diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7beb6f79..270ee5f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,9 @@ on: - 'docker-compose/cpdp-frr/**' - '!docker-compose/cpdp-frr/**.md' - '!docker-compose/cpdp-frr/**.png' + - '!clab/ixp-openbgpd/**' + - '!clab/ixp-openbgpd/**.md' + - '!clab/ixp-openbgpd/**.png' - 'clab/rtbh/**' - '!clab/rtbh/**.md' - '!clab/rtbh/**.png' @@ -34,6 +37,9 @@ on: - 'docker-compose/cpdp-frr/**' - '!docker-compose/cpdp-frr/**.md' - '!docker-compose/cpdp-frr/**.png' + - '!clab/ixp-openbgpd/**' + - '!clab/ixp-openbgpd/**.md' + - '!clab/ixp-openbgpd/**.png' - 'clab/rtbh/**' - '!clab/rtbh/**.md' - '!clab/rtbh/**.png' @@ -49,6 +55,7 @@ jobs: docker-compose-cpdp-b2b: ${{ steps.changes.outputs.docker-compose-cpdp-b2b }} docker-compose-cpdp-frr: ${{ steps.changes.outputs.docker-compose-cpdp-frr }} clab-cpdp-frr: ${{ steps.changes.outputs.clab-cpdp-frr }} + clab-ixp-openbgpd: ${{ steps.changes.outputs.clab-ixp-openbgpd }} clab-rtbh: ${{ steps.changes.outputs.clab-rtbh }} steps: - uses: actions/checkout@v3 @@ -68,6 +75,8 @@ jobs: - 'docker-compose/cpdp-frr/**' clab-cpdp-frr: - 'docker-compose/cpdp-frr/**' + clab-ixp-openbgpd: + - 'clab/ixp-openbgpd/**' clab-rtbh: - 'clab/rtbh/**' - name: docker-compose b2b @@ -85,6 +94,9 @@ jobs: - name: clab cpdp-frr if: steps.changes.outputs.clab-cpdp-frr == 'true' run: echo "Run clab cpdp-frr CI" + - name: clab ixp-openbgpd + if: steps.changes.outputs.clab-ixp-openbgpd == 'true' + run: echo "Run Clab ixp-openbgpd CI" - name: clab rtbh if: steps.changes.outputs.clab-rtbh == 'true' run: echo "Run Clab RTBH CI" @@ -182,6 +194,26 @@ jobs: password: ${{ secrets.ENV_GITHUB_PAT }} - name: Run all-clab run: make all-clab + clab-ixp-openbgpd: + name: Run Clab ixp-openbgpd CI + runs-on: ubuntu-20.04 + needs: paths-filter + defaults: + run: + working-directory: ./clab/ixp-openbgpd + if: needs.paths-filter.outputs.clab-ixp-openbgpd == 'true' + steps: + - uses: actions/checkout@v3 + with: + submodules: 'true' + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ secrets.ENV_GITHUB_USER }} + password: ${{ secrets.ENV_GITHUB_PAT }} + - name: Run all and clean + run: make all clean pull-clean clab-rtbh: name: Run Clab RTBH CI runs-on: ubuntu-20.04 diff --git a/clab/ixp-openbgpd/Makefile b/clab/ixp-openbgpd/Makefile new file mode 100644 index 00000000..af7cf7d5 --- /dev/null +++ b/clab/ixp-openbgpd/Makefile @@ -0,0 +1,108 @@ +SHELL = /bin/bash + +.PHONY: all +all: install pull deploy run + +.PHONY: clean +clean: remove-clab remove-net + +.PHONY: clean-all +clean-all: clean pull-clean install-clean + +############################### +# Install components +############################### + +.PHONY: install +install: install-clab install-otgen + +install-clab: /usr/bin/containerlab +/usr/bin/containerlab: + bash -c "$$(curl -sL https://get.containerlab.dev)" + +install-otgen: /usr/local/bin/otgen +/usr/local/bin/otgen: + curl -L "https://github.com/open-traffic-generator/otgen/releases/download/v0.4.0-rc1/otgen_0.4.0-rc1_$$(uname -s)_$$(uname -m).tar.gz" | tar xzv otgen + sudo mv otgen /usr/local/bin/otgen + sudo chmod +x /usr/local/bin/otgen + +install-clean: + -sudo rm -f `command -v otgen` + -sudo apt remove containerlab -y + +############################### +# Pull images +############################### + +.PHONY: pull + +pull: pull-ceos + +pull-clean: remove-ceos + +pull-ceos: +ifeq ($(shell docker images -q ceos:latest 2> /dev/null),) + docker pull ghcr.io/open-traffic-generator/ceos:4.28.0F + docker tag ghcr.io/open-traffic-generator/ceos:4.28.0F ceos:latest +endif + +remove-ceos: +ifneq ($(shell docker images -q ceos:latest 2> /dev/null),) + docker rmi `docker images -q ceos:latest 2> /dev/null` --force +endif + + +############################### +# Deploy lab +############################### + +.PHONY: deploy +deploy: deploy-net deploy-clab + +deploy-net: + sudo bash -c 'ip link add name ixp type bridge && ip link set dev ixp up' + +deploy-clab: + sudo -E containerlab deploy --reconfigure + sleep 30 # pause for all components to initialize + +remove-clab: + sudo containerlab destroy --cleanup + +remove-net: + -sudo ip link delete dev ixp + +############################### +# Run tests +############################### + +.PHONY: run +run: run-connected run-ce + +run-connected: + @echo "#################################################################" + @echo "# Run traffic between subnets directly connected to r1 and r2" + @echo "#################################################################" + + otgen --log debug run --insecure --file otg.json --json --metrics flow | otgen transform --metrics flow | otgen display -m table + + @echo + +run-ce: export OTG_LOCATION_P1 = localhost:5555+localhost:50071 +run-ce: export OTG_LOCATION_P2 = localhost:5556+localhost:50072 +run-ce: + @echo "#################################################################" + @echo "# Run raffic from behind emulated CE routers downstream from r1 and r2" + @echo "#################################################################" + + otgen create device -n ce1111 --ip 192.0.2.2 --gw 192.0.2.1 --prefix 30 -p p1 > otgen.out + cat otgen.out | otgen add bgp -d ce1111 --asn 1111 --route 1.1.1.1/32 >> otgen.out + cat otgen.out | otgen add device -n ce2222 --ip 203.0.113.2 --gw 203.0.113.1 --prefix 30 -p p2 >> otgen.out + cat otgen.out | otgen add bgp -d ce2222 --asn 2222 --route 2.2.2.2/32 >> otgen.out + cat otgen.out | otgen add flow -n f1 --tx ce1111 --rx ce2222 --dmac auto --src 1.1.1.1 --dst 2.2.2.2 --rate 100 --count 1000 --size 512 >> otgen.out + cat otgen.out | otgen add flow -n f2 --tx ce2222 --rx ce1111 --dmac auto --dst 1.1.1.1 --src 2.2.2.2 --rate 100 --count 1000 --size 512 >> otgen.out + cat otgen.out | otgen --log debug run --insecure --metrics flow | otgen transform --metrics flow | otgen display -m table + + -@rm otgen.out + @echo + diff --git a/clab/ixp-openbgpd/README.md b/clab/ixp-openbgpd/README.md new file mode 100644 index 00000000..65486963 --- /dev/null +++ b/clab/ixp-openbgpd/README.md @@ -0,0 +1,115 @@ +# Guest lab: IXP with OpenBGPd Route Server + +## Overview + +## Lab configuration + +### Layer 3 topology and generated traffic flows + +![IP Diagram](./ip-diagram.png) + +## Prerequisites + +* Licensed [Keysight Elastic Network Generator](https://www.keysight.com/us/en/products/network-test/protocol-load-test/keysight-elastic-network-generator.html) images. Read more in [KENG.md](/KENG.md) +* Linux host or VM with sudo permissions and Docker support +* [Docker](https://docs.docker.com/engine/install/) +* Arista cEOSLab image. Arista EOS containerized version is called cEOSLab and can be obtained by registering on Arista website and downloading an archive with container image. Follow the [instructions](https://containerlab.dev/manual/kinds/ceos/#getting-ceos-image) provided on Containerlab website to get it. Once the image is installed, tag it as `ceos:latest`: + + ```Shell + docker tag ceos:latest + ``` + +* Clone of this repository + + ```Shell + git clone https://github.com/open-traffic-generator/otg-examples.git + ``` + +## Quick start + +To run all the steps at once, execute: + +```Shell +cd otg-examples/clab/ixp-openbgpd +make all +make clean +``` + +Otherwise, follow step-by-step instructions below: + +## Install components + +1. Install the latest release of Containerlab. For more installation options see [here](https://containerlab.dev/install/). + + ```Shell + bash -c "$(curl -sL https://get.containerlab.dev)" + ``` + +2. Install `otgen` tool, version `0.4.0-rc1` or later. + + ```Shell + curl -L "https://github.com/open-traffic-generator/otgen/releases/download/v0.4.0-rc1/otgen_0.4.0-rc1_$(uname -s)_$(uname -m).tar.gz" | tar xzv otgen + sudo mv otgen /usr/local/bin/otgen + sudo chmod +x /usr/local/bin/otgen + ``` + +3. Make sure `/usr/local/bin` is in your `$PATH` variable (by default this is not the case on CentOS 7) + + ```Shell + cmd=otgen + dir=/usr/local/bin + if ! command -v ${cmd} &> /dev/null && [ -x ${dir}/${cmd} ]; then + echo "${cmd} exists in ${dir} but not in the PATH, updating PATH to:" + PATH="/usr/local/bin:${PATH}" + echo $PATH + fi + ``` + +## Deploy the lab + +1. Create a bridge `ixp` to represent an IXP LAN segment + + ```Shell + sudo bash -c 'ip link add name ixp type bridge && ip link set dev ixp up' + ``` + +2. Launch the deployment using Containerlab + + ```Shell + cd otg-examples/clab/ixp-openbgpd + sudo -E containerlab deploy + ``` + +## Run tests + +1. Traffic between subnets directly connected to `r1` and `r2` + + ```Shell + otgen --log debug run -k --file otg.json -m flow | otgen transform -m flow | otgen display -m table + ``` + +2. Traffic from behind emulated CE routers downstream from `r1` and `r2`. These emulated routers are created by OTG Test Ports as `ce1111` and `ce2222`: + + ```Shell + export OTG_LOCATION_P1="localhost:5555+localhost:50071" + export OTG_LOCATION_P2="localhost:5556+localhost:50072" + + otgen create device -n ce1111 --ip 192.0.2.2 --gw 192.0.2.1 --prefix 30 -p p1 | \ + otgen add bgp -d ce1111 --asn 1111 --route 1.1.1.1/32 | \ + otgen add device -n ce2222 --ip 203.0.113.2 --gw 203.0.113.1 --prefix 30 -p p2 | \ + otgen add bgp -d ce2222 --asn 2222 --route 2.2.2.2/32 | \ + otgen add flow -n f1 --tx ce1111 --rx ce2222 --dmac auto --src 1.1.1.1 --dst 2.2.2.2 --rate 100 --count 1000 --size 512 | \ + otgen add flow -n f2 --tx ce2222 --rx ce1111 --dmac auto --dst 1.1.1.1 --src 2.2.2.2 --rate 100 --count 1000 --size 512 | \ + otgen --log debug run --insecure --metrics flow | otgen transform --metrics flow | otgen display -m table + ``` + +## Destroy the lab + +```Shell +sudo containerlab destroy -c +sudo ip link delete dev ixp +``` + +## Credits + +* Original [`Basic IXP Lab with OpenBGPd Route Server`](https://github.com/hellt/openbgpd-lab) lab copyright of [Roman Dodin](https://github.com/hellt) diff --git a/clab/ixp-openbgpd/ceos.cfg b/clab/ixp-openbgpd/ceos.cfg new file mode 100644 index 00000000..955a6cdf --- /dev/null +++ b/clab/ixp-openbgpd/ceos.cfg @@ -0,0 +1,53 @@ +! +transceiver qsfp default-mode 4x10G +! +service routing protocols model multi-agent +! +spanning-tree mode mstp +! +no aaa root +! +username admin privilege 15 role network-admin secret sha512 $6$q7rxnFPBdUBokO6F$WTwfyP70x9.HnajAr/2D8facyvqqxecIAYeMxXOifjJqJ5WbMKWZzsWlkiUj4J975VY5vXsqXG7BLFDgA5jtR. +! +interface Ethernet1 + no switchport + ip address 192.168.0.2/24 +! +interface Ethernet2 + no switchport + ip address 203.0.113.1/30 +! +interface Loopback0 + ip address 10.0.0.2/32 +! +ip prefix-list loopback + seq 10 permit 10.0.0.2/32 +! +ip prefix-list CE + seq 10 permit 203.0.113.0/30 +! +route-map redis_connected permit 10 + match ip address prefix-list loopback +! +route-map redis_connected permit 20 + match ip address prefix-list CE +! +ip routing +! +router bgp 65002 + router-id 10.0.0.2 + no bgp enforce-first-as + neighbor 192.168.0.3 remote-as 65003 + neighbor 203.0.113.2 remote-as 2222 + redistribute connected route-map redis_connected +! +management api http-commands + no shutdown +! +management api gnmi + transport grpc default +! +management api netconf + transport ssh default +! +end \ No newline at end of file diff --git a/clab/ixp-openbgpd/ip-diagram.png b/clab/ixp-openbgpd/ip-diagram.png new file mode 100644 index 00000000..510f4f29 Binary files /dev/null and b/clab/ixp-openbgpd/ip-diagram.png differ diff --git a/clab/ixp-openbgpd/openbgpd.conf b/clab/ixp-openbgpd/openbgpd.conf new file mode 100644 index 00000000..9d197fd6 --- /dev/null +++ b/clab/ixp-openbgpd/openbgpd.conf @@ -0,0 +1,20 @@ +# example config for a test lab, DO NOT USE FOR PRODUCTION + +# global configuration +AS 65003 +router-id 10.0.0.3 + +# do not add our own AS (a route server behavior) in ASPATH +transparent-as yes + +group "route-server-clients" { + # IPv4 Peering LAN + neighbor 192.168.0.0/24 +} + +## in a lab we can as far as not doing any filtering +allow to ebgp +allow from ebgp + +# set's these communities to identify from where RS learned a route +match from any set large-community local-as:0:neighbor-as diff --git a/clab/ixp-openbgpd/otg.json b/clab/ixp-openbgpd/otg.json new file mode 100644 index 00000000..26a1404f --- /dev/null +++ b/clab/ixp-openbgpd/otg.json @@ -0,0 +1,214 @@ +{ + "ports": [ + { + "location": "localhost:5555+localhost:50071", + "name": "p1" + }, + { + "location": "localhost:5556+localhost:50072", + "name": "p2" + } + ], + "devices": [ + { + "ethernets": [ + { + "port_name": "p1", + "ipv4_addresses": [ + { + "gateway": "192.0.2.1", + "address": "192.0.2.2", + "prefix": 30, + "name": "otg1.eth[0].ipv4[0]" + } + ], + "mac": "02:00:00:00:01:aa", + "mtu": 1500, + "name": "otg1.eth[0]" + } + ], + "name": "otg1" + }, + { + "ethernets": [ + { + "port_name": "p2", + "ipv4_addresses": [ + { + "gateway": "203.0.113.1", + "address": "203.0.113.2", + "prefix": 30, + "name": "otg2.eth[0].ipv4[0]" + } + ], + "mac": "02:00:00:00:02:aa", + "mtu": 1500, + "name": "otg2.eth[0]" + } + ], + "name": "otg2" + } + ], + "flows": [ + { + "tx_rx": { + "choice": "device", + "device": { + "mode": "mesh", + "tx_names": [ + "otg1.eth[0].ipv4[0]" + ], + "rx_names": [ + "otg2.eth[0].ipv4[0]" + ] + } + }, + "packet": [ + { + "choice": "ethernet", + "ethernet": { + "src": { + "choice": "value", + "value": "02:00:00:00:01:aa" + } + } + }, + { + "choice": "ipv4", + "ipv4": { + "version": { + "choice": "value", + "value": 4 + }, + "src": { + "choice": "value", + "value": "192.0.2.2" + }, + "dst": { + "choice": "value", + "value": "203.0.113.2" + } + } + }, + { + "choice": "tcp", + "tcp": { + "src_port": { + "choice": "increment", + "increment": { + "start": 1024, + "step": 7, + "count": 64511 + } + }, + "dst_port": { + "choice": "value", + "value": 7 + } + } + } + ], + "size": { + "choice": "fixed", + "fixed": 256 + }, + "rate": { + "choice": "pps", + "pps": "100" + }, + "duration": { + "choice": "fixed_packets", + "fixed_packets": { + "packets": 1000, + "gap": 12 + } + }, + "metrics": { + "enable": true, + "loss": false, + "timestamps": false + }, + "name": "f1" + }, + { + "tx_rx": { + "choice": "device", + "device": { + "mode": "mesh", + "tx_names": [ + "otg2.eth[0].ipv4[0]" + ], + "rx_names": [ + "otg1.eth[0].ipv4[0]" + ] + } + }, + "packet": [ + { + "choice": "ethernet", + "ethernet": { + "src": { + "choice": "value", + "value": "02:00:00:00:02:aa" + } + } + }, + { + "choice": "ipv4", + "ipv4": { + "version": { + "choice": "value", + "value": 4 + }, + "dst": { + "choice": "value", + "value": "192.0.2.2" + }, + "src": { + "choice": "value", + "value": "203.0.113.2" + } + } + }, + { + "choice": "tcp", + "tcp": { + "src_port": { + "choice": "increment", + "increment": { + "start": 1024, + "step": 7, + "count": 64511 + } + }, + "dst_port": { + "choice": "value", + "value": 7 + } + } + } + ], + "size": { + "choice": "fixed", + "fixed": 256 + }, + "rate": { + "choice": "pps", + "pps": "100" + }, + "duration": { + "choice": "fixed_packets", + "fixed_packets": { + "packets": 1000, + "gap": 12 + } + }, + "metrics": { + "enable": true, + "loss": false, + "timestamps": false + }, + "name": "f2" + } + ] +} diff --git a/clab/ixp-openbgpd/srlinux.cfg b/clab/ixp-openbgpd/srlinux.cfg new file mode 100644 index 00000000..7855061f --- /dev/null +++ b/clab/ixp-openbgpd/srlinux.cfg @@ -0,0 +1,128 @@ +#### +# this configuration is in CLI format and can be pasted in the terminal +#### + +interface ethernet-1/1 { + admin-state enable + subinterface 0 { + admin-state enable + ipv4 { + address 192.168.0.1/24 { + } + } + } +} + +interface ethernet-1/2 { + admin-state enable + subinterface 0 { + admin-state enable + ipv4 { + address 192.0.2.1/30 { + } + } + } +} + +interface lo0 { + admin-state enable + subinterface 0 { + admin-state enable + ipv4 { + address 10.0.0.1/32 { + } + } + } +} + +routing-policy { + prefix-set loopback { + prefix 10.0.0.0/24 mask-length-range 24..32 { + } + } + prefix-set CE { + prefix 192.0.2.0/24 mask-length-range 24..32 { + } + prefix 1.1.1.0/24 mask-length-range 24..32 { + } + } + policy ixp_egress { + default-action { + reject { + } + } + statement 10 { + match { + prefix-set loopback + } + action { + accept { + } + } + } + statement 20 { + match { + prefix-set CE + } + action { + accept { + } + } + } + } + policy ingress_all { + default-action { + accept { + } + } + } +} + +network-instance default { + interface ethernet-1/1.0 { + } + interface ethernet-1/2.0 { + } + interface lo0.0 { + } + protocols { + bgp { + admin-state enable + autonomous-system 65001 + router-id 10.0.0.1 + group rs { + export-policy ixp_egress + import-policy ingress_all + peer-as 65003 + ipv4-unicast { + admin-state enable + } + timers { + connect-retry 1 + hold-time 9 + keepalive-interval 3 + minimum-advertisement-interval 1 + } + } + group otg { + import-policy ingress_all + peer-as 1111 + ipv4-unicast { + admin-state enable + } + timers { + connect-retry 1 + hold-time 9 + keepalive-interval 3 + minimum-advertisement-interval 1 + } + } + neighbor 192.168.0.3 { + peer-group rs + } + neighbor 192.0.2.2 { + peer-group otg + } + } + } +} \ No newline at end of file diff --git a/clab/ixp-openbgpd/topo.clab.yml b/clab/ixp-openbgpd/topo.clab.yml new file mode 100644 index 00000000..0058e3c5 --- /dev/null +++ b/clab/ixp-openbgpd/topo.clab.yml @@ -0,0 +1,109 @@ +name: obgpd + +topology: + nodes: + ixp: + kind: bridge + labels: + graph-level: 2 + graph-icon: switch + r1: + kind: nokia_srlinux + image: ghcr.io/nokia/srlinux:22.6.4 + startup-config: srlinux.cfg + labels: + graph-level: 3 + r2: + kind: arista_ceos + image: ceos:latest + startup-config: ceos.cfg + labels: + graph-level: 3 + openbgpd: + kind: linux + image: quay.io/openbgpd/openbgpd:7.7 + binds: + - ./openbgpd.conf:/etc/bgpd/bgpd.conf + exec: + - "ip address add dev eth1 192.168.0.3/24" + labels: + graph-level: 1 + graph-icon: server + otg: + kind: linux + image: ghcr.io/open-traffic-generator/licensed/ixia-c-controller:0.0.1-3587 + network-mode: host + cmd: --accept-eula --http-port 443 + ports: + - 443:443 + labels: + graph-hide: yes + te1: + kind: linux + image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.6.0.19 + ports: + - 5555:5555 + - 50071:50071 + env: + OPT_LISTEN_PORT: 5555 + ARG_IFACE_LIST: virtual@af_packet,eth1 + OPT_NO_HUGEPAGES: Yes + OPT_NO_PINNING: Yes + WAIT_FOR_IFACE: Yes + labels: + graph-level: 4 + graph-icon: server + pe1: + kind: linux + image: ghcr.io/open-traffic-generator/licensed/ixia-c-protocol-engine:1.00.0.236 + network-mode: container:te1 + startup-delay: 5 + env: + INTF_LIST: eth1 + labels: + graph-hide: yes + te2: + kind: linux + image: ghcr.io/open-traffic-generator/ixia-c-traffic-engine:1.6.0.19 + ports: + - 5556:5556 + - 50072:50071 + env: + OPT_LISTEN_PORT: 5556 + ARG_IFACE_LIST: virtual@af_packet,eth1 + OPT_NO_HUGEPAGES: Yes + OPT_NO_PINNING: Yes + WAIT_FOR_IFACE: Yes + labels: + graph-level: 4 + graph-icon: server + pe2: + kind: linux + image: ghcr.io/open-traffic-generator/licensed/ixia-c-protocol-engine:1.00.0.236 + network-mode: container:te2 + startup-delay: 5 + env: + INTF_LIST: eth1 + labels: + graph-hide: yes + + graphite: + kind: linux + image: netreplica/graphite:latest + env: + CLAB_SSH_CONNECTION: ${SSH_CONNECTION} + binds: + - __clabDir__/topology-data.json:/htdocs/default/default.json:ro + ports: + - 8080:80 + exec: + - sh -c 'graphite_motd.sh 8080' + labels: + graph-hide: yes + + links: + - endpoints: ["openbgpd:eth1", "ixp:eth3"] + - endpoints: ["r1:e1-1", "ixp:eth1"] + - endpoints: ["r1:e1-2", "te1:eth1"] + - endpoints: ["r2:eth1", "ixp:eth2"] + - endpoints: ["r2:eth2", "te2:eth1"] diff --git a/submodules/otgen b/submodules/otgen index 98177ab2..a25cdcb0 160000 --- a/submodules/otgen +++ b/submodules/otgen @@ -1 +1 @@ -Subproject commit 98177ab279fc8ac9dcc7b873da4ae583dc49f2bf +Subproject commit a25cdcb054b73e056c0417146ab37b1d9dfad873