capture - personal code review 82/5282/1
authorimarom <[email protected]>
Wed, 25 Jan 2017 11:54:51 +0000 (13:54 +0200)
committerimarom <[email protected]>
Wed, 25 Jan 2017 11:54:51 +0000 (13:54 +0200)
Signed-off-by: imarom <[email protected]>
scripts/automation/trex_control_plane/stl/console/trex_capture.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
src/rpc-server/commands/trex_rpc_cmd_general.cpp
src/stateless/common/trex_stateless_pkt.cpp
src/stateless/common/trex_stateless_pkt.h
src/stateless/messaging/trex_stateless_messaging.cpp
src/stateless/messaging/trex_stateless_messaging.h
src/stateless/rx/trex_stateless_capture.cpp
src/stateless/rx/trex_stateless_capture.h
src/stateless/rx/trex_stateless_capture_rc.h [new file with mode: 0644]

index dfd7f0a..aac685a 100644 (file)
@@ -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 <out.pcap>' when done ***\n".format(rc['id']), 'bold'))
index d81765c..654ceaf 100755 (executable)
@@ -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: <new_id>, 'ts': <starting timestamp>}
@@ -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):
index c20c77d..54798ab 100644 (file)
@@ -892,6 +892,12 @@ void
 TrexRpcCmdCapture::parse_cmd_start(const Json::Value &params, 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 &params, 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();
index 14c1446..43cbbe1 100644 (file)
@@ -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;
+}
index 573f495..f44355d 100644 (file)
@@ -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;
index 21fe7a1..f89ca34 100644 (file)
@@ -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);
index ed14b10..cd79d6e 100644 (file)
@@ -494,10 +494,12 @@ class TrexStatelessRxCaptureStart : public TrexStatelessRxCapture {
 public:
     TrexStatelessRxCaptureStart(const CaptureFilter& filter,
                                 uint64_t limit,
+                                TrexPktBuffer::mode_e mode,
                                 MsgReply<TrexCaptureRCStart> &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<TrexCaptureRCStart>    &m_reply;
 };
 
index 7b02044..bf7623d 100644 (file)
@@ -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);
     }
index 852aee2..e4a2e63 100644 (file)
@@ -25,160 +25,14 @@ limitations under the License.
 #include <assert.h>
 
 #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<TrexStatelessCapture *> 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 (file)
index 0000000..12b37c1
--- /dev/null
@@ -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__ */
+