1/*
2 Hanoh Haim
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2016 Cisco Systems, Inc.
8
9Licensed under the Apache License, Version 2.0 (the "License");
10you may not use this file except in compliance with the License.
11You may obtain a copy of the License at
12
13    http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software
16distributed under the License is distributed on an "AS IS" BASIS,
17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18See the License for the specific language governing permissions and
19limitations under the License.
20*/
21
22#include <fstream>
23#include <iostream>
24#include <stdlib.h>
25#include "common/basic_utils.h"
26#include "utl_yaml.h"
27#include "platform_cfg.h"
28#include "utl_yaml.h"
29
30void CPlatformMemoryYamlInfo::reset(){
31       int i;
32       i=0;
33       for (i=0; i<MBUF_ELM_SIZE; i++) {
34           m_mbuf[i] = CONST_NB_MBUF_2_10G;
35       }
36       m_mbuf[MBUF_64]           = m_mbuf[MBUF_64]*2;
37
38       m_mbuf[MBUF_2048]         = CONST_NB_MBUF_2_10G/2;
39
40       m_mbuf[MBUF_4096]         = 128;
41       m_mbuf[MBUF_9k]           = 512;
42
43
44       m_mbuf[TRAFFIC_MBUF_64]           = m_mbuf[MBUF_64] * 4;
45       m_mbuf[TRAFFIC_MBUF_128]           = m_mbuf[MBUF_128] * 4;
46
47       m_mbuf[TRAFFIC_MBUF_2048]         = CONST_NB_MBUF_2_10G * 8;
48
49       m_mbuf[TRAFFIC_MBUF_4096]         = 128;
50       m_mbuf[TRAFFIC_MBUF_9k]           = 512;
51
52
53       m_mbuf[MBUF_DP_FLOWS]     = (1024*1024/2);
54       m_mbuf[MBUF_GLOBAL_FLOWS] =(10*1024/2);
55}
56
57const std::string names []={
58                   "MBUF_64",
59                   "MBUF_128",
60                   "MBUF_256",
61                   "MBUF_512",
62                   "MBUF_1024",
63                   "MBUF_2048",
64                   "MBUF_4096",
65                   "MBUF_9K",
66
67                   "TRAFFIC_MBUF_64",
68                   "TRAFFIC_MBUF_128",
69                   "TRAFFIC_MBUF_256",
70                   "TRAFFIC_MBUF_512",
71                   "TRAFFIC_MBUF_1024",
72                   "TRAFFIC_MBUF_2048",
73                   "TRAFFIC_MBUF_4096",
74                   "TRAFFIC_MBUF_9K",
75
76                   "MBUF_DP_FLOWS",
77                   "MBUF_GLOBAL_FLOWS"
78
79};
80
81const std::string * get_mbuf_names(void){
82  return names;
83}
84
85void CPlatformDualIfYamlInfo::Dump(FILE *fd){
86    fprintf(fd,"    socket  : %d  \n",m_socket);
87    int i;
88    fprintf(fd,"   [  ");
89    for (i=0; i<m_threads.size(); i++) {
90        fprintf(fd," %d  ",(int)m_threads[i]);
91    }
92    fprintf(fd,"   ]  \n");
93}
94
95void CPlatformCoresYamlInfo::Dump(FILE *fd){
96    if ( m_is_exists == false){
97       fprintf(fd," no platform info \n");
98       return;
99    }
100    fprintf(fd," master   thread  : %d  \n", m_master_thread);
101    fprintf(fd," rx  thread  : %d  \n", m_rx_thread);
102    int i;
103    for (i=0; i<m_dual_if.size(); i++) {
104        printf(" dual_if : %d \n",i);
105        CPlatformDualIfYamlInfo * lp=&m_dual_if[i];
106        lp->Dump(fd);
107    }
108}
109
110void operator >> (const YAML::Node& node, CPlatformDualIfYamlInfo & plat_info) {
111    node["socket"] >> plat_info.m_socket;
112    const YAML::Node& threads = node["threads"];
113    /* fill the vector*/
114    for(unsigned i=0;i<threads.size();i++) {
115        uint32_t fi;
116        const YAML::Node & node = threads;
117        node[i]  >> fi;
118        plat_info.m_threads.push_back(fi);
119    }
120}
121
122void operator >> (const YAML::Node& node, CPlatformCoresYamlInfo & plat_info) {
123     node["master_thread_id"] >> plat_info.m_master_thread;
124     if (node.FindValue("rx_thread_id")) {
125         node["rx_thread_id"] >> plat_info.m_rx_thread;
126     } else {
127         // Obolete option.
128         if (node.FindValue("latency_thread_id")) {
129             node["latency_thread_id"] >> plat_info.m_rx_thread;
130         } else {
131             node["rx_thread_id"] >> plat_info.m_rx_thread; // do this to get the error message
132         }
133     }
134
135     const YAML::Node& dual_info = node["dual_if"];
136     for(unsigned i=0;i<dual_info.size();i++) {
137        CPlatformDualIfYamlInfo  fi;
138         dual_info[i]  >> fi;
139         plat_info.m_dual_if.push_back(fi);
140     }
141}
142
143void CPlatformMemoryYamlInfo::Dump(FILE *fd){
144    fprintf(fd," memory per 2x10G ports  \n");
145    const std::string * names =get_mbuf_names();
146
147    int i=0;
148    for (i=0; i<MBUF_ELM_SIZE; i++) {
149        fprintf(fd," %-40s  : %lu \n",names[i].c_str(), (ulong)m_mbuf[i]);
150    }
151}
152
153void CMacYamlInfo::copy_dest(char *p){
154    assert(m_dest_base.size() == 6);
155    int i;
156    for (i=0; i<m_dest_base.size(); i++) {
157        p[i]=m_dest_base[i];
158    }
159}
160
161void CMacYamlInfo::copy_src(char *p){
162        assert(m_src_base.size() == 6);
163        int i;
164        for (i=0; i<m_src_base.size(); i++) {
165            p[i]=m_src_base[i];
166        }
167}
168
169uint32_t CMacYamlInfo::get_def_gw() {
170    return m_def_gw;
171}
172
173uint32_t CMacYamlInfo::get_ip() {
174    return m_ip;
175}
176
177uint32_t CMacYamlInfo::get_mask() {
178    return m_mask;
179}
180
181uint32_t CMacYamlInfo::get_vlan() {
182    return m_vlan;
183}
184
185void CMacYamlInfo::Dump(FILE *fd){
186    if (m_dest_base.size() != 6) {
187        fprintf(fd,"ERROR in dest mac addr \n");
188        return;
189    }
190    if (m_src_base.size() != 6) {
191        fprintf(fd,"ERROR in src mac addr \n");
192        return;
193    }
194    fprintf (fd," src     : ");
195    dump_mac_vector( m_src_base,fd);
196    fprintf (fd," dest    : ");
197    dump_mac_vector( m_dest_base,fd);
198
199}
200
201void operator >> (const YAML::Node& node, CMacYamlInfo & mac_info) {
202    uint32_t fi;
203    bool res;
204    std::string mac_str;
205
206    if (node.FindValue("dest_mac")) {
207        const YAML::Node& dmac = node["dest_mac"];
208        if (dmac.Type() == YAML::NodeType::Sequence) { // [1,2,3,4,5,6]
209            ASSERT_MSG(dmac.size() == 6, "Array of dest MAC should have 6 elements.");
210            for(unsigned i=0;i<dmac.size();i++) {
211                dmac[i]  >> fi;
212                mac_info.m_dest_base.push_back(fi);
213            }
214        }
215        else if (dmac.Type() == YAML::NodeType::Scalar) { // "12:34:56:78:9a:bc"
216            dmac >> mac_str;
217            res = mac2vect(mac_str, mac_info.m_dest_base);
218            ASSERT_MSG(res && mac_info.m_dest_base.size() == 6
219                       , "String of dest MAC should be in format '12:34:56:78:9a:bc'.");
220        }
221    } else {
222        for(unsigned i = 0; i < 6; i++) {
223            mac_info.m_dest_base.push_back(0);
224        }
225    }
226
227    if (node.FindValue("src_mac")) {
228        const YAML::Node& smac = node["src_mac"];
229        if (smac.Type() == YAML::NodeType::Sequence) {
230            ASSERT_MSG(smac.size() == 6, "Array of src MAC should have 6 elements.");
231            for(unsigned i=0;i<smac.size();i++) {
232                smac[i]  >> fi;
233                mac_info.m_src_base.push_back(fi);
234            }
235        }
236        else if (smac.Type() == YAML::NodeType::Scalar) {
237            smac >> mac_str;
238            res = mac2vect(mac_str, mac_info.m_src_base);
239            ASSERT_MSG(res && mac_info.m_src_base.size() == 6
240                       , "String of src MAC should be in format '12:34:56:78:9a:bc'.");
241        }
242    } else {
243        for(unsigned i = 0; i < 6; i++) {
244            mac_info.m_src_base.push_back(0);
245        }
246    }
247
248    if (! utl_yaml_read_ip_addr(node, "default_gw", mac_info.m_def_gw)) {
249        mac_info.m_def_gw = 0;
250    }
251
252    if (! utl_yaml_read_ip_addr(node, "ip", mac_info.m_ip)) {
253        mac_info.m_ip = 0;
254    }
255    if (! utl_yaml_read_ip_addr(node, "mask", mac_info.m_mask)) {
256        mac_info.m_mask = 0;
257    }
258    if (! utl_yaml_read_uint16(node, "vlan", mac_info.m_vlan, 0, 0xfff)) {
259        mac_info.m_vlan = 0;
260    }
261}
262
263void operator >> (const YAML::Node& node, CPlatformMemoryYamlInfo & plat_info) {
264    if ( node.FindValue("mbuf_64") ){
265        node["mbuf_64"] >> plat_info.m_mbuf[MBUF_64];
266    }
267
268    if ( node.FindValue("mbuf_128") ){
269        node["mbuf_128"] >> plat_info.m_mbuf[MBUF_128];
270    }
271
272    if ( node.FindValue("mbuf_256") ){
273        node["mbuf_256"] >> plat_info.m_mbuf[MBUF_256];
274    }
275
276    if ( node.FindValue("mbuf_512") ){
277        node["mbuf_512"] >> plat_info.m_mbuf[MBUF_512];
278    }
279
280    if ( node.FindValue("mbuf_1024") ){
281        node["mbuf_1024"] >> plat_info.m_mbuf[MBUF_1024];
282    }
283
284    if ( node.FindValue("mbuf_2048") ){
285        node["mbuf_2048"] >> plat_info.m_mbuf[MBUF_2048];
286    }
287
288    if ( node.FindValue("mbuf_4096") ){
289        node["mbuf_4096"] >> plat_info.m_mbuf[MBUF_4096];
290    }
291
292    if ( node.FindValue("mbuf_9k") ){
293        node["mbuf_9k"] >> plat_info.m_mbuf[MBUF_9k];
294    }
295
296
297    if ( node.FindValue("traffic_mbuf_64") ){
298        node["traffic_mbuf_64"] >> plat_info.m_mbuf[TRAFFIC_MBUF_64];
299    }
300
301    if ( node.FindValue("traffic_mbuf_128") ){
302        node["traffic_mbuf_128"] >> plat_info.m_mbuf[TRAFFIC_MBUF_128];
303    }
304
305    if ( node.FindValue("traffic_mbuf_256") ){
306        node["traffic_mbuf_256"] >> plat_info.m_mbuf[TRAFFIC_MBUF_256];
307    }
308
309    if ( node.FindValue("traffic_mbuf_512") ){
310        node["traffic_mbuf_512"] >> plat_info.m_mbuf[TRAFFIC_MBUF_512];
311    }
312
313    if ( node.FindValue("traffic_mbuf_1024") ){
314        node["traffic_mbuf_1024"] >> plat_info.m_mbuf[TRAFFIC_MBUF_1024];
315    }
316
317    if ( node.FindValue("traffic_mbuf_2048") ){
318        node["traffic_mbuf_2048"] >> plat_info.m_mbuf[TRAFFIC_MBUF_2048];
319    }
320
321    if ( node.FindValue("traffic_mbuf_4096") ){
322        node["traffic_mbuf_4096"] >> plat_info.m_mbuf[TRAFFIC_MBUF_4096];
323    }
324
325    if ( node.FindValue("traffic_mbuf_9k") ){
326        node["traffic_mbuf_9k"] >> plat_info.m_mbuf[TRAFFIC_MBUF_9k];
327    }
328
329
330    if ( node.FindValue("dp_flows") ){
331        node["dp_flows"] >> plat_info.m_mbuf[MBUF_DP_FLOWS];
332    }
333
334    if ( node.FindValue("global_flows") ){
335        node["global_flows"] >> plat_info.m_mbuf[MBUF_GLOBAL_FLOWS];
336    }
337
338}
339
340void operator >> (const YAML::Node& node, CPlatformYamlInfo & plat_info) {
341    if (node.FindValue("interface_mask")) {
342        printf("WARNING interface_mask in not used any more !\n");
343    }
344
345    /* must have interfaces */
346    const YAML::Node& interfaces = node["interfaces"];
347    if ( interfaces.size() > TREX_MAX_PORTS ) {
348        printf("ERROR: Maximal number of interfaces is: %d, you have specified: %d.\n",
349                    TREX_MAX_PORTS, (int) interfaces.size());
350        exit(-1);
351    }
352
353    for(unsigned i=0;i<interfaces.size();i++) {
354        std::string  fi;
355        const YAML::Node & node = interfaces;
356        node[i]  >> fi;
357        plat_info.m_if_list.push_back(fi);
358    }
359
360
361    if ( node.FindValue("port_limit") ){
362        node["port_limit"] >> plat_info.m_port_limit;
363        plat_info.m_port_limit_exist=true;
364    }
365
366
367    plat_info.m_enable_zmq_pub_exist = true;
368
369    if ( node.FindValue("enable_zmq_pub") ){
370        node["enable_zmq_pub"] >> plat_info.m_enable_zmq_pub;
371        plat_info.m_enable_zmq_pub_exist = true;
372    }
373
374    if ( node.FindValue("zmq_pub_port") ){
375        node["zmq_pub_port"] >> plat_info.m_zmq_pub_port;
376        plat_info.m_enable_zmq_pub_exist = true;
377    }
378
379    if ( node.FindValue("prefix") ){
380        node["prefix"] >> plat_info.m_prefix;
381    }
382
383    if ( node.FindValue("limit_memory") ){
384        node["limit_memory"] >> plat_info.m_limit_memory;
385    }
386
387    if ( node.FindValue("c") ){
388        node["c"] >> plat_info.m_thread_per_dual_if;
389    }
390
391    if ( node.FindValue("telnet_port") ){
392        node["telnet_port"] >> plat_info.m_telnet_port;
393        plat_info.m_telnet_exist=true;
394    }
395
396    if ( node.FindValue("zmq_rpc_port") ){
397        node["zmq_rpc_port"] >> plat_info.m_zmq_rpc_port;
398    }
399
400    if ( node.FindValue("port_bandwidth_gb") ){
401        node["port_bandwidth_gb"] >> plat_info.m_port_bandwidth_gb;
402    }
403
404    if ( node.FindValue("memory") ){
405        node["memory"] >> plat_info.m_memory;
406    }
407
408    if ( node.FindValue("platform") ){
409        node["platform"] >> plat_info.m_platform;
410        plat_info.m_platform.m_is_exists=true;
411    }
412
413    if ( node.FindValue("tw") ){
414        node["tw"] >> plat_info.m_tw;
415    }
416
417
418    if ( node.FindValue("port_info")  ) {
419        const YAML::Node& mac_info = node["port_info"];
420        for(unsigned i=0;i<mac_info.size();i++) {
421           CMacYamlInfo  fi;
422            const YAML::Node & node =mac_info;
423            node[i]  >> fi;
424            plat_info.m_mac_info.push_back(fi);
425        }
426        plat_info.m_mac_info_exist = true;
427    }
428}
429
430int CPlatformYamlInfo::load_from_yaml_file(std::string file_name){
431    reset();
432    m_info_exist =true;
433
434    if ( !utl_is_file_exists(file_name) ){
435        printf(" ERROR file %s does not exists \n",file_name.c_str());
436        exit(-1);
437    }
438
439    try {
440       std::ifstream fin((char *)file_name.c_str());
441       YAML::Parser parser(fin);
442       YAML::Node doc;
443
444       parser.GetNextDocument(doc);
445       for(unsigned i=0;i<doc.size();i++) {
446          doc[i] >> *this;
447          break;
448       }
449    } catch ( const std::exception& e ) {
450        std::cout << e.what() << "\n";
451        exit(-1);
452    }
453    return (0);
454}
455
456std::string CPlatformYamlInfo::get_use_if_comma_seperated(){
457    std::string s="";
458    int i;
459    for (i=0; i<(int)m_if_list.size()-1; i++) {
460        s+=m_if_list[i]+",";
461    }
462    s+=m_if_list[i];
463    return (s);
464}
465
466void CPlatformYamlInfo::Dump(FILE *fd){
467    if ( m_info_exist ==false ){
468        fprintf(fd," file info does not exist  \n");
469        return;
470    }
471
472    if (m_port_limit_exist && (m_port_limit != 0xffffffff)) {
473        fprintf(fd," port limit     :  %d \n",m_port_limit);
474    }else{
475        fprintf(fd," port limit     :  not configured \n");
476    }
477    fprintf(fd," port_bandwidth_gb    :  %lu \n", (ulong)m_port_bandwidth_gb);
478
479    if ( m_if_mask_exist && m_if_mask.size() ) {
480        fprintf(fd," if_mask        : ");
481        int i;
482        for (i=0; i<(int)m_if_mask.size(); i++) {
483            fprintf(fd," %s,",m_if_mask[i].c_str());
484        }
485        fprintf(fd,"\n");
486
487    }else{
488        fprintf(fd," if_mask        : None \n");
489    }
490
491    if ( m_prefix.length() ){
492        fprintf(fd," prefix              : %s \n",m_prefix.c_str());
493    }
494    if ( m_limit_memory.length() ){
495        fprintf(fd," limit_memory        : %s \n",m_limit_memory.c_str());
496    }
497    fprintf(fd," thread_per_dual_if      : %d \n",(int)m_thread_per_dual_if);
498
499    fprintf(fd," if        : ");
500    int i;
501    for (i=0; i<(int)m_if_list.size(); i++) {
502        fprintf(fd," %s,",m_if_list[i].c_str());
503    }
504    fprintf(fd,"\n");
505
506    if ( m_enable_zmq_pub_exist ){
507        fprintf(fd," enable_zmq_pub :  %d \n",m_enable_zmq_pub?1:0);
508        fprintf(fd," zmq_pub_port   :  %d \n",m_zmq_pub_port);
509    }
510    if ( m_telnet_exist ){
511        fprintf(fd," telnet_port    :  %d \n",m_telnet_port);
512
513    }
514    fprintf(fd," m_zmq_rpc_port    :  %d \n",m_zmq_rpc_port);
515
516    if ( m_mac_info_exist ){
517        int i;
518        for (i=0; i<(int)m_mac_info.size(); i++) {
519            m_mac_info[i].Dump(fd);
520        }
521    }
522    m_memory.Dump(fd);
523    m_platform.Dump(fd);
524    m_tw.Dump(fd);
525}
526