├── .gitignore ├── 10-basics ├── basic.clab.yml └── README.md ├── 20-vm ├── vm.clab.yml └── README.md ├── 15-startup ├── startup.clab.yml ├── ceos.cfg ├── srl.cfg └── README.md ├── README.md ├── 05-install └── README.md ├── 45-streaming-telemetry └── README.md ├── 40-packet-capture └── README.md ├── 30-registry └── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | sync.sh -------------------------------------------------------------------------------- /10-basics/basic.clab.yml: -------------------------------------------------------------------------------- 1 | name: basic 2 | 3 | topology: 4 | nodes: 5 | srl: 6 | kind: nokia_srlinux 7 | image: ghcr.io/nokia/srlinux 8 | 9 | ceos: 10 | kind: arista_ceos 11 | image: ceos:4.32.0F 12 | 13 | links: 14 | - endpoints: [srl:e1-1, ceos:eth1] 15 | -------------------------------------------------------------------------------- /20-vm/vm.clab.yml: -------------------------------------------------------------------------------- 1 | name: vm 2 | topology: 3 | nodes: 4 | sros: 5 | kind: nokia_sros 6 | image: vrnetlab/nokia_sros:24.7.R1 7 | license: ~/images/sros-24.lic 8 | 9 | c8000v: 10 | kind: cisco_c8000v 11 | image: vrnetlab/cisco_c8000v:17.11.01a 12 | 13 | links: 14 | - endpoints: [sros:eth1, c8000v:eth1] 15 | -------------------------------------------------------------------------------- /15-startup/startup.clab.yml: -------------------------------------------------------------------------------- 1 | name: startup 2 | topology: 3 | nodes: 4 | srl: 5 | kind: nokia_srlinux 6 | image: ghcr.io/nokia/srlinux 7 | startup-config: srl.cfg 8 | ceos: 9 | kind: arista_ceos 10 | image: ceos:4.32.0F 11 | startup-config: ceos.cfg 12 | 13 | links: 14 | - endpoints: [srl:e1-1, ceos:eth1] 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Containerlab Workshop at DENOG 16 2 | 3 | A list of workshop modules. Each module is a self-contained guide that can be followed independently, but it is recommended to go through them in order if you are new to Containerlab. 4 | 5 | Use the [official slide deck](https://gitlab.com/rdodin/pics/-/wikis/uploads/419c501863a492c9016f0e7b345b1c68/Containerlab_DENOG16_Workshop-export.pdf) to follow along with the workshop. 6 | 7 | 1. [Containerlab Installation](05-install/README.md) guide 8 | 2. [Basics first](10-basics/README.md) 9 | 3. [Dealing with startup config](15-startup/README.md) 10 | 4. [VM-based nodes](20-vm/README.md) 11 | 5. [Container registry](30-registry/README.md) 12 | 6. [Packet capture](40-packet-capture/README.md) 13 | 7. [A lab that has it ~all](45-streaming-telemetry/README.md) 14 | 15 | Did you love this workshop? Let us know in the comments of this [LinkedIn post](TBD). 16 | -------------------------------------------------------------------------------- /05-install/README.md: -------------------------------------------------------------------------------- 1 | # Containerlab Installation 2 | 3 | ## All In One installer 4 | 5 | Installs 6 | 7 | * docker 8 | * latest containerlab, 9 | * `gh` cli 10 | 11 | all in one, multi-OS installer: 12 | 13 | ```bash 14 | curl -L http://containerlab.dev/setup | \ 15 | sudo bash -s "all" 16 | ``` 17 | 18 | The automation script adds the `docker` group to your `user`, in order for these changes to take effect, log out from the current session and log back in. 19 | 20 | Check that docker is installed and running: 21 | 22 | ```bash 23 | docker run --rm hello-world 24 | # Expected output: Hello from Docker! 25 | ``` 26 | 27 | Check that containerlab is installed successfully: 28 | 29 | ```bash 30 | sudo containerlab version 31 | ``` 32 | 33 | * Alternative Containerlab installation options are available [here](https://containerlab.dev/install/). 34 | * Alternative Docker installation options can be found [here](https://docs.docker.com/engine/install/). 35 | -------------------------------------------------------------------------------- /15-startup/ceos.cfg: -------------------------------------------------------------------------------- 1 | hostname {{ .ShortName }} 2 | username admin privilege 15 secret admin 3 | ! 4 | service routing protocols model multi-agent 5 | ! 6 | {{- if .Env.CLAB_MGMT_VRF }} 7 | vrf instance {{ .Env.CLAB_MGMT_VRF }} 8 | ! 9 | {{end}} 10 | {{ if .MgmtIPv4Gateway }}ip route {{ if .Env.CLAB_MGMT_VRF }}vrf {{ .Env.CLAB_MGMT_VRF }} {{end}}0.0.0.0/0 {{ .MgmtIPv4Gateway }}{{end}} 11 | {{ if .MgmtIPv6Gateway }}ipv6 route {{ if .Env.CLAB_MGMT_VRF }}vrf {{ .Env.CLAB_MGMT_VRF }} {{end}}::0/0 {{ .MgmtIPv6Gateway }}{{end}} 12 | ! 13 | interface {{ .MgmtIntf }} 14 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}} 15 | {{ if .MgmtIPv4Address }}ip address {{ .MgmtIPv4Address }}/{{.MgmtIPv4PrefixLength}}{{end}} 16 | {{ if .MgmtIPv6Address }}ipv6 address {{ .MgmtIPv6Address }}/{{.MgmtIPv6PrefixLength}}{{end}} 17 | ! 18 | management api gnmi 19 | transport grpc default 20 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}} 21 | ! 22 | management api netconf 23 | transport ssh default 24 | {{ if .Env.CLAB_MGMT_VRF }} vrf {{ .Env.CLAB_MGMT_VRF }}{{end}} 25 | ! 26 | management api http-commands 27 | no shutdown 28 | {{- if .Env.CLAB_MGMT_VRF }} 29 | ! 30 | vrf {{ .Env.CLAB_MGMT_VRF }} 31 | no shutdown 32 | {{end}} 33 | ! 34 | 35 | 36 | interface Ethernet1 37 | no switchport 38 | ip address 192.168.1.2/24 39 | ! 40 | interface Loopback0 41 | ip address 10.10.10.2/32 42 | ! 43 | ip routing 44 | ! 45 | router bgp 65001 46 | router-id 10.10.10.2 47 | neighbor 192.168.1.1 remote-as 65001 48 | network 10.10.10.2/32 49 | ! 50 | 51 | end -------------------------------------------------------------------------------- /15-startup/srl.cfg: -------------------------------------------------------------------------------- 1 | interface ethernet-1/1 { 2 | subinterface 0 { 3 | admin-state enable 4 | ipv4 { 5 | admin-state enable 6 | address 192.168.1.1/24 { 7 | } 8 | } 9 | } 10 | } 11 | interface lo0 { 12 | subinterface 0 { 13 | admin-state enable 14 | ipv4 { 15 | admin-state enable 16 | address 10.10.10.1/32 { 17 | } 18 | } 19 | } 20 | } 21 | network-instance default { 22 | interface ethernet-1/1.0 { 23 | } 24 | interface lo0.0 { 25 | } 26 | protocols { 27 | bgp { 28 | admin-state enable 29 | autonomous-system 65001 30 | router-id 10.10.10.1 31 | afi-safi ipv4-unicast { 32 | admin-state enable 33 | } 34 | group ibgp { 35 | export-policy [ export-lo ] 36 | afi-safi ipv4-unicast { 37 | admin-state enable 38 | } 39 | } 40 | neighbor 192.168.1.2 { 41 | admin-state enable 42 | peer-as 65001 43 | peer-group ibgp 44 | } 45 | } 46 | } 47 | } 48 | routing-policy { 49 | prefix-set loopback { 50 | prefix 10.10.10.1/32 mask-length-range exact { 51 | } 52 | } 53 | policy export-lo { 54 | statement 10 { 55 | match { 56 | prefix-set loopback 57 | } 58 | action { 59 | policy-result accept 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /15-startup/README.md: -------------------------------------------------------------------------------- 1 | # Startup configuration 2 | 3 | This exercise demonstrates how to provide startup configuration to the lab nodes by means of the [`startup-config`](https://containerlab.dev/manual/nodes/#startup-config) node parameter in the topology file. 4 | 5 | Startup configuration is a way to provide initial configuration to the lab nodes when they boot up. This is useful when you want to automate the configuration of the nodes and avoid manual intervention. It also brings your lab to a desired state when you need to test a specific scenario. 6 | 7 | To enter the lab directory, run the following command from anywhere in your terminal: 8 | 9 | ```bash 10 | [*]─[rd-13]─[~] 11 | └──> cd ~/clab-workshop/15-startup/ 12 | 13 | [*]─[rd-13]─[~/clab-workshop/15-startup] 14 | └──> 15 | ``` 16 | 17 | We start by deploying a lab defined in the `startup.clab.yml` topology file. The lab consists of two nodes: `srl` (Nokia SR Linux) and `ceos` (Arista cEOS). Both nodes are configured with a startup configuration file that resides in the same directory as the topology file. 18 | 19 | We will use the shortened syntax when deploying the lab; less typing and more fun! 20 | 21 | ```bash 22 | sudo clab dep -c 23 | ``` 24 | 25 | > Note, that when calling `clab dep -c` the containerlab will try to find the `*.clab.yml` file in the current working directory. If the file is located elsewhere, you can specify the path to the file as an argument to the `clab dep` command. 26 | > The `-c` flag stands for `--cleanup` and it will ensure that if the lab is already running, it will be stopped and removed before deploying a new one. 27 | 28 | The startup configuration files - [srl.cfg](srl.cfg) and [ceos.cfg](ceos.cfg) - configure the interfaces, IP addressing, loopbacks and BGP peering between SR Linux and cEOS nodes respectively. 29 | 30 | In particular, the `srl` node is configured to announce its loopback address `10.10.10.1/32` towards the `ceos` node and the `ceos` node is configured to announce its loopback address `10.10.10.2/32` towards the `srl` node. 31 | 32 | After the lab is deployed, we can expect that the nodes will boot up and apply the startup configuration snippets provided in the topology file. Consequently, it is fair to assume that the nodes will establish BGP peering and exchange routes. 33 | 34 | Let's connect to the `clab-startup-srl` node and check the BGP peering status: 35 | 36 | ```bash 37 | ssh clab-startup-srl 38 | ``` 39 | 40 | ``` 41 | --{ running }--[ ]-- 42 | A:srl# show network-instance default protocols bgp neighbor 192.168.1.2 43 | ``` 44 | 45 | You should see 1 route sent/received for the aforementioned BGP neighbor. 46 | 47 | Now, let's connect to the `clab-startup-ceos` node and make sure that it can reach the loopback address announced by the `srl` node. 48 | 49 | ```bash 50 | ssh clab-startup-ceos 51 | ``` 52 | 53 | When in the EOS shell, issue a ping towards the `srl` node's loopback address: 54 | 55 | ``` 56 | ping 10.10.10.1 57 | ``` 58 | 59 | You should see a successful ping response. 60 | 61 | You have successfully deployed the lab with the nodes equipped with the startup configuration. This is a powerful feature that can be used to provision the nodes with the desired configuration when they boot up. 62 | -------------------------------------------------------------------------------- /45-streaming-telemetry/README.md: -------------------------------------------------------------------------------- 1 | # Streaming Telemetry Lab 2 | 3 | > [!CAUTION] 4 | > Before proceeding, please destroy all other labs to free up the memory 5 | > `sudo clab des -c -a` - destroys all running labs and removes their respective lab dirs 6 | 7 | When pulling together what we have learned so far, we can build a lab that embodies a lot of what containerlab has to offer. One of the labs that we've built to demonstrate the power of containerlab is the [Streaming Telemetry Lab](https://github.com/srl-labs/srl-telemetry-lab). 8 | 9 | To deploy this lab we will use another neat containerlab feature - the ability to deploy a lab by specifying lab's remote URL. For the labs stored as a repo on GitHub we could even use the shorthand syntax: 10 | 11 | ```bash 12 | cd ~ 13 | sudo containerlab deploy -t srl-labs/srl-telemetry-lab 14 | ``` 15 | 16 | This will pull down the repository and deploy the lab right away. 17 | 18 | ## Exploring the topology file 19 | 20 | The streaming telemetry lab' [topology file](https://github.com/srl-labs/srl-telemetry-lab/blob/main/st.clab.yml) is worth a closer look. It features: 21 | 22 | - customization of the management network 23 | - use of `defaults` and `kinds` sections to simplify the topology file 24 | - static management IPs for consistency 25 | - combination of network OSes and "regular" containerized workloads like iperf clients, streaming telemetry and logging stack 26 | - use of the bind mounts to load the configuration files 27 | - use of env vars to parametrize the started containers 28 | - `exec` command to run commands in the started containers 29 | - port exposure to the host to make the lab services accessible from the outside 30 | - using of `group` parameter to influence lab nodes ordering in the graph products 31 | 32 | As you can see, this topo file is not a joke, and once the deployment finishes, you might want to understand what exactly was deployed and how the topology is structured. Enter graphs. 33 | 34 | ## Containerlab and graphing options 35 | 36 | When your topology has 3-5 nodes and a few links, you can easily visualize the topology in your head, but once your lab grows bigger, with more nodes involved and more links created, it becomes harder to remember what is what and where. 37 | 38 | To help you with visualizing the topology, containerlab provides a few graphing options () that we will explore briefly. 39 | 40 | ### Web graph 41 | 42 | After you deployed the lab, run the `graph` command: 43 | 44 | ``` 45 | sudo clab graph 46 | ``` 47 | 48 | The local web server provided by containerlab will be welcoming you at `http://d.srexperts.net:50080` where `` is your ID. The web server will render the deployed topology in an interactive graph that you can sort vertically or horizontally. 49 | 50 | The `group` options on the node level help you to order the lab nodes in the graph. 51 | 52 | ### Drawio export 53 | 54 | The web graph is great, but has a number of limitations: 55 | 56 | - Not editable 57 | - Opinionated 58 | - Only one ”pane” - physical 59 | 60 | To combat these limitations, another project has been created in the containerlab ecosystem - [clab-io-draw](https://github.com/srl-labs/clab-io-draw). 61 | 62 | It allows to generate a drawio topology from a containerlab topology and does so with style! 63 | 64 | ```bash 65 | sudo clab graph --drawio --drawio-args "--theme grafana_dark" 66 | ``` 67 | 68 | It has many neat options, so please go checkout the readme file at the projects' repo. 69 | 70 | ### Mermaid 71 | 72 | And last graphing option is the mermaid graph that can be very handy when embedding the mermaid graphs in your markdown docs. 73 | -------------------------------------------------------------------------------- /40-packet-capture/README.md: -------------------------------------------------------------------------------- 1 | # Packet capture 2 | 3 | Every lab emulation software must provide its users with the packet capturing abilities. Looking at the frames as they traverse the network links is not only educational, but also helps to troubleshoot the issues that might arise during the lab development. 4 | 5 | Containerlab offers a simple way to capture the packets from any interface of any node in the lab since every interface is exposed to the underlying Linux OS. This article will explain how to do that. 6 | 7 | Everything we are going to do in this exercise is explained in details in the [Containerlab documentation](https://containerlab.dev/manual/wireshark/). 8 | 9 | ## Remote capture 10 | 11 | The first way to capture the packets from a containerlab node running on a remote host that we are going to explore is called "remote capture". In this scenario a user has a network connectivity (ssh) to the host that runs containerlab topology and wishes to get the packet capture displayed in the Wireshark running locally. 12 | 13 | To achieve this, we will execute the `tcpdump` command on the remote host and pipe the output to the local Wireshark app. Here is a command that does it all for the host `d1` which is the instructors host. 14 | 15 | It captures the traffic from SR OS (`clab-vm-sros`) port `eth1` (`1/1/1`) running on `d1` host and displaying the capture in the Wireshark. 16 | 17 | The command is provided for WSL and Mac systems, assuming default Wireshark installation path 18 | 19 | Windows/WSL: 20 | 21 | ```bash 22 | ssh user@d1.srexperts.net \ 23 | "ip netns exec clab-vm-sros tcpdump -U -nni eth1 -w -" | \ 24 | /mnt/c/Program\ Files/Wireshark/wireshark.exe -k -i - 25 | ``` 26 | 27 | macOS: 28 | 29 | ``` 30 | ssh user@d1.srexperts.net \ 31 | "ip netns exec clab-vm-sros tcpdump -U -nni eth1 -w -" | \ 32 | /Applications/Wireshark.app/Contents/MacOS/Wireshark -k -i - 33 | ``` 34 | 35 | ## Edgeshark 36 | 37 | [Edgeshark](https://edgeshark.siemens.io/#/) is a set of tools that offer (among many things) a Web UI that displays every interface of every container and can start a wireshark as easy as clicking a button. 38 | 39 | Edgeshark installation consists of two parts: 40 | 41 | 1. A service that runs on the host that runs containerlab topologies 42 | 2. A wireshark capture plugin that runs next to the Wireshark on a user's PC 43 | 44 | To install the service, past the installer command that uses docker compose to deploy the service: 45 | 46 | ```bash 47 | curl -sL \ 48 | https://github.com/siemens/edgeshark/raw/main/deployments/wget/docker-compose.yaml | \ 49 | docker compose -f - up -d 50 | ``` 51 | 52 | Now, you have to install the client plugin based on the OS of your PC. 53 | 54 | ### Windows 55 | 56 | Windows users get to enjoy a simple installer-based workflow that installs the URL handler and the Wireshark plugin in one go. 57 | 58 | Download the installer file - 59 | 60 | Unzip the archive and launch the installer script. 61 | 62 | ### MacOs 63 | 64 | MacOs users have to suffer a little. But it is not that bad either. 65 | 66 | To install the URL handler paste the following in the Mac terminal app: 67 | 68 | ```bash 69 | mkdir -p /tmp/pflix-handler && cd /tmp/pflix-handler && \ 70 | rm -rf packetflix-handler.zip packetflix-handler.app __MACOSX && \ 71 | curl -sLO https://github.com/srl-labs/containerlab/files/14278951/packetflix-handler.zip && \ 72 | unzip packetflix-handler.zip && \ 73 | sudo mv packetflix-handler.app /Applications 74 | ``` 75 | 76 | To install the extpcap wireshark plugin execute in the Mac terminal: 77 | 78 | ```bash 79 | # for x86_64 MacOS use https://github.com/siemens/cshargextcap/releases/download/v0.10.7/cshargextcap_0.10.7_darwin_amd64.tar.gz 80 | DOWNLOAD_URL=https://github.com/siemens/cshargextcap/releases/download/v0.10.7/cshargextcap_0.10.7_darwin_arm64.tar.gz 81 | mkdir -p /tmp/pflix-handler && curl -sL $DOWNLOAD_URL | tar -xz -C /tmp/pflix-handler && \ 82 | open /tmp/pflix-handler && open /Applications/Wireshark.app/Contents/MacOS/extcap 83 | ``` 84 | 85 | The command above will open two Finder windows, one with the `cshargextcap` binary and the other with the Wireshark's existing plugins. Move the `cshargextcap` file over to the window with Wireshark plugins. 86 | 87 | ### Web UI 88 | 89 | To access the Edgeshark UI, open a browser and navigate to the following URL (substitute the hostname with your assigned VM): 90 | 91 | 92 | 93 | Note, the http schema is important, since https is not enabled. 94 | -------------------------------------------------------------------------------- /30-registry/README.md: -------------------------------------------------------------------------------- 1 | # Container registry and Containerlab 2 | 3 | Containerlab is better when used with a container registry. No one loved to witness the uncontrolled proliferation of unversioned disk image (qcow2, vmdk) files shared via ftps, one drives and IM attachments. 4 | 5 | We can do better! 6 | 7 | Since containerlab deals with container images, it is natural to use a container registry to store them. Versioned, immutable, tagged and easily shareable with granular access control. 8 | 9 | Whether you choose to use one of the public registries or a run a private one, the workflow is the same. Let's see what it looks like. 10 | 11 | ## Harbor registry 12 | 13 | In this workshop we make use of an open-source registry called [Harbor](https://goharbor.io/). It is a CNCF graduated project and is a great choice for a private registry. 14 | 15 | The registry has been already deployed in the workshop environment, but it is quite easy to deploy yourself in your own organization. It is a single docker compose stack that can be deployed in a few minutes. 16 | 17 | The Harbor registry offers a neat Web UI to browse the registry contents, manage users and tune access control. You can log in to the registry UI like this: 18 | 19 | 20 | 21 | using the `admin` user and the password available in your workshop handout. 22 | 23 | When logged in as `admin` you can created users, repositories, browse the registry contents and many more. Managing the harbor registry is out of the scope of this workshop. 24 | 25 | ## Pushing images to the registry 26 | 27 | We will push one of the images that we've built in the previous section to the registry effectively saving it and making it available and reusable to other users who have access to this registry. 28 | 29 | ### 1 Logging in to the registry 30 | 31 | To be able to push and pull the images from the workshop's registry, you need to login to the registry. 32 | 33 | ```bash 34 | # username: admin 35 | # password: as per your workshop handout 36 | docker login registry-d16.srexperts.net 37 | ``` 38 | 39 | ### 2 Listing local images 40 | 41 | First, we need to identify the name of the image that we want to push to the registry. By listing the images in the local image store we can reliably identify the name of the image that we want to push. 42 | 43 | ``` 44 | docker images 45 | ``` 46 | 47 | On your system you will see a list of images, among which you will see: 48 | 49 | ``` 50 | REPOSITORY TAG IMAGE ID CREATED SIZE 51 | vrnetlab/nokia_sros 24.7.R1 d45128fc2914 2 hours ago 889MB 52 | ``` 53 | 54 | This is the image that we built before and that we want to push to the registry so that next time we want to use it we won't have to build it again. 55 | 56 | The image name consists of two parts: 57 | 58 | - `vrnetlab/nokia_sros` - the repository name 59 | - `24.7.R1` - the tag 60 | 61 | Catenating these two parts together we get the full name of the image that we want to push to the registry. 62 | 63 | ### 3 Pushing the image to the registry 64 | 65 | Now that we know the name of the image that we want to push to the registry, we can push it. Usually you will see a sequence of `docker tag` and `docker push` commands being executed, but we are cool kids here so we will do it in one go. 66 | 67 | Using the skopeo tool - - we can push the image to the registry in one go. The command to use has the following format: 68 | 69 | ``` 70 | skopeo copy docker-deamon:// docker:///: 71 | ``` 72 | 73 | Since everyone would want to push their own image to the registry we will need to append a user id to the tag name so that you won't overwrite each other's images. Like the below command pushes the image to the user with ID=1: 74 | 75 | ```bash 76 | # note the appended -1 at the end of the tag 77 | skopeo copy \ 78 | docker-daemon:vrnetlab/nokia_sros:24.7.R1 \ 79 | docker://registry-d16.srexperts.net/library/nokia_sros:24.7.R1-1 80 | ``` 81 | 82 | ## Listing images from the registry 83 | 84 | Once the image is copied, you can see it in the registry UI. 85 | 86 | ![pic](https://gitlab.com/rdodin/pics/-/wikis/uploads/3f3d08696dd6bb83cf6e223a5f8f6c39/image.png) 87 | 88 | If you want to get the list of available repositories/tags in the registry, you can use registry API and skopeo. 89 | 90 | Listing available repositories: 91 | 92 | ```bash 93 | curl -s -u 'admin:d16ClabW$' https://registry-d16.srexperts.net/v2/_catalog | jq 94 | { 95 | "repositories": [ 96 | "admin/nokia_sros", 97 | "library/nokia_sros" 98 | ] 99 | } 100 | ``` 101 | 102 | Listing available tags for a given repository: 103 | 104 | ```bash 105 | skopeo list-tags docker://registry-d16.srexperts.net/library/nokia_sros 106 | { 107 | "Repository": "registry-d16.srexperts.net/library/nokia_sros", 108 | "Tags": [ 109 | "24.7.R1-1" 110 | ] 111 | } 112 | ``` 113 | 114 | ## Using images from the registry 115 | 116 | The whole point of pushing the image to the registry is to be able to use it in the future yourself and also to share it with others. And now that we have the image in the registry, we can modify the `20-vm.clab.yml` file to make use of it: 117 | 118 | ```diff 119 | name: vm 120 | topology: 121 | nodes: 122 | sros: 123 | kind: nokia_sros 124 | - image: vrnetlab/nokia_sros:24.7.R1 125 | + image: registry-d16.srexperts.net/library/nokia_sros:24.7.R1-1 126 | license: ~/images/sros-24.lic 127 | 128 | c8000v: 129 | kind: cisco_c8000v 130 | image: vrnetlab/cisco_c8000v:17.11.01a 131 | 132 | links: 133 | - endpoints: [sros:eth1, c8000v:eth1] 134 | ``` 135 | 136 | Not only this gives us an easy way to share images with others, but also it enables stronger reproducibility of the lab, as the users of our lab would use exactly the same image that we built. 137 | -------------------------------------------------------------------------------- /10-basics/README.md: -------------------------------------------------------------------------------- 1 | # Containerlab Basics 2 | 3 | This workshop section introduces you to containerlab basics - topology file, image management workflows and lab lifecycle. It is loosely based on the official [Containerlab quickstart](https://containerlab.dev/quickstart/). 4 | 5 | ## Repository 6 | 7 | Clone the repository to your workshop VM at DENOG16 tag: 8 | 9 | ```bash 10 | cd ~ 11 | git clone https://github.com/srl-labs/clab-workshop.git -b denog16 12 | cd clab-workshop/10-basics 13 | ``` 14 | 15 | The repo should be cloned and you should be in the `ac1-workshop` directory as per the output below: 16 | 17 | ``` 18 | [*]─[rd-13]─[~/clab-workshop/10-basics] 19 | └──> 20 | ``` 21 | 22 | ## Topology 23 | 24 | The topology file `basic.clab.yml` defines the lab we are going to use in this basics exercise. It consists of the two nodes: 25 | 26 | * Nokia SR Linux 27 | * Arista cEOS 28 | 29 | The nodes are interconnected with a single link over their respective first Ethernet interfaces. 30 | 31 | ```yaml 32 | name: basic 33 | topology: 34 | nodes: 35 | srl: 36 | kind: nokia_srlinux 37 | image: ghcr.io/nokia/srlinux 38 | ceos: 39 | kind: arista_ceos 40 | image: ceos:4.32.0F 41 | 42 | links: 43 | - endpoints: [srl:e1-1, ceos:eth1] 44 | ``` 45 | 46 | ## Deployment attempt #1 47 | 48 | Try to deploy the lab: 49 | 50 | ```bash 51 | sudo containerlab deploy -t basic.clab.yml 52 | ``` 53 | 54 | Deployment fails, why? 55 | 56 | ## Image management 57 | 58 | Check what images are available on the system: 59 | 60 | ```bash 61 | docker images 62 | ``` 63 | 64 | Pull SR Linux container image (if it has not been pulled during attempt #1): 65 | 66 | ```bash 67 | docker pull ghcr.io/nokia/srlinux 68 | ``` 69 | 70 | Import cEOS image and pay attention to the 2nd argument for the `docker import` command where you have to specify the image: 71 | 72 | ```bash 73 | docker import ~/images/cEOS64-lab-4.32.0F.tar.xz ceos:4.32.0F 74 | ``` 75 | 76 | Check the local image store again: 77 | 78 | ```bash 79 | docker images 80 | ``` 81 | 82 | ## Deployment attempt #2 83 | 84 | Now that the images are available, try to deploy the lab again: 85 | 86 | ```bash 87 | sudo containerlab deploy -t basic.clab.yml 88 | ``` 89 | 90 | Note, you can use a shortcut version of the same command - `sudo clab dep -t basic.clab.yml`. 91 | 92 | The deployment should succeed. 93 | 94 | ## Connecting to the nodes 95 | 96 | Connect to the Nokia SR Linux node using the container name: 97 | 98 | ```bash 99 | ssh clab-basic-srl 100 | ``` 101 | 102 | Connect to the cEOS node using its IP address (note, the IP might be different in your lab): 103 | 104 | ```bash 105 | ssh admin@172.20.20.3 106 | ``` 107 | 108 | ## Containerlab hosts automation 109 | 110 | Containerlab creates `/etc/hosts` entries for each deployed lab so that you can access the nodes using their names. Check the entries: 111 | 112 | ```bash 113 | cat /etc/hosts 114 | ``` 115 | 116 | ## Containerlab ssh config automation 117 | 118 | Containerlab creates ssh config entries in `/etc/ssh/ssh_config.d/clab-.conf` file to provide easy access to the nodes. Check the entries: 119 | 120 | ```bash 121 | cat /etc/ssh/ssh_config.d/clab-basic.conf 122 | ``` 123 | 124 | ## Checking network connectivity 125 | 126 | SR Linux and cEOS are started with their first Ethernet interfaces connected. Check the connectivity between the nodes: 127 | 128 | The nodes also come up with LLDP enabled, our goal is to verify that the basic network connectivity is working by inspecting 129 | 130 | ```bash 131 | ssh clab-basic-srl 132 | ``` 133 | 134 | and checking the LLDP neighbors on ethernet-1/1 interface 135 | 136 | ``` 137 | show /system lldp neighbor interface ethernet-1/1 138 | ``` 139 | 140 | The expected output should be: 141 | 142 | ``` 143 | --{ running }--[ ]-- 144 | A:srl# show /system lldp neighbor interface ethernet-1/1 145 | +----------+----------+---------+---------+---------+---------+---------+ 146 | | Name | Neighbor | Neighbo | Neighbo | Neighbo | Neighbo | Neighbo | 147 | | | | r | r | r First | r Last | r Port | 148 | | | | System | Chassis | Message | Update | | 149 | | | | Name | ID | | | | 150 | +==========+==========+=========+=========+=========+=========+=========+ 151 | | ethernet | 00:1C:73 | ceos | 00:1C:7 | 20 | 16 | Etherne | 152 | | -1/1 | :46:95:5 | | 3:46:95 | hours | seconds | t1 | 153 | | | C | | :5C | ago | ago | | 154 | +----------+----------+---------+---------+---------+---------+---------+ 155 | ``` 156 | 157 | ## Listing running labs 158 | 159 | When you are in the directory that contains the lab file, you can list the nodes of that lab simply by running: 160 | 161 | ```bash 162 | [*]─[rd-13]─[~/clab-workshop/10-basics] 163 | └──> sudo containerlab inspect 164 | INFO[0000] Parsing & checking topology file: basic.clab.yml 165 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 166 | | # | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address | 167 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 168 | | 1 | clab-basic-ceos | c279d892ea22 | ceos:4.32.0F | arista_ceos | running | 172.20.20.2/24 | 2001:172:20:20::2/64 | 169 | | 2 | clab-basic-srl | 7c46eb454f51 | ghcr.io/nokia/srlinux | nokia_srlinux | running | 172.20.20.3/24 | 2001:172:20:20::3/64 | 170 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 171 | ``` 172 | 173 | If the topology file is located in a different directory, you can specify the path to the topology file: 174 | 175 | ```bash 176 | [*]─[rd-13]─[/tmp] 177 | └──> sudo containerlab inspect -t ~/clab-workshop/10-basics/ 178 | INFO[0000] Parsing & checking topology file: basic.clab.yml 179 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 180 | | # | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address | 181 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 182 | | 1 | clab-basic-ceos | c279d892ea22 | ceos:4.32.0F | arista_ceos | running | 172.20.20.2/24 | 2001:172:20:20::2/64 | 183 | | 2 | clab-basic-srl | 7c46eb454f51 | ghcr.io/nokia/srlinux | nokia_srlinux | running | 172.20.20.3/24 | 2001:172:20:20::3/64 | 184 | +---+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 185 | ``` 186 | 187 | You can also list all running labs regardless of where their topology files are located: 188 | 189 | ```bash 190 | [*]─[rd-13]─[~/clab-workshop/10-basics] 191 | └──> sudo containerlab inspect --all 192 | +---+----------------+----------+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 193 | | # | Topo Path | Lab Name | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address | 194 | +---+----------------+----------+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 195 | | 1 | basic.clab.yml | basic | clab-basic-ceos | c279d892ea22 | ceos:4.32.0F | arista_ceos | running | 172.20.20.2/24 | 2001:172:20:20::2/64 | 196 | | 2 | | | clab-basic-srl | 7c46eb454f51 | ghcr.io/nokia/srlinux | nokia_srlinux | running | 172.20.20.3/24 | 2001:172:20:20::3/64 | 197 | +---+----------------+----------+-----------------+--------------+-----------------------+---------------+---------+----------------+----------------------+ 198 | ``` 199 | 200 | The output will contain all labs and their nodes. 201 | 202 | Shortcuts: 203 | 204 | * `sudo clab ins` == `sudo containerlab inspect` 205 | * `sudo clab ins -a` == `sudo containerlab inspect --all` 206 | 207 | ## Lab directory 208 | 209 | Lab directory stores the artifacts generated by containerlab that are related to the lab: 210 | 211 | * tls certificates 212 | * startup configurations 213 | * inventory files 214 | * topology export json file 215 | * bind mounted directories 216 | 217 | To list the contents of the lab directory, run: 218 | 219 | ``` 220 | [*]─[rd-13]─[~/clab-workshop/10-basics] 221 | └──> tree -L 3 clab-basic/ 222 | ``` 223 | 224 | ## Destroying the lab 225 | 226 | When you are done with the lab, you can destroy it. Containerlab can try and find the `*.clab.yml` file in the current directory and use it so that you don't have to type it out. 227 | Try it: 228 | 229 | ```bash 230 | sudo clab des --cleanup 231 | ``` 232 | 233 | Alternatively, you could specify the topology file explicitly: 234 | 235 | ```bash 236 | sudo clab des -t basic.clab.yml --cleanup 237 | ``` 238 | 239 | The `--cleanup` flag ensures that the lab directory gets removed as well. 240 | 241 | You finished the basics lab exercise! 242 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /20-vm/README.md: -------------------------------------------------------------------------------- 1 | # VM-based nodes in containerlab 2 | 3 | VM nodes integration in containerlab is based on the [hellt/vrnetlab](https://github.com/hellt/vrnetlab) project which is a **fork** of `vrnetlab/vrnetlab` where things were added to make it work with the container networking. 4 | 5 | Start with cloning the project: 6 | 7 | ```bash 8 | cd ~ 9 | git clone https://github.com/hellt/vrnetlab.git 10 | cd ~/vrnetlab 11 | ``` 12 | 13 | ## Building Cisco Catalyst 8000v image 14 | 15 | Cisco c8000v qcow image is located at `~/images/c8000v-universalk9_16G_serial.17.11.01a.qcow2` and should be copied to the `~/vrnetlab/c8000v/` directory before building the container image. 16 | 17 | ```bash 18 | cp ~/images/c8000v-universalk9_16G_serial.17.11.01a.qcow2 ~/vrnetlab/c8000v/ 19 | ``` 20 | 21 | Once copied, we can enter in the `~/vrnetlab/c8000v` image and build the container image: 22 | 23 | ```bash 24 | cd ~/vrnetlab/c8000v 25 | make 26 | ``` 27 | 28 | Note, that c8000v image will run the VM during the container build time. This is to unpack the image once at build time, instead of doing it every time a container is started. That is why the build time is longer than for SR OS image. 29 | 30 | While it is building the image, open another terminal window and proceed with building the SR OS image 31 | 32 | The resulting image will be tagged as `vrnetlab/cisco_c8000v:17.11.01a`. 33 | 34 | ## Building Nokia SR OS image 35 | 36 | SR OS qcow image is located at `~/images/sros-vm-24.3.R1.qcow2` and should be copied to the `~/vrnetlab/sros/` directory before building the container image. 37 | 38 | ```bash 39 | cp ~/images/sros-vm-24.7.R1.qcow2 ~/vrnetlab/sros/ 40 | ``` 41 | 42 | Once copied, we can enter in the `~/vrnetlab/sros` image and build the container image: 43 | 44 | ```bash 45 | cd ~/vrnetlab/sros 46 | make 47 | ``` 48 | 49 | The image will be built and tagged as `vrnetlab/nokia_sros:24.7.R1`. The tag is auto-derived from the file name. 50 | 51 | ## Deploying the VM-based nodes lab 52 | 53 | With the images built, we can proceed with the lab deployment. First, let's switch back to the lab directory: 54 | 55 | ```bash 56 | cd ~/clab-workshop/20-vm 57 | ``` 58 | 59 | Now lets deploy the lab: 60 | 61 | ```bash 62 | sudo clab dep -c 63 | ``` 64 | 65 | ### Monitoring the boot process 66 | 67 | You will notice that the lab deployment log will show the following message and the deployment process will appear stuck: 68 | 69 | ``` 70 | Waiting for clab-vm-sros to be ready. This may take a while. Monitor boot log with `sudo docker logs -f clab-vm-sros` 71 | ``` 72 | 73 | This is because containerlab waits for SR OS node to boot and become ready for containerlab to inject SSH keys to enabled passwordless SSH access. To monitor the boot process, you can open a new terminal and run the following command: 74 | 75 | ```bash 76 | docker logs -f clab-vm-sros 77 | ``` 78 | 79 | > the SR OS boot time is approx 3 minutes. 80 | 81 | You will see the boot process of the SR OS node as it would have been seen in a terminal connected to the real hardware console. 82 | 83 | The same `docker logs` command can be used for the `clab-vm-c8000v` node to monitor the boot log of the Cisco Catalyst 8000v node. 84 | 85 | > The c8000v boot time is approx 3 minutes. 86 | 87 | ## Connecting to the nodes 88 | 89 | To connect to SR OS node: 90 | 91 | ``` 92 | ssh clab-vm-sros 93 | ``` 94 | 95 | No user/password is needed, since username is injected by containerlab as well as the local public key for passwordless SSH access. 96 | 97 | To connect to the c8000v node use `admin:admin` credentials: 98 | 99 | ```bash 100 | ssh clab-vm-c8000v 101 | ``` 102 | 103 | ## Configuring the nodes 104 | 105 | ### SR OS 106 | 107 | If not logged in yet, open a new terminal and connect to the SR OS node: 108 | 109 | ``` 110 | ssh clab-vm-sros 111 | ``` 112 | 113 | While logged in in the SR OS CLI paste the following snippet to configure SR OS: 114 | 115 | ``` 116 | edit-config private 117 | /configure port 1/1/c1 admin-state enable 118 | /configure port 1/1/c1 connector breakout c1-100g 119 | /configure port 1/1/c1/1 admin-state enable 120 | /configure port 1/1/c1/1 description "port 1/1/c1/1" 121 | /configure port 1/1/c1/1 ethernet mode hybrid 122 | /configure port 1/1/c1/1 { ethernet lldp } 123 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge notification true 124 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge port-id-subtype tx-if-name 125 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge receive true 126 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge transmit true 127 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-tlvs port-desc true 128 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-tlvs sys-name true 129 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-tlvs sys-desc true 130 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-tlvs sys-cap true 131 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-mgmt-address oob admin-state enable 132 | /configure port 1/1/c1/1 ethernet lldp dest-mac nearest-bridge tx-mgmt-address system admin-state enable 133 | 134 | /configure router "Base" interface "toC8kv" { admin-state enable } 135 | /configure router "Base" interface "toC8kv" { port 1/1/c1/1:0 } 136 | /configure router "Base" interface "toC8kv" { ipv4 primary address 192.168.1.2 } 137 | /configure router "Base" interface "toC8kv" { ipv4 primary prefix-length 24 } 138 | commit 139 | exit all 140 | ``` 141 | 142 | ### Cisco Catalyst 8000v 143 | 144 | If not logged in yet, open a new terminal and connect to the SR OS node: 145 | 146 | ```bash 147 | # password admin 148 | ssh clab-vm-c8000v 149 | ``` 150 | 151 | And paste the following configuration: 152 | 153 | ``` 154 | conf t 155 | lldp run 156 | interface GigabitEthernet2 157 | ip address 192.168.1.1 255.255.255.0 158 | lldp receive 159 | lldp transmit 160 | no shutdown 161 | ``` 162 | 163 | Now we configured the two systems to be able to communicate with each other and enabled LLDP on both sides. Perform a ping from SR OS towards the c8000v node and let it run: 164 | 165 | ### Verify the connectivity 166 | 167 | While in SR OS CLI, let's check a few things. First, let's see if LLDP is working and we detect the c8000v node: 168 | 169 | ``` 170 | (pr)[/] 171 | A:admin@sros# / show port "1/1/c1/1" ethernet lldp remote-info 172 | 173 | ============================================================================== 174 | Link Layer Discovery Protocol (LLDP) Port Information 175 | ============================================================================== 176 | Port 1/1/c1/1 Bridge nearest-bridge Remote Peer Information 177 | ------------------------------------------------------------------------------- 178 | Remote Peer Index 1 at timestamp 11/07/2024 13:36:07: 179 | Supported Caps : bridge router 180 | Enabled Caps : router 181 | Chassis Id Subtype : 4 (macAddress) 182 | Chassis Id : 00:1E:BD:D7:38:00 183 | PortId Subtype : 5 (interfaceName) 184 | Port Id : 47:69:32 185 | "Gi2" 186 | Port Description : GigabitEthernet2 187 | System Name : c8000v.example.com 188 | System Description : Cisco IOS Software [Dublin], Virtual XE Software 189 | (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 17.11.1a, 190 | RELEASE SOFTWARE (fc3) 191 | Technical Support: http://www.cisco.com/techsupport 192 | Copyright (c) 1986-2023 by Cisco Systems, Inc. 193 | Compiled Wed 05-Apr-23 06:54 by 194 | Age : 213 seconds 195 | 196 | 197 | Port 1/1/c1/1 Bridge nearest-non-tpmr Remote Peer Information 198 | ------------------------------------------------------------------------------- 199 | No remote peers found 200 | 201 | Port 1/1/c1/1 Bridge nearest-customer Remote Peer Information 202 | ------------------------------------------------------------------------------- 203 | No remote peers found 204 | 205 | ============================================================================== 206 | ``` 207 | 208 | Great, the neighboring router is detected, which means that L2 protocols such as LLDP are working fine. 209 | 210 | Next, check the configuration status of the interface towards the c8000v node: 211 | 212 | ``` 213 | (pr)[/] 214 | A:admin@sros# / show router "Base" interface "toC8kv" 215 | 216 | =============================================================================== 217 | Interface Table (Router: Base) 218 | =============================================================================== 219 | Interface-Name Adm Opr(v4/v6) Mode Port/SapId 220 | IP-Address PfxState 221 | ------------------------------------------------------------------------------- 222 | toC8kv Up Up/Down Network 1/1/c1/1:0 223 | 192.168.1.2/24 n/a 224 | ------------------------------------------------------------------------------- 225 | Interfaces : 1 226 | =============================================================================== 227 | ``` 228 | 229 | The interface is up and the remote IP address is 192.168.1.1, let's start the ping it to verify the datapath and make it run for a while with thousands of probes requested: 230 | 231 | ``` 232 | [/] 233 | A:admin@sros# ping 192.168.1.1 count 2000 234 | PING 192.168.1.1 56 data bytes 235 | 64 bytes from 192.168.1.1: icmp_seq=1 ttl=255 time=50.4ms. 236 | 64 bytes from 192.168.1.1: icmp_seq=2 ttl=255 time=1.57ms. 237 | ``` 238 | 239 | Pings are flowing, neat. Let them run in this terminal window, we will need them later. 240 | 241 | ## Exploring the VM networking setup 242 | 243 | In a new terminal window open c8000v node's container shell: 244 | 245 | ```bash 246 | docker exec -it clab-vm-c8000v bash 247 | ``` 248 | 249 | Explore the Linux link interfaces available in the container: 250 | 251 | ```bash 252 | ip link 253 | ``` 254 | 255 | the `tap1` interface corresponds to the VM's interfaces and it is transparently "stitched" (with `tc mirred` rules) 256 | 257 | You can sniff the traffic on both `eth1` and `tap1` interface, and see that they carry the same traffic, as they are merely two ends of the same virtual link. 258 | 259 | ```bash 260 | tcpdump -nni tap1 261 | ``` 262 | 263 | The management interface doesn't use the `tapX` interface, but rather leverage the qemu user mode networking, where qemu is instructed to forward connections made to certain ports on the localhost to a special qemu-managed interface that represents the VM's management interface. 264 | 265 | You can see those host forward rules created by vrnetlab, when you list the qemu process: 266 | 267 | ```bash 268 | root@c8000v:/# ps auxw | grep qemu 269 | root 13 99.9 25.8 4667132 4231652 pts/0 Sl+ 14:11 126:16 qemu-system-x86_64 -enable-kvm -display none -machine pc -monitor tcp:0.0.0.0:4000,server,nowait -serial telnet:0.0.0.0:5000,server,nowait -m 4096 -cpu host -smp 1 -drive if=ide,file=/c8000v-universalk9_16G_serial.17.11.01a-overlay-overlay-overlay.qcow2 -device pci-bridge,chassis_nr=1,id=pci.1 -device virtio-net-pci,netdev=p00,mac=0C:00:ed:ba:55:00 -netdev user,id=p00,net=10.0.0.0/24,tftp=/tftpboot,hostfwd=tcp:0.0.0.0:22-10.0.0.15:22,hostfwd=udp:0.0.0.0:161-10.0.0.15:161,hostfwd=tcp:0.0.0.0:830-10.0.0.15:830,hostfwd=tcp:0.0.0.0:80-10.0.0.15:80,hostfwd=tcp:0.0.0.0:443-10.0.0.15:443,hostfwd=tcp:0.0.0.0:9339-10.0.0.15:9339,hostfwd=tcp:0.0.0.0:57400-10.0.0.15:57400,hostfwd=tcp:0.0.0.0:6030-10.0.0.15:6030,hostfwd=tcp:0.0.0.0:32767-10.0.0.15:32767,hostfwd=tcp:0.0.0.0:8080-10.0.0.15:8080 -device virtio-net-pci,netdev=p01,mac=0C:00:7e:5c:84:01,bus=pci.1,addr=0x2 -netdev tap,id=p01,ifname=tap1,script=/etc/tc-tap-ifup,downscript=no 270 | root 1622 0.0 0.0 3324 1596 pts/1 S+ 16:17 0:00 grep qemu 271 | ``` 272 | 273 | Look for `hostfwd` options in the qemu command line. Those are the port forwarding rules that qemu uses to forward the connections to the VM's management interface. For example, as per the output above, the `hostfwd=tcp:0.0.0.0:22-10.0.0.15:22` rule forwards connections made to the localhost:22 to the VM's interface 10.0.0.15:22. 274 | --------------------------------------------------------------------------------