Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 core/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
clabnodescisco_sdwan "github.com/srl-labs/containerlab/nodes/cisco_sdwan"
clabnodescisco_vios "github.com/srl-labs/containerlab/nodes/cisco_vios"
clabnodescjunosevolved "github.com/srl-labs/containerlab/nodes/cjunosevolved"
clabnodescodelaboratory_bng "github.com/srl-labs/containerlab/nodes/codelaboratory_bng"
clabnodescrpd "github.com/srl-labs/containerlab/nodes/crpd"
clabnodescvx "github.com/srl-labs/containerlab/nodes/cvx"
clabnodesdell_sonic "github.com/srl-labs/containerlab/nodes/dell_sonic"
Expand Down Expand Up @@ -117,4 +118,5 @@ func (c *CLab) RegisterNodes() { //nolint:funlen
clabnodesvyosnetworks_vyos.Register(c.Reg)
clabnodescjunosevolved.Register(c.Reg)
clabnodesarrcus_arcos.Register(c.Reg)
clabnodescodelaboratory_bng.Register(c.Reg)
}
75 changes: 75 additions & 0 deletions docs/lab-examples/bng01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
| | |
| ----------------------------- | -------------------------------------------------------------------------------------- |
| **Description** | BNG with subscriber simulator and core router |
| **Components** | [Code Laboratory BNG][bng], [BNG Blaster][blaster], [FRR][frr] |
| **Resource requirements**[^1] | :fontawesome-solid-microchip: 2 <br/>:fontawesome-solid-memory: 2 GB |
| **Topology file** | [bng01.clab.yml][topofile] |
| **Name** | bng01 |

## Description

This lab demonstrates Code Laboratory's eBPF/XDP-based BNG handling IPoE/DHCPv4 subscriber sessions. The topology consists of three nodes:

| Node | Role | Image |
|------|------|-------|
| `bng1` | Broadband Network Gateway | `ghcr.io/codelaboratoryltd/bng:latest` |
| `subscribers` | Subscriber simulator (BNG Blaster) | `veesixnetworks/bngblaster:0.9.30` |
| `corerouter1` | Core/upstream router (FRR) | `frrouting/frr:v8.4.1` |

## Topology

```
subscribers:eth1 <-----> bng1:eth1 (access)
bng1:eth2 (core) <-----> corerouter1:eth1
```

## Deploying the lab

```bash
sudo clab deploy -t lab-examples/bng01/bng01.clab.yml
```

## Verification

Check BNG is running:

```bash
docker logs clab-bng01-bng1
```

Check FRR routing:

```bash
docker exec clab-bng01-corerouter1 vtysh -c "show ip route"
```

Run BNG Blaster to simulate 10 untagged IPoE/DHCPv4 subscribers:

```bash
docker exec -it clab-bng01-subscribers bngblaster -C /config/config.json
```

A QinQ (802.1ad) subscriber config is also provided for double-tagged deployments:

```bash
docker exec -it clab-bng01-subscribers bngblaster -C /config/qinq.json
```

Check BNG metrics:

```bash
curl http://clab-bng01-bng1:9090/metrics
```

## Cleanup

```bash
sudo clab destroy -t lab-examples/bng01/bng01.clab.yml
```

[bng]: https://github.com/codelaboratoryltd/bng
[blaster]: https://github.com/rtbrick/bngblaster
[frr]: https://docs.frrouting.org/en/stable-8.4/
[topofile]: https://github.com/srl-labs/containerlab/tree/main/lab-examples/bng01/bng01.clab.yml

[^1]: Resource requirements are provisional. Consult with the installation guides for additional information.
167 changes: 167 additions & 0 deletions docs/manual/kinds/codelaboratory_bng.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
---
search:
boost: 4
kind_code_name: codelaboratory_bng
kind_display_name: Code Laboratory BNG
---
# Code Laboratory BNG

Code Laboratory's eBPF/XDP-based Broadband Network Gateway is identified with `-{{ kind_code_name }}-` kind in the [topology file](../topo-def-file.md).

The BNG uses eBPF/XDP for kernel-level DHCP fast path processing, achieving sub-100μs DHCP response times for cached subscribers. Unlike VPP-based BNGs, it requires only `NET_ADMIN` and `BPF` Linux capabilities — no hugepages, DPDK, or dedicated NICs.

## Getting -{{ kind_display_name }}- image

The -{{ kind_display_name }}- container image is available from GitHub Container Registry:

```bash
docker pull ghcr.io/codelaboratoryltd/bng:latest
```

Source code and build instructions are available on [GitHub](https://github.com/codelaboratoryltd/bng).

## Managing -{{ kind_display_name }}- nodes

### Health check

The BNG exposes a health endpoint on the metrics port:

```bash
curl http://<node-name>:9090/health
```

### Prometheus metrics

Metrics are served at the configured metrics address (default `:9090`):

```bash
curl http://<node-name>:9090/metrics
```

Key metrics include DHCP fast/slow path latencies, cache hit rates, pool utilization, and active session counts.

## Interfaces naming

-{{ kind_display_name }}- nodes use the following interface naming convention:

| Interface | Purpose |
|-----------|---------|
| `eth0` | Management (containerlab default) |
| `eth1` | Access / subscriber-facing |
| `eth2+` | Core / upstream links |

The `eth0` interface can only be used when `network-mode` is set to `none`.

There are no other restrictions on the interface naming besides the generic Linux interface naming rules.

## Features and options

### Startup configuration

The [`startup-config`](../nodes.md#startup-config) property sets the path to a YAML config file that is mounted to `/etc/bng/config.yaml` inside the container.

The config file uses a flat `key: value` format where each key matches a CLI flag name (without `--`). CLI flags take precedence over config file values.

Example minimal config:

```yaml
interface: eth1
pool-network: 10.0.1.0/24
pool-gateway: 10.0.1.1
pool-dns: "8.8.8.8,8.8.4.4"
lease-time: 3600s
metrics-addr: ":9090"
log-level: info
```

Example with advanced features:

```yaml
interface: eth1
pool-network: 10.0.1.0/24
pool-gateway: 10.0.1.1
pool-dns: "8.8.8.8,8.8.4.4"
lease-time: 3600s
metrics-addr: ":9090"
log-level: info

# Anti-spoofing (disabled, strict, loose, log-only)
antispoof-mode: log-only

# Walled garden captive portal
walled-garden: "false"
walled-garden-portal: "10.255.255.1:8080"

# NAT44/CGNAT
nat-enabled: "true"
nat-inside-interface: eth1
nat-outside-interface: eth2

# PPPoE
pppoe-enabled: "false"

# HA failover (active or standby)
ha-role: ""
ha-peer: ""
```

### Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `BNG_INTERFACE` | `eth1` | Subscriber-facing interface |
| `BNG_LOG_LEVEL` | `info` | Log level (debug, info, warn, error) |

### Linux capabilities

The -{{ kind_display_name }}- kind automatically adds the following capabilities:

| Capability | Purpose |
|------------|---------|
| `NET_ADMIN` | Network interface and eBPF map management |
| `BPF` | Loading eBPF/XDP programs into the kernel |

This is significantly lighter than VPP-based BNGs which additionally require `SYS_ADMIN`, `IPC_LOCK`, `SYS_NICE`, and `SYS_RAWIO` for DPDK hugepage management.

### QinQ (802.1ad) support

The BNG supports QinQ double VLAN tagging at the eBPF/XDP data plane level. Subscribers are identified by S-TAG (service VLAN, outer) and C-TAG (customer VLAN, inner) pairs, supporting up to 100,000 concurrent VLAN-based subscribers.

The [bng01 lab example](../../lab-examples/bng01.md) includes both untagged and QinQ subscriber configs for [BNG Blaster][blaster].

[blaster]: https://github.com/rtbrick/bngblaster

## Quickstart

The following topology creates a minimal BNG lab with a subscriber simulator and core router:

```yaml
name: bng-quickstart

topology:
nodes:
bng1:
kind: codelaboratory_bng
image: ghcr.io/codelaboratoryltd/bng:latest
startup-config: bng1/config.yaml
exec:
- ip addr add 10.0.1.1/24 dev eth1
- ip addr add 10.0.0.1/24 dev eth2
subscribers:
kind: linux
image: veesixnetworks/bngblaster:0.9.30
binds:
- subscribers/config.json:/config/config.json
corerouter1:
kind: linux
image: frrouting/frr:v8.4.1
binds:
- corerouter1/daemons:/etc/frr/daemons
- corerouter1/frr.conf:/etc/frr/frr.conf

links:
- endpoints: ["subscribers:eth1", "bng1:eth1"]
- endpoints: ["bng1:eth2", "corerouter1:eth1"]
```

See the [bng01 lab example](../../lab-examples/bng01.md) for a complete working topology with all config files.
1 change: 1 addition & 0 deletions docs/manual/kinds/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ Within each predefined kind, we store the necessary information that is used to
| **6WIND VSR** | [`6wind_vsr`](6wind_vsr.md) | supported | container |
| **Keysight ixia-c-one** | [`keysight_ixia-c-one`](keysight_ixia-c-one.md) | supported | container |
| **Arrcus ArcOS** | [`arrcus_arcos`](arrcus_arcos.md) | supported | container |
| **Code Laboratory BNG** | [`codelaboratory_bng`](codelaboratory_bng.md) | supported | container |
| **FD.io VPP** | [`fdio_vpp`](fdio_vpp.md) | supported | container |
| **RARE/freeRtr** | [`rare`](rare-freertr.md) | supported | container |
| **VyOS Networks VyOS** | [`vyosnetworks_vyos`](vyosnetworks_vyos.md) | supported | VM |
Expand Down
27 changes: 27 additions & 0 deletions lab-examples/bng01/bng01.clab.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: bng01

topology:
nodes:
bng1:
kind: codelaboratory_bng
image: ghcr.io/codelaboratoryltd/bng:latest
startup-config: bng1/config.yaml
exec:
- ip addr add 10.0.1.1/24 dev eth1
- ip addr add 10.0.0.1/24 dev eth2
corerouter1:
kind: linux
image: frrouting/frr:v8.4.1
binds:
- corerouter1/daemons:/etc/frr/daemons
- corerouter1/frr.conf:/etc/frr/frr.conf
subscribers:
kind: linux
image: veesixnetworks/bngblaster:0.9.30
binds:
- subscribers/config.json:/config/config.json
- subscribers/qinq.json:/config/qinq.json

links:
- endpoints: ["subscribers:eth1", "bng1:eth1"]
- endpoints: ["bng1:eth2", "corerouter1:eth1"]
12 changes: 12 additions & 0 deletions lab-examples/bng01/bng1/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# BNG startup configuration for containerlab
#
# Flat key=value format where each key matches a CLI flag name (without --).
# CLI flags take precedence over values in this file.

interface: eth1
pool-network: 10.0.1.0/24
pool-gateway: 10.0.1.1
pool-dns: "8.8.8.8,8.8.4.4"
lease-time: 3600s
metrics-addr: ":9090"
log-level: info
22 changes: 22 additions & 0 deletions lab-examples/bng01/corerouter1/daemons
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
zebra=yes
bgpd=no
ospfd=yes
ospf6d=no
ripd=no
ripngd=no
isisd=no
pimd=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
staticd=yes
pbrd=no
bfdd=no
fabricd=no

vtysh_enable=yes
zebra_options=" -A 127.0.0.1"
ospfd_options=" -A 127.0.0.1"
staticd_options="-A 127.0.0.1"
28 changes: 28 additions & 0 deletions lab-examples/bng01/corerouter1/frr.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
frr version 8.4.1
frr defaults traditional
hostname corerouter1
log syslog informational
service integrated-vtysh-config
!
interface eth1
ip address 10.0.0.2/24
ip ospf area 0.0.0.0
ip ospf network point-to-point
exit
!
interface lo
ip address 10.255.0.2/32
ip ospf area 0.0.0.0
ip ospf passive
exit
!
router ospf
ospf router-id 10.255.0.2
log-adjacency-changes
redistribute connected
exit
!
ip route 10.0.1.0/24 10.0.0.1
!
line vty
!
26 changes: 26 additions & 0 deletions lab-examples/bng01/subscribers/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"interfaces": {
"access": [
{
"interface": "eth1",
"type": "ipoe",
"vlan-mode": "N:1"
}
]
},
"dhcp": {
"enable": true
},
"ipoe": {
"ipv4": true,
"ipv6": false
},
"sessions": {
"count": 10,
"start-rate": 2
},
"access-line": {
"agent-circuit-id": "eth 0/1/{session-global}",
"agent-remote-id": "BNG-Blaster-{session-global}"
}
}
Loading