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
10 changes: 10 additions & 0 deletions sonic-vpp/sonic-vpp-BGPEVPN/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# ContainerLab runtime state
/clab-*

# Backups and editor junk
*.bak
.idea/

# Sensitive files
*.env
*.key
191 changes: 191 additions & 0 deletions sonic-vpp/sonic-vpp-BGPEVPN/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# SONiC-VPP BGP EVPN

This example demonstrates the integration of a high-performance software data plane ([VPP](https://fd.io/)) with a standardized network operating system ([SONiC](https://sonicfoundation.dev/)) to run advanced data center fabric protocols ([BGP EVPN](https://pantheon.tech/blog-news/what-is-bgp-evpn/)).

You will see two 2-site EVPN-VXLAN labs using **SONiC** + **VPP** data plane:
- **Single-VNI** — two router nodes, one L2 VNI (1000 / VLAN 100), two PCs sharing one broadcast domain
- **Multi-VNI** — two router nodes, two L2 VNIs (1000 / VLAN 100 and 2000 / VLAN 200), four PCs across two isolated broadcast domains

## Prerequisites
- This example was successfully replicated on an **Ubuntu (24.04.2 LTS) WSL** instance in Windows
- [Docker](https://docs.docker.com/engine/install/)
- [ContainerLab](https://containerlab.dev/install/)
- [sshpass](https://www.cyberciti.biz/faq/noninteractive-shell-script-ssh-password-provider/)

**Files to inspect**

Single-VNI:
- Topology: [single-vni.clab.yml](single-vni.clab.yml)
- Launch script: [run-single-vni.sh](run-single-vni.sh)
- Interface helper: [scripts/setup-single-vni.sh](scripts/setup-single-vni.sh)
- Router VXLAN commands: [routers/router1/vxlan-single-vni.cmd](routers/router1/vxlan-single-vni.cmd), [routers/router2/vxlan-single-vni.cmd](routers/router2/vxlan-single-vni.cmd)

Multi-VNI:
- Topology: [multi-vni.clab.yml](multi-vni.clab.yml)
- Launch script: [run-multi-vni.sh](run-multi-vni.sh)
- Interface helper: [scripts/setup-multi-vni.sh](scripts/setup-multi-vni.sh)
- Router VXLAN commands: [routers/router1/vxlan-multi-vni.cmd](routers/router1/vxlan-multi-vni.cmd), [routers/router2/vxlan-multi-vni.cmd](routers/router2/vxlan-multi-vni.cmd)

Shared (used by both labs):
- BGP underlay & EVPN configs: [routers/router1](routers/router1), [routers/router2](routers/router2)
- Common shell helpers: [lib/common.sh](lib/common.sh)

## Running the example
First, clone the repository so you have a local copy:

```bash
git clone https://github.com/PANTHEONtech/cnf-examples.git
```

### Single-VNI

To launch the single-VNI lab, simply execute the *run-single-vni.sh* script within the folder you downloaded the example to:

```bash
cd /cnf-examples/sonic-vpp/sonic-vpp-BGPEVPN
./run-single-vni.sh
```

The run-single-vni.sh script orchestrates the setup and configuration of the VXLAN environment.

**Configuration flow**

The `run-single-vni.sh` script performs these high-level actions:

1. Deploy the ContainerLab topology from `single-vni.clab.yml`
2. Configure host interfaces and router underlay IPs using `scripts/setup-single-vni.sh`
3. Apply FRR/`vtysh` underlay configurations in `routers/*/bgp-underlay.vtysh` to bring up the IPv4 underlay
4. Apply VPP VXLAN commands in `routers/*/vxlan-single-vni.cmd` to create the VTEP and the VLAN-to-VNI mapping (VLAN 100 → VNI 1000)
5. Apply FRR/`vtysh` BGP EVPN configurations in `routers/*/bgp-evpn.vtysh` to activate the BGP EVPN address-family

**Verification**

1. Start with topology and container checks (use `clab` first, fall back to `docker`):

```bash
clab inspect
docker ps
```

2. Check BGP peerings and EVPN routes

```bash
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "vtysh -c 'show bgp summary'"
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router2 "vtysh -c 'show bgp summary'"

sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "vtysh -c 'show bgp l2vpn evpn'"
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router2 "vtysh -c 'show bgp l2vpn evpn'"
```

3. Check VXLAN interfaces on SONiC and VPP:

```bash
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "show vxlan tunnel"
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router2 "show vxlan tunnel"

sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "docker exec syncd vppctl show vxlan tunnel"
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router2 "docker exec syncd vppctl show vxlan tunnel"
```

4. Test L2 connectivity between PCs (run from host with `clab exec`):

```bash
docker exec clab-sonic-vpp-single-vni-PC1 ping -c 5 168.95.10.1
```

5. To stop and destroy the example, simply execute the *stop-single-vni.sh* script within the folder you downloaded the example to:

```bash
./stop-single-vni.sh
```

### Multi-VNI

To launch the multi-VNI lab, simply execute the *run-multi-vni.sh* script within the folder you downloaded the example to:

```bash
cd /cnf-examples/sonic-vpp/sonic-vpp-BGPEVPN
./run-multi-vni.sh
```

The run-multi-vni.sh script orchestrates the setup of two simultaneous VXLAN VNIs.

**Configuration flow**

The `run-multi-vni.sh` script performs these high-level actions:

1. Deploy the ContainerLab topology from `multi-vni.clab.yml` (two routers, four PCs across two VLANs)
2. Configure host interfaces and router underlay IPs using `scripts/setup-multi-vni.sh`
3. Apply FRR/`vtysh` underlay configurations in `routers/*/bgp-underlay.vtysh` to bring up the IPv4 underlay
4. Apply VPP VXLAN commands in `routers/*/vxlan-multi-vni.cmd` to create the VTEP and both VLAN-to-VNI mappings (VLAN 100 → VNI 1000 and VLAN 200 → VNI 2000)
5. Apply FRR/`vtysh` BGP EVPN configurations in `routers/*/bgp-evpn.vtysh` to activate the BGP EVPN address-family

**Verification**

1. Start with topology and container checks (use `clab` first, fall back to `docker`):

```bash
clab inspect
docker ps
```

2. Check BGP peerings and EVPN routes (Type-2 / Type-3 entries should appear for both VNIs):

```bash
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router1 "vtysh -c 'show bgp summary'"
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router2 "vtysh -c 'show bgp summary'"

sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router1 "vtysh -c 'show bgp l2vpn evpn'"
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router2 "vtysh -c 'show bgp l2vpn evpn'"
```

3. Check VXLAN interfaces on SONiC and VPP (both VNI 1000 and VNI 2000 should be visible):

```bash
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router1 "show vxlan tunnel"
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router2 "show vxlan tunnel"

sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router1 "docker exec syncd vppctl show vxlan tunnel"
sshpass -p admin ssh admin@clab-sonic-vpp-multi-vni-router2 "docker exec syncd vppctl show vxlan tunnel"
```

4. Test L2 connectivity within each VNI — cross-VNI traffic should fail by design, since the two VNIs are isolated L2 broadcast domains:

```bash
# VNI 1000 — PC1 ↔ PC2
docker exec clab-sonic-vpp-multi-vni-PC1 ping -c 5 10.100.1.2

# VNI 2000 — PC3 ↔ PC4
docker exec clab-sonic-vpp-multi-vni-PC3 ping -c 5 10.200.1.2
```

5. Run the included test suites for end-to-end validation (multi-VLAN reachability, MAC learning, BUM flooding, dynamic VNI hot-add, scale, link-flap recovery):

```bash
./tests/test_multi_vlan_vxlan.sh
./tests/test_l2_vxlan_advanced.sh
```

6. To stop and destroy the example, simply execute the *stop-multi-vni.sh* script within the folder you downloaded the example to:

```bash
./stop-multi-vni.sh
```

## Packet tracing

To trace packets in VPP on Router1 (single-VNI lab shown — substitute `clab-sonic-vpp-multi-vni-router1` and the appropriate PC/IP for the multi-VNI lab):

```bash
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "docker exec syncd vppctl trace add dpdk-input 10"
# Generate traffic (from PC1):
docker exec clab-sonic-vpp-single-vni-PC1 ping -c 5 168.95.10.1
# View trace results:
sshpass -p admin ssh admin@clab-sonic-vpp-single-vni-router1 "docker exec syncd vppctl show trace"
```

# About

Learn more about [SONiC](https://pantheon.tech/services/expertise/sonic-nos/) and [how to orchestrate it](https://pantheon.tech/products/sandwork/).

Explore our other [SONiC-VPP examples in this repo](https://github.com/PANTHEONtech/cnf-examples/tree/master/sonic-vpp).
113 changes: 113 additions & 0 deletions sonic-vpp/sonic-vpp-BGPEVPN/lib/common.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/bin/bash
#
# common.sh — Shared helpers for SONiC-VPP BGP EVPN examples.
# Source this from run-*.sh scripts; do not execute directly.

# -----------------------------------------------------------------------------
# Prerequisites
# -----------------------------------------------------------------------------
check_prereqs() {
if ! command -v docker &> /dev/null; then
echo "Docker is not installed. See https://docs.docker.com/engine/install/"
exit 1
fi

if ! command -v clab &> /dev/null; then
echo "Containerlab is not installed. See https://containerlab.dev/install/"
exit 1
fi

if ! command -v sshpass &> /dev/null; then
echo "sshpass is not installed. Install it with: sudo apt-get install sshpass"
exit 1
fi

if ! groups "$USER" | grep -q '\bdocker\b'; then
echo "You are not a member of the docker group. Run:"
echo " sudo usermod -aG docker $USER"
echo "Then log out and back in for the changes to take effect."
exit 1
fi
}

# -----------------------------------------------------------------------------
# Topology deployment
# -----------------------------------------------------------------------------
deploy_topology() {
local topo_file="$1"

if ! sudo clab deploy --topo "$topo_file"; then
echo "Deploy failed. To retry from a clean state:"
echo " sudo clab destroy --topo $topo_file"
echo "Then rerun this script."
exit 1
fi
}

# -----------------------------------------------------------------------------
# Wait until the expected number of nodes report as healthy.
#
# Args:
# $1 — topology file (passed to `clab inspect`)
# $2 — number of nodes expected to be healthy
# -----------------------------------------------------------------------------
wait_for_healthy() {
local topo_file="$1"
local target="$2"
local retry_interval=10
local max_retries=20

for ((i=1; i<=max_retries; i++)); do
echo "Attempt $i of $max_retries..."
local healthy
healthy=$(clab inspect --topo "$topo_file" -f json \
| grep -o '"status": *"healthy"' | wc -l)

if [ "$healthy" -ge "$target" ]; then
echo "Success: $healthy nodes are healthy. Continuing..."
return 0
fi

echo "Currently $healthy healthy nodes. Waiting for $target..."
if [ "$i" -eq "$max_retries" ]; then
echo "Error: Timeout waiting for $target healthy nodes."
exit 1
fi
sleep "$retry_interval"
done
}

# -----------------------------------------------------------------------------
# you can set any log level for any component here
# -----------------------------------------------------------------------------
set_swss_log_level() {
local ssh_cmd="$1"
$ssh_cmd swssloglevel -l ERROR -a
$ssh_cmd swssloglevel -l SAI_LOG_LEVEL_INFO -s -a
}

# -----------------------------------------------------------------------------
# Apply a config file to a router.
#
# Args:
# $1 — SSH command prefix (e.g. "sshpass -p admin ssh admin@...")
# $2 — path to config file (relative to the caller's working directory)
# -----------------------------------------------------------------------------
execute() {
local ssh_cmd="$1"
local file="$2"

if [[ "$file" == *.vtysh ]]; then
$ssh_cmd bash <<EOF
vtysh <<EOV
$(cat "$file")
EOV
EOF
else
local cmd
while IFS= read -r cmd || [ -n "$cmd" ]; do
[ -z "$cmd" ] && continue
$ssh_cmd "$cmd" < /dev/null
done < "$file"
fi
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: sonic-vpp02
name: sonic-vpp-multi-vni

topology:
nodes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ sudo config vlan member add -u 200 Ethernet8
sudo config vxlan add vtep 10.0.1.1
sudo config vxlan evpn_nvo add nvo vtep
sudo config vxlan map add vtep 100 1000
sudo config vxlan map add vtep 200 2000
sudo config vxlan map add vtep 200 2000
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
sudo config vlan add 100
sudo config vlan member add -u 100 Ethernet4
sudo config vxlan add vtep 10.0.1.1
sudo config vxlan evpn_nvo add nvo vtep
sudo config vxlan add vtep 10.0.1.1
sudo config vxlan evpn_nvo add nvo vtep
sudo config vxlan map add vtep 100 1000
53 changes: 53 additions & 0 deletions sonic-vpp/sonic-vpp-BGPEVPN/run-multi-vni.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/bash
#
# Deploy the multi-VNI L2 VXLAN EVPN example.
# Two SONiC-VPP routers, two VNIs (1000 / VLAN 100, 2000 / VLAN 200), four PCs.

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

source lib/common.sh

TOPO="multi-vni.clab.yml"
LAB="sonic-vpp-multi-vni"

ROUTER1="sshpass -p admin ssh admin@clab-${LAB}-router1"
ROUTER2="sshpass -p admin ssh admin@clab-${LAB}-router2"

check_prereqs
deploy_topology "$TOPO"
wait_for_healthy "$TOPO" 2

set_swss_log_level "$ROUTER1"
set_swss_log_level "$ROUTER2"

./scripts/setup-multi-vni.sh

sleep 5

# BGP underlay (IPv4 unicast + /31 neighbor)
execute "$ROUTER1" "routers/router1/bgp-underlay.vtysh"
execute "$ROUTER2" "routers/router2/bgp-underlay.vtysh"

sleep 5

# VXLAN VTEP + VLAN-to-VNI mappings for both VNIs
execute "$ROUTER1" "routers/router1/vxlan-multi-vni.cmd"
execute "$ROUTER2" "routers/router2/vxlan-multi-vni.cmd"

sleep 5

# activate BGP EVPN address-family
execute "$ROUTER1" "routers/router1/bgp-evpn.vtysh"
execute "$ROUTER2" "routers/router2/bgp-evpn.vtysh"

echo ""
echo "Multi-VNI lab ready. Verify with:"
echo " docker exec clab-${LAB}-PC1 ping -c 3 10.100.1.2 # VNI 1000"
echo " docker exec clab-${LAB}-PC3 ping -c 3 10.200.1.2 # VNI 2000"
echo ""
echo "Run the test suite with:"
echo " ./tests/test_multi_vlan_vxlan.sh"
echo " ./tests/test_l2_vxlan_advanced.sh"
Loading