From 8691f4019dc2123c1aa7413cf3666138756c2f66 Mon Sep 17 00:00:00 2001 From: imarom Date: Tue, 3 May 2016 14:57:34 +0300 Subject: first remote PCAP push - draft --- src/stateless/dp/trex_stateless_dp_core.cpp | 120 +++++++++++++++++++++++++- src/stateless/dp/trex_stateless_dp_core.h | 12 ++- src/stateless/dp/trex_stream_node.h | 129 ++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+), 3 deletions(-) (limited to 'src/stateless/dp') diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index d3d49a34..31c907fa 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -262,6 +262,36 @@ bool TrexStatelessDpPerPort::pause_traffic(uint8_t port_id){ return (true); } +bool TrexStatelessDpPerPort::push_pcap(uint8_t port_id, const std::string &pcap_filename){ + + /* push pcap can only happen on an idle port from the core prespective */ + assert(m_state == TrexStatelessDpPerPort::ppSTATE_IDLE); + + CGenNodePCAP *pcap_node = m_core->allocate_pcap_node(); + if (!pcap_node) { + return (false); + } + + pkt_dir_t dir = m_core->m_node_gen.m_v_if->port_id_to_dir(port_id); + + uint8_t mac_addr[12]; + m_core->m_node_gen.m_v_if->update_mac_addr_from_global_cfg(dir, mac_addr); + + bool rc = pcap_node->create(port_id, pcap_filename, dir, mac_addr); + if (!rc) { + m_core->free_node((CGenNode *)pcap_node); + return (false); + } + + /* schedule the node for now */ + pcap_node->m_time = m_core->m_cur_time_sec; + m_core->m_node_gen.add_node((CGenNode *)pcap_node); + + m_state = TrexStatelessDpPerPort::ppSTATE_TRANSMITTING; + + return (true); +} + bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id, bool stop_on_id, @@ -305,7 +335,6 @@ bool TrexStatelessDpPerPort::stop_traffic(uint8_t port_id, void TrexStatelessDpPerPort::create(CFlowGenListPerThread * core){ m_core=core; m_state=TrexStatelessDpPerPort::ppSTATE_IDLE; - m_port_id=0; m_active_streams=0; m_active_nodes.clear(); } @@ -579,6 +608,7 @@ void TrexStatelessDpCore::add_stream(TrexStatelessDpPerPort * lp_port, TrexStream * stream, TrexStreamsCompiledObj *comp) { + CGenNodeStateless *node = m_core->create_node_sl(); /* add periodic */ @@ -834,6 +864,37 @@ TrexStatelessDpCore::pause_traffic(uint8_t port_id){ lp_port->pause_traffic(port_id); } + +void +TrexStatelessDpCore::push_pcap(uint8_t port_id, int event_id, const std::string &pcap_filename) { + + TrexStatelessDpPerPort * lp_port = get_port_db(port_id); + + lp_port->set_event_id(event_id); + + /* delegate the command to the port */ + bool rc = lp_port->push_pcap(port_id, pcap_filename); + if (!rc) { + /* report back that we stopped */ + CNodeRing *ring = CMsgIns::Ins()->getCpDp()->getRingDpToCp(m_core->m_thread_id); + TrexStatelessDpToCpMsgBase *event_msg = new TrexDpPortEventMsg(m_core->m_thread_id, + port_id, + event_id, + false); + ring->Enqueue((CGenNode *)event_msg); + return; + } + + m_state = TrexStatelessDpCore::STATE_TRANSMITTING; + + #if 0 + if ( duration > 0.0 ){ + add_port_duration(duration, port_id, event_id); + } + #endif +} + + void TrexStatelessDpCore::update_traffic(uint8_t port_id, double factor) { @@ -895,3 +956,60 @@ TrexStatelessDpCore::barrier(uint8_t port_id, int event_id) { event_id); ring->Enqueue((CGenNode *)event_msg); } + + +/** + * PCAP node + */ +bool CGenNodePCAP::create(uint8_t port_id, const std::string &pcap_filename, pkt_dir_t dir, const uint8_t *mac_addr) { + std::stringstream ss; + + m_type = CGenNode::PCAP_PKT; + m_flags = 0; + m_src_port = 0; + m_port_id = port_id; + + /* copy MAC addr info */ + memcpy(m_mac_addr, mac_addr, 12); + + /* set the dir */ + set_mbuf_dir(dir); + + /* create the PCAP reader */ + m_reader = CCapReaderFactory::CreateReader((char *)pcap_filename.c_str(), 0, ss); + if (!m_reader) { + return false; + } + + m_raw_packet = new CCapPktRaw(); + if ( m_reader->ReadPacket(m_raw_packet) == false ){ + /* handle error */ + delete m_reader; + return (false); + } + + /* this is the reference time */ + //m_base_time = m_raw_packet->get_time(); + m_last_pkt_time = m_raw_packet->get_time(); + + /* ready */ + m_state = PCAP_ACTIVE; + + return true; +} + +void CGenNodePCAP::destroy() { + + if (m_raw_packet) { + delete m_raw_packet; + m_raw_packet = NULL; + } + + if (m_reader) { + delete m_reader; + m_reader = NULL; + } + + m_state = PCAP_INVALID; +} + diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index cb102b8d..01033a7c 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -70,6 +70,8 @@ public: bool update_traffic(uint8_t port_id, double factor); + bool push_pcap(uint8_t port_id, const std::string &pcap_filename); + bool stop_traffic(uint8_t port_id, bool stop_on_id, int event_id); @@ -91,7 +93,6 @@ public: public: state_e m_state; - uint8_t m_port_id; uint32_t m_active_streams; /* how many active streams on this port */ @@ -149,7 +150,7 @@ public: */ void start_traffic(TrexStreamsCompiledObj *obj, double duration, - int m_event_id); + int event_id); /* pause the streams, work only if all are continues */ @@ -160,6 +161,13 @@ public: void resume_traffic(uint8_t port_id); + /** + * push a PCAP file on port + * + */ + void push_pcap(uint8_t port_id, int event_id, const std::string &pcap_filename); + + /** * update current traffic rate * diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index c85bf8b5..8ccb5286 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -26,6 +26,8 @@ limitations under the License. #include class TrexStatelessDpCore; +class TrexStatelessDpPerPort; + #include class TrexStatelessCpToDpMsgBase; @@ -387,6 +389,133 @@ private: static_assert(sizeof(CGenNodeStateless) == sizeof(CGenNode), "sizeof(CGenNodeStateless) != sizeof(CGenNode)" ); +/* this is a event for PCAP transmitting */ +struct CGenNodePCAP : public CGenNodeBase { +friend class TrexStatelessDpPerPort; + +public: + + /** + * creates a node from a PCAP file + */ + bool create(uint8_t port_id, const std::string &pcap_filename, pkt_dir_t dir, const uint8_t *mac_addr); + void destroy(); + + /** + * advance - will read the next packet + * + * @author imarom (03-May-16) + */ + void next() { + assert(m_state == PCAP_ACTIVE); + + /* save the previous packet time */ + m_last_pkt_time = m_raw_packet->get_time(); + + /* advance */ + if ( m_reader->ReadPacket(m_raw_packet) == false ){ + m_state = PCAP_EOF; + return; + } + + } + + /** + * return true if the PCAP has next packet + * + */ + bool has_next() { + assert(m_state != PCAP_INVALID); + return (m_state == PCAP_ACTIVE); + } + + /** + * return the time for the next scheduling for a packet + * + */ + inline double get_ipg() { + assert(m_state != PCAP_INVALID); + return m_raw_packet->get_time() - m_last_pkt_time; + //return 0.00001; + } + + /** + * get the current packet as MBUF + * + */ + inline rte_mbuf_t *get_pkt() { + assert(m_state != PCAP_INVALID); + + rte_mbuf_t *m = CGlobalInfo::pktmbuf_alloc( get_socket_id(), m_raw_packet->getTotalLen()); + assert(m); + + char *p = rte_pktmbuf_append(m, m_raw_packet->getTotalLen()); + assert(p); + /* copy the packet */ + memcpy(p, m_raw_packet->raw, m_raw_packet->getTotalLen()); + + /* fix the MAC */ + memcpy(p, m_mac_addr, 12); + + return (m); + } + + + inline void handle(CFlowGenListPerThread *thread) { + assert(m_state != PCAP_INVALID); + thread->m_node_gen.m_v_if->send_node( (CGenNode *)this); + } + + void set_mbuf_dir(pkt_dir_t dir) { + if (dir) { + m_flags |=NODE_FLAGS_DIR; + }else{ + m_flags &=~NODE_FLAGS_DIR; + } + } + + inline pkt_dir_t get_mbuf_dir(){ + return ((pkt_dir_t)( m_flags &1)); + } + + uint8_t get_port_id() { + return m_port_id; + } + +private: + + enum { + PCAP_INVALID = 0, + PCAP_ACTIVE, + PCAP_EOF + }; + + /* cache line 0 */ + /* important stuff here */ + uint8_t m_mac_addr[12]; + uint8_t m_state; + + //double m_base_time; + //double m_current_pkt_time; + double m_last_pkt_time; + + void * m_cache_mbuf; + + double m_next_time_offset; /* in sec */ + + CCapReaderBase *m_reader; + CCapPktRaw *m_raw_packet; + + uint8_t m_port_id; + + /* pad to match the size of CGenNode */ + uint8_t m_pad_end[25]; + +} __rte_cache_aligned; + + +static_assert(sizeof(CGenNodePCAP) == sizeof(CGenNode), "sizeof(CGenNodePCAP) != sizeof(CGenNode)" ); #endif /* __TREX_STREAM_NODE_H__ */ + -- cgit 1.2.3-korg