tuple_gen.h revision fb823791
1#ifndef TUPLE_GEN_H_
2#define TUPLE_GEN_H_
3
4/*
5 Wenxian Li
6
7 Cisco Systems, Inc.
8*/
9
10/*
11Copyright (c) 2015-2015 Cisco Systems, Inc.
12
13Licensed under the Apache License, Version 2.0 (the "License");
14you may not use this file except in compliance with the License.
15You may obtain a copy of the License at
16
17    http://www.apache.org/licenses/LICENSE-2.0
18
19Unless required by applicable law or agreed to in writing, software
20distributed under the License is distributed on an "AS IS" BASIS,
21WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22See the License for the specific language governing permissions and
23limitations under the License.
24*/
25
26#include <stdio.h>
27#include <stdint.h>
28#include <string.h>
29#include <vector>
30#include <algorithm>
31#include <map>
32#include <string>
33#include <iostream>
34#include <fstream>
35#include <string>
36#include <queue>
37#include "common/c_common.h"
38#include <bitset>
39#include <yaml-cpp/yaml.h>
40#include "trex_client_config.h"
41
42#include <random>
43
44class CTupleBase {
45public:
46
47       CTupleBase() {
48           m_client_cfg = NULL;
49       }
50
51       uint32_t getClient() {
52           return m_client_ip;
53       }
54       void setClient(uint32_t ip) {
55           m_client_ip = ip;
56       }
57       uint32_t getClientId() {
58           return m_client_idx;
59       }
60       void setClientId(uint32_t id) {
61           m_client_idx = id;
62       }
63
64       uint32_t getServer(){
65           return m_server_ip;
66       }
67       void setServer(uint32_t ip) {
68           m_server_ip = ip;
69       }
70       uint32_t getServerId(){
71           return m_server_idx;
72       }
73       void setServerId(uint32_t id) {
74           m_server_idx = id;
75       }
76       uint16_t getServerPort() {
77           return m_server_port;
78       }
79       void setServerPort(uint16_t port) {
80           m_server_port = port;
81       }
82       uint16_t getClientPort() {
83           return m_client_port;
84       }
85       void setClientPort(uint16_t port) {
86           m_client_port = port;
87       }
88       void setClientCfg(ClientCfgBase *cfg) {
89           m_client_cfg = cfg;
90       }
91       ClientCfgBase *getClientCfg() {
92           return m_client_cfg;
93       }
94
95
96       void setClientTuple(uint32_t ip, ClientCfgBase *cfg, uint16_t port) {
97           setClient(ip);
98           setClientPort(port);
99           setClientCfg(cfg);
100       }
101
102       void setClientAll2(uint32_t id, uint32_t ip,uint16_t port) {
103           setClientId(id);
104           setClient(ip);
105           setClientPort(port);
106       }
107
108       void setServerAll(uint32_t id, uint32_t ip) {
109           setServerId(id);
110           setServer(ip);
111       }
112       void getClientAll(uint32_t & id, uint32_t & ip, uint32_t & port) {
113           id = getClientId();
114           ip = getClient();
115           port = getClientPort();
116       }
117       void getServerAll(uint32_t & id, uint32_t & ip) {
118           id = getServerId();
119           ip = getServer();
120       }
121private:
122       uint32_t m_client_ip;
123       uint32_t m_client_idx;
124
125       uint32_t m_server_ip;
126       uint32_t m_server_idx;
127
128       ClientCfgBase *m_client_cfg;
129
130       uint16_t m_client_port;
131       uint16_t m_server_port;
132};
133
134
135
136/*
137 * Class that handle the client info
138 */
139#define MAX_CLIENTS 1000000
140#define MAX_PORT (64000)
141#define MIN_PORT (1024)
142#define ILLEGAL_PORT (0)
143
144#define PORT_FREE (0)
145#define PORT_IN_USE (1)
146
147/*FIXME*/
148#define VLAN_SIZE (2)
149
150#define FOREACH(vector) for(int i=0;i<vector.size();i++)
151
152
153/* Client distribution */
154typedef enum  {
155    cdSEQ_DIST    = 0,
156    cdRANDOM_DIST = 1,
157    cdNORMAL_DIST = 2,
158    cdMAX_DIST    = 3
159} IP_DIST_t ;
160
161/* For type 1, we generator port by maintaining a 64K bit array for each port.
162 * In this case, we cannot support large number of clients due to memory exhausted.
163 *
164 * So we develop a type 2 tuple generator. In this case, we only maintain a 16 bit
165 * current port number for each client. To apply to type 2, it should meet:
166 * number of clients > (longest_flow*Total_CPS)/64K
167 *
168 * TRex will decide which type to use automatically. It is transparent to users.
169 * */
170
171#define TYPE1 0
172#define TYPE2 1
173#define MAX_TYPE 3
174
175class CIpInfoBase {
176    public:
177        virtual uint16_t get_new_free_port() = 0;
178        virtual void return_port(uint16_t a) = 0;
179        virtual void generate_tuple(CTupleBase & tuple) = 0;
180        virtual void return_all_ports() = 0;
181        uint32_t get_ip() {
182            return m_ip;
183        }
184        void set_ip(uint32_t ip) {
185            m_ip = ip;
186        }
187        virtual ~CIpInfoBase() {}
188    protected:
189        uint32_t          m_ip;
190};
191
192//CClientInfo for large amount of clients support
193class CIpInfoL : public CIpInfoBase {
194 private:
195    uint16_t m_curr_port;
196 public:
197    CIpInfoL() {
198        m_curr_port = MIN_PORT;
199    }
200    uint16_t get_new_free_port() {
201        if (m_curr_port>MAX_PORT) {
202            m_curr_port = MIN_PORT;
203        }
204        return m_curr_port++;
205    }
206
207    void return_port(uint16_t a) {
208    }
209
210    void return_all_ports() {
211        m_curr_port = MIN_PORT;
212    }
213};
214
215
216class CIpInfo : public CIpInfoBase {
217 private:
218    std::bitset<MAX_PORT>  m_bitmap_port;
219    uint16_t m_head_port;
220    friend class CClientInfoUT;
221
222 private:
223    bool is_port_available(uint16_t port) {
224        if (!is_port_legal(port)) {
225            return PORT_IN_USE;
226        }
227        return (m_bitmap_port[port] == PORT_FREE);
228    }
229
230    /*
231     * Return true if the port is legal
232     *        false if the port is illegal.
233     */
234    bool is_port_legal(uint16_t port) {
235        if (port>=MAX_PORT || port < MIN_PORT) {
236                return false;
237        }
238        return true;
239    }
240
241    void m_head_port_set(uint16_t head) {
242        if (!is_port_legal(head)) {
243            return;
244        }
245        m_head_port = head;
246    }
247
248    // Try to find next free port
249    void get_next_free_port_by_bit() {
250        uint16_t cnt = 0;
251        if (!is_port_legal(m_head_port)) {
252            m_head_port = MIN_PORT;
253        }
254        while (true) {
255            if (is_port_available(m_head_port)) {
256                return;
257            }
258            cnt++;
259            if (cnt>20) {
260                /*FIXME: need to trigger some alarms?*/
261                return;
262            }
263            m_head_port++;
264            if (m_head_port>=MAX_PORT) {
265                m_head_port = MIN_PORT;
266            }
267        }
268    }
269
270
271 public:
272    CIpInfo() {
273        m_head_port = MIN_PORT;
274        m_bitmap_port.reset();
275    }
276
277    uint16_t get_new_free_port() {
278        uint16_t r;
279
280        get_next_free_port_by_bit();
281        if (!is_port_available(m_head_port)) {
282            m_head_port = MIN_PORT;
283            return ILLEGAL_PORT;
284        }
285
286        m_bitmap_port[m_head_port] = PORT_IN_USE;
287        r = m_head_port;
288        m_head_port++;
289        if (m_head_port>MAX_PORT) {
290            m_head_port = MIN_PORT;
291        }
292        return r;
293    }
294
295    void return_port(uint16_t a) {
296        assert(is_port_legal(a));
297        assert(m_bitmap_port[a]==PORT_IN_USE);
298        m_bitmap_port[a] = PORT_FREE;
299    }
300
301    void return_all_ports() {
302        m_head_port = MIN_PORT;
303        m_bitmap_port.reset();
304    }
305};
306
307
308/**
309 * a flat client info (no configuration)
310 *
311 * using template to avoid duplicating the code for CIpInfo and
312 * CIpInfoL
313 *
314 * @author imarom (27-Jun-16)
315 */
316template <typename T>
317class CSimpleClientInfo : public T {
318
319public:
320     CSimpleClientInfo(uint32_t ip) {
321        T::set_ip(ip);
322     }
323
324     void generate_tuple(CTupleBase &tuple) {
325         tuple.setClientTuple(T::m_ip,
326                              NULL,
327                              T::get_new_free_port());
328    }
329};
330
331/**
332 * a configured client object
333 *
334 * @author imarom (26-Jun-16)
335 */
336template <typename T>
337class CConfiguredClientInfo : public T {
338
339public:
340    CConfiguredClientInfo(uint32_t ip, const ClientCfgBase &cfg) : m_cfg(cfg) {
341        T::set_ip(ip);
342    }
343
344    void generate_tuple(CTupleBase &tuple) {
345        tuple.setClientTuple(T::m_ip,
346                             &m_cfg,
347                             T::get_new_free_port());
348    }
349
350private:
351    ClientCfgBase m_cfg;
352};
353
354
355class CServerInfo : public CIpInfo {
356    void generate_tuple(CTupleBase & tuple) {
357        tuple.setServer(m_ip);
358    }
359};
360
361class CServerInfoL : public CIpInfoL {
362    void generate_tuple(CTupleBase & tuple) {
363        tuple.setServer(m_ip);
364    }
365};
366
367
368
369
370class CIpPool {
371    public:
372       uint16_t GenerateOnePort(uint32_t idx) {
373            CIpInfoBase* ip_info = m_ip_info[idx];
374            uint16_t port;
375            port = ip_info->get_new_free_port();
376
377            //printf(" alloc extra  %x %d \n",c_ip,port);
378            if (port==ILLEGAL_PORT) {
379                m_port_allocation_error++;
380            }
381            m_active_alloc++;
382            return (port);
383        }
384
385       bool is_valid_ip(uint32_t ip){
386            CIpInfoBase* ip_front = m_ip_info.front();
387            CIpInfoBase* ip_back  = m_ip_info.back();
388            if ((ip>=ip_front->get_ip()) &&
389                (ip<=ip_back->get_ip())) {
390                return(true);
391            }
392            printf("invalid ip:%x, min_ip:%x, max_ip:%x, this:%p\n",
393                   ip, ip_front->get_ip(),
394                   ip_back->get_ip(),this);
395            return(false);
396        }
397
398        uint32_t get_curr_ip() {
399            return m_ip_info[m_cur_idx]->get_ip();
400        }
401        uint32_t get_ip(uint32_t idx) {
402            return m_ip_info[idx]->get_ip();
403        }
404        CIpInfoBase* get_ip_info_by_idx(uint32_t idx) {
405            return m_ip_info[idx];
406        }
407
408        void inc_cur_idx() {
409            switch (m_dist) {
410            case cdRANDOM_DIST:
411                m_cur_idx = get_random_idx();
412                break;
413            case cdSEQ_DIST :
414            default:
415                m_cur_idx++;
416                if (m_cur_idx >= m_ip_info.size())
417                    m_cur_idx = 0;
418            }
419        }
420        //return a valid client idx in this pool
421        uint32_t generate_ip() {
422            uint32_t res_idx = m_cur_idx;
423            inc_cur_idx();
424            return res_idx;
425        }
426
427
428
429        void set_dist(IP_DIST_t dist) {
430            if (dist>=cdMAX_DIST) {
431                m_dist = cdSEQ_DIST;
432            } else {
433                m_dist = dist;
434            }
435        }
436        void Delete() {
437            FOREACH(m_ip_info) {
438                delete m_ip_info[i];
439            }
440            m_ip_info.clear();
441        }
442        uint32_t get_total_ips() {
443            return m_ip_info.size();
444        }
445        void return_all_ports() {
446            FOREACH(m_ip_info) {
447                m_ip_info[i]->return_all_ports();
448            }
449        }
450        void FreePort(uint32_t id, uint16_t port) {
451    //        assert(id<m_ip_info.size());
452            m_active_alloc--;
453            CIpInfoBase* client = m_ip_info[id];
454            client->return_port(port);
455        }
456
457
458    public:
459        std::vector<CIpInfoBase*> m_ip_info;
460        IP_DIST_t  m_dist;
461        uint32_t m_cur_idx;
462        uint32_t m_active_alloc;
463        uint32_t m_port_allocation_error;
464        std::default_random_engine generator;
465        std::uniform_int_distribution<int> *rand_dis;
466        void CreateBase() {
467            switch (m_dist) {
468            case cdRANDOM_DIST:
469                rand_dis = new std::uniform_int_distribution<int>
470                    (0,get_total_ips()-1);
471                break;
472            default:
473                break;
474            }
475            m_cur_idx = 0;
476            m_active_alloc = 0;
477            m_port_allocation_error = 0;
478        }
479        uint32_t get_random_idx() {
480            uint32_t res =  (*rand_dis)(generator);
481            return (res);
482        }
483        bool IsFreePortRequired(void){
484            return(true);
485        }
486
487
488};
489
490class CClientPool : public CIpPool {
491public:
492
493    uint32_t GenerateTuple(CTupleBase & tuple) {
494        uint32_t idx = generate_ip();
495        CIpInfoBase* ip_info = m_ip_info[idx];
496        ip_info->generate_tuple(tuple);
497
498        tuple.setClientId(idx);
499        if (tuple.getClientPort()==ILLEGAL_PORT) {
500            m_port_allocation_error++;
501        }
502        m_active_alloc++;
503        return idx;
504    }
505
506    uint16_t get_tcp_aging() {
507        return m_tcp_aging;
508    }
509    uint16_t get_udp_aging() {
510        return m_udp_aging;
511    }
512
513    void Create(IP_DIST_t       dist_value,
514                uint32_t        min_ip,
515                uint32_t        max_ip,
516                double          l_flow,
517                double          t_cps,
518                ClientCfgDB     &client_info,
519                uint16_t        tcp_aging,
520                uint16_t        udp_aging);
521
522public:
523    uint16_t m_tcp_aging;
524    uint16_t m_udp_aging;
525
526private:
527    void allocate_simple_clients(uint32_t  min_ip,
528                                 uint32_t  total_ip,
529                                 bool      is_long_range);
530
531    void allocate_configured_clients(uint32_t        min_ip,
532                                     uint32_t        total_ip,
533                                     bool            is_long_range,
534                                     ClientCfgDB     &client_info);
535
536};
537
538class CServerPoolBase {
539    public:
540
541    virtual ~CServerPoolBase() {}
542
543    virtual void GenerateTuple(CTupleBase& tuple) = 0;
544    virtual uint16_t GenerateOnePort(uint32_t idx) = 0;
545    virtual void Delete() = 0;
546    virtual uint32_t get_total_ips()=0;
547    virtual void Create(IP_DIST_t  dist_value,
548               uint32_t min_ip,
549               uint32_t max_ip,
550               double l_flow,
551               double t_cps) = 0;
552
553};
554
555class CServerPoolSimple : public CServerPoolBase {
556public:
557    void Create(IP_DIST_t  dist_value,
558               uint32_t min_ip,
559               uint32_t max_ip,
560               double l_flow,
561               double t_cps) {
562        m_max_server_ip = max_ip;
563        m_min_server_ip = min_ip;
564        m_cur_server_ip = min_ip;
565    }
566    void Delete() {
567        return ;
568    }
569    void GenerateTuple(CTupleBase& tuple) {
570        tuple.setServer(m_cur_server_ip);
571        m_cur_server_ip ++;
572        if (m_cur_server_ip > m_max_server_ip) {
573            m_cur_server_ip = m_min_server_ip;
574        }
575    }
576    uint16_t GenerateOnePort(uint32_t idx) {
577        // do nothing
578        return 0;
579    }
580    uint32_t get_total_ips() {
581        return (m_max_server_ip-m_min_server_ip+1);
582    }
583private:
584    uint32_t m_max_server_ip;
585    uint32_t m_min_server_ip;
586    uint32_t m_cur_server_ip;
587};
588
589class CServerPool : public CServerPoolBase {
590public:
591    void GenerateTuple(CTupleBase & tuple) {
592       uint32_t idx = gen->generate_ip();
593       tuple.setServerAll(idx, gen->get_ip(idx));
594    }
595    uint16_t GenerateOnePort(uint32_t idx) {
596        return gen->GenerateOnePort(idx);
597    }
598    void Create(IP_DIST_t  dist_value,
599                uint32_t min_ip,
600                uint32_t max_ip,
601                double l_flow,
602                double t_cps);
603
604    void Delete() {
605        if (gen!=NULL) {
606            gen->Delete();
607            delete gen;
608            gen=NULL;
609        }
610    }
611    uint32_t get_total_ips() {
612        return gen->m_ip_info.size();
613    }
614private:
615    CIpPool *gen;
616};
617
618/* generate for each template */
619class CTupleGeneratorSmart {
620public:
621    /* return the active socket */
622    uint32_t ActiveSockets(void){
623        uint32_t total_active_alloc = 0;
624        FOREACH(m_client_pool) {
625            total_active_alloc += m_client_pool[i]->m_active_alloc;
626        }
627        return (total_active_alloc);
628    }
629
630    uint32_t getTotalClients(void){
631        uint32_t total_clients = 0;
632        FOREACH(m_client_pool) {
633            total_clients += m_client_pool[i]->get_total_ips();
634        }
635        return (total_clients);
636    }
637
638    uint32_t getTotalServers(void){
639        uint32_t total_servers = 0;
640        FOREACH(m_server_pool) {
641            total_servers += m_server_pool[i]->get_total_ips();
642        }
643        return total_servers;
644    }
645
646    uint32_t SocketsPerClient(void){
647        return (MAX_PORT -MIN_PORT+1);
648    }
649
650    uint32_t MaxSockets(void){
651        return (SocketsPerClient() * getTotalClients());
652    }
653
654
655    void FreePort(uint8_t pool_idx, uint32_t id, uint16_t port) {
656        get_client_pool(pool_idx)->FreePort(id, port);
657    }
658
659    bool IsFreePortRequired(uint8_t pool_idx){
660        return(get_client_pool(pool_idx)->IsFreePortRequired());
661    }
662    uint16_t get_tcp_aging(uint8_t pool_idx) {
663        return (get_client_pool(pool_idx)->get_tcp_aging());
664    }
665    uint16_t get_udp_aging(uint8_t pool_idx) {
666        return (get_client_pool(pool_idx)->get_udp_aging());
667    }
668
669public:
670    CTupleGeneratorSmart(){
671        m_was_init=false;
672    }
673
674    bool Create(uint32_t _id, uint32_t thread_id);
675
676    void Delete();
677
678    inline uint32_t GetThreadId(){
679        return (  m_thread_id );
680    }
681
682    uint32_t getErrorAllocationCounter(){
683        uint32_t total_alloc_error = 0;
684        FOREACH(m_client_pool) {
685            total_alloc_error += m_client_pool[i]->m_port_allocation_error;
686        }
687        return (total_alloc_error);
688    }
689
690    bool add_client_pool(IP_DIST_t     client_dist,
691                         uint32_t      min_client,
692                         uint32_t      max_client,
693                         double        l_flow,
694                         double        t_cps,
695                         ClientCfgDB   &client_info,
696                         uint16_t      tcp_aging,
697                         uint16_t      udp_aging);
698
699    bool add_server_pool(IP_DIST_t  server_dist,
700                         uint32_t   min_server,
701                         uint32_t   max_server,
702                         double     l_flow,
703                         double     t_cps,
704                         bool       is_bundling);
705
706    CClientPool* get_client_pool(uint8_t idx) {
707        return m_client_pool[idx];
708    }
709    uint8_t get_client_pool_num() {
710        return m_client_pool.size();
711    }
712    uint8_t get_server_pool_num() {
713        return m_server_pool.size();
714    }
715    CServerPoolBase* get_server_pool(uint8_t idx) {
716        return m_server_pool[idx];
717    }
718private:
719    uint32_t m_id;
720    uint32_t m_thread_id;
721    std::vector<CClientPool*> m_client_pool;
722    std::vector<CServerPoolBase*> m_server_pool;
723    bool     m_was_init;
724};
725
726class CTupleTemplateGeneratorSmart {
727public:
728    /* simple tuple genertion for one low*/
729    void GenerateTuple(CTupleBase & tuple){
730        if (m_w==1) {
731            /* new client each tuple generate */
732            m_client_gen->GenerateTuple(tuple);
733            m_server_gen->GenerateTuple(tuple);
734            m_cache_client_ip = tuple.getClient();
735            m_cache_client_idx = tuple.getClientId();
736        }else{
737            if (m_cnt==0) {
738                m_client_gen->GenerateTuple(tuple);
739                m_server_gen->GenerateTuple(tuple);
740                m_cache_client_ip = tuple.getClient();
741                m_cache_client_idx = tuple.getClientId();
742                tuple.getServerAll(m_cache_server_idx, m_cache_server_ip);
743            }else{
744                tuple.setServerAll(m_cache_server_idx,
745                                   m_cache_server_ip);
746                tuple.setClientAll2(m_cache_client_idx,
747                                    m_cache_client_ip,
748                                    m_client_gen->GenerateOnePort(m_cache_client_idx));
749            }
750            m_cnt++;
751            if (m_cnt>=m_w) {
752                m_cnt=0;
753            }
754        }
755        if ( m_is_single_server ) {
756            tuple.setServer(m_server_ip);
757        }
758    }
759
760    uint16_t GenerateOneSourcePort(){
761        return ( m_client_gen->GenerateOnePort(m_cache_client_idx) );
762    }
763
764    inline uint32_t GetThreadId(){
765        return ( m_gen->GetThreadId() );
766    }
767
768public:
769
770    bool Create( CTupleGeneratorSmart * gen,uint8_t c_pool,uint8_t s_pool){
771        m_gen=gen;
772        m_is_single_server=false;
773        m_server_ip=0;
774        SetW(1);
775        m_client_gen = gen->get_client_pool(c_pool);
776        m_server_gen = gen->get_server_pool(s_pool);
777        return (true);
778    }
779
780    void Delete(){
781    }
782public:
783    void SetW(uint16_t w){
784        m_w=w;
785        m_cnt=0;
786    }
787
788    uint16_t getW(){
789        return (m_w);
790    }
791
792
793    void SetSingleServer(bool is_single,
794                         uint32_t server_ip,
795                         uint32_t dual_port_index,
796                         uint32_t dual_mask){
797        m_is_single_server = is_single;
798        m_server_ip = server_ip+dual_mask*dual_port_index;
799    }
800    bool IsSingleServer(){
801        return (m_is_single_server);
802    }
803
804    CTupleGeneratorSmart * get_gen() {
805        return m_gen;
806    }
807private:
808    CTupleGeneratorSmart * m_gen;
809    CClientPool          * m_client_gen;
810    CServerPoolBase      * m_server_gen;
811    uint16_t               m_w;
812    uint16_t               m_cnt;
813    uint32_t               m_server_ip;
814    uint32_t               m_cache_client_ip;
815    uint32_t               m_cache_client_idx;
816    uint32_t               m_cache_server_ip;
817    uint32_t               m_cache_server_idx;
818    bool                   m_is_single_server;
819};
820
821
822/* YAML of generator */
823#if 0
824        -  client_distribution      : 'seq' - ( e.g c0,1,2,3,4
825                                      'random' - random from the pool
826                                      'normal' - need to give average and dev -- second phase
827
828        -  client_pool_mask         : 10.0.0.0-20.0.0.0
829        -  server_pool_mask         : 70.0.0.0-70.0.20.0
830        -  number_of_clients_per_gb : 20
831        -  dual_interface_mask      : 1.0.0.0  // each dual ports will add this to the pool of clients
832#endif
833
834struct CTupleGenPoolYaml {
835    IP_DIST_t       m_dist;
836    uint32_t        m_ip_start;
837    uint32_t        m_ip_end;
838    uint32_t        m_number_of_clients_per_gb;
839    uint32_t        m_min_clients;
840    uint32_t        m_dual_interface_mask;
841    uint16_t        m_tcp_aging_sec; /* 0 means there is no aging */
842    uint16_t        m_udp_aging_sec;
843    std::string     m_name;
844    bool            m_is_bundling;
845    public:
846    uint32_t getTotalIps(void){
847        return ( m_ip_end-m_ip_start+1);
848    }
849    uint32_t getDualMask() {
850        return m_dual_interface_mask;
851    }
852    uint32_t get_ip_start() {
853        return m_ip_start;
854    }
855    uint32_t get_ip_end() {
856        return m_ip_end;
857    }
858    bool is_valid(uint32_t num_threads,bool is_plugins);
859    void Dump(FILE *fd);
860};
861
862
863struct CTupleGenYamlInfo {
864    std::vector<CTupleGenPoolYaml> m_client_pool;
865    std::vector<CTupleGenPoolYaml> m_server_pool;
866
867public:
868    bool is_valid(uint32_t num_threads,bool is_plugins);
869    uint8_t get_server_pool_id(std::string name){
870         if (name=="default") {
871             return 0;
872         }
873        for (uint8_t i=0;i<m_server_pool.size();i++) {
874            if (m_server_pool[i].m_name==name)
875                return i;
876        }
877        printf("ERROR invalid server pool name %s, please review your YAML file\n",(char *)name.c_str());
878        exit(-1);
879        return 0;
880    }
881
882    uint8_t get_client_pool_id(std::string name){
883         if (name=="default") {
884             return 0;
885         }
886        for (uint8_t i=0;i<m_client_pool.size();i++) {
887            if (m_client_pool[i].m_name==name)
888                return i;
889        }
890        printf("ERROR invalid client pool name %s, please review your YAML file\n",(char *)name.c_str());
891        exit(-1);
892        return 0;
893    }
894
895    bool find_port(uint32_t ip_start, uint32_t ip_end, uint8_t &port);
896    void dump(FILE *fd);
897};
898
899
900void operator >> (const YAML::Node& node, CTupleGenPoolYaml & fi) ;
901
902void operator >> (const YAML::Node& node, CTupleGenYamlInfo & fi) ;
903
904
905struct CIpPortion {
906    uint32_t m_ip_start;
907    uint32_t m_ip_end;
908};
909void split_ips(uint32_t thread_id,
910                   uint32_t total_threads,
911                   uint32_t dual_port_id,
912                   CTupleGenPoolYaml& poolinfo,
913                   CIpPortion & portion);
914
915
916
917#endif //TUPLE_GEN_H_
918