summaryrefslogtreecommitdiffstats
path: root/src/bp_sim.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bp_sim.cpp')
-rwxr-xr-xsrc/bp_sim.cpp367
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);
}