Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cisco IOL kind #2211

Merged
merged 23 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3d91203
Add Cisco IOL kind
kaelemc Sep 30, 2024
9c8ffb0
Add IOL documentation
kaelemc Sep 30, 2024
0e3373c
Update resoruce requirements documentation
kaelemc Oct 1, 2024
a85210f
Minor documentation fixes.
kaelemc Oct 1, 2024
a3a0d34
Add KSM note in documentation and correct accuracy of management inte…
kaelemc Oct 1, 2024
b01e092
Remove erroneous 'VM' references in docs.
kaelemc Oct 1, 2024
6ab6926
added schema and slightly renamed examples
hellt Oct 3, 2024
326210a
Add NETMAP/IOUYAP generation and template configuration.
kaelemc Oct 3, 2024
f55d6e8
Add full template configuration inclusive of L2 node and add NETMAP/I…
kaelemc Oct 4, 2024
6e50e36
Fix link in documentation to point at `cisco_iol.md` instead of `iol.md`
kaelemc Oct 4, 2024
837c78c
Add information about new `type` field
kaelemc Oct 4, 2024
4795f37
Fix bind mount path for IOL nvram.
kaelemc Oct 4, 2024
ea1b063
Change node type to `default node` and add interface mapping to creat…
kaelemc Oct 4, 2024
c572487
Use `IFaceAlias` instead of `IfaceName` when displaying incorrectly d…
kaelemc Oct 4, 2024
abd58b0
Fix documentation information about discontigious interface naming + …
kaelemc Oct 4, 2024
1c2b50f
refactor type check
hellt Oct 4, 2024
30a469b
move cidrtoddn to utils
hellt Oct 4, 2024
3a7b740
added basic test
hellt Oct 4, 2024
4f21265
fix image urls
hellt Oct 4, 2024
0edbb64
added tmate
hellt Oct 4, 2024
82b1f58
add a timer
hellt Oct 4, 2024
9c22093
bump wait timer
hellt Oct 4, 2024
83e54d7
bump timer even more
hellt Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clab/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
fortinet_fortigate "github.com/srl-labs/containerlab/nodes/fortinet_fortigate"
generic_vm "github.com/srl-labs/containerlab/nodes/generic_vm"
host "github.com/srl-labs/containerlab/nodes/host"
cisco_iol "github.com/srl-labs/containerlab/nodes/iol"
ipinfusion_ocnos "github.com/srl-labs/containerlab/nodes/ipinfusion_ocnos"
k8s_kind "github.com/srl-labs/containerlab/nodes/k8s_kind"
keysight_ixiacone "github.com/srl-labs/containerlab/nodes/keysight_ixiacone"
Expand Down Expand Up @@ -93,4 +94,5 @@ func (c *CLab) RegisterNodes() {
c8000.Register(c.Reg)
border0.Register(c.Reg)
k8s_kind.Register(c.Reg)
cisco_iol.Register(c.Reg)
}
1 change: 1 addition & 0 deletions docs/manual/kinds/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Within each predefined kind, we store the necessary information that is used to
| **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 IOL** | [`cisco_iol`](iol.md) | supported | container |
| **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
135 changes: 135 additions & 0 deletions docs/manual/kinds/iol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
search:
boost: 4
kind_code_name: cisco_iol
kind_display_name: Cisco IOL
kind_short_display_name: IOL
---
# [[[ kind_display_name ]]]

Cisco IOL (IOS On Linux) (or [[[ kind_short_display_name ]]] for short) is a version of Cisco IOS/IOS-XE software which doesn't run as a virtual machine.

Cisco IOL is distributed as a binary and executes directly ontop of Linux, hence the name IOS *On Linux*.

It is identified with `[[[ kind_code_name ]]]` kind in the [topology file](../topo-def-file.md) and built using [vrnetlab](../vrnetlab.md) project and essentially is the IOL binary packaged into a docker container.

## Getting and building [[[ kind_display_name ]]]

You can get [[[ kind_display_name ]]] from Cisco's CML refplat .iso. It is identified by the `iol` or `ioll2` prefix.

From the IOL binary you are required to build a container using the [vrnetlab](../vrnetlab.md) project.

IOL is distributed as two versions:

- IOL
- For usage as an L3 router, lacks L2 switching functionality.
- IOL-L2
- For usage as a virtual version of an IOS-XE switch. Still has support for some L3 features.

## Resource requirements

[[[ kind_display_name ]]] is very light on resources. Each IOL node requires at minimum 1GB of disk space for the NVRAM (where configuration is saved) and 1G of RAM. Assume 1vCPU per node, but you can oversubscribe and run multiple IOL nodes per vCPU.

Using [KSM](../vrnetlab.md#memory-optimization) you can achieve a higher density of IOL nodes per GB of RAM.

## Managing [[[ kind_display_name ]]] nodes

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

/// tab | CLI
to connect to the [[[ kind_short_display_name ]]] CLI

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

///
/// tab | bash
to connect to a `bash` shell of a running [[[ kind_short_display_name ]]] container:

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

///

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

## Interface naming

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: `Ethernet0/X` (or `e0/X`), where `X` is the port number.

With that naming convention in mind:

- `e0/1` - first data port available
- `e0/2` - second data port, and so on...

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

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

When containerlab launches [[[ kind_display_name ]]], the `Ethernet0/0` or `Vlan1` interface of the container gets assigned management IPv4 and IPv6 addresses from docker. On IOL the `Ethernet0/0` is in it's own management VRF so configuration in the global context will not affect the management interface. On IOL-L2 the management interface is the `Vlan1` interface, it is also in it's own management VRF.


Interfaces must be defined in a contigous manner in your toplogy file. For example, if you want to use `Ethernet0/4` you must define `Ethernet0/1`, `Ethernet0/2` and `Ethernet0/3`. See the example below.

```yaml
name: my-iol-lab
topology:
nodes:
iol-1:
kind: cisco_iol
image: vrnetlab/vr-iol:17.12.01
iol-2:
kind: cisco_iol
image: vrnetlab/vr-iol:17.12.01

links:
- endpoints: ["iol-1:Ethernet0/1","iol-2:Ethernet0/1"]
- endpoints: ["iol-1:Ethernet0/2","iol-2:Ethernet0/2"]
- endpoints: ["iol-1:Ethernet0/3", "iol-2:Ethernet0/3"]
- endpoints: ["iol-1:Ethernet0/4", "iol-2:Ethernet0/4"]
```

/// warning
You may see more interfaces than you have defined in the [[[ kind_short_display_name ]]] CLI, this is because interfaces are provisioned in groups. Links/interfaces that you did not define in your containerlab topology will *not* pass any traffic.
///

Data interfaces `Ethernet0/1+` need to be configured with IP addressing manually using CLI or other available management interfaces and will appear `unset` in the CLI:

```
iol#sh ip int br
Interface IP-Address OK? Method Status Protocol
Ethernet0/0 172.20.20.5 YES TFTP up up
Ethernet0/1 unassigned YES unset administratively down down
Ethernet0/2 unassigned YES unset administratively down down
Ethernet0/3 unassigned YES unset administratively down down
```
## Sample topology

Below is a sample topology of two IOL nodes connected via an IOL-L2 switch.

```yaml
name: my-iol-lab
topology:
nodes:
iol-router1:
kind: cisco_iol
image: vrnetlab/vr-iol:17.12.01
iol-router2:
kind: cisco_iol
image: vrnetlab/vr-iol:17.12.01
iol-switch:
kind: cisco_iol
image: vrnetlab/vr-iol-l2:17.12.01

links:
- endpoints: ["iol-router1:Ethernet0/1","iol-switch:Ethernet0/1"]
- endpoints: ["iol-router2:Ethernet0/1","iol-switch:Ethernet0/2"]
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ nav:
- Cisco 8000: manual/kinds/c8000.md
- Cisco c8000v: manual/kinds/vr-c8000v.md
- Cisco Catalyst 9000v: manual/kinds/vr-cat9kv.md
- Cisco IOL: manual/kinds/iol.md
- Cisco FTDv: manual/kinds/vr-ftdv.md
- Juniper:
- Juniper cRPD: manual/kinds/crpd.md
Expand Down
70 changes: 70 additions & 0 deletions nodes/iol/iol.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2020 Nokia
// Licensed under the BSD 3-Clause License.
// SPDX-License-Identifier: BSD-3-Clause

package cisco_iol

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

"github.com/srl-labs/containerlab/nodes"
"github.com/srl-labs/containerlab/types"
"github.com/srl-labs/containerlab/utils"
)

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

InterfaceRegexp = regexp.MustCompile(`(?:e|Ethernet)\s?0/(?P<port>\d+)$`)
InterfaceOffset = 1
InterfaceHelp = "e0/X or Ethernet0/X (where X >= 1) or ethX (where X >= 1)"
)

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

type iol struct {
nodes.VRNode
}
hellt marked this conversation as resolved.
Show resolved Hide resolved

func (n *iol) Init(cfg *types.NodeConfig, opts ...nodes.NodeOption) error {
// Init VRNode
n.VRNode = *nodes.NewVRNode(n)

n.Cfg = cfg
for _, o := range opts {
o(n)
}

// mount nvram so that config persists
n.Cfg.Binds = append(n.Cfg.Binds, fmt.Sprint(path.Join(n.Cfg.LabDir, "nvram"), ":/opt/iol/nvram_00001"))

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

return nil
}

func (s *iol) PreDeploy(_ context.Context, params *nodes.PreDeployParams) error {
utils.CreateDirectory(s.Cfg.LabDir, 0777)

if !utils.FileExists(path.Join(s.Cfg.LabDir, "nvram")) {
// create nvram file
utils.CreateFile(path.Join(s.Cfg.LabDir, "nvram"), "")
}

_, err := s.LoadOrGenerateCertificate(params.Cert, params.TopologyName)
if err != nil {
return nil
}
return err
}
Loading