├── .deepsource.toml
├── .devcontainer
├── Dockerfile
├── dclab
├── docker-in-docker
│ └── devcontainer.json
├── docker-in-docker_slim
│ └── devcontainer.json
├── docker-outside-of-docker
│ └── devcontainer.json
├── docker-outside-of-docker_slim
│ └── devcontainer.json
├── slim.Dockerfile
└── zsh
│ ├── .p10k.zsh
│ ├── .zshrc
│ ├── .zshrc-slim
│ ├── install-tools-completions.sh
│ └── install-zsh-plugins.sh
├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ ├── build-containerlab.yml
│ ├── build-devcontainer.yml
│ ├── cicd.yml
│ ├── cisco_iol-tests.yml
│ ├── codeql-analysis.yml
│ ├── fdio_vpp-tests.yml
│ ├── force-build.yml
│ ├── fortigate-tests.yml
│ ├── golangci-lint.yml
│ ├── install-podman.sh
│ ├── kind-tests.yml
│ ├── smoke-tests.yml
│ ├── srlinux-tests.yml
│ ├── sros-tests.yml
│ └── vxlan-tests.yml
├── .gitignore
├── .gitlab-ci.yml
├── .golangci.yml
├── .goreleaser.yml
├── .markdownlint.yml
├── .mk
└── lint.mk
├── .pre-commit-config.yaml
├── LICENSE
├── Makefile
├── README.md
├── cert
├── ca.go
├── cert.go
├── certificate.go
├── csr_input.go
└── local_dir_cert_storage.go
├── clab
├── authz_keys.go
├── cert.go
├── clab.go
├── clab_test.go
├── config.go
├── config
│ ├── send.go
│ ├── template.go
│ ├── templates
│ │ ├── base__srl.tmpl
│ │ ├── base__vr-sros.tmpl
│ │ └── srl-ifaces__srl.tmpl
│ ├── transport
│ │ ├── ssh.go
│ │ ├── sshkind.go
│ │ └── transport.go
│ ├── utils.go
│ └── utils_test.go
├── config_test.go
├── dependency_manager
│ ├── dependency_manager.go
│ ├── dependency_manager_test.go
│ ├── dependency_node.go
│ └── depender_node_stage.go
├── deploy_options.go
├── exec
│ ├── exec.go
│ └── exec_test.go
├── exec_options.go
├── export.go
├── export_templates
│ ├── auto.tmpl
│ └── full.tmpl
├── file.go
├── graph.go
├── graph_templates
│ └── nextui
│ │ ├── LICENSE.txt
│ │ ├── nextui.html
│ │ └── static
│ │ ├── css
│ │ ├── next.css
│ │ └── tailwind.css
│ │ ├── fonts
│ │ ├── CiscoSansExtraLight.otf
│ │ ├── CiscoSansRegular.otf
│ │ ├── ciscosansextralight-webfont.eot
│ │ ├── ciscosansextralight-webfont.svg
│ │ ├── ciscosansextralight-webfont.ttf
│ │ ├── ciscosansextralight-webfont.woff
│ │ ├── ciscosansregular-webfont.eot
│ │ ├── ciscosansregular-webfont.svg
│ │ ├── ciscosansregular-webfont.ttf
│ │ ├── ciscosansregular-webfont.woff
│ │ ├── next-font.eot
│ │ ├── next-font.svg
│ │ ├── next-font.ttf
│ │ └── next-font.woff
│ │ └── js
│ │ ├── next.js
│ │ └── script.js
├── hostsfile.go
├── inventory.go
├── inventory_ansible.go.tpl
├── inventory_nornir_simple.go.tpl
├── inventory_test.go
├── network.go
├── register.go
├── ssh_config.go.tpl
├── sshconfig.go
└── test_data
│ ├── clab-topo2
│ └── node1
│ │ └── node1
│ ├── default.lic
│ ├── envfile1
│ ├── envfile2
│ ├── kind.lic
│ ├── node1.lic
│ ├── topo1.yml
│ ├── topo10.yml
│ ├── topo11-ext-cont.yaml
│ ├── topo12.yml
│ ├── topo13.yml
│ ├── topo14.yml
│ ├── topo15.yml
│ ├── topo2.yml
│ ├── topo3.yml
│ ├── topo4.yml
│ ├── topo5.yml
│ ├── topo6.yml
│ ├── topo7-dup-rootnetns.yml
│ ├── topo8_ansible_groups.yml
│ ├── topo8_nornir_groups.yml
│ └── topo9.yml
├── cmd
├── common
│ ├── common.go
│ └── sudo.go
├── completion.go
├── config.go
├── config_template.go
├── deploy.go
├── destroy.go
├── disableTxOffload.go
├── exec.go
├── generate.go
├── generate_test.go
├── graph.go
├── inspect
│ ├── inspect.go
│ └── inspect_interfaces.go
├── redeploy.go
├── root.go
├── save.go
├── tool_sshx.go
├── tools.go
├── tools_api.go
├── tools_api_start.go
├── tools_api_status.go
├── tools_api_stop.go
├── tools_cert.go
├── tools_netem.go
├── tools_veth.go
├── version
│ ├── check.go
│ ├── logo.txt
│ ├── upgrade.go
│ ├── version.go
│ └── version_test.go
└── vxlan.go
├── codecov.yml
├── docs
├── CNAME
├── cmd
│ ├── completion.md
│ ├── deploy.md
│ ├── destroy.md
│ ├── exec.md
│ ├── generate.md
│ ├── graph.md
│ ├── inspect
│ │ ├── index.md
│ │ └── interfaces.md
│ ├── redeploy.md
│ ├── save.md
│ ├── tools
│ │ ├── api-server
│ │ │ ├── start.md
│ │ │ ├── status.md
│ │ │ └── stop.md
│ │ ├── cert
│ │ │ ├── ca
│ │ │ │ └── create.md
│ │ │ └── sign.md
│ │ ├── disable-tx-offload.md
│ │ ├── netem
│ │ │ ├── reset.md
│ │ │ ├── set.md
│ │ │ └── show.md
│ │ ├── sshx
│ │ │ ├── attach.md
│ │ │ ├── detach.md
│ │ │ ├── list.md
│ │ │ └── reattach.md
│ │ ├── veth
│ │ │ └── create.md
│ │ └── vxlan
│ │ │ ├── create.md
│ │ │ └── delete.md
│ └── version
│ │ ├── check.md
│ │ └── index.md
├── community.md
├── htmltest-w-github.yml
├── htmltest.yml
├── images
│ ├── containerlab-og.png
│ ├── containerlab_black.png
│ ├── containerlab_dark_no_text.svg
│ ├── containerlab_export.svg
│ ├── containerlab_export_white_ink.svg
│ ├── containerlab_export_white_ink_js.svg
│ ├── containerlab_full_white_no_text.svg
│ ├── containerlab_grey.pdf
│ ├── containerlab_grey.png
│ ├── containerlab_white_no_text.svg
│ ├── favicon.svg
│ ├── flask.svg
│ └── topoviewer-icons
│ │ ├── client.svg
│ │ ├── controller.svg
│ │ ├── dcgw.svg
│ │ ├── pon.svg
│ │ ├── rgw.svg
│ │ ├── router.svg
│ │ ├── server.svg
│ │ ├── spine.svg
│ │ └── switch.svg
├── index.md
├── install.md
├── lab-examples
│ ├── bgp-vpls-nok-jun.md
│ ├── cvx01.md
│ ├── cvx02.md
│ ├── ext-bridge.md
│ ├── freebsd01.md
│ ├── frr01.md
│ ├── ftdv01.md
│ ├── generic_vm01.md
│ ├── ixiacone-srl.md
│ ├── lab-examples.md
│ ├── min-5clos.md
│ ├── min-clos.md
│ ├── multinode.md
│ ├── openbsd01.md
│ ├── ost-srl.md
│ ├── peering-lab.md
│ ├── rare-freertr.md
│ ├── single-srl.md
│ ├── srl-ceos.md
│ ├── srl-crpd.md
│ ├── srl-frr.md
│ ├── srl-sonic.md
│ ├── srl-vjunos-switch.md
│ ├── srl-vjunosevolved.md
│ ├── srl-xrd.md
│ ├── templated01.md
│ ├── templated02.md
│ ├── two-srls.md
│ ├── vr-sros.md
│ ├── vr-vmx.md
│ ├── vr-xrv.md
│ ├── vr-xrv9k.md
│ ├── vsrx01.md
│ └── wan.md
├── macos.md
├── manual
│ ├── cert.md
│ ├── clabernetes
│ │ ├── index.md
│ │ ├── install.md
│ │ ├── pcap.md
│ │ └── quickstart.md
│ ├── codespaces.md
│ ├── conf-artifacts.md
│ ├── config-mgmt.md
│ ├── dev
│ │ ├── debug.md
│ │ ├── doc.md
│ │ ├── index.md
│ │ └── test.md
│ ├── images.md
│ ├── impairments.md
│ ├── inventory.md
│ ├── kinds
│ │ ├── 6wind_vsr.md
│ │ ├── bridge.md
│ │ ├── c8000.md
│ │ ├── ceos.md
│ │ ├── checkpoint_cloudguard.md
│ │ ├── cisco_iol.md
│ │ ├── crpd.md
│ │ ├── cvx.md
│ │ ├── dell_sonic.md
│ │ ├── ext-container.md
│ │ ├── fdio_vpp.md
│ │ ├── fortinet_fortigate.md
│ │ ├── freebsd.md
│ │ ├── generic_vm.md
│ │ ├── host.md
│ │ ├── huawei_vrp.md
│ │ ├── index.md
│ │ ├── ipinfusion-ocnos.md
│ │ ├── k8s-kind.md
│ │ ├── keysight_ixia-c-one.md
│ │ ├── linux.md
│ │ ├── openbsd.md
│ │ ├── openwrt.md
│ │ ├── ostinato.md
│ │ ├── ovs-bridge.md
│ │ ├── rare-freertr.md
│ │ ├── sonic-vm.md
│ │ ├── sonic-vs.md
│ │ ├── srl.md
│ │ ├── vr-aoscx.md
│ │ ├── vr-c8000v.md
│ │ ├── vr-cat9kv.md
│ │ ├── vr-csr.md
│ │ ├── vr-ftdv.md
│ │ ├── vr-ftosv.md
│ │ ├── vr-n9kv.md
│ │ ├── vr-pan.md
│ │ ├── vr-ros.md
│ │ ├── vr-sros.md
│ │ ├── vr-veos.md
│ │ ├── vr-vjunosevolved.md
│ │ ├── vr-vjunosrouter.md
│ │ ├── vr-vjunosswitch.md
│ │ ├── vr-vmx.md
│ │ ├── vr-vqfx.md
│ │ ├── vr-vsrx.md
│ │ ├── vr-xrv.md
│ │ ├── vr-xrv9k.md
│ │ └── xrd.md
│ ├── multi-node.md
│ ├── network.md
│ ├── node-filtering.md
│ ├── nodes.md
│ ├── share-access.md
│ ├── topo-def-file.md
│ ├── vrnetlab.md
│ ├── vsc-extension.md
│ └── wireshark.md
├── overrides
│ ├── .icons
│ │ └── clab
│ │ │ └── icon.svg
│ ├── main.html
│ └── partials
│ │ ├── comments.html
│ │ └── copyright.html
├── quickstart.md
├── rn
│ ├── 0.11.0.md
│ ├── 0.12.0.md
│ ├── 0.13.0.md
│ ├── 0.14.0.md
│ ├── 0.14.1.md
│ ├── 0.14.2.md
│ ├── 0.14.3.md
│ ├── 0.14.4.md
│ ├── 0.15.md
│ ├── 0.16.md
│ ├── 0.17.md
│ ├── 0.18.md
│ ├── 0.19.md
│ ├── 0.20.md
│ ├── 0.21.md
│ ├── 0.22.md
│ ├── 0.23.md
│ ├── 0.24.md
│ ├── 0.25.md
│ ├── 0.26.md
│ ├── 0.27.md
│ ├── 0.28.md
│ ├── 0.29.md
│ ├── 0.30.md
│ ├── 0.31.md
│ ├── 0.32.md
│ ├── 0.33.md
│ ├── 0.34.md
│ ├── 0.35.md
│ ├── 0.36.md
│ ├── 0.37.md
│ ├── 0.38.md
│ ├── 0.39.md
│ ├── 0.40.md
│ ├── 0.41.md
│ ├── 0.42.md
│ ├── 0.43.md
│ ├── 0.44.md
│ ├── 0.45.md
│ ├── 0.46.md
│ ├── 0.47.md
│ ├── 0.48.md
│ ├── 0.49.md
│ ├── 0.50.md
│ ├── 0.51.md
│ ├── 0.52.md
│ ├── 0.53.md
│ ├── 0.54.md
│ ├── 0.55.md
│ ├── 0.56.md
│ ├── 0.57.md
│ ├── 0.58.md
│ ├── 0.59.md
│ ├── 0.60.md
│ ├── 0.61.md
│ ├── 0.62.md
│ ├── 0.63.md
│ ├── 0.64.md
│ ├── 0.65.md
│ ├── 0.66.md
│ ├── 0.67.md
│ └── 0.68.md
├── stylesheets
│ └── extra.css
└── windows.md
├── errors
└── errors.go
├── get.sh
├── git
├── __repo_parser_test.go
├── git.go
├── github.go
├── github_test.go
├── gitlab.go
├── gitlab_test.go
└── repo.go
├── go.mod
├── go.sum
├── goreleaser.dockerfile
├── internal
├── mermaid
│ └── graph.go
├── slices
│ └── slices.go
└── tc
│ └── tc.go
├── lab-examples
├── .gitignore
├── br01
│ └── br01.clab.yml
├── cert01
│ └── cert01.clab.yml
├── clos01
│ └── clos01.clab.yml
├── clos02
│ ├── README.md
│ ├── clos02.clab.yml
│ ├── configs
│ │ ├── client1.sh
│ │ ├── client2.sh
│ │ ├── client3.sh
│ │ ├── client4.sh
│ │ ├── leaf1.yaml
│ │ ├── leaf2.yaml
│ │ ├── leaf3.yaml
│ │ ├── leaf4.yaml
│ │ ├── spine1.yaml
│ │ ├── spine2.yaml
│ │ ├── spine3.yaml
│ │ ├── spine4.yaml
│ │ ├── superspine1.yaml
│ │ └── superspine2.yaml
│ ├── setup.clos02.clab.yml
│ └── setup.sh
├── cvx01
│ ├── README.md
│ ├── sw1
│ │ └── interfaces
│ ├── sw2
│ │ └── frr.conf
│ └── topo.clab.yml
├── cvx02
│ ├── README.md
│ ├── h1
│ │ └── interfaces
│ ├── sw1
│ │ └── interfaces
│ └── topo.clab.yml
├── fortigate
│ └── fortigate.clab.yml
├── freebsd01
│ └── freebsd01.clab.yml
├── frr01
│ ├── PC-interfaces.sh
│ ├── README.md
│ ├── frr01.clab.yml
│ ├── router1
│ │ ├── daemons
│ │ └── frr.conf
│ ├── router2
│ │ ├── daemons
│ │ └── frr.conf
│ ├── router3
│ │ ├── daemons
│ │ └── frr.conf
│ └── run.sh
├── ftdv01
│ └── ftdv01.yml
├── generic_vm01
│ └── generic_vm.clab.yml
├── ixiac01
│ ├── go.mod
│ ├── go.sum
│ ├── ipv4_forwarding.go
│ ├── ixiac01.clab.yml
│ └── srl.cfg
├── k8s_kind01
│ ├── k01-config.yaml
│ └── k8s_kind01.clab.yml
├── openbsd01
│ └── openbsd01.yml
├── ost-srl
│ ├── ost-srl.clab.yml
│ ├── ost-srl.ossn
│ └── srl.cfg
├── sonic01
│ └── sonic01.clab.yml
├── srl-quickstart
│ ├── srl01.clab.yml
│ └── srl02.clab.yml
├── srl01
│ └── srl01.clab.yml
├── srl02
│ ├── srl02.clab.yml
│ ├── srl1.cfg
│ └── srl2.cfg
├── srl03
│ └── srl03.clab.yml
├── srlceos01
│ └── srlceos01.clab.yml
├── srlcrpd01
│ └── srlcrpd01.clab.yml
├── srlfrr01
│ ├── daemons
│ ├── frr.cfg
│ ├── srl.cfg
│ └── srlfrr01.clab.yml
├── srlvjunos01
│ ├── srl.cli
│ ├── srlvjunos01.clab.yml
│ └── vjunos.cfg
├── srlvjunos02
│ ├── srl.cli
│ ├── srlvjunos02.clab.yml
│ └── vjunos.cfg
├── srlxrd01
│ ├── srl.cfg
│ ├── srlxrd01.clab.yml
│ └── xrd.cfg
├── templated01
│ ├── configure.sh
│ ├── templated01.clab.gotmpl
│ ├── templated01.clab_vars.yaml
│ └── topology_config.gotmpl
├── templated02
│ ├── configure.sh
│ ├── templated02.clab.gotmpl
│ ├── templated02.clab_vars.yaml
│ └── topology_config.gotmpl
├── vr01
│ ├── srl.cfg
│ ├── sros.cfg
│ └── vr01.clab.yml
├── vr02
│ ├── srl.cfg
│ ├── vmx.cfg
│ └── vr02.clab.yml
├── vr03
│ ├── srl.cfg
│ ├── vr03.clab.yml
│ └── xrv.cfg
├── vr04
│ ├── srl.cfg
│ ├── vr04.clab.yml
│ └── xrv9k.cfg
├── vr05
│ ├── sros4.clab.yml
│ └── vr01.clab.yml
├── vsrx01
│ ├── srx1.cfg
│ └── vsrx01.yml
└── vxlan01
│ ├── vxlan-sros.clab.yml
│ └── vxlan-vmx.clab.yml
├── labels
└── labels.go
├── links
├── endpoint.go
├── endpoint_bridge.go
├── endpoint_dummy.go
├── endpoint_host.go
├── endpoint_macvlan.go
├── endpoint_raw.go
├── endpoint_veth.go
├── endpoint_vxlan.go
├── generic_link_node.go
├── link.go
├── link_brief.go
├── link_dummy.go
├── link_host.go
├── link_macvlan.go
├── link_mgmt-net.go
├── link_test.go
├── link_veth.go
├── link_veth_test.go
├── link_vxlan.go
└── link_vxlan_stitched.go
├── macros
└── main.py
├── main.go
├── mkdocs.yml
├── mocks
├── dependency_manager.go
├── exec.go
├── mocknodes
│ ├── default_node.go
│ └── node.go
└── mockruntime
│ └── runtime.go
├── netconf
└── netconf.go
├── nodes
├── 6wind_vsr
│ ├── 6wind_vsr.go
│ └── 6wind_vsr_default_config.go.tpl
├── bridge
│ └── bridge.go
├── c8000
│ ├── c8000.cfg
│ └── c8000.go
├── ceos
│ ├── ceos.cfg
│ └── ceos.go
├── checkpoint_cloudguard
│ └── checkpoint_cloudguard.go
├── crpd
│ ├── crpd.cfg
│ ├── crpd.go
│ └── sshd_config
├── cvx
│ └── cvx.go
├── default_node.go
├── default_node_test.go
├── dell_sonic
│ └── dell_sonic.go
├── ext_container
│ └── ext_container.go
├── fdio_vpp
│ ├── fdio_vpp.go
│ └── vpp_startup_config.go.tpl
├── fortinet_fortigate
│ ├── fortigate.go
│ └── fortigate_test.go
├── generic_vm
│ └── generic_vm.go
├── host
│ └── host.go
├── huawei_vrp
│ └── huawei_vrp.go
├── iol
│ ├── iol.cfg.tmpl
│ └── iol.go
├── ipinfusion_ocnos
│ └── ipinfusion_ocnos.go
├── k8s_kind
│ ├── k8s_kind.go
│ └── logger.go
├── keysight_ixiacone
│ └── ixiac-one.go
├── linux
│ └── linux.go
├── node.go
├── node_registry.go
├── ovs
│ └── ovs.go
├── rare
│ └── rare.go
├── sonic
│ └── sonic.go
├── sonic_vm
│ └── sonic_vm.go
├── srl
│ ├── banner.go
│ ├── eda.go
│ ├── macaddr.go
│ ├── prompt.go
│ ├── prompt_test.go
│ ├── srl.go
│ ├── srl_default_config.go.tpl
│ ├── srl_test.go
│ ├── test_data
│ │ └── rsa_key
│ ├── topology
│ │ ├── 7215IXSA1.yml
│ │ ├── 7220IXRD1.yml
│ │ ├── 7220IXRD2.yml
│ │ ├── 7220IXRD2L.yml
│ │ ├── 7220IXRD3.yml
│ │ ├── 7220IXRD3L.yml
│ │ ├── 7220IXRD4.yml
│ │ ├── 7220IXRD5.yml
│ │ ├── 7220IXRH2.yml
│ │ ├── 7220IXRH3.yml
│ │ ├── 7220IXRH4-32D.yml
│ │ ├── 7220IXRH4.yml
│ │ ├── 7220IXRH5-32D.yml
│ │ ├── 7220IXRH5-64D.yml
│ │ ├── 7220IXRH5-64O.yml
│ │ ├── 7250IXR10.yml
│ │ ├── 7250IXR10e.yml
│ │ ├── 7250IXR18e.yml
│ │ ├── 7250IXR6.yml
│ │ ├── 7250IXR6e.yml
│ │ ├── 7250IXRX1b.yml
│ │ ├── 7250IXRX3b.yml
│ │ ├── 7730SXR-1d-32d.yml
│ │ └── 7730SXR-1x-44s.yml
│ ├── version.go
│ └── version_test.go
├── state
│ └── state.go
├── vr_aoscx
│ ├── vr-aoscx.go
│ └── vr-aoscx_test.go
├── vr_c8000v
│ ├── vr-c8000v.go
│ └── vr-c8000v_test.go
├── vr_cat9kv
│ └── vr-cat9kv.go
├── vr_csr
│ ├── vr-csr.go
│ └── vr-csr_test.go
├── vr_freebsd
│ ├── vr-freebsd.go
│ └── vr-freebsd_test.go
├── vr_ftdv
│ ├── vr-ftdv.go
│ └── vr-ftdv_test.go
├── vr_ftosv
│ └── vr-ftosv.go
├── vr_n9kv
│ ├── vr-n9kv.go
│ └── vr-n9kv_test.go
├── vr_node.go
├── vr_node_test.go
├── vr_openbsd
│ ├── vr-openbsd.go
│ └── vr-openbsd_test.go
├── vr_openwrt
│ └── vr_openwrt.go
├── vr_pan
│ ├── vr-pan.go
│ └── vr-pan_test.go
├── vr_ros
│ ├── vr-ros.go
│ └── vr-ros_test.go
├── vr_sros
│ ├── sshKey.go
│ ├── sshKey_test.go
│ ├── ssh_keys.go.tpl
│ ├── vr-sros.go
│ └── vr-sros_test.go
├── vr_veos
│ ├── vr-veos.go
│ └── vr-veos_test.go
├── vr_vjunosevolved
│ ├── vr-vjunosevolved.go
│ └── vr-vjunosevolved_test.go
├── vr_vjunosswitch
│ ├── vr-vjunosswitch.go
│ └── vr-vjunosswitch_test.go
├── vr_vmx
│ ├── vr-vmx.go
│ └── vr-vmx_test.go
├── vr_vqfx
│ ├── vr-vqfx.go
│ └── vr-vqfx_test.go
├── vr_vsrx
│ ├── vr-vsrx.go
│ └── vr-vsrx_test.go
├── vr_xrv
│ ├── vr-vrx_test.go
│ └── vr-xrv.go
├── vr_xrv9k
│ ├── vr-xrv9k.go
│ └── vr-xrv9k_test.go
└── xrd
│ ├── mgmt_intf_v6_addr.sh.tmpl
│ ├── xrd.cfg
│ └── xrd.go
├── pyproject.toml
├── runtime
├── all
│ ├── all.go
│ └── all_with_podman.go
├── docker
│ ├── auth.go
│ ├── auth_test.go
│ ├── docker.go
│ ├── firewall.go
│ ├── firewall
│ │ ├── definitions
│ │ │ └── definitions.go
│ │ ├── firewall.go
│ │ ├── iptables
│ │ │ └── client.go
│ │ └── nftables
│ │ │ ├── client.go
│ │ │ └── rule.go
│ └── test_data
│ │ ├── docker.config
│ │ └── invalid_docker.config
├── generic_container.go
├── ignite
│ └── ignite.go
├── podman
│ ├── podman.go
│ ├── portmaps.go
│ └── util.go
└── runtime.go
├── schemas
└── clab.schema.json
├── tests
├── 01-smoke
│ ├── 01-basic-flow.robot
│ ├── 01-linux-nodes.clab.yml
│ ├── 01-linux-single-node.clab.yml
│ ├── 01-test.json
│ ├── 01-test.txt
│ ├── 02-destroy-all.robot
│ ├── 03-bridges-and-host.robot
│ ├── 03-linux-nodes-to-bridge-and-host.clab.yml
│ ├── 04-generate.robot
│ ├── 05-docker-bridge.clab.yml
│ ├── 05-docker-bridge.robot
│ ├── 06-tools-certs.robot
│ ├── 07-keep-mgmt-net.robot
│ ├── 07-linux-single-node.clab.yml
│ ├── 08-tools-cmds.robot
│ ├── 09-external-ca.clab.yml
│ ├── 09-external-ca.robot
│ ├── 10-ca-parameter.robot
│ ├── 10-internal-ca.clab.yml
│ ├── 11-node-filter.robot
│ ├── 12-tools-veth.clab.yaml
│ ├── 12-tools-veth.robot
│ ├── 13-stdin-lab.robot
│ ├── 14-macvlan.robot
│ ├── 15-netw-modes.robot
│ ├── 16-mgmtnet.robot
│ ├── 16-mgmtnetinterface.clab.yml
│ ├── 17-cloned-lab.robot
│ ├── 18-stages.robot
│ ├── 19-stages-race.robot
│ ├── 20-graph-generation.robot
│ ├── 21-tools-sshx.robot
│ ├── 22-tools-api-server.robot
│ ├── macvlan.clab.yml
│ ├── netmodes.clab.yml
│ ├── node-filter.clab.yml
│ ├── single-topo-folder
│ │ └── lab1.clab.yml
│ ├── stages-race.clab.yml
│ └── stages.clab.yml
├── 02-basic-srl
│ ├── 01-two-srls.robot
│ ├── 02-srl02.clab.yml
│ ├── 03-srl-bgp.clab.yml
│ ├── 03-srl-bgp.robot
│ ├── 03-srl1-bgp.config
│ ├── 03-srl2-bgp.config
│ ├── srl1-startup.cli
│ └── srl2-startup.cli
├── 03-basic-ceos
│ ├── 01-two-ceos.robot
│ └── 03-ceos01-clab.yml
├── 04-basic-ixiacone
│ ├── 01-ixiacone.robot
│ └── 04-ixiacone01-clab.yml
├── 05-k8s-kind
│ ├── 01-basic-k8s-kind.clab.yml
│ ├── 01-basic-k8s-kind.robot
│ └── k01-config.yaml
├── 06-ext-container
│ ├── 01-ext-container.clab.yml
│ ├── 01-ext-container.robot
│ ├── 02-shared-namespace-ext.clab.yaml
│ ├── 02-shared-namespace.clab.yaml
│ └── 02-shared-namespace.robot
├── 07-sros
│ ├── 01-single-sros.robot
│ └── 1-sros.clab.yml
├── 08-vxlan
│ ├── 01-vxlan-s1.config
│ ├── 01-vxlan.clab.yml
│ ├── 01-vxlan.robot
│ ├── 02-vxlan-stitch.clab.yml
│ ├── 02-vxlan-stitch.robot
│ ├── 03-tools-veth-vxlan.robot
│ └── 03-vxlan-tools.clab.yml
├── 09-fortigate
│ ├── 01-two-fortigates.robot
│ └── fortigates.clab.yml
├── 10-basic-cisco_iol
│ ├── 01-iol.robot
│ ├── iol.clab.yml
│ ├── loopback_config.partial
│ └── router3-full.cfg
├── 11-fdio-vpp
│ ├── 01-e2e-lab.robot
│ └── e2e-lab
│ │ ├── config
│ │ ├── vpp1
│ │ │ ├── bird-local.conf
│ │ │ └── vppcfg.yaml
│ │ └── vpp2
│ │ │ ├── bird-local.conf
│ │ │ └── vppcfg.yaml
│ │ └── vpp.clab.yml
├── common.robot
├── rf-run.sh
└── ssh.robot
├── types
├── bind.go
├── constants.go
├── host_requirements.go
├── license_policy_value.go
├── node_definition.go
├── settings.go
├── ssh_config.go
├── stages.go
├── stages_test.go
├── test_data
│ ├── config.cfg
│ └── lic1.key
├── topo_paths.go
├── topology.go
├── topology_test.go
└── types.go
├── utils
├── containers.go
├── containers_test.go
├── env.go
├── env_test.go
├── ethtool.go
├── file.go
├── file_test.go
├── firacode-download.ps1
├── if-wait.go
├── ip.go
├── kernel_module.go
├── kernel_module_test.go
├── keys.go
├── netlink.go
├── networkcli.go
├── password.go
├── pointer.go
├── postinstall.sh
├── process.go
├── quick-setup.sh
├── regexp.go
├── resolve.go
├── resolve_test.go
├── ssh.go
├── ssh_test.go
├── template.go
├── template_test.go
├── test_data
│ ├── keys
│ └── keys1.txt
└── userauth.go
├── uv.lock
└── virt
├── memory.go
└── virt.go
/.deepsource.toml:
--------------------------------------------------------------------------------
1 | version = 1
2 |
3 | test_patterns = ["*/*_test.go"]
4 |
5 | [[analyzers]]
6 | name = "go"
7 | enabled = true
8 |
9 | [analyzers.meta]
10 | import_root = "github.com/srl-labs/containerlab"
11 |
--------------------------------------------------------------------------------
/.devcontainer/dclab:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | /clab/bin/containerlab "$@"
3 |
--------------------------------------------------------------------------------
/.devcontainer/zsh/install-tools-completions.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | gnmic completion zsh > "/home/vscode/.oh-my-zsh/custom/plugins/zsh-autocomplete/Completions/_gnmic"
3 | # generate gnoic completions
4 | gnoic completion zsh > "/home/vscode/.oh-my-zsh/custom/plugins/zsh-autocomplete/Completions/_gnoic"
5 | # generate gh
6 | gh completion -s zsh > "/home/vscode/.oh-my-zsh/custom/plugins/zsh-autocomplete/Completions/_gh"
7 |
--------------------------------------------------------------------------------
/.devcontainer/zsh/install-zsh-plugins.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # atuin
3 | # bash <(curl --proto '=https' --tlsv1.2 -sSf https://setup.atuin.sh)
4 | curl -LsSf https://github.com/atuinsh/atuin/releases/download/v18.3.0/atuin-installer.sh | sh
5 |
6 | # theme
7 | git clone --depth 1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k
8 |
9 | # zsh-autosuggestions and autocompletions
10 | git clone --depth 1 https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
11 | git clone --depth 1 https://github.com/marlonrichert/zsh-autocomplete.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autocomplete
12 |
13 | # syntax highlighting
14 | git clone --depth 1 https://github.com/z-shell/F-Sy-H.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/F-Sy-H
15 |
16 | ###
17 | ### Shell completions
18 | ###
19 | # generate containerlab completions
20 | /usr/bin/containerlab completion zsh > "/home/vscode/.oh-my-zsh/custom/plugins/zsh-autocomplete/Completions/_containerlab"
21 | # add clab alias to the completions
22 | sed -i 's/compdef _containerlab containerlab/compdef _containerlab containerlab clab/g' /home/vscode/.oh-my-zsh/custom/plugins/zsh-autocomplete/Completions/_containerlab
23 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Do not detect languages in the following folders
2 | templates/** -linguist-detectable
3 | docs/** -linguist-detectable
4 | lab-examples/** -linguist-detectable
5 | # nextui is vendored
6 | clab/graph_templates/nextui/** linguist-vendored
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2 |
3 | version: 2
4 | updates:
5 | - package-ecosystem: "github-actions"
6 | directory: "/"
7 | schedule:
8 | interval: "weekly"
9 | - package-ecosystem: "gomod"
10 | directory: "/"
11 | schedule:
12 | interval: "weekly"
13 |
--------------------------------------------------------------------------------
/.github/workflows/build-containerlab.yml:
--------------------------------------------------------------------------------
1 | name: build-clab
2 |
3 | "on":
4 | workflow_call:
5 | inputs:
6 | go_ver:
7 | required: true
8 | type: string
9 |
10 | jobs:
11 | build-clab:
12 | runs-on: ubuntu-22.04
13 | steps:
14 | - uses: actions/checkout@v4
15 | - uses: WillAbides/setup-go-faster@v1.14.0
16 | with:
17 | go-version: ${{ inputs.go_ver }}
18 |
19 | - name: Cache go modules
20 | uses: actions/cache@v4
21 | with:
22 | # In order:
23 | # * Module download cache
24 | # * Build cache (Linux)
25 | path: |
26 | ~/go/pkg/mod
27 | ~/.cache/go-build
28 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
29 | restore-keys: |
30 | ${{ runner.os }}-go-
31 |
32 | - name: Build containerlab
33 | run: make build-with-podman-debug BINARY=containerlab
34 | # store clab binary as artifact
35 | - name: Upload containerlab binary
36 | uses: actions/upload-artifact@v4
37 | with:
38 | name: containerlab
39 | path: containerlab
40 | compression-level: 0
41 |
--------------------------------------------------------------------------------
/.github/workflows/golangci-lint.yml:
--------------------------------------------------------------------------------
1 | name: golangci-lint
2 | on:
3 | workflow_dispatch:
4 | jobs:
5 | golangci:
6 | name: lint
7 | runs-on: ubuntu-20.04
8 | steps:
9 | - uses: actions/checkout@v4
10 | - name: golangci-lint
11 | uses: golangci/golangci-lint-action@v8
12 | with:
13 | version: v1.38
14 |
--------------------------------------------------------------------------------
/.github/workflows/install-podman.sh:
--------------------------------------------------------------------------------
1 | sudo apt purge -y podman
2 | sudo mkdir -p /etc/apt/keyrings
3 | curl -fsSL "https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/Release.key" \
4 | | gpg --dearmor \
5 | | sudo tee /etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg > /dev/null
6 |
7 | echo \
8 | "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/devel_kubic_libcontainers_unstable.gpg]\
9 | https://download.opensuse.org/repositories/devel:kubic:libcontainers:unstable/xUbuntu_$(lsb_release -rs)/ /" \
10 | | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list > /dev/null
11 |
12 | sudo apt-get update -qq
13 | sudo apt-get -qq -y install podman
14 | sudo systemctl start podman
15 | sudo mkdir -p /var/run/netns
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 | bin
8 | bin/*
9 | rpm
10 | rpm/*
11 | dist
12 | private
13 | clab-*
14 | .envrc
15 |
16 | tmp/
17 | # Test binary, built with `go test -c`
18 | *.test
19 |
20 | # Output of the go coverage tool, specifically when used with LiteIDE
21 | *.out
22 | tests/coverage
23 |
24 | # clab directories
25 | lab-examples/**/clab-*
26 |
27 | # ignore the following files/directories
28 | graph/*
29 |
30 | license.key
31 | container-lab
32 | containerlab
33 | site/
34 | .vscode/
35 | .idea/
36 | .DS_Store
37 | __rd*
38 | tests/out
39 | # ignore backup clab topo files
40 | **/.*clab.y*ml.bak
41 | **/*.y*ml.bak
42 |
43 | .python-version
44 |
45 | .devcontainer/private-*
46 |
47 |
48 | # readd test labDir files
49 | !clab/test_data/clab-*
50 | __pycache__
--------------------------------------------------------------------------------
/.markdownlint.yml:
--------------------------------------------------------------------------------
1 | "MD007": false # allow 4 spaced indentation for ul as this is used by mkdocs for nested lists
2 | "MD026": false # allow trailing punctuation to support icons shortcodes at the end of a sentence
3 | "MD038": false
4 | "MD033": false # inline html
5 | "MD013": false # line-length
6 | "MD040": false # fenced code blocks should have language selected
7 | "MD053": false # do not remove mkdocs materials footnotes
8 | "MD071": false # do not remove unordered list indentation
9 | "MD034": false # do not add angle brackets around bare links
10 |
--------------------------------------------------------------------------------
/.mk/lint.mk:
--------------------------------------------------------------------------------
1 | GOFUMPT_CMD := docker run --rm -it -e GOFUMPT_SPLIT_LONG_LINES=on -v $(CURDIR):/work ghcr.io/hellt/gofumpt:v0.7.0
2 | GOFUMPT_FLAGS := -l -w .
3 |
4 | GODOT_CMD := docker run --rm -it -v $(CURDIR):/work ghcr.io/hellt/godot:1.4.11
5 | GODOT_FLAGS := -w .
6 |
7 | GOLANGCI_CMD := docker run -it --rm -v $(CURDIR):/app -w /app golangci/golangci-lint:v1.47.2 golangci-lint
8 | GOLANGCI_FLAGS := --config ./.github/workflows/linters/.golangci.yml run -v --fix
9 |
10 |
11 | # when running in a CI env we use locally installed bind
12 | ifdef CI
13 | GOFUMPT_CMD := GOFUMPT_SPLIT_LONG_LINES=on gofumpt
14 | GODOT_CMD := godot
15 | GOLANGCI_CMD := golangci-lint
16 | endif
17 |
18 |
19 | format: gofumpt godot # apply Go formatters
20 |
21 | gofumpt:
22 | ${GOFUMPT_CMD} ${GOFUMPT_FLAGS}
23 |
24 | godot:
25 | ${GODOT_CMD} ${GODOT_FLAGS}
26 |
27 | golangci: # linting with golang-ci lint container
28 | ${GOLANGCI_CMD} ${GOLANGCI_FLAGS}
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/codespell-project/codespell
3 | rev: v2.1.0
4 | hooks:
5 | - id: codespell
6 | - repo: https://github.com/syntaqx/git-hooks
7 | rev: v0.0.17
8 | hooks:
9 | - id: forbid-binary
10 | - id: go-fmt
11 | - id: go-test
12 | - id: go-mod-tidy
13 | - id: shfmt
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2021 Nokia. All rights reserved.
2 |
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | 3. Neither the name of the copyright holder nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/cert/cert.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | // Cert is a wrapper struct for the Certificate Authority and the Certificate Storage.
4 | type Cert struct {
5 | *CA
6 | CertStorage
7 | }
8 |
9 | // CertStorage is an interface that wraps methods to load and store certificates.
10 | type CertStorage interface {
11 | LoadCaCert() (*Certificate, error)
12 | LoadNodeCert(nodeName string) (*Certificate, error)
13 | StoreCaCert(cert *Certificate) error
14 | StoreNodeCert(nodeName string, cert *Certificate) error
15 | }
16 |
--------------------------------------------------------------------------------
/cert/csr_input.go:
--------------------------------------------------------------------------------
1 | package cert
2 |
3 | import "time"
4 |
5 | // CACSRInput struct.
6 | type CACSRInput struct {
7 | CommonName string
8 | Country string
9 | Locality string
10 | Organization string
11 | OrganizationUnit string
12 | Expiry time.Duration
13 | KeySize int
14 | }
15 |
16 | // NodeCSRInput struct.
17 | type NodeCSRInput struct {
18 | Hosts []string
19 | CommonName string
20 | Country string
21 | Locality string
22 | Organization string
23 | OrganizationUnit string
24 | Expiry time.Duration
25 | KeySize int
26 | }
27 |
--------------------------------------------------------------------------------
/clab/cert.go:
--------------------------------------------------------------------------------
1 | package clab
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/srl-labs/containerlab/cert"
7 | )
8 |
9 | // LoadOrGenerateCA loads the CA certificate from the storage, or generates a new one if it does not exist.
10 | func (c *CLab) LoadOrGenerateCA(caCertInput *cert.CACSRInput) error {
11 | // try loading the CA cert, and if it fails, generate a new one
12 | caCertificate, err := c.Cert.LoadCaCert()
13 | if err != nil {
14 | // if loading certs failed, try to generate new RootCA
15 | caCertificate, err = c.Cert.GenerateCACert(caCertInput)
16 | if err != nil {
17 | return fmt.Errorf("failed generating new Root CA %v", err)
18 | }
19 | // store the root CA
20 | err = c.Cert.StoreCaCert(caCertificate)
21 | if err != nil {
22 | return nil
23 | }
24 | }
25 |
26 | // set CA cert that was either loaded or generated
27 | err = c.Cert.SetCACert(caCertificate)
28 | if err != nil {
29 | return nil
30 | }
31 |
32 | return nil
33 | }
34 |
--------------------------------------------------------------------------------
/clab/config/send.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/srl-labs/containerlab/clab/config/transport"
7 | )
8 |
9 | func Send(cs *NodeConfig, _ string) error {
10 | var tx transport.Transport
11 | var err error
12 |
13 | ct, ok := cs.TargetNode.Labels["config.transport"]
14 | if !ok {
15 | ct = "ssh"
16 | }
17 |
18 | if ct == "ssh" {
19 | ssh_cred := cs.Credentials
20 | if err != nil {
21 | return err
22 | }
23 |
24 | if len(ssh_cred) < 2 {
25 | return fmt.Errorf("SSH credentials for node %s of type %s not found, cannot configure",
26 | cs.TargetNode.ShortName, cs.TargetNode.Kind)
27 | }
28 | tx, err = transport.NewSSHTransport(
29 | cs.TargetNode,
30 | transport.WithUserNamePassword(
31 | ssh_cred[0],
32 | ssh_cred[1]),
33 | transport.HostKeyCallback(),
34 | )
35 | if err != nil {
36 | return err
37 | }
38 | } else if ct == "grpc" {
39 | // NewGRPCTransport
40 | } else {
41 | return fmt.Errorf("unknown transport: %s", ct)
42 | }
43 |
44 | err = transport.Write(tx, cs.TargetNode.LongName, cs.Data, cs.Info)
45 | if err != nil {
46 | return err
47 | }
48 | return nil
49 | }
50 |
--------------------------------------------------------------------------------
/clab/config/templates/srl-ifaces__srl.tmpl:
--------------------------------------------------------------------------------
1 | {{ expect .clab_system_ip "ip" }}
2 | {{ range .clab_links }}
3 | {{ expect .port "^(ethernet-\\d+/|e\\d+-)\\d+$" }}
4 | {{ end }}
5 | /interface lo0 {
6 | admin-state enable
7 | subinterface 0 {
8 | ipv4 {
9 | address {{ .clab_system_ip }} {
10 | }
11 | }
12 | ipv6 {
13 | address ::c1ab:{{ ip .clab_system_ip }}/128 {
14 | }
15 | }
16 | }
17 | }
18 | /network-instance default {
19 | router-id {{ ip .clab_system_ip }}
20 | interface lo0.0 {
21 | }
22 | }
23 | /system lldp admin-state enable
24 | / network-instance mgmt {
25 | description "set from clab"
26 | }
27 | {{ range .clab_links }}
28 | /interface {{ .port }} {
29 | admin-state enable
30 | }
31 | {{ end }}
--------------------------------------------------------------------------------
/clab/config/transport/transport.go:
--------------------------------------------------------------------------------
1 | package transport
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | // DebugCount is a debug verbosity counter.
8 | var DebugCount int
9 |
10 | type TransportOption func(*Transport)
11 |
12 | type Transport interface {
13 | // Connect to the target host
14 | Connect(host string, options ...TransportOption) error
15 | // Execute some config
16 | Write(data *string, info *string) error
17 | Close()
18 | }
19 |
20 | // Write config to a node.
21 | func Write(tx Transport, host string, data, info []string, options ...TransportOption) error {
22 | // the Kind should configure the transport parameters before
23 |
24 | err := tx.Connect(host, options...)
25 | if err != nil {
26 | return fmt.Errorf("%s: %s", host, err)
27 | }
28 |
29 | defer tx.Close()
30 |
31 | for i1, d1 := range data {
32 | err := tx.Write(&d1, &info[i1])
33 | if err != nil {
34 | return fmt.Errorf("could not write config %s: %s", d1, err)
35 | }
36 | }
37 |
38 | return nil
39 | }
40 |
--------------------------------------------------------------------------------
/clab/dependency_manager/depender_node_stage.go:
--------------------------------------------------------------------------------
1 | package dependency_manager
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/srl-labs/containerlab/types"
7 | )
8 |
9 | // dependerNodeStage is used to keep track of waitgroups that should be decreased (unblocked)
10 | // as soon as a certain delpoy stage is reached.
11 | type dependerNodeStage struct {
12 | depender *DependencyNode // reference to the node
13 | stage types.WaitForStage // reference to the nodes wg that is to be decremented
14 | }
15 |
16 | func newDependerNodeStage(node *DependencyNode, stage types.WaitForStage) *dependerNodeStage {
17 | return &dependerNodeStage{
18 | depender: node,
19 | stage: stage,
20 | }
21 | }
22 |
23 | func (d *dependerNodeStage) SignalDone() {
24 | d.depender.getStageWG(d.stage).Done()
25 | }
26 |
27 | func (d *dependerNodeStage) IncreaseDependencyWG() {
28 | d.depender.stageWG[d.stage].Add(1)
29 | }
30 |
31 | func (d *dependerNodeStage) String() string {
32 | return fmt.Sprintf("Node %s, State %s", d.depender.GetShortName(), d.stage)
33 | }
34 |
--------------------------------------------------------------------------------
/clab/exec/exec_test.go:
--------------------------------------------------------------------------------
1 | package exec
2 |
3 | import "testing"
4 |
5 | func TestParseExecOutputFormat(t *testing.T) {
6 | type args struct {
7 | s string
8 | }
9 | tests := []struct {
10 | name string
11 | args args
12 | want string
13 | wantErr bool
14 | }{
15 | {
16 | name: "Valid value: plain",
17 | want: ExecFormatPlain,
18 | wantErr: false,
19 | args: args{
20 | s: "plain",
21 | },
22 | },
23 | {
24 | name: "Valid value: pLAiN",
25 | want: ExecFormatPlain,
26 | wantErr: false,
27 | args: args{
28 | s: "plain",
29 | },
30 | },
31 | {
32 | name: "Valid value: json",
33 | want: ExecFormatJSON,
34 | wantErr: false,
35 | args: args{
36 | s: "json",
37 | },
38 | },
39 | {
40 | name: "Valid value: table (mapped to plain)",
41 | want: ExecFormatPlain,
42 | wantErr: false,
43 | args: args{
44 | s: "table",
45 | },
46 | },
47 | {
48 | name: "Invalid value: foobar",
49 | want: "",
50 | wantErr: true,
51 | args: args{
52 | s: "foobar",
53 | },
54 | },
55 | }
56 | for _, tt := range tests {
57 | t.Run(tt.name, func(t *testing.T) {
58 | got, err := ParseExecOutputFormat(tt.args.s)
59 | if (err != nil) != tt.wantErr {
60 | t.Errorf("ParseExecOutputFormat() error = %v, wantErr %v", err, tt.wantErr)
61 | return
62 | }
63 | if got != tt.want {
64 | t.Errorf("ParseExecOutputFormat() = %v, want %v", got, tt.want)
65 | }
66 | })
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/clab/exec_options.go:
--------------------------------------------------------------------------------
1 | package clab
2 |
3 | import "github.com/srl-labs/containerlab/types"
4 |
5 | type ExecOptions struct {
6 | filters []*types.GenericFilter
7 | }
8 |
9 | func NewExecOptions(filters []*types.GenericFilter) *ExecOptions {
10 | return &ExecOptions{
11 | filters: filters,
12 | }
13 | }
14 |
15 | func (e *ExecOptions) AddFilters(f ...*types.GenericFilter) {
16 | e.filters = append(e.filters, f...)
17 | }
18 |
--------------------------------------------------------------------------------
/clab/export_templates/full.tmpl:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ .Name }}",
3 | "type": "{{ .Type }}",
4 | "clab": {{ ToJSONPretty .Clab " " " "}},
5 | "ssh-pub-keys": {{ ToJSON .SSHPubKeys }},
6 | "nodes": { {{- $i:=0 }}{{range $n, $c := .NodeConfigs}}{{if $i}},{{end}}{{ $k := dict "tls-key" $c.TLSKey }}
7 | "{{$n}}":{{ $cj := $c | data.ToJSON | data.JSON }} {{ $dst := coll.Merge $cj $k }}{{ ToJSONPretty $dst " " " " }}{{$i = add $i 1}}{{end}}
8 | },
9 | "links": [{{range $i, $l := .Clab.Links}}{{if $i}},{{end}}
10 | {{- $eps := $l.GetEndpoints }}
11 | {{- $ep := index $eps 0 }}
12 | {
13 | "a": {
14 | "node": "{{ $ep.GetNode.GetShortName }}",
15 | "interface": "{{ $ep.GetIfaceName }}",
16 | "mac": "{{ $ep.GetMac }}",
17 | "peer": "{{if eq (len $eps) 2}}z{{else}}dummy{{end}}"
18 | }
19 | {{- if eq (len $eps) 2 }}
20 | {{- $ep := index $eps 1 }},
21 | "z": {
22 | "node": "{{ $ep.GetNode.GetShortName }}",
23 | "interface": "{{ $ep.GetIfaceName }}",
24 | "mac": "{{ $ep.GetMac }}",
25 | "peer": "a"
26 | }
27 | {{- end }}
28 | }{{end}}
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/CiscoSansExtraLight.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/CiscoSansExtraLight.otf
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/CiscoSansRegular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/CiscoSansRegular.otf
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.eot
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.ttf
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansextralight-webfont.woff
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.eot
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.ttf
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/ciscosansregular-webfont.woff
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/next-font.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/next-font.eot
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/next-font.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/next-font.ttf
--------------------------------------------------------------------------------
/clab/graph_templates/nextui/static/fonts/next-font.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/graph_templates/nextui/static/fonts/next-font.woff
--------------------------------------------------------------------------------
/clab/inventory_nornir_simple.go.tpl:
--------------------------------------------------------------------------------
1 | ---
2 | {{- range $kind, $nodes := .Nodes -}}
3 | {{- $kindProps := index $.Kinds $kind -}}
4 | {{- range $node := $nodes }}
5 | {{ $node.ShortName }}:
6 | username: {{ $kindProps.Username }}
7 | password: {{ $kindProps.Password }}
8 | platform: {{ $kindProps.Platform }}
9 | hostname: {{ $node.MgmtIPv4Address }}
10 | {{- if $node.NornirGroups }}
11 | groups:
12 | {{- range $group := $node.NornirGroups }}
13 | - {{ $group }}
14 | {{- end }}
15 | {{- end }}
16 | {{- end }}
17 | {{- end }}
--------------------------------------------------------------------------------
/clab/network.go:
--------------------------------------------------------------------------------
1 | package clab
2 |
3 | import (
4 | "context"
5 |
6 | "github.com/srl-labs/containerlab/labels"
7 | )
8 |
9 | func (c *CLab) CreateNetwork(ctx context.Context) error {
10 | // create docker network or use existing one
11 | if err := c.globalRuntime().CreateNet(ctx); err != nil {
12 | return err
13 | }
14 |
15 | // save mgmt bridge name as a label
16 | for _, n := range c.Nodes {
17 | n.Config().Labels[labels.NodeMgmtNetBr] = c.globalRuntime().Mgmt().Bridge
18 | }
19 |
20 | return nil
21 | }
22 |
--------------------------------------------------------------------------------
/clab/ssh_config.go.tpl:
--------------------------------------------------------------------------------
1 | # Containerlab SSH Config for the {{ .TopologyName }} lab
2 |
3 | {{- range .Nodes }}
4 | Host {{ .Name }}
5 | {{- if ne .Username ""}}
6 | User {{ .Username }}
7 | {{- end }}
8 | StrictHostKeyChecking=no
9 | UserKnownHostsFile=/dev/null
10 | {{- if ne .SSHConfig.PubkeyAuthentication "" }}
11 | PubkeyAuthentication={{ .SSHConfig.PubkeyAuthentication.String }}
12 | {{- end }}
13 | {{ end }}
--------------------------------------------------------------------------------
/clab/test_data/clab-topo2/node1/node1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/test_data/clab-topo2/node1/node1
--------------------------------------------------------------------------------
/clab/test_data/default.lic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/test_data/default.lic
--------------------------------------------------------------------------------
/clab/test_data/envfile1:
--------------------------------------------------------------------------------
1 | ENVFILE1=SOMEENVVARDATA
--------------------------------------------------------------------------------
/clab/test_data/envfile2:
--------------------------------------------------------------------------------
1 | ENVFILE1=SOMEOTHERDATA
2 | ENVFILE2=THISANDTHAT
--------------------------------------------------------------------------------
/clab/test_data/kind.lic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/test_data/kind.lic
--------------------------------------------------------------------------------
/clab/test_data/node1.lic:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/clab/test_data/node1.lic
--------------------------------------------------------------------------------
/clab/test_data/topo1.yml:
--------------------------------------------------------------------------------
1 | name: topo1
2 | topology:
3 | nodes:
4 | node1:
5 | kind: nokia_srlinux
6 | license: node1.lic
7 | binds:
8 | - node1.lic:/dst
9 | env:
10 | env1: val1
11 | env2: val2
12 | mgmt-ipv4: 172.100.100.11
13 | node2:
14 | kind: nokia_srlinux
15 | license: node1.lic
16 | user: custom
17 | mgmt-ipv4: 172.100.100.12
18 | labels:
19 | node-label: value
20 | # tests that unset $value is not substituted
21 | with-dollar-sign: some$value
22 |
--------------------------------------------------------------------------------
/clab/test_data/topo10.yml:
--------------------------------------------------------------------------------
1 | name: topo10
2 | topology:
3 | defaults:
4 | env-files:
5 | - envfile2
6 | nodes:
7 | node1:
8 | kind: linux
9 | env:
10 | env1: val1
11 | env2: val2
12 | mgmt-ipv4: 172.100.100.11
13 | node2:
14 | kind: linux
15 | mgmt-ipv4: 172.100.100.12
16 | labels:
17 | node-label: value
18 | env-files:
19 | - envfile1
20 |
21 |
--------------------------------------------------------------------------------
/clab/test_data/topo11-ext-cont.yaml:
--------------------------------------------------------------------------------
1 | name: topo11
2 | topology:
3 | nodes:
4 | node1:
5 | kind: ext-container
6 | exec:
7 | - ip l
8 | node2:
9 | kind: linux
10 | image: alpine:latest
11 |
12 |
13 |
--------------------------------------------------------------------------------
/clab/test_data/topo12.yml:
--------------------------------------------------------------------------------
1 | name: topo12
2 |
3 | topology:
4 | defaults:
5 | suppress-startup-config: true
6 | kinds:
7 | ceos:
8 | suppress-startup-config: false
9 | nodes:
10 | node1:
11 | kind: ceos
12 | suppress-startup-config: true
13 | node2:
14 | kind: ceos
15 | suppress-startup-config: false
16 | node3:
17 | kind: ceos
18 | node4:
19 | kind: linux
20 |
21 | links:
22 | - endpoints: ["node1:eth1", "node2:eth1"]
23 | - endpoints: ["node2:eth2", "node3:eth1"]
24 |
--------------------------------------------------------------------------------
/clab/test_data/topo13.yml:
--------------------------------------------------------------------------------
1 | name: topo13
2 | topology:
3 | kinds:
4 | nokia_srlinux:
5 | startup-config: ./configs/fabric/__clabNodeName__.cfg
6 | nodes:
7 | node1:
8 | kind: nokia_srlinux
9 |
--------------------------------------------------------------------------------
/clab/test_data/topo14.yml:
--------------------------------------------------------------------------------
1 | name: topo14
2 | topology:
3 | nodes:
4 | node1:
5 | kind: nokia_srlinux
6 | startup-config: ./configs/fabric/__clabNodeName__.cfg
7 | exec:
8 | - echo "Hello world"
9 | - echo "Hello node __clabNodeName__"
10 |
--------------------------------------------------------------------------------
/clab/test_data/topo15.yml:
--------------------------------------------------------------------------------
1 | name: topo15
2 | topology:
3 | defaults:
4 | startup-config: ./configs/fabric/__clabNodeName__.cfg
5 | nodes:
6 | node1:
7 | kind: nokia_srlinux
8 |
--------------------------------------------------------------------------------
/clab/test_data/topo2.yml:
--------------------------------------------------------------------------------
1 | name: topo2
2 | topology:
3 | kinds:
4 | nokia_srlinux:
5 | license: kind.lic
6 | type: ixrd2l
7 | env:
8 | env1: val1
9 | user: customkind
10 | labels:
11 | kind-label: value
12 | nodes:
13 | node1:
14 | kind: nokia_srlinux
15 | binds:
16 | - node1.lic:/dst1
17 | - kind.lic:/dst2
18 | - __clabNodeDir__/__clabNodeName__:/somefile
19 | node2:
20 | kind: nokia_srlinux
21 | type: ixr10
22 |
--------------------------------------------------------------------------------
/clab/test_data/topo3.yml:
--------------------------------------------------------------------------------
1 | name: topo3
2 | topology:
3 | defaults:
4 | license: default.lic
5 | binds:
6 | - default.lic:/dst
7 | type: ixrd2l
8 | env:
9 | env1: val1
10 | user: customglobal
11 | labels:
12 | default-label: value
13 | nodes:
14 | node1:
15 | kind: nokia_srlinux
16 | type: ixrd3l
17 | node2:
18 | kind: nokia_srlinux
19 |
--------------------------------------------------------------------------------
/clab/test_data/topo4.yml:
--------------------------------------------------------------------------------
1 | name: topo4
2 | topology:
3 | defaults:
4 | license: default.lic
5 | binds:
6 | - default.lic:/dst3
7 | env:
8 | env1: global
9 | env2: global
10 | env3: global
11 | user: customglobal
12 | kinds:
13 | nokia_srlinux:
14 | license: kind.lic
15 | binds:
16 | - kind.lic:/dst2
17 | env:
18 | env2: kind
19 | env4: kind
20 | user: customkind
21 | nodes:
22 | node1:
23 | kind: nokia_srlinux
24 | type: ixrd3
25 | license: node1.lic
26 | binds:
27 | - node1.lic:/dst1
28 | env:
29 | env1: node
30 | env5: node
31 | user: customnode
32 |
--------------------------------------------------------------------------------
/clab/test_data/topo5.yml:
--------------------------------------------------------------------------------
1 | name: topo5
2 | topology:
3 | kinds:
4 | nokia_srlinux:
5 | binds:
6 | - kind.lic:/dst
7 | nodes:
8 | node1:
9 | kind: nokia_srlinux
10 | type: ixrd3
11 | license: node1.lic
12 | binds:
13 | - node1.lic:/dst2
14 |
--------------------------------------------------------------------------------
/clab/test_data/topo6.yml:
--------------------------------------------------------------------------------
1 | name: topo6
2 |
3 | topology:
4 | nodes:
5 | lin1:
6 | kind: linux
7 | image: alpine:3
8 | lin2:
9 | kind: linux
10 | image: alpine:3
11 |
12 | links:
13 | - endpoints: ["lin1:eth1", lin2:eth1]
14 | - endpoints: ["lin1:eth1", lin2:eth2]
15 | - endpoints: ["lin1:eth3", lin2:eth2]
16 | - endpoints: ["lin1:eth4", lin1:eth4]
17 |
--------------------------------------------------------------------------------
/clab/test_data/topo7-dup-rootnetns.yml:
--------------------------------------------------------------------------------
1 | name: topo7
2 |
3 | topology:
4 | nodes:
5 | br1:
6 | kind: bridge
7 | l1:
8 | kind: linux
9 | image: alpine:latest
10 | cmd: sleep infinity
11 |
12 | links:
13 | - endpoints: ["l1:eth1", "br1:eth76"]
14 | - endpoints: ["l1:eth2", "host:eth76"]
15 |
--------------------------------------------------------------------------------
/clab/test_data/topo8_ansible_groups.yml:
--------------------------------------------------------------------------------
1 | name: topo8_ansible_groups
2 | topology:
3 | nodes:
4 | node1:
5 | kind: nokia_srlinux
6 | type: ixrd3
7 | license: node1.lic
8 | binds:
9 | - node1.lic:/dst
10 | env:
11 | env1: val1
12 | env2: val2
13 | mgmt-ipv4: 172.100.100.11
14 | labels:
15 | ansible-group: spine
16 | nornir-group: spine
17 | node2:
18 | kind: nokia_srlinux
19 | license: node1.lic
20 | user: custom
21 | mgmt-ipv4: 172.100.100.12
22 | labels:
23 | node-label: value
24 | ansible-group: extra_group
25 | nornir-group: extra_group
26 |
27 | node3:
28 | kind: nokia_srlinux
29 | license: node1.lic
30 | user: custom
31 | mgmt-ipv4: 172.100.100.13
32 | labels:
33 | node-label: value
34 | ansible-group: extra_group
35 | nornir-group: extra_group
36 |
37 | node4:
38 | kind: linux
39 | image: alpine:3
40 | mgmt-ipv4: 172.100.100.14
41 | labels:
42 | ansible-no-host-var: true
43 |
--------------------------------------------------------------------------------
/clab/test_data/topo8_nornir_groups.yml:
--------------------------------------------------------------------------------
1 | name: topo8_ansible_groups
2 | topology:
3 | nodes:
4 | node1:
5 | kind: nokia_srlinux
6 | type: ixrd3
7 | license: node1.lic
8 | binds:
9 | - node1.lic:/dst
10 | env:
11 | env1: val1
12 | env2: val2
13 | mgmt-ipv4: 172.100.100.11
14 | labels:
15 | nornir-group: spine
16 | node2:
17 | kind: nokia_srlinux
18 | license: node1.lic
19 | user: custom
20 | mgmt-ipv4: 172.100.100.12
21 | labels:
22 | node-label: value
23 | nornir-group: extra_group
24 | nornir-group-2: second_extra_group
25 |
26 | node3:
27 | kind: nokia_srlinux
28 | license: node1.lic
29 | user: custom
30 | mgmt-ipv4: 172.100.100.13
31 | labels:
32 | node-label: value
33 | nornir-group: extra_group
34 |
35 | node4:
36 | kind: linux
37 | image: alpine:3
38 | mgmt-ipv4: 172.100.100.14
39 | labels:
40 | ansible-no-host-var: true
41 |
--------------------------------------------------------------------------------
/clab/test_data/topo9.yml:
--------------------------------------------------------------------------------
1 | name: topo4
2 | topology:
3 | defaults:
4 | license: default.lic
5 | binds:
6 | - default.lic:/dst
7 | env:
8 | env1: global
9 | env2: global
10 | env3: global
11 | user: customglobal
12 | kinds:
13 | nokia_srlinux:
14 | license: kind.lic
15 | binds:
16 | - kind.lic:/dst
17 | env:
18 | env2: kind
19 | env4: kind
20 | user: customkind
21 | nodes:
22 | node1:
23 | kind: nokia_srlinux
24 | type: ixrd3
25 | license: node1.lic
26 | binds:
27 | - node1.lic:/dst
28 | env:
29 | env1: node
30 | env5: ${CONTAINERLAB_TEST_ENV5}
31 | user: customnode
32 |
--------------------------------------------------------------------------------
/cmd/common/common.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | var (
8 | Debug bool
9 | Timeout time.Duration
10 | )
11 |
12 | // path to the topology file.
13 | var Topo string
14 |
15 | var (
16 | VarsFile string
17 | Graph bool
18 | Runtime string
19 | )
20 |
21 | // subset of nodes to work with.
22 | var NodeFilter []string
23 |
24 | // lab Name.
25 | var Name string
26 |
27 | // Use graceful shutdown.
28 | var Graceful bool
29 |
--------------------------------------------------------------------------------
/cmd/tools.go:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Nokia
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 |
5 | package cmd
6 |
7 | import (
8 | "github.com/spf13/cobra"
9 | )
10 |
11 | // toolsCmd represents the tools command.
12 | var toolsCmd = &cobra.Command{
13 | Use: "tools",
14 | Short: "various tools your lab might need",
15 | Long: "tools command groups various tools you might need for your lab\nreference: https://containerlab.dev/cmd/tools/",
16 | }
17 |
18 | func init() {
19 | rootCmd.AddCommand(toolsCmd)
20 | }
21 |
--------------------------------------------------------------------------------
/cmd/tools_api.go:
--------------------------------------------------------------------------------
1 | // Copyright 2025
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 |
5 | package cmd
6 |
7 | import (
8 | "github.com/spf13/cobra"
9 | )
10 |
11 | func init() {
12 | toolsCmd.AddCommand(apiServerCmd)
13 | }
14 |
15 | // apiServerCmd represents the api-server command container
16 | var apiServerCmd = &cobra.Command{
17 | Use: "api-server",
18 | Short: "Containerlab API server operations",
19 | Long: "Start, stop, and manage Containerlab API server containers",
20 | }
21 |
--------------------------------------------------------------------------------
/cmd/version/logo.txt:
--------------------------------------------------------------------------------
1 | ____ ___ _ _ _____ _ ___ _ _ _____ ____ [38;2;0;201;255m_ _ [0m
2 | / ___/ _ \| \ | |_ _|/ \ |_ _| \ | | ____| _ \[38;2;0;201;255m| | __ _| |__ [0m
3 | | | | | | | \| | | | / _ \ | || \| | _| | |_) [38;2;0;201;255m| |/ _` | '_ \ [0m
4 | | |__| |_| | |\ | | |/ ___ \ | || |\ | |___| _ <[38;2;0;201;255m| | (_| | |_) |[0m
5 | \____\___/|_| \_| |_/_/ \_\___|_| \_|_____|_| \_\[38;2;0;201;255m_|\__,_|_.__/ [0m
6 |
--------------------------------------------------------------------------------
/cmd/version/version_test.go:
--------------------------------------------------------------------------------
1 | package version
2 |
3 | import (
4 | "testing"
5 |
6 | "github.com/google/go-cmp/cmp"
7 | )
8 |
9 | func TestDocsLinkFromVer(t *testing.T) {
10 | tests := []struct {
11 | name string
12 | version string
13 | expected string
14 | }{
15 | {
16 | name: "major and minor only",
17 | version: "0.47.0",
18 | expected: "0.47/",
19 | },
20 | {
21 | name: "major, minor, and patch version",
22 | version: "0.47.2",
23 | expected: "0.47/#0472",
24 | },
25 | }
26 |
27 | for _, tt := range tests {
28 | t.Run(tt.name, func(t *testing.T) {
29 | got := docsLinkFromVer(tt.version)
30 | if diff := cmp.Diff(got, tt.expected); diff != "" {
31 | t.Fatalf("docsLinkFromVer() mismatch (-want +got):\n%s", diff)
32 | }
33 | })
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | patch:
4 | default:
5 | informational: true # don't fail the build if PR coverage is missing
6 | comment:
7 | layout: "diff, files"
8 | behavior: new
9 | github_checks:
10 | annotations: false
11 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | containerlab.dev
--------------------------------------------------------------------------------
/docs/cmd/tools/disable-tx-offload.md:
--------------------------------------------------------------------------------
1 | # disable-tx-offload command
2 |
3 | ### Description
4 |
5 | The `disable-tx-offload` command under the `tools` command disables tx checksum offload for `eth0` interface of a container referenced by its name.
6 |
7 | The need for `disable-tx-offload` might arise when you launch a container outside of containerlab or restart a container. Some nodes, like SR Linux, will require correct checksums in TCP packets; thus, it is needed to disable checksum offload on those containers to do checksum calculations instead of offloading it.
8 |
9 | ### Usage
10 |
11 | `containerlab tools disable-tx-offload [local-flags]`
12 |
13 | ### Flags
14 |
15 | #### container
16 | With the local mandatory `--container | -c` flag, a user specifies which container to remove tx offload.
17 |
18 | ### Examples
19 |
20 | ```bash
21 | # disable tx checksum offload on gnmic container
22 | ❯ clab tools disable-tx-offload -c clab-st-gnmic
23 | INFO[0000] getting container 'clab-st-gnmic' information
24 | INFO[0000] Tx checksum offload disabled for eth0 interface of clab-st-gnmic container
25 | ```
--------------------------------------------------------------------------------
/docs/cmd/tools/netem/reset.md:
--------------------------------------------------------------------------------
1 | # Resetting Link Impairments
2 |
3 | With the `containerlab tools netem reset` command users can remove (reset) all network impairments on a specified interface of a containerlab node. This command deletes the netem qdisc associated with the interface, restoring it to its default state. If no impairments are present, the command will complete successfully without error.
4 |
5 | ## Usage
6 |
7 | ```bash
8 | containerlab tools netem reset [local-flags]
9 | ```
10 |
11 | ## Flags
12 |
13 | ### node
14 |
15 | The mandatory `--node | -n` flag specifies the name of the containerlab node on which to reset link impairments.
16 |
17 | ### interface
18 |
19 | The mandatory `--interface | -i` flag specifies the interface on which the netem impairments should be reset.
20 |
21 | ## Examples
22 |
23 | ### Resetting impairments on an interface
24 |
25 | This example resets the impairments on the interface `eth1` of node `clab-netem-r1`:
26 |
27 | ```bash
28 | containerlab tools netem reset -n clab-netem-r1 -i eth1
29 | ```
30 |
31 | Output:
32 |
33 | ```bash
34 | Reset impairments on node "clab-netem-r1", interface "eth1"
35 | ```
36 |
37 | ### Resetting impairments when none are set
38 |
39 | If no impairments are configured on the specified interface, the command will complete without error:
40 |
41 | ```bash
42 | containerlab tools netem reset -n clab-netem-r1 -i eth0
43 | ```
44 |
45 | Output:
46 |
47 | ```bash
48 | Reset impairments on node "clab-netem-r1", interface "eth0"
49 | ```
50 |
--------------------------------------------------------------------------------
/docs/cmd/tools/vxlan/delete.md:
--------------------------------------------------------------------------------
1 | # vxlan delete
2 |
3 | ### Description
4 |
5 | The `delete` sub-command under the `tools vxlan` command deletes VxLAN interfaces which name matches a user specified prefix. The `delete` command is typically used to remove VxLAN interfaces created with [`create`](create.md) command.
6 |
7 | ### Usage
8 |
9 | `containerlab tools vxlan delete [local-flags]`
10 |
11 | ### Flags
12 |
13 | #### prefix
14 | Set a prefix with `--prefix | -p` flag. The VxLAN interfaces which name is matched by the prefix will be deleted. Default prefix is `vx-` which is matched the default prefix used by [`create`](create.md) command.
15 |
16 | ### Examples
17 |
18 | ```bash
19 | # delete all VxLAN interfaces created by containerlab
20 | ❯ clab tools vxlan create delete
21 | INFO[0000] Deleting VxLAN link vx-srl_e1-1
22 | ```
--------------------------------------------------------------------------------
/docs/cmd/version/check.md:
--------------------------------------------------------------------------------
1 | # check
2 |
3 | ## Description
4 |
5 | The `version check` command checks if a newer version of containerlab is available.
6 |
7 | ## Usage
8 |
9 | ```
10 | containerlab version check
11 | ```
12 |
13 | When executed, the containerlab binary will reach out to the github API and check if a newer version is available and display the result.
14 |
15 | Example result output:
16 |
17 | ```
18 | 🎉 A newer containerlab version (0.62.2) is available!
19 | Release notes: https://containerlab.dev/rn/0.62/#0622
20 | Run 'sudo clab version upgrade' or see https://containerlab.dev/install/ for installation options.
21 | ```
22 |
--------------------------------------------------------------------------------
/docs/cmd/version/index.md:
--------------------------------------------------------------------------------
1 | # version
2 |
3 | ## Description
4 |
5 | The `version` command displays the version of containerlab installed.
6 |
7 | ## Usage
8 |
9 | ```
10 | containerlab version
11 | ```
12 |
13 | The version command contains:
14 |
15 | * version in the semantic versioning format
16 | * commit hash of the project repository
17 | * build date
18 | * a link to the github repo
19 | * a link to the release notes of the current version
20 |
--------------------------------------------------------------------------------
/docs/images/containerlab-og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/docs/images/containerlab-og.png
--------------------------------------------------------------------------------
/docs/images/containerlab_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/docs/images/containerlab_black.png
--------------------------------------------------------------------------------
/docs/images/containerlab_grey.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/docs/images/containerlab_grey.pdf
--------------------------------------------------------------------------------
/docs/images/containerlab_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/docs/images/containerlab_grey.png
--------------------------------------------------------------------------------
/docs/images/flask.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/client.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/controller.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/dcgw.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/pon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/rgw.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/router.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/server.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/spine.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/images/topoviewer-icons/switch.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/manual/dev/index.md:
--------------------------------------------------------------------------------
1 | # Developers Guide
2 |
3 | Containerlab relies on contributions from the community to improve existing functionality and add new features. The developers guide provides information on how to contribute to various bits of the project.
4 |
5 | Remember, that all contributions are welcome and important, no matter how big or small they are. Spot a typo in the documentation? Found a bug? Have an idea for a new feature? Want to improve the performance of the code? All of these are valuable contributions to the project.
6 |
7 | Thank you for considering contributing to containerlab!
8 |
--------------------------------------------------------------------------------
/docs/manual/impairments.md:
--------------------------------------------------------------------------------
1 | ---
2 | comments: true
3 | ---
4 |
5 | # Link Impairments
6 |
7 | Labs are meant to be a reflection of real-world scenarios. To make simulated networks exhibit real-life behavior you can set link impairments (delay, jitter, packet loss) on any link that belongs to a container node. Link impairment feature is powered by the `tools netem` command collection:
8 |
9 | * [`tools netem set`](../cmd/tools/netem/set.md)
10 | * [`tools netem show`](../cmd/tools/netem/show.md)
11 | * [`tools netem reset`](../cmd/tools/netem/reset.md)
12 |
13 | These commands allow users to set, show and reset link impairments (delay, jitter, packet loss) on any link that belongs to a container node and create labs simulating real-world network conditions.
14 |
15 | ```bash title="setting packet loss at 10% rate on eth1 interface of clab-netem-r1 node"
16 | containerlab tools netem set -n clab-netem-r1 -i eth1 --loss 10
17 | ```
18 |
--------------------------------------------------------------------------------
/docs/manual/kinds/host.md:
--------------------------------------------------------------------------------
1 | ---
2 | search:
3 | boost: 4
4 | ---
5 |
6 | # Host
7 |
8 | A node of kind `host` represents the containerlab host the labs are running on. It is a special node that is implicitly used when nodes have links connected to the host - see [host links](../network.md#host-links).
9 |
10 | But there is a use case when users might want to define the node of kind `host` explicitly in the topology. For example, when some commands need to be executed on the host for the lab to function.
11 |
12 | In such case, the following topology definition can be used:
13 |
14 | ```yaml
15 | h1:
16 | kind: host
17 | exec:
18 | - ip link set dev enp0s3 up
19 | ```
20 |
21 | In the above example, the node `h1` is defined as a node of kind `host` and the `exec` option is used to run the command `ip link set dev enp0s3 up` in the containerlab host. Of course, the command can be any other command that is required for the lab to function.
22 |
--------------------------------------------------------------------------------
/docs/rn/0.14.1.md:
--------------------------------------------------------------------------------
1 | # Release 0.14.1
2 | :material-calendar: 2021-05-20
3 |
4 | ## fix lab deletion data race
5 | This patch release fixes data race which could occur during the deletion of a lab with many nodes.
--------------------------------------------------------------------------------
/docs/rn/0.14.2.md:
--------------------------------------------------------------------------------
1 | # Release 0.14.2
2 | :material-calendar: 2021-05-27
3 |
4 | ## fix additional interfaces to management network
5 | This patch release fixes issues with containerlab failing to add additional data interfaces to management network as described [here](../manual/network.md#additional-connections-to-management-network).
--------------------------------------------------------------------------------
/docs/rn/0.14.3.md:
--------------------------------------------------------------------------------
1 | # Release 0.14.3
2 | :material-calendar: 2021-05-28
3 |
4 |
5 | ## Fixes and improvements
6 | - fixed missing IPv4/6 information in `containerlab inspect --all` output
7 | - prevented deployment of the lab if the same-named lab has already been deployed
8 | - install script now checks if the released version set by the user actually exists
9 |
10 |
--------------------------------------------------------------------------------
/docs/rn/0.14.4.md:
--------------------------------------------------------------------------------
1 | # Release 0.14.4
2 | :material-calendar: 2021-06-06
3 |
4 |
5 | ## Fixes and improvements
6 | - [fixed](https://github.com/srl-labs/containerlab/pull/440) generate command
7 | - added "Y/n" prompt when doing `containerlab version upgrade`.
8 | - version command will return a link to the relevant release notes
9 |
10 |
--------------------------------------------------------------------------------
/docs/rn/0.27.md:
--------------------------------------------------------------------------------
1 | # Release 0.27
2 | :material-calendar: 2022-07-06
3 |
4 | ## Multiple kind names
5 | When we started containerlab, using short kind names was easy. Everybody knew that `srl` is SR Linux, and, say, `ceos` is cEOS. As we grew, more people started to use containerlab and not everyone knew the short names of NOSes.
6 |
7 | Therefore we added an ability to use long names for kinds, for example, `nokia_srlinux` or `arista_ceos`. These new "long" names have been added to kind docs.
8 |
9 | ## Juniper vQFX and Juniper vMX startup config
10 | We finally added support to provision vMX and vQFX with startup configuration. The same [`startup-config`](../manual/nodes.md#startup-config) node property allows users to point to a file that contains configuration lines that will get applied to a network element when it starts.
11 |
12 |
13 | ## Misc
14 |
15 | * SR Linux nodes will be able to use the names of the other nodes of the same #891
16 |
17 | ## Patches
18 |
19 | ### 0.27.1
20 |
21 | * adding missing config dir mount for vMX
--------------------------------------------------------------------------------
/docs/rn/0.28.md:
--------------------------------------------------------------------------------
1 | # Release 0.28
2 | :material-calendar: 2022-06-27
3 |
4 | ## Topology file auto-detect
5 | With embedded shorthands `containerlab`->`clab`, `deploy`->`dep` and so on, we made using containerlab over the CLI a fast and pleasant experience. But even then, typing `clab dep -t mytopo.clab.yml` is one argument too long.
6 |
7 | Please welcome the topology file auto-detect feature which turns `clab dep -t mytopo.clab.yml` to just `clab dep` :partying_face:
8 |
9 | !!!note
10 | A single file matching `*.clab.y*ml` pattern must be present in the current working directory for auto-detect feature to work.
11 |
12 | Should you have multiple topology files, use the `--topo` flag as before.
13 |
14 | ## Ignite-based linux containers
15 | Weaveworks/ignite runtime integration that was added by @networkop for [Cumulus VX](../manual/kinds/cvx.md) nodes got a new application. With #910 merged, users now can run Linux VMs in a container packaging and leverage VM-like experience while running lightweight and fast.
16 |
17 | ## Miscellaneous
18 |
19 | * added `-c` shorthand for `--reconfigure` as it is very handy to use `clab dep -c` to cleanly redeploy the lab during the iterations of lab build-out.
20 |
21 | ## Patches
22 |
23 | ### 0.28.1
24 |
25 | * fixed crpd kind name #922
26 | * added missing kinds to clab.schema.json
27 | * ceos nodes now have default route pointing to management gw address #920
28 | * iptables has been added to clab container #921
29 | * diagrams rendering engine update to latest version
30 |
--------------------------------------------------------------------------------
/docs/rn/0.29.md:
--------------------------------------------------------------------------------
1 | # Release 0.29
2 |
3 | :material-calendar: 2022-07-11
4 |
5 | ## Checkpoint Cloudguard
6 |
7 | Our firewall-focused camp got a new member - [Checkpoint Cloudguard](../manual/kinds/checkpoint_cloudguard.md) platform. This platform is built with [boxen](https://github.com/carlmontanari/boxen) project instead of vrnetlab. We are slowly building confidence in boxen and new platforms will likely be solely powered by boxen. PR #934
8 |
9 | ## Miscellaneous
10 |
11 | * added `-c` shorthand for `--cleanup` flag of the `destroy` command. Now to remove a lab and get rid of the lab directory simply call `clab des -c`.
12 | * [`inspect`](../cmd/inspect/index.md) command has been fixed to display IP information even for nodes connected to external networks.
13 | * added srlinux 6e and 10e platforms
14 |
--------------------------------------------------------------------------------
/docs/rn/0.30.md:
--------------------------------------------------------------------------------
1 | # Release 0.30
2 |
3 | :material-calendar: 2022-07-28
4 |
5 | ## Podman v4
6 |
7 | Podman v4 delivers a new API to schedule containers within the Podman runtime. Version 4 allows us to deliver better support for this runtime in the context of containerlab #919.
8 |
9 | ## Miscellaneous
10 |
11 | * ipv6 gateway support in arista ceos startup-config #940.
12 | * management vrf support in ceos with the use of a [`CLAB_MGMT_VRF` env var](../manual/kinds/ceos.md#mgmt-vrf) #941
13 | * SR Linux mac address generation function allows for multi-node setups with random seed #942
14 | * fixed Netconf save operations #953
15 |
--------------------------------------------------------------------------------
/docs/rn/0.33.md:
--------------------------------------------------------------------------------
1 | # Release 0.33
2 |
3 | :material-calendar: 2022-11-28
4 |
5 | ## External container kind
6 |
7 | With a new [`ext-container`](../manual/kinds/ext-container.md) kind it is possible to enrich clab topology with nodes scheduled by other tools (e.g. `k8s-kind`). Thanks @steiler.
8 |
9 | ## Graph enhancements
10 |
11 | Thanks to @gamerslouis our [graph](../cmd/graph.md) feature got some important fixes like properly displaying bridge properties in #1097 and renders bridges in offline mode in #1098.
12 |
13 | ## SR OS and BOF persistency
14 |
15 | Making SR OS BOF persistent was not a trivial task, but @mabra94 added a nice doc section explaining how bind mounts and boot-good-exec SR OS option combined can achieve that. #1107
16 |
17 | ## Miscellaneous
18 |
19 | * fixed ssse3 check #1092
20 | * housekeeping item by @steiler - default node embedding #1099
21 | * startup-config support for PAN OS nodes #1109
22 | * save CPU from spinning when waiting for nodes to boot #1108
23 |
--------------------------------------------------------------------------------
/docs/rn/0.34.md:
--------------------------------------------------------------------------------
1 | ---
2 | icon: fontawesome/solid/tree
3 | ---
4 |
5 | # Release 0.34 :christmas_tree:
6 |
7 | :material-calendar: 2022-12-23
8 |
9 | ## Cisco XRd support
10 |
11 | Thanks to @trustywolf we finally landed support for [Cisco XRd](../manual/kinds/xrd.md)! No more dealing with a 16GB mem-hungry VM monster when all you need is a control plane. #1144
12 |
13 | ## Major codebase refactoring
14 |
15 | @steiler went into the berzerk mode and refactored half of the containerlab's internal code base to have a cleaner separation of packages, internal APIs and increased extensibility.
16 |
17 | This change was carried over in multiple PRs and touched a lot of files; while we did quite some testing and maintained the same user experience, there might be things that work differently, do let us know if there is something out of order.
18 |
19 | ## Miscellaneous
20 |
21 | * Containerlab can now be installed on Core OS #1115
22 | * Fixed pull image function to support pulling images without explicit tags #1123
23 | * Memory calculation function has been fixed to report on available memory, not just free one #1133
24 |
--------------------------------------------------------------------------------
/docs/rn/0.35.md:
--------------------------------------------------------------------------------
1 | # Release 0.35
2 |
3 | :material-calendar: 2023-01-17
4 |
5 | ## DNS options
6 |
7 | A new node property - [DNS](../manual/nodes.md#dns) - allows users to provide DNS options to the nodes.
8 |
9 | ## `containerlab exec` fixes and improvements
10 |
11 | Thanks to efforts by @steiler we have refactored [`exec`](../cmd/exec.md) command and fixed a few bugs along the way. The command now supports multiple `--cmd` arguments. #1161
12 |
13 | ## Miscellaneous
14 |
15 | * Internal refactoring of the node registry #1156
16 | * fixed ovs-bridge init #1172
17 | * interface name checks enabled for all VM-based nodes #1191
18 |
19 | ## Patches
20 |
21 | ### 0.35.1
22 |
23 | * fixed the regexp used in the interface name check function #1201
24 |
25 | ### 0.35.2
26 |
27 | * removed interface name checks for linux kinds.
28 | * added a note on [`et_X_Y`](../manual/kinds/ceos.md#additional-interface-naming-considerations) nameing of ceos.
29 | * fixed `containerlab config` command for SR OS nodes.
30 |
--------------------------------------------------------------------------------
/docs/rn/0.36.md:
--------------------------------------------------------------------------------
1 | # Release 0.36
2 |
3 | :material-calendar: 2023-01-27 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Image Pull Policy
6 |
7 | Now we give you control over the image pulling behavior by introducing [`image-pull-policy`](../manual/nodes.md#image-pull-policy) node property. You want your image to be always fetched from the remote registry? Now it is possible. #1223
8 |
9 | ## Cisco c8000
10 |
11 | A new kind - [`cisco_8000`](../manual/kinds/c8000.md) - has been added to the list of supported platforms thanks to an awesome contribution from @rskorka in #1216.
12 |
13 | ## Miscellaneous
14 |
15 | * Fixed Cumulus interface name checks #1224
16 | * Housekeeping items in #1208 #1209 and #1225 by @steiler
17 | * Fixed credentials extraction for DockerHub images
18 |
19 | ## Patches
20 |
21 | ### 0.36.1
22 |
23 | * fixed certificate creation for SR Linux nodes identified with `nokia_srlinux` kind.
24 |
--------------------------------------------------------------------------------
/docs/rn/0.38.md:
--------------------------------------------------------------------------------
1 | # Release 0.38
2 |
3 | :material-calendar: 2023-03-13 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Remote startup-configs
6 |
7 | Node's [`startup-config`](../manual/nodes.md#startup-config) can now point to a remote http/https location. Containerlab will download the remote file and use it as a startup-config. #1283
8 |
9 | ## Link MTU
10 |
11 | Now users can set the MTU of the link between two nodes. This is done by [setting the `mtu`](../manual/network.md#link-mtu) field in the link definition. Prior to that change, MTU was always 9500B. #1285
12 |
13 | ## Miscellaneous
14 |
15 | * Network mode `none` has been added to allow running nodes without docker networking #1284
16 | * Fix extra newline chars added to files that already had one #1286
17 | * Default interface name checks are no longer enforced, with only specific kinds using them #1276
18 | * Updated Go to v1.20 #1287
19 |
--------------------------------------------------------------------------------
/docs/rn/0.40.md:
--------------------------------------------------------------------------------
1 | # Release 0.40
2 |
3 | :material-calendar: 2023-04-28 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## IPv4/6 SANs for SR Linux
6 |
7 | In #1345 we added support for IPv4/6 SANs for SR Linux nodes. With this addition, the certificate will contain IPv4/6 addresses assigned by the container runtime as SANs, so TLS connections can be established using these addresses.
8 |
9 | ## Miscellaneous
10 |
11 | * SR Linux variants D4 and H4 have been added #1339
12 | * Deploy command honors Ctrl-C and cleans up interrupted deployment #1340
13 | * SR Linux agent path can now be a remote HTTP(S) URL #1336
14 | * Improvements to the license handling process #1330
15 | * Doc examples updated to comply with changes in SR Linux 23.3.1 #1341
16 |
--------------------------------------------------------------------------------
/docs/rn/0.42.md:
--------------------------------------------------------------------------------
1 | # Release 0.42
2 |
3 | :material-calendar: 2023-06-17 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Home dir for `sudo` user
6 |
7 | Now when you run `sudo containerlab deploy`, the topology files will be searched in the home directory of the user that runs the command and not the root user. Before that change users had to use `sudo -E` to preserve the environment variables and run the command as the current user. Now we made it simpler, just in the spirit of containerlab. #1412
8 |
9 | ## Miscellaneous
10 |
11 | * Optimized link creation #1395
12 | * Kernel version check is performed for topologies with SR Linux nodes which require kernel v4.10+ #1415
13 | * SNMP has been added to the list of services that are enabled by default in SR Linux #1416
14 | * Checkpoint named `clab-initial` is automatically generated on SR Linux nodes when the node is booted #1431
15 | * Partial startup configs with no commands do not cause panic anymore #1423
16 |
--------------------------------------------------------------------------------
/docs/rn/0.49.md:
--------------------------------------------------------------------------------
1 | ---
2 | icon: fontawesome/solid/tree
3 | ---
4 | # Release 0.49 :christmas_tree:
5 |
6 | :material-calendar: 2023-12-21 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
7 |
8 | ## Healthchecks
9 |
10 | @steiler added support for container [healthchecks](../manual/nodes.md#healthcheck) in #1426. Now you can specify healthcheck parameters for your containers in the lab topology file and Containerlab will configure the healthcheck for you.
11 |
12 | This allows you to monitor health of your containerlab nodes as well as serves as a prerequisite for the upcoming [dependency manager improvements](https://github.com/srl-labs/containerlab/pull/1759) to create dependencies on healthiness of the lab nodes.
13 |
14 | ## OpenBSD support
15 |
16 | Fearless @dteslya added support for the mighty [OpenBSD](../manual/kinds/openbsd.md) in #1762. Not only you can deploy labs with OpenBSD, but also startup config support were baked in.
17 |
18 | ## Juniper Evolved (EVO) support
19 |
20 | Thanks to @akielaries Containerlab got another platform under its belt! Welcome [Juniper vJunos-Evolved](../manual/kinds/vr-vjunosevolved.md) #1775.
21 |
22 | ## Cisco FTDv support
23 |
24 | Again thanks to @dteslya we now have support for [Cisco FTDv](../manual/kinds/vr-ftdv.md) platform #1783.
25 |
26 | ## Miscellaneous
27 |
28 | * Ctrl+C now does not remove the lab files #1769
29 | * When using filters to execute commands with [`exec`](../cmd/exec.md), the error is now returned if no nodes match the filter #1786
30 | * ixia-c example lab has been updated by @bortok to feature latest developments done for the ixia-c kind #1795
31 |
--------------------------------------------------------------------------------
/docs/rn/0.53.md:
--------------------------------------------------------------------------------
1 | # Release 0.53
2 |
3 | :material-calendar: 2024-03-25 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Fortinet Fortigate
6 |
7 | @robotwalk added support for the Fortinet Fortigate firewall image. Refer to the [`fortinet_fortigate`](../manual/kinds/fortinet_fortigate.md) kind documentation to learn more about the supported options.
8 |
9 | ## FreeBSD
10 |
11 | After clearing the OpenBSD, @dteslya added support for the [FreeBSD](../manual/kinds/freebsd.md) kind as well!
12 |
13 | ## Containerlab to Drawio
14 |
15 | @FloSch62 created a new tool - [clab-io-draw](https://github.com/srl-labs/clab-io-draw/) - that allows containerlab users to generate drawio (aka diagrams.net) diagrams from their containerlab topologies. The tool is available as a standalone container image, and we packaged it under the [`containerlab graph --drawio`](../cmd/graph.md) command to make it easier to use.
16 |
17 | 
18 |
19 | /// note
20 | This feature is in the "preview" status, we will likely change the command structure in the next release.
21 | ///
22 |
23 | ## Miscellaneous
24 |
25 | * Support for SR Linux release 24.3+
26 | * fixed container network mode #1940
27 | * first steps in making containerlab consumable as a package #1906
28 |
--------------------------------------------------------------------------------
/docs/rn/0.54.md:
--------------------------------------------------------------------------------
1 | # Release 0.54
2 |
3 | :material-calendar: 2024-04-04 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Cisco c8000v
6 |
7 | @mzagozen added support for the long-awaited Cisco c8000v router image. Cisco c8000v is a successor of [Cisco CSR1000v](../manual/kinds/vr-csr.md) and is a **different** product from [Cisco 8000](../manual/kinds/c8000.md) platform emulator.
8 |
9 | Refer to the [`cisco_c8000v`](../manual/kinds/vr-c8000v.md) kind documentation to learn more about the supported options.
10 |
11 | ## Miscellaneous
12 |
13 | * root login allowed for crpd #1967
14 | * support for podman local images #1969
15 | * fixes to SR Linux v24.3+ startup config #1968 #1971
16 |
17 | ## Patches
18 |
19 | ### 0.54.1
20 |
21 | * add `insecure-mgmt` gRPC server to the [default SR Linux config](../manual/kinds/srl.md#grpc-server) #1979
22 | * use Docker v25 API and Podman v5 #1980
23 |
24 | ### 0.54.2
25 |
26 | * fix inspect command behavior with respect to the named-based lab fetching #1984
27 |
--------------------------------------------------------------------------------
/docs/rn/0.59.md:
--------------------------------------------------------------------------------
1 | # Release 0.59
2 |
3 | :material-calendar: 2024-10-23 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Per-stage exec hooks
6 |
7 | Back in 0.51 when we introduced the stages support every stage had a single exec hook that allowed you to execute a command in a container when it enters/exits a stage. It was a good start, but it had one hole in it - it was not possible to execute a command on a host machine when a container enters/exits a particular stage.
8 |
9 | Thanks to @steiler the stages support for execs became much more powerful in this release with allowing you to flexibly define where command is executed (host or container) and when (what stage and what event). Here is an example of a refactored exec hooks:
10 |
11 | ```yaml
12 | nodes:
13 | node1:
14 | stages:
15 | create-links:
16 | exec:
17 | - command: ls /sys/class/net/
18 | target: container #(1)!
19 | phase: on-enter #(2)!
20 | ```
21 |
22 | 1. `target` defaults to "container" and can be omitted. Possible values `container` or `host`
23 | 2. `phase` defaults to "on-enter" and can be omitted. Possible values `on-enter` or `on-exit`
24 |
25 |
26 | Note, this is a breaking change if you used execs in the stages before.
27 |
28 | ## Miscellaneous
29 |
30 | - fixed loading custom export templates #2240
31 | - iptables kernel load to support compressed modules #2251
32 | - fixed the release retrieval routine #2250
33 | - Cisco IOL to support custom PIDs and randomized MACs #2239
34 | - SR Linux kind drops support for mounted authz_keys file #2254
35 |
--------------------------------------------------------------------------------
/docs/rn/0.66.md:
--------------------------------------------------------------------------------
1 | # Release 0.66
2 |
3 | :material-calendar: 2025-03-07 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Netem Reset Command
6 |
7 | The [`reset` command](../cmd/tools/netem/reset.md) has been added to the `netem` tools command to reset the network emulation settings. #2488
8 |
9 | ## WSL-Containerlab goes GA
10 |
11 | The [Containerlab on Windows](../windows.md) documentation has been updated with recommendations to use WSL-Containerlab distribution as the default choice. #2498
12 |
13 | If you haven't yet tried out WSL-Containerlab, now is the time to do it!
14 |
15 | ## Miscellaneous
16 |
17 | * fixed sudo-less operation when AD groups are used #2496
18 | * added missing `seq` template function #2497
19 | * updated VS Code extension documentation #2499
20 | * support for detecting proxy settings when performing `containerlab version upgrade` command #2507
21 | * support for custom SR Linux topology files #2509
22 |
--------------------------------------------------------------------------------
/docs/rn/0.67.md:
--------------------------------------------------------------------------------
1 | # Release 0.67
2 |
3 | :material-calendar: 2025-04-01 · :material-list-status: [Full Changelog](https://github.com/srl-labs/containerlab/releases)
4 |
5 | ## Share access to lab nodes
6 |
7 | Lightweight, fast to deploy, and reproducible containerlabs are meant to be shared via Git. But sometimes, you can't quite share the entire lab... Maybe the recipient doesn't have access to the container images or has other limitations that prevent them from running a copy of you lab.
8 |
9 | Yet, you might find yourself in need to share access of your lab with one or many users. Quite often you want someone else to have a look at your lab when you found something or got stuck. Or maybe you are a lecturer and want to broadcast your lab interaction to your students.
10 |
11 | Checkout the web-based on-demand lab access sharing [using sshx](../manual/share-access.md).
12 |
13 | ## Nornir inventory support
14 |
15 | Thanks to @danlindow, Containerlab will now [generate Nornir' Simple Inventory](../manual/inventory.md#nornir) right next to the Ansible inventory. This opens up a door to your reusing your existing automation stacks built with Nornir.
16 |
17 | ## Miscellaneous
18 |
19 | * docker version you get installed when using the quick-setup script has been bumped to 27.5.1
20 | * added openwrt kind support (no docs yet)
21 | * new SR Linux types - `ixr18e` and `ixrh432d`
22 | * delete process won't require lab dir presence anymore
23 | * bumped required Go version to 1.23
24 |
--------------------------------------------------------------------------------
/errors/errors.go:
--------------------------------------------------------------------------------
1 | package errors
2 |
3 | import "errors"
4 |
5 | // ErrFileNotFound is returned when a file is not found.
6 | var ErrFileNotFound = errors.New("file not found")
7 |
8 | // ErrIncorrectInput is returned when the user input is incorrect.
9 | var ErrIncorrectInput = errors.New("incorrect input")
10 |
--------------------------------------------------------------------------------
/goreleaser.dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine:3
2 |
3 | LABEL maintainer="Roman Dodin "
4 | LABEL documentation="https://containerlab.dev"
5 | LABEL repo="https://github.com/srl-labs/containerlab"
6 |
7 | RUN apk add --no-cache bash \
8 | curl \
9 | docker-cli \
10 | git \
11 | openssh \
12 | make \
13 | iptables \
14 | device-mapper \
15 | e2fsprogs-extra
16 |
17 | COPY containerlab_*.apk /tmp/
18 | RUN apk add --allow-untrusted /tmp/containerlab_*.apk && rm -f /tmp/containerlab_*.apk
19 |
20 | CMD ["/usr/bin/containerlab", "help"]
21 |
--------------------------------------------------------------------------------
/internal/mermaid/graph.go:
--------------------------------------------------------------------------------
1 | package mermaid
2 |
3 | import (
4 | "fmt"
5 | "io"
6 |
7 | "golang.org/x/exp/slices"
8 | )
9 |
10 | // A very minimalistic Mermaid flowchart generator
11 | // that covers the usecase of `containerlab graph`
12 | // command.
13 |
14 | type FlowChart struct {
15 | title string
16 | direction string
17 | edges []Edge
18 | }
19 |
20 | type Edge struct {
21 | nodeA string
22 | nodeB string
23 | }
24 |
25 | func NewFlowChart() *FlowChart {
26 | return &FlowChart{
27 | edges: []Edge{},
28 | }
29 | }
30 |
31 | func (fc *FlowChart) SetTitle(title string) {
32 | fc.title = title
33 | }
34 |
35 | func (fc *FlowChart) SetDirection(direction string) error {
36 | validDirections := []string{"TB", "TD", "BT", "RL", "LR"}
37 | if !slices.Contains(validDirections, direction) {
38 | return fmt.Errorf("invalid direction %s (should be one of %v)", direction, validDirections)
39 | }
40 | fc.direction = direction
41 | return nil
42 | }
43 |
44 | func (fc *FlowChart) AddEdge(nodeA string, nodeB string) {
45 | fc.edges = append(fc.edges, Edge{nodeA: nodeA, nodeB: nodeB})
46 | }
47 |
48 | func (fc *FlowChart) Generate(w io.Writer) {
49 | fmt.Fprintf(w, "---\n")
50 | fmt.Fprintf(w, "title: %s\n", fc.title)
51 | fmt.Fprintf(w, "---\n")
52 | fmt.Fprintf(w, "graph %s\n", fc.direction)
53 | for _, edge := range fc.edges {
54 | fmt.Fprintf(w, " %s---%s\n", edge.nodeA, edge.nodeB)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/internal/slices/slices.go:
--------------------------------------------------------------------------------
1 | package slices
2 |
3 | // Index returns the index of the first occurrence of v in s,
4 | // or -1 if not present.
5 | func Index[E comparable](s []E, v E) int {
6 | for i, vs := range s {
7 | if v == vs {
8 | return i
9 | }
10 | }
11 | return -1
12 | }
13 |
14 | // Contains reports whether v is present in s.
15 | func Contains[E comparable](s []E, v E) bool {
16 | return Index(s, v) >= 0
17 | }
18 |
--------------------------------------------------------------------------------
/lab-examples/.gitignore:
--------------------------------------------------------------------------------
1 | clab-*
--------------------------------------------------------------------------------
/lab-examples/br01/br01.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/ext-bridge/
2 | name: br01
3 |
4 | topology:
5 | kinds:
6 | nokia_srlinux:
7 | type: ixrd2l
8 | image: ghcr.io/nokia/srlinux
9 | nodes:
10 | srl1:
11 | kind: nokia_srlinux
12 | srl2:
13 | kind: nokia_srlinux
14 | srl3:
15 | kind: nokia_srlinux
16 | # note, that the bridge br-clab must be created manually
17 | br-clab:
18 | kind: bridge
19 |
20 | links:
21 | - endpoints: ["srl1:e1-1", "br-clab:eth1"]
22 | - endpoints: ["srl2:e1-1", "br-clab:eth2"]
23 | - endpoints: ["srl3:e1-1", "br-clab:eth3"]
24 |
--------------------------------------------------------------------------------
/lab-examples/cert01/cert01.clab.yml:
--------------------------------------------------------------------------------
1 | name: cert01
2 | topology:
3 | nodes:
4 | sr:
5 | kind: nokia_sros
6 | image: vrnetlab/vr-sros:21.2.R1
7 | license: license-sros21.txt
8 |
--------------------------------------------------------------------------------
/lab-examples/clos01/clos01.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/min-clos/
2 | name: clos01
3 |
4 | topology:
5 | kinds:
6 | nokia_srlinux:
7 | image: ghcr.io/nokia/srlinux
8 | linux:
9 | image: ghcr.io/hellt/network-multitool
10 | nodes:
11 | leaf1:
12 | kind: nokia_srlinux
13 | type: ixrd2l
14 | leaf2:
15 | kind: nokia_srlinux
16 | type: ixrd2l
17 | spine:
18 | kind: nokia_srlinux
19 | type: ixrd3l
20 | client1:
21 | kind: linux
22 | client2:
23 | kind: linux
24 |
25 | links:
26 | - endpoints: ["leaf1:e1-1", "spine:e1-1"]
27 | - endpoints: ["leaf2:e1-1", "spine:e1-2"]
28 | - endpoints: ["client1:eth1", "leaf1:e1-2"]
29 | - endpoints: ["client2:eth1", "leaf2:e1-2"]
30 |
--------------------------------------------------------------------------------
/lab-examples/clos02/configs/client1.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cat > /etc/network/interfaces << EOF
4 | auto eth1
5 |
6 | iface eth1 inet static
7 | address 10.0.0.25
8 | netmask 255.255.255.254
9 |
10 | iface eth1 inet6 static
11 | address 1000:10:0:0::25
12 | netmask 127
13 | pre-up echo 0 > /proc/sys/net/ipv6/conf/eth1/accept_ra
14 | EOF
15 |
16 | ifup eth1
17 |
--------------------------------------------------------------------------------
/lab-examples/clos02/configs/client2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cat > /etc/network/interfaces << EOF
4 | auto eth1
5 |
6 | iface eth1 inet static
7 | address 10.0.0.27
8 | netmask 255.255.255.254
9 |
10 | iface eth1 inet6 static
11 | address 1000:10:0:0::27
12 | netmask 127
13 | pre-up echo 0 > /proc/sys/net/ipv6/conf/eth1/accept_ra
14 | EOF
15 |
16 | ifup eth1
17 |
--------------------------------------------------------------------------------
/lab-examples/clos02/configs/client3.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cat > /etc/network/interfaces << EOF
4 | auto eth1
5 |
6 | iface eth1 inet static
7 | address 10.0.0.29
8 | netmask 255.255.255.254
9 |
10 | iface eth1 inet6 static
11 | address 1000:10:0:0::29
12 | netmask 127
13 | pre-up echo 0 > /proc/sys/net/ipv6/conf/eth1/accept_ra
14 | EOF
15 |
16 | ifup eth1
17 |
--------------------------------------------------------------------------------
/lab-examples/clos02/configs/client4.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | cat > /etc/network/interfaces << EOF
4 | auto eth1
5 |
6 | iface eth1 inet static
7 | address 10.0.0.31
8 | netmask 255.255.255.254
9 |
10 | iface eth1 inet6 static
11 | address 1000:10:0:0::31
12 | netmask 127
13 | pre-up echo 0 > /proc/sys/net/ipv6/conf/eth1/accept_ra
14 | EOF
15 |
16 | ifup eth1
17 |
--------------------------------------------------------------------------------
/lab-examples/clos02/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | CFG_DIR=./configs
4 | SRL_PASSWORD=NokiaSrl1!
5 |
6 | configure_SRL() {
7 | OUT=$(gnmic -a clab-clos02-$1 --timeout 30s -u admin -p $SRL_PASSWORD -e json_ietf --skip-verify set --update-path / --update-file $CFG_DIR/$1.yaml 2>&1)
8 | echo $OUT | grep -q -e '\"operation\": \"UPDATE\"'
9 | if [ $? -eq 0 ]; then
10 | docker exec clab-clos02-$1 sr_cli "save startup" > /dev/null
11 | else
12 | echo "Error: Unable to push config into clab-clos02-$1."
13 | fi
14 | echo $OUT > /dev/null
15 | }
16 |
17 | configure_CLIENT() {
18 | docker cp $CFG_DIR/$1.sh clab-clos02-$1:/tmp/
19 | docker exec clab-clos02-$1 bash /tmp/$1.sh 2>/dev/null
20 | }
21 |
22 | echo
23 | PIDS=""
24 | NE=("leaf1" "leaf2" "leaf3" "leaf4" "spine1" "spine2" "spine3" "spine4" "superspine1" "superspine2")
25 | CLIENT=("client1" "client2" "client3" "client4")
26 |
27 | for VARIANT in ${NE[@]}; do
28 | ( configure_SRL $VARIANT ) &
29 | REF=$!
30 | echo "[$REF] Configuring $VARIANT..."
31 | PIDS+=" $REF"
32 | done
33 |
34 | for VARIANT in ${CLIENT[@]}; do
35 | ( configure_CLIENT $VARIANT ) &
36 | REF=$!
37 | echo "[$REF] Configuring $VARIANT..."
38 | PIDS+=" $REF"
39 | done
40 |
41 | echo
42 | for p in $PIDS; do
43 | if wait $p; then
44 | echo "Process $p success"
45 | else
46 | echo "Process $p fail"
47 | fi
48 | done
49 | echo
--------------------------------------------------------------------------------
/lab-examples/cvx01/README.md:
--------------------------------------------------------------------------------
1 | Example of how to run `cvx` inside `ignite` runtime together with nodes running in `docker` runtime.
--------------------------------------------------------------------------------
/lab-examples/cvx01/sw1/interfaces:
--------------------------------------------------------------------------------
1 | auto swp12
2 | iface swp12
3 | address 12.12.12.1/24
--------------------------------------------------------------------------------
/lab-examples/cvx01/sw2/frr.conf:
--------------------------------------------------------------------------------
1 | interface eth21
2 | ip address 12.12.12.2/24
3 | !
4 |
5 |
--------------------------------------------------------------------------------
/lab-examples/cvx01/topo.clab.yml:
--------------------------------------------------------------------------------
1 | name: cvx01
2 |
3 | topology:
4 | nodes:
5 | sw1:
6 | kind: cumulus_cvx
7 | image: networkop/cx:4.3.0
8 | binds:
9 | - sw1/interfaces:/etc/network/interfaces.d/host-mounts
10 | sw2:
11 | kind: linux
12 | image: frrouting/frr:v7.5.1
13 | binds:
14 | - sw2/frr.conf:/etc/frr/frr.conf
15 |
16 | links:
17 | - endpoints: ["sw1:swp12", "sw2:eth21"]
18 |
--------------------------------------------------------------------------------
/lab-examples/cvx02/README.md:
--------------------------------------------------------------------------------
1 | Example of how to run `cvx` nodes inside docker runtime.
2 |
3 |
--------------------------------------------------------------------------------
/lab-examples/cvx02/h1/interfaces:
--------------------------------------------------------------------------------
1 | auto lo
2 | iface lo inet loopback
3 |
4 | auto eth1
5 | iface eth1
6 | address 12.12.12.2/24
--------------------------------------------------------------------------------
/lab-examples/cvx02/sw1/interfaces:
--------------------------------------------------------------------------------
1 | auto lo
2 | iface lo inet loopback
3 |
4 | auto mgmt
5 | iface mgmt
6 | vrf-table auto
7 |
8 | auto eth0
9 | iface eth0
10 | vrf mgmt
11 |
12 | auto swp12
13 | iface swp12
14 | address 12.12.12.1/24
--------------------------------------------------------------------------------
/lab-examples/cvx02/topo.clab.yml:
--------------------------------------------------------------------------------
1 | name: cvx02
2 |
3 | topology:
4 | nodes:
5 | sw1:
6 | kind: cumulus_cvx
7 | image: networkop/cx:4.3.0
8 | runtime: docker
9 | binds:
10 | - /lib/modules:/lib/modules:ro # for kernel modules like ebtables
11 | - sw1/interfaces:/etc/network/interfaces
12 | h1:
13 | kind: linux
14 | image: networkop/host:ifreload
15 | binds:
16 | - h1/interfaces:/etc/network/interfaces
17 | cmd: "2" # wait for 2 interfaces to be connected: eth0 + eth1
18 |
19 | links:
20 | - endpoints: ["sw1:swp12", "h1:eth1"]
21 |
--------------------------------------------------------------------------------
/lab-examples/fortigate/fortigate.clab.yml:
--------------------------------------------------------------------------------
1 | name: fortigate
2 | topology:
3 | nodes:
4 | forti1:
5 | kind: fortinet_fortigate
6 | image: vrnetlab/vr-fortigate:7.0.14
7 | forti2:
8 | kind: fortinet_fortigate
9 | image: vrnetlab/vr-fortigate:7.0.14
10 | links:
11 | - endpoints: ["forti1:eth1", "forti2:eth1"]
12 |
--------------------------------------------------------------------------------
/lab-examples/freebsd01/freebsd01.clab.yml:
--------------------------------------------------------------------------------
1 | name: freebsd01
2 | topology:
3 | nodes:
4 | fbsd1:
5 | kind: freebsd
6 | image: vrnetlab/vr-freebsd:13.2
7 | client1:
8 | kind: "linux"
9 | image: wbitt/network-multitool:alpine-extra
10 | exec:
11 | - ip addr add 192.168.1.2/30 dev eth1
12 | - ip route add 192.168.2.0/30 via 192.168.1.1
13 | client2:
14 | kind: "linux"
15 | image: wbitt/network-multitool:alpine-extra
16 | exec:
17 | - ip addr add 192.168.2.2/30 dev eth1
18 | - ip route add 192.168.1.0/30 via 192.168.2.1
19 | links:
20 | - endpoints: ["fbsd1:eth1", "client1:eth1"]
21 | - endpoints: ["fbsd1:eth2", "client2:eth1"]
--------------------------------------------------------------------------------
/lab-examples/frr01/PC-interfaces.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | sudo docker exec -d clab-frr01-PC1 ip link set eth1 up
3 | sudo docker exec -d clab-frr01-PC1 ip addr add 192.168.11.2/24 dev eth1
4 | sudo docker exec -d clab-frr01-PC1 ip route add 192.168.0.0/16 via 192.168.11.1 dev eth1
5 | sudo docker exec -d clab-frr01-PC1 ip route add 10.10.10.0/24 via 192.168.11.1 dev eth1
6 |
7 | sudo docker exec -d clab-frr01-PC2 ip link set eth1 up
8 | sudo docker exec -d clab-frr01-PC2 ip addr add 192.168.12.2/24 dev eth1
9 | sudo docker exec -d clab-frr01-PC2 ip route add 192.168.0.0/16 via 192.168.12.1 dev eth1
10 | sudo docker exec -d clab-frr01-PC2 ip route add 10.10.10.0/24 via 192.168.12.1 dev eth1
11 |
12 | sudo docker exec -d clab-frr01-PC3 ip link set eth1 up
13 | sudo docker exec -d clab-frr01-PC3 ip addr add 192.168.13.2/24 dev eth1
14 | sudo docker exec -d clab-frr01-PC3 ip route add 192.168.0.0/16 via 192.168.13.1 dev eth1
15 | sudo docker exec -d clab-frr01-PC3 ip route add 10.10.10.0/24 via 192.168.13.1 dev eth1
16 |
--------------------------------------------------------------------------------
/lab-examples/frr01/README.md:
--------------------------------------------------------------------------------
1 | # Simple OSPF lab using FRR
2 |
3 | This lab example consists of three FRR routers connected in a ring topology. Each router has one PC connected to it.
4 |
5 | This is also an example of how to pre-configure lab nodes on "linux" node types in Containerlab.
6 |
7 | To start this lab, run the *run.sh* script, which will run the containerlab deploy commands, and then configure the PC interfaces.
8 |
9 | The lab configuration is documented in detail at: https://www.brianlinkletter.com/2021/05/use-containerlab-to-emulate-open-source-routers/
10 |
--------------------------------------------------------------------------------
/lab-examples/frr01/frr01.clab.yml:
--------------------------------------------------------------------------------
1 | name: frr01
2 |
3 | topology:
4 | nodes:
5 | router1:
6 | kind: linux
7 | image: frrouting/frr:v7.5.1
8 | binds:
9 | - router1/daemons:/etc/frr/daemons
10 | - router1/frr.conf:/etc/frr/frr.conf
11 | router2:
12 | kind: linux
13 | image: frrouting/frr:v7.5.1
14 | binds:
15 | - router2/daemons:/etc/frr/daemons
16 | - router2/frr.conf:/etc/frr/frr.conf
17 | router3:
18 | kind: linux
19 | image: frrouting/frr:v7.5.1
20 | binds:
21 | - router3/daemons:/etc/frr/daemons
22 | - router3/frr.conf:/etc/frr/frr.conf
23 | PC1:
24 | kind: linux
25 | image: praqma/network-multitool:latest
26 | PC2:
27 | kind: linux
28 | image: praqma/network-multitool:latest
29 | PC3:
30 | kind: linux
31 | image: praqma/network-multitool:latest
32 |
33 | links:
34 | - endpoints: ["router1:eth1", "router2:eth1"]
35 | - endpoints: ["router1:eth2", "router3:eth1"]
36 | - endpoints: ["router2:eth2", "router3:eth2"]
37 | - endpoints: ["PC1:eth1", "router1:eth3"]
38 | - endpoints: ["PC2:eth1", "router2:eth3"]
39 | - endpoints: ["PC3:eth1", "router3:eth3"]
40 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router1/daemons:
--------------------------------------------------------------------------------
1 | zebra=yes
2 | bgpd=no
3 | ospfd=yes
4 | ospf6d=no
5 | ripd=no
6 | ripngd=no
7 | isisd=no
8 | pimd=no
9 | ldpd=yes
10 | nhrpd=no
11 | eigrpd=no
12 | babeld=no
13 | sharpd=no
14 | staticd=no
15 | pbrd=no
16 | bfdd=no
17 | fabricd=no
18 |
19 | vtysh_enable=yes
20 | zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
21 | bgpd_options=" --daemon -A 127.0.0.1"
22 | ospfd_options=" --daemon -A 127.0.0.1"
23 | ospf6d_options=" --daemon -A ::1"
24 | ripd_options=" --daemon -A 127.0.0.1"
25 | ripngd_options=" --daemon -A ::1"
26 | isisd_options=" --daemon -A 127.0.0.1"
27 | pimd_options=" --daemon -A 127.0.0.1"
28 | ldpd_options=" --daemon -A 127.0.0.1"
29 | nhrpd_options=" --daemon -A 127.0.0.1"
30 | eigrpd_options=" --daemon -A 127.0.0.1"
31 | babeld_options=" --daemon -A 127.0.0.1"
32 | sharpd_options=" --daemon -A 127.0.0.1"
33 | staticd_options=" --daemon -A 127.0.0.1"
34 | pbrd_options=" --daemon -A 127.0.0.1"
35 | bfdd_options=" --daemon -A 127.0.0.1"
36 | fabricd_options=" --daemon -A 127.0.0.1"
37 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router1/frr.conf:
--------------------------------------------------------------------------------
1 | frr version 7.5.1_git
2 | frr defaults traditional
3 | hostname router1
4 | no ipv6 forwarding
5 | !
6 | interface eth1
7 | ip address 192.168.1.1/24
8 | !
9 | interface eth2
10 | ip address 192.168.2.1/24
11 | !
12 | interface eth3
13 | ip address 192.168.11.1/24
14 | !
15 | interface lo
16 | ip address 10.10.10.1/32
17 | !
18 | router ospf
19 | passive-interface eth3
20 | network 192.168.1.0/24 area 0.0.0.0
21 | network 192.168.2.0/24 area 0.0.0.0
22 | network 192.168.11.0/24 area 0.0.0.0
23 | !
24 | line vty
25 | !
26 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router2/daemons:
--------------------------------------------------------------------------------
1 | zebra=yes
2 | bgpd=no
3 | ospfd=yes
4 | ospf6d=no
5 | ripd=no
6 | ripngd=no
7 | isisd=no
8 | pimd=no
9 | ldpd=yes
10 | nhrpd=no
11 | eigrpd=no
12 | babeld=no
13 | sharpd=no
14 | staticd=no
15 | pbrd=no
16 | bfdd=no
17 | fabricd=no
18 |
19 | vtysh_enable=yes
20 | zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
21 | bgpd_options=" --daemon -A 127.0.0.1"
22 | ospfd_options=" --daemon -A 127.0.0.1"
23 | ospf6d_options=" --daemon -A ::1"
24 | ripd_options=" --daemon -A 127.0.0.1"
25 | ripngd_options=" --daemon -A ::1"
26 | isisd_options=" --daemon -A 127.0.0.1"
27 | pimd_options=" --daemon -A 127.0.0.1"
28 | ldpd_options=" --daemon -A 127.0.0.1"
29 | nhrpd_options=" --daemon -A 127.0.0.1"
30 | eigrpd_options=" --daemon -A 127.0.0.1"
31 | babeld_options=" --daemon -A 127.0.0.1"
32 | sharpd_options=" --daemon -A 127.0.0.1"
33 | staticd_options=" --daemon -A 127.0.0.1"
34 | pbrd_options=" --daemon -A 127.0.0.1"
35 | bfdd_options=" --daemon -A 127.0.0.1"
36 | fabricd_options=" --daemon -A 127.0.0.1"
37 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router2/frr.conf:
--------------------------------------------------------------------------------
1 | frr version 7.5.1_git
2 | frr defaults traditional
3 | hostname router2
4 | no ipv6 forwarding
5 | !
6 | interface eth1
7 | ip address 192.168.1.2/24
8 | !
9 | interface eth2
10 | ip address 192.168.3.1/24
11 | !
12 | interface eth3
13 | ip address 192.168.12.1/24
14 | !
15 | interface lo
16 | ip address 10.10.10.2/32
17 | !
18 | router ospf
19 | passive-interface eth3
20 | network 192.168.1.0/24 area 0.0.0.0
21 |
22 | network 192.168.3.0/24 area 0.0.0.0
23 | network 192.168.12.0/24 area 0.0.0.0
24 | !
25 | line vty
26 | !
27 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router3/daemons:
--------------------------------------------------------------------------------
1 | zebra=yes
2 | bgpd=no
3 | ospfd=yes
4 | ospf6d=no
5 | ripd=no
6 | ripngd=no
7 | isisd=no
8 | pimd=no
9 | ldpd=yes
10 | nhrpd=no
11 | eigrpd=no
12 | babeld=no
13 | sharpd=no
14 | staticd=no
15 | pbrd=no
16 | bfdd=no
17 | fabricd=no
18 |
19 | vtysh_enable=yes
20 | zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
21 | bgpd_options=" --daemon -A 127.0.0.1"
22 | ospfd_options=" --daemon -A 127.0.0.1"
23 | ospf6d_options=" --daemon -A ::1"
24 | ripd_options=" --daemon -A 127.0.0.1"
25 | ripngd_options=" --daemon -A ::1"
26 | isisd_options=" --daemon -A 127.0.0.1"
27 | pimd_options=" --daemon -A 127.0.0.1"
28 | ldpd_options=" --daemon -A 127.0.0.1"
29 | nhrpd_options=" --daemon -A 127.0.0.1"
30 | eigrpd_options=" --daemon -A 127.0.0.1"
31 | babeld_options=" --daemon -A 127.0.0.1"
32 | sharpd_options=" --daemon -A 127.0.0.1"
33 | staticd_options=" --daemon -A 127.0.0.1"
34 | pbrd_options=" --daemon -A 127.0.0.1"
35 | bfdd_options=" --daemon -A 127.0.0.1"
36 | fabricd_options=" --daemon -A 127.0.0.1"
37 |
--------------------------------------------------------------------------------
/lab-examples/frr01/router3/frr.conf:
--------------------------------------------------------------------------------
1 | frr version 7.5.1_git
2 | frr defaults traditional
3 | hostname router3
4 | no ipv6 forwarding
5 | !
6 | interface eth1
7 | ip address 192.168.2.2/24
8 | !
9 | interface eth2
10 | ip address 192.168.3.2/24
11 | !
12 | interface eth3
13 | ip address 192.168.13.1/24
14 | !
15 | interface lo
16 | ip address 10.10.10.3/32
17 | !
18 | router ospf
19 | passive-interface eth3
20 | network 192.168.2.0/24 area 0.0.0.0
21 | network 192.168.3.0/24 area 0.0.0.0
22 | network 192.168.13.0/24 area 0.0.0.0
23 | !
24 | line vty
25 | !
26 |
--------------------------------------------------------------------------------
/lab-examples/frr01/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | clab deploy --topo frr01.clab.yml
3 | ./PC-interfaces.sh
4 |
--------------------------------------------------------------------------------
/lab-examples/ftdv01/ftdv01.yml:
--------------------------------------------------------------------------------
1 | name: ftdv01
2 | topology:
3 | nodes:
4 | ftdv1:
5 | kind: cisco_ftdv
6 | image: vrnetlab/vr-ftdv:7.2.5
7 | client1:
8 | kind: "linux"
9 | image: wbitt/network-multitool:alpine-extra
10 | exec:
11 | - ip addr add 192.168.1.2/30 dev eth1
12 | - ip route add 192.168.2.0/30 via 192.168.1.1
13 | client2:
14 | kind: "linux"
15 | image: wbitt/network-multitool:alpine-extra
16 | exec:
17 | - ip addr add 192.168.2.2/30 dev eth1
18 | - ip route add 192.168.1.0/30 via 192.168.2.1
19 | links:
20 | - endpoints: ["ftdv1:eth1", "client1:eth1"]
21 | - endpoints: ["ftdv1:eth2", "client2:eth1"]
22 |
--------------------------------------------------------------------------------
/lab-examples/generic_vm01/generic_vm.clab.yml:
--------------------------------------------------------------------------------
1 | name: generic_vm
2 |
3 | topology:
4 | nodes:
5 | ubuntu:
6 | kind: generic_vm
7 | image: vrnetlab/vr-ubuntu:jammy
8 | srl:
9 | kind: nokia_srlinux
10 | image: ghcr.io/nokia/srlinux:24.3.2
11 | startup-config: |
12 | set / interface ethernet-1/1 admin-state enable
13 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
14 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.2/24
15 | set / network-instance default interface ethernet-1/1.0
16 | links:
17 | - endpoints: ["srl:e1-1", "ubuntu:eth1"]
18 |
--------------------------------------------------------------------------------
/lab-examples/ixiac01/go.mod:
--------------------------------------------------------------------------------
1 | module ixiac01
2 |
3 | go 1.23
4 |
5 | toolchain go1.23.0
6 |
7 | require github.com/open-traffic-generator/snappi/gosnappi v1.31.0
8 |
9 | require (
10 | github.com/Masterminds/semver/v3 v3.3.1 // indirect
11 | github.com/ghodss/yaml v1.0.0 // indirect
12 | github.com/kr/text v0.2.0 // indirect
13 | golang.org/x/net v0.35.0 // indirect
14 | golang.org/x/sys v0.30.0 // indirect
15 | golang.org/x/text v0.22.0 // indirect
16 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
17 | google.golang.org/grpc v1.72.2 // indirect
18 | google.golang.org/protobuf v1.36.6 // indirect
19 | gopkg.in/yaml.v2 v2.4.0 // indirect
20 | )
21 |
--------------------------------------------------------------------------------
/lab-examples/ixiac01/ixiac01.clab.yml:
--------------------------------------------------------------------------------
1 | name: ixiac01
2 | topology:
3 | nodes:
4 | ixia-c:
5 | kind: keysight_ixia-c-one
6 | image: ghcr.io/open-traffic-generator/ixia-c-one:1.31.0-3
7 | srl:
8 | kind: nokia_srlinux
9 | image: ghcr.io/nokia/srlinux:23.10.1
10 | startup-config: srl.cfg
11 | links:
12 | - endpoints: ["ixia-c:eth1", "srl:e1-1"]
13 | - endpoints: ["ixia-c:eth2", "srl:e1-2"]
14 |
--------------------------------------------------------------------------------
/lab-examples/ixiac01/srl.cfg:
--------------------------------------------------------------------------------
1 | set /interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
2 | set /interface ethernet-1/1 subinterface 0 ipv4 address 1.1.1.2/24
3 | set /interface ethernet-1/2 subinterface 0 ipv4 admin-state enable
4 | set /interface ethernet-1/2 subinterface 0 ipv4 address 2.2.2.2/24
5 | set /network-instance default interface ethernet-1/1.0
6 | set /network-instance default interface ethernet-1/2.0
7 |
8 | set /network-instance default next-hop-groups group group1 nexthop 1 ip-address 2.2.2.1 admin-state enable
9 | set /network-instance default static-routes route 20.20.20.0/24 next-hop-group group1 admin-state enable
10 |
--------------------------------------------------------------------------------
/lab-examples/k8s_kind01/k01-config.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kind.x-k8s.io/v1alpha4
2 | kind: Cluster
3 | nodes:
4 | - role: control-plane
5 | - role: worker
6 |
--------------------------------------------------------------------------------
/lab-examples/k8s_kind01/k8s_kind01.clab.yml:
--------------------------------------------------------------------------------
1 | name: kind01
2 |
3 | topology:
4 | kinds:
5 | nokia_srlinux:
6 | image: ghcr.io/nokia/srlinux:23.10.1
7 | nodes:
8 | srl01:
9 | kind: nokia_srlinux
10 | k01:
11 | kind: k8s-kind
12 | startup-config: k01-config.yaml
13 | k02:
14 | kind: k8s-kind
15 |
16 | # k01 cluster contains 2 nodes: a control-plane and a worker
17 | # the cluster config is defined in k01-config.yaml
18 | k01-control-plane:
19 | kind: ext-container
20 | exec:
21 | - "ip addr add dev eth1 192.168.10.1/24"
22 | k01-worker:
23 | kind: ext-container
24 | exec:
25 | - "ip addr add dev eth1 192.168.11.1/24"
26 |
27 | # k02 cluster has an all-in-one node
28 | k02-control-plane:
29 | kind: ext-container
30 | exec:
31 | - "ip addr add dev eth1 192.168.20.1/24"
32 |
33 | links:
34 | - endpoints: ["srl01:e1-1", "k01-control-plane:eth1"]
35 | - endpoints: ["srl01:e1-2", "k01-worker:eth1"]
36 |
37 | - endpoints: ["srl01:e1-4", "k02-control-plane:eth1"]
38 |
--------------------------------------------------------------------------------
/lab-examples/openbsd01/openbsd01.yml:
--------------------------------------------------------------------------------
1 | name: openbsd01
2 | topology:
3 | nodes:
4 | obsd1:
5 | kind: openbsd
6 | image: vrnetlab/vr-openbsd:7.3
7 | client1:
8 | kind: "linux"
9 | image: wbitt/network-multitool:alpine-extra
10 | exec:
11 | - ip addr add 192.168.1.2/30 dev eth1
12 | - ip route add 192.168.2.0/30 via 192.168.1.1
13 | client2:
14 | kind: "linux"
15 | image: wbitt/network-multitool:alpine-extra
16 | exec:
17 | - ip addr add 192.168.2.2/30 dev eth1
18 | - ip route add 192.168.1.0/30 via 192.168.2.1
19 | links:
20 | - endpoints: ["obsd1:eth1", "client1:eth1"]
21 | - endpoints: ["obsd1:eth2", "client2:eth1"]
--------------------------------------------------------------------------------
/lab-examples/ost-srl/ost-srl.clab.yml:
--------------------------------------------------------------------------------
1 | name: ost-srl
2 |
3 | topology:
4 | nodes:
5 | ost:
6 | kind: linux
7 | image: ostinato/ostinato:v1.3.0-1
8 | ports:
9 | - 5900:5900/tcp
10 | - 7878:7878/tcp
11 | binds:
12 | - .:/root/shared
13 | srl:
14 | kind: nokia_srlinux
15 | image: ghcr.io/nokia/srlinux:24.3.2
16 | startup-config: srl.cfg
17 | links:
18 | - endpoints: ["ost:eth1", "srl:e1-1"]
19 | - endpoints: ["ost:eth2", "srl:e1-2"]
20 |
--------------------------------------------------------------------------------
/lab-examples/ost-srl/ost-srl.ossn:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/lab-examples/ost-srl/ost-srl.ossn
--------------------------------------------------------------------------------
/lab-examples/ost-srl/srl.cfg:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 subinterface 0 ipv4 address 10.0.0.1/24
2 | set / interface ethernet-1/2 subinterface 0 ipv4 address 20.0.0.1/24
3 | set / network-instance default interface ethernet-1/1.0
4 | set / network-instance default interface ethernet-1/2.0
5 |
--------------------------------------------------------------------------------
/lab-examples/sonic01/sonic01.clab.yml:
--------------------------------------------------------------------------------
1 | name: sonic01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | sonic:
9 | kind: sonic-vs
10 | image: docker-sonic-vs:2020-11-12
11 |
12 | links:
13 | - endpoints: ["srl:e1-1", "sonic:eth1"]
14 |
--------------------------------------------------------------------------------
/lab-examples/srl-quickstart/srl01.clab.yml:
--------------------------------------------------------------------------------
1 | name: srl
2 | # node name will be srl unless overridden by CLAB_PREFIX
3 | prefix: ${CLAB_PREFIX:=""}
4 |
5 | topology:
6 | nodes:
7 | srl:
8 | kind: nokia_srlinux
9 | image: ${SRL_IMAGE:=ghcr.io/nokia/srlinux}:${SRL_VERSION:=latest}
10 | type: ${SRL_TYPE:=ixrd3l}
11 |
--------------------------------------------------------------------------------
/lab-examples/srl-quickstart/srl02.clab.yml:
--------------------------------------------------------------------------------
1 | name: srl2
2 | # node names will be srl1 and srl2 unless overridden by CLAB_PREFIX
3 | prefix: ${CLAB_PREFIX:=""}
4 |
5 | topology:
6 | nodes:
7 | srl1:
8 | kind: nokia_srlinux
9 | image: ghcr.io/nokia/srlinux:${SRL_VERSION:=latest}
10 | type: ${SRL_TYPE:=ixrd3l}
11 |
12 | srl2:
13 | kind: nokia_srlinux
14 | image: ghcr.io/nokia/srlinux:${SRL_VERSION:=latest}
15 | type: ${SRL_TYPE:=ixrd3l}
16 |
17 | links:
18 | - endpoints: [srl1:e1-1, srl2:e1-1]
19 | - endpoints: [srl1:e1-2, srl2:e1-2]
20 |
--------------------------------------------------------------------------------
/lab-examples/srl01/srl01.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/single-srl/
2 | name: srl01
3 |
4 | topology:
5 | kinds:
6 | nokia_srlinux:
7 | type: ixrd3
8 | image: ghcr.io/nokia/srlinux
9 | nodes:
10 | srl:
11 | kind: nokia_srlinux
12 |
--------------------------------------------------------------------------------
/lab-examples/srl02/srl02.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/two-srls/
2 | name: srl02
3 |
4 | topology:
5 | nodes:
6 | srl1:
7 | kind: nokia_srlinux
8 | image: ghcr.io/nokia/srlinux
9 | startup-config: srl1.cfg
10 | srl2:
11 | kind: nokia_srlinux
12 | image: ghcr.io/nokia/srlinux
13 | startup-config: srl2.cfg
14 |
15 | links:
16 | - endpoints: ["srl1:e1-1", "srl2:e1-1"]
17 |
--------------------------------------------------------------------------------
/lab-examples/srl02/srl1.cfg:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 0
3 | set / interface ethernet-1/1 subinterface 0 ipv4
4 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
5 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.0/31
6 | set / interface ethernet-1/1 subinterface 0 ipv6
7 | set / interface ethernet-1/1 subinterface 0 ipv6 admin-state enable
8 | set / interface ethernet-1/1 subinterface 0 ipv6 address 2002::192.168.0.0/127
9 |
10 | set / network-instance default
11 | set / network-instance default interface ethernet-1/1.0
12 |
--------------------------------------------------------------------------------
/lab-examples/srl02/srl2.cfg:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 0
3 | set / interface ethernet-1/1 subinterface 0 ipv4
4 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
5 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.1/31
6 | set / interface ethernet-1/1 subinterface 0 ipv6
7 | set / interface ethernet-1/1 subinterface 0 ipv6 admin-state enable
8 | set / interface ethernet-1/1 subinterface 0 ipv6 address 2002::192.168.0.1/127
9 |
10 | set / network-instance default
11 | set / network-instance default interface ethernet-1/1.0
--------------------------------------------------------------------------------
/lab-examples/srlceos01/srlceos01.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/srl-ceos/
2 | name: srlceos01
3 |
4 | topology:
5 | nodes:
6 | srl:
7 | kind: nokia_srlinux
8 | image: ghcr.io/nokia/srlinux:24.10
9 | ceos:
10 | kind: arista_ceos
11 | image: ceos:4.32.0F
12 |
13 | links:
14 | - endpoints: ["srl:ethernet-1/1", "ceos:eth1"]
15 |
--------------------------------------------------------------------------------
/lab-examples/srlcrpd01/srlcrpd01.clab.yml:
--------------------------------------------------------------------------------
1 | # topology documentation: http://containerlab.dev/lab-examples/srl-crpd/
2 | name: srlcrpd01
3 | topology:
4 | nodes:
5 | crpd:
6 | kind: juniper_crpd
7 | image: crpd:20.2R1.10
8 | srl:
9 | kind: nokia_srlinux
10 | image: ghcr.io/nokia/srlinux
11 |
12 | links:
13 | - endpoints: ["srl:e1-1", "crpd:eth1"]
14 |
--------------------------------------------------------------------------------
/lab-examples/srlfrr01/frr.cfg:
--------------------------------------------------------------------------------
1 | interface eth1
2 | ip address 192.168.1.2/24
3 | !
4 | interface lo
5 | ip address 10.10.10.2/32
6 | !
7 | router bgp 65001
8 | bgp router-id 10.10.10.2
9 | neighbor 192.168.1.1 remote-as 65001
10 | !
11 | address-family ipv4 unicast
12 | network 10.10.10.2/32
13 | exit-address-family
--------------------------------------------------------------------------------
/lab-examples/srlfrr01/srl.cfg:
--------------------------------------------------------------------------------
1 | # enter candidate datastore
2 | enter candidate
3 |
4 | # configure loopback and data interfaces
5 | set / interface ethernet-1/1 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 admin-state enable
7 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.1.1/24
8 |
9 | set / interface lo0 subinterface 0 admin-state enable
10 | set / interface lo0 subinterface 0 ipv4 address 10.10.10.1/32
11 | set / network-instance default interface ethernet-1/1.0
12 | set / network-instance default interface lo0.0
13 |
14 | # configure BGP
15 | set / network-instance default protocols bgp admin-state enable
16 | set / network-instance default protocols bgp router-id 10.10.10.1
17 | set / network-instance default protocols bgp autonomous-system 65001
18 | set / network-instance default protocols bgp group ibgp ipv4-unicast admin-state enable
19 | set / network-instance default protocols bgp group ibgp export-policy export-lo
20 | set / network-instance default protocols bgp neighbor 192.168.1.2 admin-state enable
21 | set / network-instance default protocols bgp neighbor 192.168.1.2 peer-group ibgp
22 | set / network-instance default protocols bgp neighbor 192.168.1.2 peer-as 65001
23 |
24 | # create export policy
25 | set / routing-policy policy export-lo statement 10 match protocol local
26 | set / routing-policy policy export-lo statement 10 action accept
27 |
28 | # commit config
29 | commit now
--------------------------------------------------------------------------------
/lab-examples/srlfrr01/srlfrr01.clab.yml:
--------------------------------------------------------------------------------
1 | name: srlfrr01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | frr:
9 | kind: linux
10 | image: frrouting/frr:v7.5.0
11 | binds:
12 | - daemons:/etc/frr/daemons
13 |
14 | links:
15 | - endpoints: ["srl:e1-1", "frr:eth1"]
16 |
--------------------------------------------------------------------------------
/lab-examples/srlvjunos01/srl.cli:
--------------------------------------------------------------------------------
1 | interface ethernet-1/1 {
2 | admin-state enable
3 | subinterface 0 {
4 | ipv4 {
5 | admin-state enable
6 | address 192.168.0.2/24 {
7 | }
8 | }
9 | }
10 | }
11 | interface ethernet-1/2 {
12 | admin-state enable
13 | subinterface 0 {
14 | ipv4 {
15 | admin-state enable
16 | address 192.168.1.2/24 {
17 | }
18 | }
19 | }
20 | }
21 | interface ethernet-1/3 {
22 | admin-state enable
23 | subinterface 0 {
24 | ipv4 {
25 | admin-state enable
26 | address 192.168.2.2/24 {
27 | }
28 | }
29 | }
30 | }
31 |
32 | network-instance default {
33 | interface ethernet-1/1.0 {
34 | }
35 | interface ethernet-1/2.0 {
36 | }
37 | interface ethernet-1/3.0 {
38 | }
39 | }
--------------------------------------------------------------------------------
/lab-examples/srlvjunos01/srlvjunos01.clab.yml:
--------------------------------------------------------------------------------
1 | name: srlvjunos01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux:23.7.1
8 | startup-config: srl.cli
9 |
10 | vswitch:
11 | kind: juniper_vjunosswitch
12 | image: vrnetlab/vr-vjunosswitch:23.2R1.14
13 | startup-config: vjunos.cfg
14 |
15 | links:
16 | - endpoints: ["srl:e1-1", "vswitch:eth1"]
17 | - endpoints: ["srl:e1-2", "vswitch:eth2"]
18 | - endpoints: ["srl:e1-3", "vswitch:eth3"]
19 |
--------------------------------------------------------------------------------
/lab-examples/srlvjunos01/vjunos.cfg:
--------------------------------------------------------------------------------
1 | interfaces {
2 | ge-0/0/0 {
3 | unit 0 {
4 | family inet {
5 | address 192.168.0.1/24;
6 | }
7 | }
8 | }
9 | ge-0/0/1 {
10 | unit 0 {
11 | family inet {
12 | address 192.168.1.1/24;
13 | }
14 | }
15 | }
16 | ge-0/0/2 {
17 | unit 0 {
18 | family inet {
19 | address 192.168.2.1/24;
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lab-examples/srlvjunos02/srl.cli:
--------------------------------------------------------------------------------
1 | interface ethernet-1/1 {
2 | admin-state enable
3 | subinterface 0 {
4 | ipv4 {
5 | admin-state enable
6 | address 192.168.0.2/24 {
7 | }
8 | }
9 | }
10 | }
11 | interface ethernet-1/2 {
12 | admin-state enable
13 | subinterface 0 {
14 | ipv4 {
15 | admin-state enable
16 | address 192.168.1.2/24 {
17 | }
18 | }
19 | }
20 | }
21 | interface ethernet-1/3 {
22 | admin-state enable
23 | subinterface 0 {
24 | ipv4 {
25 | admin-state enable
26 | address 192.168.2.2/24 {
27 | }
28 | }
29 | }
30 | }
31 |
32 | network-instance default {
33 | interface ethernet-1/1.0 {
34 | }
35 | interface ethernet-1/2.0 {
36 | }
37 | interface ethernet-1/3.0 {
38 | }
39 | }
--------------------------------------------------------------------------------
/lab-examples/srlvjunos02/srlvjunos02.clab.yml:
--------------------------------------------------------------------------------
1 | name: srlvjunos02
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux:23.7.1
8 | startup-config: srl.cli
9 |
10 | vevo:
11 | kind: juniper_vjunosevolved
12 | image: vrnetlab/vr-vjunosevolved:23.2R1-S1.8-EVO
13 | startup-config: vjunos.cfg
14 |
15 | links:
16 | - endpoints: ["srl:e1-1", "vevo:eth1"]
17 | - endpoints: ["srl:e1-2", "vevo:eth2"]
18 | - endpoints: ["srl:e1-3", "vevo:eth3"]
19 |
--------------------------------------------------------------------------------
/lab-examples/srlvjunos02/vjunos.cfg:
--------------------------------------------------------------------------------
1 | interfaces {
2 | et-0/0/0 {
3 | unit 0 {
4 | family inet {
5 | address 192.168.0.1/24;
6 | }
7 | }
8 | }
9 | et-0/0/1 {
10 | unit 0 {
11 | family inet {
12 | address 192.168.1.1/24;
13 | }
14 | }
15 | }
16 | et-0/0/2 {
17 | unit 0 {
18 | family inet {
19 | address 192.168.2.1/24;
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lab-examples/srlxrd01/srl.cfg:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 0
3 | set / interface ethernet-1/1 subinterface 0 ipv4
4 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
5 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.0/31
6 | set / interface ethernet-1/1 subinterface 0 ipv6
7 | set / interface ethernet-1/1 subinterface 0 ipv6 admin-state enable
8 | set / interface ethernet-1/1 subinterface 0 ipv6 address 2002::192.168.0.0/127
9 |
10 | set / network-instance default
11 | set / network-instance default interface ethernet-1/1.0
--------------------------------------------------------------------------------
/lab-examples/srlxrd01/srlxrd01.clab.yml:
--------------------------------------------------------------------------------
1 | name: srlxrd01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | startup-config: srl.cfg
9 |
10 | xrd:
11 | kind: cisco_xrd
12 | image: xrd-control-plane
13 | startup-config: xrd.cfg
14 |
15 | links:
16 | - endpoints: ["srl:e1-1", "xrd:Gi0-0-0-0"]
17 |
--------------------------------------------------------------------------------
/lab-examples/srlxrd01/xrd.cfg:
--------------------------------------------------------------------------------
1 | !
2 | hostname {{ .ShortName }}
3 | !
4 | username clab
5 | group root-lr
6 | group cisco-support
7 | secret clab@123
8 | !
9 | grpc
10 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
11 | port 9339
12 | no-tls
13 | address-family dual
14 | !
15 | {{- if .Env.CLAB_MGMT_VRF }}
16 | vrf {{ .Env.CLAB_MGMT_VRF }}
17 | address-family ipv4 unicast
18 | !
19 | address-family ipv6 unicast
20 | !
21 | {{- end}}
22 | !
23 | line default
24 | transport input ssh
25 | !
26 | netconf-yang agent
27 | ssh
28 | !
29 | interface MgmtEth0/RP0/CPU0/0
30 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
31 | !
32 | interface GigabitEthernet0/0/0/0
33 | ipv4 address 192.168.0.1 255.255.255.254
34 | !
35 | router static
36 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
37 | {{- if .MgmtIPv4Gateway }}
38 | address-family ipv4 unicast
39 | 0.0.0.0/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv4Gateway }}
40 | !
41 | {{- end}}
42 | {{- if .MgmtIPv6Gateway }}
43 | address-family ipv6 unicast
44 | ::/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv6Gateway }}
45 | !
46 | {{- end}}
47 | !
48 | ssh server v2
49 | {{- if .Env.CLAB_MGMT_VRF }}
50 | ssh server vrf {{ .Env.CLAB_MGMT_VRF }}
51 | {{- end}}
52 | ssh server netconf {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
53 | end
54 |
--------------------------------------------------------------------------------
/lab-examples/templated01/configure.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | # make sure gnmic is installed
6 | gnmic --help >/dev/null
7 | # make sure gomplate is installed
8 | gomplate --help >/dev/null
9 | # make sure curl is installed
10 | curl --help >/dev/null
11 |
12 | # generate the variables file based on the number of spines and leaves in the topology
13 | gomplate -f topology_config.gotmpl -d templated01.clab_vars.yaml >vars.yaml
14 |
15 | # build targets string
16 | targets=$(docker ps -f label=clab-node-kind=nokia_srlinux -f label=containerlab=templated01 --format {{.Names}} | paste -s -d, -)
17 | # base gnmic command
18 | gnmic_cmd="gnmic --log -a ${targets} --skip-verify -u admin -p NokiaSrl1!"
19 |
20 | curl -sLO https://raw.githubusercontent.com/karimra/gnmic/main/examples/set-request-templates/Nokia/SRL/1.interfaces/interfaces_template.gotmpl
21 | curl -sLO https://raw.githubusercontent.com/karimra/gnmic/main/examples/set-request-templates/Nokia/SRL/1.interfaces/subinterfaces_template.gotmpl
22 |
23 | # run gNMI interfaces config
24 | $gnmic_cmd \
25 | set \
26 | --request-file interfaces_template.gotmpl \
27 | --request-vars vars.yaml
28 |
29 | # run gNMI subinterfaces config
30 | $gnmic_cmd \
31 | set \
32 | --request-file subinterfaces_template.gotmpl \
33 | --request-vars vars.yaml
34 |
35 | # delete generated variables file
36 | rm vars.yaml
37 |
38 | # delete downloaded templates
39 | rm interfaces_template.gotmpl
40 | rm subinterfaces_template.gotmpl
41 |
--------------------------------------------------------------------------------
/lab-examples/templated01/templated01.clab.gotmpl:
--------------------------------------------------------------------------------
1 | name: templated01
2 |
3 | topology:
4 | defaults:
5 | kind: nokia_srlinux
6 | kinds:
7 | nokia_srlinux:
8 | image: ghcr.io/nokia/srlinux
9 |
10 | nodes:
11 | # spines
12 | {{- range $spineIndex := seq 1 $.spines.num }}
13 | {{ $.spines.prefix }}{{ $spineIndex }}:
14 | type: {{ $.spines.type }}
15 | {{- end }}
16 | # leaves
17 | {{- range $leafIndex := seq 1 $.leaves.num }}
18 | {{ $.leaves.prefix }}{{ $leafIndex }}:
19 | type: {{ $.leaves.type }}
20 | {{- end }}
21 |
22 | links:
23 | {{- range $spineIndex := seq 1 $.spines.num }}
24 | # {{ $.spines.prefix }}{{ $spineIndex }}
25 | {{- range $leafIndex := seq 1 $.leaves.num }}
26 | - endpoints: ["{{ $.spines.prefix }}{{ $spineIndex }}:e1-{{ $leafIndex }}", "{{ $.leaves.prefix }}{{ $leafIndex }}:e1-{{ $spineIndex }}"]
27 | {{- end }}
28 | {{- end }}
29 |
--------------------------------------------------------------------------------
/lab-examples/templated01/templated01.clab_vars.yaml:
--------------------------------------------------------------------------------
1 | spines:
2 | # SRL spine type
3 | type: ixrd3
4 | # number of spines
5 | num: 2
6 | # prefix of spines name: ${prefix}${index}
7 | prefix: spine
8 | leaves:
9 | # SRL leaf type
10 | type: ixrd3
11 | # number of leaves
12 | num: 4
13 | # prefix of leaf name: ${prefix}${index}
14 | prefix: leaf
15 |
--------------------------------------------------------------------------------
/lab-examples/templated02/configure.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | # make sure gnmic is installed
6 | gnmic --help >/dev/null
7 | # make sure gomplate is installed
8 | gomplate --help >/dev/null
9 | # make sure curl is installed
10 | curl --help >/dev/null
11 |
12 | # generate the variables file based on the number of spines and leaves in the topology
13 | gomplate -f topology_config.gotmpl -d templated02.clab_vars.yaml >vars.yaml
14 |
15 | # build targets string
16 | targets=$(docker ps -f label=clab-node-kind=nokia_srlinux -f label=containerlab=templated02 --format {{.Names}} | paste -s -d, -)
17 | # base gnmic command
18 | gnmic_cmd="gnmic --log -a ${targets} --skip-verify -u admin -p NokiaSrl1!"
19 |
20 | curl -sLO https://raw.githubusercontent.com/karimra/gnmic/main/examples/set-request-templates/Nokia/SRL/1.interfaces/interfaces_template.gotmpl
21 | curl -sLO https://raw.githubusercontent.com/karimra/gnmic/main/examples/set-request-templates/Nokia/SRL/1.interfaces/subinterfaces_template.gotmpl
22 |
23 | # run gNMI interfaces config
24 | $gnmic_cmd \
25 | set \
26 | --request-file interfaces_template.gotmpl \
27 | --request-vars vars.yaml
28 |
29 | # run gNMI subinterfaces config
30 | $gnmic_cmd \
31 | set \
32 | --request-file subinterfaces_template.gotmpl \
33 | --request-vars vars.yaml
34 |
35 | # delete generated variables file
36 | rm vars.yaml
37 |
38 | # delete downloaded templates
39 | rm interfaces_template.gotmpl
40 | rm subinterfaces_template.gotmpl
41 |
--------------------------------------------------------------------------------
/lab-examples/templated02/templated02.clab_vars.yaml:
--------------------------------------------------------------------------------
1 | super_spines:
2 | # SRL super spine type
3 | type: ixrd3l
4 | # number of super spines
5 | num: 2
6 | # prefix of super spines name: ${prefix}${index}
7 | prefix: super-spine
8 |
9 | pods:
10 | # number of pods
11 | num: 4
12 | spines:
13 | # SRL spine type
14 | type: ixrd3l
15 | # number of spines per pod
16 | num: 2
17 | # prefix of spines name: ${prefix}${pod_index}-${index}
18 | prefix: spine
19 | leaves:
20 | # SRL leaf type
21 | type: ixrd2l
22 | # number of leaves per pod
23 | num: 4
24 | # prefix of leaf name: ${prefix}${pod_index}-${index}
25 | prefix: leaf
26 |
--------------------------------------------------------------------------------
/lab-examples/vr01/srl.cfg:
--------------------------------------------------------------------------------
1 | enter candidate
2 | set / interface ethernet-1/1 admin-state enable
3 | set / interface ethernet-1/1 subinterface 0
4 | set / interface ethernet-1/1 subinterface 0 ipv4
5 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.1.1/24
7 | set / network-instance default
8 | set / network-instance default interface ethernet-1/1.0
9 | commit now
--------------------------------------------------------------------------------
/lab-examples/vr01/vr01.clab.yml:
--------------------------------------------------------------------------------
1 | name: vr01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | sros:
9 | kind: nokia_sros
10 | image: nokia_sros:20.10.R1
11 | type: sr-1
12 | license: /opt/nokia/sros/license-sros20.txt # Not included in the lab, ask your Nokia representative
13 |
14 | links:
15 | - endpoints: ["srl:e1-1", "sros:eth1"]
16 |
--------------------------------------------------------------------------------
/lab-examples/vr02/srl.cfg:
--------------------------------------------------------------------------------
1 | enter candidate
2 | set / interface ethernet-1/1 admin-state enable
3 | set / interface ethernet-1/1 subinterface 0
4 | set / interface ethernet-1/1 subinterface 0 ipv4
5 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.1.1/24
7 | set / network-instance default
8 | set / network-instance default interface ethernet-1/1.0
9 | commit now
--------------------------------------------------------------------------------
/lab-examples/vr02/vmx.cfg:
--------------------------------------------------------------------------------
1 | configure
2 | set interfaces ge-0/0/0 unit 0 family inet address 192.168.1.2/24
3 | commit
4 |
--------------------------------------------------------------------------------
/lab-examples/vr02/vr02.clab.yml:
--------------------------------------------------------------------------------
1 | name: vr02
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | vmx:
9 | kind: juniper_vmx
10 | image: vrnetlab/vr-vmx:20.2R1.10
11 |
12 | links:
13 | - endpoints: ["srl:e1-1", "vmx:eth1"]
14 |
--------------------------------------------------------------------------------
/lab-examples/vr03/srl.cfg:
--------------------------------------------------------------------------------
1 | enter candidate
2 | set / interface ethernet-1/1 admin-state enable
3 | set / interface ethernet-1/1 subinterface 0
4 | set / interface ethernet-1/1 subinterface 0 ipv4
5 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.1.1/24
7 | set / network-instance default
8 | set / network-instance default interface ethernet-1/1.0
9 | commit now
--------------------------------------------------------------------------------
/lab-examples/vr03/vr03.clab.yml:
--------------------------------------------------------------------------------
1 | name: vr03
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | xrv:
9 | kind: cisco_xrv
10 | image: vrnetlab/vr-xrv:6.1.2
11 |
12 | links:
13 | - endpoints: ["srl:e1-1", "xrv:eth1"]
14 |
--------------------------------------------------------------------------------
/lab-examples/vr03/xrv.cfg:
--------------------------------------------------------------------------------
1 | configure
2 | interface Gi0/0/0/0 ipv4 address 192.168.1.2 255.255.255.0
3 | commit
--------------------------------------------------------------------------------
/lab-examples/vr04/srl.cfg:
--------------------------------------------------------------------------------
1 | enter candidate
2 | set / interface ethernet-1/1 admin-state enable
3 | set / interface ethernet-1/1 subinterface 0
4 | set / interface ethernet-1/1 subinterface 0 ipv4
5 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.1.1/24
7 | set / network-instance default
8 | set / network-instance default interface ethernet-1/1.0
9 | commit now
--------------------------------------------------------------------------------
/lab-examples/vr04/vr04.clab.yml:
--------------------------------------------------------------------------------
1 | name: vr04
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | xrv9k:
9 | kind: cisco_xrv9k
10 | image: vr-xrv9k:7.2.1 # do not forget to re-tag the image if needed
11 |
12 | links:
13 | - endpoints: ["srl:e1-1", "xrv9k:eth1"]
14 |
--------------------------------------------------------------------------------
/lab-examples/vr04/xrv9k.cfg:
--------------------------------------------------------------------------------
1 | configure
2 | interface GigabitEthernet 0/0/0/0
3 | ipv4 address 192.168.1.2/24
4 | no shutdown
5 | commit
--------------------------------------------------------------------------------
/lab-examples/vr05/sros4.clab.yml:
--------------------------------------------------------------------------------
1 | name: conf1
2 |
3 | topology:
4 | defaults:
5 | kind: nokia_sros
6 | image: vrnetlab/vr-sros:21.2.R1
7 | license: ~/license/sros.txt
8 | config:
9 | vars:
10 | isis_iid: 1
11 | nodes:
12 | sr1:
13 | config:
14 | vars:
15 | clab_system_ip: 10.0.50.31/32
16 | sid_idx: 1
17 | sr2:
18 | config:
19 | vars:
20 | clab_system_ip: 10.0.50.32/32
21 | sid_idx: 2
22 | sr3:
23 | config:
24 | vars:
25 | clab_system_ip: 10.0.50.33/32
26 | sid_idx: 3
27 | sr4:
28 | config:
29 | vars:
30 | clab_system_ip: 10.0.50.34/32
31 | sid_idx: 4
32 | links:
33 | - endpoints: [sr1:eth1, sr2:eth2]
34 | vars:
35 | port: [1/1/c1/1, 1/1/c2/1]
36 | clab_link_ip: 1.1.1.2/30
37 | vlan: [99, 99]
38 | isis_iid: 1
39 | - endpoints: [sr2:eth1, sr3:eth2]
40 | vars:
41 | port: [1/1/c1/1, 1/1/c2/1]
42 | vlan: 98
43 | isis_iid: 1
44 | - endpoints: [sr3:eth1, sr4:eth2]
45 | vars:
46 | port: [1/1/c1/1, 1/1/c2/1]
47 | isis_iid: 1
48 | - endpoints: [sr4:eth1, sr1:eth2]
49 | vars:
50 | port: [1/1/c1/1, 1/1/c2/1]
51 | isis_iid: 1
52 |
--------------------------------------------------------------------------------
/lab-examples/vr05/vr01.clab.yml:
--------------------------------------------------------------------------------
1 | name: vr01
2 |
3 | topology:
4 | nodes:
5 | srl:
6 | kind: nokia_srlinux
7 | image: ghcr.io/nokia/srlinux
8 | config:
9 | vars:
10 | clab_system_ip: 10.0.50.50/32
11 | isis_iid: 1
12 | sid_idx: 11
13 | sros:
14 | kind: nokia_sros
15 | image: vrnetlab/vr-sros:21.2.R1
16 | type: sr-1
17 | license: ~/license/sros.txt
18 | config:
19 | vars:
20 | clab_system_ip: 10.0.50.51/32
21 | sid_idx: 10
22 | isis_iid: 1
23 |
24 | links:
25 | - endpoints: ["srl:e1-1", "sros:eth1"]
26 | vars:
27 | port: [ethernet-1/1, 1/1/c1/1]
28 | vlan: 10
29 | isis_iid: 1
30 |
--------------------------------------------------------------------------------
/lab-examples/vsrx01/srx1.cfg:
--------------------------------------------------------------------------------
1 | interfaces ge-0/0/0 {
2 | unit 0 {
3 | family {
4 | inet {
5 | address 192.168.1.1/30;
6 | }
7 | }
8 | }
9 | }
10 | interfaces ge-0/0/1 {
11 | unit 0 {
12 | family {
13 | inet {
14 | address 192.168.2.1/30;
15 | }
16 | }
17 | }
18 | }
19 | security {
20 | zones {
21 | security-zone trust {
22 | interfaces ge-0/0/0 {
23 | host-inbound-traffic {
24 | system-services all;
25 | }
26 | }
27 | interfaces ge-0/0/1 {
28 | host-inbound-traffic {
29 | system-services all;
30 | }
31 | }
32 | }
33 | }
34 | forwarding-options {
35 | family {
36 | mpls {
37 | mode {
38 | packet-based;
39 | }
40 | }
41 | }
42 | }
43 | }
44 | system {
45 | services {
46 | web-management {
47 | https {
48 | system-generated-certificate;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lab-examples/vsrx01/vsrx01.yml:
--------------------------------------------------------------------------------
1 | name: vsrx1
2 | topology:
3 | nodes:
4 | srx1:
5 | kind: juniper_vsrx
6 | image: vrnetlab/vr-vsrx:23.2R1.13
7 | startup-config: srx1.cfg
8 | client1:
9 | kind: "linux"
10 | image: wbitt/network-multitool:alpine-extra
11 | exec:
12 | - ip addr add 192.168.1.2/30 dev eth1
13 | - ip route add 192.168.2.0/30 via 192.168.1.1
14 | client2:
15 | kind: "linux"
16 | image: wbitt/network-multitool:alpine-extra
17 | exec:
18 | - ip addr add 192.168.2.2/30 dev eth1
19 | - ip route add 192.168.1.0/30 via 192.168.2.1
20 | links:
21 | - endpoints: ["srx1:eth1", "client1:eth1"]
22 | - endpoints: ["srx1:eth2", "client2:eth1"]
23 |
--------------------------------------------------------------------------------
/lab-examples/vxlan01/vxlan-sros.clab.yml:
--------------------------------------------------------------------------------
1 | name: vxlan
2 |
3 | topology:
4 | nodes:
5 | sros:
6 | kind: nokia_sros
7 | image: vr-sros:21.2.R1
8 | license: license-sros20.txt
9 | # vmx node is defined in a `vxlan-vmx.clab.yml` topo file
10 | # that is launched on another VM
11 |
12 | links:
13 | # we expose two sros container interfaces
14 | # to host namespace by using host interfaces style
15 | # docs: https://containerlab.dev/manual/network/#host-links
16 | - endpoints: ["sros:eth1", "host:sr-eth1"]
17 | - endpoints: ["sros:eth2", "host:sr-eth2"]
18 |
--------------------------------------------------------------------------------
/lab-examples/vxlan01/vxlan-vmx.clab.yml:
--------------------------------------------------------------------------------
1 | name: vxlan
2 |
3 | topology:
4 | nodes:
5 | vmx:
6 | kind: juniper_vmx
7 | image: vrnetlab/vr-vmx:20.4R1.12
8 | # sros node is defined in a `vxlan-sros.clab.yml` topo file
9 | # that is launched on another VM
10 |
11 | links:
12 | # we expose two sros container interfaces
13 | # to host namespace by using host interfaces style
14 | # docs: https://containerlab.dev/manual/network/#host-links
15 | - endpoints: ["vmx:eth1", "host:vmx-eth1"]
16 | - endpoints: ["vmx:eth2", "host:vmx-eth2"]
17 |
--------------------------------------------------------------------------------
/labels/labels.go:
--------------------------------------------------------------------------------
1 | package labels
2 |
3 | const (
4 | // label names constants.
5 | Containerlab = "containerlab"
6 | NodeName = "clab-node-name"
7 | LongName = "clab-node-longname"
8 | NodeKind = "clab-node-kind"
9 | NodeType = "clab-node-type"
10 | NodeGroup = "clab-node-group"
11 | NodeLabDir = "clab-node-lab-dir"
12 | TopoFile = "clab-topo-file"
13 | NodeMgmtNetBr = "clab-mgmt-net-bridge"
14 | Owner = "clab-owner"
15 | )
16 |
--------------------------------------------------------------------------------
/links/endpoint_dummy.go:
--------------------------------------------------------------------------------
1 | package links
2 |
3 | import "context"
4 |
5 | type EndpointDummy struct {
6 | EndpointGeneric
7 | }
8 |
9 | func NewEndpointDummy(eg *EndpointGeneric) *EndpointDummy {
10 | return &EndpointDummy{
11 | EndpointGeneric: *eg,
12 | }
13 | }
14 |
15 | // Verify verifies the veth based deployment pre-conditions.
16 | func (e *EndpointDummy) Verify(_ context.Context, _ *VerifyLinkParams) error {
17 | return CheckEndpointUniqueness(e)
18 | }
19 |
20 | func (e *EndpointDummy) Deploy(ctx context.Context) error {
21 | return e.GetLink().Deploy(ctx, e)
22 | }
23 |
24 | func (*EndpointDummy) IsNodeless() bool {
25 | return false
26 | }
27 |
--------------------------------------------------------------------------------
/links/endpoint_host.go:
--------------------------------------------------------------------------------
1 | package links
2 |
3 | import (
4 | "context"
5 | "errors"
6 | )
7 |
8 | type EndpointHost struct {
9 | EndpointGeneric
10 | }
11 |
12 | func NewEndpointHost(eg *EndpointGeneric) *EndpointHost {
13 | return &EndpointHost{
14 | EndpointGeneric: *eg,
15 | }
16 | }
17 |
18 | func (e *EndpointHost) Deploy(ctx context.Context) error {
19 | return e.GetLink().Deploy(ctx, e)
20 | }
21 |
22 | func (e *EndpointHost) Verify(ctx context.Context, _ *VerifyLinkParams) error {
23 | var errs []error
24 | err := CheckEndpointUniqueness(e)
25 | if err != nil {
26 | errs = append(errs, err)
27 | }
28 | err = CheckEndpointDoesNotExistYet(ctx, e)
29 | if err != nil {
30 | errs = append(errs, err)
31 | }
32 | if len(errs) > 0 {
33 | return errors.Join(errs...)
34 | }
35 | return nil
36 | }
37 |
38 | func (e *EndpointHost) IsNodeless() bool {
39 | return true
40 | }
41 |
--------------------------------------------------------------------------------
/links/endpoint_macvlan.go:
--------------------------------------------------------------------------------
1 | package links
2 |
3 | import "context"
4 |
5 | type EndpointMacVlan struct {
6 | EndpointGeneric
7 | }
8 |
9 | func NewEndpointMacVlan(eg *EndpointGeneric) *EndpointMacVlan {
10 | return &EndpointMacVlan{
11 | EndpointGeneric: *eg,
12 | }
13 | }
14 |
15 | func (e *EndpointMacVlan) Deploy(ctx context.Context) error {
16 | return e.GetLink().Deploy(ctx, e)
17 | }
18 |
19 | // Verify runs verification to check if the endpoint can be deployed.
20 | func (e *EndpointMacVlan) Verify(ctx context.Context, _ *VerifyLinkParams) error {
21 | return CheckEndpointExists(ctx, e)
22 | }
23 |
24 | func (e *EndpointMacVlan) IsNodeless() bool {
25 | return false
26 | }
27 |
--------------------------------------------------------------------------------
/links/endpoint_veth.go:
--------------------------------------------------------------------------------
1 | package links
2 |
3 | import "context"
4 |
5 | type EndpointVeth struct {
6 | EndpointGeneric
7 | }
8 |
9 | func NewEndpointVeth(eg *EndpointGeneric) *EndpointVeth {
10 | return &EndpointVeth{
11 | EndpointGeneric: *eg,
12 | }
13 | }
14 |
15 | // Verify verifies the veth based deployment pre-conditions.
16 | func (e *EndpointVeth) Verify(_ context.Context, _ *VerifyLinkParams) error {
17 | return CheckEndpointUniqueness(e)
18 | }
19 |
20 | func (e *EndpointVeth) Deploy(ctx context.Context) error {
21 | return e.GetLink().Deploy(ctx, e)
22 | }
23 |
24 | func (e *EndpointVeth) IsNodeless() bool {
25 | return false
26 | }
27 |
--------------------------------------------------------------------------------
/links/endpoint_vxlan.go:
--------------------------------------------------------------------------------
1 | package links
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "net"
7 | )
8 |
9 | type EndpointVxlan struct {
10 | EndpointGeneric
11 | udpPort int
12 | remote net.IP
13 | parentIface string
14 | vni int
15 | randName string
16 | }
17 |
18 | func NewEndpointVxlan(node Node, link Link) *EndpointVxlan {
19 | return &EndpointVxlan{
20 | randName: genRandomIfName(),
21 | EndpointGeneric: EndpointGeneric{
22 | Link: link,
23 | Node: node,
24 | },
25 | }
26 | }
27 |
28 | func (e *EndpointVxlan) String() string {
29 | return fmt.Sprintf("vxlan remote: %q, udp-port: %d, vni: %d", e.remote, e.udpPort, e.vni)
30 | }
31 |
32 | // Verify verifies that the endpoint is valid and can be deployed.
33 | func (e *EndpointVxlan) Verify(_ context.Context, _ *VerifyLinkParams) error {
34 | return CheckEndpointUniqueness(e)
35 | }
36 |
37 | func (e *EndpointVxlan) Deploy(ctx context.Context) error {
38 | return e.GetLink().Deploy(ctx, e)
39 | }
40 |
41 | func (e *EndpointVxlan) IsNodeless() bool {
42 | return false
43 | }
44 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Nokia
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 |
5 | package main
6 |
7 | import "github.com/srl-labs/containerlab/cmd"
8 |
9 | func main() {
10 | cmd.Execute()
11 | }
12 |
--------------------------------------------------------------------------------
/mocks/exec.go:
--------------------------------------------------------------------------------
1 | // Code generated by MockGen. DO NOT EDIT.
2 | // Source: clab/exec/exec.go
3 | //
4 | // Generated by this command:
5 | //
6 | // mockgen -package=mocks -source=clab/exec/exec.go -destination=./mocks/exec.go
7 | //
8 |
9 | // Package mocks is a generated GoMock package.
10 | package mocks
11 |
--------------------------------------------------------------------------------
/netconf/netconf.go:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Nokia
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 |
5 | // Package netconf contains netconf-based functions used in containerlab.
6 | package netconf
7 |
8 | import (
9 | "fmt"
10 |
11 | "github.com/scrapli/scrapligo/driver/netconf"
12 | "github.com/scrapli/scrapligo/driver/options"
13 | "github.com/scrapli/scrapligo/transport"
14 | "github.com/scrapli/scrapligo/util"
15 | )
16 |
17 | // SaveConfig saves the running config to the startup by means
18 | // of invoking a netconf rpc from running to startup datastore
19 | // this method is used on the network elements that can't perform configuration save via other means.
20 | func SaveConfig(addr, username, password, _ string) error {
21 | opts := []util.Option{
22 | options.WithAuthNoStrictKey(),
23 | options.WithAuthUsername(username),
24 | options.WithAuthPassword(password),
25 | options.WithTransportType(transport.StandardTransport),
26 | options.WithPort(830),
27 | }
28 |
29 | d, err := netconf.NewDriver(
30 | addr,
31 | opts...,
32 | )
33 | if err != nil {
34 | return fmt.Errorf("could not create netconf driver for %s: %+v", addr, err)
35 | }
36 |
37 | err = d.Open()
38 | if err != nil {
39 | return fmt.Errorf("failed to open netconf driver for %s: %+v", addr, err)
40 | }
41 | defer d.Close()
42 |
43 | _, err = d.CopyConfig("running", "startup")
44 | if err != nil {
45 | return fmt.Errorf("%s: Could not send save config via Netconf: %+v", addr, err)
46 | }
47 |
48 | return nil
49 | }
50 |
--------------------------------------------------------------------------------
/nodes/6wind_vsr/6wind_vsr_default_config.go.tpl:
--------------------------------------------------------------------------------
1 | / vrf main ssh-server
2 | {{- if .SSHPubKeys }}
3 | / system auth
4 | / system auth user admin
5 | / system auth user admin role admin
6 | {{- range $idx, $key := .SSHPubKeys }}
7 | / system auth user admin authorized-key "{{ $key }}"
8 | {{- end }}
9 | {{- end }}
10 | {{- if .License }}
11 | / system license online serial "{{ .License }}"
12 | {{- end }}
13 | {{- if .Banner }}
14 | cmd banner post-login message "{{ .Banner }}"
15 | {{- end }}
16 |
--------------------------------------------------------------------------------
/nodes/c8000/c8000.cfg:
--------------------------------------------------------------------------------
1 | !
2 | hostname {{ .ShortName }}
3 | !
4 | username cisco123
5 | group root-lr
6 | group cisco-support
7 | secret cisco123
8 |
9 | grpc
10 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
11 | port 9339
12 | no-tls
13 | address-family dual
14 | !
15 | {{- if .Env.CLAB_MGMT_VRF }}
16 | vrf {{ .Env.CLAB_MGMT_VRF }}
17 | address-family ipv4 unicast
18 | !
19 | address-family ipv6 unicast
20 | !
21 | {{- end}}
22 | !
23 | line default
24 | transport input ssh
25 | !
26 | netconf-yang agent
27 | ssh
28 | !
29 | interface MgmtEth0/RP0/CPU0/0
30 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
31 | !
32 | router static
33 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
34 | {{- if .MgmtIPv4Gateway }}
35 | address-family ipv4 unicast
36 | 0.0.0.0/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv4Gateway }}
37 | !
38 | {{- end}}
39 | {{- if .MgmtIPv6Gateway }}
40 | address-family ipv6 unicast
41 | ::/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv6Gateway }}
42 | !
43 | {{- end}}
44 | !
45 | ssh server v2
46 | {{- if .Env.CLAB_MGMT_VRF }}
47 | ssh server vrf {{ .Env.CLAB_MGMT_VRF }}
48 | {{- end}}
49 | ssh server netconf {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
50 | end
51 |
--------------------------------------------------------------------------------
/nodes/ceos/ceos.cfg:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Nokia
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 |
5 | hostname {{ .ShortName }}
6 | username admin privilege 15 secret admin
7 | !
8 | service routing protocols model multi-agent
9 | !
10 | {{- if .Env.CLAB_MGMT_VRF }}
11 | vrf instance {{ .Env.CLAB_MGMT_VRF }}
12 | !
13 | {{end}}
14 | {{ if .MgmtIPv4Gateway }}ip route {{ if .Env.CLAB_MGMT_VRF }}vrf {{ .Env.CLAB_MGMT_VRF }} {{end}}0.0.0.0/0 {{ .MgmtIPv4Gateway }}{{end}}
15 | {{ if .MgmtIPv6Gateway }}ipv6 route {{ if .Env.CLAB_MGMT_VRF }}vrf {{ .Env.CLAB_MGMT_VRF }} {{end}}::0/0 {{ .MgmtIPv6Gateway }}{{end}}
16 | !
17 | interface {{ .MgmtIntf }}
18 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
19 | {{ if .MgmtIPv4Address }}ip address {{ .MgmtIPv4Address }}/{{.MgmtIPv4PrefixLength}}{{end}}
20 | {{ if .MgmtIPv6Address }}ipv6 address {{ .MgmtIPv6Address }}/{{.MgmtIPv6PrefixLength}}{{end}}
21 | !
22 | management api gnmi
23 | transport grpc default
24 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
25 | !
26 | management api netconf
27 | transport ssh default
28 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
29 | !
30 | management api http-commands
31 | no shutdown
32 | {{- if .Env.CLAB_MGMT_VRF }}
33 | !
34 | vrf {{ .Env.CLAB_MGMT_VRF }}
35 | no shutdown
36 | {{end}}
37 | !
38 | end
39 |
--------------------------------------------------------------------------------
/nodes/crpd/crpd.cfg:
--------------------------------------------------------------------------------
1 | system {
2 | root-authentication {
3 | encrypted-password "$6$lB5c6$Zeud8c6IhCTE6hnZxXBl3ZMZTC2hOx9pxxYUWTHKW1oC32SATWLMH2EXarxWS5k685qMggUfFur1lq.o4p4cg1"; ## SECRET-DATA
4 | }
5 | services {
6 | ssh {
7 | root-login allow;
8 | }
9 | netconf {
10 | ssh;
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/nodes/fdio_vpp/vpp_startup_config.go.tpl:
--------------------------------------------------------------------------------
1 | ## VPP Startup configuration
2 | ## Generated by clab
3 |
4 | unix {
5 | interactive
6 | log /var/log/vpp/vpp.log
7 | full-coredump
8 | cli-listen /run/vpp/cli.sock
9 | cli-prompt {{ .ShortName }}#
10 | cli-no-pager
11 | poll-sleep-usec 100
12 | exec /etc/vpp/bootstrap.vpp
13 | }
14 |
15 | api-trace {
16 | on
17 | }
18 |
19 | memory {
20 | main-heap-size 512M
21 | main-heap-page-size 4k
22 | }
23 |
24 | buffers {
25 | buffers-per-numa 16000
26 | default data-size 2048
27 | page-size 4k
28 | }
29 |
30 | statseg {
31 | size 64M
32 | page-size 4k
33 | per-node-counters on
34 | }
35 |
36 | plugins {
37 | plugin default { enable }
38 | plugin dpdk_plugin.so { disable }
39 | plugin linux_cp_plugin.so { enable }
40 | plugin linux_nl_plugin.so { enable }
41 | plugin sflow_plugin.so { enable }
42 | }
43 |
44 | linux-cp {
45 | default netns dataplane
46 | lcp-sync
47 | lcp-auto-subint
48 | del-static-on-link-down
49 | del-dynamic-on-link-down
50 | }
51 |
--------------------------------------------------------------------------------
/nodes/iol/iol.cfg.tmpl:
--------------------------------------------------------------------------------
1 | hostname {{ .Hostname }}
2 | !
3 | no aaa new-model
4 | !
5 | ip domain name lab
6 | !
7 | ip cef
8 | !
9 | ipv6 unicast-routing
10 | !
11 | no ip domain lookup
12 | !
13 | username admin privilege 15 secret admin
14 | !
15 | vrf definition clab-mgmt
16 | description clab-mgmt
17 | address-family ipv4
18 | !
19 | address-family ipv6
20 | !
21 | !
22 | interface Ethernet0/0
23 | {{ if .IsL2Node }}
24 | no switchport
25 | {{ end }}
26 | vrf forwarding clab-mgmt
27 | description clab-mgmt
28 | ip address {{ .MgmtIPv4Addr }} {{ .MgmtIPv4SubnetMask }}
29 | ipv6 address {{ .MgmtIPv6Addr }}/{{ .MgmtIPv6PrefixLen }}
30 | no shutdown
31 | !{{ range $index, $item := .DataIFaces }}
32 | interface Ethernet{{ .Slot }}/{{ .Port }}
33 | no shutdown
34 | !{{ end }}
35 | ip forward-protocol nd
36 | !
37 | ip route vrf clab-mgmt 0.0.0.0 0.0.0.0 Ethernet0/0 {{ .MgmtIPv4GW }}
38 | ipv6 route vrf clab-mgmt ::/0 Ethernet0/0 {{ .MgmtIPv6GW }}
39 | !
40 | ip ssh version 2
41 | crypto key generate rsa modulus 2048
42 | !
43 | line vty 0 4
44 | login local
45 | transport input ssh
46 | !
47 | {{ .PartialCfg }}
48 | end
49 |
--------------------------------------------------------------------------------
/nodes/srl/macaddr.go:
--------------------------------------------------------------------------------
1 | package srl
2 |
3 | import (
4 | "crypto/rand"
5 | "fmt"
6 | "math/big"
7 |
8 | "github.com/srl-labs/containerlab/types"
9 | )
10 |
11 | type mac struct {
12 | MAC string
13 | }
14 |
15 | // genMac returns a struct with a generated MAC address string to use in SR Linux
16 | // topology file.
17 | func genMac(cfg *types.NodeConfig) mac {
18 | // Generated MAC address conforms to the following addressing scheme
19 | // first byte - `1a` - fixed for easy identification of SRL Mac addresses
20 | // second byte - random, to distinguish projects
21 | // third byte - index of the topology node
22 |
23 | projID, _ := rand.Int(rand.Reader, big.NewInt(256))
24 | macPrefix := fmt.Sprintf("1a:%02x", projID)
25 |
26 | // labs up to 256 nodes are supported, behaviour is undefined when more nodes are defined
27 | m := fmt.Sprintf("%s:%02x:00:00:00", macPrefix, cfg.Index%256)
28 |
29 | // set system Mac in NodeConfig
30 | cfg.MacAddress = m
31 |
32 | return mac{
33 | MAC: m,
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/nodes/srl/prompt_test.go:
--------------------------------------------------------------------------------
1 | package srl
2 |
3 | import (
4 | "testing"
5 | )
6 |
7 | func Test_getPrompt(t *testing.T) {
8 | tests := []struct {
9 | name string
10 | s string
11 | want string
12 | wantErr bool
13 | }{
14 | {
15 | name: "Test with valid input",
16 | s: `value = "test-prompt"`,
17 | want: "test-prompt",
18 | wantErr: false,
19 | },
20 | {
21 | name: "Test with invalid input",
22 | s: `invalid input`,
23 | want: "",
24 | wantErr: true,
25 | },
26 | }
27 | for _, tt := range tests {
28 | t.Run(tt.name, func(t *testing.T) {
29 | got, err := getPrompt(tt.s)
30 | if (err != nil) != tt.wantErr {
31 | t.Errorf("getPrompt() error = %v, wantErr %v", err, tt.wantErr)
32 | return
33 | }
34 | if got != tt.want {
35 | t.Errorf("getPrompt() = %v, want %v", got, tt.want)
36 | }
37 | })
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/nodes/srl/test_data/rsa_key:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs4Qv1yrBk6ygt+o7J4sUcYv+WfDjdAyABDoinOt3PgSmCcVqqAP2qS8UtTnMNuy93Orp6+/R/7/R3O5xdY6I4YViK3WVlKTAUVm7vdeTKp9uq1tNeWgo7+J3baSbQ3INp85ScTfFvRzRCFkr/W97Wh6pTa7ysgkcPvc2/tXG2z36Mx7/TFBk3Q1LY3ByKLtGrC5JnVpMTrqrsCwcLEVHHEZ4z5R4FZED/lpz+wTNFnR/l9HA6yDkKYensHynx+guqYpYD6y4yEGY/LcUnwBg0zIlUhmOsvdmxWBz12Lp7EBiNjSwhnPfe+o3efLGGnjWUAa4TgO8Sa8PQP0pK/ZNd
--------------------------------------------------------------------------------
/nodes/srl/topology/7215IXSA1.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 80
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 196
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 196
13 | "mda_type": 8
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD1.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 64
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 175
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 175
13 | "mda_type": 196
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD2.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 65
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 176
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 176
13 | "mda_type": 195 # imm48-25g-sfp28+8-100g-qsfp28
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD2L.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 72
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 187
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 187
13 | "mda_type": 208
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD3.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 66
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 177
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 177
13 | "mda_type": 194
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD3L.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 73
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 188
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 188
13 | "mda_type": 202
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD4.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 78
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 189
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 189
13 | "mda_type": 210
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRD5.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 71
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 190
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 190
13 | "mda_type": 201
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH2.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 61
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 179 # imm128-100g-qsfp28
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 179
13 | "mda_type": 197
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH3.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 62
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 178 #IMM2_10g_sfpp_32_400g_qsfpdd
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 178
13 | "mda_type": 198
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH4-32D.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 84
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 18
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 18
13 | "mda_type": 25
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH4.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 79
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 191
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 191
13 | "mda_type": 211
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH5-32D.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2025 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 47
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 180
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 180
13 | "mda_type": 106
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH5-64D.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2025 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 85
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 171
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 171
13 | "mda_type": 18
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7220IXRH5-64O.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2025 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 98
7 | "base_mac": "{{.MAC}}"
8 | "cpm_card_type": 157
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 157
13 | "mda_type": 154
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXR10.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 43
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 69 # cpm2-ixr
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 127
13 | "mda_type": 36 # 32xQSFP28+4xQSFP-DD (imm32-100g-qsfp28+4-400g-qsfpdd)
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXR10e.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 69
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 184
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 182
13 | "mda_type": 199
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXR18e.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 70
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 184
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 33
13 | "mda_type": 13
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXR6.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 42
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 69 # cpm2-ixr
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 127
13 | "mda_type": 36 # 32xQSFP28+4xQSFP-DD (imm32-100g-qsfp28+4-400g-qsfpdd)
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXR6e.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 68
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 184
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 182
13 | "mda_type": 199
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXRX1b.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 82
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 32
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 32
13 | "mda_type": 19
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7250IXRX3b.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 81
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 27
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 27
13 | "mda_type": 12
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7730SXR-1d-32d.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 54
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 11
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 11
13 | "mda_type": 201
14 |
--------------------------------------------------------------------------------
/nodes/srl/topology/7730SXR-1x-44s.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | chassis_configuration:
6 | "chassis_type": 51
7 | "base_mac": "{{ .MAC }}"
8 | "cpm_card_type": 177
9 |
10 | slot_configuration:
11 | 1:
12 | "card_type": 2
13 | "mda_type": 40
14 |
--------------------------------------------------------------------------------
/nodes/state/state.go:
--------------------------------------------------------------------------------
1 | package state
2 |
3 | type NodeState uint
4 |
5 | const (
6 | Unknown NodeState = iota
7 | // Deployed means the underlying container has been started and deploy function succeeded.
8 | Deployed
9 | )
10 |
--------------------------------------------------------------------------------
/nodes/vr_openwrt/vr_openwrt.go:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Nokia
2 | // Licensed under the BSD 3-Clause License.
3 | // SPDX-License-Identifier: BSD-3-Clause
4 | package vr_openwrt
5 |
6 | import (
7 | "context"
8 | "fmt"
9 | "path/filepath"
10 |
11 | "github.com/srl-labs/containerlab/nodes"
12 | "github.com/srl-labs/containerlab/types"
13 | "github.com/srl-labs/containerlab/utils"
14 | )
15 |
16 | var kindNames = []string{"openwrt"}
17 |
18 | const (
19 | generateable = true
20 | generateIfFormat = "eth%d"
21 | )
22 |
23 | // Register registers the node in the NodeRegistry.
24 | func Register(r *nodes.NodeRegistry) {
25 | generateNodeAttributes := nodes.NewGenerateNodeAttributes(generateable, generateIfFormat)
26 | nrea := nodes.NewNodeRegistryEntryAttributes(nil, generateNodeAttributes, nil)
27 |
28 | r.Register(kindNames, func() nodes.Node {
29 | return new(vrOpenWrt)
30 | }, nrea)
31 | }
32 |
33 | type vrOpenWrt struct {
34 | nodes.DefaultNode
35 | }
36 |
37 | func (n *vrOpenWrt) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
38 | // Init DefaultNode
39 | n.DefaultNode = *nodes.NewDefaultNode(n)
40 |
41 | n.Cfg = cfg
42 | for _, o := range opts {
43 | o(n)
44 | }
45 |
46 | // Add a simple bind-mount for the 'overlay' directory
47 | n.Cfg.Binds = append(n.Cfg.Binds,
48 | fmt.Sprint(filepath.Join(n.Cfg.LabDir, "overlay"), ":/overlay"),
49 | )
50 |
51 | return nil
52 | }
53 |
54 | func (n *vrOpenWrt) PreDeploy(_ context.Context, params *nodes.PreDeployParams) error {
55 | // Ensure the overlay directory exists
56 | utils.CreateDirectory(filepath.Join(n.Cfg.LabDir, "overlay"), 0777)
57 | return nil
58 | }
59 |
--------------------------------------------------------------------------------
/nodes/vr_sros/ssh_keys.go.tpl:
--------------------------------------------------------------------------------
1 | {{/* this is a template for sros public key config for ssh admin user access */}}
2 |
3 | {{/* to enable long list of keys from agent where the configured key may not be in the default first three keys */}}
4 | /configure system security user-params attempts count 64
5 |
6 | {{ range $index, $key := .SSHPubKeysRSA }}
7 | /configure system security user-params local-user user "admin" public-keys rsa rsa-key {{ subtract 32 $index }} key-value {{ $key }}
8 | {{ end }}
9 |
10 | {{ range $index, $key := .SSHPubKeysECDSA }}
11 | /configure system security user-params local-user user "admin" public-keys ecdsa ecdsa-key {{ subtract 32 $index }} key-value {{ $key }}
12 | {{ end }}
--------------------------------------------------------------------------------
/nodes/xrd/mgmt_intf_v6_addr.sh.tmpl:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | source /pkg/bin/ztp_helper.sh
4 |
5 | xrapply_string "interface MgmtEth0/RP0/CPU0/0\n no ipv6 address\n{{- if .MgmtIPv6Addr }}ipv6 address {{ .MgmtIPv6Addr }}/{{ .MgmtIPv6PrefixLen }}\n{{- end}}"
--------------------------------------------------------------------------------
/nodes/xrd/xrd.cfg:
--------------------------------------------------------------------------------
1 | !
2 | hostname {{ .ShortName }}
3 | !
4 | username clab
5 | group root-lr
6 | group cisco-support
7 | secret clab@123
8 | !
9 | grpc
10 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
11 | port 9339
12 | no-tls
13 | address-family dual
14 | !
15 | {{- if .Env.CLAB_MGMT_VRF }}
16 | vrf {{ .Env.CLAB_MGMT_VRF }}
17 | address-family ipv4 unicast
18 | !
19 | address-family ipv6 unicast
20 | !
21 | {{- end}}
22 | !
23 | line default
24 | transport input ssh
25 | !
26 | netconf-yang agent
27 | ssh
28 | !
29 | interface MgmtEth0/RP0/CPU0/0
30 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
31 | !
32 | router static
33 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
34 | {{- if .MgmtIPv4Gateway }}
35 | address-family ipv4 unicast
36 | 0.0.0.0/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv4Gateway }}
37 | !
38 | {{- end}}
39 | {{- if .MgmtIPv6Gateway }}
40 | address-family ipv6 unicast
41 | ::/0 MgmtEth0/RP0/CPU0/0 {{ .MgmtIPv6Gateway }}
42 | !
43 | {{- end}}
44 | !
45 | ssh server v2
46 | {{- if .Env.CLAB_MGMT_VRF }}
47 | ssh server vrf {{ .Env.CLAB_MGMT_VRF }}
48 | {{- end}}
49 | ssh server netconf {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}}
50 | end
51 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "containerlab"
3 | version = "0.1.0"
4 | description = "Containerlab testing framework"
5 | readme = "README.md"
6 | requires-python = ">=3.12"
7 | dependencies = [
8 | "robotframework==6.1.1",
9 | "robotframework-sshlibrary==3.8.0",
10 | ]
11 |
--------------------------------------------------------------------------------
/runtime/all/all.go:
--------------------------------------------------------------------------------
1 | //go:build !podman
2 | // +build !podman
3 |
4 | package all
5 |
6 | import (
7 | _ "github.com/srl-labs/containerlab/runtime/docker"
8 | _ "github.com/srl-labs/containerlab/runtime/ignite"
9 | )
10 |
--------------------------------------------------------------------------------
/runtime/all/all_with_podman.go:
--------------------------------------------------------------------------------
1 | //go:build linux && podman
2 | // +build linux,podman
3 |
4 | package all
5 |
6 | import (
7 | _ "github.com/srl-labs/containerlab/runtime/docker"
8 | _ "github.com/srl-labs/containerlab/runtime/ignite"
9 | _ "github.com/srl-labs/containerlab/runtime/podman"
10 | )
11 |
--------------------------------------------------------------------------------
/runtime/docker/firewall/definitions/definitions.go:
--------------------------------------------------------------------------------
1 | package definitions
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | var ErrNotAvailable = errors.New("not available")
8 |
9 | const (
10 | DockerUserChain = "DOCKER-USER"
11 | ForwardChain = "FORWARD"
12 | FilterTable = "filter"
13 | AcceptAction = "ACCEPT"
14 | InDirection = "in"
15 | OutDirection = "out"
16 |
17 | ContainerlabComment = "set by containerlab"
18 |
19 | IPTablesCommentMaxSize = 256
20 | )
21 |
22 | // ClabFirewall is the interface that all firewall clients must implement.
23 | type ClabFirewall interface {
24 | DeleteForwardingRules(rule FirewallRule) error
25 | InstallForwardingRules(rule FirewallRule) error
26 | Name() string
27 | }
28 |
29 | type FirewallRule struct {
30 | Chain string
31 | Table string
32 | Interface string
33 | Direction string
34 | Action string
35 | Comment string
36 | }
37 |
--------------------------------------------------------------------------------
/runtime/docker/firewall/firewall.go:
--------------------------------------------------------------------------------
1 | package firewall
2 |
3 | import (
4 | "github.com/srl-labs/containerlab/runtime/docker/firewall/definitions"
5 | "github.com/srl-labs/containerlab/runtime/docker/firewall/iptables"
6 | "github.com/srl-labs/containerlab/runtime/docker/firewall/nftables"
7 | )
8 |
9 | // NewFirewallClient returns a firewall client based on the availability of nftables or iptables.
10 | func NewFirewallClient() (definitions.ClabFirewall, error) {
11 | var clf definitions.ClabFirewall
12 |
13 | clf, err := nftables.NewNftablesClient()
14 | if err == nil {
15 | return clf, nil
16 | }
17 |
18 | clf, err = iptables.NewIpTablesClient()
19 | if err == nil {
20 | return clf, nil
21 | }
22 |
23 | return nil, err
24 | }
25 |
--------------------------------------------------------------------------------
/runtime/docker/test_data/docker.config:
--------------------------------------------------------------------------------
1 | {
2 | "auths": {
3 | "test.example.com": {
4 | "auth": "dGVzdHVzZXIxOnRlc3RwYXNzMQo="
5 | },
6 | "other.example.com": {
7 | "auth": "dGVzdHVzZXI6dGVzdHBhc3MK"
8 | },
9 | "bad.example.com": {
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/runtime/docker/test_data/invalid_docker.config:
--------------------------------------------------------------------------------
1 | {
2 | "auths": {
3 | "test.example.com": {
4 | "auth": "dGVzdHVzZXIxOnRlc3RwYXNzMQo="
5 | }
6 | "other.example.com": {
7 | "auth": "dGVzdHVzZXI6dGVzdHBhc3MK"
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/tests/01-smoke/01-linux-single-node.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: single-node
6 |
7 | mgmt:
8 | network: test
9 | ipv4-subnet: 172.20.30.0/24
10 | ipv4-range: 172.20.30.8/30
11 |
12 | topology:
13 | nodes:
14 | l1:
15 | kind: linux
16 | image: alpine:3
17 | cmd: ash -c "sleep 9999"
18 |
--------------------------------------------------------------------------------
/tests/01-smoke/01-test.json:
--------------------------------------------------------------------------------
1 | {
2 | "containerlab": "is cool"
3 | }
--------------------------------------------------------------------------------
/tests/01-smoke/01-test.txt:
--------------------------------------------------------------------------------
1 | Hello, containerlab
--------------------------------------------------------------------------------
/tests/01-smoke/03-linux-nodes-to-bridge-and-host.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 03-bridge-and-host
6 | mgmt:
7 | bridge: 01-03-mgmt
8 |
9 | topology:
10 | nodes:
11 | l1:
12 | kind: linux
13 | image: alpine:3
14 | cmd: ash -c "sleep 9999"
15 | br-01-03-clab:
16 | kind: bridge
17 | hostnode: # is not used, it is here for coverage
18 | kind: host
19 |
20 | links:
21 | - endpoints: ["l1:eth1", "br-01-03-clab:l1-eth1"]
22 | - endpoints: ["br-01-03-clab:l1-eth2", "l1:eth2"]
23 | # l1:eth3 is connected to host via host link
24 | # https://containerlab.dev/manual/network/#host-links
25 | - endpoints: ["l1:eth3", "host:l1-01-03-eth3"]
26 |
--------------------------------------------------------------------------------
/tests/01-smoke/05-docker-bridge.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 05-docker-bridge
6 | # use the default docker network named "bridge"
7 | mgmt:
8 | network: bridge
9 |
10 | topology:
11 | nodes:
12 | l1:
13 | kind: linux
14 | image: alpine:3
15 | cmd: ash -c "sleep 9999"
16 |
--------------------------------------------------------------------------------
/tests/01-smoke/07-linux-single-node.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: single-node
6 | mgmt:
7 | bridge: 01-07-net
8 |
9 | topology:
10 | nodes:
11 | l1:
12 | kind: linux
13 | image: alpine:3
14 | cmd: ash -c "sleep 9999"
15 |
--------------------------------------------------------------------------------
/tests/01-smoke/09-external-ca.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: external-ca
6 |
7 | settings:
8 | certificate-authority:
9 | cert: rootCACert.pem
10 | key: rootCAKey.pem
11 |
12 | topology:
13 | nodes:
14 | l1:
15 | kind: linux
16 | image: alpine:3
17 | certificate:
18 | issue: true
19 |
--------------------------------------------------------------------------------
/tests/01-smoke/10-internal-ca.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: internal-ca
6 |
7 | settings:
8 | certificate-authority:
9 | key-size: 512
10 | validity-duration: 5h
11 |
12 | topology:
13 | defaults:
14 | certificate:
15 | issue: true
16 | key-size: 512
17 | nodes:
18 | l1:
19 | kind: linux
20 | image: alpine:3
21 | certificate:
22 | issue: true
23 | validity-duration: 25h
24 | l2:
25 | kind: linux
26 | image: alpine:3
27 | certificate:
28 | issue: true
29 | key-size: 1024
30 | sans:
31 | - 192.168.33.44
32 | - my.text.fqdn
33 | l3:
34 | kind: linux
35 | image: alpine:3
36 | certificate:
37 | issue: false
38 |
--------------------------------------------------------------------------------
/tests/01-smoke/12-tools-veth.clab.yaml:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: dual-node
6 |
7 | topology:
8 | nodes:
9 | n1:
10 | kind: linux
11 | image: alpine:latest
12 |
13 | n2:
14 | kind: linux
15 | image: alpine:latest
16 |
--------------------------------------------------------------------------------
/tests/01-smoke/13-stdin-lab.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library OperatingSystem
3 | Library String
4 | Library Process
5 | Resource ../common.robot
6 |
7 | Suite Teardown Run Keyword Teardown
8 |
9 |
10 | *** Variables ***
11 | ${lab-url} https://gist.githubusercontent.com/hellt/9baa28d7e3cb8290ade1e1be38a8d12b/raw/03067e242d44c9bbe38afa81131e46bab1fa0c42/test.clab.yml
12 |
13 |
14 | *** Test Cases ***
15 | Deploy remote lab
16 | ${rc} ${output} = Run And Return Rc And Output
17 | ... sudo curl -s ${lab-url} | ${CLAB_BIN} --runtime ${runtime} deploy -c -t -
18 | Log ${output}
19 | Should Be Equal As Integers ${rc} 0
20 |
21 | Ensure inspect works
22 | ${rc} ${output} = Run And Return Rc And Output
23 | ... ${CLAB_BIN} --runtime ${runtime} inspect --all
24 | Log ${output}
25 | Should Be Equal As Integers ${rc} 0
26 |
27 |
28 | *** Keywords ***
29 | Teardown
30 | # destroy all labs
31 | Run ${CLAB_BIN} --runtime ${runtime} destroy -c -a
32 |
--------------------------------------------------------------------------------
/tests/01-smoke/15-netw-modes.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library OperatingSystem
3 | Library String
4 | Library Process
5 | Resource ../common.robot
6 |
7 | Suite Setup Run Keyword Teardown
8 | Suite Teardown Run Keyword Teardown
9 |
10 |
11 | *** Variables ***
12 | ${lab} ${CURDIR}/netmodes.clab.yml
13 |
14 |
15 | *** Test Cases ***
16 | Deploy lab
17 | ${output} = Process.Run Process
18 | ... ${CLAB_BIN} --runtime ${runtime} deploy -t ${lab}
19 | ... shell=True
20 | Log ${output.stdout}
21 | Log ${output.stderr}
22 | Should Be Equal As Integers ${output.rc} 0
23 |
24 |
25 | *** Keywords ***
26 | Teardown
27 | # destroy all labs
28 | Run ${CLAB_BIN} --runtime ${runtime} destroy -c -a
29 |
--------------------------------------------------------------------------------
/tests/01-smoke/16-mgmtnet.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library OperatingSystem
3 | Library String
4 | Library Process
5 | Resource ../common.robot
6 |
7 | Suite Setup Setup
8 | Suite Teardown Run Keyword Teardown
9 |
10 |
11 | *** Variables ***
12 | ${lab-name} mgmtnetif
13 | ${topo} ${CURDIR}/16-mgmtnetinterface.clab.yml
14 | ${runtime} docker
15 |
16 |
17 | *** Test Cases ***
18 | Deploy ${lab-name} lab
19 | ${result} = Run Process
20 | ... ${CLAB_BIN} --runtime ${runtime} deploy -t ${topo}
21 | ... shell=True
22 | Log ${result.stdout}
23 | Should Be Equal As Integers ${result.rc} 0
24 |
25 | Check host side interface is attached to mgmt bridge and up
26 | ${params} = Set Variable docker network inspect clab --format '{{ $opt := index .Options "com.docker.network.bridge.name"}}{{ $opt }}'
27 | ${mgmtbrname} = Run Process ${params}
28 | ... shell=True
29 | Log ${mgmtbrname.stdout}
30 | ${result} = Run Process
31 | ... sudo -E ip link show dev l1eth1
32 | ... shell=True
33 | Log ${result.stdout}
34 | Should Be Equal As Integers ${result.rc} 0
35 | Should Contain ${result.stdout} state UP
36 | Should Contain ${result.stdout} master ${mgmtbrname.stdout}
37 |
38 | *** Keywords ***
39 | Teardown
40 | # destroy all labs
41 | Run ${CLAB_BIN} --runtime ${runtime} destroy -c -a
42 |
43 | Setup
44 | # skipping this test suite for podman for now
45 | Skip If '${runtime}' == 'podman'
46 |
--------------------------------------------------------------------------------
/tests/01-smoke/16-mgmtnetinterface.clab.yml:
--------------------------------------------------------------------------------
1 | name: mgmtnetif
2 |
3 | topology:
4 | nodes:
5 | l1:
6 | kind: linux
7 | image: alpine:latest
8 | cmd: sleep infinity
9 | links:
10 | - endpoints: [l1:eth1, mgmt-net:l1eth1]
--------------------------------------------------------------------------------
/tests/01-smoke/macvlan.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: macvlan
6 |
7 | topology:
8 | nodes:
9 | l1:
10 | kind: linux
11 | image: alpine:3
12 | exec:
13 | - apk add iproute2
14 |
15 | links:
16 | - endpoints: ["l1:eth1", "macvlan:${host_link:=ens3}"]
17 |
--------------------------------------------------------------------------------
/tests/01-smoke/netmodes.clab.yml:
--------------------------------------------------------------------------------
1 | name: container-mode
2 | topology:
3 | nodes:
4 | node1:
5 | kind: linux
6 | image: alpine:3
7 | node2:
8 | kind: linux
9 | image: alpine:3
10 | network-mode: container:node1
11 |
--------------------------------------------------------------------------------
/tests/01-smoke/node-filter.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: node-filter
6 | # based on https://containerlab.dev/manual/node-filtering/
7 | topology:
8 | defaults:
9 | kind: linux
10 | image: alpine:3
11 | nodes:
12 | node1:
13 | node2:
14 | node3:
15 | node4:
16 |
17 | links:
18 | - endpoints: ["node1:eth1", "node2:eth1"]
19 | - endpoints: ["node1:eth2", "node3:eth2"]
20 | - endpoints: ["node1:eth3", "node4:eth3"]
21 | - endpoints: ["node2:eth2", "node4:eth2"]
22 | - endpoints: ["node3:eth1", "node4:eth1"]
23 |
--------------------------------------------------------------------------------
/tests/01-smoke/single-topo-folder/lab1.clab.yml:
--------------------------------------------------------------------------------
1 | name: lab1
2 |
3 | topology:
4 | nodes:
5 | node1:
6 | kind: linux
7 | image: alpine:3
--------------------------------------------------------------------------------
/tests/01-smoke/stages-race.clab.yml:
--------------------------------------------------------------------------------
1 | name: stages-race
2 |
3 | topology:
4 | kinds:
5 | linux:
6 | image: alpine
7 | nodes:
8 | l1:
9 | kind: linux
10 | exec:
11 | - ip l show dev eth1
12 | l2:
13 | kind: linux
14 | startup-delay: 3
15 | links:
16 | - endpoints: ["l1:eth1", "l2:eth1"]
17 |
--------------------------------------------------------------------------------
/tests/02-basic-srl/02-srl02.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 02-01-two-srls
6 |
7 | topology:
8 | kinds:
9 | nokia_srlinux:
10 | image: ghcr.io/nokia/srlinux
11 | nodes:
12 | srl1:
13 | kind: nokia_srlinux
14 | startup-config: srl1-startup.cli
15 | mgmt-ipv4: 172.20.20.200
16 | srl2:
17 | kind: nokia_srlinux
18 | image: ghcr.io/nokia/srlinux
19 | env:
20 | SRL_LOCATION: test123
21 | startup-config: https://raw.githubusercontent.com/srl-labs/containerlab/main/tests/02-basic-srl/srl2-startup.cli
22 | mgmt-ipv4: 172.20.20.201
23 |
24 | links:
25 | - endpoints: ["srl1:ethernet-1/1", "srl2:e1-1"]
26 |
--------------------------------------------------------------------------------
/tests/02-basic-srl/03-srl-bgp.clab.yml:
--------------------------------------------------------------------------------
1 | name: srl-bgp
2 |
3 | topology:
4 | kinds:
5 | nokia_srlinux:
6 | image: ghcr.io/nokia/srlinux
7 | nodes:
8 | srl1:
9 | kind: nokia_srlinux
10 | startup-config: 03-srl1-bgp.config
11 | srl2:
12 | kind: nokia_srlinux
13 | startup-config: 03-srl2-bgp.config
14 |
15 | links:
16 | - endpoints: ["srl1:e1-1", "srl2:e1-1"]
17 |
--------------------------------------------------------------------------------
/tests/02-basic-srl/srl1-startup.cli:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 0
3 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
4 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.0/31
5 | set / interface ethernet-1/1 subinterface 0 ipv6 admin-state enable
6 | set / interface ethernet-1/1 subinterface 0 ipv6 address 2002::192.168.0.0/127
7 |
8 | set / network-instance default
9 | set / network-instance default interface ethernet-1/1.0
--------------------------------------------------------------------------------
/tests/02-basic-srl/srl2-startup.cli:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 0
3 | set / interface ethernet-1/1 subinterface 0 admin-state enable
4 | set / interface ethernet-1/1 subinterface 0 ipv4 admin-state enable
5 | set / interface ethernet-1/1 subinterface 0 ipv4 address 192.168.0.1/31
6 | set / interface ethernet-1/1 subinterface 0 ipv6 admin-state enable
7 | set / interface ethernet-1/1 subinterface 0 ipv6 address 2002::192.168.0.1/127
8 |
9 | set / network-instance default
10 | set / network-instance default interface ethernet-1/1.0
11 |
12 | set / system information location {{.Env.SRL_LOCATION}}
--------------------------------------------------------------------------------
/tests/03-basic-ceos/03-ceos01-clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 03-01-two-ceos
6 |
7 | topology:
8 | kinds:
9 | ceos:
10 | image: ceos:4.32.0F
11 | env:
12 | CLAB_MGMT_VRF: MGMT
13 | nodes:
14 | n1:
15 | kind: ceos
16 | n2:
17 | kind: ceos
18 | mgmt-ipv4: 172.20.20.22
19 |
20 | links:
21 | - endpoints: ["n1:eth1", "n2:eth1"]
22 |
--------------------------------------------------------------------------------
/tests/04-basic-ixiacone/04-ixiacone01-clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 04-01-ixiacone
6 | prefix: ""
7 | topology:
8 | nodes:
9 | ixia:
10 | kind: keysight_ixia-c-one
11 | image: ghcr.io/open-traffic-generator/ixia-c-one:1.31.0-3
12 | linux:
13 | kind: linux
14 | image: alpine:3
15 | links:
16 | - endpoints: ["ixia:eth1", "linux:eth1"]
17 | - endpoints: ["ixia:eth2", "linux:eth2"]
18 |
--------------------------------------------------------------------------------
/tests/05-k8s-kind/01-basic-k8s-kind.clab.yml:
--------------------------------------------------------------------------------
1 | name: 01-basic-k8s-kind
2 |
3 | topology:
4 | kinds:
5 | nokia_srlinux:
6 | type: ixrd3
7 | image: ghcr.io/nokia/srlinux
8 | nodes:
9 | br01:
10 | kind: bridge
11 | alpine:
12 | kind: linux
13 | image: alpine
14 | cmd: ash -c "sleep 9999"
15 | exec:
16 | - "ip a add dev eth1 192.168.237.20/24"
17 | k01:
18 | kind: k8s-kind
19 | startup-config: k01-config.yaml
20 | k02:
21 | kind: k8s-kind
22 |
23 | # k01 -> resulting nodes due to startup-config assigned config `k01-config.yaml`
24 | k01-control-plane:
25 | kind: ext-container
26 | exec:
27 | - "ip a del dev eth1"
28 | - "ip a add dev eth1 192.168.237.1/24"
29 |
30 | k01-worker:
31 | kind: ext-container
32 | exec:
33 | - "ip a del dev eth1"
34 | - "ip a add dev eth1 192.168.237.2/24"
35 |
36 | k02-control-plane:
37 | kind: ext-container
38 | exec:
39 | - "ip a del dev eth1"
40 | - "ip a add dev eth1 192.168.237.3/24"
41 |
42 | links:
43 | - endpoints: ["br01:e1", "k01-control-plane:eth1"]
44 | - endpoints: ["br01:e2", "k01-worker:eth1"]
45 | - endpoints: ["br01:e3", "k02-control-plane:eth1"]
46 | - endpoints: ["br01:e4", "alpine:eth1"]
47 |
48 | - endpoints: ["br01:e5", "k01-control-plane:eth2"]
49 | - endpoints: ["br01:e6", "k02-control-plane:eth2"]
50 |
--------------------------------------------------------------------------------
/tests/05-k8s-kind/k01-config.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: kind.x-k8s.io/v1alpha4
2 | kind: Cluster
3 | nodes:
4 | - role: control-plane
5 | - role: worker
--------------------------------------------------------------------------------
/tests/06-ext-container/01-ext-container.clab.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2022 Nokia
2 | # Licensed under the BSD 3-Clause License.
3 | # SPDX-License-Identifier: BSD-3-Clause
4 |
5 | name: 06-ext-container
6 |
7 | topology:
8 | nodes:
9 | ext1:
10 | kind: ext-container
11 | exec:
12 | - "ip address add dev eth1 192.168.0.1/24"
13 | ext2:
14 | kind: ext-container
15 | exec:
16 | - "ip address add dev eth1 192.168.0.2/24"
17 |
18 | links:
19 | - endpoints: ["ext1:eth1", "ext2:eth1"]
20 |
--------------------------------------------------------------------------------
/tests/06-ext-container/02-shared-namespace-ext.clab.yaml:
--------------------------------------------------------------------------------
1 | name: shared-namespace-ext
2 | prefix: ""
3 |
4 | topology:
5 | kinds:
6 | linux:
7 | cmd: sh
8 | nodes:
9 | ext-node:
10 | kind: linux
11 | image: alpine
12 | exec:
13 | - ip l add dev d1 type dummy
14 | - ip a add dev d1 128.66.0.1/32
--------------------------------------------------------------------------------
/tests/06-ext-container/02-shared-namespace.clab.yaml:
--------------------------------------------------------------------------------
1 | name: shared-namespace
2 |
3 | topology:
4 | kinds:
5 | linux:
6 | cmd: sh
7 | nodes:
8 | node0:
9 | kind: linux
10 | image: alpine
11 | exec:
12 | - ip a
13 | node1:
14 | kind: linux
15 | image: alpine
16 | network-mode: container:ext-node
17 | exec:
18 | - ip a
19 | links:
20 | - endpoints: ["node0:net0", "node1:net0"]
--------------------------------------------------------------------------------
/tests/07-sros/1-sros.clab.yml:
--------------------------------------------------------------------------------
1 | name: 1-sros
2 |
3 | topology:
4 | nodes:
5 | sros1:
6 | kind: nokia_sros
7 | image: registry.srlinux.dev/pub/vr-sros:23.10.R2
8 | license: sros23.key
9 |
--------------------------------------------------------------------------------
/tests/08-vxlan/01-vxlan-s1.config:
--------------------------------------------------------------------------------
1 | set / interface ethernet-1/1 admin-state enable
2 | set / interface ethernet-1/1 subinterface 1 admin-state enable
3 | set / interface ethernet-1/1 subinterface 1 ipv4
4 | set / interface ethernet-1/1 subinterface 1 ipv4 admin-state enable
5 | set / interface ethernet-1/1 subinterface 1 ipv4 address 192.168.67.1/30
6 | set / network-instance default interface ethernet-1/1.1
--------------------------------------------------------------------------------
/tests/08-vxlan/01-vxlan.clab.yml:
--------------------------------------------------------------------------------
1 | name: vxlan
2 |
3 | mgmt:
4 | network: clab-vxlan
5 | bridge: clab-vxlan-br
6 | ipv4-subnet: 172.20.25.0/24
7 |
8 | topology:
9 | nodes:
10 | srl1:
11 | kind: nokia_srlinux
12 | image: ghcr.io/nokia/srlinux
13 | startup-config: 01-vxlan-s1.config
14 | mgmt-ipv4: 172.20.25.21
15 | l2:
16 | kind: linux
17 | image: alpine:3
18 | exec:
19 | - >
20 | ash -c '
21 | apk add iproute2 &&
22 | ip link add name vxlan0 type vxlan id 100 remote 172.20.25.21 dstport 14788 &&
23 | ip l set dev vxlan0 up &&
24 | ip addr add dev vxlan0 192.168.67.2/30'
25 | mgmt-ipv4: 172.20.25.22
26 |
27 | links:
28 | - type: vxlan
29 | endpoint:
30 | node: srl1
31 | interface: e1-1
32 | mac: 02:00:00:00:00:04
33 | remote: 172.20.25.22
34 | vni: 100
35 | udp-port: 14788
36 |
--------------------------------------------------------------------------------
/tests/08-vxlan/02-vxlan-stitch.clab.yml:
--------------------------------------------------------------------------------
1 | # yaml-language-server: $schema=../../schemas/clab.schema.json
2 | name: vxlan-stitch
3 |
4 | mgmt:
5 | network: clab-vxlan
6 | bridge: clab-vxlan-br
7 | mtu: 9100
8 | ipv4-subnet: 172.20.25.0/24
9 |
10 | topology:
11 | nodes:
12 | srl1:
13 | kind: nokia_srlinux
14 | image: ghcr.io/nokia/srlinux
15 | startup-config: 01-vxlan-s1.config
16 | mgmt-ipv4: 172.20.25.21
17 |
18 | # this node doesn't participate in the vxlan datapath
19 | # we just put it here to test that long named nodes
20 | # are treated correctly with ip aliases added to link name.
21 | some_very_long_node_name_l1:
22 | kind: linux
23 | image: alpine:3
24 | exec:
25 | - apk add iproute2
26 |
27 | l2:
28 | kind: linux
29 | image: alpine:3
30 | exec:
31 | - >
32 | ash -c '
33 | apk add iproute2 &&
34 | ip link add name vxlan0 type vxlan id 100 remote 172.20.25.21 dstport 14788 &&
35 | ip l set dev vxlan0 up &&
36 | ip addr add dev vxlan0 192.168.67.2/30'
37 | mgmt-ipv4: 172.20.25.22
38 |
39 | links:
40 | - type: vxlan-stitch
41 | endpoint:
42 | node: srl1
43 | interface: e1-1
44 | mac: 02:00:00:00:00:04
45 | remote: 172.20.25.22
46 | vni: 100
47 | udp-port: 14788
48 |
49 | - type: vxlan-stitch
50 | endpoint:
51 | node: some_very_long_node_name_l1
52 | interface: e1-1
53 | remote: 172.20.25.23
54 | vni: 101
55 | udp-port: 14789
56 |
--------------------------------------------------------------------------------
/tests/09-fortigate/fortigates.clab.yml:
--------------------------------------------------------------------------------
1 | name: forti
2 | topology:
3 | nodes:
4 | forti1:
5 | kind: fortinet_fortigate
6 | image: ghcr.io/srl-labs/fortigate:7.0.14
7 | # image: registry.srlinux.dev/pub/fortinet_fortigate:7.0.14
8 | forti2:
9 | kind: fortinet_fortigate
10 | image: ghcr.io/srl-labs/fortigate:7.0.14
11 | # image: registry.srlinux.dev/pub/fortinet_fortigate:7.0.14
12 | links:
13 | - endpoints: ["forti1:eth1", "forti2:eth1"]
14 |
--------------------------------------------------------------------------------
/tests/10-basic-cisco_iol/iol.clab.yml:
--------------------------------------------------------------------------------
1 | name: iol
2 | topology:
3 | nodes:
4 | router1:
5 | kind: cisco_iol
6 | image: ghcr.io/srl-labs/containerlab/cisco_iol:17.12.01
7 | router2:
8 | kind: cisco_iol
9 | image: ghcr.io/srl-labs/containerlab/cisco_iol:17.12.01
10 | startup-config: ./loopback_config.partial
11 | router3:
12 | kind: cisco_iol
13 | image: ghcr.io/srl-labs/containerlab/cisco_iol:17.12.01
14 | startup-config: ./router3-full.cfg
15 | switch:
16 | kind: cisco_iol
17 | image: ghcr.io/srl-labs/containerlab/cisco_iol:L2-17.12.01
18 | type: l2
19 | links:
20 | - endpoints: ["router1:Ethernet0/1", "switch:Ethernet0/1"]
21 | - endpoints: ["router2:Ethernet0/1", "switch:e0/2"]
22 |
--------------------------------------------------------------------------------
/tests/10-basic-cisco_iol/loopback_config.partial:
--------------------------------------------------------------------------------
1 | interface Loopback0
2 | description PARTIAL_CFG
3 | !
--------------------------------------------------------------------------------
/tests/10-basic-cisco_iol/router3-full.cfg:
--------------------------------------------------------------------------------
1 | hostname FULL_STARTUP_CFG-{{ .Hostname }}
2 | !
3 | no aaa new-model
4 | !
5 | ip domain name lab
6 | !
7 | ip cef
8 | !
9 | ipv6 unicast-routing
10 | !
11 | no ip domain lookup
12 | !
13 | username admin privilege 15 secret admin
14 | !
15 | vrf definition clab-mgmt
16 | description clab-mgmt
17 | address-family ipv4
18 | !
19 | address-family ipv6
20 | !
21 | !
22 | interface Ethernet0/0
23 | {{ if .IsL2Node }}
24 | no switchport
25 | {{ end }}
26 | vrf forwarding clab-mgmt
27 | description clab-mgmt
28 | ip address {{ .MgmtIPv4Addr }} {{ .MgmtIPv4SubnetMask }}
29 | ipv6 address {{ .MgmtIPv6Addr }}/{{ .MgmtIPv6PrefixLen }}
30 | no shutdown
31 | !{{ range $index, $item := .DataIFaces }}
32 | interface Ethernet{{ .Slot }}/{{ .Port }}
33 | no shutdown
34 | !{{ end }}
35 | ip forward-protocol nd
36 | !
37 | ip route vrf clab-mgmt 0.0.0.0 0.0.0.0 Ethernet0/0 {{ .MgmtIPv4GW }}
38 | ipv6 route vrf clab-mgmt ::/0 Ethernet0/0 {{ .MgmtIPv6GW }}
39 | !
40 | ip ssh version 2
41 | crypto key generate rsa modulus 2048
42 | !
43 | line vty 0 4
44 | login local
45 | transport input ssh
46 | !
47 | end
48 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/01-e2e-lab.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library OperatingSystem
3 | Resource ../ssh.robot
4 | Resource ../common.robot
5 |
6 | Suite Teardown Run Keyword Cleanup
7 |
8 |
9 | *** Variables ***
10 | ${lab-name} e2e-vpp
11 | ${lab-file-name} e2e-lab/vpp.clab.yml
12 | ${runtime} docker
13 |
14 |
15 | *** Test Cases ***
16 | Deploy ${lab-name} lab
17 | Log ${CURDIR}
18 | ${rc} ${output} = Run And Return Rc And Output
19 | ... ${CLAB_BIN} --runtime ${runtime} deploy -t ${CURDIR}/${lab-file-name}
20 | Log ${output}
21 | Should Be Equal As Integers ${rc} 0
22 |
23 | Pause to let OSPF converge
24 | Sleep 40s
25 |
26 | Ensure client1 can ping client2
27 | ${rc} ${output} = Run And Return Rc And Output
28 | ... ${CLAB_BIN} --runtime ${runtime} exec -t ${CURDIR}/${lab-file-name} --label clab-node-name\=client1 --cmd "ping -c 5 10.82.98.82"
29 | Log ${output} console=True
30 | Should Be Equal As Integers ${rc} 0
31 | Should Contain ${output} 5 packets transmitted, 4 packets received, 20% packet loss
32 |
33 |
34 | *** Keywords ***
35 | Cleanup
36 | Run ${CLAB_BIN} --runtime ${runtime} destroy -t ${CURDIR}/${lab-file-name} --cleanup
37 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/e2e-lab/config/vpp1/bird-local.conf:
--------------------------------------------------------------------------------
1 | protocol bfd bfd1 {
2 | interface "eth2" { interval 100 ms; multiplier 30; };
3 | }
4 |
5 | protocol ospf v2 ospf4 {
6 | ipv4 { import all; export all; };
7 | area 0 {
8 | interface "loop0" { stub yes; };
9 | interface "eth2" { type pointopoint; cost 10; bfd on; };
10 | };
11 | }
12 |
13 | protocol ospf v3 ospf6 {
14 | ipv6 { import all; export all; };
15 | area 0 {
16 | interface "loop0" { stub yes; };
17 | interface "eth2" { type pointopoint; cost 10; bfd on; };
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/e2e-lab/config/vpp1/vppcfg.yaml:
--------------------------------------------------------------------------------
1 | interfaces:
2 | eth1:
3 | description: "To client1"
4 | mtu: 1500
5 | lcp: eth1
6 | addresses: [10.82.98.65/28, 2001:db8:8298:101::1/64]
7 | eth2:
8 | description: "To vpp2"
9 | mtu: 9216
10 | lcp: eth2
11 | addresses: [10.82.98.16/31, 2001:db8:8298:1::1/64]
12 | loopbacks:
13 | loop0:
14 | description: "vpp1"
15 | lcp: loop0
16 | addresses: [10.82.98.0/32, 2001:db8:8298::/128]
17 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/e2e-lab/config/vpp2/bird-local.conf:
--------------------------------------------------------------------------------
1 | protocol bfd bfd1 {
2 | interface "eth2" { interval 100 ms; multiplier 30; };
3 | }
4 |
5 | protocol ospf v2 ospf4 {
6 | ipv4 { import all; export all; };
7 | area 0 {
8 | interface "loop0" { stub yes; };
9 | interface "eth2" { type pointopoint; cost 10; bfd on; };
10 | };
11 | }
12 |
13 | protocol ospf v3 ospf6 {
14 | ipv6 { import all; export all; };
15 | area 0 {
16 | interface "loop0" { stub yes; };
17 | interface "eth2" { type pointopoint; cost 10; bfd on; };
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/e2e-lab/config/vpp2/vppcfg.yaml:
--------------------------------------------------------------------------------
1 | interfaces:
2 | eth1:
3 | description: "To client2"
4 | mtu: 1500
5 | lcp: eth1
6 | addresses: [10.82.98.81/28, 2001:db8:8298:102::1/64]
7 | eth2:
8 | description: "To vpp1"
9 | mtu: 9216
10 | lcp: eth2
11 | addresses: [10.82.98.17/31, 2001:db8:8298:1::2/64]
12 | loopbacks:
13 | loop0:
14 | description: "vpp2"
15 | lcp: loop0
16 | addresses: [10.82.98.1/32, 2001:db8:8298::1/128]
17 |
--------------------------------------------------------------------------------
/tests/11-fdio-vpp/e2e-lab/vpp.clab.yml:
--------------------------------------------------------------------------------
1 | name: e2e-vpp
2 |
3 | topology:
4 | kinds:
5 | fdio_vpp:
6 | image: git.ipng.ch/ipng/vpp-containerlab:latest
7 | startup-config: config/__clabNodeName__/vppcfg.yaml
8 | binds:
9 | - config/__clabNodeName__/bird-local.conf:/etc/bird/bird-local.conf:ro
10 | linux:
11 | image: alpine:latest
12 |
13 | nodes:
14 | vpp1:
15 | kind: fdio_vpp
16 | vpp2:
17 | kind: fdio_vpp
18 | client1:
19 | kind: linux
20 | exec:
21 | - ip link set address 00:c1:ab:00:00:01 dev eth1
22 | - ip addr add 10.82.98.66/28 dev eth1
23 | - ip route add 10.82.98.0/24 via 10.82.98.65
24 | - ip addr add 2001:db8:8298:101::2/64 dev eth1
25 | - ip route add 2001:db8:8298::/48 via 2001:db8:8298:101::1
26 | client2:
27 | kind: linux
28 | exec:
29 | - ip link set address 00:c1:ab:00:00:02 dev eth1
30 | - ip addr add 10.82.98.82/28 dev eth1
31 | - ip route add 10.82.98.0/24 via 10.82.98.81
32 | - ip addr add 2001:db8:8298:102::2/64 dev eth1
33 | - ip route add 2001:db8:8298::/48 via 2001:db8:8298:102::1
34 |
35 | links:
36 | - endpoints: ["vpp1:eth2", "vpp2:eth2"]
37 | - endpoints: ["client1:eth1", "vpp1:eth1"]
38 | - endpoints: ["client2:eth1", "vpp2:eth1"]
39 |
--------------------------------------------------------------------------------
/tests/common.robot:
--------------------------------------------------------------------------------
1 | *** Variables ***
2 | ${CLAB_BIN} containerlab
3 |
--------------------------------------------------------------------------------
/tests/rf-run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright 2020 Nokia
3 | # Licensed under the BSD 3-Clause License.
4 | # SPDX-License-Identifier: BSD-3-Clause
5 |
6 | # arguments
7 | # $1 - container runtime: [docker, podman]
8 | # $2 - test suite to execute
9 |
10 | # set containerlab binary path to a value of CLAB_BIN env variable
11 | # unless it is not set, then use 'containerlab' as a default value
12 | if [ -z "${CLAB_BIN}" ]; then
13 | CLAB_BIN=containerlab
14 | fi
15 |
16 | echo "Running tests with containerlab binary at $(which ${CLAB_BIN}) path and selected runtime: $1"
17 |
18 | COV_DIR=/tmp/clab-tests/coverage
19 |
20 | # coverage output directory
21 | mkdir -p ${COV_DIR}
22 |
23 | # parses the dir or file name passed to the rf-run.sh script
24 | # and in case of a directory, it returns the name of the directory
25 | # in case of a file it returns the name of the file's dir catenated with file name without extension
26 | function get_logname() {
27 | path=$1
28 | filename=$(basename "$path")
29 | if [[ "$filename" == *.* ]]; then
30 | dirname=$(dirname "$path")
31 | basename=$(basename "$path" | cut -d. -f1)
32 | echo "${dirname##*/}-${basename}"
33 | else
34 | echo "${filename}"
35 | fi
36 | }
37 |
38 | # activate venv
39 | source .venv/bin/activate
40 |
41 | GOCOVERDIR=${COV_DIR} robot --consolecolors on -r none --variable CLAB_BIN:${CLAB_BIN} --variable runtime:$1 -l ./tests/out/$(get_logname $2)-$1-log --output ./tests/out/$(basename $2)-$1-out.xml $2
42 |
--------------------------------------------------------------------------------
/tests/ssh.robot:
--------------------------------------------------------------------------------
1 | *** Settings ***
2 | Library SSHLibrary
3 |
4 |
5 | *** Keywords ***
6 | Login via SSH with username and password
7 | [Arguments]
8 | ... ${address}=${None}
9 | ... ${port}=22
10 | ... ${username}=${None}
11 | ... ${password}=${None}
12 | # seconds to try and succesfully login
13 | ... ${try_for}=4
14 | ... ${conn_timeout}=3
15 | FOR ${i} IN RANGE ${try_for}
16 | SSHLibrary.Open Connection ${address} timeout=${conn_timeout}
17 | ${status}= Run Keyword And Return Status SSHLibrary.Login ${username} ${password}
18 | IF ${status} BREAK
19 | Sleep 1s
20 | END
21 | IF $status!=True
22 | Fail Unable to connect to ${address} via SSH in ${try_for} attempts
23 | END
24 | Log Exited the loop.
25 |
26 | Login via SSH with public key
27 | [Arguments]
28 | ... ${address}=${None}
29 | ... ${port}=22
30 | ... ${username}=${None}
31 | ... ${keyfile}=~/.ssh/id_rsa
32 | # seconds to try and succesfully login
33 | ... ${try_for}=4
34 | ... ${conn_timeout}=3
35 | Log ${keyfile}
36 | FOR ${i} IN RANGE ${try_for}
37 | SSHLibrary.Open Connection ${address} timeout=${conn_timeout}
38 | ${status}= Run Keyword And Return Status SSHLibrary.Login With Public Key ${username} ${keyfile}
39 | IF ${status} BREAK
40 | Sleep 1s
41 | END
42 | IF $status!=True
43 | Fail Unable to connect to ${address} via SSH in ${try_for} attempts
44 | END
45 | Log Exited the loop.
46 |
--------------------------------------------------------------------------------
/types/constants.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | const (
4 | // env var containing the expected number of interfaces injected into every container.
5 | CLAB_ENV_INTFS = "CLAB_INTFS"
6 | )
7 |
--------------------------------------------------------------------------------
/types/license_policy_value.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | // LicensePolicy is a value of LicensePolicy.
4 | type LicensePolicy string
5 |
6 | const (
7 | // LicensePolicyRequired means a node should exit if no license provided.
8 | LicensePolicyRequired = "required"
9 | // LicensePolicyWarn means a node should warn (but not exit) if no license provided.
10 | LicensePolicyWarn = "warn"
11 | // LicensePolicyNone means a node doesn't care about a license.
12 | LicensePolicyNone = "none"
13 | )
14 |
--------------------------------------------------------------------------------
/types/settings.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import "time"
4 |
5 | // Settings is the structure for global containerlab settings.
6 | type Settings struct {
7 | CertificateAuthority *CertificateAuthority `yaml:"certificate-authority"`
8 | }
9 |
10 | // CertificateAuthority is the structure for global containerlab certificate authority settings.
11 | type CertificateAuthority struct {
12 | // Cert is the path to the CA certificate file in the External CA mode of operation.
13 | Cert string `yaml:"cert"`
14 | // Key is the path to the CA private key file in the External CA mode of operation.
15 | Key string `yaml:"key"`
16 | // KeySize is the size of the CA private key in bits
17 | // when containerlab is in charge of the CA generation.
18 | KeySize int `yaml:"key-size"`
19 | // ValidityDuration is the duration of the CA certificate validity
20 | // when containerlab is in charge of the CA generation.
21 | ValidityDuration time.Duration `yaml:"validity-duration"`
22 | }
23 |
--------------------------------------------------------------------------------
/types/ssh_config.go:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | type PubkeyAuthValue string
4 |
5 | const (
6 | PubkeyAuthValueYes PubkeyAuthValue = "yes"
7 | PubkeyAuthValueNo PubkeyAuthValue = "no"
8 | PubkeyAuthValueHostBound PubkeyAuthValue = "host-bound"
9 | PubkeyAuthValueUnbound PubkeyAuthValue = "unbound"
10 | )
11 |
12 | func (p PubkeyAuthValue) String() string {
13 | return string(p)
14 | }
15 |
16 | // SSHConfig is the SSH client configuration that a clab node requires.
17 | type SSHConfig struct {
18 | PubkeyAuthentication PubkeyAuthValue
19 | }
20 |
21 | func NewSSHConfig() *SSHConfig {
22 | return &SSHConfig{}
23 | }
24 |
--------------------------------------------------------------------------------
/types/test_data/config.cfg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/types/test_data/config.cfg
--------------------------------------------------------------------------------
/types/test_data/lic1.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/srl-labs/containerlab/0c0f592795be47424fe0470bd5ce182ebf078102/types/test_data/lic1.key
--------------------------------------------------------------------------------
/utils/if-wait.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | // IfWaitScript is used in ENTRYPOINT/CMD of the nodes that need to ensure that all
4 | // of the clab links/interfaces are available in the container before calling the main process.
5 | var IfWaitScript string = `#!/bin/sh
6 |
7 | INTFS=$(echo $CLAB_INTFS)
8 | SLEEP=0
9 |
10 | int_calc ()
11 | {
12 | index=0
13 | for i in $(ls -1v /sys/class/net/ | grep -E '^et|^ens|^eno|^e[0-9]'); do
14 | index=$((index+1))
15 | done
16 | MYINT=$index
17 | }
18 |
19 | int_calc
20 |
21 | echo "Waiting for all $INTFS interfaces to be connected"
22 | while [ "$MYINT" -lt "$INTFS" ]; do
23 | echo "Connected $MYINT interfaces out of $INTFS"
24 | sleep 1
25 | int_calc
26 | done
27 |
28 | echo "Sleeping $SLEEP seconds before boot"
29 | sleep $SLEEP
30 | `
31 |
--------------------------------------------------------------------------------
/utils/ip.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "crypto/rand"
5 | "encoding/hex"
6 | "fmt"
7 | "net"
8 | "strings"
9 |
10 | "github.com/charmbracelet/log"
11 | )
12 |
13 | // GenerateIPv6ULASubnet creates a random /64 ULA (Unique Local Address) IPv6 subnet in the fd00::/8 range.
14 | func GenerateIPv6ULASubnet() (string, error) {
15 | var ula strings.Builder
16 |
17 | ula.WriteString("fd00:")
18 |
19 | bytes := make([]byte, 2)
20 | for i := 0; i < 3; i++ {
21 | // Generate a random 16-bit hex field
22 | if _, err := rand.Read(bytes); err != nil {
23 | return "", err
24 | }
25 |
26 | ula.WriteString(hex.EncodeToString(bytes))
27 | ula.WriteString(":")
28 | }
29 |
30 | ula.WriteString(":/64")
31 |
32 | return ula.String(), nil
33 | }
34 |
35 | // CIDRToDDN converts CIDR mask to a Dotted Decimal Notation
36 | // ie CIDR: 24 -> DDN: 255.255.255.0
37 | // The result is a string.
38 | func CIDRToDDN(length int) string {
39 | // check mask length is valid
40 | if length < 0 || length > 32 {
41 | log.Errorf("Invalid prefix length: %d", length)
42 | return ""
43 | }
44 |
45 | mask := net.CIDRMask(length, 32)
46 | return fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
47 | }
48 |
--------------------------------------------------------------------------------
/utils/keys.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "github.com/charmbracelet/log"
5 | "golang.org/x/crypto/ssh"
6 | )
7 |
8 | // LoadSSHPubKeysFromFiles parses openssh keys from the files referenced by the paths
9 | // and returns a slice of ssh.PublicKey pointers.
10 | // The files may contain multiple keys each on a separate line.
11 | func LoadSSHPubKeysFromFiles(paths []string) ([]ssh.PublicKey, error) {
12 | var keys []ssh.PublicKey
13 |
14 | for _, p := range paths {
15 | lines, err := FileLines(p, "#")
16 | if err != nil {
17 | return nil, err
18 | }
19 |
20 | for _, l := range lines {
21 | pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(l))
22 |
23 | log.Debugf("Loaded public key %s", l)
24 |
25 | if err != nil {
26 | return nil, err
27 | }
28 |
29 | keys = append(keys, pubKey)
30 | }
31 |
32 | }
33 |
34 | return keys, nil
35 | }
36 |
--------------------------------------------------------------------------------
/utils/password.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "os"
6 |
7 | "golang.org/x/term"
8 | )
9 |
10 | func ReadPasswordFromTerminal() (string, error) {
11 | fmt.Print("password: ")
12 | pass, err := term.ReadPassword(int(os.Stdin.Fd()))
13 | if err != nil {
14 | return "", err
15 | }
16 | fmt.Println()
17 | return string(pass), nil
18 | }
19 |
--------------------------------------------------------------------------------
/utils/pointer.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | // Pointer returns a pointer to a value of any type.
4 | func Pointer[T any](v T) *T {
5 | return &v
6 | }
7 |
--------------------------------------------------------------------------------
/utils/process.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import "syscall"
4 |
5 | // PauseProcessGroup sends the SIGSTOP signal to a process group, causing all
6 | // the processes within the group to be Paused e.g. SRL runs multilpe processes, if the
7 | // container is meant to be stopped, all the related processes must be paused.
8 | // To me it seams like the ProcessGroupID is set correctly so we can count on that field.
9 | // The syscall.Kill interpretes negative ints as a PGID and not as a common PID.
10 | func PauseProcessGroup(pgid int) error {
11 | return syscall.Kill(-pgid, syscall.SIGSTOP)
12 | }
13 |
14 | // UnpauseProcessGroup send the SIGCONT to the given ProcessGroup identified by its ID.
15 | func UnpauseProcessGroup(pgid int) error {
16 | return syscall.Kill(-pgid, syscall.SIGCONT)
17 | }
18 |
--------------------------------------------------------------------------------
/utils/regexp.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | import (
4 | "fmt"
5 | "regexp"
6 | )
7 |
8 | func GetRegexpCaptureGroups(r *regexp.Regexp, search string) (map[string]string, error) {
9 | matches := r.FindStringSubmatch(search)
10 | if len(matches) == 0 {
11 | return nil, fmt.Errorf("%q does not match regexp %q, no match", search, r)
12 | }
13 |
14 | captureGroups := make(map[string]string)
15 | for i, name := range r.SubexpNames() {
16 | if i != 0 && name != "" {
17 | captureGroups[name] = matches[i]
18 | }
19 | }
20 |
21 | return captureGroups, nil
22 | }
23 |
--------------------------------------------------------------------------------
/utils/test_data/keys:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs4Qv1yrBk6ygt+o7J4sUcYv+WfDjdAyABDoinOt3PgSmCcVqqAP2qS8UtTnMNuy93Orp6+/R/7/R3O5xdY6I4YViK3WVlKTAUVm7vdeTKp9uq1tNeWgo7+J3baSbQ3INp85ScTfFvRzRCFkr/W97Wh6pTa7ysgkcPvc2/tXG2z36Mx7/TFBk3Q1LY3ByKLtGrC5JnVpMTrqrsCwcLEVHHEZ4z5R4FZED/lpz+wTNFnR/l9HA6yDkKYensHynx+guqYpYD6y4yEGY/LcUnwBg0zIlUhmOsvdmxWBz12Lp7EBiNjSwhnPfe+o3efLGGnjWUAa4TgO8Sa8PQP0pK/ZNd
2 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILKdXYzPIq8kHRJtDrh21wMVI76AnuPk7HDLeDteKN74
--------------------------------------------------------------------------------
/utils/test_data/keys1.txt:
--------------------------------------------------------------------------------
1 | valid line
2 | # comment
3 | another valid line
--------------------------------------------------------------------------------
/virt/memory.go:
--------------------------------------------------------------------------------
1 | package virt
2 |
3 | import (
4 | "github.com/charmbracelet/log"
5 | "github.com/mackerelio/go-osstat/memory"
6 | )
7 |
8 | type MemoryType int
9 |
10 | const (
11 | MemoryTypeTotal MemoryType = iota
12 | MemoryTypeAvailable
13 | )
14 |
15 | // GetSysMemory reports on total installed or available memory (in bytes).
16 | func GetSysMemory(mt MemoryType) uint64 {
17 | memoryResult, err := memory.Get()
18 | if err != nil {
19 | log.Errorf("unable to determine available memory: %v", err)
20 | return 0
21 | }
22 | switch mt {
23 | case MemoryTypeAvailable:
24 | return memoryResult.Available
25 | case MemoryTypeTotal:
26 | return memoryResult.Total
27 | }
28 | return 0
29 | }
30 |
--------------------------------------------------------------------------------