diff options
Diffstat (limited to 'src/stateless/cp')
-rw-r--r-- | src/stateless/cp/trex_dp_port_events.cpp | 215 | ||||
-rw-r--r-- | src/stateless/cp/trex_dp_port_events.h | 165 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 65 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 21 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 64 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.h | 14 |
6 files changed, 533 insertions, 11 deletions
diff --git a/src/stateless/cp/trex_dp_port_events.cpp b/src/stateless/cp/trex_dp_port_events.cpp new file mode 100644 index 00000000..533ab605 --- /dev/null +++ b/src/stateless/cp/trex_dp_port_events.cpp @@ -0,0 +1,215 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 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. +*/ + +#include <trex_dp_port_events.h> +#include <sstream> +#include <os_time.h> +#include <trex_stateless.h> + +/** + * port events + */ +void +TrexDpPortEvents::create(TrexStatelessPort *port) { + m_port = port; + + for (int i = 0; i < TrexDpPortEvent::EVENT_MAX; i++) { + m_events[i].create((TrexDpPortEvent::event_e) i, port); + } + + m_event_id_counter = EVENT_ID_INVALID; +} + +/** + * generate a new event ID + * + */ +int +TrexDpPortEvents::generate_event_id() { + return (++m_event_id_counter); +} + +/** + * mark the next allowed event + * all other events will be disabled + * + */ +void +TrexDpPortEvents::wait_for_event(TrexDpPortEvent::event_e ev, int event_id, int timeout_ms) { + + /* first disable all events */ + for (TrexDpPortEvent & e : m_events) { + e.disable(); + } + + /* mark this event as allowed */ + m_events[ev].wait_for_event(event_id, timeout_ms); +} + +/** + * handle an event + * + */ +void +TrexDpPortEvents::handle_event(TrexDpPortEvent::event_e ev, int thread_id, int event_id) { + m_events[ev].handle_event(thread_id, event_id); +} + +/*********** + * single event object + * + */ + +void +TrexDpPortEvent::create(event_e type, TrexStatelessPort *port) { + m_event_type = type; + m_port = port; + + /* add the core ids to the hash */ + m_signal.clear(); + for (int core_id : m_port->get_core_id_list()) { + m_signal[core_id] = false; + } + + /* event is disabled */ + disable(); +} + + +/** + * wait the event using event id and timeout + * + */ +void +TrexDpPortEvent::wait_for_event(int event_id, int timeout_ms) { + + /* set a new event id */ + m_event_id = event_id; + + /* do we have a timeout ? */ + if (timeout_ms > 0) { + m_expire_limit_ms = os_get_time_msec() + timeout_ms; + } else { + m_expire_limit_ms = -1; + } + + /* prepare the signal array */ + m_pending_cnt = 0; + for (auto & core_pair : m_signal) { + core_pair.second = false; + m_pending_cnt++; + } +} + +void +TrexDpPortEvent::disable() { + m_event_id = TrexDpPortEvents::EVENT_ID_INVALID; +} + +/** + * get the event status + * + */ + +TrexDpPortEvent::event_status_e +TrexDpPortEvent::status() { + + /* is it even active ? */ + if (m_event_id == TrexDpPortEvents::EVENT_ID_INVALID) { + return (EVENT_DISABLE); + } + + /* did it occured ? */ + if (m_pending_cnt == 0) { + return (EVENT_OCCURED); + } + + /* so we are enabled and the event did not occur - maybe we timed out ? */ + if ( (m_expire_limit_ms > 0) && (os_get_time_msec() > m_expire_limit_ms) ) { + return (EVENT_TIMED_OUT); + } + + /* so we are still waiting... */ + return (EVENT_PENDING); + +} + +void +TrexDpPortEvent::err(int thread_id, int event_id, const std::string &err_msg) { + std::stringstream err; + err << "DP event '" << event_name(m_event_type) << "' on thread id '" << thread_id << "' with key '" << event_id <<"' - "; +} + +/** + * event occured + * + */ +void +TrexDpPortEvent::handle_event(int thread_id, int event_id) { + + /* if the event is disabled - we don't care */ + if (!is_active()) { + return; + } + + /* check the event id is matching the required event */ + if (event_id != m_event_id) { + err(thread_id, event_id, "event key mismatch"); + } + + /* mark sure no double signal */ + if (m_signal.at(thread_id)) { + err(thread_id, event_id, "double signal"); + + } else { + /* mark */ + m_signal.at(thread_id) = true; + m_pending_cnt--; + } + + /* event occured */ + if (m_pending_cnt == 0) { + m_port->on_dp_event_occured(m_event_type); + m_event_id = TrexDpPortEvents::EVENT_ID_INVALID; + } +} + +bool +TrexDpPortEvent::is_active() { + return (status() != EVENT_DISABLE); +} + +bool +TrexDpPortEvent::has_timeout_expired() { + return (status() == EVENT_TIMED_OUT); +} + +const char * +TrexDpPortEvent::event_name(event_e type) { + switch (type) { + case EVENT_STOP: + return "DP STOP"; + + default: + throw TrexException("unknown event type"); + } + +} diff --git a/src/stateless/cp/trex_dp_port_events.h b/src/stateless/cp/trex_dp_port_events.h new file mode 100644 index 00000000..309288df --- /dev/null +++ b/src/stateless/cp/trex_dp_port_events.h @@ -0,0 +1,165 @@ +/* + Itay Marom + Cisco Systems, Inc. +*/ + +/* +Copyright (c) 2015-2015 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_DP_PORT_EVENTS_H__ +#define __TREX_DP_PORT_EVENTS_H__ + +#include <unordered_map> +#include <string> + +class TrexStatelessPort; + +/** + * describes a single DP event related to port + * + * @author imarom (18-Nov-15) + */ +class TrexDpPortEvent { +public: + + enum event_e { + EVENT_STOP = 1, + EVENT_MAX + }; + + /** + * status of the event for the port + */ + enum event_status_e { + EVENT_DISABLE, + EVENT_PENDING, + EVENT_TIMED_OUT, + EVENT_OCCURED + }; + + /** + * init for the event + * + */ + void create(event_e type, TrexStatelessPort *port); + + /** + * create a new pending event + * + */ + void wait_for_event(int event_id, int timeout_ms = -1); + + /** + * mark event as not allowed to happen + * + */ + void disable(); + + /** + * get the event status + * + */ + event_status_e status(); + + /** + * event occured + * + */ + void handle_event(int thread_id, int event_id); + + /** + * returns true if event is active + * + */ + bool is_active(); + + /** + * has timeout already expired ? + * + */ + bool has_timeout_expired(); + + /** + * generate error + * + */ + void err(int thread_id, int event_id, const std::string &err_msg); + + /** + * event to name + * + */ + static const char * event_name(event_e type); + + +private: + + event_e m_event_type; + std::unordered_map<int, bool> m_signal; + int m_pending_cnt; + + TrexStatelessPort *m_port; + int m_event_id; + int m_expire_limit_ms; + +}; + +/** + * all the events related to a port + * + */ +class TrexDpPortEvents { +public: + friend class TrexDpPortEvent; + + void create(TrexStatelessPort *port); + + /** + * generate a new event ID to be used with wait_for_event + * + */ + int generate_event_id(); + + /** + * wait a new DP event on the port + * returns a key which will be used to identify + * the event happened + * + * @author imarom (18-Nov-15) + * + * @param ev - type of event + * @param event_id - a unique identifier for the event + * @param timeout_ms - does it has a timeout ? + * + */ + void wait_for_event(TrexDpPortEvent::event_e ev, int event_id, int timeout_ms = -1); + + /** + * event has occured + * + */ + void handle_event(TrexDpPortEvent::event_e ev, int thread_id, int event_id); + +private: + static const int EVENT_ID_INVALID = -1; + + TrexDpPortEvent m_events[TrexDpPortEvent::EVENT_MAX]; + int m_event_id_counter; + + TrexStatelessPort *m_port; + +}; + +#endif /* __TREX_DP_PORT_EVENTS_H__ */ diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 1a05257c..5203b2a2 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -25,6 +25,71 @@ limitations under the License. /************************************** * stream *************************************/ + + +std::string TrexStream::get_stream_type_str(stream_type_t stream_type){ + + std::string res; + + + switch (stream_type) { + + case stCONTINUOUS : + res="stCONTINUOUS "; + break; + + case stSINGLE_BURST : + res="stSINGLE_BURST "; + break; + + case stMULTI_BURST : + res="stMULTI_BURST "; + break; + default: + res="Unknow "; + }; + return(res); +} + + +void TrexStream::Dump(FILE *fd){ + + fprintf(fd,"\n"); + fprintf(fd,"==> Stream_id : %lu \n",(ulong)m_stream_id); + fprintf(fd," Enabled : %lu \n",(ulong)(m_enabled?1:0)); + fprintf(fd," Self_start : %lu \n",(ulong)(m_self_start?1:0)); + + if (m_next_stream_id>=0) { + fprintf(fd," Nex_stream_id : %lu \n",(ulong)m_next_stream_id); + }else { + fprintf(fd," Nex_stream_id : %d \n",m_next_stream_id); + } + + fprintf(fd," Port_id : %lu \n",(ulong)m_port_id); + + if (m_isg_usec>0.0) { + fprintf(fd," isg : %6.2f \n",m_isg_usec); + } + fprintf(fd," type : %s \n",get_stream_type_str(m_type).c_str()); + + if ( m_type == TrexStream::stCONTINUOUS ) { + fprintf(fd," pps : %f \n",m_pps); + } + if (m_type == TrexStream::stSINGLE_BURST) { + fprintf(fd," pps : %f \n",m_pps); + fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); + } + if (m_type == TrexStream::stMULTI_BURST) { + fprintf(fd," pps : %f \n",m_pps); + fprintf(fd," burst : %lu \n",(ulong)m_burst_total_pkts); + fprintf(fd," mburst : %lu \n",(ulong)m_num_bursts); + if (m_ibg_usec>0.0) { + fprintf(fd," m_ibg_usec : %f \n",m_ibg_usec); + } + } +} + + TrexStream::TrexStream(uint8_t type, uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index c2628cc3..0634829e 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -1,5 +1,6 @@ /* Itay Marom + Hanoch Haim Cisco Systems, Inc. */ @@ -65,6 +66,9 @@ public: stMULTI_BURST = 6 }; + typedef uint8_t stream_type_t ; + + static std::string get_stream_type_str(stream_type_t stream_type); public: TrexStream(uint8_t type,uint8_t port_id, uint32_t stream_id); @@ -80,6 +84,12 @@ public: /* access the stream json */ const Json::Value & get_stream_json(); + /* compress the stream id to be zero based */ + void fix_dp_stream_id(uint32_t my_stream_id,int next_stream_id){ + m_stream_id = my_stream_id; + m_next_stream_id = next_stream_id; + } + double get_pps() { return m_pps; } @@ -96,6 +106,14 @@ public: return ( m_type ); } + bool is_dp_next_stream(){ + if (m_next_stream_id<0) { + return (false); + }else{ + return (true); + } + } + void set_multi_burst(uint32_t burst_total_pkts, @@ -132,11 +150,12 @@ public: return (dp); } + void Dump(FILE *fd); public: /* basic */ uint8_t m_type; uint8_t m_port_id; - uint32_t m_stream_id; + uint32_t m_stream_id; /* id from RPC can be anything */ /* config fields */ diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 0c3b4ef0..bdfc3c01 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -36,6 +36,7 @@ class GraphNode { public: GraphNode(TrexStream *stream, GraphNode *next) : m_stream(stream), m_next(next) { marked = false; + m_compressed_stream_id=-1; } uint32_t get_stream_id() const { @@ -46,6 +47,7 @@ public: GraphNode *m_next; std::vector<const GraphNode *> m_parents; bool marked; + int m_compressed_stream_id; }; /** @@ -143,8 +145,10 @@ TrexStreamsCompiledObj::~TrexStreamsCompiledObj() { m_objs.clear(); } + void -TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { +TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream){ + obj_st obj; obj.m_stream = stream->clone_as_dp(); @@ -152,6 +156,26 @@ TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream) { m_objs.push_back(obj); } +void +TrexStreamsCompiledObj::add_compiled_stream(TrexStream * stream, + uint32_t my_dp_id, int next_dp_id) { + obj_st obj; + + obj.m_stream = stream->clone_as_dp(); + /* compress the id's*/ + obj.m_stream->fix_dp_stream_id(my_dp_id,next_dp_id); + + m_objs.push_back(obj); +} + +void TrexStreamsCompiledObj::Dump(FILE *fd){ + for (auto obj : m_objs) { + obj.m_stream->Dump(fd); + } +} + + + TrexStreamsCompiledObj * TrexStreamsCompiledObj::clone() { @@ -197,6 +221,8 @@ void TrexStreamsCompiler::allocate_pass(const std::vector<TrexStream *> &streams, GraphNodeMap *nodes) { std::stringstream ss; + uint32_t compressed_stream_id=0; + /* first pass - allocate all nodes and check for duplicates */ for (auto stream : streams) { @@ -216,6 +242,10 @@ TrexStreamsCompiler::allocate_pass(const std::vector<TrexStream *> &streams, } GraphNode *node = new GraphNode(stream, NULL); + /* allocate new compressed id */ + node->m_compressed_stream_id = compressed_stream_id; + + compressed_stream_id++; /* add to the map */ assert(nodes->add(node)); @@ -323,9 +353,8 @@ TrexStreamsCompiler::check_for_unreachable_streams(GraphNodeMap *nodes) { * @return bool */ void -TrexStreamsCompiler::pre_compile_check(const std::vector<TrexStream *> &streams) { - - GraphNodeMap nodes; +TrexStreamsCompiler::pre_compile_check(const std::vector<TrexStream *> &streams, + GraphNodeMap & nodes) { m_warnings.clear(); @@ -348,9 +377,20 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams, TrexStreamsCompiledObj &obj, std::string *fail_msg) { +#if 0 + fprintf(stdout,"------------pre compile \n"); + for (auto stream : streams) { + stream->Dump(stdout); + } + fprintf(stdout,"------------pre compile \n"); +#endif + + GraphNodeMap nodes; + + /* compile checks */ try { - pre_compile_check(streams); + pre_compile_check(streams,nodes); } catch (const TrexException &ex) { if (fail_msg) { *fail_msg = ex.what(); @@ -360,6 +400,7 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams, return false; } + /* for now we do something trivial, */ for (auto stream : streams) { @@ -368,8 +409,19 @@ TrexStreamsCompiler::compile(const std::vector<TrexStream *> &streams, continue; } + int new_id= nodes.get(stream->m_stream_id)->m_compressed_stream_id; + assert(new_id>=0); + uint32_t my_stream_id = (uint32_t)new_id; + int my_next_stream_id=-1; + if (stream->m_next_stream_id>=0) { + my_next_stream_id=nodes.get(stream->m_next_stream_id)->m_compressed_stream_id; + } + /* add it */ - obj.add_compiled_stream(stream); + obj.add_compiled_stream(stream, + my_stream_id, + my_next_stream_id + ); } return true; diff --git a/src/stateless/cp/trex_streams_compiler.h b/src/stateless/cp/trex_streams_compiler.h index c80dddef..200f7ce9 100644 --- a/src/stateless/cp/trex_streams_compiler.h +++ b/src/stateless/cp/trex_streams_compiler.h @@ -50,6 +50,10 @@ public: return m_objs; } + uint8_t get_port_id(){ + return (m_port_id); + } + /** * clone the compiled object * @@ -60,12 +64,13 @@ public: return (m_mul); } - uint8_t get_port_id() { - return m_port_id; - } + void Dump(FILE *fd); private: + void add_compiled_stream(TrexStream * stream, + uint32_t my_dp_id, int next_dp_id); void add_compiled_stream(TrexStream * stream); + std::vector<obj_st> m_objs; uint8_t m_port_id; @@ -94,7 +99,8 @@ public: private: - void pre_compile_check(const std::vector<TrexStream *> &streams); + void pre_compile_check(const std::vector<TrexStream *> &streams, + GraphNodeMap & nodes); void allocate_pass(const std::vector<TrexStream *> &streams, GraphNodeMap *nodes); void direct_pass(GraphNodeMap *nodes); void check_for_unreachable_streams(GraphNodeMap *nodes); |