From 31b141a7d2d9fc4d75e3468cfdbbc342d346fa7d Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Thu, 19 May 2022 16:31:04 +0000 Subject: [PATCH 01/18] Add VLAN and PortChannel test plan For vlan, it includes: 1. Vlan functionalities - Flooding - Forwarding - Trunk/Access - Tagging/Untagging(802.1Q) - VLAN interface (RIF/SVI) 2. SAI APIs operations - Vlan Counters - Vlan and member list operations For PortChannel, it includes: 1. Lag functionalities - Loadbalance 2. Lag SAI APIs - create/check/remove lag and lag member Signed-off-by: richardyu-ms --- doc/sai-ptf/img/Component_topology.jpg | Bin 0 -> 39862 bytes doc/sai-ptf/img/Device_topology.jpg | Bin 0 -> 17549 bytes doc/sai-ptf/img/SAI_PTF_Topology.jpg | Bin 0 -> 11474 bytes doc/sai-ptf/lag_test_plan.md | 140 +++++++ doc/sai-ptf/vlan_test_plan.md | 531 +++++++++++++++++++++++++ 5 files changed, 671 insertions(+) create mode 100644 doc/sai-ptf/img/Component_topology.jpg create mode 100644 doc/sai-ptf/img/Device_topology.jpg create mode 100644 doc/sai-ptf/img/SAI_PTF_Topology.jpg create mode 100644 doc/sai-ptf/lag_test_plan.md create mode 100644 doc/sai-ptf/vlan_test_plan.md diff --git a/doc/sai-ptf/img/Component_topology.jpg b/doc/sai-ptf/img/Component_topology.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a51295929bab78355ba2fe1ec7e657f92932e983 GIT binary patch literal 39862 zcmeEucUTkaws+_#AcFL+ARq{+bSV)L5D*chR~6|3(mPQQkw`~Cx`2q(Nbdxs_g)M_ z=)Hv+AmtnPx%-^Gy=ULEZ~5*$f1LOXdB(gm^RD%-`djNA`~-dmbY4waRT)G;KmhUr z{(B7qlLeU2>+o@iIDtocnfh6TSA}4v**)m%uY;85o(ESuXSP@m~=T6PJ*blD?^U zM@d=buBzHY9bG+r14AQ=r#vmkL>CP}7a=h*5i!{hx(En8frE&KnB?MhQd$Kqvd7LBF5P%ZPIo&x zqqyk|x2X0G{S%kLvkW|9vzJjnNc)AdKSx;Le~Gfc681N`5Fkn-0$}loXh2}l=@VNK zM|bs)>fbC37Pv^Bkls+aWs9^P0k7~$Vh@q?s@8bW#pLaiHRK6Re!08-ecF;DWHxbJkj32%%1+wlB%T0d^1uyGM9@$h#KkpJ8GA}y6M z0f;KumyrGca7LU4xmX^Ke@*C**X&;$`j-s-OUwRg?a+sM`%@)Da2c;tGSf7qt!y3K z!im~Q-^PQ~hQe*TGBqu3mSr(XR36-f@@IZnlg>+Sz5G7;zaAKD|uk`659`ILc|ZZLm_(yfLHNT!O{8G&Y5GdhIkN?1`i5$E7LkK zdi<|J|6;+Pmx3#tp>_5-UJ2@@qeVh#GLx@v=d&i+?y7<5gBQPF44?o@n?ic|HHbU0F{& zNUjiq>fg!gKp`=Q<##_KO!yjFdj&yCu46WJWgP z=q^WTGF4KRW^v`BbCevMWqb_0K;w=FnQ#Jevv|Ls2p$w|ft#${FR)iovT=XB)|Kgb zQ-D9Sy6;5+9&{ekUIKw*1#g#P6!0L9P8=SzU-$(NY7LFxM&DcG&xB@KB$eVpQN2f4 zcPA|QC?flJal2IHoIf%;oH}Ux(jS^~ABQ81w+1ky$z%OQKR{-qtso~DCoF-W31^$K zAllkciBA8M_e&+Z2L%6(gN*xUoveekoA1haIpG=rT~WU5lkIH)n-d*t#)Hm~XruTr zZ!7VjgLM(y3%kwVo!TclK706k_4^ASl|@cg@SwgLmVNFLSs!Fel$H{`^5g&FoJkxk za0-m(2TcIWFPI#C#e+h(MMD#11mno})Y>5#>ovS(1qk`loVBwdln%l%4{`=J`PfyKb=^gn z&?=e@F@1oD-V`eA;iFZQ&!WA_c{{sAuon-qp{7JbzD~0Z*D1_u+!$6xkrd?+t|A|Y zKeo@YYI>75|6Jg{O2tiDYE4woS2M=sM)}KQRy#}ah=fCp5u}~{og1OVR~4PwT*%o@ zb@tSCCmIY^PDDM%+i;ZC)e+OkRs`kny;<%EIW-3BC(l6yC8~0HedTiyDx2}ZVSUuO zxSa1d$Y@Nb+b_iNyznR{W8?78k3$ztJGQ4o^2z~HQ-(m z?PltvF=BL{GP7@!m;an|t*ulawYl0*0fb^DfN6-udgm}M`&;6z3*ztilZ#VG1*F&P zpA?!Q5@pP9WkRpK0n{4wXO0Cwz>siPzQ%*rHzE5^^z-!N(CauACn`K>9DxU|w7_&= zg7g?=p9#n;SDqOUpxPdI5U$=55D+TUpZ~*Es22+PATwM&scxMiWuplG8lj7&hu zd`B|O@A^C|voJ=yz<7=3>!g)VS0{~hqt^tf$;>>LHEFdj9u!;Vbb5gi4^pRkfEqc! z0xvrXbZ5W8G*^uxDLhEaDP26hqt#ZzeQir&dmMDG`2qt{=mfdrgbB|kUyENg-_b}5 zo=rc$g1Z>8tHH6iDVQ^@YU$#aqbY2Is+WHx8Wy3fl96W=8SW=;!CTJW_F)zyd+}yc zc0q|4hYhJL$wN3-WNnIPtBZLlA0`N6fd^Sc0Dwk@kmgQ5PJOv0{iv)T%PYocamAE5GC>B_IpViDh(k-NL=qwo08|XT9Ng1Tb~&_uB<5R@#yl=C8rHS6&p((x6IJMRkW;B@J0fT9wU z&}rTJGY5V79~q*IKXNife##x&O&fhsD1Xtz-?(Z9*0)-kf(BeR z52P7#ND%_~Zu++M0M0=_mD7hN6YDi@jAJOYp{2nmlh4l2KS+*KLT(-iQEQY8?)y53 z+z;t2D-C@TDA!uS#YA*f6&#wkI*Yw1YlP!7zGqirhz&22ZC_$TW=EG8WJkQgUTKD>Vn%7D`i~wzavwhX(`#ny>Y1j3g!Qx@F%_8 z|CJZEPW2jYHj~kOyE+dhhkTXcvA)CdENZQ^FGSw;u7S7BcNa2qqskdL>H7A(5(*Yk zZY((Ugu<$#xNJD{Y1!~#WZ#48?^_ehR_$ySpJei`C>c%bW1Jv8)jAIT$Pmo+rQTUi zcC>LTOYhMOCt0v_&iavqzpG{8nW#yVF9Zn5H|$*##IM;NJvu0a2b-O*+gUy=$}hCL zzQ(czcN2D}c=Kd;&O~?wDlRQUF^ z%G%38!8A`fZ4=F7#S>=X$mH2y4)|FOn;2ZVCssAKwiZ`V04OpcU@2exnM2T?bC9kC8 zZ1f;+!1Le0NL*ZoA&v`3*`MM;kQ2QL$XrW14Tjepn2T0%@9*?h`*%TOiV8}8yQ3|n z=_uO#58{b>iBp{HCt!{anEalGbC8ZwFg8FE_ad%{dY+peBU%6iJ;Sn%KvVE3?*;KVem5M z$f-jMo8b-QWRtt}?YPnzJSg7W1rNG*^6~WV4x)n;puvj?-{C#-x$?`Owamzyx!y%Tpg)9*OKx=V?~2(dj1u5z@c?f?!PFn}T0dIq46=8Txl)n%82te1hp0 z@t|LS`E^qNn#%t;SLmm_gb*53?0rjovFNkg-FtRSt7>Ay8uo?o-o%kC0lSUbzps|2 z=K!_kdJ8)Nq~qjFk?$-7^Oo~)3ZCupL_+00wUwKWmXb^A@02vy8Xbg_i^bwWtHyv# zzrDbwvXeOSBXMaL|6MAl){j$^L>`R7_qp}$oH<)g;oK~oWYbE2F@NFK>1zycmLX9MVBdQ18~zZn4NRfEwQ65}d@7D>JWaim;cIVnk9Cb5?-A}H#km74qIMz93()1}c z5ZaDPs}f@u7gmC&4XGCEdkjeN@!;qIs?LBz!7C5y@gTSh1SOu5_f@zz>2}ysQS`W$ zNhF2`2gK+Zw~uhxPCTduK$d<#Tz)#;1y`tF{3phW`TF=buZ{Y$yVG~zL0>iJG*9S6 zAlu*5F&dmZvFKP_Fa`4Thz}3Cpi-IhUH*UZrX%_R*TSJNpIhCJ*0`my?g2xUL>kq?)sU4{87Mr(N z7lzZ60@dVTk%O%4h`b?nuyH;qWFPIz!?Oj z1A+>Zh}R0sCy{DaS%UXWe9J6`m$@TP7`DON!*~!%3}Ukm-xr#OAaej!vDe(V=eZjo zh-v(f$JyXo+97;%@E)opLDo|hQ($_IdpIok$ATS3)B=;ATE?D000sKrx}Ug2NM5(E zyLfqPmT@etH zpw)HuOI+~{=Z{4LtU7vFE;-cr40%iL{qK{3kwV{mchm znPV_L?$NVB10>?+HkQIO{b&^rLMMTL&;NglJC0{~apIKFIQW2mf)_*^H(YM(2NQ~} zh^`f1lP3dWlmIYnpMHI3ig~bAH%HtmVa>%tp3eLa6S)uobBa*|B}dQ7=S=9L%cEtBkX?bTH?|%ubtrQ`H&Um zqLDdp=uv>Om^^hI^bf+n)k-94Q4;Iwv}k6zu*!0PC5=g(ddfJRj8kcIXh zCM;kpBoZ_U3HYzRN-uw0LI4(ahAvJ`Y_7Ui{Sukxhu>~oYgcEi018(Icb3L`&Bc^z z9kGdh-vdR%tfB7M(em)H@yghCCnqOXb+M9by5V$BOD_z7&h#>tR5@;FD7oC!j3mvb zsy|47<)_XY>9NK&N>XNKoW*uEkW+G#^$gc?*NP{bi1@gc)h~#tNqd{qF|Sc2*2Nsl zR6aa@9hHnzjV}ZsS0Lh376Q3&5C8%o-;AqHU$TEvj3ELLKK~G`E4XJYa#ASZ`?H2Y zP6XlW-M4-d2SoKgQE07s9rU+uKLE#xVuxY<@Su%P^)+=W^CFlRn~?QoJjhafbF}#l z?&8WUxn*>I5==BVJFVnH8T0JPR7p6*PaNck)WqY(<`V z{GeXo3^S|F7bp?YJ1JM%y8Nq6ce$@;k#Yrpw;?Ld%%3ttAXa1SBp(XZ7hFrsj)zRW z8K8`Jn3#MyE+?2cTuiN7? z#*pJq1N@np_0^T7rSV%^UWJ=8iaf(=v$SGFmlGpFpffxJ#N}TD2F-Wx_hbFr@t{(D zCwo~*iQ?~*8f*hSFXv+B%D!k&UJl3& z&ot-B8W5zOFJSeaO;uMEsCpPwwl5zt)L;>sIn8?x;R5SZkrP^6Qv^cUZ>TK$-Dvpkn6>;2kz#P-88 z&jxQ>#CCgLFKBxLRp5Ek*)CORPK)kCs-sAgGZ8k3v|{hPNmX~p3exW)2^>=`WkYS? zaOXh#yxz%^RYdN625LJ**zcn6oXp!qu~SoF{UEJ~UAdBPJs*iKHHTc=v1JT@E8u8vZUlPE89)d~pY?W$kn3?+mCCfi@Tv0pgZ zKSwP_%*EKOE&meDRzXK&Ao)`(j$>kyq1j>|0EZ#`anyOt;#i{(%+7o z#~|+d$rK_ckjj=N@aorK-dX3U=P{yf%-$SNKKZzFJ(N|LuV+<3EhW#&d@e$4Yg1I% z4BorOIL%Fa{gHwzD@mhl#K^Jf&>B1IN<-Kr>*T)|X+u36~m=|cxz){cN?fh?gByTVH)uT}N! z*|Lb5q+~frv_=}Z5k_`5ztf=Y&1x%mHZtYZ4yS|={4Q@VKKk@n5L9pm@oL9Q%&6bo ze0`fe5us&p9^I@`g<^>Oh$yS1Dl$-oSUa->QQS$E=1B>>^EN`x6^i^c45+#(F#vjS z$;tq+9mY!&IEQ5WQojU{O!LTfEQ!|<-~rJ)={Nv%Q9I-W>}>~}bNuA&-Y)W(WloN9 z#Uc!?1^N3Pwub!=>Ox1?SuZ|1v{nMDWmgdN>2uWRL(L;RDEl|?Oa&*p_<9TEOsW!{ zmd-QR-#2II`~sJIsK*UF5^PWLL?9bljN7Rl#?~`8Fm2ze9-!9i9ggm0J;2DB~Ot*4SM5RF8(Dv#w3vCR{D2>pm%g9H`%K zT;TiWN}I@!1X)o3cAnuNZJGnDBz=OL%%zW+-+_T#CPb6H|LzFy(1fp=m?$j5(E^ zPitGQc=-aOJ~ZEB>}G0j(i91?NJ>;k{uNMk0`YuAindo!V*u0G-BaDT9>GJU(x+cW zgs;ZjWt4g1{&L_Zs0Z}u7UiuqTfxuS(Fm*L zt^BC#^^ILokn%=!luAa9NbqHV;mP)x#A`!-{oOmN=T~EmH9r}DH|&UXxGJzy!qi|Kv1iaIu7fE3yys6bitzM!W4X5bG>n&la1KmV?9gq{2KWy9AYD~Dszf+WIH7a zPKSb<6c4@dpyG*Z=Z+XM8dKFJc3UqK=#yMeDlAw_g1x~Bqu;8<-bYzweX{WwEB@9z zyJ;o^V)4SXCFx0ClYO<5CvQn$9G0|ounqFkHyYus9Vu|Ue5w;FG+ML9NQ0QV>3|qE z&VQ3Fb%)F+B^b1DHoe8{+<Eo&Y}=^S6aShf2f|qz7vF^#O`aH4o(15DH2^ci7ZUA| z2c1B1Zd7&Z`@4cj*`4P=Wt&?9V&Q*Pp>$zS`!>3BJqWtkz(u8rqYY-XVyM|2cKSv{ zfMn{IE;?!i@A6GR#zir`wnEuo>g}6|AvTt0EhqOZhUJ1iYWxP&mQ(UwbR63gz213+ zd08P(ZE(x|9Cs729v*28NHhCY78GX~e3uA7Q(@`YcjJ}%;x@Zo?N%Hn1ND(SqjM;o z^fHxD%~#uH$@VQf^@$X@hN?H!rk|ba(8Zl~9sPp!@!2yfHIm$@wD8PUkum#@ju^8? zZ!Z#RR;DWWEk?(IOzx7;N8f=tdsOQ} z>Rr(3M>eZ^6;^;$!?tDT7UjD$RlOst(bK1;l)992%Y&sCYNEtFLLGA#Twv#_BK2|0); zmoFl6MrZ6HhIyxUwWrWg?5&$=j+AAXAkh}ndH<%OqH4niHni%ta1nP&UAggU*to}- zPvK~NVRIA_V`YR=XeCI}GQiQ(nm0ImTmuZGDje3>XL8R@@StXqfiCRl+3NHekvB0D z(vyU;P3O)8TPg!V{Kb%>dG#d3yhdeO?~uCfWBuTPMMH9uyYlZ_<)yeHMjf=7#z+)c zT0Rq!v`M@iW}2t(F~CUf_{Rzu8<@7+#3bt9$BooToNaxJvU$3DdrO+46g2bV8o!aL z8x9Vuck1o$aC zb47?ZE}DPOI>b62BgwQo{PKl!hwMn&rJaDF!nMJ*gecQy2pcbf=i|>NhWAi0=i0s4 znMY`%n4-=|wQ2Cf-1z{wBN~bsKHaXGJWAfigE}RT!NV4P2V|&b8wj;q`guD$oqV-(6`+UDmNgMea}cyjn(%%@f*UtN4ST{_pJ{8o&s`3q6&%z5T0_|WF>|#mKcmNb_-n^}S5y|abklL?xnrS} zc%Hpp`T1re_O^QW0?nL{l?h|qn$@0Gmhs;icFb z@vKNXJm@Ln_=YWqc~r9G$J*jD3n@9fHd!EwkrOjNJrY5WV##o~Jj@R^IdOpkQ$A;J zI(pwogDJj5*^J>qvjPLSF@$&3>1}LE3+#);!RfJdoAdB=J%tmH6feUUoTAhee@@gS^EH&Cl$S-v;1x2`qkgjSfJIMMv(*VcH2FEO=Q z4rS*1OeEqnP)^^I#V*V1`9l)M>Yw~J3z67SB#e74e(V1I!I6`sUDsz#j|C@V6T1ZW z;(;j5LKS0{%^3oI26Tt!=U}UHQWqLF;Rl^3r{g6*XCU8#6XZEk3hlEiTGd^b0gz#q zD`cks4WIp_$4)mIdLs8^8Zj7uBBNa6o;d%$^kSnlSBt#q#G_l{-_VWI2)}1Lc4(`v zw(af#Cq42aC$ni0ex_@R1uh)#+q?S1`75mrf8>|^qRH2r`JfMC)BKXx?@zi zoh=$=t-~IQAWEr7ip+k2%Tfd zoUA{)Q>YuCG8e!KGpZ}9ZpSK$Jswh$Q@k=0X<=Z*`O;4^Tf_cx0ppNRgnT#EbiTVg zRW;FB3#cJ8-OENULb7`g(o*1KodK`vO#wsJj(!?OMpDe4R;~-PF?w_d^snSYXG(-rb_QOv7mXayjHDI zdE>oi;_IPr#B3HLbt<#Z=ZM5x2A54#R^nN@+DH_)AL*rxPRt>bCf`x zJmpSHz=h;y^{lT5hi=jS3#BsZ+-!*~x78CxgX$_~Zb^60Wqmq@G?{1b?+E~H1f95= zl!$Ofs2J8l&r7VI*0zRXC03ectdM>o+UyFe5g+4)y9Bqtkpu>Qco}POA{;$O0sA&K z-f|eggCaqOvfc}NplYuDzTnffqKmsh&o0J!T&Q$ii06qli~We!yfcg&coMNYyOnWG zUFa~&*^@8cC$p}v2kH~`k?@vWu=#*nEj#0#@*%Mf*|#$MdQ6w5dyDBFQ5N%{)@=90 zQY(j$g78tlxL|kpPw6|z1)NWsYo1rdo*s%cV@~euuB{lH5^V?zuDRRIJ~i5+Y|sKd z$NKDU4w=*qJ*S}YHhmVS*Y1Uq_fdY8M-M0a^QMvO4E+}FPQsL}4!EJO*N7~ModrQ3 ze8xX{fxjZCgUdS0uwh_^wL+wkl$tj=Bid5U^Z?Oa0t8~TE3B4>d>Y%=Yg71f> zEyNf?9#q-iWs8~2s<6J!dxpnBp=`fZoIfXXShKgHUc55%0@?xlETP-}q%;e59;JeS z%u1jbzx5dOq*=eGo;qyzIXppiw;0NE+YeTKFXSfW_>eT$Hgf1?+c#bg7t^_~ufUQ~ z)t9_v4ZhCliR!0E`cdscX0MLPVjHaEB{x@7zt3g9mYNGwp%oC=*JUCs@M8eX(69*} z~|Fw7$DY?G{zErITIbciJERc4e#jEeXUX~ZuMbg zV^f@6-k##rW=qJC`+6^B9`jS}YYJqaVY>PGG>le>%PbV=^x1xB8Rr?KUFaP3xwWDC zv{bRdH``^q(eZb`!@93NK98B8id_N8g5QYWK~cZPxXv*NiF=IXj9Mfsq_NX(dHL1S z%6>A8x%5Ibv~=&0qjak;M>>#d7@4yUI{CV~A9_|s_-<-1t=+Y7eoZ4*ay^ne@F8h= zoyh||w z^!Craq8k|O4<~jH*iHFBoHa&6PxN=BIfET>14&bDp*uO+5`x@oEN@KZTQ4blvlvD+ zmFv*nC5Zs>K}Uz{Xl8vW*oFIs@9oYEI!NxDVZPTA{50ycZBQ0$_?rPo`1Jm2gK37SO=$?1*vGe|m58`E%Kgg)i7 z5B$h+!)wL0S2#9vHOVULv$?^fw?0e3y4?J6*tGpC@^fdn{PIXi$>=1q0~~W<^*K1m zi;7B-gqb8fNTg*(sLUQh?e}CyIM`-mXLXvTzA_w{PjZbiy-4)l4trZphF4#=8me@C z(B3Dmb)XV%s#+vg|A4Ye=~Xeq2Hk>4e8`dYIR&m0`lXQUDX-V#CTSyb*c4jhrYj!D z7E!tGlc_l}`k&9t0}6ATQ6q4>tga7T|7Y!B}@(+{WLE0LzO&Hs0bRGSJSv zlZpF-in80yc1)l!d>sgsR(Su?sdp7J>4A&edLnWApR&X2F=;MP9Pf@inFHXKk@Qk0 z%o|al8Sb_wmhh%9H*F(I!lNVmzFez|UI67t!TfbYuTNXkHzq6Ygk{NBos*u?7x!^V z)>AQKDd0*Mm8*fGAZVonT=R+U^E^CwCZO8gE24tB7c@NTtO zFmsdxsn1VLUo2E}Nga~8c98p(A@&$U9{+_rHITbvJ6Azky2l*=U zqtdzz1d>45jB$y4{P4^Fz=En^E}d*+&-p~+fO={>{~^5$*?)QsE*wGuD8K`=G_6JDt&;n!B57!QIe;l;2l_R z%6?@+u6`5H@@r54Uk931S8`w`Fy@i{P)Bj4hKiBP227{s}1IgP-ld;JFTshF| zj|cg~@gPRiiF?B&lyXw{J!~(R0!_(!MZQY(fTDk^>BmxzBabElg>-{ht%LVP%^^r9 zpgnwC<*ki8 z4FMaGbc#EL;DjT8|B&)8oO^pakOj7!GX03}kWRI6Fi<7E{s1WJ{D!QNB;j|5`mQFu zUPm{2?nKyOxfd%>Pa|VA}0CUB^@#vEGe})(>Gm)R} zrScQY5EInL$7t~GxraY2DXw=6vSI}w&kabRUn%SNEZclWhQVMskIAlV(*2_;|5X5j z-u=bu{(c#MdWs6cf zW>v*heZAm_A2pDzVj$)#g0g94f>z>d3R7Zm#q|G*Tis_0kNWaYySD=Y;hnn4^_b`S(66>xbb5_m$s3YTuAvHB*G4H5+|ATd^Wd`LoqLuTQ9UO<0c= zx!KW;eb;wg4-S{xdsasC=B?gA^mpa?-d>Zc)5$e*4i_8JcihtUSV=!{9d4lUN|iO9 zF_wE!g3VQl^~ge7npm%rubNuxEHF313hQw4q(ejWhFzq7@A!x)9X4YCO88 z^-yOhxBB2c(;WBfSI$(@*@ZR7``>}O#=zR2>8<@SMw*iy(y=)UKRE^J?{RB!ivd4D zAziHynlzv|b5|fC6ue*x7&Mq6WS>ai?sumq-L4kzN&u_xM2&TaV9E7_91J0yk|DSn zIPR4oLxXuJd>ROGf&-o{XV=x=2HNYACH^+W0(Q<;y_1g}hb(5<^65NnOb0ySl;;{} zqKJ-@JqabBO(Lb1io_Oq5XJ=cN{`Xatv*h#mr9^mVYcbcGA3PvI~j5JB4e(7s96Y0 z^U;OV*-O-%ix=7EPMo)$3!woSyG5MmxI2GUR730Yu^YN#k4PEXJmRN8$ue@H8^>yS3_Z9OYB@PHrBO&c@YY8HwGi13Y4hVKZlDmLkyzjsu+YEkg%KR6`>Qhd+yCZd&C3{lAP0UJ z%lKaimJh1Jqy9;2cE1w-<6AIcOe~VTA0??VvYiv`r$ArpA4B9^{!yWJ=^MtNd*+n$ z{!Qo}oX$(qumQc7<@Jf=&1yx(%)O;s%*>vs%G|!$;ps0eW`ku;c>rIJIRc(6WSlcH z!R-eaVa&M)fk%Ab|D|&MYX$oseE**{Dm2{osp>bqzUa+nTg;-ufM|MtyZhjrysSaNJAElI$+QryL4W{qts_8LN6Ma>+)k z1K!s=MSEsyuUosuKQV|=<<0G!bvUzGRETIl(yz=sal0TzCH1HYcf|HtiiwO3x*Bl< z>O6=L7V@h+J(^mh1;Ac#7c%pPpW%nK!<+R;Xq`xIyOTE$*Yr2jPp9@%(AzNzRICJP z3dRsT6tU**?AG6oWiEc_#B!y0w!-e$`FFT_6G?Nnl(HI8YFZuMZP40h8{ zoAY)o+yW03AHJEZPvXy+q3mRlQjr4DHZFju2|tbcfj_R%APNpYiCVN4#Fxs|MNv8k zL^A8?atD5xnQ?B+%?bUKSv`svI-FGZ9PhTOIR|*>@6Ie64g4iLqDpdY*`GSxPrV9w zljfv_8NPkINA}c;I?%wcWq}}NY^>N`-$j2`+iv=+4r9;DJW__CK>2|Un zU5+3KeZ@5EV7j`7yt;A>U9~YR&6^pa`>5$#x1(#6JW3XHQ@7Anqhw61+HF&r^Cse% zlg37M6Y+VSKyog&AVh4d!Z%~}+SS32wcE7^0RA+dyX=!zUH}iV9Nl!>P6E?XZijg+5!I0A*u_&kgkNDhKV2BeCq7p+aD&uRPQV4WanG79#B-c$K$yCXz= zhQF`xhf?*+y~8Cl?Ts|ckGKf-ES!NNqj)h&Di_TsCN*{SFiOcWXj}HrZP9xhwNEcYAL88dp1feA?$xdZ)|KQ;0e>i;yMi*5nZ5d7eyq%9vT3Wi#=CweKQBiz(d<2qquc00cT6J1?TF0?1;RFrk z<7Vt_o-NeWTaG!Hk#B9it+>~9+dDkI&A0f8=n5#03TCH=2T_*88QODA)C)!5@RmRE zD->3^)MjDuev^dgX{rBKPLOHt&R7`2$UxPB=Sz0il$CKJhjN_3joQ0ChHtps`CgDI zKod^M?%s@BJT4CZH1hcTG$~K}^PravH#~})xOuGEtmzc#RUc}_G*liK*m#N*Q8Iwh)5{m6&@#t)&3Pg&2XXf1c>R=zv}Fq*lQV zSJ&;PrS$y8FB|gy*0q}Un-12Iol4Z2Pe2Z@$gC3f587e=c$@UPGb`6WB|`Pf9>ibb zogaGRl(&w9>-v*DZd@;OldJFbQF1}Fzo`?kN6Bam zz^*p0d!D~uQFD5uGA75fdx`VCBjWoxIp?J176(or1PpD_*Ax3Z$F4376X1gZi{=7b zratTgapGUP#{R_j|D@k_JFrH(pUsT75S$^1Jqot;k6*|60~@>=s64=wgPdQ_hbTEs zgSFBQ;D=t|`Q`{; zMmU|$jDPk|qduPH#P0B)%5v^~1)t97Q=b$n;sU^p5aR@kZd|uJ9wa{uL6Sz6OhNj~ zkVj3h2fq&0`t_MvSiKCu?Qza<{_C25@!G0*s@l(9?>{ZyEYlhOyjq*3+N5Ea20(*nzC-p&>#}ecfP(r8mA6^0 zlEXpGYp`zi#4a3tA3$S2hyxIMDgdS5vhO-j<3E|Yby6tY9tU(;dvan4VEh2!z6CxZ zGSklk-qg27Hfrl33;XqMDi}Uz06k>ct=ERiS3Z!>S1(?K{CczbgZ@%GFnt-4IoTJD zYdY6fzWZ{I92v+e>yPu2lS7}-)`hf<;rN^o`OU6~*3axh&l)_#B%`uux4#Fh$QHTw zPaPK6Ke6Pgjyq6^O&)B%oyw;jo4QO~FdcCMPM9%;4f6dbTTV|ckYb+4-o*K zm5Ic?7>`>6-eXwv^1#S6Qt%jHkW{l2gm%v#m$QiE;v2gmUmcvCn zmR2$eFFSi}0fMQqghlY{rsDLK6*1T1IZ{#)(&^~?vw-aBjxYTpV4No;rU6fC?5>=8 zQvf_+>&Ngt2LwxCeUI)p*VFlW|B$~wx|siP_s2rGf_G8@K>b!etmhZW0Pmlz!L+)K zXl*Y1VCfQMRwe}ZQs4aj52b*t(7PW)S3hS>cKncDpy~71=>oF-Z&RQj)>5gA`mv0_ zrkGb-f0-+=$p1!w;HS(;C$1kdC&<^L&a{^xp6xT8vEA=9e2+i zwXAo;BBIbiD(UX9kfrnAK*+0kIkcQvm}c-)tG~u5u(%rY9!9zw1NZyzF1S9u^^BmHbvU#XFc~bf^4^R{GVC z1!;$H3{~U{`xV$kWt*8pDl!medHkVw^z}Tj;}u0V5Y-4Nn~p0-QOuN`9JO{+)7l>S z_!q^8QTgmUC3rS4@CFy9|5n=SBJX{5NlD`tQFE9a6 zGP$V#X<-2F2lRqn#b}|xAvjrE9P9A(lw0p%r>qdUh2(qXIfGqtvM?W4pj5n<&hB?< z*iRjGyS+`+uC&o1OhY`ch3TG!w24H3*$WQpS+j7%hYz(ABs+F?lca-X?+X~@c&X{X zt~~OqbptkDK}U`Ve`egz=l|aoHga56W9C%zZIXV-c7ZNN(fL{1(Dp{&v>H2-FYzeB zV{FEGJ#753iO8Dw+dm5l#{+S=lpR5iA7E$Y=f^0&=`JuOE(im>n>f)Aj%Q0xGip@pl1w>AA@YKuO@-iMegna@`*MMrft z2a<1Hsd3m$%dkp_XMApI+?g7yz!l9(9Q2xvLxD5c#mKU+KF`l+{OY+{p`y4fp_FKZ zg3}pMu{W)8Q-cxx37NAc0XuB^?3w8Fhi{wZX@|4w>W3X*!&*s84rEH|Z(r?NBcNP& zpX!8dAHP@jrs(M8A@&ubUvOTZzEM2ncjXiMt--j%R=Kf#ZN2hRy9#vaL@1b8b)lW8 zz~)Yn^X|m!ukq|FD*#s0lK&~Bd0ZPEUVhi@6+F#e(BV4Y9&e0N_*2!xOPK{00xuet zxV|*@x&Uubg&Y%X>L$;L(0D;^olo^N9d?74S$CegFFf~t-{!H+E!EK{2W*KR%b921 zs=JV_;Z;L*Sk8t-tP^Y98@zFg?M*k?14W{sy>s4Err>azOtf$Qojp}i-h`WFB_vcA zX(W3*Ufl560qqlJ=2Rtb+_X~`T@@0XWmt)erQN++dr_Gndd97zp<;~OX829y1Efev~q@1m`bVl*v z&Qm>>Z}PC%I}BRfR9OR(+_r$CsaQ4-rJjGKsQUFD6Rpp zz9r_BRHDh6#y9i4*lCe?K&3dVY%#6{>$q$ zN1GvMfS1Xcw9Nu<2qWu3a*7Knb0XfV@51;rOS-MTkhsWx>7gLlaB*EvINqD%DEP<+9%2KOg6#KFa;4N~V#MH1rW0~OBfZ=1P( zTpO2Xc&m%Lze?F4Ke#2bsk5-OVnSc36?3ac|616&T7G@o$^PvrktB?YLxZ{N@DAkV zHjDpMA<$qp@x9sAiND8Hk;~0F<#}^Zhq$=6KD5Z4n!-k6nqj9ES9};rjrO;Sr{W#! zDe%?F>wJEsLSm5h_|h@jMYU^gE3(Kdp=FwXK` z*;?k>k!o7XkCS|g2Ngm(V||skPbM*gtMr;JEQPN_vwHLFVviZ(XPBQ(^p??rW)=8i zZl2xaq_LkCjcmpVqS$kwvM*<`4uu69kkVNj%WyNVGEg;1fh>Bx7n87>25B=W+5F;>c_U|$vwFk z=$CHLx!#uqSIk>avokf8mn&EH0GnpR9H4vs^CiALP_yHYi<5HZoi2D~HQp4C zo1-Z7Fh9?mMLf6EWp85<&cgt^Sx3sFuS0r++yfFb8ABL=fo$(gYL` z1nIrTMi)`(U8NHN>79s35$Ongw9uqCfj~e?q$5R;76c&>gwRQ-p~buPjB`G9ygSbK z?z`uWao;2wjJH@ieXcQfX1Jf;m z9;-hRlekHJrduxxe&Ww7dFXqM^W3hf=dexVaFZCCyli}1UOCqU$iz@A<}&pb?a|CO zeri{QGi~zLHK^TZE1y)BoLkX3_4AhuWh=HK zy+;lSh607_d2Y22`)ky(y2ei2ULj&y>q-3X^=Hpx^D;$}IEG7o*+@RJM z=wJ^D)W4L8s;Y56_tP7F;J0y3J1SbMofSw(3U`7jlnRX-+!U!U>0jn;h$Uv>HJ~mN zYd=F)shAc6I%}_$Gw|jFx{w34fofQ{WNw(~Pu1zbE{JcKmykI3P!PQ*GMHxAm~IEN zkNA+Z4HUfMw($)1-9y0uv9&LOrGry%)twawCF@Wrn>+J`jGsE5%Z^K3yZMaR_L|Qw zU*fLh%2o4chET!~WQ$@1w7P)UVcikfMorQXZkX7e1i%R)`ajLxdSkT;RN}k|hYP@X zn19ABk=_HaA9y=r=X@*y?}9CMi=2L)a|Nb4#t0Dl&bov{miT}e32IL5nD=`ER(1wt zza0|Fj@tm)Dfdt2Rzc>3u$w2R0l>9|?f5(9_2<6wpi1qZ2WzB@$}I6(0Sdq>BKwVK zGYk+N2mP`UCidx```SQ>-~|Fb3JA;(-31-ZA=+Yp+emKyi&DmsgkvPYfByL>zibra zvrqG{KC!apw7vKuvlHmYLpdAnOQJVGcVg@@uU7c(f^+hKH-#R+jsf=HSHT-{7o#^Z$BsIf}h>&dxGybTWLUAc&_44>zdJspLa`M&Du{aE$* z-s`qMuJYv8*Z%135SYbRaTv;Q-vo-wLT8@W!f}RgcxXG0nj6jVYs?9MXtL%gxxpSh zG^S+QN?;#d-|-QFbtWsF^1+N44tO3Zbcw!r7(GGs^fSA`0)r6Idz{+yCK)u_wr|O2 zZJt3QczSPB8e@F~eL#bOjDC`vPVa1tPI0N9PPn9#_{R8R*I;jQpN_fwnQikr)8f-t z&dM#Q@n!jq=7tuakh|XdAxOyTVf9gze=Nn4#Ik%$s!-UfxyeF>i`909Z*{_(I&YgG zG?twGfzPWpC@0b`&B^qxX+b^gh`sU6Qw~m1jknLPcP)@1;dcdXBSDoTTSK5q z=NY`aS{m9^Nhx*1sk5|ptRK#ET_VD8!1gmI-&Zq{T9sV<`L;>(4!0?XVXd$4$M=?f zeWgadK8d#TXb4t!0(f5v6Lv;m^`M@9Z~GmPOcl>+P42NQrKtu`3Q$>LD2NC0Zv%W z=${eAMn!RGXR@FsW>| zX6>8`ClE9M@-_gF|I#Erec=@5(Ec;2`2CsFIP}#2W@t z0@E7TcjK54Tua)|`P_;EBch&@74tdQ-#?q}x)BzALy=MmxiEjbgr+}~&y6E>GN`n-R zSfn&0N1Nf`iO0q^b;f$V5gnnAQ+poVAetvTQ+AK+pIxT@CJi3Z=C`{&u@uDjsaBzA zsIk?iNJTO-`os1O%=T2@ss#uU-9-F%de)$)M2e=~emi z?$2va9ywI-P7GEtSZ9`;RrI4An$%ol{0yuPzl`wjBW}>|_c4)oA^(rja+R^2GybMt zudj`$67i1F^k458WcMz4=MpLDbgLu9Ft z;a3V%MV4BxL38GK3BogAsX~1K;Y)t&E-z(MTmAN|DC5o~7TP1&uC2iu_2D6FoqJdL z64_G~6PGPMS*Xo#9*7t~c9*{q!M>Ij;_~DX?I}6U-^&R2VE!v^%K(H!Qrlv6FLU@S ze8kx%X2n$cN+!cOnnCNG4GH-?<_toLu5V&fF2Jhy_P=u`bTzvlN?bX!Tn^W>8qdqMIR~g z$OKtjy}Zvm$MYryXW2PM=xTjz<8h;( zJ|qGF0AV0v$95PA<(L^6EXXc?L8^00^3_`N{uc66D1*6Xi< zf;I8<>b>fbE7SU6H;%7fisaX|7UKbD%rOuj>cSc-1F0(?MIU}~^tV|X9#?E^IYy3H zWO09hAz}#}&A2!6r|kVoUT%_>+|l=T7J{AUa69Ag+5H4(PS&Lp>1WyA_eu~vExxw} z9<|fqqlnC&U5E{UhTztr(@y0bgs0ChT?xY9Xxz?+GTYs&QDJ|^{%nOBByUzzvtPR- zH~(UQiQ^3iuN-`%FW$b<D zCu8QMXpvk3?#8_#Cz#XCVP9?s?)ct!k5uoXl{euC#%24+_!lbr`pgt(h!}c=%4Z)x zdd~l07$njt^J0J{{YYb(tsrbv)zPyHd&!{DTGPyGYq5o$|;I5&zkJWzO!IgAB{o%9nmF z9qKM=-FKU65_PUFo_*Wfx^G3Pa9qfBWGG>U1LQIGEhJ;xS92Wu7H7_>{86$oV`_gz z@vHk(Wt~r@aTtG&c3ek%h5L(pXCM^zb@1~CZ8IVga;Ue?$4d*DDb0AgYr?im!;u{o z)+d;r=7mY*hz_C$tt=jJe?*x>+lF)_)!$cWtEMn9R7IbQy=t>(mZmRi20PdxBw~zz z1d5)oZi)OjdDX&*Rn+EW#+$UY-D4KRQQz8as3`g|$Mz);(O0s2kW7KgZywR<>#Lp$ zenzUGmD;%EvK!z%ZU=hOoNl6)VmGso9NGqjLReugZ1^gVb53mcU};9v^MAW-Yk@N$ z3&G@*0%e}%TBv3E2)k6 zKOD?&T1=bKN2?EP10)4Ojyip{3wIL_JM|Tsg*Z%wry4_DA?!^uWj?WOdwe%d!LJ6m z^+I&D*b1*weIt6Uv1J~92g3!G5x~T#IT*KGfsH$t=gMig|TowBk@iRBxXEPSQ-) zkTb4lkPN%J&T$^c8Qf%CRGQ~=crHT9R*7j5eaq7+W1kHwwj@{uAW0Uhb$g3w4+gy-0|TpXQGzPh%n zby0vfc~X7aOmqtNcK)=roz(qdO^YmV%Vtos*IQ_Dcj4;D1|($D!=S1OHUhYt04#55 zIeiNZcA0y1A5YYdhyu?!5yCpM!Q5=G#)gQOEqWX(+KP&@s~ik*kSMtr|~Lg)oyKOfXG>vsn>PF6>Dyj36>3Vm*S1Tv5=Flyh3& zT!;?gZ+P?+W2^c!Sk*O7jnQkc-QsEs@-nWxd<-7Co2hk2OUY8Z0nQp_WmOd&Kdk=V zld>Ho9;a#;;}BH2h1$HncM#MVh&-BTVZcFa$^sO|q&^f3?JSqof*U0~{WdR_H;I1y z^wNx}k2agWF-~mW&5&+BmQ%YDe*t|V?8~)k3P~0WdTCNR4pa z&upASEuMhr-y#G~wV3$^in>Fabeqo42|}pw5TlVw5vDzq-l&U6fe1}~crV;nzq9$g;O(_^!LW>%P^68PK72*8GXlb55o&j+P8h0zkQeG4tByTq`C? z$ZNekmz69?6L*cgzAE|4d2vecBdzTG1Mi6 z!s~nma1(;HCE2m>g_xbv(l;YKRSCoQVp&r9b>ri1J+#Z|>1H?NL=VOcEpza+3}<6I zQqI{ZwAm!=_g>SByNkLuYt6B{GHH?ZsKDeTUAwBT<{5iLIob%RTz`*LceF`ju2~gV zQAUCJfQt^4D1z_cMN#W-T0A18}yRED|Ctga$#gcR!-57 z=GBf1&1$@HpF{cwx;a}^m_e*87gal!krcBoM`7NROgNXIuHU1U_<+1$Ni!mbrcP)4 zolbv;R;ENr(!gzR7wL_IejbDNx z4>Idjw1ss;?JAIv(q_jf`r0bAqe$B_b*pe-e`Z>9PgxAsfCqvRXAu({OjAcnfV`l@ z6-EsK1&(lN=4#LUNuiYle`4#Ms*QtG&+A4s_Y`vy*VFb#!+7Ad*VL;7*62dnZq74z z-?6HF+&!ChM(wFEH#X))qM$Rqa60+JnTDwhq~iSjsbmA`eo@~}eVvs*lFo_v;qGp> zz~MQTXtJpC03qy_C6k7YQok0va~w_lA3fLab!Q@cthZzRwl=8n)lsH7q?dRVr*3 z1P%U<=>GAa`4NBr{a@}+{O(`;-v2EMRe7^g=_DI~)))&Q$UexD)O~y$+w1!({^4P6 zmUN)6)>zC*VAct>{N6iUY{a<9>wQ1{jZ8;p)?Qn;JS4wrV2iE^1p8Le7f@rat^5km z67-)ML}jYwEYD#WHLeWm3baJ zgkl^4U=!bc=%0ITT5tW;y_FtB0$fxh4n-i`WrEy-e1{c&?!{<$(Kt|JO72?#RLOHB z-B~+=CIp?op%=e&KM1$3U;47EDfpdk`Os&Z5DK;gfW_~Q@XtLt-U+2Q3eaK|fU6Vsl zidPQb#2*y2Yt?P%$0(;4F?#G^B=zr>!OOo@G z`^G_3$TCHpxpZxB?QP`&pU@!NUWWlQYc}P5XNxfFOuLD!^v}a)q+Rffs9o zgV~S~ccE=^w>$D$z@s^~RU^;zb6&Mz@WPdu4JN0~vleKC9kqb%TGpaYgocOy1%CzB3P4O-|&j<9K=3y@%QOJ_hT5*O6(zMN-c{>7A zG8i;yNHnfTre+zutG^faHEHTuX&e7VqUBX%Y2{Nm+w{VU=r_meO?98p_ZdV#6sYj_ zi+N1cB*;?}3&u}nziG&wNpTWs28!~e>LhFMtlNGgVuQrLpSBeV1}e*5h95kc!&#O8 zVK!&DE{bjWOsK6v+qjSppa&_Q2crY-N9|ls0|m8aTRt4S&QEC(B1dT?V7UfY9nDGkR zhu*cYr)sn;b9C~a7@ox7`vIC*3=sOIY#dVlya%e4wEMW#G|*knY7o5#^joU{@|BqbaA%un{EKo} zp|#Y7#g^wkZ1diJh`=&VB0{}T49XXm3DTpI{^^Z%a6*5UL`iq!`qPB6N6xCm{Dm3w zP`Pq#t9FPpZt)fRhA)uUXVvb?`T4l)pvAH1Uk`6g4QjYA2WevDLvq#MHn#dhxVNaYZA{b(?O zUQmZLK(V?SxogUHVsI$t?dtk;M3XX3LB4K#d!1+9py#wmzS{uPYp4K@bfXsCEYmLk z!f&8s$Y{o%cIFQ8qdL6=ec>Z4HSPQe>=Ox>HT6G-0ugr)KnN!%LU6nB)aB?_hj?B=x>6iCI z%@U~1-Q#YoPzw%K1jsBNtJmV}rn~?@F`;{H#&G7#-2UbubC+0bSLp;^p1IbAVcKj) zatNP&`2$7w+qP1g*Vmt9ekPN9-`z}K$am%)Ku%BsowB-rwQv%J1>$+n-d%QpQ16s> zj@D`wj7m;9uqyO*rOAT4s3%@yUu}DEgbX)2E&||yyAif4@g$|lC-KN)c!qzj>el18 zY(690q#^VeHr2bzn|Hwl70DysYM^^SrCH+cW56Dcs|W?AMZiS8sk!U8mGu%(fMOg% ztODlyl7>aOg@NGTf`B)G_>EZoUo}9!|KI;0_vW81D1ZO^|1=w$vGw?N10HTyWMPgs z^SQRPhxLt+67$?ktQ9}lB3NY4V+XDbe{qn>Rp=G`pnM*mI4|>R$BDBe_CoOEPqkz; z;-pQcIplGr>nwr@iir>01>jG|H_(>U_Ts8(m$)b?1ol>k3?)Iukl;<0(Ghp>XoN_Ef3a%_UVjm}H z#vM2w#dHw7rs}S1=TDPA5P7vmgIyF>{jQtc(Re!MRPbnmA4T6#lkQxm^ZL4n3*EAO z6fUaC!247Gijukk&;5GVQA1Ksw2}?TLBW!ud{Hu0Q5sq9w7@5Ews&JX8s%Zd(p~GR z%!LyPmt^7AcJE-d_+vP#3l6VpGxI0omh{j;9Mm3?e5yThf{c#l=E3TpuZ%0CJLILY z=t;V%&Ly=j-C(CPk_l4A@|KS#BQ2z`YZA9Rtz)zeNUgbxxaw}?l|Nf5Dq)ged=(f_ zXJFDC+Bsrc-rGvms~E=A_4!mtW;i$1&|-d;?nutq!{NnIA*+^msy;#%HuSxv`;j?v z4;A8Mv(M@MFFdl}&6$R8L=hGjEEycIrs?Cg{=VL&5&I!s0z0Q};J~EdIRaxvA&^IqggQBJA;_s6 z3!3W?!UYjWTPPr_pyJlsK<#}Q`!W%{!8^e9H-zjjAik?7mV1H@*#ULF%{~aOSGj?@ zbyw!g^gll`KX72OQIxw^Bv4U36kH7O6c)UJLTUi+^j*S{0;vml^SzsdWBB(>h1IyV z|36Q%|2Iz*QwIoDRDfVY8zPE2O2bpV?A%k(r#HChF)ZErevGc;MTLTS6|d#Ea)FuZ zvHjnttH1L7lY9DqUaDm7hih+4xCVgRrVjuj%2hx|%Y@O=pzg>y#oZ3kcXV5X>DbPB zfm?QSJU7>w>hdzIAYInwvn4?rh&DiW*ZBz1et_j+2coeL5+C+NG2<&WYsRIVw2bP* z3`V((JDb$68^xPl%qBT_=*74UqBs@#Y9NmBW=8CdkZ7p-w8cP>A)l}U6q5HYR=eWT0Pfdb~S2^ zQGLMRjITNmAL(5i;jYz3WG;KABvVENwLG7*FU@HYVQil^ZlmY;9#>0-jLM zbzS|DMciiWMu3)8em|UP($68@xMN#n+E(FP<1tkY-w39 z-~UFGb`*)cW4hP!_OYBYl~wGKuTI!BX~ zXHEX@bM;a$Cl|LmcP2I;ZBK1#Fnh6`UGXDaC#G}YT|%M+2`WJscl&{dPTW8 zR8$MYh?L0NWqHkOX};ppeFjiz5qge1J_@3Zz!imc>cLJ98Z08zgY(5?a!T=}*`(5V zj{loCv^Q8E_I9}w>SYRfYZ3<;M*|*UD>7#}KM!`&@ffl$%oN;ym$W{0o@ZNqrND0L zIio~9|8k6bf{qfpN7C|afDB;@JJ_`zw5?YQ*LiDt(M_Spd102kvw@5YDk@Li&`Iaz zJ@WT@&G-oWz02n%uI*YNk|b7xb^{y`vN=lsZzV0 z;vkM}oaH(xI`)E`2zYL3Q^6Ps%dUUey~M zFARiJW>Mr0X$dRxE}@cI3Y|RVoh_LRZm0a>db7u;8Hf#yhj*qey4U>bGQp51Mq*(r zq)9R)ab9n^xyC9oDE_*L%r6wl|BgHG7f0B3D7ehhdVaqgSm0S38z4;}d2KcI+Jr5Q zbG?+|u0&DR1V*wwp~~Z(^li>L(~prw2NkYeWyMEz*PJakX+B2xoy;AKLDozy50+&X zL2a@BXyvU`5nSFwj8YzVEfBEBOJ5K(oSBA%PN3)wG%?8PnE$8dVHqSHOH-y*Wd%5c zK0zKoc3ldT9i99}G^l|PBQQYzYz7*D2JmF#yc1PFPFF@`KOCbER5NmdVBVnq0IU_z zpH1ab&c$PrRr)ofABSg4Icnbq$Ql!Mi0xsQen=?ipDq2^?I7aamtOzux?)SZ4-iC$ z9gR#sj;#9q;#Ls<7$UVlTVqzosAqwX&0qaEY~GJc^Rzr-LK6J64`Q)-f3|)Mm2#DE z=a1q1^y9iJPhJ6diqe(iZv6e9n!85dh-79t|2?e#9@c+9t^b|`{-2&(^%Sq)sJlZO u1X%|B&p#J{C79N&%g?v1Kr@_khId~);uT!Gv#ROpT7>}o95RP*pZ^2uI<%$$ literal 0 HcmV?d00001 diff --git a/doc/sai-ptf/img/Device_topology.jpg b/doc/sai-ptf/img/Device_topology.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77a1d7761d6979788a7243ab961260cdae1a92b0 GIT binary patch literal 17549 zcmeHu1zc2JyYJA5q;!Lnv~)8l0wU6#qaZCHCC#Wvmwf4_Ur@LMx`X79cBv(|dz|NNf?dICKUBE6@qstm%wzyNsze<1WU zND+jMiG_uQi4DAA123E_xH!P;Dn35$6{4#|L_}8!35iK5$cRbENeBtA(Oe^^q@t## zCMKh$r=_B!prWSw(Fw+nJ8^IbaB&H!NC-)&{?jjX6Nn5Sw2rBcg>fB(Nrr(%hJkJa zF@r!DIDoW21pdnl0}~4y2Nw_j3c*$2f=W^lCdO~le~9o=E337@yY2K{QTm_xG+Fi z|2C|@jqG>hA_K;SiH(hgjrU_*7?@r_!y?1RVHLu?c1s)Yp)2`y;pg}ix8pvQHeX>A z(b=c8bQ>g~Vi#TDIQTKN-$wS&4eZ5#X=HyJ*x$!B1tP@402U963-Sc;U(j7&BN$8YV5fIIzLZ;3oQ?OY-_$N=N96xbj{@S=~yW;>A;YNdOOrTF)5cmmbP(;R0 zQ(%@JTcCwfI%7Gl1iyQY2K_vhKgnFIt@7L4yz(+OdAJa4(E-U`(A9Gr{`4Wcx> zk+C@fjtlrISERXW4gP7QdeEOFD0r>?Z_+XSH%_%%gnW_WIraCTsS%Wo?$1)I{JhpR zO3VhI5RtpL{u2}TE@|x5w9mB`YlF)>R-Cr7RG=tw6HiSOG)R{O>EDh9eTt~jy(bi` zdZU0Jto1(Sh0__qjr3Z=mWUf4G5^|fEp8{#wJ32XJgDZQd}O`$WbFkHQrG32L=fr6 zjKnvfd6`9#JhVQPVqaB<_p`*mY9}}HpHRF1vvc7?6@ijJhz%2aI)qR;RVw?^9KGiK z4cCT%f+zJk31qAixcPiy}im->LnR z1=P=>NarG;$C8SGrWf=TPwrSY^Sm!U+d1K=)Ykhq%?I~OF zw|-Mv?bJ%&ya_butIj2I8BiM>v#e0n+dXxN3B550$2r9gbXm*`4KhndgC;jubSu%I zSEF-Cw@5U|w&3-;Kgk#*g&>W(EAW;Qg+a%|TP%dhYbaKDRcA}`-7jBs#oF468fxFu zlH?t0cW5@aKDD4c2#uj|VB#LN9xlv0PcI9{TZo$BA^uI0oy{>&uOJ4vR?(c){2*gtd_pXT4i#NId2&>sfD-wnhq0G^jcG z`w^dyZCMJf>+xkV6coV2qpTC8{nW|s(kGEBLA@X&y|Qk9JZ8r~GR(hV#De00$FBfN ziUzUk69KpD>>Cs@#T9g|ZMci`?}FFfqJmOYoHOR=HS4Mmg6pdmH1=^aD#25h+C8Nkpv7(Ww z|H*>ayU%O4)}G_j@y$Gy33uLFqA6|PFY?jyGj-ejrAERbI{0iXF~^l({kcYVnfjM* zHxdeXbWTZlPQJI=XJfw2TT)WrbtLVRikm7x@V!TWR4hYtFguon=Rm3)WLzo>{)+II!Uvk6-eKR|^Pg*`h|ytt@=6d#9lYes%-e;y6nOLjfipjM6?u?F-AY8p33d|3~+*w=Nf(n9j77PS4VwcNB&HW-U{JyLj zaMEcFc>n}|GT<~52XI>a2n7dlMp!-?WG)%L0`42_{c4Gy)5V8GHWDX$iud$c7?S z4N=jGhXy~HBP|vS7yZJ&S1%@>K;F;nUhz_$bLcALjL}-c$h=L1V{0SFxZsI*kuyTj z(~@^|lK%MB zXsZ3rv-bLwz&Z_HE0I3`E6%d62O?SrV(@Dd8)f+08P0mIG+N;pUoJlv4=<(&!%4Jw z+BMi{@k--vA$e1gDVQV}-zhIUwE}?Ei9>_#8vv-;<($+74cbXVMc+H{j;oBf0&k6K zB3VDYgI=x(9;h6t2rZGm(%qMo7sD57u=Hm&_}~2IpFWh+|odzSy$Cqp;n+8 zZ}*7SP_el%mZ;NOuyu=lgo?BBlFp~mS$v66!`G00{w$T5L6nKyFTA3hG;-9bJss zb}ED}1ZKfX!%D{c?tOz>m?7i_5&bZ$`vF3o8xcs{D&k<@*PD7T+=A*MHlr2iOcXr* zWUnoc{mxUgo3Y(hMW1w(sl^J7f^0kQr=D<77#u`d7ExN#y8sS~=Ou-<66nvG?ig&O z6;LT5=(=UGzMLcSKKSH_8WjR)0?Cr*U|@FaJOum=aCj5Fz#HhVjVA^A)d#u-1hw_s z#rooaVjiMFP+N;cH%SOj%- z_>F=IymJ%}DCm#tmgAawn&$YzPjm+sCC@$*3;xbg>1v`u@e6=zSOC68snZw=LW7nc z9k?I^05AEe&#+!I+dF=sGl_02noxi%THko(*7H)m7c{ZE<6m7vD}(tMy>(xYN`Fhx zHtX*e9_txpD%S5_F(6iTzm?@>?U&J5ax?g&x>b9hJAbb$u2Y{A>T}>_^~q_U9n{WW z2@Ohf1Ye$$ph47X3+m);j>z%=S3W8U!)|f41_oUIn%M5USk+4qnfI&uBK68lsmxam zWK##LrJeZgyZEO}>x?TmV*n>4DXI5*vwbef9 z0Fc4fZOZ|t3cI8OFEAe%A_-5SXX9v)6@&~`w90%;B#6KSBkE7V6*r&*0G59aMky@& z?_5O%o}_gF$)W7u4^MW)B`t>+B6b~(bM7|9E96U5NlE4bs|DVeLxUJga&s2Gui$Wn zy>Q9M-mQm)`IHUBJNW_2y0eEGIf8_`ZQ!+66}Wg6&}!@yu$V_5rqW}-*H4?$MJY%d zA_LK&?d*nY-%WQp$*5fWd!hG^U_YN~ybN(uNtj=`)u(ajydhZ>zs3Dj_I@YrNq)Y6 zk+G>EbdV`QiNbJ@;lIUOX*CHaK78dHq(oWzZUsgN1c;Z4i%fY7SC>|ry#(J`ZhKoH z*fzTrE{b_e;rUngiBNb5AXW^9Yx&>b_k=}M9D6TQO+}Z8kFx~Im@+JZ zJfT2?3Yc5ykN5&GgJx?T1@Yvv-Wz=OE`Y?`(7JwIom3z603_R(sJRgPBIS0xxs_4c zPIBMs{j!9*?g4g8--Pcdthut1bVqIaP*ZWk&Xiu zvElL@^+$VrvW(CG7f~3uvd=ZX8}xdGfs;}L?BnU)btok{T~vKGpsYl0u<{Z_0^nsJ zZqV%tjCUk42wTRsp)`!meh!wfDJk*J=dnp-YpFTxN5;NMQJ$Bv*Nlq`a^OLV5vTgW zI^1n)BbeRnq45%!K8S*eg1$yM=vTj%w3Cau3kp4qQB%0hBKMHuVo{)a6us2|nL+b9 z)N829<)dSYL9jDtHGk~vZH0#~NNBO$qdfL>wG~L`n#RT56spNhlW4BBD0rUHVh6si z{#M!d{xjd<^gGhrH`lPT{qk6%P?Y=>82tc%;CBVkpjQ}d4*@|qR~$2ntBXrrQ#U}N zLA@*?^&Xa~tqw(y^k=LQxN2QF66BJvZ;%Pmvvv4bi1hn($>H5&d;aD^Eyz`bFD##x z{qcRXK9}PSNWT7=#jTFf6DCexpp9ofHG|vpn_2J@jBTo(RBgk%~{z6EC;Amu( zlv@MvX!N+E5=bfFs+n;Y<^Uh=9UhLC&o)vw@3Mh|skPn}ETJUZydP->{Wh~GcnSDMG>E=9A_CO^%_C2=l{>*` z#0Am&z~XLnIqhYgzVF&G<&)bj=f$$;Pb(hEzK?$PLSv!B%{}JJysOTj0_{{U|7n;r zaPqvADza~LADeRPZdD9U*QkXvWalr~OsK%Ko=10L(aQPiz1G5$0lac$Cz5FPIvNB! zfF9H~e6l;-s3zgv^38&KPM00tv9|Dy&Lwu#i2wzEwDPY8+r8!K(CxzZc@$5)DD*zc zs>J=yD-npw69G>BXxjTM(XsE{lttoVq;?$~ZeW2ehL%U(urd|p+M|r6F6qhH7u-{4{+c-=BzS{;8f$LQmw2@9Ujg7fB zjgy;E&*-9P^O}E3LD^XZ#t87M`G$%DWZLtP*_pQCu0yrn^#0Ai!4$+EZSzS z&y9{78#oxO(UcMWv$=j|-q~q-7TK_oNu)LNQSXM3|H(3_~ zZ1cG`^gyiDVX!E}!9aXi#K2p95nRpC#nbWEWw zikAMJhO?fM)r6Qgr8=bK3g(YA@Oy2y66~ME&%o7k|@VX7a z3^czN+k_TSLf5qw(I8wf>dq=^Fcygez#|OEsxhD;}Q`(n85 zDUooVzOaKfsYvrYnHhi}FbeJI-b81sF8)j)<)PHTlAE!+PuxR1j#MzIZD<_kF$_vILB7R9;@}>YX#$gXt12~ED(e4|+r&zRSZsGLu6SWET z(FZKYDRN%~>1Zp^6agd|!8-}Si_2uMNiB{Fom)}%&H$hwHgvC8G)%N$A~>^%oWHWr zo@qr=l0Gyi%NIw5qoJVi{Wou(Sge;InNlyp$~%6++7I)2wm3bv|Db)#07s^jJ{YE0Lq) z)e3<8fShw#p&Ef4WYRI~z^Ul-esQ)^y+S1S=i4N^bjyLbJ?!8s&Ng8?@lsrmB>VBT zR7^m-Cy^5sGn`vm?}Z}9s1jSE;wi4V?zMYYM+eLUYYfp~&o`vWNP2JiQ8m2UC73ee{UK;2Yv}CcWd5EIGIAQ#Qb^3Yj zC{9XFZUPBIFXV!zAn{i|+Nc#id<@CUfKv|~17viS2=MmoZ!LT7kO^{e3cesMNc`FN zP08mDr9p15P-vUd{#8>LQnU8wTBxU9jwfvNbA0IODq9$#;$oj?lF9`y7;S@8x}o2fwZ0W$3Gfu0>VMb1hU7ztrC2!VLvqU`(y4JeW6$Y8nv87Gg!!zEpHt`YYQqtV1A4rM2E}~C0}`XF zNv+IB3kA@*w`dT2g?Ycm9~g{0T{ZF?7<`N&;5M(pF5JQT39Z<`g)xP4h~GN%GEqWi=VZ4+t%Uoq*J&9wpjhiF zu2YR3fE!y7MD;>twaI( zOT$oUJ5U9OoZwsDK2){mNsq~V%|dVp4s8^u-Jc6KRjS!9I+?1E>3^a}+JuQe6~H@{ z`;i1&a6t!{8G<7Nrn$#SfU4xm_u2a_^0SHx5;)NLn6`<~ny<`C2uQ~!(SXw`191L4 zqyLd{|F>lIf50qIGLDdbpRT7SV=uicUMn49!1R)-l7j+ct<0ZczwU0YpqL(^8>LMw z)`YbPP&f$|TZlbJgGOO{$54cG!?g&|5e%+tK?7I~(iFhNfFX3O|KVlL`!0aKApv~@ z&ckQCOyq*Ild@YMS`oBj<5N;9gUNwJX|{0iA0o!TAX=Ek2GyJA!z0b=seFmP3_d>L zjh5O2S3IvZe#kB&2YZA0>45@r;W4F*0vDsFPhw|ir74iy*E%=kz;C+{&6&=Yj){4@ ze7Y1bu%mpf+(p0lE=A~-b@)>!NoU+eFkR!^7;Jp$GdTE6qW;!W=5QdpJ&ML$D5v_1 zP^Vw+mD8fvk@)$D~`bc<8B8ZH{SMjgKh@nA*@JQ|Y@e?^ggE7I(#vrvY4dKTAEe)VvDNQ_3o72_rmb2S9F)H&WuY_LrX}>q%pI=SrqbK-;jEFB^D`LAjPNC@N!s&c2AVcWgv8`D8gwsq zxddK84mYm`;EDCc^nT48EZko*l>ZzRpQS)QACrCu2Yd>4I9%$!QNOZLHc-x_Q0#MBuVZN$*z zCM#alZYRyo9kCS{^J5>OBaAosjU2AgsMB^G#L_d+}`W6mKYC=gs?Ds1QL!{1*TVc|cp{;hq56 zrbeln0m;_JMGP-0KyB9+JbrWT=n(8H6Tur%1+Uyc^?MltCKK48;n}PBpsbm91B7s_ zEOgK=xHmh*?^{4OT%?h8&YqT0^DE5I`vrpZ{6==>DE{w*j-O%9KXd#qa7e$4cz?*M zL4>_`7xqwG-XXJoe&QXOY%1b$yC5pwdc^bxkE$QTWHWjAUJ)h^raCW zr5iGx478i?Fdj`$9fu~!nR&ByHa+m(gT355bQ7-+e?kAermYpp#wLg)q;BMrDVxPzgP+-z&ts5MrG~DRX2^;6s3@ zlp6Vs)&5KTqx?GzHT;0Oqw zJ7Ch|P`E8P`cdh~$I8m5F^m0n+RmTitPkJON;qLlfcat0(_k(*&E0^tbNv?M?SgR_tp0_&ZGf580T3Kbmr|;ASS3Y07>KLFgWzMUb ze1ppKjbwHhYrL71UO4IuEQJ-MKZ;^bTY)B*3c74Hz`)JlPfBRFPAzEnx2M`KG}&E+ zuPZsHWF@OS38%wU;Opy(1a%u0uF#`XH4i`EVR zH{v67b2h5!PEJz=KcYIFET)u3xXOs=%{taQq%tiy^ob2r%%a}s38w-{ip$Yu$wcwo z_z4wgZZ{Hdfd`;Mb)n`f7D1KGwNYuM2TD1eC zxO34UY?dHF^+5BvzX0R$S7$zsVbKCvpHhvi*I`RE=gw5(TnxBwe#5@JXpkv11$n1Z zPCR0tncSP|?Cz*XpNvsu)yQ#J1!cHR-G0_s9rJXupBcA-ycgNITr&_JjWc7EA-b+h4i~Mr@-EF9@It3w! zGVu*>5Zr)IBTja##sF8Z__rMEr+kZh;^%D(`A@-z6pd(*5BM0vkeBYa5?~*X|3B_w z(2kdxsHC;6j+j+SBn>>Yd`UU8o+D>JYf}Iu1y7-HsyT#nd5-oi$u60h0#(kxUg2l6w>Ir;X=%31oKU%h_O zCIgTdKxxWP$|qpGMoITb403+-ql2m+@x>>(1aUrz2F;rS(M7(L7wSJ0e1_>~xnut-1YUVk(rn~weXxi=09b)%U3Ec8sJsKJ%L5el}c0z(AhDX4pEVc=~6=&^W7mh8`S=w01ja)pSbZEiZN1L*+p-F9tt zZI9es4`Z^TpFVW;NR&hi>gjWud95f;kjJE73i@ye_rEOqAvWV1otQFZ(<40sUiL0rpJ* z8T}`M8ok}cI=UBT(<+2P-8XvJvxL4%(dcd%jl*@T`sj3Ll5XS&{-QF!Xvi4r53LhK z1Woqz>?w8gr2VQgzZ$?v7+@|}(IA#nx5LXpw}_lyEMomvl@73EOhaJ;7AyC@zVX;B zJ@5Qy9sgxHn2kaKvw8+QB(W6~Y@q&sSYVY8{)!2Z(MACixQqJu?(x^mirH*hT0PR@ zwpW?9GOh;T1&DViDuOcus2FhmVBr{>KfvsXWWTF0xSVn>N?nce(eYw|^31_u){A~0 z=;&h!XEh1OdhdU3TCsT0uFxU9l+fo$?ddLF*sBRQoCS!F^zd9XXs!$Pg9$0A2Xsb> zTpJ+u5}*g&GjNw2?>BQT1f_2ku{W<|G>P+5GbiP>gm|= zxjdl%@P3EPE6J9NlL7hHO=&2~vnc3#x&!#^(B%hx$h!yR%7b@CpnJ=62)Ar_`@-&|*Jf7FvNzOIZH9 z)7zmzq{|1boQVY%{J~4RDls->(^wt!!`a>^9|4^AyD5GRZD~A+MN+7%pilr0(8)W< zr(;z3DaQ7Q{qCsw(b-#Kb$OQ)b<{@Y%qu1-&JW)4!V>K%y?M>8W@P6fnU_R!NXnFf z{v{xf&O;DoZBl>ZdsEB#Apo=IM&fSvBbgVh`d@XQcXcwPW_pc(2^rQe{Q@C`YfKjN zTY?=fwI3Y7k9azP7nOGACLRj+hO>9~J@0Ts%{ao~GEkp9gv{qU*cZR>>0X1le&c6x z&${-SDBCtlyNDx~B(p*!Eo4+F)5BKSSU&S)o?vBp!Y}})J!u2j76pty!=ho9zPDi2 z*u#}_@%0}2xr@tFb^8Ec2ICMW8h^!?^bTEHjd>!U0k-N80pSsl1lQpw>X#Z5GiSd!v zgjLk?^YK(LfoOm-z~3wo!%inH9^zDNP!ziv`S^5bn%SO|Bs3pb6B@Y6mg?H)uxEJ| z1lN=>4vi}xCn=5;B=)D0SxQxxS2a8xw_UBJOZ#=2>Ilx)<^xvC^Wlq{#MuqGMw6{J zhssrl`!M16PEr=dost6$zGsN*$w^4!z0=K^cw?{5 zbWx0L-~Zfxwu+rgv(w4>#c>9!J(c{RFDA>@(QgsU$-d(L*LF8WZVO=r+9lC4f1A;a zxQqbeQDap?!su5j4xn8WlqjvYytHX_Kg3&Kc zs`6y)Ph)FU8Bn_`z7M?z{EuQ1qXD8lM-Qk=@aG_r4&Vik&9q}2paKLdQeYHp-*RDy zR=zqwX#So4X_WHmDH`N`lTQt(J7W_!6!={Vwx#Wtz{nMy5N$eXQWSHKm4DN`+!vA1pkYU8%1d)vn@knNwX7!Llk&F0LFks$;IJ z0qGhA++5E&RlB6Hncfr3(|24r3R%q~!R%|{%got7jC%S$VCG;=ATtPub~I9R_k79W zYu0TZ@?dySnBpmTR3=wwz{cNZkZ9}<>_chssC`_fo(>1s5co=td@RKDqILlb7nThlCK z%z%be0wxa{_p}n|H0gWyIM?T{d_1U~TDxD}Gdk?i3gRllT;T@R2ykXr%sX zetxu~;UL!`YQu5jQ2wR3-GTOSY|D(+2EX$dbaMDy{c&>!nAaBjiO;|i;EGRUL%{2a z4s&o|+p1V~v8t0`i`+dmIRSHFs^MaB6E$a6yD!eUlC)Cb7{^peGg;ny_4Zj38HtH= z1v76p)thg1O?s^R;BAkiK^$+^P|X8~rIK{sHRxmsN{xR28I*S33Atlf`qm$?vu5V6 zM^EU10|pqd-|E^U{myX zk+uSp8nE2s?Z8fO+9BvZ1CR!T7fj$VRFJeL3M&>RVNv<-$z{KI)OkAgb6*StEpt~& zULNCC#@}77`;y>)_)$_WQQ4=7IZtf(4=P1JGibj*rd)*4)pKO8`yxzM-X{^sS3(;- z;-24O!&?E_#Cm zS1)h7Z12I91AFSv!FET8zJ_Y2CGfo9W#FgK%yA!fdh?XLq*4M*$2_!)8LV7rnN~- zMwmJh7*T8Z8O3r1!v(Q$65yX7V1RG&bwSddOz8J#<~ZB>*&lM=j1ufF3b-9{BlpHX zlJ37J;s15tdDmhi=p@>%AbbkqG8~el-&Y4(XK-$?-B}j+{)qS{{#JVciIT@cDM4i7 zd}eC$dw7&gVTQeA<;1zyCG{dTlHg(-d6|IVwi=XYrKMoL>L{DG`vrM-vGG%St$dvd z%3tLG4H8M)^n|S)!$=Ngy9XB7bxf4lr%p2nW1iLf7)-Re)i6GBNQw-k*39vKx_NdF zV6N^RQsDCHKgd>mMIzsnuoq=mq-{nPucKZPH*=$!s@T5{8F_FO6&&D*LUsWRa=QO5 zYo1xkvAc4&qR)}M8(;SxFOP73j@iYlt-cfQ==qA4&ETtn^(MyD1XuC!hVD3Y9Ps-C zVJPtG6Qo8p0+qCYQi(tfNE=3NBV0wN8q@NOHo`3j3k`AJ$hD6=%lBLJnfH>f+|koE zn@C1YIhf@coAi9$X#IA2b7j@VbOzXRV79vO&k*l_dd;nz*~z(SWO~Q$)m+7To4f49 zb%_yW%dW4QUdWItY5rR^lalfKzR6UVr>E$XW&-Lr#xy+FpU3xVfVOUe5KO$ z&Yu!rFW;2Imum+}|B*-fli!H3mTW^jiEJ)a##p|I?vYR0W4e1TAa5(=c{b?rmF^it zb*C8Jc!JCLx!b3(NNw?st6d{m<$e@3)!4<#%WASduMG3e_^DQWrNgP&nfi`^ehkY? z<>8)3hMtQh1a^(A$=oM2B~*4+c5fW{Z!h*M(v#j3XF82IdG>Ecmkw;OpHjw>H4(laHZNb{-=;xO{q2!;VTvf2@Z%1oZAd>bx-;SvjARO zGj!Y{!KhmO-q50BoG0H?--eln`m%#0Z?-r~x2MsQx^?h!^)UpiJ@~~5l*I0+F}`-B zT-9CHI`hG>{Kh*k37jDLn@=*AiG_5EGuB)>HQ`|B_hXlCG$;hNFTd37uZ=A|@T_8w z+JR2!M-7wzAUbhqV~0X1ryM7vD)d^}CtMDq5EdKdu08XT)-){RuFNfi+3WiuY4+)J zn`sWivQj<_5<(m6rTJ77b?M4p#Ftj=L`b*0#XVZzL?fr=jB--1 z-iWvV1|cO&1AT7EZI+z(H7xNL8}=xY?_b}5l8iT_9tHIVZJ)Z*M-kH?->B$D#T}9Q z9vHwDNcZ;;tkDZ#AZ8>~xjU_O&1&96Tvi7hr8ds+y1n`@1^>U88VS~*zsN#?;AFlF z-PFdIv~5_$M2U-&XNui5-V!;kx7RB^;y(G#s?2`#F{xt%++H-n-{jzZ5mM8QK0K`%Y0~dz8W3r6wBA{5t}bj&+enSzS(BF6>354|?yidULVimU!nh z%QGGjXNnOiPwfbx`khk!_>~v?RV}&X&7!fx9+|BXOk!~{s$W%d*?_j9o}EC)PqJY? zYqON!MEPA#A;z8`$TdbxhB|eU2lx1|SzV>&WL@GT9(t0)_RSzBq*moQ*mhdowl$gQ zgLS?Go%(C-fcPQF>)J-G#K}(4pDTm?D~uv` zCO)}VJXne{u=unfW4~K3!9Y#qk_~r4e0{9I$6+1TNwvoRp2bFXIiX@LMorMi{sXaVoe{5X8 zg-hJc>MX;J5!#)DO_qp93mR;Ubwqi=);!OgN>}Rw0l3QxZXBQM31sn}T5AK7oM0#2 z8{RD}66G~*Fqnmk-Lq&I`WPzoH52=0@7*q`EBzv=2`v(VHvqP7c!|AXoPTYIkFCP9 zjLPkel3gYbo0X8BtbgajS=W~FJB`@;=^G}E$+h<)&3)HrHig2Mk%-I}8eZ1QdJNoH zB@D?`jkJTq9VCn1^QrtAb_TSW5r>arJhhtrzXstivxqz>iwCx9YV%fR$3i+0Rma4Q zCQwL8UQ1sgyu1yHbE0`|t}3EdxpbkY?k(SZh<;6lL2&ZTp(N|KJ7Do^vP|y^&>-TI zJ#tfc%H92b7&3uRIyAKZlilNoadhL|cCXsmWa0$wbcJ4J<_WY=7B38Bgewp4sN$yF z4B4ffcYF%_;>{Xk_0E9iUAF=~m%Ne5Sg68~MFPki-PZMKkOU=kzOJo zO+_+%Aj#1%v&B*pg^A)%t8qNSl_Id+Ui{4D!f@&ECQ_ywS+ z1gc3oNlDHDN9ajN=}CxR0T=*~kVD$;EBx0N$q`aA@}m@#RMa%k4@yn|M@UFXkC2g) zlarA_zYc)D2gvBj8P19+A3dpKNpa4VQT*|Xca&V0Kh`nncA>c??z#n0Q8S-nVP)gt z<>NmuASrcGT1Hk*<%;T6wQK4cdin;p42^CZTUp!Ov$eB#aQE8ypfE7XIXE zL`>|N!rv8lPG^;>sOZ(skw;Lz~o)bz~k z-2B4g5@vm4b8CACi`(6|iv%G3i&=lO>>uo+hwM5+Mn+0Tv2Pd25ih8b(vy*&6+6nH ztV3bxdh(q3V@k%$FW!BuqvDd#MKj%X>!N1nmYn3l?3?zRW&b_Hg8o;Q{mrny+cgZ( zl9E81M@kRCfmMG`zdZG+6=}7eEvf=$@8`knk-_frv@zAwkJX6)rEMf?!7i2v9C@GK zXt8b}3EMeK1iFysNHe$W#d?LBXcpZl<5)Krwb2bERz<;v2&i01#WG33&|%(fVAxYQ zTEJn`S3s#4E?VBR^b!wl`!wUvric@PcWK&q>cm4rzKVmChmTT=|%^&b(b*$m?22 zUzS+k3;xrA`v>t)2mT*FfeI&m^6I7q39y^J_o|HU-p9pAMAf~tW}fksTG*ODbD9Xm zd@Mjzh=L(;uGveMHOwNjG$gYqn70BN4uh1r>r@d=AdznGIT2WBE>g=bKsR&_&|!MF zsQJ?>e!NYK;0ONJ%9BzffeW9O-=X)7NrtcCR}K4J6218%hL}5|M;GZBV3S zn@OH^&&W$YSAa%7doBNMRk&B2g5x=778x$Ch?Gx~)Phe^r{Y7&)~`5~9OZBH5>gLF z=8;19RX@;)n(u)ID0?E%*k4?dMXU`YFrF2Y6Q>r(d1JhP z#Y{HgTfGa&+Yb^&#U!jBShz*=ptYQUl8RZU}1Oz7&_+;5qMjjy7Lo( zF<98t-EB9Y-c5$h;yXAo(hb;Zcv@>V@7oPVPqQ%28ZEiGst)qS?RfA^adp@j!_*v^ z#5D?$OKS#!+=!MWIKdN11TGiADTzQ!dL|JVsO*mu(D2ZUU9#19V?V`y_w&aR$o#Xz zznlK=_DqM*`ahoi8dz9hxCqyDc(!*QsPR4+oPqC(Eq5*dP%t0@JbKDRzzs%V*;?3K z_P?-63vbrzNZdY0h|~ zzpPqZaBuWWet37-zkuCH)n0oRN6x5YYHO#X%1F}ce~k#dxQN(YhJm4`^YwWnIYllj zv*mG<*YvFKf6e_l{dgo|0X*QmLc>W>e5j}B?i6a5>0tw5hzOWP^MPCIL_nesI@VM2 zmk((7yOsxgx>IOms1?Spw!Eq)QI^ZI4Pg0rKSnDst{b{wSs$U@PHrZkOJMaD*sVVJ z1QI88V+ujKB$xG+d?j;;d55+((B#Zb;P}x%XA;G{&KzCyzUIW1^&Fk>50N<8BnVrm zQ<}jbFW63f*MaeXa*?;QnP&Zm#Rq2M?G6!E{#M_uFTXwG-I_a2f$p1o?BvRWpPeuN zA{I7!;=D}VPP@%YR?BQhk(Enc&%DmIuUEy31Iry;x>pCU)T`G>BUWp5=M&YH*SM$4 zWzN2~5yP0~Fc;4Sr`Zp0^3gU|Y)Zo@SY@{x_3}ilYu+J6i>;Tk&4>s3T2rH8N*LYo%vkpG=sW#gbQD2st`7 z7sTpz)%$1gctUAhDyl4g+T*M@xQ0*+Lmcp_`QBtcDeD7-MJRsztF16?xK83=O zWf302S_Y0waF|C?^*-z4`V>Y=Cl?_ipW+2&J}D4(!iSLroHi(c#9o1L4uo*-8+0H0 z8qd5-TU^PtND|CDvD9(m5rxqcfQfsWb2`$!Lsp7owlK%X=6EjKHyUY`vt`lr9Cc%ke?WG@|WA>*phx3qVq4e`89Xfl}j=D*EdJM+)FjRSP+~y9`N}aB}MB9 z5_{ZzgsBeMq#(o?Q!`c_9VtcU#G52?=++k1Ti~ddEVddEn*x0pu~&FWggksX_8y|D zDk2NLQy+_z+XZ=<%TDAxPJfege*@1A`%&XBY-33FeshipJo1TqI~nO}JcM|?*n7(Y z&$a8dsxkJT*8xg?hBMwV`_6waK!9WT-=-fu2k&6>!6;OU(fxza%56c-V)^Ds}q3@*l z^HGOPfE^MOJ~QdFjYs@sd-<=-W=1}!-V21Ik7)>sg7gIWy)roVlqeBkQak9XXKLl< z0Vo*uXr}w_smM(ye*tCJnbB07SJLeLy@xLKg@=vF>-Y={b#KuPaF}j2N7;tVqL>%p zv;;?^tFh1K?lJM*))1ht@Pm-ncPVwP8J}3-olrMin>oc(^{JOz(wez4@;AP;@{5(r$WXBIvF{paV~xgnh(Kx!5m>87gnCxG$EoQi z8NU%Ikm=UXeV?c(VTL9&y_@v*Sauv@m>Octc=Yqzw-7*U9~G(5+wam$Ox1JD6pA|@ zS&5c&nr_OjrFK_ufXvcQ5%cTtJ#^}%8eYhSfe3WWAa*9<_32An6+R;Q7X4`a(nBwc z0rwo_m*INv*EVt)&Dw?xxD?A#ZL=!(9)(*SQU3DT%MV7{-j6A`H@uh)A7p2D)AGAp zz4Omk&*>_h$@F|jLm#H&T0F43>U%G0a_>I&GDJ~2;dlz!>6#^uQ{*8OJu%q?LC9h~R=U87h#mRf!WDVSQfsyGVF$N#zNI#&n}i zoMTsG6>Vy+FjDG38nThsfzfJqrY8}Yf!9lL+U|VguwAfX@AW@4<(X+L|%!@K(q{4 z5dn)uh)jssJzneI4WDuRNCb*Dp>Wt3Kw(ziKILkubRLi5EOf$qzEk7k(sZp*ry#IG zuu`cpH=&2Q`69^s;n>TQ!P|YTusC-;^)=k!Lf&~nlXaJMC>5Yu4JHDLg>dw~M0!F~ z?dey+qDg1XLw}7;C1-6Fq|AN`6@r-2=_UfpV~$)?G#Vh;y%aI_?_H-Z4N(uV zvaYqmzZetZ)6*N?*Ubf_eIsLVHYMGZx&gP$a#bY)pO*)hv(qBxCZuM~OhGAhH719b}A=S%Wa!LajiG!(}$9*1V0`wUEO4H4knO+G&H z49fB#lH-;(#1b*4Vvi%Rm4|1WzWh)sPXwL^Xob5p5`otcvy;cSzrEUc3OL^E@NAzh zawtNyC}pXXO%Z|b5FcXzQB|Fdd?0BmDDoJcU0jq}q|SY3CcCT-e%W+-9iojA`g3>i z!AlK0(r!LU|3C`pztl0}fWrS@BL9AWINJXa(I2<5pFalKB5tl$?^^35?#YX{;#ZG^Svy7fU0KQ1;~9*;dzWH2uFobYv{u7Hf3_OMfW&hR?+}h9z_8RW5%r2ih|VEbC`jfQqW+0=;g)1F8@bYQG(3NjmD~(UpuSI z#6MG>K?eMsDzKl7Z~Ri+}j;*2}@Ocvi}9`>)B97 zol8(1`cK*|#rdb3Z5)?1sgy=|zF#XkXJVwS^krxymhA#--P-V@i~RXLMT-`LsUw1Z z?1>M@#{GR<2RJ^tr%?WKXrCn%rf^E@;sX8K$Pnk{lWP}#x^6A1mV7W{w#%o$q&!b} z|GhA0`*|k*U4|L6z;S6>wU!RnMdOVL6BBJm+D}gLi{CCMsS90>SCj)tW-z#}xl=+q zMmbXj=S(t#SeBZGw_;(2V9nSt(C=-lCNuQxF?Ukw#U#F?z{;@G;q`4EBQF?zarM)OSodQY zCwt!g+@T=l;8=Z{vE)T>YO(mx&|L*ARA1>DlIRnDkz?v2z-(cQy>uM4fpp7JHRBniAd#w&9g zsTVzz+hvz{oh^1r$Nr(tM6K5tPbHO!q8qlgqdzeKN?Wk5QX>!t7AET`AM5Bk72vSD zzU!JbaV@^Ie)g-?j(P|sCGG7b;NpX8O;ob?$}BxIy;amgg!CLJ^h*+*R&}hCXK9D- zGaQ}rsr%CCY3R$7JaR?DM)e&xH2YKU0%hx{1Kjc!4SCCgW_4`CWG~CSxDs*N zk@R_kV%>s0pQDcnx@_)Z5kel6#zzM5X`=Sp&Ej0$bT@qumg4uLYYLqGRS{ zCrBIf_`*JiSJixq?;KQ}ZDdMnK8Jr6SrPYmn(!jkIj&dlY?z?8RTxV*fBMbrCvOEF zcLH+M0j9I4se5~7!uKq^-7oiv1omXx zReFwMY34?aGol`MS_ipak_f9kGGDKBu~+ERu4m&!vU7`gVfM$T)~24i-|*4pe2I$+ zdXk0+bTm)(GePZKWg+F`UTHzU8U{sWcYO!67zILa9(nu-SkxEt;DBAP@QZ@0fB2lD zTryi$dTl7oJ?K*FTyoz)9O{U17j6P0J_2goMGSJFHr;yT;TTDb!4__ALfhh_NlKGS z*z0gm24!Gra&P#g>vpPum}_y{$@{14=VdzH`!p(NE`ES+_`{pUmG9MkC`Gx%guZ_T zsJLUi*VLU{EE+$S&E+atVdAa&HJ3sC^06Q3GGtqv)|fRd0-{KC`MWRyVbLE>ZkuiD z0P;f>(O!C%gQ1s>DudQi82`IL$~u;|@cYrez6MUhNtdurQe(;O-|2YvRHVKp(D9cd zSFT5K8gidE;Es*1elze+<^7;ZL1lxD6T`?6PAZ1S%--@3luY+@RWcX1yUo(Me(r3D@wY)!)^jyHJg z$H#TquBDY;G30v3Ny~1~;6iFz&>AN3;E9fnfV4mi6|hyu>H3SmwhSz#v3FT^Gv-fw z@dxLSGkC9T$6FT@O?_!GjehRFA0D3*6pV^|_$Hc!)9r#?Z?)DA{P3t)i!&pHcejcz;+D*Deo;AH`Xod_cN`2$$;A&KbtK zYnPc>8Q8yfGvM}aP7>=-jh32uq&CKAqWLW8R+O)x#C6QkgnU(ncxiLnp&z_gqh3s} zZEyjQBE=BfqktZWqeTr{RJ=UTfMd9CHYQy<%4ackF51w~$iK}!J*{}_hRcnvv}nz} z%xCTLcQ0j*t1RTcEe<>qt3Kc{=5$XkpyO3%>5!GR-58zIw=Wm)s?2_&{Y_DfI@c_J zkDC9f{y!akwM?2|5SulL*rRENIB!Mw33_3hP7i`HIK;9zTvDa#!xs5uzIk=F*=fQP z^^>U!Y}t>u^vPR%9jk@ZaI_bRyQZEY`kXPf<}+!_V&#WTQF^;lB0%G`8N@Qtez%J! zsQ!9!Rd7%q@|BqESkJ(_BCTZF()Fw5ZD(~-U2oU2bkBGBi)Gm-2%m0uI?}Yl%AXW5(lT)fL||8YlEzi#mQ(ZEW|KBcrCYURmF>05+?&N-~SLXu)G0UCs&-sY??FkSp!uCr)QDA+Kjad~; zY8A1Hmt3z4?X|W}aihz@FLQxRx56Rr%NI$&YlG)XW}~iMU9&pl)14#8z51hJPoo(` zI6>^;5)p`k4c~%q?72YYs3G1FVxmF~-a*yOcsld}RMtF!9_k%jD&a%8*ACNGZtAyM zB7mi^BxFKV4;ZPwxPo1X%5tlV; zAPCV1^lJNyQS|2`1oj|0nj?HW4v7axAil1T2(TS6bpZDNNa6(w=)k}&*d8_&uX?7Q zV`3C$oP*C>gNo#b2Q9J#yFWtzID**QMNOL`4vE3gxu4;Y{_fd7J@n@p`tz3ki9>%P zH59i0jacT`fxocK*Jx(b6?{HgmsLv{7xNiDX<&!g*nytFPJD$P3J97sfHXY{vOYXx l842PV7@W`R-bdn8O~582j!TQ7c |(Trunk:10)->pkt(Tag:10) +1. pkt(tagged:10) ->(trunk:10)|DUT| + DMAC-> |(Acess:10)->pkt(Untag) + + DMAC-> |(Trunk:10)->pkt(Tag:10) +2. pkt(tagged:10) -> (access:10)|DUT| + DMAC-> |(Acess:10)->pkt(Untag) + +3. pkt(Tagged:20) -> (Trunk:10)|DUT| -> X +``` + +Below is the test for checking this. +Precondition/Setup: +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + +Cases: +| Goal| Cases | Expect | +|-|-|-| +|``Tag``:Trunk -> Trunk port.| Send VLAN10 ``tagged`` packet with dest mac4 on port1. | VLAN10 ``tagged`` packet received on port4.| +|``Tag``:Trunk -> Acess port.| Send VLAN10 ``tagged`` packet with dest mac5 on port1. | ``Untag`` packet received on port5.| +|``Tag``:Acess -> Trunk port.| Send VLAN10 ``tagged`` packet with dest mac4 on port6. | VLAN10 ``tagged`` packet received on port4.| +|``Tag``:Acess -> Acess port.| Send VLAN10 ``tagged`` packet with dest mac5 on port6. | ``Untag`` packet received on port4.| +|Drop: Unmatched ``Tag`` on the trunk.| Send VLAN10 ``tagged`` packet with dest mac4 on port1. | Drop.| + +### Test suite: Flooding and learning + +#### Trunk VLAN +Those tests will verify flooding and learning for VLAN. + +VLANs divide the broadcast domains into multicast domains. When flooding a VLAN packet, the broadcast should only happen within a target VLAN. + +After saving the mac address to the forwarding table, only unicast will happen with the target mac. + +ARP requests and responses will also be covered in this test suite. + +**Testing Description** +For flooding on the VLAN packet, it should only flood to VLAN members. +``` +Test example: +Without DMAC in CAM + | pkt(Untag):VLAN10:access + pkt(tagged:10:DMAC) -> (trunk:10)|DUT| -> Flooding -> VLAN:10 + | pkt(Tag):VLAN10:Trunk +With MAC in CAM + pkt(tagged:10:DMAC) -> (trunk:10)|DUT| -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT +``` +**Precondition** +- Create VLAN as the basic configuration. + +*Need to loop on all the trunk ports.* + +Cases: +| Goal |Cases | Expect | +|-|-|-| +| Flooding to VLAN members. | Send ``VLAN10`` ``tagged`` packet with dest ``mac4`` on ``port1~3``. |``Tagged`` Packets from ``Trunk``, ``Untag`` Packet from ``Access``| +|Unicast on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac1~3`` on ``port4``.| Received ``VLAN10`` ``tagged`` packet on mac matched port.| +|No flooding on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac1~3`` on ``port4``.| No other packet than mac matched port.| +|MAC learning.| Use FDB SAI API to check FDB entries.| ``4`` entries should be added, and marked with VLAN id.| + +#### Access VLAN +**Testing Description** +For flooding on the VLAN packet, it should only flood to VLAN members. +``` +Test example: +Without DMAC in CAM + | pkt(Untag):VLAN10:Access + pkt(tagged:10:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 + | pkt(Tag):VLAN10:Trunk +With MAC in CAM + pkt(tagged:10:DMAC) -> (access:10)|DUT| -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT +``` +Precondition/Setup: +- Create VLAN as the basic configuration. + +*Need to loop on all the trunk ports.* + +| Goal | Steps | Expect | +|-|-|-| +| Flooding to VLAN members. | Send ``Untagged`` packet with dest ``mac5`` on ``port6~8``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| +|Unicast on VLAN port after learning.| Send ``Untagged`` packet with dest ``mac6~8`` on ``port5``.| Received ``Untagged`` packet on mac matched port.| +|No flooding on VLAN port after learning.| Send ``Untagged`` packet with dest ``mac6~8`` on ``port5``.| No other packet than mac matched port.| +|MAC learning.| Use FDB SAI API to check FDB entries.| | 4 entries should be added, and marked with VLAN id.| + +### Composit scenario: ARP Flooding and learn +- ARP request + ```Python + simple_arp_packet( + eth_dst='FF:FF:FF:FF:FF:FF', # boardcast + eth_src='00:11:11:11:11:11', + arp_op=1, # ARP request + ip_tgt='10.10.10.2', + ip_snd='10.10.10.1', + hw_snd='00:11:11:11:11:11', + hw_tgt="00:00:00:00:00:00") + ``` +- ARP response + ```Python + simple_arp_packet( + eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + arp_op=2, # ARP response + ip_tgt='10.10.10.1', + ip_snd='10.10.10.2', + hw_snd='00:22:22:22:22:22', + hw_tgt="00:11:11:11:11:11") + ``` +In the ARP scenario, the mac learning process is: +1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff +2. After the encountered device get the ARP packet and sends out a response, the packet will be filled with a source mac, this is the mac we want from step 1. +3. Switch received that response, cause the switch learned a MAC on step 1 on the sending port, then it can make a unicast here. + +**p.s. The test will be ended here, will not test the send from the port in step 1 again, it is already covered in other tests.** + +**Testing Description** + +Testing ARP scernairo +``` +Test example: +1. ARP Request + | pkt(Untag):VLAN10:Access + ARP Req pkt(Untag:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 + | pkt(Tag):VLAN10:Trunk +2. ARP REsponse + pkt(access:10)|DUT| <- Forward(FDB:MAC=DMAC) <- VLAN:10:PORT <- RP Resp pkt(tagged:10:DMAC) + +``` +Precondition/Setup: +- Create VLAN as the basic configuration. + +| Goal | Steps | Expect | +|-|-|-| +| ARP Request flooding to all ports. | Send ``Untagged`` ARP packet with dest ``mac4`` on ``port1``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| +| Mac learned from ARP request and ARP response.| Send a ``tagged`` ARP response packet with src:mac4, dest:mac1 to port4 and check the FDB entries.|Unicast happened.| +| FDB entries added.| Call API to check the FDB entries.|New mac entries in CAM.| + + +### Test case: Test Frame Filtering +**Testing Objective** + +The switch will not forward packet source MAC equals to the port's mac in FDB. + +**Testing Description** + +The switch will drop the packet when the packet sends to a dest MAC, but the same dest mac-address already exists in the FDB and is mapping to that port. +``` +Test example: + | SRCPORT:MAC1 = DMAC| + pkt(Untag:DMAC):vlan:10 -> SRCPORT(Trunk:10) -> |DUT| -> |FDB| | -> X + | MAC2 | + +``` +Precondition/Setup: +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + +| Goal |Steps | Expect | +|-|-|-| +| FDB added.| Add a non-existing ``MacX`` to port1. Check FDB |FDB added.| +| Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| +| Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| + +### Test case: Test native vlan + +**Testing Objective** + +For Native VLAN, only consider the ingress direction, the entry condition for VLAN, and the behavior below +| Port mode | packet tag mode | Action | +| ---------|--------------- | --------------------------------------- | +| Access|Tag| Drop, if the native id does not match. | +| Trunk |Untag| Drop, if native VLAN id does not match.. | +| |Tag| Drop, if the VLAN id does not match and does not meet the native VLAN case. | + +**Testing Description** + +Test for native VLAN +*Only Consider the ingress direction* +``` +Test example: + | Y Native VLAN -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT + pkt(tagged:10:DMAC) -> (Access:10)|DUT| + | N Native VLAN -> Drop + + pkt(untagged:10:DMAC) -> (Trunk:10)|DUT| Native VLAN -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT + + | Y (VLAN||Native VLAN) -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT + pkt(tagged:10:DMAC) -> (Trunk:10)|DUT| + | N (VLAN&Native VLAN) -> Drop +``` +**Precondition** +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + +*Need to loop on all the access and trunk ports.* + +Cases: +| Goal |Cases | Expect | +|-|-|-| +| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| +| Drop, ``VLAN40`` ``Tagged`` packet on ``Native`` from a ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | Packet dropped.| +| Forwarding, ``Untagged`` packet on ``Native`` from a ``Trunk``.|Send ``Untagged`` packet with dest ``mac3`` on ``port1``. | ``tagged`` packet received on port3.| ``Untagged`` packet with dest mac3 on port1. | Packet dropped.| +| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Trunk``.|Send ``tagged`` packet with dest ``mac3`` on ``port1``. | ``tagged`` packet received on port3.| +| Drop, ``VLAN40`` ``Tagged`` packet on ``Native`` from a ``Trunk``.|Send ``tagged`` packet with dest ``mac3`` on ``port1``. | Packet dropped.| + + +## SAI APIs operations + +### Test case: Test VLAN related counters. +**Testing Objective** +For VLAN-related counters, SAI should be able to get the counter and clear them. + +Below is the sample API to operate those data + +Check counters +```Python + stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) + in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] + out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] + in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] + in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] + out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] + out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] + +``` +Clear counters +```Python +sai_thrift_clear_vlan_stats(self.client, self.vlan10) +``` + +Precondition/Setup: +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + +| Goal |Steps/Cases | Expect | +|-|-|-| +| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| +| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| +| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | + + +### Test case: Vlan member list. +**Testing Objective** +Test VLAN and member list. + +Sample APIs + +Get VLAN member list +```Python + vlan_member_list = sai_thrift_object_list_t(count=100) + mbr_list = sai_thrift_get_vlan_attribute( + self.client, self.vlan10, member_list=vlan_member_list) +``` + +nagtive test +```python + vlan_attr = sai_thrift_get_vlan_attribute( + self.client, vlan_oid=11, learn_disable=True) + + incorrect_member = sai_thrift_create_vlan_member( + self.client, + vlan_id=11, + bridge_port_id=self.port27_bp, + vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_TAGGED) +``` + +Precondition/Setup: +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + + +| Steps/Cases | Goal | Expect | +|-|-|-| +| VLAN member list and member count are right. |Use the SAI API to check the VLAN member | Vlan member list.| +| VLAN and its member removed.|Remove the VLAN member from VLAN 10 and remove VLAN. | VLAN and its member removed.| +| Error when creating member to un-exist VLAN. |Use the SAI API to create a VLAN member on VLAN 10 | Vlan attribute is 0.| + + + +## Test Case: VLAN interface (RIF/SVI) +**Testing Objective** +Test the configuration as below + +```xml + + + + + +``` +Convert to config_db.json +```json + "VLAN": { + "Vlan608": { + "members": [ + "Ethernet6/1", + "Ethernet7/1", + "Ethernet8/1", + ], + "vlanid": "608" + } + }, + "VLAN_INTERFACE": { + "Vlan608": {}, + "Vlan608|10.95.88.209/28": {}, + "Vlan608|2603:10a0:31c:8144::1/64": {} + }, + "VLAN_MEMBER": { + "Vlan608|Ethernet6/1": { + "tagging_mode": "untagged" + }, + "Vlan608|Ethernet7/1": { + "tagging_mode": "untagged" + }, + + "Vlan608|Ethernet8/1": { + "tagging_mode": "untagged" + }, + } +``` + +Need the APIs as below + +- Create Router Interface for a VLAN interface + ```Python + sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_VLAN, + virtual_router_id=self.default_vrf, + vlan_id=self.vlan10) + ``` +- Create next hop to a IP address '10.10.0.1' and mac + ```python + sai_thrift_create_next_hop( + self.client, + ip=sai_ipaddress('10.10.0.1'), + router_interface_id=self.vlan100_rif, + type=SAI_NEXT_HOP_TYPE_IP) + sai_thrift_create_neighbor_entry( + self.client, self.neighbor_entry1, dst_mac_address=self.dmac1) + sai_thrift_route_entry_t( + vr_id=self.default_vrf, destination=sai_ipprefix('10.10.10.1/32')) + ``` +**Testing Description** +When a switch needs to forward in layer3, it needs a vlan interface in layer3(SVI). By this vlan interface, swtich can forward the packet to other VLAN, which can be on other ports in the same switch or to other server port, that dest port then can accept packet from different ports. +``` +Test example: + +pkt(Tagged:10) -> (Trunk:10)|DUT| -> RIF(VLAN_IF->MAC5:IP1) + PORT <- FDB(PORT:MAC) <-| + OR | -> Server(NHop) +``` + +**Precondition/Setup:** +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. + +Below is the test for checking this. +| Goal |Steps/Cases | Expect | +|-|-|-| +| Create a VLAN interface. |Create route entry and next hop for VLAN 10, with [IP1] and [mac5].| Vlan interface created.| +| Add FDB entries for RIF. MAC is [mac5], and map it to Port5 in the FDB entry. |Simulate the mac learning.| Set up forwarding table| +| Forwarding from trunk to a trunk port on native VLAN.| Send ``tagged`` packet with dest mac3 on port1. | ``tagged`` packet received on ``port5``.| From 5c5a0e2d62e09d848450f0a1fd72d01bbf68e286 Mon Sep 17 00:00:00 2001 From: zhoudongxu <1315364814@qq.com> Date: Tue, 24 May 2022 05:12:19 -0700 Subject: [PATCH 02/18] Update lag_test_plan.md Signed-off-by: richardyu-ms --- doc/sai-ptf/lag_test_plan.md | 159 ++++++---- doc/sai-ptf/vlan_test_plan.md | 542 +++++++++++++++++++++++----------- 2 files changed, 469 insertions(+), 232 deletions(-) diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 007b84e0c..85a509c67 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -4,12 +4,15 @@ - [Test Topology](#test-topology) - [Testbed](#testbed) - [Scope](#scope) -- [Basic SAI APIs and sample packets](#basic-sai-apis-and-sample-packets) - - [APIs](#apis) +- [Basic Configurations SAI API and sample packets](#basic-configurations-sai-api-and-sample-packets) + - [Basic Configurations And SAI API](#basic-configurations-and-sai-api) - [Packets](#packets) - [Test suites](#test-suites) - [Test suite #1: PortChannel Loadbalanceing](#test-suite-1-portchannel-loadbalanceing) - [Test suite #2: Ingress/Egreee disable](#test-suite-2-ingressegreee-disable) + - [Test suite #3: Remove Lag member](#test-suite-3-remove-lag-member) + - [ToDO Test suite #4: Scaling test cases](#todo-test-suite-4-scaling-test-cases) + - [ToDO Test suite #5: Hash LoadBalancing test cases](#todo-test-suite-5-hash-loadbalancing-test-cases) ## Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -31,59 +34,71 @@ The test will include two parts - create/check/remove lag and lag member -# Basic SAI APIs and sample packets +# Basic Configurations, SAI API and sample packets -## APIs - -Create and lag member -```Python -sai_thrift_create_lag(self.client) -sai_thrift_create_lag_member( - self.client, lag_id=lag3, port_id=self.port24) -``` - -Get lag members +## Basic Configurations And SAI API +### Basic Portchannel configuration +|PortChannel Name|Ports| +|-|-| +| lag3 |Port14-16| +#### Create lag and lag member Using SAI API ```Python -sai_thrift_get_lag_attribute( - self.client, lag3, port_list=portlist) -count = attr_list["SAI_LAG_ATTR_PORT_LIST"].count + +------------+------------+-----------+-----------+ + | lag3 | -- | port14 | -- | + | lag3_rif | | port15 | | + | | | port16 | | + +------------+------------+-----------+-----------+ + sai_thrift_create_lag(self.client) + + self.lag3_member14 = sai_thrift_create_lag_member( + self.client, lag_id=self.lag3, port_id=self.port14) + self.lag3_member15 = sai_thrift_create_lag_member( + self.client, lag_id=self.lag3, port_id=self.port15) + self.lag3_member16 = sai_thrift_create_lag_member( + self.client, lag_id=self.lag3, port_id=self.port16) + + self.lag3_rif = sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_PORT, + virtual_router_id=self.default_vrf, + port_id=self.lag3) + ``` -Get port counter -```Python -counter_results = sai_thrift_get_port_stats(client, port) - -counter_results["SAI_PORT_STAT_IF_IN_DISCARDS"], -counter_results["SAI_PORT_STAT_IF_IN_DISCARDS"], -counter_results["SAI_PORT_STAT_IF_IN_UCAST_PKTS"], -counter_results["SAI_PORT_STAT_IF_OUT_UCAST_PKTS"])) -``` +### Basic Route Entry -Add fdb entry -**P.s.For fordwarding packet with vlan tag, fdb entry should enable the bv_id** -```python -sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) -sai_thrift_create_fdb_entry( - self.client, - fdb_entry, - type=SAI_FDB_ENTRY_TYPE_STATIC, - bridge_port_id=port_bp, - packet_action=SAI_PACKET_ACTION_FORWARD) -``` +|DestIp|Next Hop |Next Hop ip|Next Hop Mac| +|-|-|-|-| +|10.10.10.2|lag3|10.10.10.10|00:99:99:99:99:99| -Remove lag member +#### Create Router Entry Using SAI API ```Python -sai_thrift_remove_lag_member(self.client, self.lag1_member6) -``` + nhop = sai_thrift_create_next_hop(self.client, + ip=sai_ipaddress('10.10.10.10'), + router_interface_id=self.lag3_rif, + type=SAI_NEXT_HOP_TYPE_IP) + neighbor_entry = sai_thrift_neighbor_entry_t( + rif_id=self.lag3_rif, ip_address=sai_ipaddress('10.10.10.10')) + sai_thrift_create_neighbor_entry(self.client, neighbor_entry, + dst_mac_address='00:99:99:99:99:99') + route1 = sai_thrift_route_entry_t( + vr_id=self.default_vrf, destination=sai_ipprefix('10.10.10.2/32')) + sai_thrift_create_route_entry(self.client, route1, next_hop_id=nhop) +``` ## Packets -Vlan tagged packet ```Python -simple_udp_packet(eth_dst=dst_mac, - eth_src=src_mac, - dl_vlan_enable=True, - vlan_vid=vlan_id, - pktlen=104) + pkt = simple_tcp_packet( + eth_dst=dev_port11_MAC, + eth_src='00:22:22:22:22:22', + ip_dst='10.10.10.2', + ip_src=srcip) + + exp_pkt = simple_tcp_packet( + eth_dst='00:99:99:99:99:99', + eth_src=dev_port11_MAC, + ip_dst='10.10.10.2', + ip_src=srcip) ``` # Test suites @@ -97,28 +112,29 @@ Disbale egress ```Python sai_thrift_set_lag_member_attribute( self.client, - self.lag1_member4, + self.lag3_member14, ingress_disable=True, egress_disable=True) ``` -| Steps/Cases | Goal | Expect | +| Goal| Steps/Cases | Expect | |-|-|-| -| Create lag, add lag members, port1 - 4. Add FDB entry for lag, map with a MAC. | Create lag and member| lag, and member created| -| Send packet with.| Prepare to send from lag to VLAN.| Vlan and members have been created.| -| Send packet on port0 to the lag by specifying lag mac as dest mac. 4 times .| Packet forwards on port equally.| Loadbalance on lag members.| -| Every time, disable egress/ingress on one lag member, then send packet | Packet forwards on available ports equally.| Loadbalance on lag members.| -| Every time, enable egress/ingress on one lag member, then send packet | Packet forwards on available ports equally.| Loadbalance on lag members.| -| Every time, remove one lag member, then send packet | Packet forwards on available ports equally.| Loadbalance on lag members.| +| Prepare to send from dev_port11 to Lag3.| Send packet with.| Lag3 and members have been created.| +| Packet forwards on port equally.| Send packet on dev_port11 to the lag3 4 times .| Loadbalance on lag members.| +| Packet forwards on available ports equally.| Every time, disable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| +| Packet forwards on available ports equally.| Every time, enable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| +| Packet forwards on available ports equally.| Every time, remove one lag member, then send packet | Loadbalance on lag members.| ## Test suite #2: Ingress/Egreee disable +For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. + Sample APIs Ingress/Egreee disable ```python status = sai_thrift_set_lag_member_attribute( self.client, - self.lag1_member4, + self.lag3_member14, ingress_disable=True, egress_disable=True) @@ -127,14 +143,35 @@ Ingress/Egreee disable lag port list ```Python sai_thrift_get_lag_attribute( - self.client, self.lag1, port_list=portlist) + self.client, self.lag3, port_list=portlist) ``` -| Steps/Cases | Goal | Expect | +| Goal | Steps/Cases | Expect | |-|-|-| -| Add FDB entry for port4 map to a MAC. Create lag and add port4 as a member. | Create lag and member| lag, and member created| -| Create VLAN and add VLAN member with port0 and port1.| Prepare to send from lag to VLAN.| Vlan and members have been created.| -| Send packet on port1 with target mac on port4. | Forwarding from port1 to port4.| Receive packet on port4.| -| Disable egress and ingress on lag member4. send packet | Packet dropped on port4| Packet drop.| -| Enable lag egress and ingress. Send packet with VLAN tag on lag port4 with a new dest mac.|Packet flooding on VLAN members, port0 and port1.|Packet received.| +|Packet dropped on port14| Disable egress and ingress on lag member14. send packet | Packet drop.| + +## Test suite #3: Remove Lag member +Test verifies the LAG load balancing for scenario when LAG members are removed. + +Sample APIs + +Remove Lag member +```python + print("Remove LAG member 16") + status = sai_thrift_remove_lag_member(self.client, self.lag3_member16) + +``` +How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag), +```python + self.max_itrs =100 + for i in range(0, n): + self.assertTrue((count[i] >= ((self.max_itrs / n) * 0.7)), + +``` +| Goal | Steps/Cases | Expect | +|-|-|-| +|Remove port16 and forwarding packet from port1 to port14,15|Remove port16 form Lag3 and Send packet on dev_port11 to lag3 100 times| Port14 and port15 will receive an equal number of packets.| + +## ToDO Test suite #4: Scaling test cases +## ToDO Test suite #5: Hash LoadBalancing test cases diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 7bdb353e9..e795f7e7a 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -4,24 +4,34 @@ - [Test Topology](#test-topology) - [Testbed](#testbed) - [Scope](#scope) - - [Basic Test data and SAI APIs](#basic-test-data-and-sai-apis) - - [Create VLAN and VLAN member](#create-vlan-and-vlan-member) - - [Packet example](#packet-example) - - [Basic Configurations](#basic-configurations) + - [Basic Configurations and SAI APIs](#basic-configurations-and-sai-apis) - [Basic VLAN configuration](#basic-vlan-configuration) + - [Create VLAN and VLAN member](#create-vlan-and-vlan-member) - [Basic Forwarding Table](#basic-forwarding-table) + - [Create FDB Entry](#create-fdb-entry) + - [Packet example](#packet-example) - [Tests](#tests) + - [Test Case: VLAN interface (RIF/SVI)](#test-case-vlan-interface-rifsvi) + - [Test the configuration](#test-the-configuration) + - [Test description](#test-description) + - [Route entry](#route-entry) + - [VLAN interface input packet](#vlan-interface-input-packet) + - [VLAN interface output packet](#vlan-interface-output-packet) + - [Test case](#test-case) + - [Test Case: VLAN interface (RIF/SVI)](#test-case-vlan-interface-rifsvi-1) + - [Route entry](#route-entry-1) + - [VLAN interface to Port](#vlan-interface-to-port) - [Test suite: Tagging and trunk/access](#test-suite-tagging-and-trunkaccess) - [Test suite: Flooding and learning](#test-suite-flooding-and-learning) - [Trunk VLAN](#trunk-vlan) - [Access VLAN](#access-vlan) - [Composit scenario: ARP Flooding and learn](#composit-scenario-arp-flooding-and-learn) - [Test case: Test Frame Filtering](#test-case-test-frame-filtering) - - [Test case: Test native vlan](#test-case-test-native-vlan) + - [Test case: Test native vlan (Optional)](#test-case-test-native-vlan-optional) - [SAI APIs operations](#sai-apis-operations) - - [Test case: Test VLAN related counters.](#test-case-test-vlan-related-counters) - [Test case: Vlan member list.](#test-case-vlan-member-list) - - [Test Case: VLAN interface (RIF/SVI)](#test-case-vlan-interface-rifsvi) + - [Test case: Test VLAN related counters.](#test-case-test-vlan-related-counters) + - [ToDO Test Case: Scaling test cases](#todo-test-case-scaling-test-cases) ## Overriew The purpose of this test plan is to test the VLAN function from SAI. @@ -49,46 +59,84 @@ The test will include three parts 3. Composit scenario - VLAN Interface (RIF/SVI) -## Basic Test data and SAI APIs +## Basic Configurations and SAI APIs During testing, we need to use SAI APIs for testing. By using the SAI-PTF structure, we can invoke the SAI with RPC APIs remotely, the sample code is below. + + +### Basic VLAN configuration +|VLAN ID|Ports|Tag mode| +|-|-|-| +|10|Port1-4|Tag| +||Port5-8|Untag| +|100|port9-12|Tag| +||Port13-16|Untag| + ### Create VLAN and VLAN member - Create Vlan 10 ```Python sai_thrift_create_vlan(self.client, vlan_id=10) ``` -- Create Native vlan +- Create Native vlan 10 ```python sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=10) ``` - Create Vlan member and VLAN member with different mode Untag mode and access port ```python + ------------------------ + |VLAN ID|Ports|Tag mode| + |-------|-----|--------| + | 10 |Port1| Tag | + | 10 |Port2| Untag | + ------------------------ + sai_thrift_create_vlan_member( self.client, vlan_id=10, - bridge_port_id=port_bridge_port, + bridge_port_id=port_bridge_port1, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) - ``` - Tag mode and trunk port - ```python + sai_thrift_create_vlan_member( self.client, vlan_id=10, - bridge_port_id=port_bridge_port, + bridge_port_id=port_bridge_port2, vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_TAGGED) ``` + +### Basic Forwarding Table +For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule as below +|Name|MAC|PORT|VLAN| +|-|-|-|-| +|fdb1-4 |mac1-00:11:11:11:11:11 - mac4-00:44:44:44:44:44|Port1-4|10| +|fdb5-8 |mac5-00:55:55:55:55:55 - mac8-00:88:88:88:88:88|Port5-8|10| +|fdb9-12 |mac9-00:99:99:99:99:99 - mac12-01:22:22:22:22:22|Port9-12|100| +|fdb13-16|mac13-01:33:33:33:33:33 - mac16-01:66:66:66:66:66|Port13-16|100| +|fdb17-32|mac17-01:77:77:77:77:77 - mac32-03:22:22:22:22:22|Port17-32|| + + +### Create FDB Entry + - Add static FDB entry in the FDB table - In the code below, we can create FDB entry, and bind the SMAC with a port with a static dfb entry. + In the sample code below, we can see how to create FDB entry. + + This FDB entry is a static entry, it will ``forward`` packet when the packet with a mac1 on port1. ```python + ------------------------------------------ + | MAC |Ports| VLAN | Type | Action | + |-------|-----|----------|---------------- + | mac1 |Port1| vlan_oid |StATIC| FORWARD| + ------------------------------------------ + sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) sai_thrift_create_fdb_entry( self.client, fdb_entry, type=SAI_FDB_ENTRY_TYPE_STATIC, - bridge_port_id=port_bp, + bridge_port_id=Port1, packet_action=SAI_PACKET_ACTION_FORWARD) ``` + - FDB operations Get FDB entries ```python @@ -123,32 +171,253 @@ During testing, we need to use SAI APIs for testing. By using the SAI-PTF struct ip_dst='172.16.0.1', ip_ttl=64) ``` -## Basic Configurations -### Basic VLAN configuration -|VLAN ID|Ports|Tag mode| + +## Tests + +### Test Case: VLAN interface (RIF/SVI) +**Testing Objective** + +When a switch needs to forward in layer3, it needs a VLAN interface in layer3(SVI) for packet routing. + +In this test case, we will test VLAN interface and VLAN function. + +#### Test the configuration +For VLAN interface in layer3(SVI), it can be configured from a config_db.json. This json file, can be generated from a xml config as below. Base on this configuration we can see what the actual configuration will be. + + +```xml + + + + + +``` +Convert to config_db.json +```json + "VLAN": { + "Vlan608": { + "members": [ + "Ethernet6/1", + "Ethernet7/1", + "Ethernet8/1", + ], + "vlanid": "608" + } + }, + "VLAN_INTERFACE": { + "Vlan608": {}, + "Vlan608|10.95.88.209/28": {}, + "Vlan608|2603:10a0:31c:8144::1/64": {} + }, + "VLAN_MEMBER": { + "Vlan608|Ethernet6/1": { + "tagging_mode": "untagged" + }, + "Vlan608|Ethernet7/1": { + "tagging_mode": "untagged" + }, + + "Vlan608|Ethernet8/1": { + "tagging_mode": "untagged" + }, + } +``` +#### Test description +``` +Test example: +Vlan to Port: + pkt(Untag) -> |DUT|Port3(VLAN10:Trunk) -> RIF(VLAN_IF->MAC:IP1) ||| vlan100 || -> Port(Access) -> ... +``` + +#### Route entry + +|DestIp|Next Hop |Next Hop ip|Next Hop Mac| +|-|-|-|-| +|10.10.0.1|vlanInterface(VLAN100)|10.10.10.10(SVI_IP)|PORTMAC| + +- Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) + ```Python + self.vlan100_rif = sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_VLAN, + virtual_router_id=self.default_vrf, + vlan_id=self.vlan100) + + self.nhop1 = sai_thrift_create_next_hop( + self.client, + ip=sai_ipaddress(next_hop_ip), #SVI_IP + router_interface_id=self.vlan100_rif, + type=SAI_NEXT_HOP_TYPE_IP) + self.neighbor_entry1 = sai_thrift_neighbor_entry_t( + rif_id=self.vlan100_rif, + ip_address=sai_ipaddress(next_hop_ip))#SVI_IP + #Nhop to vlan interface + sai_thrift_create_neighbor_entry( + self.client, self.neighbor_entry1, + dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan100 + #Route to vlan interface + self.route_entry1 = sai_thrift_route_entry_t( + vr_id=self.default_vrf, + destination=sai_ipprefix(pkt_dest_ip+'/32')) # Packet dest IP + sai_thrift_create_route_entry( + self.client, self.route_entry1, next_hop_id=self.nhop1) + ``` + +#### VLAN interface input packet + ```Python + simple_tcp_packet( + eth_dst=SVI_MAC, #Forwarding in vlan + eth_src=SRC_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +#### VLAN interface output packet + ```Python + simple_tcp_packet( + eth_dst=PORT_MAC, + eth_src=SVI_MAC, #Switch MAC + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +**Precondition/Setup:** +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. +- Create VLAN Interface for ``VLAN100`` with ``SVI_IP`` +- Create route ``DEST_IP`` and next hop with ``SVI_IP`` and ``PORTAMC`` to ``PORT15``. + +#### Test case +| Goal |Steps/Cases | Expect | |-|-|-| -|10|Port1-4|Tag| -||Port5-8|Untag| -|100|port9-12|Tag| -||Port13-16|Untag| +| Forwarding packet on ``VLAN_INTERFACE`` .| Send ``Untagged`` packet with dest ``SVI_MAC`` on port1. | ``Untagged`` packet received on ``PORT15``.| -### Basic Forwarding Table -For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule as below -|Name|MAC|PORT|VLAN| + + + +### Test Case: VLAN interface (RIF/SVI) +**Testing Objective** + +Test the configuration as below + +```xml + + + + + +``` +Convert to config_db.json +```json + "VLAN": { + "Vlan608": { + "members": [ + "Ethernet6/1", + "Ethernet7/1", + "Ethernet8/1", + ], + "vlanid": "608" + } + }, + "VLAN_INTERFACE": { + "Vlan608": {}, + "Vlan608|10.95.88.209/28": {}, + "Vlan608|2603:10a0:31c:8144::1/64": {} + }, + "VLAN_MEMBER": { + "Vlan608|Ethernet6/1": { + "tagging_mode": "untagged" + }, + "Vlan608|Ethernet7/1": { + "tagging_mode": "untagged" + }, + + "Vlan608|Ethernet8/1": { + "tagging_mode": "untagged" + }, + } +``` + +**Testing Description** + +When a switch needs to forward in layer3, it needs a VLAN interface in layer3(SVI) for packet routing or Trunk connection to other devices/servers. +``` +Test example: +Vlan to Port: + pkt(Untag) -> |DUT|Port3(VLAN10:Trunk) -> RIF(VLAN_IF->MAC:IP1) ||| vlan100 || -> Port(Access) -> ... +``` + +Need the APIs as below + +- Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) + ```Python + self.vlan100_rif = sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_VLAN, + virtual_router_id=self.default_vrf, + vlan_id=self.vlan100) + + self.nhop1 = sai_thrift_create_next_hop( + self.client, + ip=sai_ipaddress(next_hop_ip), #SVI_IP + router_interface_id=self.vlan100_rif, + type=SAI_NEXT_HOP_TYPE_IP) + self.neighbor_entry1 = sai_thrift_neighbor_entry_t( + rif_id=self.vlan100_rif, + ip_address=sai_ipaddress(next_hop_ip))#SVI_IP + #Nhop to vlan interface + sai_thrift_create_neighbor_entry( + self.client, self.neighbor_entry1, + dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan100 + #Route to vlan interface + self.route_entry1 = sai_thrift_route_entry_t( + vr_id=self.default_vrf, + destination=sai_ipprefix(pkt_dest_ip+'/32')) # Packet dest IP + sai_thrift_create_route_entry( + self.client, self.route_entry1, next_hop_id=self.nhop1) + ``` + +#### Route entry +|DestIp|Next Hop |Next Hop ip|Next Hop Mac| |-|-|-|-| -|fdb1-4 |mac1:00:11:11:11:11:11 - mac4:00:44:44:44:44:44|Port1-4|10| -|fdb5-8 |mac5:00:55:55:55:55:55 - mac8:00:88:88:88:88:88|Port5-8|10| -|fdb9-12 |mac9:00:99:99:99:99:99 - mac12:01:22:22:22:22:22|Port9-12|100| -|fdb13-16|mac13:01:33:33:33:33:33 - mac16:01:66:66:66:66:66|Port13-16|100| -|fdb17-32|mac17:01:77:77:77:77:77 - mac32:03:22:22:22:22:22|Port17-32|| +|10.10.0.1|vlanInterface(VLAN100)|10.10.10.10(SVI_IP)|PORTMAC| + +#### VLAN interface to Port +VLAN interface input packet + ```Python + simple_tcp_packet( + eth_dst=SVI_MAC, #Forwarding in vlan + eth_src=SRC_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +VLAN interface output packet + ```Python + simple_tcp_packet( + eth_dst=PORT_MAC, + eth_src=SVI_MAC, #Switch MAC + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +**Precondition/Setup:** +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. +- Create VLAN Interface for ``VLAN100`` with ``SVI_IP`` +- Create route DESTIP:IP1 to ``PORT15`` + +Below is the test for checking this. +| Goal |Steps/Cases | Expect | +|-|-|-| +| Forwarding packet on ``VLAN_INTERFACE`` .| Send ``Untagged`` packet with dest ``SVI_MAC`` on port1. | ``Untagged`` packet received on ``PORT15``.| -## Tests ### Test suite: Tagging and trunk/access -This is a basic set of testing. This test suite will cover the basic VLAN function around tag/untag and trunk/access port. +This is a basic funcation testing. This test suite will cover the basic VLAN function around tag/untag and trunk/access port. -*p.s. Do not take native VLAN in this scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* +*p.s. This test will not check function with native VLAN scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* **Testing Objective** @@ -167,15 +436,15 @@ With a Tagged packet or untagged packet, on the trunk and access port, when ingr **Testing Description** ``` Test example: - DMAC-> |(Trunk:10)->pkt(Tag:10) -1. pkt(tagged:10) ->(trunk:10)|DUT| - DMAC-> |(Acess:10)->pkt(Untag) + DMAC-> |(Trunk:10)->pkt(Tag:10) +1. pkt(tagged:10) -> (trunk:10)|DUT| + DMAC-> |(Acess:10)->pkt(Untag) - DMAC-> |(Trunk:10)->pkt(Tag:10) + DMAC-> |(Trunk:10)->pkt(Tag:10) 2. pkt(tagged:10) -> (access:10)|DUT| - DMAC-> |(Acess:10)->pkt(Untag) + DMAC-> |(Acess:10)->pkt(Untag) -3. pkt(Tagged:20) -> (Trunk:10)|DUT| -> X +3. pkt(Tagged:20) -> (Trunk:10)|DUT| -> DROP ``` Below is the test for checking this. @@ -204,6 +473,7 @@ After saving the mac address to the forwarding table, only unicast will happen w ARP requests and responses will also be covered in this test suite. **Testing Description** + For flooding on the VLAN packet, it should only flood to VLAN members. ``` Test example: @@ -222,13 +492,15 @@ With MAC in CAM Cases: | Goal |Cases | Expect | |-|-|-| -| Flooding to VLAN members. | Send ``VLAN10`` ``tagged`` packet with dest ``mac4`` on ``port1~3``. |``Tagged`` Packets from ``Trunk``, ``Untag`` Packet from ``Access``| -|Unicast on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac1~3`` on ``port4``.| Received ``VLAN10`` ``tagged`` packet on mac matched port.| -|No flooding on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac1~3`` on ``port4``.| No other packet than mac matched port.| +| Flooding to VLAN members. | Every time, send ``VLAN10`` ``tagged`` one packet with dest ``mac4`` for each port in ``port1~3`` with port's mac. |``Tagged`` Packets from ``Trunk``, ``Untag`` Packet from ``Access``| +|Unicast on VLAN port after learning.| Every time, send ``VLAN10`` ``tagged`` one packet for each dest in ``mac1~3`` on ``port4``.| Received ``VLAN10`` ``tagged`` packet on mac matched port.| +|No flooding on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac4`` on ``port1``.| Only one packet received on ``port4``.| +|||No other packets on ``Port1~3``.| |MAC learning.| Use FDB SAI API to check FDB entries.| ``4`` entries should be added, and marked with VLAN id.| #### Access VLAN **Testing Description** + For flooding on the VLAN packet, it should only flood to VLAN members. ``` Test example: @@ -246,9 +518,10 @@ Precondition/Setup: | Goal | Steps | Expect | |-|-|-| -| Flooding to VLAN members. | Send ``Untagged`` packet with dest ``mac5`` on ``port6~8``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| -|Unicast on VLAN port after learning.| Send ``Untagged`` packet with dest ``mac6~8`` on ``port5``.| Received ``Untagged`` packet on mac matched port.| -|No flooding on VLAN port after learning.| Send ``Untagged`` packet with dest ``mac6~8`` on ``port5``.| No other packet than mac matched port.| +| Flooding to VLAN members. | Every time, send ``Tagged`` one packet with dest ``mac5`` for each port in ``port6~8``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| +|Unicast on VLAN port after learning.| Every time, send ``Tagged`` packet for each dest ``mac6~8`` on ``port5``.| Received ``Untagged`` packet on mac matched port.| +|No flooding on VLAN port after learning.| Send ``Tagged`` packet with dest ``mac5`` on ``port6``.| Only one packet received on ``port5``.| +|||No other packets on ``Port1~3``.| |MAC learning.| Use FDB SAI API to check FDB entries.| | 4 entries should be added, and marked with VLAN id.| ### Composit scenario: ARP Flooding and learn @@ -265,18 +538,32 @@ Precondition/Setup: ``` - ARP response ```Python + Untagged: + + simple_arp_packet( + eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + arp_op=2, # ARP response + ip_tgt='10.10.10.1', + ip_snd='10.10.10.2', + hw_snd='00:22:22:22:22:22', + hw_tgt="00:11:11:11:11:11") + Tagged: + simple_arp_packet( eth_dst='00:11:11:11:11:11', eth_src='00:22:22:22:22:22', arp_op=2, # ARP response ip_tgt='10.10.10.1', ip_snd='10.10.10.2', + vlan_vid=10, hw_snd='00:22:22:22:22:22', hw_tgt="00:11:11:11:11:11") ``` + In the ARP scenario, the mac learning process is: 1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff -2. After the encountered device get the ARP packet and sends out a response, the packet will be filled with a source mac, this is the mac we want from step 1. +2. After the encountered device get the ARP packet and sends out a response, the packet will be filled with a source mac, this is the target device mac for the dest IP. 3. Switch received that response, cause the switch learned a MAC on step 1 on the sending port, then it can make a unicast here. **p.s. The test will be ended here, will not test the send from the port in step 1 again, it is already covered in other tests.** @@ -290,7 +577,7 @@ Test example: | pkt(Untag):VLAN10:Access ARP Req pkt(Untag:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 | pkt(Tag):VLAN10:Trunk -2. ARP REsponse +2. ARP Response pkt(access:10)|DUT| <- Forward(FDB:MAC=DMAC) <- VLAN:10:PORT <- RP Resp pkt(tagged:10:DMAC) ``` @@ -307,11 +594,12 @@ Precondition/Setup: ### Test case: Test Frame Filtering **Testing Objective** -The switch will not forward packet source MAC equals to the port's mac in FDB. +Drop packet when packet's dest mac is port mac in MAC table. **Testing Description** -The switch will drop the packet when the packet sends to a dest MAC, but the same dest mac-address already exists in the FDB and is mapping to that port. +Drop packet when packet's dest mac is port mac in MAC table. + ``` Test example: | SRCPORT:MAC1 = DMAC| @@ -322,23 +610,23 @@ Test example: Precondition/Setup: - Create VLAN as the basic configuration. - Create an FDB table as a basic configuration. +- Add a non-existing ``MacX`` to port1 | Goal |Steps | Expect | |-|-|-| -| FDB added.| Add a non-existing ``MacX`` to port1. Check FDB |FDB added.| | Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| | Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| -### Test case: Test native vlan +### Test case: Test native vlan (Optional) **Testing Objective** -For Native VLAN, only consider the ingress direction, the entry condition for VLAN, and the behavior below +Testing native vlan. | Port mode | packet tag mode | Action | | ---------|--------------- | --------------------------------------- | | Access|Tag| Drop, if the native id does not match. | -| Trunk |Untag| Drop, if native VLAN id does not match.. | -| |Tag| Drop, if the VLAN id does not match and does not meet the native VLAN case. | + +*For Native VLAN, only consider the ingress direction* **Testing Description** @@ -349,12 +637,6 @@ Test example: | Y Native VLAN -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT pkt(tagged:10:DMAC) -> (Access:10)|DUT| | N Native VLAN -> Drop - - pkt(untagged:10:DMAC) -> (Trunk:10)|DUT| Native VLAN -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT - - | Y (VLAN||Native VLAN) -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT - pkt(tagged:10:DMAC) -> (Trunk:10)|DUT| - | N (VLAN&Native VLAN) -> Drop ``` **Precondition** - Create VLAN as the basic configuration. @@ -367,48 +649,14 @@ Cases: |-|-|-| | Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| | Drop, ``VLAN40`` ``Tagged`` packet on ``Native`` from a ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | Packet dropped.| -| Forwarding, ``Untagged`` packet on ``Native`` from a ``Trunk``.|Send ``Untagged`` packet with dest ``mac3`` on ``port1``. | ``tagged`` packet received on port3.| ``Untagged`` packet with dest mac3 on port1. | Packet dropped.| -| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Trunk``.|Send ``tagged`` packet with dest ``mac3`` on ``port1``. | ``tagged`` packet received on port3.| -| Drop, ``VLAN40`` ``Tagged`` packet on ``Native`` from a ``Trunk``.|Send ``tagged`` packet with dest ``mac3`` on ``port1``. | Packet dropped.| -## SAI APIs operations - -### Test case: Test VLAN related counters. -**Testing Objective** -For VLAN-related counters, SAI should be able to get the counter and clear them. - -Below is the sample API to operate those data - -Check counters -```Python - stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) - in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] - out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] - in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] - in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] - out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] - out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] - -``` -Clear counters -```Python -sai_thrift_clear_vlan_stats(self.client, self.vlan10) -``` - -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. - -| Goal |Steps/Cases | Expect | -|-|-|-| -| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| -| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| -| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | +## SAI APIs operations ### Test case: Vlan member list. **Testing Objective** + Test VLAN and member list. Sample APIs @@ -443,89 +691,41 @@ Precondition/Setup: | VLAN and its member removed.|Remove the VLAN member from VLAN 10 and remove VLAN. | VLAN and its member removed.| | Error when creating member to un-exist VLAN. |Use the SAI API to create a VLAN member on VLAN 10 | Vlan attribute is 0.| - - -## Test Case: VLAN interface (RIF/SVI) +### Test case: Test VLAN related counters. **Testing Objective** -Test the configuration as below -```xml - - - - - -``` -Convert to config_db.json -```json - "VLAN": { - "Vlan608": { - "members": [ - "Ethernet6/1", - "Ethernet7/1", - "Ethernet8/1", - ], - "vlanid": "608" - } - }, - "VLAN_INTERFACE": { - "Vlan608": {}, - "Vlan608|10.95.88.209/28": {}, - "Vlan608|2603:10a0:31c:8144::1/64": {} - }, - "VLAN_MEMBER": { - "Vlan608|Ethernet6/1": { - "tagging_mode": "untagged" - }, - "Vlan608|Ethernet7/1": { - "tagging_mode": "untagged" - }, +For VLAN-related counters, SAI should be able to get the counter and clear them. - "Vlan608|Ethernet8/1": { - "tagging_mode": "untagged" - }, - } -``` +Below is the sample API to operate those data -Need the APIs as below +Check counters +```Python + stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) + in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] + out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] + in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] + in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] + out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] + out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] -- Create Router Interface for a VLAN interface - ```Python - sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_VLAN, - virtual_router_id=self.default_vrf, - vlan_id=self.vlan10) - ``` -- Create next hop to a IP address '10.10.0.1' and mac - ```python - sai_thrift_create_next_hop( - self.client, - ip=sai_ipaddress('10.10.0.1'), - router_interface_id=self.vlan100_rif, - type=SAI_NEXT_HOP_TYPE_IP) - sai_thrift_create_neighbor_entry( - self.client, self.neighbor_entry1, dst_mac_address=self.dmac1) - sai_thrift_route_entry_t( - vr_id=self.default_vrf, destination=sai_ipprefix('10.10.10.1/32')) - ``` -**Testing Description** -When a switch needs to forward in layer3, it needs a vlan interface in layer3(SVI). By this vlan interface, swtich can forward the packet to other VLAN, which can be on other ports in the same switch or to other server port, that dest port then can accept packet from different ports. ``` -Test example: - -pkt(Tagged:10) -> (Trunk:10)|DUT| -> RIF(VLAN_IF->MAC5:IP1) - PORT <- FDB(PORT:MAC) <-| - OR | -> Server(NHop) +Clear counters +```Python +sai_thrift_clear_vlan_stats(self.client, self.vlan10) ``` -**Precondition/Setup:** +Precondition/Setup: - Create VLAN as the basic configuration. - Create an FDB table as a basic configuration. +- Create VLAN Interface for ``VLAN10`` with ``IP1`` +- Create route DESTIP:IP1 to ``PORT20`` -Below is the test for checking this. -| Goal |Steps/Cases | Expect | +| Goal |Steps/Cases | Expect | |-|-|-| -| Create a VLAN interface. |Create route entry and next hop for VLAN 10, with [IP1] and [mac5].| Vlan interface created.| -| Add FDB entries for RIF. MAC is [mac5], and map it to Port5 in the FDB entry. |Simulate the mac learning.| Set up forwarding table| -| Forwarding from trunk to a trunk port on native VLAN.| Send ``tagged`` packet with dest mac3 on port1. | ``tagged`` packet received on ``port5``.| +| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| +| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| +| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | + + + +## ToDO Test Case: Scaling test cases \ No newline at end of file From cfdd7f4a005fcbda020fd2b29161938578b2f5ef Mon Sep 17 00:00:00 2001 From: zhoudongxu <1315364814@qq.com> Date: Wed, 25 May 2022 16:44:17 -0700 Subject: [PATCH 03/18] Update lag_test_plan.md Signed-off-by: richardyu-ms --- doc/sai-ptf/lag_test_plan.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 85a509c67..2b45c0025 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -4,8 +4,12 @@ - [Test Topology](#test-topology) - [Testbed](#testbed) - [Scope](#scope) -- [Basic Configurations SAI API and sample packets](#basic-configurations-sai-api-and-sample-packets) +- [Basic Configurations, SAI API and sample packets](#basic-configurations-sai-api-and-sample-packets) - [Basic Configurations And SAI API](#basic-configurations-and-sai-api) + - [Basic Portchannel configuration](#basic-portchannel-configuration) + - [Create lag and lag member Using SAI API](#create-lag-and-lag-member-using-sai-api) + - [Basic Route Entry](#basic-route-entry) + - [Create Router Entry Using SAI API](#create-router-entry-using-sai-api) - [Packets](#packets) - [Test suites](#test-suites) - [Test suite #1: PortChannel Loadbalanceing](#test-suite-1-portchannel-loadbalanceing) From 93a6b6606236d7f9d360d505e7994d12382a8977 Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Thu, 26 May 2022 18:30:02 +0000 Subject: [PATCH 04/18] remove cases not related to T0 Signed-off-by: richardyu-ms --- doc/sai-ptf/img/Component_topology.jpg | Bin 39862 -> 0 bytes doc/sai-ptf/img/Device_topology.jpg | Bin 17549 -> 0 bytes doc/sai-ptf/img/SAI_PTF_Topology.jpg | Bin 11474 -> 0 bytes doc/sai-ptf/lag_test_plan.md | 7 +- doc/sai-ptf/vlan_test_plan.md | 263 +++++-------------------- 5 files changed, 46 insertions(+), 224 deletions(-) delete mode 100644 doc/sai-ptf/img/Component_topology.jpg delete mode 100644 doc/sai-ptf/img/Device_topology.jpg delete mode 100644 doc/sai-ptf/img/SAI_PTF_Topology.jpg diff --git a/doc/sai-ptf/img/Component_topology.jpg b/doc/sai-ptf/img/Component_topology.jpg deleted file mode 100644 index a51295929bab78355ba2fe1ec7e657f92932e983..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39862 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 diff --git a/doc/sai-ptf/img/Device_topology.jpg b/doc/sai-ptf/img/Device_topology.jpg deleted file mode 100644 index 77a1d7761d6979788a7243ab961260cdae1a92b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17549 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 l842PV7@W`R-bdn8O~582j!TQ7c - - - - -``` -Convert to config_db.json -```json - "VLAN": { - "Vlan608": { - "members": [ - "Ethernet6/1", - "Ethernet7/1", - "Ethernet8/1", - ], - "vlanid": "608" - } - }, - "VLAN_INTERFACE": { - "Vlan608": {}, - "Vlan608|10.95.88.209/28": {}, - "Vlan608|2603:10a0:31c:8144::1/64": {} - }, - "VLAN_MEMBER": { - "Vlan608|Ethernet6/1": { - "tagging_mode": "untagged" - }, - "Vlan608|Ethernet7/1": { - "tagging_mode": "untagged" - }, - - "Vlan608|Ethernet8/1": { - "tagging_mode": "untagged" - }, - } -``` #### Test description ``` Test example: Vlan to Port: - pkt(Untag) -> |DUT|Port3(VLAN10:Trunk) -> RIF(VLAN_IF->MAC:IP1) ||| vlan100 || -> Port(Access) -> ... + pkt(Untag) -> |DUT|Port3(VLAN1000:Access) -> RIF(VLAN_IF->MAC:IP1) ||| vlan1000 || -> Port(Access) -> ... ``` #### Route entry |DestIp|Next Hop |Next Hop ip|Next Hop Mac| |-|-|-|-| -|10.10.0.1|vlanInterface(VLAN100)|10.10.10.10(SVI_IP)|PORTMAC| +|10.10.0.1|vlanInterface(VLAN100)|192.168.0.1(SVI_IP)|PORTMAC| - Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) ```Python @@ -284,7 +228,7 @@ Vlan to Port: **Precondition/Setup:** - Create VLAN as the basic configuration. - Create an FDB table as a basic configuration. -- Create VLAN Interface for ``VLAN100`` with ``SVI_IP`` +- Create VLAN Interface for ``VLAN1000`` with ``SVI_IP`` - Create route ``DEST_IP`` and next hop with ``SVI_IP`` and ``PORTAMC`` to ``PORT15``. #### Test case @@ -415,36 +359,24 @@ Below is the test for checking this. ### Test suite: Tagging and trunk/access -This is a basic funcation testing. This test suite will cover the basic VLAN function around tag/untag and trunk/access port. +This is a basic funcation testing. This test suite will cover the basic VLAN function around untag and access port. *p.s. This test will not check function with native VLAN scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* **Testing Objective** -With a Tagged packet or untagged packet, on the trunk and access port, when ingress and egress happen, the behavior as below +With a untagged packet, on the access port, when ingress and egress happen, the behavior as below | Port mode | packet tag mode | Direction | Action | | :---------|--------------- | :-------- | :--------------------------------------- | | Access|Untag| Ingress | Accept the packet. | | |Untag | Egress | Untag the packet. | -| |Tag| Ingress | Drop if the native VLAN doesn't match the tag. Accept if the native VLAN matches the tag.| -| |Tag | Egress | Untag the packet. | -| Trunk |Untag| Ingress | Drop if native VLAN doesn't match the tag. Accept if the native VLAN matches the tag. | -| |Untag| Egress | Tag the packet. | -| |Tag| Ingress | Drop, if both VLAN and native VLAN don't match. | -| |Tag| Egress | Tag the packet. | + **Testing Description** ``` Test example: - DMAC-> |(Trunk:10)->pkt(Tag:10) -1. pkt(tagged:10) -> (trunk:10)|DUT| - DMAC-> |(Acess:10)->pkt(Untag) - - DMAC-> |(Trunk:10)->pkt(Tag:10) -2. pkt(tagged:10) -> (access:10)|DUT| - DMAC-> |(Acess:10)->pkt(Untag) - -3. pkt(Tagged:20) -> (Trunk:10)|DUT| -> DROP + +1. pkt(Untag:10) -> (access:10)|DUT|DMAC-> |(Acess:10)->pkt(Untag) ``` Below is the test for checking this. @@ -455,74 +387,7 @@ Precondition/Setup: Cases: | Goal| Cases | Expect | |-|-|-| -|``Tag``:Trunk -> Trunk port.| Send VLAN10 ``tagged`` packet with dest mac4 on port1. | VLAN10 ``tagged`` packet received on port4.| -|``Tag``:Trunk -> Acess port.| Send VLAN10 ``tagged`` packet with dest mac5 on port1. | ``Untag`` packet received on port5.| -|``Tag``:Acess -> Trunk port.| Send VLAN10 ``tagged`` packet with dest mac4 on port6. | VLAN10 ``tagged`` packet received on port4.| -|``Tag``:Acess -> Acess port.| Send VLAN10 ``tagged`` packet with dest mac5 on port6. | ``Untag`` packet received on port4.| -|Drop: Unmatched ``Tag`` on the trunk.| Send VLAN10 ``tagged`` packet with dest mac4 on port1. | Drop.| - -### Test suite: Flooding and learning - -#### Trunk VLAN -Those tests will verify flooding and learning for VLAN. - -VLANs divide the broadcast domains into multicast domains. When flooding a VLAN packet, the broadcast should only happen within a target VLAN. - -After saving the mac address to the forwarding table, only unicast will happen with the target mac. - -ARP requests and responses will also be covered in this test suite. - -**Testing Description** - -For flooding on the VLAN packet, it should only flood to VLAN members. -``` -Test example: -Without DMAC in CAM - | pkt(Untag):VLAN10:access - pkt(tagged:10:DMAC) -> (trunk:10)|DUT| -> Flooding -> VLAN:10 - | pkt(Tag):VLAN10:Trunk -With MAC in CAM - pkt(tagged:10:DMAC) -> (trunk:10)|DUT| -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT -``` -**Precondition** -- Create VLAN as the basic configuration. - -*Need to loop on all the trunk ports.* - -Cases: -| Goal |Cases | Expect | -|-|-|-| -| Flooding to VLAN members. | Every time, send ``VLAN10`` ``tagged`` one packet with dest ``mac4`` for each port in ``port1~3`` with port's mac. |``Tagged`` Packets from ``Trunk``, ``Untag`` Packet from ``Access``| -|Unicast on VLAN port after learning.| Every time, send ``VLAN10`` ``tagged`` one packet for each dest in ``mac1~3`` on ``port4``.| Received ``VLAN10`` ``tagged`` packet on mac matched port.| -|No flooding on VLAN port after learning.| Send ``VLAN10`` ``tagged`` packet with dest ``mac4`` on ``port1``.| Only one packet received on ``port4``.| -|||No other packets on ``Port1~3``.| -|MAC learning.| Use FDB SAI API to check FDB entries.| ``4`` entries should be added, and marked with VLAN id.| - -#### Access VLAN -**Testing Description** - -For flooding on the VLAN packet, it should only flood to VLAN members. -``` -Test example: -Without DMAC in CAM - | pkt(Untag):VLAN10:Access - pkt(tagged:10:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 - | pkt(Tag):VLAN10:Trunk -With MAC in CAM - pkt(tagged:10:DMAC) -> (access:10)|DUT| -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT -``` -Precondition/Setup: -- Create VLAN as the basic configuration. - -*Need to loop on all the trunk ports.* - -| Goal | Steps | Expect | -|-|-|-| -| Flooding to VLAN members. | Every time, send ``Tagged`` one packet with dest ``mac5`` for each port in ``port6~8``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| -|Unicast on VLAN port after learning.| Every time, send ``Tagged`` packet for each dest ``mac6~8`` on ``port5``.| Received ``Untagged`` packet on mac matched port.| -|No flooding on VLAN port after learning.| Send ``Tagged`` packet with dest ``mac5`` on ``port6``.| Only one packet received on ``port5``.| -|||No other packets on ``Port1~3``.| -|MAC learning.| Use FDB SAI API to check FDB entries.| | 4 entries should be added, and marked with VLAN id.| +|``Untag``:Acess -> Acess port.| Send VLAN100 ``Untagged`` packet with dest mac5 on port6. | ``Untag`` packet received on port4.| ### Composit scenario: ARP Flooding and learn - ARP request @@ -556,7 +421,7 @@ Precondition/Setup: arp_op=2, # ARP response ip_tgt='10.10.10.1', ip_snd='10.10.10.2', - vlan_vid=10, + vlan_vid=1000, hw_snd='00:22:22:22:22:22', hw_tgt="00:11:11:11:11:11") ``` @@ -574,11 +439,11 @@ Testing ARP scernairo ``` Test example: 1. ARP Request - | pkt(Untag):VLAN10:Access - ARP Req pkt(Untag:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 - | pkt(Tag):VLAN10:Trunk + + ARP Req pkt(Untag:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 -> pkt(Untag):VLAN10:Access + 2. ARP Response - pkt(access:10)|DUT| <- Forward(FDB:MAC=DMAC) <- VLAN:10:PORT <- RP Resp pkt(tagged:10:DMAC) + pkt(access:10)|DUT| <- Forward(FDB:MAC=DMAC) <- VLAN:10:PORT <- RP Resp pkt(Untag:10:DMAC) ``` Precondition/Setup: @@ -586,8 +451,8 @@ Precondition/Setup: | Goal | Steps | Expect | |-|-|-| -| ARP Request flooding to all ports. | Send ``Untagged`` ARP packet with dest ``mac4`` on ``port1``. |``Tagged`` Packets from ``Trunk``, ``Untagged`` Packet from ``Access``| -| Mac learned from ARP request and ARP response.| Send a ``tagged`` ARP response packet with src:mac4, dest:mac1 to port4 and check the FDB entries.|Unicast happened.| +| ARP Request flooding to all ports. | Send ``Untagged`` ARP packet with dest ``mac4`` on ``port1``. |``Untagged`` Packets from ``Access``, ``Untagged`` Packet from ``Access``| +| Mac learned from ARP request and ARP response.| Send a ``Untagged`` ARP response packet with src:mac4, dest:mac1 to port4 and check the FDB entries.|Unicast happened.| | FDB entries added.| Call API to check the FDB entries.|New mac entries in CAM.| @@ -603,7 +468,7 @@ Drop packet when packet's dest mac is port mac in MAC table. ``` Test example: | SRCPORT:MAC1 = DMAC| - pkt(Untag:DMAC):vlan:10 -> SRCPORT(Trunk:10) -> |DUT| -> |FDB| | -> X + pkt(Untag:DMAC):vlan:10 -> SRCPORT(Access:10) -> |DUT| -> |FDB| | -> X | MAC2 | ``` @@ -614,42 +479,8 @@ Precondition/Setup: | Goal |Steps | Expect | |-|-|-| -| Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| -| Filter frame. | Send VLAN10 ``tagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| - -### Test case: Test native vlan (Optional) - -**Testing Objective** - -Testing native vlan. -| Port mode | packet tag mode | Action | -| ---------|--------------- | --------------------------------------- | -| Access|Tag| Drop, if the native id does not match. | - -*For Native VLAN, only consider the ingress direction* - -**Testing Description** - -Test for native VLAN -*Only Consider the ingress direction* -``` -Test example: - | Y Native VLAN -> Forward(FDB:MAC=DMAC) -> VLAN:10:PORT - pkt(tagged:10:DMAC) -> (Access:10)|DUT| - | N Native VLAN -> Drop -``` -**Precondition** -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. - -*Need to loop on all the access and trunk ports.* - -Cases: -| Goal |Cases | Expect | -|-|-|-| -| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| -| Drop, ``VLAN40`` ``Tagged`` packet on ``Native`` from a ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | Packet dropped.| - +| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| +| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| ## SAI APIs operations @@ -671,13 +502,13 @@ Get VLAN member list nagtive test ```python vlan_attr = sai_thrift_get_vlan_attribute( - self.client, vlan_oid=11, learn_disable=True) + self.client, vlan_oid=1000, learn_disable=True) incorrect_member = sai_thrift_create_vlan_member( self.client, - vlan_id=11, + vlan_id=1000, bridge_port_id=self.port27_bp, - vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_TAGGED) + vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) ``` Precondition/Setup: @@ -722,10 +553,6 @@ Precondition/Setup: | Goal |Steps/Cases | Expect | |-|-|-| -| Forwarding, ``VLAN10`` ``Tagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``tagged`` packet with dest ``mac3`` on ``port5``. | ``tagged`` packet received on port3.| +| Forwarding, ``VLAN10`` ``Untagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``Untagged`` packet with dest ``mac3`` on ``port5``. | ``Untagged`` packet received on port3.| | Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| | Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | - - - -## ToDO Test Case: Scaling test cases \ No newline at end of file From 525e2b3fbb2edbeb2557b0890da442a82ba5422c Mon Sep 17 00:00:00 2001 From: zhoudongxu <1315364814@qq.com> Date: Thu, 26 May 2022 15:59:38 -0700 Subject: [PATCH 05/18] Update lag_test_plan.md Signed-off-by: richardyu-ms --- doc/sai-ptf/lag_test_plan.md | 70 +++++----- doc/sai-ptf/vlan_test_plan.md | 238 +++++++++++----------------------- 2 files changed, 108 insertions(+), 200 deletions(-) diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 207a8cfe0..565860805 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -13,8 +13,8 @@ - [Packets](#packets) - [Test suites](#test-suites) - [Test suite #1: PortChannel Loadbalanceing](#test-suite-1-portchannel-loadbalanceing) - - [Test suite #2: Ingress/Egreee disable](#test-suite-2-ingressegreee-disable) - - [Test suite #3: Remove Lag member](#test-suite-3-remove-lag-member) + - [Test suite #2: Remove Lag member](#test-suite-2-remove-lag-member) + - [Test suite #3: Ingress/Egreee disable](#test-suite-3-ingressegreee-disable) ## Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -109,14 +109,17 @@ For load balancing, expecting the ports in a lag should receive the packet equal Even after removing and disabling the port in a lag. -Sample APIS -Disbale egress -```Python -sai_thrift_set_lag_member_attribute( - self.client, - self.lag3_member14, - ingress_disable=True, - egress_disable=True) +Sample SAI API +```python + + #How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag) + self.packet_numbers =100 + for i in range(0, n): + self.assertTrue((count[i] >= ((self.packet_numbers / n) * 0.7)), + + #Send packet from dev_port11 + send_packet(self, self.dev_port11, pkt) + ``` | Goal| Steps/Cases | Expect | @@ -127,50 +130,35 @@ sai_thrift_set_lag_member_attribute( | Packet forwards on available ports equally.| Every time, enable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| | Packet forwards on available ports equally.| Every time, remove one lag member, then send packet | Loadbalance on lag members.| -## Test suite #2: Ingress/Egreee disable -For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. +## Test suite #2: Remove Lag member +Test verifies the LAG load balancing for scenario when LAG members are removed. Sample APIs -Ingress/Egreee disable +Remove Lag member ```python - status = sai_thrift_set_lag_member_attribute( - self.client, - self.lag3_member14, - ingress_disable=True, - egress_disable=True) - -``` - -lag port list -```Python -sai_thrift_get_lag_attribute( - self.client, self.lag3, port_list=portlist) + print("Remove LAG member 16") + status = sai_thrift_remove_lag_member(self.client, self.lag3_member16) ``` - | Goal | Steps/Cases | Expect | |-|-|-| -|Packet dropped on port14| Disable egress and ingress on lag member14. send packet | Packet drop.| +|Remove port16 and forwarding packet from port1 to port14,15|Remove port16 form Lag3 and Send packet on dev_port11 to lag3 100 times| Port14 and port15 will receive an equal number of packets.| -## Test suite #3: Remove Lag member -Test verifies the LAG load balancing for scenario when LAG members are removed. -Sample APIs +## Test suite #3: Ingress/Egreee disable +For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. -Remove Lag member -```python - print("Remove LAG member 16") - status = sai_thrift_remove_lag_member(self.client, self.lag3_member16) +Sample APIs -``` -How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag), +Ingress/Egreee disable ```python - self.max_itrs =100 - for i in range(0, n): - self.assertTrue((count[i] >= ((self.max_itrs / n) * 0.7)), + status = sai_thrift_set_lag_member_attribute( + self.client, + self.lag3_member14, + ingress_disable=True, + egress_disable=True) ``` | Goal | Steps/Cases | Expect | |-|-|-| -|Remove port16 and forwarding packet from port1 to port14,15|Remove port16 form Lag3 and Send packet on dev_port11 to lag3 100 times| Port14 and port15 will receive an equal number of packets.| - +|Packet dropped on port14| Disable egress and ingress on lag member14. send packet | Packet drop.| diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 42cb13325..b7c907a29 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -4,25 +4,23 @@ - [Testbed](#testbed) - [Scope](#scope) - [Basic Configurations and SAI APIs](#basic-configurations-and-sai-apis) + - [Testbed stablization and impact](#testbed-stablization-and-impact) - [Basic VLAN configuration](#basic-vlan-configuration) - [Create VLAN and VLAN member](#create-vlan-and-vlan-member) - [Basic Forwarding Table](#basic-forwarding-table) - [Create FDB Entry](#create-fdb-entry) - [Packet example](#packet-example) - [Tests](#tests) - - [Test Case: VLAN interface (RIF/SVI)](#test-case-vlan-interface-rifsvi) + - [Test Case: VLAN-Interface (SVI)](#test-case-vlan-interface-svi) - [Test the configuration](#test-the-configuration) - [Test description](#test-description) - [Route entry](#route-entry) - [VLAN interface input packet](#vlan-interface-input-packet) - [VLAN interface output packet](#vlan-interface-output-packet) - [Test case](#test-case) - - [Test Case: VLAN interface (RIF/SVI)](#test-case-vlan-interface-rifsvi-1) - - [Route entry](#route-entry-1) - - [VLAN interface to Port](#vlan-interface-to-port) - - [Test suite: Tagging and trunk/access](#test-suite-tagging-and-trunkaccess) + - [Test suite: Basic function - Untagging and access](#test-suite-basic-function---untagging-and-access) + - [Test case: Basic function - Test Frame Filtering](#test-case-basic-function---test-frame-filtering) - [Composit scenario: ARP Flooding and learn](#composit-scenario-arp-flooding-and-learn) - - [Test case: Test Frame Filtering](#test-case-test-frame-filtering) - [SAI APIs operations](#sai-apis-operations) - [Test case: Vlan member list.](#test-case-vlan-member-list) - [Test case: Test VLAN related counters.](#test-case-test-vlan-related-counters) @@ -50,16 +48,18 @@ The test will include three parts ## Basic Configurations and SAI APIs During testing, we need to use SAI APIs for testing. By using the SAI-PTF structure, we can invoke the SAI with RPC APIs remotely, the sample code is below. +### Testbed stablization and impact +Cause the test bed might also encounter some issue, like the host interface is down. +Before run the actual test there will be need some sanity test to check the DUT status, and select the active ports for testing. -*P.S. All the tests are target on T0 scenario.* ### Basic VLAN configuration |VLAN ID|Ports|Tag mode|HostIf |-|-|-|-| -|1000|Port1-25|Untag|Ethernet4-96| +|1000|Port1-24|Untag|Ethernet4-96| |VLAN connection|Ports|Tag mode| |-|-|-| -|1000|Port1-25|Untag| +|1000|Port1-24|Untag| ### Create VLAN and VLAN member - Create Vlan 1000 @@ -73,11 +73,11 @@ During testing, we need to use SAI APIs for testing. By using the SAI-PTF struct - Create Vlan member and VLAN member with different mode Untag mode and access port ```python - ------------------------ - |VLAN ID|Ports|Tag mode| - |-------|-----|--------| - | 1000 |Port1| Untag | - ------------------------ + ---------------------------------- + |VLAN ID|Ports|Tag mode| HostIf | + |-------|-----|--------|---------| + | 1000 |Port1| Untag |Ethernet4| + ---------------------------------- sai_thrift_create_vlan_member( self.client, @@ -89,10 +89,12 @@ During testing, we need to use SAI APIs for testing. By using the SAI-PTF struct ### Basic Forwarding Table For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule as below -|Name|MAC|PORT|VLAN| -|-|-|-|-| -|fdb1-25 |mac1-00:11:11:11:11:11 - mac25-03:55:55:55:55:55|Port1-25|1000| -|fdb26-32|mac17-02:66:66:66:66:66 - mac32-03:22:22:22:22:22|Port26-32|| +|Name|MAC|PORT|VLAN|HostIf| +|-|-|-|-|-| +|fdb0|mac0-00:00:00:00:00:11|Port0||Ethernet0| +|fdb1-24 |mac1-00:11:11:11:11:11 - mac24-02:55:55:55:55:55|Port1-24|1000|Ethernet4-Ethernet96| +|fdb25-32|mac25-02:55:55:55:55:55 - mac31-03:11:11:11:11:11|Port25-32||Ethernet100-Ethernet128| + ### Create FDB Entry @@ -103,11 +105,11 @@ For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule a This FDB entry is a static entry, it will ``forward`` packet when the packet with a mac1 on port1. ```python - ------------------------------------------ - | MAC |Ports| VLAN | Type | Action | - |-------|-----|----------|---------------- - | mac1 |Port1| vlan_oid |STATIC| FORWARD| - ------------------------------------------ + ---------------------------------------------------- + | MAC |Ports| VLAN | Type | Action | HostIf | + |-------|-----|----------|-------------------------- + | mac1 |Port1| vlan_oid |STATIC| FORWARD|Ethernet4| + ---------------------------------------------------- sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) sai_thrift_create_fdb_entry( @@ -156,96 +158,19 @@ For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule a ## Tests -### Test Case: VLAN interface (RIF/SVI) +### Test Case: VLAN-Interface (SVI) **Testing Objective** -When a switch needs to forward in layer3, it needs a VLAN interface in layer3(SVI) for packet routing. - -In this test case, we will test VLAN interface and VLAN function. +Testing L3 switch, VLAN-Interface(SVI) in layer3 for packet routing. +In this case, it will cover the scenarios like +- Server to T1 +- Server to Server #### Test the configuration -For VLAN interface in layer3(SVI), it can be configured from a config_db.json. This json file, can be generated from a xml config as below. Base on this configuration we can see what the actual configuration will be. - -#### Test description -``` -Test example: -Vlan to Port: - pkt(Untag) -> |DUT|Port3(VLAN1000:Access) -> RIF(VLAN_IF->MAC:IP1) ||| vlan1000 || -> Port(Access) -> ... -``` - -#### Route entry - -|DestIp|Next Hop |Next Hop ip|Next Hop Mac| -|-|-|-|-| -|10.10.0.1|vlanInterface(VLAN100)|192.168.0.1(SVI_IP)|PORTMAC| - -- Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) - ```Python - self.vlan100_rif = sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_VLAN, - virtual_router_id=self.default_vrf, - vlan_id=self.vlan100) - - self.nhop1 = sai_thrift_create_next_hop( - self.client, - ip=sai_ipaddress(next_hop_ip), #SVI_IP - router_interface_id=self.vlan100_rif, - type=SAI_NEXT_HOP_TYPE_IP) - self.neighbor_entry1 = sai_thrift_neighbor_entry_t( - rif_id=self.vlan100_rif, - ip_address=sai_ipaddress(next_hop_ip))#SVI_IP - #Nhop to vlan interface - sai_thrift_create_neighbor_entry( - self.client, self.neighbor_entry1, - dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan100 - #Route to vlan interface - self.route_entry1 = sai_thrift_route_entry_t( - vr_id=self.default_vrf, - destination=sai_ipprefix(pkt_dest_ip+'/32')) # Packet dest IP - sai_thrift_create_route_entry( - self.client, self.route_entry1, next_hop_id=self.nhop1) - ``` - -#### VLAN interface input packet - ```Python - simple_tcp_packet( - eth_dst=SVI_MAC, #Forwarding in vlan - eth_src=SRC_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` - -#### VLAN interface output packet - ```Python - simple_tcp_packet( - eth_dst=PORT_MAC, - eth_src=SVI_MAC, #Switch MAC - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` - -**Precondition/Setup:** -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. -- Create VLAN Interface for ``VLAN1000`` with ``SVI_IP`` -- Create route ``DEST_IP`` and next hop with ``SVI_IP`` and ``PORTAMC`` to ``PORT15``. - -#### Test case -| Goal |Steps/Cases | Expect | -|-|-|-| -| Forwarding packet on ``VLAN_INTERFACE`` .| Send ``Untagged`` packet with dest ``SVI_MAC`` on port1. | ``Untagged`` packet received on ``PORT15``.| - - - - -### Test Case: VLAN interface (RIF/SVI) -**Testing Objective** - -Test the configuration as below +For VLAN-Interface(SVI), it can be configured from a config_db.json. This json file, can be generated from a xml config as below. Base on this configuration we can see what the actual configuration will be. ```xml - + @@ -275,23 +200,28 @@ Convert to config_db.json "Vlan608|Ethernet7/1": { "tagging_mode": "untagged" }, - "Vlan608|Ethernet8/1": { "tagging_mode": "untagged" }, } ``` -**Testing Description** - -When a switch needs to forward in layer3, it needs a VLAN interface in layer3(SVI) for packet routing or Trunk connection to other devices/servers. +#### Test description ``` Test example: Vlan to Port: - pkt(Untag) -> |DUT|Port3(VLAN10:Trunk) -> RIF(VLAN_IF->MAC:IP1) ||| vlan100 || -> Port(Access) -> ... +Server To Server + pkt(From Server) -> |DUT|Ethernet -> SVI(VLAN_IF->MAC:IP1) ||| vlan1000 || -> Ethernet(T1) -> ... + +Server to T1 + pkt(From Server) -> |DUT|Ethernet -> SVI(VLAN_IF->MAC:IP2) ||| vlan1000 || -> Ethernet(Server) -> ... ``` -Need the APIs as below +#### Route entry + +|DestIp|Next Hop |Next Hop ip|Next Hop Mac| +|-|-|-|-| +|192.168.0.1|vlanInterface(VLAN1000)|192.168.1.1(SVI_IP)|PORTMAC| - Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) ```Python @@ -299,7 +229,7 @@ Need the APIs as below self.client, type=SAI_ROUTER_INTERFACE_TYPE_VLAN, virtual_router_id=self.default_vrf, - vlan_id=self.vlan100) + vlan_id=self.vlan1000) self.nhop1 = sai_thrift_create_next_hop( self.client, @@ -307,12 +237,12 @@ Need the APIs as below router_interface_id=self.vlan100_rif, type=SAI_NEXT_HOP_TYPE_IP) self.neighbor_entry1 = sai_thrift_neighbor_entry_t( - rif_id=self.vlan100_rif, + rif_id=self.vlan1000_rif, ip_address=sai_ipaddress(next_hop_ip))#SVI_IP #Nhop to vlan interface sai_thrift_create_neighbor_entry( self.client, self.neighbor_entry1, - dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan100 + dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan1000 #Route to vlan interface self.route_entry1 = sai_thrift_route_entry_t( vr_id=self.default_vrf, @@ -321,22 +251,16 @@ Need the APIs as below self.client, self.route_entry1, next_hop_id=self.nhop1) ``` -#### Route entry -|DestIp|Next Hop |Next Hop ip|Next Hop Mac| -|-|-|-|-| -|10.10.0.1|vlanInterface(VLAN100)|10.10.10.10(SVI_IP)|PORTMAC| - -#### VLAN interface to Port -VLAN interface input packet +#### VLAN interface input packet ```Python simple_tcp_packet( - eth_dst=SVI_MAC, #Forwarding in vlan + eth_dst=SVI_MAC, eth_src=SRC_MAC, ip_dst=DEST_IP, ip_src=SRC_IP) ``` -VLAN interface output packet +#### VLAN interface output packet ```Python simple_tcp_packet( eth_dst=PORT_MAC, @@ -348,16 +272,16 @@ VLAN interface output packet **Precondition/Setup:** - Create VLAN as the basic configuration. - Create an FDB table as a basic configuration. -- Create VLAN Interface for ``VLAN100`` with ``SVI_IP`` -- Create route DESTIP:IP1 to ``PORT15`` +- Create VLAN Interface for ``VLAN1000`` with ``SVI_IP`` +- Create route ``DEST_IP`` and next hop with ``SVI_IP`` and ``PORTAMC`` to ``PORT15``. -Below is the test for checking this. +#### Test case | Goal |Steps/Cases | Expect | |-|-|-| | Forwarding packet on ``VLAN_INTERFACE`` .| Send ``Untagged`` packet with dest ``SVI_MAC`` on port1. | ``Untagged`` packet received on ``PORT15``.| -### Test suite: Tagging and trunk/access +### Test suite: Basic function - Untagging and access This is a basic funcation testing. This test suite will cover the basic VLAN function around untag and access port. @@ -389,6 +313,32 @@ Cases: |-|-|-| |``Untag``:Acess -> Acess port.| Send VLAN100 ``Untagged`` packet with dest mac5 on port6. | ``Untag`` packet received on port4.| +### Test case: Basic function - Test Frame Filtering +**Testing Objective** + +Drop packet when packet's dest mac is port mac in MAC table. + +**Testing Description** + +Drop packet when packet's dest mac is port mac in MAC table. + +``` +Test example: + | SRCPORT:MAC1 = DMAC| + pkt(Untag:DMAC):vlan:10 -> SRCPORT(Access:10) -> |DUT| -> |FDB| | -> X + | MAC2 | + +``` +Precondition/Setup: +- Create VLAN as the basic configuration. +- Create an FDB table as a basic configuration. +- Add a non-existing ``MacX`` to port1 + +| Goal |Steps | Expect | +|-|-|-| +| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| +| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| + ### Composit scenario: ARP Flooding and learn - ARP request ```Python @@ -455,34 +405,6 @@ Precondition/Setup: | Mac learned from ARP request and ARP response.| Send a ``Untagged`` ARP response packet with src:mac4, dest:mac1 to port4 and check the FDB entries.|Unicast happened.| | FDB entries added.| Call API to check the FDB entries.|New mac entries in CAM.| - -### Test case: Test Frame Filtering -**Testing Objective** - -Drop packet when packet's dest mac is port mac in MAC table. - -**Testing Description** - -Drop packet when packet's dest mac is port mac in MAC table. - -``` -Test example: - | SRCPORT:MAC1 = DMAC| - pkt(Untag:DMAC):vlan:10 -> SRCPORT(Access:10) -> |DUT| -> |FDB| | -> X - | MAC2 | - -``` -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. -- Add a non-existing ``MacX`` to port1 - -| Goal |Steps | Expect | -|-|-|-| -| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| -| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| - - ## SAI APIs operations ### Test case: Vlan member list. @@ -548,8 +470,6 @@ sai_thrift_clear_vlan_stats(self.client, self.vlan10) Precondition/Setup: - Create VLAN as the basic configuration. - Create an FDB table as a basic configuration. -- Create VLAN Interface for ``VLAN10`` with ``IP1`` -- Create route DESTIP:IP1 to ``PORT20`` | Goal |Steps/Cases | Expect | |-|-|-| From 70a140044e269526b3b4ce0b539547afe3b3925a Mon Sep 17 00:00:00 2001 From: richardyu Date: Wed, 1 Jun 2022 02:24:52 +0000 Subject: [PATCH 06/18] Add VLAN and Lag test plan and put topo config in seperated files Signed-off-by: richardyu --- doc/sai-ptf/config_data/LAG_config_t0.md | 158 +++++ doc/sai-ptf/config_data/fdb_config_t0.md | 79 +++ doc/sai-ptf/config_data/route_config_t0.md | 148 +++++ doc/sai-ptf/config_data/vlan_config_t0.md | 187 ++++++ doc/sai-ptf/lag_test_plan.md | 201 +++--- doc/sai-ptf/vlan_test_plan.md | 684 +++++++++------------ 6 files changed, 921 insertions(+), 536 deletions(-) create mode 100644 doc/sai-ptf/config_data/LAG_config_t0.md create mode 100644 doc/sai-ptf/config_data/fdb_config_t0.md create mode 100644 doc/sai-ptf/config_data/route_config_t0.md create mode 100644 doc/sai-ptf/config_data/vlan_config_t0.md diff --git a/doc/sai-ptf/config_data/LAG_config_t0.md b/doc/sai-ptf/config_data/LAG_config_t0.md new file mode 100644 index 000000000..de9d77865 --- /dev/null +++ b/doc/sai-ptf/config_data/LAG_config_t0.md @@ -0,0 +1,158 @@ +# Sample T0 Configurations and data for VLAN +- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) + - [Overriew](#overriew) + - [LAG configuration](#lag-configuration) + - [LAG and lag members](#lag-and-lag-members) + - [APIs for LAG configuration](#apis-for-lag-configuration) + - [Create lag and its member](#create-lag-and-its-member) + - [Check LoadBalance](#check-loadBalance) + - [Remove Lag member](#remove-lag-member) + - [Ingress Egreee disable](#ingress-egreee-disable) + - [Sample data/packet](#sample-datapacket) + - [Packet example](#packet-example) + - [config data](#config-data) +## Overriew +This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. + +**Note: This configuration focused on T0 topology.** + +## LAG configuration + +### LAG and LAG members + +|HostIf|VLAN ID|Ports| +|-|-|-| +|Ethernet76-80|lag1|Port17-18| +|Ethernet84-88|lag2|Port19-20| +|Ethernet92-96|lag3|Port21-22| + +## APIs for LAG configuration +APIs relate to LAG and LAG attributes. + +### Create lag and its member +```Python + +------------+------------+-----------+-----------+ + | lag1 | -- | port1 | -- | + | lag1_rif | | port2 | | + | | | | | + +------------+------------+-----------+-----------+ + sai_thrift_create_lag(self.client) + + self.lag1_member1 = sai_thrift_create_lag_member( + self.client, lag_id=self.lag1, port_id=self.port17) + self.lag1_membe2 = sai_thrift_create_lag_member( + self.client, lag_id=self.lag1, port_id=self.port18) + + + self.lag1_rif = sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_PORT, + virtual_router_id=self.default_vrf, + port_id=self.lag1) + +``` +### Check LoadBalance + +```python + + #How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag) + self.packet_numbers =100 + for i in range(0, n): + self.assertTrue((count[i] >= ((self.packet_numbers / n) * 0.7)), + + +``` +### Remove Lag member + +```python + print("Remove LAG2 member 2") + status = sai_thrift_remove_lag_member(self.client, self.lag2_member2) +``` + +### Ingress Egreee disable +```python + status = sai_thrift_set_lag_member_attribute( + self.client, + self.lag3_member2, + ingress_disable=True, + egress_disable=True) + +``` + +## Sample data/packet + +### Packet example +- Input packet +```Python + pkt = simple_tcp_packet( + eth_dst=ROUTER_MAC, + eth_src=srcmac, + ip_dst=dstip, + ip_src=srcip) + + +``` + +- Output packet + ```Python + exp_pkt = simple_tcp_packet( + eth_dst=dstmac, + eth_src=ROUTER_MAC, + ip_dst=dstip, + ip_src=srcip) + ``` + +## config data + +Below is the sample config data in config_db.json + +```JSON + "PORTCHANNEL": { + "PortChannel1": { + "admin_status": "up", + "members": [ + "Ethernet76", + "Ethernet80" + ], + "min_links": "1", + "mtu": "9100" + }, + "PortChannel2": { + "admin_status": "up", + "members": [ + "Ethernet84", + "Ethernet188" + ], + "min_links": "1", + "mtu": "9100" + }, + "PortChannel3": { + "admin_status": "up", + "members": [ + "Ethernet92", + "Ethernet96" + ], + "min_links": "1", + "mtu": "9100" + }, +}, +"PORTCHANNEL_INTERFACE": { + "PortChannel1": {}, + "PortChannel1|10.10.192.19/31": {}, + "PortChannel1|2603:10b0:31f:278::2a/126": {}, + "PortChannel2": {}, + "PortChannel2|10.10.193.19/31": {}, + "PortChannel2|2603:10b0:31f:279::2a/126": {}, + "PortChannel3": {}, + "PortChannel3|10.10.194.19/31": {} + "PortChannel3|2603:10b0:31f:27a::2a/126": {}, +}, +"PORTCHANNEL_MEMBER": { + "PortChannel1|Ethernet76": {}, + "PortChannel1|Ethernet80": {}, + "PortChannel2|Ethernet84": {}, + "PortChannel2|Ethernet88": {}, + "PortChannel3|Ethernet92": {}, + "PortChannel3|Ethernet96": {}, +}, +``` diff --git a/doc/sai-ptf/config_data/fdb_config_t0.md b/doc/sai-ptf/config_data/fdb_config_t0.md new file mode 100644 index 000000000..d6e6ad126 --- /dev/null +++ b/doc/sai-ptf/config_data/fdb_config_t0.md @@ -0,0 +1,79 @@ +# Sample T0 Configurations and data for FDB +- [Sample T0 Configurations and data for FDB](#sample-t0-configurations-and-data-for-fdb) + - [Overriew](#overriew) + - [FDB Configuration](#fdb-configuration) + - [MAC Table](#mac-table) + - [APIs for FDB configuration](#apis-for-fdb-configuration) + - [Create FDB Entries](#create-fdb-entries) + - [Get FDB entties](#get-fdb-entties) + - [Clear FDB entries in a VLAN](#clear-fdb-entries-in-a-vlan) +## Overriew +This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around FDB testing. +**Note: This configuration focused on T0 topology.** + +## FDB Configuration +### MAC Table +The MAC Table for VLAN L2 forwarding as below +|Name|MAC|PORT|VLAN|HostIf| +|-|-|-|-|-| +|mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| +|mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| +|mac9-16 |00:99:99:99:99:99 - 01:66:66:66:66:66|Port9-16|2000|Ethernet36-Ethernet64| +|mac17-mac31 |01:77:77:77:77:77 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| + + +## APIs for FDB configuration +APIs relate to FDB and FDB attributes. + +**P.S. There are just some sample APIs, for more attributes please refer to https://github.com/richardyu-ms/SAI/blob/support_ptf_sai_build/inc/saifdb.h** + +### Create FDB Entries + +- Add static FDB entry in the FDB table + + In the sample code below, we can see how to create an FDB entry. + + This FDB entry is a static entry, it will ``forward`` packet when the packet is with a mac1 on port1. + ```python + + sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1) + sai_thrift_create_fdb_entry( + self.client, + fdb_entry, + type=SAI_FDB_ENTRY_TYPE_STATIC, + bridge_port_id=Port1, + packet_action=SAI_PACKET_ACTION_FORWARD) + ``` + +- Add static FDB entry with **VLAN ID** in the FDB table + + In the sample code below, we can see how to create an FDB entry. + + This FDB entry is a static entry, it will ``forward`` packet when the packet is with a mac1 on port1. + ```python + + sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) + sai_thrift_create_fdb_entry( + self.client, + fdb_entry, + type=SAI_FDB_ENTRY_TYPE_STATIC, + bridge_port_id=Port1, + packet_action=SAI_PACKET_ACTION_FORWARD) + ``` + +### Get FDB entties + ```python + attr = sai_thrift_get_switch_attribute( + self.client, available_fdb_entry=True) + max_fdb_entry = attr["available_fdb_entry"] + ``` + + +### Clear FDB entries in a VLAN + Clear the learned FDB entries with the VLAN id object id + ```python + sai_thrift_flush_fdb_entries( + self.client, + bv_id=self.vlan_oid, + entry_type=SAI_FDB_ENTRY_TYPE_DYNAMIC) + ``` \ No newline at end of file diff --git a/doc/sai-ptf/config_data/route_config_t0.md b/doc/sai-ptf/config_data/route_config_t0.md new file mode 100644 index 000000000..a8a585fc8 --- /dev/null +++ b/doc/sai-ptf/config_data/route_config_t0.md @@ -0,0 +1,148 @@ +# Sample T0 Configurations and data for Route +- [Sample T0 Configurations and data for Route](#sample-t0-configurations-and-data-for-route) + - [Overriew](#overriew) + - [Route Configuration](#route-configuration) + - [rotue entries](#rotue-entries) + - [APIs for Route related configuration](#apis-for-route-related-configuration) + - [Create VLAN Interface and Route entry](#create-vlan-interface-and-route-entry) + - [Create LAG Router interface and Route entry](#create-lag-router-interface-and-route-entry) + - [Sample data/packet](#sample-datapacket) + - [Packet example](#packet-example) +## Overriew +This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around Route testing. + +It includes the related data and config for a route, including +- Next Hop +- Neighbor +- Route entry + +**Note: This configuration focused on T0 topology.** + +## Route Configuration + +### rotue entries + +VLAN interfaces route entries +|VLAN ID | VLAN Member | NH IP | NH MAC| +|-|-|-|-| +|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | +|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | + +*For vlan interface related configuration please refer to [VLAN_Config](./VLAN_config.md)** + +## APIs for Route related configuration + +### Create VLAN Interface and Route entry + +Neighbors + +|Name|IP|dest_mac| +|-|-|-| +|nb1-8| 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | +|nb9-16| 192.168.20.11 ~ 192.168.20.18 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | +|nb23-32| 192.168.0.17 ~ 192.168.0.26 | 00:00:77:77:77:77 - 00:00:ff:ff:ff:ff | +|nbvlan1000_gw| 192.168.10.255 | FF:FF:FF:FF:FF:FF | +|nbvlan2000_gw| 192.168.20.255 | FF:FF:FF:FF:FF:FF | + +Route entry + +|DestIp|Next Hop |Next Hop ip| +|-|-|-| +| 192.168.10.11 ~ 192.168.10.18 |port1 - 8 | 192.168.10.11 - 192.168.10.18 | +| 192.168.20.11 ~ 192.168.20.18 | port9 -16 | 192.168.20.11 - 192.168.20.18 | +| 192.168.0.17 ~ 192.168.0.26 | port23-32 | 192.168.0.17 - 192.168.0.26 | +|192.168.10.1|vlanInterface(VLAN1000)|CPU_PORT| +|192.168.20.1|vlanInterface(VLAN2000)|CPU_PORT| + +- Create a Router for a VLAN interface + ```Python + + self.vlan100_rif = sai_thrift_create_router_interface( + self.client, + type=SAI_ROUTER_INTERFACE_TYPE_VLAN, + virtual_router_id=self.default_vrf, + vlan_id=self.vlan1000) + self.rifnh = sai_thrift_create_next_hop( + self.client, ip=sai_ipaddress('192.168.10.1'), + router_interface_id=rif, type=CPU_PORT) + ``` + +- Create VLAN Interface GW + ```python + self.neighbor_entry1 = sai_thrift_neighbor_entry_t( + rif_id=self.vlan100_rif, + ip_address=sai_ipaddress('192.168.20.255'), + dst_mac_address='FF:FF:FF:FF:FF:FF') + ``` + +- Create Port Neighbor and next hop ( Port9 -> DestIP ) + ```Python + rif = sai_thrift_create_router_interface( + self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, + port_id=self.port9, virtual_router_id=self.vr) + rifnh = sai_thrift_create_next_hop( + self.client, ip=sai_ipaddress('192.168.20.2'), + router_interface_id=rif, type=SAI_NEXT_HOP_TYPE_IP) + self.neighbor_entry1 = sai_thrift_neighbor_entry_t( + rif_id=self.rif, + ip_address=sai_ipaddress('192.168.20.2'), + dst_mac_address='20:00:11:11:11:11') + self.route_entry1 = sai_thrift_route_entry_t( + vr_id=self.default_vrf, + destination=sai_ipprefix('192.168.20.2'+'/32')) # Packet dest IP + sai_thrift_create_route_entry( + self.client, self.route_entry1, next_hop_id=self.nhop1) + ``` +### Create LAG Router interface and Route entry + +Neighbors + +|Name|IP|dest_mac| +|-|-|-| +|lag1_nb| 192.168.0.11 | 00:00:11:11:11:11 | +|lag2_nb| 1 192.168.0.12|00:00:22:22:22:22 | +|lag3_nb| 192.168.0.13| 00:00:33:33:33:33 | +Route entry + +|DestIp|Next Hop |Next Hop ip| +|-|-|-| +| 192.168.0.11 |lag1:port17-18|192.168.0.11 | +|192.168.0.12 |lag2: port19 -20 | 192.168.0.12 | +| 192.168.0.13 | lag3:port21-22 | 192.168.0.13 | + +```Python + nhop = sai_thrift_create_next_hop(self.client, + ip=sai_ipaddress('192.168.0.11'), + router_interface_id=self.lag1_rif, + type=SAI_NEXT_HOP_TYPE_IP) + neighbor_entry = sai_thrift_neighbor_entry_t( + rif_id=self.lag1_rif, ip_address=sai_ipaddress('192.168.0.11')) + sai_thrift_create_neighbor_entry(self.client, neighbor_entry, + dst_mac_address='00:11:11:11:11:11') + route1 = sai_thrift_route_entry_t( + vr_id=self.default_vrf, destination=sai_ipprefix('192.168.0.11/32')) + sai_thrift_create_route_entry(self.client, route1, next_hop_id=nhop) + + +## Sample data/packet + +### Packet example +When routing a packet, it will check the neighbor/adjacent table, and based on the Next-hop table, change the SRC MAC and Dest MAC. + +- Input Packet + ```Python + simple_tcp_packet( + eth_dst=SW_MAC, + eth_src=SRC_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +- Output Packet + ```Python + simple_tcp_packet( + eth_dst=PORT_MAC, + eth_src=SW_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` diff --git a/doc/sai-ptf/config_data/vlan_config_t0.md b/doc/sai-ptf/config_data/vlan_config_t0.md new file mode 100644 index 000000000..f5444545a --- /dev/null +++ b/doc/sai-ptf/config_data/vlan_config_t0.md @@ -0,0 +1,187 @@ +# Sample T0 Configurations and data for VLAN +- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) + - [Overriew](#overriew) + - [VLAN configuration](#vlan-configuration) + - [VLAN and VLAN members](#vlan-and-vlan-members) + - [VLAN Interfaces](#vlan-interfaces) + - [APIs for VLAN configuration](#apis-for-vlan-configuration) + - [Create vlan and its member](#create-vlan-and-its-member) + - [Get VLAN, VLAN members, and attributes](#get-vlan-vlan-members-and-attributes) + - [Update VLAN, VLAN members and attributes](#update-vlan-vlan-members-and-attributes) + - [Delete VLAN and VLAN members](#delete-vlan-and-vlan-members) + - [Sample data/packet](#sample-datapacket) + - [Packet example](#packet-example) + - [config data](#config-data) +## Overriew +This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. + +**Note: This configuration focused on T0 topology.** + +## VLAN configuration + +### VLAN and VLAN members + +|HostIf|VLAN ID|Ports|Tag mode| +|-|-|-|-| +|Ethernet4-32|1000|Port1-8|Untag| +|Ethernet36-72|2000|Port9-16|Untag| + +### VLAN Interfaces +|VLAN ID | VLAN Interface IP | VLAN Interface MAC | +|-|-|-| +|1000|192.168.10.1|10:00:01:11:11:11| +|2000|192.168.20.1|20:00:01:22:22:22| + +## APIs for VLAN configuration +APIs relate to VLAN and VLAN attributes. + +**P.S. There are just some sample APIs, for more attributes please refer to https://github.com/richardyu-ms/SAI/blob/support_ptf_sai_build/inc/saivlan.h** + +### Create vlan and its member +- Create Vlan 1000 + ```Python + self.vlan1000 = sai_thrift_create_vlan(self.client, vlan_id=1000) + ``` +- Create VLAN members with different modes + Untag mode and access port + ```python + ---------------------------------- + |VLAN ID|Ports|Tag mode| HostIf | + |-------|-----|--------|---------| + | 1000 |Port1| Untag |Ethernet4| + ---------------------------------- + + self.vlan_member1 = sai_thrift_create_vlan_member( + self.client, + vlan_id=1000, + bridge_port_id=port_bridge_port1, + vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) + + ``` +### Get VLAN, VLAN members, and attributes +- Get VLAN member list +```Python +vlan_member_list = sai_thrift_object_list_t(count=1000) +mbr_list = sai_thrift_get_vlan_attribute( + self.client, self.vlan10, member_list=vlan_member_list) +vlan_members = mbr_list['SAI_VLAN_ATTR_MEMBER_LIST'].idlist +#equals to vlan_members = mbr_list['member_list'].idlist +``` +- Get VLAN + +```python + vlan_attr = sai_thrift_get_vlan_attribute( + self.client, vlan_oid=1000, learn_disable=True) +``` +- Get counters +```Python + stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) + in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] + out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] + in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] + in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] + out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] + out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] + +``` + +### Update VLAN, VLAN members and attributes +- Set mac learning + ```python + sai_thrift_set_vlan_attribute(self.client, self.vlan20, learn_disable=True) + ``` +- Set Native vlan 1000 on a port + ```python + sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=1000) + ``` +- Clear counters + ```Python + sai_thrift_clear_vlan_stats(self.client, self.vlan10) + ``` + +### Delete VLAN and VLAN members +- Remoev VLAN member + ```python + sai_thrift_remove_vlan_member(self.client, self.vlan_member1) + ``` +- Remoev VLAN + ```python + sai_thrift_remove_vlan(self.client, self.vlan1000) + ``` + +## Sample data/packet + +### Packet example +- Tagged packet with VLAN id + + When a packet sent to a access port or send out from a access port, we will get a packet without the VLAN id. + *In T0, we don't need to test tagged packet.* + ```python + tagged_packet(eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + vlan_vid=1000, + ip_dst='172.16.0.1', + ip_ttl=64) + ``` +- Untagged packet + ```Python + simple_tcp_packet(eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + ip_dst='172.16.0.1', + ip_ttl=64) + ``` + +## config data + +Below is the sample config data in config_db.json + +```JSON + { + "VLAN": { + "Vlan1000": { + "members": [ + "Ethernet4", + "Ethernet8", + "Ethernet12", + "Ethernet16", + "Ethernet20", + "Ethernet24", + "Ethernet28", + "Ethernet32" + ], + "vlanid": "1000" + } + }, + "VLAN_INTERFACE": { + "Vlan1000": {}, + "Vlan1000|192.168.0.1/21": {}, + "Vlan1000|fc02:1000::1/64": {} + }, + "VLAN_MEMBER": { + "Vlan1000|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet12": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet16": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet20": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet24": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet28": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet32": { + "tagging_mode": "untagged" + } + } + } +``` \ No newline at end of file diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 565860805..dd1720063 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -1,164 +1,103 @@ # SAI Lag Test plan - [SAI Lag Test plan](#sai-lag-test-plan) - - [Overriew](#overriew) - - [Test Topology](#test-topology) - - [Testbed](#testbed) - - [Scope](#scope) -- [Basic Configurations, SAI API and sample packets](#basic-configurations-sai-api-and-sample-packets) - - [Basic Configurations And SAI API](#basic-configurations-and-sai-api) - - [Basic Portchannel configuration](#basic-portchannel-configuration) - - [Create lag and lag member Using SAI API](#create-lag-and-lag-member-using-sai-api) - - [Basic Route Entry](#basic-route-entry) - - [Create Router Entry Using SAI API](#create-router-entry-using-sai-api) - - [Packets](#packets) -- [Test suites](#test-suites) - - [Test suite #1: PortChannel Loadbalanceing](#test-suite-1-portchannel-loadbalanceing) - - [Test suite #2: Remove Lag member](#test-suite-2-remove-lag-member) - - [Test suite #3: Ingress/Egreee disable](#test-suite-3-ingressegreee-disable) +- [Overriew](#overriew) +- [Test Environment](#test-environment) + - [Testbed](#testbed) + - [Test Configuration](#test-configuration) + - [Variations](#variations) +- [Test Execution](#test-execution) + - [Basic function test](#basic-function-test) + - [PortChannel Loadbalanceing](#portchannel-loadbalanceing) + - [Testing Objective](#testing-objective) + - [Test Data/Packet](#test-datapacket) + - [Test Cases](#test-cases) + - [SAI API test](#sai-api-test) + - [Renove lag member](#remove-lag-member) + - [Testing Objective](#testing-objective) + - [Test Cases](#test-cases) + - [Disable Lag memeber](#disable-lag-memeber.) + - [Testing Objective](#testing-objective) + - [Test Data/Packet](#test-datapacket) + - [Test Cases](#test-case) + ## Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. -### Test Topology -For SAI-PTF, it will use a non-topology network structure for the sai testing. - -### Testbed +# Test Environment +## Testbed Those tests will be run on the testbed structure, the components are: * PTF - running in a server that can connect to the target DUT * SAI server - running on a dut +## Test Configuration -*P.S. All the tests are target on T0 scenario.* - -## Scope -The test will include two parts -1. Lag functionalities - - Load balancing -2. Lag SAI APIs - - create/check/remove lag and lag member - - -# Basic Configurations, SAI API and sample packets - -## Basic Configurations And SAI API -### Basic Portchannel configuration -|PortChannel Name|Ports| -|-|-| -| lag3 |Port14-16| -#### Create lag and lag member Using SAI API -```Python - +------------+------------+-----------+-----------+ - | lag3 | -- | port14 | -- | - | lag3_rif | | port15 | | - | | | port16 | | - +------------+------------+-----------+-----------+ - sai_thrift_create_lag(self.client) - - self.lag3_member14 = sai_thrift_create_lag_member( - self.client, lag_id=self.lag3, port_id=self.port14) - self.lag3_member15 = sai_thrift_create_lag_member( - self.client, lag_id=self.lag3, port_id=self.port15) - self.lag3_member16 = sai_thrift_create_lag_member( - self.client, lag_id=self.lag3, port_id=self.port16) - - self.lag3_rif = sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_PORT, - virtual_router_id=self.default_vrf, - port_id=self.lag3) - -``` - -### Basic Route Entry - -|DestIp|Next Hop |Next Hop ip|Next Hop Mac| -|-|-|-|-| -|10.10.10.2|lag3|10.10.10.10|00:99:99:99:99:99| - -#### Create Router Entry Using SAI API -```Python - nhop = sai_thrift_create_next_hop(self.client, - ip=sai_ipaddress('10.10.10.10'), - router_interface_id=self.lag3_rif, - type=SAI_NEXT_HOP_TYPE_IP) - neighbor_entry = sai_thrift_neighbor_entry_t( - rif_id=self.lag3_rif, ip_address=sai_ipaddress('10.10.10.10')) - sai_thrift_create_neighbor_entry(self.client, neighbor_entry, - dst_mac_address='00:99:99:99:99:99') - route1 = sai_thrift_route_entry_t( - vr_id=self.default_vrf, destination=sai_ipprefix('10.10.10.2/32')) - sai_thrift_create_route_entry(self.client, route1, next_hop_id=nhop) - -``` -## Packets -```Python - pkt = simple_tcp_packet( - eth_dst=dev_port11_MAC, - eth_src='00:22:22:22:22:22', - ip_dst='10.10.10.2', - ip_src=srcip) - - exp_pkt = simple_tcp_packet( - eth_dst='00:99:99:99:99:99', - eth_src=dev_port11_MAC, - ip_dst='10.10.10.2', - ip_src=srcip) -``` - -# Test suites -## Test suite #1: PortChannel Loadbalanceing -For load balancing, expecting the ports in a lag should receive the packet equally. +For the test configuration, please refer to the file + - [VLAN_config](./config_data/vlan_config_t0.md) + - [FDB_config](./config_data/fdb_config_t0.md) + - [Route_config](./config_data/route_config_t0.md) + - [LAG_config](./config_data/LAG_config_t0.md) -Even after removing and disabling the port in a lag. + +**Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** + +## Variations +Cause the testbed might also encounter some issues like the host interface being down. +Before running the actual test there will need some sanity test to check the DUT status and select the active ports for testing. + +**All the ports in this test plan just to illustrate the test purpose, they are not exactly the same for the actual environment.** -Sample SAI API -```python +# Test Execution +## Basic function test - #How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag) - self.packet_numbers =100 - for i in range(0, n): - self.assertTrue((count[i] >= ((self.packet_numbers / n) * 0.7)), - - #Send packet from dev_port11 - send_packet(self, self.dev_port11, pkt) +### PortChannel Loadbalanceing +#### Testing Objective +For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side +Even after removing and disabling the port in a lag. + +#### Test Data/Packet -``` +[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) +- Input Packet +- Output Packet +#### Test Cases | Goal| Steps/Cases | Expect | |-|-|-| -| Prepare to send from dev_port11 to Lag3.| Send packet with.| Lag3 and members have been created.| -| Packet forwards on port equally.| Send packet on dev_port11 to the lag3 4 times .| Loadbalance on lag members.| +| Prepare to send from port0 to Lag1.| Send packet with.| Lag1 and members have been created.| +| Packet forwards on port equally.| Send packet on port0 to the lag1 100 times .| Loadbalance on lag members.| | Packet forwards on available ports equally.| Every time, disable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| | Packet forwards on available ports equally.| Every time, enable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| | Packet forwards on available ports equally.| Every time, remove one lag member, then send packet | Loadbalance on lag members.| -## Test suite #2: Remove Lag member + + +## SAI API test +### Remove Lag member +#### Testing Objective Test verifies the LAG load balancing for scenario when LAG members are removed. -Sample APIs -Remove Lag member -```python - print("Remove LAG member 16") - status = sai_thrift_remove_lag_member(self.client, self.lag3_member16) -``` +#### Test Data/Packet + +[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) +- Input Packet +- Output Packet + +#### Test Cases | Goal | Steps/Cases | Expect | |-|-|-| -|Remove port16 and forwarding packet from port1 to port14,15|Remove port16 form Lag3 and Send packet on dev_port11 to lag3 100 times| Port14 and port15 will receive an equal number of packets.| +|Remove lag2_member2 and forwarding packet from port0 to lag2|Remove lag2_member2 form Lag2 and Send packet on port0 to lag2 100 times| Port0 will receive an equal number of packets.| -## Test suite #3: Ingress/Egreee disable +### Disable Lag memeber For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. -Sample APIs +#### Test Data/Packet -Ingress/Egreee disable -```python - status = sai_thrift_set_lag_member_attribute( - self.client, - self.lag3_member14, - ingress_disable=True, - egress_disable=True) +[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) +- Input Packet +- Output Packet -``` +#### Test Cases | Goal | Steps/Cases | Expect | |-|-|-| -|Packet dropped on port14| Disable egress and ingress on lag member14. send packet | Packet drop.| +|Packet dropped on port22| Disable egress and ingress on lag3 member2. send packet | Packet drop.| diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index b7c907a29..360058f73 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -1,478 +1,352 @@ -# SAI Vlan Test plan -- [SAI Vlan Test plan](#sai-vlan-test-plan) - - [Overriew](#overriew) - - [Testbed](#testbed) - - [Scope](#scope) - - [Basic Configurations and SAI APIs](#basic-configurations-and-sai-apis) - - [Testbed stablization and impact](#testbed-stablization-and-impact) - - [Basic VLAN configuration](#basic-vlan-configuration) - - [Create VLAN and VLAN member](#create-vlan-and-vlan-member) - - [Basic Forwarding Table](#basic-forwarding-table) - - [Create FDB Entry](#create-fdb-entry) - - [Packet example](#packet-example) - - [Tests](#tests) - - [Test Case: VLAN-Interface (SVI)](#test-case-vlan-interface-svi) - - [Test the configuration](#test-the-configuration) - - [Test description](#test-description) - - [Route entry](#route-entry) - - [VLAN interface input packet](#vlan-interface-input-packet) - - [VLAN interface output packet](#vlan-interface-output-packet) - - [Test case](#test-case) - - [Test suite: Basic function - Untagging and access](#test-suite-basic-function---untagging-and-access) - - [Test case: Basic function - Test Frame Filtering](#test-case-basic-function---test-frame-filtering) - - [Composit scenario: ARP Flooding and learn](#composit-scenario-arp-flooding-and-learn) - - [SAI APIs operations](#sai-apis-operations) - - [Test case: Vlan member list.](#test-case-vlan-member-list) - - [Test case: Test VLAN related counters.](#test-case-test-vlan-related-counters) -## Overriew +# SAI VLAN Test plan + +- [Overriew](#overriew) +- [Test Environment](#test-environment) + - [Testbed](#testbed) + - [Test Configuration](#test-configuration) + - [Variations](#variations) +- [Test Execution](#test-execution) + - [Basic function test](#basic-function-test) + - [Untagging and access](#untagging-and-access) + - [Testing Objective](#testing-objective) + - [Test Data/Packet](#test-datapacket) + - [Test Cases](#test-cases) + - [Frame Filtering](#frame-filtering) + - [Testing Objective](#testing-objective-1) + - [Test Data/Packet](#test-datapacket-1) + - [Additional config:](#additional-config) + - [Test Cases](#test-cases-1) + - [MAC learning](#mac-learning) + - [Testing Objective](#testing-objective-2) + - [Test Data/Packet](#test-datapacket-2) + - [Additional config:](#additional-config-1) + - [Test Cases](#test-cases-2) + - [SAI API test](#sai-api-test) + - [Vlan member list](#vlan-member-list) + - [Testing Objective](#testing-objective-3) + - [Test Cases](#test-cases-3) + - [VLAN related counters.](#vlan-related-counters) + - [Testing Objective](#testing-objective-4) + - [Test Data/Packet](#test-datapacket-3) + - [Test Cases](#test-cases-4) + - [Disable mac learning](#disable-mac-learning) + - [Testing Objective](#testing-objective-5) + - [Test Data/Packet](#test-datapacket-4) + - [Additional config:](#additional-config-2) + - [Test Cases](#test-cases-5) + - [Composit scenario](#composit-scenario) + - [L3 switching(Inter-VLAN)](#l3-switchinginter-vlan) + - [Testing Objective](#testing-objective-6) + - [Test Data/Packet](#test-datapacket-5) + - [Test Cases](#test-cases-6) + - [ARP Flooding and mac learning](#arp-flooding-and-mac-learning) + - [Testing Objective](#testing-objective-7) + - [Test Data/Packet](#test-datapacket-6) + - [Additional config:](#additional-config-3) + - [Test Cases](#test-cases-7) +# Overriew The purpose of this test plan is to test the VLAN function from SAI. -### Testbed +The test will include three parts +- Vlan functionalities +- SAI APIs operations +- Composit scenario + +# Test Environment +## Testbed Those tests will be run on the testbed structure, the components are: * PTF - running in a server that can connect to the target DUT * SAI server - running on a dut -*P.S. All the tests are target on T0 scenario.* -## Scope -The test will include three parts -1. Vlan functionalities - - Flooding - - Forwarding - - Access - - Untagging(802.1Q) - - ARP -2. SAI APIs operations - - Vlan Counters - - Vlan and member list operations -3. Composit scenario - - VLAN Interface (RIF/SVI) - -## Basic Configurations and SAI APIs -During testing, we need to use SAI APIs for testing. By using the SAI-PTF structure, we can invoke the SAI with RPC APIs remotely, the sample code is below. -### Testbed stablization and impact -Cause the test bed might also encounter some issue, like the host interface is down. -Before run the actual test there will be need some sanity test to check the DUT status, and select the active ports for testing. - -### Basic VLAN configuration -|VLAN ID|Ports|Tag mode|HostIf -|-|-|-|-| -|1000|Port1-24|Untag|Ethernet4-96| - -|VLAN connection|Ports|Tag mode| -|-|-|-| -|1000|Port1-24|Untag| - -### Create VLAN and VLAN member -- Create Vlan 1000 - ```Python - sai_thrift_create_vlan(self.client, vlan_id=1000) - ``` -- Create Native vlan 1000 - ```python - sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=1000) - ``` -- Create Vlan member and VLAN member with different mode - Untag mode and access port - ```python - ---------------------------------- - |VLAN ID|Ports|Tag mode| HostIf | - |-------|-----|--------|---------| - | 1000 |Port1| Untag |Ethernet4| - ---------------------------------- - - sai_thrift_create_vlan_member( - self.client, - vlan_id=1000, - bridge_port_id=port_bridge_port1, - vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) - - ``` - -### Basic Forwarding Table -For testing, we can use basic FDB APIs to Add the FDB entry into CAM. The Rule as below -|Name|MAC|PORT|VLAN|HostIf| -|-|-|-|-|-| -|fdb0|mac0-00:00:00:00:00:11|Port0||Ethernet0| -|fdb1-24 |mac1-00:11:11:11:11:11 - mac24-02:55:55:55:55:55|Port1-24|1000|Ethernet4-Ethernet96| -|fdb25-32|mac25-02:55:55:55:55:55 - mac31-03:11:11:11:11:11|Port25-32||Ethernet100-Ethernet128| - - - -### Create FDB Entry - -- Add static FDB entry in the FDB table - - In the sample code below, we can see how to create FDB entry. - - This FDB entry is a static entry, it will ``forward`` packet when the packet with a mac1 on port1. - ```python - ---------------------------------------------------- - | MAC |Ports| VLAN | Type | Action | HostIf | - |-------|-----|----------|-------------------------- - | mac1 |Port1| vlan_oid |STATIC| FORWARD|Ethernet4| - ---------------------------------------------------- - - sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) - sai_thrift_create_fdb_entry( - self.client, - fdb_entry, - type=SAI_FDB_ENTRY_TYPE_STATIC, - bridge_port_id=Port1, - packet_action=SAI_PACKET_ACTION_FORWARD) - ``` - -- FDB operations - Get FDB entries - ```python - sai_thrift_get_switch_attribute( - self.client, - available_fdb_entry=True) - ``` -- Clear FDB entries - Clear the learned FDB entries with the VLAN id object id - ```python - sai_thrift_flush_fdb_entries( - self.client, - bv_id=self.vlan_oid, - entry_type=SAI_FDB_ENTRY_TYPE_DYNAMIC) - ``` +## Test Configuration -### Packet example -- Tagged packet with VLAN id - - When a packet sent to a access port or send out from a access port, we will get a packet with the VLAN id. - *In T0, we don't need to test tagged packet.* - ```python - tagged_packet(eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - vlan_vid=1000, - ip_dst='172.16.0.1', - ip_ttl=64) - ``` -- Untagged packet - ```Python - simple_tcp_packet(eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - ip_dst='172.16.0.1', - ip_ttl=64) - ``` +For the test configuration, please refer to the file + - [VLAN_config](./config_data/vlan_config_t0.md) + - [FDB_config](./config_data/fdb_config_t0.md) + - [Route_config](./config_data/route_config_t0.md) -## Tests - -### Test Case: VLAN-Interface (SVI) -**Testing Objective** +**Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** -Testing L3 switch, VLAN-Interface(SVI) in layer3 for packet routing. - -In this case, it will cover the scenarios like -- Server to T1 -- Server to Server -#### Test the configuration -For VLAN-Interface(SVI), it can be configured from a config_db.json. This json file, can be generated from a xml config as below. Base on this configuration we can see what the actual configuration will be. - -```xml - - - - - -``` -Convert to config_db.json -```json - "VLAN": { - "Vlan608": { - "members": [ - "Ethernet6/1", - "Ethernet7/1", - "Ethernet8/1", - ], - "vlanid": "608" - } - }, - "VLAN_INTERFACE": { - "Vlan608": {}, - "Vlan608|10.95.88.209/28": {}, - "Vlan608|2603:10a0:31c:8144::1/64": {} - }, - "VLAN_MEMBER": { - "Vlan608|Ethernet6/1": { - "tagging_mode": "untagged" - }, - "Vlan608|Ethernet7/1": { - "tagging_mode": "untagged" - }, - "Vlan608|Ethernet8/1": { - "tagging_mode": "untagged" - }, - } -``` - -#### Test description -``` -Test example: -Vlan to Port: -Server To Server - pkt(From Server) -> |DUT|Ethernet -> SVI(VLAN_IF->MAC:IP1) ||| vlan1000 || -> Ethernet(T1) -> ... +*p.s. Please refer the sample packet in [VLAN_config#Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket)* -Server to T1 - pkt(From Server) -> |DUT|Ethernet -> SVI(VLAN_IF->MAC:IP2) ||| vlan1000 || -> Ethernet(Server) -> ... -``` - -#### Route entry - -|DestIp|Next Hop |Next Hop ip|Next Hop Mac| -|-|-|-|-| -|192.168.0.1|vlanInterface(VLAN1000)|192.168.1.1(SVI_IP)|PORTMAC| - -- Create Router for a VLAN interface (not used in currernt test, just for explain the route creation.) - ```Python - self.vlan100_rif = sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_VLAN, - virtual_router_id=self.default_vrf, - vlan_id=self.vlan1000) - - self.nhop1 = sai_thrift_create_next_hop( - self.client, - ip=sai_ipaddress(next_hop_ip), #SVI_IP - router_interface_id=self.vlan100_rif, - type=SAI_NEXT_HOP_TYPE_IP) - self.neighbor_entry1 = sai_thrift_neighbor_entry_t( - rif_id=self.vlan1000_rif, - ip_address=sai_ipaddress(next_hop_ip))#SVI_IP - #Nhop to vlan interface - sai_thrift_create_neighbor_entry( - self.client, self.neighbor_entry1, - dst_mac_address=self.portmac) #Dest port mac, i.e port15:mac15 in vlan1000 - #Route to vlan interface - self.route_entry1 = sai_thrift_route_entry_t( - vr_id=self.default_vrf, - destination=sai_ipprefix(pkt_dest_ip+'/32')) # Packet dest IP - sai_thrift_create_route_entry( - self.client, self.route_entry1, next_hop_id=self.nhop1) - ``` - -#### VLAN interface input packet - ```Python - simple_tcp_packet( - eth_dst=SVI_MAC, - eth_src=SRC_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` - -#### VLAN interface output packet - ```Python - simple_tcp_packet( - eth_dst=PORT_MAC, - eth_src=SVI_MAC, #Switch MAC - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` +## Variations +Cause the testbed might also encounter some issues like the host interface being down. +Before running the actual test there will need some sanity test to check the DUT status and select the active ports for testing. -**Precondition/Setup:** -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. -- Create VLAN Interface for ``VLAN1000`` with ``SVI_IP`` -- Create route ``DEST_IP`` and next hop with ``SVI_IP`` and ``PORTAMC`` to ``PORT15``. +**All the ports in this test plan just to illustrate the test purpose, they are not exactly the same for the actual environment.** -#### Test case -| Goal |Steps/Cases | Expect | -|-|-|-| -| Forwarding packet on ``VLAN_INTERFACE`` .| Send ``Untagged`` packet with dest ``SVI_MAC`` on port1. | ``Untagged`` packet received on ``PORT15``.| +# Test Execution +## Basic function test +### Untagging and access -### Test suite: Basic function - Untagging and access +#### Testing Objective +This test verifies the VLAN function around untag and access ports. -This is a basic funcation testing. This test suite will cover the basic VLAN function around untag and access port. +*p.s. This test will not check function with the native VLAN scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* -*p.s. This test will not check function with native VLAN scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* -**Testing Objective** -With a untagged packet, on the access port, when ingress and egress happen, the behavior as below +With an untagged packet, on the access port, when ingress and egress happen, the behavior as below | Port mode | packet tag mode | Direction | Action | | :---------|--------------- | :-------- | :--------------------------------------- | | Access|Untag| Ingress | Accept the packet. | | |Untag | Egress | Untag the packet. | +| Access|Tag| Ingress | Accept the packet. | +| |Tag | Egress | Untag the packet. | -**Testing Description** ``` Test example: - -1. pkt(Untag:10) -> (access:10)|DUT|DMAC-> |(Acess:10)->pkt(Untag) +Untagged: + pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000-> Port2:Access:VLAN1000 -> pkt(Untag:DMAC=MAC2) +Tagged: + pkt(Tag:VLAN2000:DMAC=MAC10) -> Port9:Access:VLAN2000-> Port10:Access:VLAN2000 -> pkt(Untag:DMAC=MAC10) ``` -Below is the test for checking this. -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. +#### Test Data/Packet +[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) +- Input: Packet(Untag) and Packet(Tag) +- Expected: Packet(Tag) + + *p.s. please refer the sample packet in [VLAN_config#Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket)* -Cases: +#### Test Cases | Goal| Cases | Expect | |-|-|-| -|``Untag``:Acess -> Acess port.| Send VLAN100 ``Untagged`` packet with dest mac5 on port6. | ``Untag`` packet received on port4.| - -### Test case: Basic function - Test Frame Filtering -**Testing Objective** - -Drop packet when packet's dest mac is port mac in MAC table. +|``Untag``:Acess -> Acess port.| Send VLAN100 ``Untagged`` packet on Port1 with mac2 as dest mac. | ``Untag`` packet received on port2.| +|``Tag``:Acess -> Acess port.| Send VLAN2000 ``Untagged`` packet on Port9 with mac10 mac as dest mac. | ``Untag`` packet received on port10.| -**Testing Description** +### Frame Filtering +#### Testing Objective -Drop packet when packet's dest mac is port mac in MAC table. +Drop packet when packet's dest mac is port SRC MAC in MAC table. ``` Test example: - | SRCPORT:MAC1 = DMAC| - pkt(Untag:DMAC):vlan:10 -> SRCPORT(Access:10) -> |DUT| -> |FDB| | -> X - | MAC2 | - + | MAC1 | + pkt(Untag:DMAC=MAC1 or MACX) -> Port1:Access:VLAN1000 -> FDB(contains:MAC1,MACX)| | -> X + | MACX | ``` -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. + +#### Test Data/Packet + +[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) +- Input: Packet(Untag) +- Expected: Drop + +#### Additional config: - Add a non-existing ``MacX`` to port1 -| Goal |Steps | Expect | +#### Test Cases +| Goal | Case | Expect | |-|-|-| -| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| -| Filter frame. | Send VLAN100 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| +| Filter frame. | Send VLAN1000 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| +| Filter frame. | Send VLAN1000 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| -### Composit scenario: ARP Flooding and learn -- ARP request - ```Python - simple_arp_packet( - eth_dst='FF:FF:FF:FF:FF:FF', # boardcast - eth_src='00:11:11:11:11:11', - arp_op=1, # ARP request - ip_tgt='10.10.10.2', - ip_snd='10.10.10.1', - hw_snd='00:11:11:11:11:11', - hw_tgt="00:00:00:00:00:00") - ``` -- ARP response - ```Python - Untagged: - simple_arp_packet( - eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - arp_op=2, # ARP response - ip_tgt='10.10.10.1', - ip_snd='10.10.10.2', - hw_snd='00:22:22:22:22:22', - hw_tgt="00:11:11:11:11:11") - Tagged: - simple_arp_packet( - eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - arp_op=2, # ARP response - ip_tgt='10.10.10.1', - ip_snd='10.10.10.2', - vlan_vid=1000, - hw_snd='00:22:22:22:22:22', - hw_tgt="00:11:11:11:11:11") - ``` +### MAC learning +#### Testing Objective +For mac learning in VLAN scenario, in contain those two cases +1. the packet sent to the VLAN port will flood to other ports in the same VLAN before learning the mac address from the packet +2. The packet is only sent to the target port when the MAC table contains the MAC address on the target port(Dest MAC). -In the ARP scenario, the mac learning process is: -1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff -2. After the encountered device get the ARP packet and sends out a response, the packet will be filled with a source mac, this is the target device mac for the dest IP. -3. Switch received that response, cause the switch learned a MAC on step 1 on the sending port, then it can make a unicast here. -**p.s. The test will be ended here, will not test the send from the port in step 1 again, it is already covered in other tests.** +``` +1. Flooding + | Port2| + pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000 -> Flooding ->| To |-> pkt(Untag) + | Port8| -**Testing Description** +2. unicast + pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) -Testing ARP scernairo ``` -Test example: -1. ARP Request - - ARP Req pkt(Untag:DMAC) -> (access:10)|DUT| -> Flooding -> VLAN:10 -> pkt(Untag):VLAN10:Access -2. ARP Response - pkt(access:10)|DUT| <- Forward(FDB:MAC=DMAC) <- VLAN:10:PORT <- RP Resp pkt(Untag:10:DMAC) +#### Test Data/Packet -``` -Precondition/Setup: -- Create VLAN as the basic configuration. +[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) +- Input: Packet(Untag) +- Expected: Packet(Untag) + +#### Additional config: +- Do not config the MAC table -| Goal | Steps | Expect | +#### Test Cases +| Goal | Case | Expect | |-|-|-| -| ARP Request flooding to all ports. | Send ``Untagged`` ARP packet with dest ``mac4`` on ``port1``. |``Untagged`` Packets from ``Access``, ``Untagged`` Packet from ``Access``| -| Mac learned from ARP request and ARP response.| Send a ``Untagged`` ARP response packet with src:mac4, dest:mac1 to port4 and check the FDB entries.|Unicast happened.| -| FDB entries added.| Call API to check the FDB entries.|New mac entries in CAM.| +| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac2`` on ``port1``. |Receive ``Untagged`` packet from Port2 to Port8| +|MAC learning|check the FDB entries.|New mac entries in FDB.| +| Forwarding based on MAC table.| Send a ``Untagged`` packet with src:mac2, dest:mac1 on port2.| Receive ``Untagged`` packet on Port1| +|MAC learning|check the FDB entries.|New mac entries in FDB.| -## SAI APIs operations -### Test case: Vlan member list. -**Testing Objective** +## SAI API test + +### Vlan member list +#### Testing Objective Test VLAN and member list. -Sample APIs +#### Test Cases +| Goal | Cases | Expect | +|-|-|-| +| VLAN APIs get VLAN and its member. |Use the SAI API to check the VLAN and its member.| VLAN and VLAN member list.| +| Remove VLAN and its member.|Remove the VLAN member from VLAN 1000 and remove VLAN. | VLAN and its member removed.| +| Error when creating member to un-exist VLAN. |Use the SAI API to create a VLAN member on VLAN 1000 | Error happened.| -Get VLAN member list -```Python - vlan_member_list = sai_thrift_object_list_t(count=100) - mbr_list = sai_thrift_get_vlan_attribute( - self.client, self.vlan10, member_list=vlan_member_list) -``` +### VLAN related counters. +#### Testing Objective -nagtive test -```python - vlan_attr = sai_thrift_get_vlan_attribute( - self.client, vlan_oid=1000, learn_disable=True) +For VLAN-related counters, SAI should be able to get the counter and clear them. - incorrect_member = sai_thrift_create_vlan_member( - self.client, - vlan_id=1000, - bridge_port_id=self.port27_bp, - vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) -``` +#### Test Data/Packet +[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) +- Input: Packet(Untag) +- Expected: Packet(Untag) -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. +#### Test Cases +| Goal |Cases | Expect | +|-|-|-| +| Packet Forwarding.|Send VLAN100 ``Untagged`` packet on Port1 with port2 mac as dest mac. | ``Untagged`` packet received on port3.| +| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| +| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | + + +### Disable mac learning +#### Testing Objective +Test the function when disabling VLAN MAC learning. +When disabled, no new MAC will be learned in the MAC table. +#### Test Data/Packet -| Steps/Cases | Goal | Expect | +[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) +- Input: Packet(Untag) +- Expected: Packet(Untag) + +#### Additional config: +- Do not config the MAC table + +#### Test Cases +| Goal | Case | Expect | |-|-|-| -| VLAN member list and member count are right. |Use the SAI API to check the VLAN member | Vlan member list.| -| VLAN and its member removed.|Remove the VLAN member from VLAN 10 and remove VLAN. | VLAN and its member removed.| -| Error when creating member to un-exist VLAN. |Use the SAI API to create a VLAN member on VLAN 10 | Vlan attribute is 0.| +| Disable Vlan MAC learning. | Set the VLAN attribute to disable the VLAN MAC learning. |VLAN attribute set.| +| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac2`` on ``port1``. |Receive ``Untagged`` packet from Port2 to Port8| +| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac1`` on ``port2``. |Receive ``Untagged`` packet on ports except for port2.| +|MAC learning|check the FDB entries.|No new mac entries in FDB.| -### Test case: Test VLAN related counters. -**Testing Objective** +## Composit scenario -For VLAN-related counters, SAI should be able to get the counter and clear them. +### L3 switching(Inter-VLAN) +#### Testing Objective -Below is the sample API to operate those data +Testing L3 switching(Inter-VLAN). -Check counters -```Python - stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) - in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] - out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] - in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] - in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] - out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] - out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] +In this case, it will cover the scenarios for Server to Server (east/west) in different VLAN(Inter-VLAN) ``` -Clear counters -```Python -sai_thrift_clear_vlan_stats(self.client, self.vlan10) +Server To Server + PC1 -> pkt(Untag) -> |DUT|Port1:Access:VLAN1000 + |L3| <-> |Virtual Switch| + PC2 <- pkt(Untag) <- |DUT|Port9:Access:VLAN2000 ``` +*All the layer 3 router tables are created as the basic config, not MAC and ARP learning in this test process.* +The process is as below: +1. PC1 sends a untag packet to port1, which is a VLAN1000 access port +2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT MAC, forwarding to PORT9 +3. Packet goes through VLAN2000 port9 + +#### Test Data/Packet +- Input Packet + ```Python + simple_tcp_packet( + eth_dst=SVI_MAC, + eth_src=SRC_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` + +- Expected Packet + ```Python + simple_tcp_packet( + eth_dst=PORT_MAC, + eth_src=SVI_MAC, + ip_dst=DEST_IP, + ip_src=SRC_IP) + ``` +#### Test Cases +| Goal | Case | Expect | +|-|-|-| +| Inter-VLAN switching .| Send ``Untagged`` packet on port1 with dest ``SVI_MAC``. | ``Untagged`` packet received on ``PORT9``.| + -Precondition/Setup: -- Create VLAN as the basic configuration. -- Create an FDB table as a basic configuration. -| Goal |Steps/Cases | Expect | + +### ARP Flooding and mac learning +#### Testing Objective +In the ARP scenario, the mac learning process is: +1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff +2. After the target port gets the ARP packet MAC table fills with port SRC MAC. +3. Switch received that response, based on the MAC table, it makes a unicast here. + +**p.s. The test will be ended here, will not test the send from the port in step 1 again, it is already covered in other tests.** + +Testing ARP scenario +``` +Test example: +1. ARP Request + | Port2| + ARP Req pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000 -> Flooding ->| to |-> pkt(Untag) + | Port8| + +2. ARP Response + ARP Resp pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) + +``` +#### Test Data/Packet +**Both those two packets will be used in input and output.** +- ARP request + ```Python + simple_arp_packet( + eth_dst='FF:FF:FF:FF:FF:FF', # boardcast + eth_src=MAC1, + arp_op=1, # ARP request + ip_tgt=IP2, + ip_snd=IP1, + hw_snd=MAC1, + hw_tgt=MAC2) + ``` +- ARP response + ```Python + #Untagged: + simple_arp_packet( + eth_dst=MAC1, + eth_src=MAC2, + arp_op=2, # ARP response + ip_tgt=IP1, + ip_snd=IP2, + hw_snd=MAC2, + hw_tgt=MAC1) + + #Tagged(Just Sample, not used in this case): + simple_arp_packet( + eth_dst=MAC1, + eth_src=MAC2, + arp_op=2, # ARP response + ip_tgt=IP1, + ip_snd=IP2, + vlan_vid=1000, + hw_snd=MAC2, + hw_tgt=MAC2) + ``` + +#### Additional config: +- Do not config the MAC table + +#### Test Cases +| Goal | Case | Expect | |-|-|-| -| Forwarding, ``VLAN10`` ``Untagged`` packet on ``Native`` from a ``VLAN10`` ``Access``.|Send ``Untagged`` packet with dest ``mac3`` on ``port5``. | ``Untagged`` packet received on port3.| -| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| -| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | +| ARP Request flooding. | Send ``Untagged`` ARP packet with dest ``mac2`` on ``port1``. |``Untagged`` Arp request from Port2 to Port8| +|MAC learning|check the FDB entries.|New mac entries in FDB.| +| ARP response Forwarding.| Send a ``Untagged`` ARP response packet with src:mac2, dest:mac1 on port2.|``Untagged`` ARP response from Port1| +|MAC learning|check the FDB entries.|New mac entries in FDB.| From 1ab24e830c789825ded8ffc3965b84a90c230c37 Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Wed, 1 Jun 2022 06:15:32 +0000 Subject: [PATCH 07/18] fix typo and more description more clear Signed-off-by: richardyu-ms --- doc/sai-ptf/vlan_test_plan.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 360058f73..289b84629 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -113,13 +113,13 @@ Tagged: #### Test Cases | Goal| Cases | Expect | |-|-|-| -|``Untag``:Acess -> Acess port.| Send VLAN100 ``Untagged`` packet on Port1 with mac2 as dest mac. | ``Untag`` packet received on port2.| +|``Untag``:Acess -> Acess port.| Send VLAN1000 ``Untagged`` packet on Port1 with mac2 as dest mac. | ``Untag`` packet received on port2.| |``Tag``:Acess -> Acess port.| Send VLAN2000 ``Untagged`` packet on Port9 with mac10 mac as dest mac. | ``Untag`` packet received on port10.| ### Frame Filtering #### Testing Objective -Drop packet when packet's dest mac is port SRC MAC in MAC table. +Drop packet when the destination port from MAC table search is the port which packet come into the switch. ``` Test example: @@ -208,7 +208,7 @@ For VLAN-related counters, SAI should be able to get the counter and clear them. #### Test Cases | Goal |Cases | Expect | |-|-|-| -| Packet Forwarding.|Send VLAN100 ``Untagged`` packet on Port1 with port2 mac as dest mac. | ``Untagged`` packet received on port3.| +| Packet Forwarding.|Send VLAN1000 ``Untagged`` packet on Port1 with port2 mac as dest mac. | ``Untagged`` packet received on port3.| | Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| | Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | From 304888f5055976448ea7147b63149cf11da5cb47 Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Thu, 2 Jun 2022 12:32:43 +0800 Subject: [PATCH 08/18] fix lag test typo (#29) Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/LAG_config_t0.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/sai-ptf/config_data/LAG_config_t0.md b/doc/sai-ptf/config_data/LAG_config_t0.md index de9d77865..d7fc774ee 100644 --- a/doc/sai-ptf/config_data/LAG_config_t0.md +++ b/doc/sai-ptf/config_data/LAG_config_t0.md @@ -1,5 +1,5 @@ -# Sample T0 Configurations and data for VLAN -- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) +# Sample T0 Configurations and data for LAG +- [Sample T0 Configurations and data for LAG](#sample-t0-configurations-and-data-for-lag) - [Overriew](#overriew) - [LAG configuration](#lag-configuration) - [LAG and lag members](#lag-and-lag-members) @@ -121,7 +121,7 @@ Below is the sample config data in config_db.json "admin_status": "up", "members": [ "Ethernet84", - "Ethernet188" + "Ethernet88" ], "min_links": "1", "mtu": "9100" @@ -130,7 +130,7 @@ Below is the sample config data in config_db.json "admin_status": "up", "members": [ "Ethernet92", - "Ethernet96" + "Ethernet96" ], "min_links": "1", "mtu": "9100" @@ -144,7 +144,7 @@ Below is the sample config data in config_db.json "PortChannel2|10.10.193.19/31": {}, "PortChannel2|2603:10b0:31f:279::2a/126": {}, "PortChannel3": {}, - "PortChannel3|10.10.194.19/31": {} + "PortChannel3|10.10.194.19/31": {}, "PortChannel3|2603:10b0:31f:27a::2a/126": {}, }, "PORTCHANNEL_MEMBER": { From c3706e6362c59ca5030f785f544f850480c839d0 Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Fri, 3 Jun 2022 12:36:06 +0000 Subject: [PATCH 09/18] refactor vlan test plan and config Signed-off-by: richardyu-ms --- doc/sai-ptf/config_data/LAG_config_t0.md | 158 --------- doc/sai-ptf/config_data/config_t0.md | 120 +++++++ doc/sai-ptf/config_data/fdb_config_t0.md | 79 ----- doc/sai-ptf/config_data/route_config_t0.md | 148 --------- doc/sai-ptf/config_data/vlan_config_t0.md | 187 ----------- doc/sai-ptf/vlan_test_plan.md | 359 ++++++++++----------- 6 files changed, 286 insertions(+), 765 deletions(-) delete mode 100644 doc/sai-ptf/config_data/LAG_config_t0.md create mode 100644 doc/sai-ptf/config_data/config_t0.md delete mode 100644 doc/sai-ptf/config_data/fdb_config_t0.md delete mode 100644 doc/sai-ptf/config_data/route_config_t0.md delete mode 100644 doc/sai-ptf/config_data/vlan_config_t0.md diff --git a/doc/sai-ptf/config_data/LAG_config_t0.md b/doc/sai-ptf/config_data/LAG_config_t0.md deleted file mode 100644 index d7fc774ee..000000000 --- a/doc/sai-ptf/config_data/LAG_config_t0.md +++ /dev/null @@ -1,158 +0,0 @@ -# Sample T0 Configurations and data for LAG -- [Sample T0 Configurations and data for LAG](#sample-t0-configurations-and-data-for-lag) - - [Overriew](#overriew) - - [LAG configuration](#lag-configuration) - - [LAG and lag members](#lag-and-lag-members) - - [APIs for LAG configuration](#apis-for-lag-configuration) - - [Create lag and its member](#create-lag-and-its-member) - - [Check LoadBalance](#check-loadBalance) - - [Remove Lag member](#remove-lag-member) - - [Ingress Egreee disable](#ingress-egreee-disable) - - [Sample data/packet](#sample-datapacket) - - [Packet example](#packet-example) - - [config data](#config-data) -## Overriew -This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. - -**Note: This configuration focused on T0 topology.** - -## LAG configuration - -### LAG and LAG members - -|HostIf|VLAN ID|Ports| -|-|-|-| -|Ethernet76-80|lag1|Port17-18| -|Ethernet84-88|lag2|Port19-20| -|Ethernet92-96|lag3|Port21-22| - -## APIs for LAG configuration -APIs relate to LAG and LAG attributes. - -### Create lag and its member -```Python - +------------+------------+-----------+-----------+ - | lag1 | -- | port1 | -- | - | lag1_rif | | port2 | | - | | | | | - +------------+------------+-----------+-----------+ - sai_thrift_create_lag(self.client) - - self.lag1_member1 = sai_thrift_create_lag_member( - self.client, lag_id=self.lag1, port_id=self.port17) - self.lag1_membe2 = sai_thrift_create_lag_member( - self.client, lag_id=self.lag1, port_id=self.port18) - - - self.lag1_rif = sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_PORT, - virtual_router_id=self.default_vrf, - port_id=self.lag1) - -``` -### Check LoadBalance - -```python - - #How to check if each port of Lag receive an equal number of packets (if we have n members in a Lag) - self.packet_numbers =100 - for i in range(0, n): - self.assertTrue((count[i] >= ((self.packet_numbers / n) * 0.7)), - - -``` -### Remove Lag member - -```python - print("Remove LAG2 member 2") - status = sai_thrift_remove_lag_member(self.client, self.lag2_member2) -``` - -### Ingress Egreee disable -```python - status = sai_thrift_set_lag_member_attribute( - self.client, - self.lag3_member2, - ingress_disable=True, - egress_disable=True) - -``` - -## Sample data/packet - -### Packet example -- Input packet -```Python - pkt = simple_tcp_packet( - eth_dst=ROUTER_MAC, - eth_src=srcmac, - ip_dst=dstip, - ip_src=srcip) - - -``` - -- Output packet - ```Python - exp_pkt = simple_tcp_packet( - eth_dst=dstmac, - eth_src=ROUTER_MAC, - ip_dst=dstip, - ip_src=srcip) - ``` - -## config data - -Below is the sample config data in config_db.json - -```JSON - "PORTCHANNEL": { - "PortChannel1": { - "admin_status": "up", - "members": [ - "Ethernet76", - "Ethernet80" - ], - "min_links": "1", - "mtu": "9100" - }, - "PortChannel2": { - "admin_status": "up", - "members": [ - "Ethernet84", - "Ethernet88" - ], - "min_links": "1", - "mtu": "9100" - }, - "PortChannel3": { - "admin_status": "up", - "members": [ - "Ethernet92", - "Ethernet96" - ], - "min_links": "1", - "mtu": "9100" - }, -}, -"PORTCHANNEL_INTERFACE": { - "PortChannel1": {}, - "PortChannel1|10.10.192.19/31": {}, - "PortChannel1|2603:10b0:31f:278::2a/126": {}, - "PortChannel2": {}, - "PortChannel2|10.10.193.19/31": {}, - "PortChannel2|2603:10b0:31f:279::2a/126": {}, - "PortChannel3": {}, - "PortChannel3|10.10.194.19/31": {}, - "PortChannel3|2603:10b0:31f:27a::2a/126": {}, -}, -"PORTCHANNEL_MEMBER": { - "PortChannel1|Ethernet76": {}, - "PortChannel1|Ethernet80": {}, - "PortChannel2|Ethernet84": {}, - "PortChannel2|Ethernet88": {}, - "PortChannel3|Ethernet92": {}, - "PortChannel3|Ethernet96": {}, -}, -``` diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md new file mode 100644 index 000000000..a40d44461 --- /dev/null +++ b/doc/sai-ptf/config_data/config_t0.md @@ -0,0 +1,120 @@ +# Sample T0 Configurations and data for VLAN +- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) + - [Overriew](#overriew) + - [VLAN configuration](#vlan-configuration) + - [VLAN and VLAN members](#vlan-and-vlan-members) + - [VLAN Interfaces](#vlan-interfaces) + - [Json config data](#json-config-data) + - [Route Configuration](#route-configuration) + - [rotue entries](#rotue-entries) + - [LAG configuration](#lag-configuration) + - [LAG and LAG members](#lag-and-lag-members) + - [FDB Configuration](#fdb-configuration) + - [MAC Table](#mac-table) +## Overriew +This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. + +**Note: This configuration focused on T0 topology.** + +## VLAN configuration + +### VLAN and VLAN members + +|HostIf|VLAN ID|Ports|Tag mode| +|-|-|-|-| +|Ethernet4-32|1000|Port1-8|Untag| +|Ethernet36-72|2000|Port9-16|Untag| + +### VLAN Interfaces +|VLAN ID | VLAN Interface IP | VLAN Interface MAC | +|-|-|-| +|1000|192.168.10.1|10:00:01:11:11:11| +|2000|192.168.20.1|20:00:01:22:22:22| + +### Json config data + +Below is the sample config data in config_db.json + +```JSON + { + "VLAN": { + "Vlan1000": { + "members": [ + "Ethernet4", + "Ethernet8", + "Ethernet12", + "Ethernet16", + "Ethernet20", + "Ethernet24", + "Ethernet28", + "Ethernet32" + ], + "vlanid": "1000" + } + }, + "VLAN_INTERFACE": { + "Vlan1000": {}, + "Vlan1000|192.168.0.1/21": {}, + "Vlan1000|fc02:1000::1/64": {} + }, + "VLAN_MEMBER": { + "Vlan1000|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet8": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet12": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet16": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet20": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet24": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet28": { + "tagging_mode": "untagged" + }, + "Vlan1000|Ethernet32": { + "tagging_mode": "untagged" + } + } + } +``` + + +## Route Configuration + +### rotue entries + +VLAN interfaces route entries +|VLAN ID | VLAN Member | NH IP | NH MAC| +|-|-|-|-| +|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | +|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | + + +## LAG configuration + +### LAG and LAG members + +|HostIf|VLAN ID|Ports| +|-|-|-| +|Ethernet76-80|lag1|Port17-18| +|Ethernet84-88|lag2|Port19-20| +|Ethernet92-96|lag3|Port21-22| + + +## FDB Configuration +### MAC Table +The MAC Table for VLAN L2 forwarding as below +|Name|MAC|PORT|VLAN|HostIf| +|-|-|-|-|-| +|mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| +|mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| +|mac9-16 |00:99:99:99:99:99 - 01:66:66:66:66:66|Port9-16|2000|Ethernet36-Ethernet64| +|mac17-mac31 |01:77:77:77:77:77 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| diff --git a/doc/sai-ptf/config_data/fdb_config_t0.md b/doc/sai-ptf/config_data/fdb_config_t0.md deleted file mode 100644 index d6e6ad126..000000000 --- a/doc/sai-ptf/config_data/fdb_config_t0.md +++ /dev/null @@ -1,79 +0,0 @@ -# Sample T0 Configurations and data for FDB -- [Sample T0 Configurations and data for FDB](#sample-t0-configurations-and-data-for-fdb) - - [Overriew](#overriew) - - [FDB Configuration](#fdb-configuration) - - [MAC Table](#mac-table) - - [APIs for FDB configuration](#apis-for-fdb-configuration) - - [Create FDB Entries](#create-fdb-entries) - - [Get FDB entties](#get-fdb-entties) - - [Clear FDB entries in a VLAN](#clear-fdb-entries-in-a-vlan) -## Overriew -This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around FDB testing. -**Note: This configuration focused on T0 topology.** - -## FDB Configuration -### MAC Table -The MAC Table for VLAN L2 forwarding as below -|Name|MAC|PORT|VLAN|HostIf| -|-|-|-|-|-| -|mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| -|mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| -|mac9-16 |00:99:99:99:99:99 - 01:66:66:66:66:66|Port9-16|2000|Ethernet36-Ethernet64| -|mac17-mac31 |01:77:77:77:77:77 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| - - -## APIs for FDB configuration -APIs relate to FDB and FDB attributes. - -**P.S. There are just some sample APIs, for more attributes please refer to https://github.com/richardyu-ms/SAI/blob/support_ptf_sai_build/inc/saifdb.h** - -### Create FDB Entries - -- Add static FDB entry in the FDB table - - In the sample code below, we can see how to create an FDB entry. - - This FDB entry is a static entry, it will ``forward`` packet when the packet is with a mac1 on port1. - ```python - - sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1) - sai_thrift_create_fdb_entry( - self.client, - fdb_entry, - type=SAI_FDB_ENTRY_TYPE_STATIC, - bridge_port_id=Port1, - packet_action=SAI_PACKET_ACTION_FORWARD) - ``` - -- Add static FDB entry with **VLAN ID** in the FDB table - - In the sample code below, we can see how to create an FDB entry. - - This FDB entry is a static entry, it will ``forward`` packet when the packet is with a mac1 on port1. - ```python - - sai_thrift_fdb_entry_t(switch_id=self.switch_id, mac_address=mac1, bv_id=self.vlan_oid) - sai_thrift_create_fdb_entry( - self.client, - fdb_entry, - type=SAI_FDB_ENTRY_TYPE_STATIC, - bridge_port_id=Port1, - packet_action=SAI_PACKET_ACTION_FORWARD) - ``` - -### Get FDB entties - ```python - attr = sai_thrift_get_switch_attribute( - self.client, available_fdb_entry=True) - max_fdb_entry = attr["available_fdb_entry"] - ``` - - -### Clear FDB entries in a VLAN - Clear the learned FDB entries with the VLAN id object id - ```python - sai_thrift_flush_fdb_entries( - self.client, - bv_id=self.vlan_oid, - entry_type=SAI_FDB_ENTRY_TYPE_DYNAMIC) - ``` \ No newline at end of file diff --git a/doc/sai-ptf/config_data/route_config_t0.md b/doc/sai-ptf/config_data/route_config_t0.md deleted file mode 100644 index a8a585fc8..000000000 --- a/doc/sai-ptf/config_data/route_config_t0.md +++ /dev/null @@ -1,148 +0,0 @@ -# Sample T0 Configurations and data for Route -- [Sample T0 Configurations and data for Route](#sample-t0-configurations-and-data-for-route) - - [Overriew](#overriew) - - [Route Configuration](#route-configuration) - - [rotue entries](#rotue-entries) - - [APIs for Route related configuration](#apis-for-route-related-configuration) - - [Create VLAN Interface and Route entry](#create-vlan-interface-and-route-entry) - - [Create LAG Router interface and Route entry](#create-lag-router-interface-and-route-entry) - - [Sample data/packet](#sample-datapacket) - - [Packet example](#packet-example) -## Overriew -This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around Route testing. - -It includes the related data and config for a route, including -- Next Hop -- Neighbor -- Route entry - -**Note: This configuration focused on T0 topology.** - -## Route Configuration - -### rotue entries - -VLAN interfaces route entries -|VLAN ID | VLAN Member | NH IP | NH MAC| -|-|-|-|-| -|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | -|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | - -*For vlan interface related configuration please refer to [VLAN_Config](./VLAN_config.md)** - -## APIs for Route related configuration - -### Create VLAN Interface and Route entry - -Neighbors - -|Name|IP|dest_mac| -|-|-|-| -|nb1-8| 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | -|nb9-16| 192.168.20.11 ~ 192.168.20.18 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | -|nb23-32| 192.168.0.17 ~ 192.168.0.26 | 00:00:77:77:77:77 - 00:00:ff:ff:ff:ff | -|nbvlan1000_gw| 192.168.10.255 | FF:FF:FF:FF:FF:FF | -|nbvlan2000_gw| 192.168.20.255 | FF:FF:FF:FF:FF:FF | - -Route entry - -|DestIp|Next Hop |Next Hop ip| -|-|-|-| -| 192.168.10.11 ~ 192.168.10.18 |port1 - 8 | 192.168.10.11 - 192.168.10.18 | -| 192.168.20.11 ~ 192.168.20.18 | port9 -16 | 192.168.20.11 - 192.168.20.18 | -| 192.168.0.17 ~ 192.168.0.26 | port23-32 | 192.168.0.17 - 192.168.0.26 | -|192.168.10.1|vlanInterface(VLAN1000)|CPU_PORT| -|192.168.20.1|vlanInterface(VLAN2000)|CPU_PORT| - -- Create a Router for a VLAN interface - ```Python - - self.vlan100_rif = sai_thrift_create_router_interface( - self.client, - type=SAI_ROUTER_INTERFACE_TYPE_VLAN, - virtual_router_id=self.default_vrf, - vlan_id=self.vlan1000) - self.rifnh = sai_thrift_create_next_hop( - self.client, ip=sai_ipaddress('192.168.10.1'), - router_interface_id=rif, type=CPU_PORT) - ``` - -- Create VLAN Interface GW - ```python - self.neighbor_entry1 = sai_thrift_neighbor_entry_t( - rif_id=self.vlan100_rif, - ip_address=sai_ipaddress('192.168.20.255'), - dst_mac_address='FF:FF:FF:FF:FF:FF') - ``` - -- Create Port Neighbor and next hop ( Port9 -> DestIP ) - ```Python - rif = sai_thrift_create_router_interface( - self.client, type=SAI_ROUTER_INTERFACE_TYPE_PORT, - port_id=self.port9, virtual_router_id=self.vr) - rifnh = sai_thrift_create_next_hop( - self.client, ip=sai_ipaddress('192.168.20.2'), - router_interface_id=rif, type=SAI_NEXT_HOP_TYPE_IP) - self.neighbor_entry1 = sai_thrift_neighbor_entry_t( - rif_id=self.rif, - ip_address=sai_ipaddress('192.168.20.2'), - dst_mac_address='20:00:11:11:11:11') - self.route_entry1 = sai_thrift_route_entry_t( - vr_id=self.default_vrf, - destination=sai_ipprefix('192.168.20.2'+'/32')) # Packet dest IP - sai_thrift_create_route_entry( - self.client, self.route_entry1, next_hop_id=self.nhop1) - ``` -### Create LAG Router interface and Route entry - -Neighbors - -|Name|IP|dest_mac| -|-|-|-| -|lag1_nb| 192.168.0.11 | 00:00:11:11:11:11 | -|lag2_nb| 1 192.168.0.12|00:00:22:22:22:22 | -|lag3_nb| 192.168.0.13| 00:00:33:33:33:33 | -Route entry - -|DestIp|Next Hop |Next Hop ip| -|-|-|-| -| 192.168.0.11 |lag1:port17-18|192.168.0.11 | -|192.168.0.12 |lag2: port19 -20 | 192.168.0.12 | -| 192.168.0.13 | lag3:port21-22 | 192.168.0.13 | - -```Python - nhop = sai_thrift_create_next_hop(self.client, - ip=sai_ipaddress('192.168.0.11'), - router_interface_id=self.lag1_rif, - type=SAI_NEXT_HOP_TYPE_IP) - neighbor_entry = sai_thrift_neighbor_entry_t( - rif_id=self.lag1_rif, ip_address=sai_ipaddress('192.168.0.11')) - sai_thrift_create_neighbor_entry(self.client, neighbor_entry, - dst_mac_address='00:11:11:11:11:11') - route1 = sai_thrift_route_entry_t( - vr_id=self.default_vrf, destination=sai_ipprefix('192.168.0.11/32')) - sai_thrift_create_route_entry(self.client, route1, next_hop_id=nhop) - - -## Sample data/packet - -### Packet example -When routing a packet, it will check the neighbor/adjacent table, and based on the Next-hop table, change the SRC MAC and Dest MAC. - -- Input Packet - ```Python - simple_tcp_packet( - eth_dst=SW_MAC, - eth_src=SRC_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` - -- Output Packet - ```Python - simple_tcp_packet( - eth_dst=PORT_MAC, - eth_src=SW_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` diff --git a/doc/sai-ptf/config_data/vlan_config_t0.md b/doc/sai-ptf/config_data/vlan_config_t0.md deleted file mode 100644 index f5444545a..000000000 --- a/doc/sai-ptf/config_data/vlan_config_t0.md +++ /dev/null @@ -1,187 +0,0 @@ -# Sample T0 Configurations and data for VLAN -- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) - - [Overriew](#overriew) - - [VLAN configuration](#vlan-configuration) - - [VLAN and VLAN members](#vlan-and-vlan-members) - - [VLAN Interfaces](#vlan-interfaces) - - [APIs for VLAN configuration](#apis-for-vlan-configuration) - - [Create vlan and its member](#create-vlan-and-its-member) - - [Get VLAN, VLAN members, and attributes](#get-vlan-vlan-members-and-attributes) - - [Update VLAN, VLAN members and attributes](#update-vlan-vlan-members-and-attributes) - - [Delete VLAN and VLAN members](#delete-vlan-and-vlan-members) - - [Sample data/packet](#sample-datapacket) - - [Packet example](#packet-example) - - [config data](#config-data) -## Overriew -This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. - -**Note: This configuration focused on T0 topology.** - -## VLAN configuration - -### VLAN and VLAN members - -|HostIf|VLAN ID|Ports|Tag mode| -|-|-|-|-| -|Ethernet4-32|1000|Port1-8|Untag| -|Ethernet36-72|2000|Port9-16|Untag| - -### VLAN Interfaces -|VLAN ID | VLAN Interface IP | VLAN Interface MAC | -|-|-|-| -|1000|192.168.10.1|10:00:01:11:11:11| -|2000|192.168.20.1|20:00:01:22:22:22| - -## APIs for VLAN configuration -APIs relate to VLAN and VLAN attributes. - -**P.S. There are just some sample APIs, for more attributes please refer to https://github.com/richardyu-ms/SAI/blob/support_ptf_sai_build/inc/saivlan.h** - -### Create vlan and its member -- Create Vlan 1000 - ```Python - self.vlan1000 = sai_thrift_create_vlan(self.client, vlan_id=1000) - ``` -- Create VLAN members with different modes - Untag mode and access port - ```python - ---------------------------------- - |VLAN ID|Ports|Tag mode| HostIf | - |-------|-----|--------|---------| - | 1000 |Port1| Untag |Ethernet4| - ---------------------------------- - - self.vlan_member1 = sai_thrift_create_vlan_member( - self.client, - vlan_id=1000, - bridge_port_id=port_bridge_port1, - vlan_tagging_mode=SAI_VLAN_TAGGING_MODE_UNTAGGED) - - ``` -### Get VLAN, VLAN members, and attributes -- Get VLAN member list -```Python -vlan_member_list = sai_thrift_object_list_t(count=1000) -mbr_list = sai_thrift_get_vlan_attribute( - self.client, self.vlan10, member_list=vlan_member_list) -vlan_members = mbr_list['SAI_VLAN_ATTR_MEMBER_LIST'].idlist -#equals to vlan_members = mbr_list['member_list'].idlist -``` -- Get VLAN - -```python - vlan_attr = sai_thrift_get_vlan_attribute( - self.client, vlan_oid=1000, learn_disable=True) -``` -- Get counters -```Python - stats = sai_thrift_get_vlan_stats(self.client, self.vlan10) - in_bytes = stats["SAI_VLAN_STAT_IN_OCTETS"] - out_bytes = stats["SAI_VLAN_STAT_OUT_OCTETS"] - in_packets = stats["SAI_VLAN_STAT_IN_PACKETS"] - in_ucast_packets = stats["SAI_VLAN_STAT_IN_UCAST_PKTS"] - out_packets = stats["SAI_VLAN_STAT_OUT_PACKETS"] - out_ucast_packets = stats["SAI_VLAN_STAT_OUT_UCAST_PKTS"] - -``` - -### Update VLAN, VLAN members and attributes -- Set mac learning - ```python - sai_thrift_set_vlan_attribute(self.client, self.vlan20, learn_disable=True) - ``` -- Set Native vlan 1000 on a port - ```python - sai_thrift_set_port_attribute(self.client, port_id, port_vlan_id=1000) - ``` -- Clear counters - ```Python - sai_thrift_clear_vlan_stats(self.client, self.vlan10) - ``` - -### Delete VLAN and VLAN members -- Remoev VLAN member - ```python - sai_thrift_remove_vlan_member(self.client, self.vlan_member1) - ``` -- Remoev VLAN - ```python - sai_thrift_remove_vlan(self.client, self.vlan1000) - ``` - -## Sample data/packet - -### Packet example -- Tagged packet with VLAN id - - When a packet sent to a access port or send out from a access port, we will get a packet without the VLAN id. - *In T0, we don't need to test tagged packet.* - ```python - tagged_packet(eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - vlan_vid=1000, - ip_dst='172.16.0.1', - ip_ttl=64) - ``` -- Untagged packet - ```Python - simple_tcp_packet(eth_dst='00:11:11:11:11:11', - eth_src='00:22:22:22:22:22', - ip_dst='172.16.0.1', - ip_ttl=64) - ``` - -## config data - -Below is the sample config data in config_db.json - -```JSON - { - "VLAN": { - "Vlan1000": { - "members": [ - "Ethernet4", - "Ethernet8", - "Ethernet12", - "Ethernet16", - "Ethernet20", - "Ethernet24", - "Ethernet28", - "Ethernet32" - ], - "vlanid": "1000" - } - }, - "VLAN_INTERFACE": { - "Vlan1000": {}, - "Vlan1000|192.168.0.1/21": {}, - "Vlan1000|fc02:1000::1/64": {} - }, - "VLAN_MEMBER": { - "Vlan1000|Ethernet4": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet8": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet12": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet16": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet20": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet24": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet28": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet32": { - "tagging_mode": "untagged" - } - } - } -``` \ No newline at end of file diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 289b84629..457eb652d 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -1,90 +1,71 @@ # SAI VLAN Test plan -- [Overriew](#overriew) -- [Test Environment](#test-environment) - - [Testbed](#testbed) - - [Test Configuration](#test-configuration) - - [Variations](#variations) +- [Test Configuration](#test-configuration) - [Test Execution](#test-execution) - - [Basic function test](#basic-function-test) - - [Untagging and access](#untagging-and-access) - - [Testing Objective](#testing-objective) - - [Test Data/Packet](#test-datapacket) - - [Test Cases](#test-cases) - - [Frame Filtering](#frame-filtering) - - [Testing Objective](#testing-objective-1) - - [Test Data/Packet](#test-datapacket-1) - - [Additional config:](#additional-config) - - [Test Cases](#test-cases-1) - - [MAC learning](#mac-learning) - - [Testing Objective](#testing-objective-2) - - [Test Data/Packet](#test-datapacket-2) - - [Additional config:](#additional-config-1) - - [Test Cases](#test-cases-2) - - [SAI API test](#sai-api-test) - - [Vlan member list](#vlan-member-list) - - [Testing Objective](#testing-objective-3) - - [Test Cases](#test-cases-3) - - [VLAN related counters.](#vlan-related-counters) - - [Testing Objective](#testing-objective-4) - - [Test Data/Packet](#test-datapacket-3) - - [Test Cases](#test-cases-4) - - [Disable mac learning](#disable-mac-learning) - - [Testing Objective](#testing-objective-5) - - [Test Data/Packet](#test-datapacket-4) - - [Additional config:](#additional-config-2) - - [Test Cases](#test-cases-5) - - [Composit scenario](#composit-scenario) - - [L3 switching(Inter-VLAN)](#l3-switchinginter-vlan) - - [Testing Objective](#testing-objective-6) - - [Test Data/Packet](#test-datapacket-5) - - [Test Cases](#test-cases-6) - - [ARP Flooding and mac learning](#arp-flooding-and-mac-learning) - - [Testing Objective](#testing-objective-7) - - [Test Data/Packet](#test-datapacket-6) - - [Additional config:](#additional-config-3) - - [Test Cases](#test-cases-7) -# Overriew -The purpose of this test plan is to test the VLAN function from SAI. - -The test will include three parts -- Vlan functionalities -- SAI APIs operations -- Composit scenario - -# Test Environment -## Testbed -Those tests will be run on the testbed structure, the components are: -* PTF - running in a server that can connect to the target DUT -* SAI server - running on a dut -## Test Configuration + - [Common Test Data/Packet](#common-test-datapacket) + - [Test Group: Tagging and access](#test-group-tagging-and-access) + - [Case1: test_untag_access_to_access](#case1-test_untag_access_to_access) + - [Case2: test_tag_access_to_access](#case2-test_tag_access_to_access) + - [Test Group: Frame Filtering](#test-group-frame-filtering) + - [Case3: test_untagged_frame_filtering](#case3-test_untagged_frame_filtering) + - [Case4: test_tagged_frame_filtering](#case4-test_tagged_frame_filtering) + - [Test Group: VLAN flooding](#test-group-vlan-flooding) + - [Case5: test_tagged_vlan_flooding](#case5-test_tagged_vlan_flooding) + - [Case6: test_untagged_vlan_flooding](#case6-test_untagged_vlan_flooding) + - [Test Group: MAC learning](#test-group-mac-learning) + - [Case7: test_untagged_mac_learning](#case7-test_untagged_mac_learning) + - [Case8: test_tagged_mac_learning](#case8-test_tagged_mac_learning) + - [Test Case9: Vlan member API](#test-case9-vlan-member-api) + - [Test Case10: Add to illegal VLAN failure](#test-case10-add-to-illegal-vlan-failure) + - [Test Group: VLAN Counters/Status](#test-group-vlan-countersstatus) + - [Case11: test_tagged_vlan_status](#case11-test_tagged_vlan_status) + - [Case12: test_untagged_vlan_status](#case12-test_untagged_vlan_status) + - [Test Group7: Disable mac learning](#test-group7-disable-mac-learning) + - [Case13: test_disable_mac_learning_tagged](#case13-test_disable_mac_learning_tagged) + - [Case14: test_disable_mac_learning_untagged](#case14-test_disable_mac_learning_untagged) + - [Test Case15: L3 switching(Inter-VLAN)](#test-case15-l3-switchinginter-vlan) + - [Test Group: ARP Flooding and mac learning](#test-group-arp-flooding-and-mac-learning) + - [Case16: test_arp_request_flooding](#case16-test_arp_request_flooding) + - [Case17: test_arp_response_learning](#case17-test_arp_response_learning) +# Test Configuration For the test configuration, please refer to the file - - [VLAN_config](./config_data/vlan_config_t0.md) - - [FDB_config](./config_data/fdb_config_t0.md) - - [Route_config](./config_data/route_config_t0.md) + - [Config_t0](./config_data/config_t0.md) **Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** -*p.s. Please refer the sample packet in [VLAN_config#Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket)* - -## Variations -Cause the testbed might also encounter some issues like the host interface being down. -Before running the actual test there will need some sanity test to check the DUT status and select the active ports for testing. - -**All the ports in this test plan just to illustrate the test purpose, they are not exactly the same for the actual environment.** - # Test Execution -## Basic function test -### Untagging and access +## Common Test Data/Packet +In this VLAN test, most of test case will be tested with Tagged or Untagged packet, the example packet structure as below. +- Tagged packet with VLAN id + + ```python + tagged_packet(eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + vlan_vid=1000, + ip_dst='172.16.0.1', + ip_ttl=64) + ``` +- Untagged packet + ```Python + simple_tcp_packet(eth_dst='00:11:11:11:11:11', + eth_src='00:22:22:22:22:22', + ip_dst='172.16.0.1', + ip_ttl=64) + ``` +**Note. If need other kinds of packet, it will be added in the test case/group respectively.** -#### Testing Objective -This test verifies the VLAN function around untag and access ports. +## Test Group: Tagging and access +### Case1: test_untag_access_to_access +### Case2: test_tag_access_to_access -*p.s. This test will not check function with the native VLAN scenario (it will be in other tests). Please make sure the native VLAN will not impact the result.* +### Testing Objective +This test verifies the VLAN function around untag and access ports. +**This test will cover tagged and untagged mode respectivily.** +*p.s. This test will not check function with the native VLAN scenario. Please make sure the native VLAN will not impact the result.* With an untagged packet, on the access port, when ingress and egress happen, the behavior as below | Port mode | packet tag mode | Direction | Action | @@ -103,142 +84,133 @@ Tagged: pkt(Tag:VLAN2000:DMAC=MAC10) -> Port9:Access:VLAN2000-> Port10:Access:VLAN2000 -> pkt(Untag:DMAC=MAC10) ``` -#### Test Data/Packet -[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) -- Input: Packet(Untag) and Packet(Tag) -- Expected: Packet(Tag) - - *p.s. please refer the sample packet in [VLAN_config#Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket)* - -#### Test Cases -| Goal| Cases | Expect | -|-|-|-| -|``Untag``:Acess -> Acess port.| Send VLAN1000 ``Untagged`` packet on Port1 with mac2 as dest mac. | ``Untag`` packet received on port2.| -|``Tag``:Acess -> Acess port.| Send VLAN2000 ``Untagged`` packet on Port9 with mac10 mac as dest mac. | ``Untag`` packet received on port10.| +### Test steps: +Test Steps: + - Create ``Untagged``/``Tagged VLAN 1000`` packet with ``mac2`` as dest mac. + - Send packet on Port1. + - Verify ``Untagged`` packet received port2. -### Frame Filtering -#### Testing Objective +## Test Group: Frame Filtering +### Case3: test_untagged_frame_filtering +### Case4: test_tagged_frame_filtering +### Testing Objective Drop packet when the destination port from MAC table search is the port which packet come into the switch. +**This test will cover tagged and untagged mode respectivily.** + ``` -Test example: +Test example(Untag): | MAC1 | pkt(Untag:DMAC=MAC1 or MACX) -> Port1:Access:VLAN1000 -> FDB(contains:MAC1,MACX)| | -> X | MACX | ``` -#### Test Data/Packet - -[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) -- Input: Packet(Untag) -- Expected: Drop - -#### Additional config: -- Add a non-existing ``MacX`` to port1 - -#### Test Cases -| Goal | Case | Expect | -|-|-|-| -| Filter frame. | Send VLAN1000 ``Untagged`` packet with dest ``MacX`` on ``port1``. |Packet dropped| -| Filter frame. | Send VLAN1000 ``Untagged`` packet with dest ``MAC1`` on ``port1``. |Packet dropped| - - - -### MAC learning -#### Testing Objective -For mac learning in VLAN scenario, in contain those two cases -1. the packet sent to the VLAN port will flood to other ports in the same VLAN before learning the mac address from the packet -2. The packet is only sent to the target port when the MAC table contains the MAC address on the target port(Dest MAC). - - +### Test steps + - Add another ``MacX`` as Port1 mac address into MAC table + - Create ``Untagged``/``Tagged VLAN1000`` packet, ``mac1`` as src mac, ``MacX`` as dest mac + - Send packet on VLAN Port. + - Verify no packet received on any port. + +## Test Group: VLAN flooding +### Case5: test_tagged_vlan_flooding +### Case6: test_untagged_vlan_flooding +### Testing Objective +For mac flooding in VLAN scenario, before learning the mac address from the packet, the packet sends to the VLAN port will flood to other ports, the egress ports will be in the same VLAN as ingress port. ``` -1. Flooding +Flooding | Port2| pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000 -> Flooding ->| To |-> pkt(Untag) | Port8| - -2. unicast - pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) - ``` -#### Test Data/Packet +**This test will cover tagged and untagged mode respectivily.** -[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) -- Input: Packet(Untag) -- Expected: Packet(Untag) +### Test Steps: + - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as source MAC and a un-existing ``MacX`` as dest MAC + - Send packet on Port1. + - Verify received packet on all port expect Port1. -#### Additional config: -- Do not config the MAC table +## Test Group: MAC learning +### Case7: test_untagged_mac_learning +### Case8: test_tagged_mac_learning +### Testing Objective +For mac learning in VLAN scenario, after learning the mac address from the packet, the packet sends to the VLAN port will only sends to the port whose MAC address matching the MAC table entry. -#### Test Cases -| Goal | Case | Expect | -|-|-|-| -| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac2`` on ``port1``. |Receive ``Untagged`` packet from Port2 to Port8| -|MAC learning|check the FDB entries.|New mac entries in FDB.| -| Forwarding based on MAC table.| Send a ``Untagged`` packet with src:mac2, dest:mac1 on port2.| Receive ``Untagged`` packet on Port1| -|MAC learning|check the FDB entries.|New mac entries in FDB.| +``` + unicast + pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) +``` +**This test will cover tagged and untagged mode respectivily.** +### Test Steps: + - Create ``Untagged``/``Tagged VLAN1000`` packet, with a un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC + - Send packet on a VLAN source port1. + - Verify packet received on port2. + - Verify MAC table get a new entry for ``MacX`` on port1, -## SAI API test -### Vlan member list -#### Testing Objective +## Test Case9: Vlan member API + - test_vlan_member_api -Test VLAN and member list. +### Testing Objective -#### Test Cases -| Goal | Cases | Expect | -|-|-|-| -| VLAN APIs get VLAN and its member. |Use the SAI API to check the VLAN and its member.| VLAN and VLAN member list.| -| Remove VLAN and its member.|Remove the VLAN member from VLAN 1000 and remove VLAN. | VLAN and its member removed.| -| Error when creating member to un-exist VLAN. |Use the SAI API to create a VLAN member on VLAN 1000 | Error happened.| +Test VLAN and member APIs. -### VLAN related counters. -#### Testing Objective +### Test steps: +Test steps: + - Use VLAN API to list all of the VLAN member in VLAN + - Verify the VLAN member and the account of the VLAN member are same as config in [config](./config_data/config_t0.md) + - Use VLAN API add a new Member, into VLAN + - Verify the VLAN member and the account of the VLAN member are increased by 1. -For VLAN-related counters, SAI should be able to get the counter and clear them. +## Test Case10: Add to illegal VLAN failure + - test_add_vlan_member_failed +### Testing Objective -#### Test Data/Packet -[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) -- Input: Packet(Untag) -- Expected: Packet(Untag) +When add a VLAN member to a non-exist VLAN, it will fail. -#### Test Cases -| Goal |Cases | Expect | -|-|-|-| -| Packet Forwarding.|Send VLAN1000 ``Untagged`` packet on Port1 with port2 mac as dest mac. | ``Untagged`` packet received on port3.| -| Counter Changed accordingly.|Use the SAI API to check the counters | Counter increased, bytes counter: OCTETS increased, other counters + 1| -| Counter reset.|Use the SAI API to clear the counters.| Related counter is reset to zero. | +### Test Steps: + - Use VLAN API add a new Member to a non-exist VLAN, ``VLAN1010`` + - Verify the VLAN member added failed. +## Test Group: VLAN Counters/Status +### Case11: test_tagged_vlan_status +### Case12: test_untagged_vlan_status +### Testing Objective -### Disable mac learning -#### Testing Objective +For VLAN-related counters, SAI should be able to get the counter and clear them. +**This test will cover tagged and untagged mode respectivily.** + +### Test Steps: +Steps: + - Use SAI API to get the VLAN Status ``_sai_vlan_stat_t`` from [VLAN_HEADER](https://github.com/opencomputeproject/SAI/blob/master/inc/saivlan.h) + - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + - Send packet from the source port1 + - Verify packet received on the target port2 + - Verify counters increased, bytes counter: OCTETS increased, other counters + 1 + - Use VLAN clear status API + - Verify counters have been reset + +## Test Group7: Disable mac learning +### Case13: test_disable_mac_learning_tagged +### Case14: test_disable_mac_learning_untagged +### Testing Objective Test the function when disabling VLAN MAC learning. When disabled, no new MAC will be learned in the MAC table. +**This test will cover tagged and untagged mode respectivily.** -#### Test Data/Packet - -[Sample_Packet](./config_data/vlan_config_t0.md#sample-datapacket) -- Input: Packet(Untag) -- Expected: Packet(Untag) - -#### Additional config: +### Additional config: - Do not config the MAC table -#### Test Cases -| Goal | Case | Expect | -|-|-|-| -| Disable Vlan MAC learning. | Set the VLAN attribute to disable the VLAN MAC learning. |VLAN attribute set.| -| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac2`` on ``port1``. |Receive ``Untagged`` packet from Port2 to Port8| -| Flooding in VLAN. | Send ``Untagged`` packet with dest ``mac1`` on ``port2``. |Receive ``Untagged`` packet on ports except for port2.| -|MAC learning|check the FDB entries.|No new mac entries in FDB.| - -## Composit scenario +### Test steps: + - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + - Send packet from the source port1. + - Verify packets received on all ports except the source port1. + - Verify MAC table, no new entry added in MAC table -### L3 switching(Inter-VLAN) -#### Testing Objective +## Test Case15: L3 switching(Inter-VLAN) +### Testing Objective Testing L3 switching(Inter-VLAN). @@ -256,7 +228,7 @@ The process is as below: 2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT MAC, forwarding to PORT9 3. Packet goes through VLAN2000 port9 -#### Test Data/Packet +### Test Data/Packet - Input Packet ```Python simple_tcp_packet( @@ -274,16 +246,15 @@ The process is as below: ip_dst=DEST_IP, ip_src=SRC_IP) ``` -#### Test Cases -| Goal | Case | Expect | -|-|-|-| -| Inter-VLAN switching .| Send ``Untagged`` packet on port1 with dest ``SVI_MAC``. | ``Untagged`` packet received on ``PORT9``.| - - - - -### ARP Flooding and mac learning -#### Testing Objective +### Test Steps: + - Create Packet, with with dest ``SVI_MAC`` as dest mac, and dest IP ``192.168.20.21``(config as [Config_t0](./config_data/config_t0.md)) + - Send ``Untagged`` packet on ``port1`` + - Verify ``Untagged`` packet received on ``PORT9`` + +## Test Group: ARP Flooding and mac learning +### Case16: test_arp_request_flooding +### Case17: test_arp_response_learning +### Testing Objective In the ARP scenario, the mac learning process is: 1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff 2. After the target port gets the ARP packet MAC table fills with port SRC MAC. @@ -303,7 +274,7 @@ Test example: ARP Resp pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) ``` -#### Test Data/Packet +### Test Data/Packet **Both those two packets will be used in input and output.** - ARP request ```Python @@ -340,13 +311,15 @@ Test example: hw_tgt=MAC2) ``` -#### Additional config: +### Additional config: - Do not config the MAC table -#### Test Cases -| Goal | Case | Expect | -|-|-|-| -| ARP Request flooding. | Send ``Untagged`` ARP packet with dest ``mac2`` on ``port1``. |``Untagged`` Arp request from Port2 to Port8| -|MAC learning|check the FDB entries.|New mac entries in FDB.| -| ARP response Forwarding.| Send a ``Untagged`` ARP response packet with src:mac2, dest:mac1 on port2.|``Untagged`` ARP response from Port1| -|MAC learning|check the FDB entries.|New mac entries in FDB.| +### Test Steps: +- test_arp_request_flooding + - Create ARP packet with dest ``mac2`` + - Send ``Untagged`` ARP packet on ``port1`` + - Verify ``Untagged`` Arp request received from Port2 to Port8 +- test_arp_response_learning + - Create ARP response packet with src:mac2, dest:mac1 + - Send ARP response packet on port2 + - Verify ``Untagged`` ARP response from Port1 From 12f90e786e4e41aa8b9618bb24e82f40a03e952d Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Mon, 6 Jun 2022 21:49:16 +0800 Subject: [PATCH 10/18] refactor lag test plan (#33) Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/config_t0.md | 17 ++- doc/sai-ptf/lag_test_plan.md | 161 ++++++++++++--------------- 2 files changed, 87 insertions(+), 91 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index a40d44461..973ba7e40 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -9,6 +9,7 @@ - [rotue entries](#rotue-entries) - [LAG configuration](#lag-configuration) - [LAG and LAG members](#lag-and-lag-members) + - [LAG route and neighbor config](#lag-route-and-neighbor-config) - [FDB Configuration](#fdb-configuration) - [MAC Table](#mac-table) ## Overriew @@ -102,12 +103,22 @@ VLAN interfaces route entries ### LAG and LAG members -|HostIf|VLAN ID|Ports| +|HostIf|LAG ID|Ports| |-|-|-| |Ethernet76-80|lag1|Port17-18| -|Ethernet84-88|lag2|Port19-20| -|Ethernet92-96|lag3|Port21-22| +### LAG route and neighbor config +Neighbors + +|Name|IP|dest_mac| +|-|-|-| +|lag1_nb1-nb8| 192.168.0.11-192.168.0.18| 00:00:11:11:11:11-00:00:88:88:88:88| + +Route entry + +|DestIp|Next Hop |Next Hop ip| +|-|-|-| +|192.168.0.11-192.168.0.18|lag1:port17-18|192.168.0.11-192.168.0.18| ## FDB Configuration ### MAC Table diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index dd1720063..b560a4428 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -1,103 +1,88 @@ # SAI Lag Test plan - [SAI Lag Test plan](#sai-lag-test-plan) - [Overriew](#overriew) -- [Test Environment](#test-environment) - - [Testbed](#testbed) - - [Test Configuration](#test-configuration) - - [Variations](#variations) +- [Test Configuration](#test-configuration) - [Test Execution](#test-execution) - - [Basic function test](#basic-function-test) - - [PortChannel Loadbalanceing](#portchannel-loadbalanceing) - - [Testing Objective](#testing-objective) - - [Test Data/Packet](#test-datapacket) - - [Test Cases](#test-cases) - - [SAI API test](#sai-api-test) - - [Renove lag member](#remove-lag-member) - - [Testing Objective](#testing-objective) - - [Test Cases](#test-cases) - - [Disable Lag memeber](#disable-lag-memeber.) - - [Testing Objective](#testing-objective) - - [Test Data/Packet](#test-datapacket) - - [Test Cases](#test-case) + - [Test Data/Packet](#test-datapacket) + - [Test Group: L3 PortChannel Loadbalanceing](#test-group-l3-portchannel-loadbalanceing) + - [Testing Objective](#testing-objective) + - [Case2: Change destinstion_port](#case2-change-destinstion_port) + - [Case3: Change source_ip](#case3-change-source_ip) + - [Case4: Change destinstion_ip](#case4-change-destinstion_ip) + - [Case5: Case5: Change protocol](#case4-change-protocol) -## Overriew +# Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. -# Test Environment -## Testbed -Those tests will be run on the testbed structure, the components are: -* PTF - running in a server that can connect to the target DUT -* SAI server - running on a dut -## Test Configuration -For the test configuration, please refer to the file - - [VLAN_config](./config_data/vlan_config_t0.md) - - [FDB_config](./config_data/fdb_config_t0.md) - - [Route_config](./config_data/route_config_t0.md) - - [LAG_config](./config_data/LAG_config_t0.md) +# Test Configuration +For the test configuration, please refer to LAG configuration section ofthe file + - [Config_t0](./config_data/config_t0.md) **Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** -## Variations -Cause the testbed might also encounter some issues like the host interface being down. -Before running the actual test there will need some sanity test to check the DUT status and select the active ports for testing. - -**All the ports in this test plan just to illustrate the test purpose, they are not exactly the same for the actual environment.** - # Test Execution -## Basic function test - -### PortChannel Loadbalanceing -#### Testing Objective -For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side -Even after removing and disabling the port in a lag. - -#### Test Data/Packet - -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet - -#### Test Cases -| Goal| Steps/Cases | Expect | -|-|-|-| -| Prepare to send from port0 to Lag1.| Send packet with.| Lag1 and members have been created.| -| Packet forwards on port equally.| Send packet on port0 to the lag1 100 times .| Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, disable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, enable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, remove one lag member, then send packet | Loadbalance on lag members.| - - - -## SAI API test -### Remove Lag member -#### Testing Objective -Test verifies the LAG load balancing for scenario when LAG members are removed. - - -#### Test Data/Packet - -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet - -#### Test Cases -| Goal | Steps/Cases | Expect | -|-|-|-| -|Remove lag2_member2 and forwarding packet from port0 to lag2|Remove lag2_member2 form Lag2 and Send packet on port0 to lag2 100 times| Port0 will receive an equal number of packets.| - - -### Disable Lag memeber -For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. - -#### Test Data/Packet +## Test Data/Packet +```Python +pkt = simple_udp_packet(eth_dst=ROUTER_MAC, + eth_src=src_mac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + udp_sport=udp_sport, + udp_dport=udp_dport, + ip_id=106, + ip_ttl=64) + + exp_pkt = simple_udp_packet(eth_dst=dstmac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + udp_sport=udp_sport, + udp_dport=udp_dport, + ip_id=106, + ip_ttl=63) +``` +TCP Packet +```Python +pkt = simple_tcp_packet(eth_dst=ROUTER_MAC, + eth_src=src_mac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + tcp_sport=tcp_sport, + tcpp_dport=tcp_dport, + ip_id=106, + ip_ttl=64) + + exp_pkt = simple_udp_packet(eth_dst=dstmac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + tcp_sport=tcp_sport, + tcp_dport=tcp_dport, + ip_id=106, + ip_ttl=63) +``` + +## Test Group: L3 PortChannel Loadbalanceing +These cases will cover five scenarios: src/dst ip, src/dst port , protocol + +### Case1: Change source_port +### Case2: Change destinstion_port +### Case3: Change source_ip +### Case4: Change destinstion_ip +### Case5: Change protocol + + +### Testing Objective +For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. + +### Test steps: +Test steps: + - 1.Set switch hash attribute as (SAI_NATIVE_HASH_FIELD_SRC_IP, + SAI_NATIVE_HASH_FIELD_DST_IP, + SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, + SAI_NATIVE_HASH_FIELD_L4_DST_PORT, + SAI_NATIVE_HASH_FIELD_L4_SRC_PORT), which mean switch computes hash value using the five fields of packet. + - 2.Gerate different packets by updating source port/destination port/source ip/destination ip of packet. + - 3.Send these packetes on port0 to the lag1. Check if packet forwards on ports of lag1 equally. -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet -#### Test Cases -| Goal | Steps/Cases | Expect | -|-|-|-| -|Packet dropped on port22| Disable egress and ingress on lag3 member2. send packet | Packet drop.| From 9c526f2526922c4e59efc3bfac283b72597e4972 Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Tue, 7 Jun 2022 07:16:22 -0700 Subject: [PATCH 11/18] refactor pc and vlan test Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/config_t0.md | 38 ++++- doc/sai-ptf/lag_test_plan.md | 199 +++++++++++++++------------ doc/sai-ptf/vlan_test_plan.md | 4 +- 3 files changed, 147 insertions(+), 94 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index a40d44461..9fb34a598 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -12,7 +12,7 @@ - [FDB Configuration](#fdb-configuration) - [MAC Table](#mac-table) ## Overriew -This document describes the sample configuration data, sample test data/packet, and APIs to make the configuration that is used around VLAN testing. +This document describes the sample configuration data. **Note: This configuration focused on T0 topology.** @@ -97,18 +97,46 @@ VLAN interfaces route entries |1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | |2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | +VLAN Neighbors +|Name|IP|dest_mac| +|-|-|-| +|vlan1000_nb1-nb8| 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88| +|vlan2000_nb1-nb8|192.168.20.21 ~ 192.168.20.28 |20:00:11:11:11:11 - 20:00:88:88:88:88 | + + +|Name|IP|dest_mac| +|-|-|-| +|lag1_nb1-nb8| 192.168.0.11-192.168.0.18| 00:00:11:11:11:11-00:00:88:88:88:88| +|lag2_nb1|192.168.0.19|00:00:99:99:99:99| +|lag3_nb1|192.168.0.20|00:00:aa:aa:aa:aa| + +LAG Route entry + +|DestIp|Next Hop |Next Hop ip| +|-|-|-| +|192.168.0.11-192.168.0.18|lag1:port17-18|192.168.0.11-192.168.0.18| +|192.168.0.19|lag2:port19-20|192.168.0.19| +|192.168.0.20|lag3:port21-22|192.168.0.20| + +LAG Neighbors + +|Name|IP|dest_mac| +|-|-|-| +|lag1_nb1-nb8| 192.168.0.11-192.168.0.18| 00:00:11:11:11:11-00:00:88:88:88:88| +|lag2_nb1|192.168.0.19|00:00:99:99:99:99| +|lag3_nb1|192.168.0.20|00:00:aa:aa:aa:aa| + ## LAG configuration ### LAG and LAG members -|HostIf|VLAN ID|Ports| +|HostIf|LAG ID|Ports| |-|-|-| |Ethernet76-80|lag1|Port17-18| |Ethernet84-88|lag2|Port19-20| |Ethernet92-96|lag3|Port21-22| - ## FDB Configuration ### MAC Table The MAC Table for VLAN L2 forwarding as below @@ -116,5 +144,5 @@ The MAC Table for VLAN L2 forwarding as below |-|-|-|-|-| |mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| |mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| -|mac9-16 |00:99:99:99:99:99 - 01:66:66:66:66:66|Port9-16|2000|Ethernet36-Ethernet64| -|mac17-mac31 |01:77:77:77:77:77 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| +|mac9-16 |00:99:99:99:99:99 - 01:00:00:00:00:00|Port9-16|2000|Ethernet36-Ethernet64| +|mac17-mac31 |01:11:11:11:11:11 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index dd1720063..9cdba020d 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -1,103 +1,128 @@ # SAI Lag Test plan - [SAI Lag Test plan](#sai-lag-test-plan) - [Overriew](#overriew) -- [Test Environment](#test-environment) - - [Testbed](#testbed) - - [Test Configuration](#test-configuration) - - [Variations](#variations) +- [Test Configuration](#test-configuration) - [Test Execution](#test-execution) - - [Basic function test](#basic-function-test) - - [PortChannel Loadbalanceing](#portchannel-loadbalanceing) - - [Testing Objective](#testing-objective) - - [Test Data/Packet](#test-datapacket) - - [Test Cases](#test-cases) - - [SAI API test](#sai-api-test) - - [Renove lag member](#remove-lag-member) - - [Testing Objective](#testing-objective) - - [Test Cases](#test-cases) - - [Disable Lag memeber](#disable-lag-memeber.) - - [Testing Objective](#testing-objective) - - [Test Data/Packet](#test-datapacket) - - [Test Cases](#test-case) - -## Overriew + - [Test Data/Packet](#test-datapacket) + - [Test Group: L3 PortChannel Loadbalanceing](#test-group-l3-portchannel-loadbalanceing) + - [Case1: Change source_port](#case1-change-source_port) + - [Case2: Change destinstion_port](#case2-change-destinstion_port) + - [Case3: Change source_ip](#case3-change-source_ip) + - [Case4: Change destinstion_ip](#case4-change-destinstion_ip) + - [Case5: Change protocol](#case5-change-protocol) + - [Testing Objective](#testing-objective) + - [Test Group: Disable Egress/Ingress](#test-group-disable-egressingress) + - [Case6: Disable_egress](#case6-disable_egress) + - [Case7: Disable_ingress](#case7-disable_ingress) + - [Testing Objective](#testing-objective-1) + - [Test Case: Remove lag member](#test-case-remove-lag-member) + - [Testing Objective](#testing-objective-2) +# Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. -# Test Environment -## Testbed -Those tests will be run on the testbed structure, the components are: -* PTF - running in a server that can connect to the target DUT -* SAI server - running on a dut -## Test Configuration -For the test configuration, please refer to the file - - [VLAN_config](./config_data/vlan_config_t0.md) - - [FDB_config](./config_data/fdb_config_t0.md) - - [Route_config](./config_data/route_config_t0.md) - - [LAG_config](./config_data/LAG_config_t0.md) +# Test Configuration +For the test configuration, please refer to LAG configuration section ofthe file + - [Config_t0](./config_data/config_t0.md) **Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** -## Variations -Cause the testbed might also encounter some issues like the host interface being down. -Before running the actual test there will need some sanity test to check the DUT status and select the active ports for testing. - -**All the ports in this test plan just to illustrate the test purpose, they are not exactly the same for the actual environment.** - # Test Execution -## Basic function test - -### PortChannel Loadbalanceing -#### Testing Objective -For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side -Even after removing and disabling the port in a lag. - -#### Test Data/Packet - -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet - -#### Test Cases -| Goal| Steps/Cases | Expect | -|-|-|-| -| Prepare to send from port0 to Lag1.| Send packet with.| Lag1 and members have been created.| -| Packet forwards on port equally.| Send packet on port0 to the lag1 100 times .| Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, disable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, enable egress/ingress on one lag member, then send packet | Loadbalance on lag members.| -| Packet forwards on available ports equally.| Every time, remove one lag member, then send packet | Loadbalance on lag members.| - - - -## SAI API test -### Remove Lag member -#### Testing Objective -Test verifies the LAG load balancing for scenario when LAG members are removed. - - -#### Test Data/Packet - -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet - -#### Test Cases -| Goal | Steps/Cases | Expect | -|-|-|-| -|Remove lag2_member2 and forwarding packet from port0 to lag2|Remove lag2_member2 form Lag2 and Send packet on port0 to lag2 100 times| Port0 will receive an equal number of packets.| - +## Test Data/Packet +```Python +pkt = simple_udp_packet(eth_dst=ROUTER_MAC, + eth_src=src_mac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + udp_sport=udp_sport, + udp_dport=udp_dport, + ip_id=106, + ip_ttl=64) + + exp_pkt = simple_udp_packet(eth_dst=dstmac, + eth_src=ROUTER_MAC, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + udp_sport=udp_sport, + udp_dport=udp_dport, + ip_id=106, + ip_ttl=63) +``` + +```Python +pkt = simple_tcp_packet(eth_dst=ROUTER_MAC, + eth_src=src_mac, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + tcp_sport=tcp_sport, + tcpp_dport=tcp_dport, + ip_id=106, + ip_ttl=64) + + exp_pkt = simple_udp_packet(eth_dst=dstmac, + eth_src=ROUTER_MAC, + ip_dst=dst_ip_addr, + ip_src=src_ip_addr, + tcp_sport=tcp_sport, + tcp_dport=tcp_dport, + ip_id=106, + ip_ttl=63) +``` + +## Test Group: L3 PortChannel Loadbalanceing +These cases will cover five scenarios: src/dst ip, src/dst port , protocol. considering the mighty hash collision, please make sure the volume of the test data, and we can check the final result is in a range. + + +### Case1: Change source_port +### Case2: Change destinstion_port +### Case3: Change source_ip +### Case4: Change destinstion_ip +### Case5: Change protocol + + +### Testing Objective +For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. +### Test steps: +Test steps: + - Set switch hash attribute as (SAI_NATIVE_HASH_FIELD_SRC_IP, + SAI_NATIVE_HASH_FIELD_DST_IP, + SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, + SAI_NATIVE_HASH_FIELD_L4_DST_PORT, + SAI_NATIVE_HASH_FIELD_L4_SRC_PORT), which mean switch computes hash value using the five fields of packet. + + - Generate different packets by updating source port, destination port, source ip, destination ip of packet. Packets use lag1 neighbor IPs asdestination ip, lag1 neighbor MAC as destination MAC. + + - Send these packetes on port1. + - Check if packets are recieved on ports of lag1 equally. + +## Test Group: Disable Egress/Ingress + + +### Case6: Disable_egress +### Case7: Disable_ingress + +### Testing Objective +These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. + +### Test steps: +Test steps: +- Disable egress/ingress on lag2 member port20; For case7, Remove port22 from lag3 +- Create packet with lag2 neighbor IP as destination ip, lag2 neighbor MAC as destination MAC +- Send packet from port1 +- Check if Packet drop on port20 + +## Test Case: Remove lag member +### Testing Objective +These cases will cover lag memeber removement. We can remove a lag member, then expect traffic drop on the lag member. + +### Test steps: +Test steps: +- Remove port22 from lag3 +- Create packet with lag3 neighbor IP as destination ip, lag3 neighbor MAC as destination MAC +- Send packet from port1 +- Check if Packet drop on port22 -### Disable Lag memeber -For lag, we can disable it from ingress or egress direction, after we disable the member of a lag, we expect traffic can be loadbalanced to other lag members. -#### Test Data/Packet -[Sample_Packet](./config_data/LAG_config_t0.md#sample-datapacket) -- Input Packet -- Output Packet -#### Test Cases -| Goal | Steps/Cases | Expect | -|-|-|-| -|Packet dropped on port22| Disable egress and ingress on lag3 member2. send packet | Packet drop.| diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 457eb652d..28e84505f 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -16,7 +16,7 @@ - [Case7: test_untagged_mac_learning](#case7-test_untagged_mac_learning) - [Case8: test_tagged_mac_learning](#case8-test_tagged_mac_learning) - [Test Case9: Vlan member API](#test-case9-vlan-member-api) - - [Test Case10: Add to illegal VLAN failure](#test-case10-add-to-illegal-vlan-failure) + - [Test Case10: Failed to add member to invalidate VLAN](#test-case10-failed-to-add-member-to-invalidate-vlan) - [Test Group: VLAN Counters/Status](#test-group-vlan-countersstatus) - [Case11: test_tagged_vlan_status](#case11-test_tagged_vlan_status) - [Case12: test_untagged_vlan_status](#case12-test_untagged_vlan_status) @@ -164,7 +164,7 @@ Test steps: - Use VLAN API add a new Member, into VLAN - Verify the VLAN member and the account of the VLAN member are increased by 1. -## Test Case10: Add to illegal VLAN failure +## Test Case10: Failed to add member to invalidate VLAN - test_add_vlan_member_failed ### Testing Objective From bc7fcf0c16be409245b07681b6e3c03aa0662d7b Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Tue, 7 Jun 2022 23:12:46 +0800 Subject: [PATCH 12/18] Improve pc and vlan test Doc (#35) * fix typo Signed-off-by: zhoudongxu * remove some unnecessary comments Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/config_t0.md | 24 +++++++++++++----------- doc/sai-ptf/lag_test_plan.md | 9 +++------ doc/sai-ptf/vlan_test_plan.md | 9 +-------- 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index 88a61f1c4..9a16b2645 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -6,7 +6,10 @@ - [VLAN Interfaces](#vlan-interfaces) - [Json config data](#json-config-data) - [Route Configuration](#route-configuration) - - [rotue entries](#rotue-entries) + - [VLAN interfaces route entries](#vlan-interfaces-route-entries) + - [VLAN Neighbors](#vlan-neighbors) + - [LAG Route entry](#lag-route-entry) + - [LAG Neighbors](#lag-neighbors) - [LAG configuration](#lag-configuration) - [LAG and LAG members](#lag-and-lag-members) - [FDB Configuration](#fdb-configuration) @@ -89,22 +92,21 @@ Below is the sample config data in config_db.json ## Route Configuration -### rotue entries -VLAN interfaces route entries -|VLAN ID | VLAN Member | NH IP | NH MAC| -|-|-|-|-| -|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88 | -|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | 20:00:11:11:11:11 - 20:00:88:88:88:88 | +### VLAN interfaces route entries +|VLAN ID | VLAN Member | NH IP | +|-|-|-| +|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | +|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | -VLAN Neighbors +### VLAN Neighbors |Name|IP|dest_mac| |-|-|-| |vlan1000_nb1-nb8| 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88| |vlan2000_nb1-nb8|192.168.20.21 ~ 192.168.20.28 |20:00:11:11:11:11 - 20:00:88:88:88:88 | -LAG Route entry +### LAG Route entry |DestIp|Next Hop |Next Hop ip| |-|-|-| @@ -112,7 +114,7 @@ LAG Route entry |192.168.0.19|lag2:port19-20|192.168.0.19| |192.168.0.20|lag3:port21-22|192.168.0.20| -LAG Neighbors +### LAG Neighbors |Name|IP|dest_mac| |-|-|-| @@ -139,4 +141,4 @@ The MAC Table for VLAN L2 forwarding as below |mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| |mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| |mac9-16 |00:99:99:99:99:99 - 01:00:00:00:00:00|Port9-16|2000|Ethernet36-Ethernet64| -|mac17-mac31 |01:11:11:11:11:11 - 03:11:11:11:11:11|Port17-31||Ethernet68-Ethernet124| +|mac17-mac31 |01:11:11:11:11:11 - 01:ff:ff:ff:ff:ff|Port17-31||Ethernet68-Ethernet124| diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 9cdba020d..a1741f833 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -10,13 +10,10 @@ - [Case3: Change source_ip](#case3-change-source_ip) - [Case4: Change destinstion_ip](#case4-change-destinstion_ip) - [Case5: Change protocol](#case5-change-protocol) - - [Testing Objective](#testing-objective) - [Test Group: Disable Egress/Ingress](#test-group-disable-egressingress) - [Case6: Disable_egress](#case6-disable_egress) - [Case7: Disable_ingress](#case7-disable_ingress) - - [Testing Objective](#testing-objective-1) - [Test Case: Remove lag member](#test-case-remove-lag-member) - - [Testing Objective](#testing-objective-2) # Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -81,7 +78,7 @@ These cases will cover five scenarios: src/dst ip, src/dst port , protocol. cons ### Case5: Change protocol -### Testing Objective +### Testing Objective For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. ### Test steps: Test steps: @@ -102,7 +99,7 @@ Test steps: ### Case6: Disable_egress ### Case7: Disable_ingress -### Testing Objective +### Testing Objective These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. ### Test steps: @@ -113,7 +110,7 @@ Test steps: - Check if Packet drop on port20 ## Test Case: Remove lag member -### Testing Objective +### Testing Objective These cases will cover lag memeber removement. We can remove a lag member, then expect traffic drop on the lag member. ### Test steps: diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 28e84505f..7ebc00cf5 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -63,8 +63,6 @@ In this VLAN test, most of test case will be tested with Tagged or Untagged pack ### Testing Objective This test verifies the VLAN function around untag and access ports. -**This test will cover tagged and untagged mode respectivily.** - *p.s. This test will not check function with the native VLAN scenario. Please make sure the native VLAN will not impact the result.* With an untagged packet, on the access port, when ingress and egress happen, the behavior as below @@ -97,7 +95,6 @@ Test Steps: Drop packet when the destination port from MAC table search is the port which packet come into the switch. -**This test will cover tagged and untagged mode respectivily.** ``` Test example(Untag): @@ -124,7 +121,6 @@ Flooding | Port8| ``` -**This test will cover tagged and untagged mode respectivily.** ### Test Steps: - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as source MAC and a un-existing ``MacX`` as dest MAC @@ -142,7 +138,6 @@ For mac learning in VLAN scenario, after learning the mac address from the packe pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) ``` -**This test will cover tagged and untagged mode respectivily.** ### Test Steps: - Create ``Untagged``/``Tagged VLAN1000`` packet, with a un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC - Send packet on a VLAN source port1. @@ -180,7 +175,6 @@ When add a VLAN member to a non-exist VLAN, it will fail. ### Testing Objective For VLAN-related counters, SAI should be able to get the counter and clear them. -**This test will cover tagged and untagged mode respectivily.** ### Test Steps: Steps: @@ -198,7 +192,6 @@ Steps: ### Testing Objective Test the function when disabling VLAN MAC learning. When disabled, no new MAC will be learned in the MAC table. -**This test will cover tagged and untagged mode respectivily.** ### Additional config: - Do not config the MAC table @@ -222,7 +215,7 @@ Server To Server |L3| <-> |Virtual Switch| PC2 <- pkt(Untag) <- |DUT|Port9:Access:VLAN2000 ``` -*All the layer 3 router tables are created as the basic config, not MAC and ARP learning in this test process.* + The process is as below: 1. PC1 sends a untag packet to port1, which is a VLAN1000 access port 2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT MAC, forwarding to PORT9 From 7644b2cb593bff10be28bb936ce99b5aaed5a098 Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Tue, 7 Jun 2022 16:08:12 +0000 Subject: [PATCH 13/18] reformat and adjust the description of the tests Signed-off-by: richardyu-ms --- doc/sai-ptf/config_data/config_t0.md | 58 +------------------- doc/sai-ptf/lag_test_plan.md | 79 +++++++++++++++------------- 2 files changed, 44 insertions(+), 93 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index 9a16b2645..312943103 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -4,7 +4,6 @@ - [VLAN configuration](#vlan-configuration) - [VLAN and VLAN members](#vlan-and-vlan-members) - [VLAN Interfaces](#vlan-interfaces) - - [Json config data](#json-config-data) - [Route Configuration](#route-configuration) - [VLAN interfaces route entries](#vlan-interfaces-route-entries) - [VLAN Neighbors](#vlan-neighbors) @@ -25,6 +24,7 @@ This document describes the sample configuration data. |HostIf|VLAN ID|Ports|Tag mode| |-|-|-|-| +|Ethernet0||Port0|| |Ethernet4-32|1000|Port1-8|Untag| |Ethernet36-72|2000|Port9-16|Untag| @@ -34,62 +34,6 @@ This document describes the sample configuration data. |1000|192.168.10.1|10:00:01:11:11:11| |2000|192.168.20.1|20:00:01:22:22:22| -### Json config data - -Below is the sample config data in config_db.json - -```JSON - { - "VLAN": { - "Vlan1000": { - "members": [ - "Ethernet4", - "Ethernet8", - "Ethernet12", - "Ethernet16", - "Ethernet20", - "Ethernet24", - "Ethernet28", - "Ethernet32" - ], - "vlanid": "1000" - } - }, - "VLAN_INTERFACE": { - "Vlan1000": {}, - "Vlan1000|192.168.0.1/21": {}, - "Vlan1000|fc02:1000::1/64": {} - }, - "VLAN_MEMBER": { - "Vlan1000|Ethernet4": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet8": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet12": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet16": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet20": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet24": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet28": { - "tagging_mode": "untagged" - }, - "Vlan1000|Ethernet32": { - "tagging_mode": "untagged" - } - } - } -``` - - ## Route Configuration diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index a1741f833..2f460366d 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -5,22 +5,22 @@ - [Test Execution](#test-execution) - [Test Data/Packet](#test-datapacket) - [Test Group: L3 PortChannel Loadbalanceing](#test-group-l3-portchannel-loadbalanceing) - - [Case1: Change source_port](#case1-change-source_port) - - [Case2: Change destinstion_port](#case2-change-destinstion_port) - - [Case3: Change source_ip](#case3-change-source_ip) - - [Case4: Change destinstion_ip](#case4-change-destinstion_ip) - - [Case5: Change protocol](#case5-change-protocol) + - [Case1: test_loadbalance_on_source_port](#case1-test_loadbalance_on_source_port) + - [Case2: test_loadbalance_on_destinstion_port](#case2-test_loadbalance_on_destinstion_port) + - [Case3: test_loadbalance_on_source_ip](#case3-test_loadbalance_on_source_ip) + - [Case4: test_loadbalance_on_destinstion_ip](#case4-test_loadbalance_on_destinstion_ip) + - [Case5: test_loadbalance_on_protocol](#case5-test_loadbalance_on_protocol) - [Test Group: Disable Egress/Ingress](#test-group-disable-egressingress) - - [Case6: Disable_egress](#case6-disable_egress) - - [Case7: Disable_ingress](#case7-disable_ingress) - - [Test Case: Remove lag member](#test-case-remove-lag-member) + - [Case6: test_disable_egress](#case6-test_disable_egress) + - [Case7: test_disable_ingress](#case7-test_disable_ingress) + - [Test Case8: Remove lag member](#test-case8-remove-lag-member) # Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. # Test Configuration -For the test configuration, please refer to LAG configuration section ofthe file +For the test configuration, please refer to LAG configuration section of the file - [Config_t0](./config_data/config_t0.md) **Note. All the tests will be based on the configuration above, if any additional configuration is required, it will be specified in the Test case.** @@ -71,53 +71,60 @@ pkt = simple_tcp_packet(eth_dst=ROUTER_MAC, These cases will cover five scenarios: src/dst ip, src/dst port , protocol. considering the mighty hash collision, please make sure the volume of the test data, and we can check the final result is in a range. -### Case1: Change source_port -### Case2: Change destinstion_port -### Case3: Change source_ip -### Case4: Change destinstion_ip -### Case5: Change protocol +### Case1: test_loadbalance_on_source_port +### Case2: test_loadbalance_on_destinstion_port +### Case3: test_loadbalance_on_source_ip +### Case4: test_loadbalance_on_destinstion_ip +### Case5: test_loadbalance_on_protocol ### Testing Objective For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. -### Test steps: -Test steps: - - Set switch hash attribute as (SAI_NATIVE_HASH_FIELD_SRC_IP, - SAI_NATIVE_HASH_FIELD_DST_IP, - SAI_NATIVE_HASH_FIELD_IP_PROTOCOL, - SAI_NATIVE_HASH_FIELD_L4_DST_PORT, - SAI_NATIVE_HASH_FIELD_L4_SRC_PORT), which mean switch computes hash value using the five fields of packet. - - - Generate different packets by updating source port, destination port, source ip, destination ip of packet. Packets use lag1 neighbor IPs asdestination ip, lag1 neighbor MAC as destination MAC. - - Send these packetes on port1. - - Check if packets are recieved on ports of lag1 equally. +### Additional config: +- Set switch hash attribute as below, which mean switch computes hash value using the five fields of packet. +``` +SAI_NATIVE_HASH_FIELD_SRC_IP +SAI_NATIVE_HASH_FIELD_DST_IP +SAI_NATIVE_HASH_FIELD_IP_PROTOCOL +SAI_NATIVE_HASH_FIELD_L4_DST_PORT +SAI_NATIVE_HASH_FIELD_L4_SRC_PORT +``` +### Test steps: +- Generate different packets by updating source port, destination port, source ip, and destination ip of the packet. Packets use lag1 neighbor IPs as destination ip, lag1 neighbor MAC as destination MAC. +- Send these packetes with different protocols on port1. +- Check if packets are recieved on ports of lag1 equally. ## Test Group: Disable Egress/Ingress -### Case6: Disable_egress -### Case7: Disable_ingress +### Case6: test_disable_egress +### Case7: test_disable_ingress ### Testing Objective These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. -### Test steps: -Test steps: -- Disable egress/ingress on lag2 member port20; For case7, Remove port22 from lag3 -- Create packet with lag2 neighbor IP as destination ip, lag2 neighbor MAC as destination MAC +### Test steps: +- Create packets with variations of the src_ip, dest_ip is lag2 neighbor IP and MAC is lag2 neighbor MAC. - Send packet from port1 +- Verify packets appear on differnt lag2 members. +- Disable egress/ingress on lag2 member port20 +- Create packets with variations of the src_ip, dest ip is lag2 neighbor IP and MAC is lag2 neighbor MAC. +- Send packet from port1 - Check if Packet drop on port20 -## Test Case: Remove lag member +## Test Case8: Remove lag member +- test_remove_lag_member ### Testing Objective These cases will cover lag memeber removement. We can remove a lag member, then expect traffic drop on the lag member. -### Test steps: -Test steps: +### Test steps: +- Create packets with variations of the src_ip, dest_ip is lag3 neighbor IP and MAC is lag3 neighbor MAC. +- Send packet from port0 +- Verify packets appear on differnt lag3 members. - Remove port22 from lag3 -- Create packet with lag3 neighbor IP as destination ip, lag3 neighbor MAC as destination MAC -- Send packet from port1 +- Create packets with variations of the src_ip, dest ip is lag3 neighbor IP and MAC is lag3 neighbor MAC. +- Send packet from port0 - Check if Packet drop on port22 From 191471cc02b632427e39e1f2f46d996b865dc4ee Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Wed, 8 Jun 2022 05:10:51 +0800 Subject: [PATCH 14/18] set hash algorithm (#36) Signed-off-by: zhoudongxu --- doc/sai-ptf/lag_test_plan.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 2f460366d..22fe4a0f4 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -82,6 +82,7 @@ These cases will cover five scenarios: src/dst ip, src/dst port , protocol. cons For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. ### Additional config: +- Set hash alogrithm as SAI_HASH_ALGORITHM_CRC - Set switch hash attribute as below, which mean switch computes hash value using the five fields of packet. ``` SAI_NATIVE_HASH_FIELD_SRC_IP From d9e53d7dc6242f94200527d2e95054626ce42f17 Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Wed, 8 Jun 2022 20:17:47 +0800 Subject: [PATCH 15/18] refine lag test (#37) Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/config_t0.md | 17 +++++++-- doc/sai-ptf/lag_test_plan.md | 56 ++++++++++++++-------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index 312943103..f70178a39 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -11,6 +11,7 @@ - [LAG Neighbors](#lag-neighbors) - [LAG configuration](#lag-configuration) - [LAG and LAG members](#lag-and-lag-members) + - [LAG Hash Rule](#lag-hash-rule) - [FDB Configuration](#fdb-configuration) - [MAC Table](#mac-table) ## Overriew @@ -56,7 +57,7 @@ This document describes the sample configuration data. |-|-|-| |192.168.0.11-192.168.0.18|lag1:port17-18|192.168.0.11-192.168.0.18| |192.168.0.19|lag2:port19-20|192.168.0.19| -|192.168.0.20|lag3:port21-22|192.168.0.20| + ### LAG Neighbors @@ -64,7 +65,7 @@ This document describes the sample configuration data. |-|-|-| |lag1_nb1-nb8| 192.168.0.11-192.168.0.18| 00:00:11:11:11:11-00:00:88:88:88:88| |lag2_nb1|192.168.0.19|00:00:99:99:99:99| -|lag3_nb1|192.168.0.20|00:00:aa:aa:aa:aa| + ## LAG configuration @@ -75,7 +76,17 @@ This document describes the sample configuration data. |-|-|-| |Ethernet76-80|lag1|Port17-18| |Ethernet84-88|lag2|Port19-20| -|Ethernet92-96|lag3|Port21-22| + +### LAG Hash Rule +- Set hash alogrithm as SAI_HASH_ALGORITHM_CRC +- Set switch hash attribute as below, which mean switch computes hash value using the five fields of packet. +``` +SAI_NATIVE_HASH_FIELD_SRC_IP +SAI_NATIVE_HASH_FIELD_DST_IP +SAI_NATIVE_HASH_FIELD_IP_PROTOCOL +SAI_NATIVE_HASH_FIELD_L4_DST_PORT +SAI_NATIVE_HASH_FIELD_L4_SRC_PORT +``` ## FDB Configuration ### MAC Table diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 22fe4a0f4..9f0b1a886 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -1,5 +1,5 @@ -# SAI Lag Test plan -- [SAI Lag Test plan](#sai-lag-test-plan) +# SAI LAG Test plan +- [SAI LAG Test plan](#sai-lag-test-plan) - [Overriew](#overriew) - [Test Configuration](#test-configuration) - [Test Execution](#test-execution) @@ -13,7 +13,9 @@ - [Test Group: Disable Egress/Ingress](#test-group-disable-egressingress) - [Case6: test_disable_egress](#case6-test_disable_egress) - [Case7: test_disable_ingress](#case7-test_disable_ingress) - - [Test Case8: Remove lag member](#test-case8-remove-lag-member) + - [Test Group: Remove/Add LAG member](#test-group-removeadd-lag-member) + - [Case8: test_remove_lag_member](#case8-test_remove_lag_member) + - [Case9: test_add_lag_member](#case9-test_add_lag_member) # Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -81,16 +83,6 @@ These cases will cover five scenarios: src/dst ip, src/dst port , protocol. cons ### Testing Objective For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. -### Additional config: -- Set hash alogrithm as SAI_HASH_ALGORITHM_CRC -- Set switch hash attribute as below, which mean switch computes hash value using the five fields of packet. -``` -SAI_NATIVE_HASH_FIELD_SRC_IP -SAI_NATIVE_HASH_FIELD_DST_IP -SAI_NATIVE_HASH_FIELD_IP_PROTOCOL -SAI_NATIVE_HASH_FIELD_L4_DST_PORT -SAI_NATIVE_HASH_FIELD_L4_SRC_PORT -``` ### Test steps: - Generate different packets by updating source port, destination port, source ip, and destination ip of the packet. Packets use lag1 neighbor IPs as destination ip, lag1 neighbor MAC as destination MAC. - Send these packetes with different protocols on port1. @@ -106,28 +98,34 @@ SAI_NATIVE_HASH_FIELD_L4_SRC_PORT These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. ### Test steps: -- Create packets with variations of the src_ip, dest_ip is lag2 neighbor IP and MAC is lag2 neighbor MAC. +- Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) - Send packet from port1 -- Verify packets appear on differnt lag2 members. -- Disable egress/ingress on lag2 member port20 -- Create packets with variations of the src_ip, dest ip is lag2 neighbor IP and MAC is lag2 neighbor MAC. +- Verify packets appear on differnt lag1 members. +- Disable egress/ingress on lag1 member port18 +- Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) - Send packet from port1 -- Check if Packet drop on port20 +- Check if Packet drop on port18 -## Test Case8: Remove lag member -- test_remove_lag_member +## Test Group: Remove/Add LAG member +### Case8: test_remove_lag_member +### Case9: test_add_lag_member ### Testing Objective -These cases will cover lag memeber removement. We can remove a lag member, then expect traffic drop on the lag member. +These cases will cover add and remove lag memeber . We can remove or add a lag member, then expect traffic drop/appear on the lag member. ### Test steps: -- Create packets with variations of the src_ip, dest_ip is lag3 neighbor IP and MAC is lag3 neighbor MAC. -- Send packet from port0 -- Verify packets appear on differnt lag3 members. -- Remove port22 from lag3 -- Create packets with variations of the src_ip, dest ip is lag3 neighbor IP and MAC is lag3 neighbor MAC. -- Send packet from port0 -- Check if Packet drop on port22 - +- test_remove_lag_member + - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) + - Send packet from port0 + - Verify packets appear on lag1 port18. + - Remove port18 from lag1 + - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) + - Send packet from port0 + - Check if Packet drop on port18 +- test_add_lag_member + - Add port21 to lag1 + - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) + - Send packet from port0 + - Verify packets appear on lag1 port21. From d4c2bb9f78aa3acf566354aa1ed347c3f48d1ec8 Mon Sep 17 00:00:00 2001 From: zhoudongxu Date: Thu, 9 Jun 2022 10:24:50 +0800 Subject: [PATCH 16/18] correct vlan interface test (#38) Signed-off-by: zhoudongxu --- doc/sai-ptf/config_data/config_t0.md | 8 ++++---- doc/sai-ptf/vlan_test_plan.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index f70178a39..64916698c 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -30,10 +30,10 @@ This document describes the sample configuration data. |Ethernet36-72|2000|Port9-16|Untag| ### VLAN Interfaces -|VLAN ID | VLAN Interface IP | VLAN Interface MAC | -|-|-|-| -|1000|192.168.10.1|10:00:01:11:11:11| -|2000|192.168.20.1|20:00:01:22:22:22| +|VLAN ID | VLAN Interface IP| +|-|-| +|1000|192.168.10.1| +|2000|192.168.20.1| ## Route Configuration diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 7ebc00cf5..bc056a00c 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -218,7 +218,7 @@ Server To Server The process is as below: 1. PC1 sends a untag packet to port1, which is a VLAN1000 access port -2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT MAC, forwarding to PORT9 +2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT neighbor MAC, forwarding to PORT9 3. Packet goes through VLAN2000 port9 ### Test Data/Packet @@ -234,7 +234,7 @@ The process is as below: - Expected Packet ```Python simple_tcp_packet( - eth_dst=PORT_MAC, + eth_dst=PORT_NB_MAC, eth_src=SVI_MAC, ip_dst=DEST_IP, ip_src=SRC_IP) From 08c90dc679fff707c5f6ae54ff4a8dcd9b2b6f1d Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Thu, 9 Jun 2022 03:36:42 +0000 Subject: [PATCH 17/18] workaround for the sequence number issue in github and correct typo standardise the ip and mac naming in config add lag test for ingress port indifferenate in lag hash redesign the mac and ip namin convention and reformat Signed-off-by: richardyu-ms --- doc/sai-ptf/config_data/config_t0.md | 176 +++++++++++------- doc/sai-ptf/lag_test_plan.md | 88 +++++---- doc/sai-ptf/vlan_test_plan.md | 257 +++++++++++++-------------- 3 files changed, 287 insertions(+), 234 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index 64916698c..928c0d2b4 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -1,85 +1,112 @@ -# Sample T0 Configurations and data for VLAN -- [Sample T0 Configurations and data for VLAN](#sample-t0-configurations-and-data-for-vlan) - - [Overriew](#overriew) - - [VLAN configuration](#vlan-configuration) - - [VLAN and VLAN members](#vlan-and-vlan-members) - - [VLAN Interfaces](#vlan-interfaces) - - [Route Configuration](#route-configuration) - - [VLAN interfaces route entries](#vlan-interfaces-route-entries) - - [VLAN Neighbors](#vlan-neighbors) - - [LAG Route entry](#lag-route-entry) - - [LAG Neighbors](#lag-neighbors) - - [LAG configuration](#lag-configuration) - - [LAG and LAG members](#lag-and-lag-members) - - [LAG Hash Rule](#lag-hash-rule) - - [FDB Configuration](#fdb-configuration) - - [MAC Table](#mac-table) -## Overriew +# Sample T0 Configurations and data +- [Overriew](#overriew) +- [IP and MAC naming convention](#ip-and-mac-naming-convention) + - [MAC](#mac) + - [IP](#ip) +- [1. L2 Configurations](#1-l2-configurations) + - [1.1 FDB Configuration](#11-fdb-configuration) + - [1.2 VLAN configuration](#12-vlan-configuration) +- [2. L3 configuration](#2-l3-configuration) + - [2.1 VLAN Interfaces](#21-vlan-interfaces) + - [2.2 LAG configuration](#22-lag-configuration) + - [2.2.1 LAG Hash Rule](#221-lag-hash-rule) + - [2.3 Route Configuration](#23-route-configuration) + - [2.3.1 VLAN interfaces route entries](#231-vlan-interfaces-route-entries) + - [2.3.2 LAG Route entry](#232-lag-route-entry) + - [2.4 Neighbor Configuration](#24-neighbor-configuration) + - [2.4.1 VLAN Neighbors](#241-vlan-neighbors) + - [2.4.2 LAG Neighbors](#242-lag-neighbors) +# Overriew This document describes the sample configuration data. **Note: This configuration focused on T0 topology.** -## VLAN configuration +# IP and MAC naming convention +In this configuration, we mapped the IP and MAC address into different parts of this configuration as below. -### VLAN and VLAN members +## MAC +For MAC addresses, we can use different sections in the MAC addresses to map different title numbers. +The pattern is +``` +L1_NUM:L2_NUM:L3_NUM:ROLE:EXTRA:SEQ +ROLE: T1=1, Server=99 +``` -|HostIf|VLAN ID|Ports|Tag mode| -|-|-|-|-| -|Ethernet0||Port0|| -|Ethernet4-32|1000|Port1-8|Untag| -|Ethernet36-72|2000|Port9-16|Untag| +For example: +For the MAC address in ``1.1 FDB Configuration``. +``` +#Server MAC +01:01:00:99:02:01~01:01:00:99:02:32 +# 99: Server +# 02: EXTRA (Group ID) +``` -### VLAN Interfaces -|VLAN ID | VLAN Interface IP| -|-|-| -|1000|192.168.10.1| -|2000|192.168.20.1| -## Route Configuration +## IP +For IP addresses, we will use different prefix for different role +Format: ROLE.NUM.GROUP_ID.SEQ -### VLAN interfaces route entries -|VLAN ID | VLAN Member | NH IP | -|-|-|-| -|1000| Ethernet4-32 | 192.168.10.11 ~ 192.168.10.18 | -|2000| Ethernet36-72 | 192.168.20.21 ~ 192.168.20.28 | +- ROLE_NUM +T0: 10.0.0.0 +T1: 10.0.0.0 +Server: 192.168.0.0 -### VLAN Neighbors -|Name|IP|dest_mac| -|-|-|-| -|vlan1000_nb1-nb8| 192.168.10.11 ~ 192.168.10.18 | 10:00:11:11:11:11 - 10:00:88:88:88:88| -|vlan2000_nb1-nb8|192.168.20.21 ~ 192.168.20.28 |20:00:11:11:11:11 - 20:00:88:88:88:88 | +For example +``` +# IP in +# 2.4.1 VLAN Neighbors +#Group0 (For Vlan10) +192.168.1.1~ 192.168.1.8 +#Group1 (ForVlan20) +192.168.2.1~ 192.168.2.8 +``` -### LAG Route entry -|DestIp|Next Hop |Next Hop ip| -|-|-|-| -|192.168.0.11-192.168.0.18|lag1:port17-18|192.168.0.11-192.168.0.18| -|192.168.0.19|lag2:port19-20|192.168.0.19| +# 1. L2 Configurations -### LAG Neighbors +## 1.1 FDB Configuration -|Name|IP|dest_mac| -|-|-|-| -|lag1_nb1-nb8| 192.168.0.11-192.168.0.18| 00:00:11:11:11:11-00:00:88:88:88:88| -|lag2_nb1|192.168.0.19|00:00:99:99:99:99| +The MAC Table for VLAN L2 forwarding as below +|Name|MAC|PORT|VLAN|HostIf| +|-|-|-|-|-| +|mac0|01:01:00:99:00:00|Port0||Ethernet0| +|mac1-8 |01:01:00:99:01:01 - 01:01:00:99:01:08|Port1-8|10|Ethernet4-Ethernet32| +|mac9-16 |01:01:00:99:02:09 - 01:01:00:99:02:16|Port9-16|20|Ethernet36-Ethernet64| +## 1.2 VLAN configuration +|HostIf|VLAN ID|Ports|Tag mode| +|-|-|-|-| +|Ethernet4-32|10|Port1-8|Untag| +|Ethernet36-72|20|Port9-16|Untag| + + +# 2. L3 configuration -## LAG configuration +Host interface IP +|Port|Interface IP| +|-|-| +|port0|10.0.0.100| + +## 2.1 VLAN Interfaces +|VLAN ID | VLAN Interface IP| +|-|-| +|10|192.168.1.100| +|20|192.168.2.100| -### LAG and LAG members +## 2.2 LAG configuration |HostIf|LAG ID|Ports| |-|-|-| |Ethernet76-80|lag1|Port17-18| |Ethernet84-88|lag2|Port19-20| -### LAG Hash Rule -- Set hash alogrithm as SAI_HASH_ALGORITHM_CRC -- Set switch hash attribute as below, which mean switch computes hash value using the five fields of packet. +### 2.2.1 LAG Hash Rule +- Set hash algorithm as SAI_HASH_ALGORITHM_CRC +- Set switch hash attribute as below, which means switch computes hash using the five fields and seed(SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_SEED) as the hash configuration. ``` SAI_NATIVE_HASH_FIELD_SRC_IP SAI_NATIVE_HASH_FIELD_DST_IP @@ -88,12 +115,33 @@ SAI_NATIVE_HASH_FIELD_L4_DST_PORT SAI_NATIVE_HASH_FIELD_L4_SRC_PORT ``` -## FDB Configuration -### MAC Table -The MAC Table for VLAN L2 forwarding as below -|Name|MAC|PORT|VLAN|HostIf| -|-|-|-|-|-| -|mac0|mac0-00:00:00:00:00:11|Port0||Ethernet0| -|mac1-8 |00:11:11:11:11:11 - 00:88:88:88:88:88|Port1-8|1000|Ethernet4-Ethernet32| -|mac9-16 |00:99:99:99:99:99 - 01:00:00:00:00:00|Port9-16|2000|Ethernet36-Ethernet64| -|mac17-mac31 |01:11:11:11:11:11 - 01:ff:ff:ff:ff:ff|Port17-31||Ethernet68-Ethernet124| +## 2.3 Route Configuration + +### 2.3.1 VLAN interfaces route entries +|VLAN ID | route IP | Type | +|-|-| - | +|10| 192.168.1.100/24 | Direct Connect| +|20| 192.168.2.100/24 | Direct Connect| +### 2.3.2 LAG Route entry + +|LAG ID | route IP | Type | VALUE| +|-|-| - |-| +|1| 10.0.1.100/31 | Direct Connect|| +|2| 10.0.2.100/31 | Direct Connect|| +|1| 192.168.10.1-192.168.10.100| NH|lag1_nb| +|2| 192.168.11.1-192.168.11.100| NH|lag2_nb| + +## 2.4 Neighbor Configuration +### 2.4.1 VLAN Neighbors +|Name|Port|IP|dest_mac| +|-|-|-|-| +|vlan10_nb1-nb8|Port1-8 |192.168.1.1 ~ 192.168.1.8 |01:01:00:99:01:01 - 01:01:00:99:01:08| +|vlan20_nb1-nb8|Port9-16|192.168.2.9 ~ 192.168.2.16 |01:01:00:99:02:09 - 01:01:00:99:02:16 | + + +### 2.4.2 LAG Neighbors + +|Name|Port|IP|dest_mac| +|-|-|-|-| +|lag1_nb|lag1| 10.0.1.101 | 02:04:02:01:01:01| +|lag2_nb|lag2| 10.0.2.101 | 02:04:02:01:02:01| diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index 9f0b1a886..d7a61a681 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -4,18 +4,21 @@ - [Test Configuration](#test-configuration) - [Test Execution](#test-execution) - [Test Data/Packet](#test-datapacket) - - [Test Group: L3 PortChannel Loadbalanceing](#test-group-l3-portchannel-loadbalanceing) + - [Test Group1: L3 PortChannel Load balancing](#test-group1-l3-portchannel-load-balancing) - [Case1: test_loadbalance_on_source_port](#case1-test_loadbalance_on_source_port) - [Case2: test_loadbalance_on_destinstion_port](#case2-test_loadbalance_on_destinstion_port) - [Case3: test_loadbalance_on_source_ip](#case3-test_loadbalance_on_source_ip) - [Case4: test_loadbalance_on_destinstion_ip](#case4-test_loadbalance_on_destinstion_ip) - [Case5: test_loadbalance_on_protocol](#case5-test_loadbalance_on_protocol) - - [Test Group: Disable Egress/Ingress](#test-group-disable-egressingress) + - [Test Group2: Disable Egress/Ingress](#test-group2-disable-egressingress) - [Case6: test_disable_egress](#case6-test_disable_egress) - [Case7: test_disable_ingress](#case7-test_disable_ingress) - - [Test Group: Remove/Add LAG member](#test-group-removeadd-lag-member) + - [Test Group3: Remove/Add LAG member](#test-group3-removeadd-lag-member) - [Case8: test_remove_lag_member](#case8-test_remove_lag_member) - [Case9: test_add_lag_member](#case9-test_add_lag_member) + - [Test Group4: Indifference Ingress Port in Hash](#test-group4-indifference-ingress-port-in-hash) + - [Case10: test_ingress_port_hash_indiff](#case10-test_ingress_port_hash_indiff) + - [Test Objective](#test-objective) # Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -68,9 +71,8 @@ pkt = simple_tcp_packet(eth_dst=ROUTER_MAC, ip_id=106, ip_ttl=63) ``` - -## Test Group: L3 PortChannel Loadbalanceing -These cases will cover five scenarios: src/dst ip, src/dst port , protocol. considering the mighty hash collision, please make sure the volume of the test data, and we can check the final result is in a range. +## Test Group1: L3 PortChannel Load balancing +These cases will cover five scenarios: src/dst IP, src/dst port, and protocol. considering the mighty hash collision, please make sure the volume of the test data, and we can check the final result is in a range. ### Case1: test_loadbalance_on_source_port @@ -81,14 +83,14 @@ These cases will cover five scenarios: src/dst ip, src/dst port , protocol. cons ### Testing Objective -For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server side to T1 side. +For load balancing, expecting the ports in a lag should receive the packet equally. Traffic direction: from server-side to T1 side. ### Test steps: -- Generate different packets by updating source port, destination port, source ip, and destination ip of the packet. Packets use lag1 neighbor IPs as destination ip, lag1 neighbor MAC as destination MAC. -- Send these packetes with different protocols on port1. -- Check if packets are recieved on ports of lag1 equally. +1. Generate different packets by updating different factors for each case. The factor includes source port(L4), destination port(L4), source IP, and destination IP of the packet. Packets use lag1 neighbor IPs as destination IP, and lag1 MAC (Switch MAC) as destination MAC. +2. Send these packets with different protocols on port1(with different cases). +3. Check if packets are received on ports of lag1 equally. -## Test Group: Disable Egress/Ingress +## Test Group2: Disable Egress/Ingress ### Case6: test_disable_egress @@ -98,34 +100,56 @@ For load balancing, expecting the ports in a lag should receive the packet equal These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. ### Test steps: -- Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) -- Send packet from port1 -- Verify packets appear on differnt lag1 members. -- Disable egress/ingress on lag1 member port18 -- Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) -- Send packet from port1 -- Check if Packet drop on port18 - -## Test Group: Remove/Add LAG member +- test_disable_egress + +1. Generate different packets by updating different factors for each case. The factor includes source port(L4), destination port(L4), source IP, and destination IP of the packet. Packets use lag1 neighbor IPs as destination IP, and lag1 MAC (Switch MAC) as destination MAC. +2. Send packet from port1 +3. Verify packets appear on different lag1 members(Baseline check). +4. Disable egress on lag1 member port18 +5. Send packets in step1 from port1 again +6. Check if the Packet drop on port18 + +- test_disable_ingress + +1. Generate packet using port1 neighbor IP as destination IP, VLAN Interface MAC (Switch MAC) as destination MAC. +2. Send packet from lag1 port18 +3. Verify packets appear on Port1(Baseline check). +4. Disable ingress on lag1 member port18 +5. Send packet in step1 again from lag1 port18 +6. Check if Packet drop on port1 + +## Test Group3: Remove/Add LAG member ### Case8: test_remove_lag_member ### Case9: test_add_lag_member ### Testing Objective -These cases will cover add and remove lag memeber . We can remove or add a lag member, then expect traffic drop/appear on the lag member. +These cases will cover adding and removing the lag members. We can remove or add a lag member, then expect traffic to drop/appear on the lag member. ### Test steps: - test_remove_lag_member - - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) - - Send packet from port0 - - Verify packets appear on lag1 port18. - - Remove port18 from lag1 - - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) - - Send packet from port0 - - Check if Packet drop on port18 + +1. Generate different packets by updating different factors for each case. The factor includes source port(L4), destination port(L4), source IP, and destination IP of the packet. Packets use lag1 neighbor IPs as destination IP and lag1 MAC (Switch MAC) as destination MAC. +2. Send packet from port1 +3. Verify packets appear on lag1 port18(Baseline check). +4. Remove port18 from lag1 +5. Send packets in step1 from port1 again +6. Check if the Packet drop on port18 + - test_add_lag_member - - Add port21 to lag1 - - Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) - - Send packet from port0 - - Verify packets appear on lag1 port21. + +1. Add port21 to lag1 +2. Create packets with variations of the src_ip, dest_ip, src_port,dest_port.(dest_ip is lag1 neighbor IP and MAC is lag1 neighbor MAC) +3. Send packet from port1 +4. Verify packets appear on all the lag1 members, including port21. +## Test Group4: Indifference Ingress Port in Hash +### Case10: test_ingress_port_hash_indiff +### Test Objective +This case will verify the ingress ports should not be as a Hash Factor in Lag loadbalance. +When forwarding the packet from different ingress ports, if only the ingress port changed, then the loadbalance should not happen among lag members. + +### Test steps: +1. Generate packet using one lag1 neighbor IP as destination IP, lag1 MAC (Switch MAC) as destination MAC, and keep all packets from different ports have the same src_ip, dest_ip, src_port(L4),dest_port(L4), and protocol. +2. Send packet from Port1 ~ Port16 +3. Verify packets only appear on one LAG member port diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index bc056a00c..43d9a8e1b 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -3,30 +3,33 @@ - [Test Configuration](#test-configuration) - [Test Execution](#test-execution) - [Common Test Data/Packet](#common-test-datapacket) - - [Test Group: Tagging and access](#test-group-tagging-and-access) + - [Test Group1: Tagging and access](#test-group1-tagging-and-access) - [Case1: test_untag_access_to_access](#case1-test_untag_access_to_access) - - [Case2: test_tag_access_to_access](#case2-test_tag_access_to_access) - - [Test Group: Frame Filtering](#test-group-frame-filtering) + - [Case2: test_unmatch_drop](#case2-test_unmatch_drop) + - [Test Group2: Frame Filtering](#test-group2-frame-filtering) - [Case3: test_untagged_frame_filtering](#case3-test_untagged_frame_filtering) - [Case4: test_tagged_frame_filtering](#case4-test_tagged_frame_filtering) - - [Test Group: VLAN flooding](#test-group-vlan-flooding) + - [Test Group3: VLAN flooding](#test-group3-vlan-flooding) - [Case5: test_tagged_vlan_flooding](#case5-test_tagged_vlan_flooding) - [Case6: test_untagged_vlan_flooding](#case6-test_untagged_vlan_flooding) - - [Test Group: MAC learning](#test-group-mac-learning) - - [Case7: test_untagged_mac_learning](#case7-test_untagged_mac_learning) - - [Case8: test_tagged_mac_learning](#case8-test_tagged_mac_learning) - - [Test Case9: Vlan member API](#test-case9-vlan-member-api) - - [Test Case10: Failed to add member to invalidate VLAN](#test-case10-failed-to-add-member-to-invalidate-vlan) - - [Test Group: VLAN Counters/Status](#test-group-vlan-countersstatus) - - [Case11: test_tagged_vlan_status](#case11-test_tagged_vlan_status) - - [Case12: test_untagged_vlan_status](#case12-test_untagged_vlan_status) - - [Test Group7: Disable mac learning](#test-group7-disable-mac-learning) - - [Case13: test_disable_mac_learning_tagged](#case13-test_disable_mac_learning_tagged) - - [Case14: test_disable_mac_learning_untagged](#case14-test_disable_mac_learning_untagged) - - [Test Case15: L3 switching(Inter-VLAN)](#test-case15-l3-switchinginter-vlan) - - [Test Group: ARP Flooding and mac learning](#test-group-arp-flooding-and-mac-learning) - - [Case16: test_arp_request_flooding](#case16-test_arp_request_flooding) - - [Case17: test_arp_response_learning](#case17-test_arp_response_learning) + - [Test Group4: VLAN broadcast](#test-group4-vlan-broadcast) + - [Case7: test_vlan_broadcast](#case7-test_vlan_broadcast) + - [Test Group5: MAC learning](#test-group5-mac-learning) + - [Case8: test_untagged_mac_learning](#case8-test_untagged_mac_learning) + - [Case9: test_tagged_mac_learning](#case9-test_tagged_mac_learning) + - [Test Group6: Vlan member API](#test-group6-vlan-member-api) + - [Case10:test_vlan_member_api](#case10test_vlan_member_api) + - [Test Group7: Add member to invalidate VLAN](#test-group7-add-member-to-invalidate-vlan) + - [Case11:test_add_vlan_member_failed](#case11test_add_vlan_member_failed) + - [Test Group8: Disable mac learning](#test-group8-disable-mac-learning) + - [Case12: test_disable_mac_learning_tagged](#case12-test_disable_mac_learning_tagged) + - [Case13: test_disable_mac_learning_untagged](#case13-test_disable_mac_learning_untagged) + - [Test Group9: ARP Flooding and mac learning](#test-group9-arp-flooding-and-mac-learning) + - [Case14: test_arp_request_flooding](#case14-test_arp_request_flooding) + - [Case15: test_arp_response_learning](#case15-test_arp_response_learning) + - [Test Group10: VLAN Counters/Status](#test-group10-vlan-countersstatus) + - [Case16: test_tagged_vlan_status](#case16-test_tagged_vlan_status) + - [Case17: test_untagged_vlan_status](#case17-test_untagged_vlan_status) # Test Configuration For the test configuration, please refer to the file @@ -37,7 +40,7 @@ For the test configuration, please refer to the file # Test Execution ## Common Test Data/Packet -In this VLAN test, most of test case will be tested with Tagged or Untagged packet, the example packet structure as below. +In this VLAN test, most of the test cases will be tested with a Tagged or Untagged packet, the example packet structure as below. - Tagged packet with VLAN id ```python @@ -54,46 +57,49 @@ In this VLAN test, most of test case will be tested with Tagged or Untagged pack ip_dst='172.16.0.1', ip_ttl=64) ``` -**Note. If need other kinds of packet, it will be added in the test case/group respectively.** +**Note. If need other kinds of packets, they will be added to the test case/group respectively.** -## Test Group: Tagging and access +## Test Group1: Tagging and access ### Case1: test_untag_access_to_access -### Case2: test_tag_access_to_access +### Case2: test_unmatch_drop ### Testing Objective This test verifies the VLAN function around untag and access ports. -*p.s. This test will not check function with the native VLAN scenario. Please make sure the native VLAN will not impact the result.* +*p.s. This test will not check the function with the native VLAN scenario. Please make sure the native VLAN will not impact the result.* With an untagged packet, on the access port, when ingress and egress happen, the behavior as below | Port mode | packet tag mode | Direction | Action | | :---------|--------------- | :-------- | :--------------------------------------- | | Access|Untag| Ingress | Accept the packet. | | |Untag | Egress | Untag the packet. | -| Access|Tag| Ingress | Accept the packet. | -| |Tag | Egress | Untag the packet. | ``` Test example: Untagged: pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000-> Port2:Access:VLAN1000 -> pkt(Untag:DMAC=MAC2) -Tagged: - pkt(Tag:VLAN2000:DMAC=MAC10) -> Port9:Access:VLAN2000-> Port10:Access:VLAN2000 -> pkt(Untag:DMAC=MAC10) ``` ### Test steps: -Test Steps: - - Create ``Untagged``/``Tagged VLAN 1000`` packet with ``mac2`` as dest mac. - - Send packet on Port1. - - Verify ``Untagged`` packet received port2. +- test_untag_access_to_access -## Test Group: Frame Filtering +1. Create ``Untagged`` packet with ``mac2`` as dest mac. +2. Send packet on Port1. +3. Verify ``Untagged`` packet received port2. + +- test_unmatch_drop + +1. Create ``Tagged VLAN 1010`` packet with ``mac2`` as dest mac. +2. Send packet on Port1. +3. Verify packet is dropped. + +## Test Group2: Frame Filtering ### Case3: test_untagged_frame_filtering ### Case4: test_tagged_frame_filtering ### Testing Objective -Drop packet when the destination port from MAC table search is the port which packet come into the switch. +Drop packet when the destination port from MAC table search is the port which packet comes into the switch. ``` @@ -104,16 +110,16 @@ Test example(Untag): ``` ### Test steps - - Add another ``MacX`` as Port1 mac address into MAC table - - Create ``Untagged``/``Tagged VLAN1000`` packet, ``mac1`` as src mac, ``MacX`` as dest mac - - Send packet on VLAN Port. - - Verify no packet received on any port. + 1. Add another ``MacX`` as Port1 mac address into the MAC table + 1. Create ``Untagged``/``Tagged VLAN1000`` packet, ``mac1`` as src mac, ``MacX`` as dest mac + 1. Send packet on VLAN Port. + 1. Verify no packet was received on any port. -## Test Group: VLAN flooding +## Test Group3: VLAN flooding ### Case5: test_tagged_vlan_flooding ### Case6: test_untagged_vlan_flooding ### Testing Objective -For mac flooding in VLAN scenario, before learning the mac address from the packet, the packet sends to the VLAN port will flood to other ports, the egress ports will be in the same VLAN as ingress port. +For mac flooding in the VLAN scenario, before learning the mac address from the packet, the packet sent to the VLAN port will flood to other ports, and the egress ports will be in the same VLAN as the ingress port. ``` Flooding | Port2| @@ -123,15 +129,27 @@ Flooding ### Test Steps: - - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as source MAC and a un-existing ``MacX`` as dest MAC - - Send packet on Port1. - - Verify received packet on all port expect Port1. + 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as source MAC and an un-existing ``MacX`` as dest MAC + 1. Send packet on Port1. + 1. Verify received packet on all VLAN 1000 ports expect Port1. -## Test Group: MAC learning -### Case7: test_untagged_mac_learning -### Case8: test_tagged_mac_learning + +## Test Group4: VLAN broadcast +### Case7: test_vlan_broadcast ### Testing Objective -For mac learning in VLAN scenario, after learning the mac address from the packet, the packet sends to the VLAN port will only sends to the port whose MAC address matching the MAC table entry. +A VLAN is a logical broadcast domain that can span multiple physical LAN segments. + + +### Test Steps: + 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``broadcast`` MAC as dest MAC + 2. Send packet on Port1. + 3. Verify received packet on all VLAN 1000 ports expect Port1. + +## Test Group5: MAC learning +### Case8: test_untagged_mac_learning +### Case9: test_tagged_mac_learning +### Testing Objective +For mac learning in the VLAN scenario, after learning the mac address from the packet, the packet sent to the VLAN port will only send to the port whose MAC address matches the MAC table entry. ``` unicast @@ -139,56 +157,38 @@ For mac learning in VLAN scenario, after learning the mac address from the packe ``` ### Test Steps: - - Create ``Untagged``/``Tagged VLAN1000`` packet, with a un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC - - Send packet on a VLAN source port1. - - Verify packet received on port2. - - Verify MAC table get a new entry for ``MacX`` on port1, + 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with an un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC + 1. Send packet on a VLAN source port1. + 1. Verify packet received on port2. + 1. Verify MAC table get a new entry for ``MacX`` on port1, - -## Test Case9: Vlan member API - - test_vlan_member_api +## Test Group6: Vlan member API +### Case10:test_vlan_member_api ### Testing Objective Test VLAN and member APIs. ### Test steps: -Test steps: - - Use VLAN API to list all of the VLAN member in VLAN - - Verify the VLAN member and the account of the VLAN member are same as config in [config](./config_data/config_t0.md) - - Use VLAN API add a new Member, into VLAN - - Verify the VLAN member and the account of the VLAN member are increased by 1. - -## Test Case10: Failed to add member to invalidate VLAN - - test_add_vlan_member_failed + 1. Use VLAN API to list all of the VLAN members in VLAN + 1. Verify the VLAN member and the account of the VLAN member are the same as config in [config](./config_data/config_t0.md) + 1. Use VLAN API to add a new Member to VLAN + 1. Verify the VLAN member and the account of the VLAN member is increased by 1. + +## Test Group7: Add member to invalidate VLAN +### Case11:test_add_vlan_member_failed ### Testing Objective -When add a VLAN member to a non-exist VLAN, it will fail. +When adding a VLAN member to a non-exist VLAN, it will fail. ### Test Steps: - - Use VLAN API add a new Member to a non-exist VLAN, ``VLAN1010`` - - Verify the VLAN member added failed. + 1. Use VLAN API to add a new Member to a non-exist VLAN, ``VLAN1010`` + 1. Verify the VLAN member added failed. -## Test Group: VLAN Counters/Status -### Case11: test_tagged_vlan_status -### Case12: test_untagged_vlan_status -### Testing Objective - -For VLAN-related counters, SAI should be able to get the counter and clear them. -### Test Steps: -Steps: - - Use SAI API to get the VLAN Status ``_sai_vlan_stat_t`` from [VLAN_HEADER](https://github.com/opencomputeproject/SAI/blob/master/inc/saivlan.h) - - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC - - Send packet from the source port1 - - Verify packet received on the target port2 - - Verify counters increased, bytes counter: OCTETS increased, other counters + 1 - - Use VLAN clear status API - - Verify counters have been reset - -## Test Group7: Disable mac learning -### Case13: test_disable_mac_learning_tagged -### Case14: test_disable_mac_learning_untagged +## Test Group8: Disable mac learning +### Case12: test_disable_mac_learning_tagged +### Case13: test_disable_mac_learning_untagged ### Testing Objective Test the function when disabling VLAN MAC learning. When disabled, no new MAC will be learned in the MAC table. @@ -197,56 +197,15 @@ When disabled, no new MAC will be learned in the MAC table. - Do not config the MAC table ### Test steps: - - Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC - - Send packet from the source port1. - - Verify packets received on all ports except the source port1. - - Verify MAC table, no new entry added in MAC table - -## Test Case15: L3 switching(Inter-VLAN) -### Testing Objective - -Testing L3 switching(Inter-VLAN). - -In this case, it will cover the scenarios for Server to Server (east/west) in different VLAN(Inter-VLAN) - -``` -Server To Server - PC1 -> pkt(Untag) -> |DUT|Port1:Access:VLAN1000 - |L3| <-> |Virtual Switch| - PC2 <- pkt(Untag) <- |DUT|Port9:Access:VLAN2000 -``` - -The process is as below: -1. PC1 sends a untag packet to port1, which is a VLAN1000 access port -2. Based on packet dest IP, derive the route to the dest IP, Dest MAC and Port derived from L3 table. Then SRC MAC change to Switch MAC, Dest MAC change to PORT neighbor MAC, forwarding to PORT9 -3. Packet goes through VLAN2000 port9 + 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + 1. Send packet from the source port1. + 1. Verify packets received on all ports except the source port1. + 1. Verify MAC table, no new entry added in MAC table -### Test Data/Packet -- Input Packet - ```Python - simple_tcp_packet( - eth_dst=SVI_MAC, - eth_src=SRC_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` -- Expected Packet - ```Python - simple_tcp_packet( - eth_dst=PORT_NB_MAC, - eth_src=SVI_MAC, - ip_dst=DEST_IP, - ip_src=SRC_IP) - ``` -### Test Steps: - - Create Packet, with with dest ``SVI_MAC`` as dest mac, and dest IP ``192.168.20.21``(config as [Config_t0](./config_data/config_t0.md)) - - Send ``Untagged`` packet on ``port1`` - - Verify ``Untagged`` packet received on ``PORT9`` - -## Test Group: ARP Flooding and mac learning -### Case16: test_arp_request_flooding -### Case17: test_arp_response_learning +## Test Group9: ARP Flooding and mac learning +### Case14: test_arp_request_flooding +### Case15: test_arp_response_learning ### Testing Objective In the ARP scenario, the mac learning process is: 1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff @@ -308,11 +267,33 @@ Test example: - Do not config the MAC table ### Test Steps: + - test_arp_request_flooding - - Create ARP packet with dest ``mac2`` - - Send ``Untagged`` ARP packet on ``port1`` - - Verify ``Untagged`` Arp request received from Port2 to Port8 + + +1. Create ARP packet with dest ``mac2`` +2. Send ``Untagged`` ARP packet on ``port1`` +3. Verify ``Untagged`` Arp request received from Port2 to Port8 + - test_arp_response_learning - - Create ARP response packet with src:mac2, dest:mac1 - - Send ARP response packet on port2 - - Verify ``Untagged`` ARP response from Port1 + +1. Create ARP response packet with src:mac2, dest:mac1 +2. Send ARP response packet on port2 +3. Verify ``Untagged`` ARP response from Port1 + + +## Test Group10: VLAN Counters/Status +### Case16: test_tagged_vlan_status +### Case17: test_untagged_vlan_status +### Testing Objective + +For VLAN-related counters, SAI should be able to get the counter and clear them. + +### Test Steps: + 1. Use SAI API to get the VLAN Status ``_sai_vlan_stat_t`` (defined in [saivlan.h](https://github.com/opencomputeproject/SAI/blob/master/inc/saivlan.h) ) + 2. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + 3. Send packet from the source port1 + 4. Verify the packet received on the target port2 + 5. Verify counters increased, bytes counter: OCTETS increased, other counters + 1 + 6. Use VLAN clear status API + 7. Verify counters have been reset \ No newline at end of file From 0c53ec545274a9ccc65280a55eaceed00c4c0d69 Mon Sep 17 00:00:00 2001 From: richardyu-ms Date: Sun, 19 Jun 2022 04:11:30 +0000 Subject: [PATCH 18/18] adjust the case numbers and vlan id Signed-off-by: richardyu-ms --- doc/sai-ptf/config_data/config_t0.md | 21 +++--- doc/sai-ptf/lag_test_plan.md | 23 +++--- doc/sai-ptf/vlan_test_plan.md | 108 +++++++++++++-------------- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/doc/sai-ptf/config_data/config_t0.md b/doc/sai-ptf/config_data/config_t0.md index 928c0d2b4..fe5fac4c9 100644 --- a/doc/sai-ptf/config_data/config_t0.md +++ b/doc/sai-ptf/config_data/config_t0.md @@ -28,15 +28,16 @@ In this configuration, we mapped the IP and MAC address into different parts of For MAC addresses, we can use different sections in the MAC addresses to map different title numbers. The pattern is ``` -L1_NUM:L2_NUM:L3_NUM:ROLE:EXTRA:SEQ +00:TITLE_L1_NUM:TITLE_L2_NUM:ROLE:EXTRA:SEQ ROLE: T1=1, Server=99 ``` For example: -For the MAC address in ``1.1 FDB Configuration``. +For the MAC address in ``1.1 FDB Configuration``. +`1.1` is the title number. ``` #Server MAC -01:01:00:99:02:01~01:01:00:99:02:32 +00:01:01:99:02:01~00:01:01:99:02:32 # 99: Server # 02: EXTRA (Group ID) ``` @@ -49,7 +50,7 @@ Format: ROLE.NUM.GROUP_ID.SEQ - ROLE_NUM T0: 10.0.0.0 -T1: 10.0.0.0 +T1: 10.1.0.0 Server: 192.168.0.0 For example @@ -73,8 +74,8 @@ The MAC Table for VLAN L2 forwarding as below |Name|MAC|PORT|VLAN|HostIf| |-|-|-|-|-| |mac0|01:01:00:99:00:00|Port0||Ethernet0| -|mac1-8 |01:01:00:99:01:01 - 01:01:00:99:01:08|Port1-8|10|Ethernet4-Ethernet32| -|mac9-16 |01:01:00:99:02:09 - 01:01:00:99:02:16|Port9-16|20|Ethernet36-Ethernet64| +|mac1-8 |00:01:01:99:01:01 - 00:01:01:99:01:08|Port1-8|10|Ethernet4-Ethernet32| +|mac9-16 |00:01:01:99:02:09 - 00:01:01:99:02:16|Port9-16|20|Ethernet36-Ethernet64| ## 1.2 VLAN configuration @@ -135,13 +136,13 @@ SAI_NATIVE_HASH_FIELD_L4_SRC_PORT ### 2.4.1 VLAN Neighbors |Name|Port|IP|dest_mac| |-|-|-|-| -|vlan10_nb1-nb8|Port1-8 |192.168.1.1 ~ 192.168.1.8 |01:01:00:99:01:01 - 01:01:00:99:01:08| -|vlan20_nb1-nb8|Port9-16|192.168.2.9 ~ 192.168.2.16 |01:01:00:99:02:09 - 01:01:00:99:02:16 | +|vlan10_nb1-nb8|Port1-8 |192.168.1.1 ~ 192.168.1.8 |00:01:01:99:01:01 - 00:01:01:99:01:08| +|vlan20_nb1-nb8|Port9-16|192.168.2.9 ~ 192.168.2.16 |00:01:01:99:02:09 - 00:01:01:99:02:16| ### 2.4.2 LAG Neighbors |Name|Port|IP|dest_mac| |-|-|-|-| -|lag1_nb|lag1| 10.0.1.101 | 02:04:02:01:01:01| -|lag2_nb|lag2| 10.0.2.101 | 02:04:02:01:02:01| +|lag1_nb|lag1| 10.1.1.101 | 02:04:02:01:01:01| +|lag2_nb|lag2| 10.1.2.101 | 02:04:02:01:02:01| diff --git a/doc/sai-ptf/lag_test_plan.md b/doc/sai-ptf/lag_test_plan.md index d7a61a681..b80672adb 100644 --- a/doc/sai-ptf/lag_test_plan.md +++ b/doc/sai-ptf/lag_test_plan.md @@ -11,14 +11,13 @@ - [Case4: test_loadbalance_on_destinstion_ip](#case4-test_loadbalance_on_destinstion_ip) - [Case5: test_loadbalance_on_protocol](#case5-test_loadbalance_on_protocol) - [Test Group2: Disable Egress/Ingress](#test-group2-disable-egressingress) - - [Case6: test_disable_egress](#case6-test_disable_egress) - - [Case7: test_disable_ingress](#case7-test_disable_ingress) + - [Case1: test_disable_egress](#case1-test_disable_egress) + - [Case2: test_disable_ingress](#case2-test_disable_ingress) - [Test Group3: Remove/Add LAG member](#test-group3-removeadd-lag-member) - - [Case8: test_remove_lag_member](#case8-test_remove_lag_member) - - [Case9: test_add_lag_member](#case9-test_add_lag_member) + - [Case1: test_remove_lag_member](#case1-test_remove_lag_member) + - [Case2: test_add_lag_member](#case2-test_add_lag_member) - [Test Group4: Indifference Ingress Port in Hash](#test-group4-indifference-ingress-port-in-hash) - - [Case10: test_ingress_port_hash_indiff](#case10-test_ingress_port_hash_indiff) - - [Test Objective](#test-objective) + - [Case1: test_ingress_port_hash_indiff](#case1-test_ingress_port_hash_indiff) # Overriew The purpose of this test plan is to test the LAG/PortChannel function from SAI. @@ -93,8 +92,8 @@ For load balancing, expecting the ports in a lag should receive the packet equal ## Test Group2: Disable Egress/Ingress -### Case6: test_disable_egress -### Case7: test_disable_ingress +### Case1: test_disable_egress +### Case2: test_disable_ingress ### Testing Objective These cases will cover two scenarios: disable egress and ingress. We can disable ingress or egress on a lag member, then we expect traffic drop on the disabled lag member. @@ -119,8 +118,8 @@ These cases will cover two scenarios: disable egress and ingress. We can disabl 6. Check if Packet drop on port1 ## Test Group3: Remove/Add LAG member -### Case8: test_remove_lag_member -### Case9: test_add_lag_member +### Case1: test_remove_lag_member +### Case2: test_add_lag_member ### Testing Objective These cases will cover adding and removing the lag members. We can remove or add a lag member, then expect traffic to drop/appear on the lag member. @@ -143,9 +142,9 @@ These cases will cover adding and removing the lag members. We can remove or ad ## Test Group4: Indifference Ingress Port in Hash -### Case10: test_ingress_port_hash_indiff +### Case1: test_ingress_port_hash_indiff -### Test Objective +### Test Objective This case will verify the ingress ports should not be as a Hash Factor in Lag loadbalance. When forwarding the packet from different ingress ports, if only the ingress port changed, then the loadbalance should not happen among lag members. diff --git a/doc/sai-ptf/vlan_test_plan.md b/doc/sai-ptf/vlan_test_plan.md index 43d9a8e1b..c5dca691b 100644 --- a/doc/sai-ptf/vlan_test_plan.md +++ b/doc/sai-ptf/vlan_test_plan.md @@ -7,29 +7,29 @@ - [Case1: test_untag_access_to_access](#case1-test_untag_access_to_access) - [Case2: test_unmatch_drop](#case2-test_unmatch_drop) - [Test Group2: Frame Filtering](#test-group2-frame-filtering) - - [Case3: test_untagged_frame_filtering](#case3-test_untagged_frame_filtering) - - [Case4: test_tagged_frame_filtering](#case4-test_tagged_frame_filtering) + - [Case1: test_untagged_frame_filtering](#case1-test_untagged_frame_filtering) + - [Case2: test_tagged_frame_filtering](#case2-test_tagged_frame_filtering) - [Test Group3: VLAN flooding](#test-group3-vlan-flooding) - - [Case5: test_tagged_vlan_flooding](#case5-test_tagged_vlan_flooding) - - [Case6: test_untagged_vlan_flooding](#case6-test_untagged_vlan_flooding) + - [Case1: test_tagged_vlan_flooding](#case1-test_tagged_vlan_flooding) + - [Case2: test_untagged_vlan_flooding](#case2-test_untagged_vlan_flooding) - [Test Group4: VLAN broadcast](#test-group4-vlan-broadcast) - - [Case7: test_vlan_broadcast](#case7-test_vlan_broadcast) + - [Case1: test_vlan_broadcast](#case1-test_vlan_broadcast) - [Test Group5: MAC learning](#test-group5-mac-learning) - - [Case8: test_untagged_mac_learning](#case8-test_untagged_mac_learning) - - [Case9: test_tagged_mac_learning](#case9-test_tagged_mac_learning) + - [Case1: test_untagged_mac_learning](#case1-test_untagged_mac_learning) + - [Case2: test_tagged_mac_learning](#case2-test_tagged_mac_learning) - [Test Group6: Vlan member API](#test-group6-vlan-member-api) - - [Case10:test_vlan_member_api](#case10test_vlan_member_api) + - [Case1:test_vlan_member_api](#case1test_vlan_member_api) - [Test Group7: Add member to invalidate VLAN](#test-group7-add-member-to-invalidate-vlan) - - [Case11:test_add_vlan_member_failed](#case11test_add_vlan_member_failed) + - [Case1:test_add_vlan_member_failed](#case1test_add_vlan_member_failed) - [Test Group8: Disable mac learning](#test-group8-disable-mac-learning) - - [Case12: test_disable_mac_learning_tagged](#case12-test_disable_mac_learning_tagged) - - [Case13: test_disable_mac_learning_untagged](#case13-test_disable_mac_learning_untagged) + - [Case1: test_disable_mac_learning_tagged](#case1-test_disable_mac_learning_tagged) + - [Case2: test_disable_mac_learning_untagged](#case2-test_disable_mac_learning_untagged) - [Test Group9: ARP Flooding and mac learning](#test-group9-arp-flooding-and-mac-learning) - - [Case14: test_arp_request_flooding](#case14-test_arp_request_flooding) - - [Case15: test_arp_response_learning](#case15-test_arp_response_learning) + - [Case1: test_arp_request_flooding](#case1-test_arp_request_flooding) + - [Case2: test_arp_response_learning](#case2-test_arp_response_learning) - [Test Group10: VLAN Counters/Status](#test-group10-vlan-countersstatus) - - [Case16: test_tagged_vlan_status](#case16-test_tagged_vlan_status) - - [Case17: test_untagged_vlan_status](#case17-test_untagged_vlan_status) + - [Case1: test_tagged_vlan_status](#case1-test_tagged_vlan_status) + - [Case2: test_untagged_vlan_status](#case2-test_untagged_vlan_status) # Test Configuration For the test configuration, please refer to the file @@ -46,7 +46,7 @@ In this VLAN test, most of the test cases will be tested with a Tagged or Untagg ```python tagged_packet(eth_dst='00:11:11:11:11:11', eth_src='00:22:22:22:22:22', - vlan_vid=1000, + vlan_vid=10, ip_dst='172.16.0.1', ip_ttl=64) ``` @@ -78,7 +78,7 @@ With an untagged packet, on the access port, when ingress and egress happen, the ``` Test example: Untagged: - pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000-> Port2:Access:VLAN1000 -> pkt(Untag:DMAC=MAC2) + pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN10-> Port2:Access:VLAN10 -> pkt(Untag:DMAC=MAC2) ``` ### Test steps: @@ -90,13 +90,13 @@ Untagged: - test_unmatch_drop -1. Create ``Tagged VLAN 1010`` packet with ``mac2`` as dest mac. +1. Create ``Tagged VLAN 11`` packet with ``mac2`` as dest mac. 2. Send packet on Port1. 3. Verify packet is dropped. ## Test Group2: Frame Filtering -### Case3: test_untagged_frame_filtering -### Case4: test_tagged_frame_filtering +### Case1: test_untagged_frame_filtering +### Case2: test_tagged_frame_filtering ### Testing Objective Drop packet when the destination port from MAC table search is the port which packet comes into the switch. @@ -104,66 +104,66 @@ Drop packet when the destination port from MAC table search is the port which pa ``` Test example(Untag): - | MAC1 | - pkt(Untag:DMAC=MAC1 or MACX) -> Port1:Access:VLAN1000 -> FDB(contains:MAC1,MACX)| | -> X - | MACX | + | MAC1 | + pkt(Untag:DMAC=MAC1 or MACX) -> Port1:Access:VLAN10 -> FDB(contains:MAC1,MACX)| | -> X + | MACX | ``` ### Test steps 1. Add another ``MacX`` as Port1 mac address into the MAC table - 1. Create ``Untagged``/``Tagged VLAN1000`` packet, ``mac1`` as src mac, ``MacX`` as dest mac + 1. Create ``Untagged``/``Tagged VLAN10`` packet, ``mac1`` as src mac, ``MacX`` as dest mac 1. Send packet on VLAN Port. 1. Verify no packet was received on any port. ## Test Group3: VLAN flooding -### Case5: test_tagged_vlan_flooding -### Case6: test_untagged_vlan_flooding +### Case1: test_tagged_vlan_flooding +### Case2: test_untagged_vlan_flooding ### Testing Objective For mac flooding in the VLAN scenario, before learning the mac address from the packet, the packet sent to the VLAN port will flood to other ports, and the egress ports will be in the same VLAN as the ingress port. ``` Flooding - | Port2| - pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000 -> Flooding ->| To |-> pkt(Untag) - | Port8| + | Port2| + pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN10 -> Flooding ->| To |-> pkt(Untag) + | Port8| ``` ### Test Steps: - 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as source MAC and an un-existing ``MacX`` as dest MAC + 1. Create ``Untagged``/``Tagged VLAN10`` packet, with ``mac1`` as source MAC and an un-existing ``MacX`` as dest MAC 1. Send packet on Port1. - 1. Verify received packet on all VLAN 1000 ports expect Port1. + 1. Verify received packet on all VLAN 10 ports expect Port1. ## Test Group4: VLAN broadcast -### Case7: test_vlan_broadcast +### Case1: test_vlan_broadcast ### Testing Objective A VLAN is a logical broadcast domain that can span multiple physical LAN segments. ### Test Steps: - 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``broadcast`` MAC as dest MAC + 1. Create ``Untagged``/``Tagged VLAN10`` packet, with ``broadcast`` MAC as dest MAC 2. Send packet on Port1. - 3. Verify received packet on all VLAN 1000 ports expect Port1. + 3. Verify received packet on all VLAN 10 ports expect Port1. ## Test Group5: MAC learning -### Case8: test_untagged_mac_learning -### Case9: test_tagged_mac_learning +### Case1: test_untagged_mac_learning +### Case2: test_tagged_mac_learning ### Testing Objective For mac learning in the VLAN scenario, after learning the mac address from the packet, the packet sent to the VLAN port will only send to the port whose MAC address matches the MAC table entry. ``` unicast - pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) + pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN10-> Port1:Access:VLAN10 -> pkt(Untag:DMAC=MAC1) ``` ### Test Steps: - 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with an un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC + 1. Create ``Untagged``/``Tagged VLAN10`` packet, with an un-existing ``MacX`` as src MAC and ``mac2`` as dest MAC 1. Send packet on a VLAN source port1. 1. Verify packet received on port2. 1. Verify MAC table get a new entry for ``MacX`` on port1, ## Test Group6: Vlan member API -### Case10:test_vlan_member_api +### Case1:test_vlan_member_api ### Testing Objective @@ -176,19 +176,19 @@ Test VLAN and member APIs. 1. Verify the VLAN member and the account of the VLAN member is increased by 1. ## Test Group7: Add member to invalidate VLAN -### Case11:test_add_vlan_member_failed +### Case1:test_add_vlan_member_failed ### Testing Objective When adding a VLAN member to a non-exist VLAN, it will fail. ### Test Steps: - 1. Use VLAN API to add a new Member to a non-exist VLAN, ``VLAN1010`` + 1. Use VLAN API to add a new Member to a non-exist VLAN, ``VLAN11`` 1. Verify the VLAN member added failed. ## Test Group8: Disable mac learning -### Case12: test_disable_mac_learning_tagged -### Case13: test_disable_mac_learning_untagged +### Case1: test_disable_mac_learning_tagged +### Case2: test_disable_mac_learning_untagged ### Testing Objective Test the function when disabling VLAN MAC learning. When disabled, no new MAC will be learned in the MAC table. @@ -197,15 +197,15 @@ When disabled, no new MAC will be learned in the MAC table. - Do not config the MAC table ### Test steps: - 1. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + 1. Create ``Untagged``/``Tagged VLAN10`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC 1. Send packet from the source port1. 1. Verify packets received on all ports except the source port1. 1. Verify MAC table, no new entry added in MAC table ## Test Group9: ARP Flooding and mac learning -### Case14: test_arp_request_flooding -### Case15: test_arp_response_learning +### Case1: test_arp_request_flooding +### Case2: test_arp_response_learning ### Testing Objective In the ARP scenario, the mac learning process is: 1. Send an ARP request, with the source MAC, dest IP, and src IP, for broadcast, the DST MAC is ff:ff:ff:ff:ff:ff @@ -218,12 +218,12 @@ Testing ARP scenario ``` Test example: 1. ARP Request - | Port2| - ARP Req pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN1000 -> Flooding ->| to |-> pkt(Untag) - | Port8| + | Port2| + ARP Req pkt(Untag:DMAC=MAC2) -> Port1:Access:VLAN10 -> Flooding ->| to |-> pkt(Untag) + | Port8| 2. ARP Response - ARP Resp pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN1000-> Port1:Access:VLAN1000 -> pkt(Untag:DMAC=MAC1) + ARP Resp pkt(Untag:DMAC=MAC1) -> Port2:Access:VLAN10-> Port1:Access:VLAN10 -> pkt(Untag:DMAC=MAC1) ``` ### Test Data/Packet @@ -258,7 +258,7 @@ Test example: arp_op=2, # ARP response ip_tgt=IP1, ip_snd=IP2, - vlan_vid=1000, + vlan_vid=10, hw_snd=MAC2, hw_tgt=MAC2) ``` @@ -283,15 +283,15 @@ Test example: ## Test Group10: VLAN Counters/Status -### Case16: test_tagged_vlan_status -### Case17: test_untagged_vlan_status +### Case1: test_tagged_vlan_status +### Case2: test_untagged_vlan_status ### Testing Objective For VLAN-related counters, SAI should be able to get the counter and clear them. ### Test Steps: 1. Use SAI API to get the VLAN Status ``_sai_vlan_stat_t`` (defined in [saivlan.h](https://github.com/opencomputeproject/SAI/blob/master/inc/saivlan.h) ) - 2. Create ``Untagged``/``Tagged VLAN1000`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC + 2. Create ``Untagged``/``Tagged VLAN10`` packet, with ``mac1`` as src MAC and ``mac2`` as dest MAC 3. Send packet from the source port1 4. Verify the packet received on the target port2 5. Verify counters increased, bytes counter: OCTETS increased, other counters + 1