trex_rpc_cmd_general.cpp revision 0fdd81a9
1/*
2 Itay Marom
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2015 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 "trex_rpc_cmds.h"
23#include <trex_rpc_server_api.h>
24#include <trex_stateless.h>
25#include <trex_stateless_port.h>
26#include <trex_rpc_cmds_table.h>
27
28#include <internal_api/trex_platform_api.h>
29
30#include "trex_stateless_rx_core.h"
31
32#include <fstream>
33#include <iostream>
34#include <unistd.h>
35
36#ifdef RTE_DPDK
37    #include <../linux_dpdk/version.h>
38#endif
39
40using namespace std;
41
42/**
43 * API sync
44 */
45trex_rpc_cmd_rc_e
46TrexRpcCmdAPISync::_run(const Json::Value &params, Json::Value &result) {
47    const Json::Value &api_vers = parse_array(params, "api_vers", result);
48
49    Json::Value api_ver_rc = Json::arrayValue;
50
51    /* for every element in the list - generate the appropirate API handler */
52    for (const auto api_ver : api_vers) {
53        Json::Value single_rc;
54
55        /* only those are supported */
56        const std::string type = parse_choice(api_ver, "type", {"core"}, result);
57
58        int major = parse_int(api_ver, "major", result);
59        int minor = parse_int(api_ver, "minor", result);
60        APIClass::type_e api_type;
61
62        /* decode type of API */
63        if (type == "core") {
64            api_type = APIClass::API_CLASS_TYPE_CORE;
65        }
66
67        single_rc["type"]    = type;
68
69        /* this section might throw exception in case versions do not match */
70        try {
71            single_rc["api_h"] = get_stateless_obj()->verify_api(api_type, major, minor);
72
73        } catch (const TrexAPIException &e) {
74            generate_execute_err(result, e.what());
75        }
76
77        /* add to the response */
78        api_ver_rc.append(single_rc);
79    }
80
81    result["result"]["api_vers"] = api_ver_rc;
82
83    return (TREX_RPC_CMD_OK);
84}
85
86/**
87 * ping command
88 */
89trex_rpc_cmd_rc_e
90TrexRpcCmdPing::_run(const Json::Value &params, Json::Value &result) {
91
92    result["result"] = Json::objectValue;
93    return (TREX_RPC_CMD_OK);
94}
95
96/**
97 * shutdown command
98 */
99trex_rpc_cmd_rc_e
100TrexRpcCmdShutdown::_run(const Json::Value &params, Json::Value &result) {
101
102    const string &user = parse_string(params, "user", result);
103    bool force = parse_bool(params, "force", result);
104
105    /* verify every port is either free or owned by the issuer */
106    for (auto port : get_stateless_obj()->get_port_list()) {
107        TrexPortOwner &owner = port->get_owner();
108        if ( (!owner.is_free()) && (!owner.is_owned_by(user)) && !force) {
109            std::stringstream ss;
110            ss << "port " << int(port->get_port_id()) << " is owned by '" << owner.get_name() << "' - specify 'force' for override";
111            generate_execute_err(result, ss.str());
112        }
113    }
114
115    /* signal that we got a shutdown request */
116    get_stateless_obj()->get_platform_api()->mark_for_shutdown();
117
118    result["result"] = Json::objectValue;
119    return (TREX_RPC_CMD_OK);
120}
121
122/**
123 * query command
124 */
125trex_rpc_cmd_rc_e
126TrexRpcCmdGetCmds::_run(const Json::Value &params, Json::Value &result) {
127    vector<string> cmds;
128
129    TrexRpcCommandsTable::get_instance().query(cmds);
130
131    Json::Value test = Json::arrayValue;
132    for (auto cmd : cmds) {
133        test.append(cmd);
134    }
135
136    result["result"] = test;
137
138    return (TREX_RPC_CMD_OK);
139}
140
141/**
142 * get version
143 *
144 */
145trex_rpc_cmd_rc_e
146TrexRpcCmdGetVersion::_run(const Json::Value &params, Json::Value &result) {
147
148    Json::Value &section = result["result"];
149
150    #ifdef RTE_DPDK
151
152    section["version"]       = VERSION_BUILD_NUM;
153    section["build_date"]    = get_build_date();
154    section["build_time"]    = get_build_time();
155    section["built_by"]      = VERSION_USER;
156
157    #else
158
159    section["version"]       = "v1.75";
160    section["build_date"]    = __DATE__;
161    section["build_time"]    = __TIME__;
162    section["built_by"]      = "MOCK";
163
164    #endif
165
166    return (TREX_RPC_CMD_OK);
167}
168
169trex_rpc_cmd_rc_e
170TrexRpcCmdGetActivePGIds::_run(const Json::Value &params, Json::Value &result) {
171    flow_stat_active_t active_flow_stat;
172    flow_stat_active_it_t it;
173    int i = 0;
174
175    Json::Value &section = result["result"];
176    section["ids"] = Json::arrayValue;
177
178    if (get_stateless_obj()->get_platform_api()->get_active_pgids(active_flow_stat) < 0)
179        return TREX_RPC_CMD_INTERNAL_ERR;
180
181    for (it = active_flow_stat.begin(); it != active_flow_stat.end(); it++) {
182        section["ids"][i++] = *it;
183    }
184
185    return (TREX_RPC_CMD_OK);
186}
187
188// get utilization of CPU per thread with up to 20 latest values + mbufs per socket
189trex_rpc_cmd_rc_e
190TrexRpcCmdGetUtilization::_run(const Json::Value &params, Json::Value &result) {
191    cpu_util_full_t cpu_util_full;
192
193    Json::Value &section = result["result"];
194
195    if (get_stateless_obj()->get_platform_api()->get_mbuf_util(section) != 0) {
196        return TREX_RPC_CMD_INTERNAL_ERR;
197    }
198
199    if (get_stateless_obj()->get_platform_api()->get_cpu_util_full(cpu_util_full) != 0) {
200        return TREX_RPC_CMD_INTERNAL_ERR;
201    }
202
203    for (int thread_id = 0; thread_id < cpu_util_full.size(); thread_id++) {
204
205        /* history */
206        for (int history_id = 0; history_id < cpu_util_full[thread_id].m_history.size(); history_id++) {
207            section["cpu"][thread_id]["history"].append(cpu_util_full[thread_id].m_history[history_id]);
208        }
209
210        /* ports */
211        section["cpu"][thread_id]["ports"] = Json::arrayValue;
212        section["cpu"][thread_id]["ports"].append(cpu_util_full[thread_id].m_port1);
213        section["cpu"][thread_id]["ports"].append(cpu_util_full[thread_id].m_port2);
214    }
215
216    return (TREX_RPC_CMD_OK);
217}
218
219/**
220 * get the CPU model
221 *
222 */
223std::string
224TrexRpcCmdGetSysInfo::get_cpu_model() {
225
226    static const string cpu_prefix = "model name";
227    std::ifstream cpuinfo("/proc/cpuinfo");
228
229    if (cpuinfo.is_open()) {
230        while (cpuinfo.good()) {
231
232            std::string line;
233            getline(cpuinfo, line);
234
235            int pos = line.find(cpu_prefix);
236            if (pos == string::npos) {
237                continue;
238            }
239
240            /* trim it */
241            int index = cpu_prefix.size() + 1;
242            while ( (line[index] == ' ') || (line[index] == ':') ) {
243                index++;
244            }
245
246            return line.substr(index);
247        }
248    }
249
250    return "unknown";
251}
252
253void
254TrexRpcCmdGetSysInfo::get_hostname(string &hostname) {
255    char buffer[256];
256    buffer[0] = 0;
257
258    gethostname(buffer, sizeof(buffer));
259
260    /* write hostname */
261    hostname = buffer;
262}
263
264/**
265 * get system info
266 *
267 */
268trex_rpc_cmd_rc_e
269TrexRpcCmdGetSysInfo::_run(const Json::Value &params, Json::Value &result) {
270    string hostname;
271
272    TrexStateless * main = get_stateless_obj();
273
274    Json::Value &section = result["result"];
275
276    get_hostname(hostname);
277    section["hostname"]  = hostname;
278
279    section["uptime"] = TrexRpcServer::get_server_uptime();
280
281    /* FIXME: core count */
282    section["dp_core_count"] = main->get_dp_core_count();
283    section["dp_core_count_per_port"] = main->get_dp_core_count() / (main->get_port_count() / 2);
284    section["core_type"] = get_cpu_model();
285
286    /* ports */
287
288
289    section["port_count"] = main->get_port_count();
290
291    section["ports"] = Json::arrayValue;
292
293    for (int i = 0; i < main->get_port_count(); i++) {
294        string driver;
295        string pci_addr;
296        string description;
297        supp_speeds_t supp_speeds;
298        int numa;
299
300        TrexStatelessPort *port = main->get_port_by_id(i);
301
302        port->get_properties(driver);
303
304        port->get_pci_info(pci_addr, numa);
305        main->get_platform_api()->getPortAttrObj(i)->get_description(description);
306        main->get_platform_api()->getPortAttrObj(i)->get_supported_speeds(supp_speeds);
307
308        section["ports"][i]["index"]   = i;
309
310        section["ports"][i]["driver"]       = driver;
311        section["ports"][i]["description"]  = description;
312
313        section["ports"][i]["pci_addr"]     = pci_addr;
314        section["ports"][i]["numa"]         = numa;
315
316        uint16_t caps = port->get_rx_caps();
317        section["ports"][i]["rx"]["caps"]      = Json::arrayValue;
318        if (caps & TrexPlatformApi::IF_STAT_IPV4_ID) {
319            section["ports"][i]["rx"]["caps"].append("flow_stats");
320        }
321        if (caps & TrexPlatformApi::IF_STAT_PAYLOAD) {
322            section["ports"][i]["rx"]["caps"].append("latency");
323        }
324        if (caps & TrexPlatformApi::IF_STAT_RX_BYTES_COUNT) {
325            section["ports"][i]["rx"]["caps"].append("rx_bytes");
326        }
327        section["ports"][i]["rx"]["counters"]  = port->get_rx_count_num();
328        section["ports"][i]["is_fc_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_fc_change_supported();
329        section["ports"][i]["is_led_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_led_change_supported();
330        section["ports"][i]["is_link_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_link_change_supported();
331        section["ports"][i]["is_virtual"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_virtual();
332        section["ports"][i]["supp_speeds"] = Json::arrayValue;
333        for (int speed_id=0; speed_id<supp_speeds.size(); speed_id++) {
334            section["ports"][i]["supp_speeds"].append(supp_speeds[speed_id]);
335        }
336
337    }
338
339    return (TREX_RPC_CMD_OK);
340}
341
342
343int
344TrexRpcCmdSetPortAttr::parse_rx_filter_mode(const Json::Value &msg, uint8_t port_id, Json::Value &result) {
345    const std::string type = parse_choice(msg, "mode", {"hw", "all"}, result);
346
347    rx_filter_mode_e filter_mode;
348    if (type == "hw") {
349        filter_mode = RX_FILTER_MODE_HW;
350    } else if (type == "all") {
351        filter_mode = RX_FILTER_MODE_ALL;
352    } else {
353        /* can't happen - parsed choice */
354        assert(0);
355    }
356
357    return get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_rx_filter_mode(filter_mode);
358}
359
360/**
361 * set port commands
362 *
363 * @author imarom (24-Feb-16)
364 *
365 * @param params
366 * @param result
367 *
368 * @return trex_rpc_cmd_rc_e
369 */
370trex_rpc_cmd_rc_e
371TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
372
373    uint8_t port_id = parse_port(params, result);
374
375    const Json::Value &attr = parse_object(params, "attr", result);
376
377    int ret = 0;
378
379    /* iterate over all attributes in the dict */
380    for (const std::string &name : attr.getMemberNames()) {
381
382        if (name == "promiscuous") {
383            bool enabled = parse_bool(attr[name], "enabled", result);
384            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_promiscuous(enabled);
385        }
386
387        else if (name == "link_status") {
388            bool up = parse_bool(attr[name], "up", result);
389            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_link_up(up);
390        }
391
392        else if (name == "led_status") {
393            bool on = parse_bool(attr[name], "on", result);
394            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_led(on);
395        }
396
397        else if (name == "flow_ctrl_mode") {
398            int mode = parse_int(attr[name], "mode", result);
399            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_flow_ctrl(mode);
400        }
401
402        else if (name == "rx_filter_mode") {
403            const Json::Value &rx = parse_object(attr, name, result);
404            ret = parse_rx_filter_mode(rx, port_id, result);
405        }
406
407        /* unknown attribute */
408        else {
409            generate_execute_err(result, "unknown attribute type: '" + name + "'");
410            break;
411        }
412
413        /* check error code */
414        if ( ret == -ENOTSUP ) {
415            generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC.");
416        } else if (ret) {
417            generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret));
418        }
419    }
420
421    result["result"] = Json::objectValue;
422    return (TREX_RPC_CMD_OK);
423
424}
425
426
427/**
428 * returns the current owner of the device
429 *
430 * @author imarom (08-Sep-15)
431 *
432 * @param params
433 * @param result
434 *
435 * @return trex_rpc_cmd_rc_e
436 */
437trex_rpc_cmd_rc_e
438TrexRpcCmdGetOwner::_run(const Json::Value &params, Json::Value &result) {
439    Json::Value &section = result["result"];
440
441    uint8_t port_id = parse_port(params, result);
442
443    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
444    section["owner"] = port->get_owner().get_name();
445
446    return (TREX_RPC_CMD_OK);
447}
448
449/**
450 * acquire device
451 *
452 */
453trex_rpc_cmd_rc_e
454TrexRpcCmdAcquire::_run(const Json::Value &params, Json::Value &result) {
455
456    uint8_t port_id = parse_port(params, result);
457
458    const string  &new_owner  = parse_string(params, "user", result);
459    bool force = parse_bool(params, "force", result);
460    uint32_t session_id = parse_uint32(params, "session_id", result);
461
462    /* if not free and not you and not force - fail */
463    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
464
465    try {
466        port->acquire(new_owner, session_id, force);
467    } catch (const TrexException &ex) {
468        generate_execute_err(result, ex.what());
469    }
470
471    result["result"] = port->get_owner().get_handler();
472
473    return (TREX_RPC_CMD_OK);
474}
475
476/**
477 * release device
478 *
479 */
480trex_rpc_cmd_rc_e
481TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
482
483    uint8_t port_id = parse_port(params, result);
484
485    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
486
487    try {
488        port->release();
489    } catch (const TrexException &ex) {
490        generate_execute_err(result, ex.what());
491    }
492
493    result["result"] = Json::objectValue;
494
495    return (TREX_RPC_CMD_OK);
496}
497
498/**
499 * get port extended stats names (keys of dict)
500 *
501 */
502trex_rpc_cmd_rc_e
503TrexRpcCmdGetPortXStatsNames::_run(const Json::Value &params, Json::Value &result) {
504
505    uint8_t port_id = parse_port(params, result);
506    xstats_names_t xstats_names;
507
508    int ret = get_stateless_obj()->get_platform_api()->get_xstats_names(port_id, xstats_names);
509    if (ret < 0) {
510        if ( ret == -ENOTSUP ) {
511            generate_execute_err(result, "Operation not supported");
512        }
513        else if (ret) {
514            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
515        }
516    } else {
517        for (int i=0; i<xstats_names.size(); i++) {
518            result["result"]["xstats_names"].append(xstats_names[i]);
519        }
520    }
521
522    return (TREX_RPC_CMD_OK);
523}
524
525/**
526 * get port extended stats (values of dict)
527 *
528 */
529trex_rpc_cmd_rc_e
530TrexRpcCmdGetPortXStatsValues::_run(const Json::Value &params, Json::Value &result) {
531
532    uint8_t port_id = parse_port(params, result);
533    xstats_values_t xstats_values;
534
535    int ret = get_stateless_obj()->get_platform_api()->get_xstats_values(port_id, xstats_values);
536    if (ret < 0) {
537        if ( ret == -ENOTSUP ) {
538            generate_execute_err(result, "Operation not supported");
539        }
540        else if (ret) {
541            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
542        }
543    } else {
544        for (int i=0; i<xstats_values.size(); i++) {
545            result["result"]["xstats_values"].append((Json::Value::UInt64) xstats_values[i]);
546        }
547    }
548
549    return (TREX_RPC_CMD_OK);
550}
551
552/**
553 * get port stats
554 *
555 */
556trex_rpc_cmd_rc_e
557TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
558
559    uint8_t port_id = parse_port(params, result);
560
561    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
562
563    try {
564        port->encode_stats(result["result"]);
565    } catch (const TrexException &ex) {
566        generate_execute_err(result, ex.what());
567    }
568
569    return (TREX_RPC_CMD_OK);
570}
571
572/**
573 * fetch the port status
574 *
575 * @author imarom (09-Dec-15)
576 *
577 * @param params
578 * @param result
579 *
580 * @return trex_rpc_cmd_rc_e
581 */
582trex_rpc_cmd_rc_e
583TrexRpcCmdGetPortStatus::_run(const Json::Value &params, Json::Value &result) {
584    uint8_t port_id = parse_port(params, result);
585
586    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
587
588    result["result"]["owner"]         = (port->get_owner().is_free() ? "" : port->get_owner().get_name());
589    result["result"]["state"]         = port->get_state_as_string();
590    result["result"]["max_stream_id"] = port->get_max_stream_id();
591
592    /* attributes */
593    get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->to_json(result["result"]["attr"]);
594
595    /* RX info */
596    try {
597        result["result"]["rx_info"] = port->rx_features_to_json();
598    } catch (const TrexException &ex) {
599        generate_execute_err(result, ex.what());
600    }
601
602    return (TREX_RPC_CMD_OK);
603}
604
605/**
606 * publish async data now (fast flush)
607 *
608 */
609trex_rpc_cmd_rc_e
610TrexRpcPublishNow::_run(const Json::Value &params, Json::Value &result) {
611    TrexStateless *main = get_stateless_obj();
612
613    uint32_t key  = parse_uint32(params, "key", result);
614    bool baseline = parse_bool(params, "baseline", result);
615
616    main->get_platform_api()->publish_async_data_now(key, baseline);
617
618    result["result"] = Json::objectValue;
619    return (TREX_RPC_CMD_OK);
620
621}
622
623
624/**
625 * push a remote PCAP on a port
626 *
627 */
628trex_rpc_cmd_rc_e
629TrexRpcCmdPushRemote::_run(const Json::Value &params, Json::Value &result) {
630
631    uint8_t port_id = parse_port(params, result);
632    std::string  pcap_filename  = parse_string(params, "pcap_filename", result);
633    double       ipg_usec       = parse_double(params, "ipg_usec", result);
634    double       speedup        = parse_double(params, "speedup", result);
635    uint32_t     count          = parse_uint32(params, "count", result);
636    double       duration       = parse_double(params, "duration", result);
637    bool         is_dual        = parse_bool(params,   "is_dual", result, false);
638    std::string  slave_handler  = parse_string(params, "slave_handler", result, "");
639
640    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
641
642    /* for dual mode - make sure slave_handler matches */
643    if (is_dual) {
644        TrexStatelessPort *slave = get_stateless_obj()->get_port_by_id(port_id ^ 0x1);
645        if (!slave->get_owner().verify(slave_handler)) {
646            generate_execute_err(result, "incorrect or missing slave port handler");
647        }
648    }
649
650
651    try {
652        port->push_remote(pcap_filename, ipg_usec, speedup, count, duration, is_dual);
653    } catch (const TrexException &ex) {
654        generate_execute_err(result, ex.what());
655    }
656
657    result["result"] = Json::objectValue;
658    return (TREX_RPC_CMD_OK);
659
660}
661
662/**
663 * set on/off RX software receive mode
664 *
665 */
666trex_rpc_cmd_rc_e
667TrexRpcCmdSetRxFeature::_run(const Json::Value &params, Json::Value &result) {
668
669    uint8_t port_id = parse_port(params, result);
670    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
671
672    /* decide which feature is being set */
673    const std::string type = parse_choice(params, "type", {"capture", "queue", "server"}, result);
674
675    if (type == "capture") {
676        parse_capture_msg(params, port, result);
677    } else if (type == "queue") {
678        parse_queue_msg(params, port, result);
679    } else if (type == "server") {
680        parse_server_msg(params, port, result);
681    } else {
682        assert(0);
683    }
684
685    result["result"] = Json::objectValue;
686    return (TREX_RPC_CMD_OK);
687
688}
689
690void
691TrexRpcCmdSetRxFeature::parse_capture_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
692
693    bool enabled = parse_bool(msg, "enabled", result);
694
695    if (enabled) {
696
697        std::string pcap_filename = parse_string(msg, "pcap_filename", result);
698        uint64_t limit = parse_uint32(msg, "limit", result);
699
700        if (limit == 0) {
701            generate_parse_err(result, "limit cannot be zero");
702        }
703
704        try {
705            port->start_rx_capture(pcap_filename, limit);
706        } catch (const TrexException &ex) {
707            generate_execute_err(result, ex.what());
708        }
709
710    } else {
711
712        try {
713            port->stop_rx_capture();
714        } catch (const TrexException &ex) {
715            generate_execute_err(result, ex.what());
716        }
717
718    }
719
720}
721
722void
723TrexRpcCmdSetRxFeature::parse_queue_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
724    bool enabled = parse_bool(msg, "enabled", result);
725
726    if (enabled) {
727
728        uint64_t size = parse_uint32(msg, "size", result);
729
730        if (size == 0) {
731            generate_parse_err(result, "queue size cannot be zero");
732        }
733
734        try {
735            port->start_rx_queue(size);
736        } catch (const TrexException &ex) {
737            generate_execute_err(result, ex.what());
738        }
739
740    } else {
741
742        try {
743            port->stop_rx_queue();
744        } catch (const TrexException &ex) {
745            generate_execute_err(result, ex.what());
746        }
747
748    }
749
750}
751
752void
753TrexRpcCmdSetRxFeature::parse_server_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
754}
755
756
757trex_rpc_cmd_rc_e
758TrexRpcCmdGetRxQueuePkts::_run(const Json::Value &params, Json::Value &result) {
759
760    uint8_t port_id = parse_port(params, result);
761
762    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
763
764    try {
765        const RXPacketBuffer *pkt_buffer = port->get_rx_queue_pkts();
766        if (pkt_buffer) {
767            result["result"]["pkts"] = pkt_buffer->to_json();
768            delete pkt_buffer;
769
770        } else {
771            result["result"]["pkts"] = Json::arrayValue;
772        }
773
774    } catch (const TrexException &ex) {
775        generate_execute_err(result, ex.what());
776    }
777
778
779    return (TREX_RPC_CMD_OK);
780}
781
782
783/**
784 * configures a port in L2 mode
785 *
786 */
787trex_rpc_cmd_rc_e
788TrexRpcCmdSetL2::_run(const Json::Value &params, Json::Value &result) {
789    uint8_t port_id = parse_port(params, result);
790
791    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
792
793    const std::string dst_mac_str  = parse_string(params, "dst_mac", result);
794
795    uint8_t dst_mac[6];
796    if (!utl_str_to_macaddr(dst_mac_str, dst_mac)) {
797        std::stringstream ss;
798        ss << "'invalid MAC address: '" << dst_mac_str << "'";
799        generate_parse_err(result, ss.str());
800    }
801
802    port->set_l2_mode(dst_mac);
803
804    return (TREX_RPC_CMD_OK);
805}
806
807/**
808 * configures a port in L3 mode
809 *
810 */
811trex_rpc_cmd_rc_e
812TrexRpcCmdSetL3::_run(const Json::Value &params, Json::Value &result) {
813    uint8_t port_id = parse_port(params, result);
814
815    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
816
817    const std::string src_ipv4_str  = parse_string(params, "src_addr", result);
818    const std::string dst_ipv4_str  = parse_string(params, "dst_addr", result);
819
820    uint32_t src_ipv4;
821    if (!utl_ipv4_to_uint32(src_ipv4_str.c_str(), src_ipv4)) {
822        std::stringstream ss;
823        ss << "invalid source IPv4 address: '" << src_ipv4_str << "'";
824        generate_parse_err(result, ss.str());
825    }
826
827    uint32_t dst_ipv4;
828    if (!utl_ipv4_to_uint32(dst_ipv4_str.c_str(), dst_ipv4)) {
829        std::stringstream ss;
830        ss << "invalid destination IPv4 address: '" << dst_ipv4_str << "'";
831        generate_parse_err(result, ss.str());
832    }
833
834
835
836    /* did we get a resolved MAC as well ? */
837    if (params["resolved_mac"] != Json::Value::null) {
838        const std::string resolved_mac  = parse_string(params, "resolved_mac", result);
839
840        uint8_t mac[6];
841        if (!utl_str_to_macaddr(resolved_mac, mac)) {
842            std::stringstream ss;
843            ss << "'invalid MAC address: '" << resolved_mac << "'";
844            generate_parse_err(result, ss.str());
845        }
846
847        port->set_l3_mode(src_ipv4, dst_ipv4, mac);
848
849    } else {
850
851        port->set_l3_mode(src_ipv4, dst_ipv4);
852    }
853
854    return (TREX_RPC_CMD_OK);
855
856}
857