From 3689edf311778c8cb921db61f293db6cd43a9b14 Mon Sep 17 00:00:00 2001 From: imarom Date: Wed, 25 Jan 2017 13:54:51 +0200 Subject: capture - personal code review Signed-off-by: imarom --- .../trex_control_plane/stl/console/trex_capture.py | 18 +- .../stl/trex_stl_lib/trex_stl_client.py | 19 +- src/rpc-server/commands/trex_rpc_cmd_general.cpp | 8 +- src/stateless/common/trex_stateless_pkt.cpp | 43 +++- src/stateless/common/trex_stateless_pkt.h | 23 ++- .../messaging/trex_stateless_messaging.cpp | 4 +- src/stateless/messaging/trex_stateless_messaging.h | 3 + src/stateless/rx/trex_stateless_capture.cpp | 98 ++++++--- src/stateless/rx/trex_stateless_capture.h | 229 +++++++-------------- src/stateless/rx/trex_stateless_capture_rc.h | 195 ++++++++++++++++++ 10 files changed, 420 insertions(+), 220 deletions(-) create mode 100644 src/stateless/rx/trex_stateless_capture_rc.h diff --git a/scripts/automation/trex_control_plane/stl/console/trex_capture.py b/scripts/automation/trex_control_plane/stl/console/trex_capture.py index dfd7f0a4..aac685a1 100644 --- a/scripts/automation/trex_control_plane/stl/console/trex_capture.py +++ b/scripts/automation/trex_control_plane/stl/console/trex_capture.py @@ -88,7 +88,10 @@ class CaptureMonitorWriterStdout(CaptureMonitorWriter): # class CaptureMonitorWriterPipe(CaptureMonitorWriter): def __init__ (self, logger): - self.logger = logger + self.logger = logger + self.fifo_name = None + self.fifo = None + self.start_ts = None def init (self, start_ts): self.start_ts = start_ts @@ -125,7 +128,14 @@ class CaptureMonitorWriterPipe(CaptureMonitorWriter): def deinit (self): try: - os.unlink(self.fifo_name) + if self.fifo: + os.close(self.fifo) + self.fifo = None + + if self.fifo_name: + os.unlink(self.fifo_name) + self.fifo_name = None + except OSError: pass @@ -207,7 +217,7 @@ class CaptureMonitor(object): with self.logger.supress(): - data = self.client.start_capture(tx_port_list, rx_port_list, limit = rate_pps) + data = self.client.start_capture(tx_port_list, rx_port_list, limit = rate_pps, mode = 'cyclic') self.capture_id = data['id'] self.start_ts = data['ts'] @@ -477,7 +487,7 @@ class CaptureManager(object): self.record_start_parser.formatted_error('please provide either --tx or --rx') return - rc = self.c.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit) + rc = self.c.start_capture(opts.tx_port_list, opts.rx_port_list, opts.limit, mode = 'fixed') self.logger.log(format_text("*** Capturing ID is set to '{0}' ***".format(rc['id']), 'bold')) self.logger.log(format_text("*** Please call 'capture record stop --id {0} -o ' when done ***\n".format(rc['id']), 'bold')) diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index d81765c6..654ceaf6 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -3005,7 +3005,7 @@ class STLClient(object): @__api_check(True) - def start_capture (self, tx_ports, rx_ports, limit = 1000): + def start_capture (self, tx_ports, rx_ports, limit = 1000, mode = 'fixed'): """ Starts a capture to PCAP on port(s) @@ -3014,6 +3014,11 @@ class STLClient(object): rx_ports - on which ports to capture RX limit - limit how many packets will be written + mode - 'fixed': when full, future packets will be + dropped + 'cyclic: when full, oldest packets will be + dropped + :returns: returns a dictionary containing {'id: , 'ts': } @@ -3023,6 +3028,7 @@ class STLClient(object): """ + # check arguments tx_ports = self._validate_port_list(tx_ports, allow_empty = True) rx_ports = self._validate_port_list(rx_ports, allow_empty = True) merge_ports = set(tx_ports + rx_ports) @@ -3030,28 +3036,29 @@ class STLClient(object): if not merge_ports: raise STLError("start_capture - must get at least one port to capture") - # check arguments validate_type('limit', limit, (int)) if limit <= 0: raise STLError("'limit' must be a positive value") + if mode not in ('fixed', 'cyclic'): + raise STLError("'mode' must be either 'fixed' or 'cyclic'") + + # verify service mode non_service_ports = list_difference(set(tx_ports + rx_ports), self.get_service_enabled_ports()) if non_service_ports: raise STLError("Port(s) {0} are not under service mode. PCAP capturing requires all ports to be in service mode".format(non_service_ports)) + # actual job self.logger.pre_cmd("Starting PCAP capturing up to {0} packets".format(limit)) - - rc = self._transmit("capture", params = {'command': 'start', 'limit': limit, 'tx': tx_ports, 'rx': rx_ports}) + rc = self._transmit("capture", params = {'command': 'start', 'limit': limit, 'mode': mode, 'tx': tx_ports, 'rx': rx_ports}) self.logger.post_cmd(rc) - if not rc: raise STLError(rc) return {'id': rc.data()['capture_id'], 'ts': rc.data()['start_ts']} - def __fetch_capture_packets (self, capture_id, output_filename, pkt_count): diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index c20c77d4..54798abb 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -892,6 +892,12 @@ void TrexRpcCmdCapture::parse_cmd_start(const Json::Value ¶ms, Json::Value &result) { uint32_t limit = parse_uint32(params, "limit", result); + + /* parse mode type */ + const std::string mode_str = parse_choice(params, "mode", {"fixed", "cyclic"}, result); + TrexPktBuffer::mode_e mode = ( (mode_str == "fixed") ? TrexPktBuffer::MODE_DROP_TAIL : TrexPktBuffer::MODE_DROP_HEAD); + + /* parse filters */ const Json::Value &tx_json = parse_array(params, "tx", result); const Json::Value &rx_json = parse_array(params, "rx", result); CaptureFilter filter; @@ -927,7 +933,7 @@ TrexRpcCmdCapture::parse_cmd_start(const Json::Value ¶ms, Json::Value &resul reply.reset(); /* send a start message to RX core */ - TrexStatelessRxCaptureStart *start_msg = new TrexStatelessRxCaptureStart(filter, limit, reply); + TrexStatelessRxCaptureStart *start_msg = new TrexStatelessRxCaptureStart(filter, limit, mode, reply); get_stateless_obj()->send_msg_to_rx(start_msg); TrexCaptureRCStart rc = reply.wait_for_reply(); diff --git a/src/stateless/common/trex_stateless_pkt.cpp b/src/stateless/common/trex_stateless_pkt.cpp index 14c14462..43cbbe1c 100644 --- a/src/stateless/common/trex_stateless_pkt.cpp +++ b/src/stateless/common/trex_stateless_pkt.cpp @@ -120,12 +120,7 @@ TrexPktBuffer::push(const rte_mbuf_t *m, int port, TrexPkt::origin_e origin, uin } } - /* push packet */ - m_buffer[m_head] = new TrexPkt(m, port, origin, pkt_index); - m_bytes += m_buffer[m_head]->get_size(); - - /* advance */ - m_head = next(m_head); + push_internal(new TrexPkt(m, port, origin, pkt_index)); } /** @@ -133,19 +128,32 @@ TrexPktBuffer::push(const rte_mbuf_t *m, int port, TrexPkt::origin_e origin, uin * packet pointer is invalid after this call */ void -TrexPktBuffer::push(const TrexPkt *pkt) { +TrexPktBuffer::push(const TrexPkt *pkt, uint64_t pkt_index) { /* if full - decide by the policy */ if (is_full()) { if (m_mode == MODE_DROP_HEAD) { delete pop(); } else { /* drop the tail (current packet) */ - delete pkt; return; } } - /* push packet */ + /* duplicate packet */ + TrexPkt *dup = new TrexPkt(*pkt); + + /* update packet index if given */ + if (pkt_index != 0) { + dup->set_index(pkt_index); + } + + push_internal(dup); +} + + +void +TrexPktBuffer::push_internal(const TrexPkt *pkt) { + /* push the packet */ m_buffer[m_head] = pkt; m_bytes += pkt->get_size(); @@ -188,3 +196,20 @@ TrexPktBuffer::to_json() const { return output; } +TrexPktBuffer * +TrexPktBuffer::pop_n(uint32_t count) { + /* can't pop more than total */ + assert(count <= get_element_count()); + + // TODO: consider returning NULL if no packets exists + // to avoid mallocing + + TrexPktBuffer *partial = new TrexPktBuffer(count); + + for (int i = 0; i < count; i++) { + const TrexPkt *pkt = pop(); + partial->push_internal(pkt); + } + + return partial; +} diff --git a/src/stateless/common/trex_stateless_pkt.h b/src/stateless/common/trex_stateless_pkt.h index 573f4950..f44355dc 100644 --- a/src/stateless/common/trex_stateless_pkt.h +++ b/src/stateless/common/trex_stateless_pkt.h @@ -70,6 +70,9 @@ public: m_index = index; } + uint64_t get_index() const { + return m_index; + } /* slow path and also RVO - pass by value is ok */ Json::Value to_json() const { @@ -163,13 +166,10 @@ public: /** * push an existing packet structure - * packet will *not* be duplicated - * - * after calling this function - * the packet is no longer usable - * from caller prespective + * packet will be duplicated + * if pkt_index is non zero - it will be updated */ - void push(const TrexPkt *pkt); + void push(const TrexPkt *pkt, uint64_t pkt_index = 0); /** * pops a packet from the buffer @@ -177,6 +177,15 @@ public: */ const TrexPkt * pop(); + /** + * pops N packets from the buffer + * N must be <= get_element_count() + * + * returns a new buffer + */ + TrexPktBuffer * pop_n(uint32_t count); + + /** * generate a JSON output of the queue * @@ -225,6 +234,8 @@ private: return ( (v + 1) % m_size ); } + void push_internal(const TrexPkt *pkt); + mode_e m_mode; int m_head; int m_tail; diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index 21fe7a13..f89ca343 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -266,7 +266,7 @@ TrexStatelessRxCaptureStart::handle(CRxCoreStateless *rx_core) { TrexCaptureRCStart start_rc; - TrexStatelessCaptureMngr::getInstance().start(m_filter, m_limit, start_rc); + TrexStatelessCaptureMngr::getInstance().start(m_filter, m_limit, m_mode, start_rc); /* mark as done */ m_reply.set_reply(start_rc); @@ -305,7 +305,7 @@ TrexStatelessRxCaptureStatus::handle(CRxCoreStateless *rx_core) { TrexCaptureRCStatus status_rc; - status_rc.set_status(TrexStatelessCaptureMngr::getInstance().to_json()); + status_rc.set_rc(TrexStatelessCaptureMngr::getInstance().to_json()); /* mark as done */ m_reply.set_reply(status_rc); diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index ed14b100..cd79d6e7 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -494,10 +494,12 @@ class TrexStatelessRxCaptureStart : public TrexStatelessRxCapture { public: TrexStatelessRxCaptureStart(const CaptureFilter& filter, uint64_t limit, + TrexPktBuffer::mode_e mode, MsgReply &reply) : m_reply(reply) { m_limit = limit; m_filter = filter; + m_mode = mode; } virtual bool handle(CRxCoreStateless *rx_core); @@ -506,6 +508,7 @@ private: uint8_t m_port_id; uint64_t m_limit; CaptureFilter m_filter; + TrexPktBuffer::mode_e m_mode; MsgReply &m_reply; }; diff --git a/src/stateless/rx/trex_stateless_capture.cpp b/src/stateless/rx/trex_stateless_capture.cpp index 7b020444..bf7623d5 100644 --- a/src/stateless/rx/trex_stateless_capture.cpp +++ b/src/stateless/rx/trex_stateless_capture.cpp @@ -21,9 +21,17 @@ limitations under the License. #include "trex_stateless_capture.h" #include "trex_exception.h" -TrexStatelessCapture::TrexStatelessCapture(capture_id_t id, uint64_t limit, const CaptureFilter &filter) { +/************************************** + * Capture + * + * A single instance of a capture + *************************************/ +TrexStatelessCapture::TrexStatelessCapture(capture_id_t id, + uint64_t limit, + const CaptureFilter &filter, + TrexPktBuffer::mode_e mode) { m_id = id; - m_pkt_buffer = new TrexPktBuffer(limit, TrexPktBuffer::MODE_DROP_TAIL); + m_pkt_buffer = new TrexPktBuffer(limit, mode); m_filter = filter; m_state = STATE_ACTIVE; m_start_ts = now_sec(); @@ -37,26 +45,22 @@ TrexStatelessCapture::~TrexStatelessCapture() { } void -TrexStatelessCapture::handle_pkt_tx(TrexPkt *pkt) { +TrexStatelessCapture::handle_pkt_tx(const TrexPkt *pkt) { if (m_state != STATE_ACTIVE) { - delete pkt; return; } /* if not in filter - back off */ if (!m_filter.in_filter(pkt)) { - delete pkt; return; } if (pkt->get_ts() < m_start_ts) { - delete pkt; return; } - pkt->set_index(++m_pkt_index); - m_pkt_buffer->push(pkt); + m_pkt_buffer->push(pkt, ++m_pkt_index); } void @@ -100,9 +104,13 @@ TrexStatelessCapture::to_json() const { return output; } +/** + * fetch up to 'pkt_limit' from the capture + * + */ TrexPktBuffer * TrexStatelessCapture::fetch(uint32_t pkt_limit, uint32_t &pending) { - + /* if the total sum of packets is within the limit range - take it */ if (m_pkt_buffer->get_element_count() <= pkt_limit) { TrexPktBuffer *current = m_pkt_buffer; @@ -111,22 +119,29 @@ TrexStatelessCapture::fetch(uint32_t pkt_limit, uint32_t &pending) { return current; } - /* harder part - partial fetch */ - TrexPktBuffer *partial = new TrexPktBuffer(pkt_limit); - for (int i = 0; i < pkt_limit; i++) { - const TrexPkt *pkt = m_pkt_buffer->pop(); - partial->push(pkt); - } - + /* partial fetch - take a partial list */ + TrexPktBuffer *partial = m_pkt_buffer->pop_n(pkt_limit); pending = m_pkt_buffer->get_element_count(); return partial; } + +/************************************** + * Capture Manager + * handles all the captures + * in the system + *************************************/ + +/** + * holds the global filter in the capture manager + * which ports in the entire system are monitored + */ void TrexStatelessCaptureMngr::update_global_filter() { CaptureFilter new_filter; + /* recalculates the global filter */ for (TrexStatelessCapture *capture : m_captures) { new_filter += capture->get_filter(); } @@ -134,6 +149,10 @@ TrexStatelessCaptureMngr::update_global_filter() { m_global_filter = new_filter; } + +/** + * lookup a specific capture by ID + */ TrexStatelessCapture * TrexStatelessCaptureMngr::lookup(capture_id_t capture_id) { @@ -147,17 +166,37 @@ TrexStatelessCaptureMngr::lookup(capture_id_t capture_id) { return nullptr; } + +int +TrexStatelessCaptureMngr::lookup_index(capture_id_t capture_id) { + for (int i = 0; i < m_captures.size(); i++) { + if (m_captures[i]->get_id() == capture_id) { + return i; + } + } + return -1; +} + + +/** + * starts a new capture + * + */ void -TrexStatelessCaptureMngr::start(const CaptureFilter &filter, uint64_t limit, TrexCaptureRCStart &rc) { +TrexStatelessCaptureMngr::start(const CaptureFilter &filter, + uint64_t limit, + TrexPktBuffer::mode_e mode, + TrexCaptureRCStart &rc) { - if (m_captures.size() > MAX_CAPTURE_SIZE) { + /* check for maximum active captures */ + if (m_captures.size() >= MAX_CAPTURE_SIZE) { rc.set_err(TrexCaptureRC::RC_CAPTURE_LIMIT_REACHED); return; } - + /* create a new capture*/ int new_id = m_id_counter++; - TrexStatelessCapture *new_capture = new TrexStatelessCapture(new_id, limit, filter); + TrexStatelessCapture *new_capture = new TrexStatelessCapture(new_id, limit, filter, mode); m_captures.push_back(new_capture); /* update global filter */ @@ -179,6 +218,7 @@ TrexStatelessCaptureMngr::stop(capture_id_t capture_id, TrexCaptureRCStop &rc) { rc.set_rc(capture->get_pkt_count()); } + void TrexStatelessCaptureMngr::fetch(capture_id_t capture_id, uint32_t pkt_limit, TrexCaptureRCFetch &rc) { TrexStatelessCapture *capture = lookup(capture_id); @@ -190,21 +230,14 @@ TrexStatelessCaptureMngr::fetch(capture_id_t capture_id, uint32_t pkt_limit, Tre uint32_t pending = 0; TrexPktBuffer *pkt_buffer = capture->fetch(pkt_limit, pending); - rc.set_pkt_buffer(pkt_buffer, pending, capture->get_start_ts()); + rc.set_rc(pkt_buffer, pending, capture->get_start_ts()); } void TrexStatelessCaptureMngr::remove(capture_id_t capture_id, TrexCaptureRCRemove &rc) { - - int index = -1; - for (int i = 0; i < m_captures.size(); i++) { - if (m_captures[i]->get_id() == capture_id) { - index = i; - break; - } - } - /* does not exist */ + /* lookup index */ + int index = lookup_index(capture_id); if (index == -1) { rc.set_err(TrexCaptureRC::RC_CAPTURE_NOT_FOUND); return; @@ -219,7 +252,7 @@ TrexStatelessCaptureMngr::remove(capture_id_t capture_id, TrexCaptureRCRemove &r /* update global filter */ update_global_filter(); - rc.set_ok(); + rc.set_rc(); } void @@ -228,11 +261,12 @@ TrexStatelessCaptureMngr::reset() { while (m_captures.size() > 0) { remove(m_captures[0]->get_id(), dummy); + assert(!!dummy); } } void -TrexStatelessCaptureMngr::handle_pkt_tx(TrexPkt *pkt) { +TrexStatelessCaptureMngr::handle_pkt_tx_slow_path(const TrexPkt *pkt) { for (TrexStatelessCapture *capture : m_captures) { capture->handle_pkt_tx(pkt); } diff --git a/src/stateless/rx/trex_stateless_capture.h b/src/stateless/rx/trex_stateless_capture.h index 852aee2a..e4a2e632 100644 --- a/src/stateless/rx/trex_stateless_capture.h +++ b/src/stateless/rx/trex_stateless_capture.h @@ -25,160 +25,14 @@ limitations under the License. #include #include "trex_stateless_pkt.h" +#include "trex_stateless_capture_rc.h" -typedef int32_t capture_id_t; -class TrexCaptureRC { -public: - - TrexCaptureRC() { - m_rc = RC_INVALID; - m_pkt_buffer = NULL; - } - - enum rc_e { - RC_INVALID = 0, - RC_OK = 1, - RC_CAPTURE_NOT_FOUND, - RC_CAPTURE_LIMIT_REACHED, - RC_CAPTURE_FETCH_UNDER_ACTIVE - }; - - bool operator !() const { - return (m_rc != RC_OK); - } - - std::string get_err() const { - assert(m_rc != RC_INVALID); - - switch (m_rc) { - case RC_OK: - return ""; - case RC_CAPTURE_LIMIT_REACHED: - return "capture limit has reached"; - case RC_CAPTURE_NOT_FOUND: - return "capture ID not found"; - case RC_CAPTURE_FETCH_UNDER_ACTIVE: - return "fetch command cannot be executed on an active capture"; - default: - assert(0); - } - } - - void set_err(rc_e rc) { - m_rc = rc; - } - - Json::Value get_json() const { - return m_json_rc; - } - -public: - rc_e m_rc; - capture_id_t m_capture_id; - TrexPktBuffer *m_pkt_buffer; - Json::Value m_json_rc; -}; - -class TrexCaptureRCStart : public TrexCaptureRC { -public: - - void set_rc(capture_id_t new_id, dsec_t start_ts) { - m_capture_id = new_id; - m_start_ts = start_ts; - m_rc = RC_OK; - - } - - capture_id_t get_new_id() const { - return m_capture_id; - } - - dsec_t get_start_ts() const { - return m_start_ts; - } - -private: - capture_id_t m_capture_id; - dsec_t m_start_ts; -}; - - -class TrexCaptureRCStop : public TrexCaptureRC { -public: - void set_rc(uint32_t pkt_count) { - m_pkt_count = pkt_count; - m_rc = RC_OK; - } - - uint32_t get_pkt_count() const { - return m_pkt_count; - } - -private: - uint32_t m_pkt_count; -}; - -class TrexCaptureRCFetch : public TrexCaptureRC { -public: - - TrexCaptureRCFetch() { - m_pkt_buffer = nullptr; - m_pending = 0; - } - - void set_pkt_buffer(const TrexPktBuffer *pkt_buffer, uint32_t pending, dsec_t start_ts) { - m_pkt_buffer = pkt_buffer; - m_pending = pending; - m_start_ts = start_ts; - m_rc = RC_OK; - } - - const TrexPktBuffer *get_pkt_buffer() const { - return m_pkt_buffer; - } - - uint32_t get_pending() const { - return m_pending; - } - - dsec_t get_start_ts() const { - return m_start_ts; - } - -private: - const TrexPktBuffer *m_pkt_buffer; - uint32_t m_pending; - dsec_t m_start_ts; -}; - -class TrexCaptureRCRemove : public TrexCaptureRC { -public: - void set_ok() { - m_rc = RC_OK; - } -}; - -class TrexCaptureRCStatus : public TrexCaptureRC { -public: - - void set_status(const Json::Value &json) { - m_json = json; - m_rc = RC_OK; - } - - const Json::Value & get_status() const { - return m_json; - } - -private: - Json::Value m_json; -}; - -/** - * capture filter +/************************************** + * Capture Filter + * * specify which ports to capture and if TX/RX or both - */ + *************************************/ class CaptureFilter { public: CaptureFilter() { @@ -186,10 +40,16 @@ public: m_rx_active = 0; } + /** + * add a port to the active TX port list + */ void add_tx(uint8_t port_id) { m_tx_active |= (1LL << port_id); } + /** + * add a port to the active RX port list + */ void add_rx(uint8_t port_id) { m_rx_active |= (1LL << port_id); } @@ -226,6 +86,10 @@ public: return ( in_tx(port_id) || in_rx(port_id) ); } + /** + * updates the current filter with another filter + * the result is the aggregation of TX /RX active lists + */ CaptureFilter& operator +=(const CaptureFilter &other) { m_tx_active |= other.m_tx_active; m_rx_active |= other.m_rx_active; @@ -248,19 +112,36 @@ private: }; +/************************************** + * Capture + * + * A single instance of a capture + *************************************/ class TrexStatelessCapture { public: + enum state_e { STATE_ACTIVE, STATE_STOPPED, }; - TrexStatelessCapture(capture_id_t id, uint64_t limit, const CaptureFilter &filter); + TrexStatelessCapture(capture_id_t id, + uint64_t limit, + const CaptureFilter &filter, + TrexPktBuffer::mode_e mode); - void handle_pkt_tx(TrexPkt *pkt); + ~TrexStatelessCapture(); + + /** + * handles a packet from the TX side + */ + void handle_pkt_tx(const TrexPkt *pkt); + + /** + * handles a packet from the RX side + */ void handle_pkt_rx(const rte_mbuf_t *m, int port); - ~TrexStatelessCapture(); uint64_t get_id() const { return m_id; @@ -270,8 +151,12 @@ public: return m_filter; } - Json::Value to_json() const; + /** + * stop the capture - from now on all packets will be ignored + * + * @author imarom (1/24/2017) + */ void stop() { m_state = STATE_STOPPED; } @@ -290,6 +175,9 @@ public: return m_start_ts; } + + Json::Value to_json() const; + private: state_e m_state; TrexPktBuffer *m_pkt_buffer; @@ -299,6 +187,14 @@ private: uint64_t m_pkt_index; }; + +/************************************** + * Capture Manager + * Handles all the captures in + * the system + * + * the design is a singleton + *************************************/ class TrexStatelessCaptureMngr { public: @@ -317,7 +213,10 @@ public: /** * starts a new capture */ - void start(const CaptureFilter &filter, uint64_t limit, TrexCaptureRCStart &rc); + void start(const CaptureFilter &filter, + uint64_t limit, + TrexPktBuffer::mode_e mode, + TrexCaptureRCStart &rc); /** * stops an existing capture @@ -346,7 +245,8 @@ public: /** - * return true if any filter is active + * return true if any filter is active + * on a specific port * * @author imarom (1/3/2017) * @@ -359,14 +259,20 @@ public: /** * handle packet from TX */ - void handle_pkt_tx(TrexPkt *pkt); + void handle_pkt_tx(const TrexPkt *pkt) { + if (!m_global_filter.in_filter(pkt)) { + return; + } + + handle_pkt_tx_slow_path(pkt); + } /** * handle packet from RX */ void handle_pkt_rx(const rte_mbuf_t *m, int port) { - /* fast path */ - if (!is_active(port)) { + /* fast path - check the global filter */ + if (!m_global_filter.in_rx(port)) { return; } @@ -385,8 +291,11 @@ private: TrexStatelessCapture * lookup(capture_id_t capture_id); + int lookup_index(capture_id_t capture_id); void handle_pkt_rx_slow_path(const rte_mbuf_t *m, int port); + void handle_pkt_tx_slow_path(const TrexPkt *pkt); + void update_global_filter(); std::vector m_captures; diff --git a/src/stateless/rx/trex_stateless_capture_rc.h b/src/stateless/rx/trex_stateless_capture_rc.h new file mode 100644 index 00000000..12b37c1d --- /dev/null +++ b/src/stateless/rx/trex_stateless_capture_rc.h @@ -0,0 +1,195 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2016 Cisco Systems, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +#ifndef __TREX_STATELESS_CAPTURE_RC_H__ +#define __TREX_STATELESS_CAPTURE_RC_H__ + +typedef int32_t capture_id_t; + +/** + * a base class for a capture command RC + * not to be used directly + */ +class TrexCaptureRC { + +protected: + /* cannot instantiate this object from outside */ + TrexCaptureRC() { + m_rc = RC_INVALID; + } + +public: + + /** + * error types for commands + */ + enum rc_e { + RC_INVALID = 0, + RC_OK = 1, + RC_CAPTURE_NOT_FOUND, + RC_CAPTURE_LIMIT_REACHED, + RC_CAPTURE_FETCH_UNDER_ACTIVE + }; + + bool operator !() const { + return (m_rc != RC_OK); + } + + std::string get_err() const { + assert(m_rc != RC_INVALID); + + switch (m_rc) { + case RC_OK: + return ""; + case RC_CAPTURE_LIMIT_REACHED: + return "capture limit has reached"; + case RC_CAPTURE_NOT_FOUND: + return "capture ID not found"; + case RC_CAPTURE_FETCH_UNDER_ACTIVE: + return "fetch command cannot be executed on an active capture"; + case RC_INVALID: + /* should never be called under invalid */ + assert(0); + + default: + assert(0); + } + } + + void set_err(rc_e rc) { + m_rc = rc; + } + + +protected: + rc_e m_rc; +}; + +/** + * return code for executing capture start + */ +class TrexCaptureRCStart : public TrexCaptureRC { +public: + + void set_rc(capture_id_t new_id, dsec_t start_ts) { + m_capture_id = new_id; + m_start_ts = start_ts; + m_rc = RC_OK; + } + + capture_id_t get_new_id() const { + assert(m_rc == RC_OK); + return m_capture_id; + } + + dsec_t get_start_ts() const { + assert(m_rc == RC_OK); + return m_start_ts; + } + +private: + capture_id_t m_capture_id; + dsec_t m_start_ts; +}; + +/** + * return code for exectuing capture stop + */ +class TrexCaptureRCStop : public TrexCaptureRC { +public: + + void set_rc(uint32_t pkt_count) { + m_pkt_count = pkt_count; + m_rc = RC_OK; + } + + uint32_t get_pkt_count() const { + assert(m_rc == RC_OK); + return m_pkt_count; + } + +private: + uint32_t m_pkt_count; +}; + +/** + * return code for executing capture fetch + */ +class TrexCaptureRCFetch : public TrexCaptureRC { +public: + + void set_rc(const TrexPktBuffer *pkt_buffer, uint32_t pending, dsec_t start_ts) { + m_pkt_buffer = pkt_buffer; + m_pending = pending; + m_start_ts = start_ts; + m_rc = RC_OK; + } + + const TrexPktBuffer *get_pkt_buffer() const { + assert(m_rc == RC_OK); + return m_pkt_buffer; + } + + uint32_t get_pending() const { + assert(m_rc == RC_OK); + return m_pending; + } + + dsec_t get_start_ts() const { + assert(m_rc == RC_OK); + return m_start_ts; + } + +private: + const TrexPktBuffer *m_pkt_buffer; + uint32_t m_pending; + dsec_t m_start_ts; +}; + + + +class TrexCaptureRCRemove : public TrexCaptureRC { +public: + void set_rc() { + m_rc = RC_OK; + } +}; + + +class TrexCaptureRCStatus : public TrexCaptureRC { +public: + + void set_rc(const Json::Value &json) { + m_json = json; + m_rc = RC_OK; + } + + const Json::Value & get_status() const { + assert(m_rc == RC_OK); + return m_json; + } + +private: + Json::Value m_json; +}; + + +#endif /* __TREX_STATELESS_CAPTURE_RC_H__ */ + -- cgit 1.2.3-korg