1/*
2 Itay Marom
3 Hanoch Haim
4 Cisco Systems, Inc.
5*/
6
7/*
8Copyright (c) 2015-2016 Cisco Systems, Inc.
9
10Licensed under the Apache License, Version 2.0 (the "License");
11you may not use this file except in compliance with the License.
12You may obtain a copy of the License at
13
14    http://www.apache.org/licenses/LICENSE-2.0
15
16Unless required by applicable law or agreed to in writing, software
17distributed under the License is distributed on an "AS IS" BASIS,
18WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19See the License for the specific language governing permissions and
20limitations under the License.
21*/
22#include <string.h>
23
24#include "trex_stateless_messaging.h"
25#include "trex_stateless_dp_core.h"
26#include "trex_stateless_rx_core.h"
27#include "trex_streams_compiler.h"
28#include "trex_stateless.h"
29#include "bp_sim.h"
30
31/*************************
32  start traffic message
33 ************************/
34TrexStatelessDpStart::TrexStatelessDpStart(uint8_t port_id, int event_id, TrexStreamsCompiledObj *obj, double duration) {
35    m_port_id = port_id;
36    m_event_id = event_id;
37    m_obj = obj;
38    m_duration = duration;
39}
40
41
42/**
43 * clone for DP start message
44 *
45 */
46TrexStatelessCpToDpMsgBase *
47TrexStatelessDpStart::clone() {
48
49    TrexStreamsCompiledObj *new_obj = m_obj->clone();
50
51    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpStart(m_port_id, m_event_id, new_obj, m_duration);
52
53    return new_msg;
54}
55
56TrexStatelessDpStart::~TrexStatelessDpStart() {
57    if (m_obj) {
58        delete m_obj;
59    }
60}
61
62bool
63TrexStatelessDpStart::handle(TrexStatelessDpCore *dp_core) {
64
65    /* staet traffic */
66    dp_core->start_traffic(m_obj, m_duration,m_event_id);
67
68    return true;
69}
70
71/*************************
72  stop traffic message
73 ************************/
74bool
75TrexStatelessDpStop::handle(TrexStatelessDpCore *dp_core) {
76
77
78    dp_core->stop_traffic(m_port_id,m_stop_only_for_event_id,m_event_id);
79    return true;
80}
81
82
83void TrexStatelessDpStop::on_node_remove(){
84    if ( m_core ) {
85        assert(m_core->m_non_active_nodes>0);
86        m_core->m_non_active_nodes--;
87    }
88}
89
90
91TrexStatelessCpToDpMsgBase * TrexStatelessDpPause::clone(){
92
93    TrexStatelessDpPause *new_msg = new TrexStatelessDpPause(m_port_id);
94    return new_msg;
95}
96
97
98bool TrexStatelessDpPause::handle(TrexStatelessDpCore *dp_core){
99    dp_core->pause_traffic(m_port_id);
100    return (true);
101}
102
103
104
105TrexStatelessCpToDpMsgBase * TrexStatelessDpResume::clone(){
106    TrexStatelessDpResume *new_msg = new TrexStatelessDpResume(m_port_id);
107    return new_msg;
108}
109
110bool TrexStatelessDpResume::handle(TrexStatelessDpCore *dp_core){
111    dp_core->resume_traffic(m_port_id);
112    return (true);
113}
114
115
116/**
117 * clone for DP stop message
118 *
119 */
120TrexStatelessCpToDpMsgBase *
121TrexStatelessDpStop::clone() {
122    TrexStatelessDpStop *new_msg = new TrexStatelessDpStop(m_port_id);
123
124    new_msg->set_event_id(m_event_id);
125    new_msg->set_wait_for_event_id(m_stop_only_for_event_id);
126    /* set back pointer to master */
127    new_msg->set_core_ptr(m_core);
128
129    return new_msg;
130}
131
132
133
134TrexStatelessCpToDpMsgBase *
135TrexStatelessDpQuit::clone(){
136
137    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpQuit();
138
139    return new_msg;
140}
141
142
143bool TrexStatelessDpQuit::handle(TrexStatelessDpCore *dp_core){
144
145    /* quit  */
146    dp_core->quit_main_loop();
147    return (true);
148}
149
150bool TrexStatelessDpCanQuit::handle(TrexStatelessDpCore *dp_core){
151
152    if ( dp_core->are_all_ports_idle() ){
153        /* if all ports are idle quit now */
154        set_quit(true);
155    }
156    return (true);
157}
158
159TrexStatelessCpToDpMsgBase *
160TrexStatelessDpCanQuit::clone(){
161
162    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpCanQuit();
163
164    return new_msg;
165}
166
167/*************************
168  update traffic message
169 ************************/
170bool
171TrexStatelessDpUpdate::handle(TrexStatelessDpCore *dp_core) {
172    dp_core->update_traffic(m_port_id, m_factor);
173
174    return true;
175}
176
177TrexStatelessCpToDpMsgBase *
178TrexStatelessDpUpdate::clone() {
179    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpUpdate(m_port_id, m_factor);
180
181    return new_msg;
182}
183
184
185/*************************
186  push PCAP message
187 ************************/
188bool
189TrexStatelessDpPushPCAP::handle(TrexStatelessDpCore *dp_core) {
190    dp_core->push_pcap(m_port_id,
191                       m_event_id,
192                       m_pcap_filename,
193                       m_ipg_usec,
194                       m_min_ipg_sec,
195                       m_speedup,
196                       m_count,
197                       m_duration,
198                       m_is_dual);
199    return true;
200}
201
202TrexStatelessCpToDpMsgBase *
203TrexStatelessDpPushPCAP::clone() {
204    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpPushPCAP(m_port_id,
205                                                                      m_event_id,
206                                                                      m_pcap_filename,
207                                                                      m_ipg_usec,
208                                                                      m_min_ipg_sec,
209                                                                      m_speedup,
210                                                                      m_count,
211                                                                      m_duration,
212                                                                      m_is_dual);
213
214    return new_msg;
215}
216
217
218/*************************
219  barrier message
220 ************************/
221
222bool
223TrexStatelessDpBarrier::handle(TrexStatelessDpCore *dp_core) {
224    dp_core->barrier(m_port_id, m_event_id);
225    return true;
226}
227
228TrexStatelessCpToDpMsgBase *
229TrexStatelessDpBarrier::clone() {
230
231    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpBarrier(m_port_id, m_event_id);
232
233    return new_msg;
234}
235
236/*************************
237  service mode message
238 ************************/
239
240bool
241TrexStatelessDpServiceMode::handle(TrexStatelessDpCore *dp_core) {
242    dp_core->set_service_mode(m_port_id, m_enabled);
243    return true;
244}
245
246TrexStatelessCpToDpMsgBase *
247TrexStatelessDpServiceMode::clone() {
248
249    TrexStatelessCpToDpMsgBase *new_msg = new TrexStatelessDpServiceMode(m_port_id, m_enabled);
250
251    return new_msg;
252}
253
254/************************* messages from DP to CP **********************/
255bool
256TrexDpPortEventMsg::handle() {
257    TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(m_port_id);
258    port->get_dp_events().on_core_reporting_in(m_event_id, m_thread_id, get_status());
259
260    return (true);
261}
262
263/************************* messages from CP to RX **********************/
264bool TrexStatelessRxEnableLatency::handle (CRxCoreStateless *rx_core) {
265    rx_core->enable_latency();
266    m_reply.set_reply(true);
267
268    return true;
269}
270
271bool TrexStatelessRxDisableLatency::handle (CRxCoreStateless *rx_core) {
272    rx_core->disable_latency();
273    return true;
274}
275
276bool TrexStatelessRxQuit::handle (CRxCoreStateless *rx_core) {
277    rx_core->quit();
278    return true;
279}
280
281
282bool
283TrexStatelessRxCaptureStart::handle(CRxCoreStateless *rx_core) {
284
285    TrexCaptureRCStart start_rc;
286
287    TrexStatelessCaptureMngr::getInstance().start(m_filter, m_limit, m_mode, start_rc);
288
289    /* mark as done */
290    m_reply.set_reply(start_rc);
291
292    return true;
293}
294
295bool
296TrexStatelessRxCaptureStop::handle(CRxCoreStateless *rx_core) {
297
298    TrexCaptureRCStop stop_rc;
299
300    TrexStatelessCaptureMngr::getInstance().stop(m_capture_id, stop_rc);
301
302    /* mark as done */
303    m_reply.set_reply(stop_rc);
304
305    return true;
306}
307
308bool
309TrexStatelessRxCaptureFetch::handle(CRxCoreStateless *rx_core) {
310
311    TrexCaptureRCFetch fetch_rc;
312
313    TrexStatelessCaptureMngr::getInstance().fetch(m_capture_id, m_pkt_limit, fetch_rc);
314
315    /* mark as done */
316    m_reply.set_reply(fetch_rc);
317
318    return true;
319}
320
321bool
322TrexStatelessRxCaptureStatus::handle(CRxCoreStateless *rx_core) {
323
324    TrexCaptureRCStatus status_rc;
325
326    status_rc.set_rc(TrexStatelessCaptureMngr::getInstance().to_json());
327
328    /* mark as done */
329    m_reply.set_reply(status_rc);
330
331    return true;
332}
333
334bool
335TrexStatelessRxCaptureRemove::handle(CRxCoreStateless *rx_core) {
336
337    TrexCaptureRCRemove remove_rc;
338
339    TrexStatelessCaptureMngr::getInstance().remove(m_capture_id, remove_rc);
340
341    /* mark as done */
342    m_reply.set_reply(remove_rc);
343
344    return true;
345}
346
347
348bool
349TrexStatelessRxStartQueue::handle(CRxCoreStateless *rx_core) {
350    rx_core->start_queue(m_port_id, m_size);
351
352    /* mark as done */
353    m_reply.set_reply(true);
354
355    return true;
356}
357
358bool
359TrexStatelessRxStopQueue::handle(CRxCoreStateless *rx_core) {
360    rx_core->stop_queue(m_port_id);
361
362    return true;
363}
364
365
366
367bool
368TrexStatelessRxQueueGetPkts::handle(CRxCoreStateless *rx_core) {
369    const TrexPktBuffer *pkt_buffer = rx_core->get_rx_queue_pkts(m_port_id);
370
371    /* set the reply */
372    m_reply.set_reply(pkt_buffer);
373
374    return true;
375}
376
377
378bool
379TrexStatelessRxFeaturesToJson::handle(CRxCoreStateless *rx_core) {
380    Json::Value output = rx_core->get_rx_port_mngr(m_port_id).to_json();
381
382    /* set the reply */
383    m_reply.set_reply(output);
384
385    return true;
386}
387
388bool
389TrexStatelessRxSetL2Mode::handle(CRxCoreStateless *rx_core) {
390    rx_core->get_rx_port_mngr(m_port_id).set_l2_mode();
391
392    return true;
393}
394
395bool
396TrexStatelessRxSetL3Mode::handle(CRxCoreStateless *rx_core) {
397    rx_core->get_rx_port_mngr(m_port_id).set_l3_mode(m_src_addr, m_is_grat_arp_needed);
398
399    return true;
400}
401
402bool
403TrexStatelessRxQuery::handle(CRxCoreStateless *rx_core) {
404
405    query_rc_e rc = RC_OK;
406
407    switch (m_query_type) {
408
409    case SERVICE_MODE_ON:
410        /* for service mode on - always allow this */
411        rc = RC_OK;
412        break;
413
414    case SERVICE_MODE_OFF:
415        /* cannot leave service mode when RX queue is active */
416        if (rx_core->get_rx_port_mngr(m_port_id).is_feature_set(RXPortManager::QUEUE)) {
417            rc = RC_FAIL_RX_QUEUE_ACTIVE;
418            break;
419        }
420
421        /* cannot leave service mode if PCAP capturing is active */
422        if (TrexStatelessCaptureMngr::getInstance().is_active(m_port_id)) {
423            rc = RC_FAIL_CAPTURE_ACTIVE;
424            break;
425        }
426
427        break;
428
429    default:
430        assert(0);
431        break;
432
433    }
434
435    m_reply.set_reply(rc);
436
437    return true;
438}
439