diff options
Diffstat (limited to 'src/bp_sim.cpp')
-rwxr-xr-x | src/bp_sim.cpp | 367 |
1 files changed, 247 insertions, 120 deletions
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index 0e3aa2ae..f9cb3220 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -3570,106 +3570,71 @@ void CNodeGenerator::dump_json(std::string & json){ } -int CNodeGenerator::flush_file(dsec_t max_time, - dsec_t d_time, - bool always, - CFlowGenListPerThread * thread, - double &old_offset){ - CGenNode * node; - dsec_t flush_time=now_sec(); - dsec_t offset=0.0; - dsec_t n_time; - if (always) { - offset=old_offset; - } - uint32_t events=0; - bool done=false; - - thread->m_cpu_dp_u.start_work(); +void CNodeGenerator::add_exit_node(CFlowGenListPerThread * thread, + dsec_t max_time){ - /** - * if a positive value was given to max time - * schedule an exit node - */ - if ( (max_time > 0) && (!always) ) { + if ( max_time > 0 ) { CGenNode *exit_node = thread->create_node(); - exit_node->m_type = CGenNode::EXIT_SCHED; exit_node->m_time = max_time; add_node(exit_node); } +} - while (true) { - - node = m_p_queue.top(); - n_time = node->m_time + offset; - - events++; -/*#ifdef VALG - if (events > 1 ) { - CALLGRIND_START_INSTRUMENTATION; - } -#endif*/ - - if ( likely ( m_is_realtime ) ){ - dsec_t dt ; - thread->m_cpu_dp_u.commit(); - - while ( true ) { - dt = now_sec() - n_time ; +inline bool CNodeGenerator::handle_stl_node(CGenNode * node, + CFlowGenListPerThread * thread){ + uint8_t type=node->m_type; - if (dt> (-0.00003)) { - break; - } + if ( likely( type == CGenNode::STATELESS_PKT ) ) { + m_p_queue.pop(); + CGenNodeStateless *node_sl = (CGenNodeStateless *)node; + /* if the stream has been deactivated - end */ + if ( unlikely( node_sl->is_mask_for_free() ) ) { + thread->free_node(node); + } else { + /* count before handle - node might be destroyed */ + #ifdef TREX_SIM + update_stl_stats(node_sl); + #endif - rte_pause(); - } - thread->m_cpu_dp_u.start_work(); + node_sl->handle(thread); - /* add offset in case of faliures more than 100usec */ - if ( unlikely( dt > 0.000100 ) ) { - offset += dt; - } - /* update histogram */ - if ( unlikely( events % 16 ) ==0 ) { - m_realtime_his.Add(dt); - } - /* flush evey 10 usec */ - if ( now_sec() - flush_time > 0.00001 ){ - m_v_if->flush_tx_queue(); - flush_time=now_sec(); + #ifdef TREX_SIM + if (has_limit_reached()) { + thread->m_stateless_dp_info.stop_traffic(node_sl->get_port_id(), false, 0); } + #endif } + return (true); + } + return(false); +} - uint8_t type=node->m_type; - - if ( type == CGenNode::STATELESS_PKT ) { - m_p_queue.pop(); - CGenNodeStateless *node_sl = (CGenNodeStateless *)node; - - /* if the stream has been deactivated - end */ - if ( unlikely( node_sl->is_mask_for_free() ) ) { - thread->free_node(node); - } else { +inline bool CNodeGenerator::do_work_stl(CGenNode * node, + CFlowGenListPerThread * thread, + bool always){ - /* count before handle - node might be destroyed */ - #ifdef TREX_SIM - update_stl_stats(node_sl); - #endif + if ( handle_stl_node(node,thread)){ + return (false); + }else{ + return (handle_slow_messages(node->m_type,node,thread,always)); + } +} - node_sl->handle(thread); +inline bool CNodeGenerator::do_work_both(CGenNode * node, + CFlowGenListPerThread * thread, + dsec_t d_time, + bool always + ){ - #ifdef TREX_SIM - if (has_limit_reached()) { - thread->m_stateless_dp_info.stop_traffic(node_sl->get_port_id(), false, 0); - } - #endif + bool exit_scheduler=false; + uint8_t type=node->m_type; + bool done; - } - - - } else if ( likely( type == CGenNode::FLOW_PKT ) ) { + if ( handle_stl_node (node,thread) ){ + }else{ + if ( likely( type == CGenNode::FLOW_PKT ) ) { /* PKT */ if ( !(node->is_repeat_flow()) || (always==false)) { flush_one_node_to_file(node); @@ -3682,45 +3647,91 @@ int CNodeGenerator::flush_file(dsec_t max_time, if ((node->is_repeat_flow()) && (always==false)) { /* Flow is repeated, reschedule it */ thread->reschedule_flow( node); - } else { + }else{ /* Flow will not be repeated, so free node */ thread->free_last_flow_node( node); } - } else { + }else{ node->update_next_pkt_in_flow(); m_p_queue.push(node); } - } else if ((type == CGenNode::FLOW_FIF)) { - /* callback to our method */ - m_p_queue.pop(); - if ( always == false) { - thread->m_cur_time_sec = node->m_time ; + }else{ + if ((type == CGenNode::FLOW_FIF)) { + /* callback to our method */ + m_p_queue.pop(); + if ( always == false) { + thread->m_cur_time_sec = node->m_time ; - if ( thread->generate_flows_roundrobin(&done) <0){ - break; - } - if (!done) { - node->m_time +=d_time; - m_p_queue.push(node); - } else { + thread->generate_flows_roundrobin(&done); + + if (!done) { + node->m_time +=d_time; + m_p_queue.push(node); + }else{ + thread->free_node(node); + } + }else{ thread->free_node(node); } - } else { - thread->free_node(node); - } - } else { - bool exit_sccheduler = handle_slow_messages(type,node,thread,always); - if (exit_sccheduler) { - break; + }else{ + exit_scheduler = handle_slow_messages(type,node,thread,always); } } } + return (exit_scheduler); +} + + + +template<int SCH_MODE> +inline bool CNodeGenerator::do_work(CGenNode * node, + CFlowGenListPerThread * thread, + dsec_t d_time, + bool always + ){ + /* template filter in compile time */ + if ( SCH_MODE == smSTATELESS ) { + return ( do_work_stl(node,thread,always) ); + }else{ + /* smSTATEFUL */ + return ( do_work_both(node,thread,d_time,always) ); + } +} + + +inline void CNodeGenerator::do_sleep(dsec_t & cur_time, + CFlowGenListPerThread * thread, + dsec_t n_time){ + thread->m_cpu_dp_u.commit1(); + dsec_t dt; + + /* TBD make this better using calculation, minimum now_sec() */ + while ( true ) { + cur_time = now_sec(); + dt = cur_time - n_time ; + + if (dt> WAIT_WINDOW_SIZE ) { + break; + } + + rte_pause(); + } + + thread->m_cpu_dp_u.start_work1(); +} + + +inline int CNodeGenerator::teardown(CFlowGenListPerThread * thread, + bool always, + double &old_offset, + double offset){ + /* to do */ if ( thread->is_terminated_by_master() ) { return (0); } - + if (!always) { old_offset =offset; }else{ @@ -3729,6 +3740,122 @@ int CNodeGenerator::flush_file(dsec_t max_time, } return (0); } + + + +template<int SCH_MODE> +inline int CNodeGenerator::flush_file_realtime(dsec_t max_time, + dsec_t d_time, + bool always, + CFlowGenListPerThread * thread, + double &old_offset){ + CGenNode * node; + dsec_t offset=0.0; + dsec_t cur_time; + dsec_t n_time; + if (always) { + offset=old_offset; + }else{ + add_exit_node(thread,max_time); + } + + thread->m_cpu_dp_u.start_work1(); + + sch_state_t state = scINIT; + node = m_p_queue.top(); + n_time = node->m_time + offset; + cur_time = now_sec(); + + while (state!=scTERMINATE) { + + switch (state) { + case scINIT: + cur_time = now_sec(); + { + dsec_t dt = cur_time - n_time ; + if (dt>0) { + state=scWORK; + if (dt > BURST_OFFSET_DTIME) { + offset += dt; + } + }else{ + state=scWAIT; + } + } ; + break; + case scWORK: + do { + bool s=do_work<SCH_MODE>(node,thread,d_time,always); + if (s) { // can we remove this IF ? + state=scTERMINATE; + break; + } + node = m_p_queue.top(); + n_time = node->m_time + offset; + + if ((n_time-cur_time)>EAT_WINDOW_DTIME) { + state=scINIT; + break; + } + } while ( true ); + break; + + case scWAIT: + do_sleep(cur_time,thread,n_time); // estimate loop + state=scWORK; + break; + default: + assert(0); + } /* switch */ + }/* while*/ + + return (teardown(thread,always,old_offset,offset)); +} + +FORCE_NO_INLINE int CNodeGenerator::flush_file_sim(dsec_t max_time, + dsec_t d_time, + bool always, + CFlowGenListPerThread * thread, + double &old_offset){ + CGenNode * node; + + if (!always) { + add_exit_node(thread,max_time); + } + + while (true) { + node = m_p_queue.top(); + + bool do_exit; + if ( get_is_stateless() ) { + do_exit=do_work<smSTATELESS>(node,thread,d_time,always); + }else{ + do_exit=do_work<smSTATEFUL>(node,thread,d_time,always); + } + if ( do_exit ){ + break; + } + } + return (teardown(thread,always,old_offset,0)); +} + +int CNodeGenerator::flush_file(dsec_t max_time, + dsec_t d_time, + bool always, + CFlowGenListPerThread * thread, + double &old_offset){ + #ifdef TREX_SIM + return ( flush_file_sim(max_time, d_time,always,thread,old_offset) ); + #else + if ( get_is_stateless() ) { + return ( flush_file_realtime<smSTATELESS>(max_time, d_time,always,thread,old_offset) ); + }else{ + return ( flush_file_realtime<smSTATEFUL>(max_time, d_time,always,thread,old_offset) ); + } + + #endif +} + void CNodeGenerator::handle_flow_pkt(CGenNode *node, CFlowGenListPerThread *thread) { @@ -4133,8 +4260,6 @@ void CFlowGenListPerThread::check_msgs(void) { } } -//void delay(int msec); - void CFlowGenListPerThread::start_stateless_simulation_file(std::string erf_file_name, @@ -4851,21 +4976,25 @@ int CErfIFStl::update_mac_addr_from_global_cfg(pkt_dir_t dir, uint8_t * p){ int CErfIFStl::send_sl_node(CGenNodeStateless *node_sl) { pkt_dir_t dir=(pkt_dir_t)node_sl->get_mbuf_cache_dir(); - /* check that we have mbuf */ - rte_mbuf_t * m=node_sl->get_cache_mbuf(); - if (m) { - /* cache packet */ - fill_raw_packet(m, (CGenNode*)node_sl, dir); - /* can't free the m, it is cached*/ + rte_mbuf_t * m; + if ( likely(node_sl->is_cache_mbuf_array()) ) { + m=node_sl->cache_mbuf_array_get_cur(); + fill_raw_packet(m,(CGenNode *)node_sl,dir); }else{ + m=node_sl->get_cache_mbuf(); + if (m) { + /* cache packet */ + fill_raw_packet(m,(CGenNode *)node_sl,dir); + /* can't free the m, it is cached*/ + }else{ - m=node_sl->alloc_node_with_vm(); - assert(m); - fill_raw_packet(m, (CGenNode*)node_sl, dir); - rte_pktmbuf_free(m); - + m=node_sl->alloc_node_with_vm(); + assert(m); + fill_raw_packet(m,(CGenNode *)node_sl,dir); + rte_pktmbuf_free(m); + } } - + /* check that we have mbuf */ int rc = write_pkt(m_raw); BP_ASSERT(rc == 0); @@ -4903,9 +5032,7 @@ int CErfIFStl::send_node(CGenNode * _no_to_use){ default: assert(0); } - } - return (0); } |