1/*
2 Itay Marom
3 Cisco Systems, Inc.
4*/
5
6/*
7Copyright (c) 2015-2015 Cisco Systems, Inc.
8
9Licensed under the Apache License, Version 2.0 (the "License");
10you may not use this file except in compliance with the License.
11You may obtain a copy of the License at
12
13    http://www.apache.org/licenses/LICENSE-2.0
14
15Unless required by applicable law or agreed to in writing, software
16distributed under the License is distributed on an "AS IS" BASIS,
17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18See the License for the specific language governing permissions and
19limitations under the License.
20*/
21#include <trex_stream.h>
22#include <cstddef>
23#include <string.h>
24#include <assert.h>
25#include <trex_stateless.h>
26
27/**************************************
28 * stream
29 *************************************/
30
31
32std::string TrexStream::get_stream_type_str(stream_type_t stream_type){
33
34    std::string res;
35
36
37    switch (stream_type) {
38
39    case        stCONTINUOUS :
40         res="stCONTINUOUS  ";
41        break;
42
43    case stSINGLE_BURST :
44        res="stSINGLE_BURST  ";
45        break;
46
47    case stMULTI_BURST :
48        res="stMULTI_BURST  ";
49        break;
50    default:
51        res="Unknow  ";
52    };
53    return(res);
54}
55
56
57void
58TrexStream::vm_compile() {
59
60    /* in case there are no instructions - nothing to do */
61    if (m_vm.is_vm_empty()) {
62        return;
63    }
64
65    /* compile */
66    m_vm.set_pkt(m_pkt.binary);
67    m_vm.compile(m_pkt.len);
68    m_vm.set_pkt(0);
69
70    /* create DP object */
71    m_vm_dp = m_vm.generate_dp_object();
72
73}
74
75
76void TrexStream::Dump(FILE *fd){
77
78    fprintf(fd,"\n");
79    fprintf(fd,"==> Stream_id    : %lu \n",(ulong)m_stream_id);
80    fprintf(fd," Enabled      : %lu \n",(ulong)(m_enabled?1:0));
81    fprintf(fd," Self_start   : %lu \n",(ulong)(m_self_start?1:0));
82
83    if (m_next_stream_id>=0) {
84        fprintf(fd," Nex_stream_id  : %lu \n",(ulong)m_next_stream_id);
85    }else {
86        fprintf(fd," Nex_stream_id  : %d \n",m_next_stream_id);
87    }
88
89    fprintf(fd," Port_id      : %lu \n",(ulong)m_port_id);
90
91    if (m_isg_usec>0.0) {
92        fprintf(fd," isg    : %6.2f \n",m_isg_usec);
93    }
94    fprintf(fd," type    : %s \n",get_stream_type_str(m_type).c_str());
95
96    if ( m_type == TrexStream::stCONTINUOUS ) {
97    }
98    if (m_type == TrexStream::stSINGLE_BURST) {
99        fprintf(fd," burst      : %lu \n",(ulong)m_burst_total_pkts);
100    }
101    if (m_type == TrexStream::stMULTI_BURST) {
102        fprintf(fd," burst      : %lu \n",(ulong)m_burst_total_pkts);
103        fprintf(fd," mburst     : %lu \n",(ulong)m_num_bursts);
104        if (m_ibg_usec>0.0) {
105            fprintf(fd," m_ibg_usec : %f \n",m_ibg_usec);
106        }
107    }
108
109    if (m_rx_check.m_enabled) {
110        fprintf(fd, " Flow stat enabled:\n");
111        fprintf(fd, "   seq check %s latency check %s packet group id %d hw_id %d\n"
112                , m_rx_check.m_seq_enabled ? "enabled":"disabled"
113                , m_rx_check.m_latency ? "enabled":"disabled", m_rx_check.m_pg_id, m_rx_check.m_hw_id
114                );
115    } else {
116        fprintf(fd, " Flow stat disabled\n");
117    }
118    fprintf(fd," rate    :\n\n");
119
120    fprintf(fd," pps         : %f\n", m_rate.get_pps());
121    fprintf(fd," bps L1      : %f\n", m_rate.get_bps_L1());
122    fprintf(fd," bps L2      : %f\n", m_rate.get_bps_L2());
123    fprintf(fd," percentage  : %f\n", m_rate.get_percentage());
124    fprintf(fd," cache_size  : %lu\n", (ulong)m_cache_size);
125}
126
127
128TrexStream::TrexStream(uint8_t type,
129                       uint8_t port_id, uint32_t stream_id) : m_port_id(port_id), m_stream_id(stream_id) , m_rate(*this) {
130
131    /* default values */
132    m_type              = type;
133    m_isg_usec          = 0;
134    m_next_stream_id    = -1;
135    m_enabled           = false;
136    m_self_start        = false;
137    m_cache_size        = 0;
138
139    m_mc_phase_pre_sec           = 0;
140    m_mc_phase_post_sec          = 0;
141
142    m_pkt.binary       = NULL;
143    m_pkt.len          = 0;
144    m_expected_pkt_len = 0.0;
145
146    m_rx_check.m_enabled = false;
147
148    m_burst_total_pkts=0;
149    m_num_bursts=1;
150    m_ibg_usec=0.0;
151    m_vm_dp = NULL;
152    m_flags=0;
153    m_action_count=0;
154    m_null_stream = false;
155}
156
157TrexStream::~TrexStream() {
158#if 0
159    if (m_rx_check.m_enabled) {
160        try {
161            get_stateless_obj()->m_rx_flow_stat.del_stream(this);
162        } catch (TrexFStatEx) {}
163    }
164#endif
165    if (m_pkt.binary) {
166        delete [] m_pkt.binary;
167    }
168    if (m_vm_dp){
169        delete m_vm_dp;
170        m_vm_dp = NULL;
171    }
172}
173
174void
175TrexStream::store_stream_json(const Json::Value &stream_json) {
176    /* deep copy */
177    m_stream_json = stream_json;
178}
179
180const Json::Value &
181TrexStream::get_stream_json() {
182    return m_stream_json;
183}
184
185
186/**************************************
187 * stream table
188 *************************************/
189TrexStreamTable::TrexStreamTable() {
190
191}
192
193TrexStreamTable::~TrexStreamTable() {
194    for (auto stream : m_stream_table) {
195        delete stream.second;
196    }
197}
198
199void TrexStreamTable::add_stream(TrexStream *stream) {
200    TrexStream *old_stream = get_stream_by_id(stream->m_stream_id);
201    if (old_stream) {
202        remove_stream(old_stream);
203        delete old_stream;
204    }
205
206    m_stream_table[stream->m_stream_id] = stream;
207}
208
209void TrexStreamTable::remove_stream(TrexStream *stream) {
210    m_stream_table.erase(stream->m_stream_id);
211}
212
213
214TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) {
215    auto search = m_stream_table.find(stream_id);
216
217    if (search != m_stream_table.end()) {
218        return search->second;
219    } else {
220        return NULL;
221    }
222}
223
224int
225TrexStreamTable::get_max_stream_id() const {
226    int max_id = 0;
227
228    for (const auto stream : m_stream_table) {
229        max_id = std::max(stream.first, max_id);
230    }
231
232    return max_id;
233}
234
235void TrexStreamTable::get_id_list(std::vector<uint32_t> &id_list) {
236    id_list.clear();
237
238    for (auto stream : m_stream_table) {
239        id_list.push_back(stream.first);
240    }
241}
242
243void TrexStreamTable::get_object_list(std::vector<TrexStream *> &object_list) {
244    object_list.clear();
245
246    for (auto stream : m_stream_table) {
247        object_list.push_back(stream.second);
248    }
249
250}
251
252int TrexStreamTable::size() {
253    return m_stream_table.size();
254}
255
256
257/**************************************
258 * TrexStreamRate
259 *************************************/
260uint64_t
261TrexStreamRate::get_line_speed_bps() {
262    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_stream.m_port_id);
263    return port->get_port_speed_bps();
264}
265
266double
267TrexStreamRate::get_pkt_size() {
268    double pkt_size = m_stream.get_pkt_size();
269
270    // compensate for Ethernet FCS (CRC) added by driver
271    pkt_size += 4;
272
273    return pkt_size;
274}
275