diff --git a/README.md b/README.md
index 7263011..483d80a 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,16 @@ one Alpine linux container, in the following topology:
 
 ![learn-vpp](learn-vpp.png)
 
-You can deploy it using `containerlab deploy --topo vpp.clab.yml`.
+This container ships with both Bird2 and FRRouting as controlplane agents.
 
-Two relevant files for VPP are included in this repository:
+You can deploy:
+*   Bird2: `containerlab deploy --topo vpp-bird.clab.yml`.
+*   FRR: `containerlab deploy --topo vpp-frr.clab.yml`.
+
+three relevant files for VPP are included in this repository:
 1.   `config/vpp*/vppcfg.yaml` configures the dataplane interfaces, including a loopback address.
 1.   `config/vpp*/bird-local.conf` configures the controlplane to enable BFD and OSPF.
+1.   `config/vpp*/frr.conf` configures the controlplane to enable BFD and OSPF.
 
 Once the lab comes up, you can SSH to the VPP containers (`vpp1` and `vpp2`) which will have your
 SSH keys installed (if available). Otherwise, you can log in as user `root` using password `vpp`.
diff --git a/config/lab-frr.env b/config/lab-frr.env
new file mode 100644
index 0000000..c58f346
--- /dev/null
+++ b/config/lab-frr.env
@@ -0,0 +1,2 @@
+BIRD_ENABLED=false
+FRR_ENABLED=true
diff --git a/config/vpp1/frr.conf b/config/vpp1/frr.conf
new file mode 100644
index 0000000..e320dad
--- /dev/null
+++ b/config/vpp1/frr.conf
@@ -0,0 +1,34 @@
+frr version 10.3
+frr defaults traditional
+hostname vpp1
+log syslog informational
+service integrated-vtysh-config
+!
+ip router-id 10.82.98.0
+!
+interface eth2
+ ip ospf bfd
+ ip ospf cost 10
+ ip ospf network point-to-point
+ ipv6 ospf6 area 0
+ ipv6 ospf6 bfd
+ ipv6 ospf6 cost 10
+ ipv6 ospf6 network point-to-point
+exit
+!
+interface loop0
+ ip ospf passive
+exit
+!
+router ospf
+ redistribute connected
+ network 10.82.98.0/24 area 0
+exit
+!
+router ospf6
+ redistribute connected
+exit
+!
+bfd
+exit
+!
diff --git a/config/vpp2/frr.conf b/config/vpp2/frr.conf
new file mode 100644
index 0000000..93661ad
--- /dev/null
+++ b/config/vpp2/frr.conf
@@ -0,0 +1,31 @@
+frr version 10.3
+frr defaults traditional
+hostname vpp2
+log syslog informational
+service integrated-vtysh-config
+!
+ip router-id 10.82.98.1
+!
+interface eth2
+ ip ospf bfd
+ ip ospf cost 10
+ ip ospf network point-to-point
+ ipv6 ospf6 area 0
+ ipv6 ospf6 bfd
+ ipv6 ospf6 cost 10
+ ipv6 ospf6 network point-to-point
+exit
+!
+interface loop0
+ ip ospf passive
+exit
+!
+router ospf
+ redistribute connected
+ network 10.82.98.0/24 area 0
+exit
+!
+router ospf6
+ redistribute connected
+exit
+!
diff --git a/docker/Dockerfile.bookworm b/docker/Dockerfile.bookworm
index d68de1a..cc4acd6 100644
--- a/docker/Dockerfile.bookworm
+++ b/docker/Dockerfile.bookworm
@@ -17,9 +17,16 @@ RUN pip install --break-system-packages build netaddr yamale argparse pyyaml ipa
 RUN git clone https://git.ipng.ch/ipng/vppcfg.git && cd vppcfg && python3 -m build && \
     pip install --break-system-packages dist/vppcfg-*-py3-none-any.whl
 
+# Install FRR
+RUN curl -s -o /usr/share/keyrings/frrouting.gpg https://deb.frrouting.org/frr/keys.gpg && \
+   echo deb '[signed-by=/usr/share/keyrings/frrouting.gpg]' https://deb.frrouting.org/frr bookworm frr-stable \
+        > /etc/apt/sources.list.d/frr.list && \
+   apt -y update && apt -y install frr frr-pythontools && apt clean
+
 # Config files
 COPY files/etc/vpp/* /etc/vpp/
 COPY files/etc/bird/* /etc/bird/
+COPY files/etc/frr/* /etc/frr/
 COPY files/init-container.sh /sbin/
 RUN chmod 755 /sbin/init-container.sh
 CMD ["/sbin/init-container.sh"]
diff --git a/docker/files/etc/frr/daemons b/docker/files/etc/frr/daemons
new file mode 100644
index 0000000..da38b48
--- /dev/null
+++ b/docker/files/etc/frr/daemons
@@ -0,0 +1,17 @@
+# These are the daemons that FRR will use for VPP Containerlab
+# NOTE: we need to run in the 'dataplane' network namespace, and use the `dplane_fpm_nl` plugin
+bgpd=yes
+ospfd=yes
+ospf6d=yes
+bfdd=yes
+ldpd=yes
+
+vtysh_enable=yes
+watchfrr_options="--netns=dataplane"
+zebra_options="  -A 127.0.0.1 -s 67108864 -M dplane_fpm_nl"
+bgpd_options="   -A 127.0.0.1"
+ospfd_options="  -A 127.0.0.1"
+ospf6d_options=" -A ::1"
+staticd_options="-A 127.0.0.1"
+bfdd_options="   -A 127.0.0.1"
+ldpd_options="   -A 127.0.0.1"
diff --git a/docker/files/etc/frr/frr.conf b/docker/files/etc/frr/frr.conf
new file mode 100644
index 0000000..1e128d0
--- /dev/null
+++ b/docker/files/etc/frr/frr.conf
@@ -0,0 +1,10 @@
+# This is the VPP Containerlab default FRR configuration.
+
+frr defaults traditional
+log syslog informational
+ip forwarding
+ipv6 forwarding
+service integrated-vtysh-config
+!
+ip router-id 192.0.2.1
+!
diff --git a/docker/files/init-container.sh b/docker/files/init-container.sh
index 9920c26..d765775 100755
--- a/docker/files/init-container.sh
+++ b/docker/files/init-container.sh
@@ -5,6 +5,7 @@ CLAB_VPP_FILE=${CLAB_VPP_FILE:=/etc/vpp/clab.vpp}
 VPPCFG_VPP_FILE=${VPPCFG_VPP_FILE:=/etc/vpp/vppcfg.vpp}
 NETNS=${NETNS:="dataplane"}
 BIRD_ENABLED=${BIRD_ENABLED:="true"}
+FRR_ENABLED=${FRR_ENABLED:="false"}
 
 echo "Creating dataplane namespace"
 /usr/bin/mkdir -p /etc/netns/$NETNS
@@ -25,6 +26,13 @@ if [ "$BIRD_ENABLED" == "true" ]; then
   /usr/bin/nsenter --net=/var/run/netns/$NETNS /usr/sbin/bird -u bird -g bird
 fi
 
+if [ "$FRR_ENABLED" == "true" ]; then
+  echo "Starting FRRouting in $NETNS"
+  ROUTERID=$(ip -br a show eth0 | awk '{ print $3 }' | cut -f1 -d/)
+  sed -i -e "s,^ip router-id .*,ip router-id $ROUTERID," /etc/frr/frr.conf
+  /etc/init.d/frr start
+fi
+
 echo "Generating $CLAB_VPP_FILE"
 : > $CLAB_VPP_FILE
 MTU=9216
diff --git a/vpp-bird.clab.yml b/vpp-bird.clab.yml
new file mode 100644
index 0000000..f6ac1a2
--- /dev/null
+++ b/vpp-bird.clab.yml
@@ -0,0 +1,39 @@
+name: learn-vpp
+prefix: ""
+
+topology:
+  kinds:
+    fdio_vpp:
+      image: git.ipng.ch/ipng/vpp-containerlab:latest
+      startup-config: config/__clabNodeName__/vppcfg.yaml
+      binds:
+        - config/__clabNodeName__/bird-local.conf:/etc/bird/bird-local.conf:ro
+    linux:
+      image: alpine:latest
+
+  nodes:
+    vpp1:
+      kind: fdio_vpp
+    vpp2:
+      kind: fdio_vpp
+    client1:
+      kind: linux
+      exec:
+        - ip link set address 00:c1:ab:00:00:01 dev eth1
+        - ip addr add 10.82.98.66/28 dev eth1
+        - ip route add 10.82.98.0/24 via 10.82.98.65
+        - ip addr add 2001:db8:8298:101::2/64 dev eth1
+        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:101::1
+    client2:
+      kind: linux
+      exec:
+        - ip link set address 00:c1:ab:00:00:02 dev eth1
+        - ip addr add 10.82.98.82/28 dev eth1
+        - ip route add 10.82.98.0/24 via 10.82.98.81
+        - ip addr add 2001:db8:8298:102::2/64 dev eth1
+        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:102::1
+
+  links:
+    - endpoints: ["vpp1:eth2", "vpp2:eth2"]
+    - endpoints: ["client1:eth1", "vpp1:eth1"]
+    - endpoints: ["client2:eth1", "vpp2:eth1"]
diff --git a/vpp-frr.clab.yml b/vpp-frr.clab.yml
new file mode 100644
index 0000000..4aeaa39
--- /dev/null
+++ b/vpp-frr.clab.yml
@@ -0,0 +1,41 @@
+name: learn-vpp
+prefix: ""
+
+topology:
+  kinds:
+    fdio_vpp:
+      image: git.ipng.ch/ipng/vpp-containerlab:latest
+      startup-config: config/__clabNodeName__/vppcfg.yaml
+      binds:
+        - config/__clabNodeName__/frr.conf:/etc/frr/frr.conf
+      env-files:
+        - config/lab-frr.env
+    linux:
+      image: alpine:latest
+
+  nodes:
+    vpp1:
+      kind: fdio_vpp
+    vpp2:
+      kind: fdio_vpp
+    client1:
+      kind: linux
+      exec:
+        - ip link set address 00:c1:ab:00:00:01 dev eth1
+        - ip addr add 10.82.98.66/28 dev eth1
+        - ip route add 10.82.98.0/24 via 10.82.98.65
+        - ip addr add 2001:db8:8298:101::2/64 dev eth1
+        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:101::1
+    client2:
+      kind: linux
+      exec:
+        - ip link set address 00:c1:ab:00:00:02 dev eth1
+        - ip addr add 10.82.98.82/28 dev eth1
+        - ip route add 10.82.98.0/24 via 10.82.98.81
+        - ip addr add 2001:db8:8298:102::2/64 dev eth1
+        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:102::1
+
+  links:
+    - endpoints: ["vpp1:eth2", "vpp2:eth2"]
+    - endpoints: ["client1:eth1", "vpp1:eth1"]
+    - endpoints: ["client2:eth1", "vpp2:eth1"]
diff --git a/vpp.clab.yml b/vpp.clab.yml
deleted file mode 100644
index f6ac1a2..0000000
--- a/vpp.clab.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: learn-vpp
-prefix: ""
-
-topology:
-  kinds:
-    fdio_vpp:
-      image: git.ipng.ch/ipng/vpp-containerlab:latest
-      startup-config: config/__clabNodeName__/vppcfg.yaml
-      binds:
-        - config/__clabNodeName__/bird-local.conf:/etc/bird/bird-local.conf:ro
-    linux:
-      image: alpine:latest
-
-  nodes:
-    vpp1:
-      kind: fdio_vpp
-    vpp2:
-      kind: fdio_vpp
-    client1:
-      kind: linux
-      exec:
-        - ip link set address 00:c1:ab:00:00:01 dev eth1
-        - ip addr add 10.82.98.66/28 dev eth1
-        - ip route add 10.82.98.0/24 via 10.82.98.65
-        - ip addr add 2001:db8:8298:101::2/64 dev eth1
-        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:101::1
-    client2:
-      kind: linux
-      exec:
-        - ip link set address 00:c1:ab:00:00:02 dev eth1
-        - ip addr add 10.82.98.82/28 dev eth1
-        - ip route add 10.82.98.0/24 via 10.82.98.81
-        - ip addr add 2001:db8:8298:102::2/64 dev eth1
-        - ip route add 2001:db8:8298::/48 via 2001:db8:8298:102::1
-
-  links:
-    - endpoints: ["vpp1:eth2", "vpp2:eth2"]
-    - endpoints: ["client1:eth1", "vpp1:eth1"]
-    - endpoints: ["client2:eth1", "vpp2:eth1"]
diff --git a/vpp.clab.yml b/vpp.clab.yml
new file mode 120000
index 0000000..3d17018
--- /dev/null
+++ b/vpp.clab.yml
@@ -0,0 +1 @@
+vpp-bird.clab.yml
\ No newline at end of file