trex_rpc_cmd_general.cpp revision d09b1239
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 hw_macaddr;
296        string src_macaddr;
297        string dst_macaddr;
298        string pci_addr;
299        string description;
300        supp_speeds_t supp_speeds;
301        int numa;
302
303        TrexStatelessPort *port = main->get_port_by_id(i);
304
305        port->get_properties(driver);
306        port->get_macaddr(hw_macaddr, src_macaddr, dst_macaddr);
307
308        port->get_pci_info(pci_addr, numa);
309        main->get_platform_api()->getPortAttrObj(i)->get_description(description);
310        main->get_platform_api()->getPortAttrObj(i)->get_supported_speeds(supp_speeds);
311
312        section["ports"][i]["index"]   = i;
313
314        section["ports"][i]["driver"]       = driver;
315        section["ports"][i]["description"]  = description;
316        section["ports"][i]["hw_macaddr"]   = hw_macaddr;
317        section["ports"][i]["src_macaddr"]  = src_macaddr;
318        section["ports"][i]["dst_macaddr"]  = dst_macaddr;
319
320        section["ports"][i]["pci_addr"]         = pci_addr;
321        section["ports"][i]["numa"]             = numa;
322
323        uint16_t caps = port->get_rx_caps();
324        section["ports"][i]["rx"]["caps"]      = Json::arrayValue;
325        if (caps & TrexPlatformApi::IF_STAT_IPV4_ID) {
326            section["ports"][i]["rx"]["caps"].append("flow_stats");
327        }
328        if (caps & TrexPlatformApi::IF_STAT_PAYLOAD) {
329            section["ports"][i]["rx"]["caps"].append("latency");
330        }
331        if (caps & TrexPlatformApi::IF_STAT_RX_BYTES_COUNT) {
332            section["ports"][i]["rx"]["caps"].append("rx_bytes");
333        }
334        section["ports"][i]["rx"]["counters"]  = port->get_rx_count_num();
335        section["ports"][i]["is_fc_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_fc_change_supported();
336        section["ports"][i]["is_led_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_led_change_supported();
337        section["ports"][i]["is_link_supported"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_link_change_supported();
338        section["ports"][i]["is_virtual"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(i)->is_virtual();
339        section["ports"][i]["supp_speeds"] = Json::arrayValue;
340        for (int speed_id=0; speed_id<supp_speeds.size(); speed_id++) {
341            section["ports"][i]["supp_speeds"].append(supp_speeds[speed_id]);
342        }
343
344    }
345
346    return (TREX_RPC_CMD_OK);
347}
348
349
350int
351TrexRpcCmdSetPortAttr::parse_rx_filter_mode(const Json::Value &msg, uint8_t port_id, Json::Value &result) {
352    const std::string type = parse_choice(msg, "mode", {"hw", "all"}, result);
353
354    rx_filter_mode_e filter_mode;
355    if (type == "hw") {
356        filter_mode = RX_FILTER_MODE_HW;
357    } else if (type == "all") {
358        filter_mode = RX_FILTER_MODE_ALL;
359    } else {
360        assert(0);
361    }
362
363    return get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_rx_filter_mode(filter_mode);
364}
365
366/**
367 * set port commands
368 *
369 * @author imarom (24-Feb-16)
370 *
371 * @param params
372 * @param result
373 *
374 * @return trex_rpc_cmd_rc_e
375 */
376trex_rpc_cmd_rc_e
377TrexRpcCmdSetPortAttr::_run(const Json::Value &params, Json::Value &result) {
378
379    uint8_t port_id = parse_port(params, result);
380
381    const Json::Value &attr = parse_object(params, "attr", result);
382    int ret = 0;
383
384    /* iterate over all attributes in the dict */
385    for (const std::string &name : attr.getMemberNames()) {
386
387        if (name == "promiscuous") {
388            bool enabled = parse_bool(attr[name], "enabled", result);
389            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_promiscuous(enabled);
390        }
391
392        else if (name == "link_status") {
393            bool up = parse_bool(attr[name], "up", result);
394            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_link_up(up);
395        }
396
397        else if (name == "led_status") {
398            bool on = parse_bool(attr[name], "on", result);
399            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_led(on);
400        }
401
402        else if (name == "flow_ctrl_mode") {
403            int mode = parse_int(attr[name], "mode", result);
404            ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->set_flow_ctrl(mode);
405        }
406
407        else if (name == "rx_filter_mode") {
408            ret = parse_rx_filter_mode(attr[name], port_id, result);
409        }
410
411        else {
412            generate_execute_err(result, "Not recognized attribute: " + name);
413            break;
414        }
415
416        if ( ret == -ENOTSUP ) {
417            generate_execute_err(result, "Error applying " + name + ": operation is not supported for this NIC.");
418        }
419        else if (ret) {
420            generate_execute_err(result, "Error applying " + name + " attribute, return value: " + to_string(ret));
421        }
422    }
423
424    result["result"] = Json::objectValue;
425    return (TREX_RPC_CMD_OK);
426}
427
428
429/**
430 * returns the current owner of the device
431 *
432 * @author imarom (08-Sep-15)
433 *
434 * @param params
435 * @param result
436 *
437 * @return trex_rpc_cmd_rc_e
438 */
439trex_rpc_cmd_rc_e
440TrexRpcCmdGetOwner::_run(const Json::Value &params, Json::Value &result) {
441    Json::Value &section = result["result"];
442
443    uint8_t port_id = parse_port(params, result);
444
445    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
446    section["owner"] = port->get_owner().get_name();
447
448    return (TREX_RPC_CMD_OK);
449}
450
451/**
452 * acquire device
453 *
454 */
455trex_rpc_cmd_rc_e
456TrexRpcCmdAcquire::_run(const Json::Value &params, Json::Value &result) {
457
458    uint8_t port_id = parse_port(params, result);
459
460    const string  &new_owner  = parse_string(params, "user", result);
461    bool force = parse_bool(params, "force", result);
462    uint32_t session_id = parse_uint32(params, "session_id", result);
463
464    /* if not free and not you and not force - fail */
465    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
466
467    try {
468        port->acquire(new_owner, session_id, force);
469    } catch (const TrexException &ex) {
470        generate_execute_err(result, ex.what());
471    }
472
473    result["result"] = port->get_owner().get_handler();
474
475    return (TREX_RPC_CMD_OK);
476}
477
478/**
479 * release device
480 *
481 */
482trex_rpc_cmd_rc_e
483TrexRpcCmdRelease::_run(const Json::Value &params, Json::Value &result) {
484
485    uint8_t port_id = parse_port(params, result);
486
487    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
488
489    try {
490        port->release();
491    } catch (const TrexException &ex) {
492        generate_execute_err(result, ex.what());
493    }
494
495    result["result"] = Json::objectValue;
496
497    return (TREX_RPC_CMD_OK);
498}
499
500/**
501 * get port extended stats names (keys of dict)
502 *
503 */
504trex_rpc_cmd_rc_e
505TrexRpcCmdGetPortXStatsNames::_run(const Json::Value &params, Json::Value &result) {
506
507    uint8_t port_id = parse_port(params, result);
508    xstats_names_t xstats_names;
509
510    int ret = get_stateless_obj()->get_platform_api()->get_xstats_names(port_id, xstats_names);
511    if (ret < 0) {
512        if ( ret == -ENOTSUP ) {
513            generate_execute_err(result, "Operation not supported");
514        }
515        else if (ret) {
516            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
517        }
518    } else {
519        for (int i=0; i<xstats_names.size(); i++) {
520            result["result"]["xstats_names"].append(xstats_names[i]);
521        }
522    }
523
524    return (TREX_RPC_CMD_OK);
525}
526
527/**
528 * get port extended stats (values of dict)
529 *
530 */
531trex_rpc_cmd_rc_e
532TrexRpcCmdGetPortXStatsValues::_run(const Json::Value &params, Json::Value &result) {
533
534    uint8_t port_id = parse_port(params, result);
535    xstats_values_t xstats_values;
536
537    int ret = get_stateless_obj()->get_platform_api()->get_xstats_values(port_id, xstats_values);
538    if (ret < 0) {
539        if ( ret == -ENOTSUP ) {
540            generate_execute_err(result, "Operation not supported");
541        }
542        else if (ret) {
543            generate_execute_err(result, "Operation failed, error code: " + to_string(ret));
544        }
545    } else {
546        for (int i=0; i<xstats_values.size(); i++) {
547            result["result"]["xstats_values"].append((Json::Value::UInt64) xstats_values[i]);
548        }
549    }
550
551    return (TREX_RPC_CMD_OK);
552}
553
554/**
555 * get port stats
556 *
557 */
558trex_rpc_cmd_rc_e
559TrexRpcCmdGetPortStats::_run(const Json::Value &params, Json::Value &result) {
560
561    uint8_t port_id = parse_port(params, result);
562
563    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
564
565    try {
566        port->encode_stats(result["result"]);
567    } catch (const TrexException &ex) {
568        generate_execute_err(result, ex.what());
569    }
570
571    return (TREX_RPC_CMD_OK);
572}
573
574/**
575 * fetch the port status
576 *
577 * @author imarom (09-Dec-15)
578 *
579 * @param params
580 * @param result
581 *
582 * @return trex_rpc_cmd_rc_e
583 */
584trex_rpc_cmd_rc_e
585TrexRpcCmdGetPortStatus::_run(const Json::Value &params, Json::Value &result) {
586    uint8_t port_id = parse_port(params, result);
587
588    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
589
590    result["result"]["owner"]         = (port->get_owner().is_free() ? "" : port->get_owner().get_name());
591    result["result"]["state"]         = port->get_state_as_string();
592    result["result"]["max_stream_id"] = port->get_max_stream_id();
593
594    /* attributes */
595    result["result"]["attr"]["promiscuous"]["enabled"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_promiscuous();
596    result["result"]["attr"]["link"]["up"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->is_link_up();
597    result["result"]["attr"]["speed"]      = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_link_speed();
598
599    int mode;
600    int ret = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_flow_ctrl(mode);
601    if (ret != 0) {
602        mode = -1;
603    }
604    result["result"]["attr"]["fc"]["mode"] = mode;
605
606    /* RX filter */
607    result["result"]["attr"]["rx_filter_mode"] = get_stateless_obj()->get_platform_api()->getPortAttrObj(port_id)->get_rx_filter_mode();
608
609    /* RX info */
610    port->get_rx_features().to_json(result["result"]["rx_info"]);
611
612    return (TREX_RPC_CMD_OK);
613}
614
615/**
616 * publish async data now (fast flush)
617 *
618 */
619trex_rpc_cmd_rc_e
620TrexRpcPublishNow::_run(const Json::Value &params, Json::Value &result) {
621    TrexStateless *main = get_stateless_obj();
622
623    uint32_t key  = parse_uint32(params, "key", result);
624    bool baseline = parse_bool(params, "baseline", result);
625
626    main->get_platform_api()->publish_async_data_now(key, baseline);
627
628    result["result"] = Json::objectValue;
629    return (TREX_RPC_CMD_OK);
630
631}
632
633
634/**
635 * push a remote PCAP on a port
636 *
637 */
638trex_rpc_cmd_rc_e
639TrexRpcCmdPushRemote::_run(const Json::Value &params, Json::Value &result) {
640
641    uint8_t port_id = parse_port(params, result);
642    std::string  pcap_filename  = parse_string(params, "pcap_filename", result);
643    double       ipg_usec       = parse_double(params, "ipg_usec", result);
644    double       speedup        = parse_double(params, "speedup", result);
645    uint32_t     count          = parse_uint32(params, "count", result);
646    double       duration       = parse_double(params, "duration", result);
647    bool         is_dual        = parse_bool(params,   "is_dual", result, false);
648    std::string  slave_handler  = parse_string(params, "slave_handler", result, "");
649
650    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
651
652    /* for dual mode - make sure slave_handler matches */
653    if (is_dual) {
654        TrexStatelessPort *slave = get_stateless_obj()->get_port_by_id(port_id ^ 0x1);
655        if (!slave->get_owner().verify(slave_handler)) {
656            generate_execute_err(result, "incorrect or missing slave port handler");
657        }
658    }
659
660
661    try {
662        port->push_remote(pcap_filename, ipg_usec, speedup, count, duration, is_dual);
663    } catch (const TrexException &ex) {
664        generate_execute_err(result, ex.what());
665    }
666
667    result["result"] = Json::objectValue;
668    return (TREX_RPC_CMD_OK);
669
670}
671
672/**
673 * set on/off RX software receive mode
674 *
675 */
676trex_rpc_cmd_rc_e
677TrexRpcCmdSetRxFeature::_run(const Json::Value &params, Json::Value &result) {
678
679    uint8_t port_id = parse_port(params, result);
680    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
681
682    /* decide which feature is being set */
683    const std::string type = parse_choice(params, "type", {"capture", "queue", "server"}, result);
684
685    if (type == "capture") {
686        parse_capture_msg(params, port, result);
687    } else if (type == "queue") {
688        parse_queue_msg(params, port, result);
689    } else if (type == "server") {
690        parse_server_msg(params, port, result);
691    } else {
692        assert(0);
693    }
694
695    result["result"] = Json::objectValue;
696    return (TREX_RPC_CMD_OK);
697
698}
699
700void
701TrexRpcCmdSetRxFeature::parse_capture_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
702
703    bool enabled = parse_bool(msg, "enabled", result);
704
705    if (enabled) {
706
707        std::string pcap_filename = parse_string(msg, "pcap_filename", result);
708        uint64_t limit = parse_uint32(msg, "limit", result);
709
710        if (limit == 0) {
711            generate_parse_err(result, "limit cannot be zero");
712        }
713
714        try {
715            port->start_rx_capture(pcap_filename, limit);
716        } catch (const TrexException &ex) {
717            generate_execute_err(result, ex.what());
718        }
719
720    } else {
721
722        try {
723            port->stop_rx_capture();
724        } catch (const TrexException &ex) {
725            generate_execute_err(result, ex.what());
726        }
727
728    }
729
730}
731
732void
733TrexRpcCmdSetRxFeature::parse_queue_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
734	bool enabled = parse_bool(msg, "enabled", result);
735
736	if (enabled) {
737
738		uint64_t size = parse_uint32(msg, "size", result);
739
740		if (size == 0) {
741			generate_parse_err(result, "queue size cannot be zero");
742		}
743
744		try {
745			port->start_rx_queue(size);
746		} catch (const TrexException &ex) {
747			generate_execute_err(result, ex.what());
748		}
749
750	} else {
751
752		try {
753			port->stop_rx_queue();
754		} catch (const TrexException &ex) {
755			generate_execute_err(result, ex.what());
756		}
757
758	}
759
760}
761
762void
763TrexRpcCmdSetRxFeature::parse_server_msg(const Json::Value &msg, TrexStatelessPort *port, Json::Value &result) {
764}
765
766
767trex_rpc_cmd_rc_e
768TrexRpcCmdGetRxQueuePkts::_run(const Json::Value &params, Json::Value &result) {
769
770    uint8_t port_id = parse_port(params, result);
771
772    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id);
773
774    try {
775        RxPacketBuffer *pkt_buffer = port->get_rx_queue_pkts();
776        result["result"]["pkts"] = pkt_buffer->to_json();
777
778    } catch (const TrexException &ex) {
779        generate_execute_err(result, ex.what());
780    }
781
782
783    return (TREX_RPC_CMD_OK);
784}
785