From 5b848048d7077f110123d226efbd9b4bcbb290cd Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Sat, 11 Mar 2017 12:48:55 +0700 Subject: [PATCH 001/133] snapcraft: Replace temporary logo with official FRR logo Signed-off-by: Martin Winter --- snapcraft/setup/gui/icon.png | Bin 21830 -> 35316 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/snapcraft/setup/gui/icon.png b/snapcraft/setup/gui/icon.png index e8f68e6ddea002f7a3f87ae71742444603640fb4..3ab3f8fc16745fbef3f5510059aebd3c11293b0c 100644 GIT binary patch delta 34459 zcmV)>K!d-=ssZ$q0{SW`O4)6pP(q<){sme} z7j#leOUr1(2&+KZl)ZN#YzQNJ5y+11#Cuz|r2qTQeNUDhkM|_mmJ{7Xvh?)c9p~P& z&pp=@M3F>^4+sPUA|7vi^d-@Y9RdQ0)i%J>91QrSt!j(u1(2WLe-kAEf&PL(f&lav zq&v4`30@v=l2knRAE|uhVZDRjgZ=~&=nSsJ_r8HZf&lalTwT=~Xl|DBzn>{vAN{uk zni|BD1R@ZCI*`!LT){DMvwH|62!MN-#rz3xMwWPoiqt&*Gbx$e2-@INR4 z3AWaYH)oo7Qb$SUoo7kuU4N3cnsTEOu&;C#CQ1SVF@ivXe*nY?kWp0w)+cgmB3dk-pujh%^fGz z4__uFH~&I>WgFl*!1N_th5b7v+gWP~0uT=q8ZH6Y+CX@}sQ0(RF5pd-*reF<_tCjexy%fp&o)q=7o91G|bRd4yEV`GJ(( zbB*|GtBhTM_@A%~^ajYp?-m3S1RyS!LRWHsPaT7+5b*+%nkU|Z$x{2=A7%567fJKl z6_%?If4?U}hm7)qjcfh>d&XTeqY;KfpMf7`F5b?asmLd^OTDnTT`-R_@B5P&$C zV&_J{o;u4A;zn#KOqHafY0@}vwrsv`mNYE;)I5}M74`(Y9rm{b0f>jGrzjsP;krTS zqQej5^p>lzcsFU?_@rS|Eoq~xZbO3Q{X;VQ(mqs@e?(1z8H`!_)V25jyPrw%o*lD`{2VCc#2KX{Nx zgmwYcojiP3X{nk zf%p!x7AwBL30uVk%h#KBB^e0*TWy>UW z%D1K9oNFX=@}7DVi4?sBiLzrrAVC27VxHB)PDBRh4KwhymY3)j-iFWKkd|dHNT6b! za(-|2X!YOspJg6>gKFSG+A)9CeD3+nK=E#t5o~+O?M1aJIl0%|w&k#rufLP9M zSKQv;ihO>{q<;Pz()j6f(zfv(W%8cPA>vIR32sb79b@|2(3Ac|I3sCzQgS5FxIuyq z)slPCby9HZMIZ<{=#M3dgb}bvr)kLkYr$on_o2ZEyCNtx(ItN6=TOUAzENa5MPleAGgD`XNXK`a(X z{ML~m0MX115g!(P+n~p)XjH5J;$5kq_o%cie@dCUiuftnrlkNly>feg?N5$xns0x% zI6Nn<4qTTr#kcw`@qo#Db0-0*l9juX<13DHFsiK?EXPDe?VSf&jRkAMUDCBr-_cvU!cveekl>f4}p9w66OIZZ;r( z&aS8x(t*F(AdcHMBD&w^=oXUmtTE-=kIM1%j8uEr{;X^k5B%u1HTB z`#%*1!W{e#yTG@vkfFz(g@a0{wj?Bhh^8ivA4(7ar<0>TavQmTKcyR__TA^e@$ZFU z?=x(}1>$5+S8USge><($5DBMExVz6rcsv#2=0JA*1L@J=A3+pgu(bps!MF#=PK`q) zlblJCG;{*ejqfDMLr3ECa7i9gAW1nxBq=)|#>osA0&y^jBE28i^Fa_ofeP-rnYcTy zA&?*dy-iOij^9?bMQYx8Uh3YsQ`$CtBA!eje&#eqE=7Fhf0A^e^+f?<+g#Y20&$&4 z$(Vj%w<7ySgY4w$knX)XBY@=7C1vCkNg1(=qzoS`DTN~qvS$O?aVoJV6)Zndc321` z2tapJ4@3)s>)SywfyO$d+j?DUUbI*gWuPIDAOKy=KnDXKjAL~R-k0hZZkLwNA5l@?lQk7j0ZXv=-Wc}!Le#gg z5N82+lE9@&kXp(m&`_$nI}G+XPW(Vg9lN)r?XsJse~q0gsUyJQf$*Lb5Q(meA~=7r z>Ne=zey0wjFUHc|MB-C?K_Ec@!skP|etXz1v+P#Ae7`ij^*6;CZ$6A;K%O8BX=*v^ zj6mUaMe~_fdUARg@`5cDh#`O;53xRJNWP@(JX6vq?I-CIfb?S~NJ_zQ=;vJ^JU1Mn z2IIZ6e~>zX;L*&=cKK|A09ezi{(MW+_19HN_1q_=_QijSf6FSQ-iD~3oB_^@(|HV9 z#c(kwngUa)v?qh40O{N6f%NNDyiXcdENN4YmyGF$7^ELLPDT0-9Z{z_&t$diGw9ZN4q3oz*A0-aA4XRf-Mm58;{twppo?Dj)rew62*a-u$sJqGf|4n?pCK zhsUHS;=^-5Ridp~g7se-5x;Pfr0;%`WPjsm$(XXIB3BopTLJ=+ zLtuv^0O1z?*2*%eeC|I|_rg{1hXd6Sf58`|WuM}{^8d&I+x{f5mqxwhEFgY^1ggJM zgie`ojAZS5qGa!VxTKGrY)Ki`Q$%{Z{RGmtgEH|c<`CGS2tYXU*DriuDj&W^T2{P* z({?8SM^k~I;QFyFM0|?+P$L3WUn4P}NctW>lI#Odl&sz0vmaUxH@1VPO64wVk1RMm255h5q5Dn?JT3e*z`Fo}2v5PeS zUQ*$7MO3`S1o=J5^v`?5U%gamO8Q>s%8;37OV;iOh9N$P1PeHRY|a5R)wRDPIx#@` zz1>CFxt(AeGX5Y-QCn5Hf3%iwmewsBrL}Cmv~9(!Vm%1gMg$)%m0+F7$bWoh2!L@v zv^SIZwB12q`y&7pT~Wwo>D%A>;6J3{&6}`MW*ppmNPUG(G^Rwug()6G&u2cp2DtO; znk04C6D9B1^CagRM#TDIqJRAc-Jy99@NL&!N2d>Y^y|$7?l00&T= zp=`%m)K}sL#3%hhf8F6oA82V3-MAr^z{`>K#fe>24W z6D0rCUr5fLe}|x2Q*U@5TsP6x19k*pNQyA+5b2w~UM7u8Ka%EU?@H^2mk?D5t_>|i zv;E|83cxo>U~pY^g*P-)2eM>jyIQdzVYr)P2kXP?dsB zL_uJ}f0mMt1xOlRA2SU%;P|kHk6%KH@%yo92<^eX=t;+Zh3pK_2katLNrCnarUtT0 z0^w~)B>wgcfk8_EY~*jNsgSa}{~(R?ZiBuL|339tZsdsu`K{P}fAu07`(?-vZ#C($ zvvL)h;r51}!Q1<r?-d@ z28)I)aiRAn6L%ya5Q4yX|)xQt!7!fC=$Pa-UJN5$2@R8S* zOV06sl!8+(M%wHm1*$D^xQ1|t2hfgM^?|q+5oxO~m%2~q;#`5pA?81!-UV;o7`QHB z!yuQ(4nk8B$ld{zi7zpMz@Q=kjCLdPf46L2D`hwTpZHe2gv6M%^n+ch^C}V~0nuPk zPf`ZlhD(s*d$e-xba zSIL~TyDo#6aDB942kx*^hU3dKVD?HRHO==XT^Yi1^_6HsVKY!`Q)AaALSo zL10i202}#f6)&6pe+KyrqDOvD3X*iRV&`7vTFE-{mr`)X6;=#9U?y~8HMe>+DhgI0V?)Zg9^AJk9JSKzo3uE?m6wJ#oydjeo1 zkq?_!N^kzD_`ZDE;{4pk%Myu*4CIE3FVMIdNjNL@5X@mG{ur77w(=73xlp4q^r>~8 zE(RLVgE7*z2?ScFaDJ_fsXBqq=MSjcDj~#se zip6lR?JI>B-XdAMenWw*?L~w9VO&4h=98LtUzF-+Z$P5a_YsmjO1wqGfcQAhi#Z5l zm1wljmq!#0sNusSEgQdQP%$>0e`qj$!s#CiCUl7J-*kf5>(o_kT}`_?Z-+`$s)m%SaiF=(9MEOYquK3Lk6P^tDv{@81YV zo-Lldp*WHofB6S^(oZP=KxA#W>{49b9wY*{Z32`>8zKNg;7OT+W7Po@5>S65ygJXo zGxChoLOMv<n~WXU=|FyCL{u9MiFHCfh}m4n4*{V5M=Fm}J?}ZG zdhmRl$v4j6CvgwZOhLQx8^l8|7Yy}47xI|QDR7UVtnaE`uGc9|(z z`=25?`+iH4uh{O@kjpk95!euQ{WmTMfYJLAf8x7ojcmR1G9bMld-{jNa0Xw$?L&4v zG%Pl7eZCa=Px=dx|JV2mAAdB+4@04e4e)3dp7Q^~IEhV2NqTZH2umpUK-dCz+~*zS zMvD$~J6aF~-SFhcjW|M0BR!dVZT+iK{pG7t_r~s$b-Xo2I03McpB#1TeSgCC*N-vrwD?DX{1E*W`A@vsaDEN&iQLB@F7nrX`nHtca~Zq| z$Onj>dM4veG`R=5nVB8-GLaZBdQK1;Es(andGMq_eF)Spl-j2kO2a#MNY`xlOk^U_l6&4*@EHC$#_scp4%M%cbhS7s}?p{y?hVc@8;Jnn8=P zq?HiZA=cg2n)m?_7%&1r_Yfzle{tm(u=rn$6j%9}JP0J%1CJkEP7cF+vyc&Y36A1A zPm0d@z2@eR82QmRqnae)AdM|jdfTt1_Nl92<(~{c6%3QiGVHpKE{Bx3y$c9%T~O4A zixtGclR6A)*mNXsc}vP~I#Eh){sl55FVg2|D5Ufj88hjk>FxB=fDiy9e^z^O3{|<5 zKX5e;*Vqd2ZZr@JN$*_KB*YFNw%=dASkk7SDn$tLVN_W($j?PXPU0(BCnf*-sWiTG zD-v`}$7L)ia3J@6+)h`I<6$9daYRyGcMVt!LU&Qt<5>4;!VOm3Y*q5NW2EAlyRp%$ z9&?EJ0Sc4qZRoD99s7F!e-i-J`x)2~l!~WrmzKrPSn0c|=eg_->*B^9+eY_0L|nR zMq*{G3iN*3VjvYH6=91w42MAaiY~la(njs96CH97xv4UQ{7_3)EtJyh z&qB`qxz^TWW*p)IN+7=*kn&y<<3Q6EMSR9}cv5gQdIw_Qw#F{*C*z>n23M>%txyB9 znioDGCD$G!Rj)sWf2o5V2ojwV0ehaisAfmJ)UO0U53mG9X6S6?L%&5hXbK24qydO> z?vM+F1j#$qTi|Puf}h+inN#-EMPPQ9xkOZZQP3u_{BtS0@eFAz{}hsm<&M;q;j+#h zaW!=@X2xH5GloJ+TMrw}B5cE63N^|HLXcyK0Xeiv1zkMsfA$hNJq?AhBP9)mHwo=j z+;+N@-UatE)XflMu;<%t{oCRF{pSWG$0ijszpO`Nx`v^f9~0h(Ek5E$dcD z^Op;x<;#zxe{I9-*pdxF04_aGHnJk6W?P8smJxK-CrSfI4G%-DCk@f01;g~b2;cg} zQuyP)O2*F2vW$|58Bj2IV2uaX^h04YK(eaW|0fl5PSfNVs#8Zm{h7U&IsCF`UM0iN z|1(w+Exv}pxEhH)bRz%C1wj5Yz@e5S@Wkf)E{Tb&f5zkCW=_2&*{CFjBh%YTWyJ44 zl8lMSi^#cgOHexuE3AIK9z-hlQrK5kO4G8BrD@S?i2a|dzj*U-GI81v<=TR?3(q)ikQ55*byM45xYtH1AUzRVk(+-_+Ad8>+WaLr_7_Nux|;7}lVlg?7w2g$Ou24(JRtZIGnA@yOnL zbxe?-_K31uE`ol#z<49JOXRl1`@fXJpFJmee}^8g+(oB}+{Hz)seWrksg&Gw5wg|56{%T< znP}8qT`rpK=UV|Y!k$Ra)aNLSvk11V!3$r2@H|a8sbD`z88t&v#vonS$eksnXf%>? zU`JjCGIgjJ-be5NAuvk=^@q(LV=rnycuDHtz8CvK=EK921zW*52m)9yBm~i@ei26rJ&NNC$`*jZlgtTnBUMQvzTEwRP)e+5Gn(V$b|r*zU{w}#JCd`wHNWV(t@|$#$jQr)@5sUt|&QHH^f9XAck-F#q ztf8bqWTlCXuF263R3Rc^KZJFhIaQ@#9TKQQa7r0-xTH-*%B`vUN;;9gXcQ10Nens{ z&KX|=m4`3Xe!KCtdEF{xR(?nt=3Y(XJ`8zK9~myLdq&#t>pYa6zk>*XI8v(gmo5hp z_=7T)9Z?eKI|5+2SsGV-e<3B;?1cq4M)!ETi}lB1B(?TcVZy7W_}A|si|@Wz0FhYy z+oc7j8>_nKCkPmsf&~vtMoxc%3@XTbhihC_z(Y6(jH7w<{c)3c>{;S;dce~eM4U_!?&7`W~$ z37yFpMIw-U%3sayQDiEPXnnbEKRzCyVjcTJF^fL`))uLH;VvA$fv?$c@o0h%7gU?B zDU?8UnG87_d%%JGEFDrw>y=*K$XP6rvG$|arTSqY|FE&RgzGR)x>X~3X{{fAw#H)_ z^_YLqU%5<;c&SrPf0XP4PtlxuX(PvhFtkrG7dEJ!fgi+eJJ()6bl7DRFdS+ezeNaO zM9kjv5D>EIQuW%mq~@uMU(Wy&^3)g9(%MbqBf2yUDKI4Zn@)x(k7?h)2 z&aK7Prs&OUmSeNX3D_vI78YS78@2YCJMB?i+^0HhDi$d+9Kn_nsDn!tbTWO<^Cai6 z?}13}W3uYnowYdqpw6m`G3$~dVxlxG`9vxn`imYE<1LtE2sk4EU2i1ABMMI#Nzp){ z{7V^n!TmDyf7r9wj9%k9-kwYB34ld8dEWh|znzVPF`mb6EhKW#3335Uif7z*>#vdF zSH6Q#-@T$jet&J1Y`)<_X<3E?Mus8K$E`Fn;H!Y#n>s$M*l?i+YS%!m63N)-63IQ{ zG(~*suy#?R$1fJr*w+X1-*6*cTlH2c|KH70|H@xre^^Gs&@{w@xHc|Z&>#^&3Nis) zgY_Gv@bXtBcmJae0pKm$F%f8&4`a15EMV2V_aZ1XkRJzNs?o-!)s`I2U$t3={P0#q zelrg))CWF*iM8Xu%b%Jf%?tjAZM{~AZMY6H zZU1&Lf1hkpStUhim$2%y&d09ekXnE-CJ!l;;phEXD#uPimZmd-{H0(t*4(;WYXBCI zANd8~X$q!gOZi2^#2V!BF5p-C<2_N#sEPCWrvMNgV<9Ty-ic8&S5 zX(V;p@sfYE9kB%}?Rp}N#8HE6F?G-5jDbRAe;mR@51vAm3CIjDNU&uq_D=vN6Hk(& zpS>(2fA(+a#Rn_$t8Q;0zH)rma2h-i;Tj-uv)9_tnP*7xFWx}};qK}wA`(YbKm=%1 z^k$7i#NY&^P2ZwkhZn&B8X#(d+rapmPRcGs^p(? zf4L;_P)V)ZU03Y|(!BmlseBme!7|g(KL|V#8H@&EB7yu2;NgizIL?fsfBrdls~a@; zz+*yw>kw?VXQb}}{JPfEs3~e79Dc>ak}~cnO$?)3j`bN5P&dWo7D&pUA-h3Vrm8`5uRE;jVNk}U1dm$mu>mDE+88)g{gzMqK@SiBMgZl@{S4;M{ zu9Td;4z+%DH<2o~!HOL4HDTxBO$hT{3d#=d@74|x-nV}HjIol-QP*!Nm%!HLl6mk? zW#sQ(5guV~_C7!w!s1sX*ufCL!!%IMq2z;gld##{FwQd>MJ%KQ@UoRor&kgoXT#>oiHokYiwp zRZ)+kztcJ}J7Lm7^_x#g(|dDZhkzt97({>S`Up_*;Itfnvs)IO$e-YY#>{5%-OI;kY!l5?v)paF3KBVZ4xkc!8y*OQ=B3b53Uh=79m zV;`NpFyD5FbVQ9gd&mWA?WV#oj$8N18`8S=BV&zaf=|bsn?C<^__UWv%7kx8-eD(d zV+0h%VaG+qViSN=`OF+_e;ita*nyqE{oVA%aceQW5y%fiU!ZZly7%%4T)`re-h~z@7vEqjBm!nO$Ch(y-~${OLnd z&D3Hnw%TF7Ie+IoDxpHuCi>a?i>S%9@3P;{d!%OnaP?Zj_%pfiw%h(O^;DZc0iBz7%__vC%E3C;Bu zbSz~}FE&DIp82(8e@@?D!>TD|x{^#S9AR3r*77nKcI^=7ZpK7{pPD8nk`wn@&v$co zRF|V80PL8xIP1T7M|@w+Gsk7Q0yGz13OL_#Nu7EU0x)LkfLsGPVERHAWc5@3P&Gv9 zr?t4Ff>NJ6OoC+sdzdRPW#=QM@VtMTL>y>Ok)PqPeNi}Xe>P`fAFPmTHq}})Ch$MKp+!ka$Ir6CwA2n4{BHWZS?QmK6Qb{To;O^_(C zk%;TcA!D)Ea$8M>l-_VU_G*-1D|RvZ!hPA{5-yn@BRp%-MwX1Y@;RJ=NL85g6@Fjr zCMHT1fE|O!f3Chp>gGKLoe5tQ;qn{N$>&(~_$yNq?Q37C88>&>kO|zxukxOy* zB=S+HLDM zCP)Ej%UdAQIRANRJM#NzYbZKP0^kxc91JmX0zl4y1r@~E?)C3Kr+s6(sbGM4{+t#J znDtQiKWdgFVY82N^RR{5YfVIc8h_A_>X-kEe1kOH@RXr=jQGP?$$=QsTZVn;$NgT4 ze~^sAn~vkgsPD&EX= ztE{s=IJ*nu0)gbqU$#PWPxv!9KMq7C^78=GSRy}wVh9SR7u+Y%R4;Y&-;&L zptHU%n{T>A%C0*?nm)J{3wWH0!JhP;6ajQUJ@?d;Xp;6S_?^!|H{FPU~{2ft090z53xy|@NMio zT!nc8Md_jsBo3a;ENNc+njtoP&~ZDw*;$E*01)w5==y8={6$SJN&Uq!MWxuzkl$MP z{U;qA;{IAMDV@V&-^y$;f6ZUqgAF0OpbNCD##;e&aCCWF=`zVW`qxrC>(>~6jFF!U z8VkfG%nge_l9Jg!mn}COjg;H>f!j|~(U*%}GcuD%hB%-FbN(@FG~NIhU4O7p>@}Nr z$af_3kV}yQex;ED+|;b_!d$}GUH{HQaOsuk)2hZgs>i^Y;oOAH*$1B{$@xV( z4qH!hGAKhVym|_3?c7IHT=L-PZXP>j_s>Z^eSZ&-5`ic@$RzWi^TGMCF^LH%Dfai~ z4|do&8y4jJjK(bcf6vuYdffp~iS7W$+C?)Sqd{1jk&jW;H0MOtVHe{5HdO@(b3|3< zpKv~s)Qs1_D~~1!bx8GSQ&1^jS7}}SCeoC>qvKW^ixck5b#D>ftlbX8=~GbuT9EFp zE6)V)qZ)v&H7)tTT{|vj!#x48j4HvlR->N)@40cs`T2g}fBxWxfrcfLJZcZg-s>>! zt}VJc>pPH2i3lh$I9>A>|5XkbcM*S>L`D9}McCSWq7?o3&ytjdt-Un(#RB=c=-39m z2B@<=@xtb zWZT|Cw?+BEH36WTf~95SSJJZdWdz*NnBvB0gkeD+4kFo4=02xtumbD-$Ff4^&-x-rhhz{gKDj6@KN*SBS( zl-z!ml+QjH5ry-ynQB*LxIuCYW?-gdriP{{#OPbLV7d3^PC|C6Cxl6FwO94FHU9UyIt_)F$V^SYJ2 zRUOgqf9?nX5YN^z=|iR~%abt{0HNMZdevJ2ro!kEY^e|rJbu~VI8q-l+}}-COj`tg z(`R>q`%h5OtScb))}y}p9peO5*CWR8vEbZ)n}{wFg)S!AZ66d~R;)n%g7;w7;nSHyXcz|A>5CWF=lxp4whi;4VgBz@a_<_}o5@>G3!H)CLX?6&HZ5I*%T`7Tv5}fTfOXI3d|6MFnoh;ms ze@Uo&?^&gwMuc)Bg_u_R?42AJ6CJ4DC__%WON<|vt)brzIYoDU3rP?df8|RLz`B1h za@)U)5bWIm6GT+1U)gG_yGjQ5I;BV=KG%~Mge(c_Q0EspCGX)Y=EYjaIr|+YsS}Qc z6aen3dbrb;C`q(H3MfLFxhM6wd-J5he-Ed%q>dabsk?j&?SmmI9(8`63BPu0N54rJiV3`&mnlkif4AZs2M0kBOT^6bDx>&o5g4_co*HU zCa-DD3TgWEUReGS->uxv1rf0a(kFj09@;o6R!HVym&(v@&(c=hdN{i3nvMK{f2Ia0 zyYE`5ymJ;jFrxqiq{nWpQKG0srmKhJ{KfZV<-=@9LB(zB#>!zZfhf0>3l6AE`-55Jp^P-i6!QJYqNfq|DH!6p_SGxs_c z|DpRgZ-$P#8^S5~*LLkNUWc6kr8W~)KmQGI*sU;hG2?K&xc)5Ur-5_izEW`7sRELJQro{jjJQU~&-kee+-V17u zGx^eI94l#~#%mv34Td}ZP+BXuNaH8Z7{F1SaNGxdyzky1uIa`mM0XB7<7z#3&qz4Y zA*Vrpulk)!Z@F9==H05qm!g!0JX1`J^I{_}IsO9=J|L%l_f$Fif9$j6j@$2$&lh|y zwY9a<*48HF73K2wJ8#R4H{K{GpLDXE{iCzxwbx(M(UEwtp4b$FWGMy1CHtV$5tD-D z+?6}7+s3dKp@w-gip973br{9J);rx=>C;BL76V;=Z8+LG=i9$GdF6FbcCVd`aNB!qPQjp)(wi@nmPLry+LhS2Z8ZaW#YX;$iVC^*+G`cLhmRO8Gj^MSe`5&26!_0t&=ik{7Y)~I zGz`A@+Kcky3opv-n`g^~7hEVQDcCw5CP_p*Fd~t){<8KuTxwq|01}oXqLp0ONh}GT z$DA_)mM2!zNXNW{P8phgU&_!TNgcZf&d+$$8VXlOgqeszlh` zu0J}%UUovce?5GX*h~_rSPuyRVwoGa8}Gy$NyO2MdXbJL2cyc9{tkWu2AGpD&_&J zFb3(k-2gE9VMbDejjS~_HFDMOu2SURW6wRLsHjNVe_Gq5xusd{02KfEqJ+@Y+@zoR z>>j)BAycPKl}j(VRBpNDmJssuw^)_*ohBd!8+`J$*r(s6PrjR$sGsZp4&cR#Pjqc6 zo>)lR%~R&G&BdYCrH-GW*K`MKXM(PT3Q_>Hi?+>+k*@(nDu%@w0ni2w#cNtV-!Oe8 z2;^?ge+sSt!G;!y|3{mQKl+&S1*}FiJkzpaHT^uW8@5C$G zMgPu|=?qkQmyP_S_+@wh0pYw4L+7`UU+-`ZI~UEy^i~`BS?Qg3-l^jL-uvt=KA%q! zJwOhMLQdBC#p`^&p`k&NlapoojOlXu<(JE|f6u}5gJK&8^-H90x`xp{q60JcI9zMd z?d;Y*m)@&2>z~0ozBTj1LW7+VCtF=e8#7T6oQIQ`n2nBjW$XasVR!p1)J810KgZ{g z0GJL@_ikB5V~Npq(c9i(q<7HhK`SS$|I-gN&xA=8PAaiI1&zz*!(f9=6zL;SXMF7W ze^;x2)k;a<=SPxv(6Krkom^{yIT>I0J+{G*>dn@Nu9wF5Zikz11~@+ru7j_9@WBW2 zt6%*}CQq5HoV~TxWZiW#5+XXK0uq5?g~R09zh0{bL_TY)4NmIm@*d2ON@@6!QfbnN zJz=9-0ig}-R+&qePj$Gc!8)mmdGrL(+Gi zYCU9C>Yxhc{ur>vA1r=Xd(Gpp)iUDX`M$e_V}q3+*{~d=PcTs1oE>ZVq0!M6z$UE`}7%Ekx$PIt?vn`v~ zO2z$G8cBy)dR!f_605;QUJsGdM)WUNeJNk9{z`@n8KQ2!NQon#qnmKT#0m2LhwsaV z4I3iwV5cW-T|6B=c5g1c0lrGW9t+(Ohb6(r8U;^mEmmXI6ag$eN*OWU zG{^6@XrMLWjo-oW*hbryuR{@m_RrD$?Uex76t)$CKdl=+hxiX&#OieK4P!7A|8c~X zci4!~={D+q={(48Dzn=PB2#ViaztDK7A9gpC7~12-8Tru{_wHY)pHE7DI@?k!Z$Wz!&8ikjqFUmnKBwlL#b)#B6YaN z$eok(;RfEIe@SxKExS&qU1U6fCkyz&y&T)DA@qYTNAB>f2OicShkzD`{p+C zAT8@xS^7W29Z3KjG_JRRLP9M{o3M8%?Uy}?J@m`^seQs*kS5t*iiDL+J~H6qzeU(; z)*z+#MUpvr57XamCa(7p>KzsrXen7MRZsi{J0+2Uf0jQC5?{ZLp_?~y{=O*A*N}tO zId7Z;aQ)QLlkk~e>9y(=Jy1EHC2|5Uu+EunS&Lm~Z_VpOLqbA2d~Yt+b{qZtU9?M_ z12d%!u8k@9>|(7Q`>Wf(U9=Qdg#raVgm_8=2gjawN=u(8U9fkMzv8V14D=DB5Nr@n(oPB$Nt-OI_sWk$B$IsEvr8@ z!4d<`6)`SQ`(Pci8BhAQWLmnv5&$PsQKy013$J0xC(xQB3?u+cYS!>)I;K>>T0!$U7NAzfK#zF@Q4F0N8 zNW65F8J^I7Q_r912}l}(*cJ*N-ANu6!ux@bu_`@}&>9$%f3|I124`t5Mr9~)uN_d% z1__|K9{&G5;r<)m>m%LW&{|#!10>FOf6GLSxT84j?rMtBbx?ceGtAuYMBP%VwOW(o zss+GE!<#|%t6#ZKRV6(kSc#mgn&RqaBC1UQCQh6v2Oe~wl$0U|1Pplgb+;YnbE&DR zvTp4zA0CgfJ>Hu)mu)>>35V{j@I#)&joj_v09I$4^w|=EIs{t3C^nU~) zD*ymM07*naRPXE0?}Q1x8g-?THuYrT;gb;;E*R+kOs-lt?+Ihy;92%@5#SW@s6r1C zS?vuwC!KVX#`3ROvqo~Vks;aT;^qChxw-Pi=U>PV&iH{GcKBi14(qpxLa5=0KNv*! zrlkWB3(Yd`juUUw2A(D6B0w(CRDTTuz+JNLOHvl>8eI3?a(Dbl0syHxh?t02lWD(k&Q1cotxD(r}soro>bp`a{Ao{Or8!i(jOpvSpe1El6lvk(@ zpPh}+SrAhj2Ho|@zJ~@sMig={z!g_qA$hrZ`m7yn)ZO!uT<6I>Dy_Pl29=DxLtyj5 z>B=p}MQKQigI*d4DMakPuMhRQ-qnV79G-+#g2G<`Nj{b_#82Hqm>Ir`lAj z+~2sz>OXl+g0(z?8u1lzmD+4u2)MlxE(M%?^2svi_Bpb0#Y$mb01^S(1b7eE8o9as z;&&o9#r*87Z24@_XHveUTpoJhA=zusz1()g+5KTt=+#hjKE|~k_J2cPL=89s)p==7mm0$|_gud6`-&{`9v zWKk;nw;um;V!yoOK&d7O5ifQ8VUjv>oHhKe zCaOosgg75Vew)5{PJc5SsaRnTy649S)vrWkTNSwA{0rovhaS@X{-1yLxyJL;ut#FR zjY9T|X~CEzw6v^LKL7l4*>A7?G=132nKO0lBoMZA5j$YC&!ZxuU2*$m`%2e;l~yoc z1(&HC{k**aZz>3Yenn;Nm#y}IPyB@Id_^vzS{3`i+kAJ1Dwn73mt0BijFQSiP z+n#mtJbQ`m0uISV<8T-TbXz`2^5wKxx3(hZeXtSRNAv9fB&QX``aXuTVn6_a1~nlo z3yZ5U@c}MgD>$Zc`KQvhalUw&*Km-<`*SExi%kUh_lz^nkZIGV$^G}=FONU*xGY+@ zsM~6G+kH2=?0?eBV18K{2jXx*`X~&S}a;R$*k0M9cy*)jqxO0_uVpD zw!!*IW$-x$rCS1E`y$(_K>!*`VWHmHH0-2N82VJ-M;}v)$Kna}n*DV}0E}?biWFoD zROsIWCjp@I+#G^5TulCuw)1p_g4wsy*WT=mS>eMN+C&Yca5m|`%EUpQzKIQVw z%{tYpiIps7owwV%?Ca*&-rg1G^bs@GZSJ=(0~YqjZSHY-p=$zQEmGFiR)x(CRB5;c zSVM4mwSTAP`5Tax{(AgLDHzEIlpxqdMKAR97S?|2mi4L^ao@JR2zq+7uYO|$WWcux zo0|4SP!ouumY(3yb5B~BTXDs!ICCDZAB{S5w^(|vJwAUW5#Sv1#RMND1blIqAGZoq zRiNmfnVA{dO~{e(I-l*g;@a4Zb)ejzA}^L}Du1{H3dh+e1S|4ow+#rpCIDf#`D+k# z0NC^VKSjV^sUt;PaW8d}+ z9PwqwHP;gnp2UFqe|X_^N+amb06bzNH4$AI3;MvnHc{p8 zBo6&n>_vwL11$!Dwe4<}`ZoQdeT+$J5hh;w=-(xI$n}ywcCx{hu)4Q-F6=_U2SnpC zpt`FOuVFvxYQc}}526N11Y%LTBmnkuq@EgRtP!|3k?IOjfXSe6#!u06+fWz0(tiX4 z;B?*P#GBpGECY3aeGP(cKy;EoLFrbl*p^gpM2U{W-unug~FeHzLYO~B08_inW=C*Av03qSV^<<30IRP(7 z>5Y|Ae97(R_&cuMZizs9{XxVJ1b>m}$TJk~W)c+jdbJ}uKWR0|sUbu1Hr;S}p-Tc_ zQ(^9MD>(Bv68!$<00^mZduMxX2O^#ax=>P%*$rlkzP&ydc7wmZ7Liq}Apub2cF}fN z9WnVxY70G`!cPiv$FX!fpAH&q-CBYa&+lV%(`dMJ;49t1xW5As4cIM=%zq4k@hG2j z-3zXhW`v1PNATPSQhLLgQhe#XVH?J}Vj7Cp+EV7O`%2~!=SkxScOggMbfX$}AOes? zSw&hFBn=yN`F!NXuBBrQDqcVw1IKSScy+v`Z@-yA`RlOjsTFcJe8mGw0Dz#}9p=rM zA}L7V7<7vn0PW)5Fmr0-Kk0ZwPh-WN4Dm$RuBQ3G-L*j zu3HQu@LegoiF!Yh}w#$4lKO zZyF#f5(A4n7Z3rul_@a~zwob;eavrg$`p3sGW?zqhU%HXqN4)SrW$pInaer+#-uO-61V5Mnp_kOf* zZ9AaEm2Dwl5WNjvuYm4+#nxP#Dr|eRgDY@(`alG-DayCXmVX~9HSfJ>o})Vy$lkf= z<}ff^rj{T6<3CF7iC2ri42gJHcw!N;AOE>mA+lg4t*OIXuYUxf!`=Pz1rre>0MNyB zUWjaFg8HQkof=UCCNzbXy9jRx7bt)I-661N8@4HupL8_E0rKP9kr z6}mzWghVv><9}t|fEbndBLHD|PJK)Z2}0QQ7>(UUHE5rd7yGqs;^g9C>sB*>KvM&B z%u?gpjEcj!??K{;?jb;gWKs2ucG+;TTYri0jYI%80dIP-rn4`f^IfTY`9ZDB=J=g! z4iN$DOe{L%avAc&TX6vC*Fb)ggf=PH%a}ea1I0FKj}zwBUBr57O*ot5a4ih1VNf3Z& zrX^<2+JQ)I)#cdDyTt5#H4`1PHb_-;zeh5{obz{<>i=FKTOXSZj$n{qx0QEl%_ai8 zJnZ-%$*`Y10(%0r6FX|s;wqh*!hZhxr^wj#5N;+Z>Sa|3{0?+t6Z!#2@g zAME-D+5n`DfhM*wvFrO1SNk6VzRm04zkdVVmdROwX|XQ!0C3kQba`*VM5%e?GL;01 z&b%BdA%cH;kp%LOK3$E_$@x5+gC%TnnhUPqL^E&el&SM#d*mi~{Bca6a7qkk?c5n$?Y`2CBgO5KZpk+Qq~sBtghVtWk)!!ajP;ZQt`9O=l9%#ts5zPAUHTzI+qenIM_< zM|d`onC;-jh`)w6ub0v}2>wAFLia=fTu6yP^y|=uU;GjPAip9@?8a)3IfB1N41Wnm zn&~C1MeeWgc;Qa$OAZs(UgBd95CAgS;(z1HFLZmhm-{m`??r!zoKx-`8v zM@nzGT+bIYM1Z1xCj?NY7`wj3F#$l=VifM!!xC`z6XA_{;6{;Xi-&pNQkec35gl=( z-$XmA!TEeh{Kx+N#xLe-aF%X*vwwB$ei;^t01V#PYmzj42F{1LUrJ|RB0eOHF>wN1 zc%6tq4Eq&_1i(-?hB|su5sjr|?>hkW3QKL;^ojY{wI~&K*C$g0RLnF;0BJ~Ttr>uO zZ9Q>AA3{K<5%o8(Ss^V;{)6)X#)2-xN*_ZV+gbNX1mO1OCZeL<(3dBq^na!cq-En* zN(2-M`iKa`Apx*K1{DC|knIwXjY9VC{rA^yS@$N`&AP+?5VQBDXTbxAKn_1#fe8t~ zhGzf&B|=$RLn17DR!T$g<6h&SP8R2Fk?kS)K5EHLL|vpR|z4SF%?BMom?5p3=3zVWENNW1fQ!YvVoU_$j{q1vQ3#P+YEfz( z_Jg_FkMAG?*uCek*@{I%-97TcqoabYPjbz~&_)q|1c0p8qH#xArfqi#~K?b-M^<%8Fj#$ zi<|#2PaDV3A zbG^PeXAr}caP;x~LI2bgV;LinAG1)(Z#`M6UVBu>*N&s0EX2>-27Q zc-ju|On>^MJ*5uh*BGDTlnzGiA6wkyt(6~>Yj74ldwq& zPQ6Ga8+(j)Yfk>gB>}MAV@a9tnGYR}Lo^huPJhPJNB2NL0_Cf5z+f|Xt zIr4LQV6UOK07toH9(XC#(=0vU#b2=$DZ5sg*bdyn17vyTg8)%g#Y6i+8X390JtQGS z2!B-)fi@({NzMQP+eNA${6CyW(j00B_jfXilV6i+Q0CF#?Sl7_iAK%_%52n|8C ze|1@D;`SaPU=!-b<)2HR3fwv&oG_f$igE69r0#9oBa@ zeWO8K6N{Lf0yY1;!sHbA;V;n!5{J4V0`W-z$W;jp{7os|NnxU{LHjzu)b9lghJRvS zp!zFmS^uSE>@wXQ_qRLjHDlwUE1A0=CJk@hU?R|%6HXU^ePiNpEFfSb1Jiw#KX^5` zCHCMC83yhTcdld464xRQyyYRTKMLX74DD{PwFRD{YH6!1(+xd7 z#Pj<$t^iS3BL1!KN)Tt=XhF&W4}XHfJSjM6hAF=xU4(L9avhLz@YNkbpftkBMI6J& zoC3Aa{z0<~6`ymJrWLoxZMD|zpZFvI+FepZ5P+gFW|x-wX}h6_-3~8SKM-k=yNx;? z=A?P`LXmHt40Vu7ydhN1TY?(Ex-fwmQ}&dUv4jn^o5=aV_ALx02dLz{bN(;$w5#uy&5(X144rxKv2S_bS z7`W!}1ly(u1J5NFPm}uB{(r8LK=Duhqz8;RAp-GB01W;sb@k?e2vF}yL0}NC4@jZ7 zh64SrW%Vc0TDb*BITZn!vB*e`T@-r{Kx)xw$=LgNseR%d5$1VJAioPJ_Hrx5Y7%Ia z%9kIK`j@ZP6kHJ<#ZK;z^~Y%*a@={a#Ag8^sS<>v4;H3!ZdDesCV$YdO&pXc3{ zK$wC~QFj}NLIYka#DA;Nh#q@c)c_Iz%!d2UV0GBkIeXuu;F1~v@eOAMq(K}^7z5qI zv-1_#66taDUrRgP037`e9xgS9~s8@Axs~<21}0axfq_zq;`pkCw=vfnA_qNz#bj zW$1U#(I=Jr_rO&{)mw9HzMJ{RVlnH57ui?*(c2&`c+)b3QXyYi)A!ZKc#sT@jIHH1 zQ80!^o*U?|_ypbuYx$|6F%yJgq$G{nS6Y@oBBeL`q<{FL8zgnaSlnbuupRnjv}p5yhWyQISICyzE=Kg`I{3^POYg?$XTgGVgpa|xCdr4@U-xiC zGS?kI3x7gj(*hu){ZW|+T2o^;?l(3C5Cv=>PvvXGPLefaf33-nZRv(6lprvTlEPPT zPs66Lc@c=hA_;D>*62r1%I3N)GW_RvOZrZeOfR^G!-zoqN&xJn)!8(3o+6L#*S4>B z0BS#d;evoA*qgHpB$DT(>FZ^Zv)7^Sk>BdBZGQ{M+VvZfx&JTW5%{Mh72rr{29YF+ zI|zg!f6Io|Qa1ZSh|VADmRg3<+WNTTN@?4nv{$-NGLQJVC%9e+vZQ z5Cc?BGAGDQ!DQIta^MvDm!{Q=kxTDf7>wtJA%8eabutc2B#eHv`Ul}*8+yhyk~V5*<;EVy za70jeJb0*pfRKnNAtCaU%frRT7v4g*b^8GbZ=R=n0O(6Bz5>s z>bA^3>U51>)q2^kRpM6#Fg-Qzh<|QMpSZU)zGHX0eE{~A{`-rzk{RG798J zMT%f4(zaz4j^@5zat}Pl>Io@45YB0_=G2GHW95(Dpb@QUoSdn1_cKA#mkE28`?gMVK{FoRf~oQ;UR#gcKrxl(ZQ1qz<YtvCxP3gy%Q>0I{JXy-kC-N@qbEx0$ej`GI$C1{xcikU<04u^;T=<=U|+D-V>iqx zz6k(fhK^HAP6d}u9y1d@_*Y@o9q6bz0F^GmtjW^4`V~k4@5+$FPk)MH;y6i=0J@+T%4A>0>k4ZxkB?JK#lfgCN9SXqLUGemti0{YYnps64$OwG#MPTh` z<*3(_nuAd9#aL$tNzvJV(2P{Bk)KsrYqoyDds6@ERgye;8VC#33T*hoe70?xE3IG8 zl}1SY4D#^~8K(xvynhp}kfHD_nGzv0v7X-MPY0sV{;La_rv0J*{ABl=K{x4>50n7H zv7sdQXBWC|%bH|{Zr06xP|tN!@t>k!Bn2WG7aK*;VcI49%#-G}%pgoyk!`hPX7hmpBJiZ1xK8lH{O z&)r(H4TX&It9<;Qm^*YCZ^7mY6XXR0FBur~|0fTh4s``ypQg1Es9Jy>qPv<2vxr=O z%wF6R0G)75KEaqi^&3htbvq=*;{h(*QRc~-09VVCQa69D_J%!;wAjZ%Q56_A>(5x! zDIj>8!9Cy=*nfeEfFeGCYAo#wf0w_|5=$rwKkV(|g+2CTNc0e=y4+xDuX`vg0HhlxU4`0VpSrux5MFF*YFo?1vD9Qi1wl4`9|A+n^I+-GlBiAg9eyDP7T^R(j_jW$V9= zmq6VzNg4)KkS8oLa4KTtN2)i3Uk8xzb?8qXmD~f4Hee#bwZ%_|fU|>mn7y~|`Co`P ze+<+Cx_@)S*C~-3XotEz*zgmmT`Vc%4wt;cvAK*zrJMu-Fu<_hZKOyYJ_b_25lS%? zi2X<@J9H@Q3m2d_XR`Q~KP$EGy`;a`JGjDbbN-Qw&f@m@-};{9eeXsXr9ki~@hBIG zM#ga7jRC!r;=bRgLnNqy=0>T0>uK5i*Y8UGOMicX&O8xbn4Q5v5!$P;iU48w9Fl6# zMHi@8Bl$nNNAiz4%?#UCHCzCJ{bgT$WgDgPp+D)9Oc_Rx5hiZinyB)j4?(E3Lr(gI z8Ub+u%esquw|zQhR|bUyKciSkdms9?Aa{1fRwa0xc+sriO4c_oLEORO?T-kM>yaDt zMX?wzm_3q-+v(m zr`Ya3{N@t**>C%q$`|jK#<@4*Y(MDziu^j1j&HmlHitmtTBtBP%g_@qgk6gVlVD74 z+wNF%MBm~8gB*3-j+^K9$@JZ4O5NJGC76xH18%9JlcQSt?j~}iq@m;B_PJ8B_B>Rw zcZZ}BB|$evK|dCLjufAFwUpvmvVX>R=cx5qIUsEV9RFY|iu9a2bX@yyaXoPV##M`? zcHUFch%K#wno`}y>&+gj2xT((MloI@AFTbsmI~MqN}==LCqs`rTcH<;yU(mU)A!m> z-jM1?kSk#5SX}1TT&OVH1P)=$NCOW!2ezGB$vgcP%?-&8*lMnJrXSx14SxY3cd#cZ zd#`Uw{p)}dsVu{02Q*s{XA6q};v`*m%wS&m`1Lxm$+=j#pzJn>h-6-EBEUmZhF|zM zDFe4?c=KNng{NRKfm>=WL3ggINcs`=GZgQM_$Uew+B&SlOudcEKa;xmpF_eq6v=WU6o^3qj^y(_edp?SHww*k8UxG7h{@hJ5S0VeLmcw)VOs`80S407hp^0nERa zHsvg7Ui<(~+MNP=8V4I^z{%*|VI*41;%B7l#lxiV2R}25oeMu~!GF7*sCFWdC&SOb zMz&<-!OHw+>>M1gM8|A(b-#e!_9LSEEyO3%hjTgV%PrWo*0A_PY54d#@vVGXjpg2) z(GZPkJ%^r8*B-^FsH7YsKiUT8_g5~0TW-7*UU0YMeB%fmPNW3dW=6iU4YK8q%dzPO zIRo;TZmhdNB)AAQw|~GI%-duc_Whsf{(rlkh+rFohXxe^P$a^F@}_4>)&VC-^XCt6 zc^KrfxJwLR5=9l1Qd%&<cx?C$jLJn;j_n1Yrd~^gEW1$Seh2SE6q!uhJS}+0}g)yisnuLo+I@Z z#AkC%x2@;5OA1b!?066LY9s@JtJYt(NKz&qEk)=3GnA{3F1JXeGqw1`=*R3mWq14r zQGIVfTIpryA?#Hu%^<0>8@wlQvCUQGZ&#co@M*+<$;5#BSlvzGSEo zH}~XgkXzsc)4sB=Xvb+)72%&jNB|7LXbj9c_y;%`;R8v|=3eb?{H+lJCi2H11^D3= z$exaU3-3w!L)XcOORh((x4V4p-L-FsfZ<$u2OkIG@~V_S@MmfM;t6mes055^BO!nY z-Ti{>u7CDeUN?lAhj5l&d#J{4Xm0!roc4s|m1+z_KQ%+IHXAEMK)c|!+)^Dt4u58G z&i~OIHTE&(mWupT$0AV4R9puUrzErGo~vPyz13tH#(b0DbO~=79+8gBU%p7v_dXqN z-HUa!k*Xg0a17rD#_|x&061}UnV{tCHxr9~9Dl-POR=C3k!KVF{cWJ%G;`3fsk%tY zpT0}GqvD>`_h|a3Vk;3GYc6BLbQyWYosxIj^~fZ<2A1<>5Gx_}GJCATg9~%uiY|0a zP15j5P>uFLto=w3s3r}CZBKm`3*dBcZmDzpbWHO6UAm8h>8@ryjyVn}rhju8^N=kXeObj|o(7mZ3j-L~`~% zyuI5INFePG$M)0UBmjVc4MQH$m3i<_0chmakGBmoSnL`lm|mm|&iIGhRV!MVM)MlBQVl0G^!+#Rds9y(L zHb~A%e+AcnL=&`-&?u8oqSFP3?yc9>+)!;}e1GZ9Ka+`~>r1Qw1FZ(=?@TleiJ2=>+t z7a~Moh6?*@R!G^c7fbW{Rey@Ku_OY7L%1}MvGX*<4E$M!|K=0PI`WqgMb~3L0T2b- zUR6&fvE;r2U68~~y!fZ9HQn17`{j3b4u$5Ia2(a52W}ommMiD#$E5Ej3BP!Zz`f90^-0))YHh2jD24x2ZWg?+w)*%<;nS(|F2gO8zBs zDV|x#*2BW--=BzB#(%O8c^|p{aZ*m%GD+F#SSkGZvoi8$H=C5#=#(Owa{b7bb~vIk z$3y8qPL`ZX=b!YHXRC=6u_)5(EaENiz{|!Bmt(XZe53k^?$DmWcX!sByG$@v#5x3 zM8H@S)T4B1SX-%7pe}S0DCVRKEP6R6leM zh$H^zGsuUj*?%}cUCj}JOyti3@-LRmgU*-YpMcnAAPympk)LoL+ysErL28de3v2eb zekwJOTmk~XN#b>4RXi0CET{tv+G$V$7g_F-or z&Gk`|tmiV~vL!)9Ebg-k3rT66Z~g!Ft^`b~>Pnxk>V4lgc0~k1qegU$3kH{{V_d)t zDx>3|#$eP*qDFE5h`VuAOw0_LQAb1&m+&zm#tbs95j85CARt?SMtaBIs@M7dbKh%< zrngtUP=BxL-H+-js@}Wr-gEE$@7eA-Nb6m;;0Y-E9zxuKp0!qO*dqre6(YtkBved% zw&YwhPclwA$8@D1+=lI^boy=qfs(9)qKuJtTLTU4taYdN_vXvK0szkiG*;r=N3Imj zdR-DnazUc7(R^v-oX*&Bb6Jmnt@iP{)_?jM#Bo?4Rj*#7_@tr5>95eGvX6JM4ROFY z4i>#^&bd=N>*D9M?aSgvd(eND`i(1P*Aq8N<#X3yz6>!Z`npy2@h;3M zDo)Xc<`QW8&%Hwmuf5;$@^jDPXHOyr063snNX)j9brDX<;e=UR0A5%+P$5h}QfHtG z+N>tRq+&!D9wC*_Un9H!^G<25+<$}lX_@FKzYk;q7!U~Bm1lfjKRy$+W1Udd#6`!B z^mZ)RZ;U7CvUl;_Qf+%u61)fkp%&hYIvBRQ?6v=pl84Si41(w2s*LjqdUy!lirs>X z@$eHIGHNYF_Ml51lY$w{A&}-8wm+D3kplqi6(uH(QfY?T-F9@THmgk@m|ya$g3>kpQn2g=ya zPKyB@729gRL`b^7OZK(%B!B-hBqc%EHn+(99lO?5Z#!P+j{gGybg`hdnP*Lt#G|Jo z2n1wo1cSg2;oApJIx3r>Amh=}#x4INyC0k+j4?-zyt3-rH#(rWtZ>mYq7Ut93eaXD z^{yA>kZQpNj0Bi(l=6j-sk}~Z#UAJ0)wAy^+ggx_l=IpDx(GDKKYyN4(6)5}PO2|} z9|D7ll&{8af0*R`;xCeY&UCGqZE5GA_C3lKpZxctxT2-KY$Q!N91uT(hQ#I$m)ehh zkHv)@Nc91X9Mr`i_p<(hyNvB3``v^I2Ae$kQ1{`B(oj;4EH#HB07xF@D7gX1m~4bj z*nw+J-)qLoLK}Ta$$!$YqY^#`{|kM`P$*^rbWYmNYrzTlQin=l{hvi35+sj14prcL zi=B7eR$b6YGy~Id;G0^6bpNAin`-=(y8EicwdRDOPo0kv#!r!g8|F%?Wwqfr*`TuT zCii@bH~=8&?FAB#q>HUBd59{z5W7eLehK#-)S7%eXac7aUw>+WG;a8l)O@lO0Y=KaxU=|3F83Ua-YMj(>`@1x4T?P=~&T0?vV3XR(^DqHvFUQN5 zhG;@K=~(~Qm!*E|c4(UOH0S$1u>k#K)s7aFleUC@t-Zu)7x!fhliK&^>w*$L+zq=m zv2}bVYNAzuL020}rE&W%NjdH;a7y&FGvnOxj-LLn~jT z8XJWbQ=z3|jVhM2uYN)D5QS-k z+!vpP$=AdyI?^J{{%^GpEVB>CU46)YOBdqWkDiyno&Y@I3WW(%l@;bhR2>IqbT~~) zZHs9WWq+!C4nYf#jjmy!}IIX-Sh*ob?Y~6d=v4w!u5Hac`S6 ztb7Azz!8`k&{wq7;*{YgNjz$r6#Vq}CWxplf~n(>H9n3y5q=j(EC7(yW^zFM=R(OC zh3Gub!%Y|fpqgGP1zj+RI`IiuG>L(Of#ZJT`hTTT`|)CFtZGu1Snja8@OdpJwfeLh z0`Tv_EohU9E1-EIay!<2wGNImA6R-0r`#C(haEpTO9E?O7k}|YA+Ts+-<=k_ZCKFp zIFnJo_A@N{6=1wd5nljt`+qbCX~OT+Ou<^U%KHF^2r3Z`0A_((C_nOWX$~YoAMgrL zo`0eM7nMtjJ-KP7qPdXz4CF)ztXeEJALCF@74s8jOI#*_fd2nj4EE$^7w!8GQg@B= z5{g+wG>$DCEwvv$iOWtM*!uHTqb+fX;!lUjfCM5sxvl=| z&dG&#kibBfIG)WYJ#GG>&}qDcF(@>BaYRGX0G5)Zp&IC<`P)`W{qAJT79W~E0Dl!K zU8q=$KWvg@{o@Q1wj1p-CO(*H4-(xRktT$TBj+qY51m&w6s%rg=VmE+csioBd}IVY*xMd5{4C z&*m=L8mL3U&!0>Ein->TePcBm{{=+-y~2!8sFr~a_q8h* zBXr^0(>ZDYfE~8coEc|#KYAj*$;M7nsLm$NCZJ8eaCygq;K3B0n};8JYxQPTWc!Pc zk;L&okmRFIM)cq#jp?l8LgU0&NMK)dpSICqKsslS0iz<7+Oy3s83}e8 z5i#`Wu#;V=Gjbl}?`R1i5HRmObR2DU>+wRH;0G03_z$q3pCXClj+dlE#%t&-n$ZTm zDB$3!*jaT9=3or6859LTq<=?+EfDHW!ypc6%zb!!CXAgb#kV|T9ms(w5G4z^H)QJW zn&<)mQi6-b+68&~jt6jjdDJ9h0;*!r!36A%vIp}w1p*VBj=MSoleRT%!Qm*=C||~K zi5qsJBphEmUMx|7W3l@ggxOyDE5zHwseec&dv#nGTLEFt zO4c9%=dU$9x>nJFrFUFyl-v+~0DytD*--8}d*(eN)r)RJiYnxE*J!U!wbJ1{Qvh~k zXvr1mi9Gfl)(<4GY@>IZWrd>!!Jj`-;)=%Lb%}`|wTi zyA+XJkf*NusIP7veJm0!SXdefm|AU^3&|bOs(?k;*0dABHbEDN3`3sy6#n+#C6V;H zf$Fsl#5JG2E8jc{r=FzYYUXtAtqCpw`50SqO3$D7JxvJ0=zqZW7!OqYBcWcG3%#Ka zfjLnI84~8Q{C}AxDU)y1uugjLLn8~@izf7EgwLJaQLSB7&4}Ov!0ohiJWw9`QjUNq zG*0|Oil9Rn1TlauvNY_eNNAFN;gix@u^qU?XFK5lNM!&S!gXstMtBL9FM107gX=J@ zALInQ(j^6=7JmRp5gP>P-(7I^Y)L+4CS*w*AEtv!#DPF(a{wU6T^^vIU;qn3TT=k!y1sZ(1P3Me}+P5E-%H^+{y9qLb)gMRg z4UdbX8UQ#1HVDuYtPlYmlTZE$f{L!OKmh9Vb`x2641d_bwE_#p+K~tD83)!(Z9PH2 zpOP-Qm))i(AbDm(y#yVB02ew^vjezeQV>97!EKtUD7K9MgdzCpszyKC67y6HGJ_Y1~}%z04A___)t30-2{z zmE_4k*OXr|h|%Ym1A}tY~1)!9TjhCE@Z-127VJ9GD`YQZClyGkJ=xY>z?g*)V z?YezgnLPkFVAMPS=s*%11Q>ZI|H@fNwLJ$R#y9G&qOk=X$)z1C_x{^01xR~>EYB}w zUwSXtdHfeFJ(GdrQ@8i-|0Bc)oSZb{B~t#tM)$hk^<=`o{bP(_XB*lK!y*+G)R2_0*a6{CHjI;UYA+0)1gGlt?hznpF=zkwT)8J^S`SWb4es_u0FmMQ7Q3`kf(9J|p z#gS#FPMbJc3U7Tw;t$1yL=s4~4yazhV=22KVMssO;2WEnD>>8e#Nx-&=aFHiFn0<9 zkRxJnACE~_ynL7DKvdJ9Ckp7;cmUAT6y>QhDv$6=I&^{*-SVuYoPHCs=pso49Diq+ zJ=Ws{dLp9p-)++%lcr`&oeR!uM~I>Txd503Q;*aDBIU0<4)s92iUPJ1lJnL@&K({A z^kytA2N_P7xa

3OpcLGmytGumflB;WQMVL1zNg%Og6CW&Nhe-~ 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 D8d3Un delta 20866 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 From 9cbae545f06d8cd8914c16d7d1f599c6004cc0c3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 09:25:43 -0400 Subject: [PATCH 002/133] zebra: Fix protobuf build on stable/2.0 When compiling w/ --enable-protobuf on stable/2.0 we were attempting to dereference the zvrf->vrf_id which got moved to zvrf->vrf->vrf_id. Signed-off-by: Donald Sharp --- zebra/zebra_fpm_protobuf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 702c355f1a..cd88af134d 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -53,7 +53,7 @@ create_delete_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, } fpm__delete_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id; qpb_address_family_set(&msg->address_family, rib_dest_af(dest)); @@ -159,7 +159,7 @@ create_add_route_message (qpb_allocator_t *allocator, rib_dest_t *dest, fpm__add_route__init(msg); - msg->vrf_id = rib_dest_vrf(dest)->vrf_id; + msg->vrf_id = rib_dest_vrf(dest)->vrf->vrf_id; qpb_address_family_set (&msg->address_family, rib_dest_af(dest)); From 358336ef366377b4a96c59efe2d6c14e881fa18c Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 09:37:03 -0400 Subject: [PATCH 003/133] zebra: zebra_fpm_dt.c does not always need protobuf When compiling zebra_fpm_dt.c only pull in protobuf headers if we've turned it on. Signed-off-by: Donald Sharp --- zebra/zebra_fpm_dt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c index 715e250a66..7b4e1b90dc 100644 --- a/zebra/zebra_fpm_dt.c +++ b/zebra/zebra_fpm_dt.c @@ -50,8 +50,10 @@ #include "qpb/qpb_allocator.h" #include "qpb/linear_allocator.h" +#ifdef HAVE_PROTOBUF #include "qpb/qpb.h" #include "fpm/fpm.pb-c.h" +#endif /* * Externs. From 7e2b760345f2dc43d9fc5381617ac4acc1cfd1d1 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 15:45:28 -0500 Subject: [PATCH 004/133] *: Remove non-vrf based ifindex lookup Signed-off-by: Donald Sharp --- lib/bfd.c | 2 +- lib/if.c | 12 +++--------- lib/if.h | 3 +-- lib/zclient.c | 8 ++++---- nhrpd/netlink_arp.c | 4 ++-- nhrpd/nhrp_interface.c | 2 +- nhrpd/nhrp_packet.c | 2 +- nhrpd/nhrp_route.c | 2 +- ospf6d/ospf6_interface.c | 2 +- ospfd/ospf_packet.c | 3 ++- ospfd/ospf_vty.c | 6 +++--- pimd/pim_iface.c | 2 +- pimd/pim_pim.c | 2 +- pimd/pim_rpf.c | 2 +- pimd/pim_ssmpingd.c | 3 ++- pimd/pim_zlookup.c | 2 +- ripngd/ripngd.c | 2 +- zebra/if_sysctl.c | 2 +- zebra/irdp_packet.c | 2 +- zebra/kernel_socket.c | 8 ++++---- zebra/rt_netlink.c | 4 ++-- zebra/zebra_mpls.c | 2 +- zebra/zebra_rib.c | 8 ++++---- 23 files changed, 40 insertions(+), 45 deletions(-) diff --git a/lib/bfd.c b/lib/bfd.c index a5edaea217..b651a05a09 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -293,7 +293,7 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp, /* Lookup index. */ if (ifindex != 0) { - ifp = if_lookup_by_index_vrf (ifindex, vrf_id); + ifp = if_lookup_by_index (ifindex, vrf_id); if (ifp == NULL) { if (bfd_debug) diff --git a/lib/if.c b/lib/if.c index f25be591d9..84489f9e42 100644 --- a/lib/if.c +++ b/lib/if.c @@ -239,7 +239,7 @@ if_add_hook (int type, int (*func)(struct interface *ifp)) /* Interface existance check by index. */ struct interface * -if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id) +if_lookup_by_index (ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; @@ -252,18 +252,12 @@ if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id) return NULL; } -struct interface * -if_lookup_by_index (ifindex_t ifindex) -{ - return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); -} - const char * ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ? + return ((ifp = if_lookup_by_index (ifindex, vrf_id)) != NULL) ? ifp->name : "unknown"; } @@ -1188,7 +1182,7 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) return ifp; } else - return if_lookup_by_index(ifindex); + return if_lookup_by_index(ifindex, VRF_DEFAULT); } #endif /* ifaddr_ipv4_table */ diff --git a/lib/if.h b/lib/if.h index 32e5d92a97..6afce9dda6 100644 --- a/lib/if.h +++ b/lib/if.h @@ -390,7 +390,6 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); extern struct interface *if_create (const char *name, int namelen); -extern struct interface *if_lookup_by_index (ifindex_t); extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct connected *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); @@ -399,7 +398,7 @@ extern void if_update_vrf (struct interface *, const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id); -extern struct interface *if_lookup_by_index_vrf (ifindex_t, vrf_id_t vrf_id); +extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id); extern struct connected *if_lookup_address_vrf (void *matchaddr, int family, diff --git a/lib/zclient.c b/lib/zclient.c index 859751deb8..990bf7906e 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1153,7 +1153,7 @@ zebra_interface_link_params_read (struct stream *s) ifindex = stream_getl (s); - struct interface *ifp = if_lookup_by_index (ifindex); + struct interface *ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); if (ifp == NULL) { @@ -1302,7 +1302,7 @@ zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id) ifindex = stream_getl (s); /* Lookup index. */ - ifp = if_lookup_by_index_vrf (ifindex, vrf_id); + ifp = if_lookup_by_index (ifindex, vrf_id); if (ifp == NULL) { zlog_warn ("INTERFACE_ADDRESS_%s: Cannot find IF %u in VRF %d", @@ -1396,7 +1396,7 @@ zebra_interface_nbr_address_read (int type, struct stream *s, vrf_id_t vrf_id) ifindex = stream_getl (s); /* Lookup index. */ - ifp = if_lookup_by_index_vrf (ifindex, vrf_id); + ifp = if_lookup_by_index (ifindex, vrf_id); if (ifp == NULL) { zlog_warn ("INTERFACE_NBR_%s: Cannot find IF %u in VRF %d", @@ -1447,7 +1447,7 @@ zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id, ifindex = stream_getl (s); /* Lookup interface. */ - ifp = if_lookup_by_index_vrf (ifindex, vrf_id); + ifp = if_lookup_by_index (ifindex, vrf_id); if (ifp == NULL) { zlog_warn ("INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d", diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index a418ecabd3..76419a7ff1 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -75,7 +75,7 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb) } } - ifp = if_lookup_by_index(ndm->ndm_ifindex); + ifp = if_lookup_by_index(ndm->ndm_ifindex, VRF_DEFAULT); if (!ifp || sockunion_family(&addr) == AF_UNSPEC) return; @@ -185,7 +185,7 @@ static void netlink_log_indication(struct nlmsghdr *msg, struct zbuf *zb) if (!pkthdr || !in_ndx || !zbuf_used(&pktpl)) return; - ifp = if_lookup_by_index(htonl(*in_ndx)); + ifp = if_lookup_by_index(htonl(*in_ndx), VRF_DEFAULT); if (!ifp) return; diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 4ac612d3ad..052b9c1e83 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -127,7 +127,7 @@ static void nhrp_interface_update_nbma(struct interface *ifp) if (saddr.s_addr) sockunion_set(&nbma, AF_INET, (u_char *) &saddr.s_addr, sizeof(saddr.s_addr)); else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL) - nbmaifp = if_lookup_by_index(nifp->linkidx); + nbmaifp = if_lookup_by_index(nifp->linkidx, VRF_DEFAULT); } break; default: diff --git a/nhrpd/nhrp_packet.c b/nhrpd/nhrp_packet.c index 5d2866a67e..36dbdfd777 100644 --- a/nhrpd/nhrp_packet.c +++ b/nhrpd/nhrp_packet.c @@ -290,7 +290,7 @@ static int nhrp_packet_recvraw(struct thread *t) goto err; } - ifp = if_lookup_by_index(ifindex); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); if (!ifp) goto err; p = nhrp_peer_get(ifp, &remote_nbma); diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 8d066eeaef..69c55e3058 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -198,7 +198,7 @@ int nhrp_route_read(int cmd, struct zclient *zclient, zebra_size_t length, vrf_i for (i = 0; i < ifindex_num; i++) { ifindex = stream_getl(s); if (i == 0 && ifindex != IFINDEX_INTERNAL) - ifp = if_lookup_by_index(ifindex); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); } } if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 8998799cf6..62c77e6f87 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -69,7 +69,7 @@ ospf6_interface_lookup_by_ifindex (ifindex_t ifindex) struct ospf6_interface *oi; struct interface *ifp; - ifp = if_lookup_by_index (ifindex); + ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); if (ifp == NULL) return (struct ospf6_interface *) NULL; diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index a0cc367cd7..d09e0f7d80 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -35,6 +35,7 @@ #include "sockopt.h" #include "checksum.h" #include "md5.h" +#include "vrf.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_network.h" @@ -2218,7 +2219,7 @@ ospf_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) ifindex = getsockopt_ifindex (AF_INET, &msgh); - *ifp = if_lookup_by_index (ifindex); + *ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); if (ret != ip_len) { diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index ce4bc9dfaa..33fc0bf525 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7948,7 +7948,7 @@ show_ip_ospf_route_network (struct vty *vty, struct route_table *rt) if (or->type == OSPF_DESTINATION_NETWORK) for (ALL_LIST_ELEMENTS (or->paths, pnode, pnnode, path)) { - if (if_lookup_by_index(path->ifindex)) + if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", @@ -7998,7 +7998,7 @@ show_ip_ospf_route_router (struct vty *vty, struct route_table *rtrs) for (ALL_LIST_ELEMENTS_RO (or->paths, pnode, path)) { - if (if_lookup_by_index(path->ifindex)) + if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", @@ -8047,7 +8047,7 @@ show_ip_ospf_route_external (struct vty *vty, struct route_table *rt) for (ALL_LIST_ELEMENTS (er->paths, pnode, pnnode, path)) { - if (if_lookup_by_index(path->ifindex)) + if (if_lookup_by_index(path->ifindex, VRF_DEFAULT)) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 94ee07a0e5..def72c29f8 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1028,7 +1028,7 @@ int pim_if_find_vifindex_by_ifindex(ifindex_t ifindex) struct pim_interface *pim_ifp; struct interface *ifp; - ifp = if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); + ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); if (!ifp || !ifp->info) return -1; pim_ifp = ifp->info; diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 471d8aa39e..f82687245d 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -331,7 +331,7 @@ static int pim_sock_read(struct thread *t) if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) sprintf(to_str, ""); - recv_ifp = if_lookup_by_index(ifindex); + recv_ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); if (recv_ifp) { zassert(ifindex == (int) recv_ifp->ifindex); } diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index ff8a6054cf..56e01dc0e7 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -106,7 +106,7 @@ int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int nei { first_ifindex = nexthop_tab[i].ifindex; - ifp = if_lookup_by_index(first_ifindex); + ifp = if_lookup_by_index(first_ifindex, VRF_DEFAULT); if (!ifp) { if (PIM_DEBUG_ZEBRA) diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 0354083332..76b327ab07 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -24,6 +24,7 @@ #include "log.h" #include "memory.h" #include "sockopt.h" +#include "vrf.h" #include "pimd.h" #include "pim_ssmpingd.h" @@ -259,7 +260,7 @@ static int ssmpingd_read_msg(struct ssmpingd_sock *ss) return -1; } - ifp = if_lookup_by_index(ifindex); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); if (buf[0] != PIM_SSMPINGD_REQUEST) { char source_str[INET_ADDRSTRLEN]; diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c index 7ec31c7d50..f77990ab5a 100644 --- a/pimd/pim_zlookup.c +++ b/pimd/pim_zlookup.c @@ -253,7 +253,7 @@ static int zclient_read_nexthop(struct zclient *zlookup, nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET6; stream_get (&nexthop_tab[num_ifindex].nexthop_addr.u.prefix6, s, 16); nexthop_tab[num_ifindex].ifindex = stream_getl (s); - nbr = pim_neighbor_find_if (if_lookup_by_index_vrf (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); + nbr = pim_neighbor_find_if (if_lookup_by_index (nexthop_tab[num_ifindex].ifindex, VRF_DEFAULT)); if (nbr) { nexthop_tab[num_ifindex].nexthop_addr.family = AF_INET; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 108da21c11..8e98f5b0ef 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1348,7 +1348,7 @@ ripng_read (struct thread *thread) } packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf); - ifp = if_lookup_by_index (ifindex); + ifp = if_lookup_by_index (ifindex, VRF_DEFAULT); /* RIPng packet received. */ if (IS_RIPNG_DEBUG_EVENT) diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 8326f0e396..c62d9926a2 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -80,7 +80,7 @@ ifstat_update_sysctl (void) ifm = (struct if_msghdr *) buf; if (ifm->ifm_type == RTM_IFINFO) { - ifp = if_lookup_by_index (ifm->ifm_index); + ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT); if (ifp) ifp->stats = ifm->ifm_data; } diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index c9c32ce311..4c58b6b35d 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -238,7 +238,7 @@ int irdp_read_raw(struct thread *r) if (ret < 0) zlog_warn ("IRDP: RX Error length = %d", ret); - ifp = if_lookup_by_index(ifindex); + ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); if(! ifp ) return ret; zi= ifp->info; diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 1bb85a31ab..20de52c11a 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -324,7 +324,7 @@ ifan_read (struct if_announcemsghdr *ifan) { struct interface *ifp; - ifp = if_lookup_by_index (ifan->ifan_index); + ifp = if_lookup_by_index (ifan->ifan_index, VRF_DEFAULT); if (ifp) assert ( (ifp->ifindex == ifan->ifan_index) @@ -460,7 +460,7 @@ ifm_read (struct if_msghdr *ifm) * messages, such as up/down status changes on NetBSD, do not include a * sockaddr_dl). */ - if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL ) + if ( (ifp = if_lookup_by_index (ifm->ifm_index, VRF_DEFAULT)) != NULL ) { /* we have an ifp, verify that the name matches as some systems, * eg Solaris, have a 1:many association of ifindex:ifname @@ -723,7 +723,7 @@ ifam_read (struct ifa_msghdr *ifam) /* Allocate and read address information. */ ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen); - if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL) + if ((ifp = if_lookup_by_index(ifam->ifam_index, VRF_DEFAULT)) == NULL) { zlog_warn ("%s: no interface for ifname %s, index %d", __func__, ifname, ifam->ifam_index); @@ -1099,7 +1099,7 @@ rtm_write (int message, msg.rtm.rtm_inits |= RTV_HOPCOUNT; } - ifp = if_lookup_by_index (index); + ifp = if_lookup_by_index (index, VRF_DEFAULT); if (gate && (message == RTM_ADD || message == RTM_CHANGE)) msg.rtm.rtm_flags |= RTF_GATEWAY; diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 6ac1314496..a544593dd6 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -465,13 +465,13 @@ netlink_route_change_read_multicast (struct sockaddr_nl *snl, struct nlmsghdr *h strcpy (gbuf, inet_ntoa (m->sg.grp)); for (count = 0; count < oif_count; count++) { - ifp = if_lookup_by_index_vrf (oif[count], vrf); + ifp = if_lookup_by_index (oif[count], vrf); char temp[256]; sprintf (temp, "%s ", ifp->name); strcat (oif_list, temp); } - ifp = if_lookup_by_index_vrf (iif, vrf); + ifp = if_lookup_by_index (iif, vrf); zlog_debug ("MCAST %s (%s,%s) IIF: %s OIF: %s jiffies: %lld", nl_msg_type_to_str(h->nlmsg_type), sbuf, gbuf, ifp->name, oif_list, m->lastused); } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 56a6ca7afa..55a2745b53 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -291,7 +291,7 @@ nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe) case NEXTHOP_TYPE_IPV6_IFINDEX: if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index f9734fdf7d..76c32c3971 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -272,7 +272,7 @@ rib_nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, if (src) nexthop->src.ipv4 = *src; nexthop->ifindex = ifindex; - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); /*Pending: need to think if null ifp here is ok during bootup? There was a crash because ifp here was coming to be NULL */ if (ifp) @@ -388,7 +388,7 @@ nexthop_active (afi_t afi, struct rib *rib, struct nexthop *nexthop, int set, */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) { - ifp = if_lookup_by_index (nexthop->ifindex); + ifp = if_lookup_by_index (nexthop->ifindex, VRF_DEFAULT); if (ifp && connected_is_unnumbered(ifp)) { if (if_is_operative(ifp)) @@ -938,7 +938,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: - ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); + ifp = if_lookup_by_index (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -965,7 +965,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, family = AFI_IP6; if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { - ifp = if_lookup_by_index_vrf (nexthop->ifindex, rib->vrf_id); + ifp = if_lookup_by_index (nexthop->ifindex, rib->vrf_id); if (ifp && if_is_operative(ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else From 4e5266b8a3fb5f1928a610bf86739b415d078bee Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 15:48:43 -0500 Subject: [PATCH 005/133] lib, ospfd, pimd: Convert to using VRF based interface creation Signed-off-by: Donald Sharp --- lib/if.c | 12 +++--------- lib/if.h | 5 ++--- ospfd/ospf_interface.c | 2 +- pimd/pim_iface.c | 2 +- zebra/kernel_socket.c | 2 +- 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/if.c b/lib/if.c index 84489f9e42..8b10c91b94 100644 --- a/lib/if.c +++ b/lib/if.c @@ -123,7 +123,7 @@ if_cmp_func (struct interface *ifp1, struct interface *ifp2) /* Create new interface structure. */ struct interface * -if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id) +if_create (const char *name, int namelen, vrf_id_t vrf_id) { struct interface *ifp; struct list *intf_list = vrf_iflist_get (vrf_id); @@ -158,12 +158,6 @@ if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id) return ifp; } -struct interface * -if_create (const char *name, int namelen) -{ - return if_create_vrf (name, namelen, VRF_DEFAULT); -} - /* Create new interface structure. */ void if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id) @@ -468,7 +462,7 @@ if_get_by_name_vrf (const char *name, vrf_id_t vrf_id) struct interface *ifp; return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp : - if_create_vrf (name, strlen(name), vrf_id); + if_create (name, strlen(name), vrf_id); } struct interface * @@ -515,7 +509,7 @@ if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int v } } } - return (if_create_vrf (name, namelen, vrf_id)); + return (if_create (name, namelen, vrf_id)); } struct interface * diff --git a/lib/if.h b/lib/if.h index 6afce9dda6..10740957b5 100644 --- a/lib/if.h +++ b/lib/if.h @@ -389,15 +389,14 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern struct interface *if_create (const char *name, int namelen); extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct connected *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); extern void if_update_vrf (struct interface *, const char *name, int namelen, vrf_id_t vrf_id); -extern struct interface *if_create_vrf (const char *name, int namelen, - vrf_id_t vrf_id); +extern struct interface *if_create (const char *name, int namelen, + vrf_id_t vrf_id); extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id); diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 936ec69666..4fb206589a 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -874,7 +874,7 @@ ospf_vl_new (struct ospf *ospf, struct ospf_vl_data *vl_data) zlog_debug ("ospf_vl_new(): creating pseudo zebra interface"); snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count); - vi = if_create (ifname, strnlen(ifname, sizeof(ifname))); + vi = if_create (ifname, strnlen(ifname, sizeof(ifname)), VRF_DEFAULT); /* * if_create sets ZEBRA_INTERFACE_LINKDETECTION * virtual links don't need this. diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index def72c29f8..76687cea30 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1471,7 +1471,7 @@ void pim_if_update_assert_tracking_desired(struct interface *ifp) void pim_if_create_pimreg (void) { if (!pim_regiface) { - pim_regiface = if_create("pimreg", strlen("pimreg")); + pim_regiface = if_create("pimreg", strlen("pimreg"), VRF_DEFAULT); pim_regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF; pim_if_new(pim_regiface, 0, 0); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 20de52c11a..ad04e1a8a4 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -517,7 +517,7 @@ ifm_read (struct if_msghdr *ifm) if (ifp == NULL) { /* Interface that zebra was not previously aware of, so create. */ - ifp = if_create (ifname, ifnlen); + ifp = if_create (ifname, ifnlen, VRF_DEFAULT); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug ("%s: creating ifp for ifindex %d", __func__, ifm->ifm_index); From c5e2cb11ad79a7e3e7d0f8be391d1e9ab067b8da Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 15:51:36 -0500 Subject: [PATCH 006/133] lib, pimd, zebra: Convert if_lookup_exact_address to VRF only Signed-off-by: Donald Sharp --- lib/if.c | 8 +------- lib/if.h | 3 +-- pimd/pim_rp.c | 2 +- ripd/rip_snmp.c | 2 +- zebra/zebra_routemap.c | 8 ++++---- 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/lib/if.c b/lib/if.c index 8b10c91b94..14c333a4e7 100644 --- a/lib/if.c +++ b/lib/if.c @@ -339,7 +339,7 @@ if_lookup_by_name_len(const char *name, size_t namelen) /* Lookup interface by IPv4 address. */ struct interface * -if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id) +if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id) { struct listnode *node; struct listnode *cnode; @@ -371,12 +371,6 @@ if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id) return NULL; } -struct interface * -if_lookup_exact_address (void *src, int family) -{ - return if_lookup_exact_address_vrf (src, family, VRF_DEFAULT); -} - /* Lookup interface by IPv4 address. */ struct connected * if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) diff --git a/lib/if.h b/lib/if.h index 10740957b5..6be1d4b891 100644 --- a/lib/if.h +++ b/lib/if.h @@ -389,7 +389,6 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern struct interface *if_lookup_exact_address (void *matchaddr, int family); extern struct connected *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); @@ -398,7 +397,7 @@ extern void if_update_vrf (struct interface *, const char *name, int namelen, extern struct interface *if_create (const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); -extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, +extern struct interface *if_lookup_exact_address (void *matchaddr, int family, vrf_id_t vrf_id); extern struct connected *if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index dc19002a42..5155354625 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -752,7 +752,7 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) return 1; } - if (if_lookup_exact_address (&dest_addr, AF_INET)) + if (if_lookup_exact_address (&dest_addr, AF_INET, VRF_DEFAULT)) return 1; return 0; diff --git a/ripd/rip_snmp.c b/ripd/rip_snmp.c index c28b9379cc..fede5bed07 100644 --- a/ripd/rip_snmp.c +++ b/ripd/rip_snmp.c @@ -255,7 +255,7 @@ rip2IfLookup (struct variable *v, oid name[], size_t *length, oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr); - return if_lookup_exact_address ((void *)addr, AF_INET); + return if_lookup_exact_address ((void *)addr, AF_INET, VRF_DEFAULT); } else { diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 5fe4a7ab9d..6b81f66a26 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -375,11 +375,11 @@ DEFUN (set_src, RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { if (family == AF_INET) - pif = if_lookup_exact_address_vrf ((void *)&src.ipv4, AF_INET, - vrf->vrf_id); + pif = if_lookup_exact_address ((void *)&src.ipv4, AF_INET, + vrf->vrf_id); else if (family == AF_INET6) - pif = if_lookup_exact_address_vrf ((void *)&src.ipv6, AF_INET6, - vrf->vrf_id); + pif = if_lookup_exact_address ((void *)&src.ipv6, AF_INET6, + vrf->vrf_id); if (pif != NULL) break; From 95af5f130aca6c73465112e18f0dbe7fa4b3c979 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 15:54:53 -0500 Subject: [PATCH 007/133] lib, ospfd, ripd: Convert if_lookup_address to be vrf aware Signed-off-by: Donald Sharp --- lib/if.c | 8 +------- lib/if.h | 7 +++---- ospfd/ospf_packet.c | 2 +- ripd/ripd.c | 8 ++++---- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/lib/if.c b/lib/if.c index 14c333a4e7..c4deeb7920 100644 --- a/lib/if.c +++ b/lib/if.c @@ -373,7 +373,7 @@ if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id) /* Lookup interface by IPv4 address. */ struct connected * -if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) +if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id) { struct listnode *node; struct prefix addr; @@ -414,12 +414,6 @@ if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) return match; } -struct connected * -if_lookup_address (void *matchaddr, int family) -{ - return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT); -} - /* Lookup interface by prefix */ struct interface * if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id) diff --git a/lib/if.h b/lib/if.h index 6be1d4b891..72d78c5d5c 100644 --- a/lib/if.h +++ b/lib/if.h @@ -389,7 +389,6 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern struct connected *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); extern void if_update_vrf (struct interface *, const char *name, int namelen, @@ -398,9 +397,9 @@ extern struct interface *if_create (const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); extern struct interface *if_lookup_exact_address (void *matchaddr, int family, - vrf_id_t vrf_id); -extern struct connected *if_lookup_address_vrf (void *matchaddr, int family, - vrf_id_t vrf_id); + vrf_id_t vrf_id); +extern struct connected *if_lookup_address (void *matchaddr, int family, + vrf_id_t vrf_id); extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index d09e0f7d80..b7721adb3e 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2789,7 +2789,7 @@ ospf_read (struct thread *thread) /* Handle cases where the platform does not support retrieving the ifindex, and also platforms (such as Solaris 8) that claim to support ifindex retrieval but do not. */ - c = if_lookup_address ((void *)&iph->ip_src, AF_INET); + c = if_lookup_address ((void *)&iph->ip_src, AF_INET, VRF_DEFAULT); if (c) ifp = c->ifp; if (ifp == NULL) diff --git a/ripd/ripd.c b/ripd/ripd.c index e0f96f9aaf..abc2faf2e9 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1129,7 +1129,7 @@ rip_response_process (struct rip_packet *packet, int size, /* The datagram's IPv4 source address should be checked to see whether the datagram is from a valid neighbor; the source of the datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */ - if (if_lookup_address((void *)&from->sin_addr, AF_INET) == NULL) + if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) == NULL) { zlog_info ("This datagram doesn't came from a valid neighbor: %s", inet_ntoa (from->sin_addr)); @@ -1215,7 +1215,7 @@ rip_response_process (struct rip_packet *packet, int size, continue; } - if (! if_lookup_address ((void *)&rte->nexthop, AF_INET)) + if (! if_lookup_address ((void *)&rte->nexthop, AF_INET, VRF_DEFAULT)) { struct route_node *rn; struct rip_info *rinfo; @@ -1816,7 +1816,7 @@ rip_read (struct thread *t) } /* Which interface is this packet comes from. */ - ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET); + ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET, VRF_DEFAULT); if (ifc) ifp = ifc->ifp; @@ -2517,7 +2517,7 @@ rip_update_process (int route_type) { p = &rp->p; - connected = if_lookup_address (&p->u.prefix4, AF_INET); + connected = if_lookup_address (&p->u.prefix4, AF_INET, VRF_DEFAULT); if (! connected) { zlog_warn ("Neighbor %s doesnt have connected interface!", From fa787f911c3063133e4cdc7788645766e64376eb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:09:21 -0500 Subject: [PATCH 008/133] lib, ospfd: Refactor if_lookup_by_name_len Signed-off-by: Donald Sharp --- lib/if.c | 12 +++--------- lib/if.h | 6 ++---- lib/zclient.c | 6 +++--- ospfd/ospf_zebra.c | 3 ++- 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/lib/if.c b/lib/if.c index c4deeb7920..633c949ca3 100644 --- a/lib/if.c +++ b/lib/if.c @@ -315,7 +315,7 @@ if_lookup_by_name (const char *name) } struct interface * -if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id) +if_lookup_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; @@ -331,12 +331,6 @@ if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id) return NULL; } -struct interface * -if_lookup_by_name_len(const char *name, size_t namelen) -{ - return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT); -} - /* Lookup interface by IPv4 address. */ struct interface * if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id) @@ -466,7 +460,7 @@ if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int v struct vrf *vrf; struct listnode *node; - ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id); + ifp = if_lookup_by_name_len (name, namelen, vrf_id); if (ifp) return ifp; @@ -705,7 +699,7 @@ if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id) struct interface *ifp; size_t seppos = 0; - if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL) + if ( (ifp = if_lookup_by_name_len (name, nlen, vrf_id)) != NULL) return ifp; /* hunt the primary interface name... */ diff --git a/lib/if.h b/lib/if.h index 72d78c5d5c..7a1274c31e 100644 --- a/lib/if.h +++ b/lib/if.h @@ -417,12 +417,10 @@ extern struct interface *if_get_by_name_vrf (const char *ifname, /* For these 2 functions, the namelen argument should be the precise length of the ifname string (not counting any optional trailing '\0' character). In most cases, strnlen should be used to calculate the namelen value. */ -extern struct interface *if_lookup_by_name_len(const char *ifname, - size_t namelen); extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen); -extern struct interface *if_lookup_by_name_len_vrf(const char *ifname, - size_t namelen, vrf_id_t vrf_id); +extern struct interface *if_lookup_by_name_len(const char *ifname, + size_t namelen, vrf_id_t vrf_id); extern struct interface *if_get_by_name_len_vrf(const char *ifname, size_t namelen, vrf_id_t vrf_id, int vty); diff --git a/lib/zclient.c b/lib/zclient.c index 990bf7906e..2a4816625e 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1092,9 +1092,9 @@ zebra_interface_state_read (struct stream *s, vrf_id_t vrf_id) stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup this by interface index. */ - ifp = if_lookup_by_name_len_vrf (ifname_tmp, - strnlen (ifname_tmp, INTERFACE_NAMSIZ), - vrf_id); + ifp = if_lookup_by_name_len (ifname_tmp, + strnlen (ifname_tmp, INTERFACE_NAMSIZ), + vrf_id); if (ifp == NULL) { zlog_warn ("INTERFACE_STATE: Cannot find IF %s in VRF %d", diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index b0ff5d0e3c..cb14273eed 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -165,7 +165,8 @@ zebra_interface_if_lookup (struct stream *s, vrf_id_t vrf_id) /* And look it up. */ return if_lookup_by_name_len(ifname_tmp, - strnlen(ifname_tmp, INTERFACE_NAMSIZ)); + strnlen(ifname_tmp, INTERFACE_NAMSIZ), + VRF_DEFAULT); } static int From a90607a4ba81caec852bd2e15f541ff12b08c031 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:13:49 -0500 Subject: [PATCH 009/133] lib, ospf6d: Refactor if_lookup_prefix Signed-off-by: Donald Sharp --- lib/if.c | 8 +------- lib/if.h | 3 +-- ospf6d/ospf6_intra.c | 3 ++- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/if.c b/lib/if.c index 633c949ca3..4c8f16d37d 100644 --- a/lib/if.c +++ b/lib/if.c @@ -410,7 +410,7 @@ if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id) /* Lookup interface by prefix */ struct interface * -if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id) +if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id) { struct listnode *node; struct listnode *cnode; @@ -430,12 +430,6 @@ if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id) return NULL; } -struct interface * -if_lookup_prefix (struct prefix *prefix) -{ - return if_lookup_prefix_vrf (prefix, VRF_DEFAULT); -} - /* Get interface by name if given name interface doesn't exist create one. */ struct interface * diff --git a/lib/if.h b/lib/if.h index 7a1274c31e..7a0e6042bc 100644 --- a/lib/if.h +++ b/lib/if.h @@ -389,7 +389,6 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern struct interface *if_lookup_prefix (struct prefix *prefix); extern void if_update_vrf (struct interface *, const char *name, int namelen, vrf_id_t vrf_id); @@ -400,7 +399,7 @@ extern struct interface *if_lookup_exact_address (void *matchaddr, int family, vrf_id_t vrf_id); extern struct connected *if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id); -extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix, +extern struct interface *if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id); /* These 2 functions are to be used when the ifname argument is terminated diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c index d93406fb68..6461963856 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -30,6 +30,7 @@ #include "table.h" #include "vty.h" #include "command.h" +#include "vrf.h" #include "ospf6_proto.h" #include "ospf6_message.h" @@ -1311,7 +1312,7 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa) if (direct_connect) { - ifp = if_lookup_prefix(&route->prefix); + ifp = if_lookup_prefix(&route->prefix, VRF_DEFAULT); if (ifp) ospf6_route_add_nexthop (route, ifp->ifindex, NULL); } From 1306c09a1b6996f7afa3ac651659c40146117834 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:27:15 -0500 Subject: [PATCH 010/133] *: Refactor if_lookup_by_name to be VRF aware Signed-off-by: Donald Sharp --- bgpd/bgp_network.c | 4 ++-- bgpd/bgp_zebra.c | 6 +++--- bgpd/bgpd.c | 2 +- isisd/isis_te.c | 2 +- ldpd/ldp_vty_conf.c | 12 ++++++------ lib/if.c | 20 +++++++------------- lib/if.h | 5 ++--- nhrpd/nhrp_interface.c | 2 +- ospf6d/ospf6_asbr.c | 2 +- ospf6d/ospf6_interface.c | 6 +++--- ospf6d/ospf6_top.c | 2 +- ospfd/ospf_routemap.c | 3 ++- ospfd/ospf_te.c | 2 +- ospfd/ospf_vty.c | 8 ++++---- pimd/pim_cmd.c | 8 ++++---- pimd/pim_iface.c | 4 ++-- ripd/rip_routemap.c | 3 ++- ripd/ripd.c | 4 ++-- ripngd/ripng_routemap.c | 2 +- ripngd/ripngd.c | 4 ++-- zebra/if_ioctl.c | 2 +- zebra/interface.c | 4 ++-- zebra/kernel_socket.c | 2 +- zebra/zebra_vrf.c | 2 +- zebra/zebra_vty.c | 6 +++--- 25 files changed, 56 insertions(+), 61 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 1358ebc5ef..b85dcf6c41 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -262,7 +262,7 @@ bgp_get_instance_for_inc_conn (int sock, struct bgp **bgp_inst) if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) continue; - ifp = if_lookup_by_name_vrf (name, bgp->vrf_id); + ifp = if_lookup_by_name (name, bgp->vrf_id); if (ifp) { *bgp_inst = bgp; @@ -544,7 +544,7 @@ bgp_update_source (struct peer *peer) /* Source is specified with interface name. */ if (peer->update_if) { - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); if (! ifp) return -1; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 2a513dda25..32ad87cb7a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1026,7 +1026,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, { nexthop->v4 = local->sin.sin_addr; if (peer->update_if) - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); else ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr, peer->bgp->vrf_id); } @@ -1035,10 +1035,10 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote, if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { if (peer->conf_if || peer->ifname) - ifp = if_lookup_by_name_vrf (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); } else if (peer->update_if) - ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id); + ifp = if_lookup_by_name (peer->update_if, peer->bgp->vrf_id); else ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr, local->sin6.sin6_scope_id, diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index ce0718df5a..30243e80b2 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1435,7 +1435,7 @@ bgp_peer_conf_if_to_su_update (struct peer *peer) return; prev_family = peer->su.sa.sa_family; - if ((ifp = if_lookup_by_name_vrf (peer->conf_if, peer->bgp->vrf_id))) + if ((ifp = if_lookup_by_name (peer->conf_if, peer->bgp->vrf_id))) { peer->ifp = ifp; /* If BGP unnumbered is not "v6only", we first see if we can derive the diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 830ccb37c6..b04d0db3ca 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -1323,7 +1323,7 @@ DEFUN (show_isis_mpls_te_interface, /* Interface name is specified. */ else { - if ((ifp = if_lookup_by_name (argv[idx_interface]->arg)) == NULL) + if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL) vty_out (vty, "No such interface name%s", VTY_NEWLINE); else show_mpls_te_sub (vty, ifp); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 4d1af62146..f313bc147b 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -900,7 +900,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) goto cancel; } - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); if (ifp) { @@ -1558,7 +1558,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) goto cancel; } - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); if (ifp) { @@ -1616,7 +1616,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) goto cancel; } - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); if (ifp) { @@ -1809,7 +1809,7 @@ iface_new_api(struct ldpd_conf *conf, const char *name) memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); if (ifp) { kif.ifindex = ifp->ifindex; kif.flags = ifp->flags; @@ -1920,7 +1920,7 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); if (ifp) { kif.ifindex = ifp->ifindex; kif.flags = ifp->flags; @@ -1951,7 +1951,7 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); if (ifp) { kif.ifindex = ifp->ifindex; kif.flags = ifp->flags; diff --git a/lib/if.c b/lib/if.c index 4c8f16d37d..4f2eb3a1c5 100644 --- a/lib/if.c +++ b/lib/if.c @@ -136,7 +136,7 @@ if_create (const char *name, int namelen, vrf_id_t vrf_id) strncpy (ifp->name, name, namelen); ifp->name[namelen] = '\0'; ifp->vrf_id = vrf_id; - if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL) + if (if_lookup_by_name (ifp->name, vrf_id) == NULL) listnode_add_sort (intf_list, ifp); else zlog_err("if_create(%s): corruption detected -- interface with this " @@ -173,7 +173,7 @@ if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vr strncpy (ifp->name, name, namelen); ifp->name[namelen] = '\0'; ifp->vrf_id = vrf_id; - if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL) + if (if_lookup_by_name (ifp->name, vrf_id) == NULL) listnode_add_sort (intf_list, ifp); else zlog_err("if_create(%s): corruption detected -- interface with this " @@ -266,7 +266,7 @@ ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex + return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp->ifindex : IFINDEX_INTERNAL; } @@ -278,7 +278,7 @@ ifname2ifindex (const char *name) /* Interface existance check by interface name. */ struct interface * -if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id) +if_lookup_by_name (const char *name, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; @@ -300,7 +300,7 @@ if_lookup_by_name_all_vrf (const char *name) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_name_vrf (name, vrf->vrf_id); + ifp = if_lookup_by_name (name, vrf->vrf_id); if (ifp) return ifp; } @@ -308,12 +308,6 @@ if_lookup_by_name_all_vrf (const char *name) return NULL; } -struct interface * -if_lookup_by_name (const char *name) -{ - return if_lookup_by_name_vrf (name, VRF_DEFAULT); -} - struct interface * if_lookup_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id) { @@ -437,7 +431,7 @@ if_get_by_name_vrf (const char *name, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp : + return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp : if_create (name, strlen(name), vrf_id); } @@ -771,7 +765,7 @@ DEFUN_NOSH (no_interface, if (argc > 3) VRF_GET_ID (vrf_id, vrfname); - ifp = if_lookup_by_name_vrf (ifname, vrf_id); + ifp = if_lookup_by_name (ifname, vrf_id); if (ifp == NULL) { diff --git a/lib/if.h b/lib/if.h index 7a0e6042bc..262e292ac5 100644 --- a/lib/if.h +++ b/lib/if.h @@ -404,12 +404,11 @@ extern struct interface *if_lookup_prefix (struct prefix *prefix, /* These 2 functions are to be used when the ifname argument is terminated by a '\0' character: */ -extern struct interface *if_lookup_by_name (const char *ifname); extern struct interface *if_get_by_name (const char *ifname); extern struct interface *if_lookup_by_name_all_vrf (const char *ifname); -extern struct interface *if_lookup_by_name_vrf (const char *ifname, - vrf_id_t vrf_id); +extern struct interface *if_lookup_by_name (const char *ifname, + vrf_id_t vrf_id); extern struct interface *if_get_by_name_vrf (const char *ifname, vrf_id_t vrf_id); diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c index 052b9c1e83..bbaa630cd5 100644 --- a/nhrpd/nhrp_interface.c +++ b/nhrpd/nhrp_interface.c @@ -117,7 +117,7 @@ static void nhrp_interface_update_nbma(struct interface *ifp) sockunion_family(&nbma) = AF_UNSPEC; if (nifp->source) - nbmaifp = if_lookup_by_name(nifp->source); + nbmaifp = if_lookup_by_name(nifp->source, VRF_DEFAULT); switch (ifp->ll_type) { case ZEBRA_LLT_IPGRE: { diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index 5f2d662b78..8caae50221 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -866,7 +866,7 @@ ospf6_routemap_rule_match_interface (void *rule, struct prefix *prefix, if (type == RMAP_OSPF6) { ei = ((struct ospf6_route *) object)->route_option; - ifp = if_lookup_by_name ((char *)rule); + ifp = if_lookup_by_name ((char *)rule, VRF_DEFAULT); if (ifp != NULL && ei->ifindex == ifp->ifindex) diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 62c77e6f87..8e0779df92 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1006,7 +1006,7 @@ DEFUN (show_ipv6_ospf6_interface, if (argc == 5) { - ifp = if_lookup_by_name (argv[idx_ifname]->arg); + ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); if (ifp == NULL) { vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg, @@ -1043,7 +1043,7 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, struct interface *ifp; struct ospf6_interface *oi; - ifp = if_lookup_by_name (argv[idx_ifname]->arg); + ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); if (ifp == NULL) { vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg, VNL); @@ -1897,7 +1897,7 @@ DEFUN (clear_ipv6_ospf6_interface, } else /* Interface name is specified. */ { - if ((ifp = if_lookup_by_name (argv[idx_ifname]->arg)) == NULL) + if ((ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT)) == NULL) { vty_out (vty, "No such Interface: %s%s", argv[idx_ifname]->arg, VNL); return CMD_WARNING; diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 92111c73fc..9e741d07d2 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -728,7 +728,7 @@ DEFUN (no_ospf6_interface_area, struct interface *ifp; u_int32_t area_id; - ifp = if_lookup_by_name (argv[idx_ifname]->arg); + ifp = if_lookup_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); if (ifp == NULL) { vty_out (vty, "No such interface %s%s", argv[idx_ifname]->arg, VNL); diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index 717dc25f94..db51abca23 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -32,6 +32,7 @@ #include "command.h" #include "log.h" #include "plist.h" +#include "vrf.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_asbr.h" @@ -360,7 +361,7 @@ route_match_interface (void *rule, struct prefix *prefix, if (type == RMAP_OSPF) { ei = object; - ifp = if_lookup_by_name ((char *)rule); + ifp = if_lookup_by_name ((char *)rule, VRF_DEFAULT); if (ifp == NULL || ifp->ifindex != ei->ifindex) return RMAP_NOMATCH; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 4c5862e84a..449f9e7b97 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -2630,7 +2630,7 @@ DEFUN (show_ip_ospf_mpls_te_link, /* Interface name is specified. */ else { - if ((ifp = if_lookup_by_name (argv[idx_interface]->arg)) == NULL) + if ((ifp = if_lookup_by_name (argv[idx_interface]->arg, VRF_DEFAULT)) == NULL) vty_out (vty, "No such interface name%s", VTY_NEWLINE); else show_mpls_te_link_sub (vty, ifp); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 33fc0bf525..cc3b47c0c4 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -3592,7 +3592,7 @@ show_ip_ospf_interface_common (struct vty *vty, struct ospf *ospf, int argc, else { /* Interface name is specified. */ - if ((ifp = if_lookup_by_name (argv[iface_argv]->arg)) == NULL) + if ((ifp = if_lookup_by_name (argv[iface_argv]->arg, VRF_DEFAULT)) == NULL) { if (use_json) json_object_boolean_true_add(json, "noSuchIface"); @@ -3950,7 +3950,7 @@ show_ip_ospf_neighbor_int_common (struct vty *vty, struct ospf *ospf, int arg_ba VTY_NEWLINE, VTY_NEWLINE); } - ifp = if_lookup_by_name (argv[arg_base]->arg); + ifp = if_lookup_by_name (argv[arg_base]->arg, VRF_DEFAULT); if (!ifp) { if (use_json) @@ -4609,7 +4609,7 @@ show_ip_ospf_neighbor_int_detail_common (struct vty *vty, struct ospf *ospf, VTY_NEWLINE, VTY_NEWLINE); } - ifp = if_lookup_by_name (argv[arg_base]->arg); + ifp = if_lookup_by_name (argv[arg_base]->arg, VRF_DEFAULT); if (!ifp) { if (!use_json) @@ -9142,7 +9142,7 @@ DEFUN (clear_ip_ospf_interface, } else /* Interface name is specified. */ { - if ((ifp = if_lookup_by_name (argv[idx_ifname]->text)) == NULL) + if ((ifp = if_lookup_by_name (argv[idx_ifname]->text, VRF_DEFAULT)) == NULL) vty_out (vty, "No such interface name%s", VTY_NEWLINE); else ospf_interface_clear(ifp); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 465c368f43..081f62b90b 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -4418,7 +4418,7 @@ DEFUN (interface_ip_mroute, int result; oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname); + oif = if_lookup_by_name(oifname, VRF_DEFAULT); if (!oif) { vty_out(vty, "No such interface name %s%s", oifname, VTY_NEWLINE); @@ -4465,7 +4465,7 @@ DEFUN (interface_ip_mroute_source, int result; oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname); + oif = if_lookup_by_name(oifname, VRF_DEFAULT); if (!oif) { vty_out(vty, "No such interface name %s%s", oifname, VTY_NEWLINE); @@ -4516,7 +4516,7 @@ DEFUN (interface_no_ip_mroute, int result; oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname); + oif = if_lookup_by_name(oifname, VRF_DEFAULT); if (!oif) { vty_out(vty, "No such interface name %s%s", oifname, VTY_NEWLINE); @@ -4564,7 +4564,7 @@ DEFUN (interface_no_ip_mroute_source, int result; oifname = argv[idx_interface]->arg; - oif = if_lookup_by_name(oifname); + oif = if_lookup_by_name(oifname, VRF_DEFAULT); if (!oif) { vty_out(vty, "No such interface name %s%s", oifname, VTY_NEWLINE); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 76687cea30..0864796431 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -858,7 +858,7 @@ pim_find_primary_addr (struct interface *ifp) if (!v4_addrs && v6_addrs && !if_is_loopback (ifp)) { struct interface *lo_ifp; - lo_ifp = if_lookup_by_name_vrf ("lo", VRF_DEFAULT); + lo_ifp = if_lookup_by_name ("lo", VRF_DEFAULT); if (lo_ifp) return pim_find_primary_addr (lo_ifp); } @@ -1005,7 +1005,7 @@ struct interface *pim_if_find_by_vif_index(ifindex_t vif_index) struct interface *ifp; if (vif_index == 0) - return if_lookup_by_name_vrf ("pimreg", VRF_DEFAULT); + return if_lookup_by_name ("pimreg", VRF_DEFAULT); for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) { if (ifp->info) { diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 6fd647596c..baba9592e0 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -31,6 +31,7 @@ #include "log.h" #include "sockunion.h" /* for inet_aton () */ #include "plist.h" +#include "vrf.h" #include "ripd/ripd.h" @@ -136,7 +137,7 @@ route_match_interface (void *rule, struct prefix *prefix, if (type == RMAP_RIP) { ifname = rule; - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); if (!ifp) return RMAP_NOMATCH; diff --git a/ripd/ripd.c b/ripd/ripd.c index abc2faf2e9..fab31b322f 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3763,7 +3763,7 @@ rip_distribute_update (struct distribute *dist) if (! dist->ifname) return; - ifp = if_lookup_by_name (dist->ifname); + ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); if (ifp == NULL) return; @@ -3962,7 +3962,7 @@ rip_if_rmap_update (struct if_rmap *if_rmap) struct rip_interface *ri; struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname); + ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); if (ifp == NULL) return; diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 7cab5861bf..ad8dbc92f3 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -110,7 +110,7 @@ route_match_interface (void *rule, struct prefix *prefix, if (type == RMAP_RIPNG) { ifname = rule; - ifp = if_lookup_by_name(ifname); + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); if (!ifp) return RMAP_NOMATCH; diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 8e98f5b0ef..591316e50f 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2814,7 +2814,7 @@ ripng_distribute_update (struct distribute *dist) if (! dist->ifname) return; - ifp = if_lookup_by_name (dist->ifname); + ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT); if (ifp == NULL) return; @@ -3009,7 +3009,7 @@ ripng_if_rmap_update (struct if_rmap *if_rmap) struct ripng_interface *ri; struct route_map *rmap; - ifp = if_lookup_by_name (if_rmap->ifname); + ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT); if (ifp == NULL) return; diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index a4498a84f6..2393e0f9c5 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -201,7 +201,7 @@ if_getaddrs (void) continue; } - ifp = if_lookup_by_name (ifap->ifa_name); + ifp = if_lookup_by_name (ifap->ifa_name, VRF_DEFAULT); if (ifp == NULL) { zlog_err ("if_getaddrs(): Can't lookup interface %s\n", diff --git a/zebra/interface.c b/zebra/interface.c index 5a9de5b70b..902e53dc5e 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1320,7 +1320,7 @@ DEFUN (show_interface_name_vrf, VRF_GET_ID (vrf_id, argv[idx_name]->arg); /* Specified interface print. */ - ifp = if_lookup_by_name_vrf (argv[idx_ifname]->arg, vrf_id); + ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf_id); if (ifp == NULL) { vty_out (vty, "%% Can't find interface %s%s", argv[idx_ifname]->arg, @@ -1352,7 +1352,7 @@ DEFUN (show_interface_name_vrf_all, RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { /* Specified interface print. */ - ifp = if_lookup_by_name_vrf (argv[idx_ifname]->arg, vrf->vrf_id); + ifp = if_lookup_by_name (argv[idx_ifname]->arg, vrf->vrf_id); if (ifp) { if_dump_vty (vty, ifp); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index ad04e1a8a4..fee7bce1cd 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -487,7 +487,7 @@ ifm_read (struct if_msghdr *ifm) * be filled in. */ if ( (ifp == NULL) && ifnlen) - ifp = if_lookup_by_name (ifname); + ifp = if_lookup_by_name (ifname, VRF_DEFAULT); /* * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL), diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 6fc41c3a14..bc18ee5863 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -171,7 +171,7 @@ zebra_vrf_enable (struct vrf *vrf) si->vrf_id = vrf->vrf_id; if (si->ifindex) { - ifp = if_lookup_by_name_vrf (si->ifname, si->vrf_id); + ifp = if_lookup_by_name (si->ifname, si->vrf_id); if (ifp) si->ifindex = ifp->ifindex; else diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 7946089aea..1c315670bd 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -184,7 +184,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, ret = inet_aton (gate_str, &gate); if (!ret) { - struct interface *ifp = if_lookup_by_name_vrf (gate_str, zvrf_id (zvrf)); + struct interface *ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Unknown interface: %s%s", gate_str, VTY_NEWLINE); @@ -2459,7 +2459,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, } type = STATIC_IPV6_GATEWAY_IFINDEX; gate = &gate_addr; - ifp = if_lookup_by_name_vrf (ifname, zvrf_id (zvrf)); + ifp = if_lookup_by_name (ifname, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Malformed Interface name %s%s", ifname, VTY_NEWLINE); @@ -2477,7 +2477,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, else { type = STATIC_IFINDEX; - ifp = if_lookup_by_name_vrf (gate_str, zvrf_id (zvrf)); + ifp = if_lookup_by_name (gate_str, zvrf_id (zvrf)); if (!ifp) { vty_out (vty, "%% Malformed Interface name %s%s", gate_str, VTY_NEWLINE); From 92a57eb206d51a6e9a28c9ffa1066557a18da9b2 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:30:52 -0500 Subject: [PATCH 011/133] *: Refactor if_get_by_name to be VRF aware Signed-off-by: Donald Sharp --- lib/if.c | 8 +------- lib/if.h | 6 ++---- ospf6d/ospf6_top.c | 2 +- ospfd/ospf_vty.c | 4 ++-- zebra/if_netlink.c | 4 ++-- 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/lib/if.c b/lib/if.c index 4f2eb3a1c5..3deec8025b 100644 --- a/lib/if.c +++ b/lib/if.c @@ -427,7 +427,7 @@ if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id) /* Get interface by name if given name interface doesn't exist create one. */ struct interface * -if_get_by_name_vrf (const char *name, vrf_id_t vrf_id) +if_get_by_name (const char *name, vrf_id_t vrf_id) { struct interface *ifp; @@ -435,12 +435,6 @@ if_get_by_name_vrf (const char *name, vrf_id_t vrf_id) if_create (name, strlen(name), vrf_id); } -struct interface * -if_get_by_name (const char *name) -{ - return if_get_by_name_vrf (name, VRF_DEFAULT); -} - struct interface * if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) { diff --git a/lib/if.h b/lib/if.h index 262e292ac5..aeb3d340ee 100644 --- a/lib/if.h +++ b/lib/if.h @@ -402,14 +402,12 @@ extern struct connected *if_lookup_address (void *matchaddr, int family, extern struct interface *if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id); -/* These 2 functions are to be used when the ifname argument is terminated +/* These 3 functions are to be used when the ifname argument is terminated by a '\0' character: */ -extern struct interface *if_get_by_name (const char *ifname); - extern struct interface *if_lookup_by_name_all_vrf (const char *ifname); extern struct interface *if_lookup_by_name (const char *ifname, vrf_id_t vrf_id); -extern struct interface *if_get_by_name_vrf (const char *ifname, +extern struct interface *if_get_by_name (const char *ifname, vrf_id_t vrf_id); /* For these 2 functions, the namelen argument should be the precise length diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 9e741d07d2..a367d1e141 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -668,7 +668,7 @@ DEFUN (ospf6_interface_area, u_int32_t area_id; /* find/create ospf6 interface */ - ifp = if_get_by_name (argv[idx_ifname]->arg); + ifp = if_get_by_name (argv[idx_ifname]->arg, VRF_DEFAULT); oi = (struct ospf6_interface *) ifp->info; if (oi == NULL) oi = ospf6_interface_create (ifp); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index cc3b47c0c4..059a17fa9f 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -387,7 +387,7 @@ DEFUN (ospf_passive_interface, return CMD_SUCCESS; } - ifp = if_get_by_name (argv[1]->arg); + ifp = if_get_by_name (argv[1]->arg, VRF_DEFAULT); params = IF_DEF_PARAMS (ifp); @@ -457,7 +457,7 @@ DEFUN (no_ospf_passive_interface, return CMD_SUCCESS; } - ifp = if_get_by_name (argv[2]->arg); + ifp = if_get_by_name (argv[2]->arg, VRF_DEFAULT); params = IF_DEF_PARAMS (ifp); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 65fc8789f9..2572320cce 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -375,7 +375,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h, } /* Add interface. */ - ifp = if_get_by_name_vrf (name, vrf_id); + ifp = if_get_by_name (name, vrf_id); set_ifindex(ifp, ifi->ifi_index, zns); ifp->flags = ifi->ifi_flags & 0x0000fffff; if (vrf_device) @@ -722,7 +722,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, if (ifp == NULL) { /* unknown interface */ - ifp = if_get_by_name_vrf (name, vrf_id); + ifp = if_get_by_name (name, vrf_id); } else { From 07a112a1dc224df494490872894250fea12e8797 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:34:21 -0500 Subject: [PATCH 012/133] lib: Refactor if_get_by_name_len to be VRF aware Signed-off-by: Donald Sharp --- lib/if.c | 14 ++++---------- lib/if.h | 4 +--- lib/zclient.c | 6 +++--- zebra/if_ioctl.c | 6 ++++-- zebra/if_ioctl_solaris.c | 2 +- zebra/kernel_socket.c | 3 ++- 6 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/if.c b/lib/if.c index 3deec8025b..2e929ac755 100644 --- a/lib/if.c +++ b/lib/if.c @@ -436,7 +436,7 @@ if_get_by_name (const char *name, vrf_id_t vrf_id) } struct interface * -if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) +if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) { struct interface *ifp; struct vrf *vrf; @@ -476,12 +476,6 @@ if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id, int v return (if_create (name, namelen, vrf_id)); } -struct interface * -if_get_by_name_len (const char *name, size_t namelen) -{ - return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT, 0); -} - /* Does interface up ? */ int if_is_up (struct interface *ifp) @@ -690,9 +684,9 @@ if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id) /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ if (seppos < nlen) - return if_get_by_name_len_vrf (name, seppos, vrf_id, 1); + return if_get_by_name_len (name, seppos, vrf_id, 1); else - return if_get_by_name_len_vrf (name, nlen, vrf_id, 1); + return if_get_by_name_len (name, nlen, vrf_id, 1); } #endif /* SUNOS_5 */ @@ -728,7 +722,7 @@ DEFUN (interface, #ifdef SUNOS_5 ifp = if_sunwzebra_get (ifname, sl, vrf_id); #else - ifp = if_get_by_name_len_vrf (ifname, sl, vrf_id, 1); + ifp = if_get_by_name_len (ifname, sl, vrf_id, 1); #endif /* SUNOS_5 */ if (!ifp) diff --git a/lib/if.h b/lib/if.h index aeb3d340ee..f8e89d2cfb 100644 --- a/lib/if.h +++ b/lib/if.h @@ -413,11 +413,9 @@ extern struct interface *if_get_by_name (const char *ifname, /* For these 2 functions, the namelen argument should be the precise length of the ifname string (not counting any optional trailing '\0' character). In most cases, strnlen should be used to calculate the namelen value. */ -extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen); - extern struct interface *if_lookup_by_name_len(const char *ifname, size_t namelen, vrf_id_t vrf_id); -extern struct interface *if_get_by_name_len_vrf(const char *ifname, +extern struct interface *if_get_by_name_len(const char *ifname, size_t namelen, vrf_id_t vrf_id, int vty); diff --git a/lib/zclient.c b/lib/zclient.c index 2a4816625e..620cd6bc4e 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1066,9 +1066,9 @@ zebra_interface_add_read (struct stream *s, vrf_id_t vrf_id) stream_get (ifname_tmp, s, INTERFACE_NAMSIZ); /* Lookup/create interface by name. */ - ifp = if_get_by_name_len_vrf (ifname_tmp, - strnlen (ifname_tmp, INTERFACE_NAMSIZ), - vrf_id, 0); + ifp = if_get_by_name_len (ifname_tmp, + strnlen (ifname_tmp, INTERFACE_NAMSIZ), + vrf_id, 0); zebra_interface_if_set_value (s, ifp); diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index 2393e0f9c5..5333f0331e 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -110,7 +110,8 @@ interface_list_ioctl (void) ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n); ifp = if_get_by_name_len(ifreq->ifr_name, strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name))); + sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); if_add_update (ifp); size = ifreq->ifr_addr.sa_len; if (size < sizeof (ifreq->ifr_addr)) @@ -123,7 +124,8 @@ interface_list_ioctl (void) { ifp = if_get_by_name_len(ifreq->ifr_name, strnlen(ifreq->ifr_name, - sizeof(ifreq->ifr_name))); + sizeof(ifreq->ifr_name)), + VRF_DEFAULT, 0); if_add_update (ifp); ifreq++; } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index 339e00b22c..dbc4109913 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -170,7 +170,7 @@ calculate_lifc_len: /* must hold privileges to enter here */ && ( *(lifreq->lifr_name + normallen) != ':') ) normallen++; - ifp = if_get_by_name_len(lifreq->lifr_name, normallen); + ifp = if_get_by_name_len(lifreq->lifr_name, normallen, VRF_DEFAULT, 0); if (lifreq->lifr_addr.ss_family == AF_INET) ifp->flags |= IFF_IPV4; diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index fee7bce1cd..7212ed6f26 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -341,7 +341,8 @@ ifan_read (struct if_announcemsghdr *ifan) /* Create Interface */ ifp = if_get_by_name_len(ifan->ifan_name, strnlen(ifan->ifan_name, - sizeof(ifan->ifan_name))); + sizeof(ifan->ifan_name)), + VRF_DEFAULT, 0); ifp->ifindex = ifan->ifan_index; if_get_metric (ifp); From baaea325e6a425321296cff40cc7a3b47b53efb3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:47:46 -0500 Subject: [PATCH 013/133] *: Refactor ifindex2ifname to be VRF aware Signed-off-by: Donald Sharp --- bgpd/bgp_nexthop.c | 6 +++--- lib/if.c | 8 +------- lib/if.h | 3 +-- ospf6d/ospf6_route.c | 6 +++--- ospfd/ospf_spf.c | 4 ++-- ospfd/ospf_vty.c | 12 ++++++------ pimd/pim_zebra.c | 2 +- ripd/ripd.c | 14 +++++++------- ripngd/ripngd.c | 16 ++++++++-------- zebra/zebra_mpls.c | 8 ++++---- zebra/zebra_rib.c | 2 +- zebra/zebra_vty.c | 22 +++++++++++----------- 12 files changed, 48 insertions(+), 55 deletions(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 0cf96101c2..c76ff2c098 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -415,7 +415,7 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) vty_out(vty, " gate %s, if %s%s", inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex), + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4: @@ -425,13 +425,13 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " if %s%s", - ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " gate %s, if %s%s", inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), VTY_NEWLINE); break; default: vty_out (vty, " invalid nexthop type %u%s", diff --git a/lib/if.c b/lib/if.c index 2e929ac755..f4f7ad7749 100644 --- a/lib/if.c +++ b/lib/if.c @@ -247,7 +247,7 @@ if_lookup_by_index (ifindex_t ifindex, vrf_id_t vrf_id) } const char * -ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) +ifindex2ifname (ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; @@ -255,12 +255,6 @@ ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) ifp->name : "unknown"; } -const char * -ifindex2ifname (ifindex_t ifindex) -{ - return ifindex2ifname_vrf (ifindex, VRF_DEFAULT); -} - ifindex_t ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) { diff --git a/lib/if.h b/lib/if.h index f8e89d2cfb..bee783d930 100644 --- a/lib/if.h +++ b/lib/if.h @@ -447,8 +447,7 @@ extern const char *if_link_type_str (enum zebra_link_type); /* Please use ifindex2ifname instead of if_indextoname where possible; ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ -extern const char *ifindex2ifname (ifindex_t); -extern const char *ifindex2ifname_vrf (ifindex_t, vrf_id_t vrf_id); +extern const char *ifindex2ifname (ifindex_t, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index 29956c61a0..b8e5ca6196 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -349,7 +349,7 @@ ospf6_route_zebra_copy_nexthops (struct ospf6_route *route, { const char *ifname; inet_ntop (AF_INET6, &nh->address, buf, sizeof (buf)); - ifname = ifindex2ifname (nh->ifindex); + ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); zlog_debug (" nexthop: %s%%%.*s(%d)", buf, IFNAMSIZ, ifname, nh->ifindex); } @@ -1040,7 +1040,7 @@ ospf6_route_show (struct vty *vty, struct ospf6_route *route) /* nexthop */ inet_ntop (AF_INET6, &nh->address, nexthop, sizeof (nexthop)); - ifname = ifindex2ifname (nh->ifindex); + ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); if (!i) { @@ -1146,7 +1146,7 @@ ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route) { /* nexthop */ inet_ntop (AF_INET6, &nh->address, nexthop, sizeof (nexthop)); - ifname = ifindex2ifname (nh->ifindex); + ifname = ifindex2ifname (nh->ifindex, VRF_DEFAULT); vty_out (vty, " %s %.*s%s", nexthop, IFNAMSIZ, ifname, VNL); } vty_out (vty, "%s", VNL); diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c index 077d0e68ad..31f0d9d286 100644 --- a/ospfd/ospf_spf.c +++ b/ospfd/ospf_spf.c @@ -1159,14 +1159,14 @@ ospf_rtrs_print (struct route_table *rtrs) { if (IS_DEBUG_OSPF_EVENT) zlog_debug (" directly attached to %s\r\n", - ifindex2ifname (path->ifindex)); + ifindex2ifname (path->ifindex), VRF_DEFAULT); } else { if (IS_DEBUG_OSPF_EVENT) zlog_debug (" via %s, %s\r\n", inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex)); + ifindex2ifname (path->ifindex), VRF_DEFAULT); } } } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 059a17fa9f..71befc84b5 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -7952,11 +7952,11 @@ show_ip_ospf_route_network (struct vty *vty, struct route_table *rt) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", - "", ifindex2ifname (path->ifindex), VTY_NEWLINE); + "", ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); else vty_out (vty, "%24s via %s, %s%s", "", inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex), VTY_NEWLINE); + ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); } } } @@ -8002,12 +8002,12 @@ show_ip_ospf_route_router (struct vty *vty, struct route_table *rtrs) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", - "", ifindex2ifname (path->ifindex), + "", ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); else vty_out (vty, "%24s via %s, %s%s", "", inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex), + ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); } } @@ -8051,11 +8051,11 @@ show_ip_ospf_route_external (struct vty *vty, struct route_table *rt) { if (path->nexthop.s_addr == 0) vty_out (vty, "%24s directly attached to %s%s", - "", ifindex2ifname (path->ifindex), VTY_NEWLINE); + "", ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); else vty_out (vty, "%24s via %s, %s%s", "", inet_ntoa (path->nexthop), - ifindex2ifname (path->ifindex), + ifindex2ifname (path->ifindex, VRF_DEFAULT), VTY_NEWLINE); } } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 1db6616c58..fb62fc3f14 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -847,7 +847,7 @@ static int fib_lookup_if_vif_index(struct in_addr addr) pim_inet4_dump("", addr, addr_str, sizeof(addr_str)); zlog_debug("%s %s: found nexthop ifindex=%d (interface %s) for address %s", __FILE__, __PRETTY_FUNCTION__, - first_ifindex, ifindex2ifname(first_ifindex), addr_str); + first_ifindex, ifindex2ifname(first_ifindex, VRF_DEFAULT), addr_str); } vif_index = pim_if_find_vifindex_by_ifindex(first_ifindex); diff --git a/ripd/ripd.c b/ripd/ripd.c index fab31b322f..82e460ced8 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1552,12 +1552,12 @@ rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, if (IS_RIP_DEBUG_EVENT) { if (!nexthop) zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex)); + inet_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); else zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop), - ifindex2ifname(ifindex)); + inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); } rip_event (RIP_TRIGGERED_UPDATE, 0); @@ -1600,7 +1600,7 @@ rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, zlog_debug ("Poisone %s/%d on the interface %s with an " "infinity metric [delete]", inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex)); + ifindex2ifname(ifindex, VRF_DEFAULT)); rip_event (RIP_TRIGGERED_UPDATE, 0); } @@ -2660,8 +2660,8 @@ rip_redistribute_withdraw (int type) struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p; zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]", - inet_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex)); + inet_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); } rip_event (RIP_TRIGGERED_UPDATE, 0); diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 591316e50f..caad85457a 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -979,12 +979,12 @@ ripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, if (IS_RIPNG_DEBUG_EVENT) { if (!nexthop) zlog_debug ("Redistribute new prefix %s/%d on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(ifindex)); + inet6_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(ifindex, VRF_DEFAULT)); else zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s", - inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop), - ifindex2ifname(ifindex)); + inet6_ntoa(p->prefix), p->prefixlen, inet6_ntoa(*nexthop), + ifindex2ifname(ifindex, VRF_DEFAULT)); } ripng_event (RIPNG_TRIGGERED_UPDATE, 0); @@ -1032,7 +1032,7 @@ ripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, zlog_debug ("Poisone %s/%d on the interface %s with an " "infinity metric [delete]", inet6_ntoa (p->prefix), p->prefixlen, - ifindex2ifname (ifindex)); + ifindex2ifname (ifindex, VRF_DEFAULT)); ripng_event (RIPNG_TRIGGERED_UPDATE, 0); } @@ -1074,8 +1074,8 @@ ripng_redistribute_withdraw (int type) struct prefix_ipv6 *p = (struct prefix_ipv6 *) &rp->p; zlog_debug ("Poisone %s/%d on the interface %s [withdraw]", - inet6_ntoa(p->prefix), p->prefixlen, - ifindex2ifname(rinfo->ifindex)); + inet6_ntoa(p->prefix), p->prefixlen, + ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); } ripng_event (RIPNG_TRIGGERED_UPDATE, 0); @@ -2066,7 +2066,7 @@ DEFUN (show_ipv6_ripng, if ((rinfo->type == ZEBRA_ROUTE_RIPNG) && (rinfo->sub_type == RIPNG_ROUTE_RTE)) { - len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex)); + len = vty_out (vty, "%s", ifindex2ifname(rinfo->ifindex, VRF_DEFAULT)); } else if (rinfo->metric == RIPNG_METRIC_INFINITY) { len = vty_out (vty, "kill"); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 55a2745b53..5a3ed7545d 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -869,7 +869,7 @@ nhlfe_json (zebra_nhlfe_t *nhlfe) inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); if (nexthop->ifindex) - json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex)); + json_object_string_add(json_nhlfe, "interface", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); break; default: break; @@ -900,14 +900,14 @@ nhlfe_print (zebra_nhlfe_t *nhlfe, struct vty *vty) case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: vty_out (vty, " via %s", inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); if (nexthop->ifindex) - vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex)); + vty_out (vty, " dev %s", ifindex2ifname (nexthop->ifindex, VRF_DEFAULT)); break; default: break; @@ -1183,7 +1183,7 @@ snhlfe2str (zebra_snhlfe_t *snhlfe, char *buf, int size) case NEXTHOP_TYPE_IPV6_IFINDEX: inet_ntop (AF_INET6, &snhlfe->gate.ipv6, buf, size); if (snhlfe->ifindex) - strcat (buf, ifindex2ifname (snhlfe->ifindex)); + strcat (buf, ifindex2ifname (snhlfe->ifindex, VRF_DEFAULT)); break; default: break; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 76c32c3971..f5b54a2c04 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1021,7 +1021,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, srcdest_rnode2str(rn, buf, sizeof(buf)); zlog_debug("%u:%s: Filtering out with NH out %s due to route map", rib->vrf_id, buf, - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); } UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 1c315670bd..05c1aa274a 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -725,7 +725,7 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) vty_out (vty, " %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) vty_out (vty, ", via %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: @@ -733,11 +733,11 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn, int mcast) inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); if (nexthop->ifindex) vty_out (vty, ", via %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " directly connected, %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out (vty, " directly connected, Null0"); @@ -874,7 +874,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, if (nexthop->ifindex) { json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, rib->vrf_id)); } break; case NEXTHOP_TYPE_IPV6: @@ -885,14 +885,14 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, if (nexthop->ifindex) { json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, rib->vrf_id)); } break; case NEXTHOP_TYPE_IFINDEX: json_object_boolean_true_add(json_nexthop, "directlyConnected"); json_object_int_add(json_nexthop, "interfaceIndex", nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + json_object_string_add(json_nexthop, "interfaceName", ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: json_object_boolean_true_add(json_nexthop, "blackhole"); @@ -975,7 +975,7 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, vty_out (vty, " via %s", inet_ntoa (nexthop->gate.ipv4)); if (nexthop->ifindex) vty_out (vty, ", %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: @@ -983,12 +983,12 @@ vty_show_ip_route (struct vty *vty, struct route_node *rn, struct rib *rib, inet_ntop (AF_INET6, &nexthop->gate.ipv6, buf, BUFSIZ)); if (nexthop->ifindex) vty_out (vty, ", %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " is directly connected, %s", - ifindex2ifname_vrf (nexthop->ifindex, rib->vrf_id)); + ifindex2ifname (nexthop->ifindex, rib->vrf_id)); break; case NEXTHOP_TYPE_BLACKHOLE: vty_out (vty, " is directly connected, Null0"); @@ -2292,7 +2292,7 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const char *cmd) case STATIC_IPV6_GATEWAY_IFINDEX: vty_out (vty, " %s %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ), - ifindex2ifname_vrf (si->ifindex, si->vrf_id)); + ifindex2ifname (si->ifindex, si->vrf_id)); break; } @@ -3784,7 +3784,7 @@ static_config_ipv6 (struct vty *vty) case STATIC_IPV6_GATEWAY_IFINDEX: vty_out (vty, " %s %s", inet_ntop (AF_INET6, &si->addr.ipv6, buf, BUFSIZ), - ifindex2ifname_vrf (si->ifindex, si->vrf_id)); + ifindex2ifname (si->ifindex, si->vrf_id)); break; } From 128c2be2a1b1592e4641b79d897c8ceebc0e8bf5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:52:59 -0500 Subject: [PATCH 014/133] bgpd, lib, zebra: Refactor ifname2ifindex to be VRF aware Signed-off-by: Donald Sharp --- bgpd/bgp_network.c | 2 +- bgpd/bgp_zebra.c | 2 +- lib/if.c | 8 +------- lib/if.h | 3 +-- zebra/zebra_routemap.c | 2 +- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index b85dcf6c41..46ae882b2e 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -617,7 +617,7 @@ bgp_connect (struct peer *peer) } if (peer->conf_if || peer->ifname) - ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname); + ifindex = ifname2ifindex (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id); if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s [Event] Connect start to %s fd %d", diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 32ad87cb7a..64c20f3184 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1509,7 +1509,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, if (!ifindex) { if (mpinfo->peer->conf_if || mpinfo->peer->ifname) - ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname); + ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname, bgp->vrf_id); else if (mpinfo->peer->nexthop.ifp) ifindex = mpinfo->peer->nexthop.ifp->ifindex; } diff --git a/lib/if.c b/lib/if.c index f4f7ad7749..6dbadb868c 100644 --- a/lib/if.c +++ b/lib/if.c @@ -256,7 +256,7 @@ ifindex2ifname (ifindex_t ifindex, vrf_id_t vrf_id) } ifindex_t -ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) +ifname2ifindex (const char *name, vrf_id_t vrf_id) { struct interface *ifp; @@ -264,12 +264,6 @@ ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) : IFINDEX_INTERNAL; } -ifindex_t -ifname2ifindex (const char *name) -{ - return ifname2ifindex_vrf (name, VRF_DEFAULT); -} - /* Interface existance check by interface name. */ struct interface * if_lookup_by_name (const char *name, vrf_id_t vrf_id) diff --git a/lib/if.h b/lib/if.h index bee783d930..7d88a9edf9 100644 --- a/lib/if.h +++ b/lib/if.h @@ -452,8 +452,7 @@ extern const char *ifindex2ifname (ifindex_t, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must make a system call. */ -extern ifindex_t ifname2ifindex(const char *ifname); -extern ifindex_t ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); +extern ifindex_t ifname2ifindex(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new (void); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 6b81f66a26..847da52952 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -189,7 +189,7 @@ route_match_interface (void *rule, struct prefix *prefix, nh_data = object; if (!nh_data || !nh_data->nexthop) return RMAP_NOMATCH; - ifindex = ifname2ifindex_vrf (ifname, nh_data->vrf_id); + ifindex = ifname2ifindex (ifname, nh_data->vrf_id); if (ifindex == 0) return RMAP_NOMATCH; if (nh_data->nexthop->ifindex == ifindex) From 631eb2fad08f47932ecb321cad87da870dc6a960 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 07:56:55 -0500 Subject: [PATCH 015/133] bgpd: Some nexthop display code needs to be VRF aware When displaying nexthops we need to be able to handle the correct VRF. Signed-off-by: Donald Sharp --- bgpd/bgp_nexthop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index c76ff2c098..9300345899 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -415,7 +415,7 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) vty_out(vty, " gate %s, if %s%s", inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4: @@ -425,13 +425,13 @@ bgp_show_nexthops (struct vty *vty, struct bgp *bgp, int detail) break; case NEXTHOP_TYPE_IFINDEX: vty_out (vty, " if %s%s", - ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; case NEXTHOP_TYPE_IPV4_IFINDEX: vty_out (vty, " gate %s, if %s%s", inet_ntop(AF_INET, &nexthop->gate.ipv4, buf, sizeof (buf)), - ifindex2ifname(nexthop->ifindex, VRF_DEFAULT), VTY_NEWLINE); + ifindex2ifname(nexthop->ifindex, bgp->vrf_id), VTY_NEWLINE); break; default: vty_out (vty, " invalid nexthop type %u%s", From 17d990c1d3fb11460cc410855c4c2bd9a5901d5a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 11 Mar 2017 19:06:09 -0500 Subject: [PATCH 016/133] zebra: Fix non-Null Terminated help string Signed-off-by: Donald Sharp --- zebra/zebra_vty.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 05c1aa274a..ffc075f43f 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -3825,7 +3825,7 @@ static_config_ipv6 (struct vty *vty) DEFUN (allow_external_route_update, allow_external_route_update_cmd, "allow-external-route-update", - "Allow FRR routes to be overwritten by external processes") + "Allow FRR routes to be overwritten by external processes\n") { allow_delete = 1; @@ -3835,7 +3835,8 @@ DEFUN (allow_external_route_update, DEFUN (no_allow_external_route_update, no_allow_external_route_update_cmd, "no allow-external-route-update", - "Allow FRR routes to be overwritten by external processes") + NO_STR + "Allow FRR routes to be overwritten by external processes\n") { allow_delete = 0; From 61cd110086ad09428ab7b0d4b66625b83fdf54eb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 10:49:21 -0400 Subject: [PATCH 017/133] ldpd: Move if_update to ldp_if_update The if_update function should be owned by lib/if.h. Move the function out of the way so we can rename lib/if.h if_update_vrf -> if_update Signed-off-by: Donald Sharp --- ldpd/interface.c | 8 ++++---- ldpd/ldpd.c | 2 +- ldpd/ldpe.c | 2 +- ldpd/ldpe.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ldpd/interface.c b/ldpd/interface.c index 8fea91b878..17b3237b37 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -206,7 +206,7 @@ if_addr_add(struct kaddr *ka) if (if_addr_lookup(&iface->addr_list, ka) == NULL) { if_addr = if_addr_new(ka); LIST_INSERT_HEAD(&iface->addr_list, if_addr, entry); - if_update(iface, if_addr->af); + ldp_if_update(iface, if_addr->af); } } } @@ -227,7 +227,7 @@ if_addr_del(struct kaddr *ka) if_addr = if_addr_lookup(&iface->addr_list, ka); if (if_addr) { LIST_REMOVE(if_addr, entry); - if_update(iface, if_addr->af); + ldp_if_update(iface, if_addr->af); free(if_addr); } } @@ -368,7 +368,7 @@ if_update_af(struct iface_af *ia, int link_ok) } void -if_update(struct iface *iface, int af) +ldp_if_update(struct iface *iface, int af) { int link_ok; @@ -386,7 +386,7 @@ if_update_all(int af) struct iface *iface; RB_FOREACH(iface, iface_head, &leconf->iface_tree) - if_update(iface, af); + ldp_if_update(iface, af); } uint16_t diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 98ea5ca53e..2263b159c7 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1360,7 +1360,7 @@ merge_iface_af(struct iface_af *ia, struct iface_af *xi) if (ia->enabled != xi->enabled) { ia->enabled = xi->enabled; if (ldpd_process == PROC_LDP_ENGINE) - if_update(ia->iface, ia->af); + ldp_if_update(ia->iface, ia->af); } ia->hello_holdtime = xi->hello_holdtime; ia->hello_interval = xi->hello_interval; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 3bb84e92a9..c9f0e19076 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -294,7 +294,7 @@ ldpe_dispatch_main(struct thread *thread) iface = if_lookup_name(leconf, kif->ifname); if (iface) { if_update_info(iface, kif); - if_update(iface, AF_UNSPEC); + ldp_if_update(iface, AF_UNSPEC); break; } diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index 22b75eb008..992fbd38d5 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -220,7 +220,7 @@ void if_update_info(struct iface *, struct kif *); struct iface_af *iface_af_get(struct iface *, int); void if_addr_add(struct kaddr *); void if_addr_del(struct kaddr *); -void if_update(struct iface *, int); +void ldp_if_update(struct iface *, int); void if_update_all(int); uint16_t if_get_hello_holdtime(struct iface_af *); uint16_t if_get_hello_interval(struct iface_af *); From f15dd9a4ee8b6148604858df9678e8b03179e204 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Mar 2017 10:55:42 -0400 Subject: [PATCH 018/133] bgpd, lib, zebra: Rename if_update_vrf -> if_update Signed-off-by: Donald Sharp --- bgpd/bgp_zebra.c | 2 +- lib/if.c | 4 ++-- lib/if.h | 4 ++-- zebra/if_netlink.c | 2 +- zebra/interface.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 64c20f3184..72bd081a7e 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -570,7 +570,7 @@ bgp_interface_vrf_update (int command, struct zclient *zclient, zebra_size_t len } } - if_update_vrf (ifp, ifp->name, strlen (ifp->name), new_vrf_id); + if_update (ifp, ifp->name, strlen (ifp->name), new_vrf_id); bgp = bgp_lookup_by_vrf_id (new_vrf_id); if (!bgp) diff --git a/lib/if.c b/lib/if.c index 6dbadb868c..ecb7463168 100644 --- a/lib/if.c +++ b/lib/if.c @@ -160,7 +160,7 @@ if_create (const char *name, int namelen, vrf_id_t vrf_id) /* Create new interface structure. */ void -if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id) +if_update (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id) { struct list *intf_list = vrf_iflist_get (vrf_id); @@ -455,7 +455,7 @@ if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty) } else { - if_update_vrf (ifp, name, namelen, vrf_id); + if_update (ifp, name, namelen, vrf_id); return ifp; } } diff --git a/lib/if.h b/lib/if.h index 7d88a9edf9..49f2a52478 100644 --- a/lib/if.h +++ b/lib/if.h @@ -390,8 +390,8 @@ struct nbr_connected /* Prototypes. */ extern int if_cmp_name_func (char *, char *); -extern void if_update_vrf (struct interface *, const char *name, int namelen, - vrf_id_t vrf_id); +extern void if_update (struct interface *, const char *name, int namelen, + vrf_id_t vrf_id); extern struct interface *if_create (const char *name, int namelen, vrf_id_t vrf_id); extern struct interface *if_lookup_by_index (ifindex_t, vrf_id_t vrf_id); diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 2572320cce..0a1cafd87e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -728,7 +728,7 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h, { /* pre-configured interface, learnt now */ if (ifp->vrf_id != vrf_id) - if_update_vrf (ifp, name, strlen(name), vrf_id); + if_update (ifp, name, strlen(name), vrf_id); } /* Update interface information. */ diff --git a/zebra/interface.c b/zebra/interface.c index 902e53dc5e..9abb54cec8 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -715,7 +715,7 @@ if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id) zebra_interface_vrf_update_del (ifp, vrf_id); /* update VRF */ - if_update_vrf (ifp, ifp->name, strlen (ifp->name), vrf_id); + if_update (ifp, ifp->name, strlen (ifp->name), vrf_id); /* Send out notification on interface VRF change. */ /* This is to issue an ADD, if needed. */ From 1bc9827622572b24c7c47656565dc1a2601d6dc5 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 22 Feb 2017 07:28:36 -0800 Subject: [PATCH 019/133] pimd: Nexthop tracking support Add pim Nexthop tracking feature 1st part where, specific RP or Source address (unicast address) register with Zebra. Once nexthop update received from Zebra for a given address, scan RP or upstream entries impacted by the change in nexthop. Reviewed By: CCR-5761, Donald Sharp Testing Done: Tested with multiple RPs and multiple *,G entries at LHR. Add new Nexthop or remove one of the link towards RP and verify RP and upstream nexthop update. similar test done at RP with multiple S,G entries to reach source. Signed-off-by: Chirag Shah --- pimd/Makefile.am | 4 +- pimd/pim_main.c | 3 +- pimd/pim_memory.c | 2 + pimd/pim_memory.h | 3 + pimd/pim_mroute.c | 2 +- pimd/pim_nht.c | 647 ++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_nht.h | 60 ++++ pimd/pim_rp.c | 53 +++- pimd/pim_rp.h | 15 + pimd/pim_rpf.c | 22 +- pimd/pim_rpf.h | 2 +- pimd/pim_upstream.c | 47 +++- pimd/pim_upstream.h | 1 + pimd/pim_zebra.c | 146 ++-------- pimd/pim_zebra.h | 6 +- pimd/pimd.c | 148 ++++++++++ pimd/pimd.h | 13 + 17 files changed, 1020 insertions(+), 154 deletions(-) create mode 100644 pimd/pim_nht.c create mode 100644 pimd/pim_nht.h diff --git a/pimd/Makefile.am b/pimd/Makefile.am index 59abd1aa30..7e1b451eab 100644 --- a/pimd/Makefile.am +++ b/pimd/Makefile.am @@ -53,7 +53,7 @@ libpim_a_SOURCES = \ pim_ssmpingd.c pim_int.c pim_rp.c \ pim_static.c pim_br.c pim_register.c pim_routemap.c \ pim_msdp.c pim_msdp_socket.c pim_msdp_packet.c \ - pim_jp_agg.c + pim_jp_agg.c pim_nht.c noinst_HEADERS = \ pim_memory.h \ @@ -65,7 +65,7 @@ noinst_HEADERS = \ pim_msg.h pim_upstream.h pim_rpf.h pim_macro.h \ pim_igmp_join.h pim_ssmpingd.h pim_int.h pim_rp.h \ pim_static.h pim_br.h pim_register.h \ - pim_msdp.h pim_msdp_socket.h pim_msdp_packet.h \ + pim_msdp.h pim_msdp_socket.h pim_msdp_packet.h pim_nht.h \ pim_jp_agg.h pimd_SOURCES = \ diff --git a/pimd/pim_main.c b/pimd/pim_main.c index a0e42aab58..07f2812725 100644 --- a/pimd/pim_main.c +++ b/pimd/pim_main.c @@ -89,6 +89,7 @@ FRR_DAEMON_INFO(pimd, PIM, .privs = &pimd_privs, ) + int main(int argc, char** argv, char** envp) { frr_preinit(&pimd_di, argc, argv); frr_opt_add("", longopts, ""); @@ -116,7 +117,7 @@ int main(int argc, char** argv, char** envp) { /* * Initializations */ - vrf_init (); + pim_vrf_init (); access_list_init(); prefix_list_init (); prefix_list_add_hook (pim_rp_prefix_list_update); diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 5af2a8203f..f46cf193bb 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -49,3 +49,5 @@ DEFINE_MTYPE(PIMD, PIM_MSDP_MG_MBR, "PIM MSDP mesh group mbr") DEFINE_MTYPE(PIMD, PIM_SEC_ADDR, "PIM secondary address") DEFINE_MTYPE(PIMD, PIM_JP_AGG_GROUP, "PIM JP AGG Group") DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") +DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") +DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index 0d5f131a4f..bd9e12f2fc 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -48,4 +48,7 @@ DECLARE_MTYPE(PIM_MSDP_MG_MBR) DECLARE_MTYPE(PIM_SEC_ADDR) DECLARE_MTYPE(PIM_JP_AGG_GROUP) DECLARE_MTYPE(PIM_JP_AGG_SOURCE) +DECLARE_MTYPE(PIM_PIM_INSTANCE) +DECLARE_MTYPE(PIM_NEXTHOP_CACHE) + #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 9401475813..a244534ab4 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -759,7 +759,7 @@ int pim_mroute_add(struct channel_oil *c_oil, const char *name) ++qpim_mroute_add_events; /* Do not install route if incoming interface is undefined. */ - if (c_oil->oil.mfcc_parent == MAXVIFS) + if (c_oil->oil.mfcc_parent >= MAXVIFS) { if (PIM_DEBUG_MROUTE) { diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c new file mode 100644 index 0000000000..c8cc187305 --- /dev/null +++ b/pimd/pim_nht.c @@ -0,0 +1,647 @@ +/* + * PIM for Quagga + * Copyright (C) 2017 Cumulus Networks, Inc. + * Chirag Shah + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#include +#include "network.h" +#include "zclient.h" +#include "stream.h" +#include "nexthop.h" +#include "if.h" +#include "hash.h" +#include "jhash.h" + +#include "pimd.h" +#include "pimd/pim_nht.h" +#include "log.h" +#include "pim_time.h" +#include "pim_oil.h" +#include "pim_ifchannel.h" +#include "pim_mroute.h" +#include "pim_zebra.h" +#include "pim_upstream.h" +#include "pim_join.h" +#include "pim_jp_agg.h" +#include "pim_zebra.h" + +/** + * pim_sendmsg_zebra_rnh -- Format and send a nexthop register/Unregister + * command to Zebra. + */ +static void +pim_sendmsg_zebra_rnh (struct zclient *zclient, struct pim_nexthop_cache *pnc, + int command) +{ + struct stream *s; + struct prefix *p; + int ret; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return; + + p = &(pnc->rpf.rpf_addr); + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, command, VRF_DEFAULT); + /* get update for all routes for a prefix */ + stream_putc (s, 0); + + stream_putw (s, PREFIX_FAMILY (p)); + stream_putc (s, p->prefixlen); + switch (PREFIX_FAMILY (p)) + { + case AF_INET: + stream_put_in_addr (s, &p->u.prefix4); + break; + case AF_INET6: + stream_put (s, &(p->u.prefix6), 16); + break; + default: + break; + } + stream_putw_at (s, 0, stream_get_endp (s)); + + ret = zclient_send_message (zclient); + if (ret < 0) + zlog_warn ("sendmsg_nexthop: zclient_send_message() failed"); + + + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (p, buf, sizeof (buf)); + zlog_debug ("%s: NHT Addr %s %sregistered with Zebra ret:%d ", + __PRETTY_FUNCTION__, buf, + (command == ZEBRA_NEXTHOP_REGISTER) ? " " : "de", ret); + } + + return; +} + +struct pim_nexthop_cache * +pim_nexthop_cache_find (struct pim_rpf *rpf) +{ + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; + + lookup.rpf.rpf_addr.family = rpf->rpf_addr.family; + lookup.rpf.rpf_addr.prefixlen = rpf->rpf_addr.prefixlen; + lookup.rpf.rpf_addr.u.prefix4.s_addr = rpf->rpf_addr.u.prefix4.s_addr; + + pnc = hash_lookup (pimg->rpf_hash, &lookup); + + return pnc; + +} + +static int +pim_rp_list_cmp (void *v1, void *v2) +{ + struct rp_info *rp1 = (struct rp_info *) v1; + struct rp_info *rp2 = (struct rp_info *) v2; + + if (rp1 == rp2) + return 0; + + if (!rp1 && rp2) + return -1; + + if (rp1 && !rp2) + return 1; + + /* + * Sort by RP IP address + */ + if (rp1->rp.rpf_addr.u.prefix4.s_addr < rp2->rp.rpf_addr.u.prefix4.s_addr) + return -1; + + if (rp1->rp.rpf_addr.u.prefix4.s_addr > rp2->rp.rpf_addr.u.prefix4.s_addr) + return 1; + + /* + * Sort by group IP address + */ + if (rp1->group.u.prefix4.s_addr < rp2->group.u.prefix4.s_addr) + return -1; + + if (rp1->group.u.prefix4.s_addr > rp2->group.u.prefix4.s_addr) + return 1; + + return -1; +} + +struct pim_nexthop_cache * +pim_nexthop_cache_add (struct pim_rpf *rpf_addr) +{ + struct pim_nexthop_cache *pnc; + + pnc = XCALLOC (MTYPE_PIM_NEXTHOP_CACHE, sizeof (struct pim_nexthop_cache)); + if (!pnc) + { + zlog_err ("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); + return NULL; + } + pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; + pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; + pnc->rpf.rpf_addr.u.prefix4.s_addr = rpf_addr->rpf_addr.u.prefix4.s_addr; + + pnc = hash_get (pimg->rpf_hash, pnc, hash_alloc_intern); + + pnc->rp_list = list_new (); + pnc->rp_list->cmp = pim_rp_list_cmp; + + pnc->upstream_list = list_new (); + pnc->upstream_list->cmp = pim_upstream_compare; + + if (PIM_DEBUG_ZEBRA) + { + char rpf_str[PREFIX_STRLEN]; + pim_addr_dump ("", &rpf_addr->rpf_addr, rpf_str, + sizeof (rpf_str)); + zlog_debug ("%s: NHT hash node, RP and UP lists allocated for %s ", + __PRETTY_FUNCTION__, rpf_str); + } + + return pnc; +} + +/* This API is used to Register an address with Zebra */ +int +pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp) +{ + struct pim_nexthop_cache *pnc = NULL; + struct pim_rpf rpf; + struct listnode *ch_node = NULL; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get (); + memset (&rpf, 0, sizeof (struct pim_rpf)); + rpf.rpf_addr.family = addr->family; + rpf.rpf_addr.prefixlen = addr->prefixlen; + rpf.rpf_addr.u.prefix4 = addr->u.prefix4; + + pnc = pim_nexthop_cache_find (&rpf); + if (!pnc) + { + if (PIM_DEBUG_ZEBRA) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); + zlog_debug ("%s: NHT New PNC allocated for addr %s ", + __PRETTY_FUNCTION__, buf); + } + pnc = pim_nexthop_cache_add (&rpf); + if (pnc) + pim_sendmsg_zebra_rnh (zclient, pnc, + ZEBRA_NEXTHOP_REGISTER); + else + { + zlog_warn ("%s: pnc node allocation failed. ", __PRETTY_FUNCTION__); + } + } + + if (rp != NULL) + { + ch_node = listnode_lookup (pnc->rp_list, rp); + if (ch_node == NULL) + { + if (PIM_DEBUG_ZEBRA) + { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump ("", &rp->rp.rpf_addr, rp_str, + sizeof (rp_str)); + zlog_debug ("%s: NHT add RP %s node to cached list", + __PRETTY_FUNCTION__, rp_str); + } + listnode_add_sort (pnc->rp_list, rp); + } + } + + if (up != NULL) + { + ch_node = listnode_lookup (pnc->upstream_list, up); + if (ch_node == NULL) + { + if (PIM_DEBUG_ZEBRA) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (addr, buf, sizeof (buf)); + zlog_debug + ("%s: NHT add upstream %s node to cached list, rpf %s", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + listnode_add_sort (pnc->upstream_list, up); + } + } + + if (CHECK_FLAG (pnc->flags, PIM_NEXTHOP_VALID)) + return 1; + + return 0; +} + +void +pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp) +{ + struct pim_nexthop_cache *pnc = NULL; + struct pim_nexthop_cache lookup; + struct zclient *zclient = NULL; + + zclient = pim_zebra_zclient_get (); + + /* Remove from RPF hash if it is the last entry */ + lookup.rpf.rpf_addr = *addr; + pnc = hash_lookup (pimg->rpf_hash, &lookup); + if (pnc) + { + if (rp) + listnode_delete (pnc->rp_list, rp); + if (up) + listnode_delete (pnc->upstream_list, up); + + if (PIM_DEBUG_ZEBRA) + zlog_debug ("%s: NHT rp_list count:%d upstream_list count:%d ", + __PRETTY_FUNCTION__, pnc->rp_list->count, + pnc->upstream_list->count); + + if (pnc->rp_list->count == 0 && pnc->upstream_list->count == 0) + { + pim_sendmsg_zebra_rnh (zclient, pnc, + ZEBRA_NEXTHOP_UNREGISTER); + + list_delete (pnc->rp_list); + list_delete (pnc->upstream_list); + + hash_release (pimg->rpf_hash, pnc); + if (pnc->nexthop) + nexthops_free (pnc->nexthop); + XFREE (MTYPE_PIM_NEXTHOP_CACHE, pnc); + } + } +} + +/* Update RP nexthop info based on Nexthop update received from Zebra.*/ +static int +pim_update_rp_nh (struct pim_nexthop_cache *pnc) +{ + struct listnode *node = NULL; + struct rp_info *rp_info = NULL; + int ret = 0; + + /*Traverse RP list and update each RP Nexthop info */ + for (ALL_LIST_ELEMENTS_RO (pnc->rp_list, node, rp_info)) + { + if (rp_info->rp.rpf_addr.u.prefix4.s_addr == INADDR_NONE) + continue; + + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, + rp_info->rp.rpf_addr.u.prefix4, 1) != 0) + { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug ("Unable to lookup nexthop for rp specified"); + ret++; + continue; + } + + if (PIM_DEBUG_TRACE) + { + char rp_str[PREFIX_STRLEN]; + pim_addr_dump ("", &rp_info->rp.rpf_addr, rp_str, + sizeof (rp_str)); + zlog_debug ("%s: NHT update nexthop for RP %s to interface %s ", + __PRETTY_FUNCTION__, rp_str, + rp_info->rp.source_nexthop.interface->name); + } + } + + if (ret) + return 0; + + return 1; + +} + +/* Update Upstream nexthop info based on Nexthop update received from Zebra.*/ +static int +pim_update_upstream_nh (struct pim_nexthop_cache *pnc) +{ + struct listnode *up_node; + struct listnode *ifnode; + struct listnode *up_nextnode; + struct listnode *node; + struct pim_upstream *up; + struct interface *ifp; + int vif_index = 0; + + for (ALL_LIST_ELEMENTS (pnc->upstream_list, up_node, up_nextnode, up)) + { + enum pim_rpf_result rpf_result; + struct pim_rpf old; + + if (up == NULL) + { + zlog_debug ("%s: Upstream node is NULL ", __PRETTY_FUNCTION__); + continue; + } + + old.source_nexthop.interface = up->rpf.source_nexthop.interface; + rpf_result = pim_rpf_update (up, &old, 0); + if (rpf_result == PIM_RPF_FAILURE) + continue; + + if (rpf_result == PIM_RPF_CHANGED) + { + + /* + * We have detected a case where we might need to rescan + * the inherited o_list so do it. + */ + if (up->channel_oil && up->channel_oil->oil_inherited_rescan) + { + pim_upstream_inherited_olist_decide (up); + up->channel_oil->oil_inherited_rescan = 0; + } + + if (up->join_state == PIM_UPSTREAM_JOINED) + { + /* + * If we come up real fast we can be here + * where the mroute has not been installed + * so install it. + */ + if (up->channel_oil && !up->channel_oil->installed) + pim_mroute_add (up->channel_oil, __PRETTY_FUNCTION__); + + /* + RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages + + Transitions from Joined State + + RPF'(S,G) changes not due to an Assert + + The upstream (S,G) state machine remains in Joined + state. Send Join(S,G) to the new upstream neighbor, which is + the new value of RPF'(S,G). Send Prune(S,G) to the old + upstream neighbor, which is the old value of RPF'(S,G). Set + the Join Timer (JT) to expire after t_periodic seconds. + */ + pim_jp_agg_switch_interface (&old, &up->rpf, up); + + pim_upstream_join_timer_restart (up, &old); + } /* up->join_state == PIM_UPSTREAM_JOINED */ + + /* FIXME can join_desired actually be changed by pim_rpf_update() + returning PIM_RPF_CHANGED ? */ + pim_upstream_update_join_desired (up); + + } /* PIM_RPF_CHANGED */ + + if (PIM_DEBUG_TRACE) + { + zlog_debug ("%s: NHT upstream %s old ifp %s new ifp %s", + __PRETTY_FUNCTION__, up->sg_str, + old.source_nexthop.interface->name, + up->rpf.source_nexthop.interface->name); + } + /* update kernel multicast forwarding cache (MFC) */ + if (up->channel_oil) + { + vif_index = + pim_if_find_vifindex_by_ifindex (up->rpf. + source_nexthop.interface-> + ifindex); + /* Pass Current selected NH vif index to mroute download */ + if (vif_index) + pim_scan_individual_oil (up->channel_oil, vif_index); + else + { + if (PIM_DEBUG_ZEBRA) + zlog_debug ("%s: NHT upstream %s channel_oil IIF %s vif_index is not valid", + __PRETTY_FUNCTION__, up->sg_str, + up->rpf.source_nexthop.interface->name); + } + } + + } /* for (pnc->upstream_list) */ + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), ifnode, ifp)) + if (ifp->info) + { + struct pim_interface *pim_ifp = ifp->info; + struct pim_iface_upstream_switch *us; + + for (ALL_LIST_ELEMENTS_RO (pim_ifp->upstream_switch_list, node, us)) + { + struct pim_rpf rpf; + rpf.source_nexthop.interface = ifp; + rpf.rpf_addr.u.prefix4 = us->address; + pim_joinprune_send (&rpf, us->us); + pim_jp_agg_clear_group (us->us); + } + } + + return 0; +} + +/* This API is used to parse Registered address nexthop update coming from Zebra */ +void +pim_parse_nexthop_update (struct zclient *zclient, int command, + vrf_id_t vrf_id) +{ + struct stream *s; + struct prefix p; + struct nexthop *nexthop; + struct nexthop *oldnh; + struct nexthop *nhlist_head = NULL; + struct nexthop *nhlist_tail = NULL; + uint32_t metric, distance; + u_char nexthop_num = 0; + int i; + struct pim_rpf rpf; + struct pim_nexthop_cache *pnc = NULL; + struct pim_neighbor *nbr = NULL; + struct interface *ifp = NULL; + + s = zclient->ibuf; + memset (&p, 0, sizeof (struct prefix)); + p.family = stream_getw (s); + p.prefixlen = stream_getc (s); + switch (p.family) + { + case AF_INET: + p.u.prefix4.s_addr = stream_get_ipv4 (s); + break; + case AF_INET6: + stream_get (&p.u.prefix6, s, 16); + break; + default: + break; + } + + if (command == ZEBRA_NEXTHOP_UPDATE) + { + rpf.rpf_addr.family = p.family; + rpf.rpf_addr.prefixlen = p.prefixlen; + rpf.rpf_addr.u.prefix4.s_addr = p.u.prefix4.s_addr; + pnc = pim_nexthop_cache_find (&rpf); + if (!pnc) + { + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&rpf.rpf_addr, buf, sizeof (buf)); + zlog_debug ("%s: NHT addr %s is not in local cached DB.", + __PRETTY_FUNCTION__, buf); + } + return; + } + } + + pnc->last_update = pim_time_monotonic_sec (); + distance = stream_getc (s); + metric = stream_getl (s); + nexthop_num = stream_getc (s); + + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&p, buf, sizeof (buf)); + zlog_debug ("%s: NHT Update for %s nexthop_num %d vrf:%d upcount %d rpcount %d", + __PRETTY_FUNCTION__, buf, nexthop_num, vrf_id, + listcount (pnc->upstream_list), listcount (pnc->rp_list)); + } + + if (nexthop_num) + { + pnc->flags |= PIM_NEXTHOP_VALID; + pnc->distance = distance; + pnc->metric = metric; + pnc->nexthop_num = nexthop_num; + + for (i = 0; i < nexthop_num; i++) + { + nexthop = nexthop_new (); + nexthop->type = stream_getc (s); + switch (nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); + nexthop->ifindex = stream_getl (s); + break; + case NEXTHOP_TYPE_IFINDEX: + nexthop->ifindex = stream_getl (s); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: + nexthop->gate.ipv4.s_addr = stream_get_ipv4 (s); + nexthop->ifindex = stream_getl (s); + break; + case NEXTHOP_TYPE_IPV6: + stream_get (&nexthop->gate.ipv6, s, 16); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + stream_get (&nexthop->gate.ipv6, s, 16); + nexthop->ifindex = stream_getl (s); + nbr = + pim_neighbor_find_if (if_lookup_by_index_vrf + (nexthop->ifindex, VRF_DEFAULT)); + /* Overwrite with Nbr address as NH addr */ + if (nbr) + nexthop->gate.ipv4 = nbr->source_addr; + + break; + default: + /* do nothing */ + break; + } + + if (PIM_DEBUG_TRACE) + { + char p_str[PREFIX2STR_BUFFER]; + prefix2str (&p, p_str, sizeof (p_str)); + zlog_debug ("%s: NHT addr %s %d-nhop via %s type %d", + __PRETTY_FUNCTION__, p_str, i + 1, + inet_ntoa (nexthop->gate.ipv4), nexthop->type); + } + + ifp = if_lookup_by_index (nexthop->ifindex); + if (!ifp) + { + if (PIM_DEBUG_ZEBRA) + { + char buf[NEXTHOP_STRLEN]; + zlog_debug("%s: could not find interface for ifindex %d (addr %s)", + __PRETTY_FUNCTION__, + nexthop->ifindex, nexthop2str (nexthop, buf, sizeof (buf))); + } + nexthop_free (nexthop); + continue; + } + + if (!ifp->info) + { + if (PIM_DEBUG_ZEBRA) + { + char buf[NEXTHOP_STRLEN]; + zlog_debug + ("%s: multicast not enabled on input interface %s (ifindex=%d, addr %s)", + __PRETTY_FUNCTION__, ifp->name, nexthop->ifindex, + nexthop2str (nexthop, buf, sizeof (buf))); + } + nexthop_free (nexthop); + continue; + } + + if (nhlist_tail) + { + nhlist_tail->next = nexthop; + nhlist_tail = nexthop; + } + else + { + nhlist_tail = nexthop; + nhlist_head = nexthop; + } + + for (oldnh = pnc->nexthop; oldnh; oldnh = oldnh->next) + if (nexthop_same_no_recurse (oldnh, nexthop)) + break; + } + /* Reset existing pnc->nexthop before assigning new list */ + nexthops_free (pnc->nexthop); + pnc->nexthop = nhlist_head; + } + else + { + pnc->flags &= ~PIM_NEXTHOP_VALID; + pnc->nexthop_num = nexthop_num; + nexthops_free (pnc->nexthop); + pnc->nexthop = NULL; + } + + pim_rpf_set_refresh_time (); + + if (listcount (pnc->rp_list)) + pim_update_rp_nh (pnc); + if (listcount (pnc->upstream_list)) + pim_update_upstream_nh (pnc); + +} diff --git a/pimd/pim_nht.h b/pimd/pim_nht.h new file mode 100644 index 0000000000..6e6602b3be --- /dev/null +++ b/pimd/pim_nht.h @@ -0,0 +1,60 @@ +/* + * PIM for Quagga + * Copyright (C) 2017 Cumulus Networks, Inc. + * Chirag Shah + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +#ifndef PIM_NHT_H +#define PIM_NHT_H + +#include "prefix.h" +#include +#include "zclient.h" +#include "vrf.h" + +#include "pimd.h" +#include "pim_rp.h" +#include "pim_rpf.h" + +/* PIM nexthop cache value structure. */ +struct pim_nexthop_cache +{ + struct pim_rpf rpf; + /* IGP route's metric. */ + u_int32_t metric; + uint32_t distance; + /* Nexthop number and nexthop linked list. */ + u_char nexthop_num; + struct nexthop *nexthop; + int64_t last_update; + u_int16_t flags; +#define PIM_NEXTHOP_VALID (1 << 0) + + struct list *rp_list; + struct list *upstream_list; +}; + +void pim_parse_nexthop_update (struct zclient *zclient, int command, + vrf_id_t vrf_id); +int pim_find_or_track_nexthop (struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp); +void pim_delete_tracked_nexthop (struct prefix *addr, struct pim_upstream *up, + struct rp_info *rp); +struct pim_nexthop_cache *pim_nexthop_cache_add (struct pim_rpf *rpf_addr); +struct pim_nexthop_cache *pim_nexthop_cache_find (struct pim_rpf *rpf); + +#endif diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index dc19002a42..de30116ed4 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -42,14 +42,8 @@ #include "pim_memory.h" #include "pim_iface.h" #include "pim_msdp.h" +#include "pim_nht.h" -struct rp_info -{ - struct prefix group; - struct pim_rpf rp; - int i_am_rp; - char *plist; -}; static struct list *qpim_rp_list = NULL; static struct rp_info *tail = NULL; @@ -305,6 +299,7 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) struct listnode *node, *nnode; struct rp_info *tmp_rp_info; char buffer[BUFSIZ]; + struct prefix nht_p; rp_info = XCALLOC (MTYPE_PIM_RP, sizeof (*rp_info)); if (!rp_info) @@ -401,6 +396,19 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) rp_all->rp.rpf_addr = rp_info->rp.rpf_addr; XFREE (MTYPE_PIM_RP, rp_info); + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_all->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + zlog_debug ("%s: NHT Register rp_all addr %s with NHT ", + __PRETTY_FUNCTION__, buf); + } + pim_find_or_track_nexthop (&nht_p, NULL, rp_all); + if (pim_nexthop_lookup (&rp_all->rp.source_nexthop, rp_all->rp.rpf_addr.u.prefix4, 1) != 0) return PIM_RP_NO_PATH; @@ -448,11 +456,23 @@ pim_rp_new (const char *rp, const char *group_range, const char *plist) listnode_add_sort (qpim_rp_list, rp_info); + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + zlog_debug ("%s: NHT Register RP addr %s with Zebra ", __PRETTY_FUNCTION__, buf); + } + pim_find_or_track_nexthop (&nht_p, NULL, rp_info); + if (pim_nexthop_lookup (&rp_info->rp.source_nexthop, rp_info->rp.rpf_addr.u.prefix4, 1) != 0) return PIM_RP_NO_PATH; pim_rp_check_interfaces (rp_info); - pim_rp_refresh_group_to_rp_mapping(); + pim_rp_refresh_group_to_rp_mapping (); return PIM_SUCCESS; } @@ -465,6 +485,7 @@ pim_rp_del (const char *rp, const char *group_range, const char *plist) struct rp_info *rp_info; struct rp_info *rp_all; int result; + struct prefix nht_p; if (group_range == NULL) result = str2prefix ("224.0.0.0/4", &group); @@ -492,6 +513,18 @@ pim_rp_del (const char *rp, const char *group_range, const char *plist) rp_info->plist = NULL; } + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = rp_info->rp.rpf_addr.u.prefix4; + if (PIM_DEBUG_PIM_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + zlog_debug ("%s: Deregister RP addr %s with NHT ", __PRETTY_FUNCTION__, buf); + } + pim_delete_tracked_nexthop (&nht_p, NULL, rp_info); + str2prefix ("224.0.0.0/4", &g_all); rp_all = pim_rp_find_match_group (&g_all); @@ -504,7 +537,7 @@ pim_rp_del (const char *rp, const char *group_range, const char *plist) } listnode_delete (qpim_rp_list, rp_info); - pim_rp_refresh_group_to_rp_mapping(); + pim_rp_refresh_group_to_rp_mapping (); return PIM_SUCCESS; } @@ -754,7 +787,7 @@ pim_rp_check_is_my_ip_address (struct in_addr group, struct in_addr dest_addr) if (if_lookup_exact_address (&dest_addr, AF_INET)) return 1; - + return 0; } diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h index b32228ed49..e5580cfa63 100644 --- a/pimd/pim_rp.h +++ b/pimd/pim_rp.h @@ -21,6 +21,21 @@ #ifndef PIM_RP_H #define PIM_RP_H +#include +#include "prefix.h" +#include "vty.h" +#include "plist.h" +#include "pim_iface.h" +#include "pim_rpf.h" + +struct rp_info +{ + struct prefix group; + struct pim_rpf rp; + int i_am_rp; + char *plist; +}; + void pim_rp_init (void); void pim_rp_free (void); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index ff8a6054cf..3d278f12a7 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -34,11 +34,12 @@ #include "pim_zlookup.h" #include "pim_ifchannel.h" #include "pim_time.h" +#include "pim_nht.h" static long long last_route_change_time = -1; long long nexthop_lookups_avoided = 0; -static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up); +static struct in_addr pim_rpf_find_rpf_addr (struct pim_upstream *up); void pim_rpf_set_refresh_time (void) @@ -184,14 +185,31 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1, (nh1->mrib_route_metric != nh2->mrib_route_metric); } -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old) +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new) { struct pim_rpf *rpf = &up->rpf; struct pim_rpf saved; + struct prefix nht_p; saved.source_nexthop = rpf->source_nexthop; saved.rpf_addr = rpf->rpf_addr; + if (is_new) + { + if (PIM_DEBUG_ZEBRA) + { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", up->upstream_addr, source_str, sizeof(source_str)); + zlog_debug ("%s: NHT Register upstream %s addr %s with Zebra.", + __PRETTY_FUNCTION__, up->sg_str, source_str); + } + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr; + pim_find_or_track_nexthop (&nht_p, up, NULL); + } + if (pim_nexthop_lookup(&rpf->source_nexthop, up->upstream_addr, !PIM_UPSTREAM_FLAG_TEST_FHR (up->flags) && diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index f4a987793e..85fb1ed897 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -64,7 +64,7 @@ struct pim_upstream; extern long long nexthop_lookups_avoided; int pim_nexthop_lookup(struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); -enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old); +enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, uint8_t is_new); int pim_rpf_addr_is_inaddr_none (struct pim_rpf *rpf); int pim_rpf_addr_is_inaddr_any (struct pim_rpf *rpf); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 19f7d3336c..183db532ba 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -52,6 +52,7 @@ #include "pim_register.h" #include "pim_msdp.h" #include "pim_jp_agg.h" +#include "pim_nht.h" struct hash *pim_upstream_hash = NULL; struct list *pim_upstream_list = NULL; @@ -142,6 +143,7 @@ pim_upstream_find_parent (struct pim_upstream *child) void pim_upstream_free(struct pim_upstream *up) { XFREE(MTYPE_PIM_UPSTREAM, up); + up = NULL; } static void upstream_channel_oil_detach(struct pim_upstream *up) @@ -156,6 +158,7 @@ void pim_upstream_del(struct pim_upstream *up, const char *name) { bool notify_msdp = false; + struct prefix nht_p; if (PIM_DEBUG_TRACE) zlog_debug ("%s(%s): Delete %s ref count: %d", @@ -209,10 +212,25 @@ pim_upstream_del(struct pim_upstream *up, const char *name) listnode_delete (pim_upstream_list, up); hash_release (pim_upstream_hash, up); - if (notify_msdp) { - pim_msdp_up_del(&up->sg); - } - pim_upstream_free(up); + if (notify_msdp) + { + pim_msdp_up_del (&up->sg); + } + + /* Deregister addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + if (PIM_DEBUG_TRACE) + { + char buf[PREFIX2STR_BUFFER]; + prefix2str (&nht_p, buf, sizeof (buf)); + zlog_debug ("%s: Deregister upstream %s upstream addr %s with NHT ", + __PRETTY_FUNCTION__, up->sg_str, buf); + } + pim_delete_tracked_nexthop (&nht_p, up, NULL); + + pim_upstream_free (up); } void @@ -517,7 +535,7 @@ pim_upstream_switch(struct pim_upstream *up, } } -static int +int pim_upstream_compare (void *arg1, void *arg2) { const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; @@ -548,11 +566,12 @@ pim_upstream_new (struct prefix_sg *sg, struct pim_upstream *up; up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); - if (!up) { - zlog_err("%s: PIM XCALLOC(%zu) failure", + if (!up) + { + zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, sizeof(*up)); - return NULL; - } + return NULL; + } up->sg = *sg; pim_str_sg_set (sg, up->sg_str); @@ -600,7 +619,7 @@ pim_upstream_new (struct prefix_sg *sg, if (up->sg.src.s_addr != INADDR_ANY) wheel_add_item (pim_upstream_sg_wheel, up); - rpf_result = pim_rpf_update(up, NULL); + rpf_result = pim_rpf_update(up, NULL, 1); if (rpf_result == PIM_RPF_FAILURE) { if (PIM_DEBUG_TRACE) zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, @@ -631,7 +650,11 @@ pim_upstream_new (struct prefix_sg *sg, listnode_add_sort(pim_upstream_list, up); if (PIM_DEBUG_TRACE) - zlog_debug ("%s: Created Upstream %s", __PRETTY_FUNCTION__, up->sg_str); + { + zlog_debug ("%s: Created Upstream %s upstream_addr %s", + __PRETTY_FUNCTION__, up->sg_str, + inet_ntoa (up->upstream_addr)); + } return up; } @@ -1403,7 +1426,7 @@ pim_upstream_find_new_rpf (void) if (PIM_DEBUG_TRACE) zlog_debug ("Upstream %s without a path to send join, checking", up->sg_str); - pim_rpf_update (up, NULL); + pim_rpf_update (up, NULL, 1); } } } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index b191fe9404..0bc4c4410a 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -183,4 +183,5 @@ void pim_upstream_init (void); void pim_upstream_terminate (void); void join_timer_start (struct pim_upstream *up); +int pim_upstream_compare (void *arg1, void *arg2); #endif /* PIM_UPSTREAM_H */ diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 1db6616c58..ad4ef64eda 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -45,6 +45,7 @@ #include "pim_rp.h" #include "pim_igmpv3.h" #include "pim_jp_agg.h" +#include "pim_nht.h" #undef PIM_DEBUG_IFADDR_DUMP #define PIM_DEBUG_IFADDR_DUMP @@ -375,8 +376,8 @@ static void scan_upstream_rpf_cache() old.source_nexthop.interface = up->rpf.source_nexthop.interface; old.source_nexthop.nbr = up->rpf.source_nexthop.nbr; - rpf_result = pim_rpf_update(up, &old); - zlog_debug ("Looking at upstream: %s %d", up->sg_str, rpf_result); + rpf_result = pim_rpf_update(up, &old, 0); + if (rpf_result == PIM_RPF_FAILURE) continue; @@ -444,7 +445,7 @@ static void scan_upstream_rpf_cache() } void -pim_scan_individual_oil (struct channel_oil *c_oil) +pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index) { struct in_addr vif_source; int input_iface_vif_index; @@ -453,7 +454,10 @@ pim_scan_individual_oil (struct channel_oil *c_oil) if (!pim_rp_set_upstream_addr (&vif_source, c_oil->oil.mfcc_origin, c_oil->oil.mfcc_mcastgrp)) return; - input_iface_vif_index = fib_lookup_if_vif_index (vif_source); + if (in_vif_index) + input_iface_vif_index = in_vif_index; + else + input_iface_vif_index = fib_lookup_if_vif_index (vif_source); if (input_iface_vif_index < 1) { if (PIM_DEBUG_ZEBRA) @@ -548,7 +552,7 @@ void pim_scan_oil() ++qpim_scan_oil_events; for (ALL_LIST_ELEMENTS(pim_channel_oil_list, node, nextnode, c_oil)) - pim_scan_individual_oil (c_oil); + pim_scan_individual_oil (c_oil, 0); } static int on_rpf_cache_refresh(struct thread *t) @@ -594,124 +598,11 @@ void sched_rpf_cache_refresh(void) 0, qpim_rpf_cache_refresh_delay_msec); } -static int redist_read_ipv4_route(int command, struct zclient *zclient, - zebra_size_t length, vrf_id_t vrf_id) +static int +pim_zebra_nexthop_update (int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) { - struct stream *s; - struct zapi_ipv4 api; - ifindex_t ifindex; - struct in_addr nexthop; - struct prefix_ipv4 p; - int min_len = 4; - - if (length < min_len) { - zlog_warn("%s %s: short buffer: length=%d min=%d", - __FILE__, __PRETTY_FUNCTION__, - length, min_len); - return -1; - } - - s = zclient->ibuf; - ifindex = 0; - nexthop.s_addr = 0; - - /* Type, flags, message. */ - api.type = stream_getc(s); - api.instance = stream_getw (s); - api.flags = stream_getl(s); - api.message = stream_getc(s); - - /* IPv4 prefix length. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - p.prefixlen = stream_getc(s); - - min_len += - PSIZE(p.prefixlen) + - CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? 5 : 0 + - CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? 5 : 0 + - CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? 1 : 0 + - CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? 4 : 0; - - if (PIM_DEBUG_ZEBRA) { - zlog_debug("%s %s: length=%d min_len=%d flags=%s%s%s%s", - __FILE__, __PRETTY_FUNCTION__, - length, min_len, - CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) ? "nh" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX) ? " ifi" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? " dist" : "", - CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? " metr" : ""); - } - - /* IPv4 prefix. */ - stream_get(&p.prefix, s, PSIZE(p.prefixlen)); - - /* Nexthop, ifindex, distance, metric. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { - api.nexthop_num = stream_getc(s); - nexthop.s_addr = stream_get_ipv4(s); - } - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_IFINDEX)) { - api.ifindex_num = stream_getc(s); - ifindex = stream_getl(s); - } - - api.distance = CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? - stream_getc(s) : - 0; - - api.metric = CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? - stream_getl(s) : - 0; - - if (CHECK_FLAG (api.message, ZAPI_MESSAGE_TAG)) - api.tag = stream_getl (s); - else - api.tag = 0; - - switch (command) { - case ZEBRA_REDISTRIBUTE_IPV4_ADD: - if (PIM_DEBUG_ZEBRA) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("%s: add %s %s/%d " - "nexthop %s ifindex %d metric%s %u distance%s %u", - __PRETTY_FUNCTION__, - zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - ifindex, - CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss", - api.metric, - CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss", - api.distance); - } - break; - case ZEBRA_REDISTRIBUTE_IPV4_DEL: - if (PIM_DEBUG_ZEBRA) { - char buf[2][INET_ADDRSTRLEN]; - zlog_debug("%s: delete %s %s/%d " - "nexthop %s ifindex %d metric%s %u distance%s %u", - __PRETTY_FUNCTION__, - zebra_route_string(api.type), - inet_ntop(AF_INET, &p.prefix, buf[0], sizeof(buf[0])), - p.prefixlen, - inet_ntop(AF_INET, &nexthop, buf[1], sizeof(buf[1])), - ifindex, - CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC) ? "-recv" : "-miss", - api.metric, - CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE) ? "-recv" : "-miss", - api.distance); - } - break; - default: - zlog_warn("%s: unknown command=%d", __PRETTY_FUNCTION__, command); - return -1; - } - - sched_rpf_cache_refresh(); - - pim_rp_setup (); + pim_parse_nexthop_update (zclient, command, vrf_id); return 0; } @@ -742,8 +633,7 @@ void pim_zebra_init(void) zclient->interface_down = pim_zebra_if_state_down; zclient->interface_address_add = pim_zebra_if_address_add; zclient->interface_address_delete = pim_zebra_if_address_del; - zclient->redistribute_route_ipv4_add = redist_read_ipv4_route; - zclient->redistribute_route_ipv4_del = redist_read_ipv4_route; + zclient->nexthop_update = pim_zebra_nexthop_update; zclient_init(zclient, ZEBRA_ROUTE_PIM, 0); if (PIM_DEBUG_PIM_TRACE) { @@ -1262,3 +1152,11 @@ pim_zebra_zclient_update (struct vty *vty) vty_out(vty, "%s", VTY_NEWLINE); } } + +struct zclient *pim_zebra_zclient_get (void) +{ + if (zclient) + return zclient; + else + return NULL; +} diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 751a7be25d..5dc06a4a19 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -21,13 +21,16 @@ #ifndef PIM_ZEBRA_H #define PIM_ZEBRA_H +#include +#include "zclient.h" + #include "pim_igmp.h" #include "pim_ifchannel.h" void pim_zebra_init(void); void pim_zebra_zclient_update (struct vty *vty); -void pim_scan_individual_oil (struct channel_oil *c_oil); +void pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index); void pim_scan_oil(void); void igmp_anysource_forward_start(struct igmp_group *group); @@ -40,4 +43,5 @@ void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); void sched_rpf_cache_refresh(void); +struct zclient *pim_zebra_zclient_get (void); #endif /* PIM_ZEBRA_H */ diff --git a/pimd/pimd.c b/pimd/pimd.c index c8a0efc401..b67544b28e 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -26,6 +26,8 @@ #include "prefix.h" #include "vty.h" #include "plist.h" +#include "hash.h" +#include "jhash.h" #include "pimd.h" #include "pim_cmd.h" @@ -40,6 +42,7 @@ #include "pim_static.h" #include "pim_rp.h" #include "pim_zlookup.h" +#include "pim_nht.h" const char *const PIM_ALL_SYSTEMS = MCAST_ALL_SYSTEMS; const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS; @@ -71,10 +74,127 @@ unsigned int qpim_keep_alive_time = PIM_KEEPALIVE_PERIOD; signed int qpim_rp_keep_alive_time = 0; int64_t qpim_nexthop_lookups = 0; int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS; +struct pim_instance *pimg = NULL; int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT; int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT; +static struct pim_instance *pim_instance_init (vrf_id_t vrf_id, afi_t afi); +static void pim_instance_terminate (void); + +static int +pim_vrf_new (struct vrf *vrf) +{ + zlog_debug ("VRF Created: %s(%d)", vrf->name, vrf->vrf_id); + return 0; +} + +static int +pim_vrf_delete (struct vrf *vrf) +{ + zlog_debug ("VRF Deletion: %s(%d)", vrf->name, vrf->vrf_id); + return 0; +} + +static int +pim_vrf_enable (struct vrf *vrf) +{ + + if (!vrf) // unexpected + return -1; + + if (vrf->vrf_id == VRF_DEFAULT) + { + pimg = pim_instance_init (VRF_DEFAULT, AFI_IP); + if (pimg == NULL) + zlog_err ("%s %s: pim class init failure ", __FILE__, + __PRETTY_FUNCTION__); + } + return 0; +} + +static int +pim_vrf_disable (struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return 0; + + if (vrf->vrf_id == VRF_DEFAULT) + pim_instance_terminate (); + + /* Note: This is a callback, the VRF will be deleted by the caller. */ + return 0; +} + +void +pim_vrf_init (void) +{ + vrf_add_hook (VRF_NEW_HOOK, pim_vrf_new); + vrf_add_hook (VRF_ENABLE_HOOK, pim_vrf_enable); + vrf_add_hook (VRF_DISABLE_HOOK, pim_vrf_disable); + vrf_add_hook (VRF_DELETE_HOOK, pim_vrf_delete); + + vrf_init (); +} + +static void +pim_vrf_terminate (void) +{ + vrf_add_hook (VRF_NEW_HOOK, NULL); + vrf_add_hook (VRF_ENABLE_HOOK, NULL); + vrf_add_hook (VRF_DISABLE_HOOK, NULL); + vrf_add_hook (VRF_DELETE_HOOK, NULL); + + vrf_terminate (); +} + +/* Key generate for pim->rpf_hash */ +static unsigned int +pim_rpf_hash_key (void *arg) +{ + struct pim_nexthop_cache *r = (struct pim_nexthop_cache *) arg; + + return jhash_1word (r->rpf.rpf_addr.u.prefix4.s_addr, 0); +} + +/* Compare pim->rpf_hash node data */ +static int +pim_rpf_equal (const void *arg1, const void *arg2) +{ + const struct pim_nexthop_cache *r1 = + (const struct pim_nexthop_cache *) arg1; + const struct pim_nexthop_cache *r2 = + (const struct pim_nexthop_cache *) arg2; + + return prefix_same (&r1->rpf.rpf_addr, &r2->rpf.rpf_addr); +} + +/* Cleanup pim->rpf_hash each node data */ +static void +pim_rp_list_hash_clean (void *data) +{ + struct pim_nexthop_cache *pnc; + + pnc = (struct pim_nexthop_cache *) data; + if (pnc->rp_list->count) + list_delete_all_node (pnc->rp_list); + if (pnc->upstream_list->count) + list_delete_all_node (pnc->upstream_list); +} + +static void +pim_instance_terminate (void) +{ + /* Traverse and cleanup rpf_hash */ + if (pimg && pimg->rpf_hash) + { + hash_clean (pimg->rpf_hash, (void *) pim_rp_list_hash_clean); + hash_free (pimg->rpf_hash); + } + + XFREE (MTYPE_PIM_PIM_INSTANCE, pimg); +} + static void pim_free() { pim_ssmpingd_destroy(); @@ -96,6 +216,27 @@ static void pim_free() zprivs_terminate(&pimd_privs); } +static struct pim_instance * +pim_instance_init (vrf_id_t vrf_id, afi_t afi) +{ + struct pim_instance *pim; + + pim = XCALLOC (MTYPE_PIM_PIM_INSTANCE, sizeof (struct pim_instance)); + if (!pim) + return NULL; + + pim->vrf_id = vrf_id; + pim->afi = afi; + + pim->rpf_hash = hash_create_size (256, pim_rpf_hash_key, pim_rpf_equal); + + if (PIM_DEBUG_ZEBRA) + zlog_debug ("%s: NHT rpf hash init ", __PRETTY_FUNCTION__); + + + return pim; +} + void pim_init() { qpim_rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; @@ -147,4 +288,11 @@ void pim_init() void pim_terminate() { pim_free(); + + /* reverse prefix_list_init */ + prefix_list_add_hook (NULL); + prefix_list_delete_hook (NULL); + prefix_list_reset (); + + pim_vrf_terminate (); } diff --git a/pimd/pimd.h b/pimd/pimd.h index 0906016300..b3bdd9e243 100644 --- a/pimd/pimd.h +++ b/pimd/pimd.h @@ -22,6 +22,8 @@ #define PIMD_H #include +#include "zebra.h" +#include "libfrr.h" #include "pim_str.h" #include "pim_memory.h" @@ -232,10 +234,21 @@ extern int32_t qpim_register_probe_time; #define PIM_DONT_DEBUG_MSDP_PACKETS (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS) #define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL) +/* Per VRF PIM DB */ +struct pim_instance +{ + afi_t afi; + vrf_id_t vrf_id; + struct hash *rpf_hash; +}; + +extern struct pim_instance *pimg; //Pim Global Instance + void pim_init(void); void pim_terminate(void); extern void pim_route_map_init (void); extern void pim_route_map_terminate(void); +void pim_vrf_init (void); #endif /* PIMD_H */ From 2f89147c6b521f5c45c2afaf555d298ee2a5e1ef Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 10:23:40 -0500 Subject: [PATCH 020/133] pimd: Add additional output to 'show ip pim state json' Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 465c368f43..a85de0aabc 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1422,6 +1422,14 @@ pim_show_state(struct vty *vty, const char *src_or_group, const char *group, u_c if (!json_ifp_in) { json_ifp_in = json_object_new_object(); json_object_object_add(json_source, in_ifname, json_ifp_in); + json_object_int_add (json_source, "Installed", c_oil->installed); + json_object_int_add (json_source, "RefCount", c_oil->oil_ref_count); + json_object_int_add (json_source, "OilListSize", c_oil->oil_size); + json_object_int_add (json_source, "OilRescan", c_oil->oil_inherited_rescan); + json_object_int_add (json_source, "LastUsed", c_oil->cc.lastused); + json_object_int_add (json_source, "PacketCount", c_oil->cc.pktcnt); + json_object_int_add (json_source, "ByteCount", c_oil->cc.bytecnt); + json_object_int_add (json_source, "WrongInterface", c_oil->cc.wrong_if); } } else { vty_out(vty, "%-9d %-15s %-15s %-7s ", From e711cd3cece039d91a59834e6a9396f878b99c56 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 10:26:00 -0500 Subject: [PATCH 021/133] pimd: Carefully Reconstruct FHR state when interface bounces When an interface bounces and we receive a packet before pim has a chance to fully bring the 'struct pim_usptream' back up correctly, first check to see if we already have an associated data structure before creating it again. This removes a case where both the c_oil and up ref counts were being incremented and never removed properly. Signed-off-by: Donald Sharp --- pimd/pim_mroute.c | 30 ++++++++++-------------------- pimd/pim_upstream.c | 23 +++++++++++++++++++++++ pimd/pim_upstream.h | 3 +++ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index a244534ab4..04b6a4c697 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -118,7 +118,6 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg struct pim_upstream *up; struct pim_rpf *rpg; struct prefix_sg sg; - struct channel_oil *oil; rpg = RP(msg->im_dst); /* @@ -153,25 +152,17 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg sg.src = msg->im_src; sg.grp = msg->im_dst; - oil = pim_channel_oil_add (&sg, pim_ifp->mroute_vif_index); - if (!oil) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failure to add channel oil for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); + up = pim_upstream_find_or_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); + if (!up) + { + if (PIM_DEBUG_MROUTE) + { + zlog_debug("%s: Failure to add upstream information for %s", + __PRETTY_FUNCTION__, + pim_str_sg_dump (&sg)); + } + return 0; } - return 0; - } - - up = pim_upstream_add (&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR, __PRETTY_FUNCTION__); - if (!up) { - if (PIM_DEBUG_MROUTE) { - zlog_debug("%s: Failure to add upstream information for %s", - __PRETTY_FUNCTION__, - pim_str_sg_dump (&sg)); - } - return 0; - } /* * I moved this debug till after the actual add because @@ -185,7 +176,6 @@ pim_mroute_msg_nocache (int fd, struct interface *ifp, const struct igmpmsg *msg PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags); pim_upstream_keep_alive_timer_start (up, qpim_keep_alive_time); - up->channel_oil = oil; up->channel_oil->cc.pktcnt++; PIM_UPSTREAM_FLAG_SET_FHR(up->flags); pim_channel_add_oif (up->channel_oil, pim_regiface, PIM_OIF_FLAG_PROTO_PIM); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 183db532ba..b29e71a334 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -669,6 +669,29 @@ struct pim_upstream *pim_upstream_find(struct prefix_sg *sg) return up; } +struct pim_upstream * +pim_upstream_find_or_add(struct prefix_sg *sg, + struct interface *incoming, + int flags, const char *name) +{ + struct pim_upstream *up; + + up = pim_upstream_find(sg); + + if (up) + { + if (!(up->flags & flags)) + { + up->flags |= flags; + up->ref_count++; + } + } + else + up = pim_upstream_add (sg, incoming, flags, name); + + return up; +} + static void pim_upstream_ref(struct pim_upstream *up, int flags) { up->flags |= flags; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 0bc4c4410a..21c78021e5 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -129,6 +129,9 @@ struct hash *pim_upstream_hash; void pim_upstream_free(struct pim_upstream *up); struct pim_upstream *pim_upstream_find (struct prefix_sg *sg); +struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, + struct interface *ifp, int flags, + const char *name); struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct interface *ifp, int flags, const char *name); From ec97ac659388fb0fae4aceb77598d355502f21c8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 14 Mar 2017 07:58:17 -0400 Subject: [PATCH 022/133] pimd: Remember to delete reference to upstream in failure When creating the pim upstream data structure, if we fail to create remove the reference we saved to it on the side in the pnc code. Signed-off-by: Donald Sharp --- pimd/pim_upstream.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index b29e71a334..06f0c5c03c 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -621,10 +621,17 @@ pim_upstream_new (struct prefix_sg *sg, rpf_result = pim_rpf_update(up, NULL, 1); if (rpf_result == PIM_RPF_FAILURE) { + struct prefix nht_p; + if (PIM_DEBUG_TRACE) zlog_debug ("%s: Attempting to create upstream(%s), Unable to RPF for source", __PRETTY_FUNCTION__, up->sg_str); + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = up->upstream_addr; + pim_delete_tracked_nexthop (&nht_p, up, NULL); + if (up->parent) { listnode_delete (up->parent->sources, up); From d0db90bf4453b635c1fe4935fcbefd0918b4fd51 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 10 Mar 2017 15:01:11 -0500 Subject: [PATCH 023/133] pimd: Cleanup JP Agg a bit more The J/P Aggregation + the NHT tracking code was not playing nicely together 1) Clean up pim_upstream ref counting to keep a bit better track of it. 2) When we delete pim_upstream zero it out to hopefully catch issues faster in the future 3) Clean up J/P Agg source list a bit better to keep order Signed-off-by: Donald Sharp --- pimd/pim_jp_agg.c | 43 ++++++++++++++++++++++++++++++++++--------- pimd/pim_upstream.c | 12 +++++++++--- pimd/pim_upstream.h | 3 ++- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 8d4510324c..4c1c0c7de1 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -40,6 +40,8 @@ pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag) static void pim_jp_agg_src_free (struct pim_jp_sources *js) { + struct pim_upstream *up = js->up; + /* * When we are being called here, we know * that the neighbor is going away start @@ -47,7 +49,11 @@ pim_jp_agg_src_free (struct pim_jp_sources *js) * pick this shit back up when the * nbr comes back alive */ - join_timer_start(js->up); + + up = pim_upstream_del (up, __PRETTY_FUNCTION__); + + if (up) + join_timer_start(js->up); XFREE (MTYPE_PIM_JP_AGG_SOURCE, js); } @@ -72,6 +78,12 @@ pim_jp_agg_src_cmp (void *arg1, void *arg2) const struct pim_jp_sources *js1 = (const struct pim_jp_sources *)arg1; const struct pim_jp_sources *js2 = (const struct pim_jp_sources *)arg2; + if (js1->is_join && !js2->is_join) + return -1; + + if (!js1->is_join && js2->is_join) + return 1; + if (js1->up->sg.src.s_addr < js2->up->sg.src.s_addr) return -1; @@ -99,6 +111,7 @@ pim_jp_agg_clear_group (struct list *group) { for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) { + pim_upstream_del (js->up, __PRETTY_FUNCTION__); listnode_delete(jag->sources, js); XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); } @@ -126,7 +139,7 @@ pim_jp_agg_get_interface_upstream_switch_list (struct pim_rpf *rpf) pius = XCALLOC(MTYPE_PIM_JP_AGG_GROUP, sizeof (struct pim_iface_upstream_switch)); pius->address.s_addr = rpf->rpf_addr.u.prefix4.s_addr; pius->us = list_new(); - listnode_add (pim_ifp->upstream_switch_list, pius); + listnode_add_sort (pim_ifp->upstream_switch_list, pius); } return pius; @@ -154,9 +167,12 @@ pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) break; } - listnode_delete(jag->sources, js); - - XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + if (js) + { + pim_upstream_del (up, __PRETTY_FUNCTION__); + listnode_delete(jag->sources, js); + XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); + } if (jag->sources->count == 0) { @@ -185,7 +201,7 @@ pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) jag->sources = list_new(); jag->sources->cmp = pim_jp_agg_src_cmp; jag->sources->del = (void (*)(void *))pim_jp_agg_src_free; - listnode_add (group, jag); + listnode_add_sort (group, jag); } for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) @@ -197,11 +213,20 @@ pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) if (!js) { js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, sizeof (struct pim_jp_sources)); + pim_upstream_ref (up, 0); js->up = up; - listnode_add (jag->sources, js); + js->is_join = is_join; + listnode_add_sort (jag->sources, js); + } + else + { + if (js->is_join != is_join) + { + listnode_delete(jag->sources, js); + js->is_join = is_join; + listnode_add_sort (jag->sources, js); + } } - - js->is_join = is_join; } void diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 06f0c5c03c..8ea9e3d688 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -142,6 +142,7 @@ pim_upstream_find_parent (struct pim_upstream *child) void pim_upstream_free(struct pim_upstream *up) { + memset (up, 0, sizeof (struct pim_upstream)); XFREE(MTYPE_PIM_UPSTREAM, up); up = NULL; } @@ -154,7 +155,7 @@ static void upstream_channel_oil_detach(struct pim_upstream *up) } } -void +struct pim_upstream * pim_upstream_del(struct pim_upstream *up, const char *name) { bool notify_msdp = false; @@ -167,7 +168,9 @@ pim_upstream_del(struct pim_upstream *up, const char *name) --up->ref_count; if (up->ref_count >= 1) - return; + return up; + else if (up->ref_count < 0) + return NULL; THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -231,6 +234,8 @@ pim_upstream_del(struct pim_upstream *up, const char *name) pim_delete_tracked_nexthop (&nht_p, up, NULL); pim_upstream_free (up); + + return NULL; } void @@ -699,7 +704,8 @@ pim_upstream_find_or_add(struct prefix_sg *sg, return up; } -static void pim_upstream_ref(struct pim_upstream *up, int flags) +void +pim_upstream_ref(struct pim_upstream *up, int flags) { up->flags |= flags; ++up->ref_count; diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 21c78021e5..126824e988 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -135,7 +135,8 @@ struct pim_upstream *pim_upstream_find_or_add (struct prefix_sg *sg, struct pim_upstream *pim_upstream_add (struct prefix_sg *sg, struct interface *ifp, int flags, const char *name); -void pim_upstream_del(struct pim_upstream *up, const char *name); +void pim_upstream_ref (struct pim_upstream *up, int flags); +struct pim_upstream *pim_upstream_del(struct pim_upstream *up, const char *name); int pim_upstream_evaluate_join_desired(struct pim_upstream *up); int pim_upstream_evaluate_join_desired_interface(struct pim_upstream *up, From ce2b6ce0984a6a0c7dbfccafeb1b440128f5c878 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 11:15:32 -0400 Subject: [PATCH 024/133] pimd: Consider interface change a RPF_CHANGED event Suppose you have a unnumbered ecmp connections between two switches: st1-l3# show ip pim neighbor Interface Neighbor Uptime Holdtime DR Pri swp52 6.0.0.10 00:00:01 00:00:29 1 swp53 6.0.0.10 00:00:06 00:00:26 1 And for a given (S,G) the RPF goes: st1-l3# show ip nht 99.1.1.1 resolved via bgp fe80::4e76:25ff:fee7:42d1, via swp52 fe80::4e76:25ff:fee7:42d5, via swp53 Client list: pim(fd 14) Now suppose, 52 is the choosen RPF( since we can only pick one ) and the interface goes down. As such we will choose to use swp53. The problem was that the pim_rpf_update call is made it will change the rpf interface to 53, but not tell the calling function that the RPF_CHANGED because it is only looking at the rpf_addr(the nexthop) to see if it is changed and if we are in an unnumbered dual ecmp to the same box it was not detecting and notifying. Signed-off-by: Donald Sharp --- pimd/pim_rpf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index 3d278f12a7..180586a786 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -263,7 +263,9 @@ enum pim_rpf_result pim_rpf_update(struct pim_upstream *up, struct pim_rpf *old, } /* detect change in RPF'(S,G) */ - if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr) { + if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr || + saved.source_nexthop.interface != rpf->source_nexthop.interface) + { /* return old rpf to caller ? */ if (old) From cb35003fdca20dfd12e260891acc8d0ceef5c03e Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 08:38:03 -0400 Subject: [PATCH 025/133] pimd: When the RPF is changed remove the group When changing the RPF cleanup the old entry in the J/P Agg neighbor list. Signed-off-by: Donald Sharp --- pimd/pim_nht.c | 6 ++++++ pimd/pim_upstream.c | 7 ------- pimd/pim_zebra.c | 7 +++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index c8cc187305..5fc5d08d16 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -370,6 +370,12 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find (old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); /* * We have detected a case where we might need to rescan diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 8ea9e3d688..0f16bc0f86 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -337,13 +337,6 @@ join_timer_start(struct pim_upstream *up) */ void pim_upstream_join_timer_restart(struct pim_upstream *up, struct pim_rpf *old) { - struct pim_neighbor *nbr; - - nbr = pim_neighbor_find (old->source_nexthop.interface, - old->rpf_addr.u.prefix4); - if (nbr) - pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - //THREAD_OFF(up->t_join_timer); join_timer_start(up); } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index ad4ef64eda..3ff0d38185 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -382,6 +382,13 @@ static void scan_upstream_rpf_cache() continue; if (rpf_result == PIM_RPF_CHANGED) { + struct pim_neighbor *nbr; + + nbr = pim_neighbor_find (old.source_nexthop.interface, + old.rpf_addr.u.prefix4); + if (nbr) + pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); + /* * We have detected a case where we might need to rescan * the inherited o_list so do it. From 06e12762c21bce1586f7dbea2cae05e8345d1b7b Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 12:56:59 -0400 Subject: [PATCH 026/133] pimd: Add code to catch J/P Agg list issues Signed-off-by: Donald Sharp --- pimd/pim_jp_agg.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ pimd/pim_jp_agg.h | 3 ++ pimd/pim_upstream.c | 3 ++ 3 files changed, 75 insertions(+) diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 4c1c0c7de1..eb13ebf31b 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -22,6 +22,8 @@ #include "linklist.h" #include "log.h" +#include "vrf.h" +#include "if.h" #include "pimd.h" #include "pim_msg.h" @@ -181,6 +183,73 @@ pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) } } +int +pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up) +{ + struct listnode *node, *nnode; + struct pim_jp_agg_group *jag = NULL; + struct pim_jp_sources *js = NULL; + + for (ALL_LIST_ELEMENTS (group, node, nnode, jag)) + { + if (jag->group.s_addr == up->sg.grp.s_addr) + break; + } + + if (!jag) + return 0; + + for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) + { + if (js->up == up) + return 1; + } + + return 0; + } + +//#define PIM_JP_AGG_DEBUG 1 +/* + * For the given upstream, check all the neighbor + * jp_agg lists and ensure that it is not + * in another list + * + * *IF* ignore is true we can skip + * up->rpf.source_nexthop.interface particular interface for checking + * + * This is a debugging function, Probably + * can be safely compiled out in real + * builds + */ +void +pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore) +{ +#ifdef PIM_JP_AGG_DEBUG + struct listnode *node; + struct interface *ifp; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp)) + { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *nnode; + + if (ignore && ifp == up->rpf.source_nexthop.interface) + continue; + + if (pim_ifp) + { + struct pim_neighbor *neigh; + for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, nnode, neigh)) + { + assert (!pim_jp_agg_is_in_list(neigh->upstream_jp_agg, up)); + } + } + } +#else + return; +#endif +} + void pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) { diff --git a/pimd/pim_jp_agg.h b/pimd/pim_jp_agg.h index 4c84c120eb..b2cbdf6f41 100644 --- a/pimd/pim_jp_agg.h +++ b/pimd/pim_jp_agg.h @@ -34,6 +34,9 @@ struct pim_jp_agg_group struct list *sources; }; +void pim_jp_agg_upstream_verification (struct pim_upstream *up, bool ignore); +int pim_jp_agg_is_in_list (struct list *group, struct pim_upstream *up); + void pim_jp_agg_group_list_free (struct pim_jp_agg_group *jag); int pim_jp_agg_group_list_cmp (void *arg1, void *arg2); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 0f16bc0f86..31b623280b 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -187,6 +187,7 @@ pim_upstream_del(struct pim_upstream *up, const char *name) } join_timer_stop(up); + pim_jp_agg_upstream_verification (up, false); up->rpf.source_nexthop.interface = NULL; if (up->sg.src.s_addr != INADDR_ANY) { @@ -297,6 +298,7 @@ static void join_timer_stop(struct pim_upstream *up) pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); THREAD_OFF (up->t_join_timer); + pim_jp_agg_upstream_verification (up, false); } void @@ -326,6 +328,7 @@ join_timer_start(struct pim_upstream *up) on_join_timer, up, qpim_t_periodic); } + pim_jp_agg_upstream_verification (up, true); } /* From 4252a5777116bb614c7e6a48e5db683b92df3dfb Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 14:14:00 -0400 Subject: [PATCH 027/133] pimd: Remove unneeded debug statement Left over debug statement that is not needed anymore Signed-off-by: Donald Sharp --- pimd/pim_join.c | 1 - 1 file changed, 1 deletion(-) diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c19468da6f..c531545541 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -493,7 +493,6 @@ int pim_joinprune_send(struct pim_rpf *rpf, curr_ptr += group_size; packet_left -= group_size; packet_size += group_size; - zlog_debug ("\tpl: %zd ps: %zd", packet_left, packet_size); pim_msg_build_jp_groups (grp, group); grp = (struct pim_jp_groups *)curr_ptr; From febdb373c3a1a19fcd0b4eb322fe6485e74d34d3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 14:19:17 -0400 Subject: [PATCH 028/133] pimd: Remove unused value Dead code, remove. Signed-off-by: Donald Sharp --- pimd/pim_jp_agg.h | 1 - 1 file changed, 1 deletion(-) diff --git a/pimd/pim_jp_agg.h b/pimd/pim_jp_agg.h index b2cbdf6f41..ad014d9520 100644 --- a/pimd/pim_jp_agg.h +++ b/pimd/pim_jp_agg.h @@ -30,7 +30,6 @@ struct pim_jp_sources struct pim_jp_agg_group { struct in_addr group; - //int onetime; struct list *sources; }; From bc72292aeb24d161e634c0b9dc0df072dd882faf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 15:52:36 -0400 Subject: [PATCH 029/133] pimd: Remove dead code This code is impossible to reach. Signed-off-by: Donald Sharp --- pimd/pim_nht.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index 5fc5d08d16..12632c13bb 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -357,12 +357,6 @@ pim_update_upstream_nh (struct pim_nexthop_cache *pnc) enum pim_rpf_result rpf_result; struct pim_rpf old; - if (up == NULL) - { - zlog_debug ("%s: Upstream node is NULL ", __PRETTY_FUNCTION__); - continue; - } - old.source_nexthop.interface = up->rpf.source_nexthop.interface; rpf_result = pim_rpf_update (up, &old, 0); if (rpf_result == PIM_RPF_FAILURE) From 7eb9068901571e0dcd23ce887bdc3e018683f298 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 15:56:54 -0400 Subject: [PATCH 030/133] pimd: Cleanup ref counting pim_jp_agg list should not ref count pim_upstream as that the deletion of pim_upstream deletion should remove the pim_upstream from the j/p agg list. Cleanup a memory leag of jag Make comparison of js cleaner in add_group Move THREAD_OFF to before the neighbor find. Signed-off-by: Donald Sharp --- pimd/pim_jp_agg.c | 13 ++++++------- pimd/pim_upstream.c | 10 ++++------ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index eb13ebf31b..29faace322 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -51,9 +51,6 @@ pim_jp_agg_src_free (struct pim_jp_sources *js) * pick this shit back up when the * nbr comes back alive */ - - up = pim_upstream_del (up, __PRETTY_FUNCTION__); - if (up) join_timer_start(js->up); XFREE (MTYPE_PIM_JP_AGG_SOURCE, js); @@ -113,8 +110,8 @@ pim_jp_agg_clear_group (struct list *group) { for (ALL_LIST_ELEMENTS(jag->sources, snode, snnode, js)) { - pim_upstream_del (js->up, __PRETTY_FUNCTION__); listnode_delete(jag->sources, js); + js->up = NULL; XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); } jag->sources = NULL; @@ -171,7 +168,7 @@ pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) if (js) { - pim_upstream_del (up, __PRETTY_FUNCTION__); + js->up = NULL; listnode_delete(jag->sources, js); XFREE(MTYPE_PIM_JP_AGG_SOURCE, js); } @@ -179,8 +176,11 @@ pim_jp_agg_remove_group (struct list *group, struct pim_upstream *up) if (jag->sources->count == 0) { list_delete(jag->sources); + jag->sources = NULL; listnode_delete(group, jag); + XFREE(MTYPE_PIM_JP_AGG_GROUP, jag); } + } int @@ -275,14 +275,13 @@ pim_jp_agg_add_group (struct list *group, struct pim_upstream *up, bool is_join) for (ALL_LIST_ELEMENTS(jag->sources, node, nnode, js)) { - if (js->up->sg.src.s_addr == up->sg.src.s_addr) + if (js->up == up) break; } if (!js) { js = XCALLOC(MTYPE_PIM_JP_AGG_SOURCE, sizeof (struct pim_jp_sources)); - pim_upstream_ref (up, 0); js->up = up; js->is_join = is_join; listnode_add_sort (jag->sources, js); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 31b623280b..759c955412 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -142,7 +142,6 @@ pim_upstream_find_parent (struct pim_upstream *child) void pim_upstream_free(struct pim_upstream *up) { - memset (up, 0, sizeof (struct pim_upstream)); XFREE(MTYPE_PIM_UPSTREAM, up); up = NULL; } @@ -162,15 +161,13 @@ pim_upstream_del(struct pim_upstream *up, const char *name) struct prefix nht_p; if (PIM_DEBUG_TRACE) - zlog_debug ("%s(%s): Delete %s ref count: %d", - __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count); + zlog_debug ("%s(%s): Delete %s ref count: %d, flags: %d (Pre decrement)", + __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count, up->flags); --up->ref_count; if (up->ref_count >= 1) return up; - else if (up->ref_count < 0) - return NULL; THREAD_OFF(up->t_ka_timer); THREAD_OFF(up->t_rs_timer); @@ -291,13 +288,14 @@ static void join_timer_stop(struct pim_upstream *up) { struct pim_neighbor *nbr; + THREAD_OFF (up->t_join_timer); + nbr = pim_neighbor_find (up->rpf.source_nexthop.interface, up->rpf.rpf_addr.u.prefix4); if (nbr) pim_jp_agg_remove_group (nbr->upstream_jp_agg, up); - THREAD_OFF (up->t_join_timer); pim_jp_agg_upstream_verification (up, false); } From 4a57e76af4235267aabd145fea198720bc8ac8f8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 16:43:01 -0400 Subject: [PATCH 031/133] pimd: Cleanup pim_register_recv upstream create When we get a register packet from a FHR, we were doing allot of work twice. Signed-off-by: Donald Sharp --- pimd/pim_register.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 46d8e3ec2e..cb9d7e3744 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -332,34 +332,16 @@ pim_register_recv (struct interface *ifp, */ if (!upstream) { - upstream = pim_upstream_add (&sg, ifp, - PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, - __PRETTY_FUNCTION__); + upstream = pim_upstream_add (&sg, ifp, + PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, + __PRETTY_FUNCTION__); if (!upstream) { zlog_warn ("Failure to create upstream state"); return 1; } - PIM_UPSTREAM_FLAG_SET_SRC_STREAM(upstream->flags); upstream->upstream_register = src_addr; - pim_rp_set_upstream_addr (&upstream->upstream_addr, sg.src, sg.grp); - if (pim_nexthop_lookup (&upstream->rpf.source_nexthop, - upstream->upstream_addr, 1) != 0) - { - if (PIM_DEBUG_PIM_REG) - { - zlog_debug ("Received Register(%s), for which I have no path back", upstream->sg_str); - } - PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(upstream->flags); - pim_upstream_del (upstream, __PRETTY_FUNCTION__); - return 1; - } - upstream->sg.src = sg.src; - upstream->rpf.rpf_addr = upstream->rpf.source_nexthop.mrib_nexthop_addr; - - upstream->join_state = PIM_UPSTREAM_NOTJOINED; - } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) || From b616d3a9c7a61525115149b4b73fd90de54fc585 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 20:06:31 -0400 Subject: [PATCH 032/133] pimd: Fix uninitialized access of req Signed-off-by: Donald Sharp --- pimd/pim_igmp_join.h | 1 + 1 file changed, 1 insertion(+) diff --git a/pimd/pim_igmp_join.h b/pimd/pim_igmp_join.h index ba80db0696..228d30c5c4 100644 --- a/pimd/pim_igmp_join.h +++ b/pimd/pim_igmp_join.h @@ -45,6 +45,7 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex, struct sockaddr_in group; struct sockaddr_in source; + memset(&req, 0, sizeof(req)); memset(&group, 0, sizeof(group)); group.sin_family = AF_INET; group.sin_addr = group_addr; From 6233f087385b876557dc83ef16e10159d647a3bd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Mar 2017 20:07:08 -0400 Subject: [PATCH 033/133] pimd: Fix connected data structure not being freed Signed-off-by: Donald Sharp --- pimd/pim_zebra.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 3ff0d38185..727bceff5b 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -338,26 +338,27 @@ static int pim_zebra_if_address_del(int command, struct zclient *client, return 0; p = c->address; - if (p->family != AF_INET) - return 0; - - if (PIM_DEBUG_ZEBRA) { - char buf[BUFSIZ]; - prefix2str(p, buf, BUFSIZ); - zlog_debug("%s: %s disconnected IP address %s flags %u %s", - __PRETTY_FUNCTION__, - c->ifp->name, buf, c->flags, - CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); - -#ifdef PIM_DEBUG_IFADDR_DUMP - dump_if_address(c->ifp); -#endif - } + if (p->family == AF_INET) + { + if (PIM_DEBUG_ZEBRA) { + char buf[BUFSIZ]; + prefix2str(p, buf, BUFSIZ); + zlog_debug("%s: %s disconnected IP address %s flags %u %s", + __PRETTY_FUNCTION__, + c->ifp->name, buf, c->flags, + CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary"); - pim_if_addr_del(c, 0); - pim_rp_setup(); - pim_i_am_rp_re_evaluate(); - +#ifdef PIM_DEBUG_IFADDR_DUMP + dump_if_address(c->ifp); +#endif + } + + pim_if_addr_del(c, 0); + pim_rp_setup(); + pim_i_am_rp_re_evaluate(); + } + + connected_free (c); return 0; } From d1e77284c1ed8b5a86aadfe0485f25fa26e48e67 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 17 Mar 2017 13:46:47 -0400 Subject: [PATCH 034/133] pimd: Add display of SGRpt state for ifchannel When we get a SGrpt Prune embedded in the *,G Join, Display the created ifchannel as being SGRpt state. Signed-off-by: Donald Sharp --- pimd/pim_cmd.c | 5 +++-- pimd/pim_ifchannel.c | 40 ++++++++++++++++++++++++++++------------ pimd/pim_ifchannel.h | 2 +- pimd/pim_upstream.c | 6 +++--- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index a85de0aabc..b2edb94711 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1168,7 +1168,8 @@ static void pim_show_join(struct vty *vty, u_char uj) json_object_string_add(json_row, "upTime", uptime); json_object_string_add(json_row, "expire", expire); json_object_string_add(json_row, "prune", prune); - json_object_string_add(json_row, "channelJoinName", pim_ifchannel_ifjoin_name(ch->ifjoin_state)); + json_object_string_add(json_row, "channelJoinName", + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) json_object_int_add(json_row, "SGRpt", 1); @@ -1187,7 +1188,7 @@ static void pim_show_join(struct vty *vty, u_char uj) inet_ntoa(ifaddr), ch_src_str, ch_grp_str, - pim_ifchannel_ifjoin_name(ch->ifjoin_state), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), uptime, expire, prune, diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index ee75793024..6dc1fba375 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -239,15 +239,15 @@ void pim_ifchannel_ifjoin_switch(const char *caller, zlog_debug ("PIM_IFCHANNEL(%s): %s is switching from %s to %s", ch->interface->name, ch->sg_str, - pim_ifchannel_ifjoin_name (ch->ifjoin_state), - pim_ifchannel_ifjoin_name (new_state)); + pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags), + pim_ifchannel_ifjoin_name (new_state, 0)); if (old_state == new_state) { if (PIM_DEBUG_PIM_EVENTS) { zlog_debug("%s calledby %s: non-transition on state %d (%s)", __PRETTY_FUNCTION__, caller, new_state, - pim_ifchannel_ifjoin_name(new_state)); + pim_ifchannel_ifjoin_name(new_state, 0)); } return; } @@ -331,15 +331,31 @@ void pim_ifchannel_ifjoin_switch(const char *caller, } } -const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state) +const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, + int flags) { switch (ifjoin_state) { - case PIM_IFJOIN_NOINFO: return "NOINFO"; - case PIM_IFJOIN_JOIN: return "JOIN"; - case PIM_IFJOIN_PRUNE: return "PRUNE"; - case PIM_IFJOIN_PRUNE_PENDING: return "PRUNEP"; - case PIM_IFJOIN_PRUNE_TMP: return "PRUNET"; - case PIM_IFJOIN_PRUNE_PENDING_TMP: return "PRUNEPT"; + case PIM_IFJOIN_NOINFO: + if (PIM_IF_FLAG_TEST_S_G_RPT(flags)) + return "SGRpt"; + else + return "NOINFO"; + break; + case PIM_IFJOIN_JOIN: + return "JOIN"; + break; + case PIM_IFJOIN_PRUNE: + return "PRUNE"; + break; + case PIM_IFJOIN_PRUNE_PENDING: + return "PRUNEP"; + break; + case PIM_IFJOIN_PRUNE_TMP: + return "PRUNET"; + break; + case PIM_IFJOIN_PRUNE_PENDING_TMP: + return "PRUNEPT"; + break; } return "ifjoin_bad_state"; @@ -609,7 +625,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t) { zlog_warn("%s: IFCHANNEL%s Prune Pending Timer Popped while in %s state", __PRETTY_FUNCTION__, pim_str_sg_dump (&ch->sg), - pim_ifchannel_ifjoin_name (ch->ifjoin_state)); + pim_ifchannel_ifjoin_name (ch->ifjoin_state, ch->flags)); } return 0; @@ -1198,7 +1214,7 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom) if (PIM_DEBUG_PIM_TRACE) zlog_debug ("%s: %s %s eom: %d", __PRETTY_FUNCTION__, - pim_ifchannel_ifjoin_name(ch->ifjoin_state), + pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags), ch->sg_str, eom); if (!ch->sources) return; diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index c7084034a0..fe9fb9a7f1 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -139,7 +139,7 @@ void pim_ifchannel_local_membership_del(struct interface *ifp, void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch, enum pim_ifjoin_state new_state); -const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state); +const char *pim_ifchannel_ifjoin_name(enum pim_ifjoin_state ifjoin_state, int flags); const char *pim_ifchannel_ifassert_name(enum pim_ifassert_state ifassert_state); int pim_ifchannel_isin_oiflist(struct pim_ifchannel *ch); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 759c955412..327e4f07d7 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -744,11 +744,11 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, if (ch->upstream == up) { - if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) - return 1; - if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) return 0; + + if (!pim_macro_ch_lost_assert(ch) && pim_macro_chisin_joins_or_include(ch)) + return 1; } /* From d1c2443dc7990f57c8e777bd8da8f259c7414554 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 17 Mar 2017 20:43:27 -0700 Subject: [PATCH 035/133] snapcraft: Add missing snapcraft files from dist (make dist) archive Signed-off-by: Martin Winter --- snapcraft/Makefile.am | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index 15813be72f..d32e18d071 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -1,11 +1,5 @@ EXTRA_DIST = snapcraft.yaml \ - scripts/Makefile scripts/zebra-service scripts/bgpd-service \ - scripts/isisd-service scripts/ripd-service scripts/ripngd-service \ - scripts/ospf6d-service scripts/ospfd-service \ - scripts/isisd-service scripts/pimd-service \ - scripts/ldpd-service \ - defaults/bgpd.conf.default defaults/isisd.conf.default \ - defaults/ospf6d.conf.default defaults/ospfd.conf.default \ - defaults/pimd.conf.default defaults/zebra.conf.default \ - defaults/ripd.conf.default defaults/ripngd.conf.default \ - defaults/ldpd.conf.default defaults/vtysh.conf.default + README.* \ + scripts/Makefile scripts/*-service \ + defaults/*.conf.default \ + helpers setup From 567dd75c077b36f0001d771bb287ae55c9312363 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 17 Mar 2017 20:50:09 -0700 Subject: [PATCH 036/133] snapcraft: Change setup/ to snap/ directory based on new snap format DEPRECATED: Assets in 'setup/gui' should now be placed in 'snap/gui'. See http://snapcraft.io/docs/deprecation-notices/dn3 for more information. Signed-off-by: Martin Winter --- snapcraft/Makefile.am | 2 +- snapcraft/{setup => snap}/gui/icon.png | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename snapcraft/{setup => snap}/gui/icon.png (100%) diff --git a/snapcraft/Makefile.am b/snapcraft/Makefile.am index d32e18d071..8cc4e0b4c6 100644 --- a/snapcraft/Makefile.am +++ b/snapcraft/Makefile.am @@ -2,4 +2,4 @@ EXTRA_DIST = snapcraft.yaml \ README.* \ scripts/Makefile scripts/*-service \ defaults/*.conf.default \ - helpers setup + helpers snap diff --git a/snapcraft/setup/gui/icon.png b/snapcraft/snap/gui/icon.png similarity index 100% rename from snapcraft/setup/gui/icon.png rename to snapcraft/snap/gui/icon.png From 595b4beeb2bb6cbc4f854685cf822becf6158b87 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Fri, 17 Mar 2017 15:41:04 -0300 Subject: [PATCH 037/133] ldpd: remove pseudowire LSP check In order to bring a pseudowire up, we must make sure that there's at least one LSP available to its remote end (otherwise the labeled frames from the CEs wouldn't reach their destination). We were doing this check in ldpd, but doing so is very limiting because it doesn't consider other types of LSPs that might be available (static LSPs, RSVP-TE, SR, etc). Thus remove this check from the l2vpn_pw_ok() function. Later on we'll implement a pseudowire manager in zebra which will solve this problem in a much better way (including notifying ldpd about failures to install a pseudowire in the kernel/hardware). Signed-off-by: Renato Westphal --- ldpd/l2vpn.c | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 3f4e21e685..2516e62753 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -282,9 +282,6 @@ l2vpn_pw_reset(struct l2vpn_pw *pw) int l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) { - struct fec fec; - struct fec_node *fn; - /* check for a remote label */ if (fnh->remote_label == NO_LABEL) return (0); @@ -298,34 +295,6 @@ l2vpn_pw_ok(struct l2vpn_pw *pw, struct fec_nh *fnh) pw->remote_status != PW_FORWARDING) return (0); - /* check for a working lsp to the nexthop */ - memset(&fec, 0, sizeof(fec)); - switch (pw->af) { - case AF_INET: - fec.type = FEC_TYPE_IPV4; - fec.u.ipv4.prefix = pw->addr.v4; - fec.u.ipv4.prefixlen = 32; - break; - case AF_INET6: - fec.type = FEC_TYPE_IPV6; - fec.u.ipv6.prefix = pw->addr.v6; - fec.u.ipv6.prefixlen = 128; - break; - default: - fatalx("l2vpn_pw_ok: unknown af"); - } - - fn = (struct fec_node *)fec_find(&ft, &fec); - if (fn == NULL || fn->local_label == NO_LABEL) - return (0); - /* - * Need to ensure that there's a label binding for all nexthops. - * Otherwise, ECMP for this route could render the pseudowire unusable. - */ - LIST_FOREACH(fnh, &fn->nexthops, entry) - if (fnh->remote_label == NO_LABEL) - return (0); - return (1); } From fea12efb86407248c6baea2df49e4f03d564dad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Fingen?= Date: Mon, 20 Mar 2017 15:34:49 +0100 Subject: [PATCH 038/133] Implement generic label manager Label Manager allows to share MPLS label space among different daemons. Each daemon can request a chunk of consecutive labels and release it if it doesn't need them anymore. Label Manager stores the daemon protocol and instance to identify the owner client. It uses them to perform garbage collection, releasing all label chunks from a client when it gets disconnected or reconnected. Additionally, every client can request that the chunk is never garbage collected. In that case client has the responsibility to release non-used labels. Zebra can host the label manager itself (if no -l param is provided) or connect to an external one using zserv/zclient (providing its address with -l param). Client code is in lib/zclient.c, but currently only LDP is using it. TODO: Allow for custom ranges requests, i.e., specify the start label besides the chunk. TODO: Release labels from LDP. Signed-off-by: Bingen Eguzkitza --- ldpd/lde.c | 150 ++++++++++++++++++-- ldpd/lde.h | 9 +- ldpd/ldpd.c | 35 +++-- ldpd/ldpd.h | 4 +- lib/log.c | 3 + lib/mpls.h | 2 + lib/zclient.c | 218 +++++++++++++++++++++++++++++ lib/zclient.h | 7 + tests/test_lblmgr.c | 150 ++++++++++++++++++++ zebra/Makefile.am | 4 +- zebra/label_manager.c | 317 ++++++++++++++++++++++++++++++++++++++++++ zebra/label_manager.h | 74 ++++++++++ zebra/main.c | 28 ++-- zebra/zserv.c | 176 +++++++++++++++++++++++ zebra/zserv.h | 1 + 15 files changed, 1150 insertions(+), 28 deletions(-) create mode 100644 tests/test_lblmgr.c create mode 100644 zebra/label_manager.c create mode 100644 zebra/label_manager.h diff --git a/ldpd/lde.c b/ldpd/lde.c index 08339c720a..d4b95637f9 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -33,6 +33,10 @@ #include "privs.h" #include "sigevent.h" #include "mpls.h" +#include +#include "zclient.h" +#include "stream.h" +#include "network.h" static void lde_shutdown(void); static int lde_dispatch_imsg(struct thread *); @@ -50,6 +54,11 @@ static void lde_map_free(void *); static int lde_address_add(struct lde_nbr *, struct lde_addr *); static int lde_address_del(struct lde_nbr *, struct lde_addr *); static void lde_address_list_free(struct lde_nbr *); +static void zclient_sync_init (u_short instance); +static void lde_label_list_init(void); +static int lde_get_label_chunk (void); +static void on_get_label_chunk_response(uint32_t start, uint32_t end); +static uint32_t lde_get_next_label(void); RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare) @@ -83,6 +92,10 @@ static struct zebra_privs_t lde_privs = .cap_num_i = 0 }; +/* List of chunks of labels externally assigned by Zebra */ +struct list *label_chunk_list; +struct listnode *current_label_chunk; + /* SIGINT / SIGTERM handler. */ static void sigint(void) @@ -102,9 +115,31 @@ static struct quagga_signal_t lde_signals[] = }, }; +struct zclient *zclient_sync = NULL; +static void +zclient_sync_init(u_short instance) +{ + /* Initialize special zclient for synchronous message exchanges. */ + log_debug("Initializing synchronous zclient for label manager"); + zclient_sync = zclient_new(master); + zclient_sync->sock = -1; + zclient_sync->redist_default = ZEBRA_ROUTE_LDP; + zclient_sync->instance = instance; + while (zclient_socket_connect(zclient_sync) < 0) { + fprintf(stderr, "Error connecting synchronous zclient!\n"); + sleep(1); + } + + /* Connect to label manager */ + while (lm_label_manager_connect(zclient_sync) != 0) { + fprintf(stderr, "Error connecting to label manager!\n"); + sleep(1); + } +} + /* label decision engine */ void -lde(const char *user, const char *group) +lde(const char *user, const char *group, u_short instance) { struct thread thread; struct timeval now; @@ -152,6 +187,10 @@ lde(const char *user, const char *group) gettimeofday(&now, NULL); global.uptime = now.tv_sec; + /* Init synchronous zclient and label list */ + zclient_sync_init(instance); + lde_label_list_init(); + /* Fetch next active thread. */ while (thread_fetch(master, &thread)) thread_call(&thread); @@ -587,7 +626,6 @@ lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen) uint32_t lde_update_label(struct fec_node *fn) { - static uint32_t label = MPLS_LABEL_RESERVED_MAX; struct fec_nh *fnh; int connected = 0; @@ -652,12 +690,7 @@ lde_update_label(struct fec_node *fn) fn->local_label > MPLS_LABEL_RESERVED_MAX) return (fn->local_label); - /* - * TODO: request label to zebra or define a range of labels for ldpd. - */ - - label++; - return (label); + return lde_get_next_label (); } void @@ -1533,3 +1566,104 @@ lde_address_list_free(struct lde_nbr *ln) free(lde_addr); } } + +static void +lde_del_label_chunk(void *val) +{ + free(val); +} +static int +lde_get_label_chunk(void) +{ + int ret; + uint32_t start, end; + + log_debug("Getting label chunk"); + ret = lm_get_label_chunk(zclient_sync, 0, CHUNK_SIZE, &start, &end); + if (ret < 0) + { + log_warnx("Error getting label chunk!"); + close(zclient_sync->sock); + zclient_sync->sock = -1; + return -1; + } + + on_get_label_chunk_response(start, end); + + return 0; +} +static void +lde_label_list_init(void) +{ + label_chunk_list = list_new(); + label_chunk_list->del = lde_del_label_chunk; + + /* get first chunk */ + while (lde_get_label_chunk() != 0) { + fprintf(stderr, "Error getting first label chunk!\n"); + sleep(1); + } +} + +static void +on_get_label_chunk_response(uint32_t start, uint32_t end) +{ + struct label_chunk *new_label_chunk; + + log_debug("Label Chunk assign: %u - %u", start, end); + + new_label_chunk = calloc(1, sizeof(struct label_chunk)); + + new_label_chunk->start = start; + new_label_chunk->end = end; + new_label_chunk->used_mask = 0; + + listnode_add(label_chunk_list, (void *)new_label_chunk); + + /* let's update current if needed */ + if (!current_label_chunk) + current_label_chunk = listtail(label_chunk_list); +} + +static uint32_t +lde_get_next_label(void) +{ + struct label_chunk *label_chunk; + uint32_t i, pos, size; + uint32_t label = NO_LABEL; + + while (current_label_chunk) { + label_chunk = listgetdata(current_label_chunk); + if (!label_chunk) + goto end; + + /* try to get next free label in currently used label chunk */ + size = label_chunk->end - label_chunk->start + 1; + for (i = 0, pos = 1; i < size; i++, pos <<= 1) { + if (!(pos & label_chunk->used_mask)) { + label_chunk->used_mask |= pos; + label = label_chunk->start + i; + goto end; + } + } + current_label_chunk = listnextnode(current_label_chunk); + } + +end: + /* we moved till the last chunk, or were not able to find a label, + so let's ask for another one */ + if (!current_label_chunk || current_label_chunk == listtail(label_chunk_list) + || label == NO_LABEL) { + if (lde_get_label_chunk() != 0) + log_warn("%s: Error getting label chunk!", __func__); + + } + + return NO_LABEL; +} +/* TODO: not used yet. Have to check label release */ +static void +lde_release_label_chunk(void) +{ + return; +} diff --git a/ldpd/lde.h b/ldpd/lde.h index b5bcb42c8b..d9836097af 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -124,6 +124,13 @@ struct fec_node { void *data; /* fec specific data */ }; +#define CHUNK_SIZE 64 +struct label_chunk { + uint32_t start; + uint32_t end; + uint64_t used_mask; +}; + #define LDE_GC_INTERVAL 300 extern struct ldpd_conf *ldeconf; @@ -132,7 +139,7 @@ extern struct nbr_tree lde_nbrs; extern struct thread *gc_timer; /* lde.c */ -void lde(const char *, const char *); +void lde(const char *, const char *, u_short instance); int lde_imsg_compose_parent(int, pid_t, void *, uint16_t); int lde_imsg_compose_ldpe(int, uint32_t, pid_t, void *, uint16_t); int lde_acl_check(char *, int, union ldpd_addr *, uint8_t); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 98ea5ca53e..8fa33ff099 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -45,7 +45,7 @@ static void ldpd_shutdown(void); static pid_t start_child(enum ldpd_process, char *, int, int, - const char *, const char *, const char *); + const char *, const char *, const char *, const char *); static int main_dispatch_ldpe(struct thread *); static int main_dispatch_lde(struct thread *); static int main_imsg_send_ipc_sockets(struct imsgbuf *, @@ -119,6 +119,7 @@ char ctl_sock_path[MAXPATHLEN] = LDPD_SOCKET; static struct option longopts[] = { { "ctl_socket", required_argument, NULL, OPTION_CTLSOCK}, + { "instance", required_argument, NULL, 'n'}, { 0 } }; @@ -186,6 +187,8 @@ main(int argc, char *argv[]) char *ctl_sock_name; const char *user = NULL; const char *group = NULL; + u_short instance = 0; + const char *instance_char = NULL; ldpd_process = PROC_MAIN; @@ -194,8 +197,9 @@ main(int argc, char *argv[]) saved_argv0 = (char *)"ldpd"; frr_preinit(&ldpd_di, argc, argv); - frr_opt_add("LE", longopts, - " --ctl_socket Override ctl socket path\n"); + frr_opt_add("LEn:", longopts, + " --ctl_socket Override ctl socket path\n" + "-n, --instance Instance id\n"); while (1) { int opt; @@ -227,6 +231,12 @@ main(int argc, char *argv[]) strlcat(ctl_sock_path, ctl_sock_name, sizeof(ctl_sock_path)); break; + case 'n': + instance = atoi(optarg); + instance_char = optarg; + if (instance < 1) + exit(0); + break; case 'L': lflag = 1; break; @@ -258,7 +268,7 @@ main(int argc, char *argv[]) LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); if (lflag) - lde(user, group); + lde(user, group, instance); else if (eflag) ldpe(user, group, ctl_sock_path); @@ -308,10 +318,10 @@ main(int argc, char *argv[]) /* start children */ lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0, pipe_parent2lde[1], pipe_parent2lde_sync[1], - user, group, ctl_sock_custom_path); + user, group, ctl_sock_custom_path, instance_char); ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0, pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], - user, group, ctl_sock_custom_path); + user, group, ctl_sock_custom_path, instance_char); /* drop privileges */ zprivs_init(&ldpd_privs); @@ -414,9 +424,10 @@ ldpd_shutdown(void) static pid_t start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync, - const char *user, const char *group, const char *ctl_sock_custom_path) + const char *user, const char *group, const char *ctl_sock_custom_path, + const char *instance) { - char *argv[9]; + char *argv[13]; int argc = 0; pid_t pid; @@ -459,6 +470,14 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync, argv[argc++] = (char *)"--ctl_socket"; argv[argc++] = (char *)ctl_sock_custom_path; } + /* zclient serv path */ + argv[argc++] = (char *)"-z"; + argv[argc++] = (char *)zclient_serv_path_get(); + /* instance */ + if (instance) { + argv[argc++] = (char *)"-n"; + argv[argc++] = (char *)instance; + } argv[argc++] = NULL; execvp(argv0, argv); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 0a7e1177bc..c665656aa6 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -140,7 +140,9 @@ enum imsg_type { IMSG_RECONF_END, IMSG_DEBUG_UPDATE, IMSG_LOG, - IMSG_ACL_CHECK + IMSG_ACL_CHECK, + IMSG_GET_LABEL_CHUNK, + IMSG_RELEASE_LABEL_CHUNK }; union ldpd_addr { diff --git a/lib/log.c b/lib/log.c index 0fd9621f37..69225dbf7a 100644 --- a/lib/log.c +++ b/lib/log.c @@ -964,6 +964,9 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_ADD), DESC_ENTRY (ZEBRA_IPV6_NEXTHOP_DELETE), DESC_ENTRY (ZEBRA_IPMR_ROUTE_STATS), + DESC_ENTRY (ZEBRA_LABEL_MANAGER_CONNECT), + DESC_ENTRY (ZEBRA_GET_LABEL_CHUNK), + DESC_ENTRY (ZEBRA_RELEASE_LABEL_CHUNK), }; #undef DESC_ENTRY diff --git a/lib/mpls.h b/lib/mpls.h index b5c1a653b1..13a46e1012 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -23,6 +23,8 @@ #ifndef _QUAGGA_MPLS_H #define _QUAGGA_MPLS_H +#include + /* Well-known MPLS label values (RFC 3032 etc). */ #define MPLS_V4_EXP_NULL_LABEL 0 #define MPLS_RA_LABEL 1 diff --git a/lib/zclient.c b/lib/zclient.c index 859751deb8..6f7fb9b1be 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -33,6 +33,7 @@ #include "memory.h" #include "table.h" #include "nexthop.h" +#include "mpls.h" DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient") DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs") @@ -1461,6 +1462,223 @@ zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id, *new_vrf_id = new_id; return ifp; } +/** + * Connect to label manager in a syncronous way + * + * It first writes the request to zcient output buffer and then + * immediately reads the answer from the input buffer. + * + * @param zclient Zclient used to connect to label manager (zebra) + * @result Result of response + */ +int +lm_label_manager_connect (struct zclient *zclient) +{ + int ret; + struct stream *s; + u_char result; + u_int16_t size; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t cmd; + + zlog_debug ("Connecting to Label Manager"); + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, ZEBRA_LABEL_MANAGER_CONNECT, VRF_DEFAULT); + + /* proto */ + stream_putc (s, zclient->redist_default); + /* instance */ + stream_putw (s, zclient->instance); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen (zclient->sock, s->data, stream_get_endp (s)); + if (ret < 0) + { + zlog_err ("%s: can't write to zclient->sock", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) + { + zlog_err ("%s: zclient->sock connection closed", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + zlog_debug ("%s: Label manager connect request (%d bytes) sent", __func__, ret); + + /* read response */ + s = zclient->ibuf; + stream_reset (s); + + ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, + &vrf_id, &cmd); + if (ret != 0 || cmd != ZEBRA_LABEL_MANAGER_CONNECT) { + zlog_err ("%s: Invalid Label Manager Connect Message Reply Header", __func__); + return -1; + } + /* result */ + result = stream_getc(s); + zlog_debug ("%s: Label Manager connect response (%d bytes) received, result %u", + __func__, size, result); + + return (int)result; +} + +/** + * Function to request a label chunk in a syncronous way + * + * It first writes the request to zlcient output buffer and then + * immediately reads the answer from the input buffer. + * + * @param zclient Zclient used to connect to label manager (zebra) + * @param keep Avoid garbage collection + * @param chunk_size Amount of labels requested + * @param start To write first assigned chunk label to + * @param end To write last assigned chunk label to + * @result 0 on success, -1 otherwise + */ +int +lm_get_label_chunk (struct zclient *zclient, u_char keep, uint32_t chunk_size, + uint32_t *start, uint32_t *end) +{ + int ret; + struct stream *s; + u_int16_t size; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t cmd; + u_char response_keep; + + zlog_debug ("Getting Label Chunk"); + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, ZEBRA_GET_LABEL_CHUNK, VRF_DEFAULT); + /* keep */ + stream_putc (s, keep); + /* chunk size */ + stream_putl (s, chunk_size); + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen (zclient->sock, s->data, stream_get_endp (s)); + if (ret < 0) + { + zlog_err ("%s: can't write to zclient->sock", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) + { + zlog_err ("%s: zclient->sock connection closed", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + zlog_debug ("%s: Label chunk request (%d bytes) sent", __func__, ret); + + /* read response */ + s = zclient->ibuf; + stream_reset (s); + + ret = zclient_read_header (s, zclient->sock, &size, &marker, &version, + &vrf_id, &cmd); + if (ret != 0 || cmd != ZEBRA_GET_LABEL_CHUNK) { + zlog_err ("%s: Invalid Get Label Chunk Message Reply Header", __func__); + return -1; + } + zlog_debug ("%s: Label chunk response (%d bytes) received", __func__, size); + /* keep */ + response_keep = stream_getc(s); + /* start and end labels */ + *start = stream_getl(s); + *end = stream_getl(s); + + /* not owning this response */ + if (keep != response_keep) { + zlog_err ("%s: Invalid Label chunk: %u - %u, keeps mismatch %u != %u", + __func__, *start, *end, keep, response_keep); + } + /* sanity */ + if (*start > *end + || *start < MPLS_MIN_UNRESERVED_LABEL + || *end > MPLS_MAX_UNRESERVED_LABEL) { + zlog_err ("%s: Invalid Label chunk: %u - %u", __func__, + *start, *end); + return -1; + } + + zlog_debug ("Label Chunk assign: %u - %u (%u) ", + *start, *end, response_keep); + + return 0; +} + +/** + * Function to release a label chunk + * + * @param zclient Zclient used to connect to label manager (zebra) + * @param start First label of chunk + * @param end Last label of chunk + * @result 0 on success, -1 otherwise + */ +int +lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end) +{ + int ret; + struct stream *s; + + zlog_debug ("Releasing Label Chunk"); + if (zclient->sock < 0) + return -1; + + /* send request */ + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, ZEBRA_RELEASE_LABEL_CHUNK, VRF_DEFAULT); + + /* start */ + stream_putl (s, start); + /* end */ + stream_putl (s, end); + + /* Put length at the first point of the stream. */ + stream_putw_at(s, 0, stream_get_endp(s)); + + ret = writen (zclient->sock, s->data, stream_get_endp (s)); + if (ret < 0) + { + zlog_err ("%s: can't write to zclient->sock", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + if (ret == 0) + { + zlog_err ("%s: zclient->sock connection closed", __func__); + close (zclient->sock); + zclient->sock = -1; + return -1; + } + + return 0; +} /* Zebra client message read function. */ static int diff --git a/lib/zclient.h b/lib/zclient.h index 89fc865c78..d3d0a202c5 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -91,6 +91,9 @@ typedef enum { ZEBRA_IPV6_NEXTHOP_ADD, ZEBRA_IPV6_NEXTHOP_DELETE, ZEBRA_IPMR_ROUTE_STATS, + ZEBRA_LABEL_MANAGER_CONNECT, + ZEBRA_GET_LABEL_CHUNK, + ZEBRA_RELEASE_LABEL_CHUNK, } zebra_message_types_t; struct redist_proto @@ -271,6 +274,10 @@ extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, extern struct interface *zebra_interface_link_params_read (struct stream *); extern size_t zebra_interface_link_params_write (struct stream *, struct interface *); +extern int lm_label_manager_connect (struct zclient *zclient); +extern int lm_get_label_chunk (struct zclient *zclient, u_char keep, + uint32_t chunk_size, uint32_t *start, uint32_t *end); +extern int lm_release_label_chunk (struct zclient *zclient, uint32_t start, uint32_t end); /* IPv6 prefix add and delete function prototype. */ struct zapi_ipv6 diff --git a/tests/test_lblmgr.c b/tests/test_lblmgr.c new file mode 100644 index 0000000000..4a4aaa0014 --- /dev/null +++ b/tests/test_lblmgr.c @@ -0,0 +1,150 @@ +/* + * Label Manager Test + * + * Copyright (C) 2017 by Bingen Eguzkitza, + * Volta Networks Inc. + * + * This file is part of FreeRangeRouting (FRR) + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include "lib/stream.h" +#include "lib/zclient.h" + +#define ZSERV_PATH "/tmp/zserv.api" // TODO!! +#define KEEP 0 /* change to 1 to avoid garbage collection */ +#define CHUNK_SIZE 32 + +struct zclient *zclient; +u_short instance = 1; + +const char *sequence = "GGRGGGRRG"; + +static int zebra_send_get_label_chunk (void); +static int zebra_send_release_label_chunk (uint32_t start, uint32_t end); + +static void +process_next_call (uint32_t start, uint32_t end) +{ + sleep (3); + if (!*sequence) + exit (0); + if (*sequence == 'G') + zebra_send_get_label_chunk (); + else if (*sequence == 'R') + zebra_send_release_label_chunk (start, end); +} + +/* Connect to Label Manager */ + +static int +zebra_send_label_manager_connect () +{ + int ret; + + printf("Connect to Label Manager\n"); + + ret = lm_label_manager_connect (zclient); + printf ("Label Manager connection result: %u \n", ret); + if (ret != 0 ) { + fprintf (stderr, "Error %d connecting to Label Manager %s\n", ret, + strerror(errno)); + exit (1); + } + + process_next_call (0, 0); +} + +/* Get Label Chunk */ + +static int +zebra_send_get_label_chunk () +{ + uint32_t start; + uint32_t end; + int ret; + + printf("Ask for label chunk \n"); + + ret = lm_get_label_chunk (zclient, KEEP, CHUNK_SIZE, &start, &end); + if (ret != 0 ) { + fprintf (stderr, "Error %d requesting label chunk %s\n", ret, strerror(errno)); + exit (1); + } + + sequence++; + + printf ("Label Chunk assign: %u - %u \n", + start, end); + + process_next_call (start, end); +} + +/* Release Label Chunk */ + +static int +zebra_send_release_label_chunk (uint32_t start, uint32_t end) +{ + struct stream *s; + int ret; + + printf("Release label chunk: %u - %u\n", start, end); + + ret = lm_release_label_chunk (zclient, start, end); + if (ret != 0 ) { + fprintf (stderr, "Error releasing label chunk\n"); + exit (1); + } + + sequence++; + + process_next_call (start-CHUNK_SIZE, end-CHUNK_SIZE); +} + + +void init_zclient (struct thread_master *master, char *lm_zserv_path) +{ + if (lm_zserv_path) + zclient_serv_path_set(lm_zserv_path); + + zclient = zclient_new(master); + /* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */ + zclient->sock = -1; + zclient->redist_default = ZEBRA_ROUTE_LDP; + zclient->instance = instance; + if (zclient_socket_connect (zclient) < 0) { + printf ("Error connecting synchronous zclient!\n"); + exit (1); + } + +} + +int main (int argc, char *argv[]) +{ + struct thread_master *master; + struct thread thread; + int ret; + + printf ("Sequence to be tested: %s\n", sequence); + + master = thread_master_create(); + init_zclient (master, ZSERV_PATH); + + zebra_send_label_manager_connect (); + + return 0; +} diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 1910e7b80f..50bc065c6e 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -45,7 +45,7 @@ zebra_SOURCES = \ $(othersrc) zebra_ptm.c zebra_rnh.c zebra_ptm_redistribute.c \ zebra_ns.c zebra_vrf.c zebra_static.c zebra_mpls.c zebra_mpls_vty.c \ $(protobuf_srcs) zebra_mroute.c \ - $(dev_srcs) + $(dev_srcs) label_manager.c testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ zebra_vty.c zebra_ptm.c zebra_routemap.c zebra_ns.c zebra_vrf.c \ @@ -60,7 +60,7 @@ noinst_HEADERS = \ rt_netlink.h zebra_fpm.h zebra_fpm_private.h zebra_rnh.h \ zebra_ptm_redistribute.h zebra_ptm.h zebra_routemap.h \ zebra_ns.h zebra_vrf.h ioctl_solaris.h zebra_static.h zebra_mpls.h \ - kernel_netlink.h if_netlink.h zebra_mroute.h + kernel_netlink.h if_netlink.h zebra_mroute.h label_manager.h zebra_LDADD = $(otherobj) ../lib/libfrr.la $(LIBCAP) $(Q_FPM_PB_CLIENT_LDOPTS) diff --git a/zebra/label_manager.c b/zebra/label_manager.c new file mode 100644 index 0000000000..2e96c4ebaf --- /dev/null +++ b/zebra/label_manager.c @@ -0,0 +1,317 @@ +/* + * Label Manager for FRR + * + * Copyright (C) 2017 by Bingen Eguzkitza, + * Volta Networks Inc. + * + * This file is part of FreeRangeRouting (FRR) + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include +#include + +#include "zebra.h" +#include "zserv.h" +#include "lib/log.h" +#include "lib/memory.h" +#include "lib/mpls.h" +#include "lib/network.h" +#include "lib/stream.h" +#include "lib/zclient.h" + +#include "label_manager.h" + +#define CONNECTION_DELAY 5 + +struct label_manager lbl_mgr; + +DEFINE_MGROUP(LBL_MGR, "Label Manager"); +DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk"); + +/* In case this zebra daemon is not acting as label manager, + * it will be a proxy to relay messages to external label manager + * This zclient thus is to connect to it + */ +static struct zclient *zclient; +bool lm_is_external; + +static void delete_label_chunk(void *val) +{ + XFREE(MTYPE_LM_CHUNK, val); +} + +/** + * Receive a request to get or release a label chunk and forward it to external + * label manager. + * + * It's called from zserv in case it's not an actual label manager, but just a + * proxy. + * + * @param cmd Type of request (connect, get or release) + * @param src Input buffer from zserv + * @return 0 on success, -1 otherwise + */ +int zread_relay_label_manager_request(int cmd, struct zserv *zserv) +{ + struct stream *src, *dst; + int ret; + + if (zclient->sock < 0) { + zlog_err("%s: Error relaying label chunk request: no zclient socket", + __func__); + return -1; + } + /* Send request to external label manager */ + src = zserv->ibuf; + dst = zclient->obuf; + + stream_copy(dst, src); + + ret = writen(zclient->sock, dst->data, stream_get_endp(dst)); + if (ret <= 0) { + zlog_err("%s: Error relaying label chunk request: %s", __func__, + strerror(errno)); + return -1; + } + zlog_debug("%s: Label chunk request relayed. %d bytes sent", __func__, + ret); + + /* Release label chunk has no response */ + if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) + return 0; + + /* read response */ + src = zclient->ibuf; + dst = zserv->obuf; + + stream_reset(src); + + u_int16_t size; + u_char marker; + u_char version; + vrf_id_t vrf_id; + u_int16_t resp_cmd; + ret = zclient_read_header(src, zclient->sock, &size, &marker, &version, + &vrf_id, &resp_cmd); + if (ret < 0) { + zlog_err("%s: Error reading label chunk response: %s", __func__, + strerror(errno)); + return -1; + } + zlog_debug("%s: Label chunk response received, %d bytes", __func__, + size); + + /* send response back */ + stream_copy(dst, src); + stream_copy(zserv->obuf, zclient->ibuf); + ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); + if (ret <= 0) { + zlog_err("%s: Error sending label chunk response back: %s", + __func__, strerror(errno)); + return -1; + } + zlog_debug("%s: Label chunk response (%d bytes) sent back", __func__, + ret); + + return 0; +} + +static int zclient_connect(struct thread *t) +{ + zclient->t_connect = NULL; + + if (zclient->sock >= 0) + return 0; + + if (zclient_socket_connect(zclient) < 0) { + zlog_err("Error connecting synchronous zclient!"); + THREAD_TIMER_ON(zebrad.master, zclient->t_connect, + zclient_connect, + zclient, CONNECTION_DELAY); + return -1; + } + + return 0; +} + +/** + * Function to initialize zclient in case this is not an actual + * label manager, but just a proxy to an external one. + * + * @param lm_zserv_path Path to zserv socket of external label manager + */ +static void lm_zclient_init(char *lm_zserv_path) +{ + if (lm_zserv_path) + zclient_serv_path_set(lm_zserv_path); + + /* Set default values. */ + zclient = zclient_new(zebrad.master); + zclient->sock = -1; + zclient->t_connect = NULL; + zclient_connect (NULL); +} + +/** + * Init label manager (or proxy to an external one) + */ +void label_manager_init(char *lm_zserv_path) +{ + /* this is an actual label manager */ + if (!lm_zserv_path) { + zlog_debug("Initializing own label manager"); + lm_is_external = false; + lbl_mgr.lc_list = list_new(); + lbl_mgr.lc_list->del = delete_label_chunk; + } else { /* it's acting just as a proxy */ + zlog_debug("Initializing external label manager at %s", + lm_zserv_path); + lm_is_external = true; + lm_zclient_init(lm_zserv_path); + } +} + +/** + * Core function, assigns label cunks + * + * It first searches through the list to check if there's one available + * (previously released). Otherwise it creates and assigns a new one + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @param keep If set, avoid garbage collection + * @para size Size of the label chunk + * @return Pointer to the assigned label chunk + */ +struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, + u_char keep, uint32_t size) +{ + struct label_manager_chunk *lmc; + struct listnode *node; + + node = lbl_mgr.lc_list->head; + /* first check if there's one available */ + for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { + if (lmc->proto == NO_PROTO && lmc->end - lmc->start + 1 == size) { + lmc->proto = proto; + lmc->instance = instance; + lmc->keep = keep; + return lmc; + } + } + /* otherwise create a new one */ + lmc = XCALLOC(MTYPE_LM_CHUNK, sizeof(struct label_manager_chunk)); + + if (list_isempty(lbl_mgr.lc_list)) + lmc->start = MPLS_MIN_UNRESERVED_LABEL; + else + lmc->start = ((struct label_manager_chunk *) + listgetdata(listtail(lbl_mgr.lc_list)))->end + 1; + if (lmc->start > MPLS_MAX_UNRESERVED_LABEL - size + 1) { + zlog_err("Reached max labels. Start: %u, size: %u", lmc->start, + size); + return NULL; + } + lmc->end = lmc->start + size - 1; + lmc->proto = proto; + lmc->instance = instance; + lmc->keep = keep; + listnode_add(lbl_mgr.lc_list, lmc); + + return lmc; +} + +/** + * Core function, release no longer used label cunks + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @param start First label of the chunk + * @param end Last label of the chunk + * @return 0 on success, -1 otherwise + */ +int +release_label_chunk(u_char proto, u_short instance, uint32_t start, + uint32_t end) +{ + struct listnode *node; + struct label_manager_chunk *lmc; + int ret = -1; + + /* check that size matches */ + zlog_debug("Releasing label chunk: %u - %u", start, end); + /* find chunk and disown */ + for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { + if (lmc->start != start) + continue; + if (lmc->end != end) + continue; + if (lmc->proto != proto || lmc->instance != instance) { + zlog_err("%s: Daemon mismatch!!", __func__); + continue; + } + lmc->proto = NO_PROTO; + lmc->instance = 0; + lmc->keep = 0; + ret = 0; + break; + } + if (ret != 0) + zlog_err("%s: Label chunk not released!!", __func__); + + return ret; +} + +/** + * Release label chunks from a client. + * + * Called on client disconnection or reconnection. It only releases chunks + * with empty keep value. + * + * @param proto Daemon protocol of client, to identify the owner + * @param instance Instance, to identify the owner + * @return Number of chunks released + */ +int release_daemon_chunks(u_char proto, u_short instance) +{ + struct listnode *node; + struct label_manager_chunk *lmc; + int count = 0; + int ret; + + for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { + if (lmc->proto == proto && lmc->instance == instance + && lmc->keep == 0) { + ret = + release_label_chunk(lmc->proto, lmc->instance, + lmc->start, lmc->end); + if (ret == 0) + count++; + } + } + + zlog_debug("%s: Released %d label chunks", __func__, count); + + return count; +} + +void label_manager_close() +{ + list_delete(lbl_mgr.lc_list); +} diff --git a/zebra/label_manager.h b/zebra/label_manager.h new file mode 100644 index 0000000000..0c6a5ebc7d --- /dev/null +++ b/zebra/label_manager.h @@ -0,0 +1,74 @@ +/* + * Label Manager header + * + * Copyright (C) 2017 by Bingen Eguzkitza, + * Volta Networks Inc. + * + * This file is part of FreeRangeRouting (FRR) + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _LABEL_MANAGER_H +#define _LABEL_MANAGER_H + +#include + +#include "lib/linklist.h" +#include "lib/thread.h" + +#define NO_PROTO 0 + +/* + * Label chunk struct + * Client daemon which the chunk belongs to can be identified by either + * proto (daemon protocol) + instance. + * If the client then passes a non-empty value to keep field when it requests + * for chunks, the chunks won't be garbage collected and the client will be + * responsible of its release. + * Otherwise, if the keep field is not set (value 0) for the chunk, it will be + * automatically released when the client disconnects or when it reconnects + * (in case it died unexpectedly, we can know it's the same because it will have + * the same proto and instance values) + */ +struct label_manager_chunk { + u_char proto; + u_short instance; + u_char keep; + uint32_t start; /* First label of the chunk */ + uint32_t end; /* Last label of the chunk */ +}; + +/* + * Main label manager struct + * Holds a linked list of label chunks. + */ +struct label_manager { + struct list *lc_list; +}; + +bool lm_is_external; + +int zread_relay_label_manager_request(int cmd, struct zserv *zserv); +void label_manager_init(char *lm_zserv_path); +struct label_manager_chunk *assign_label_chunk(u_char proto, u_short instance, + u_char keep, uint32_t size); +int release_label_chunk(u_char proto, u_short instance, uint32_t start, + uint32_t end); +int release_daemon_chunks(u_char proto, u_short instance); +void label_manager_close(void); + +#endif /* _LABEL_MANAGER_H */ diff --git a/zebra/main.c b/zebra/main.c index 98177a423e..26e66f961d 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. + * 02111-1307, USA. */ #include @@ -48,6 +48,7 @@ #include "zebra/zebra_ns.h" #include "zebra/redistribute.h" #include "zebra/zebra_mpls.h" +#include "zebra/label_manager.h" #define ZEBRA_PTM_SUPPORT @@ -78,7 +79,7 @@ u_int32_t nl_rcvbufsize = 4194304; #endif /* HAVE_NETLINK */ /* Command line options. */ -struct option longopts[] = +struct option longopts[] = { { "batch", no_argument, NULL, 'b'}, { "allow_delete", no_argument, NULL, 'a'}, @@ -86,6 +87,7 @@ struct option longopts[] = { "fpm_format", required_argument, NULL, 'F'}, { "socket", required_argument, NULL, 'z'}, { "ecmp", required_argument, NULL, 'e'}, + { "label_socket", no_argument, NULL, 'l'}, { "retain", no_argument, NULL, 'r'}, #ifdef HAVE_NETLINK { "nl-bufsize", required_argument, NULL, 's'}, @@ -93,7 +95,7 @@ struct option longopts[] = { 0 } }; -zebra_capabilities_t _caps_p [] = +zebra_capabilities_t _caps_p [] = { ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN, @@ -118,7 +120,7 @@ struct zebra_privs_t zserv_privs = unsigned int multipath_num = MULTIPATH_NUM; /* SIGHUP handler. */ -static void +static void sighup (void) { zlog_info ("SIGHUP received"); @@ -182,8 +184,8 @@ sigusr1 (void) struct quagga_signal_t zebra_signals[] = { - { - .signal = SIGHUP, + { + .signal = SIGHUP, .handler = &sighup, }, { @@ -220,10 +222,13 @@ main (int argc, char **argv) // int batch_mode = 0; char *zserv_path = NULL; char *fpm_format = NULL; + /* Socket to external label manager */ + char *lblmgr_path = NULL; + frr_preinit(&zebra_di, argc, argv); - frr_opt_add("bakF:z:e:r" + frr_opt_add("bakF:z:e:l:r" #ifdef HAVE_NETLINK "s:" #endif @@ -233,6 +238,7 @@ main (int argc, char **argv) " -F, --fpm_format Set fpm format to 'netlink' or 'protobuf'\n" " -z, --socket Set path of zebra socket\n" " -e, --ecmp Specify ECMP to use.\n" + " -l, --label_socket Socket to external label manager\n"\ " -k, --keep_kernel Don't delete old routes which installed by zebra.\n" " -r, --retain When program terminates, retain added route by zebra.\n" #ifdef HAVE_NETLINK @@ -247,7 +253,7 @@ main (int argc, char **argv) if (opt == EOF) break; - switch (opt) + switch (opt) { case 0: break; @@ -274,6 +280,9 @@ main (int argc, char **argv) case 'z': zserv_path = optarg; break; + case 'l': + lblmgr_path = optarg; + break; case 'r': retain_mode = 1; break; @@ -359,6 +368,9 @@ main (int argc, char **argv) /* This must be done only after locking pidfile (bug #403). */ zebra_zserv_socket_init (zserv_path); + /* Init label manager */ + label_manager_init (lblmgr_path); + frr_run (zebrad.master); /* Not reached... */ diff --git a/zebra/zserv.c b/zebra/zserv.c index 064489acd9..f9205a12c8 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -55,6 +55,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/zebra_fpm.h" #include "zebra/zebra_mroute.h" +#include "zebra/label_manager.h" /* Event list of zebra. */ enum event { ZEBRA_SERV, ZEBRA_READ, ZEBRA_WRITE }; @@ -113,6 +114,9 @@ zebra_server_send_message(struct zserv *client) if (client->t_suicide) return -1; + if (client->is_synchronous) + return 0; + stream_set_getp(client->obuf, 0); client->last_write_cmd = stream_getw_from(client->obuf, 6); switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), @@ -1770,6 +1774,167 @@ zread_mpls_labels (int command, struct zserv *client, u_short length, distance, out_label); } } +/* Send response to a label manager connect request to client */ +static int +zsend_label_manager_connect_response (struct zserv *client, vrf_id_t vrf_id, u_short result) +{ + struct stream *s; + + s = client->obuf; + stream_reset (s); + + zserv_create_header (s, ZEBRA_LABEL_MANAGER_CONNECT, vrf_id); + + /* result */ + stream_putc (s, result); + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); + + return writen (client->sock, s->data, stream_get_endp (s)); +} + +static void +zread_label_manager_connect (struct zserv *client, vrf_id_t vrf_id) +{ + struct stream *s; + /* type of protocol (lib/zebra.h) */ + u_char proto; + u_short instance; + + /* Get input stream. */ + s = client->ibuf; + + /* Get data. */ + proto = stream_getc (s); + instance = stream_getw (s); + + /* accept only dynamic routing protocols */ + if ((proto >= ZEBRA_ROUTE_MAX) + || (proto <= ZEBRA_ROUTE_STATIC)) + { + zlog_err ("client %d has wrong protocol %s", + client->sock, zebra_route_string(proto)); + zsend_label_manager_connect_response (client, vrf_id, 1); + return; + } + zlog_notice ("client %d with instance %u connected as %s", + client->sock, instance, zebra_route_string(proto)); + client->proto = proto; + client->instance = instance; + + /* + Release previous labels of same protocol and instance. + This is done in case it restarted from an unexpected shutdown. + */ + release_daemon_chunks (proto, instance); + + zlog_debug (" Label Manager client connected: sock %d, proto %s, instance %u", + client->sock, zebra_route_string(proto), instance); + /* send response back */ + zsend_label_manager_connect_response (client, vrf_id, 0); +} +/* Send response to a get label chunk request to client */ +static int +zsend_assign_label_chunk_response (struct zserv *client, vrf_id_t vrf_id, + struct label_manager_chunk *lmc) +{ + struct stream *s; + + s = client->obuf; + stream_reset (s); + + zserv_create_header (s, ZEBRA_GET_LABEL_CHUNK, vrf_id); + + if (lmc) + { + /* keep */ + stream_putc (s, lmc->keep); + /* start and end labels */ + stream_putl (s, lmc->start); + stream_putl (s, lmc->end); + + } + + /* Write packet size. */ + stream_putw_at (s, 0, stream_get_endp (s)); + + return writen (client->sock, s->data, stream_get_endp (s)); +} + +static void +zread_get_label_chunk (struct zserv *client, vrf_id_t vrf_id) +{ + struct stream *s; + u_char keep; + uint32_t size; + struct label_manager_chunk *lmc; + + /* Get input stream. */ + s = client->ibuf; + + /* Get data. */ + keep = stream_getc (s); + size = stream_getl (s); + + lmc = assign_label_chunk (client->proto, client->instance, keep, size); + if (!lmc) + zlog_err ("%s: Unable to assign Label Chunk of size %u", __func__, size); + else + zlog_debug ("Assigned Label Chunk %u - %u to %u", + lmc->start, lmc->end, keep); + /* send response back */ + zsend_assign_label_chunk_response (client, vrf_id, lmc); +} + +static void +zread_release_label_chunk (struct zserv *client) +{ + struct stream *s; + uint32_t start, end; + + /* Get input stream. */ + s = client->ibuf; + + /* Get data. */ + start = stream_getl (s); + end = stream_getl (s); + + release_label_chunk (client->proto, client->instance, start, end); +} +static void +zread_label_manager_request (int cmd, struct zserv *client, vrf_id_t vrf_id) +{ + /* to avoid sending other messages like ZERBA_INTERFACE_UP */ + if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + client->is_synchronous = 1; + + /* external label manager */ + if (lm_is_external) + { + if (zread_relay_label_manager_request (cmd, client) != 0) + zsend_label_manager_connect_response (client, vrf_id, 1); + } + /* this is a label manager */ + else + { + if (cmd == ZEBRA_LABEL_MANAGER_CONNECT) + zread_label_manager_connect (client, vrf_id); + else + { + /* Sanity: don't allow 'unidentified' requests */ + if (!client->proto) + { + zlog_err ("Got label request from an unidentified client"); + return; + } + if (cmd == ZEBRA_GET_LABEL_CHUNK) + zread_get_label_chunk (client, vrf_id); + else if (cmd == ZEBRA_RELEASE_LABEL_CHUNK) + zread_release_label_chunk (client); + } + } +} /* Cleanup registered nexthops (across VRFs) upon client disconnect. */ static void @@ -1807,6 +1972,9 @@ zebra_client_close (struct zserv *client) /* Cleanup any registered nexthops - across all VRFs. */ zebra_client_close_cleanup_rnh (client); + /* Release Label Manager chunks */ + release_daemon_chunks (client->proto, client->instance); + /* Close file descriptor. */ if (client->sock) { @@ -1868,6 +2036,9 @@ zebra_client_create (int sock) client->ifinfo = vrf_bitmap_init (); client->ridinfo = vrf_bitmap_init (); + /* by default, it's not a synchronous client */ + client->is_synchronous = 0; + /* Add this client to linked list. */ listnode_add (zebrad.client_list, client); @@ -2087,6 +2258,11 @@ zebra_client_read (struct thread *thread) case ZEBRA_IPMR_ROUTE_STATS: zebra_ipmr_route_stats (client, sock, length, zvrf); break; + case ZEBRA_LABEL_MANAGER_CONNECT: + case ZEBRA_GET_LABEL_CHUNK: + case ZEBRA_RELEASE_LABEL_CHUNK: + zread_label_manager_request (command, client, vrf_id); + break; default: zlog_info ("Zebra received unknown command %d", command); break; diff --git a/zebra/zserv.h b/zebra/zserv.h index 21cf1004bf..9e34738238 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -78,6 +78,7 @@ struct zserv /* client's protocol */ u_char proto; u_short instance; + u_char is_synchronous; /* Statistics */ u_int32_t redist_v4_add_cnt; From bc0eb287fa07b139b6f193c3dc4f033eddda6833 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 16 Mar 2017 22:11:15 -0300 Subject: [PATCH 039/133] ldpd: provide both a brief and a detailed version of some show commands Signed-off-by: Renato Westphal --- ldpd/control.c | 3 + ldpd/ldp_vty.xml | 21 ++- ldpd/ldp_vty_exec.c | 402 +++++++++++++++++++++++++++++++++++++++----- ldpd/ldpd.h | 1 + ldpd/ldpe.c | 15 ++ ldpd/ldpe.h | 1 + 6 files changed, 395 insertions(+), 48 deletions(-) diff --git a/ldpd/control.c b/ldpd/control.c index 0bfe0abc9d..5c530e1b70 100644 --- a/ldpd/control.c +++ b/ldpd/control.c @@ -242,6 +242,9 @@ control_dispatch_imsg(struct thread *thread) case IMSG_CTL_SHOW_DISCOVERY: ldpe_adj_ctl(c); break; + case IMSG_CTL_SHOW_DISCOVERY_DTL: + ldpe_adj_detail_ctl(c); + break; case IMSG_CTL_SHOW_LIB: case IMSG_CTL_SHOW_L2VPN_PW: case IMSG_CTL_SHOW_L2VPN_BINDING: diff --git a/ldpd/ldp_vty.xml b/ldpd/ldp_vty.xml index 966b634c27..141b14d83f 100644 --- a/ldpd/ldp_vty.xml +++ b/ldpd/ldp_vty.xml @@ -333,11 +333,17 @@ - -