Skip to content

Commit

Permalink
Add support for Cisco Catalyst 9000v kind. (#2133)
Browse files Browse the repository at this point in the history
* Add support for Cisco Catalyst 9000v kind.

* Add cat9kv relevant information to schema

* Add initial Cat9kv documentation.

* added parametrized docs

* added macros and glightbox plugin to public mkdocs container

* Add interface aliasing feature.

* Update documentation to reflect interface aliases.

* Remove asic tagged image in example configuration.

* keep a single kind definition

* Minor fixes and additions re: interfaces.

---------

Co-authored-by: Roman Dodin <dodin.roman@gmail.com>
  • Loading branch information
kaelemc and hellt committed Jul 9, 2024
1 parent 9f47e27 commit 17758ab
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ site:
serve-docs-full:
ifeq ($(PUBLIC),yes)
@{ \
sed -i 's/^ - typeset/#- typeset/g; s/^ - glightbox/#- glightbox/g' mkdocs.yml; \
sed -i 's/^ - typeset/#- typeset/g' mkdocs.yml; \
}
@docker run -it --rm -p 8001:8000 -v $(CURDIR):/docs squidfunk/mkdocs-material:$(MKDOCS_VER)
@docker run -it --rm -p 8001:8000 -v $(CURDIR):/docs --entrypoint "" squidfunk/mkdocs-material:$(MKDOCS_VER) ash -c "pip install mkdocs-macros-plugin==0.7.0 mkdocs-glightbox==0.4.0 && mkdocs serve -a 0.0.0.0:8000"
else
@docker run -it --rm -p 8001:8000 -v $(CURDIR):/docs ghcr.io/srl-labs/mkdocs-material-insiders:$(MKDOCS_INS_VER)
endif
Expand Down
2 changes: 2 additions & 0 deletions clab/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
srl "github.com/srl-labs/containerlab/nodes/srl"
vr_aoscx "github.com/srl-labs/containerlab/nodes/vr_aoscx"
vr_c8000v "github.com/srl-labs/containerlab/nodes/vr_c8000v"
vr_cat9kv "github.com/srl-labs/containerlab/nodes/vr_cat9kv"
vr_csr "github.com/srl-labs/containerlab/nodes/vr_csr"
vr_freebsd "github.com/srl-labs/containerlab/nodes/vr_freebsd"
vr_ftdv "github.com/srl-labs/containerlab/nodes/vr_ftdv"
Expand Down Expand Up @@ -86,6 +87,7 @@ func (c *CLab) RegisterNodes() {
vr_xrv.Register(c.Reg)
vr_xrv9k.Register(c.Reg)
vr_sonic.Register(c.Reg)
vr_cat9kv.Register(c.Reg)
xrd.Register(c.Reg)
rare.Register(c.Reg)
c8000.Register(c.Reg)
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ In addition to native containerized NOSes, containerlab can launch traditional v
* [Juniper vJunos-switch](manual/kinds/vr-vjunosswitch.md)
* [Juniper vJunos Evolved](manual/kinds/vr-vjunosevolved.md)
* [Cisco IOS XRv9k](manual/kinds/vr-xrv9k.md)
* [Cisco Catalyst 9000v](manual/kinds/vr-cat9kv.md)
* [Cisco Nexus 9000v](manual/kinds/vr-n9kv.md)
* [Cisco c8000v](manual/kinds/vr-c8000v.md)
* [Cisco CSR 1000v](manual/kinds/vr-csr.md)
Expand Down
1 change: 1 addition & 0 deletions docs/manual/kinds/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Within each predefined kind, we store the necessary information that is used to
| **Cisco CSR1000v** | [`vr-csr/vr-cisco_csr1000v`](vr-csr.md) | supported | VM |
| **Cisco Nexus 9000v** | [`vr-n9kv/vr-cisco_n9kv`](vr-n9kv.md) | supported | VM |
| **Cisco 8000** | [`c8000/cisco_c8000`](c8000.md) | supported | VM+ |
| **Cisco Catalyst 9000v** | [`cat9kv/vr-cisco_cat9kv`](vr-cat9kv.md) | supported | VM |
| **Cisco FTDv** | [`cisco_ftdv`](vr-ftdv.md) | supported | VM |
| **Cumulus VX** | [`cvx/cumulus_cvx`](cvx.md) | supported | container |
| **Aruba ArubaOS-CX** | [`vr-aoscx/vr-aruba_aoscx`](vr-aoscx.md) | supported | VM |
Expand Down
147 changes: 147 additions & 0 deletions docs/manual/kinds/vr-cat9kv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
---
search:
boost: 4
kind_code_name: cisco_cat9kv
kind_display_name: Cisco Catalyst 9000v
kind_short_display_name: Cat9kv
---
# Cisco Catalyst 9000v

The [[[ kind_display_name ]]] (or [[[ kind_short_display_name ]]] for short) is a virtualised form of the Cisco Catalyst 9000 series switches. It is identified with `[[[ kind_code_name ]]]` kind in the [topology file](../topo-def-file.md). It is built using [vrnetlab](../vrnetlab.md) project and essentially is a Qemu VM packaged in a docker container format.

The [[[ kind_display_name ]]] performs simulation of the dataplane ASICs that are present in the physical hardware. The two simulated ASICs are:

- Cisco UADP (Unified Access Data-Plane). This is the default ASIC that's simulated.
- Silicon One Q200 (referred to as Q200).

/// note
The Q200 simulation has a limited featureset compared to the UADP simulation.
///

## Resource requirements

| | UADP | Q200 |
| --------- | ----- | ----- |
| vCPU | 4 | 4 |
| RAM (MB) | 18432 | 12288 |
| Disk (GB) | 4 | 4 |

## Managing [[[ kind_display_name ]]] nodes

You can manage the [[[ kind_display_name ]]] with containerlab via the following interfaces:

/// tab | bash
to connect to a `bash` shell of a running Cisco CSR1000v container:

```bash
docker exec -it <container-name/id> bash
```

///
/// tab | CLI
to connect to the Catalyst 9000v CLI

```bash
ssh admin@<container-name/id>
```

///
/// tab | NETCONF
NETCONF server is running over port 830

```bash
ssh admin@<container-name> -p 830 -s netconf
```

///
/// note
Default credentials: `admin:admin`
///

## Interface naming convention

You can use [interfaces names](../topo-def-file.md#interface-naming) in the topology file like they appear in the [[[ kind_display_name ]]] CLI.

The interface naming convention is: `GigabitEthernet1/0/X` (or `Gi1/0/X`), where `X` is the port number.

With that naming convention in mind:

* `Gi1/0/1` - first data port available
* `Gi1/0/2` - second data port, and so on...

The example ports above would be mapped to the following Linux interfaces inside the container running the [[[ kind_display_name ]]] VM:

- `eth0` - management interface connected to the containerlab management network.
- `eth1` - First data-plane interface. Mapped to `GigabitEthernet1/0/1` interface.
- `eth2` - Second data-plane interface. Mapped to `GigabitEthernet1/0/2` interface and so on.

/// note
Data interfaces may take 5+ minutes to function correctly after the node boots.
///

You must define interfaces in a contigous manner in your toplogy file. For example, if you want to use `Gi1/0/4` you must define `Gi1/0/1`, `Gi1/0/2` and `Gi1/0/3`. See the example below.

```yaml
name: my-cat9kv-lab
topology:
nodes:
cat9kv1:
kind: cisco_cat9kv
image: vrnetlab/vr-cat9kv:17.12.01p
cat9kv2:
kind: cisco_cat9kv
image: vrnetlab/vr-cat9kv:17.12.01p

links:
- endpoints: ["cat9kv1:Gi1/0/1","cat9kv2:GigabitEthernet1/0/1"]
- endpoints: ["cat9kv1:Gi1/0/2","cat9kv2:GigabitEthernet1/0/2"]
- endpoints: ["cat9kv1:Gi1/0/3", "cat9kv2:GigabitEthernet1/0/3"]
- endpoints: ["cat9kv1:Gi1/0/4", "cat9kv2:GigabitEthernet1/0/4"]
```
/// warning
Regardless of how many links are defined in your containerlab topology, the Catalyst 9000v will always display 8 data-plane interfaces. Links/interfaces that you did not define in your containerlab topology will *not* pass any traffic.
///
## Features and options
### ASIC data-plane simulation configuration
The default ASIC simulation of the node will be UADP. To enable the Q200 simulation or to enable specific features for the UADP simulation, you must provide a `vswitch.xml` file (with the relevant configuration).

You can do this when building the image with [vrnetlab](../vrnetlab.md), Please refer to the README file in vrnetlab/cat9kv for more information.

You can also use supply the vswitch.xml file via `binds` in the containerlab topology file. Refer to the example below.

```yaml
name: my-cat9kv-lab
topology:
nodes:
node1:
kind: cisco_cat9kv
image: vrnetlab/vr-cat9kv:17.12.01p
binds:
- /path/to/vswitch.xml:/vswitch.xml
```

/// note
You can obtain a `vswitch.xml` file from the relevant Cisco CML node definitions.
///

### Environment variables

There are `VCPU` and `RAM` environment variables defined. It is not recommended reduce the resources below the required amount. The node will be unable to boot in this case.

The example below assigns 6vCPUs and 20 gigabytes of RAM to the node.

```yaml
name: my-cat9kv-lab
topology:
nodes:
node1:
kind: cisco_cat9kv
image: vrnetlab/vr-cat9kv:17.12.01p
env:
VCPU: 6
RAM: 20480
```
3 changes: 2 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ nav:
- Cisco Nexus 9000v: manual/kinds/vr-n9kv.md
- Cisco 8000: manual/kinds/c8000.md
- Cisco c8000v: manual/kinds/vr-c8000v.md
- Cisco Catalyst 9000v: manual/kinds/vr-cat9kv.md
- Cisco FTDv: manual/kinds/vr-ftdv.md
- Juniper:
- Juniper cRPD: manual/kinds/crpd.md
Expand Down Expand Up @@ -259,7 +260,7 @@ plugins:
redirect_maps:
lab-examples/tls-cert.md: https://clabs.netdevops.me/security/gnmitls/
lab-examples/ixp-lab.md: lab-examples/peering-lab.md
- typeset
#- typeset
- glightbox
- macros:
j2_block_start_string: "[[[%"
Expand Down
108 changes: 108 additions & 0 deletions nodes/vr_cat9kv/vr-cat9kv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2020 Nokia
// Licensed under the BSD 3-Clause License.
// SPDX-License-Identifier: BSD-3-Clause

package vr_cat9kv

import (
"context"
"fmt"
"path"
"regexp"

log "github.com/sirupsen/logrus"
"github.com/srl-labs/containerlab/netconf"
"github.com/srl-labs/containerlab/nodes"
"github.com/srl-labs/containerlab/types"
"github.com/srl-labs/containerlab/utils"
)

var (
kindnames = []string{"cisco_cat9kv"}
defaultCredentials = nodes.NewCredentials("admin", "admin")

InterfaceRegexp = regexp.MustCompile(`(?:Gi|GigabitEthernet)\s?1/0/(?P<port>\d+)$`)
InterfaceOffset = 1
InterfaceHelp = "Gi1/0/X or GigabitEthernet1/0/X (where X >= 1) or ethX (where X >= 1)"
)

const (
scrapliPlatformName = "cisco_iosxe"

configDirName = "config"
startupCfgFName = "startup-config.cfg"
)

// Register registers the node in the NodeRegistry.
func Register(r *nodes.NodeRegistry) {
r.Register(kindnames, func() nodes.Node {
return new(vrCat9kv)
}, defaultCredentials)
}

type vrCat9kv struct {
nodes.VRNode
}

func (n *vrCat9kv) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
// Init VRNode
n.VRNode = *nodes.NewVRNode(n)
// set virtualization requirement
n.HostRequirements.VirtRequired = true

n.Cfg = cfg
for _, o := range opts {
o(n)
}
// env vars are used to set launch.py arguments in vrnetlab container
defEnv := map[string]string{
"CONNECTION_MODE": nodes.VrDefConnMode,
"USERNAME": defaultCredentials.GetUsername(),
"PASSWORD": defaultCredentials.GetPassword(),
"DOCKER_NET_V4_ADDR": n.Mgmt.IPv4Subnet,
"DOCKER_NET_V6_ADDR": n.Mgmt.IPv6Subnet,
"VCPU": "4",
"RAM": "18432",
}
n.Cfg.Env = utils.MergeStringMaps(defEnv, n.Cfg.Env)

// mount config dir to support startup-config functionality
n.Cfg.Binds = append(n.Cfg.Binds, fmt.Sprint(path.Join(n.Cfg.LabDir, configDirName), ":/config"))

if n.Cfg.Env["CONNECTION_MODE"] == "macvtap" {
// mount dev dir to enable macvtap
n.Cfg.Binds = append(n.Cfg.Binds, "/dev:/dev")
}

n.Cfg.Cmd = fmt.Sprintf("--username %s --password %s --hostname %s --connection-mode %s --vcpu %s --ram %s --trace",
n.Cfg.Env["USERNAME"], n.Cfg.Env["PASSWORD"], n.Cfg.ShortName, n.Cfg.Env["CONNECTION_MODE"], n.Cfg.Env["VCPU"], n.Cfg.Env["RAM"])

n.InterfaceRegexp = InterfaceRegexp
n.InterfaceOffset = InterfaceOffset
n.InterfaceHelp = InterfaceHelp

return nil
}

func (s *vrCat9kv) PreDeploy(_ context.Context, params *nodes.PreDeployParams) error {
utils.CreateDirectory(s.Cfg.LabDir, 0777)
_, err := s.LoadOrGenerateCertificate(params.Cert, params.TopologyName)
if err != nil {
return nil
}
return nodes.LoadStartupConfigFileVr(s, configDirName, startupCfgFName)
}

func (n *vrCat9kv) SaveConfig(_ context.Context) error {
err := netconf.SaveConfig(n.Cfg.LongName,
defaultCredentials.GetUsername(),
defaultCredentials.GetPassword(),
scrapliPlatformName,
)
if err != nil {
return err
}

log.Infof("saved %s running configuration to startup configuration file\n", n.Cfg.ShortName)
return nil
}
4 changes: 4 additions & 0 deletions schemas/clab.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"c8000",
"cisco_c8000",
"cisco_c8000v",
"cisco_cat9kv",
"cvx",
"cumulus_cvx",
"openbsd",
Expand Down Expand Up @@ -950,6 +951,9 @@
"vr-csr": {
"$ref": "#/definitions/node-config"
},
"cisco_cat9kv": {
"$ref": "#/definitions/node-config"
},
"cisco_ftdv": {
"$ref": "#/definitions/node-config"
},
Expand Down

0 comments on commit 17758ab

Please sign in to comment.