/** * register a monitor * this function is thread safe * */ void TrexWatchDog::register_monitor(TrexMonitor *monitor) { if (!m_enable){ return; } /* critical section start */ std::unique_lock<std::mutex> lock(m_lock); /* sanity - not a must but why not... */ for (int i = 0; i < m_mon_count; i++) { if ( (monitor == m_monitors[i]) || (m_monitors[i]->get_tid() == pthread_self()) ) { std::stringstream ss; ss << "WATCHDOG: double register detected\n\n" << Backtrace(); throw TrexException(ss.str()); } } /* check capacity */ if (m_mon_count == MAX_MONITORS) { std::stringstream ss; ss << "WATCHDOG: too many registered monitors\n\n" << Backtrace(); throw TrexException(ss.str()); } /* add monitor */ m_monitors[m_mon_count++] = monitor; /* critical section end */ lock.unlock(); }
bool TrexDpPortEvent::on_core_reporting_in(int thread_id, bool status) { /* mark sure no double signal */ if (m_signal.at(thread_id)) { std::stringstream err; err << "double signal detected on event id: " << m_event_id; throw TrexException(err.str()); } /* mark */ m_signal.at(thread_id) = true; m_pending_cnt--; /* if any core reported an error - mark as a failure */ if (!status) { on_error(thread_id); } /* event occured */ if (m_pending_cnt == 0) { on_event(); return true; } else { return false; } }
/** * split a specific stream's VM to multiple cores * number of cores is implied by the size of the vector * */ void TrexVmSplitter::split(TrexStream *stream, std::vector<TrexStream *> core_streams) { /* nothing to do if no VM */ if (stream->m_vm.is_vm_empty()) { return; } /* prepare some vars */ m_dp_core_count = core_streams.size(); m_core_streams = &core_streams; m_stream = stream; uint16_t cache_size=m_stream->m_cache_size; /* split the cache_size */ if (cache_size>0) { /* TBD need to check if we need to it is not too big from pool */ if (cache_size > 10000) { throw TrexException("Cache is too big try to reduce it "); } /* split like variable splitters with leftovers */ uint16_t cache_per_core = cache_size/m_dp_core_count; uint16_t leftover = cache_size % m_dp_core_count; if (cache_per_core<1) { cache_per_core=1; leftover=0; } for (TrexStream *core_stream : *m_core_streams) { core_stream->m_cache_size = cache_per_core; if (leftover) { core_stream->m_cache_size+=1; leftover-=1; } } } /* if we cannot split - compile the main and duplicate */ bool rc = split_internal(); if (!rc) { /* compile the stream and simply clone it to all streams */ m_stream->vm_compile(); /* for every core - simply clone the DP object */ for (TrexStream *core_stream : *m_core_streams) { core_stream->m_vm_dp = m_stream->m_vm_dp->clone(); } /* no need for the reference stream DP object */ delete m_stream->m_vm_dp; m_stream->m_vm_dp = NULL; } }
void TrexDpPortEvents::destroy_event(int event_id) { TrexDpPortEvent *event = lookup(event_id); if (!event) { /* cannot find event */ throw TrexException("internal error - cannot find event"); } m_events.erase(event_id); delete event; }
void TrexWatchDog::start() { if (!m_enable){ return ; } m_active = true; m_thread = new std::thread(&TrexWatchDog::_main, this); if (!m_thread) { throw TrexException("unable to create watchdog thread"); } }
/** * for a single root we can until done or a loop detected * * @author imarom (24-Nov-15) * * @param root_stream_id */ void TrexStreamsGraph::generate_graph_for_one_root(uint32_t root_stream_id) { std::unordered_map<uint32_t, bool> loop_hash; std::stringstream ss; uint32_t stream_id = root_stream_id; double offset = 0; while (true) { const TrexStream *stream; /* fetch the stream from the hash - if it is not present, report an error */ try { stream = m_streams_hash.at(stream_id); } catch (const std::out_of_range &e) { ss << "stream id " << stream_id << " does not exists"; throw TrexException(ss.str()); } /* add the node to the hash for loop detection */ loop_hash[stream_id] = true; /* create the right rate events for the stream */ add_rate_events_for_stream(offset, stream); /* do we have a next stream ? */ if (stream->m_next_stream_id == -1) { break; } /* loop detection */ auto search = loop_hash.find(stream->m_next_stream_id); if (search != loop_hash.end()) { m_graph_obj->on_loop_detection(); break; } /* handle the next one */ stream_id = stream->m_next_stream_id; } }
bool TrexVmSplitter::split_internal() { const StreamVmInstructionVar *split_instr = m_stream->m_vm.get_split_instruction(); /* if no split instruction was specified - fall back*/ if (split_instr == NULL) { return false; } if (split_instr->get_instruction_type() == StreamVmInstruction::itFLOW_MAN) { return split_by_flow_var( (const StreamVmInstructionFlowMan *)split_instr ); } else if (split_instr->get_instruction_type() == StreamVmInstruction::itFLOW_CLIENT) { return split_by_flow_client_var( (const StreamVmInstructionFlowClient *)split_instr ); } else { throw TrexException("VM splitter : cannot split by instruction which is not flow var or flow client var"); } }
void TrexStreamsCompiler::err(const std::string &err) { throw TrexException("*** error: " + err); }
void StreamVm::err(const std::string &err){ throw TrexException("*** error: " + err); }