diff options
Diffstat (limited to 'src/stateless')
-rw-r--r-- | src/stateless/cp/trex_api_class.h | 110 | ||||
-rw-r--r-- | src/stateless/cp/trex_exception.h | 41 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless.cpp | 3 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless.h | 39 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 40 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 12 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 9 | ||||
-rw-r--r-- | src/stateless/cp/trex_streams_compiler.cpp | 6 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 1 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.cpp | 43 | ||||
-rw-r--r-- | src/stateless/rx/trex_stateless_rx_core.h | 8 |
11 files changed, 262 insertions, 50 deletions
diff --git a/src/stateless/cp/trex_api_class.h b/src/stateless/cp/trex_api_class.h new file mode 100644 index 00000000..78933d23 --- /dev/null +++ b/src/stateless/cp/trex_api_class.h @@ -0,0 +1,110 @@ +/* + 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_API_CLASS_H__ +#define __TREX_API_CLASS_H__ + +#include <assert.h> + +#include "common/basic_utils.h" +#include "trex_exception.h" + +/** + * API exception + * + * @author imarom (03-Apr-16) + */ +class TrexAPIException : public TrexException { +public: + TrexAPIException(const std::string &what) : TrexException(what) { + } +}; + +/** + * define an API class + * + * @author imarom (03-Apr-16) + */ +class APIClass { +public: + + enum type_e { + API_CLASS_TYPE_CORE = 0, + API_CLASS_TYPE_MAX, + + API_CLASS_TYPE_NO_API + }; + + static const char * type_to_name(type_e type) { + switch (type) { + case API_CLASS_TYPE_CORE: + return "core"; + default: + assert(0); + } + } + + APIClass() { + /* invalid */ + m_type = API_CLASS_TYPE_MAX; + } + + void init(type_e type, int major, int minor) { + m_type = type; + m_major = major; + m_minor = minor; + + unsigned int seed = time(NULL); + m_handler = utl_generate_random_str(seed, 8); + } + + std::string & verify_api(int major, int minor) { + std::stringstream ss; + ss << "API type '" << type_to_name(m_type) << "': "; + + assert(m_type < API_CLASS_TYPE_MAX); + + /* for now a simple major check */ + if (major < m_major) { + ss << "server has a major newer API version - server: '" << m_major << "', client: '" << major << "'"; + throw TrexAPIException(ss.str()); + } + + if (major > m_major) { + ss << "server has an older API version - server: '" << m_major << "', client: '" << major << "'"; + throw TrexAPIException(ss.str()); + } + + return get_api_handler(); + } + + std::string & get_api_handler() { + return m_handler; + } + +private: + type_e m_type; + int m_major; + int m_minor; + std::string m_handler; + +}; + +#endif /* __TREX_API_CLASS_H__ */ diff --git a/src/stateless/cp/trex_exception.h b/src/stateless/cp/trex_exception.h new file mode 100644 index 00000000..b9e20761 --- /dev/null +++ b/src/stateless/cp/trex_exception.h @@ -0,0 +1,41 @@ +/* + 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_EXCEPTION_H__ +#define __TREX_EXCEPTION_H__ + +#include <stdexcept> +#include <string> + +/** + * generic exception for errors + * TODO: move this to a better place + */ +class TrexException : public std::runtime_error +{ +public: + TrexException() : std::runtime_error("") { + + } + TrexException(const std::string &what) : std::runtime_error(what) { + } +}; + +#endif /* __TREX_EXCEPTION_H__ */ diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp index 9df57a50..f6f81b96 100644 --- a/src/stateless/cp/trex_stateless.cpp +++ b/src/stateless/cp/trex_stateless.cpp @@ -53,6 +53,8 @@ TrexStateless::TrexStateless(const TrexStatelessCfg &cfg) { m_platform_api = cfg.m_platform_api; m_publisher = cfg.m_publisher; + /* API core version */ + m_api_classes[APIClass::API_CLASS_TYPE_CORE].init(APIClass::API_CLASS_TYPE_CORE, 1, 0); } /** @@ -175,3 +177,4 @@ TrexStateless::generate_publish_snapshot(std::string &snapshot) { snapshot = writer.write(root); } + diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h index 6e5e0c44..b506da61 100644 --- a/src/stateless/cp/trex_stateless.h +++ b/src/stateless/cp/trex_stateless.h @@ -27,27 +27,18 @@ limitations under the License. #include <mutex> -#include <trex_stream.h> -#include <trex_stateless_port.h> -#include <trex_rpc_server_api.h> -#include <publisher/trex_publisher.h> +#include "trex_stream.h" +#include "trex_stateless_port.h" +#include "trex_rpc_server_api.h" -#include <flow_stat.h> -#include <internal_api/trex_platform_api.h> +#include "publisher/trex_publisher.h" +#include "internal_api/trex_platform_api.h" -/** - * generic exception for errors - * TODO: move this to a better place - */ -class TrexException : public std::runtime_error -{ -public: - TrexException() : std::runtime_error("") { +#include "flow_stat.h" - } - TrexException(const std::string &what) : std::runtime_error(what) { - } -}; + +#include "trex_exception.h" +#include "trex_api_class.h" class TrexStatelessPort; @@ -81,6 +72,7 @@ public: } m_stats; }; + /** * config object for stateless object * @@ -167,6 +159,14 @@ public: return m_rpc_server; } + const std::string & verify_api(APIClass::type_e type, int major, int minor) { + return m_api_classes[type].verify_api(major, minor); + } + + const std::string & get_api_handler(APIClass::type_e type) { + return m_api_classes[type].get_api_handler(); + } + CFlowStatRuleMgr m_rx_flow_stat; protected: @@ -187,6 +187,8 @@ protected: TrexPublisher *m_publisher; + /* API */ + APIClass m_api_classes[APIClass::API_CLASS_TYPE_MAX]; }; /** @@ -197,6 +199,7 @@ protected: * @return TrexStateless& */ TrexStateless * get_stateless_obj(); +CRxCoreStateless * get_rx_sl_core_obj(); #endif /* __TREX_STATELESS_H__ */ diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index 90589d7a..2239f3f6 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -272,6 +272,22 @@ TrexStatelessPort::stop_traffic(void) { } /** + * remove all RX filters from port + * + * @author imarom (28-Mar-16) + */ +void +TrexStatelessPort::remove_rx_filters(void) { + /* only valid when IDLE or with streams and not TXing */ + verify_state(PORT_STATE_STREAMS); + + for (auto entry : m_stream_table) { + get_stateless_obj()->m_rx_flow_stat.stop_stream(entry.second); + } + +} + +/** * when a port stops, perform various actions * */ @@ -287,9 +303,6 @@ TrexStatelessPort::common_port_stop_actions(bool async) { get_stateless_obj()->get_publisher()->publish_event(TrexPublisher::EVENT_PORT_STOPPED, data); } - for (auto entry : m_stream_table) { - get_stateless_obj()->m_rx_flow_stat.stop_stream(entry.second); - } } void @@ -768,26 +781,5 @@ TrexPortOwner::TrexPortOwner() { m_seed = time(NULL); } -/** - * generate a random connection handler - * - */ -std::string -TrexPortOwner::generate_handler() { - std::stringstream ss; - - static const char alphanum[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - - /* generate 8 bytes of random handler */ - for (int i = 0; i < 8; ++i) { - ss << alphanum[rand_r(&m_seed) % (sizeof(alphanum) - 1)]; - } - - return (ss.str()); -} - const std::string TrexPortOwner::g_unowned_name = "<FREE>"; const std::string TrexPortOwner::g_unowned_handler = ""; diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 7e1838d4..2167e735 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -21,6 +21,7 @@ limitations under the License. #ifndef __TREX_STATELESS_PORT_H__ #define __TREX_STATELESS_PORT_H__ +#include "common/basic_utils.h" #include "internal_api/trex_platform_api.h" #include "trex_dp_port_events.h" #include "trex_stream.h" @@ -65,7 +66,7 @@ public: m_owner_name = owner_name; /* internal data */ - m_handler = generate_handler(); + m_handler = utl_generate_random_str(m_seed, 8); m_is_free = false; } @@ -83,7 +84,6 @@ public: private: - std::string generate_handler(); /* is this port owned by someone ? */ bool m_is_free; @@ -178,6 +178,14 @@ public: void stop_traffic(void); /** + * remove all RX filters + * valid only when port is stopped + * + * @author imarom (28-Mar-16) + */ + void remove_rx_filters(void); + + /** * pause traffic * throws TrexException in case of an error */ diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 9c7898a8..e3f0ba7c 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -106,6 +106,15 @@ void TrexStream::Dump(FILE *fd){ } } + if (m_rx_check.m_enabled) { + fprintf(fd, " Flow stat enabled:\n"); + fprintf(fd, " seq check %s latency check %s packet group id %d hw_id %d\n" + , m_rx_check.m_seq_enabled ? "enabled":"disabled" + , m_rx_check.m_latency ? "enabled":"disabled", m_rx_check.m_pg_id, m_rx_check.m_hw_id + ); + } else { + fprintf(fd, " Flow stat disabled\n"); + } fprintf(fd," rate :\n\n"); fprintf(fd," pps : %f\n", m_rate.get_pps()); diff --git a/src/stateless/cp/trex_streams_compiler.cpp b/src/stateless/cp/trex_streams_compiler.cpp index 563236c2..d6971d68 100644 --- a/src/stateless/cp/trex_streams_compiler.cpp +++ b/src/stateless/cp/trex_streams_compiler.cpp @@ -477,8 +477,10 @@ TrexStreamsCompiler::compile_stream(TrexStream *stream, TrexStream *fixed_rx_flow_stat_stream = stream->clone(true); - // not checking for errors. We assume that if add_stream succeeded, start_stream will too. - get_stateless_obj()->m_rx_flow_stat.start_stream(fixed_rx_flow_stat_stream, fixed_rx_flow_stat_stream->m_rx_check.m_hw_id); + get_stateless_obj()->m_rx_flow_stat.start_stream(fixed_rx_flow_stat_stream); + // CFlowStatRuleMgr keeps state of the stream object. We duplicated the stream here (in order not + // change the packet kept in the stream). We want the state to be saved in the original stream. + get_stateless_obj()->m_rx_flow_stat.copy_state(fixed_rx_flow_stat_stream, stream); /* can this stream be split to many cores ? */ if (!stream->is_splitable(dp_core_count)) { diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index ba25f61d..f125a46a 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -399,6 +399,7 @@ TrexStatelessDpCore::idle_state_loop() { int counter = 0; while (m_state == STATE_IDLE) { + m_core->m_node_gen.m_v_if->flush_dp_rx_queue(); bool had_msg = periodic_check_for_cp_messages(); if (had_msg) { counter = 0; diff --git a/src/stateless/rx/trex_stateless_rx_core.cpp b/src/stateless/rx/trex_stateless_rx_core.cpp index ab7c08d1..26f537f8 100644 --- a/src/stateless/rx/trex_stateless_rx_core.cpp +++ b/src/stateless/rx/trex_stateless_rx_core.cpp @@ -2,6 +2,7 @@ #include "bp_sim.h" #include "flow_stat_parser.h" #include "latency.h" +#include "pal/linux/sanb_atomic.h" #include "trex_stateless_messaging.h" #include "trex_stateless_rx_core.h" @@ -59,6 +60,8 @@ void CRxCoreStateless::idle_state_loop() { if (had_msg) { counter = 0; continue; + } else { + flush_rx(); } /* enter deep sleep only if enough time had passed */ @@ -72,8 +75,8 @@ void CRxCoreStateless::idle_state_loop() { } void CRxCoreStateless::start() { - static int count = 0; - static int i = 0; + int count = 0; + int i = 0; bool do_try_rx_queue =CGlobalInfo::m_options.preview.get_vm_one_queue_enable() ? true : false; while (true) { @@ -91,7 +94,11 @@ void CRxCoreStateless::start() { } else { if (m_state == STATE_QUIT) break; + count = 0; + i = 0; + set_working_msg_ack(false); idle_state_loop(); + set_working_msg_ack(true); } if (do_try_rx_queue) { try_rx_queues(); @@ -101,7 +108,7 @@ void CRxCoreStateless::start() { } void CRxCoreStateless::handle_rx_pkt(CLatencyManagerPerPort *lp, rte_mbuf_t *m) { - Cxl710Parser parser; + CFlowStatParser parser; if (parser.parse(rte_pktmbuf_mtod(m, uint8_t *), m->pkt_len) == 0) { uint16_t ip_id; @@ -162,6 +169,30 @@ void CRxCoreStateless::try_rx_queues() { } } +// exactly the same as try_rx, without the handle_rx_pkt +// purpose is to flush rx queues when core is in idle state +void CRxCoreStateless::flush_rx() { + rte_mbuf_t * rx_pkts[64]; + int i, total_pkts = 0; + for (i = 0; i < m_max_ports; i++) { + CLatencyManagerPerPort * lp = &m_ports[i]; + rte_mbuf_t * m; + m_cpu_dp_u.start_work(); + /* try to read 64 packets clean up the queue */ + uint16_t cnt_p = lp->m_io->rx_burst(rx_pkts, 64); + total_pkts += cnt_p; + if (cnt_p) { + int j; + for (j = 0; j < cnt_p; j++) { + m = rx_pkts[j]; + rte_pktmbuf_free(m); + } + /* commit only if there was work to do ! */ + m_cpu_dp_u.commit(); + }/* if work */ + }// all ports +} + int CRxCoreStateless::try_rx() { rte_mbuf_t * rx_pkts[64]; int i, total_pkts = 0; @@ -211,6 +242,12 @@ int CRxCoreStateless::get_rx_stats(uint8_t port_id, rx_per_flow_t *rx_stats, int return 0; } +void CRxCoreStateless::set_working_msg_ack(bool val) { + sanb_smp_memory_barrier(); + m_ack_start_work_msg = val; + sanb_smp_memory_barrier(); +} + double CRxCoreStateless::get_cpu_util() { m_cpu_cp_u.Update(); return m_cpu_cp_u.GetVal(); diff --git a/src/stateless/rx/trex_stateless_rx_core.h b/src/stateless/rx/trex_stateless_rx_core.h index 5ab12f4e..b78256c2 100644 --- a/src/stateless/rx/trex_stateless_rx_core.h +++ b/src/stateless/rx/trex_stateless_rx_core.h @@ -54,6 +54,8 @@ class CRxCoreStateless { void work() {m_state = STATE_WORKING;} void idle() {m_state = STATE_IDLE;} void quit() {m_state = STATE_QUIT;} + bool is_working() const {return (m_ack_start_work_msg == true);} + void set_working_msg_ack(bool val); double get_cpu_util(); private: @@ -62,6 +64,7 @@ class CRxCoreStateless { void idle_state_loop(); void handle_rx_pkt(CLatencyManagerPerPort * lp, rte_mbuf_t * m); void handle_rx_queue_msgs(uint8_t thread_id, CNodeRing * r); + void flush_rx(); int try_rx(); void try_rx_queues(); bool is_flow_stat_id(uint16_t id); @@ -71,10 +74,13 @@ class CRxCoreStateless { uint32_t m_max_ports; bool m_has_streams; CLatencyManagerPerPort m_ports[TREX_MAX_PORTS]; - state_e m_state; /* state of all ports */ + state_e m_state; CNodeRing *m_ring_from_cp; CNodeRing *m_ring_to_cp; CCpuUtlDp m_cpu_dp_u; CCpuUtlCp m_cpu_cp_u; + // Used for acking "work" (go out of idle) messages from cp + volatile bool m_ack_start_work_msg __rte_cache_aligned; + }; #endif |