From 9eda18ac948dc35996baf81940683bd5baea9858 Mon Sep 17 00:00:00 2001 From: Hanoh Haim Date: Tue, 3 Jan 2017 17:25:18 +0200 Subject: [PATCH] add not accurate timer wheel for better performance Signed-off-by: Hanoh Haim --- .gitignore | 20 + doc/visio_drawings/tw.xlsx | Bin 25465 -> 25923 bytes .../stf/examples/stf_active_flow.py | 7 +- scripts/cfg/kiwi02_more_flows.yaml | 12 + scripts/exp/imix-0-ex.erf | Bin 67928 -> 67928 bytes scripts/exp/imix-0.erf | Bin 67928 -> 67928 bytes scripts/exp/imix_v6-0-ex.erf | Bin 70720 -> 70720 bytes scripts/exp/imix_v6-0.erf | Bin 70720 -> 70720 bytes scripts/exp/limit_single_pkt-0-ex.erf | Bin 6512 -> 6600 bytes scripts/exp/limit_single_pkt-0.erf | Bin 6512 -> 6600 bytes scripts/exp/pcap_mode1-0.erf | Bin 91456 -> 91456 bytes scripts/exp/pcap_mode2-0-ex.erf | Bin 823104 -> 823104 bytes scripts/exp/rtsp_short1-0.erf | Bin 20024 -> 20024 bytes scripts/exp/rtsp_short1_ipv6_rxcheck.erf | Bin 21560 -> 21560 bytes scripts/exp/rtsp_short1_rxcheck.erf | Bin 20912 -> 20912 bytes scripts/exp/rtsp_short1_v6-0.erf | Bin 20672 -> 20672 bytes scripts/exp/rtsp_short2-0.erf | Bin 20024 -> 20024 bytes scripts/exp/rtsp_short2_v6-0.erf | Bin 20672 -> 20672 bytes scripts/exp/rtsp_short3-0.erf | Bin 20032 -> 20032 bytes scripts/exp/rtsp_short3_v6-0.erf | Bin 20696 -> 20696 bytes scripts/exp/sip_short1-0.erf | Bin 3576 -> 3576 bytes scripts/exp/sip_short1_v6-0.erf | Bin 3880 -> 3880 bytes scripts/exp/sip_short2-0.erf | Bin 3576 -> 3576 bytes scripts/exp/sip_short2_v6-0.erf | Bin 3880 -> 3880 bytes scripts/exp/sip_short3-0.erf | Bin 3584 -> 3584 bytes scripts/exp/sip_short3_v6-0.erf | Bin 3888 -> 3888 bytes src/bp_sim.cpp | 93 ++++- src/bp_sim.h | 34 +- src/gtest/bp_timer_gtest.cpp | 460 ++++++++++++++++++++- src/h_timer.cpp | 162 ++++++++ src/h_timer.h | 74 ++++ 31 files changed, 845 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index b3c8cfee..a8fb3f8b 100644 --- a/.gitignore +++ b/.gitignore @@ -97,6 +97,26 @@ scripts/5.cap scripts/6.cap scripts/7.cap scripts/8.cap +scripts/exp/rtsp_short1-0.erf +scripts/exp/rtsp_short1_ipv6_rxcheck.erf +scripts/exp/rtsp_short1_rxcheck.erf +scripts/exp/rtsp_short1_v6-0.erf +scripts/exp/rtsp_short2-0.erf +scripts/exp/rtsp_short2_v6-0.erf +scripts/exp/rtsp_short3-0.erf +scripts/exp/rtsp_short3_v6-0.erf +scripts/exp/sip_short1-0.erf +scripts/exp/sip_short1_v6-0.erf +scripts/exp/sip_short2-0.erf +scripts/exp/sip_short2_v6-0.erf +scripts/exp/sip_short3-0.erf +scripts/exp/sip_short3_v6-0.erf +scripts/exp/imix-0.erf +scripts/exp/imix_v6-0.erf +scripts/exp/limit_single_pkt-0.erf +scripts/exp/pcap_mode1-0.erf + + diff --git a/doc/visio_drawings/tw.xlsx b/doc/visio_drawings/tw.xlsx index 2ddc86d329376c26360a287e445846113c3e2fea..31e69fe499add37ba4fa18c823ba555b9e82179f 100644 GIT binary patch delta 13684 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 I_5T_9Khc;O`v3p{ diff --git a/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py b/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py index 0a72c9ac..8560a5db 100644 --- a/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py +++ b/scripts/automation/trex_control_plane/stf/examples/stf_active_flow.py @@ -14,8 +14,8 @@ def minimal_stateful_test(server,csv_file,a_active_flows): trex_client.start_trex( c = 7, m = 30000, -# f = 'cap2/cur_flow_single.yaml', - f = 'cap2/cur_flow.yaml', + f = 'cap2/cur_flow_single.yaml', +# f = 'cap2/cur_flow.yaml', d = 30, l = 1000, p=True, @@ -39,6 +39,7 @@ def minimal_stateful_test(server,csv_file,a_active_flows): print("WARNING QUEU WAS FULL"); tuple=(active_flows[-5],cpu_utl[-5],pps[-5],queue_full[-1]) + print(tuple) file_writer = csv.writer(test_file) file_writer.writerow(tuple); @@ -58,7 +59,7 @@ if __name__ == '__main__': max_flows = 8000000; min_flows = 100; active_flow = min_flows; - num_point = 10 + num_point = 40 factor = math.exp(math.log(max_flows/min_flows,math.e)/num_point); for i in range(num_point+1): print("<<=====================>>",i,math.floor(active_flow)) diff --git a/scripts/cfg/kiwi02_more_flows.yaml b/scripts/cfg/kiwi02_more_flows.yaml index a156d4f4..42735fdb 100644 --- a/scripts/cfg/kiwi02_more_flows.yaml +++ b/scripts/cfg/kiwi02_more_flows.yaml @@ -10,6 +10,18 @@ threads : [1,2,3,4] - socket : 1 threads : [8,9,10,11] + port_info: + - dest_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + src_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + + - dest_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + src_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + + - dest_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + src_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + + - dest_mac : [0x00,0x00,0x00,0x01,0x00,0x00] + src_mac : [0x00,0x00,0x00,0x01,0x00,0x00] memory : dp_flows : 4048576 diff --git a/scripts/exp/imix-0-ex.erf b/scripts/exp/imix-0-ex.erf index 6f5f4f07a8ab6cd730e6d86f896f68810f316613..b044cb70b04262e0f770e1f16e7bcab1842ff7b6 100755 GIT binary patch delta 26 kcmV+#0OkMKk_6b21hAvvll$N;lhEKRlY2cevn=5(D91q!sQ>@~ delta 25 hcmcaHiRH#5mJN#^Ow`t$eBpuiWM>iG%^D94GytSD3z7f; diff --git a/scripts/exp/imix-0.erf b/scripts/exp/imix-0.erf index 6f5f4f07a8ab6cd730e6d86f896f68810f316613..b044cb70b04262e0f770e1f16e7bcab1842ff7b6 100644 GIT binary patch delta 26 kcmV+#0OkMKk_6b21hAvvll$N;lhEKRlY2cevn=5(D91q!sQ>@~ delta 25 hcmcaHiRH#5mJN#^Ow`t$eBpuiWM>iG%^D94GytSD3z7f; diff --git a/scripts/exp/imix_v6-0-ex.erf b/scripts/exp/imix_v6-0-ex.erf index d52d8541d992f0e1e7a32208a7614ff094241d06..589300c273c304ddfd2ceead8697fd2672032f50 100755 GIT binary patch delta 26 kcmV+#0OkL{s06^M1hD7nlMkvilN;(ZlMg^OvxMrrDYA|X!T&;pT={2Q&e)X$;T+ diff --git a/scripts/exp/imix_v6-0.erf b/scripts/exp/imix_v6-0.erf index d52d8541d992f0e1e7a32208a7614ff094241d06..589300c273c304ddfd2ceead8697fd2672032f50 100644 GIT binary patch delta 26 kcmV+#0OkL{s06^M1hD7nlMkvilN;(ZlMg^OvxMrrDYA|X!T&;pT={2Q&e)X$;T+ diff --git a/scripts/exp/limit_single_pkt-0-ex.erf b/scripts/exp/limit_single_pkt-0-ex.erf index 344a25d00bdba88dac005d6f9ff25f35114a7eb0..0ec672fa9aa59cea08ea4e9e21d56ba98b2a039b 100755 GIT binary patch delta 49 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 MdSKc@#ZSWj0fB-kAOHXW delta 2714 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 delta 30525 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 diff --git a/scripts/exp/rtsp_short1-0.erf b/scripts/exp/rtsp_short1-0.erf index d75f8f98ff193f579a762d8cd1a9ff51825155f2..990edbebed9ad03784a68be6b3e36b31f8c9eb92 100644 GIT binary patch delta 274 zcmdlnhjGUo#tj8L%+pTY-dxO6%EGKDb$9b?fvFHiv*=xB=CzskHYZE!vVa+rWkp$- zEq31Dyjro9h2?CpY|z9Q#mS*+#w?MG<$^Z%sJ&r@uxfOGtS6u3gC^$~En%IYlMuu( zIoDf$vWc+?^Xmhao3o8;S(&r1IB$M!@fO0kZTFOkWt%#`_vRyxZ&+EsoBfrPo4nUk ze)1LfE6j~imnX0G*vh)Lacz(s*q|0q6Xqlh^~t+Ezp_eic`9Qwd94Rft=AM5iQ?-( zTfIYA&Rl$KKKY3E6PBY(cUVnc%fUIijzatj9FG)c@wy~N9_$OgjJ&hWSOeG3!I!|w1o9xtX>eq z&m|TCXWAi3YsE zlXJX7SZ@9CwU~Uw`w2^6qoVcXH9jq@AcpP4Sh>l;zNXA4Sies0_6=p-Y<1iLEXeF< F3IIExZ#n<~ diff --git a/scripts/exp/rtsp_short1_ipv6_rxcheck.erf b/scripts/exp/rtsp_short1_ipv6_rxcheck.erf index 046e0a1e22af4d483e7c72bfaf4a92404ef0e0e3..a06fe3a7664fd8f4880761178d3f1617623fa020 100644 GIT binary patch delta 273 zcmdn7f^o+R#ti{{%+pTY-W<#~mxWnT>h9*xLVF>M&El*q%xg36ZQd;%3SkH<*s?HN z?7Y7@SY;~<%h_PrpvgR%H7t>f<$^Z%Xo|3bS(AG-LpJ}=KfucJr z@qfZ9QG7kf24Y))0?V0;kIgsp1d1@S99_D@YO+eu8VKV`Pzke*R?lSb;8JFd__)c3 GgG&K-=W93s delta 273 zcmdn7f^o+R#ti{{%+G(X+#Jj|mxZ~=d-dkeLVF>M&El*q%>QPs*}Pji6v7Zzuw`NH ze6@CSu*y~z7P;2ffs=VOYgkrYc@wy~M^l6i%$nSz8M66@{sC4NQrC#wXlfiSKFl`x-R{W{q@xRiOb)$z%P GgG&Jl=xjp( diff --git a/scripts/exp/rtsp_short1_rxcheck.erf b/scripts/exp/rtsp_short1_rxcheck.erf index dc195ac0c1a7d57caf40294e5bee14aa1958c264..b5f17783dbe49283c9b0c7d8290040aaabe4a008 100644 GIT binary patch delta 278 zcmdn6m~jITRq!%TJ9T?=HE%Bqv!c}9&D=t3A&lK(UzwTLX5QPpS<00K%=j&*%ff82 z^ZsUS<+&^@XM<&fCZAEyVToKU7qr<%gM|&unrx$?xH(ntF)PcHPx3*NeN6T+PtZx2 z%x#*>{Q7|9=4#WatSs4AoJ+v!OsyZYG6Q*=r5*n=v20W4_ueey!otS<-R$pXWiMVv z=EkVYla0O4vaW4h8zeWG*HnJ8ijNO-l7{-`Vjo^c7U?ZdWhS@yo?(?Jz8+))mM`)1 zVL5a0vH9d9et%ewF5O`@`H24@>zAc$;|=2tTtLbwzgo^UjlqsHR9tOAacop Fz5p@6XwU!v delta 278 zcmdn6m~jITRq!%D|Gjc^HE%BqbCLJz&D=t3A&lK(UzwTz&04d0vy>|fnDJXqmxa0W z)!NP4%5zy*o&DEw;Sy_bNYL$T1nOZ+)Wd`y#OFRB$V$s>Y#cQ*S3kw^wOUCKV%3i#T z%x*RdCL4R7W&QAZS&-ahUQ_wWDn35UJUw2Ui+y+*S)5L=%T8|bJ;R!4z#D7>mM`)1 zVY&6k*JAP!zdtO2jf&QjkND4F1u<+VpH-Ke+#KM`dV=+%T(oE;N&~Tdzc@_>P?<) z63ZO$M`H7DlU`P4;kR0wyRH6084iD$Sah~;@!H(u{D+m%fUIijzatj9FG)c@wy~N9_$OgjJ&hWSOeG3!I!|w1o9xtX>eq z&m|TCXWAi3YsE zlXJX7SZ@9CwU~Uw`w2^6qoVcXH9jq@AcpP4Sh>l;zNXA4Sies0_6=p-Y<1iLEXeF< F3IIExZ#n<~ diff --git a/scripts/exp/rtsp_short2_v6-0.erf b/scripts/exp/rtsp_short2_v6-0.erf index ba220161faf50b8d66730ee06abde675b1dc88ed..2cb322acdb6b76c0dd6fbf93cdebdb44034f973f 100644 GIT binary patch delta 250 zcmX@GknzAm#tk04%+pTY-t5iW%EGKDb$9b+!KDyJwb)x`=CzskHfKxOvVa+@%T(oE;N&~Tdzc@_>P?<) z63ZO$M`H7DlU`P4;kR0wyRH6084iD$Sah~;@!H(u{D+mwhw;E1#tjub%+pTY-dxR7%EGKDb$9b;fvFHix9DAF=CzskHfKxfvVa-0Wkp$- zEq31Dyjii8h2?CpY|vyIwGfub#d1NLr>MPQg|J$5fUGB<FAd&c>avX72uDX7V1dEvyp7*Mn>(%Nom1p5kr7 va^~V=^T}ttpRgQVy2EPn7M~Uf!^Ss+)kdqw))uUAi?0c@Mtt1l*S?_uyiaR{ delta 262 zcmX>whw;E1#tjub%+G(X++595%EDaay?XO!fvFHix9DAF=6|!+Y|fU{WdSp0%Zjov zcfMM?d9z|G3yWOq>%hr2Y9TDEuDl7{JVosdD}>de17w-1ybGLMVzh+$VXWR{Y2#4l zfIkwOi;ZhpnT6kKZT@WW7Q%RJ_mqi6XZsef&1W3nurj-3oSwYf{VS`R%>o&@$$P!z zCtvZH!u;X$vdP(=p{zVTUQ#xb_qxkZe&TtB#pwjQ?BqROTUZkfc!O;w%Nom1p5kr7 va_f(;#pE;IPgnvQ6|E<4@o9lDYmz6pDiu2~hR)3)khrdiL+tm5JH!pGi!^-^K?C<8qp1h3AjZv2; zZ}vLNy0&p`kQ~^IbKXMCNgC>#AA9pMvPf@vDl_?u&ly&U;_E>+V0k`2A(k^2ADd5B m@%zJabmqY%EDaay?XO&!KDz!WU;r*%>QPs+1xB;%K~N`mQ!V6 z?tHa&^J}HKEG%-ZuLCFdsHd>3y7DG)^B46$tWcINkY%d!E^zV}<2|eoWA%ai#2oNPVzaPmFDtX~TdmEDt^Pt84u6?gbhdBt+PuX14=b}v#_7$AJ$V_K-E0<2 z-t2Xj^~2|7L2_U-&Up(l^YnOae(cT5$l`Q@U3T&ppEIn92E4&GV0k`2A(mTzd@Uxc m`2ArCY*e(Ktl~cf!r0>tyMGSmw=E$0t_@!~y_Bx@vd; diff --git a/scripts/exp/sip_short1-0.erf b/scripts/exp/sip_short1-0.erf index ee1ddd13d5334de2a51153c4c81bf05a0e355c15..4f8f33ce4602d8cfd67da1fba5bf2a06ea22418a 100644 GIT binary patch delta 90 zcmew%{X=>~2M4nV>#xb(9HGn$7Tliv7)W>LJfCdM8Ol6i@4d;BIYU_{Xa1f(`3+|X t^AEo>lbyLjnQ!G3Po52=-)#t({254BH|uZq=8k1#zPllJ^J*SnMgZknCCdN+ delta 90 zcmew%{X=>~2M6=gx_gtmIYODm_Pm(<7)bwV|1#N{GnAR}=IhCmIYU_v3GvUE{Dw1x tS?S09$w?b}%04K8u>#xbeoTw?b}%04MX(x_gs_Ia8U%_Pm%}4W$3Hf0_IkNHgAiJ=vQpmF18S|BT67xKfyv re%zld&7I1eGHK%EW+1&ou66QjAf2V3xjC4pl#!XO`qt*tys?Y`QkWu` diff --git a/scripts/exp/sip_short2-0.erf b/scripts/exp/sip_short2-0.erf index ee1ddd13d5334de2a51153c4c81bf05a0e355c15..4f8f33ce4602d8cfd67da1fba5bf2a06ea22418a 100644 GIT binary patch delta 90 zcmew%{X=>~2M4nV>#xb(9HGn$7Tliv7)W>LJfCdM8Ol6i@4d;BIYU_{Xa1f(`3+|X t^AEo>lbyLjnQ!G3Po52=-)#t({254BH|uZq=8k1#zPllJ^J*SnMgZknCCdN+ delta 90 zcmew%{X=>~2M6=gx_gtmIYODm_Pm(<7)bwV|1#N{GnAR}=IhCmIYU_v3GvUE{Dw1x tS?S09$w?b}%04K8u>#xbeoTw?b}%04MX(x_gs_Ia8U%_Pm%}4W$3Hf0_IkNHgAiJ=vQpmF18S|BT67xKfyv re%zld&7I1eGHK%EW+1&ou66QjAf2V3xjC4pl#!XO`qt*tys?Y`QkWu` diff --git a/scripts/exp/sip_short3-0.erf b/scripts/exp/sip_short3-0.erf index 5f21788d5caa80d83092ed36a2d7a9cfddfcc231..0d6c47961a534a8bef5f06c4be308c00840b9cbb 100644 GIT binary patch delta 90 zcmZpWX^`14frD9u_1EOd9HGn$7Tliv8c28NJfG~$8Ol6i@4d;hIYU_{Xa1f(`3q+V t^AEo>lfAh@nQ!G3PhJe9-)#t({2NGDH|uW>=8k1#zPllJ^JX4jMgXEJB{cv5 delta 90 zcmZpWX^`14frEKz-Mz_^IYODm_Pm(<8c6?X|1#N`GnAR}=IhC`IYU_v3GvUE{Dm`w tS?S09$=+O{%qf#5PF@V8cgVF){tcwF^fNaHbH_3=vsK^PyqU+B5de$UBRT*8 diff --git a/scripts/exp/sip_short3_v6-0.erf b/scripts/exp/sip_short3_v6-0.erf index 35b95903177c31cd379a81b19b717188be91cfd4..321754d185acbbfe69659b354a8e82cff175fa56 100644 GIT binary patch delta 90 zcmdlWw?S@$1Shiy>#xbuoTwmF18S|BT6dxKfyv re%zm|%$>@dGHK%EZXmrwu66QfAf2V3xjCArl#!XO`qt*lys?Y`XSgE( diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp index 938d8f65..5950a80d 100755 --- a/src/bp_sim.cpp +++ b/src/bp_sim.cpp @@ -3413,7 +3413,7 @@ bool CNodeGenerator::Create(CFlowGenListPerThread * parent){ m_socket_id =0; m_realtime_his.Create(); m_last_sync_time_sec = 0; - + m_tw_level1_next_sec = 0; return(true); } @@ -3527,7 +3527,7 @@ bool CFlowGenListPerThread::Create(uint32_t thread_id, 0 , socket_id); - RC_HTW_t tw_res=m_tw.Create(TW_BUCKETS,TW_LEVELS); + RC_HTW_t tw_res=m_tw.Create(TW_BUCKETS,TW_BUCKETS_LEVEL1_DIV); if (tw_res != RC_HTW_OK){ CHTimerWheelErrorStr err(tw_res); printf("Timer wheel configuration error,please look into the manual for details \n"); @@ -3934,7 +3934,7 @@ inline bool CNodeGenerator::do_work_both(CGenNode * node, /* update bucket time */ thread->m_cur_time_sec = node->m_time; if ( ON_TERMINATE ) { - thread->m_tw.on_tick((void*)thread,tw_on_tick_per_thread_cb_always); + thread->m_tw.on_tick_level0((void*)thread,tw_on_tick_per_thread_cb_always); if ( thread->m_tw.is_any_events_left() ){ node->m_time += BUCKET_TIME_SEC; m_p_queue.push(node); @@ -3942,7 +3942,7 @@ inline bool CNodeGenerator::do_work_both(CGenNode * node, thread->free_node(node); } }else{ - thread->m_tw.on_tick((void*)thread,tw_on_tick_per_thread_cb); + thread->m_tw.on_tick_level0((void*)thread,tw_on_tick_per_thread_cb); node->m_time += BUCKET_TIME_SEC;; m_p_queue.push(node); } @@ -4058,6 +4058,7 @@ inline int CNodeGenerator::flush_file_realtime(dsec_t max_time, }else{ add_exit_node(thread,max_time); } + m_scheduler_offset = offset; thread->m_cpu_dp_u.start_work1(); @@ -4169,6 +4170,8 @@ void CNodeGenerator::handle_time_strech(CGenNode * &node, /* fix the time offset */ dsec_t dt = cur_time - n_time; offset += dt; + /* set new offset */ + m_scheduler_offset = offset; /* check if flow sync message was delayed too much */ if ( (cur_time - m_last_sync_time_sec) > SYNC_TIME_OUT ) { @@ -4242,6 +4245,59 @@ int CNodeGenerator::flush_file(dsec_t max_time, } +void CNodeGenerator::handle_batch_tw_level1(CGenNode *node, + CFlowGenListPerThread *thread, + bool &exit_scheduler, + bool on_terminate) { + + m_p_queue.pop(); + /* update bucket time */ + thread->m_cur_time_sec = node->m_time; + + bool stop_loop=false; + + while (!stop_loop) { + na_htw_state_num_t tw_state = thread->m_tw.on_tick_level1((void*)thread,tw_on_tick_per_thread_cb); + if ( (tw_state == TW_FIRST_FINISH) || (tw_state == TW_FIRST_FINISH_ANY)){ + node->m_time += BUCKET_TIME_SEC_LEVEL1; + stop_loop=true; + }else{ + switch (tw_state) { + case TW_FIRST_BATCH: + m_tw_level1_next_sec = node->m_time + BUCKET_TIME_SEC_LEVEL1; + node->m_time = now_sec()-m_scheduler_offset; /* spread if we can */ + if (m_tw_level1_next_sec+m_scheduler_offset > now_sec() ) { + stop_loop=true; + } + break; + case TW_NEXT_BATCH : + node->m_time = now_sec()-m_scheduler_offset; /* spread if we can */ + if (m_tw_level1_next_sec+m_scheduler_offset > now_sec() ) { + stop_loop=true; + } + break; + case TW_END_BATCH: + if (m_tw_level1_next_sec+m_scheduler_offset > now_sec() ) { + node->m_time = m_tw_level1_next_sec; + }else{ + node->m_time = m_tw_level1_next_sec; /* too late but we don't have anyting to do */ + } + stop_loop=true; + break; + default: + assert(0); + }; + } + } + + if ( on_terminate && + (thread->m_tw.is_any_events_left()==false) ){ + thread->free_node(node); + }else{ + m_p_queue.push(node); + } +} + void CNodeGenerator::handle_flow_pkt(CGenNode *node, CFlowGenListPerThread *thread) { @@ -4387,6 +4443,10 @@ CNodeGenerator::handle_slow_messages(uint8_t type, handle_command(node, thread, exit_scheduler); break; + case CGenNode::TW_SYNC1: + handle_batch_tw_level1(node, thread, exit_scheduler,on_terminate); + break; + default: assert(0); } @@ -4677,6 +4737,26 @@ void CFlowGenListPerThread::handle_nat_msg(CGenNodeNatInfo * msg){ } } + +void CFlowGenListPerThread::no_memory_error(){ + printf("--------\n"); + printf("\n"); + printf("\n"); + printf("ERROR, not enough flow objects, try to enlarge the number of objects in trex_cfg file or reduce the bandwidth \n"); + printf("See in the manual how to enlarge the number of objects.\n"); + printf("\n"); + printf("\n"); + printf(" Check your active flows, 'Active-flows : 6771863', If it too high reduce the multiplier \n"); + printf(" or use --active-flows directive to reduce the number of flows\n"); + printf(" If you don't have enough memory for flows you should add something like that in your config file \n"); + printf("\n"); + printf(" memory : \n"); + printf(" dp_flows : 4048576 \n"); + printf("--------\n"); + exit(1); +} + + bool CFlowGenListPerThread::check_msgs_from_rx() { if ( likely ( m_ring_from_rx->isEmpty() ) ) { return false; @@ -4825,6 +4905,11 @@ void CFlowGenListPerThread::start_generate_stateful(std::string erf_file_name, node->m_type = CGenNode::TW_SYNC; node->m_time = m_cur_time_sec + BUCKET_TIME_SEC ; m_node_gen.add_node(node); + + node= create_node() ; + node->m_type = CGenNode::TW_SYNC1; + node->m_time = m_cur_time_sec + BUCKET_TIME_SEC_LEVEL1 ; + m_node_gen.add_node(node); } diff --git a/src/bp_sim.h b/src/bp_sim.h index 9cdfd30a..4df1dcd9 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -370,6 +370,13 @@ public: #define CONST_9k_MBUF_SIZE (MAX_PKT_ALIGN_BUF_9K + MBUF_PKT_PREFIX) +#define TW_BUCKETS (CGlobalInfo::m_options.get_tw_buckets()) +#define TW_BUCKETS_LEVEL1_DIV (16) +#define TW_LEVELS (CGlobalInfo::m_options.get_tw_levels()) +#define BUCKET_TIME_SEC (CGlobalInfo::m_options.get_tw_bucket_time_in_sec()) +#define BUCKET_TIME_SEC_LEVEL1 (CGlobalInfo::m_options.get_tw_bucket_level1_time_in_sec()) + + class CPreviewMode { public: CPreviewMode(){ @@ -726,7 +733,7 @@ public: m_arp_ref_per = 120; // in seconds m_tw_buckets = 1024; m_tw_levels = 3; - m_tw_bucket_time_sec = (20.0/1000000.0); + set_tw_bucket_time_in_usec(20.0); m_active_flows=0; } @@ -775,6 +782,7 @@ public: CMacAddrCfg m_mac_addr[TREX_MAX_PORTS]; double m_tw_bucket_time_sec; + double m_tw_bucket_time_sec_level1; uint8_t * get_src_mac_addr(int if_index){ @@ -819,8 +827,13 @@ public: return (m_tw_bucket_time_sec); } + inline double get_tw_bucket_level1_time_in_sec(void){ + return (m_tw_bucket_time_sec_level1); + } + void set_tw_bucket_time_in_usec(double usec){ - m_tw_bucket_time_sec=(usec/1000000.0); + m_tw_bucket_time_sec= (usec/1000000.0); + m_tw_bucket_time_sec_level1 = (m_tw_bucket_time_sec*(double)m_tw_buckets)/((double)TW_BUCKETS_LEVEL1_DIV); } void set_tw_buckets(uint16_t buckets){ @@ -1469,7 +1482,9 @@ public: EXIT_PORT_SCHED =8, PCAP_PKT =9, GRAT_ARP =10, - TW_SYNC =11 + TW_SYNC =11, + TW_SYNC1 =12, + }; /* flags MASKS*/ @@ -2215,6 +2230,8 @@ private: void handle_flow_sync(CGenNode *node, CFlowGenListPerThread *thread, bool &exit_scheduler); void handle_pcap_pkt(CGenNode *node, CFlowGenListPerThread *thread); void handle_maintenance(CFlowGenListPerThread *thread); + void handle_batch_tw_level1(CGenNode *node, CFlowGenListPerThread *thread,bool &exit_scheduler,bool on_terminate); + public: pqueue_t m_p_queue; @@ -2226,8 +2243,10 @@ public: uint64_t m_non_active; uint64_t m_limit; CTimeHistogram m_realtime_his; + dsec_t m_scheduler_offset; dsec_t m_last_sync_time_sec; + dsec_t m_tw_level1_next_sec; }; @@ -3798,9 +3817,6 @@ private: bool server_seq_init; /* TCP seq been init for server? */ }; -#define TW_BUCKETS (CGlobalInfo::m_options.get_tw_buckets()) -#define TW_LEVELS (CGlobalInfo::m_options.get_tw_levels()) -#define BUCKET_TIME_SEC (CGlobalInfo::m_options.get_tw_bucket_time_in_sec()) @@ -3957,6 +3973,8 @@ public: private: + FORCE_NO_INLINE void no_memory_error(); + bool check_msgs_from_rx(); void handle_nat_msg(CGenNodeNatInfo * msg); @@ -4016,7 +4034,7 @@ public: public: CNodeGenerator m_node_gen; - CHTimerWheel m_tw; + CNATimerWheel m_tw; public: uint32_t m_cur_template; @@ -4051,7 +4069,7 @@ private: inline CGenNode * CFlowGenListPerThread::create_node(void){ CGenNode * res; if ( unlikely (rte_mempool_sc_get(m_node_pool, (void **)&res) <0) ){ - rte_exit(EXIT_FAILURE, "cant allocate object , need more \n"); + no_memory_error(); return (0); } return (res); diff --git a/src/gtest/bp_timer_gtest.cpp b/src/gtest/bp_timer_gtest.cpp index 07f0e214..1e8e7069 100644 --- a/src/gtest/bp_timer_gtest.cpp +++ b/src/gtest/bp_timer_gtest.cpp @@ -216,9 +216,9 @@ TEST_F(gt_r_timer, timer7) { int i; for (i=0; i<150; i++) { - printf(" tick %d :",i); + //printf(" tick %d :",i); timer.on_tick((void *)&timer,my_test_on_tick_cb7); - printf(" \n"); + //printf(" \n"); } EXPECT_EQ( timer.Delete(),RC_HTW_OK); @@ -655,4 +655,460 @@ TEST_F(gt_r_timer, timer18) { +///////////////////////////////////////////////////////////////// +/* test for NA class */ + +class CNATimerWheelTest1Cfg { +public: + uint32_t m_wheel_size; + uint32_t m_level1_div; + uint32_t m_start_tick; + uint32_t m_restart_tick; + uint32_t m_total_ticks; + int m_verbose; + bool m_dont_assert; +}; + + +class CNATimerWheelTest1 : public CHTimerWheelBase { + +public: + bool Create(CNATimerWheelTest1Cfg & cfg); + void Delete(); + void start_test(); + virtual void on_tick(CMyTestObject *lpobj); + +private: + CNATimerWheelTest1Cfg m_cfg; + CNATimerWheel m_timer; + CMyTestObject m_event; + uint32_t m_ticks; + uint32_t m_total_ticks; + uint32_t m_expected_total_ticks; + uint32_t m_div_err; + + uint32_t m_expect_tick; + double m_max_err; +}; + +void my_test_on_tick_cb18(void *userdata,CHTimerObj *tmr){ + CHTimerWheelBase * lp=(CHTimerWheelBase *)userdata; + UNSAFE_CONTAINER_OF_PUSH + CMyTestObject *lpobj=(CMyTestObject *)((uint8_t*)tmr-offsetof (CMyTestObject,m_timer)); + UNSAFE_CONTAINER_OF_POP + lp->on_tick(lpobj); +} + + +void CNATimerWheelTest1::on_tick(CMyTestObject *lpobj){ + assert(lpobj->m_id==17); + m_total_ticks++; + if (m_cfg.m_verbose) { + printf(" [event(%d)-%d]",lpobj->m_timer.m_wheel,lpobj->m_id); + } + if (!m_cfg.m_dont_assert){ + uint32_t expect_min=m_expect_tick; + if (expect_min>m_div_err) { + expect_min-=m_div_err*2; + } + double pre=abs(100.0-100.0*(double)m_ticks/(double)m_expect_tick); + if (pre>m_max_err){ + m_max_err=pre; + } + if (pre>(200.0/(double)m_div_err)) { + printf(" =====>tick:%d expect [%d -%d] %f \n",m_ticks,expect_min,m_expect_tick+(m_div_err*2),pre); + } + } + m_timer.timer_start(&lpobj->m_timer,m_cfg.m_restart_tick); + m_expect_tick+=m_cfg.m_restart_tick; +} + + +void CNATimerWheelTest1::start_test(){ + + if (m_cfg.m_verbose) { + printf(" test start %d,restart: %d \n",m_cfg.m_start_tick,m_cfg.m_restart_tick); + } + int i; + m_expected_total_ticks=0; + uint32_t cnt=m_cfg.m_start_tick; + for (i=0; i=m_div_err) && (i%m_div_err==0)) { + int cnt_rerty=0; + while (true){ + if (m_cfg.m_verbose>1) { + printf("\n level1 - try %d \n",cnt_rerty); + } + + na_htw_state_num_t state; + state = m_timer.on_tick_level1((void *)this,my_test_on_tick_cb18); + if (m_cfg.m_verbose>1) { + printf("\n state - %lu \n",(ulong)state); + } + + if ( state !=TW_NEXT_BATCH){ + break; + } + cnt_rerty++; + } + if (m_cfg.m_verbose>1) { + printf("\n level1 - stop %d \n",cnt_rerty); + } + } + if (m_cfg.m_verbose) { + printf(" \n"); + } + } + if (m_cfg.m_verbose) { + printf(" %d == %d \n",m_expected_total_ticks,m_total_ticks); + } + if (!m_cfg.m_dont_assert){ + //assert( (m_expected_total_ticks==m_total_ticks) || ((m_expected_total_ticks+1) ==m_total_ticks) ); + } +} + + +bool CNATimerWheelTest1::Create(CNATimerWheelTest1Cfg & cfg){ + m_cfg = cfg; + m_max_err=0.0; + assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_level1_div)==RC_HTW_OK); + m_ticks=0; + return (true); +} + +void CNATimerWheelTest1::Delete(){ + //printf (" %f \n",m_max_err); + assert(m_timer.Delete()==RC_HTW_OK); +} + + +TEST_F(gt_r_timer, timer20) { + + CNATimerWheelTest1 test; + + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_start_tick = 2, + .m_restart_tick = 2, + .m_total_ticks = 1024, + .m_verbose=0 + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} + +TEST_F(gt_r_timer, timer21) { + + CNATimerWheelTest1 test; + + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_start_tick = 2, + .m_restart_tick = 34, + .m_total_ticks = 100, + .m_verbose=0 + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} + + +TEST_F(gt_r_timer, timer22) { + + CNATimerWheelTest1 test; + + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_start_tick = 2, + .m_restart_tick = 55, + .m_total_ticks = 1000, + .m_verbose=0, + .m_dont_assert =0 + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} + +TEST_F(gt_r_timer, timer23) { + + int i,j; + + for (i=0; i<100; i++) { + for (j=1; j<100; j++) { + CNATimerWheelTest1 test; + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_start_tick = (uint32_t)i, + .m_restart_tick = (uint32_t)j, + .m_total_ticks = 1000, + .m_verbose=0, + .m_dont_assert =0 + }; + + cfg.m_total_ticks= (uint32_t)(i*2+j*10); + test.Create(cfg); + test.start_test(); + test.Delete(); + } + } +} + + + +#if 0 +// too long, skip for now +TEST_F(gt_r_timer, timer24) { + + int i,j; + + for (i=0; i<2048; i++) { + printf(" %d \n",i); + for (j=1024; j<2048; j=j+7) { + CNATimerWheelTest1 test; + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 1024, + .m_level1_div = 32, + .m_start_tick = (uint32_t)i, + .m_restart_tick = (uint32_t)j, + .m_total_ticks = 3000, + .m_verbose=0, + .m_dont_assert =0 + }; + + cfg.m_total_ticks= (uint32_t)(i*2+j*10); + test.Create(cfg); + test.start_test(); + test.Delete(); + } + } +} +#endif + +/* very long flow, need to restart it */ +TEST_F(gt_r_timer, timer25) { + + + CNATimerWheelTest1 test; + + CNATimerWheelTest1Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_start_tick = 2, + .m_restart_tick = 512, + .m_total_ticks = 1000, + .m_verbose=0, + .m_dont_assert =0 + }; + + test.Create(cfg); + test.start_test(); + test.Delete(); +} + + + +//////////////////////////////////////////////////////// + +class CNATimerWheelTest2Cfg { +public: + uint32_t m_wheel_size; + uint32_t m_level1_div; + uint32_t m_number_of_con_event; + uint32_t m_total_ticks; + bool m_random; + bool m_burst; + int m_verbose; + bool m_dont_check; +}; + +class CNATimerWheelTest2 : public CHTimerWheelBase { + +public: + bool Create(CNATimerWheelTest2Cfg & cfg); + void Delete(); + void start_test(); + virtual void on_tick(CMyTestObject *lpobj); + +private: + CNATimerWheelTest2Cfg m_cfg; + CNATimerWheel m_timer; + uint32_t m_ticks; + uint32_t m_div_err; +}; + +bool CNATimerWheelTest2::Create(CNATimerWheelTest2Cfg & cfg){ + m_cfg = cfg; + assert(m_timer.Create(m_cfg.m_wheel_size,m_cfg.m_level1_div)==RC_HTW_OK); + m_ticks=0; + return (true); +} + +void CNATimerWheelTest2::Delete(){ + assert(m_timer.Delete()==RC_HTW_OK); +} + + +void CNATimerWheelTest2::start_test(){ + + CMyTestObject * m_events = new CMyTestObject[m_cfg.m_number_of_con_event]; + int i; + for (i=0; im_id=i+1; + if (m_cfg.m_random) { + lp->m_d_tick = ((rand() % m_cfg.m_number_of_con_event)+1); + if (m_cfg.m_verbose) { + printf(" flow %d : %d \n",i,lp->m_d_tick); + } + }else{ + if (m_cfg.m_burst){ + lp->m_d_tick = m_cfg.m_wheel_size*2; /* all in the same bucket */ + }else{ + lp->m_d_tick=i+1; + } + } + lp->m_t_tick=lp->m_d_tick; + m_timer.timer_start(&lp->m_timer,lp->m_d_tick); + } + + m_div_err =m_cfg.m_wheel_size/m_cfg.m_level1_div; + + for (i=0; i=m_div_err) && (i%m_div_err==0)) { + int cnt_rerty=0; + while (true){ + if (m_cfg.m_verbose>1) { + printf("\n level1 - try %d \n",cnt_rerty); + } + + na_htw_state_num_t state; + state = m_timer.on_tick_level1((void *)this,my_test_on_tick_cb18); + if (m_cfg.m_verbose>1) { + printf("\n state - %lu \n",(ulong)state); + } + + if ( state !=TW_NEXT_BATCH){ + break; + } + + cnt_rerty++; + } + if (m_cfg.m_verbose>1) { + printf("\n level1 - stop %d \n",cnt_rerty); + } + } + + + if (m_cfg.m_verbose) { + printf(" \n"); + } + } + delete []m_events; +} + + +void CNATimerWheelTest2::on_tick(CMyTestObject *lp){ + + if (!m_cfg.m_random && !m_cfg.m_burst) { + assert(lp->m_id==lp->m_d_tick); + } + if (m_cfg.m_verbose) { + printf(" [event %d ]",lp->m_id); + } + m_timer.timer_start(&lp->m_timer,lp->m_d_tick); + if (!m_cfg.m_dont_check){ + double pre=abs(100.0-100.0*(double)m_ticks/(double)lp->m_t_tick); + if (pre>(200.0/(double)m_div_err)) { + printf(" =====>tick:%d %f \n",m_ticks,pre); + assert(0); + } + } + lp->m_t_tick+=lp->m_d_tick; +} + + +TEST_F(gt_r_timer, timer30) { + + CNATimerWheelTest2 test; + CNATimerWheelTest2Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_number_of_con_event = 100, + .m_total_ticks =1000, + .m_random=false, + .m_burst=false, + .m_verbose =false + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} + +TEST_F(gt_r_timer, timer31) { + + CNATimerWheelTest2 test; + CNATimerWheelTest2Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_number_of_con_event = 500, + .m_total_ticks =5000, + .m_random=true, + .m_burst=false, + .m_verbose =false + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} + +TEST_F(gt_r_timer, timer32) { + + CNATimerWheelTest2 test; + CNATimerWheelTest2Cfg cfg ={ + .m_wheel_size = 32, + .m_level1_div = 4, + .m_number_of_con_event = 500, + .m_total_ticks =100, + .m_random=false, + .m_burst=true, + .m_verbose =0 + }; + test.Create(cfg); + test.start_test(); + test.Delete(); +} diff --git a/src/h_timer.cpp b/src/h_timer.cpp index b3d86d46..4e52c3d2 100644 --- a/src/h_timer.cpp +++ b/src/h_timer.cpp @@ -266,6 +266,168 @@ RC_HTW_t CHTimerWheel::Delete(){ return(RC_HTW_OK); } +//////////////////////////////////////////////////////// + + + +void CNATimerWheel::detach_all(void *userdata,htw_on_tick_cb_t cb){ + #ifndef _DEBUG + if (m_total_events==0) { + return; + } + #endif + int i; + uint32_t res=0; + for (i=0;idetach_all(userdata,cb); + assert(m_total_events>=res); + m_total_events -=res; + } + assert(m_total_events==0); +} + + +void CNATimerWheel::on_tick_level0(void *userdata,htw_on_tick_cb_t cb){ + + CHTimerOneWheel * lp=&m_timer_w[0]; + CHTimerObj * event; + + while ( true ) { + event = lp->pop_event(); + if (!event) { + break; + } + m_total_events--; + cb(userdata,event); + } + lp->timer_tick(); + m_ticks[0]++; +} + +/* almost always we will have burst here */ +na_htw_state_num_t CNATimerWheel::on_tick_level1(void *userdata,htw_on_tick_cb_t cb){ + + CHTimerOneWheel * lp=&m_timer_w[1]; + CHTimerObj * event; + uint32_t cnt=0; + + while ( true ) { + event = lp->pop_event(); + if (!event) { + break; + } + if (event->m_ticks_left==0) { + m_total_events--; + cb(userdata,event); + }else{ + timer_start_rest(event,event->m_ticks_left); + } + cnt++; + if (cnt>HNA_MAX_LEVEL1_EVENTS) { + /* need another batch */ + na_htw_state_num_t old_state; + old_state=m_state; + m_state=TW_NEXT_BATCH; + if (old_state ==TW_FIRST_FINISH){ + return(TW_FIRST_BATCH); + }else{ + return(TW_NEXT_BATCH); + } + } + } + lp->timer_tick(); + m_ticks[1]++; + if (m_state==TW_FIRST_FINISH) { + if (cnt>0) { + return (TW_FIRST_FINISH_ANY); + }else{ + return (TW_FIRST_FINISH); + } + }else{ + assert(m_state==TW_NEXT_BATCH); + m_state=TW_FIRST_FINISH; + return(TW_END_BATCH); + } +} + + + +RC_HTW_t CNATimerWheel::timer_stop (CHTimerObj *tmr){ + if ( tmr->is_running() ) { + assert(tmr->m_wheelm_wheel].timer_stop(tmr); + m_total_events--; + } + return (RC_HTW_OK); +} + + + +RC_HTW_t CNATimerWheel::timer_start_rest(CHTimerObj *tmr, + htw_ticks_t ticks){ + + htw_ticks_t nticks = (ticks+m_wheel_level1_err)>>m_wheel_level1_shift; + if (nticksm_ticks_left=0; + tmr->m_wheel=1; + m_timer_w[1].timer_start(tmr,nticks-1); + }else{ + tmr->m_ticks_left = ticks - ((m_wheel_size-1)<m_wheel=1; + m_timer_w[1].timer_start(tmr,m_wheel_size-1); + } + return (RC_HTW_OK); +} + + +void CNATimerWheel::reset(){ + m_wheel_shift=0; + m_total_events=0; + m_wheel_size=0; + m_wheel_mask=0; + m_wheel_level1_shift=0; + m_wheel_level1_err=0; + m_state=TW_FIRST_FINISH; + int i; + for (i=0; iutl_log2_shift((uint32_t)level1_div)); + + return(RC_HTW_OK); +} + +RC_HTW_t CNATimerWheel::Delete(){ + int i; + for (i=0; im_ticks_left=0; + tmr->m_wheel=0; + return (m_timer_w[0].timer_start(tmr,ticks)); + } + return ( timer_start_rest(tmr, ticks)); + } + + RC_HTW_t timer_stop (CHTimerObj *tmr); + + void on_tick_level0(void *userdata,htw_on_tick_cb_t cb); + + na_htw_state_num_t on_tick_level1(void *userdata,htw_on_tick_cb_t cb); + + bool is_any_events_left(){ + return(m_total_events>0?true:false); + } + + /* iterate all, detach and call the callback */ + void detach_all(void *userdata,htw_on_tick_cb_t cb); + + +private: + void reset(void); + + RC_HTW_t timer_start_rest(CHTimerObj *tmr, + htw_ticks_t ticks); + +private: + htw_ticks_t m_ticks[HNA_TIMER_LEVELS]; + uint32_t m_wheel_size; //e.g. 256 + uint32_t m_wheel_mask; //e.g 256-1 + uint32_t m_wheel_shift; // e.g 8 + uint32_t m_wheel_level1_shift; //e.g 16 + uint32_t m_wheel_level1_err; //e.g 16 + + uint64_t m_total_events; + CHTimerOneWheel m_timer_w[HNA_TIMER_LEVELS]; + na_htw_state_num_t m_state; +} ; + + #endif -- 2.16.6