diff options
Diffstat (limited to 'src/stateless/cp')
-rw-r--r-- | src/stateless/cp/trex_stateless.cpp | 212 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless.h | 202 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 228 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 230 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 116 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 209 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.cpp | 54 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream_vm.h | 171 |
8 files changed, 1422 insertions, 0 deletions
diff --git a/src/stateless/cp/trex_stateless.cpp b/src/stateless/cp/trex_stateless.cpp new file mode 100644 index 00000000..72762e26 --- /dev/null +++ b/src/stateless/cp/trex_stateless.cpp @@ -0,0 +1,212 @@ +/* + 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_stateless.h> +#include <trex_stateless_port.h> + +#include <sched.h> +#include <iostream> +#include <unistd.h> + +using namespace std; + +/*********************************************************** + * Trex stateless object + * + **********************************************************/ +TrexStateless::TrexStateless() { + m_is_configured = false; +} + + +/** + * configure the singleton stateless object + * + */ +void TrexStateless::configure(const TrexStatelessCfg &cfg) { + + TrexStateless& instance = get_instance_internal(); + + /* check status */ + if (instance.m_is_configured) { + throw TrexException("re-configuration of stateless object is not allowed"); + } + + /* create RPC servers */ + + /* set both servers to mutex each other */ + instance.m_rpc_server = new TrexRpcServer(cfg.m_rpc_req_resp_cfg, cfg.m_rpc_async_cfg, &instance.m_global_cp_lock); + instance.m_rpc_server->set_verbose(cfg.m_rpc_server_verbose); + + /* configure ports */ + + instance.m_port_count = cfg.m_port_count; + + for (int i = 0; i < instance.m_port_count; i++) { + instance.m_ports.push_back(new TrexStatelessPort(i)); + } + + /* cores */ + instance.m_dp_core_count = cfg.m_dp_core_count; + for (int i = 0; i < instance.m_dp_core_count; i++) { + instance.m_dp_cores.push_back(new TrexStatelessDpCore(i)); + } + + /* done */ + instance.m_is_configured = true; +} + +/** + * starts the control plane side + * + */ +void +TrexStateless::launch_control_plane() { + //std::cout << "\n on control/master core \n"; + + /* pin this process to the current running CPU + any new thread will be called on the same CPU + (control plane restriction) + */ + cpu_set_t mask; + CPU_ZERO(&mask); + CPU_SET(sched_getcpu(), &mask); + sched_setaffinity(0, sizeof(mask), &mask); + + /* start RPC server */ + m_rpc_server->start(); +} + +void +TrexStateless::launch_on_dp_core(uint8_t core_id) { + m_dp_cores[core_id - 1]->run(); +} + +/** + * destroy the singleton and release all memory + * + * @author imarom (08-Oct-15) + */ +void +TrexStateless::destroy() { + TrexStateless& instance = get_instance_internal(); + + if (!instance.m_is_configured) { + return; + } + + /* release memory for ports */ + for (auto port : instance.m_ports) { + delete port; + } + instance.m_ports.clear(); + + /* stops the RPC server */ + instance.m_rpc_server->stop(); + delete instance.m_rpc_server; + + instance.m_rpc_server = NULL; + + /* done */ + instance.m_is_configured = false; +} + +/** + * fetch a port by ID + * + */ +TrexStatelessPort * TrexStateless::get_port_by_id(uint8_t port_id) { + if (port_id >= m_port_count) { + throw TrexException("index out of range"); + } + + return m_ports[port_id]; + +} + +uint8_t +TrexStateless::get_port_count() { + return m_port_count; +} + +uint8_t +TrexStateless::get_dp_core_count() { + return m_dp_core_count; +} + +void +TrexStateless::update_stats() { + + /* update CPU util. + TODO + */ + m_stats.m_stats.m_cpu_util = 0; + + /* for every port update and accumulate */ + for (uint8_t i = 0; i < m_port_count; i++) { + m_ports[i]->update_stats(); + + const TrexPortStats & port_stats = m_ports[i]->get_stats(); + + m_stats.m_stats.m_tx_bps += port_stats.m_stats.m_tx_bps; + m_stats.m_stats.m_rx_bps += port_stats.m_stats.m_rx_bps; + + m_stats.m_stats.m_tx_pps += port_stats.m_stats.m_tx_pps; + m_stats.m_stats.m_rx_pps += port_stats.m_stats.m_rx_pps; + + m_stats.m_stats.m_total_tx_pkts += port_stats.m_stats.m_total_tx_pkts; + m_stats.m_stats.m_total_rx_pkts += port_stats.m_stats.m_total_rx_pkts; + + m_stats.m_stats.m_total_tx_bytes += port_stats.m_stats.m_total_tx_bytes; + m_stats.m_stats.m_total_rx_bytes += port_stats.m_stats.m_total_rx_bytes; + + m_stats.m_stats.m_tx_rx_errors += port_stats.m_stats.m_tx_rx_errors; + } +} + +void +TrexStateless::encode_stats(Json::Value &global) { + + global["cpu_util"] = m_stats.m_stats.m_cpu_util; + + global["tx_bps"] = m_stats.m_stats.m_tx_bps; + global["rx_bps"] = m_stats.m_stats.m_rx_bps; + + global["tx_pps"] = m_stats.m_stats.m_tx_pps; + global["rx_pps"] = m_stats.m_stats.m_rx_pps; + + global["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); + global["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); + + global["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); + global["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); + + global["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); + + for (uint8_t i = 0; i < m_port_count; i++) { + std::stringstream ss; + + ss << "port " << i; + Json::Value &port_section = global[ss.str()]; + + m_ports[i]->encode_stats(port_section); + } +} + diff --git a/src/stateless/cp/trex_stateless.h b/src/stateless/cp/trex_stateless.h new file mode 100644 index 00000000..649b25dd --- /dev/null +++ b/src/stateless/cp/trex_stateless.h @@ -0,0 +1,202 @@ +/* + 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_STATELESS_H__ +#define __TREX_STATELESS_H__ + +#include <stdint.h> +#include <string> +#include <stdexcept> + +#include <mutex> + +#include <trex_stream.h> +#include <trex_stateless_port.h> +#include <trex_stateless_dp_core.h> +#include <trex_rpc_server_api.h> + +/** + * 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) { + } +}; + +class TrexStatelessPort; + +/** + * unified stats + * + * @author imarom (06-Oct-15) + */ +class TrexStatelessStats { +public: + TrexStatelessStats() { + m_stats = {0}; + } + + struct { + double m_cpu_util; + + double m_tx_bps; + double m_rx_bps; + + double m_tx_pps; + double m_rx_pps; + + uint64_t m_total_tx_pkts; + uint64_t m_total_rx_pkts; + + uint64_t m_total_tx_bytes; + uint64_t m_total_rx_bytes; + + uint64_t m_tx_rx_errors; + } m_stats; +}; + +/** + * config object for stateless object + * + * @author imarom (08-Oct-15) + */ +class TrexStatelessCfg { +public: + /* default values */ + TrexStatelessCfg() { + m_port_count = 0; + m_dp_core_count = 0; + m_rpc_req_resp_cfg = NULL; + m_rpc_async_cfg = NULL; + m_rpc_server_verbose = false; + } + + const TrexRpcServerConfig *m_rpc_req_resp_cfg; + const TrexRpcServerConfig *m_rpc_async_cfg; + bool m_rpc_server_verbose; + uint8_t m_port_count; + uint8_t m_dp_core_count; +}; + +/** + * defines the T-Rex stateless operation mode + * + */ +class TrexStateless { +public: + + /** + * configure the stateless object singelton + * reconfiguration is not allowed + * an exception will be thrown + */ + static void configure(const TrexStatelessCfg &cfg); + + /** + * destroy the instance + * + */ + static void destroy(); + + /** + * singleton public get instance + * + */ + static TrexStateless& get_instance() { + TrexStateless& instance = get_instance_internal(); + + if (!instance.m_is_configured) { + throw TrexException("object is not configured"); + } + + return instance; + } + + /** + * starts the control plane side + * + */ + void launch_control_plane(); + + /** + * launch on a single DP core + * + */ + void launch_on_dp_core(uint8_t core_id); + + TrexStatelessPort * get_port_by_id(uint8_t port_id); + uint8_t get_port_count(); + + uint8_t get_dp_core_count(); + + /** + * update all the stats (deep update) + * (include all the ports and global stats) + * + */ + void update_stats(); + + /** + * fetch all the stats + * + */ + void encode_stats(Json::Value &global); + + +protected: + TrexStateless(); + + static TrexStateless& get_instance_internal () { + static TrexStateless instance; + return instance; + } + + /* c++ 2011 style singleton */ + TrexStateless(TrexStateless const&) = delete; + void operator=(TrexStateless const&) = delete; + + /* status */ + bool m_is_configured; + + /* RPC server array */ + TrexRpcServer *m_rpc_server; + + /* ports */ + std::vector <TrexStatelessPort *> m_ports; + uint8_t m_port_count; + + /* cores */ + std::vector <TrexStatelessDpCore *> m_dp_cores; + uint8_t m_dp_core_count; + + /* stats */ + TrexStatelessStats m_stats; + + std::mutex m_global_cp_lock; +}; + +#endif /* __TREX_STATELESS_H__ */ + diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp new file mode 100644 index 00000000..a31847a5 --- /dev/null +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -0,0 +1,228 @@ +/* + 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_stateless.h> +#include <trex_stateless_port.h> +#include <string> + +#ifndef TREX_RPC_MOCK_SERVER +// DPDK c++ issue +#define UINT8_MAX 255 +#define UINT16_MAX 0xFFFF +// DPDK c++ issue +#endif + +#include <rte_ethdev.h> +#include <os_time.h> + +using namespace std; + +/*************************** + * trex stateless port + * + **************************/ +TrexStatelessPort::TrexStatelessPort(uint8_t port_id) : m_port_id(port_id) { + m_port_state = PORT_STATE_UP_IDLE; + clear_owner(); +} + + +/** + * starts the traffic on the port + * + */ +TrexStatelessPort::rc_e +TrexStatelessPort::start_traffic(void) { + + if (m_port_state != PORT_STATE_UP_IDLE) { + return (RC_ERR_BAD_STATE_FOR_OP); + } + + if (get_stream_table()->size() == 0) { + return (RC_ERR_NO_STREAMS); + } + + m_port_state = PORT_STATE_TRANSMITTING; + + /* real code goes here */ + return (RC_OK); +} + +void +TrexStatelessPort::stop_traffic(void) { + + /* real code goes here */ + if (m_port_state == PORT_STATE_TRANSMITTING) { + m_port_state = PORT_STATE_UP_IDLE; + } +} + +/** +* access the stream table +* +*/ +TrexStreamTable * TrexStatelessPort::get_stream_table() { + return &m_stream_table; +} + + +std::string +TrexStatelessPort::get_state_as_string() { + + switch (get_state()) { + case PORT_STATE_DOWN: + return "down"; + + case PORT_STATE_UP_IDLE: + return "idle"; + + case PORT_STATE_TRANSMITTING: + return "transmitting"; + } + + return "unknown"; +} + +void +TrexStatelessPort::get_properties(string &driver, string &speed) { + + /* take this from DPDK */ + driver = "e1000"; + speed = "1 Gbps"; +} + + +/** + * generate a random connection handler + * + */ +std::string +TrexStatelessPort::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() % (sizeof(alphanum) - 1)]; + } + + return (ss.str()); +} + +/** + * update stats for the port + * + */ +void +TrexStatelessPort::update_stats() { + struct rte_eth_stats stats; + rte_eth_stats_get(m_port_id, &stats); + + /* copy straight values */ + m_stats.m_stats.m_total_tx_bytes = stats.obytes; + m_stats.m_stats.m_total_rx_bytes = stats.ibytes; + + m_stats.m_stats.m_total_tx_pkts = stats.opackets; + m_stats.m_stats.m_total_rx_pkts = stats.ipackets; + + /* calculate stats */ + m_stats.m_stats.m_tx_bps = m_stats.m_bw_tx_bps.add(stats.obytes); + m_stats.m_stats.m_rx_bps = m_stats.m_bw_rx_bps.add(stats.ibytes); + + m_stats.m_stats.m_tx_pps = m_stats.m_bw_tx_pps.add(stats.opackets); + m_stats.m_stats.m_rx_pps = m_stats.m_bw_rx_pps.add(stats.ipackets); + +} + +const TrexPortStats & +TrexStatelessPort::get_stats() { + return m_stats; +} + +void +TrexStatelessPort::encode_stats(Json::Value &port) { + + port["tx_bps"] = m_stats.m_stats.m_tx_bps; + port["rx_bps"] = m_stats.m_stats.m_rx_bps; + + port["tx_pps"] = m_stats.m_stats.m_tx_pps; + port["rx_pps"] = m_stats.m_stats.m_rx_pps; + + port["total_tx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_pkts); + port["total_rx_pkts"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_pkts); + + port["total_tx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_tx_bytes); + port["total_rx_bytes"] = Json::Value::UInt64(m_stats.m_stats.m_total_rx_bytes); + + port["tx_rx_errors"] = Json::Value::UInt64(m_stats.m_stats.m_tx_rx_errors); +} + + + +/*************************** + * BW measurement + * + **************************/ +/* TODO: move this to a common place */ +BWMeasure::BWMeasure() { + reset(); +} + +void BWMeasure::reset(void) { + m_start=false; + m_last_time_msec=0; + m_last_bytes=0; + m_last_result=0.0; +}; + +double BWMeasure::calc_MBsec(uint32_t dtime_msec, + uint64_t dbytes){ + double rate=0.000008*( ( (double)dbytes*(double)os_get_time_freq())/((double)dtime_msec) ); + return(rate); +} + +double BWMeasure::add(uint64_t size) { + if ( false == m_start ) { + m_start=true; + m_last_time_msec = os_get_time_msec() ; + m_last_bytes=size; + return(0.0); + } + + uint32_t ctime=os_get_time_msec(); + if ((ctime - m_last_time_msec) <os_get_time_freq() ) { + return(m_last_result); + } + + uint32_t dtime_msec = ctime-m_last_time_msec; + uint64_t dbytes = size - m_last_bytes; + + m_last_time_msec = ctime; + m_last_bytes = size; + + m_last_result= 0.5*calc_MBsec(dtime_msec,dbytes) +0.5*(m_last_result); + return( m_last_result ); +} + + diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h new file mode 100644 index 00000000..428d5aee --- /dev/null +++ b/src/stateless/cp/trex_stateless_port.h @@ -0,0 +1,230 @@ +/* + 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_STATELESS_PORT_H__ +#define __TREX_STATELESS_PORT_H__ + +#include <trex_stream.h> + +/** + * bandwidth measurement class + * + */ +class BWMeasure { +public: + BWMeasure(); + void reset(void); + double add(uint64_t size); + +private: + double calc_MBsec(uint32_t dtime_msec, + uint64_t dbytes); + +public: + bool m_start; + uint32_t m_last_time_msec; + uint64_t m_last_bytes; + double m_last_result; +}; + +/** + * TRex stateless port stats + * + * @author imarom (24-Sep-15) + */ +class TrexPortStats { + +public: + TrexPortStats() { + m_stats = {0}; + + m_bw_tx_bps.reset(); + m_bw_rx_bps.reset(); + + m_bw_tx_pps.reset(); + m_bw_rx_pps.reset(); + } + +public: + + BWMeasure m_bw_tx_bps; + BWMeasure m_bw_rx_bps; + + BWMeasure m_bw_tx_pps; + BWMeasure m_bw_rx_pps; + + struct { + + double m_tx_bps; + double m_rx_bps; + + double m_tx_pps; + double m_rx_pps; + + uint64_t m_total_tx_pkts; + uint64_t m_total_rx_pkts; + + uint64_t m_total_tx_bytes; + uint64_t m_total_rx_bytes; + + uint64_t m_tx_rx_errors; + } m_stats; +}; + +/** + * describes a stateless port + * + * @author imarom (31-Aug-15) + */ +class TrexStatelessPort { +public: + + /** + * port state + */ + enum port_state_e { + PORT_STATE_DOWN, + PORT_STATE_UP_IDLE, + PORT_STATE_TRANSMITTING + }; + + /** + * describess different error codes for port operations + */ + enum rc_e { + RC_OK, + RC_ERR_BAD_STATE_FOR_OP, + RC_ERR_NO_STREAMS, + RC_ERR_FAILED_TO_COMPILE_STREAMS + }; + + TrexStatelessPort(uint8_t port_id); + + /** + * start traffic + * + */ + rc_e start_traffic(void); + + /** + * stop traffic + * + */ + void stop_traffic(void); + + /** + * access the stream table + * + */ + TrexStreamTable *get_stream_table(); + + /** + * get the port state + * + */ + port_state_e get_state() { + return m_port_state; + } + + /** + * port state as string + * + */ + std::string get_state_as_string(); + + /** + * fill up properties of the port + * + * @author imarom (16-Sep-15) + * + * @param driver + * @param speed + */ + void get_properties(std::string &driver, std::string &speed); + + /** + * query for ownership + * + */ + const std::string &get_owner() { + return m_owner; + } + + /** + * owner handler + * for the connection + * + */ + const std::string &get_owner_handler() { + return m_owner_handler; + } + + bool is_free_to_aquire() { + return (m_owner == "none"); + } + + /** + * take ownership of the server array + * this is static + * ownership is total + * + */ + void set_owner(const std::string &owner) { + m_owner = owner; + m_owner_handler = generate_handler(); + } + + void clear_owner() { + m_owner = "none"; + m_owner_handler = ""; + } + + bool verify_owner_handler(const std::string &handler) { + + return ( (m_owner != "none") && (m_owner_handler == handler) ); + + } + + /** + * update the values of the stats + * + */ + void update_stats(); + + const TrexPortStats & get_stats(); + + /** + * encode stats as JSON + */ + void encode_stats(Json::Value &port); + +private: + + std::string generate_handler(); + + TrexStreamTable m_stream_table; + uint8_t m_port_id; + port_state_e m_port_state; + std::string m_owner; + std::string m_owner_handler; + TrexPortStats m_stats; +}; + +#endif /* __TREX_STATELESS_PORT_H__ */ diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp new file mode 100644 index 00000000..182036f1 --- /dev/null +++ b/src/stateless/cp/trex_stream.cpp @@ -0,0 +1,116 @@ +/* + 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_stream.h> +#include <cstddef> + +/************************************** + * stream + *************************************/ +TrexStream::TrexStream(uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) { + + /* default values */ + m_isg_usec = 0; + m_next_stream_id = -1; + m_enabled = false; + m_self_start = false; + + m_pkt.binary = NULL; + m_pkt.len = 0; + + m_rx_check.m_enable = false; + +} + +TrexStream::~TrexStream() { + if (m_pkt.binary) { + delete [] m_pkt.binary; + } +} + +void +TrexStream::store_stream_json(const Json::Value &stream_json) { + /* deep copy */ + m_stream_json = stream_json; +} + +const Json::Value & +TrexStream::get_stream_json() { + return m_stream_json; +} + +/************************************** + * stream table + *************************************/ +TrexStreamTable::TrexStreamTable() { + +} + +TrexStreamTable::~TrexStreamTable() { + for (auto stream : m_stream_table) { + delete stream.second; + } +} + +void TrexStreamTable::add_stream(TrexStream *stream) { + TrexStream *old_stream = get_stream_by_id(stream->m_stream_id); + if (old_stream) { + remove_stream(old_stream); + delete old_stream; + } + + m_stream_table[stream->m_stream_id] = stream; +} + +void TrexStreamTable::remove_stream(TrexStream *stream) { + m_stream_table.erase(stream->m_stream_id); +} + + +void TrexStreamTable::remove_and_delete_all_streams() { + + for (auto stream : m_stream_table) { + delete stream.second; + } + + m_stream_table.clear(); +} + +TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { + auto search = m_stream_table.find(stream_id); + + if (search != m_stream_table.end()) { + return search->second; + } else { + return NULL; + } +} + +void TrexStreamTable::get_stream_list(std::vector<uint32_t> &stream_list) { + stream_list.clear(); + + for (auto stream : m_stream_table) { + stream_list.push_back(stream.first); + } +} + +int TrexStreamTable::size() { + return m_stream_table.size(); +} diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h new file mode 100644 index 00000000..f5bc96ef --- /dev/null +++ b/src/stateless/cp/trex_stream.h @@ -0,0 +1,209 @@ +/* + 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_STREAM_H__ +#define __TREX_STREAM_H__ + +#include <unordered_map> +#include <vector> +#include <stdint.h> +#include <string> + +#include <json/json.h> + +#include <trex_stream_vm.h> + +class TrexRpcCmdAddStream; + +/** + * Stateless Stream + * + */ +class TrexStream { + /* provide the RPC parser a way to access private fields */ + friend class TrexRpcCmdAddStream; + friend class TrexRpcCmdGetStream; + friend class TrexStreamTable; + +public: + TrexStream(uint8_t port_id, uint32_t stream_id); + virtual ~TrexStream() = 0; + + /* defines the min max per packet supported */ + static const uint32_t MIN_PKT_SIZE_BYTES = 1; + static const uint32_t MAX_PKT_SIZE_BYTES = 9000; + + /* provides storage for the stream json*/ + void store_stream_json(const Json::Value &stream_json); + + /* access the stream json */ + const Json::Value & get_stream_json(); + +protected: + /* basic */ + uint8_t m_port_id; + uint32_t m_stream_id; + + + /* config fields */ + double m_isg_usec; + int m_next_stream_id; + + /* indicators */ + bool m_enabled; + bool m_self_start; + + /* pkt */ + struct { + uint8_t *binary; + uint16_t len; + std::string meta; + } m_pkt; + + /* VM */ + StreamVm m_vm; + + /* RX check */ + struct { + bool m_enable; + bool m_seq_enabled; + bool m_latency; + uint32_t m_stream_id; + + } m_rx_check; + + + /* original template provided by requester */ + Json::Value m_stream_json; +}; + +/** + * continuous stream + * + */ +class TrexStreamContinuous : public TrexStream { +public: + TrexStreamContinuous(uint8_t port_id, uint32_t stream_id, double pps) : TrexStream(port_id, stream_id), m_pps(pps) { + } + + double get_pps() { + return m_pps; + } + +protected: + double m_pps; +}; + +/** + * single burst + * + */ +class TrexStreamBurst : public TrexStream { +public: + TrexStreamBurst(uint8_t port_id, uint32_t stream_id, uint32_t total_pkts, double pps) : + TrexStream(port_id, stream_id), + m_total_pkts(total_pkts), + m_pps(pps) { + } + +protected: + uint32_t m_total_pkts; + double m_pps; +}; + +/** + * multi burst + * + */ +class TrexStreamMultiBurst : public TrexStreamBurst { +public: + TrexStreamMultiBurst(uint8_t port_id, + uint32_t stream_id, + uint32_t pkts_per_burst, + double pps, + uint32_t num_bursts, + double ibg_usec) : TrexStreamBurst(port_id, stream_id, pkts_per_burst, pps), m_num_bursts(num_bursts), m_ibg_usec(ibg_usec) { + + } +protected: + uint32_t m_num_bursts; + double m_ibg_usec; + +}; + +/** + * holds all the streams + * + */ +class TrexStreamTable { +public: + + TrexStreamTable(); + ~TrexStreamTable(); + + /** + * add a stream + * if a previous one exists, the old one will be deleted + */ + void add_stream(TrexStream *stream); + + /** + * remove a stream + */ + void remove_stream(TrexStream *stream); + + /** + * remove all streams on the table + * memory will be deleted + */ + void remove_and_delete_all_streams(); + + /** + * fetch a stream if exists + * o.w NULL + * + */ + TrexStream * get_stream_by_id(uint32_t stream_id); + + /** + * populate a list with all the stream IDs + * + * @author imarom (06-Sep-15) + * + * @param stream_list + */ + void get_stream_list(std::vector<uint32_t> &stream_list); + + /** + * get the table size + * + */ + int size(); + +private: + /** + * holds all the stream in a hash table by stream id + * + */ + std::unordered_map<int, TrexStream *> m_stream_table; +}; + +#endif /* __TREX_STREAM_H__ */ + diff --git a/src/stateless/cp/trex_stream_vm.cpp b/src/stateless/cp/trex_stream_vm.cpp new file mode 100644 index 00000000..2e760ae9 --- /dev/null +++ b/src/stateless/cp/trex_stream_vm.cpp @@ -0,0 +1,54 @@ +/* + 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_stream_vm.h> + +/*************************** + * StreamVmInstruction + * + **************************/ +StreamVmInstruction::~StreamVmInstruction() { + +} + +/*************************** + * StreamVm + * + **************************/ +void StreamVm::add_instruction(StreamVmInstruction *inst) { + m_inst_list.push_back(inst); +} + +const std::vector<StreamVmInstruction *> & +StreamVm::get_instruction_list() { + return m_inst_list; +} + +bool StreamVm::compile() { + /* implement me */ + return (false); +} + +StreamVm::~StreamVm() { + for (auto inst : m_inst_list) { + delete inst; + } +} + diff --git a/src/stateless/cp/trex_stream_vm.h b/src/stateless/cp/trex_stream_vm.h new file mode 100644 index 00000000..56edbcaf --- /dev/null +++ b/src/stateless/cp/trex_stream_vm.h @@ -0,0 +1,171 @@ +/* + 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_STREAM_VM_API_H__ +#define __TREX_STREAM_VM_API_H__ + +#include <string> +#include <stdint.h> +#include <vector> + +/** + * interface for stream VM instruction + * + */ +class StreamVmInstruction { +public: + + virtual ~StreamVmInstruction(); + +private: + static const std::string m_name; +}; + +/** + * fix checksum for ipv4 + * + */ +class StreamVmInstructionFixChecksumIpv4 : public StreamVmInstruction { +public: + StreamVmInstructionFixChecksumIpv4(uint16_t offset) : m_pkt_offset(offset) { + + } + +private: + uint16_t m_pkt_offset; +}; + +/** + * flow manipulation instruction + * + * @author imarom (07-Sep-15) + */ +class StreamVmInstructionFlowMan : public StreamVmInstruction { + +public: + + /** + * different types of operations on the object + */ + enum flow_var_op_e { + FLOW_VAR_OP_INC, + FLOW_VAR_OP_DEC, + FLOW_VAR_OP_RANDOM + }; + + StreamVmInstructionFlowMan(const std::string &var_name, + uint8_t size, + flow_var_op_e op, + uint64_t init_value, + uint64_t min_value, + uint64_t max_value) : + m_var_name(var_name), + m_size_bytes(size), + m_op(op), + m_init_value(init_value), + m_min_value(min_value), + m_max_value(max_value) { + + } + +private: + + + /* flow var name */ + std::string m_var_name; + + /* flow var size */ + uint8_t m_size_bytes; + + /* type of op */ + flow_var_op_e m_op; + + /* range */ + uint64_t m_init_value; + uint64_t m_min_value; + uint64_t m_max_value; + + +}; + +/** + * write flow var to packet + * + */ +class StreamVmInstructionWriteToPkt : public StreamVmInstruction { +public: + + StreamVmInstructionWriteToPkt(const std::string &flow_var_name, + uint16_t pkt_offset, + int32_t add_value = 0, + bool is_big_endian = true) : + + m_flow_var_name(flow_var_name), + m_pkt_offset(pkt_offset), + m_add_value(add_value), + m_is_big_endian(is_big_endian) {} +private: + + /* flow var name to write */ + std::string m_flow_var_name; + + /* where to write */ + uint16_t m_pkt_offset; + + /* add/dec value from field when writing */ + int32_t m_add_value; + + /* writing endian */ + bool m_is_big_endian; +}; + +/** + * describes a VM program + * + */ +class StreamVm { +public: + + /** + * add new instruction to the VM + * + */ + void add_instruction(StreamVmInstruction *inst); + + /** + * get const access to the instruction list + * + */ + const std::vector<StreamVmInstruction *> & get_instruction_list(); + + /** + * compile the VM + * return true of success, o.w false + * + */ + bool compile(); + + ~StreamVm(); + +private: + std::vector<StreamVmInstruction *> m_inst_list; +}; + +#endif /* __TREX_STREAM_VM_API_H__ */ |