From e8be4e8e44cce197405da94c2b2a82bd75eacde9 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Wed, 6 Nov 2024 12:21:01 +0100 Subject: [PATCH] Add README and basic examples --- README.adoc | 181 ++++++++++++++++++++++++++ examples/bird-ospf/lab.conf | 18 +++ examples/bird-ospf/lab.png | Bin 0 -> 27638 bytes examples/bird-ospf/r1/bird.conf | 38 ++++++ examples/bird-ospf/r2/bird.conf | 38 ++++++ examples/bird-ospf/r3/bird.conf | 38 ++++++ examples/podman-frr/lab.conf | 12 ++ examples/podman-frr/r1/frr/daemons | 7 + examples/podman-frr/r1/frr/frr.conf | 19 +++ examples/podman-frr/r1/frr/vtysh.conf | 0 examples/podman-frr/r2/frr/daemons | 7 + examples/podman-frr/r2/frr/frr.conf | 19 +++ examples/podman-frr/r2/frr/vtysh.conf | 0 examples/podman-frr/run.sh | 34 +++++ examples/readme/lab.conf | 21 +++ examples/readme/lab.png | Bin 0 -> 27638 bytes examples/readme/setup.sh | 32 +++++ 17 files changed, 464 insertions(+) create mode 100644 README.adoc create mode 100644 examples/bird-ospf/lab.conf create mode 100644 examples/bird-ospf/lab.png create mode 100644 examples/bird-ospf/r1/bird.conf create mode 100644 examples/bird-ospf/r2/bird.conf create mode 100644 examples/bird-ospf/r3/bird.conf create mode 100644 examples/podman-frr/lab.conf create mode 100644 examples/podman-frr/r1/frr/daemons create mode 100644 examples/podman-frr/r1/frr/frr.conf create mode 100644 examples/podman-frr/r1/frr/vtysh.conf create mode 100644 examples/podman-frr/r2/frr/daemons create mode 100644 examples/podman-frr/r2/frr/frr.conf create mode 100644 examples/podman-frr/r2/frr/vtysh.conf create mode 100755 examples/podman-frr/run.sh create mode 100644 examples/readme/lab.conf create mode 100644 examples/readme/lab.png create mode 100755 examples/readme/setup.sh diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..f33f7ff --- /dev/null +++ b/README.adoc @@ -0,0 +1,181 @@ += README + +linux-network-namespace-labs is a small program to create networking lab +setups based on Linux network namespaces in a simple manner. It provides a +quick way to setup labs using a text file describing the architecture +(networks, nodes, links, commands). This is much simpler than running each +node in a separate virtual machine. It is licensed under GPLv3+. + + +== Requirements + +- Linux compiled with `CONFIG_NET_NS` (available on most modern systems) +- iproute2 (`ip`) +- Go, no external dependencies + + +== Build + + $ go build + +Then copy the binary `linux-network-namespace-labs` to somewhere in your +`$PATH`. + + +== Usage + +The following configuration from `examples/readme/` setups a lab with three +nodes (routers) and configures static routes. + +---- +# Network range for loopback addresses of the nodes +net loops 192.0.2.0/24 3fff::/20 +# Network range for interfaces between nodes +net addrs 198.51.100.0/24 2001:db8::/32 + +# Setup three nodes (routers) and assign IPv4 and IPv6 loopback addresses +node r1 loops +node r2 loops +node r3 loops + +# Links between routers: /31 or /127 is used for each interface +link r1 r2 addrs +link r2 r3 addrs + +# Commands to run on each node; $1 is the node name (= name of network +# namespace). Here it's used to setup static routes but can also be used to +# start routing daemons like bird. +cmd ./setup.sh $1 +---- + +Then setup the lab by running (as root): + + # cd examples/readme + # linux-network-namespace-labs up lab.conf + [...] + +Now you can enter the network namespace of each router and test a simple +traceroute: + + # ip netns exec r1 sh + # ip -br a + lo UNKNOWN 127.0.0.1/8 ::1/128 + lo2 UNKNOWN 192.0.2.0/32 3fff::/128 fe80::438:67ff:fe0a:4e58/64 + r2@if287 UP 198.51.100.0/31 2001:db8::/127 fe80::a896:cdff:fe58:5c23/64 + # traceroute 192.0.2.2 + traceroute to 192.0.2.2 (192.0.2.2), 30 hops max, 60 byte packets + 1 r2 (198.51.100.1) 0.937 ms 0.818 ms 0.768 ms + 2 r3-loop (192.0.2.2) 0.722 ms 0.650 ms 0.603 ms + +Use `exit` to leave the network namespace. + +`/etc/hosts` of each node (via `/etc/netns//hosts`) is automatically +filled with all known addresses so you can use hostnames as well: + + # ping -c1 r3-loop + PING r3-loop(r3-loop (3fff::2)) 56 data bytes + 64 bytes from r3-loop (3fff::2): icmp_seq=1 ttl=63 time=0.266 ms + --- r3-loop ping statistics --- + 1 packets transmitted, 1 received, 0% packet loss, time 0ms + rtt min/avg/max/mdev = 0.266/0.266/0.266/0.000 ms + +When you change the configuration you can simply rerun "up" and it will remove +the lab (and killing all processes inside it) before starting it up again: + + # linux-network-namespace-labs up lab.conf + [...] + +When you're done you can remove the lab with: + + # linux-network-namespace-labs down lab.conf + [...] + +To get an overview of the network you can create a +https://en.wikipedia.org/wiki/DOT_(graph_description_language)[DOT] file: + + $ linux-network-namespace-labs dot lab.conf lab.dot + $ dot -Tpng lab.dot > lab.png + +image::examples/readme/lab.png[DOT style diagram of network nodes and links] + + +== Examples + +Have a look at `examples/` for a few small examples which also include running +https://bird.network.cz/[Bird] on each node and spawning a Podman container +inside the created nodes running https://frrouting.org/[FRR]. + + +== Syntax of configuration file + +One option per line, empty lines are permitted as well as comments at the +beginning of the line with `#`. + +The config files is parsed from top to bottom and the options "net", "node", +"link" must be given in this order. "cmd" can be put anywhere (but is only +executed at the end). + +=== Option "net" + + "net" ... + +"net" creates a new prefix which is used to allocate addresses for loopback +and link interfaces. Multiple IPv4 and IPv6 prefixes can be specified. When +the network is used one address of each prefix is assigned to the interface. + +=== Option "node" + + "node" [...] + +"node" creates a new node (router) and (if specified) assigns loopback +addresses from the given networks. The loopback addresses are assigned to a +new interface "lo2". + +=== Option "link" + + "link" + +"link" creates (veth-)links between nodes. The IP addresses are taken from the +given network name. /31 is used for IPv4- and /127 for IPv6-prefixes. The MAC +address is not static and allocated by the kernel. The link is named after the +node "on the other side". Multiple links can be created between two nodes. In +this case "_2", "_3", etc. is appended to the interface name. + +=== Option "cmd" + + "cmd" + +"cmd" runs the given command (by passing it as is to `sh -c`) on each node. +The first argument is the name of the node (which is also the name of the +network namespace). This can be used to run setup commands or routing daemons +on the nodes. + +If "cmd" is not flexible enough you can simply use `ip netns exec` to manually +run commands on specific nodes. + + +== Authors + +Written by Simon Ruderich . + +Please report bugs, feature requests and patches via email. + + +== License + +This program is licensed under GPL version 3 or later. + +Copyright (C) 2024 Simon Ruderich + +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 3 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. If not, see . diff --git a/examples/bird-ospf/lab.conf b/examples/bird-ospf/lab.conf new file mode 100644 index 0000000..d486108 --- /dev/null +++ b/examples/bird-ospf/lab.conf @@ -0,0 +1,18 @@ +# Start lab with: linux-network-namespace-labs up lab.conf + +# r1 <-> r2 <-> r3 + + +net loops 192.0.2.0/24 3fff::/20 +net addrs 198.51.100.0/24 2001:db8::/32 + +node r1 loops +node r2 loops +node r3 loops + +link r1 r2 addrs +link r2 r3 addrs + +# Start bird on each node, using a different config file for each +cmd bird -u bird -g bird -c $1/bird.conf -s /run/bird/$1.ctl +# Use with birdc() { command birdc -s "/run/bird/$(ip netns identify).ctl" "$@" } diff --git a/examples/bird-ospf/lab.png b/examples/bird-ospf/lab.png new file mode 100644 index 0000000000000000000000000000000000000000..6cf20a0670e84cc07c4a56dcc0090c56a096221f GIT binary patch literal 27638 zcmYhj2RPSl`#=7nG!!C9B%?CQ%!(vivZ;)ujAVo;84?~ zMX5;qU)TNozQ^&upXWI4?jrBc`?{|4e68~e)6-F>qh+I|P$+a7M^y~)?-mM$DtN;> z{Hi@bH5mU|XQ`>KLRlsM%c?I(pisCd8Y+s%J<`8qc$!5`t*)NQ=<^!dRHVZkF10r| zkTxgI=Xr8@v{s}~WO;(g;`fZE^~$V&MXd$(pUu1Qs64nrx3`EnsMmE!=i7VE!w-FR zX2M)ETyMp+dUlxo{`;_O#_dyGm(Q8sRRWBRivH9zJLLwcnfYU-ne+9svS?`y`StW@ z&J9w_+Z;P~OixeG@Ahq;&=$+@i{76J3E2-A3tVGf;YuWzf>3v@EFN=yF~ToAm$?3_6gwY=>8w55exR+ddnOe{1kO!4w%3G;d{ z8j9Y@lWK1tIM#}k>G1~^6$$+O`LpJbe{u0X2}#LX5nmIN9rN?^2m6?}Z_l}RZ;Ps` zYI->yEH*CAzrX)DGYboKp=eB06y2AvUoD)S8P=~~|N8CQ9LKj01Xoo$S%L(t_lSrv zSXfwWprZ>qx~KWy-{0JEN3-(sXil9vb@}Viw$qQU1l89cE-fuRYi+%DSD9Vf1sNHc zqdGcC2hM3}Z9Z_|0EL3j6H-vX_ghR{+`-_m5KWMPy?^MIUAv+y&UY*AVfxUOafpBa z{s26M+~LC?W@qX7`1me=eo2KFUOI6sE+ZqVu#n&E(G@zLxDC?IBPuQ~VzO7hY+ztu z@bL7sXp80EvSDp$-iy7ohIOiWjMQt^xGev1$<52lHZ0I#6+KHKf9r=2RJ(WY9z4Jv zX)LJb;c-xfhw(gJt_`OjUT%6_ zZuQ~g$AG)1AKg!S_1XH|xergnwr<$GS;f|tzrVkK^y}9sjRaou7^6QHOZVOnk~cV} zsX2vj8=sxkp|th(#-F@ns@l`jQ<~?aXI|%_c<9QPtd)O%x5l*Q{QCN~@1ffaK7K@% zgpK#*{I-scT+VBM{IMy*xpp{#bw zfgq>%4V|Wg>p$g)sb0AvC1i3xP(niDsFBgl$<8$O7|tU$LYl&i5iOOztJhpFUgV-k zTpU#h4-GvlG!xJ>raiZ`;9y$oy4TLmP9K}d?#E>39+n7`c6%waI*&LrGqa-_8ewWt zY^vCFrF$i1ga(-{%agCIES~Ru^@?xJnl+}?P8<`TK2;hPJivC^S%B3xvPI0S95xM z4F>PCWw4wJe^quSAv2RxKtQ19Wwx@w-n~IpxhxtQ8XNDNs*dg-7$|ahb@%d*N$tUS zwnP@I@FyV*hG|lcZBL&DuB`lZ9(0wbUHSL>%>2)vd*m~9e|+jLxPF})UmIlO9Nyfl zlq%)OM*iwjlL~%5zL2WinDF^|*P%!5B0E@FW3id{?%8uM>F0=qgQ1-FpV*x{carxR z&3UBDv`f9SuR!vIL%s6y2JOb}rUoXh2H99Uj zntoxbFT}j@TBoT_fZfUb*rR(S&Uft``?2`5mDBfLQcf1VrIpq5{{9;~IXDEw#S^O1 z*Y#Y`(nlRQb8T^NQE_o^xmBxiyPd)HfPm-NeSf^=9R$9$B=G6By?7BWC@9D;CKgw< zGsTW2e@jG*#O2R=C-{32ro-+A58R7V<55B8^IoEAweQauwP;Ni4@8|40cK2^1K@T2CImkp^kBehe zQdYKba*EbH@{hUu)?q85BJ=TU@jYWL5#@G$yn%s%XGb6Vmrh6sSeCP*B2p;XdZ8U1 zS~n6C#ZC?!9G{%L?fkxhi-(;5hYuf??i~m>doOThb~ub|nkSsT%ROUsRDR+rnkq&{ z+qt>9QD~d6we$@PnoSM9ieB?BNfbZdwI#E=pvvLZ{iJ#GbUDv>%EipUz_s&pbKKa( zv&PyL!~6IYt0ZQJYn8E4C481H4;t933Tw}yfFF>M$hGUsFHh>Vjbs(OPKkZ==unsn z&pv+stTbt7rp)fuLM^&wfByU+)A;p;nO9HR z+BP&aG;qmWeYM*t-{a?JMivqC$i13Lk6T)Ts?vEC%Nq=6&`j1d>>?HEfz!JerqRr< z=fZ0*eY%YT`2F|q^Fpdk>$A>x-!gu9S>R-;u|Hn#pzFc$XUzD$mc<{R$~}MB6c!d@ zZ;h@g_g-{mWo11(P<)~^?_yh!KMz#h&c{Pd>N@{ zX9^1}V#y~b=+ED8jbfhj*0pc{s5FI~$4~e8^<_tMb93_aS^MypFZEEOEWW%h7d*!w zyH(bGHWKBYM^rSnh(166&!?SCt}K4y%x6nZ9h;wM7xLoG zxE}m*YAUQXhVvsTL5GB>xT>Ne6&`yV-31y0awPWc+gIcAah*6_hZf`3tpO-F2W4c+ z{+na!t@CtmR-AaCMPFJ`JL{~+q7fHjvj2autLkW=G&?fN6(ze^!oW( z@s4Q~446|OTJ8Rr5v@WVjJ2p6(t)Ro65^m2D7j4pKEU$8cN;6v~gl$B2Iy8 z^yGVCoF%7s4|~uw9qxR4^sONW|D|tX!Oh6nnIazY(EXda)kwbZnO(1IFY(zqIEa%U z7RY2Oy?MYlRb5jr zU%gsSDbf%#F)^X|@#)@DP*z^kxUy8zFN3bcDtp;BYNFor$GSIf-Wd2uvaqm>&UttM zgH$bRpKg%TTde076tp&IJdj{Yb>qejg%c+dPb_?kY-o^w7R4Uo+_1RL)6)~*^5>iH z>ZWbm64}^?-DigtEiHKf4~(qvhn|$&SKjEXdWMD{E!}#s$O@-Vb5Qim%sTL}`S|UG zZ#3o8XXnORYCPt6=sD##b8v7h|9b0u@yeCEzj%e@<#)Zm_E)Iu*5Ok#r^^BFfK}SM zx+bHyv9Kr!vOMYUuhiktJ}tjLJUpDT?0d=EHumkSn<8hPO%If~O!o`0va|0#a3DScy>k@UhC-3gj2WrFs=S9uBcr6K z==s8jx{OAF7dNH%HEyT&_lu(N3hm&TUs%Xf3|LoQ+@M2COM7$=Q_l?nL$Wu3&hql| zT;?`z<&BMq*hE7^(}P#_{PAN2`ybB_U;PzZQnLRv5DLByl^DQgbj;`Puf5rNZF$|9 zM|7vBr+?0rHTK5sRxiW?8aP)MPda~@pNIkyO~7lfSW3aC3sMRU3Bk$GxnEIHZqvy| zQ2>azhhKDL9^u5crKXS?!Y=LfG@9cO&}|^#YBO5@q2H)bdM8e_prbuaEGj5y{nwb5 zmUjF}_59t6tG}I?nVHE#{8^eQbLe=_Jkib$yry;jy;xc_*~lF!;_ID9>Zmfi&vPsK zryl?^K$9B-NYI)-KbU{7x>_9@KR!O*SVNDiKt)Zhxv9zDHg$GJrL407pK z3qq^({`Ka(mYb*~O-yS*Obi44&VzoaVMzweZB*;&cly=V%KUI-O%_R89Bo?jdT5Ae z&z`lJ*Omk{1vn!=b!UG3*0`#6@+8Y_-}GY}^_@F+0N?#ldq@keyY`Rm>aQ)fwN3Udai&=QzEw zK|wT~=`smb%siF{e@!{!&qsm$e0_ZZW$q>YFjrAkwZMlNel5Vs$$9Y5p^p>oH{06V zpEx)ETSqaj_mXt)YFu5}lx3-;ho4f@^7z`H59`4t&wgkQ;{3%UFM9R&EYLDrlAuYm zDJ@0D!@GF=$m${kSW>IETg~shGmY1hi@nRA@2tf5DL1 zy*{%${w=Irb${ty%XHXK<$D5>9)OdPnipXt%x_e`?kAu3p&>4#?^l!iAhO=$xhLM z!NE*mKu1>o1XM8#jK5%3QNd2)+Pin}tY-f(K9Y0Qy89U!9CyrW<3mT@F$+bdr|-0X z-*7kzAgtB8l1Y`s8;BX zwwUvX9Edy6!o4H|j={U7VPC#nI3OmL4YX_kJnJAsH-^r$`}FD4cw;#z%fTHT9fj&K zyN>JWDPXB?gT-&9%>Vw)7k5K9%x4wIhF@13f04L9H$Pu3fAU?Hv^iFPk>Y@ARHaQ5;vibk{ z<8eS#lncA3b~gD&MAxGs)+5*CP!R5&ZKB=~q!hVRCcbJ9&9|dCQ0Rftz$F&%8+@vM zwYIJ4SikngbxHx>z-HYI)`FH&z+f zJ;9rITt_1%)Pf3~Gz)l}pP&CRHrK?+76oy!AnYXiU2>r&6*lB$yOvYcUSIP3K1#Lp z>nr-zHmu}rl;6_5&jZb>1xD1+i5vg@Vh2SMwR*N0*kKg!)k;WHQE2#~+a~4U&HlhU zI3l~NjMIjnJj`1azA#i7<{`IBJ6Y5p@BTk7ET-OmZwkg$bS2zZpGn{K&d?Gr;fxad~sfWetcRQyPd6V+qeNbEP%LiyQfHMl|bk|8%LiXoznQ=DqDHAvQVuml78wFI)&1|M@UEr zRm3QR-9T!4YQ4a|jr8>S0G@IF{#5_wS~)wNI*wl&pMCeJzy7Mb!HE-jCrVE0L!WTa zh*F9WqtS0^VA4zyf&&9 zb>)F3k$S{e{+x{s{)7i5G8=D#i8d&=tW5XOm9O@3?&Bb#z3=Mb z`fLAEt4eMBRd}+|Tyf^P@nlQ$?IHp)GAUK1yag>dWYC@n&;LKwAyq=dN!sYVwvG>=-TJQV2daH_#3*FE6XO&1O8+=;S2ttF4wJ zK_~`m*R2Dp-vV^y4*~&UBPeVuU-P?n8C7zV{95`!SfJTWTRAxyu*H5tF5I%g`G3E1H?@#NG}7 zry!ISty)x4G6?dQoSfXtJEx>yzkUtumQi&)8vSz*AK&hM`)L2Cuc<=Pqde~E0oB>{ zeSY46HJhF}KQ;~vt)il$u!o6TLV_8M5Lhx02U1W-2!dS}Y^$QKzFSI)1(KD={P@P|fg}7h%X;FzGd)E6k-n&827`^|2#Ei0nH&4zV{iHMO<1`2_?hSKT=Sk`sREQ`ZNup)IsQgz4dv z*_ZMO3DIHWCdu+L(~3bHNLi3L?u%nidN7{ypsei4w*h4h9w)3j%SuW%QC{LVS(WH* zUvB#I^r=eC!-tmW(gQ5Nz~zJqyUfbsB7}3YBL$Dfw4Gtorhvr6Z9ua)HUSxj+?xjn zSwJQv2hl5oQHJU&ZUs+@?Axb==lc$13ud_n<-HZaMCel8KDy2_h3MF-o8M5fC9Zri z9s*0EDtu6W3|rG~e*C$aEKW1(YfwnYR>mIGvmy|GGc!RJB0)xM7a24@14-2J^}P=n z3lb8mI9Y9wmriZq=H(3rm=9Jm5M*K!-amloJ53(!s70;KR!^ zgHf75!8s@{H5WfnQ$|b58m`~HE6l5%8VCer_49MjAJmnZFN#9@_dogYBxLTbbK{5J zJWaaZKD~dCyPIRVm20G>u3Wit@4sY4l|P#XUI zIt2v9&CkDqqGxOzil&&dFPP{E&qCUN-vrQXT^nk#9z%Cn8hoz8SJ31D65dh0M&D;HIH^G4nw^By)5NK6Bx$Jfs)QH#{C?-&U*%vl{knX2z1IR1 z>63TOG$`0!>MAOgkfVAB2lMefeb;F=k-dnv#Vh$LTlnya_7agsW5Ik>DwLV6ooUiB zP$ungk`A<%3>uwTDOQ;KrQu|IF|B!cc<0K>%0RU5(o{icWTXmq1Ef%B@q4RGJj%@L zW0R9ZM@P?+gV++jjhuDqX4nqddiwhQdi-nk%JoN~@VZR(?geK4fW_s_~wfpfIX64d{*lY#`8 z`3sxXEyB;WCpA5JvIfX_GCGR$2nzqMgP!wyl+V$Q$Ek^{T3hc~US1aU_cm zy3u3M%>h^GH*?4`e|#481bSg#)(0DeD324W#d(z+LiTpf%-#p{B)IytQj*=;yLG!&1kS3d$3AN2akk6j*% zbBsm(h}S(_lUG?OvHa&_46B^S#d;UY>qg%r#Cs4ltI^}tMw>H!bVZ1`Y%SZ*^ryyz zLbqNAEK2$zKGHbLP6&UHyqmj^tVVJx!&|&-Ucb++RsZF@?Ttf0kPygTaMOZp45f>j zGTi9Pi7sQn{^U1Wf3?#)B@mc;m#o|3-@caXoiJ&|8&DQ-Ev;!5kVQG4Qs0z<)I|IdAo)cKI6^E>+;=C?gwcThozR*ph76xxP2^ts} z*w-twFf)%rCc(if6I+29Gu+_AuCK4pzi(f0#VvGVe4JxGU^W9>s9a}EO~X+j`imPI zJd|fjZsvdH)rEis)kDa~_w!3`1AYCt7nf!Rg{T$qau%Mwe+Fa&=3#J02YNCa4l*Mn z8fFwMLe#X-2<+Q5o9`A;K(iZDxA+E&Ty0r_AUmP0n!si}k`-lo~{ab6PsqkL`7cN|Ad;HiB zc*wAX9#G!Z-TmegNPwmdJ`U%O9U4m6u>dm9+uB00y=t?M+<(e$nkgu;6gY}4@@Hvj z42qzrs3=9Ryk8Sm=8G3EYGm3HqfR(Fe)alzpGd}q#l_SVV)tC0?%xPNVm3T9^zhk_ z5&02NTKHG{8lix#LRMB0a__Ojaf%<|7Z-9HPj&YTNxENe)$?KiqFVqW(+aO2kR zKe~@RA(l{{;z@p0vo-&ydXQ4NegcRmL2|>ie3tIlsi^+SgP)D_(`Cm($Yu= zzk<9x|L#w42}0Yg?CrzhbU`6`Xj(6s_kKH8edl4X8-M*h(*PnAxVAiQZ{I}8DlQHe zvwAj)kH1z=tlS=*`QYWxTTtYQZ)#TSN&`dGZP3KbEb{N~Z)hJWr=A>RAq%#Bdq`;L z20`O{6onRsE(lq*t=&swba!-5vUM^u?2>zIbjBxWb>(;C#Y>mgP-ZPJI6A@=>sZ(d z9B75EkSyhxs^wzh@z-Po53;)QSETvL6DkT+)q(tqldf3JE~0(}B_**Gyay0gAtjW$ z(Duga;wNKDfDuDTj7?0Wp}_ZOZNDi( z>!t@2M#a+ys3G4$wK3%CDyZt2Nwj-_6kVy01QnpUeH2OhpcK`>zdaw z2ZVRG1IFYNl=tV)pPMb?R6I)&KTn}JIXMv@1{fU8j$!jIIo7*(?~r{_YEAr{}#6Ug^T>gd*~_9$JHe8YAc~`#U&=Tq%<;>8%M&E$x#lWr%*tyz0n_& z#n0;`e3q7!RE2a1$o=HbYGOtP-L9DRR#qRqKH{^cC?(~wpE!OzH$PWuk9n<`wPQcC zxRli7ipR;5C-2?AKW2%VV&IvPk>MZ&3iD|2Rnv)?JDOI8qL9wyJihy-ZCb@ifAaP% zJ8IU;fq@_uo+cpen#L!11CKw>)ifld>o>#PgI#b`S2v`rOayjR&3s>9AA7%=*Q2_n z&x3b}hQh@ZCTjU~1LZ$BitUQh-Oui9>vQ0T&bLx#3E9Gl#0%J#|I@*lV+mG35foH|iq+CPcZ#6!T*he|LPJeSN$CN44GS$qIU!*GGC(yz zU=N^xz@9yU*ZzK$CSVLrxjnbQ-t+$FGv$^v)+h+Uo~O@ZQjZ({%t%Y#`1FwH4UAj1uYG2ah7NhHO&dVWF^I%i$6c>;{cDgi!_c$ zLsg&$@RAf3*wc*^Po&4nvJAxM{|swvrLn;YpEN8TfpP>rk>_zzv^V)kx##do7-y

LuS!;bMvC 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%0Do| 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 literal 0 HcmV?d00001 diff --git a/examples/bird-ospf/r1/bird.conf b/examples/bird-ospf/r1/bird.conf new file mode 100644 index 0000000..2d4ebc2 --- /dev/null +++ b/examples/bird-ospf/r1/bird.conf @@ -0,0 +1,38 @@ +router id from "lo2"; +log syslog name "bird-r1" all; + +protocol ospf { + area 0 { + interface "lo2" { + stub; + }; + interface "r2" { + type ptp; + }; + }; +} +protocol ospf v3 { + area 0 { + interface "lo2" { + stub; + }; + interface "r2" { + type ptp; + }; + }; +} + +protocol kernel { + ipv4 { + export all; + }; +} +protocol kernel { + ipv6 { + export all; + }; +} + +protocol device {} + +# vim: ft=conf diff --git a/examples/bird-ospf/r2/bird.conf b/examples/bird-ospf/r2/bird.conf new file mode 100644 index 0000000..c46a353 --- /dev/null +++ b/examples/bird-ospf/r2/bird.conf @@ -0,0 +1,38 @@ +router id from "lo2"; +log syslog name "bird-r2" all; + +protocol ospf { + area 0 { + interface "lo2" { + stub; + }; + interface "r1", "r3" { + type ptp; + }; + }; +} +protocol ospf v3 { + area 0 { + interface "lo2" { + stub; + }; + interface "r1", "r3" { + type ptp; + }; + }; +} + +protocol kernel { + ipv4 { + export all; + }; +} +protocol kernel { + ipv6 { + export all; + }; +} + +protocol device {} + +# vim: ft=conf diff --git a/examples/bird-ospf/r3/bird.conf b/examples/bird-ospf/r3/bird.conf new file mode 100644 index 0000000..82d11f5 --- /dev/null +++ b/examples/bird-ospf/r3/bird.conf @@ -0,0 +1,38 @@ +router id from "lo2"; +log syslog name "bird-r3" all; + +protocol ospf { + area 0 { + interface "lo2" { + stub; + }; + interface "r2" { + type ptp; + }; + }; +} +protocol ospf v3 { + area 0 { + interface "lo2" { + stub; + }; + interface "r2" { + type ptp; + }; + }; +} + +protocol kernel { + ipv4 { + export all; + }; +} +protocol kernel { + ipv6 { + export all; + }; +} + +protocol device {} + +# vim: ft=conf diff --git a/examples/podman-frr/lab.conf b/examples/podman-frr/lab.conf new file mode 100644 index 0000000..180f41d --- /dev/null +++ b/examples/podman-frr/lab.conf @@ -0,0 +1,12 @@ +# Start lab with: ./run.sh + +# r1 <-> r2 + + +net loops 3fff::/20 +net addrs 2001:db8::/32 + +node r1 loops +node r2 loops + +link r1 r2 addrs diff --git a/examples/podman-frr/r1/frr/daemons b/examples/podman-frr/r1/frr/daemons new file mode 100644 index 0000000..8b7a0d0 --- /dev/null +++ b/examples/podman-frr/r1/frr/daemons @@ -0,0 +1,7 @@ +ospf6d=yes + +vtysh_enable=yes +zebra_options=" -A 127.0.0.1 -s 90000000" +mgmtd_options=" -A 127.0.0.1" +ospf6d_options=" -A ::1" +staticd_options="-A 127.0.0.1" diff --git a/examples/podman-frr/r1/frr/frr.conf b/examples/podman-frr/r1/frr/frr.conf new file mode 100644 index 0000000..c096eb2 --- /dev/null +++ b/examples/podman-frr/r1/frr/frr.conf @@ -0,0 +1,19 @@ +frr defaults traditional +log syslog +! +ip router-id 192.0.2.0 +! +interface lo2 + ipv6 ospf6 area 0 + ipv6 ospf6 passive +exit +! +interface r2 + ipv6 ospf6 area 0 + ipv6 ospf6 network point-to-point +exit +! +router ospf6 + log-adjacency-changes +exit +! diff --git a/examples/podman-frr/r1/frr/vtysh.conf b/examples/podman-frr/r1/frr/vtysh.conf new file mode 100644 index 0000000..e69de29 diff --git a/examples/podman-frr/r2/frr/daemons b/examples/podman-frr/r2/frr/daemons new file mode 100644 index 0000000..8b7a0d0 --- /dev/null +++ b/examples/podman-frr/r2/frr/daemons @@ -0,0 +1,7 @@ +ospf6d=yes + +vtysh_enable=yes +zebra_options=" -A 127.0.0.1 -s 90000000" +mgmtd_options=" -A 127.0.0.1" +ospf6d_options=" -A ::1" +staticd_options="-A 127.0.0.1" diff --git a/examples/podman-frr/r2/frr/frr.conf b/examples/podman-frr/r2/frr/frr.conf new file mode 100644 index 0000000..bace1e9 --- /dev/null +++ b/examples/podman-frr/r2/frr/frr.conf @@ -0,0 +1,19 @@ +frr defaults traditional +log syslog +! +ip router-id 192.0.2.1 +! +interface lo2 + ipv6 ospf6 area 0 + ipv6 ospf6 passive +exit +! +interface r1 + ipv6 ospf6 area 0 + ipv6 ospf6 network point-to-point +exit +! +router ospf6 + log-adjacency-changes +exit +! diff --git a/examples/podman-frr/r2/frr/vtysh.conf b/examples/podman-frr/r2/frr/vtysh.conf new file mode 100644 index 0000000..e69de29 diff --git a/examples/podman-frr/run.sh b/examples/podman-frr/run.sh new file mode 100755 index 0000000..bda1830 --- /dev/null +++ b/examples/podman-frr/run.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +set -eu + + +podman_run() { + # ulimit to prevent warning from frr: "FD Limit set: 1048576 is stupidly + # large."; "/dev/log" to forward syslog to host, "ns" to run in network + # namespace + podman run --detach --rm \ + --cap-add cap_net_admin,cap_net_raw,cap_sys_admin \ + --ulimit nofile=1024 \ + --name "$1" \ + --volume "./$1/frr":/etc/frr \ + --volume /dev/log:/dev/log \ + --network ns:/run/netns/"$1" \ + quay.io/frrouting/frr:10.1.1 +} + +podman_stop() { + podman stop "$1" 2>/dev/null +} + + +podman_stop r1 || true +podman_stop r2 || true + +linux-network-namespace-labs up lab.conf + +podman_run r1 +podman_run r2 + +# Connect to podman container with `podman exec -it r1 bash` and then run +# `vtysh` to interact with frr. diff --git a/examples/readme/lab.conf b/examples/readme/lab.conf new file mode 100644 index 0000000..75d1248 --- /dev/null +++ b/examples/readme/lab.conf @@ -0,0 +1,21 @@ +# Start lab with: linux-network-namespace-labs up lab.conf + + +# Network range for loopback addresses of the nodes +net loops 192.0.2.0/24 3fff::/20 +# Network range for interfaces between nodes +net addrs 198.51.100.0/24 2001:db8::/32 + +# Setup three nodes (routers) and assign IPv4 and IPv6 loopback addresses +node r1 loops +node r2 loops +node r3 loops + +# Links between routers: /31 or /127 is used for each interface +link r1 r2 addrs +link r2 r3 addrs + +# Commands to run on each node; $1 is the node name (= name of network +# namespace). Here it's used to setup static routes but can also be used to +# start routing daemons like bird. +cmd ./setup.sh $1 diff --git a/examples/readme/lab.png b/examples/readme/lab.png new file mode 100644 index 0000000000000000000000000000000000000000..6cf20a0670e84cc07c4a56dcc0090c56a096221f GIT binary patch literal 27638 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

LuS!;bMvC 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%0Do| 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 literal 0 HcmV?d00001 diff --git a/examples/readme/setup.sh b/examples/readme/setup.sh new file mode 100755 index 0000000..a56a109 --- /dev/null +++ b/examples/readme/setup.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +set -eu + +if test "$1" = r1; then + # Loopbacks + ip r a 192.0.2.1/32 via 198.51.100.1 + ip r a 192.0.2.2/32 via 198.51.100.1 + ip r a 3fff::1/128 via 2001:db8::1 + ip r a 3fff::2/128 via 2001:db8::1 + # Link networks + ip r a 198.51.100.2/31 via 198.51.100.1 + ip r a 2001:db8::2/127 via 2001:db8::1 + +elif test "$1" = r2; then + # Loopbacks + ip r a 192.0.2.0/32 via 198.51.100.0 + ip r a 192.0.2.2/32 via 198.51.100.3 + ip r a 3fff::0/128 via 2001:db8::0 + ip r a 3fff::2/128 via 2001:db8::3 + +elif test "$1" = r3; then + # Loopbacks + ip r a 192.0.2.1/32 via 198.51.100.2 + ip r a 192.0.2.2/32 via 198.51.100.2 + ip r a 3fff::0/128 via 2001:db8::2 + ip r a 3fff::1/128 via 2001:db8::2 + # Link networks + ip r a 198.51.100.0/31 via 198.51.100.2 + ip r a 2001:db8::0/127 via 2001:db8::2 + +fi -- 2.45.2