tuple generator phase 3.1, support random, support per template client/server generat...
authorWenxian Li <[email protected]>
Tue, 8 Sep 2015 21:23:15 +0000 (17:23 -0400)
committerWenxian Li <[email protected]>
Tue, 8 Sep 2015 21:23:15 +0000 (17:23 -0400)
Signed-off-by: Wenxian Li <[email protected]>
linux/ws_main.py
linux_dpdk/ws_main.py
scripts/cap2/per_template_gen1.yaml [new file with mode: 0644]
scripts/cap2/per_template_gen2.yaml [new file with mode: 0644]
src/bp_gtest.cpp
src/bp_sim.cpp
src/bp_sim.h
src/gtest/tuple_gen_test.cpp
src/main_dpdk.cpp
src/tuple_gen.cpp
src/tuple_gen.h

index 88662c2..44ec956 100755 (executable)
@@ -479,7 +479,7 @@ build_types = [
 def build_prog (bld, build_obj):
     bld.program(features='cxx cxxprogram', 
                 includes =includes_path,
-                cxxflags =build_obj.get_flags(),
+                cxxflags =(build_obj.get_flags()+['-std=gnu++11',]),
                 stlib = 'stdc++',
                 linkflags = build_obj.get_link_flags(),
                 source = bp.file_list(top),
index 8669549..e425163 100755 (executable)
@@ -742,7 +742,7 @@ def build_prog (bld, build_obj):
 
     bld.program(features='cxx cxxprogram', 
                 includes =includes_path,
-                cxxflags =build_obj.get_flags(),
+                cxxflags =(build_obj.get_flags()+['-std=gnu++11',]),
                 linkflags = build_obj.get_link_flags() ,
                 lib=['pthread','dl'],
                 use =[build_obj.get_dpdk_target(),'zmq'],
diff --git a/scripts/cap2/per_template_gen1.yaml b/scripts/cap2/per_template_gen1.yaml
new file mode 100644 (file)
index 0000000..22b2ba6
--- /dev/null
@@ -0,0 +1,31 @@
+- duration : 1.0
+  generator :  
+          distribution : "seq"
+          clients_start : "16.0.0.1"
+          clients_end   : "16.0.0.255"
+          servers_start : "48.0.0.1"
+          servers_end   : "48.0.255.255"
+          clients_per_gb : 201
+          min_clients    : 101
+          dual_port_mask : "1.0.0.0" 
+          tcp_aging      : 0
+          udp_aging      : 0
+          generator_clients :
+              - name : "c1"
+                distribution : "seq"
+                ip_start : "38.0.0.1"
+                ip_end : "38.0.1.255"
+          generator_servers :
+              - name : "s1"
+                distribution : "seq"
+                ip_start : "38.0.0.1"
+                ip_end : "38.0.1.255"
+                track_ports : false
+  mac        : [0x0,0x0,0x0,0x1,0x0,0x00]
+  cap_info : 
+     - name: cap2/http_get.pcap
+       cps : 1.0
+       ipg : 100
+       rtt : 10000
+       w   : 1
+
diff --git a/scripts/cap2/per_template_gen2.yaml b/scripts/cap2/per_template_gen2.yaml
new file mode 100644 (file)
index 0000000..5edc3e4
--- /dev/null
@@ -0,0 +1,33 @@
+- duration : 1.0
+  generator :  
+          distribution : "seq"
+          clients_start : "20.0.0.1"
+          clients_end   : "20.0.0.255"
+          servers_start : "90.0.0.1"
+          servers_end   : "90.0.255.255"
+          clients_per_gb : 201
+          min_clients    : 101
+          dual_port_mask : "1.0.0.0" 
+          tcp_aging      : 0
+          udp_aging      : 0
+          generator_clients :
+              - name : "c1"
+                distribution : "seq"
+                ip_start : "16.0.0.1"
+                ip_end : "16.0.0.255"
+          generator_servers :
+              - name : "s1"
+                distribution : "seq"
+                ip_start : "48.0.0.1"
+                ip_end : "48.0.255.255"
+                track_ports: true
+  mac        : [0x0,0x0,0x0,0x1,0x0,0x00]
+  cap_info : 
+     - name: cap2/http_get.pcap
+       client_pool: "c1"
+       server_pool: "s1"
+       cps : 1.0
+       ipg : 100
+       rtt : 10000
+       w   : 1
+
index 020276c..9403775 100755 (executable)
@@ -223,10 +223,10 @@ public:
 
         if ( m_req_ports ){
             int i;
-            fl.m_threads_info[0]->m_smart_gen.FreePort(tuple.getClient(),tuple.getClientPort());
+            fl.m_threads_info[0]->m_smart_gen.FreePort(0, tuple.getClientId(),tuple.getClientPort());
 
             for (i=0 ; i<m_req_ports;i++) {
-                fl.m_threads_info[0]->m_smart_gen.FreePort(tuple.getClient(),ports[i]);
+                fl.m_threads_info[0]->m_smart_gen.FreePort(0,tuple.getClientId(),ports[i]);
             }
             delete []ports;
         }
@@ -527,6 +527,44 @@ TEST_F(basic, sfr4) {
      EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
 }
 
+TEST_F(basic, per_template_gen1) {
+
+     CTestBasic t1;
+     CParserOption * po =&CGlobalInfo::m_options;
+     po->preview.setVMode(0);
+     po->preview.setFileWrite(true);
+     po->cfg_file ="cap2/per_template_gen1.yaml";
+     po->out_file ="exp/sfr_4";
+     bool res=t1.init();
+     EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+TEST_F(basic, per_template_gen2) {
+
+     CTestBasic t1;
+     CParserOption * po =&CGlobalInfo::m_options;
+     po->preview.setVMode(0);
+     po->preview.setFileWrite(true);
+     po->cfg_file ="cap2/per_template_gen2.yaml";
+     po->out_file ="exp/sfr_4";
+     bool res=t1.init();
+     EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+
+
+/*
+TEST_F(basic, sfr5) {
+
+     CTestBasic t1;
+     CParserOption * po =&CGlobalInfo::m_options;
+     po->preview.setVMode(0);
+     po->preview.setFileWrite(true);
+     po->cfg_file ="cap2/sfr5.yaml";
+     po->out_file ="exp/sfr_5";
+     bool res=t1.init();
+     EXPECT_EQ_UINT32(1, res?1:0)<< "pass";
+}
+*/
+
 
 TEST_F(basic, ipv6_convert) {
 
index f81ef44..48b4a15 100755 (executable)
@@ -2362,6 +2362,18 @@ void operator >> (const YAML::Node& node, CVlanYamlInfo & fi) {
 
 void operator >> (const YAML::Node& node, CFlowYamlInfo & fi) {
    node["name"] >> fi.m_name;
+    
+   try {
+       node["client_pool"] >> fi.m_client_pool_name;
+   } catch ( const std::exception& e ) {
+       fi.m_client_pool_name = "default"; 
+   }
+   try {
+       node["server_pool"] >> fi.m_server_pool_name;
+   } catch ( const std::exception& e ) {
+       fi.m_server_pool_name = "default"; 
+   }
    node["cps"] >>  fi.m_k_cps;
    fi.m_k_cps = fi.m_k_cps/1000.0;
    double t;
@@ -2460,7 +2472,7 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
      node["generator"] >> flows_info.m_tuple_gen;
      flows_info.m_tuple_gen_was_set =true;
    } catch ( const std::exception& e ) {
-       flows_info.m_tuple_gen_was_set =false;
+     flows_info.m_tuple_gen_was_set =false;
    }
 
    
@@ -2577,6 +2589,10 @@ void operator >> (const YAML::Node& node, CFlowsYamlInfo & flows_info) {
    for(unsigned i=0;i<cap_info.size();i++) {
        CFlowYamlInfo fi;
        cap_info[i] >> fi;
+       fi.m_client_pool_idx = 
+           flows_info.m_tuple_gen.get_client_pool_id(fi.m_client_pool_name);
+       fi.m_server_pool_idx = 
+           flows_info.m_tuple_gen.get_server_pool_id(fi.m_server_pool_name);
        flows_info.m_vec.push_back(fi);
    }
 }
@@ -2589,7 +2605,6 @@ void CVlanYamlInfo::Dump(FILE *fd){
 
 void CFlowsYamlInfo::Dump(FILE *fd){
     fprintf(fd," duration : %f sec \n",m_duration_sec);
-    m_tuple_gen.Dump(fd);
 
     fprintf(fd,"\n");
     if (CGlobalInfo::is_ipv6_enable()) {
@@ -2805,18 +2820,20 @@ bool CFlowGeneratorRecPerThread::Create(CTupleGeneratorSmart  * global_gen,
                                         CFlowsYamlInfo *        yaml_flow_info,
                                         CCapFileFlowInfo *      flow_info,
                                         uint16_t _id,
-                                        uint32_t thread_id ){
+                                        uint32_t thread_id){
 
     BP_ASSERT(info);
     m_thread_id =thread_id ;
 
-    tuple_gen.Create(global_gen);
-    CTupleGenYamlInfo * lpt=&yaml_flow_info->m_tuple_gen;
+    tuple_gen.Create(global_gen, info->m_client_pool_idx, 
+                     info->m_server_pool_idx);
+    CTupleGenYamlInfo * lpt;
+    lpt = &yaml_flow_info->m_tuple_gen;
 
     tuple_gen.SetSingleServer(info->m_one_app_server,
                               info->m_server_addr,
                               getDualPortId(thread_id),
-                              lpt->m_dual_interface_mask
+                              lpt->m_client_pool[info->m_client_pool_idx].getDualMask()
                               );
 
     tuple_gen.SetW(info->m_w);
@@ -3118,25 +3135,39 @@ bool CFlowGenListPerThread::Create(uint32_t           thread_id,
     /* split the clients to threads */
     CTupleGenYamlInfo * tuple_gen = &m_flow_list->m_yaml_info.m_tuple_gen;
 
+    m_smart_gen.Create(0,m_thread_id,m_flow_list->is_mac_info_configured);
+
     /* split the clients to threads using the mask */
-    CClientPortion  portion;
-    split_clients(m_thread_id, 
-                  m_max_threads,
-                  getDualPortId(),
-                  *tuple_gen,
+    CIpPortion  portion;
+    for (int i=0;i<tuple_gen->m_client_pool.size();i++) {
+        split_ips(m_thread_id, m_max_threads, getDualPortId(),
+                  tuple_gen->m_client_pool[i],
                   portion);
 
-    init_from_global(portion);
-    m_smart_gen.Create(0,m_thread_id,
-                       cdSEQ_DIST,
-                       portion.m_client_start,
-                       portion.m_client_end,
-                       portion.m_server_start,
-                       portion.m_server_end, 
-                       get_longest_flow(),
-                       get_total_kcps()*1000,
-                       m_flow_list);
+        m_smart_gen.add_client_pool(tuple_gen->m_client_pool[i].m_dist,
+                        portion.m_ip_start,
+                        portion.m_ip_end,
+                        get_longest_flow(i,true),
+                        get_total_kcps(i,true)*1000,
+                        m_flow_list,
+                        tuple_gen->m_client_pool[i].m_tcp_aging_sec,
+                        tuple_gen->m_client_pool[i].m_udp_aging_sec
+                        );
+    }
+    for (int i=0;i<tuple_gen->m_server_pool.size();i++) {
+        split_ips(m_thread_id, m_max_threads, getDualPortId(),
+                  tuple_gen->m_server_pool[i],
+                  portion);
+        m_smart_gen.add_server_pool(tuple_gen->m_server_pool[i].m_dist,
+                        portion.m_ip_start,
+                        portion.m_ip_end,
+                        get_longest_flow(i,false),
+                        get_total_kcps(i,false)*1000,
+                        tuple_gen->m_server_pool[i].m_is_bundling);
+    }
 
+    init_from_global(portion);
 
     CMessagingManager * rx_dp=CMsgIns::Ins()->getRxDp();
 
@@ -3153,7 +3184,8 @@ FORCE_NO_INLINE void CFlowGenListPerThread::handler_defer_job(CGenNode *p){
     CGenNodeDeferPort     *   defer=(CGenNodeDeferPort     *)p;
     int i;
     for (i=0; i<defer->m_cnt; i++) {
-        m_smart_gen.FreePort(defer->m_clients[i],defer->m_ports[i]);
+        m_smart_gen.FreePort(defer->m_pool_idx[i],
+                                 defer->m_clients[i],defer->m_ports[i]);
     }
 }
 
@@ -3173,32 +3205,34 @@ FORCE_NO_INLINE void CFlowGenListPerThread::handler_defer_job_flush(void){
 
 
 void CFlowGenListPerThread::defer_client_port_free(bool is_tcp,
-                                                   uint32_t c_ip,
-                                                   uint16_t port){
-        /* free is not required in this case */
-    if (!m_smart_gen.IsFreePortRequired() ){
+                                                   uint32_t c_idx,
+                                                   uint16_t port,
+                                                   uint8_t c_pool_idx,
+                                                   CTupleGeneratorSmart * gen){
+    /* free is not required in this case */
+    if (!gen->IsFreePortRequired(c_pool_idx) ){
         return;
     }
     CGenNodeDeferPort     *   defer;
     if (is_tcp) {
-        if (CGlobalInfo::m_options.m_tcp_aging==0) {
-            m_smart_gen.FreePort(c_ip,port);
+        if (gen->get_tcp_aging(c_pool_idx)==0) {
+            gen->FreePort(c_pool_idx,c_idx,port);
             return;
         }
         defer=get_tcp_defer();
     }else{
-        if (CGlobalInfo::m_options.m_udp_aging==0) {
-            m_smart_gen.FreePort(c_ip,port);
+        if (gen->get_udp_aging(c_pool_idx)==0) {
+            gen->FreePort(c_pool_idx, c_idx,port);
             return;
         }
         defer=get_udp_defer();
     }
-    if ( defer->add_client(c_ip,port) ){
+    if ( defer->add_client(c_pool_idx, c_idx,port) ){
         if (is_tcp) {
-            m_node_gen.schedule_node((CGenNode *)defer,CGlobalInfo::m_options.m_tcp_aging);
+            m_node_gen.schedule_node((CGenNode *)defer,gen->get_tcp_aging(c_pool_idx));
             m_tcp_dpc=0;
         }else{
-            m_node_gen.schedule_node((CGenNode *)defer,CGlobalInfo::m_options.m_udp_aging);
+            m_node_gen.schedule_node((CGenNode *)defer,gen->get_udp_aging(c_pool_idx));
             m_udp_dpc=0;
         }
     }
@@ -3206,13 +3240,15 @@ void CFlowGenListPerThread::defer_client_port_free(bool is_tcp,
 
 
 void CFlowGenListPerThread::defer_client_port_free(CGenNode *p){
-    defer_client_port_free(p->m_pkt_info->m_pkt_indication.m_desc.IsTcp(),p->m_src_ip,p->m_src_port);
+    defer_client_port_free(p->m_pkt_info->m_pkt_indication.m_desc.IsTcp(),
+                           p->m_src_idx,p->m_src_port,p->m_template_info->m_client_pool_idx,
+                           p->m_tuple_gen);
 }
 
 
 
 /* copy all info from global and div by num of threads */
-void CFlowGenListPerThread::init_from_global(CClientPortion& portion){
+void CFlowGenListPerThread::init_from_global(CIpPortion& portion){
     /* copy generator , it is the same */
     m_yaml_info =m_flow_list->m_yaml_info;
     
@@ -3235,7 +3271,10 @@ void CFlowGenListPerThread::init_from_global(CClientPortion& portion){
         yaml_info->m_one_app_server = lp->m_info->m_one_app_server;
         yaml_info->m_server_addr = lp->m_info->m_server_addr;
         yaml_info->m_dpPkt          =lp->m_info->m_dpPkt;
-
+        yaml_info->m_server_pool_idx=lp->m_info->m_server_pool_idx;
+        yaml_info->m_client_pool_idx=lp->m_info->m_client_pool_idx;
+        yaml_info->m_server_pool_name=lp->m_info->m_server_pool_name;
+        yaml_info->m_client_pool_name=lp->m_info->m_client_pool_name;
         /* fix this */
         assert(m_max_threads>0);
         if ( m_max_threads == 1 ) {
@@ -3257,8 +3296,7 @@ void CFlowGenListPerThread::init_from_global(CClientPortion& portion){
         yaml_info->m_restart_time = ( yaml_info->m_limit_was_set ) ?
             (yaml_info->m_limit / (yaml_info->m_k_cps * 1000.0)) : 0;
 
-
-        lp_thread->Create( &m_smart_gen,
+        lp_thread->Create(&m_smart_gen,
                            yaml_info,
                            lp->m_flows_info,
                            &lp->m_flow_info,
@@ -3293,6 +3331,12 @@ void CFlowGenListPerThread::Clean(){
     int i;
     for (i=0; i<(int)m_cap_gen.size(); i++) {
         CFlowGeneratorRecPerThread * lp=m_cap_gen[i];
+        if (lp->m_tuple_gen_was_set) {
+            CTupleGeneratorSmart *gen;
+            gen = lp->tuple_gen.get_gen();
+            gen->Delete();
+            delete gen;
+        }
         lp->Delete();
         delete lp;
     }
@@ -3549,6 +3593,27 @@ uint32_t CFlowGenListPerThread::getDualPortId(){
     return ( ::getDualPortId(m_thread_id) );
 }
 
+double CFlowGenListPerThread::get_longest_flow(uint8_t pool_idx, bool is_client){
+    int i;
+    double longest_flow = 0.0;
+    for (i=0;i<(int)m_cap_gen.size(); i++) {
+        CFlowGeneratorRecPerThread * lp=m_cap_gen[i];
+        if (is_client && 
+            lp->m_info->m_client_pool_idx != pool_idx)
+            continue;
+        if (!is_client && 
+            lp->m_info->m_server_pool_idx != pool_idx)
+            continue;
+        double tmp_len;
+        tmp_len = lp->m_flow_info->get_cap_file_length_sec();
+        if (longest_flow < tmp_len ) {
+            longest_flow = tmp_len;
+        }
+    }
+    return longest_flow;
+}
+
+
 double CFlowGenListPerThread::get_longest_flow(){
     int i;
     double longest_flow = 0.0;
@@ -3563,6 +3628,22 @@ double CFlowGenListPerThread::get_longest_flow(){
     return longest_flow;
 }
 
+double CFlowGenListPerThread::get_total_kcps(uint8_t pool_idx, bool is_client){
+    int i;
+    double total=0.0;
+    for (i=0; i<(int)m_cap_gen.size(); i++) {
+        CFlowGeneratorRecPerThread * lp=m_cap_gen[i];
+        if (is_client && 
+            lp->m_info->m_client_pool_idx != pool_idx)
+            continue;
+        if (!is_client && 
+            lp->m_info->m_server_pool_idx != pool_idx)
+            continue;
+        total +=lp->m_info->m_k_cps;
+    }
+    return (total);
+}
+
 double CFlowGenListPerThread::get_total_kcps(){
     int i;
     double total=0.0;
@@ -3871,9 +3952,6 @@ int CFlowGenList::load_from_yaml(std::string file_name,
     CGlobalInfo::m_options.m_vlan_port[0] =   m_yaml_info.m_vlan_info.m_vlan_per_port[0];
     CGlobalInfo::m_options.m_vlan_port[1] =   m_yaml_info.m_vlan_info.m_vlan_per_port[1];
     CGlobalInfo::m_options.preview.set_mac_ip_overide_enable(m_yaml_info.m_mac_replace_by_ip);
-    CGlobalInfo::m_options.m_tcp_aging = m_yaml_info.m_tuple_gen.m_tcp_aging_sec;
-    CGlobalInfo::m_options.m_udp_aging = m_yaml_info.m_tuple_gen.m_udp_aging_sec;
-
 
     if ( m_yaml_info.m_mac_base.size() != 6 ){
         printf(" mac addr is not valid \n");
@@ -5418,8 +5496,11 @@ void CPluginCallbackSimple::on_node_last(uint8_t plugin_id,CGenNode *     node){
         /* free the ports */
         CFlowGenListPerThread  * flow_gen=(CFlowGenListPerThread  *) lpP->m_gen;
         bool is_tcp=node->m_pkt_info->m_pkt_indication.m_desc.IsTcp();
-        flow_gen->defer_client_port_free(is_tcp,node->m_src_ip,lpP->rtp_client_0);
-        flow_gen->defer_client_port_free(is_tcp,node->m_src_ip,lpP->rtp_client_1);
+        flow_gen->defer_client_port_free(is_tcp,node->m_src_idx,lpP->rtp_client_0,
+                                node->m_template_info->m_client_pool_idx,node->m_tuple_gen);
+        flow_gen->defer_client_port_free(is_tcp,node->m_src_idx,lpP->rtp_client_1,
+                                node->m_template_info->m_client_pool_idx,  node->m_tuple_gen);
         assert(lpP);
         delete lpP;
         node->m_plugin_info=0;
index 002c9d0..6fb638e 100755 (executable)
@@ -716,8 +716,6 @@ public:
     uint16_t           m_vlan_port[2]; /* vlan value */
     uint16_t           m_src_ipv6[6];  /* Most signficant 96-bits */
     uint16_t           m_dst_ipv6[6];  /* Most signficant 96-bits */
-    uint16_t        m_tcp_aging;
-    uint16_t        m_udp_aging;
 
     uint32_t        m_latency_rate; /* pkt/sec for each thread/port zero disable */
     uint32_t        m_latency_mask;
@@ -1249,9 +1247,13 @@ struct CFlowYamlInfo {
     CFlowYamlInfo(){
         m_dpPkt=0;
         m_server_addr=0;
+        m_client_pool_idx = 0;
+        m_server_pool_idx = 0;
     }
     
     std::string     m_name;
+    std::string     m_client_pool_name;
+    std::string     m_server_pool_name;
     double          m_k_cps;    //k CPS 
        double          m_restart_time; /* restart time of this template */
     dsec_t          m_ipg_sec;   // ipg in sec 
@@ -1261,6 +1263,8 @@ struct CFlowYamlInfo {
     uint32_t        m_limit;
     uint32_t        m_flowcnt;
     uint8_t         m_plugin_id; /* 0 - default , 1 - RTSP160 , 2- RTSP250 */       
+    uint8_t         m_client_pool_idx;
+    uint8_t         m_server_pool_idx;
     bool            m_one_app_server;
     uint32_t        m_server_addr;
     bool            m_one_app_server_was_set;
@@ -1378,7 +1382,10 @@ public:
 
     uint16_t            m_nat_pad;
     mac_addr_align_t    m_src_mac;
-    uint32_t            m_end_of_cache_line[11];
+    CTupleGeneratorSmart *m_tuple_gen;
+    uint32_t            m_src_idx;
+    uint32_t            m_dest_idx;
+    uint32_t            m_end_of_cache_line[10];
 
 public:
     bool operator <(const CGenNode * rsh ) const {
@@ -1600,6 +1607,7 @@ struct CGenNodeDeferPort  {
 
     uint32_t            m_clients[DEFER_CLIENTS_NUM];
     uint16_t            m_ports[DEFER_CLIENTS_NUM];
+    uint8_t             m_pool_idx[DEFER_CLIENTS_NUM];
 public:
     void init(void){ 
         m_type=CGenNode::FLOW_DEFER_PORT_RELEASE;
@@ -1607,10 +1615,11 @@ public:
     }
 
     /* return true if object is full */
-    bool add_client(uint32_t client,
+    bool add_client(uint8_t pool_idx, uint32_t client,
                    uint16_t port){
         m_clients[m_cnt]=client;
         m_ports[m_cnt]=port;
+        m_pool_idx[m_cnt] = pool_idx;
         m_cnt++;
         if ( m_cnt == DEFER_CLIENTS_NUM ) {
             return (true);
@@ -3154,6 +3163,7 @@ public:
     CPolicer                m_policer;   
     uint16_t                m_id ;
     uint32_t                m_thread_id;
+    bool                    m_tuple_gen_was_set;
 } __rte_cache_aligned; 
 
 
@@ -3286,8 +3296,10 @@ public:
     uint32_t getDualPortId();
 public :
     double get_total_kcps();
+    double get_total_kcps(uint8_t pool_idx, bool is_client);
     double get_delta_flow_is_sec();
     double get_longest_flow(); 
+    double get_longest_flow(uint8_t pool_idx, bool is_client); 
     void inc_current_template(void);
     int generate_flows_roundrobin(bool *done);
     int reschedule_flow(CGenNode *node);
@@ -3319,9 +3331,10 @@ private:
     void terminate_nat_flows(CGenNode *node);
 
 
-    void init_from_global(CClientPortion &);
+    void init_from_global(CIpPortion &);
     void defer_client_port_free(CGenNode *p);
-    void defer_client_port_free(bool is_tcp,uint32_t c_ip,uint16_t port);
+    void defer_client_port_free(bool is_tcp,uint32_t c_ip,uint16_t port,
+                                uint8_t pool_idx, CTupleGeneratorSmart*gen);
 
 
     FORCE_NO_INLINE void   handler_defer_job(CGenNode *p);
@@ -3416,12 +3429,6 @@ inline void CFlowGenListPerThread::free_last_flow_node(CGenNode *p){
     free_node( p);
 }
 
-
-typedef struct mac_mapping_ {
-    mac_addr_align_t mac;
-    uint32_t         ip;
-} mac_mapping_t;
-
 class CFlowGenList {
 
 public:
@@ -3448,10 +3455,6 @@ public:
     double get_total_pps();
     double get_total_tx_bps();
     uint32_t get_total_repeat_flows();
-    bool is_ip_legal(uint32_t ip) {
-        return (ip >= m_yaml_info.m_tuple_gen.m_clients_ip_start && 
-            ip <= m_yaml_info.m_tuple_gen.m_clients_ip_end );
-    }
     double get_delta_flow_is_sec();
 public:
     std::vector<CFlowGeneratorRec *> m_cap_gen;   /* global info */
@@ -3492,8 +3495,11 @@ inline void CCapFileFlowInfo::generate_flow(CTupleTemplateGeneratorSmart   * tup
     node->m_flow_info = this;
     node->m_flags=0;
     node->m_template_info =template_info;
+    node->m_tuple_gen = tuple_gen->get_gen(); 
     node->m_src_ip= tuple.getClient();
     node->m_dest_ip = tuple.getServer();
+    node->m_src_idx = tuple.getClientId();
+    node->m_dest_idx = tuple.getServerId();
     node->m_src_port = tuple.getClientPort();
     memcpy(&node->m_src_mac, 
            tuple.getClientMac(), 
index 6419ced..8791b67 100755 (executable)
@@ -153,12 +153,12 @@ TEST(CClientInfoLTest, get_new_free_port) {
 
 
 
-/* UIT of CTupleGeneratorSmart */
-TEST(tuple_gen,GenerateTuple) {
-    CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001,  0x10000f01, 0x30000001, 0x40000001
-               MAX_PORT, MAX_PORT);
+/* UIT of CClientPool, using CClientInfoL */
+TEST(tuple_gen,clientPoolL) {
+    CClientPool gen;
+    gen.Create(cdSEQ_DIST, 
+               0x10000001,  0x10000f01, 64000,1,NULL,false
+               0,0);
     CTupleBase result;
     uint32_t result_src;
     uint32_t result_dest;
@@ -166,13 +166,11 @@ TEST(tuple_gen,GenerateTuple) {
 
     for(int i=0;i<10;i++) {
         gen.GenerateTuple(result);
-        printf(" C:%x S:%x P:%d \n",result.getClient(),result.getServer(),result.getClientPort());
+        printf(" C:%x P:%d \n",result.getClient(),result.getClientPort());
 
         result_src = result.getClient();
-        result_dest = result.getServer();
         result_port = result.getClientPort();
         EXPECT_EQ(result_src, (uint32_t)(0x10000001+i));
-        EXPECT_EQ(result_dest, (uint32_t) (((0x30000001+i)) ) );
         EXPECT_EQ(result_port, 1024);
     }
 
@@ -180,164 +178,229 @@ TEST(tuple_gen,GenerateTuple) {
 //    EXPECT_EQ((size_t)0, gen.m_clients.size());
 }
 
-TEST(tuple_gen,GenerateTuple2) {
-    CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001, 
-               MAX_PORT, MAX_PORT);
+/* UIT of CClientPool, using CClientInfo */
+TEST(tuple_gen,clientPool) {
+    CClientPool gen;
+    gen.Create(cdSEQ_DIST, 
+               0x10000001,  0x10000021, 64000,1000,NULL,false, 
+               0,0);
     CTupleBase result;
     uint32_t result_src;
     uint32_t result_dest;
     uint16_t result_port;
 
-    for(int i=0;i<200;i++) {
+    for(int i=0;i<10;i++) {
         gen.GenerateTuple(result);
-      //  gen.Dump(stdout);
-      //  fprintf(stdout, "i:%d\n",i);
+        printf(" C:%x P:%d \n",result.getClient(),result.getClientPort());
+
         result_src = result.getClient();
-        result_dest = result.getServer();
         result_port = result.getClientPort();
-        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%15));
-        EXPECT_EQ(result_dest, (uint32_t)((0x30000001+i) ) );
-        EXPECT_EQ(result_port, 1024+i/15);
+        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i));
+        EXPECT_EQ(result_port, 1024);
     }
 
     gen.Delete();
 //    EXPECT_EQ((size_t)0, gen.m_clients.size());
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001, 
-               MAX_PORT,MAX_PORT);
-    for(int i=0;i<200;i++) {
+}
+
+/* UIT of CServerPool */
+TEST(tuple_gen,serverPool) {
+    CServerPool gen;
+    gen.Create(cdSEQ_DIST, 
+               0x30000001,  0x30000ff1, 64000,10);
+    CTupleBase result;
+    uint32_t result_dest;
+
+    for(int i=0;i<10;i++) {
         gen.GenerateTuple(result);
-    //    gen.Dump(stdout);
-     //   fprintf(stdout, "i:%d\n",i);
-        result_src = result.getClient();
+        printf(" S:%x \n",result.getServer());
+
         result_dest = result.getServer();
-        result_port = result.getClientPort();
-        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%15));
         EXPECT_EQ(result_dest, (uint32_t) (((0x30000001+i)) ) );
-        EXPECT_EQ(result_port, 1024+i/15);
     }
 
+    gen.Delete();
 
+    gen.Create(cdSEQ_DIST, 
+               0x30000001,  0x30000003, 64000,1000);
 
-}
+    for(int i=0;i<10;i++) {
+        gen.GenerateTuple(result);
+        printf(" S:%x \n",result.getServer());
 
-TEST(tuple_gen,GenerateTupleMac) {
-    CFlowGenList  fl;
-    fl.Create();
-    fl.load_from_mac_file("avl/mac_uit.yaml");
-    fl.m_yaml_info.m_tuple_gen.m_clients_ip_start = 0x10000001;
-    fl.m_yaml_info.m_tuple_gen.m_clients_ip_end = 0x1000000f;
+        result_dest = result.getServer();
+        EXPECT_EQ(result_dest, (uint32_t) (((0x30000001+i%3)) ) );
+    }
 
+    gen.Delete();
+    //    EXPECT_EQ((size_t)0, gen.m_clients.size());
+}
 
-    CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001,  0x1000000f, 0x30000001, 0x40000001
-               MAX_PORT, MAX_PORT, &fl);
+TEST(tuple_gen,servePoolSim) {
+    CServerPoolSimple gen;
+    gen.Create(cdSEQ_DIST
+               0x30000001,  0x40000001, 64000,10);
     CTupleBase result;
-    uint32_t result_src;
     uint32_t result_dest;
-    uint16_t result_port;
 
     for(int i=0;i<10;i++) {
         gen.GenerateTuple(result);
-        printf(" C:%x S:%x P:%d \n",result.getClient(),result.getServer(),result.getClientPort());
+        printf(" S:%x \n",result.getServer());
 
-        result_src = result.getClient();
         result_dest = result.getServer();
-        result_port = result.getClientPort();
-        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%2));
         EXPECT_EQ(result_dest, (uint32_t) (((0x30000001+i)) ) );
-        EXPECT_EQ(result_port, 1024+i/2);
     }
 
     gen.Delete();
-//    EXPECT_EQ((size_t)0, gen.m_clients.size());
+
+    gen.Create(cdSEQ_DIST, 
+               0x30000001,  0x30000003, 64000,1000);
+
+    for(int i=0;i<10;i++) {
+        gen.GenerateTuple(result);
+        printf(" S:%x \n",result.getServer());
+
+        result_dest = result.getServer();
+        EXPECT_EQ(result_dest, (uint32_t) (((0x30000001+i%3)) ) );
+    }
+
+    gen.Delete();
+    //    EXPECT_EQ((size_t)0, gen.m_clients.size());
 }
 
 
 
-TEST(tuple_gen,GenerateTupleEx) {
-    CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               MAX_PORT, MAX_PORT);
+
+TEST(tuple_gen,GenerateTuple2) {
+    CClientPool c_gen;
+    CClientPool c_gen_2;
+    c_gen.Create(cdSEQ_DIST, 
+               0x10000001,  0x1000000f, 64000,4,NULL,false, 
+               0,0);
+    CServerPool s_gen;
+    CServerPool s_gen_2;
+    s_gen.Create(cdSEQ_DIST, 
+               0x30000001,  0x30000ff1, 64000,10);
     CTupleBase result;
+
     uint32_t result_src;
     uint32_t result_dest;
     uint16_t result_port;
-    uint16_t ex_port[2];
-    for(int i=0;i<20;i++) {
 
-        gen.GenerateTupleEx(result,2,ex_port);
-        fprintf(stdout, "i:%d\n",i);
+    for(int i=0;i<200;i++) {
+        c_gen.GenerateTuple(result);
+        s_gen.GenerateTuple(result);
+      //  gen.Dump(stdout);
+      //  fprintf(stdout, "i:%d\n",i);
         result_src = result.getClient();
         result_dest = result.getServer();
         result_port = result.getClientPort();
+        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%15));
+        EXPECT_EQ(result_dest, (uint32_t)((0x30000001+i) ) );
+        EXPECT_EQ(result_port, 1024+i/15);
+    }
 
+    s_gen.Delete();
+    c_gen.Delete();
+//    EXPECT_EQ((size_t)0, gen.m_clients.size());
+    c_gen.Create(cdSEQ_DIST, 
+               0x10000001,  0x1000000f, 64000,400,NULL,false, 
+               0,0);
+    s_gen.Create(cdSEQ_DIST, 
+               0x30000001,  0x30000001, 64000,10);
+    for(int i=0;i<200;i++) {
+        s_gen.GenerateTuple(result);
+        c_gen.GenerateTuple(result);
+    //    gen.Dump(stdout);
+       // fprintf(stdout, "i:%d\n",i);
+        result_src = result.getClient();
+        result_dest = result.getServer();
+        result_port = result.getClientPort();
         EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%15));
-        EXPECT_EQ(result_dest, (uint32_t)(((0x30000001+i)) ));
+        EXPECT_EQ(result_dest, (uint32_t) (((0x30000001)) ) );
+        EXPECT_EQ(result_port, 1024+i/15);
+    }
+
+    s_gen.Delete();
+    c_gen.Delete();
+
+
+}
+
+TEST(tuple_gen,GenerateTupleMac) {
+    CFlowGenList  fl;
+    fl.Create();
+    fl.load_from_mac_file("avl/mac_uit.yaml");
 
-        EXPECT_EQ(result_port, 1024+(i/15)*3);
-        EXPECT_EQ(ex_port[0], 1025+(i/15)*3);
-        EXPECT_EQ(ex_port[1], 1026+(i/15)*3);
+    CClientPool gen;
+    gen.Create(cdSEQ_DIST, 
+               0x10000001,  0x1000000f, 64000,2, &fl,true,0,0);
+    CTupleBase result;
+    uint32_t result_src;
+    uint16_t result_port;
+    mac_addr_align_t* result_mac;
+    for(int i=0;i<10;i++) {
+        gen.GenerateTuple(result);
+        printf(" C:%x P:%d \n",result.getClient(),result.getClientPort());
+
+        result_src = result.getClient();
+        result_port = result.getClientPort();
+        result_mac = result.getClientMac();
+        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%2));
+        EXPECT_EQ(result_port, 1024+i/2);
+        if (i%2==0)
+            EXPECT_EQ(result_mac->mac[3], 5);
+        else
+            EXPECT_EQ(result_mac->mac[3], 1);
     }
 
     gen.Delete();
+//    EXPECT_EQ((size_t)0, gen.m_clients.size());
 }
 
-TEST(tuple_gen,split1) {
-    CClientPortion  portion;
 
-    CTupleGenYamlInfo fi;
-    fi.m_clients_ip_start =0x10000000;
-    fi.m_clients_ip_end   =0x100000ff;
+TEST(tuple_gen,split1) {
+    CIpPortion  portion;
 
-    fi.m_servers_ip_start =0x20000000;
-    fi.m_servers_ip_end   =0x200000ff;
+    CTupleGenPoolYaml fi;
+    fi.m_ip_start =0x10000000;
+    fi.m_ip_end   =0x100000ff;
 
     fi.m_dual_interface_mask =0x01000000;
 
-    split_clients(0,
+    split_ips(0,
                   1, 
                   0,
                   fi,
                   portion);
-    EXPECT_EQ(portion.m_client_start, (uint32_t)(0x10000000));
-    EXPECT_EQ(portion.m_client_end,   (uint32_t)(0x100000ff ));
-    EXPECT_EQ(portion.m_server_start  , (uint32_t)(0x20000000));
-    EXPECT_EQ(portion.m_server_end    , (uint32_t)(0x200000ff));
-    printf(" %x %x %x %x \n",portion.m_client_start,portion.m_client_end,portion.m_server_start,portion.m_server_end);
+    EXPECT_EQ(portion.m_ip_start, (uint32_t)(0x10000000));
+    EXPECT_EQ(portion.m_ip_end,   (uint32_t)(0x100000ff ));
+    printf(" %x %x \n",portion.m_ip_start,portion.m_ip_end);
 
-    split_clients(2,
+    split_ips(2,
                   4, 
                   1,
                   fi,
                   portion);
 
-     EXPECT_EQ(portion.m_client_start, (uint32_t)(0x11000080));
-     EXPECT_EQ(portion.m_client_end, (uint32_t)(0x110000bf ));
-     EXPECT_EQ(portion.m_server_start  , (uint32_t)(0x21000080));
-     EXPECT_EQ(portion.m_server_end    , (uint32_t)(0x210000bf));
-     printf(" %x %x %x %x \n",portion.m_client_start,portion.m_client_end,portion.m_server_start,portion.m_server_end);
+     EXPECT_EQ(portion.m_ip_start, (uint32_t)(0x11000080));
+     EXPECT_EQ(portion.m_ip_end, (uint32_t)(0x110000bf ));
+     printf(" %x %x \n",portion.m_ip_start,portion.m_ip_end);
 }
 
 TEST(tuple_gen,split2) {
-    CClientPortion  portion;
+    CIpPortion  portion;
 
-    CTupleGenYamlInfo fi;
-    fi.m_clients_ip_start =0x10000000;
-    fi.m_clients_ip_end   =0x100001ff;
+    CTupleGenPoolYaml fi;
 
-    fi.m_servers_ip_start =0x20000000;
-    fi.m_servers_ip_end   =0x200001ff;
+    fi.m_ip_start =0x20000000;
+    fi.m_ip_end   =0x200001ff;
 
     fi.m_dual_interface_mask =0x01000000;
 
     int i;
     for (i=0; i<8; i++) {
-        split_clients(i,
+        split_ips(i,
                       8, 
                       (i&1),
                       fi,
@@ -345,31 +408,23 @@ TEST(tuple_gen,split2) {
 
 
         if ( (i&1) ) {
-            EXPECT_EQ(portion.m_client_start, (uint32_t)(0x11000000)+(0x40*i));
-            EXPECT_EQ(portion.m_client_end, (uint32_t)(0x11000000 +(0x40*i+0x40-1)));
-            EXPECT_EQ(portion.m_server_start  , (uint32_t)(0x21000000)+ (0x40*i) );
-            EXPECT_EQ(portion.m_server_end    , (uint32_t)(0x21000000)+(0x40*i+0x40-1) );
+            EXPECT_EQ(portion.m_ip_start  , (uint32_t)(0x21000000)+ (0x40*i) );
+            EXPECT_EQ(portion.m_ip_end    , (uint32_t)(0x21000000)+(0x40*i+0x40-1) );
         }else{
-            EXPECT_EQ(portion.m_client_start, (uint32_t)(0x10000000)+ (0x40*i) );
-            EXPECT_EQ(portion.m_client_end, (uint32_t)(0x10000000   + (0x40*i+0x40-1) ) );
-            EXPECT_EQ(portion.m_server_start  , (uint32_t)(0x20000000) + (0x40*i) );
-            EXPECT_EQ(portion.m_server_end    , (uint32_t)(0x20000000) + (0x40*i+0x40-1) );
+            EXPECT_EQ(portion.m_ip_start  , (uint32_t)(0x20000000) + (0x40*i) );
+            EXPECT_EQ(portion.m_ip_end    , (uint32_t)(0x20000000) + (0x40*i+0x40-1) );
         }
-        printf(" %x %x %x %x \n",portion.m_client_start,portion.m_client_end,portion.m_server_start,portion.m_server_end);
+        printf(" %x %x \n",portion.m_ip_start,portion.m_ip_end);
     }
 }
 
-
-
-
-
 TEST(tuple_gen,template1) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               MAX_PORT, MAX_PORT);
+    gen.Create(1, 1); 
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
     template_1.SetSingleServer(true,0x12121212,0,0);
     CTupleBase result;
 
@@ -391,11 +446,11 @@ TEST(tuple_gen,template1) {
 
 TEST(tuple_gen,template2) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               MAX_PORT, MAX_PORT);
+    gen.Create(1, 1);
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
     template_1.SetW(10);
 
     CTupleBase result;
@@ -420,11 +475,11 @@ TEST(tuple_gen,template2) {
 
 TEST(tuple_gen,no_free) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x10000001, 0x30000001, 0x300000ff,
-               MAX_PORT, MAX_PORT);
+    gen.Create(1, 1);
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x10000001,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x400000ff,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
 
     CTupleBase result;
 
@@ -445,11 +500,11 @@ TEST(tuple_gen,no_free) {
 
 TEST(tuple_gen,try_to_free) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x10000001, 0x30000001, 0x300000ff,
-               MAX_PORT, MAX_PORT);
+    gen.Create(1, 1); 
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x10000001,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x400000ff,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
 
     CTupleBase result;
 
@@ -460,7 +515,7 @@ TEST(tuple_gen,try_to_free) {
         uint32_t result_src = result.getClient();
         uint32_t result_dest = result.getServer();
         uint16_t result_port = result.getClientPort();
-        gen.FreePort(result_src,result_port);
+        gen.FreePort(0,result.getClientId(),result_port);
     }
     // should have error
     EXPECT_FALSE((gen.getErrorAllocationCounter()>0)?true:false);
@@ -474,16 +529,18 @@ TEST(tuple_gen,try_to_free) {
 /* tuple generator using CClientInfoL*/
 TEST(tuple_gen_2,GenerateTuple) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001,  0x10000f01, 0x30000001, 0x40000001, 
-               0,0);
+    gen.Create(1, 1); 
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x10000f01,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
+    CTupleTemplateGeneratorSmart template_1;
+    template_1.Create(&gen,0,0);
     CTupleBase result;
     uint32_t result_src;
     uint32_t result_dest;
     uint16_t result_port;
 
     for(int i=0;i<10;i++) {
-        gen.GenerateTuple(result);
+        template_1.GenerateTuple(result);
         printf(" C:%x S:%x P:%d \n",result.getClient(),result.getServer(),result.getClientPort());
 
         result_src = result.getClient();
@@ -500,16 +557,18 @@ TEST(tuple_gen_2,GenerateTuple) {
 
 TEST(tuple_gen_2,GenerateTuple2) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001, 
-               0,0);
+    gen.Create(1, 1);
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
+    CTupleTemplateGeneratorSmart template_1;
+    template_1.Create(&gen,0,0);
     CTupleBase result;
     uint32_t result_src;
     uint32_t result_dest;
     uint16_t result_port;
 
     for(int i=0;i<200;i++) {
-        gen.GenerateTuple(result);
+        template_1.GenerateTuple(result);
       //  gen.Dump(stdout);
       //  fprintf(stdout, "i:%d\n",i);
         result_src = result.getClient();
@@ -522,11 +581,12 @@ TEST(tuple_gen_2,GenerateTuple2) {
 
     gen.Delete();
 //    EXPECT_EQ((size_t)0, gen.m_clients.size());
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001, 
-               0,0);
+    gen.Create(1, 1); 
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
+    template_1.Create(&gen,0,0);
     for(int i=0;i<200;i++) {
-        gen.GenerateTuple(result);
+        template_1.GenerateTuple(result);
     //    gen.Dump(stdout);
      //   fprintf(stdout, "i:%d\n",i);
         result_src = result.getClient();
@@ -542,43 +602,13 @@ TEST(tuple_gen_2,GenerateTuple2) {
 }
 
 
-
-TEST(tuple_gen_2,GenerateTupleEx) {
-    CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               0,0);
-    CTupleBase result;
-    uint32_t result_src;
-    uint32_t result_dest;
-    uint16_t result_port;
-    uint16_t ex_port[2];
-    for(int i=0;i<20;i++) {
-
-        gen.GenerateTupleEx(result,2,ex_port);
-        fprintf(stdout, "i:%d\n",i);
-        result_src = result.getClient();
-        result_dest = result.getServer();
-        result_port = result.getClientPort();
-
-        EXPECT_EQ(result_src, (uint32_t)(0x10000001+i%15));
-        EXPECT_EQ(result_dest, (uint32_t)(((0x30000001+i)) ));
-
-        EXPECT_EQ(result_port, 1024+(i/15)*3);
-        EXPECT_EQ(ex_port[0], 1025+(i/15)*3);
-        EXPECT_EQ(ex_port[1], 1026+(i/15)*3);
-    }
-
-    gen.Delete();
-}
-
 TEST(tuple_gen_2,template1) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               0,0);
+    gen.Create(1, 1); 
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
     template_1.SetSingleServer(true,0x12121212,0,0);
     CTupleBase result;
 
@@ -601,11 +631,11 @@ TEST(tuple_gen_2,template1) {
 
 TEST(tuple_gen_2,template2) {
     CTupleGeneratorSmart gen;
-    gen.Create(1, 1,cdSEQ_DIST, 
-               0x10000001, 0x1000000f, 0x30000001, 0x40000001,
-               0,0);
+    gen.Create(1, 1);
+    gen.add_client_pool(cdSEQ_DIST,0x10000001,0x1000000f,64000,4,NULL,0,0);
+    gen.add_server_pool(cdSEQ_DIST,0x30000001,0x40000001,64000,4,false);
     CTupleTemplateGeneratorSmart template_1;
-    template_1.Create(&gen);
+    template_1.Create(&gen,0,0);
     template_1.SetW(10);
 
     CTupleBase result;
@@ -646,45 +676,40 @@ TEST(tuple_gen_yaml,yam_reader1) {
         std::cout << e.what() << "\n";
         exit(-1);
     }
-    fi.Dump(stdout);
 }
 
 TEST(tuple_gen_yaml,yam_is_valid) {
 
     CTupleGenYamlInfo  fi;
+    CTupleGenPoolYaml c_pool;
+    CTupleGenPoolYaml s_pool;
+    fi.m_client_pool.push_back(c_pool); 
+    fi.m_server_pool.push_back(s_pool); 
+    
+    fi.m_client_pool[0].m_ip_start = 0x10000001;
+    fi.m_client_pool[0].m_ip_end   = 0x100000ff;
 
-    fi.m_clients_ip_start = 0x10000001;
-    fi.m_clients_ip_end   = 0x100000ff;
-
-    fi.m_servers_ip_start = 0x10000001;
-    fi.m_servers_ip_end   = 0x100001ff;
+    fi.m_server_pool[0].m_ip_start = 0x10000001;
+    fi.m_server_pool[0].m_ip_end   = 0x100001ff;
 
     EXPECT_EQ(fi.is_valid(8,true)?1:0, 1);
-    EXPECT_EQ(fi.m_servers_ip_start, 0x10000001);
-    EXPECT_EQ(fi.m_servers_ip_end, 0x100001fe);
 
-    printf(" start:%x end:%x \n",fi.m_servers_ip_start,fi.m_servers_ip_end);
 
-    fi.m_clients_ip_start = 0x10000001;
-    fi.m_clients_ip_end   = 0x100000ff;
+    fi.m_client_pool[0].m_ip_start = 0x10000001;
+    fi.m_client_pool[0].m_ip_end   = 0x100000ff;
 
-    fi.m_servers_ip_start = 0x10000001;
-    fi.m_servers_ip_end   = 0x10000009;
+    fi.m_server_pool[0].m_ip_start = 0x10000001;
+    fi.m_server_pool[0].m_ip_end   = 0x10000007;
 
     EXPECT_EQ(fi.is_valid(8,true)?1:0, 0);
 
-    fi.m_clients_ip_start = 0x10000001;
-    fi.m_clients_ip_end   = 0x100000ff;
+    fi.m_client_pool[0].m_ip_start = 0x10000001;
+    fi.m_client_pool[0].m_ip_end   = 0x100000ff;
 
-    fi.m_servers_ip_start = 0x10000001;
-    fi.m_servers_ip_end   = 0x100003ff;
+    fi.m_server_pool[0].m_ip_start = 0x10000001;
+    fi.m_server_pool[0].m_ip_end   = 0x100003ff;
 
     EXPECT_EQ(fi.is_valid(8,true)?1:0, 1);
-    EXPECT_EQ(fi.m_servers_ip_start, 0x10000001);
-    EXPECT_EQ(fi.m_servers_ip_end, 0x100003fc);
-
-    printf(" start:%x end:%x \n",fi.m_servers_ip_start,fi.m_servers_ip_end);
-
 
 }
 
index 22ecc52..1e6c8b2 100755 (executable)
@@ -4094,11 +4094,10 @@ int CGlobalPortCfg::start_send_master(){
 
     CTupleGenYamlInfo * tg=&m_fl.m_yaml_info.m_tuple_gen;
 
-    m_mg.set_ip( tg->m_clients_ip_start,
-                 tg->m_servers_ip_start,
-                 tg->m_dual_interface_mask
-                  );
-
+    m_mg.set_ip( tg->m_client_pool[0].get_ip_start(),
+                 tg->m_server_pool[0].get_ip_start(),
+                 tg->m_client_pool[0].getDualMask()
+               );
 
     if (  CGlobalInfo::m_options.preview.getVMode() >0 ) {
       m_fl.DumpCsv(stdout);
index 0faa6b6..2e1099d 100755 (executable)
@@ -1,6 +1,6 @@
 /*
 
- Wenxian Li 
+ Wenxian Li
  Hanoh Haim
  Cisco Systems, Inc.
 */
@@ -21,287 +21,362 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
+
 #include "tuple_gen.h"
 #include <string.h>
 #include "utl_yaml.h"
 
-
-
-              
-/* simple tuple genertion for one low*/
-void CTupleGeneratorSmart::GenerateTuple(CTupleBase & tuple) {
-    BP_ASSERT(m_was_init);
-    Generate_client_server();
-    m_was_generated = true;
-    m_result_client_port = GenerateOneClientPort(m_client_ip);
-    tuple.setClient(m_result_client_ip);
-    tuple.setServer(m_result_server_ip);
-    tuple.setClientPort(m_result_client_port);
-    tuple.setClientMac(&m_result_client_mac);
-//    printf(" alloc  %x %d mac:%x,%x\n",m_result_client_ip,m_result_client_port, m_result_client_mac.mac[0], m_result_client_mac.mac[1]);
+void CServerPool::Create(IP_DIST_t  dist_value,
+            uint32_t min_ip,
+            uint32_t max_ip,
+            double l_flow,
+            double t_cps) {
+    gen = new CIpPool();
+    gen->set_dist(dist_value);
+    uint32_t total_ip = max_ip - min_ip +1;
+    gen->m_ip_info.resize(total_ip);
+
+    if (total_ip > ((l_flow*t_cps/MAX_PORT))) {
+        for(int idx=0;idx<total_ip;idx++){
+            gen->m_ip_info[idx] = new CServerInfoL();
+            gen->m_ip_info[idx]->set_ip(min_ip+idx);
+        }
+    } else {
+        for(int idx=0;idx<total_ip;idx++){
+            gen->m_ip_info[idx] = new CServerInfo();
+            gen->m_ip_info[idx]->set_ip(min_ip+idx);
+        }
+    }
+    gen->CreateBase();
 }
 
 
 
+void CClientPool::Create(IP_DIST_t  dist_value,
+            uint32_t min_ip,
+            uint32_t max_ip,
+            double l_flow,
+            double t_cps,
+            CFlowGenList* fl_list,
+            bool has_mac_map,
+            uint16_t tcp_aging, 
+            uint16_t udp_aging) {
+    assert(max_ip>=min_ip);
+    set_dist(dist_value);
+    uint32_t total_ip = max_ip - min_ip +1;
+    uint32_t avail_ip = total_ip;
+    if (has_mac_map && (fl_list!=NULL)) {
+        for(int idx=0;idx<total_ip;idx++){
+            mac_addr_align_t *mac_adr = NULL;
+            mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+            if (mac_adr == NULL) {
+                avail_ip--;
+            }
+        }
+    }
+    if (avail_ip!=0) {
+        m_ip_info.resize(avail_ip);
+    } else {
+        printf("\n Error, empty mac file is configured.\n"
+               "Will ignore the mac file configuration.\n");
+        m_ip_info.resize(total_ip);
+    }
 
-/*
- * allocate base tuple with n exta ports, used by bundels SIP
- * for example need to allocat 3 ports for this C/S
- */
-void CTupleGeneratorSmart::GenerateTupleEx(CTupleBase & tuple,
-                                              uint8_t extra_ports_no,
-                                              uint16_t * extra_ports) {
-    GenerateTuple(tuple) ;
-    for (int idx=0;idx<extra_ports_no;idx++) {
-        extra_ports[idx] = GenerateOneClientPort(m_client_ip);
+    if (total_ip > ((l_flow*t_cps/MAX_PORT))) {
+        if (has_mac_map) {
+            for(int idx=0;idx<total_ip;idx++){
+                mac_addr_align_t *mac_adr = NULL;
+                mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+                if (mac_adr != NULL) {
+                    m_ip_info[idx] = new CClientInfoL(has_mac_map);
+                    m_ip_info[idx]->set_ip(min_ip+idx);
+                    m_ip_info[idx]->set_mac(mac_adr);
+                }
+            }
+        } else {
+            for(int idx=0;idx<total_ip;idx++){
+                m_ip_info[idx] = new CClientInfoL(has_mac_map);
+                m_ip_info[idx]->set_ip(min_ip+idx);
+            }
+        } 
+    } else {
+        if (has_mac_map) {
+            for(int idx=0;idx<total_ip;idx++){
+                mac_addr_align_t *mac_adr = NULL;
+                mac_adr = get_mac_addr_by_ip(fl_list, min_ip+idx);
+                if (mac_adr != NULL) {
+                    m_ip_info[idx] = new CClientInfo(has_mac_map);
+                    m_ip_info[idx]->set_ip(min_ip+idx);
+                    m_ip_info[idx]->set_mac(mac_adr);
+                }
+            }
+        } else {
+            for(int idx=0;idx<total_ip;idx++){
+                m_ip_info[idx] = new CClientInfo(has_mac_map);
+                m_ip_info[idx]->set_ip(min_ip+idx);
+            }
+        } 
     }
+    m_tcp_aging = tcp_aging;
+    m_udp_aging = udp_aging;
+    CreateBase();
 }
 
-void CTupleGeneratorSmart::Dump(FILE  *fd){
-    fprintf(fd," id: %x,  %x:%x -  %x \n client:%x - %x, server:%x-%x\n",m_id,m_result_client_ip,m_result_server_ip,m_result_client_port,m_min_client_ip, m_max_client_ip, m_min_server_ip, m_max_server_ip);
+void delay(int msec);
+
+bool CTupleGeneratorSmart::add_client_pool(IP_DIST_t  client_dist,
+                                          uint32_t min_client,
+                                          uint32_t max_client,
+                                          double l_flow,
+                                          double t_cps,
+                                          CFlowGenList* fl_list, 
+                                          uint16_t tcp_aging,
+                                          uint16_t udp_aging){
+    assert(max_client>=min_client);
+    CClientPool* pool = new CClientPool();
+    pool->Create(client_dist, min_client, max_client,
+                 l_flow, t_cps, fl_list, has_mac_mapping,
+                 tcp_aging, udp_aging);
+
+    m_client_pool.push_back(pool);
+    return(true);
+}
+
+bool CTupleGeneratorSmart::add_server_pool(IP_DIST_t  server_dist,
+                                          uint32_t min_server,
+                                          uint32_t max_server,
+                                          double l_flow,
+                                          double t_cps,
+                                          bool is_bundling){
+    assert(max_server>=min_server);
+    CServerPoolBase* pool;
+    if (is_bundling) 
+        pool = new CServerPool();
+    else
+        pool = new CServerPoolSimple();
+    // we currently only supports mac mapping file for client
+    pool->Create(server_dist, min_server, max_server,
+                 l_flow, t_cps);
+    m_server_pool.push_back(pool);
+    return(true);
 }
 
 
-void delay(int msec);
 
 bool CTupleGeneratorSmart::Create(uint32_t _id,
-                                     uint32_t thread_id,
-                                     IP_DIST_t  dist,
-                                     uint32_t min_client,
-                                     uint32_t max_client,
-                                     uint32_t min_server,
-                                     uint32_t max_server,
-                                     double l_flow,
-                                     double t_cps,
-                                     CFlowGenList* fl_list){
-
-    m_active_alloc=0;
-    if (dist>=cdMAX_DIST) {
-        m_client_dist = cdSEQ_DIST;
-    } else {
-        m_client_dist = dist;
-    }
-    m_min_client_ip = min_client;
-    m_max_client_ip = max_client;
-    m_min_server_ip = min_server;
-    m_max_server_ip = max_server;
-    assert(m_max_client_ip>=m_min_client_ip);
-    assert(m_max_server_ip>=m_min_server_ip);
-    assert((m_max_client_ip- m_min_client_ip)<50000);
-
-    uint32_t total_clients = getTotalClients();
-    /*printf("\ntotal_clients:%d, longest_flow:%f sec, total_cps:%f\n",
-            total_clients, l_flow, t_cps);*/
-    m_client.resize(m_max_client_ip-m_min_client_ip+1);
-    if (fl_list == NULL || !is_mac_info_conf(fl_list)) {
-        if (total_clients > ((l_flow*t_cps/MAX_PORT))) {
-            for (int idx=0;idx<m_client.size();idx++) 
-                m_client[idx] = new CClientInfoL();
-        } else {
-            for (int idx=0;idx<m_client.size();idx++) 
-                m_client[idx] = new CClientInfo();
-        }
-    } else {
-        if (total_clients > ((l_flow*t_cps/MAX_PORT))) {
-            for (int idx=0;idx<m_client.size();idx++) {
-                m_client[idx] = new CClientInfoL(
-                           get_mac_addr_by_ip(fl_list, min_client+idx)); 
-            }
-        } else {
-            for (int idx=0;idx<m_client.size();idx++) 
-                m_client[idx] = new CClientInfo(
-                           get_mac_addr_by_ip(fl_list, min_client+idx)); 
-        }
-    }
-    m_was_generated = false;
+                                  uint32_t thread_id,
+                                  bool has_mac)
+{
     m_thread_id     = thread_id;
-
     m_id = _id;
     m_was_init=true;
-    m_port_allocation_error=0;
+    has_mac_mapping = has_mac;
     return(true);
 }
 
 void CTupleGeneratorSmart::Delete(){
-    m_was_generated = false;
     m_was_init=false;
-    m_client_dist = cdSEQ_DIST;
+    has_mac_mapping = false;
 
-    for (int idx=0;idx<m_client.size();idx++){
-        delete m_client[idx];
+    for (int idx=0;idx<m_client_pool.size();idx++) {
+        m_client_pool[idx]->Delete();
+        delete m_client_pool[idx];
     }
-    m_client.clear();
-}
+    m_client_pool.clear();
 
-void CTupleGeneratorSmart::Generate_client_server(){
-    if (m_was_generated == false) {
-        /*first time */
-        m_was_generated = true;
-        m_cur_client_ip = m_min_client_ip;
-        m_cur_server_ip = m_min_server_ip;
+    for (int idx=0;idx<m_server_pool.size();idx++) {
+        m_server_pool[idx]->Delete();
+        delete m_server_pool[idx];
     }
+    m_server_pool.clear();
+}
 
-    uint32_t client_ip;
-    int i=0;
-    for (;i<100;i++) {
-        if (is_client_available(m_cur_client_ip)) {
-            break;
-        }
-        if (m_cur_client_ip >= m_max_client_ip) {
-            m_cur_client_ip = m_min_client_ip;
-        } else {
-            m_cur_client_ip++;
-        }
-    }
-    if (i>=100) {
-        printf(" ERROR ! sparse mac-ip files is not supported yet !\n"); 
-        exit(-1);
-    }
+void CTupleGenPoolYaml::Dump(FILE *fd){
+    fprintf(fd,"  dist            : %d \n",m_dist);
+    fprintf(fd,"  IPs         : %08x -%08x \n",m_ip_start,m_ip_end);
+    fprintf(fd,"  clients per gb  : %d  \n",m_number_of_clients_per_gb);
+    fprintf(fd,"  min clients     : %d  \n",m_min_clients);
+    fprintf(fd,"  tcp aging       : %d sec \n",m_tcp_aging_sec);
+    fprintf(fd,"  udp aging       : %d sec \n",m_udp_aging_sec);
+}
 
-    m_client_ip = m_cur_client_ip;
-    CClientInfoBase* client = get_client_by_ip(m_client_ip);
-    memcpy(&m_result_client_mac, 
-           client->get_mac_addr(),
-           sizeof(mac_addr_align_t));
-    m_result_client_ip = m_client_ip;
-    m_result_server_ip = m_cur_server_ip ;
-/*
-printf("ip:%x,mac:%x,%x,%x,%x,%x,%x, inused:%x\n",m_client_ip,
-       m_result_client_mac.mac[0],
-       m_result_client_mac.mac[1],
-       m_result_client_mac.mac[2],
-       m_result_client_mac.mac[3],
-       m_result_client_mac.mac[4],
-       m_result_client_mac.mac[5],
-       m_result_client_mac.inused);
-*/
-    m_cur_client_ip ++;
-    m_cur_server_ip ++;
-    if (m_cur_client_ip > m_max_client_ip) {
-        m_cur_client_ip = m_min_client_ip;
+bool CTupleGenPoolYaml::is_valid(uint32_t num_threads,bool is_plugins){
+    if ( m_ip_start > m_ip_end ){
+        printf(" ERROR The ip_start must be bigger than ip_end \n");
+        return(false);
     }
-    if (m_cur_server_ip > m_max_server_ip) {
-        m_cur_server_ip = m_min_server_ip;
+    
+    uint32_t ips= (m_ip_end - m_ip_start +1);
+    if ( ips < num_threads ) {
+        printf(" ERROR The number of ips should be at least number of threads %d \n",num_threads);
+        return (false);
     }
-}
 
-void CTupleGeneratorSmart::return_all_client_ports() {
-    for(int idx=0;idx<m_client.size();++idx) {
-        m_client.at(idx)->return_all_ports();
+    if (ips > 1000000) {
+        printf("  The number of clients requested is %d maximum supported : %d \n",ips,1000000);
+        return (false);
     }
+    return (true);
 }
 
 
-void CTupleGenYamlInfo::Dump(FILE *fd){
-    fprintf(fd,"  dist            : %d \n",m_client_dist);
-    fprintf(fd,"  clients         : %08x -%08x \n",m_clients_ip_start,m_clients_ip_end);
-    fprintf(fd,"  servers         : %08x -%08x \n",m_servers_ip_start,m_servers_ip_end);
-    fprintf(fd,"  clients per gb  : %d  \n",m_number_of_clients_per_gb);
-    fprintf(fd,"  min clients     : %d  \n",m_min_clients);
-    fprintf(fd,"  tcp aging       : %d sec \n",m_tcp_aging_sec);
-    fprintf(fd,"  udp aging       : %d sec \n",m_udp_aging_sec);
-}
 
 
 
-void operator >> (const YAML::Node& node, CTupleGenYamlInfo & fi) {
-    std::string tmp;
 
+
+void operator >> (const YAML::Node& node, CTupleGenPoolYaml & fi) {
+    std::string tmp;
+    node["name"] >> fi.m_name;
+    node["distribution"] >> tmp ;
+    if (tmp == "random") {
+        fi.m_dist=cdRANDOM_DIST;
+    }else if (tmp == "normal") {
+        fi.m_dist=cdNORMAL_DIST;
+    } else {
+        printf("\ndist,seq\n");
+        fi.m_dist=cdSEQ_DIST;
+    }
+    utl_yaml_read_ip_addr(node,"ip_start",fi.m_ip_start);
+    utl_yaml_read_ip_addr(node,"ip_end",fi.m_ip_end);
     try {
-     node["distribution"] >> tmp ;
-      if (tmp == "seq" ) {
-          fi.m_client_dist=cdSEQ_DIST;
-      }else{
-          if (tmp == "random") {
-              fi.m_client_dist=cdRANDOM_DIST;
-          }else{
-              if (tmp == "normal") {
-                  fi.m_client_dist=cdNORMAL_DIST;
-              }
-          }
-      }
-    }catch ( const std::exception& e ) {
-        fi.m_client_dist=cdSEQ_DIST;
+        utl_yaml_read_uint32(node,"clients_per_gb",fi.m_number_of_clients_per_gb);
+    } catch ( const std::exception& e ) {
+        fi.m_number_of_clients_per_gb = 0;
     }
-   utl_yaml_read_ip_addr(node,"clients_start",fi.m_clients_ip_start);
-   utl_yaml_read_ip_addr(node,"clients_end",fi.m_clients_ip_end);
-   utl_yaml_read_ip_addr(node,"servers_start",fi.m_servers_ip_start);
-   utl_yaml_read_ip_addr(node,"servers_end",fi.m_servers_ip_end);
-   utl_yaml_read_uint32(node,"clients_per_gb",fi.m_number_of_clients_per_gb);
-   utl_yaml_read_uint32(node,"min_clients",fi.m_min_clients);
-   utl_yaml_read_ip_addr(node,"dual_port_mask",fi.m_dual_interface_mask);
-   utl_yaml_read_uint16(node,"tcp_aging",fi.m_tcp_aging_sec);
-   utl_yaml_read_uint16(node,"udp_aging",fi.m_udp_aging_sec);
-
-}
-
-bool CTupleGenYamlInfo::is_valid(uint32_t num_threads,bool is_plugins){
-    if ( m_servers_ip_start > m_servers_ip_end ){
-        printf(" ERROR The servers_ip_start must be bigger than servers_ip_end \n");
-        return(false);
+    try {
+        utl_yaml_read_uint32(node,"min_clients",fi.m_min_clients);
+    } catch ( const std::exception& e ) {
+        fi.m_min_clients = 0;
     }
-
-    if ( m_clients_ip_start > m_clients_ip_end ){
-        printf(" ERROR The clients_ip_start must be bigger than clients_ip_end \n");
-        return(false);
+    try {
+        utl_yaml_read_ip_addr(node,"dual_port_mask",fi.m_dual_interface_mask);
+    } catch ( const std::exception& e ) {
+        fi.m_dual_interface_mask = 0;
     }
-    uint32_t servers= (m_servers_ip_end - m_servers_ip_start +1);
-    if ( servers < num_threads ) {
-        printf(" ERROR The number of servers should be at least number of threads %d \n",num_threads);
-        return (false);
+    try {
+        utl_yaml_read_uint16(node,"tcp_aging",fi.m_tcp_aging_sec);
+    } catch ( const std::exception& e ) {
+        fi.m_tcp_aging_sec = 0;
     }
-
-    uint32_t clients= (m_clients_ip_end - m_clients_ip_start +1);
-    if ( clients < num_threads ) {
-        printf(" ERROR The number of clients should be at least number of threads %d \n",num_threads);
-        return (false);
+    try {
+        utl_yaml_read_uint16(node,"udp_aging",fi.m_udp_aging_sec);
+    } catch ( const std::exception& e ) {
+        fi.m_udp_aging_sec = 0;
     }
+    try {
+        node["track_ports"] >> fi.m_is_bundling;
+    } catch ( const std::exception& e ) {
+        fi.m_is_bundling = false;
+    }
+}
+void copy_global_pool_para(CTupleGenPoolYaml & src, CTupleGenPoolYaml & dst) {
+    if (src.m_number_of_clients_per_gb == 0)
+        src.m_number_of_clients_per_gb = dst.m_number_of_clients_per_gb;
+    if (src.m_min_clients == 0)
+        src.m_min_clients = dst.m_min_clients;
+    if (src.m_dual_interface_mask == 0)
+        src.m_dual_interface_mask = dst.m_dual_interface_mask;
+    if (src.m_tcp_aging_sec == 0)
+        src.m_tcp_aging_sec = dst.m_tcp_aging_sec;
+    if (src.m_udp_aging_sec == 0)
+        src.m_udp_aging_sec = dst.m_udp_aging_sec;
+}
+void operator >> (const YAML::Node& node, CTupleGenYamlInfo & fi) {
+    std::string tmp;
 
-    /* defect for plugin  */
-    if (is_plugins) {
-        if ( getTotalServers() < getTotalClients() ){
-            printf(" Plugin is configured. in that case due to a limitation ( defect trex-54 ) \n");
-            printf(" the number of servers should be bigger than number of clients  \n");
-            return (false);
+    try {
+        CTupleGenPoolYaml c_pool;
+        CTupleGenPoolYaml s_pool;
+        node["distribution"] >> tmp ;
+        if (tmp == "random") {
+            c_pool.m_dist=cdRANDOM_DIST;
+        }else if (tmp == "normal") {
+            c_pool.m_dist=cdNORMAL_DIST;
+        } else {
+            c_pool.m_dist=cdSEQ_DIST;
         }
-
-        /* update number of servers in a way that it would be exact multiplication */
-        uint32_t mul=getTotalServers() / getTotalClients();
-        uint32_t new_server_num=mul*getTotalClients();
-        m_servers_ip_end = m_servers_ip_start + new_server_num-1 ;
-
-        assert(getTotalServers() %getTotalClients() ==0);
+        s_pool.m_dist = c_pool.m_dist;
+        utl_yaml_read_ip_addr(node,"clients_start",c_pool.m_ip_start);
+        utl_yaml_read_ip_addr(node,"clients_end",c_pool.m_ip_end);
+        utl_yaml_read_ip_addr(node,"servers_start",s_pool.m_ip_start);
+        utl_yaml_read_ip_addr(node,"servers_end",s_pool.m_ip_end);
+        utl_yaml_read_uint32(node,"clients_per_gb",c_pool.m_number_of_clients_per_gb);
+        utl_yaml_read_uint32(node,"min_clients",c_pool.m_min_clients);
+        utl_yaml_read_ip_addr(node,"dual_port_mask",c_pool.m_dual_interface_mask);
+        utl_yaml_read_uint16(node,"tcp_aging",c_pool.m_tcp_aging_sec);
+        utl_yaml_read_uint16(node,"udp_aging",c_pool.m_udp_aging_sec);
+        s_pool.m_dual_interface_mask = c_pool.m_dual_interface_mask;
+        fi.m_client_pool.push_back(c_pool);
+        fi.m_server_pool.push_back(s_pool);
+    }catch ( const std::exception& e ) {
+        printf("No default generator defined.\n");
     }
+    try{
+        const YAML::Node& c_pool_info = node["generator_clients"];
+        for (uint16_t idx=0;idx<c_pool_info.size();idx++) {
+            CTupleGenPoolYaml pool;
+            try {
+                c_pool_info[idx] >> pool;
+            } catch ( const std::exception& e ) {
+                printf("client pool in YAML is wrong\n");
+            }
+            if (fi.m_client_pool.size()>0) {
+                copy_global_pool_para(pool, fi.m_client_pool[0]);
+            }
+            fi.m_client_pool.push_back(pool);
+        }
+    }catch ( const std::exception& e ) {
+        printf("no client generator pool configured, using default pool\n");
+    } 
+    try {
+        const YAML::Node& s_pool_info = node["generator_servers"];
+        for (uint16_t idx=0;idx<s_pool_info.size();idx++) {
+            CTupleGenPoolYaml pool;
+            try {
+                s_pool_info[idx] >> pool;
+            } catch ( const std::exception& e ) {
+                printf("server pool in YAML is wrong\n");
+            }
+            if (fi.m_server_pool.size()>0) {
+                copy_global_pool_para(pool, fi.m_server_pool[0]);
+            }
+            fi.m_server_pool.push_back(pool);
+        }
+    }catch ( const std::exception& e ) {
+        printf("no server generator pool configured, using default pool\n");
+    } 
+}
 
-/*    if (clients > 00000) {
-        printf("  The number of clients requested is %d maximum supported : %d \n",clients,100000);
-        return (false);
+bool CTupleGenYamlInfo::is_valid(uint32_t num_threads,bool is_plugins){
+    for (int i=0;i<m_client_pool.size();i++) {
+        if (m_client_pool[i].is_valid(num_threads, is_plugins)==false) 
+            return false;
     }
- */   return (true);
+    for (int i=0;i<m_server_pool.size();i++) {
+        if (m_server_pool[i].is_valid(num_threads, is_plugins)==false) 
+            return false;
+    }
+    return true;
 }
 
 
 /* split the clients and server by dual_port_id and thread_id ,
   clients is splited by threads and dual_port_id
   servers is spliteed by dual_port_id */
-void split_clients(uint32_t thread_id, 
-                   uint32_t total_threads, 
-                   uint32_t dual_port_id,
-                   CTupleGenYamlInfo & fi,
-                   CClientPortion & portion){
-
-    uint32_t clients_chunk = fi.getTotalClients()/total_threads;
-    // FIXME need to fix this when fixing the server 
-    uint32_t servers_chunk = fi.getTotalServers()/total_threads;
-
-    assert(clients_chunk>0);
-    assert(servers_chunk>0);
+void split_ips(uint32_t thread_id, 
+               uint32_t total_threads, 
+               uint32_t dual_port_id,
+               CTupleGenPoolYaml& poolinfo,
+               CIpPortion & portion){
 
-    uint32_t dual_if_mask=(dual_port_id*fi.m_dual_interface_mask);
+    uint32_t chunks = poolinfo.getTotalIps()/total_threads;
 
-    portion.m_client_start  = fi.m_clients_ip_start  + thread_id*clients_chunk + dual_if_mask;
-    portion.m_client_end    = portion.m_client_start + clients_chunk -1 ;
+    assert(chunks>0);
 
-    portion.m_server_start  = fi.m_servers_ip_start  + thread_id*servers_chunk +dual_if_mask;
-    portion.m_server_end    = portion.m_server_start   + servers_chunk -1;
+    uint32_t dual_if_mask=(dual_port_id*poolinfo.getDualMask());
+    
+    portion.m_ip_start  = poolinfo.get_ip_start()  + thread_id*chunks + dual_if_mask;
+    portion.m_ip_end    = portion.m_ip_start + chunks -1 ;
 }
index 96b9b01..fb85653 100755 (executable)
@@ -1,8 +1,9 @@
 #ifndef TUPLE_GEN_H_
 #define TUPLE_GEN_H_
+
 /*
- Wenxian Li 
+ Wenxian Li
+
  Cisco Systems, Inc.
 */
 
@@ -22,7 +23,6 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
@@ -39,9 +39,14 @@ limitations under the License.
 #include <yaml-cpp/yaml.h>
 
 
+#include <random>
+
+
+
 /*
  * Class that handle the client info
  */
+#define MAX_CLIENTS 1000000
 #define MAX_PORT (64000)
 #define MIN_PORT (1024)
 #define ILLEGAL_PORT (0)
@@ -52,6 +57,8 @@ limitations under the License.
 /*FIXME*/
 #define VLAN_SIZE (2)
 
+#define FOREACH(vector) for(int i=0;i<vector.size();i++)
+
 /* Client distribution */
 
 
@@ -62,14 +69,21 @@ typedef enum  {
     cdMAX_DIST    = 3
 } IP_DIST_t ;
 
+#define INUSED 0
+#define UNUSED 1
 typedef struct mac_addr_align_ {
 public:
     uint8_t mac[6];
     uint8_t inused;
     uint8_t pad;
 } mac_addr_align_t;
-#define INUSED 0
-#define UNUSED 1
+
+typedef struct mac_mapping_ {
+    mac_addr_align_t mac;
+    uint32_t         ip;
+} mac_mapping_t;
+
+
 
 /* For type 1, we generator port by maintaining a 64K bit array for each port.
  * In this case, we cannot support large number of clients due to memory exhausted. 
@@ -85,39 +99,31 @@ public:
 #define TYPE2 1
 #define MAX_TYPE 3
 
-class CClientInfoBase {
+
+class CIpInfoBase {
     public:
+        virtual mac_addr_align_t* get_mac() { return NULL;}
+        virtual void set_mac(mac_addr_align_t*){;}
         virtual uint16_t get_new_free_port() = 0;
         virtual void return_port(uint16_t a) = 0;
         virtual void return_all_ports() = 0;
-        virtual bool is_client_available() = 0;
-        virtual mac_addr_align_t* get_mac_addr() = 0; 
+        uint32_t get_ip() {
+            return m_ip;
+        }
+        void set_ip(uint32_t ip) {
+            m_ip = ip;
+        }
+    public:
+        uint32_t          m_ip;
 };
 
 //CClientInfo for large amount of clients support
-class CClientInfoL : public CClientInfoBase {
-    mac_addr_align_t mac;
+class CIpInfoL : public CIpInfoBase {
  private:
     uint16_t m_curr_port;
  public:
-    CClientInfoL(mac_addr_align_t* mac_adr) {
-        m_curr_port = MIN_PORT;
-        if (mac_adr) {
-            mac = *mac_adr;
-            mac.inused = INUSED;
-        } else {
-            memset(&mac, 0, sizeof(mac_addr_align_t));
-            mac.inused = UNUSED;
-        }
-    }
-
-    CClientInfoL() {
+    CIpInfoL() {
         m_curr_port = MIN_PORT;
-        memset(&mac, 0, sizeof(mac_addr_align_t));
-        mac.inused = INUSED;
-    }
-    mac_addr_align_t* get_mac_addr() {
-        return &mac;
     }
     uint16_t get_new_free_port() {
         if (m_curr_port>MAX_PORT) {
@@ -132,22 +138,13 @@ class CClientInfoL : public CClientInfoBase {
     void return_all_ports() {
         m_curr_port = MIN_PORT;
     }
-
-    bool is_client_available() {
-        if (mac.inused == INUSED) {
-            return true;
-        } else {
-            return false;
-        }
-    }
 };
 
 
-class CClientInfo : public CClientInfoBase {
+class CIpInfo : public CIpInfoBase {
  private:
     std::bitset<MAX_PORT>  m_bitmap_port;
     uint16_t m_head_port;
-    mac_addr_align_t mac;
     friend class CClientInfoUT;
 
  private:
@@ -200,27 +197,9 @@ class CClientInfo : public CClientInfoBase {
 
 
  public:
-    CClientInfo() {
+    CIpInfo() {
         m_head_port = MIN_PORT;
         m_bitmap_port.reset();
-        memset(&mac, 0, sizeof(mac_addr_align_t));
-        mac.inused = INUSED;
-    }
-    CClientInfo(mac_addr_align_t* mac_info) {
-        m_head_port = MIN_PORT;
-        m_bitmap_port.reset();
-        if (mac_info) {
-            mac = *mac_info;
-            mac.inused = INUSED;
-        } else {
-            memset(&mac, 0, sizeof(mac_addr_align_t));
-            mac.inused = UNUSED;
-        }
-    }
-
-    mac_addr_align_t* get_mac_addr() {
-        return &mac;
     }
 
     uint16_t get_new_free_port() {
@@ -251,30 +230,109 @@ class CClientInfo : public CClientInfoBase {
         m_head_port = MIN_PORT;
         m_bitmap_port.reset();
     }
-    bool is_client_available() {
-        if (mac.inused == INUSED) {
-            return true;
+};
+
+class CClientInfo : public CIpInfo {
+    public:
+        CClientInfo (bool has_mac) {
+            if (has_mac==true) {
+                m_mac = new mac_addr_align_t();
+            } else {
+                m_mac = NULL;
+            }
+        }
+        CClientInfo () {
+            m_mac = NULL;
+        }
+        mac_addr_align_t* get_mac() {
+            return m_mac;
+        }
+        void set_mac(mac_addr_align_t *mac) {
+            memcpy(m_mac, mac, sizeof(mac_addr_align_t));
+        }
+        ~CClientInfo() {
+            if (m_mac!=NULL){
+                delete m_mac;
+            }
+        }
+    private:
+        mac_addr_align_t *m_mac;
+};
+
+class CClientInfoL : public CIpInfoL {
+public:
+    CClientInfoL (bool has_mac) {
+        if (has_mac==true) {
+            m_mac = new mac_addr_align_t();
         } else {
-            return false;
+            m_mac = NULL;
         }
     }
+    CClientInfoL () {
+        m_mac = NULL;
+    }
+    mac_addr_align_t* get_mac() {
+        return m_mac;
+    }
+    void set_mac(mac_addr_align_t *mac) {
+        memcpy(m_mac, mac, sizeof(mac_addr_align_t));
+    }
+    ~CClientInfoL() {
+        if (m_mac!=NULL) {
+            delete m_mac;
+        }
+    }
+private:
+    mac_addr_align_t *m_mac;
+};
 
+class CServerInfo : public CIpInfo {
+    ;
 };
 
+class CServerInfoL : public CIpInfoL {
+    ;
+};
+
+
 class CTupleBase {
 public:
+       CTupleBase() {
+           m_client_mac.inused = UNUSED;
+       }
        uint32_t getClient() {
            return m_client_ip;
        }
        void setClient(uint32_t ip) {
            m_client_ip = ip;
        }
+       uint32_t getClientId() {
+           return m_client_idx;
+       }
+       void setClientId(uint32_t id) {
+           m_client_idx = id;
+       }
+       
        uint32_t getServer(){
            return m_server_ip;
        }
        void setServer(uint32_t ip) {
            m_server_ip = ip;
        }
+       uint32_t getServerId(){
+           return m_server_idx;
+       }
+       void setServerId(uint32_t id) {
+           m_server_idx = id;
+       }
+       uint16_t getServerPort() {
+           return m_server_port;
+       }
+       void setServerPort(uint16_t port) {
+           m_server_port = port;
+       }
        uint16_t getClientPort() {
            return m_client_port;
        }
@@ -285,16 +343,21 @@ public:
            return &m_client_mac;
        }
        void setClientMac(mac_addr_align_t* mac_info) {
-           memcpy(&m_client_mac, mac_info, sizeof(mac_addr_align_t));
+           if (mac_info != NULL) {
+               memcpy(&m_client_mac, mac_info, sizeof(mac_addr_align_t));
+               m_client_mac.inused = INUSED;
+           } else {
+               m_client_mac.inused = UNUSED;
+           }
        }
 private:
        uint32_t m_client_ip;
+       uint32_t m_client_idx;
        uint32_t m_server_ip;
-       uint16_t m_client_port;
-       uint16_t pad1;
-       uint32_t pad2;
+       uint32_t m_server_idx;
        mac_addr_align_t m_client_mac;
-       uint32_t pad3[3];
+       uint16_t m_client_port;
+       uint16_t m_server_port;
 };
 
 
@@ -304,43 +367,259 @@ mac_addr_align_t * get_mac_addr_by_ip(CFlowGenList *fl_list,
                                              uint32_t ip);
 bool is_mac_info_conf(CFlowGenList *fl_list);
 
-/* generate for each template */
-class CTupleGeneratorSmart {
+class CIpPool {
+    public:
+       uint16_t GenerateOnePort(uint32_t idx) {
+            CIpInfoBase* ip_info = m_ip_info[idx];
+            uint16_t port;
+            port = ip_info->get_new_free_port();
+            
+            //printf(" alloc extra  %x %d \n",c_ip,port);
+            if (port==ILLEGAL_PORT) {
+                m_port_allocation_error++;
+            }
+            m_active_alloc++;
+            return (port);
+        }
+        bool is_valid_ip(uint32_t ip){
+            CIpInfoBase* ip_front = m_ip_info.front();
+            CIpInfoBase* ip_back  = m_ip_info.back();
+            if ((ip>=ip_front->get_ip()) && 
+                (ip<=ip_back->get_ip())) {
+                return(true);
+            }
+            printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%x\n", 
+                   ip, ip_front->get_ip(), 
+                   ip_back->get_ip(),this);
+            return(false);
+        }
+
+        uint32_t get_curr_ip() {
+            return m_ip_info[m_cur_idx]->get_ip();
+        }
+        uint32_t get_ip(uint32_t idx) {
+            return m_ip_info[idx]->get_ip();
+        }
+        CIpInfoBase* get_ip_info_by_idx(uint32_t idx) {
+            return m_ip_info[idx];
+        }
+
+        void inc_cur_idx() {
+            switch (m_dist) {
+            case cdRANDOM_DIST: 
+                m_cur_idx = get_random_idx();
+                break;
+            case cdSEQ_DIST :
+            default:
+                m_cur_idx++;
+                if (m_cur_idx >= m_ip_info.size())
+                    m_cur_idx = 0;
+            }
+        }
+        //return a valid client idx in this pool
+        uint32_t generate_ip() {
+            uint32_t res_idx = m_cur_idx;
+            inc_cur_idx();
+            return res_idx;
+        }
+        void set_dist(IP_DIST_t dist) {
+            if (dist>=cdMAX_DIST) {
+                m_dist = cdSEQ_DIST;
+            } else {
+                m_dist = dist;
+            }
+        }
+        void Delete() {
+            FOREACH(m_ip_info) {
+                delete m_ip_info[i];
+            }
+            m_ip_info.clear();
+        }
+        uint32_t get_total_ips() {
+            return m_ip_info.size();
+        }
+        void return_all_ports() {
+            FOREACH(m_ip_info) {
+                m_ip_info[i]->return_all_ports();
+            }
+        }
+        void FreePort(uint32_t id, uint16_t port) {
+    //        assert(id<m_ip_info.size());
+            m_active_alloc--;
+            CIpInfoBase* client = m_ip_info[id];
+            client->return_port(port);
+        }
+        
+        mac_addr_align_t * get_curr_mac() {
+            return m_ip_info[m_cur_idx]->get_mac();
+        }
+        mac_addr_align_t *get_mac(uint32_t idx) {
+            return m_ip_info[idx]->get_mac();
+        }
+    public:
+        std::vector<CIpInfoBase*> m_ip_info;
+        IP_DIST_t  m_dist;
+        uint32_t m_cur_idx;
+        uint32_t m_active_alloc;
+        uint32_t m_port_allocation_error;
+        std::default_random_engine generator;
+        std::uniform_int_distribution<int> *rand_dis;
+        void CreateBase() {
+            switch (m_dist) {
+            case cdRANDOM_DIST:
+                rand_dis = new std::uniform_int_distribution<int>
+                    (0,get_total_ips()-1);
+                break;
+            default:
+                break;
+            }
+            m_cur_idx = 0;
+            m_active_alloc = 0;
+            m_port_allocation_error = 0;
+        }
+        uint32_t get_random_idx() {
+            uint32_t res =  (*rand_dis)(generator);
+            return (res);
+        }
+        bool IsFreePortRequired(void){
+            return(true);
+        }
+
+
+};
+
+class CClientPool : public CIpPool {
 public:
-    /* simple tuple genertion for one low*/
-    void GenerateTuple(CTupleBase & tuple);
-    /*
-     * allocate base tuple with n exta ports, used by bundels SIP
-     * for example need to allocat 3 ports for this C/S
-     */
-    void GenerateTupleEx(CTupleBase & tuple,uint8_t extra_ports_no,
-                         uint16_t * extra_ports);
+    void GenerateTuple(CTupleBase & tuple) {
+       uint32_t idx = generate_ip();
+       tuple.setClientId(idx);
+       tuple.setClient(get_ip(idx));
+       tuple.setClientMac(get_mac(idx));
+       tuple.setClientPort(GenerateOnePort(idx));
+    }
+    uint16_t get_tcp_aging() {
+        return m_tcp_aging;
+    }
+    uint16_t get_udp_aging() {
+        return m_udp_aging;
+    }
+    void Create(IP_DIST_t  dist_value,
+                uint32_t min_ip,
+                uint32_t max_ip,
+                double l_flow,
+                double t_cps,
+                CFlowGenList* fl_list,
+                bool has_mac_map, 
+                uint16_t tcp_aging,
+                uint16_t udp_aging); 
+public: 
+    uint16_t m_tcp_aging;
+    uint16_t m_udp_aging;
+};
+
+class CServerPoolBase {
+    public:
+    virtual void GenerateTuple(CTupleBase& tuple) = 0;
+    virtual uint16_t GenerateOnePort(uint32_t idx) = 0;
+    virtual void Delete() = 0;
+    virtual uint32_t get_total_ips()=0;
+    virtual void Create(IP_DIST_t  dist_value,
+               uint32_t min_ip,
+               uint32_t max_ip,
+               double l_flow,
+               double t_cps) = 0; 
+};
 
-    /* free client port */
-    void FreePort(uint32_t c_ip,
-                  uint16_t port){
-        //printf(" free %x %d \n",c_ip,port);
-        m_active_alloc--;
-        CClientInfoBase* client = get_client_by_ip(c_ip);
-        client->return_port(port);
+class CServerPoolSimple : public CServerPoolBase {
+public:
+    void Create(IP_DIST_t  dist_value,
+               uint32_t min_ip,
+               uint32_t max_ip,
+               double l_flow,
+               double t_cps) {
+        m_max_server_ip = max_ip;
+        m_min_server_ip = min_ip;
+        m_cur_server_ip = min_ip;
+    }
+    void Delete() {
+        return ;
+    }
+    void GenerateTuple(CTupleBase& tuple) {
+        tuple.setServer(m_cur_server_ip);
+        m_cur_server_ip ++;
+        if (m_cur_server_ip > m_max_server_ip) {
+            m_cur_server_ip = m_min_server_ip;
+        }
+    } 
+    uint16_t GenerateOnePort(uint32_t idx) {
+        // do nothing
+        return 0;
+    }
+    uint32_t get_total_ips() {
+        return (m_max_server_ip-m_min_server_ip+1);
     }
+private:
+    uint32_t m_max_server_ip;
+    uint32_t m_min_server_ip;
+    uint32_t m_cur_server_ip;
+};
 
-    /* return true if this type of generator require to free resource */
-    bool IsFreePortRequired(void){
-        return(true);
+class CServerPool : public CServerPoolBase {
+public:
+    CIpPool *gen;
+    void GenerateTuple(CTupleBase & tuple) {
+       uint32_t idx = gen->generate_ip();
+       tuple.setServerId(idx);
+       tuple.setServer(gen->get_ip(idx));
+    }
+    uint16_t GenerateOnePort(uint32_t idx) {
+        return gen->GenerateOnePort(idx);
+    }
+    void Create(IP_DIST_t  dist_value,
+                uint32_t min_ip,
+                uint32_t max_ip,
+                double l_flow,
+                double t_cps); 
+    void Delete() {
+        if (gen!=NULL) {
+            gen->Delete();
+            delete gen;
+        }
+    }
+    uint32_t get_total_ips() {
+        return gen->m_ip_info.size();
     }
+};
 
+/* generate for each template */
+class CTupleGeneratorSmart {
+public:
     /* return the active socket */
     uint32_t ActiveSockets(void){
-        return (m_active_alloc);
+        uint32_t total_active_alloc = 0;
+        FOREACH(m_client_pool) {
+            total_active_alloc += m_client_pool[i]->m_active_alloc;
+        }
+        return (total_active_alloc);
     }
 
     uint32_t getTotalClients(void){
-        return (m_max_client_ip -m_min_client_ip +1);
+        uint32_t total_clients = 0;
+        FOREACH(m_client_pool) {
+            total_clients += m_client_pool[i]->get_total_ips();
+        }
+        return (total_clients);
     }
 
     uint32_t getTotalServers(void){
-        return (m_max_server_ip -m_min_server_ip +1);
+        uint32_t total_servers = 0;
+        FOREACH(m_server_pool) {
+            total_servers += m_server_pool[i]->get_total_ips();
+        }
+        return total_servers;
     }
 
     uint32_t SocketsPerClient(void){
@@ -351,136 +630,103 @@ public:
         return (SocketsPerClient() * getTotalClients());
     }
 
+    
+    void FreePort(uint8_t pool_idx, uint32_t id, uint16_t port) {
+        get_client_pool(pool_idx)->FreePort(id, port);
+    }
+        
+    bool IsFreePortRequired(uint8_t pool_idx){
+        return(get_client_pool(pool_idx)->IsFreePortRequired());
+    }
+    uint16_t get_tcp_aging(uint8_t pool_idx) {
+        return (get_client_pool(pool_idx)->get_tcp_aging());
+    }
+    uint16_t get_udp_aging(uint8_t pool_idx) {
+        return (get_client_pool(pool_idx)->get_udp_aging());
+    }
 
 public:
     CTupleGeneratorSmart(){
         m_was_init=false;
-        m_client_dist = cdSEQ_DIST;
+        has_mac_mapping = false;
     }
     bool Create(uint32_t _id,
-            uint32_t thread_id,
-            IP_DIST_t  dist,
-            uint32_t min_client,
-            uint32_t max_client,
-            uint32_t min_server,
-            uint32_t max_server,
-            double longest_flow,
-            double total_cps,
-            CFlowGenList * fl_list = NULL);
+            uint32_t thread_id, bool has_mac=false);
 
     void Delete();
 
-    void Dump(FILE  *fd);
-
-    void SetClientDist(IP_DIST_t dist) {
-        m_client_dist = dist;
-    }
-
-    IP_DIST_t GetClientDist() {
-        return (m_client_dist);
-    }
-
     inline uint32_t GetThreadId(){
         return (  m_thread_id );
     }
 
-    bool is_valid_client(uint32_t c_ip){
-        if ((c_ip>=m_min_client_ip) && (c_ip<=m_max_client_ip)) {
-            return(true);
-        }
-        printf("invalid client ip:%x, min_ip:%x, max_ip:%x\n", 
-               c_ip, m_min_client_ip, m_max_client_ip);
-        return(false);
-    }
-
-    CClientInfoBase* get_client_by_ip(uint32_t c_ip){
-        BP_ASSERT( is_valid_client(c_ip) );
-        return m_client.at(c_ip-m_min_client_ip);
-    }
-
-    bool is_client_available (uint32_t c_ip) {
-        CClientInfoBase* client = get_client_by_ip(c_ip);
-        if (client) {
-            return client->is_client_available();
-        }
-        return false;
-    }
-
-    uint16_t GenerateOneClientPort(uint32_t c_ip) {
-        CClientInfoBase* client = get_client_by_ip(c_ip);
-        uint16_t port;
-        port = client->get_new_free_port();
-        
-        //printf(" alloc extra  %x %d \n",c_ip,port);
-        if (port==ILLEGAL_PORT) {
-            m_port_allocation_error++;
-        }
-        m_active_alloc++;
-        return (port);
-    }
-
     uint32_t getErrorAllocationCounter(){
-        return ( m_port_allocation_error  );
+        uint32_t total_alloc_error = 0;
+        FOREACH(m_client_pool) {
+            total_alloc_error += m_client_pool[i]->m_port_allocation_error;
+        }
+        return (total_alloc_error);
+    }
+
+    bool add_client_pool(IP_DIST_t  client_dist,
+                         uint32_t min_client,
+                         uint32_t max_client,
+                         double l_flow,
+                         double t_cps,
+                         CFlowGenList* fl_list,
+                         uint16_t tcp_aging,
+                         uint16_t udp_aging);
+    bool add_server_pool(IP_DIST_t  server_dist,
+                         uint32_t min_server,
+                         uint32_t max_server,
+                         double l_flow,
+                         double t_cps,
+                         bool is_bundling);
+    CClientPool* get_client_pool(uint8_t idx) {
+        return m_client_pool[idx];
+    }
+    uint8_t get_client_pool_num() {
+        return m_client_pool.size();
+    }
+    uint8_t get_server_pool_num() {
+        return m_server_pool.size();
+    }
+    CServerPoolBase* get_server_pool(uint8_t idx) {
+        return m_server_pool[idx];
     }
-
-private:
-    void return_all_client_ports();
-
-
-    void Generate_client_server();
-
-
 private:
-    std::vector<CClientInfoBase*> m_client;
-
     uint32_t m_id;
-    bool     m_was_generated;
-    bool     m_was_init;
-
-    IP_DIST_t  m_client_dist;
-
-    uint32_t m_cur_server_ip;
-    uint32_t m_cur_client_ip;
-    // min-max client ip +1 and get back
-    uint32_t m_min_client_ip;
-    uint32_t m_max_client_ip;
-
-    // min max server ip ( random )
-    uint32_t m_min_server_ip;
-    uint32_t m_max_server_ip;
-
     uint32_t m_thread_id;
-
-    // result of the generator FIXME need to clean this
-    uint32_t    m_client_ip;
-    uint32_t m_result_client_ip;
-    uint32_t m_result_server_ip;
-    uint32_t m_active_alloc;
-    mac_addr_align_t m_result_client_mac;
-    uint16_t m_result_client_port;
-            
-    uint32_t m_port_allocation_error;
-
+    std::vector<CClientPool*> m_client_pool;
+    std::vector<CServerPoolBase*> m_server_pool;
+    bool     m_was_init;
+    bool     has_mac_mapping;
 };
 
-
 class CTupleTemplateGeneratorSmart {
 public:
     /* simple tuple genertion for one low*/
     void GenerateTuple(CTupleBase & tuple){
         if (m_w==1) {
             /* new client each tuple generate */
-            m_gen->GenerateTuple(tuple);
-            m_cache_client_ip=tuple.getClient();
+            m_client_gen->GenerateTuple(tuple);
+            m_server_gen->GenerateTuple(tuple);
+            m_cache_client_ip = tuple.getClient();
+            m_cache_client_idx = tuple.getClientId();
         }else{
             if (m_cnt==0) {
-                m_gen->GenerateTuple(tuple);
+                m_client_gen->GenerateTuple(tuple);
+                m_server_gen->GenerateTuple(tuple);
                 m_cache_client_ip = tuple.getClient();
+                m_cache_client_idx = tuple.getClientId();
                 m_cache_server_ip = tuple.getServer();
+                m_cache_server_idx = tuple.getServerId();
             }else{
                 tuple.setServer(m_cache_server_ip);
+                tuple.setServerId(m_cache_server_idx);
                 tuple.setClient(m_cache_client_ip);
-                tuple.setClientPort( m_gen->GenerateOneClientPort(m_cache_client_ip));
+                tuple.setClientId(m_cache_client_idx);
+                tuple.setClientPort(
+                         m_client_gen->GenerateOnePort(m_cache_client_idx));
             }
             m_cnt++;
             if (m_cnt>=m_w) {
@@ -493,7 +739,7 @@ public:
     }
 
     uint16_t GenerateOneSourcePort(){
-        return ( m_gen->GenerateOneClientPort(m_cache_client_ip) );
+        return ( m_client_gen->GenerateOnePort(m_cache_client_idx) );
     }
 
     inline uint32_t GetThreadId(){
@@ -502,12 +748,13 @@ public:
 
 public:
 
-    bool Create( CTupleGeneratorSmart * gen
-                 ){
+    bool Create( CTupleGeneratorSmart * gen,uint8_t c_pool,uint8_t s_pool){
         m_gen=gen;
         m_is_single_server=false;
         m_server_ip=0;
         SetW(1);
+        m_client_gen = gen->get_client_pool(c_pool);
+        m_server_gen = gen->get_server_pool(s_pool);
         return (true);
     }
 
@@ -535,15 +782,21 @@ public:
         return (m_is_single_server);
     }
 
+    CTupleGeneratorSmart * get_gen() {
+        return m_gen;
+    }
 private:
     CTupleGeneratorSmart * m_gen;
-    bool                   m_is_single_server;
+    CClientPool          * m_client_gen;
+    CServerPoolBase      * m_server_gen;
     uint16_t               m_w;
     uint16_t               m_cnt;
     uint32_t               m_server_ip;
     uint32_t               m_cache_client_ip;
+    uint32_t               m_cache_client_idx;
     uint32_t               m_cache_server_ip;
-
+    uint32_t               m_cache_server_idx;
+    bool                   m_is_single_server;
 };
 
 
@@ -559,61 +812,70 @@ private:
         -  dual_interface_mask      : 1.0.0.0  // each dual ports will add this to the pool of clients 
 #endif
 
-struct CTupleGenYamlInfo {
-    CTupleGenYamlInfo(){
-        m_client_dist=cdSEQ_DIST;
-        m_clients_ip_start =0x11000000; 
-        m_clients_ip_end   =0x21000000;
-
-        m_servers_ip_start = 0x30000000;
-        m_servers_ip_end   = 0x40000000;
-        m_number_of_clients_per_gb=10;
-        m_min_clients=100;
-        m_dual_interface_mask=0x10000000;
-        m_tcp_aging_sec=2;
-        m_udp_aging_sec=5;
-    }
-
-    IP_DIST_t       m_client_dist;
-    uint32_t        m_clients_ip_start;
-    uint32_t        m_clients_ip_end;
-
-    uint32_t        m_servers_ip_start;
-    uint32_t        m_servers_ip_end;
+struct CTupleGenPoolYaml {
+    IP_DIST_t       m_dist;
+    uint32_t        m_ip_start;
+    uint32_t        m_ip_end;
     uint32_t        m_number_of_clients_per_gb;
     uint32_t        m_min_clients;
     uint32_t        m_dual_interface_mask;
     uint16_t        m_tcp_aging_sec; /* 0 means there is no aging */
     uint16_t        m_udp_aging_sec;
+    std::string     m_name;
+    bool            m_is_bundling;
+    public:
+    uint32_t getTotalIps(void){
+        return ( m_ip_end-m_ip_start+1);
+    }
+    uint32_t getDualMask() {
+        return m_dual_interface_mask;
+    }
+    uint32_t get_ip_start() {
+        return m_ip_start;
+    }
+    bool is_valid(uint32_t num_threads,bool is_plugins);
+    void Dump(FILE *fd);
+};
+   
 
+struct CTupleGenYamlInfo {
+    std::vector<CTupleGenPoolYaml> m_client_pool;
+    std::vector<CTupleGenPoolYaml> m_server_pool;
+        
 public:
-    void Dump(FILE *fd);
-    uint32_t getTotalClients(void){
-        return ( m_clients_ip_end-m_clients_ip_start+1);
+    bool is_valid(uint32_t num_threads,bool is_plugins);
+    uint8_t get_server_pool_id(std::string name){
+        for (uint8_t i=0;i<m_server_pool.size();i++) {
+            if (m_server_pool[i].m_name==name) 
+                return i;
+        }
+        return 0;
     }
-    uint32_t getTotalServers(void){
-        return ( m_servers_ip_end-m_servers_ip_start+1);
+
+    uint8_t get_client_pool_id(std::string name){
+        for (uint8_t i=0;i<m_client_pool.size();i++) {
+            if (m_client_pool[i].m_name==name) 
+                return i;
+        }
+        return 0;
     }
+};
 
 
-    bool is_valid(uint32_t num_threads,bool is_plugins);
-};
+void operator >> (const YAML::Node& node, CTupleGenPoolYaml & fi) ;
 
 void operator >> (const YAML::Node& node, CTupleGenYamlInfo & fi) ;
 
 
-struct CClientPortion {
-    uint32_t m_client_start;
-    uint32_t m_client_end;
-    uint32_t m_server_start;
-    uint32_t m_server_end;
+struct CIpPortion {
+    uint32_t m_ip_start;
+    uint32_t m_ip_end;
 };
-
-void split_clients(uint32_t thread_id, 
-                   uint32_t total_threads, 
+void split_ips(uint32_t thread_id,
+                   uint32_t total_threads,
                    uint32_t dual_port_id,
-                   CTupleGenYamlInfo & fi,
-                   CClientPortion & portion);
+                   CTupleGenPoolYaml& poolinfo,
+                   CIpPortion & portion);