From fda47173d794b9730ac2e7069bb7315d3000309e Mon Sep 17 00:00:00 2001 From: Ido Barnea Date: Thu, 13 Oct 2016 17:06:45 +0300 Subject: [PATCH] Adding documentation for ARP feature + major fixes to stateful and getting started Signed-off-by: Ido Barnea --- images/trex-asr-setup.png | Bin 0 -> 42119 bytes images/trex-not-supported-setup.png | Bin 0 -> 59543 bytes release_notes.asciidoc | 7 +- trex_book.asciidoc | 760 ++++++++++++++++++------------------ trex_book_basic.asciidoc | 152 +++----- trex_config.asciidoc | 221 +++++------ trex_faq.asciidoc | 20 +- trex_preso.asciidoc | 5 +- 8 files changed, 569 insertions(+), 596 deletions(-) create mode 100644 images/trex-asr-setup.png create mode 100644 images/trex-not-supported-setup.png diff --git a/images/trex-asr-setup.png b/images/trex-asr-setup.png new file mode 100644 index 0000000000000000000000000000000000000000..3cc89d765ec0ed4b09f467f9bdd6b5c9a46ec14c GIT binary patch literal 42119 zcmcfpbySsI_XP|Ck^)jncS@IZ3(_G-cM8(oEg{_{CDPs9UD6=k-60_ozWY44&vX0x z#`ykxU&nDMjB}l9Upv;CYtFe&$Xj^{)Tj7Qp`f5pr6k3aprByJp`f4>5aGdZX6gD? zz(3FqN)oT3%0>zI!4F8bk{S+BP>Ax7ztG{VP)ATu!cbCTBFe7NN9hQj%DvcqXt0O@ zP+3Xn?&ah#`rq5|usiJdBrQ9P2{=%v%e^olgT^HN>vi@?*gY!er5FsQ z@L#VlNaMac2!61VzW=^jNQIv)Age#8`s->^X#DYelxQfVe_y^hux7#@&|zQy&j$)W z`JDNGuERX@he9=D)>n-G_YUB0X2L(%{~m}ij4t{Y=wmpB(Ad9k0xtE2|9fzf9mp`R zzO?$jQT#to_XT=n?EhSctZ-Y}p78JKfhH4v!b_SwkM!3(3Y$ZIS*tA-`SGtAA|(Y=gaGTXaI%%3 z=^dLuuf`jQPC!7v zX}h!DpURKYZgQj@5XaChj6kHDuoZTS)TWo5lPc)R(uEw0V$ZsAb>iBsrv zT5^x;qnH=;sso~E0+fteb<vEPdJheKX)nrruI z|DNT1yx`1($QM~^*c;k}`uOhw^ApC@N0cD_aMxH~tX4ks^-b8;ipS{;<5)7Q=vrr) zVs=nKK!9Yc`<0_BLKn@io6~ZWCg)>1R#sM|S1DXJ8Kh}2=R;?)NYKHoU>RlY(dQ?5)>B+ag+WwY~fRs9(1zb6OrIkfwiCvO&_ z9vHM6-jY*LY=28(pDa?LZ$`iuzc9`8$`k0{vmQ=lym+`-9p+l~q^LEYi9I{Bop1H1 z@4$6ZC4J)dT=rMkr%%yRan$=>uDMB!TGU|ek}xR5_l$nNYqU2J@#Lh2d4~T=^4HZN zO?m6}XF;0`!np!P3ZnK1tl(!vn7BJZIGV`6?-2TgHd++F*^l-GRU|+^fxp*^v-$V% zpyR?^3L^wn>v_1Hbt0Jj*crJv?#aHe|ur#^|&{Y?Y^P6*%z@LLX$DRVkT=V zCMl85>vUw5Ba<}Rrc`ccZNDec7} zI0yv~7M`(6jTClcn7RFVfC}jeF0qko>t|miQE_Vr zVjM2}`|zIL-VdnJDPj3*xx%v*#a3eu*6L%EG_G={JfJxK8HGU`;vu zF(x$2IvR+KlSrphv^S0_`;<_~y9EW0P0Vyicn*R3oJXEgtl1T>*N((}4Y#H9_wAU^ z)`SGfjMx43qRj$dxO;aHY8+S>={C>X%bsouiO9Vj!bP^z<^}OLKX^=y7TdgblSqj4)97h83iKxf8k~&k`dMx%B_y$Z3+Gi}Os1^eTtB7vCH#i0apE!c} zM@_#aPpqJ9Bw$z@Fd?=Id*PP83^^vSn@vvME1;p~+Hl?ZmXcm)Lj19j&wBMm$F+#lFgVOoADccVX+_SV~^w+>U8ZzhP!yb ziPujUVM^#=$zJKzLrKtE>C>xd0u)jX3P>Ha-RZ4=XF~OOkP5?exr^lf`haLQ5K!|`T(194 za{7uO%Q3pI7jXWaWQIU?O=nx0r~m7hzHdPGuiFdEUif#U!Z5U=zVMDiwx;EO|MLIO zK>d`f<6S`JR0<;X0C1s#0g^a1RbA-h|1-*Hdsw9iXw-mvR@p{0Ob=@4VvIGp`k6A^ zD+spmTO;d0k6dfSo(}jc@pZs}XVO|DSA6sD5re!HWI5L|IF5gVF1Q^Om?-Q9N#&To zt|xVc?BWay5xIZ&k}oWSFhB!vOqeSFW=?2KL}D;gA9pq1V*Pb1Xk;)`R(@e(FQop$ zME=20sC)k(4mB>U#(ajZP`9-Sg+!3Qa~_0K$?c&8D$~(4rBY3fM#p_6n3RtQXwo2W zQR=mMDrJkKYP7i8!Qc^|DUTK$$uo=gP2GUxCw+H)yqy(HEdAEx;n&q92)m^|%F6Ng z7sJd*#)d{lxh|(GN+1ByYEp5Qr2s@6jq}kYnyM$ ztV(6tJa@>u)+;S3dpwLCLjUfOHB%V8`=yNS)WgO4a!58YG&H2-<>g&*4MHWL&X$Nu zB=Pko#Xk zU`dj$`yfLes)fSV+YeUN0`$x9Ra62_v$3LEWo_*=&x=8t1>Z8w+9Hr0`xp=`A z1r05U(`rHT_F~&)G>vCxr)GUWBu#NJLATG%X2oH9h{|HNEFnL`olc~dx$Wocg*q#G z1)+x;^68fmfg0oQc(R{`U*yT9 z9&mbG?vZg>FGYLZUGGnw?R5W$!r>p^**Hnli2P6Z`Uh68p@Gd!^s;L+MbPUt!`ZhC zAs^kRFX$*&z3)n|nKA{v7P9IF>Z}%POmX1r6!nF>-=22Yt+cqM ztNP(IydU|@=CC7cMQJl%Mde3`;uGN8fo$_UK%F~s0*ngv2Vct_9{c-vfGQ8W$2S2u zn=&8<=!q>XwAtYtwo&xofaOh!zUp-l4FApoi$*?e+<<6I;3h3{YPr@T$?@>J+~ZCA zZ={WY2>a_Jjls_x#g)aY>mkl422S(p7yRl;R;*lW*BQ&-M4W$j1@9aU}gTOMvk#B~&7_hEn{$_yjGG@Ou!Edv^LS&?P5 zqJpJ0f_v}NC&X5(`*Y>dXs#8o8dgLe539c))kwMmWLw^%r$(ZGhCu2SuNxh&r5PR_ zzrT`V#~28X9*EEFI>0k0gyAqtUmwjomEPa}ph?ybPS&Teo;AZ?Cjl6U!}+Q?-~ODg zaejZLwK=sqBeRQp1PeJm0%M&dxhL3;{1F$Z^HN~O=?h4Ue1_%;VwC&nj?upgcF{1vfQlJzbW{0?W6maQGaB@ z@nZdOH=0n1C=Nj2`BB~IOD%5IHP*`uG(0-AzCP$D=Kx9~Z-lR_h%d2HvwZEii=4J+ z$zYv7EiP}H>^JykcrO{Y8=_Mo0&QphVl8DX-VTYFvV=XxulpUn+lG1%ztwz%vp|3SF&eWU1dMEk z8>tS`wSAYMe0%X`Pn!P}YLXAIxKEC^IfBm3dLBL(^Wu+j@0#&%sw-{16?)s7aEXwE|keuZmlG2|1 zuP6l7xa3oi$EC9RoBquv!Z05qLB@UMGRULEgnTkl3H z;xeC>Yy)Mi+x5KZHb_k4!%aph=O93dv|}otP5JpfK^V%85-dv6=zkhcuUZnlP-}6w z^sCaS|5E9wOf}xo@+YYN+}}v5J$Rq@;>5C>%F`--4KPwU`GXUMiy(Lijw!btbvV=e zmlSiMPPwi?NJPZUuvNZH5)+)bbN+DfN(OmSS-)i6x9^XiB8d1@%kedu4kQvP0|L7`HtDyOswqGlW@ z;bg`#1O&|c^&Z@(@dE!WH>o6&`eGB3Qh}eU1qeu(FJ4fwe93e_pruvH`Gi8mJ8jBQ zrrr3p8+JUhoQl$@;4-;M>mVT{TB2wx(Q}^dc0oDxJH2L2!O3qBGk&#N&Q~E_4yJOI zUpI6e@>(x(&sP|Ha5fK>HiikeoprGc}|;F4I#d+8+iaXU#5R(DyoRI}Ft z=b_VewaKYixkO!2*ZbDQ@7$az44ZNCVP`a5EA8q9F>zV%dhN+%ZkY8cU`Q4$yk~V> zAe@B>07~}93mhSlk%{u@yi!@O1CMk{^xAd3f3736{+^U!{vc3cbb{jqAW>oKrGnsX zPAe1V(*ARWXud!DR-Y9n+^=p9PDXYa&>zDDHZ3v9$%{W6c1IHcb=BZ{x9 z7vPn~ZTFg>ntMlGv)-D~s4pA?x5?-6HlNd($OIl0KPSSD(B*s5$onZ3bgqbKEZ52N z02nUK-LcGB1x7ZLAxe!Z;|T+tInE&fu`cDHx{21)^`|;tLTN8JLCI0( zFfq7-&h=-bcNl^yylxy$lv{YQ&Z?FS8ykCPdJ5(A9H4@$g7@E&$%uFzqwzV+B_$<4 zUGtMC;+Oy!)l>>7IGO#)+*&oqgXzKr0;EmCJ}l~wcm_~Su}MDC+r#7>VWvq8cvHg} z?`B&{tccD5GE_!Cfil7(HjM|1ED`+P*9(B%E3x))JocwuMk}5_iWI@1lWqFfD9_N&yCM;b$s^muy$5=O0)Tg^y@D^zaKB=O*20zP+YIa zh%FuZLO-b}Mm-#iqdBy4Ok1Q@Om8vp300h+Fw zOIO<^s1im?^Sg*_XL;RPE5&Ne4~@Q^HcV$FdQFalo&#;irSjLIOaG;FLEVP10E2@> z*VofymW@sJLfr0EK=`I>uwsD3k=L)w3F5b|BIk3&WU%6Pm(scoww>JDNiMi!FBKcv zhLN3~4&k&DPo(hNPr9OWDmB;|K#0$9Vgbz}weqsomSjq^_$LU@_PC8@zjsqAEG;>n zt_b*X;p$ohyn$3ZYQ17Yn}z-piMPutdhhYn7Fir4@-g3w;%5n*DQyNp8BhcIRBjyh zSMOGLZy3&@!@E4$3Dz|;8d_eey-x`L4Wt8z<4=f;ae5MX5eqvgnH2=$SjsR$SwBot z7OE5{7Qa94U&h;X&Z4xOR>~qo7}HK#mx&r!lnX0T_MlCDKem|FVU#B5)paLF$W9V$ zhr;|=VbJ}`<7kt2t%;12=zM}j8nv9g%9&K~7C^rG;sA7H-1UJ1e{_6p4+?^yMj<1D zEY60}NH4OIp7F(!Y(+F8!>=UNFr%M2WC)ICid3fD*LINCg<@i27LrL=4Fhz9vIPyZ zSx5Uxe6;gVL;({-zu{@fJ5R6){|7g!M+4#lS*NDS>2L^;&5Soo4pEW0ffGNL9L5?6 zp~LY4UUXz5Wy41;#t@_06`ee7i9JhvjcwQb$X2$v6sIPrSPf2p`XJ)_d7?r&cwf1I4q z;R{+fPh<^$^Mloamzz+6;Z?Zl^8tcBmTSA?v|59-Zn4+ZEgA?vIJXqPc`XZ)JAYi9 zb2&n*{PuoxK3eo{0NIK&!)~-vuf|lC)5((HV$`wA4*S0+o6e7~jJ-IL6m?$*6!1hw z?mOS`tSUOrMEukiSgO7)s%yi^Faa7t!=q$f>Q$)5v;OEH)boayEZ68b$fp$8Nav=5 zMM?`-=7dyFc2_f$)%jn@(_PXq*Zq&qLiYrb@mZTiY=O8s-2zJnnPpESuQdT`C!ZN- zM*3hU6qg5nCE8e)K{A2W?Pja(=(h_){AA@lG*!$0$sVLX!R}9onawdcwWA%kuyxW9 zm80Xgy>9ZnJjn4f#E;Z^E?kM(QRE=q5f}*CC!DD2(%YR zT+n{~C!_Q!?0HF2hw_x%NwEkOOIHAD#BM+0pO&U7?F1`trT) zMnEgPl>7W@qL0Mh+2_Xy7labGm@)WbxcZWX+`yPO(e201AYdw-^wbCP47!6BqF-V2 zcG|D?abEZtB}g$?+5xWMRXN>!56y+EzK&`2dR8>}*GdQTS?)<9ojQpbG8WrBs<+ z-nDc2(x=K+L92SJ-q9Z-tjgPiwS|EumP0Z{SBfhdshS_guR(a7k5{yM*H~pWBs{%K zEt?#zuZP$0YYC7dRsh7;MoGElSeefVwnjO}cUlRVt`w-2ewK4fv>Hkd&|1k0H@f?< zeN{`lxzZ*CGL9BNELIP9H}xDA-@kc#u6G4qw;dt;US{dD1 zKEk6``58Gn)>wDz`S3rC0_sxFy^`q9siWz5b>539~hu3r3%+_7PyfQF2ux>w2b-YqQ)m z^XTvAw(51$JH=B;guA>G4XbuBv`EMP{@b|SC}LOvAVKLBi7?NPs>c?t{MS9#I-pyn zb9o}?O`e3Lbv7aDJAFe@WIKMN&@?!O~Ib$wy65grL<#w~=i+ zmQhNxy$%&gQP%)!D}Qx!+`KbgpP%c&qfOG6$;H>{`~H3UloVynvMFr-+nXeATNnbB zm@8I20okuWE$w}OF44Iq_Pj@!g81GKfq49G^pXF(2g{%P5|D2VmwkN2{YHO^uxM?N z6=-ngq3Xhp(7=sn1n@OTVCKB4oMxIdi3jnEs9%)HHA)4tJStmO0yr*3;78Y|PGFB% zD+z>cpwrIvM|rh`8?Hzs!-aPMO zX^zuy{hGDrx$Lq0_h;R6FJ1(fwr-A3ywr!{vF(w21FFH=exkJWeZ#$oKz;p&JHE`? zES%Lpoqwb@k)|q=0J%yaEerguE7YHMkxs)( zY*t*SQ5eIBzg!T@91U%>Npo3pnQ3F!LC-V%4t>YsiTV)nn1!Y)DfX?Qk^9h-i_<@rzS)*Vd1?15BmK(iJDhk!vmLJ0kLBO6_YdjYKB)8LNa{(x?cU6#G98~k zuez;R$~{cQe?QxaAmmYMa@;4U5D&M-M+@a|>w{%eL-vKjH&jtMV8i2gtr(pso~-(i zIA9Xatu6a_Fk7zI(#xRq^cnz+K;t0oKH9FbC!w&EN2~pNqK$^-@fZ^{3<^Ke- z;{EMzCXCT+C280b>dY+C73J+oxe6%6Q8H_MtR|K$)TrLWnPM7O$|z-nGkkJcC}MFn zVzC;G0ehDT%SmB5x&Vyy*tn-pc;5djOQNU2;&x%A%~JWPsx#sDv4k6K9rP;opLET} zltN#8ig?q)K<&I9!?VC@4{MZSD!cbOh21n#f8NYkDVfE<|Jgc701_|)N*BWP;0ZeB z582Ldur4+p;NB^{xc;AZ865;s9tV1ZMZ%}wvt&eUaI+3`N8a>cL-~bkGCs3u+8WCg z67kmE)UIeTYAK&)rX=~c$lQL+&y4mm>eYV(DsbY!eg?=$80)4|C_tHXx@*c%7pfqkR8)faVNCUSbi$p<-c6l_4T3CsggHjfwuHGMl$v$3}0F)97XrE4gK3Qqi0^(ra%{hVs+HgEA1#k?- zfE+alj3!1xrj{LcFf>vX##(Hb8+=IWegHnxYg5HV{_J8`pzNXTc6DCjEOM)Y`m_o2 zVqnQY_juH7IQ3>6Wqd1z#xOb`(+mAeD2r3!V^TnpR1u<063h~0wFsV6T$^!2oKuvmNG4-=$dS} zwzvxxs=q7_zdtURri;hAXHfa%_GW#*+02efWWr3piOS0E^-w+;=}Qe*gK&Nm{18t0LKc*@y-CpyMx^{Dpc5Y2YvtH zZ9Kz*v-~ewieD)n$dc(wJh44_+d6JnIbBHYBuPmJzigBYR@=Osesv@#;{ql(GC#Z7 z;k}59{mJNUH9(5ih=#O208Bh|1HXyK{z7eWWd5t0xanij{I4bllZ;gc{TPk5w@p2T z>fhq&_GdQuc)HkSM(hJ~b+YM{DD}jo3%k6fI?7?0bebq35?n#SO99qJ*6o7IC~i|o zx&0f2=wqKe%L!x{v|?GJ?WX~QpG+jCVY`Pf?!DmP>_*xWN3SSqMcN$ics?i#CY6u$ z6wd+`e1EmQo&WLY=6R%1|1wW?1s{*g?)^NxA;}2)c}$t@-gwpyQ*2A??;bZdr#XcS z%gyGk-nAYTJ?1AlmVp?`9 z+m)=$?J)IW-f5#~>^PbJd%50fhUuawArQ?|OqK^5`F2k^za1aXRf^K7mY4~~=UBOB z@IA|*vZ*Vjw<1uDX~EEVH|^S|A6*FN-jV!!?KWtkAvlA9QeOoIkh^gort~9jM%^3~HQnPMYSy<4vPEU}E~mP;0G@9j*RNhLa%0q;hhOl|mTNBASpBLd z+k+e9zBDF-rpFk_5NQ6E&ZkB&+_2yKRa5;XvIE;&>G+pf5xey(?lPu}0}1p=+6}fM z5YyFI>Tl8<3QEcz&rcAkT@YO#F&J%Jo$3~Gnkhw8x~OGBkFhzO9edpW zKN<%oISHuzw#a>3MqC@|e+os+f-DOQUtfGb3ap)V%%8W*1TrX~F>MumRRcW)`BPzF zFHD9hPX#n(D=u%EtFH%z`pbUiyg>$O?&K_-&0qv6^B})Z8i0(XL`JQlWtUY(P}rX> zqGMPPmQtgT@9-oeUv~G1V`EB|!lL6G54rXw6XA?VmlAR_VM_zK~ zQ}lwJNKG#tGB;@csRdF*e&Z;nr5;K};{5rSy-%F2FDn zG6Yu?0pZP~4EnO=H!Z0D2Ul4c|#hxR=!<@x)7RO5b;@1}Qp0iczD;H$qGTPu* zEe*Xe=2GOz4`$?H72|%Y6+D2GA&|m*a`?vxCTvatB7LpSgtA}; zrd#!1bfiVS;r2u0-S&Xn7)=02VVV}x>Zb&|p`R-!M%)r~{ln{jiaIDHSBL=$A^Ihz zHf)vg(->>ir^6IOq{Q66zc4I&uatdhMh`rl#$3&3T8_*TEH*4;){dy0{U3=7Lb0o~ zFY9_wb*_sZjlH&pF2>tyCYy4j>~jV>xCPVvcL*nSfo&YJAZ0v?+@-4sOHbfGX! z`1=COcf-CeC0dd@_op>WYIMQR$Kt3&a-Y#TH%S{ed|S0wy)KXnu|gP$BS<>MT}7hH z`TAtgi%|)K?pfd;rVo<}oiI`Lt9c$1v=0IM`nrJe$=)MC*B=HG8B<5^-!?m2Wo8la zIm-f8sHj@*=YpjD(o62CT>Z$m`?Ft@L&F5AY(|#oCx(hWkGkaCM0=(Auo+(HipmN0 zSoDX`Pg-m_pWoEl9fOpFK+w5GvzAtlv|1A2nVkk~v~`J6jWh z4L#nVTtxMgN955aCwqKGmyrfLoY4`(i_Rt}UW(4w}1 z{*nO5CpQ6YmrSXE<5$*8>gF>=R6uIOVlZ9$`UaWD=^%dgp#tU)+2HybtT#=(zt|3t zRN3seB#(Ou0AIhr?@^Dr`e@!Fn-r=a|`AE73;~ml0ncgmX)t4tIqV#*GA(4Pw zO8^R?`I9DKsqi1eeu}aRgdr(V&R&^X0pG;+&e`n}uu=;Kk1=D%*Ob)-7ngAmjgr^(K^m#0d z(2=-8K*gs7yu)lTAR7NwPV?4t*{SEf0R0JL1TVv96xif`buf7QW7la8KGAO^mMU!P zTgudNY(=D3{+2he_6F1#2`hKO$|&B@m<-;$5n4JC!Kp<6ZiTeT<(1SlzxW$d>6e=dDJl;GExD0$}~f zzcCovJhlb=RuE(IxvEG2G^*-}v}E2lw)fktx2Mbq+ogCOTe+vs13MHh)@;i&+kc+B zMh=`i?8ZmHn@xanY!e3VsU%pUj%#(5yID?M|yS+A^vZ z;fzqLyTX-k(XpK5$)=F2i?C2ri|Zqj!`}dj9lPW@7#+Xoq3e^VUngn`#K!ddYF1AM zDCKD@C2M)RfCHH<)8R|ucdOE$=~(sotwRtT`Ebz3aApd)!e7;)GX!Xa+@wGv9Z#$9 z{RWC2Dz!3g_vdrOf}RcDL;g=(*)BH1m=7Ep+#Ih`_&u&mBIjrQe?R)sEO<^C3YuE> zue2~}OiL$dMd?liPam9PVkCNI5@hTBF)^!WLisQ<*rOVtC%sgBO)wTTq^{kg;zt&Y z9t9-Xxi@U@zr9o|TjIpFtpM80wZqv{h)CLY8ik5G>OUFNfQuzt7w&N@(9eCmye4^tjT#;P#8B3SA4^8ImxKTDs z4T?S|bjk&!nO@f^Z86=LyFd8}`q(e~;t~M6xETDl`n}v;T{9}~@Xi_Kz(#dcYJAVo z)Xh$kMg4|xZ<$$oqsd&k1nhA8EIkoft&B-hngJe`h5zn948SBQ#P8a;hgc|F5SR}) z&kYU>jaI$&RY7Prt95|8tMYuvTgkq+`+TPDg!~?+Sy=qkQPs=XZ4cJXt>uyX9B>Jp zrH@Er*6q!6^}|a%BzHF5!K2I320%k>rK*ydMIfgVSPIRvr{|QHFJK@Vn2up}NZt>3 zNe!~Qxmoq0F-LS?sG{K#5O2?@!$Ywjh=h)6Y9t*F+e9Vc?*q0G*0A11=c|j@%s~09QT(G9SBU&m2B2X$Kg_^RIg@y`AqwS zVkPbMmI&m$OMZm7fVaMO$A#OX$mW<&=7eM@J8kqJ5v?9sA|g`w`T<6>T@vVZwTQ%- zIP|LDQe0b%SlS|xbXYVABMx1=n4Ar5mZRmbo(@`Wdp-VGJC=$l=b&SdqzblQER%D& z(;=G73*il(if(u~F2XLcPgUq@i1>aWT7(69T7?xw)W*hLyVf*tb08V|qZ^PP{m)Q5>oBVPrAkM^ zsi*9U1BOrv;Ix^V=ZX$_5B}4nV`{}i+%2bC4N8FUNf+)AAlAfOxGoSF^W1oDxh)y zGFj<^6*lJHn=Xutr&p8T{Uq)T(;a42W>gkz)w53i4BrcXp2v1+(Z2*&fIwo9CMsdP zPa^BnTUK2-<;NYEp}CPHoz^OoSbo<))A%I~c4?-ou55>%Z1O~&W_Od}G?6Zqpoo$z zGR!=gl~+RUxfPcXCmRI9vj%Op%%FMhs`Kj4-$9 z%Uizw;8X*4o@jRbOvUH@?k9qApo?j?&jnPgRCILG3-vbTM*Tq4vT{t?Yc}9dg*$KT zGTmRwI%aE-qkV8ouh}ud> z(N7i&{Q3U*56&vwH8?liMV43LhKb#kK%sfcpZoG`kBkC=jiLix!8~LrL8FQO)WJS+ z^0o_>*%YpDaOd7hJeq`;jXW;Ha;`+$8jqtl#c`wmTVMJ-I_S>GkGy(g&fASHW^>Gc!X{e{y_xJDF?aeu)*vj(iWjmW{4LxYZeys^p8GU=jp*2LF=8*YJ=H&h%%bFhIvB2ZhhOJ zONuvgSw*n9Tp%SBczu9~kYPHexOf9y224Tc;YK@FqVSdDk-dte69ayoR;~?1hngRL z$3I=h&3(PcXfhq`>`8Hj!y9!vu{PBb}hX87rhDUz0rqRwJ+o}2a& zEjYYK#DD0Bew6{mjh`@zBC25R9$t5w!3GK}9YBRWG`X{@em`!0`GYfaqA}N^cpR-q z1_yvolX#;)y$yrXpw*#j!)e78*elaA*A&~)eOZ4Tf8Mm06fpN`{-D_UI;%LyjZr)1 z{Dj-EiS@(OtW^HW)lPFwR{kj?cX>#|ebBc3!7MF@qSMTY8D3dcr!k5YjnlB$p1OI@ zbv1y^;Fa?Xluu7QiIPAM%Np^Ns!OxHc0x=$Q9|?AuI+49s!Lc=HCR{3O&+;7&MCUs zhf|Q%sBFYkPYDp;qV6S$?x&=|VHuH>XDGBg7mZPb@4LJ|PQV-@@M;fD5|6Z(^)~sZ zE24r4<(WP&xlU#Dv)oO$5p5tR;;W(;nGerOaI>R!r<0lHUy`@qSG6~jdo;$uzVLs zy(o(_`~6m!hE zvul&Ikc(tA*wC%8Xbb`3gvgJkgX|Hfu@V+Zar`_=-@8MTO#`et*dJTjGWuI@lZD6P z83wFYYV55acs=EFd){gALyS(l!u>s>C0|2Yc01J{>+h0Vu13h+N}a6sAH;}W)OAb6 zcDknftK{zu&l=C?c}-r0xv}NQyem{~dRtK>-6~0{2-A7Xm|n2(T=Echt+89IlVaCq zz=xQYZh#|Qy;H3G>W+EHkG(z#r@Wlng{+k*>^I_b=ID1GuAplB+A`rl_3Ps5`PJL5 z!@xPqfTZw)8S>r;Q;Er+OLgT58VlbCXtZV`md%|+xgW;fDP`%aruS}^6L1f!~rQRBP@FPyaJ^ZIen`bGHz=Ue^r|DUFfW?X6 zxJq8@gZhc>px#KSRkGpIMq}w%Or)RH%RoN4jo<{~JGTU7cbi773u4b}p=cP^zVhwSQkkA77=SBK%6 zh-S4<`ML~+hf>P0%|p<8WOh}DR}iZ7ImSllb{dnOF6xs(`=A$S|AEx#5Q>>VF=I^fBB`zB1}{2XC9x zVdB&aD;?Uk(w2#5f-*m4!S+`{Vu6}2Qe#5hZ?#vexlFCsJ7Io7X2Y-DL%)gVmWA+5 zh%`#2-6{Zgu3@@L#Q#*4>@BZPa*L~v2woO-o1i*b(!JZ-SI5jInLu_T6)YoW8jBJh z{@c!2t0(ZO<=b%zf-%*mV@)L)@pU5+)Ze2tIFsv)K*x}JrQrpz8o1>o)?Y+Mzz>@a zDKekL`O<)y@OT}1EzmNLUt6RPed18GvRWa|Rk0Q^)8a z%pkGPy&Z%chp?IB{h-=(^nf(O05)a_NEKe@K5HF*_V+*S@|}nl1)YzQ0d?2O1mupf zJ_1v~3{ioCCetO}X*R00(|E~t8bODM-}Nn^@~J`NP8=u`1^_a_GJ_hOuQG{iK53%Y z*urugctWXf0FxnvP=7{R*mQ+xDdhb|oPKOUptnjU3E^oWRZMI1tX4tz37ppGkX8u8 zwv_9tJhj{klaz^tlUezgb2iDSOW zSREi4=^-Q?aN|e;+p;l$I8BC;ggpEf9U|rvU*AmT$q~4nw%%+_DF`KiCaQrVm11Mi z*0>P;3>7s27&Rn;Nsq{!+H1DbY6*6_Tu;ya`lyg#74%>@f_|qcEQHB?1!g?9rAH*E zc)2D{DT_`;64|`ohyh6H3gC1cXn;7dBjk0IB$yVr0X1CfnmAeGR)qIYd6+^V!R$@j zzIZo*YdCG3n?j(luRaD4wp2pbx^BcXz5935u$_#-%)@t#@d)%CaiuLviCvUy5->45 zqPbQh_ZK!dFp^qtqyZX^i*F!y zZ_o?{v3nm&oh&t02L!J^wxgUfpeW+5(kNt1!xQjlAZB))gC6Mt>zc2XG?|`C?T+0C zXyHegRML{*5;*v^WLBdsz&yrsogUw!3brHZQHHlQ`dFi2j<0knp-zIHCqbSis?RUKySBX` zprJ@4N_faGAHIv4bbYpfEY};G0A;VI7K);#U`@U~>}-+~^z`QERi?wmLi{qD_m!Oh z9;?QSw-G`Qms3^xoiHE9zxZ9_cHf1hYCZ2kfHW$2lwpW!f$jmTZ;!we%4-SLSJ%vD zHcmHsIE=@D(f5Jku{xkAZb0$S)|foN4q z!app|x)6jw#CGPp`z__2jVOHIt8niYeeLXq*g!Ir(-ybzXoYY&Py#unio1TI*DYHZ z$`J5?S+2KQq)wnyne1af$cksy)4e`j_3@B+2ux}Rq>X>-*RAM!mmXA1Nh*lV@GQ`B z&O_VRL$>h*GzRb4?Lw5{DP_W4BbVKTK6C&0dbsmRQ5=%QPbGNDbK)579t$lq!55V1 zD6r94PYO@Zcs*{frPF|ll}8O5`Z+#Tl==I{Y3`BB$x>m2DQ*fN+Y^IHywyFz>MiFD z(ON-s6Iu>1P~l^=d;$DZ9MFMfKv#I}L?{+;+Ld*rhAM%={uWrfF6+(_Dkl+}_W-*u zSYtWQMyp=&B{EgF&9jj#FQNy+i9q-^FUz?KgNwcFr~@n9V>1_^?l`+yg10MqgkW?* zN7X3`-k*s!TS8imR?CcoQSf5*!_U$-`?`oyLFCoZ^*n!*E%R^^o>W}7M#c|zbF66CUMS@`_}Nm z)njFfAaHor$Yklj$p4koDJMO3;Ea)(4YK|AGgY39O2juFSBQ(DjXteJ?AuZuS}+4d z%dZ*TqGng7W-p6^Psf&-V=yE`l0+3`d(6|rrtkec=h+LR(Z+t1q&oR2h9bEo7rc*$ z_}2OR#A#KE;wuXy-Un!Q{1ou|RrA1i1ir*zd>sxHHc6mEw3ErkvctD0K-g6tgSX22 z!F_)`>!aYqqD}igI)-eTXfgtSu{dk6eg{3WmjEMTso882RK?a+I-$REvda}iwSRjUucJsXsrX)RVMG={< z!m5@qCrKM+v9nGz?V*CS3dgQ~rslyT0GJo=g7(+1 zqGBB+vj7w#qE!#jA30Ey8 zW(s#cjyPef5?+C&wmZ_lJcw^}nHbUNWwba|_wARMxcCtGMvQRk%RA7I=ak0bOs$Z? zAijrq{lFN-sUb;Pi=mI=NZ0f=ivQvhL^F}X$Kap)6d{VAvqhKul3PXYQuJ{l=@5HT zXhU*j+iKo^tLk3OgwVCj85)0Vr7N2s=_L%_H0H)k*!!dmbAzlbg~Y@(4fcb4k@{)P z8&PG+X~FHn>$;9bXc^(75vU+d9GAO+EjDF`3`A_<$u8AY{+UlXtDeOiBW|EkKj<84qqKHe+zJikF(7Rs2wZbUs{57#DmH2QEG z+a1t8cX}xp=QsT>$ir~Bj={?f7srveF!({ocddLd&z*QHLpr(GFHcWa~ zX~TKdZTN1Tgmb&FvXJCyYG_C`ZMTLTGiK_=7~kIuSI>$ebw=< zWw~d2cODxIrRHjSM@dA!rGU?z2_LrC|HIx}hE?6IUEg#|2uOz@T?zzyY-uJ%W=i~GBISvj!AhOo_*F5Jr#`v9!DTKq(K3Z^H zrV}Mme7gnOh6fs}ch^imEV+#g*9*+UmR%y9$EvczG{%<>-kRvoseBP{SdXypivl;* zjN*q$%e}4Tnd)YebI_KwR>nm+=$=&OykE=-Gxx+;_GOIqU*fufEX4;d1YD4Xj@H;| zyB3~b7FQhpUS!^%i5M-bYofEHJhagI$8+GG(P*~8LU{<6M5CTjI^KDbHG=NqtGzn+ zs}yQv3*EQN3*H64xu~v?Kl2F5x%jHXZ002D+LL5~Lun?6K7X{JU&BYPbMbpoYg#ho zg@B>IBtop(5h3n}q@yc5jw6*8+1Lq=4+qk{G14qN>E!rnYML-h7P@k11=6xjaT@qH z$Dl{?sdn3o@vRPKwFUw(MEN|Th`(5U!~+}LXD+d1p;^flguz*)w3Vxy8eumYsMyab zt}w+g%|3hTBZ|3vRvf4pm!Rn47Z@K30iP99Q~c;8`-=(LJp0Y7AM2jkp*4#lcF#l};8?+Y|Hz|}KM8ErY&vg7cW z#aVn-=|m|=06vPy9F0%sTgb63K!(_#@2Qeq9E0^YSBFw4g7mI|VX4o3oXbSIMdnY3 z*xW!VELvk3H-6RNbpyG5bgs(v@v!nmsdGv#W1dPquU^A2L1|Y{UMQAy#lqJdv6N3w zGaF|Abi;g95eAu1V^E+y8iWv-MHgSHln$@*VkTNo{YvCMC`V^cr}UfEOnHV^c5tvi zJ!6~HwwM!*4QcnfsKAY1H;I!63lXPjd}iN@rwj`d*xMNprK>#~D6{W((}L`lFDu;U z)b~l>#`Mj+UZ2(a6!$k^3)JPZz+meViW~wvlW}w`utrMcnYCG(4=_uz z+dy$Zd~b06Nmd7nPG)AN_*+^zO4A9>z|WKqL=49R=+AdTbnoh%?n4|)DHtLP?*^n| z5r@D3=sIM@e_*$Lfc>DuQdXtLgje~u4+Z@WtRR3?1kpysa`Z7J#6`i`4|Msb1Cm8~ zj@>XAF%JpCX<~Od(oZo*#WjaWk0@f^GHM0t@?s$I^abHiZ-CHhC0jue7Sh!)#Vy+& zs$ZD^HiPQK8s@*+i_j(`HZycf+!BA}_;nxe9SePZhfoFk!_V3Wbg}FPW55~=MzuzHrT4Gj*ugt#R|+eM1HLqGAm#})d+-nu*p?d zsMdgXp{~B3(7mm}H-mQ8-X`Dk(%1scLZXa^c9e0w3z@OoVQOUFZc*OfH3~tBG93Yu z#v>q08{Fjama6SLLY2+O1U}T2@1KY9&`~wwVd!w)149*6BXHQqziuW~Di9T4vVQ-$ z%Ym`JhE!&cGDVOgo@aZ~w;2bTj4K~MoTxywF?|u3-==FvH=HcXW6Az7I5nQ?v*Jr` zAA`?4fu-{)4^Q)2el93+$1GO=65k^i9HT-IzqXoWGPP^`L0-q4<;Bm)mLHF3@od=o zc=Vm;Qz;UJ!g$sf)b2G=1+v`z9i5M{{nOSm+E1Tp%aBa)$Y8g8e%&EJjR%@l-^N|G zy4y~mx7)+h_ckz0&Tsm$yp!Wnu_UCw!Wm4Fz`UaMeJKZ{+m6LAKyPQqbv_|=wL$;H z`&k1KA4lDaF8c8q^NT2AXs+Xl`lzVUm(%9)N<-7CGb=T@GI_J-lLd_60TvAN0=bML}D4Dz?M|LUdD&u8ER#|Xpe%47NNhs{5){r{! z_1}pgk#LIkAT9HZ<2-0n68RQL&B6Pd-yTE`|^bv z(xa){14O*euUdc;Uh?10Ot4{nnSPHlKAwA5N4y%!)LNI2?E0 zDX2 z19^^qU~10>fn=yw3ji!x1IfI~m}Gn}fJPh3=d>pUmhkoS)m`};jIUM5e9X#j1@9n5 zDq#bR+}521wz#aL2Ml6;|1p*z(7_^QA#FQJr%!%H#mxq6vKW46YgBafSneekYF~_o zZm?UL?gnh8|IWrv6saqKw~#Xo5()}GUU}X)GU(J-L9+UVRpplCgk{(6q-ZqA}?*RQ8w zxAg3ASx@Np7bi6S`)t0_Bou7n6_GFq(=QD)00~UfrhOgbkgH(?^&Gs-XaJ?z zp9aF`253lKFhbKXHlUxN$Esbczr6kLTqN|A`dEM~P3Jr6H%^p-o;Zfsj;=1ZY}_!5 z&xUf}UP@yVgii_Ch2Ura+k{G)u1)|Jg*Bg>`}n^NgK)C} zb!^sv5s+;Khp}4Tb6%$PqtxU6eA*stBv6zF0UJy<)%`bb;v97251dh1M(H?_9-tdh z=X#nOk?~PeI;97AYDjr(MfyRSncd7@=I8iVsL50*LIfBqO+X0f6P?NE=;$$?o%0a$ zj{MMKok)$r?@*{64w?~vBLx3nq_1qV(M+Ib;gs-(88y5cn1?ncd7`O6E1YAW4n|9}{^aYS-cfe}Y4_$kfPpjv*@XCLXde`{0D zLoPf2D0m?8OO@tpzuDIdoE5;$!O6!j0lHz;TSqb^&k455d8+Vkb+67e_b8Bh-T5pRbB~fx_s{=gR?&i$ zAGXQ5Kj0&VZRD?re?PkZiYq+9BWW*ZpZ&SteIyY;H_#$&=9eNOooMS=0Pdtq5LnHs zao>enU#SqE5$`KEZWQ8K-n^LRnPml6lQ)XXpCpBM6!3O?Zx&m-f?n^GM5vT> zjYVs}7nT~`4`LIcR!@Q+F75E>ZeU0lqXluM?7{sZMJSX)B;+Z?^x;@FTK_}4`n_f( z(2DAzE5_xVqQf5p5Ag6nZ9I4YuEU3z{$2LJeh9k{ssO7+3(3L%BpskvoDZ~V;WNbg z-#;vt1GORf9NIfe|?lVG_>yd=eU0f{vN{o@#jLtfdluGocO1_e_bmryuK<%B1SHE zuN}RjT>*KPQV4d*wtKr(@bBq5M1g#6=huz78Sxir=kW7I+V&Crc_ zIuexx_dW?Ee_fSN2o2EEP|NU7*$)aN{o}Nso8LbaZI*mI-?-lhtP$-J87{qr6IVFZT#a*N{%4h3nh9Rjo@ z?aYZ)5NyXMuTqtia*SbJFV=Tsn6wB5M_)Vn=ZDcjK|ZK7eSfQmo$_$!x#_&)f#FYj zC@ZwTtj=G+uZjQ{_A7Arlzi;WXM?^*HnuNWpn~i{h$6!T|IfGK2<8cF#YVfz>oYvL z6K{cBzSq=5N(TMStMHb|{U3y*=np~F(I`A?Aq{hwph656T$bLD_L9ZKwr4P?@S@&o_< zC6xpI|IgZT0PiRPm5>~$Aj}gr>g;nCKr=sv+eVi`y)@b5@&59{VJrOqWad>|S9#6@ zkXaj$QnEp_nFF*1*Wbk~jd}w`X!EOSYQ+zSo3jre=4(non@t9+fH}ZxVt=~z_SV&i znu|-#?eaGZjZ9n=(4zXlE7Eb%^7S%H4{i3A^jAJ!R!@?F8(q@kh`1%3A%8bHv4cAZZEDWUgxz1w6WUvUf&d3jw= zj2oWmi*x;t2Q(IHRR=*;1DkH_3jh{71X1L(y-C@0Ng!U>@kk#+e4qq6WK7cXAEyAw z*$?!Kjl<^01Wxhf>(xMt0mC`!0|4Sf?Xrc^9g=_s6a|7HJ4x8d&beiIZiEM?AbH(#gAij_ z4)uyc;d6=DF=I7#qa8Qw{Yc|nsXME^`@oF58T}sg9wzAhrCOk>FTZv^NOdb?7sA@) z)j`!rQ0>tv2%g7X#8Lf%m7s32954YPd8Gm+8tFvVlzT|q3;i$OLIG(j1&UF+IeVzn zzKZto=>cqHg8ZY)+#n)1%29)Qfl{Xz;d7PZX^M%nrp|n84i-_*J%G-Nw!9jkGBzQ9+6k?YXHI+{HfZNF4Eo_HVE@&vkXdY;cvFHS>GjD)tan@zMSfe7-iwXr+Qq%cLG6)2|{b3N0@u`T4iQ(o$ z{uv-VNO_ZN4V0k`KuVLPgg-=TS{X!4HR~=%SJ)glsGXO%^5ey8XPz%N5MxlukGdZr z(DTR;lfxc^tbrElGpz=Q(=F9<1`Dvf|#oFfDLSoaZ2dH00luQ92~twdprc0 z?ac5>AoQ4v5ij>cZQ9`WzZq+o=Zmmfr-g|K1*+7Z8_I`$K#C%#!)(d$&5NdwsJzif zd$5~8Znmn$@m)6s)XGZRRZ+nR5cA)y;|nPKGVMo#XtSwEVGv+8on{aapzA^RhtNIe zsH%@`v_{eP^4$@QAs&dbVt1nJog9rBic+lku+I+BLte1yHCg`Jb9UhxKw`#p1K`5v z-27n283S@le4tpXt89D(*u)-ytY$c>;%9<_8DhyVf6Y>xo%$2#ViPWG1qY0fA+BSf zqmR#jF$?-)_XqBWJTF0d;r)24XO~x2cEEq}hxfCL0u8#UzoaDwz-G0>by~tztt(7l zI-=O<@W-;Fp*C#)<8V4n$jr)dM=UMrBao_oNiY$+gB#>rmb>_2<(42e5yub-9y{WR zKzQ4RHJ*Tu-)muuDdswt$Pu^ zE8d-uzQ7iT-I{n_$DuGFJ;;?(8^Hh+aowB`1h&lY3Ltw3|npeM}uM&J_2h52;wYshGNl~-;4 zuvV;B86Y{R++b%ImTv^WnqT)<0^yfv?|fR@59Iaq=D7dtV0<^8ADxXW^#6-$F=vFa z-e(Jnm0IARpK}N&d@nHS#~#|-j>73vaZuXg>I=aj%m)CiQH26<3WgDsEIivSq#6>p-s~W|B@b5^~3$7Wjy3${7h?_9s~sY(@{EOqzskwhdpp zgSeg=`Jqmj;ihWisW;dTX=(wTMj`ztxYw_i{FPCfpDgu>5qJj>WePrfisA;hCp-8b zzGBYCh-6OYcZPMvqGC}Z%f6MW0ydY%GEs;nqtI|JhFN1-10~lvyuR|%6PCQ+8|QZT z?+ujoCb;meS7MV(jc>9zd}k(fns%kexZ>$La=kt~Qul=#D+?3WfX9f;VG)~c(hW{| zwe{lrLng6#F3=xnT&y&aO*)a;w+hqjgr8H{6HeQFr)Y9p{^re_Srz7L>+V^K?@c_1 z@>r(lu3-owElG#yHpa@-I$_?21w}RO+og3IH75Pf1WL!-)eT6wOgd)cdp&qJ{8;2VtKh_$udQO~f;uRs+?7Yvj#q_s4h8sBb64F~i`ZPcC=Xtb1VMxQ0Wxmezgh+*{tdqCOnHC13pkgEVdTzZLzbceZs z^S+pS++EBTQ8(V6-wsXv9-=G+1;;wwvi3|fMaVpGOhPkCG)6(D!UR{kA~VGHE7Tsv zp!?${3IU3+qC|cLLm&NQ#xs}hadv9lF2K#pFfxy3Kp|J`{zRvHB;M{2Qk4X_z0(<# zQ6MzB>^MWjfff$XT<)L3Z?>>8qxhlvUIDroOq^FD4%kpiaS)|zDFv)R<2qeOepbkVP~b@m+-_E z-#5B&>D!0LCD2^i3-qcjm}R`WMI?CQ{-#85_NVGEH)*GEcE0{x4Z6KgS(VJ^726y^ z$QXFcH-x3sJkB*jbLCMY`8c+g($6RI@7Q$-{ktfb;9(zHil)O7iNb143FjmPJ>HWH z*QzDBnH~QAbgW6-92IGCg@qkZ;l!@C5x%d1`olWXy>yCmWA3&phiz|eygijv*O?90 zXmTV$#rV8xi9o-IyzCkawwQ~%kjz9aUv|Bp8zsqRhR2731!E30N5?#-bw5)&AUeSq z5xKKsqoR&_AEkW437S;YLL@;{l&r(p3HLkllkhCYY&WW1awEgDBC|K|S#wFZqVZtc~p2l%c43IWpRh}S@08Z3*ksz$G|aM6i; zEMIN=JbgZenDnlq&$O|3qMm&C-VY|M6RRdI>XCFX#?;1wGIn{HhK#r)A)mDAwo8n2 zi}Wp|GvUaTo;dxj+c8JkBY0~4-QN-Z93unL$q&RwXk{*0IRwHE!Z7gg= zga8h;q6%0dYvLJ=3@Wbs1YvOV}tVo*V zy*&TDIPX#Vpv=Ya1Gmvtro?S`zfW&Gdr9DnEn8ejU(5%kfU3dgMe3)CR>a>md;1Ae zuH9GVbl9-k4;JyCJ^QNrc#*$b;7txO*?MMn%`JE1psa-zYP3I8fjV1H53g)fT+?8! zgZ0>DiEk++05(z;S`zN~u06(euWs3| z?v{|k9~$IgIUcVpttQRVlZA~af9=Sex7S@U>-3*RG~Xke5b>ZP#5@ z>8E}jfsD7&CzBxvW~m7BrV$SECM%q+0=waS8x3;PYFC{JMQ?BKTs&fh>Ljb%L8Z?V zl^~;VmmhuDQ6Mk4t4drvK6Vejad}wec6a%=a5ungsoqX$Cez1W^w)NX;6^M zU;0f?1s#WcMxKGx&jf2!z4y5>k)>PUT-*MHbMtxz(%>eUtkbU)^N?`v^2-zM+W*Z- z-;GM^wvlJ-3#vOTEMauvm5}I78csR|#y9v1FZ~bWoLbE*ohnLA`w=m$%A*H^$gCLJ z%_6#3FKh`{$gp={KUNSIdUO9LB<`#>>3DJm9n5C_mZnsLn zJO-}|JK*ceHb3(ZMSg%6&qTpbkTtFA*jKg;P+^k&^a8`B`rDT;E<|YJNG-YKwc`5f zP0=s9)fUvxDU0W+bc-u+P*`b#3PL-OBwiyBTzOEff8(?dySQ*{^Q87-jX0hoDI3M% zg^^~7>S(2>Ik%Wt&AUY1&}NRC)yv73B2n+jPI~(IGPOjdu2A>wY|U-{r0Q~V+Z%*n zVSPxu6^u0n<3O%W9O{bhiDZkfQqJ#COYQZ=2{`O?= zX*t4*O)$P*u^SMQU(|jnmu-0TO_>BLR!BsWm+%^L;;VJ6E~7L?wGjmT{B9p6U6B)O zH+-d1%F6ed(DCyjcB-FE&*Ysrb4H&*X6=5{KozBAwD`P0x@XC`*Img zOtYb`yy7q{Y@<5`D5r_0W(awO#j=#RQ2~$ctM-{UdoEhXZ3eb&Y&aEG(dDo>s8Jel zUa=8f({H>X$rUFU_bU!5#U9nGN~^`BJ(W4Q9%(G-YF*JMOKPxK>NnLiq0@cxl&`22 z>a0i;nplct%bq1Z738Hl&#ej1elPdt+NIrlBOYIihM!w6g!wL;EV`91Ll(w{XGIpv zIo-7T;wkZP#;p#@S@gIM<{44;gV!6F3YFDLSndd5_OgH{%&1!-c%o-wS?tGzfMHh4 zPuWlG!HvT-Tbb{;<+k~3wRR;2))}k6whX%QnZ(f}kf><#8oJsFGs_UY0mpPg__OH#{blQECGM4=pyZZU3YFOWbizlx8AcYe@S8WZ z=lV{&t9`ZI3Qy^SVIH2XxE7ICo`W_2PlLB5R&ugYwk4?9e3ogg&(LIwUSrpPv|i&) zZ3`CH0_9Vrv3jE%qAti<9~Cju0tGfT(e7u^iLi)BfYpSQN`@2XtWUP35i<1a1V0bO z*CVX7rD^RF!c*T!Phm;1CF|7pV{beglLgOCuW8#`kz~sSwvuJpn5+451TX2qxN8z6 z6U#)NI@-~XFVQ5O(s4HE8KyWv-_x(mIG*rn z60hASs$X{4VNK(3m4T|Z^F~}lpjMW0)mO3j98xMqA--8YF9UO48e!H(ToUcm@l?BH0S!P>bdTFh%zj}J~ z3ig5I^c$7U^SyUVEYdA~Sahdw3I^Sch3!POs4-@f5nJUm(ToX3qv`@$QXT+9xg}dLK zVffm3_eYuVk8h3&Nyn%xR?Kvzj(%2xw$>?+P$8I(E5jLj5tPLqp9PLqg*1!Re#-0C z?j-UlF+4@VhbwYUiSd4Ll*wI8mRsjlp-ou_y2%l}?}{e*89nVXnk1>7@kiOWZ}B@2 z$pHmR%?x;fEA2OBQV8K!N3i*xAWlDh`t(eKs}_cmWC2jhp{>aqAuogRZ!#6d+#h)v zk%>-8SqL0BHVreRn`Tp+Xtf6S z#=1?09sJ94c~F(X9wCZY8W_)s25@(fNN55c;gWHHoU<*?4(Rp#0^-4CxP=hx!3u?{H9i5GlQ+W{?1c>~j=-4QiG% zpkAKyQVBEb)K3WT70XlKz-J0l=5WSXt`M)G^HX;-kNEmAS-jbu?hKUQ?0JagRoch$ zoBOkPzIcc9XHnm~QR!u(kLkXll{R)QjgNz+OM;>!MA+f(ir!-cKkA6&bAA>EJE^pf zogylTpYg;zmH`fAFReuDhm5>@gr;kMm}4yuXn=ozZI$i#@l8Y>XhT}tC@a%mNJRx& z7t!D83ucxXZZk$g3a=+tu zaMp>UO`_i7YSOVwO1!Qj>JXLOAhh)H1U^hhyl3l8n|aOskj+^%Qo};+HmaRnn#zVi!DDa@2f&-|aD6 zBRrNeUG%id>)sXPp`c{!*^ZrNsA=JNDyD2qB|?V; zbUqsWfZiGprfc9g?`|?ZWQQgO{{FF;GBl7#ltvbla2#*!xLyA#t~Zt5tRI%*ZH`j$eG#-b|XrzA9@S2kncMmA4{$o^14tR`t1;dT*xHS447C__)5Zj2Xtt^9k#yP1tFED z!0BAjb9bqTZuOD)$m2oWiO(ycWhz`j_3`lu>dAOCdZo!DuW8b4u}~XIo4!b86m-@f zbS&H>9bVhQ3h8q=aDSF@+Z*Czb}g%_>(JOVUFSk!m+zek^Le<@!lVelP9Z9)fd59v zyqLO|}`N!SiTFlT+wwLQWPgIKO1 zF5wR>PS-#MLVP%<2a-?}05J7J`vEYV1QkFkI#n=95jY_rk}n+G z`}6D*xzF2Fs$0$Yp>4ihAOT%q?T|uJFV39L+@#k9>}k7S{%#b^h2Ncx2s!;ASY2tZ zlmr>%qhEH24Kd6dZoXPWkL@coRYJ-X(gQQDDjZBa_T8aO;oZHWGOm6_rZL+1oMC23 zqJ=H@1mtOLhj8f0B)NRvPj)=h@2fMkMRbQ-|uK#gp1ntGXg~aPM3gj+AARuLx zSh*Gy(2C5I z0%|`1w-oJ8W|-wEp&ceGu-7D`k^-rs$RzGuU3yu;Vs>bv+IoNY^fC9JZ@-lv6F!pj z9afb73fF7Y99@V{yAl2F|E6mA3wKyVC1%hOxS_c%z z_uHA7R26i~3C!ZbuZ_Qei4gnTw6?n~g*6;*Z;0BqqC%TNf6{~%CP+D=JQQU*2tnj% zx;s*l@(`$`I1QSuA>92maKfZ~Y@u8f)6v$Yg(L^u8s!D9Ad;6!PJ2#*q>gt=KvcRj z#09-9ppVMLZP)t+cHQ5j!aps_xbVq^Qkd9^-ug$LOUFR4#L;c1dsaW%0@O=9;bup4 z(~6A2Zj63e_RRNr;`jB(Mc;&>`OSIABRx5yc{wr(b znS9&^v7(nBywI?%!KcG!oUEmH@{OxeP??q7ZRhy`riu2Chcg1ADYxT4{t{-?5#+fT zq{v1Y{iu`KVr*UcrOVT|{ztEMD-8XYu8>6b5Th=Zot{0z5WYfc*CQ*MIl`$?EhoZD z5+!+QMhW0GiBJv69MS^t!PRU6jv^I#T444ULem69uEGr@WgK;uXZ0>N=Eo2#4PLgE z{j^)}f_uCNp^v@rc#XvX1s*i2W@w&_?~H0_75<6$Q4BdAb{|f~0LW{7{8@Ayg^#v* zs*`8DsgP$pHz+N{o{FPPdK%2lLO(;{^JSPGMKh3|edbq~6v-9)-f9U-(si&z0H7p zI;IQ^Vv#U=V=UGAs-J?oftIV9Y7Q-?7~vC!Ub#scxHx^qR?yA^hpvk;%sr0Q&*_{I zyvONmo8X$J&&(uJ2X5}7yvTHxBXuRUVts8m0H|RyUDRJz+VCCnZw$zegL3HGdrLIA>H;SSj#NHz2Ci^J z?L|=XFvHP&Mk`8Zk-6+TcHevA;fUn+ylDsw%lv!t^`=$aFfW#Hh2jbD4?E+j);s8z z@4|%6gD2Vgo9y~;7E(R5>NQSV>vA3>rboKxTxuqN7_PaSj{hr^Sqh2xjF5FRl z{Z9Kv*hj!aIa54gJI&HNg=r6XMzG%_Tut*-ZOxZSy3bd?s`f26w)m#EFTE+%LW01$ z@hl&KAuwCb()H_zpswlhnMCuizrzL69l_-*YuZ7qOXV|tx(@0)&{7>E$!VBi`S~2S znc9|*NiS8cpf0Ifvj5AF-KQr%{$*%?fKsO(2M}K=A~33<#7c8d#$x?Qi&|C%$5TF+vkg`o(JoV+0t{77-X=yAT z^CYlU&PdGvPNMhp>RcmX;F|G`gi~o2_r#47!N175?>J!RUmM6;xBoPu^l^#IQ0gP5 z^H_QHY9s1>wAP8|x3FI-+$!aE$hqK1PyHz)?w zHJ`{*;SOIYpIeOf`AR?+IWrqf&lf=@w3oYrd4n^Ok?H zaY$M~0kwm;#KP$CG)O0T^1g*hLZhg!NTu{YKBTKF82R91xiXE=bT#}z^TDWIu8}6V z>$~1CUOXTfQu_7-!%tIk;BpE+K7KFA=bC_x-^l>yu#}ow!W26T%UkFOAs~Rqf!UNv z=MNw@wwdC*6b;HFiQkQvy4Q!^k4(VfG0qShF2n!vR}`S7@zR)r{gs46nYZqo3Lza^ ziEfL7EpN09c5fsaeLcBi=~WV}Z}=&$ zjQQ78lZXP=6xnp010<$C&?UAXf6FahrrTIWSS;WSOf}@5XNsQWfDQ{yPC}wlyn$xqga2m-_f=8Addkbv zy#QvQt>R}I&$ph&q#N>07ihn3>x&nR{kEhs^GZHd+v#01nCyrOZZbT$y6ZP5nITr> zs!hpvjp|g&4#<5SiVFX0yT!o3AngUfu9`q`(0v_X4MuDKA;bwk9AgElbfSF(t)*%b zWREP#Fv5&^UZ(Dhp@)1G4O_(}wX%ZmCn0gi%yZqRHjLux9+Q>VZW8wu1xFv^3!YRG zPZsWky$3_=gq}xz)uMNp%9d(0$GJH`Rd%>FCZ1t{o~qh#7|-;@fHBTb(5)g%EwC8d z1JiXs0G#E3l;K<%ub`mLvR@k5)5-*+wU|M-KPF(vxP3R7^G-dUi^Vbw%nLke@z*M) zJq#7Np-H)!qIEf{PdszVrOp@~HN#EC1c2-I;3?gyN=*Fs1r;;>)x5N)JhAa?3S~m{ zZ}-(yh`822cYRNj$D90Pm!ktV*N<=sY=x{EzRbu4#-II0>eI2?%qnPUv<9(m_(8dz`Zw3O!gtDtgCHr2aBXFRlZCVtLR>& z_9P5@3FUCVN*L)_)tY|MC3Tsrx=C{`L+X{o{9+{%VQgr#7vsDpTXvn%-t>0vA)m_W zuY=Fl7d#fUeYOT^%NkBXF!h{|*WMH;u8)PV-UQx)eI|6gnO@nuj8AIlBu^?TEp?y{ z2eDaA;^`xXk7^Os3o%2~ZT-FJ78VTLq4dEKD6yc&x0yJ>T&F-IS)f$$ORw>vB)R~i zzI6Ri8@5ZT9>drm38zcv!~AX7+fy9rM?vQc5#2oSu!b%|-w|rz4m6vrqsd7~+`k@M zqWH6u5)jY@99wF$=`DTKVAk$Nt9G(ei*UM)8FJ58UF+D3R?;aERcPduCZ3Ln`M`wP zGc3s=YrZuiNUglO1j5_pbnO{j#o};Fl;ztl2?Gz{`K+rR*!7*;=R4M)dx*ogk`3NX zb5(z5i0nfte6$!Zey~y0`)~_#f)X)TC(C!50aZmbt0qAsI0aP1l*-R_W9jsj4Xmsg zF**(I-32>HYG+ZyTe=QXq zYaPiabMHm$#JAedf9ro)c=VC2jGvJcX(F)@->R(TCsmRaz@5V-U8KZE)}%on=f>vN zrY#k~QVxP~guZKsr|_0AD%=oMl@N?SOW;s=VUKcO&{E~2_E#i(r$)lvSvf04ZTAW4 zBs6X?4HXJ<1T09M+--2p(aj8KR-3D){6Y%0`GxNtwHnrR(bc+NgX(eJ|3R~cQzw^R zJ?G|CrltCtD)cZ>`ldrY;`F)fw#cKhp!r^`5L0}|ptCgdg;9!Y)qHokK363iGqLlL z?{^_e(gB!>ON%9V7KMk0*8>bJgH9(WCmSGt3>^>O55fgB)YM{NMvhIBjq3^)NAl>j zk~4Xt{7Nhtqx9%+3|G;dtqA2_zdxmk55lJ;U^-t(UG^c=iJ3FzanOe+qaYx`z-erm zw6~ddnf2z7oH`I%FAOp~ux>b(u%hHP8(FDzm&$m6&cb>3spnTv+%5>1HWf$Mt^Ikm zk)$*lTzVz;ndK!9?T=)Gadg&ir;G3fpsv`yX8eAUXG2P>G_{IZz&iRywGA#D&*_@M6)G3`v0 zi%p`-*B`o8jK9DZOv2qu`MF2hviqUnHGnZ{ZymlR`n}V?B%&;z8jm%75Od%j(N{O1 z-O5-}hF1BYT8hVTP$mi%+W-*_5D%&m=76ft8_M%E_zrg}KU z)xujaOFf&+YFnzYtxXg6T7*qc4!>4t zu;Kd}y=(4JR^{jQgFz6e`@Z#z9AUc;m)@LKGY(x$Zk7KU*8WHf1XgF^=y$1-C@ZRW zgC*ut%JH2?_|?4FBp8y8#Vq(LXAxsEEY$_J$!Io#Z~ez7bKCaJl?`5JNVm0slJ}rdfbd*E^<7v@tCjE7uPP zIAC=UTbgqmSckz_uVW^=4h5sGW1FBKZ3=9(P)E zcLs4e5BQ~1m%A=&-lsd!n*68=D#LSJU-yCTzI+h0p&)gqkCwYea5^f+n8w~(WomJH zYV58!y1)Fa=zzW^7jT%5w@k;jVNs%By47Fz3yvbvXYrQF_Z4GwBxY9r)9j7yf3AzZ zO@#hQ(X>b+?7$zG9A)5P_L2O&+*gZ;%DbWIA3LDi998g6{N6_|l$%KdDmTN5ul`sT zOw}=0*QMi?!h({&J*?w5Odjgobc%fg+3>curM={H#kyR9@xq8~gy<>J7g*HQ6W{K|^Y?*u*ayepo_L>Uy4fQ#P|}qc$1b+ih9!$K|$Hw#~O?FYj&7 zK^^{-q*FMOTtfaB`bya42v@@5Fmj6p%6Z1X#uxML8zYDbPE>egTmZJR3E)#@iWc>P zL5ta7&2xKMn-CR637qRuXJ?L3t}^f8v`O(@jQ4|TZ*ZVsdh&Mz!2V|ocD zut-l*gNsw3E=nt3uUSE{Z22I*XivOoa$6SZM{ny3kaIopm8?_MoN2Hfz6No$%eGFynF%_rmv)=^ryRioC&0guJkYHrz?}KQ1Cn8 z8cio%0-_ev<)U-i^{s_wS=Bla7oeackl&xRRxS607Wo@J(I-Ee?+2{~wYbqjXPBU&T&hxm;z_*-;;0w-J_5b3D*k&Vo>kUPy#GGQc%cd(JMa#F7pZc4}i{s89$XH zOECM>xvUA<2vgz|NJiD8IABCDbT0?RS>8sy0t6*6@E*@};|eFnu+Xu-vQkbJ>C}Sy zTTf9tNxzSUd0*$JOvCd&x7KegVJlwuH_~7a6Y+5;9=AMhpG{6@NLzWvRAdJPVB z^=cTe@9TU+Sy^Bq$N{|N*PH}ft%ZKT1ij4Rb?2hl=vIAqUgjMS_+GL=H89fb%vcB0 z#r2LxOv|9-+@fR})6+$UQk{OaO8GyVUOSn%H2yu!5K|^fA~ePy-Su6tr$PSD5zvP| zg*ee31!n-(8XDRJGr+UF(|19VzbYf(cG6)`3FQkbHJRt zn{D8aPJnuALBfURO1I(h;nvN+9?YP+VL_{;$%JkW)0&Uk&@*FpdVs6o98EZE9Xi6w zp@x)7?eN$J4l4;0e{<-xxQ{VNF8-7|TV|0Ff5V%vn>U^jXjU4*e;x&t^r*Iod@#A^ zodkMuVEeNlFJEieay0YZG?HuVeT^l<6&QU`#03dkt+H8O;+aTm55(donV|4Iiw+}X zZ=>N&L}l4TaC@*lYPdT*f#5^J`=e$UFbD_dMV_1!QI#Oe$ z<)9Aj_v`KoJO56;{zi>lI#57ue_t{Loc+*@^LrK#WDwnOI*>rPB&fx0eJ25($z9Ea zq0P0DsR9OxwiXJi?b})E0G+WgOt1Sf`AwHf>|*!#&DF?DSuuPqk6-7&2=w*jZ;G%* z2zHodeD*NbIr#+ya1x*+|G>>f0w=Z#D$bkpN00%^28~=y>2{e@AnKfj(CKCjgNXBO zPFr{j5ih1wE~9^ZWYh;HtiIK8Z(2TA$62p<%k`MgvT3=p+k4+W*1VHo`=zT=clKd> zL3?}nwrl??j??udhGUAKD=7YWaV@ljev9Cl^tX^PUn#OpYPMzLot>F5H``_(JLiWx z*Y%i>6h6KLxVTwm8S=Wisn<=7@Gq{8CbVbv$F-(csUwg-gOPmD8PHYxqd?{;Tn=g} zqbM4t=jpn9`tU#>OQ$e}6~UucFmmp^tWnZkT^SdmYQDSGXCXE=q&KlFhK#G6kfT-e zH-Lrm6qI%M9#m|)4fIl|i&Y<#4`lhEX6?4wEJ-ZQa(&+m->$xSP|6`V6{-Iqd&&ZO z6DxG#Pt*Xe|7A0rvsy$}Eq3OUvTpUeFRc8SdLx4mQ`E1qQQ>ovA8Oae^7y7K0{6(R z*Qat6__w$CyqA^>Zd~xo)|k|ze5a=-kg7%rZup&6GX*Y9LXzKgJ;gW+I%3L(JW^T5 z7x*j#cCevWly5(*HY99v1f*^(D0V>6BpCVSJ9ujD3Kpkbx4~spT_)UK%tJzr*UtDCgNs z2Qjd%*LU?gnR903tXiTJ;wZl+o(>)>3a_2|`NqlBD)BT}rFgapC^d8H1YS)VRslF> zy#&#q4YPs!8Ud}Ab-{Hz#VrS)Z^a5uEyWHiX+waQU}snzF$v`usiRVVA%W?#7WwfX zkHiCf=eo@}baVn^0`2n&t54WL|Hgc*FoTL@=;^7wr?{zzV|Z27%Y$by?eICejc#uE zY@D3RWxt8Ma%z#)v1$=C2na`<7wiJLy29N{d)VjrZZv^BFQ-y8oXQ+-u8Maz!)SY` zaeb)FC*;^L#~d&i!2LrB=?uBXJkewDo0YwN<=wvC<5(9Z#!d)6+cazv+Uhhqh&V8| zpmgN&#LdiT2>w8Mg#u6N5D>3vx>aRtb$`jK9jOl~16{bErqH&6Fw7i!e9)vDbsq-d z+>IAM-`uALONMv4uU@8-(R4vABj9Taq4v)3ZHK}zj_eF1l|}Wluhj>EbzLz3ZV=yW zpN?3PvnS|^Y@4}+`M z0gAQ}*e(f329QDj^N>b%>*ANx<``-_pzw7RClpv&1bv|T5GQ`iPdW`Q6%VDfH3Vj}a_3v3{E}vl3(*+JMovr=);GJ8sK zw^_463`WtYoWrI_--yzy91g45O!fzL2Xmlats?dXCaYY~l&=)&6ykGY&A)Y^RErjZ z<>T;H$&y$VMXuV#uMSf^=D0Un5wam6Fee&mFH$l_bR(0|-HjI<7E_Nc8OVM!O?8gB zaQ%LMjOF#O{jyZcG}yVgyCO{uldW%(ixvHB{4mS$IIr>nZ0H08(|uJ?ejMg>)S;9d zB1y{rt7!O51u9UT7YyBb2xt|GM|qC3<=e$!bxoz(S)#EOpy2)27f?b+d@c}F`_34B zV;O5W$Jo`w=;^*sNVN9hUsqr3A(a2=O@f{Q3OiiYOHs=0y6e2Tdm{fxsfipwoa?tR+N;{30+0SA{Ae zamw43Ise4VR`ijXZJjfYlvR##u8T%Y-~JQ$_Zn*zYk9ydS|OsAd}@qvk!{i&hmZV% zi$m_8v$DgeV+;hT$%ca!*XzRy=3cg!(sc3FkV=6^)Y|?1(cgs#nwRT`zn^a7@TPe- zOU^L~{`(E51K^HeoIm-zTRaRGnpfp|c0(nrs)TbPwX>f3j}Cg0nz+zll-P3Nn3o@$ z3ta>Zw5(kIzsjyW9LlzfX9>xRlp;pTlr^$sk0B|03|Sgm_N8d-66!6!N+f#;g-DiS zlp;c95U(cWwS=OSCA*69o!eOEeXsAI&o$RvbGeM?e$I2>=RWuOo%8!ONz)%ZL%KfK z{`% z{M$p)Zr4#}${lAZ2F2sCU5vpi)I>N-2qd3MOn0=4Ggfw;Ii}Vfs>x)7$DcCcTYqbB zUGt~<)FP8Ck2oWbCC?=@8$y6q#G|6U z?-YLe3`*;t6m* z1}vTw9Z!wt@Oj_mTHd*@%p!ZbvgmjPNk7-IWQWbP1fACBaii)dBZ;b$c<8i&=H_Vc&j({W+x@+f^N z0AHOYk3W64AxqT!s<{~~3FH3Bs0LtjQ@gb{&}s49WYT*-EIw_>+}7Px>{~udJM^HS z>>5h2acxlax*abPt)M5=a+Xp<$zyE#HRDsKsG5lIkeES#jC^=Xt3pPvLSNxfAE#=D9^L32&U+=z8&6j7@ zE|U}RR7{sN!1Ns|W){`mz_Z;M@d117Cm0-y+*fkj4Qr-<9MpA35=@+PjW)o1g z@OTz9%H+7m zdz;uvxo;rLawjtrX%m2Yj!2GCdi&f?kD3b`xOjO*o5`o^ECd<&)^B?EV?Vc(!^q5O znFm4+ZVvh8ap03I6+|uCD&N! z?CPmwVx5k`C-K@RRxc-)rqAXtKh3@0z0t>fJ!P8nlww$LVwuGr`Q&f~7Vq_)eDRGP zb%+)Tlx`B?Eaqm;rgZ~__(;o^0wB<@62IYNfLKY-wSvmtlr%fysgciB|2ZVY3mQa* zB_sK%jTe-?iQ}fx1oGaN{R$)X*K*91NBM4;CIG}L9ybv+a=}YvE{54mTVwlQ?D~xN zS9gW7tKq|qVW;rt&g%-TOaBZ75Dm~UwiA-036OJgT`Ckj63LFy^(g%2kR1d~nCII@ zpcjk`<$t7d27+p8?8l=nTN4sP!Zh!Q#m9Lk{E#{zYb#K-+wwzR*(2i?&hig+zCTX& zTBh7}Y%3thTSn-IE(>rW6J#RbKtyy$TRAkkA}$-g*B|R*k|57D+St7u^lstic56a( zKeMMFWxI!jRLsT+C=s)Kfq(JChY!B{T?RX@pZwNYg_k6I2^SCcitX_^r4g%dembS` zgz7f2-Y<{kF>yN*x^qmEmAC&jOP*3*+Y({9&0?(;$PsjZsJoQ86M_a4I%n>HYUX6k zMkz9w!N+#yFmdp&q=-cg}^!;p9I*ei6(~{ zy-No^ZL9AtJ&YA9$3>RkC&Wq_5uED%se2Z@I|<>$vpg46-#>-JwDMDJE2|qXUc4Ae zaP_qU;$Xxf<>>6J3pj0Sp>5@MscJLP9T^FW#qi!L~7vblV&Su``K84lO^CPar?yJRA>Jq=%uEkeS@CkoSpdvB-=I%NFtB)%NDAITQUmHuOmCNPrVlYe8M9PNCuVws_Zq_U5 zxy_*ZFN(t90l@3C0j2UEo}l4m0`U3|S1*dQE&Jy0{e3}}q`|VN;jK~yT#~l-0TwJs zpmQZUVMfu(x>kyoe>&*_No?oYuqLS-rW{}|Ye#w9WM^=B(F$B8OIbQpw*foW3(Jj~x285;8JM|R zH;{k1Y$EIO1V6?;OvsUwJ^kRC0~Mr?V!+_yxbyRz2e})3Z14UjSxaCz?#M?a3*j3d zm;dgZ;LhjVLxL$}9Ojj1!uvDL=8-en)%F-ZPK zkI2gt-H*-uzVzG)#trH3rY1j^#>pgC#h|uxJUugIvh(ph855_ip0?`k!paZut9Q=j z4UvSadG14l6c$vBBk`;Mf@()enp`3Np?+~k^2!Z|GghGT-^Z6C1H;6_bd#XiAi+&R zSdYNn<@WL*|E9RqHruFas2UM-8NzSA6tNouwl0QK;Lx z4#fj{?(TWhBY)$WI0W)bfw#5h;DH?8rdnH1iCykZzelz#+kf!R$3QHb!mu zO2Eck$zi#9kN!0>`N(PQXxZF`i{_m9IP?6YhMjv}9_bq3sc)1bYBR3r5h8bJ%hkt9 zvNdcR)E(`uvV|lU7B!ium#H|sVhaM{y6mvU-%n-!-)%`^FoW=f7+hla>qe}}*ky6u zdree=v8CORQxSYHW}VLr;8P8tH=S);723&Nn-#JPw3mdC4jQ7;UPNjEL?ZEZrdx02 zvmZRn|Hw6I5@LN)TDS~ZB|qubS{ciw>Dj$FzB>QUQJVXoxe7w+F= z0pxoi|66@~lik0zmjTvN8MbX4E(40KyyC0#?i!ABGuSBIXbkwb5U)UI3r0P(;zDGk zhwUeU1Hoiy{x=O7)C+yNO_H#0Ua@Pt$^YIlnmks=hvh`j%`b$si<{+TWqM>~ zXY1(eN7-D8Xh8HeP~5ER?0nbJ$w>!l7Mg_4-DmEW&ELrOS!Jy3VB|B|u_wFgTpO3l zF{tjAXS{JRRR3O0ami6bU+$s3+(^s@~_4o6|gpo0wa;z0W;5cFhmK zpa@vVt8S}K$hMr*+1N-)JxSwp7(;)8pavvC)k0ClC{+86SWPX{f*C z7o-_|xC#oeg$){3ojnSegX#OL+L6b<`inm-cm@ydaz~!VG+Q)ky>aT|EZW>1~aR4q4 z_IW1q`CFteBC@%a7b72Bs9HXgpJVNJ*TN5@5J|*_b?v|d29t*i{drPbNq}bbbTPoL zHELY3g__H!K1NPY#+pW%3@~kCwo(`EjJbw;zNxGxOZT~(!A08f9zg(DO~26iNFvP> z7TkyS@7F<@?X*@uYlEz2}_o{n%pz zqh- zd?zg|q99!9h1PthaNjEoE-b=enxB`4ij*KP(A3;~%Xh}+ZgMszdp06_%rVaFe$=ej za(g;*KX#kpKqrCf8%mS~MFAG-^Y_?;fLE#u#Z3`{^BFG0fL!l2T@#nYw3 zgi5iXe5R7V3i#La@QVtqZ;JRpH!+*McRqW6xozjMyq<+_%9gcH`S(l!SN4Sq=xBch z!}o&HZdk{3yx7D`FhL)P_05{h{=d&Q2$jYS?eR$4aZ)=6wopZ?_q(bP6`p>5pY-2X zWEWi@=fkauc)0eJqPuX<`oaJBApu?aU(*_520oSn;q`*ma4Ff(FyKCh%AU(%3e!(q z{{)$WLcduNn_x#67hR_E=f#C6f$zefq7@QPeWrYy@MrnuQ*29&{zAs~~D81d5Ko-$-#alQnTsS!UElT*`i>@c>`CK3Q za-D&PqDe6$3Q$k%RT)88H$l(0U?uZl%R_LEA_!6cd+MQ(z#eb8HrcD2%x8RzM+KED zfAap)R=U6Br(e1xLpx+P`K4W^`v1ND@Q%scj-GEF2z(@Kn&Rpxgz+`h6UX5z7BNQ0 zw`-6ucfMavhkANuJHP1X7X-6?JmH0b^yXlJscC%hB&lPjsE!W|37 z_pJRD4;G!qmTMO__CoB}U~_8$`9H6D9@^35)G=K=C_>i^H;~G9&o1r0p^#NJHv8kt z38?oo1dVQ58WH1t=;;C?CbuiY54DPnL#15N4`~VWfqI_T3BNV{-+wsoL6KXZuQaUt zm}BFTa~{1rlCo82Sifu!i|74hS3h@^_s`h1Mq+nGyxWA;-<9US%DzfGU#Qa&BZ46y zleV?Z<#Gg}Qgf!w?)T##&)}J?G!*j}f$S{SYxgo;YisSf8zWgDt^T~#7eS#`j>CJu zjdHx)h|=nQ+qc^4zJnW^MDhO1M3%rn3bP5^jdpYC-zfu0NWTxxr|C;~5T)nEuVSHt zLVlBRc*nETkWMyF&hrT&fiGSXgvehhOsnzJ>llIA< zt*rT1wYLQr) zCoOWi+-SGvd7Hxf9rn`1PdaN?0_3+bvSL)8EPt(Pk z;%c1XrpU4a9z;&qqQ4U*zXwqVoL>%pvaKTyp%A4>Li7+)?71TQ@`unw6RPnf?ahWJ z3yiEMQy1}jZkNk#35~{NN@WMgIgjNAyFR~_A_Zcju{11NtvZ$~_+R9@ZaZj7diaF1 znS9>7Dl19_(x3;Z+tgECp1()gut~qeFh(^y9uPr$koZRplvK1)MIEOp6cvNG9Lf7(~)e4?oo{G#x`G~>%I;^UF1cE6boi2=N634({>~xN+kBXr zm@hTb=N%+`j}(1tK%3{|_ao=Mj!#yLm@l8`EmxY*lt*Z(YbevMf`|CrR#DwKTnve= zc53HzrJ9u3{w`*SE>O`qlBC}W4>0qHBuSoWC(7SpEcztlf)=Rb5K=m@68TdL7DraJ zJ(!oOSAyBJTm&hY%cZe@MxAH1n8hpd4U^zX)36~>nB7I;d!lY(m zrNs@eUO;^y%qA0maS}d4{OBiX4qhd$EksqLY#`z5Do1mdrxNWV9mYsI=$!4xW3|XK z(Zppuf@xS=r-$H}DI1yR=mA8NC{j5^W%~j-CkGQvI(;Se?COx_PQx|JC!5k>NC*=6711pnH)Vc_JI%I)BCXHX*lNj!I*}w7F>_D@clKUfjDNsjiRqu@Z52 zS5tC!F$)ADn5(B9zVBQ&0x@jwcapI8+7_x!u)lCR$-JajmUfnD)(Up|K|~m4I+?(x zkj5U3Fx99AGckn}R%%!sss0T*3^08&z5Hwy2|bj2D${bcbEJR~sAPkkpS4FihNrSE zRTw3E29@VBXX$8eg0J*~aIn6QuKOC^Z{*#OSTU)GmcEV75|ti_P%OZ1HZ zIj@?S;OuY|X?g!KdhW9BctW8dD3m=6R9ekxc0B8~wv{xO zvSF`dvrM+dibm|E! zkQ6PtC?u(eV<=v_tR8+ViZUEk-U|GG=zmB-@w{(47gd z{ce@a^6xn7T<0969Z$&9vE6vZB5|ybs-ikqBRzqE45x%{M|oP#a;#8+Z3q*rv>kPE zK$U5|4a(P4NWc3%q>fsSLvK#r^jMA^cx=KriH<}LDHJ&O_pCmt`mj1`l(SIl zA5nq?PI8a!^@POk2-R>@j(OmCXiZkJP}qjfV`3UuOH<&;WQ578(-xJnm&@~aiUAer zzyJ&1q8VH!p$s4<7jN@uI}KSps?6qJ+K3BxLIwl7J0KT>cjU|Aowu3u{QG`y59lc9 zbI)5kQCme7DTe1O{7F0og(STRdC1s6&Ubg8lsSX&yWUqyAsP1bpA>l6!eU2?|4VIe zI1&m6v}vAJ?^HZdjP$$U8U;cl1rCJ4p3Rj*7SHEFjqn~;=b%Qz9!NXgcS0K%-~Ww| z`5%aFA6U*8OyIvXy1R&9hF+ZsC2NK2KrDjwDJEh$rgqjR(Z1t!1R092l-&PEEWd%N zWvJ*69j3Z)5-u|;AnycvihIZcyH~oi;y#aO@K+mmG}r-v=T!25=AeUKreV;5C(_u- zn;NqJ5Y58ukAhg_wI}-^5$X>Y)cUwjEFQ}14!xrGuPG9T1(SB}Zy1wyo~yG8x)cbL zgIIiFLZt%Nb}u7N-AHDPu5r65`DfMwQtmoESSlMiq%DOW-u~#q1y2j z3VPaYFJh$!ye~0f(%Hi!L|8O~^*R7@LID3~ec?n(2Iu{OrXfh`?Rd!ypr#AR4cD`X zYIvzLy%AtCckdn;NfP`SVa)u=d;PKC-+(beH^KT@9#=O=&bvRPr6UsLI*&%e++cSk z63$OLAjbf4023A71tFEb*Yg(i12$(ONdrrE&fi%&lwVX#e@8MnX0po{Rb3^6mSyBq zIn4y6=sJsZKjt99z>PD^UVq~y+PIn9|Bt$d|3*2Uo*XXKlfASO_Kdh&j*G!g;Bj`Xz3)B;8*U`ho=WcjE6xm1 ze8Vt&MZ$b;*W@HLTDN28apb_imZ8GSWle3>h=duzvT*!TF0hzBcMQ(>XSfhNAgxnz zQI?DlsAutC-Lk>B7s1q21RDg}X5Sw8L3G%(bKFgeggrDVRZ#zf^daIxF)XTYbVasB z?^&LRiJcjgV@PhC-^NT5tu)tngFWBxb(HJ8tQPP5b1FjMz`{!}uID;_%OW5zvmwd=F@@g;QzQ z%<^|z9(lI@LYD`|V~P3GN{fN@famWsvY-OseS3Q1ovu${Su7HNX)t_&=79kN=%+sj zZ7=OY73gRx7g!Xt9Ji9*kH4WIK(kh%p01OKn}TNOXvbL|iUV*!^KApb6csstsJug` z16QqhZ$1YvQl=UFPyF77G~b4s%)6p+T9E3IG>2>^%8$0sB9yEQI_1p_3ftW!FMcxr z6SPQk#;(-+pJW3H5)4kNf1=sE0~WH$`bZfj7+W1Zl(g}4cM!6kHduIbNWDb?1tl&K zY+%jnT1iD;l*=kK4!i!ChPTITjPisQhs|86^Luz4il7T~z-dKX8xaanfBbm}F*q++SjHIhPKj@%)dec7=BoD@87& zsxpTo7YtPgiZ)r!fSrK-_5ppzVAuzj&6JtMk1Y}NDR#)U*|?&Q%7u^+RHWJjQZyW- z$pvyK-q&eV=lS%|R&6Ykb1aR+KLVRg^3$bF3_usI_9x$YK3sKDbI2 zN4Qe&ooG@Vod=HoP$^+Bogh#y*Ir=JDv~F3|2a4V&6B&mW5HN{8+DBvPSt@cV0b3u)28dJi3}!Z@*d| zSOxF>Gkd44Ze;hKQll!b)s6e{xZ0RWvB~iOb?^FrDhU)em~{JS!bO>uuWl>BaMouF zN$Q&jAI&Ts2J@L83BxJdLN;@;QlP~{J7XV|i}XX2Er`W(Iu538v=mPYe{`#MEwO4< zqBdL1mI{o1XH`mrz3R|vUM*i(x=!5Kmx)=)Fz~&c{)t=ha@hf zsNKcylElEvIn*g3yuBZ$Z||uwn^M%4j8~7*lXA|1)ke0DDcwYM8>X#qNQ-C}a+zNS z2*P};dwu16+>Ia(@5`MbBK>7HS zOJN+dLIQJICa4NvM7G~kjd?$TYJ0g+m^*3pR~q&kbuB_f@!Y6W4YS|RRBvZarGv>p zFs`DR%FVajZHCFxm<5u32)cWwiOd!WL+=F$gGISgw(9?oiC`#*w-x|r)GNDUKzcvq zv*ewaeGwqcf^n4png3kyTkvj8oV=FPDVBPviZri!cuElEV7Za`Ba5leoUS`VDP;$SJw_px*7wPqY}%#ItySq{cr@2xMr3P20)BBEB>Z6sMIbcsJ2?WL+51L7NqC zK?MXHm{~H|A=NU%%{dW}kv{fW@A^kh zaLrUQG>WSuJ?=rgXkv^g03|L2GS#VXYgQw;ANjzW5Yg#eQRE1nzp#2PX=cV$g3&c3><=H@`qI3HwzoC}%Jw?JzP{QpJ;fLRgs zk>g3Fd~R2B{UhGR`a!6;MQ$Vsp#f*PYA1{ME-PY7TTvwGb&d$uE|i?W9tm_FK77s5Ew z@C^YHAtt@zFX`0$Y<0Y_8=e26zK}2ABp;I`T7i-)pC?WeCH!~_2?mt@cX>s$g5xVC z0C*t>bxaRAk%fzJ0Q7+Bd4HHLfpk2>8z-KrbQ9p`n9%Kj?k6pPkd+(sd?1k> zS+@Q@;(dr2xqX%Popbs*v_Sc+GqTKTscs%9KR=e1#1Cf>_?{45mhB+D;^>tMejDF( zHJ`ODc_^+R=AcxxzciI1>XKhIaqEA-xc|MEYc^FNFxRG3O3~PB9?R$L)qdEplc)tO zObs|ZZg!P>jcVhKOz#(gLfLdhohg(*IH!jNj76Qnoj|0`eX`!>vU02RWmNwy$NNI! znfG2kp0%^V$PXvd3c!9YkWL8~Ofoms^W3@XZ+|c+P%BqX5^~E~@$OrnKlnY6N?fN` zxzQaQCO2SKs?)66<*FO?CZZ(M1UmGFqHWUu>Zgc+#h?>DTWwWnu-*7c9RtV${hPgE z3P~j&%%X#h@^b(M&h=_i?D@wZv2ieYo9fRfjljW^18frRWP!er~QmK}j@)8HQw>cgt z=JM;s)2}Mzif%;ly#Pc8E!tpPe^_)JR%4UgAFFNS*S*IEWo z*^Qq)w5_i%j|xDpH9>j2J?j_4_YA=0a$Yx2aaUo-ABgJ^8`ES*W9W-CY3``KyvDAzq$R@*2xTd2%kw-=G~tJV8gGEfVz$r7Xc%N-@h zr5VBfSr`iRVF?2r8tTMJ8Du|`LU}Gp@$cu>x2x3DD(!|(cNg7fnV@_5>Ocjo;X)_mGD ztbIs|!Wu0u~rK_%zrF zbP5Hx9A`&a{i-=?rFPe6XA`qJEvQxv&_d}HgTsf@<}-P5Q)q9#OQ>BqOrJD^z&s@l zbctVrC3zz6px#Fgi8yRt!rVtQTacBm9m$va6_YQXxgC|&cR-=$amZifPozXn!)fYU z%#~Z=JXa0DfE+N&@m$9%L`rn7lk}<-A;uvK?kpg4Qhr6YvC_CzuA6k)KX#4hL*)&C zVM6n;Z#RQ*L8F?liPkdE_*HxyNBsiyMv^NXo|NZlcNVEC{?ep!z(6^nm<-UWAIvG5 zid;!5C!lNj`@57R4~dhGi*2v-Z!1FBN=PamtH2Z+A44MpiQX9%dqo&2m^<9>R2j_Z zl5HHVXp+i&=6iLtPzM(Ycx*XYH)~s*hE7OCDZ_gAYH0x+Mx~FZRcxDk>if$ec_yY+L#xYMVi_hmdb6!dBg~Z!_gfTva_ZFz0(sk9fiegoUC=Q zZ*mb?)^w~TXSFcwx>$H=Wfyl6%94(`K!^5O6l)_i0L^>xN7xyW8CLuU>`(gJ12MCt z-Hp2eeq#~whW(NGO=}wJE`K6U+y?x3;j6?9!HRUk-jx>&<4T5Rmf`k=f^T+QQhVYc zf0>W$7j40x9A9oMLxQm;npgt{j<|70WDT?JEf>5$o{cX=zB*EnXWwuuA^R2cE#FQU zjGX(FcRAerR*pRI;V>FNH1yqJOpxbg6RpS+Nm4Z*K9m;YzKnalZGYt`A?x*%WGDU+ zE!b`H%Ibd;HosJTBT<`OJ6B8lOS05!>Ctqh|6$)_0Ez&GOqv149av&+ACm;33P-np-F4yAu=*+CzEHc?9M@=A9G6|zzD2qG& zLuHs|_&1q5$DE<)m#i*j!9`bv(&U^`4!?oaS-;mfiH1r99hHyX)?7ioM^WH<3IV4z zsA}%Nop%;E&pyIOYMWAxqbAm)%H#d!XejA!5*;pYZD~cg@k}h7U$Rg8TtySyWrf>Z z*H1y12xgg3S!cPX2q@oGrdo52wQClcIOiYH>{K$o1-yYdVQ^oPk11xUYu$pW0FES* zBRc&k^C`V|Wn$BYe}?oCX$y|I69Nr|iWjw6WuonD6vmXkpA$1E!b2M-fkzYHOyWx{ z;^exI^T`P7?_f#Rq;|jcu${zc=crm*|G7fWG#KihY^Bdk@=b+*(QZUQQ2!WhROxp< zK`=`!hGFUkkW;|`Kmrf~H~Ok7BwL)%U9IzWFPrPZbhL?DoU%0MBf==N(HbqjvIk*z zmw?BZ>6tD*+l(8RLPuYm2J(08Xb)k*iGLdU05T>7%QF*4S9!X|Ah@_uLG`sI$U@(@ z%{t5-n|&6$qdz`?9RDr0wMlBo(0=#@)TJSY9nG58_Tw2T2bystV_}yMWGUN! zNKF7fDDm@F01f)ZNMwh}JZr|+?~>c| z&1P|8Z<}94CP>?UUsP{h-Usr?=`#@L{TY!UjAp(C@_s7G}4NEf*%q##s7?_CS z1NX0wH&G>>#691NibnPDQaQGzq6tJ>iZq;T>h@Yei3&`XeI}-33zEPTj3nGMkm-t$ zD&5F_eiL~y00?Qj$_=U09U3GI@!gAyDwIDN39u`SfS42=k|xwvf_a>S5*!pg$7nC$ z$OhI3+AMkxWom7f!%gY7kIVb=2J9RU%6g!>=o%{~zLjt{oX~XrM`ZD(mrZ2xbj>%h ze-qpng`5EN*0?*W4W1Rxn2?nv|s@{vx$mbc@@N`NENkDuWs(M99l zY7?fwm{@gBD(yYD(G#O_lP9A0>8wf&Ne7UAe?b0BQR4>W6d;9~Iu%48(R|D5pz)LV zEQpJ7RY4TZ3qbXBUUrjGRq>ZP8Lv`rx%}da7zne<7FociH`RxlcKrbcDtUh!P*Ru)p;FZQku`11 zoQxBN$P6z?W-&4GE{Y2?n4B0lB1y}ynKwe4+s@O_lG1M5ULKC-tGIA^~s{}4(bHY<(UDypE)14G2>tZZj(C zEv}4o6QNwgc9Q8k@CM3h(d*9?N-#mh&!HV-jU~H%sUQajKMZ zrY}RNfa=&^(~G)LMjF9cHl|vIT=1^`1`8oggDiz2U$^yZ0lo6i;(<@r%kvaxEq&9Q z89g6`Ds)@lIGCMo=D~>dLAe)Ii|XS|+Y`_$z1vN-k!Hqbv+j8lMxBq<9YzMh$lr~a z4sb506+Bu0%7ga0+kj+Nr5ZRMb{OXgCeLu~x(d`_raf3|Z%DcRSbdutMiv&&Mw^(&Dh0?qNg~~B9$%4+Fo#7<%P{nkL$|@8Q0hT$@ zh>r<}>ZsZdRsbyi=5#dcsu_+1Wq-cLPPr8G1v9coE++~eGWxjnj1-|{c#J8 z>YA{^X?lMy#2O%xlC%NX^c%ov95XT*4TGv__XhKDE#M##@K{W|p0DSGzhPV7@XVZ* z(;J}4#X|=*+U!qce@mcNlZ~JLy{nFT)Kegn`rWg#sc?S@;0P!pNOEahF6Es{@s@j- zwAz4iKJ4kys76MS%dAVE))67Ngfhi!R!`pP z5yFQ>vp=8tWFw3BA?eg%SDH7GhZF6_M(usY%TKKQ0BoIN@u4G1n8NN(zSk#W0g*9G zsfrn#vL^Ca3Q7oAbX5P4ZlbOp=0KygSw@sq923)aknOHO*r3CUTw&(y+Qb^jx-;2% zwqLk3CC6saTf#$7XGmXG+@t_Dnf7?<%>I7($H?@`F|!$U#-WQ^|8e2G8X*j8P;jh6Cy z|46BuIH2WtiR-W@Skt!cP^HF1 z$aQL^0CqOI8bplbOht0y6M6wC>S_2?$pD{~nl#aaRBk$n2bbIFT@1C`>ch%lHbbf{ zMXj;6)?Yhq*n&4{FJiYzgodeBUUVC=w!S`!FML>8(bmnNPRHq8v~nE+dh&ki>7y4{ z2Y@AQqS0aRlVn{hJk>&)Wdlk<0zR)tLx7X#K=`N*7SCHnwDa?sXlHON67ns$l#V%* zMH3440xuKmMGlhbe02p5;k44@GEVhZxBPH)44ZlZ!- z9b*aM&XpT0zoA2a^6`BHNO&9u;>sM}o}QmoCXj%JAuQ1KE5EpDIp6E^_86UPU^{z! znKHz$4e$iM4fL&-$1^s`EZgu1BC#JLfJ$Q&$T%oT7@k{?`trBx<~H?bVzcYf@6k`A@|uO?u+y(OuRV?2ttt> z0$7gqALf9*udtHlq3KZ+x%9%g{P5H5W7g-}y=dxe3UrS{2I|PCULK;!D@{2&25=|<-(updBjJaqqep+U~#JY(Bw4A$21pC z(y}&yH;Di~V2lE*WzGv}CPqSe(RUnXcSwDe7LOx6Soqa4Vko&GYlv zd3_q6Ri8nMt%pf35&Yub1Yz`jm)rDWEhyTpO@Gf1^K=Afp2R7)r7Ps%MnOFyzxoC`-j{=waBv9yXowXxdwd8TY>f*A4e ztaRd5-Xa_e-1!)!?d7BC0;VY!h^N*2Z^>9fAza@J)`k&pMM{3-`)*$wzn)FTA_@A; za+7Vj%Ku9AB7iAq-iHg{vfzkzlLYBHjVqzb9)4@pq2#J{Ri!8}CNjD;IKFp3$WKxv zsTQyQJbcM}+5{UtKX`XsO;Xqui^(LG1|w%)(Bl^E@tbU@^JJE`ZcTCW62)YUBNg0Ha;^Oz zinsXz)D9UvO!~5j#5a~Eg%tlNg9s52-2#b4@o>_si{O+vj7xP3IB!JtOlsaIlCvdx zXmC2)4W?bIGy0|MroijOzZo5CCd2a>%%>@YHumQ#^tLCF$T_9T+Z)hKW=}ejV5@UX zN`B3n0Vbb6GN>>%ShyZNW6hJXs{95>|0RAf+(5cOW7(A)61V<)}l{0AVoJOj~ z9FC|#p@zll*sa4+sa0uIJamsVYb@!_CP3IM7yYnugEr@s(kB}{?FA!E4{~pW{-ez! zCUc@8k0b9dVHor(h@<*82mviktPz2cut>V{`ZIB;z9irzV?09% z4mb>H`NE)z3gDY)pga8i194xD^?ot#FN zYf$8()_mMW%lf>Hnzy1K`Iu_TegkqmkjNdm$3T^G$*r^ixuCju*~QTDDvk*l{W_< z`;?#|t!a&e&iGLW9^!Z`OEozT>N`&>WV$W-25i+&fnf})`-;dxbjpf)OlWm&H6TIa zO=qwsBHxVXoAbnpvdx8#{?l1J_XUaIj3bv)Z%UMAJ7s|vme377(UCaPPcauk>C z`f>FI5vc0XPy95X%3K?7o@LWHeeqqO`Hy#?0J9uy8l&@p?LY_)Al@^@u=@oT>5Td% zzs!Leji*6d+@|&1Qs0Cr>I^KL=^xde9%)xFd^+QcP-te(Rg1zytdLl*U-Nl9tq%Rm zlH{8#whov`yMT{*U#IKUOoHZ1}Qq_<81sN^g`6I+=8` z4-5DoiKd7UvZfH_$4gGVvl*TA28=1Fq-MG%@B2iq=hZMyJ5^mI@ zP(mQ{$}z}odX~EaCo~mxq>^K{=_Kp8QqV}=R@qydiZP@EaFhmWYLAr)o<<9kgx{_; z*cpanG4}~8E|O<&mY(O&o)_^~U`RrIAmnks5$=z~9nFVFM)F5WYzQ4(i}Q&$@hW_| zgq=zNE7RioE~&U#<_vVcjZndrn+GW5I0d&XiCJK!GLF>YQC^pWK~dN?+Y(6?>cd@4 z3l;2*Mva)z+Ag1swe6M$~8g%MF=964b-%XS?}<{ZzTKsSK%)o!%U77T>hb?8M? zBLF-OKs)EB664J$9L0yyk?e(Dtke{#k_Ewlug!CACz;+j7iq)szBE>xaz~Lw(F$)k z2TYDPx8P)iB!=DEQXQ35YPU~}?}UFV^xjq~*I*#F4+^*Uw~5%9D(S^)+KKB<5DY~$ zwV9bhA_t=v_xa;lBzs;0mB_l8Mckj25P;{aTeW!uD5sc*qWcyuO2qAAHf>lGI*X$s zJo!*Y+<%C>39rk~2{@((W%?Lw8^_{+&#=y$JCv#Cwnx7x66v+R%NJ{r(U+IoeH1db z>i3b|i6N~H7)6nS9f&};&e{-@f^p1u%!4*=)c}%84mhZ0mRSN>J~0hZ8|!>KzQGS? zW%?JkH=!u{Ep-j5@9T0BMU#seUja~?`IR>$N%&h^tArg(MH-(B&%Sm=NO$r1o=!u3 zAgzjJ0#!5(3*woG*fTObA_OcMS7%?fwr(p+Q+=_2l?V#a44Rc15)>sE5Dq9oixTljk`T`V+Cq_<{o5RnBzdjRS19Lm zdWaR*KGri`fX7P^i0AODnq1q`Iq|&6!(N9C|Hh@>&U5xtb5*cyR!Hhrtpp~R`?MLz z$z4T-SlUYWkW3!fmRH`1a$Nb6L>0k$LVo?JQz2K^f!l^$E1u=4Y(kj5akQ!;>Q2Wf z$(|QtWYFCt)&}==*KpS#)KsW)yE~9dg{!$x!tcNU6Sx52ELM;xGJ~_?j8F)%tg>4A z^t)XQV#%hFf>8_$Ilhf#gn$CN<*ggr!2{N5L3MgGRUOLT0ToXj|E|KR7)lfNK)=E5 zwbCI9#Qb+VHG2$LA#6NL+?a*nd2OJe-A)&2)~J7g@wr^vWc*+H$Vs zuK%IcdFKABn&44nnEkOh2dW1d3=lcvv`OP4s^Nr#l2}va)tkvxBaIBU{ShBMSin9b zS7V-!^AliMy9fnwo6Lwe`86Z`i{>NDou^nv^@DHEQAySo3^TAND;P_^jF%l86T9hg zrx&iwpE0*xt4^)$@m=_jaQtj6{MinIL8CPd6~>U857WZtD`B1NHCW? z`KckoxbgvO)N{Ix5{yu6y$d3E9FiDOfus`VJL}Zd5Tf)qUn4l=-e}HG<4KS81&MMA^EA1 z@26jLHkI#u0_t;>Hhck;`5VJSy}BCej8hC=jB9f;5`hnVwiLQZhxX5o7k*(R{n&&| z@1W>hUoC5eFb84$pig)oCbr| z^o)hUBa1<97Vw|%y3${WRa)2qmqo{NV@Hx6m^Qr1AD{q`+x5^CGz|)GFR_|z`<X#y|d=pGlt%%5Rx`hVL0H)vNM3;dSjy1?@2-or7))x_wPSlE^(=6g>NBN6&szI&a1P&f<@4Gz@#``R@v&N`;gBZ` z=X$@G*$Do%qe|Qx{N~i@JPm6&BZjrgSmu@2Gz{1@CPZ)!(u@U{C67=K*y6Lxk+l+K zMFtnkqFGJwv|DWPQkca04buU){6N2X#m_G@;L4PVO22&0I@V&}x2T21CSUFGvH&Us z8cd>t5$5%Va7N>R8G>(i?kENp<6TUG073*vI0g}XhQZ#cz?~HvJ zB-~Sz4Fp|HQJ@-i1$10&@zdY8(JE6&e=w~DiqLu}zoV&Ud28tJEqQ8Yx67;U?d*yy z$pk83(-!^icxDu!HNB761iG&=TrSqz__^z<$Jt*&36-s7N` zT#gZ&T;$p2>jV~eVXF+7@LD)$b{OK9i7sY}*Z^i>{Ts{m3~b*3@Ht~8oJ=m4F(VWy zyI=jCsWxqt5-4X$YklipI8#R&4cL9@F00>w9Sq;kok=C*JNyxNDKw@@Bfk1<9;Gi6 z*)>029r&+#J$~2;IJs!8b_T7>=|%I!6!1Y}^?Fihb2zngRA)kZbEWb>5M`l8 zUiEU7mVHTL?*qEbqTN9srl!Y)5O@N{c^_$HobvWYN0{b|tqBX2HbSlXE3L;RDs+l; zx$D(4NmKYK@?_KFKcC5pZ(^{Sb&iX(AjnF4-S1#bQ6&f#EM1c-zjrxV+$m94)&)Fb zjS80DfMy9@>51{C2aTk0Ft4|LbtjitGFz%E`)Tpf5ZGfzmVR-)dDWOSya*H&ZbJUO zj0~k2^ZP=T%JQrssJlWR~DAm9lIkE|;;a9xACd z&~Zfm^_QT{KK7-JBwNuLs7!DlS)c%u27A%Id>f$Xmg=@@dMFsL=O^icCA6qVdpl5%D4s0}85h~=A`%tO1eettmJu}xohRf17k#@vDgtZ4#(sum8mQXqr< z+uBZC*+VP}FXBztXt4kq*-nx1XL~?+jIg$~udWUT!eV@Pxd(QsiQ(CO2i&08bgfs4 z(%)GIH8R_|I!TT$>aA%Dq4KbNzYK$jLd3peO_!(d9@c;XU=a!rpaS4gI!$W}A_i`X z*`EA40u!MUfyZr+r&5zqzV9G6gRrd`hM((KoUz5R_E%fE+8z$6!?D?91^r$u6Q?9# z*BOsm2tF@pO5X6$`N!3Dvi#(5*o`+*f#5C-keM{!M)(eUmV!SNqqJAKHGyRqGnPnt z<~S7OTPMti{~$OOH%OvAo##^iKvw_itG_kc4}>eHqs zWfegcJk|Oti9;REonxmgPW=4(6ArtbZkm!*w%0<-s`Zow5Z;6x(J6T$GZkm1ak3+a z1j$}^7E+-;7(m{?0h49X(WKPNnJSQBmb&ll1)FSku`%rYJ>3u3SmxpjyF_+Qzgv_u zO0pgmYt@%Gp7dhqu?&4eFfG%nGJ*!S6@~+zpKQRD1hDhW!ozo*a#CBrM*An!@A@}l zuifQBH$6ZHx*tMl&CfDS6t=ukd%D>DSNqlop=FIwC+rI zc$rw&_F3@$72)0`@M0jG`ur?1k8S->V7s6p*L(qs*5}{5qx%chg$l{!0O`U-9?aA4 z^fSg>_SR!6uuBN+N{DffWzXp8o8od??*J8wU}PhG&L;hif?{L8acs67FP%{047DRF zT-8rZsOGwgZSy=~5$dA_Zlp;0$^vpfnh2Jzl55e>D=9|>hQ!bBO-lswl|e?4uwW;4 zsG3xoZd1Z^lDIcFCW1UkrOm@^uqMxbXK1#(5(bawqk0hE-YA}P5eqF!uiF#;BZ=;B zES9$Vpx{_DKF{?#w>Yz(mYv7@itSKz)R}C7B1|W=?B?@yV_bl7v~xyH??m~jfr|fo zC$OJSIyJ2(dZ|Tq*HN+guU-A&;7%mwL7>}11ubc9#EDOmi8P=X-Nu|EF zMq$`kD8dzv>GV9+2Fq+G5?0syAFKf#b^fWLdwGH+DjHsaX|QZD{Z6m}8We*`kf9_5 z&u7hCfMe!i0U2lt?(>5(za&Ii)C)|m9V*%($N|VpNC}hd4jXMOhlMj-at*W=e8`kk zEH{re4;`7x(L5Pvu64e3!--MRo}X8?uAe1zQ(Z0j=0T&UMok@HKOiQJlC6Hl0$3 z+_EQ}1zm3QAe~0#N4y5E<9Nv z5OB7B3kn{0N#*vuY+3nM?-F~J_xyNk2u%Dg2Ltjb;PaJkJw3GN>6bun98ZZO(_)p} zeb48@)@-`EqNj$@+if_zX`fA?qd>~{?Q)T2EXYaYj0U#)+vL1xh;b%3%9x79?MX$mf>+6(jHQJ0RigE6_HdVqn$G)c1v&2ZVv}9#OSfu;L?Gwc!k~lB^ z4Eh6Hz!hJ%P^fsKoTVX;dOjuiB@4sTy7E)Xw@_iVMrktcS@3VY>;m7}Z17wRHMQ56 zEf{K8m^Wc@4Y2A{WaGlIMqT1Jzh(ln9*0h~)=ClsPW!waHYM;Wx?v&l((*b=t4+-# z3Eo;KLSTg|_10;6bH(*I^&0c_QCDM792cVBtNoN3j29{T)q(Kk-6bvo4sB*{?b|=Q z5Jmtq_l?Xj*{CL0#nI`j&$qYG=-d|;@nY_6lQUuSQqLIrg!Vz|c*oV+SDk<0B!42u z1yEfX1cfPZW`ItxuUO9mj%=|a3&x!tU@rY+cJIZ&3#cWQeG5Mg(*^Hb!<&Dtj+bdv z_px`{Aqxd2ZGcnOlIEc%2r8n`WPAmv>Ib%Z_$^`bZ%T~u`yc1Ry2NyUhhJ<}^5?jP zd!4W{3lJ41jdz7!ZM5{)!k7G_Sfz{msWt1qvna#){!-|aJwYdO3VH5!YL06Viu~!k zjUUydghx+Hc9(O8(vmlilooaDs)Wz-6G{hqS5kpL4Y>;dw)mkKr1w``3UeGGl!MV# zflgEi0nj`b)<FPDTzvmWj``D#Ohdxmz{*DrXI zRr^p&hh`^=)AzFK)}>zQj|F+a0Bm_?mc%D#OkpOcmQgN05!~Yl%lVvMPaQ-VFPOa* zk3=P|mK}U-wu;j$Ea1W>V8C-T7^z}YW397B?ec7tW~yfA$>+9`>B59FRBf@=P^DOI zW_M+(4M$yv-=E_o#&9#oQ>4R*pb6ER8)>V2{M~3)@yxG(@j#5(YQ$Dvp`}iN4UrB*c|dH2MCEcy#66#2HhcDU#GyPiTZz(0 zoHKhto9Jm}6B#{989_?>>_UvP_H@ST4w1m+J7exWhuaNUq9u1ICG}0}{4bfn2Z1)n zz%GvNInXi=XGDE_YSCmQKGeZ4_*~Dk8E;y>*cyBldK>Fzu< z64ITDN_R+ubazUpv~<4X|K7XaweF|$apug-dSdVW+mAAbk)7+KHWve&#Q@yg4~aG- zf!Of^ii2w0kh_1vm3v^G8{)0PJ|4G@+efebzJJPLJD1P-5gP6%>I{1Lq8EJ*t9t%; z2nhvkO3aYmfh|jtsA{V`B#&e5r#f8XPqxGttR8qM6AvJNgxQ+$sM!%XfnUy zdT8w{->}u<>=X;Eocy%wu@tW+h~o>YpnZ>)FX&IyM*h0-{=V0WD@fFEpRW|!Vh^Ws zSEHCF0AUeuWa$6V3o2xmGGuSlN5!yYyN#B(H$7Z%M$cpg_v-f9%}?@@8R+JFsOryU z$`Vn=;`|%zBp}87zVd(4Sk0yD-P`@L1-;LMG}VgKjO%|GQW~`G9uGX>W^?$?yT(0C zd>VHmDq-F`c&w7JSH zMi{9zR}Uc*CBd>6^oiz2_BCp>ffGIOBK1Yf3SL>6@AXhFD|UVvq$4d1Pp?Na=>w1J1KznB{PsYDXo~B7tCBF>hloZ3KQ*4cnDowRc9Wod|`Z8 zpEa@(I--eo+yCq{HbM;N@#m{ETzvmN!FN$o(LiLk*TpE&GnH;33{UZACR*zML|8d) zxT$;A+&wc}go}6>Rxfv))xZPPy!J*Cf{)ATlT&{dlx1stIxSzYHa`pYuKdd3Fm5Wr z8E9IE!)1nq21tgo%KqYD!eKXMX|vcb$N6|=Ng^63ScIow&^|au*S@noP?^wtdHj%g z_xr{s=S>qYQ;arOjUf$o&so}u^e3zqWt;@x50_N2{8Tbwlb26-12Y$9oqt?x1scd8 zT+!y65Lr}frm+;?YZAlfKX|Yz&8>~)jAyFqSC1QrZ3|7w21RRBU+67hLk{ldJ|UFU zC#Z*YWv$VlU#JRARoj!bO}9YAjrQ9{x7oerQ;GfFASdc(9X+}|I<_!0SW5SItZ}2Lg zQj0n0~X|ek`^*~j3?te zIKMvi^Io47G`_3r$}I*4VU3^<`$ACQAd2N z;7K0HRa87BB2WXHK%(hE^Ox(wdI8e)f4ONMlB6!<#3<5S6KY>g|d%0eYIn<7lVrp5bI^i_?m&<;diC9Vg^MHYGx=pzy1FzN3&U@uC4s5_xf#aZXdL89IqBSPoz6*{-C~#j&C@m1#l!> zrod~h{7C*J6b+pUgK%P}HcVV5Epfn_=;pN=%lcp^MD6|sC~(#xD^(aY0K?5ByGO9KX)%@g|*`F!tAQc4(sS__x?qY6^%LXOks zn@DAcrCJ0a8HO`2ug+sPE5{Z4n(+g%PoPQ(=O~)nl7G0=PE8fC|KfsQ|7>sy%boZh zQ&#&fAfe)pEPvSjyV=dGsGzXZwdcz%b(q(936pn|G%R$Jcu_ata|!dLcX_`LV@vug z*3jCW7!ky=O4`eJStp5O9pOR36M%9l&vJ#=lj_LiQu-G`+zT1!^Cp(czo3%dPtOX= z?;Xb9x_i*@hJc2i0`1I8ZtHQWCdak&r@s^105t&tIAz+&UywL*vEK~SOW~q5-WTT4 zIO#aoRNr(~*Da5X>p>oeIn0-quP-+9MF{br6~Rwt0=eoj%?x$h;et@31V@yEna88x$@nf*k=S4rBjA)|1nNI zGO_fB*ut+zWmR9*qyU1>>f8b;^*9ErqeiU|QUH{Fl;;0~W*9X3HrFSsOvH*ORe>f4 z+3?UQz}8*$+0T{P{6JcdQ};>ob4JuPukCc7`gN-Z|M@U8|I5qco!K-E%StuuWB7En zE*%I^k2)D8|FE)dd){xwvRC_F+vNy)AV*@5d!~uFY{9=pBT6xkYfD&+BYHPX%`4)2 z)%DtUxdutO%?4`B^3E@{@CQzo^RKszl;Zd~DM=%fapr~O`)xm+099NW!aiKTy|>Z0 zZIL{DgsgxLjJ`K;A(_`(W_^MY-=s}%leoS0o5xqs^SX&Yt8=LB-UGY*JJVBi`(-a8 zcB9f^w-`j_*jyILSg%AHS;Mrg&t!c-6-vPSGA%Ow7RK;fns9IGLch_M{elv(Nn}#2 zC!uwpbHW{fmG=VqRp(SaCtJ?1?~;=Zk?*@5Xnavw7j`Ba?U$w*>VRURghDj6r5n0` zoD~l$)3<*aHj|~$Zzi3hzkv{KF-P6_>(jm%(EJorgRH6la!{O*qdnb|#cIeqq?j^t zIX3yEFT1Bi*TYp=hisiim2WPcZ78Uqy980Bo<8Y1fYOFsKWH6w;$N|N0QPxmrV z9}2MdQrV|pYJH7zcjR;(8zWsEIqMI4xCM7$l36djm7dfgDS^Yi{DSz}jE2-w2XZL3 zA7ph1xuIto;r4~GC6O0<`kLU*!-6e~DPM$jH|P^m$dDV<*LW|37XOOaL^pt|EmOt=`AK1-X zrRW%YpSJ9ae`MNqmA8HsNHxk%WL94OWsx9aH9n5J+awi@6~QOs^jp|ko+%m#gL0Dr zxoS7Z!9>dD)7C$uqNz9Ei;NaF8{VQ-ZyuJ8-Tyun4#FGtud&NsUEsuS)A zs~uE7tOFmnmPN_#Dn9Q&)f%`iS($vDM`U_ws|{t9*7whu!g>Lv+cYiPo|`c+^zdnk z9TJKnwEz1ce~8O&$iFSpdpIHsBKfL#z!jLO8H&cZQ8Vd{LmIdKb&6agT_2;=iL zF96l8>TGoMaQrSlO_`XcsUZu5fpr18Z^r0V{&P+u6-1VQTG&Rvp~U=fI+$UlCy7I6 zNh~93&~uGx-%-&{`u22f?Y)A>_!_};cSJIRE>a^~85z?^PQhaM#5c>K&wI1H_d%O9 z{aMw}*0%QdK22Wx)!Q7RKX6QEKxge zftY6R0C|u-%Vc?R$D|N4P#~DGUd7=~cUg$t)~DEHLw~yLC9+>p{;prV#>F9Q;AQ^9 znJQznNjnhY#hI(X9_RC!PpN{(juq_LR!g_e1*C#D$^w!De&3>hy#_!GJ(A~B6rR27 zHo;p)BZzEw&DO!dUBhhygKc0RVHUHRe#b`h)-SCVc^T;g4+3YXK z2i)lI73l<>RwU+|TJka!u_a(9JvMT()ILat>glu z4la-;#;w~(|02Q?$C9AZ6gs5caqp0DzgfkEM5i?!1#?L3i5$s*x3z|V%8w{D@{vpkQ>iJph}qyL!uunBst$hU;}ya|P$5h6}ij1k_8)qKXR( z*#|EcdWKG!(HrWkHSVoaPy$(MZo|g|wZ`Q?nlADMs!qdRuzfwpGt<9p6X0E_z40xt z6~<@az42>NtvR~UN>c-%^m;0u(t!q>l>%*(~ek!?+a4Zk9qFEy>4k!-gJ5I+#&> z@S!utTWH|~1Q@J6Pguv3g>NcxK4ggTJi*qW2pgIEDWe_UF zpJ^KzE0~1YsK+gIj3xnFWlc@|?u*i9LTH1N6ZPb?@}p{|nyXgIeuV(kDg8vcDMA_u z%pl0Gc?lU3!>g1YyK-+Gdgxkuzy|U=}r{-KL#>X<88qPF_fUNl#)c zKX;`04vuI`->?Pl(Xq@8}4Buj$H+9%%CxP*u6szF&k>09aX zHv^ega;*mAiLGR+JGnXSnzvuP+RU$ec6XV4Uh)mHSa|{^467M|sD{tlN$mjwxO)tkPUp4_N2ar zzn2j5;mY_yavOy!6Znoq<%4^9aftD|-~-Q_&O`c<$D4e;#3gldi&E7kA!2gqyEJt_w57K{_b7OVZMJ(eCVoE9pD z{|Zy5pc3vQ74^bAn^<#f z<=eQc8f;adVuc!7PE!iwiI;!e>)no{$3UUk8mM5pli_DvQp*5o90zPC;&&{~ID7)elM@xzKz3ysxOD;%%X~^W`F-VJO zRLU=Ys}6s&`owzLpNfi?Yr*tETi)Ij8#!`UJ9HPLyZM&n+3d1H|#VmK0lF8Vd3$*~Gbd;7W z+1Mub2{$K?4`WHhyHcC9`Ij|~UoNsN@mT0;KD@ydB<;9*rsGM;sJ~U{iyxIufH#n~ z8Rpim;b)c~6_4W6vN?+TW#HJkX0~Ku#n*2Lpo~=EFx&pzA|e)ZB~~BC%fg3 z$0^`63prue%5;RxoBP#6?1MEX2a=-($SVPtUpB+$ugO|FAnM$FCDfSopjgIJG4;7i z29!?2AoGJh$u>R5CE~g0UEs5?+;H9Cm879Ie1=1!aDZzr_m8U34g}z~z?}c=ErP3% zcS<81q@bZ|>ikR+E9CYHTL;gzQi#$+e}P1p(l^=&ucG9Fj{;=rX`@D?3evx_F1r!Q zHvqrWK5H$Za`axWX+56dSApoiyVY>M z@(P$96KX;@hM>tvNu7R6tFr^If%uN%UJi%nr~CNPlu_s)5`X9Z;F&d^Xuo(m7gS-i@pe7chUNRkstzPn7HL%{A)A1*17!b|^az7sD1 z-CdyJ*rXc#CWZr)b!7};6$?qmN=YWR4JS^rca`glKi&`$#d{MAzw&Vp z{m_wu$_EU3rRn{$D#DYaw+XqStIaCK5`d?=QIU2WTy`b-$NZ6qjOvjMx1iv2y1%H9 zq(u?48|%Wh)Cqa7NqmaF$o@WxK&|zS@U5c88nVl3C($Q2lF&m~V)(wZ7$v8hnV8m`$))OY(!<>z@r7S8yK z&6=5{=_xs}y6o@&b4@@o)5$l=x$^6@r1zKZnbl^=d4ti!mP!@wEEOq-&YsM5mmQKo zqMSMla{seeJsNaZNNp#3gyl;o13viumF;)_9g2>V3$!2Arzz+@oNP3aKdUQMH=@nA zg2NZQA#~MULVG}YmJ&k+F8h~hD^q1de`w$BvTft~fL-~+7^dkR;VzO zm$Y$Bxj1esx>KkgxtIzx8mPWE02wlVfMOgn*AQ!184OHdSJnWdat(O7j&w$uT z*V>rk#wD_Po@=^G!b0WsC;nnr4(2SN{+1@L2#L_@y?!;!H|BYIG)gN0p{~x2|-(T-|L#?Lfyd{PlKX6qHf5|dzr^4NlV5hQ3tTJ^7mRv;-$xqaq!i7a@8;=lZ~c^Ud_c=QkHlUQ7^Zwh~SFJUHwIQp%Z{AsHN# zC=&MFT`eCK_WFk0D{*nw$-@xWw~pIwdf#gY zF<2|KsqxQxtTshD-2)JICU7mP$gsojuuM3u1J?4VD)+IE&~s65PnF38wx2KC6rL!$ znvZgfKL3_VzNSv#CqdY@h6-W<@qoc#P+tZf_MCgJ#KXU=^%zy zmrfx^x8P&0-}%GrSTmqh`8QZ5IMbT3ObFEWZ}iBXu6C%K|Jc03V>)r~FlP|yul`!w zqxH+Z$Gp|Ne_C1YJol2n{n5dx%0^vQgSdaqY8v$>Kic+k&m%4*CSB}qp<_%DC$=19bpY<;>4o4xi`Hu8gl(TIaZ{7A$yNT?IO z%hl!MiKUH4#6>^`B;%>`pxB68;vbSHQjov#4bcX^F~T&fr4W+&eTsDbj!w`lpU(jf z*jF=*-|&8WO7t7`O2`!Kd>H1W+`2`6d|w=4;cD4QzZh^6(q`wi#mt31aIxZadg>k& z|GMpu@g{T9B|Mx^QGjs^8kJ0=!p4u;dNtiu$J~0B`B?YVX}+SRaN^*W8ab4Iu#Q=N z9^~;0Irw#8^kC41GhX!7S^)M2vDjjOB)Uwe%5&C2nPBZY`mFtW9J|RmXub7M7(heX z17nTD8|ry4L^L8AnSmTzqJE&M{Gzb$`2DDozio;@*)J;Ep0hb%v&^lka2&(_C4%~| z><~H*EE826Os(q|$?nTi@=AwlbS8o)7L(Jvi@gNvSiB+RAAdwPgg4Ov~!yAgZ zDRFU_qO|B(5weC6aY+M*Q(T~eirX~oIg(dpj!c1lAuHn0d1I!Pr%A#D?3l00q{!+N z*YKL206UbXqT+gI+=4uzZoB8FFktAXMZ~12wRe{(x>hLFWRJuFQLKg>i@pjk{v<8q z(=2`KDYo8e-2U`4GG@2hY={}D((A(SrW;XnYsY|Y(V~OiK0BsT$ZQ2e40REkyoGuH zkmMELdek{6^=#;*>1StuT@DYM5vbf?wA371hsg&vsj zRp<*Or$$-i2}QI!j@?E^Ux2)zBw!S1YW-B`h`WsaQVB>^drw8uu^hJ3H2Mf5@nj;t zQQZNb zPDvLlkMR*b)ikrfY+Gi%coV}im1$`Ao4qDsarnm--biYq3L{d%K4WALrq5c-^X2kn zCI&anL>Fsb@m^m(E^OdZIRzBZrU!gA-%+_!QO{&GUhOv9x13&qeom9=2-1qk_>sNN z?cW$O-0BhXJL%@q|MeSzA94O1@~c<7zP7;T#-nMzjo$57j}c!H#)2;jPK_T0wwO92_x#Eg)6WeqPEL+G09agH34y65xa*sGu`|$Q z6eCdyb{*1~PgWJp{IOC`Hj&LYkwebsn6p!P5DifAL+~Qp1~Ff(9W+?B8L^h5Jp$;( zTD7I*eGUpE|H1th?O$EGG7m4R+n5yku{qWFVX{%Cd+_UlO1Mri zy$u?WsU?F@Dxrv4f;jv<4^plDUhlS*nN!*fBb+{V;vEHa_(?`SlmdWew&L#`wM4cq zS~TQ3vD$GxWb(lmZhw<+Db|Qs@ts=79Zy_@2SGI_o!`F7vRUa`>5m|$BWWPC=S3q4CB@SH9YUb)!pi&uZoPpApt zhJ-*tYAN?dH!q*_hPVap>ByuiRowSO<$nhlv_0Rf9IUp~F*a&+nEngjw%sg$+{=i$ z*4?3vncPzP!&@!g+WG&^ghHaBRAQ7v9a%c^lJQ<(4mSii*~6TJrE72z2TB zlZp{?pLBx4k-cg925y~bT5;waE`@?OneJ7>4Qw{^`KJm~+_V8>P>vp+>x-t)vJw%P zpWOtkWhei=y3eo#jcMUyU(YqbR24M#t?XJytHG))k&H9V)X>YvL{kr8z65`7mJLRR z!{u}8`JfgAS@S6i(`j?oqib)leP8SmB~K4wtrsrU_Gx^OLa5MTMMPW{l&xeH%kiEp zWHbm*dbc=W%6}XZ&xrFnqUFxt{nahK%$a4L|A3)?NXa0@x-77fk=YsqO-qW<<|#snpj~By8yH0+B=zN%R_M)de8E#D9?pxsB<+yc$fkNMh%q`8k|S z3nk`pWFiJw?eA`uw4H{VC$hOAu$PGeX5`2tkz%W+LcdW}b$@7a?a$VdCFjf2#>~DA zd}>IWYAI96oz!=2X&bg73Nb($3jY!cvF34|aKIMh_V>%NsYIHg6tx5uEH$~Q_eMYicX-a91m z6!H?7NK67KOa&QgS~#4tqIKW$V>Ts!#XX?JFi1$@NYlt+sY!`TNqinia@&h{uMTP# z;q!BI`-#mP`NQwV6XNA@D^$llH;3!rU@Q8z1DkH=-BMRWmk9FXOd4y0L3Qr_$A+x% z_4Gyml0O~`Q!q4xuo8n-W{*yu?oXS!Uf4-UEyqVkBaI}L$_#X<{W9AwE9=kJ zBqQ~)Pby)<-u|;MD0S8FcVvlXoe>gcA1@Wh&cl$i>>=bUuH*UKvB-TjUf3g0V}| z%UumnNgAGGo!RO_PrMBAZFE1Mx_$w$wXj8Ybvs{GbAgDIQg9{~yuXqGSf^YO-#4P6 zU#vFKKW4=t%5Qc9g#%hFF3uqO3p=bwxKT&%9*&GI3!wWAJ_z+LoY9=>^GpBsDYdf( z{FN9)oh@|8qXW%q8Hc7tU8<`7f${LI58f-8;`tAQGF}IsPc&7P1oz|vmQwVqUKu=A z$*N=z^8Oa99J-jbGBBO5-!&T^XMWJoMGY#%Jd$B!D-F8$#K7luHcyzrZS6FDk|(2T z16uCKr8^Kpswulv-xPX_Z#Z}|J*JAJGuN`(FnwHU-0JRu-y|UadjpUgLuLAZ1bVbR z0>yF$CQAF;h{{+8i2h{!X>eN4+pXPV`aA#>x0K$|orpmLdSh2r9!HZ?6Bp5mO~_;> zYn0Xs-%RylU{g{ed|V(wn%D?wW!Yhn$+thWYr55|1-;onj~(zl2GkywMqCK zoEXO0E0axX;r6Q%!3xZD0T)52z=Bm>O=Uz4mF^|T!Qy~5KG$yEipinD_Qr$9o`MbS zAnTcCsTThe2X?f16Ce%Z!K3@>el{)&RrGe$rB^+}{3R>q1s@<|Q)k@nilShI;(@6T z8Xt*qX04;Ilp*sW>VhqQITtbBj~6<4&l|ElR?{<6kl7!AQ5eUF5#*8bDlwAax8Tiue((LI_BpMJ^{R37EL=R7n zqyvY91h**@yepdtW%%e;P!o|` zr_%4rAMs@hG0`}kG2Fy8YQ83tJQz3B2b0;+FLcE`!8Dhf;QV79HGr`=Ri>HW^$Ov^lPBHxfJ4OT1qr^#50go3D z&LIskQ^X;}W{Lthq@IA>Y~z8th}`VI?RC;O`EZaa2Jm)@ZqG!o}+#_0o?8 zpH?0+DC~*Dt=&kEC1GUW=T>7VH?d{>8A#qD#;}gpDJr5}M4Ipxr?wOS1_}k&bLfRe zZp6ut(WXOHKrBWXAWqGb!SU6uO3_j29O(U46niDqy8S)qQ~CAIY_<iX^IT`O-`u8~G(ZYw~0w%-I(z*=dHK5uJfcb91&OUMLvJaXPAqPz6}ohzj1&k zc4eCkEHato?|iK6hg}v-6x$>e#p$0tGB_-FNgxsUoMKp)JJu*|Z}O{Gx7-e21O)*D ze~i{dUCFf~Fh7K1Ylkq-hE2#5zUTcB2reFYe#@9j8ggJ$cvGUw-+l&do5u_cF3~8* zjwfmA7nexT`O1b$1X#4+w}o^dFO~Y`>TW4_+>ZD;jA|?HRm;+vwGNS0k@K)x}x#OVhUBIPRqz1U1J|< z0S@Xt?#9$(w4f$F4t^fUCvDmH1h@k~Blb$>71(R|#VE7*I|Y%>I>2E}n*{_YSl)*$y#( zVK%p6lxUB676#`DDi7GA&|wQl6j0E!Jy>Y#>JD1OM9(b1l%kgL<>poiFI3N-1?v2x zPvtk5`jYs9;0NUdBn--#p1j#G`2_aJp5sPv@^5ne+_2#Cob;vDBSDp}tpqYl*yHX2 zvcEpdBViK{_9#p51Ol6JgAB<;4b#FJL0!g#DnXlEieVV=bfG#sJSkssF$CyAcM{?} zlYzlWy`jOZaFfdyTs*8sHjKfGm(en?ZL8%B;2AjPpLXr6lE^;KYI2>qH0csyBL2?Ukznho1rp^c3{C&U~m} z4=^C#FzbaInBsNOCJ0srn>hqMl*{pb&|Y*(0djaa;3PiSJS|-K z6f|b8CPMS&egr1ZDM=Qd&w&H`eI&3*Z06x{Hys4*qizsV-UgXmh>hHnVP=79Xu=$-Eb@7kqT^i-%cq`pZ4r}w4#LSl zz4~CnH<(F%_}y9qGW;S2&COL=g+dXufmaK5)1EtW2g}$h(IGG?Fx54U$YD`_$hTh2 zqy1QKuAU8^MhD1=pKEU0zdjNP$KBFEg^V3kscuLsGJ;Ne$s()qvV^8jyYfYzU?{5;gitxJkl|QOio{pHeCb6?_ zh|q&P&0bC4hVra}AF=PPr+qDl1&32`IX{N1=u@SbvPh*a5>?m;Ob ziJXK#K}lnv1W9WSPKJAyaq{~t>CYwf3#jyIY#uNa-L5a_;K6+gN3BCODwB@QNq}3x zQGdJf6zQ4$PLp!IZI4h!h1<$z*{Xg!;+Rfkv<$#-J6X&*f7-Hb)aooB24^b#YL@L9 z;+EE7-+JL1ID!F6=jWKIpJQ0ztKmUE^-2=MbL(-tT@duESCP4Ogeh6V=tohGq2A1* zn}Udc-w4&lM%(L(5$)^y2{%b7`tH@DOMx}s;1*2Xvc2a)<5U73P<{(&l3oK0}+fViWDaOBd zxmsukR_SAN1SJ;O3?;06ylvM)U-X{oD$0%5i=bzk-ya(_{{+1jgqGI%<41K(rIv9W zB%IBVG{Flkjl9%$umy2V;3hAjQpUMobTWT?acso6l|&R^985twp2cUGt5lw?%E!Aw zhn#eUobva0Vqa6j_x2M;8$Dt2%(Z?crX%ie9;z0R-NBby7v~idvX%^T=sR+;`KO#P zAlLW?6s@smgSdY9g;b79`Pokgj#4Lbz+L5RvYD822HBQ`iDCxJ_wvub=ufgPT%obW zuMk#U;mvfbr!+v?@Em|%&b61?~?;3?4Sp(rCZuXK>R@9{;!9vsG zNuTG&{YaK?FcS7e9EDwnXr ztEXV?(Ok4?XWSn^K{i;FdTyogHz!gxPaIR8u(83(`{W=FjFmyas;r;>oB{`6kt4fySZB2 zg7-p?lwY{u#Y;yns)H&fh#Xm*s3SP-&2q6md%|0on>!8+DKe?&`egBrNxV_X17*(@ zh5uw=;XrHMLUsrZS==5}YPQ40gts>`q=!Zkf%p&$e;>AQY_vKskD=FlUXeYH#C!?&5ToQwhqOyx;|Lj^rZWzPLYAuALG6XrcLDJ4``B<-Lm zJ(Dun=oYQk6-@}CisL4+aK_puEOY(;E*l*&@u?rzv)U7mPKoE?3aQgafg*jv51;En_4FoRPiOV4*$b)ov&japv4Qy$44p;TvaG=qV$$rRI z`&6p5a38wHjg-5$$o4BvG; zUI4RTQ<8!P1ce0#s9u;K)k<*ifG@pgCdBzsoYaQ-B*%=cH40P{WswP-w0BCHW|++A zf(WG#C_*q)hUQ4tqvo1A0v$-0_TMlqmQ`Xg5PM+X)W<;uF@n~sogyb4Wznb0(gpe( z=O7`JrlMw4lwA@+0Yo95TDHAMfcQx!M6g-D+A%(1mnYxd#?W;2MV}`y{qJ^wf>d(2#ynP! zivxsaNPZ&KXWv}aW)J`rO9y_glhQ^UonqlJLLfUwKpiz^!3p^DUkM5dICt=d{2Yz6 z=?GpCsn9Xv+0~|l^{f3YT;rL%rGj|Dj6>jaLll&P$$ zndg!Jx;t)2{{3nYXe^pW4A_3`dBz}0u|l+nDJ3YB{;kF6Ov4>Qse;qtj8#10e@?53 zv`Id@hIf(0)B3bk=Ku;ZwLl8IpF0g%G?ZhfWc>icobwMhwT<^P()a45aGh3V;v)Iv zV@X1ym4$oa1j44=#q}a#CFrq^0IvfTa?|~%nzO>?ei2(~InnJt%Eg$-H31=61wb2?!O&73pdI6R7UC#8!NT%O#*8K%W`|2#!nws+>)?DgH7P2f^Seh z<$&S+DT33Ju}|ER>BdhCF@+XmZqAwn|D2LQ5u^g0x8M)s>vUSxsUHo3UX?5BcpkQq z|3-0I9JgOQ&tdGkuw?hjpNC=agv_3{60OL1L!j+5@4ik}E-ksO*luWO#Ifo*<$L8_ z`{X=d$XZ7S9t%iULf4Ma==$_2K>vF$CB_dce!BN8oo=01t+D^@K}_z2^K$oFD~BI2KtgvR*(;F~UnldD6gn zW?sZ>cB}ldpsR(q@RB7gUUudi2^e&E`Tkg~_;sD0IbO(GrNVI-WGU=`<9fe?ZVv z>Hl>BO#3up-UCv}*9B--h_kQf)t{SNav{Uyyh`pXCun-TpMS$!`E8pgDd9KyYSSL)!G7HOqg8>tVp>K*gy(v+0Bn6(e$eSS3DWK6VA8S(<}%reo7*KZ zpIi6vaJq?IvNa#3TJ;v(=E@K^YBDZp^55`_xgqxg{Dx9)>`;CrFkg-IW$oiQJ%Ro}-#LQcMM$wJDDH z7r{g&M$W^L*lL2@O*H-+hn#sBE(&v&faVND^8AvP0P-09h;hrKWZ`>Ny_I%LqGVan z-tv>gZ5l1$3CyKi zF`ZV$x!Hy25s>+I_Q#i8H*V2(`#P(v`2~4l2PF;Dh&P|EmaIS0QFG{uD|ks2PQB~Q zc!Ci#5(7ouZDc{dHDs3Z|x#?qrmY(x#`(SKo4LTpbmrtZTTzM7@DEhWjn=4 zNdzgt#5}K!I7daJI+l=>e&VX?WPV>KNyZ_*ebl$}miDB+7Cczs^G-0K5M7C#f<(fb z$3)S{4b+lBBQY4hRy%bJcU_}^iCQR{Hk$jJm;kXp`i=nUmZlN~IwLNR-}9y-!526M za_0|RH7@(pOTk#thY~X**F-BT za5tCW&F~ftG4l*R&hzsn{~ajvzu!0u2xg}xEePx;yP+a)Pw>-oCaiHP{iy5|wMOWw^yi=G zmFksWzBhdgwqfS`eem0#ZPD{fpayl9>Tq9yN|-Edzqln%8c0i|IlJ{`+mvwjv*I~@ z-6eiOXW8tRPV~J}?$_sj*3P1O;MsP6U7E?K&r0w=`x%x(jb-%cWSwX7%b8XR7{ zs`ZeSm(=t~^SE>9MRlOKA&zS{{hiVWF7#6*qiv?!sD2-qB^Hea#zgDuS|fB8u8tlZ z@9vmlwQ)gH98(#XU)G7~QaMUN2oj0CKhWr;3n_&Dk_I`L3WFJf?z)%Tx=jMgwln;_ zj!G)5^iyN61TspyY2MzvZr-tOG$DnzyFSkIP83DhOEDKbAT z9a|tBDme+*5vpOayQ5B>XbvfFY&OrgBGgJ}yvbraQEj3IVdz`bFzsv2&IpF_5AOHN zIM+}lM&#C0uFtv#J^L|!b0_+%G#6fn=W^!Uh&$VB^+B8|p!kANwTzUmLuMm*;-#|6 zX`Y4ZivGa$4xf|lwMGoHoU_a&lV^#h6js8e#E^F%?d~EWZ$7z5mId~r8PG(UN|Hmo z(Z8BFqxXr#>Kzn5h;*Gk0p}G28?s<2DZE9adN?ZU8mssJgfhVm_2UtH1Z=BA4oN$ig8=;JN3Zzi6!Zk*AP!!nFh5U}HtmAQdvPS>~JqPsR ztK01DajhQEVminQ^m#cCY!>w8kHG0r%g!`f@F^}f&h zg!qC6qM#8dz^SD_j9z$EeD4`2xR9Fe(qZ`_hka4F@@V4Gh9|F&-KK3DeTU>g_X;K3 zeb-IQUW2v+(aT+yUjuRCgDoOzYf5r?=d%qqx`-1Fr+E~u zYH9w()lHUPA$f}j_=Mu`<^%s+_vV8MR_KmNJE}PWZvh4!SpU3+?e1!1Y2r+V~ia54+l)|_Rwnnz$kL1}hKDE0^v>=|Nc5|Y=;3nd{ydfDh zq(Em!ze=kd1T7gAB#oOZMb8)06O1;R3>Kn9rBvdEqXx}Fa<&FSXcZO+sc?vlI3SLT zm>dWapwI)Dtogfv5-Nc-?l}*?m7E$aMOP2W^?d*3I!WTB6TZl80t~Ki5ItyEP#k-% zvjo9wD26RItO9x-Exf1#6T5WDbh?mbcHTI8|DbNo=@qeqIZ4|t35*Dd=q3nxoQq1( zL?ZaSkmbZRmQX^N&b6ha8-0E`{)(d|6;f@Eg@8@ALf!+uwWC`H*tj%4PY3kn{>5e* zTiqh>9#Br?wh1<@BY(pVLO;DnUnykg?dFaf?4K3#c#2?O?3J3k%arJHe$AikMqP+( z?`qKoE)QQAOF9rXXisGYxcT$hx&g+`_f3w|xqx*555cWQ3_uYYEFJf1S(KU13?CaJ zKNt3W^@sJ(5%xKPdv3EuLAx_U7xpxAuvPy;KkQXaDS;FK+Y;!mPPp>;(Be!ETwd=( zfS%yJ3uO^;NDwUyxD3opkgI}qw>3b57V!4-VONzA`a7f5 zxUL?9l8~9mqmn3bpY23b!S)=9Tl@_5=UKFsOpr!_wdvu~lf6KVqea`nPR;(#a=YrK ztke-wZI_xN_$(Ys)G!>vjkp39hG{8r! zrQn7y!Bvk=rCwYe9$}-vA%kpjkkBGn@>6D#hNLyG?RY}T;9fIF>& zVE4uolQVb_I+Q$+#}t9tt2yhOZ?&&HTJec>X#FO(_5AegJ+M2!>clVr$} z+&$ZWyW|46AsP=dFbFxq-UQSWC7A<@?yg37^n7#9dU`~PS$v79EV>eid}yb_w=3oq zRmX!c7`)Hd{2+2fb5nzTt=ea&ka0kVc>o9ncgFgP`DZR1!y_WYqpA(t)qo7v*kA)f?TmJ>38L z8BjUNdos8$JkH2su+o5ND1q}clT`qY1~lw`IQ!eZgncOCx$E^&Q~=Q2mjmvWZrgFZ z(|{5@sWP?`8%1d4O8c~V)srO_#UHhaT&dRku)K5@uDp%Xou_dPh;%Il;=>~3YoR=W z3@!CS>9~C$H|A%k(gflcD6D+HSK+DssSHC$?%!H?49Vj2+g9tmih_0rQ?C!q)*ite zPRtvG%ie(Ybb)E0%k>j`$7-WF3-QNga0DQqGaEpbSrzE(nrvS4iSamDIVkJE!Ggm= z0$Mdi?FQk}`|-VQBpV>iCyVg=cG*Lo&Zg;6hGt;g&W|Q@3xoXqNarj|`&3p#`8QoV zKxkjki3LnQJ^-nemg*|;S6>yudAw9d-&MT83r%q#!mF?1U%6i;rao+F1bAec(!x%X zXv(msANP(#M36`>-L>K;s=yR=>F}M7mhk_yn=iT88LdRR{Gr=`!~25_m(3{aE%7O+ zrR!??W25;HdanC;NAu@(rATzri_~8SC7CX9n3I7&G(yHKs(=wS>UKn{sP#znJ)skj zLPo>wur#ac{bNLeQnl5^f}5!E9Mh`h>6q839C$UbNT8jmP&Z)uZtgE9MfaQ}neT~v%B_Htm5NBW*Rz;x1DKICn)V@tXg#!?ROWG}eio;Ie&ZAFd=Pf|3o-;Y z&xjHc#=IEAH=!R(AvbVDh{iBnMs$ww)|E|JTR3uLol6fuGTJOkvDIWw#i&=}KAh=2 zgBdz8NUyTOEXGcZCTjf3?OiBE7}lRF<`F!VkPRlyz9=zUTc)YY$r((%j*|@!B8o@z z@eKK>hrdb6)&MJAKFMz{+moq*-VJ_97gPZ51Z;zg;drctOhtmX**fnEw5>nf+tvKi z@~;IhN;K?tz<3lBt{bpL&`H+MF7YGg0Y=J6DG!McSYyM?phlHEiZGF7&8 zTl>Hm+K<###$7pppRk<}&2lgW)F$DC4GR~fJ6P)e60!Hgp%g6ipMJ{=&U4ttacp_8 zpH!^`VlXn1xpl(zZ-%3f-ngr%t_o=i2a5(^#%fq+H z3h*BVvI5O1hN$_gRW|Ix(dcmQ_QSpt8ofYlH+N$9Nr3k?Tkj>zB;19ORn@5>{}d@KBjbFv)VD@lpH+g`kckGt#Cvo8Wg``_ccu`k{ZC_lc z7EvZgkp>pa3thbe9FVTfMr1Yt7bMjZUA{ZOr*;Mih0ULkw2r)hqSKcSDS*>618v+L z|GN^hTfVN3>J4jpPVon>j*D1KJv|dxXcBBU;|0K=<#BigLlk@6HRoTIQN!EM}~PqT`Zf{HUg*`$iF;U`!y3fD-)Mg6JGl~l*!_0AKFL?E*`iJ^XNl=P>d|f)_ z&{%d-X;BvbQqb3M;}(9VB*31EJqvz!Xpy9pA#+R2{Kw4Vuv?lUIO9G4z%3cNc9~4? zTYSVEGC1HfBq{?5hK6ejlJx>eP)3~5N+|LG@d@UUzbV4`W+eG;{cr9JlWs-=O9~~V z5?mekUK#wA=ecWcX;R|;ub+XGL_@#xfv^-YYMwNfG)5I80rJ3ItF{}j(bRXgSgb-YzDm{Wl4r7l#n`i5^dWSM6yoqw?kl(MgOcl5!svT#zc4sAbb$uDIdu!?Ff zouo%|e;tu93;lTbXNT%BWcJ_XsBRBQ4KNJGpu@ZqlcWx5SS8)w7BaJ?&f)BZMJM`O z7)0^~9`2$J#`z>8w9(cVVTVm6ib#V=Iz^3(6QTWu@(U~$nxa{|eyTzGlz|VqQaHH6 z?`!7~h80&DnHa@eCT5Ba6r7NCvOlI)D1}r4VDOE!p)7J=r1vi5>laN*>!wWJ&q_de zJhV9Maf}HD8a7(s-z)y$2Q7>1_lFB&zGMviI~GR?qL-Ws>|!dY`z6#1o(5|}KNklo z<>$OC#ALy;Zg5%UI9R0N;MhrqPw*qGT3&EVfq~b+9~gWEYjpE~GRh}{nGwptZ|F=|Ljjh9``Q@dK)a}-VaM$oE&R>!YtsrPl&SN|H^Zy>Kd3%C z6#`eebYhx>n*Y!WczF;Gm-p!%7sirxPB+`Cg%ABghNLn=0F4K+(619XI$hj2M3HFKB<| zQW1Ow?f7zO?=VF+U^Mpg2h@QAU~3(494ZWXZuD-6o@$a1rX_!Yg~0C z8==XufK{Nx+=#Rgn?2u5gq}muF4p;{+%m}M2Or!5=#!BWtPV92_5xooy;51@T3Oq@ zjanFqU18l9^JhvYy+pE_=PuV7ZE^~S8Z?gMLuI^M-FWPMF)TmVg6%~9nnKU?Sz@)u z=Z=kCdF@Wjoy0YAVW8BvPW%%j(Hd{?y>;}Tf2?Z0?1shgT0md)%}R=-*e!|-w{?#_ zE*B>GE#dIbVSoJxFAu6IZRCU5!=@ae3nx6AM+GU&_eM*e}Z=);%El7$G+GES?v;Mn! z1T$Ea0U?-DrQH16U3+Rj(J9UpWc=Z#GtPbqHmxEGQelq}d7N>(ZDcDxPVr3pl8_d1 z0XGUIPnn~hJw<6VRzw*dzp4&@2O zDKg#$#)?SsAFY*h$B@TYyObS(O(-P5j&I=CcU7OQ-dVr?idIn z_Yc+JfJZB4cgIx!Z2x3uKaj^1!m{|uG`@cTp zsqdbvyA7JqlOp4M$>x(zSLbEYD(1wP=`s7GDkd>iau$UOqq7Gdan+P%Vl$gw&);^b)MwouAk*jM2My%2Hw2L*S zP901-R^wm%{2i7Rs;KT$VvL#67!L@nVTF3%$N=?%3s|uy9lW$>IUc1ByUSOB(4$s? z416yNFbmKkBgU9OT_=gx9^Lfw3AhNw$m1pIvjpkWJZRpW(of|7_#h?rxw=!}!T%c> zTzGfKPekkKdf_Xt1P%Fjdn`@PDrgaHE{pa3l)Nr26B!?73qG8vc=20Vd<0+;xZqkU zU=>WmdA-y3*mTm!NV;;Q8=CBHF+BvZfvH$LIsJsb0+$Pov-Fp{{f4V)yx?-?+v#M{ zo9VBkwgaVSM|NQ;Oql*xm{VE&{rA28DPPV115(1!pj9y<(3T+YcQq=w%=$qeUkw@TW(6&meThLX@C!gJU~{X zOJvIbR*ou}pi4uko%f~L@M`Z*;nflD&oYH`xRJZTNwy00NKl5g!UJpj7$c3E(tm4_ zhY4JH5O72;^z@9SrKMV~h`;sDNJ>Qy5GgqYm{E=}r@dnkjRXVURHT`R_5Ktyp1|NZ zY!|5Y>rNG&nMTT8$-Oq9(Q~?|u+zH#iQs+xdN_whuDQ4=I+@N=kz5ciz^uwAYB-o* zA7+LFoo2W1Hu_FV*jE5A2e6JRo*%pR2dvP2fX>~OG%0(SDhNbK{@RiK=VYwNidC6? zQ#TT;ytAf*quFLC81_N;9`8S#%Kq&&wTDE+pCiNvv3s4F98MKRJ_KE&uyy3YB?CB4 zWdwyz0wHHa1UhNO4KbIs7&e`P%JLoJ@fDy4w}Iq|bGaXCRA|@a2>by&BDMWGP)Y5x z4C~7DSe4d&V|k85q;VVIZ4oui3uNc34Hr?pbyQN$lBWpmSYJs&Y&OFRMI(?nnPcW1MX=l{p;CcJ&u#a zZOWl}bui!4mr)(He+mdDi^EdN;IfgpW7)my0CMOq(OZDWvgTmFGMu017EBbP4A{K! zq$I%R+ccXm(d#}KbSt+#2<_fVZ&$Hx)&U*I8o*2{=$&Dd z*_p0gGEwmARzrxldC#@{mYkiXrmk+YE&Xm23EbCz0Hl=DDKG$dnmmTc9fgI3#XTIS zy^s#I|Jj-8L%kw#TNM01vB%AZ85foRcBeg1N|Pcs!`SCg{_yKZ=LCqWrHzeT78yXD zWvl}H9+EhyjNQ^4pD%giIX!wqp8O?jTh6`xeQ4w|aTfR$Dr%gYWvWe4^4L#*l=Tk= zM1F45aUh1lLgYTJnTKetE8y~B8EG!!MtK}9Y|g0x^63P(t$rkn4D-LlJei(&$!wpJazEG;cZFzEd$@E}Pv+)w zjox=OT}o$q#v(G4q?OJ6&{ap0uB~}ZS7*%)e7Uc9Oq=x|lw(77PL;4ejcat>Q@Z&` zA_s)jm!OjhI7xL>#+F(LN`WXY#@X?5?7p*&bhVB&mAAs$+zcmDkKh*q`I(IXSmTcI z&+p}K8zY`)UZE=N8F*%4xEyzSs3d$UYz3WtBcZ2V10CO7zQP}z9{wp7^>U~E8u0h9 z_UP^Sr!bKKdSyB>GY9-$Vk0TATmCUi_j^^-QB=;5H<$#;cAwKowk@uq<~;z@DlW?P zjcrh&!^2mh4!{9tR@# zqXku@2`~et?7HviuaP5I7+M7}r!fV}X74>;^RZP=b!5T9-d%qvl*=967QRXo@sG>i z=3N{8UyyoJ3~DImKPoG0>v@wPI_$tPr;YW{5$(M=0m7z zPxl#pHXq$=)vDlD|CGq|z@D925iUT8wfzEx_0@g*|TXdpcFm z_5`J58P$5Ek7)es6*i__N!+J740Ha)|4x|hSfB?UkLq6#fwQ(&2HR{y2@Z8%ZDqMm z(De0RJ#TWB**r&4@i(J3Qfd5$8T$@DD7$yMUD^v6D=J9YBci(*? zh$p@f=Blfue);gdE*Z>wxQOSYsN2BT+d$i5s9iE}PF)t7jABRk=(!q)g1rg8A1_LS zyDld}1Bs!p9f^Ug!Ms~{k>9nbyWAH_Jt=kOa< zdMWp}Xsmf>FbpTxc^(FTJ))KpS>TiN&jjDMI4Nz9=fj{U6r$i`L}kdU&ZVEtcKvK& zT@M+b^@KNJvdN>FfpK67p$}S`^+snaAi=+uTsyTsD;wz*UXRTf7Zs(yr~F+qJu$d- z++zRVF8UhxRuKj;Z$KyP6G3zUkX_BDU}}em+ZOV4e|Z38&L<}(=G&uR=XcM-X5ey) z2Xz7=q`a1_0ih;oDxUUTKZEmkSAMd z;Q%5O01D=RS3vyA6e77_o`Ox&=k@B`iR-H6j%LfvTL87!%tvs~yrul13ESfbBhjMN zX}=bD_vA{{FEJMBcbet@`uulOq-Ce@a)<_6)np^~A@}u32I=*I-%k?ua~3KA_rLCK z`adr{TI6n7=8BIoYx&5-qS~OMV}9vAE64nQdRj$I*YfQZ#1p*`HS?V#AS?}|C0*rW ze*(S6Z`&rm;b=6kz!PqTv;3`0{T&aii?a)&M)i@tISMo}IW^^vY|)ULN&MEG?U=|U z^8x-M(kx`-2UBd#cZRZywgTn&l@@?yYzbEbducEv%9H8+WyYz&#Vp@^E9?D<|fKUaxG?!!7wdQ3?J&DC(r#s!ahOecYyTKgK|N=Jk+ zgnXMw!bCP0GInim03PzoPBj;&sP*wh_{D3*yt>xJ#QpIdAzUd$EBx1M;OnDtNVe$7 zwHSlF5Fe|E9gRy{*rQf~``-;pec;I000GcHX%EhlL^eVK^1D91ZLMDlm?;|YO5u{* z!{rcU%d}~O!Dteb>NCLgqpp0%lvar1ih?2AA>ut!+jhL5#uZH3E(H&-0+pJYTE`D( zlF_v|B5pOFQ+9Xur4GqTG;C5(B?HO~SOr>2K98?nyCTJ z4M{Mk4&YUqT#jI$69>c9xHBnyn}u8x)v~?ctdz}{MWCRalGkN%}|l+*1{TKUfb=X+rm5A>^ANJeRbef`EJBxr4$WMZPPw>A=9 ze-f~dJ~ho>>Pr+9vdZ;uisTgW;d{!Cgtz?cjmIKvPqeu@gn%+g7C&`tv(i!*8E%3h z7+-N||M_V16MqhqW`)-RPH$gtsTE)rdbslZ{OD`xez3JEEu2#*Gxz?#}R2;A=mk%+Z92NDy!|Bv0C1P&rkLd zg(qwtSXVc}$G5^lbr(*b$WPz9^U4Y#~_jUom%=|#zmqD3B4+1mUt=x z()TFJjZ40JD=%5 z-=xiCBrpWMDkK>&Ox5T;>M!oLf-gx<;w?5wOm%8tp)-#+f3E&uxy~Nwy|!^2!ms;P zSJNl2a(nTcwMWU6?CLkUDT%#r_P<6#{A6hIuio~269@Y#wb?OpI36oPY%9re{VF9d ztwWa^ckVf)i2laQDz`mCFQJGSKJwpLtLS3V^6KutXDs9!DquN}-7)Gn{W!#m6#K;a z6ms|y_km2aWqlrpaf|e0nKMp6NRTMpSl9c&oxfi8lumeUeHeoCaGYWMeXc_{ZsRmz zxMo$Nlq7l*4I_VxFed%l6RSJ&gnmX-B9^5g_%HK}V;)8joA{B;7{<*_wEhRDoSX;T zKeFm|9)N_`s8dGp*a%K`ab8v8$rJg1_;F>SGMEW1?B*WM&({+P9Hb>2~9Awp$nAd$ihAloQ~oAWoW4)Tp^5D4IqxR_;Hr3ioJlyeC(#LOY>O$7~j zt%gXmE+|ztTTOF*pN~&FBe6XS!OfYnQQJL3vNiw^&14Rp#)eIX1;prxJ-9 zMg?imMLeNiP4P$9cXP5ZjS`ySwPqTzRaY-1IaGTVtwrYtX7sK)U@OxYv zaO#Zl9NWcX3a2G+mz3BA6@~Kl-(NTHc`qt6G*w`F@ng{5>zP-7$2^2&aQEMTi#A`{ z;Tq0w3j2l_Og+@Fze7GJjRleoZ62malviZK=rvzA8L# z3jzR!&;pCqUZ@H9dQH9pT7_LrmXOJRjbRk;S608eAE#&=sn+HELjC@ZdTXIE3ni1! zz3A2{k2u#QW$GN~M!n zRr?85h5C>$s!bQaRF>!ZID%RzwWL`YLt1Cc0j$%eQ-EUyjnpD(q!I*Wy;MCC!D7D+ zF9pj?0f`&LhwoBAAR#SD!-@qE1A>dB03tVE4hl^699E9>O zz06@Cr<*AQW~oYTY|@YMa)BUK9IX(s6)Fnp6ldQ9toCjEk`hRXKfO-Wn!K`6syzI~ z4juzFw~vxvff^RuURrIIX~IdzrP5YEW`(!4Y~Abm5IHuzf~tfgP?#Nz^RCkn-j8WdD!<(W4O)zg93BOw0W=W>w78JQ& z7>4oF6tAl>PyzLBmc>8-xp;-%7EA2N!LdtP9y{Q;l5lgnt_+0PrO0m!10GHiq)N3t zFS@)=Wrp!TM}Zrh{O+g2vKHyg>+{u&awA|SI;Z`tQ{Z2-mLq;Tz93W=bhz_cOPI2K)@_;6mFA^7Y@LQsXZb{rF#qH0q|M@>9B1pzK zQGpomnisXRwD9444Y~MPCYKFXWcc$3q^R1dXQ0M7cnefmZTD0M+Fc|VF1Qa$HVVK$ zOSz9whi$r3oEEwQ18bn3r)0=glm69|F2N#BH}2(@0_JG66GXDgLg#S#il75!z|O{* zN1~z!T_GG9x1hivV#c)6L2R?;v;V`Ds=u@-nctcC9DX3g6qR5mrGq984mXQ6i^pN9 zXz6_5?FmlK;7?eW(Gj*mjURMty1xC$T+GtPE(wOd!yw{{(rOrtSI=TLZ3DtI!#dwm zOE-sfQGOZbjNWW?zXB#I=VTun<18}KXUgCO7j$a{vekcj6`-;45B6c35dr+gA@XRe z^!|qRzXZ*(YG7F{I2grP0=sg0^D5C7r?~F{5C6Jmw)2Us2BTRfsj=sMcdPg}8V|mv zm~UzqGh4=0Z$)!0u?+iY{m{w30rGE8?t$6d9M8041NNt!=c_9>_nahAuW3BiD=*72 zl}BJmof8Q!!Is|5@n?aWXc^zbb zNPPbh@vramWDd*ke~$@Qd~a@4T?`)%**Ei##p$ZIq>@BO>7gCoPqD zJ8kEfFzhOX0U!KJkKk}O47=_*kp~XjS%y>oBLD}Hz77Oxh_&tf1t-_QHb!FE_1zlb zjn>A@NpzS&L*qDQb%(y;&L_ZoeKI2h+$iIS@T0cC*sxyL}`%NGOzT`MJL z4o6}2O_g}rpfF~4X1q9^$$ZLiMrk1avBLrHFTofKj?eACKUI}Yx(kJ7178xI$t}@X z+_1Itm=_faX)<}r`cc=Gym?Jdpj?ryZFKiFh?Y8vWoz?)DmR35yMF;bYd zm2AfR&wJ_`CPkKgE7XeRNBsJKFI>yB)7uQDV+MX2CmsZbq*fNT9R3e(6OU?%6a0H5 z#UFBqe={7`n$sxox`nh3kEL^78`>_`7kd&DL*)CCivcgC)_D4niN>y*sWHvRgM(4^ za(PA%C2V{zPHnI!mz@Lga&(dC}3G~n8wo9dJ^!?bjtn$3W^m6xa zCDy;E4j>XuVTeA7F)}iaB*Q16{`tiGNo<5#YSM3f{y0ow%`zl$Zuv)J(x_HU zlN3N>>i9!l$~Z4Vl1PrS@*Un8w6MP&TWd35Yi9@XmXeo;h;6XEdljqw7yqBYB*m(a zJP?QX7Ji6=rce=d2Fx`~`SVMcB2=nSAP}0u&n@KQP90%}{B&q9WdJ$E7Um8B2%P(C zMW1kEDz~lf9^&*`vR~E$l5<)Ofayk?SFl@Z;HcX;_gx~`LKGIpl={C8p$Qxn%f!|+ zNTU5KSh^JeKW3}+d3TZ{CNM|^l9ycB1Nq#7DeQ$OQtJ`?03L_dvj%7N&?%&e z!7iGjWr%~gqrA?5*>u}hVcLgt@+@TDV?ibJfJM3HpGaNmlq5G`XrOgEp|Doo{Dk;U zq}C$Sc!vapD4tzw7&gvo{o-eq8Ig6#g3}<}@TDyHa~j{q!-4yG90r`S)I$&wLYM|9 z%ZUnZlc<*;tjcaeR%6&Yb$*sM7vE~W{#oWZ)sI`%HqLO$ zaJK#yj2&hKKGDC*J^nQ(GGWdQKP5*2-Zqkw72-1udAcr!t*J#N41>XD?z>PV$)5_abb4lh$ewG{8DtC;!wNaRAa45wcI``IUdJmO z29@qUB2kP?SFeQ$jqJ$K4C4PVPB(wQA6Cvwl#_p+hlF)Yb@%Y7Mn0AH%5>?Srng%L zM)3)l!yfS^%2oH$E9Z>;%;h!>8M<8aC7Wz>KWw=dlDRy)=x$Qlb@9D9I(NcBc3;v# zpNJ(vSE|{4zM12l4V|GL9`4g;^zB<|s;Te1dptyW_;E{oRCgRhKGC!Jm7Zqd>RT(@ zu7A`0O)8p4-}os+QMWPx07sWDM;hHG^&5D6mCiZjJ5^B2&&rLOF*f{$GjGj_9ocmEVNG$Ky=yVxeeNo?gCahwQPPSe~9i7bi&H zkV5A}gpW^$Ej5O#q3d$z$ivoYB^zXf_;<%=p&@ME?dm0-+kuV*m4I`3nS|Vuc}x2e zz%;IM4qI-Vv__jF>^VXdE@$9~xf{cK3(*ghj=~IV0}w9^|G&viN4Y!1uxAyt8!G=EFw0c+D4#d<%w{42kyrA>?g?2b&Ft*i zOqiA~(zLjgONgUP3Iu|-Lzgs*J^6o+^o(VB^*r21`AItEa7F^k1=kF_l?7&@J(A?A zPckNfgN#1Thtjqh#ROIhKjf)|=pRW<2}H-T9oyp;jF|T*hO+VBir)npp!g-|k{))6 z+$XlL&d=&GNr*Xeaq6(`4t|^zef7hoLXD50SV(-BelqM+Vu`wd@>Me|Bmj}~I=Krr zvlQcuE91)J6uGx^96XBN?mB0=_D$;Cgk;c`s~2)y@svJB7}`kLEOJoAqxX-4xX_xEHHWTu96oi0S}rO?{Tk)zXbrOqV{siF8k@K6 zatijFZPxuzF;tfsgFm56z3W)m)ocM-C9P0B0EZR)Tg6F7PMERkI>`%msL*q#ZQSDv ziO};I_ee!~=en870HTQ5{m0o1;l|f0x@rA(SD&3}PRj=naeZNgxBwk_`@q z{R9eBxGw;t3j2XIAo=O=rKiAz;N`&{pV#nJ83WL_m~&JzMvqL4yG% z(~#bNDci^5hm=bja zD>_+y3Suy~AO|p{9p~EkHbNz|CoY4oLlsm;k_8xHPlED))A>lejTwF4W=P2MMKdPj zD^$peGCzO&-A@#B{)iK7wspoG`BxxNyuXBpTMk8zk^BW`tTYR`P9a_){F*5oQV!OI zGu<0IPj?N^MQ&_RV`BvC0Nr|=L2dSldFi6-oe{8eU?iY2tk5sZ1Zigg-vX!3xNY`$ z=uL_gxL|@0z>WeLr}6g<%(R)NY+YTXxF5U*tSLv#_ zN-^43&m6%)5zjJF+EmQyk5GrfDs{b*UWz(9rWzk0ghBa3Uc~nOs6>XXO77>V4C}F9 zRu9dp`xmIkMlYm^@YBwZS%*nc+tmQGJw(h6ll@7ca2eA^xE0KxN+XH}^p8uk%!;oT zls;1tlH$-#0de1EcSt;#vVL+ql}fOrNc=+$ft_6S#I~Zu+|-qndReA8+g^YCZ{muR z$rOEN51X3hkpLCRWr5+cg;U&5nbP0bCmfk^%xT?}=Mx@t`>Xs%8Vi}($T7rO$obAjjZu8CXsYQPS>{>X6C}tg z3~nI%HUF=JlSXnM|JWBx$|PVnHcnA}dS=!v0R6Pr$$oGbNwC#IRTQ#JBchB}HjRgY zjqC{-)@GvtNx?#g{gSj+1Wm06RNgyoq74Fw%4>Xj7HG0mF7WTlMs~*EHrC`|ZxABS7maA}H z=m(A?r<=+BIJPKL**PgmC}tawf2p$0?Ku-!jw}3M?p*8ddV|=+pkX#E=C+VgF1`C)yuZ5+%Lk&^+I5#_%b2r^6Rkl6(6lX|& z7Ka6kJ4z}nOZw+osjD>SW9H~@CVf-`EWqsVO~@8v2$3RIN;;(7r}bcea$4i@IgfN} zYc_Xhn$$%jojO@{lgS*pS})JEcAN^CJqKC_%_P8C1gatK<%f4Xpm`NSzOozYq#o($ z_nY|rG9gKS5Gd+M^=ZE2>FGiVfOH6>4atYTWAaQ5TY@;7UY?`5!OlVi2W=E!eb8_X zV^ekH)gU5F@fW4dPz(feQsNp3Y7vs454X>^Qn~)p zACR3p4uA@x(tXJ0UFj1ZGC53F!}ujG{w0SCs`{R#dx}HTGOOcON^HJR@IQa?`y#BI z)h(JGbJSqHpHU}mA6=7q23r#99OXUXg1z3rB(Dxzxdkhh0b>s%Z=WJx#f;id-;qf@ zI7Vg0_TTCM*KEjQ0;KTy%3-B&PiHSdKHQUSS}&D92mAa@v|Br&Rp;U!1YzT@EZ7f- zL(;q&Wjb=j-km#JBeVJ9PB$}-ODXjs07WqfLt-?Q-}#vLGo4eoYXiTWZt%U#(6zH*jvWM<_5!5eFC8r$X!R=O~U$$>g#Y%+YLyYOI0D)C{p({rIm@{E+;PS4`pQ%ha<QwS7G>Pe%D!ZbqF5B1n>izd11Y+!Vv} z@cYvpVd>qPzZB=@g69ByK;II)IImbS<^qo?WNMntET{s~Z@Eh^$N62rh*I#H41 zN+)6$WeMb9!o>GVfTP~SWpGipy}pnP_4Xa?^z=y)K@j8J31JKPnauiVKCoLMFoY1XvY>+{ZD zKcNODDfPHyeHz`BCT-+QI6ah6I{Ex9mIZGveezq_YPg#%sP4)BFz=x4U)2V&5|KRIjdBozvQZSL}3!Pbp4e0|uDo$!D>(o;zMHQq>ebQIj zYjZnL^Ev)Gzh5^*roIdiIr49XctoDB)b*O|(*<^um01xISMD#B3jhdUsY|p}Q{AI# zZkdzurvawYW0mk(-IL=7G-iCO;|4k>{S?kzPUD!s*XQqm;9>V&lk>K;4olOt(eU;Y1?KLDJ|)xvmBDmC$5mN%J9BrwjV5Cr zcxkEhe&s7?5x4DZlz{tT^1m1NnMZ)%F_SMD$x_LpQycWge)73p^?WyaFOcp&DEU^M zIsk*~8DaGgUN`XHNIv?(ef@p5<{J%uahxP`=wKb6z#^w1%%{kEJ7-B&kbnlacx+7J zaHbTa%Ai&4+H1N<&W)KK!Dgxeo*C&v9gs3u0~(OS6#&ka0m2EZux7vDvsE|dUtnj~$!Nx3bsfw^TR~;;6uDY;RW*yW;|P!6RFGeN7CT+n$$cxzCK}ZMd=?z^L-hfQ_7A!P zP?8~Fkd0N^3C|)vhe|(O&l{J%@vBZGYRNb)QPD^RG>&-zKpns{@|w<1S6nA)t=|Lb z8%1I1J|tBzLl1Rmb;Ke@5v)8Le9bh^pr0;82&hJzv>$EXIguYse{|4at`$r|Clyr0 zcd5svG3ucw`TI}L0O)VI9G1A^b3F0i;BYwmI*hpYo!53nw|f8wW0TTQe&c#06r-Xq z4ON^tPJp7Y!PF{;FP2nLi!|~NQHHHSvsXTH2bV#!qv3Url!<`ymp5U?V3hMa-TE*f zO7SD_ic@F?jfnxe!w;wc&S)CL!BV z3t4-(6HHz*?G^Hu2E}faZNC&Xwad3ie^LY11YRG+CiRAs{I-6JKEDV8UUdCD*5?9L z2h9{+~QcBGds*FW9#^rchn4b4lbR&#s+x(6Q5$yQH24$Ovh7V2Kn z4S5CFUUXF`7D62sbLEQt{ts16Kah7C{-jwm}63P9ZSlJ5wC z^1VGvrKNhYe2Tpy;Z=Rz-LKqnCw2tziFg`b&k@YRCUFP{$dVn(OwL44q?M8;QQ33Sh`Fo;K1+kp~V+qGUEI)8*Vs z_j6Pi2nHkrW^lcQB_GYi`rcpJRkudazX;E%iNJ*eq^=O8ZhT`uap3%NnWX`|nT{yR zOp!=E3c%AV7tXT;_#?)(>}dBM)Rge`N(stK-M@Jng^!mDk1y*gh_%)GQc$cv+EVLz zPJBq__8|2>8`@L(@Hnw{OE$`1!#4DJEih!w()77NfYD7k($<^n%NxZzo1_>vQ2-f_ zvBY!yyt&2>8k%s)95jmWYOe_jU{CA`07PhW2e}$Gx#^QbKsU_WC-Pm*({V z^(5{M=w(OiWgw}tN=vHAVY#Gna-X@$**Kmcf8hFMGVrC4E}qX5I3}@9{0+?$%zISo zrk5_bu+&b3{M1$>?;9=^;QF)=kztTx0DlYbYXwFD_TlX(`@P@qx@56DhB?^9yODuH zy9yE=>NThm!OSqud}R6e&nr_LzsEauEeG?4Z0|=X=wbs#wuhbY;heJTV_w# z%ZMY05_q`Wcq*Lg8bH{5E+QDL$*37sZLcMc1o6?g{(PF4baj}JX@igQ5j>27≤4 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 <1> X.XX = Version number -=== Running TRex for the first time in loopback +== First time Running -Before jumping to check the DUT, you could verify TRex and NICs working in loopback. + -For performance-wise, it's better to connect interfaces on the same NUMA (controlled by one physical processor) + -However, if you have a 10Gb/sec interfaces (based on Intel 520-D2 NICs), and you connect ports that are on the same NIC to each other with SFP+, it might not sync. + -We have checked many SFP+ (Intel/Cisco/SR/LR) and had link. + -If you are still facing this issue you could either try to connect interfaces of different NICs or use link:http://www.fiberopticshare.com/tag/cisco-10g-twinax[Cisco twinax copper cable]. +=== Configuring for loopback + +Before connecting TRex to your DUT, it is strongly advised to verify that TRex and the NICs work correctly in loopback. + +To get best performance, it is advised to loopback interfaces on the same NUMA (controlled by the same physical processor). If you do not know how to check this, you can ignore this advice for now. + + +[NOTE] +===================================================================== +If you are using 10Gbs NIC based on Intel 520-D2 NICs, and you loopback ports on the same NIC, using SFP+, it might not sync, and you will fail to get link up. + +We checked many types of SFP+ (Intel/Cisco/SR/LR) and it worked for us. + +If you still encounter link issues, you can either try to loopback interfaces from different NICs, or use link:http://www.fiberopticshare.com/tag/cisco-10g-twinax[Cisco twinax copper cable]. +===================================================================== .Loopback example image:images/loopback_example.png[title="Loopback example"] -If you have a 1Gb/Sec Intel NIC (I350) or XL710/X710 NIC, you can connect any port to any port from loopback perspective *but* first filter the management port - see xref:trex_config[TRex Configuration]. - ==== Identify the ports [source,bash] ---- - $>sudo ./dpdk_setup_ports.py --s + $>sudo ./dpdk_setup_ports.py -s Network devices using DPDK-compatible driver ============================================ Network devices using kernel driver =================================== - 0000:02:00.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio *Active* 0000:03:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<1> - 0000:03:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<2> - 0000:13:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<3> - 0000:13:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<4> - + 0000:03:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb + 0000:13:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb + 0000:13:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb + 0000:02:00.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio *Active* #<2> Other network devices ===================== ---- -<1> TRex interface #1 before unbinding -<2> TRex interface #2 before unbinding -<3> TRex interface #3 before unbinding -<4> TRex interface #4 before unbinding -Choose a port to use and follow instructions in the next section to create a configuration file. +<1> If you did not run any DPDK application, you will see list of interfaces binded to the kernel, or not binded at all. +<2> Interface marked as 'active' is the one used by your ssh connection. *Never* put it in TRex config file. -==== Create minimum configuration file +Choose ports to use and follow the instructions in the next section to create configuration file. -Create a configuration file: `/etc/trex_cfg.yaml`. +==== Creating minimum configuration file -You can copy a basic configuration file from cfg folder by running this command... +Default configuration file name is: `/etc/trex_cfg.yaml`. + +You can copy basic configuration file from cfg folder [source,bash] ---- $cp cfg/simple_cfg.yaml /etc/trex_cfg.yaml ---- -...and edit the configuration file with the desired values. +Then, edit the configuration file and put your interface's and IP addresses details. Example: [source,bash] ---- -- port_limit : 4 #<1> - version : 2 #<2> - interfaces : ["03:00.0","03:00.1","13:00.1","13:00.0"] #<3> +- port_limit : 2 + version : 2 +#List of interfaces. Change to suit your setup. Use ./dpdk_setup_ports.py -s to see available options +interfaces : ["03:00.0", "03:00.1"] #<1> + port_info : # Port IPs. Change to suit your needs. In case of loopback, you can leave as is. + - ip : 1.1.1.1 + default_gw : 2.2.2.2 + - ip : 2.2.2.2 + default_gw : 1.1.1.1 ---- -<1> Mumber of ports -<2> Must add version 2 to the configuration file -<3> List of interfaces displayed by `#>sudo ./dpdk_setup_ports.py -s` +<1> You need to edit this line to match the interfaces you are using. +Notice that all NICs you are using should have the same type. You cannot mix different NIC types in one config file. For more info, see link:http://trex-tgn.cisco.com/youtrack/issue/trex-201[trex-201]. -When working with a VM, set the destination MAC of one port as the source or the other for loopback the port in the vSwitch -and you should take the right value from the hypervisor (in case of a physical NIC you can set the MAC address with virtual you can't and you should take it from the hypervisor) -and example +You can find xref:trex_config[here] full list of configuration file options. -// Clarify paragraph above. +=== Script for creating config file -[source,python] ----- - - port_limit : 2 - version : 2 - interfaces : ["03:00.0","03:00.1"] <2> - port_info : # set eh mac addr - - dest_mac : [0x1,0x0,0x0,0x1,0x0,0x00] # port 0 - src_mac : [0x2,0x0,0x0,0x2,0x0,0x00] <1> - - dest_mac : [0x2,0x0,0x0,0x2,0x0,0x00] # port 1 <1> - src_mac : [0x1,0x0,0x0,0x1,0x0,0x00] ----- -<1> Source MAC is like destination MAC (this should be set or taken from VMware). The MAC was taken from the hypervisor. -<2> Currently TRex supports only one type of NIC at a time. You cannot mix different NIC types in one config file. For more info, see link:http://trex-tgn.cisco.com/youtrack/issue/trex-197[trex-201]. +To help starting with basic configuration file that suits your needs, there a script that can automate this process. +The script helps you getting started, and you can then edit the file and add advanced options from xref:trex_config[here] +if needed. + +There are two ways to run the script. Interactively (script will pormpt you for parameters), or providing all parameters +using command line options. -// where can we describe this limitation (TRex supports only one type of NIC at a time. You cannot mix different NIC types in one config file.) and other limitations? - -==== Script for creating config file - -===== Interactive mode +==== Interactive mode [source,bash] ---- sudo ./dpdk_setup_ports.py -i ---- -Will be printed table with all interfaces and related information. + -Then, user is asked to provide desired interfaces, MAC destinations etc. +You will see a list of available interfaces with their related information + +Just follow the instructions to get basic config file. -===== Specifying input arguments from CLI +==== Specifying input arguments using command line options -Another option is to run script with all the arguments given directly from CLI. + -Run this command to see list of all interfaces and related information: +First, run this command to see the list of all interfaces and their related information: [source,bash] ---- sudo ./dpdk_setup_ports.py -t ---- -* In case of *Loopback* and/or only *L1-L2 Switches* on the way, no need to provide destination MACs. + -Will be assumed connection 0↔1, 2↔3 etc. + +* In case of *Loopback* and/or only *L1-L2 Switches* on the way, you do not need to provide IPs or destination MACs. + +The script Will assume the following interface connections: 0↔1, 2↔3 etc. + Just run: [source,bash] @@ -470,12 +461,8 @@ Just run: sudo ./dpdk_setup_ports.py -c ... ---- -* In case of *Router* (or other next hop device, such as *L3 Switch*), should be specified MACs of router interfaces as destination. - -[source,bash] ----- -sudo ./dpdk_setup_ports.py -c ... --dest-macs ... ----- +* In case of *Router* (or other next hop device, such as *L3 Switch*), you should specify the TRex IPs and default gateways, or +MACs of the router as described below. .Additional arguments to creating script (dpdk_setup_ports.py -c) [options="header",cols="2,5,3",width="100%"] @@ -484,7 +471,9 @@ sudo ./dpdk_setup_ports.py -c ... --dest-m | -c | Create a configuration file by specified interfaces (PCI address or Linux names: eth1 etc.) | -c 03:00.1 eth1 eth4 84:00.0 | --dump | Dump created config to screen. | | -o | Output the config to this file. | -o /etc/trex_cfg.yaml -| --dest-macs | Destination MACs to be used in created yaml file per each interface. Without specifying the option, will be assumed loopback (0↔1, 2↔3 etc.) | --dest-macs 11:11:11:11:11:11 22:22:22:22:22:22 +| --dest-macs | Destination MACs to be used per each interface. Specify this option if you want MAC based config instead of IP based one. You must not set it together with --ip and --def_gw | --dest-macs 11:11:11:11:11:11 22:22:22:22:22:22 +| --ip | List of IPs to use for each interface. If this option and --dest-macs is not specified, script assumes loopback connections (0↔1, 2↔3 etc.) | --ip 1.2.3.4 5.6.7.8 +|--def-gw | List of default gateways to use for each interface. If --ip given, you must provide --def_gw as well | --def-gw 3.4.5.6 7.8.9.10 | --ci | Cores include: White list of cores to use. Make sure there is enough for each NUMA. | --ci 0 2 4 5 6 | --ce | Cores exclude: Black list of cores to exclude. Make sure there will be enough for each NUMA. | --ci 10 11 12 | --no-ht | No HyperThreading: Use only one thread of each Core in created config yaml. | @@ -494,24 +483,65 @@ sudo ./dpdk_setup_ports.py -c ... --dest-m | --ignore-numa | Advanced option: Ignore NUMAs for config creation. Use this option only if you have to, as it might reduce performance. For example, if you have pair of interfaces at different NUMAs | |================= -==== Run TRex +=== Configuring ESXi for running TRex + +To get best performance, it is advised to run TRex on bare metal hardware, and not use any kind of VM. +Bandwidth on VM might be limited, and IPv6 might not be fully supported. +Having said that, there are sometimes benefits for running on VM. + +These include: + + * Virtual NICs can be used to bridge between TRex and NICs not supported by TRex. + + * If you already have VM installed, and do not require high performance. + + +1. Click the host machine, enter Configuration -> Networking. + +a. One of the NICs should be connected to the main vSwitch network to get an "outside" connection, for the TRex client and ssh: + +image:images/vSwitch_main.png[title="vSwitch_main"] + +b. Other NICs that are used for TRex traffic should be in distinguish vSwitch: + +image:images/vSwitch_loopback.png[title="vSwitch_loopback"] + +2. Right-click guest machine -> Edit settings -> Ensure the NICs are set to their networks: + +image:images/vSwitch_networks.png[title="vSwitch_networks"] + +[NOTE] +===================================================================== +Before version 2.10, the following command did not function as expected: +[subs="quotes"] +.... +sudo ./t-rex-64 -f cap2/dns.yaml *--lm 1 --lo* -l 1000 -d 100 +.... +The vSwitch did not "know" where to route the packet. Was solved on version 2.10 when TRex started to support ARP. +===================================================================== + +* Pass-through is the way to use directly the NICs from host machine inside the VM. Has no limitations except the NIC/hardware itself. The only difference via bare-metal OS is occasional spikes of latency (~10ms). Passthrough settings cannot be saved to OVA. + +1. Click on the host machine. Enter Configuration -> Advanced settings -> Edit. Mark the desired NICs. Reboot the ESXi to apply. + +image:images/passthrough_marking.png[title="passthrough_marking"] + +2. Right click on guest machine. Edit settings -> Add -> *PCI device* -> Choose the NICs one by one. + +image:images/passthrough_adding.png[title="passthrough_adding"] + +=== Configuring for running with router (or other L3 device) as DUT + +You can follow link:trex_config_guide.html[this] presentation for an example of how to configure router as DUT. + +=== Running TRex -Use the following command to begin operation of a 4x 10Gb/sec TRex: +When all is set, use the following command to start basic TRex run for 10 seconds +(it will use the default config file name /etc/trex_cfg.yaml): [source,bash] ---- -$sudo ./t-rex-64 -f cap2/dns.yaml -c 4 -m 1 -d 100 -l 1000 +$sudo ./t-rex-64 -f cap2/dns.yaml -c 4 -m 1 -d 10 -l 1000 ---- -NOTE: For a 10Gb/sec TRex with 2, 6, or 8 ports, add `--limit-ports [number of ports]` *or* follow xref:trex_config[these instructions] to configure TRex. - If successful, the output will be similar to the following: [source,python] ---- -$ sudo ./t-rex-64 -f cap2/dns.yaml -d 100 -l 1000 -Starting TRex 1.50 please wait ... +$ sudo ./t-rex-64 -f cap2/dns.yaml -d 10 -l 1000 +Starting TRex 2.09 please wait ... zmq publisher at: tcp://*:4500 - number of ports founded : 4 + number of ports found : 4 port : 0 ------------ link : link : Link Up - speed 10000 Mbps - full-duplex <1> @@ -542,48 +572,46 @@ zmq publisher at: tcp://*:4500 Tx Bw | 217.09 Kbps | 217.14 Kbps | 216.83 Kbps | 216.83 Kbps -Global stats enabled - Cpu Utilization : 0.0 % <12> 29.7 Gb/core <13> + Cpu Utilization : 0.0 % <2> 29.7 Gb/core <3> Platform_factor : 1.0 - Total-Tx : 867.89 Kbps <2> - Total-Rx : 867.86 Kbps <3> + Total-Tx : 867.89 Kbps <4> + Total-Rx : 867.86 Kbps <5> Total-PPS : 1.64 Kpps Total-CPS : 0.50 cps - Expected-PPS : 2.00 pps <9> - Expected-CPS : 1.00 cps <10> - Expected-BPS : 1.36 Kbps <11> + Expected-PPS : 2.00 pps <6> + Expected-CPS : 1.00 cps <7> + Expected-BPS : 1.36 Kbps <8> - Active-flows : 0 <6> Clients : 510 Socket-util : 0.0000 % - Open-flows : 1 <7> Servers : 254 Socket : 1 Socket/Clients : 0.0 - drop-rate : 0.00 bps <8> + Active-flows : 0 <9> Clients : 510 Socket-util : 0.0000 % + Open-flows : 1 <10> Servers : 254 Socket : 1 Socket/Clients : 0.0 + drop-rate : 0.00 bps <11> current time : 5.3 sec test duration : 94.7 sec -Latency stats enabled - Cpu Utilization : 0.2 % <14> + Cpu Utilization : 0.2 % <12> if| tx_ok , rx_ok , rx ,error, average , max , Jitter , max window | , , check, , latency(usec),latency (usec) ,(usec) , -------------------------------------------------------------------------------------------------- - 0 | 1002, 1002, 0, 0, 51 , 69, 0 | 0 69 67 <4> - 1 | 1002, 1002, 0, 0, 53 , 196, 0 | 0 196 53 <5> + 0 | 1002, 1002, 0, 0, 51 , 69, 0 | 0 69 67 <13> + 1 | 1002, 1002, 0, 0, 53 , 196, 0 | 0 196 53 2 | 1002, 1002, 0, 0, 54 , 71, 0 | 0 71 69 3 | 1002, 1002, 0, 0, 53 , 193, 0 | 0 193 52 ---- <1> Link must be up for TRex to work. -<2> Total Rx must be the same as Tx -<3> Total Rx must be the same as Tx -<4> Tx_ok == Rx_ok -<5> Tx_ok == Rx_ok -<6> Number of TRex active "flows". Could be different than the number of router flows, due to aging issues. Usualy the TRex number of active flows is much lower than that of the router. -<7> Total number of TRex flows opened since startup (including active ones, and ones already closed). -<8> Drop rate. -<9> Expected number of packets per second (calculated without latency packets). -<10> Expected number of connections per second (calculated without latency packets). -<11> Expected number of bits per second (calculated without latency packets). -<12> Average CPU utilization of transmitters threads. For best results it should be lower than 80%. -<13> Gb/sec generated per core of DP. Higher is better. -<14> Rx and latency thread CPU utilization. - +<2> Average CPU utilization of transmitters threads. For best results it should be lower than 80%. +<3> Gb/sec generated per core of DP. Higher is better. +<4> Total Tx must be the same as Rx at the end of the run +<5> Total Rx must be the same as Tx at the end of the run +<6> Expected number of packets per second (calculated without latency packets). +<7> Expected number of connections per second (calculated without latency packets). +<8> Expected number of bits per second (calculated without latency packets). +<9> Number of TRex active "flows". Could be different than the number of router flows, due to aging issues. Usualy the TRex number of active flows is much lower than that of the router because the router ages flows slower. +<10> Total number of TRex flows opened since startup (including active ones, and ones already closed). +<11> Drop rate. +<12> Rx and latency thread CPU utilization. +<13> Tx_ok on port 0 should equal Rx_ok on port 1, and vice versa. More statistics information: @@ -591,62 +619,16 @@ More statistics information: *Socket/Clients*:: Average of active flows per client, calculated as active_flows/#clients. -*Socket-util*:: Estimate of how many socket ports are used per client IP. This is approximately ~(100*active_flows/#clients)/64K, calculated as (average active flows per client*100/64K). Utilization of more than 50% means that TRex is generating too many flows per single client, and that more clients must be added. +*Socket-util*:: Estimation of number of L4 ports (sockets) used per client IP. This is approximately (100*active_flows/#clients)/64K, calculated as (average active flows per client*100/64K). Utilization of more than 50% means that TRex is generating too many flows per single client, and that more clients must be added in the generator config. // clarify above, especially the formula -*Max window*:: Momentary maximum latency for a time window of 500 msec. There are a few numbers per number of windows that are shown. - The newest number (last 500msec) is on the right. Oldest in the left. This can help identifying spikes of high latency clearing after some time. Maximum latency is the total maximum over the entire test duration. -//clarify above +*Max window*:: Momentary maximum latency for a time window of 500 msec. There are few numbers shown per port. + The newest number (last 500msec) is on the right. Oldest on the left. This can help identifying spikes of high latency clearing after some time. Maximum latency is the total maximum over the entire test duration. To best understand this, + run TRex with latency option (-l) and watch the results with this section in mind. -*Platform_factor*:: There are cases in which we duplicate the traffic using splitter/switch and we would like all numbers displayed to be multiplied by this factor (e.g. x2) -//clarify above +*Platform_factor*:: There are cases in which we duplicate the traffic using splitter/switch and we would like all numbers displayed by TRex to be multiplied by this factor, so that TRex counters will match the DUT counters. WARNING: If you don't see rx packets, revisit your MAC address configuration. -//clarify above - -==== Running TRex for the first time with ESXi: - -* Virtual NICs can be used to bridge between TRex and non-supported NICs, or for basic testing. Bandwidth is limited by vSwitch, has IPv6 issues. -// clarify, especially what IPv6 issues - -1. Click the host machine, enter Configuration -> Networking. - -a. One of the NICs should be connected to the main vSwitch network to get an "outside" connection, for the TRex client and ssh: + -image:images/vSwitch_main.png[title="vSwitch_main"] - -b. Other NICs that are used for TRex traffic should be in distinguish vSwitch: + -image:images/vSwitch_loopback.png[title="vSwitch_loopback"] - -2. Right-click guest machine -> Edit settings -> Ensure the NICs are set to their networks: + -image:images/vSwitch_networks.png[title="vSwitch_networks"] - - -[NOTE] -===================================================================== -Current limitation: The following command does not function as expected: -[subs="quotes"] -.... -sudo ./t-rex-64 -f cap2/dns.yaml *--lm 1 --lo* -l 1000 -d 100 -.... -The vSwitch does not "know" where to route the packet. This is expected to be fixed when TRex supports ARP. -===================================================================== - -* Pass-through is the way to use directly the NICs from host machine inside the VM. Has no limitations except the NIC/hardware itself. The only difference via bare-metal OS is occasional spikes of latency (~10ms). Passthrough settings cannot be saved to OVA. - -1. Click on the host machine. Enter Configuration -> Advanced settings -> Edit. Mark the desired NICs. Reboot the ESXi to apply. + -image:images/passthrough_marking.png[title="passthrough_marking"] - -2. Right click on guest machine. Edit settings -> Add -> *PCI device* -> Choose the NICs one by one. + -image:images/passthrough_adding.png[title="passthrough_adding"] - -==== Running TRex for the first time with router - -You can follow this presentation: link:trex_config_guide.html[first time TRex configuration] -or continue reading. -Without config file, TRex sets source MAC of all ports to `00:00:00:01:00:00` and expects to receive packets with this destination MAC address. -So, you just need to configure your router with static ARP entry pointing to the above MAC address. - -NOTE: Virtual routers on ESXi (for example, Cisco CSR1000v) must have distinct MAC address for each port. You need to specify the addresses in the configuration file. see more xref:trex_config[here]. Another example is TRex connected to a switch. In this case, each one of the TRex ports should have distinct MAC address. include::trex_book_basic.asciidoc[] @@ -673,7 +655,7 @@ This requires TRex to send the traffic on two VLANs, as described below. - duration : 0.1 vlan : { enable : 1 , vlan0 : 100 , vlan1 : 200 } <1> ---- -<1> Enable VLAN feature, valn0==100 , valn1==200 +<1> Enable VLAN feature, vlan0==100 , vlan1==200 *Problem definition:*:: @@ -792,8 +774,8 @@ Support for IPv6 includes: 1. Support for pcap files containing IPv6 packets 2. Ability to generate IPv6 traffic from pcap files containing IPv4 packets -The following switch enables this feature: `--ipv6` -Two new keywords (`src_ipv6`, `dst_ipv6`) have been added to the YAML file to specify the most significant 96 bits of the IPv6 address - for example: +The following command line option enables this feature: `--ipv6` +The keywords (`src_ipv6` and `dst_ipv6`) specify the most significant 96 bits of the IPv6 address - for example: [source,python] ---- @@ -802,13 +784,12 @@ Two new keywords (`src_ipv6`, `dst_ipv6`) have been added to the YAML file to sp ---- The IPv6 address is formed by placing what would typically be the IPv4 -address into the least significant 32-bits and copying the value provided -in the src_ipv6/dst_ipv6 keywords into the most signficant 96-bits. -If src_ipv6 and dst_ipv6 are not specified in the YAML file, the default -is to form IPv4-compatible addresses (where the most signifcant 96-bits -are zero). +address into the least significant 32 bits and copying the value provided +in the src_ipv6/dst_ipv6 keywords into the most signficant 96 bits. +If src_ipv6 and dst_ipv6 are not specified, the default +is to form IPv4-compatible addresses (most signifcant 96 bits are zero). -There is a support for all plugins (control flows that needed to be changed). +There is support for all plugins. *Example:*:: [source,bash] @@ -818,7 +799,8 @@ $sudo ./t-rex-64 -f cap2l/sfr_delay_10_1g.yaml -c 4 -p -l 100 -d 100000 -m 30 - *Limitations:*:: -* TRex cannot generate both IPv4 and IPv6 traffic. The `--ipv6` switch must be specified even when using a pcap file containing only IPv6 packets. +* TRex cannot generate both IPv4 and IPv6 traffic. +* The `--ipv6` switch must be specified even when using pcap file containing only IPv6 packets. *Router configuration:*:: @@ -856,42 +838,42 @@ asr1k(config)#ipv6 route 5000::/64 3001::2 <1> Enable IPv6 <2> Add pbr <3> Enable IPv6 routing -<4> MAC address setting should be like TRex +<4> MAC address setting. Should be TRex MAC. <5> PBR configuraion === Client clustering configuration -Trex supports testing a complex topology by a feature called "client clustering". -This feature allows a more detailed clustering of clients. +TRex supports testing complex topologies, using a feature called "client clustering". +This feature allows more detailed clustering of clients. -Let's assume the following topology: +Let's look at the following topology: image:images/client_clustering_topology.png[title="Client Clustering"] We would like to configure two clusters and direct traffic to them. -Using a config file, you can instruct TRex to generate clients +Using config file, you can instruct TRex to generate clients with specific configuration per cluster. -A cluster configuration includes: +Cluster configuration includes: -* IP start range -* IP end range -* Initator side configuration -* Responder side configuration +* IP start range. +* IP end range. +* Initiator side configuration. +* Responder side configuration. [NOTE] -It is important to state that this is *complimentry* to the client generator +It is important to understand that this is *complimentary* to the client generator configured per profile - it only defines how the generator will be clustered. -Let's take a look at an example: +Let's look at an example. -We have a profile which defines a client generator: +We have a profile defining client generator. [source,bash] ---- -$more cap2/dns.yaml +$cat cap2/dns.yaml - duration : 10.0 generator : distribution : "seq" @@ -904,7 +886,6 @@ $more cap2/dns.yaml dual_port_mask : "1.0.0.0" tcp_aging : 1 udp_aging : 1 - mac : [0x00,0x00,0x00,0x01,0x00,0x00] cap_info : - name: cap2/dns.pcap cps : 1.0 @@ -913,11 +894,10 @@ $more cap2/dns.yaml w : 1 ---- -We would like to create two clusters of 4 devices each. -We would also like to divide *80%* of the traffic to the upper cluster -and *20%* to the lower cluster. +We want to create two clusters with 4 devices each. +We also want to divide *80%* of the traffic to the upper cluster and *20%* to the lower cluster. -We create a cluster configuration file in YAML: +We will create the following cluster configuration file. [source,bash] ---- @@ -925,29 +905,29 @@ We create a cluster configuration file in YAML: # Client configuration example file # The file must contain the following fields # -# 'vlan' - is the entire configuration under VLAN -# if so, each client group must include vlan +# 'vlan' - if the entire configuration uses VLAN, +# each client group must include vlan # configuration # -# 'groups' - each client group must contain a range of IP -# and initiator and responder maps -# 'count' represents the number of MAC devices -# on the group. +# 'groups' - each client group must contain range of IPs +# and initiator and responder section +# 'count' represents the number of different MACs +# addresses in the group. # # initiator and responder can contain 'vlan', 'src_mac', 'dst_mac' # # each group contains a double way VLAN configuration -vlan: true <1> +vlan: true groups: -- ip_start : 16.0.0.1 <2> +- ip_start : 16.0.0.1 ip_end : 16.0.0.204 - initiator : <3> + initiator : vlan : 100 dst_mac : "00:00:00:01:00:00" - responder : <4> + responder : vlan : 200 dst_mac : "00:00:00:01:00:00" @@ -968,16 +948,16 @@ groups: ---- The above configuration will divide the generator range of 255 clients to two clusters, -where each has 4 devices and VLAN on both ways. +each with 4 devices and VLAN in both directions. -MACs will be allocated incrementaly with a wrap around. +MACs will be allocated incrementaly, with a wrap around. e.g. * 16.0.0.1 --> 00:00:00:01:00:00 * 16.0.0.2 --> 00:00:00:01:00:01 -* 16.0.0.3 --> 00:00:00:01:00:03 -* 16.0.0.4 --> 00:00:00:01:00:04 +* 16.0.0.3 --> 00:00:00:01:00:02 +* 16.0.0.4 --> 00:00:00:01:00:03 * 16.0.0.5 --> 00:00:00:01:00:00 * 16.0.0.6 --> 00:00:00:01:00:01 @@ -987,7 +967,7 @@ and so on. [source,bash] ---- -sudo ./t-rex-64 -f cap2/dns.yaml --client_cfg my_cfg.yaml -c 4 -d 100 +sudo ./t-rex-64 -f cap2/dns.yaml --client_cfg my_cfg.yaml ---- === NAT support @@ -1023,11 +1003,11 @@ This mode can give much better connections per second performance than mode 1 (s $sudo ./t-rex-64 -f cap2/http_simple.yaml -c 4 -l 1000 -d 100000 -m 30 --learn-mode 1 ---- -*SFR traffic without bundeling/ALG support* +*SFR traffic without bundling/ALG support* [source,bash] ---- -$sudo ./t-rex-64 -f avl/sfr_delay_10_1g_no_bundeling.yaml -c 4 -l 1000 -d 100000 -m 10 --learn-mode 2 +$sudo ./t-rex-64 -f avl/sfr_delay_10_1g_no_bundling.yaml -c 4 -l 1000 -d 100000 -m 10 --learn-mode 2 ---- *NAT terminal counters:*:: @@ -1051,7 +1031,7 @@ $sudo ./t-rex-64 -f avl/sfr_delay_10_1g_no_bundeling.yaml -c 4 -l 1000 -d 10000 *Configuration for Cisco ASR1000 Series:*:: -This feature was tested with the following configuration and sfr_delay_10_1g_no_bundeling. yaml traffic profile. +This feature was tested with the following configuration and sfr_delay_10_1g_no_bundling. yaml traffic profile. Client address range is 16.0.0.1 to 16.0.0.255 [source,python] @@ -1093,25 +1073,27 @@ access-list 8 permit 17.0.0.0 0.0.0.255 *Limitations:*:: -. The IPv6-IPv6 NAT feature does not exist on routers, so this feature can work on IPv4 only. +. The IPv6-IPv6 NAT feature does not exist on routers, so this feature can work only with IPv4. . Does not support NAT64. -. Bundling/plugin support is not fully supported. Consequently, sfr_delay_10.yaml does not work. Use sfr_delay_10_no_bundeling.yaml instead. -// verify file name "sfr_delay_10_no_bundeling.yaml" above. english spelling is bundling but maybe the filename has the "e" +. Bundling/plugin is not fully supported. Consequently, sfr_delay_10.yaml does not work. Use sfr_delay_10_no_bundling.yaml instead. [NOTE] ===================================================================== * `--learn-verify` is a TRex debug mechanism for testing the TRex learn mechanism. -* If the router is configured without NAT, it will verify that the inside_ip==outside_ip and inside_port==outside_port. +* Need to run it when DUT is configured without NAT. It will verify that the inside_ip==outside_ip and inside_port==outside_port. ===================================================================== === Flow order/latency verification -In normal mode (without this feature enabled), received traffic is not checked by software. Hardware (Intel NIC) testin for dropped packets occurs at the end of the test. The only exception is the Latency/Jitter packets. +In normal mode (without this feature enabled), received traffic is not checked by software. Hardware (Intel NIC) testing for dropped packets occurs at the end of the test. The only exception is the Latency/Jitter packets. This is one reason that with TRex, you *cannot* check features that terminate traffic (for example TCP Proxy). To enable this feature, add `--rx-check ` to the command line options, where is the sample rate. The number of flows that will be sent to the software for verification is (1/(sample_rate). For 40Gb/sec traffic you can use a sample rate of 1/128. Watch for Rx CPU% utilization. - INFO: This feature changes the TTL of the sampled flows to 255 and expects to receive packets with TTL 254 or 255 (one routing hop). If you have more than one hop in your setup, use `--hops` to change it to a higher value. More than one hop is possible if there are number of routers betwean TRex client side and TRex server side. +[NOTE] +============ +This feature changes the TTL of the sampled flows to 255 and expects to receive packets with TTL 254 or 255 (one routing hop). If you have more than one hop in your setup, use `--hops` to change it to a higher value. More than one hop is possible if there are number of routers betwean TRex client side and TRex server side. +============ This feature ensures that: @@ -1201,7 +1183,6 @@ Cpu Utilization : 0.1 % *Notes and Limitations:*:: -** This feature must be enabled with a latency check (`-l`). ** To receive the packets TRex does the following: *** Changes the TTL to 0xff and expects 0xFF (loopback) or oxFE (route). (Use `--hop` to configure this value.) *** Adds 24 bytes of metadata as ipv4/ipv6 option header. @@ -1235,7 +1216,7 @@ Cpu Utilization : 0.1 % mac_override_by_ip : true <8> ---- <1> Test duration (seconds). Can be overridden using the `-d` option. -<2> See the generator section. +<2> See the link:trex_manual.html#_clients_servers_ip_allocation_scheme[generator] section. // what does note 2 mean? see somewhere else? isn't this simply the generator section? <3> Default source/destination MAC address. The configuration YAML can override this. <4> true (default) indicates that the IPG is taken from the cap file (also taking into account cap_ipg_min and cap_override_ipg if they exist). false indicates that IPG is taken from per template section. @@ -1273,55 +1254,62 @@ Cpu Utilization : 0.1 % anchor:trex_config[] The configuration file, in YAML format, configures TRex behavior, including: - -- MAC address for each port (source and destination) -- Masking interfaces (usually for 1Gb/Sec TRex) to ensure that TRex does not take the management ports as traffic ports. +- IP address or MAC address for each port (source and destination). +- Masked interfaces, to ensure that TRex does not try to use the management ports as traffic ports. - Changing the zmq/telnet TCP port. -==== Basic Configuration - -Copy/install the configuration file to `/etc/trex_cfg.yaml`. -TRex loads it automatically at startup. You still can override options with the command line option switch `--cfg [file]` in the CLI -Configuration file examples can be found in the `$ROOT/cfg` folder +You specify which config file to use by adding --cfg to the command line arguments. + +If no --cfg given, the default `/etc/trex_cfg.yaml` is used. + +Configuration file examples can be found in the `$TREX_ROOT/scripts/cfg` folder. +==== Basic Configurations [source,python] ---- - - port_limit : 2 #mandatory <1> - version : 2 #mandatory <2> - interfaces : ["03:00.0","03:00.1"] #mandatory <3> - #enable_zmq_pub : true <4> - #zmq_pub_port : 4500 <5> - #prefix : setup1 <6> - #limit_memory : 1024 <7> - c : 4 <8> - port_bandwidth_gb : 10 <9> - port_info : # set eh mac addr mandatory - - dest_mac : [0x1,0x0,0x0,0x1,0x0,0x00] # port 0 <10> - src_mac : [0x2,0x0,0x0,0x2,0x0,0x00] - - dest_mac : [0x3,0x0,0x0,0x3,0x0,0x00] # port 1 - src_mac : [0x4,0x0,0x0,0x4,0x0,0x00] - - dest_mac : [0x5,0x0,0x0,0x5,0x0,0x00] # port 2 - src_mac : [0x6,0x0,0x0,0x6,0x0,0x00] - - dest_mac : [0x7,0x0,0x0,0x7,0x0,0x01] # port 3 - src_mac : [0x0,0x0,0x0,0x8,0x0,0x02] - - dest_mac : [0x0,0x0,0x0,0x9,0x0,0x03] # port 4 ----- -<1> The number of ports, should be equal to the number of interfaces in 3) - mandatory -<2> Must be set to 2 - mandatory -<3> Interface that should be used. used `sudo ./dpdk_setup_ports.py --show` - mandatory + - port_limit : 2 #mandatory <1> + version : 2 #mandatory <2> + interfaces : ["03:00.0", "03:00.1"] #mandatory <3> + #enable_zmq_pub : true #optional <4> + #zmq_pub_port : 4500 #optional <5> + #prefix : setup1 #optional <6> + #limit_memory : 1024 #optional <7> + c : 4 #optional <8> + port_bandwidth_gb : 10 #optional <9> + port_info : # set eh mac addr mandatory + - default_gw : 1.1.1.1 # port 0 <10> + dest_mac : '00:00:00:01:00:00' # Either default_gw or dest_mac is mandatory <10> + src_mac : '00:00:00:02:00:00' # optional <11> + ip : 2.2.2.2 # optional <12> + vlan : 15 # optional <13> + - dest_mac : '00:00:00:03:00:00' # port 1 + src_mac : '00:00:00:04:00:00' + - dest_mac : '00:00:00:05:00:00' # port 2 + src_mac : '00:00:00:06:00:00' + - dest_mac : [0x0,0x0,0x0,0x7,0x0,0x01] # port 3 <14> + src_mac : [0x0,0x0,0x0,0x8,0x0,0x02] # <14> +---- +<1> Number of ports. Should be equal to the number of interfaces listed in 3. - mandatory +<2> Must be set to 2. - mandatory +<3> List of interfaces to use. Run `sudo ./dpdk_setup_ports.py --show` to see the list you can choose from. - mandatory <4> Enable the ZMQ publisher for stats data, default is true. -<5> ZMQ port number. the default value is good. you can remove this line - -<6> The name of the setup should be distinct ( DPDK --file-prefix ) -<7> DPDK -m limit the packet memory -<8> Number of threads per dual interface ( like -c CLI option ) -<9> The bandwidth of each interface in Gb/sec. In this example we have 10Gb/sec interfaces. for VM put 1. it used to tune the amount of memory allocated by TRex. -<10> MAC address per port - source and destination. - - -To find out what the interfaces ids, perform the following: +<5> ZMQ port number. Default value is good. If running two TRex instances on the same machine, each should be given distinct number. Otherwise, can remove this line. +<6> If running two TRex instances on the same machine, each should be given distinct name. Otherwise, can remove this line. ( Passed to DPDK as --file-prefix arg) +<7> Limit the amount of packet memory used. (Passed to dpdk as -m arg) +<8> Number of threads (cores) TRex will use per interface pair ( Can be overridden by -c command line option ) +<9> The bandwidth of each interface in Gbs. In this example we have 10Gbs interfaces. For VM, put 1. Used to tune the amount of memory allocated by TRex. +<10> TRex need to know the destination MAC address to use on each port. You can specify this in one of two ways: + +Specify dest_mac directly. + +Specify default_gw (since version 2.10). In this case (only if no dest_mac given), TRex will issue ARP request to this IP, and will use +the result as dest MAC. If no dest_mac given, and no ARP response received, TRex will exit. + +<11> Source MAC to use when sending packets from this interface. If not given (since version 2.10), MAC address of the port will be used. +<12> If given (since version 2.10), TRex will issue gratitues ARP for the ip + src MAC pair on appropriate port. In stateful mode, +gratitues ARP for each ip will be sent every 120 seconds (Can be changed using --arp-refresh-period argument) +<13> If given, gratitues ARP and ARP request will be sent using the given VLAN tag. +<14> Old MAC address format. New format is supported since version v2.09. + +To find out which interfaces (NIC ports) can be used, perform the following: [source,bash] ---- @@ -1332,21 +1320,18 @@ To find out what the interfaces ids, perform the following: Network devices using kernel driver =================================== - 0000:02:00.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio *Active* - 0000:03:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<1> - 0000:03:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<2> - 0000:13:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<3> - 0000:13:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<4> + 0000:02:00.0 '82545EM Gigabit Ethernet Controller' if=eth2 drv=e1000 unused=igb_uio *Active* #<1> + 0000:03:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb #<2> + 0000:03:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb + 0000:13:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb + 0000:13:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv= unused=ixgb Other network devices ===================== ---- -<1> TRex interface #1 before unbinding -<2> TRex interface #2 before unbinding -<3> TRex interface #3 before unbinding -<4> TRex interface #4 before unbinding - +<1> We see that 02:00.0 is active (our management port). +<2> All other NIC ports (03:00.0, 03:00.1, 13:00.0, 13:00.1) can be used. minimum configuration file is: @@ -1354,16 +1339,15 @@ minimum configuration file is: ---- - port_limit : 4 - version : 2 #<1> - interfaces : ["03:00.0","03:00.1","13:00.1","13:00.0"] #<2> + version : 2 + interfaces : ["03:00.0","03:00.1","13:00.1","13:00.0"] ---- -<1> must add version 2 to the configuration file -<2> The list of interfaces from `sudo ./dpdk_setup_ports.py --show` - ==== Memory section configuration -The memory section is optional. It is used when there is a need to tune the amount of memory used by packet manager +The memory section is optional. It is used when there is a need to tune the amount of memory used by TRex packet manager. +Default values (from the TRex source code), are usually good for most users. Unless you have some unusual needs, you can +eliminate this section. [source,python] ---- @@ -1386,11 +1370,16 @@ The memory section is optional. It is used when there is a need to tune the amou dp_flows : 1048576 <4> global_flows : 10240 <5> ---- -<1> Memory section -<2> Per dual interfaces number of buffers - buffer for real time traffic generation -<3> Traffic buffer - when you have many template only this section should be enlarge -<4> number of TRex flows needed -<5> reserved +<1> Memory section header +<2> Numbers of memory buffers allocated for packets in transit, per port pair. Numbers are specified per packet size. +<3> Numbers of memory buffers allocated for holding the part of the packet which is remained unchanged per template. +You should increase numbers here, only if you have very large amount of templates. +<4> Number of TRex flow objects allocated (To get best performance they are allocated upfront, and not dynamically). +If you expect more concurrent flows than the default (1048576), enlarge this. +<5> Number objects TRex allocates for holding NAT ``in transit'' connections. In stateful mode, TRex learn NAT +translation by looking at the address changes done by the DUT to the first packet of each flow. So, these are the +number of flows for which TRex sent the first flow packet, but did not learn the translation yet. Again, default +here (10240) should be good. Increase only if you use NAT and see issues. ==== Platform section configuration @@ -1401,36 +1390,32 @@ a configuration file now has the folowing struct to support multi instance [source,python] ---- - version : 2 - interfaces : ["03:00.0","03:00.1"] + interfaces : ["03:00.0","03:00.1"] port_limit : 2 - prefix : setup1 <1> - limit_memory : 1024 <2> - c : 4 <3> - port_bandwidth_gb : 10 <4> - platform : <5> - master_thread_id : 0 <6> - latency_thread_id : 5 <7> - dual_if : - - socket : 0 <8> - threads : [1,2,3,4] <9> ----- -<1> The name of the setup should be distinct ( DPDK --file-prefix ) -<2> DPDK -m -<3> Number of threads per dual interface ( like -c CLI option ) -<4> The bandwidth of each interface in Gb/sec. In this example we have 10Gb/sec interfaces. for VM put 1. it used to tune the amount of memory allocated by TRex. -<5> the platform section -<6> The thread_id for control -<7> The thread_id for latency if used -<8> Socket of the dual interfaces, in this example of 03:00.0 and 03:00.1, memory should be local to the interface. (Currently dual interface can't use 2 NUMAs.) -<9> Thread to be used, should be local to the NIC. The threads are pinned to cores, thus specifying threads is like specifying cores. +.... + platform : <1> + master_thread_id : 0 <2> + latency_thread_id : 5 <3> + dual_if : <4> + - socket : 0 <5> + threads : [1,2,3,4] <6> +---- +<1> Platform section header. +<2> Hardware thread_id for control thread. +<3> Hardware thread_id for RX thread. +<4> ``dual_if'' section defines info for interface pairs (according to the order in ``interfaces'' list). +each section, starting with ``- socket'' defines info for different interface pair. +<5> The NUMA node from which memory will be allocated for use by the interface pair. +<6> Hardware threads to be used for sending packets for the interface pair. Threads are pinned to cores, so specifying threads +actually determines the hardware cores. *Real example:* anchor:numa-example[] -We've connected 2 Intel XL710 NICs close to each other on motherboard, they shared same NUMA: +We connected 2 Intel XL710 NICs close to each other on the motherboard. They shared the same NUMA: image:images/same_numa.png[title="2_NICSs_same_NUMA"] -The CPU utilization was very high ~100%, with c=2 and c=4 the results were same. +CPU utilization was very high ~100%, with c=2 and c=4 the results were same. Then, we moved the cards to different NUMAs: @@ -1455,102 +1440,117 @@ This gave best results: with *\~98 Gb/s* TX BW and c=7, CPU utilization became * anchor:cml-line[] -*-f=TRAFIC_YAML_FILE*:: - Traffic YAML configuration file. +*--allow-coredump*:: +Allow creation of core dump. + +*--arp-refresh-period *:: +Period in seconds between sending of gratuitous ARP for our addresses. Value of 0 means ``never send``. + +*-c *:: +Number of hardware threads to use per interface pair. Use at least 4 for TRex 40Gbs. + +TRex uses 2 threads for inner needs. Rest of the threads can be used. Maximum number here, can be number of free threads +divided by number of interface pairs. + +For virtual NICs on VM, we always use one thread per interface pair. + +*--cfg *:: +TRex configuration file to use. See relevant manual section for all config file options. -*-c=CORES*:: - Number of cores _per dual interface_. Use 4 for TRex 40Gb/sec. Monitor the CPU% of TRex - it should be ~50%. + - TRex uses 2 cores for inner needs, the rest of cores can be used divided by number of dual interfaces. + - For virtual NICs the limit is -c=1. +*--checksum-offload*:: +Enable IP, TCP and UDP tx checksum offloading, using DPDK. This requires all used interfaces to support this. -*-l=HZ*:: - Run the latency daemon in this Hz rate. Example: -l 1000 runs 1000 pkt/sec from each interface. A value of zero (0) disables the latency check. +*--client_cfg *:: +YAML file describing clients configuration. Look link:trex_manual.html#_client_clustering_configuration[here] for details. -*-d=DURATION*:: - Duration of the test (sec), Default: 0 +*-d *:: +Duration of the test in seconds. -*-m=MUL*:: - Factor for bandwidth (multiply the CPS of each template by this value). +*-e*:: + Same as `-p`, but change the src/dst IP according to the port. Using this, you will get all the packets of the + same flow from the same port, and with the same src/dst IP. + + It will not work good with NBAR as it expects all clients ip to be sent from same direction. + +*-f *:: +Specify traffic YAML configuration file to use. Mandatory option for stateful mode. + +*--hops *:: + Provide number of hops in the setup (default is one hop). Relevant only if the Rx check is enabled. + Look link:trex_manual.html#_flow_order_latency_verification[here] for details. + +*--iom *:: + I/O mode. Possible values: 0 (silent), 1 (normal), 2 (short). *--ipv6*:: - Convert template to IPv6 mode. + Convert templates to IPv6 mode. + +*-k *:: + Run ``warm up'' traffic for num seconds before starting the test. This is needed if TRex is connected to switch running + spanning tree. You want the switch to see traffic from all relevant source MAC addresses before starting to send real + data. Traffic sent is the same used for the latency test (-l option) + + Current limitation (holds for TRex version 1.82): does not work properly on VM. -*--learn-mode *:: - Learn the dynamic NAT translation. + - 1 - Use TCP ACK in first SYN to pass NAT translation information. Will work only for TCP streams. Initial SYN packet must be present in stream. + - 2 - Add special IP option to pass NAT translation information. Will not work on certain firewalls if they drop packets with IP options. +*-l *:: + In parallel to the test, run latency check, sending packets at rate/sec from each interface. + +*--learn-mode *:: + Learn the dynamic NAT translation. Look link:trex_manual.html#_nat_support[here] for details. *--learn-verify*:: - Learn the translation. This feature is intended for verification of the mechanism in cases where there is no NAT. - -*-p*:: - Flow-flip. Sends all flow packets from the same interface. This can solve the flow order. Does not work with any router configuration. + Used for testing the NAT learning mechanism. Do the learning as if DUT is doing NAT, but verify that packets + are not actually changed. -*-e*:: - same as `-p` but comply to the direction rules and replace source/destination IPs. it might not be good for NBAR as it is expected clients ip to be sent from same direction. +*--limit-ports *:: + Limit the number of ports used. Overrides the ``port_limit'' from config file. -//TBD: The last 2 sentences (flow order, router configuration) are unclear. +*--lm *:: +Mask specifying which ports will send traffic. For example, 0x1 - Only port 0 will send. 0x4 - only port 2 will send. +This can be used to verify port connectivity. You can send packets from one port, and look at counters on the DUT. - -*--lm=MASK*:: - Latency mask. Use this to verify port connectivity. Possible values: 0x1 (only port 0 will send traffic), 0x2 (only port 1 will send traffic). +*--lo*:: + Latency only - Send only latency packets. Do not send packets from the templates/pcap files. -*--lo*:: - Latency test. - -*--limit-ports=PORTS*:: - Limit number of ports. Configure this in the --cfg file. Possible values (number of ports): 2, 4, 6, 8. (Default: 4) - -*--nc*:: - If set, will terminate exacly at the end of the duration. This provides a faster, more accurate TRex termination. In default it wait for all the flow to terminate gracefully. In case of a very long flow the termination might be prolong. +*-m *:: + Rate multiplier. TRex will multiply the CPS rate of each template by num. + +*--mac-spread*:: + Spread the destination mac by this this factor. e.g 2 will generate the traffic to 2 devices DEST-MAC ,DEST-MAC+1. The maximum is up to 128 devices. + +*--nc*:: + If set, will terminate exacly at the end of the specified duration. + This provides faster, more accurate TRex termination. + By default (without this option), TRex waits for all flows to terminate gracefully. In case of a very long flow, termination might prolong. + +*--no-flow-control-change*:: + Prevents TRex from changing flow control. By default (without this option), TRex disables flow control at startup for all cards, except for the Intel XL710 40G card. + +*--no-key*:: Daemon mode, don't get input from keyboard. + +*--no-watchdog*:: Disable watchdog. -*-pm=MULTIFLIER*:: - Platform factor. If the setup includes a splitter, you can multiply the total results by this factor. Example: --pm 2.0 will multiply all bps results by this factor. +*-p*:: +Send all packets of the same flow from the same direction. For each flow, TRex will randomly choose between client port and +server port, and send all the packets from this port. src/dst IPs keep their values as if packets are sent from two ports. +Meaning, we get on the same port packets from client to server, and from server to client. + +If you are using this with a router, you can not relay on routing rules to pass traffic to TRex, you must configure policy +based routes to pass all traffic from one DUT port to the other. + + +*-pm *:: + Platform factor. If the setup includes splitter, you can multiply all statistic number displayed by TRex by this factor, so that they will match the DUT counters. *-pubd*:: - Disable ZMQ monitor's publishers. + Disable ZMQ monitor's publishers. -*-1g*:: - Deprecated. Configure TRex to 1G. Configure this in the --cfg file. - -*-k=SEC*:: - Run a latency test before starting the test. TRex will wait for x sec before and after sending latency packets at startup. - Current limitation (holds for TRex version 1.82): does not work properly on VM. +*--rx-check *:: + Enable Rx check module. Using this, each thread randomly samples 1/sample_rate of the flows and checks packet order, latency, and additional statistics for the sampled flows. + Note: This feature works on the RX thread. -*-w=SEC*:: - Wait additional time between NICs initialization and sending traffic. Can be useful if DUT needs extra setup time. Default is 1 second. - -*--cfg=platform_yaml*:: - Load and configure platform using this file. See example file: cfg/cfg_examplexx.yaml - This file is used to configure/mask interfaces, cores, affinity, and MAC addresses. - You can use the example file by copying it to: /etc/trex_cfg.yaml - - -*-v=VERBOSE*:: - Verbose mode (works only on the debug image! ) - 1 Show only stats. - 2 Run preview. Does not write to file. - 3 Run preview and write to stats file. - Note: When using verbose mode, it is not necessary to add an output file. - Caution: Operating in verbose mode can generate very large files (terabytes). Use with caution, only on a local drive. - - -*--rx-check=SAMPLE_RATE*:: - Enable Rx check module. Using this each thread samples flows (1/sample) and checks order, latency, and additional statistics. - Note: This feature operates as an additional thread. - -*--hops=HOPES*:: - Number of hops in the setup (default is one hop). Relevant only if the Rx check is enabled. - -*--iom=MODE*:: - I/O mode for interactive mode. Possible values: 0 (silent), 1 (normal), 2 (short) - -*--no-flow-control-change*:: - Prevents TRex from changing flow control. By default (without this option), TRex disables flow control at startup for all cards, except for the Intel XL710 40G card. +*-v *:: + Show debug info. Value of 1 shows debug info on startup. Value of 3, shows debug info during run at some cases. Might slow down operation. -*--mac-spread*:: - Spread the destination mac by this this factor. e.g 2 will generate the traffic to 2 devices DEST-MAC ,DEST-MAC+1. The maximum is up to 128 devices. +*--vlan*:: Relevant only for stateless mode with Intel 82599 10G NIC. + When configuring flow stat and latency per stream rules, assume all streams uses VLAN. +*-w *:: + Wait additional time between NICs initialization and sending traffic. Can be useful if DUT needs extra setup time. Default is 1 second. ifndef::backend-docbook[] @@ -1561,8 +1561,8 @@ endif::backend-docbook[] === Simulator -The TRex simulator is a linux application that can process on any Linux CEL (it can run on TRex itself). -you can create create output pcap file from input of traffic YAML. +The TRex simulator is a linux application (no DPDK needed) that can run on any Linux (it can also run on TRex machine itself). +you can create output pcap file from input of traffic YAML. ==== Simulator diff --git a/trex_book_basic.asciidoc b/trex_book_basic.asciidoc index 5c8af732..9e376366 100755 --- a/trex_book_basic.asciidoc +++ b/trex_book_basic.asciidoc @@ -8,13 +8,13 @@ This simulator can be run on any Cisco Linux including on the TRex itself. TRex simulates clients and servers and generates traffic based on the pcap files provided. .Clients/Servers -image:images/trex_model.png[title="generator"] +image:images/trex_model.png[title=""] The following is an example YAML-format traffic configuration file (cap2/dns_test.yaml), with explanatory notes. [source,python] ---- -$more cap2/dns_test.yaml +$cat cap2/dns_test.yaml - duration : 10.0 generator : distribution : "seq" @@ -27,7 +27,6 @@ $more cap2/dns_test.yaml dual_port_mask : "1.0.0.0" tcp_aging : 1 udp_aging : 1 - mac : [0x00,0x00,0x00,0x01,0x00,0x00] cap_info : - name: cap2/dns.pcap <3> cps : 1.0 <4> @@ -43,7 +42,7 @@ $more cap2/dns_test.yaml <6> Should be the same as ipg. .DNS template file -image:images/dns_wireshark.png[title="generator"] +image:images/dns_wireshark.png[title=""] The DNS template file includes: @@ -109,6 +108,7 @@ gives //TBD: Not sure what the output looks like here, with this line showing only "gives" .TRex generated output file +//??? missing picture image:images/dns_trex_run.png[title="generator"] As the output file shows... @@ -245,7 +245,6 @@ Use the following to display the output as a chart, with: x axis: time (seconds) y axis: flow ID The output indicates that there are 10 flows in 1 second, as expected, and the IPG is 50 msec + -//TBD: not sure what the "+ +" means ==> [hh] Ascii Doc break page ifndef::backend-docbook[] +++++++++++++++++++++++++++++++++ @@ -514,7 +513,7 @@ you need to be sure that you have enogth free sockets when running TRex in high Open-flows : 1 Servers : 254 Socket : 1 Socket/Clients : 0.0 drop-rate : 0.00 bps ---- -<1> Number of clients +<1> Number of clients <2> sockets utilization (should be lowwer than 20%, elarge the number of clients in case of an issue). === DNS, W=1 @@ -577,7 +576,7 @@ pkt,time sec,fid,flow-pkt-id,client_ip,client_port,server_ip ,desc |================= -=== Mixing HTTP and DNS template +=== Mixing HTTP and DNS templates The following example combines elements of HTTP and DNS templates: @@ -2621,32 +2620,15 @@ chart("#chart4",sfr_data,sfr_names,"time-sec","flow-id"); endif::backend-docbook[] -=== TRex command line +=== Running examples -TRex commands typically include the following main arguments, but only `-f` and `-d` are required. +TRex commands typically include the following main arguments, but only `-f` is required. [source,bash] ---- -$.sudo /t-rex-64 -f [traffic_yaml] -m [muti] -d [duration] -l [Hz=1000] -c [cores] +$.sudo /t-rex-64 -f -m -d -l -c ---- - -*-f=TRAFIC_YAML_FILE*:: - YAML traffic configuration file. - -*-m=MUL*:: - Factor for bandwidth (multiplies the CPS of each template by this value). - -*-d=DURATION*:: - Duration of the test (sec). Default: 0 - -*-l=HZ*:: - Rate (Hz) for running the latency daemon. Example: -l 1000 runs 1000 pkt/sec from each interface. A value of zero (0) disables the latency check. - -*-c=CORES*:: - Number of cores. Use 4 for TRex 40Gb/sec. Monitor the CPU% of TRex - it should be ~50%. - - -The full reference can be found xref:cml-line[here] +Full command line reference can be found xref:cml-line[here] ==== TRex command line examples @@ -2723,11 +2705,11 @@ $.sudo /t-rex-64 -f cap2/imix_64.yaml -c 4 -m 1 -d 100 -l 1000 === Mimicking stateless traffic under stateful mode [NOTE] -TRex now supports a true stateless traffic generation. +TRex supports also true stateless traffic generation. If you are looking for stateless traffic, please visit the following link: xref:trex_stateless.html[TRex Stateless Support] With this feature you can "repeat" flows and create stateless, *IXIA* like streams. -After injecting the number of flows defined by `limit`, TRex repeats the same flows. If all template has a `limit` the CPS will be zero after a time as there are no new flows after the first iteration. +After injecting the number of flows defined by `limit`, TRex repeats the same flows. If all templates have `limit` the CPS will be zero after some time as there are no new flows after the first iteration. *IMIX support:*:: Example: @@ -2739,9 +2721,9 @@ $sudo ./t-rex-64 -f cap2/imix_64.yaml -d 1000 -m 40000 -c 4 -p [WARNING] ===================================================================== The *-p* is used here to send the client side packets from both interfaces. -(Normally it is sent only from client ports only.) -Typically, the traffic client side is sent from the TRex client port; with this option, the port is selected by the client IP. -All the flow packets are sent from the same interface. This may create an issue with routing, as the client's IP will be sent from the server interface. PBR router configuration solves this issue but cannot be used in all cases. So use this `-p` option carefully. +(Normally it is sent from client ports only.) +With this option, the port is selected by the client IP. +All the packets of a flow are sent from the same interface. This may create an issue with routing, as the client's IP will be sent from the server interface. PBR router configuration solves this issue but cannot be used in all cases. So use this `-p` option carefully. ===================================================================== @@ -2817,7 +2799,7 @@ It is possible to mix stateless templates and stateful templates. w : 1 limit : 199 ---- -The templates are duplicate here to better utilize DRAM and to get better performance. +The templates are duplicated here to better utilize DRAM and to get better performance. //TBD: What exactly repeates the templates - TRex, script, ? Also, how does that better utilize DRAM. .Imix YAML `cap2/imix_fast_1g_100k_flows.yaml` example @@ -3001,8 +2983,8 @@ endif::backend-docbook[] === Clients/Servers IP allocation scheme -Currently, there is one global IP pool for clients and servers. It serves all templates. all the templates will allocate IP from this global pool. -Each TRex client/server "dual-port" (pair of ports, such as port 0 for client, port 1 for server) has it own mask offset taken from the YAML. The mask offset is called `dual_port_mask`. +Currently, there is one global IP pool for clients and servers. It serves all templates. All templates will allocate IP from this global pool. +Each TRex client/server "dual-port" (pair of ports, such as port 0 for client, port 1 for server) has its own generator offset, taken from the config file. The offset is called `dual_port_mask`. Example: @@ -3018,37 +3000,32 @@ generator : tcp_aging : 0 udp_aging : 0 ---- -<1> Mask to add per dual-port pair. -The reason we introduce dual_port_mask is to make static route configurable. With this mask, different ports has different prefix. +<1> Offset to add per port pair. +The reason for the ``dual_port_mask'' is to make static route configuration per port possible. With this offset, different ports have different prefixes. -//TBD: needs clarification - this is the format of a port mask? - -With four ports, TRex produces the following output: +For example, with four ports, TRex will produce the following ip ranges: [source,python] ---- - dual-0 (0,1) --> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128) - dual-1 (2,3) --> C (17.0.0.129-17.0.0.255 ) <-> S( 49.0.0.129 - 49.0.0.255) + mask ("1.0.0.0") + port pair-0 (0,1) --> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128) + port pair-1 (2,3) --> C (17.0.0.129-17.0.0.255 ) <-> S( 49.0.0.129 - 49.0.0.255) + mask ("1.0.0.0") ---- -In the case of setting dual-port_mask as 0.0.0.0, both ports will use the same range of ip. -With four ports and dual_port_mask as 0.0.0.0, the ip range is : +- Number of clients : 255 +- Number of servers : 255 +- The offset defined by ``dual_port_mask'' (1.0.0.0) is added for each port pair, but the total number of clients/servers will remain constant (255), and will not depend on the amount of ports. +- TCP/UDP aging is the time it takes to return the socket to the pool. It is required when the number of clients is very small and the template defines a very long duration. +//TBD: not clear - is TCP/UDP aging an option used when the template defines a long duration? also, should specify what "very long" refers to. + +If ``dual-port_mask'' was set to 0.0.0.0, both port pairs would have uses the same ip range. +For example, with four ports, we would have get the following ip range is : [source,python] ---- - dual-0 (0,1) --> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128) - dual-1 (2,3) --> C (16.0.0.129-16.0.0.255 ) <-> S( 48.0.0.129 - 48.0.0.255) + port pair-0 (0,1) --> C (16.0.0.1-16.0.0.128 ) <-> S( 48.0.0.1 - 48.0.0.128) + port pair-1 (2,3) --> C (16.0.0.129-16.0.0.255 ) <-> S( 48.0.0.129 - 48.0.0.255) ---- -//TBD: not clear what the following 5 points are referring to. This looks like it should be a continuation of the footnotes for the example a few lines up. -- Number of clients : 255 -- Number of servers : 255 -- The mask defined by dual_port_mask (1.0.0.0) is added for each dual-port pair, but the total number of clients/servers from YAML will be constant and does not depend on the amount of dual ports. -- TCP/UDP aging is required when the number of clients is very small and the template defines a very long duration. -This is the time it takes to return the socket to the pool. -//TBD: not clear - is TCP/UDP aging an option used when the template defines a long duration? also, should specify what "very long" refers to. -- In the current version, the only option for distribution is "seq". - *Router configuration for this mode:*:: @@ -3092,8 +3069,8 @@ ip route 49.0.0.0 255.0.0.0 33.11.11.12 *One server:*:: -To support a template with one server, you can add a new YAML server_addr ip. Each dual-port pair will be assigned a separate server (in compliance with the mask). -//TBD: clarify +To support a template with one server, you can add ``server_addr'' keyword. Each port pair will be get different server IP +(According to the ``dual_port_mask'' offset). [source,python] ---- @@ -3106,16 +3083,13 @@ To support a template with one server, you can add a new YAML server_addr ip. Ea one_app_server : true <2> wlength : 1 ---- -<1> Server IPv4 address. +<1> Server IP. <2> Enable one server mode. -*w/wlength:*:: -//TBD: looks like this should be a continuation of the footnotes as in 1 and 2 above. +// TBD - what is wlength??? -not require to configure them, user 1 -//TBD: ? - -*new statistic:*:: +In TRex server, you will see the following statistics. +// TBD - need to explain this [source,python] ---- @@ -3127,21 +3101,20 @@ not require to configure them, user 1 [NOTE] ===================================================================== * No backward compatibility with the old generator YAML format. -* When using -p option, TRex will not comply with the static route rules. Server-side traffic may be sent from the client side (port 0) and vice-versa. Use the -p option only with PBR configuration when the router, switch p1<->p2. -//TBD: "when router..." unclear -* VLAN (sub interface feature) does not comply with static route rules. Use it only with PBR. - VLAN0 <-> VALN1 per interface - vlan : { enable : 1 , vlan0 : 100 , vlan1 : 200 } -* Limitation: When using a template with plugins (bundles), the number of servers must be higher than the number of clients. +* When using -p option, TRex will not comply with the static route rules. Server-side traffic may be sent from the client side (port 0) and vice-versa. +If you use the -p option, you must configure policy based routing to pass all traffic from router port 1 to router port 2, and vice versa. +* xref:trex_vlan[VLAN] feature does not comply with static route rules. If you use it, you also need policy based routing +rules to pass packets from VLAN0 to VLAN1 and vice versa. +* Limitation: When using template with plugins (bundles), the number of servers must be higher than the number of clients. ===================================================================== ==== More Details about IP allocations -Each time a new flow is creaed, TRex allocates a new Client IP/port and Server IP. This 3-tuple should be distinct among active flows. +Each time a new flow is created, TRex allocates new Client IP/port and Server IP. This 3-tuple should be distinct among active flows. -Currently, only sequcency distribution is supported in IP allocation. That means the IP address is increased one by one. +Currently, only sequential distribution is supported in IP allocation. This means the IP address is increased by one for each flow. -Let's say if we have 2 candidate IPs in the pool: 16.0.0.1 and 16.0.0.2. So the sequence of allocated clients should be something like this: +For example, if we have a pool of two IP addresses: 16.0.0.1 and 16.0.0.2, the allocation of client src/port pairs will be [source,python] ---- @@ -3149,22 +3122,25 @@ Let's say if we have 2 candidate IPs in the pool: 16.0.0.1 and 16.0.0.2. So the 16.0.0.0.2 [1024] 16.0.0.0.1 [1025] 16.0.0.0.2 [1025] +16.0.0.0.1 [1026] +16.0.0.0.2 [1026] +... ---- -==== How to decide the PPS and BPS +==== How to determine the packet per second(PPS) and Bit per second (BPS) -- Example of one flow with 4 packets -- Green are first packet of flow -- Lets say the client ip pool starts from 16.0.0.1, and the distribution is seq. +- Let's look at an example of one flow with 4 packets. +- Green circles represent the first packet of each flow. +- The client ip pool starts from 16.0.0.1, and the distribution is seq. -image:images/ip_allocation.png[title="rigt"] +image:images/ip_allocation.png[title=""] latexmath:[$Total PPS = \sum_{k=0}^{n}(CPS_{k}\times {flow\_pkts}_{k})$] latexmath:[$Concurrent flow = \sum_{k=0}^{n}CPS_{k}\times flow\_duration_k $] +// TBD Ido: The latexmath formulas only looks good in pdf format. In HTML they are not clear. - -The above fomulars can be used to calculate the PPS. The TRex throughput depends on the PPS calculated above and the value of m (a multiplier assigned by TRex cli). +The above formulas can be used to calculate the PPS. The TRex throughput depends on the PPS calculated above and the value of m (a multiplier given as command line argument -m). The m value is a multiplier of total pcap files CPS. CPS of pcap file is configured on yaml file. @@ -3193,7 +3169,7 @@ So if the m is set as 1, the total PPS is : 102*2+50*20 = 1204 PPS. The BPS depends on the packet size. You can refer to your packet size and get the BPS = PPS*Packet_size. -==== Client/Server IP allocation +==== Per template allocation + future plans - *1) per-template generator* @@ -3246,13 +3222,13 @@ The YAML configuration is something like this: w : 1 ---- -- *2) More distributions will be supported (normal distribution, random distribution, etc)* +- *2) More distributions will be supported in the future (normal distribution for example)* Currently, only sequcence and random are supported. - *3) Histogram of tuple pool will be supported* -This feature gives user more flexibility to define the IP generator. +This feature will give the user more flexibility in defining the IP generator. [source,python] ---- @@ -3282,9 +3258,9 @@ This feature gives user more flexibility to define the IP generator. -=== Measure Jitter/Latency +=== Measuring Jitter/Latency -To measure jitter/latency on high priorty packets (one SCTP or ICMP flow), use `-l [Hz]` where Hz defines the number of packets to send from each port per second. +To measure jitter/latency using independent flows (SCTP or ICMP), use `-l [Hz]` where Hz defines the number of packets to send from each port per second. This option measures latency and jitter. We can define the type of traffic used for the latency measurement using the `--l-pkt-mode` option. @@ -3296,12 +3272,12 @@ This option measures latency and jitter. We can define the type of traffic used | 1 | ICMP echo request packets from both sides | 2 | -*Stateful*, send ICMP requests from one side, and matching ICMP responses from other side. +Send ICMP requests from one side, and matching ICMP responses from other side. This is particulary usefull if your DUT drops traffic from outside, and you need to open pin hole to get the outside traffic in (for example when testing a firewall) | 3 | -send ICMP request packets with a constant 0 sequence number. +Send ICMP request packets with a constant 0 sequence number from both sides. |================= diff --git a/trex_config.asciidoc b/trex_config.asciidoc index 42f21b62..ca68bbe7 100755 --- a/trex_config.asciidoc +++ b/trex_config.asciidoc @@ -1,10 +1,10 @@ TRex first time configuration ============================= -:author: hhaim with the Help of Amir Kroparo +:author: hhaim with the Help of Amir Kroparo. New rev fixes by Ido Barnea. :email: :description: TRex Getting started - instalation guide :revdate: 2014-11-01 -:revnumber: 0.1 +:revnumber: 0.2 :deckjs_theme: swiss :deckjs_transition: horizontal-slide :scrollable: @@ -94,181 +94,169 @@ html, body { $('#title-slide').css("background-position","center"); $('h1').html(''); $('h3').html('Hanoch Haim '); - $('h4').html('04/2015'); + $('h4').html('Updated 10/2016'); ++++++++++++++++++ +== General info +* This guide will help you configure Cisco ASR1K as DUT connected to TRex running in stateful mode. +* This can be easily adopted for working with any L3 device. Equivalent commands for configuring Linux as your DUT are shown at the end as well. +* Two options are given for configuring the router. Policy based route, and static route. You should +choose the one appropriate for your needs. +* TRex should be directly connected to ASR1K ports, and will act as both client and server. -== Simple configuration +== Setup description -* TRex does not implement ARP emulation -* This guide will help you to configure Cisco ASR1K to work with TRex -* TRex is directly connected to ASR1K ports. +* TRex will emulate the networks described in the figure below (on each side of the DUT, router connected to one or more clients/servers networks). -image::images/TrexConfig.png[title="TRex/Router setup"] -. TRex port 0 - Client side -. Router TenG 0/0/0 -. Router TenG 0/0/1 -. TRex port 1 - Server side - +image::images/trex-asr-setup.png[title="TRex/Router setup"] + +== Not supported setup description + +* Notice that the following setup is *not* supported (Having TRex emulate a bunch of hosts connected by switch to the DUT). +This means that the TRex IP addresses defined in ``generator'' section should be in different network then the DUT addresses +and TRex addresses defined in port_info section. + +image::images/trex-not-supported-setup.png[title="Not supported setup"] == TRex configuration -* TRex act as both client and server side -* TRex port mac address should configure correctly, so packet generated from port 1 will get to 2 and vice-versa -* To use the config file you can add this switch `--cfg [file]` -* Or edit the configuration file in `/etc/trex_cfg.yaml` +* You can specify config file to use by the `--cfg` command line argument +or use the default config file `/etc/trex_cfg.yaml` +* Below is an example of how to configure TRex IP addresses. TRex will issue ARP for default_gw, +and send gratuitous ARP for ip, on each port. This works, starting from TRex version 2.10. +If you want to configure MAC addresses manually (equivalent to static +ARP), or running older TRex version, please see the full description of config file parameters in the manual. [source,python] ---- - - port_limit : 2 - port_info : # set eh mac addr - - dest_mac : [0x0,0x0,0x0,0x1,0x0,0x00] <1> - src_mac : [0x0,0x0,0x0,0x2,0x0,0x00] <2> - - dest_mac : [0x0,0x0,0x0,0x3,0x0,0x00] <3> - src_mac : [0x0,0x0,0x0,0x4,0x0,0x00] <4> + - port_limit : 2 + port_info : + - default_gw : 11.11.11.1 <1> + ip : 11.11.11.2 <2> + - default_gw : 12.12.12.1 <3> + ip : 12.12.12.2 <4> ---- -<1> Correspond to TRex port 0 - should be Router TenG 0/0/0 mac-address -<2> Should be distinc mac-address, router should be configure to sent to this mac-address -<3> Correspond to TRex port 1 - should be Router TenG 0/0/1 mac-address -<4> Should be distinc mac-address, router should be configure to sent to this mac-address +<1> TRex port 0 config- should be router's TenG 0/0/0 IP. +TRex will try to resolve this address by sending ARP request. +<2> Next hop of router's TenG 0/0/0. TRex will send gratuitous ARP for this address. +<3> TRex port 1 config- should be router's TenG 0/0/1 IP. +TRex will try to resolve this address by sending ARP request. +<4> Next hop of router's TenG 0/0/0. TRex will send gratuitous ARP for this address. + +== TRex emulated server/client IPs definition in traffic config file -== Router configuration PBR part 1 +* You specify traffic config file by running TRex with -f (TRex stateful mode). +* Examples for client config files exist in TREX_ROOT/scripts/cfg directory. +* Add following section to the traffic config file, to define the range of IPs for clients and servers. -* Router moves packets from port 0->1 and 1->0 without looking into IP address. +[source,python] +---- +generator : + distribution : "seq" + clients_start : "16.0.0.1" + clients_end : "16.0.0.255" + servers_start : "48.0.0.1" + servers_end : "48.0.0.240" +---- -* TenG 0/0/0 <-> TenG 0/0/1 +* In this example, there are: +** 255 clients talking to 240 servers -*Router configuration:*:: +== Router config. Option 1 - static routes [source,python] ---- interface TenGigabitEthernet0/0/0 - mac-address 0000.0001.0000 <1> - mtu 4000 <2> - ip address 11.11.11.11 255.255.255.0 <3> - ip policy route-map p1_to_p2 <4> - load-interval 30 + ip address 11.11.11.1 255.255.255.0 ! - +` interface TenGigabitEthernet0/0/1 - mac-address 0000.0003.0000 <5> - mtu 4000 - ip address 12.11.11.11 255.255.255.0 - ip policy route-map p2_to_p1 - load-interval 30 + ip address 12.12.12.1 255.255.255.0 ! +ip route 16.0.0.0 255.0.0.0 11.11.11.2 <1> +ip route 48.0.0.0 255.0.0.0 12.12.12.2 <2> ---- -<1> Configure mac-address to match TRex destination port-0 -<2> Set MTU -<3> Set an ip address ( routing can't work without this) -<4> Configure PBR policy - see next slide -<5> Configure mac-address to match TRex destination port-1 +<1> Route clients network to TRex server emulation interface. +<2> Route servers network to TRex client emulation interface. -== Router configuration PBR part 2 +== Router config. Option 2 - PBR part 1 + +* Router is configured to statically route packets from 0/0/0 to 0/0/1 and from 0/0/1 to 0/0/0. + +*Router configuration:*:: [source,python] ---- - -route-map p1_to_p2 permit 10 - set ip next-hop 12.11.11.12 <1> +interface TenGigabitEthernet0/0/0 + ip address 11.11.11.1 255.255.255.0 <1> + ip policy route-map p1_to_p2 <2> + load-interval 30 ! -route-map p2_to_p1 permit 10 - set ip next-hop 11.11.11.12 <2> +interface TenGigabitEthernet0/0/1 + ip address 12.12.12.1 255.255.255.0 <1> + ip policy route-map p2_to_p1 <2> + load-interval 30 +! ---- +<1> Configure ip address for the port. +<2> Configure PBR policy - see next slide -<1> Set the destination packet to be 12.11.11.12 which correspond to TenG 0/0/1 -<2> Set the destination packet to be 11.11.11.12 which correspond to TenG 0/0/0 - - -== Router configuration PBR part 3 - -* What about destination mac-address it should be TRex source mac-address? -* The folowing configuration address it +== Router config. Option 2 - PBR part 2 [source,python] ---- - arp 11.11.11.12 0000.0002.0000 ARPA <1> - arp 12.11.11.12 0000.0004.0000 ARPA <2> ----- -<1> Destination mac-address of packets sent from If 0/0/0 is matched to TRex source mac-address port-0 -<2> Destination mac-address of packets sent from If 0/0/1 is matched to TRex source mac-address port-1 -== Static-route configuration - TRex - -* You can set static range of IPs for client and server side +route-map p1_to_p2 permit 10 + set ip next-hop 12.12.12.2 <1> +! +route-map p2_to_p1 permit 10 + set ip next-hop 11.11.11.2 <2> -[source,python] ----- -generator : - distribution : "seq" - clients_start : "16.0.0.1" - clients_end : "16.0.0.255" - servers_start : "48.0.0.1" - servers_end : "48.0.0.240" - dual_port_mask : "1.0.0.0" - tcp_aging : 0 - udp_aging : 0 ---- -* In this example, you should expect: -** Number of clients 255 -** Number of servers 240 +<1> Set the destination to be 12.12.12.2, in the subnet of TenG 0/0/1. +<2> Set the destination to be 11.11.11.2 , in the subnet to TenG 0/0/0. -== Static-route configuration - Router +== Verify cable connections -[source,python] ----- -interface TenGigabitEthernet0/0/0 - mac-address 0000.0001.0000 - mtu 4000 - ip address 11.11.11.11 255.255.255.0 -! -` -interface TenGigabitEthernet0/0/1 - mac-address 0000.0003.0000 - mtu 4000 - ip address 22.11.11.11 255.255.255.0 -! -ip route 16.0.0.0 255.0.0.0 11.11.11.12 <1> -ip route 48.0.0.0 255.0.0.0 22.11.11.12 <2> ----- -<1> Match the range of TRex YAML ( client side 0/0/0 ) -<2> Match the range of TRex YAML ( server side 0/0/1) - -== Verify configuration - -* To verify that TRex port-0 is connected to Router 0/0/0 and not 0/0/1 run +* To verify that TRex port-0 is really connected to Router 0/0/0, you can run the following. ........................................... -$./t-rex-64 -f cap2/dns.yaml -m 1 -d 100 -l 1000 --lo --lm 1 +$./t-rex-64 -f cap2/dns.yaml -m 1 -d 10 -l 1000 --lo --lm 1 ........................................... * It sends packets only from TRex port-0 ( `--lm 1` ) * to send only from TRex port 1 do this: ........................................... -$./t-rex-64 -f cap2/dns.yaml -m 1 -d 100 -l 1000 --lo --lm 2 +$./t-rex-64 -f cap2/dns.yaml -m 1 -d 10 -l 1000 --lo --lm 2 ........................................... -* In case you are connected to a Switch you must send packet from both direction first +* If you are connected to a switch, you must send packets from both directions for few seconds first, to allow +the switch to learn the MAC addresses of both sides. ........................................... -$./t-rex-64 -f cap2/dns.yaml -m 1 -d 100 -l 1000 +$./t-rex-64 -f cap2/dns.yaml -m 1 -d 10 -l 1000 ........................................... +== Linux config + +* Assuming the same setup with Linux as DUT instead of the router, you can do the following. +* Configure IPs of Linux interfaces to 12.12.12.1 and 11.11.11.1 +* route add -net 48.0.0.0 netmask 255.0.0.0 gw 12.12.12.2 +* route add -net 16.0.0.0 netmask 255.0.0.0 gw 11.11.11.2 -== Static-route configuration - IPV6 + +== Static route configuration - IPV6 [source,python] ---- interface TenGigabitEthernet1/0/0 - mac-address 0000.0001.0000 - mtu 4000 - ip address 11.11.11.11 255.255.255.0 + ip address 11.11.11.1 255.255.255.0 ip policy route-map p1_to_p2 load-interval 30 ipv6 enable #<1> @@ -300,8 +288,3 @@ csi-mcp-asr1k-40(config)#ipv6 route 5000::/64 3001::2 <5> Mac-addr setting should be like TRex <6> PBR configuraion - - - - - diff --git a/trex_faq.asciidoc b/trex_faq.asciidoc index 169b04be..44f4f237 100644 --- a/trex_faq.asciidoc +++ b/trex_faq.asciidoc @@ -197,13 +197,21 @@ Then, you can find some basic examples link:trex_manual.html#_trex_command_line[ A switch might be configured with spanning tree enabled. TRex reset the port at startup, making the switch reset it side as well, and spanning tree can drop the packets until it stabilizes. Disabling spanning tree can help. On Cisco nexus, you can do that using `spanning-tree port type edge` -You can also start Cisco with -k flag. This will send packets for k seconds before starting the actual test, letting the spanning +You can also start TRex with -k flag. This will send packets for k seconds before starting the actual test, letting the spanning tree time to stabilize. This issue will be fixed when we consolidate ``Stateful'' and ``Stateless'' RPC. -==== I can not see RX packets -TRex does not support ARP yet, you should configure the DUT to send the packets to the TRex port MAC address. From Stateless mode, you can change the port mode to promiscuous. + -Also, revisit your MAC address configuration in the TRex config file. Wrong MAC address configuration will cause all packets to be dropped. +==== I can not see any RX packets. +Most common reason is problems with MAC addresses. +If your ports are connected in loopback, follow link:trex_manual.html#_configuring_for_loopback[this] carefully. + +If loopback worked for you, continue link:trex_manual.html#_configuring_for_running_with_router_or_other_l3_device_as_dut[here]. + +If you set MAC addresses manually in your config file, check again that they are correct. + +If you have ip and default_gw in your config file, you can debug the initial ARP resolution process by running TRex with +-d 1 flag (will stop TRex 1 second after init phase, so you can scroll up and look at init stage log), and -v 1. +This will dump the result of ARP resolution (``dst MAC:...''). You can also try -v 3. +This will print more debug info, and also ARP packets TX/RX indication and statistics. + +On the DUT side - If you configured static ARP, verify it is correct. If you depend on TRex gratuitous ARP messages, look at the DUT ARP +table after TRex init phase and verify its correctness. ==== Why the performance is low? @@ -342,12 +350,12 @@ Q:: I want to use the Python API via Java (with Jython), apparently, I can not i The way I see it I have two options: 1. Creating python scripts and call them from java (with ProcessBuilder for example) -2. Call directly to the Trex server over RPC from Java +2. Call directly to the TRex server over RPC from Java However, option 2 seems like a re-writing the API for Java (which I am not going to do) On the other hand, with option 1, once the script is done, the client object destroyed and I cannot use it anymore in my tests. -Any ideas on what is the best way to use Trex within JAVA? +Any ideas on what is the best way to use TRex within JAVA? A:: diff --git a/trex_preso.asciidoc b/trex_preso.asciidoc index c89bca09..46ec91f8 100755 --- a/trex_preso.asciidoc +++ b/trex_preso.asciidoc @@ -110,6 +110,7 @@ html, body { $('h1').html(''); $('h3').html('Hanoch Haim v1.2'); $('h4').html('04/2015'); + $('h5').html('Updated 10/2016');