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