Skip to content

Commit 2ec1366

Browse files
authored
Merge pull request #5121 from tssurya/bgp-e2e-tests
Add BGP Tests: Phase1
2 parents 1fd9d3a + cbab417 commit 2ec1366

File tree

13 files changed

+615
-73
lines changed

13 files changed

+615
-73
lines changed

.github/workflows/test.yml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,8 @@ jobs:
414414
include:
415415
- {"target": "shard-conformance", "ha": "HA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-disabled"}
416416
- {"target": "shard-conformance", "ha": "noHA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
417+
- {"target": "shard-conformance", "ha": "HA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "routeadvertisements": "advertise-default"}
418+
- {"target": "shard-conformance", "ha": "HA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "routeadvertisements": "advertise-default"}
417419
- {"target": "shard-conformance", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv6", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
418420
- {"target": "shard-conformance", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
419421
- {"target": "control-plane", "ha": "HA", "gateway-mode": "shared", "ipfamily": "ipv6", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-disabled", "dns-name-resolver": "enable-dns-name-resolver"}
@@ -443,6 +445,8 @@ jobs:
443445
- {"target": "network-segmentation", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "dualstack", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-disabled"}
444446
- {"target": "network-segmentation", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
445447
- {"target": "network-segmentation", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv6", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
448+
- {"target": "bgp", "ha": "noHA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "routeadvertisements": "advertise-default"}
449+
- {"target": "bgp", "ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "snatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "routeadvertisements": "advertise-default"}
446450
- {"target": "traffic-flow-test-only","ha": "noHA", "gateway-mode": "shared", "ipfamily": "ipv4", "disable-snat-multiple-gws": "noSnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones", "traffic-flow-tests": "1-24"}
447451
- {"target": "tools", "ha": "noHA", "gateway-mode": "local", "ipfamily": "dualstack", "disable-snat-multiple-gws": "SnatGW", "second-bridge": "1br", "ic": "ic-single-node-zones"}
448452
needs: [ build-pr ]
@@ -458,8 +462,8 @@ jobs:
458462
OVN_SECOND_BRIDGE: "${{ matrix.second-bridge == '2br' }}"
459463
KIND_IPV4_SUPPORT: "${{ matrix.ipfamily == 'IPv4' || matrix.ipfamily == 'dualstack' }}"
460464
KIND_IPV6_SUPPORT: "${{ matrix.ipfamily == 'IPv6' || matrix.ipfamily == 'dualstack' }}"
461-
ENABLE_MULTI_NET: "${{ matrix.target == 'multi-homing' || matrix.target == 'kv-live-migration' || matrix.target == 'network-segmentation' || matrix.target == 'tools' || matrix.target == 'multi-homing-helm' || matrix.target == 'traffic-flow-test-only' }}"
462-
ENABLE_NETWORK_SEGMENTATION: "${{ matrix.target == 'network-segmentation' || matrix.target == 'tools' || matrix.target == 'kv-live-migration' || matrix.target == 'traffic-flow-test-only' }}"
465+
ENABLE_MULTI_NET: "${{ matrix.target == 'multi-homing' || matrix.target == 'kv-live-migration' || matrix.target == 'network-segmentation' || matrix.target == 'tools' || matrix.target == 'multi-homing-helm' || matrix.target == 'traffic-flow-test-only' || matrix.routeadvertisements != '' }}"
466+
ENABLE_NETWORK_SEGMENTATION: "${{ matrix.target == 'network-segmentation' || matrix.target == 'tools' || matrix.target == 'kv-live-migration' || matrix.target == 'traffic-flow-test-only' || matrix.target == 'bgp' }}"
463467
DISABLE_UDN_HOST_ISOLATION: "true"
464468
KIND_INSTALL_KUBEVIRT: "${{ matrix.target == 'kv-live-migration' }}"
465469
OVN_COMPACT_MODE: "${{ matrix.target == 'compact-mode' }}"
@@ -471,6 +475,8 @@ jobs:
471475
USE_HELM: "${{ matrix.target == 'control-plane-helm' || matrix.target == 'multi-homing-helm' }}"
472476
OVN_ENABLE_DNSNAMERESOLVER: "${{ matrix.dns-name-resolver == 'enable-dns-name-resolver' }}"
473477
TRAFFIC_FLOW_TESTS: "${{ matrix.traffic-flow-tests }}"
478+
ENABLE_ROUTE_ADVERTISEMENTS: "${{ matrix.routeadvertisements != '' }}"
479+
ADVERTISE_DEFAULT_NETWORK: "${{ matrix.routeadvertisements == 'advertise-default' }}"
474480
steps:
475481

476482
- name: Install VRF kernel module
@@ -514,6 +520,30 @@ jobs:
514520
echo OVN_TEST_EX_GW_NETWORK=kindexgw >> $GITHUB_ENV
515521
echo OVN_ENABLE_EX_GW_NETWORK_BRIDGE=true >> $GITHUB_ENV
516522
fi
523+
if [[ "$JOB_NAME" == *"shard-conformance"* ]] && [ "$ADVERTISE_DEFAULT_NETWORK" == "true" ]; then
524+
echo "ADVERTISE_DEFAULT_NETWORK=true" >> $GITHUB_ENV
525+
526+
# Use proper variable declaration with default values
527+
NET_CIDR_IPV4=${NET_CIDR_IPV4:-10.244.0.0/16}
528+
NET_CIDR_IPV6=${NET_CIDR_IPV6:-fd00:10:244::/48}
529+
530+
sudo ip a
531+
sudo ip r
532+
533+
# Add masquerade rules for both IPv4 and IPv6 networks
534+
echo "Adding masquerade rule for $NET_CIDR_IPV4"
535+
sudo iptables -t nat -A POSTROUTING -s $NET_CIDR_IPV4 -o eth0 -j MASQUERADE
536+
537+
echo "Adding masquerade rule for $NET_CIDR_IPV6"
538+
sudo ip6tables -t nat -A POSTROUTING -s $NET_CIDR_IPV6 -o eth0 -j MASQUERADE
539+
540+
# Verify the rules were added
541+
echo "IPv4 POSTROUTING rules:"
542+
sudo iptables -t nat -L POSTROUTING -v
543+
544+
echo "IPv6 POSTROUTING rules:"
545+
sudo ip6tables -t nat -L POSTROUTING -v
546+
fi
517547
518548
- name: Disable ufw
519549
# For IPv6 and Dualstack, ufw (Uncomplicated Firewall) should be disabled.
@@ -569,6 +599,8 @@ jobs:
569599
make -C test conformance
570600
elif [ "${{ matrix.target }}" == "network-segmentation" ]; then
571601
make -C test control-plane WHAT="Network Segmentation"
602+
elif [ "${{ matrix.target }}" == "bgp" ]; then
603+
make -C test control-plane WHAT="BGP"
572604
elif [ "${{ matrix.target }}" == "tools" ]; then
573605
make -C go-controller build
574606
make -C test tools

contrib/kind-common

Lines changed: 135 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -652,14 +652,23 @@ get_kubevirt_release_url() {
652652
echo "$kubevirt_release_url"
653653
}
654654

655-
readonly FRR_K8S_VERSION=v0.0.14
655+
readonly FRR_K8S_VERSION=v0.0.17
656656
readonly FRR_TMP_DIR=$(mktemp -d -u)
657657

658658
clone_frr() {
659659
[ -d "$FRR_TMP_DIR" ] || {
660660
mkdir -p "$FRR_TMP_DIR" && trap 'rm -rf $FRR_TMP_DIR' EXIT
661661
pushd "$FRR_TMP_DIR" || exit 1
662662
git clone --depth 1 --branch $FRR_K8S_VERSION https://github.com/metallb/frr-k8s
663+
664+
# Download the patches
665+
curl -Ls https://github.com/jcaamano/frr-k8s/archive/refs/heads/ovnk-bgp.tar.gz | tar xzvf - frr-k8s-ovnk-bgp/patches --strip-components 1
666+
667+
# Change into the cloned repo directory before applying patches
668+
pushd frr-k8s
669+
git apply ../patches/*
670+
popd
671+
663672
popd || exit 1
664673
}
665674
}
@@ -676,19 +685,86 @@ deploy_frr_external_container() {
676685
# can peer with acting as BGP (reflector) external gateway
677686
pushd "${FRR_TMP_DIR}"/frr-k8s/hack/demo || exit 1
678687
# modify config template to configure neighbors as route reflector clients
688+
# First check if IPv4 network already exists
689+
grep -q 'network '"${BGP_SERVER_NET_SUBNET_IPV4}" frr/frr.conf.tmpl || \
690+
sed -i '/address-family ipv4 unicast/a \ \ network '"${BGP_SERVER_NET_SUBNET_IPV4}"'' frr/frr.conf.tmpl
691+
692+
# Add route reflector client config
679693
sed -i '/remote-as 64512/a \ neighbor {{ . }} route-reflector-client' frr/frr.conf.tmpl
694+
695+
if [ "$KIND_IPV6_SUPPORT" == true ]; then
696+
# Check if IPv6 address-family section exists
697+
if ! grep -q 'address-family ipv6 unicast' frr/frr.conf.tmpl; then
698+
# Add IPv6 address-family section if it doesn't exist
699+
sed -i '/exit-address-family/a \ \
700+
address-family ipv6 unicast\
701+
network '"${BGP_SERVER_NET_SUBNET_IPV6}"'\
702+
exit-address-family' frr/frr.conf.tmpl
703+
else
704+
# Add network to existing IPv6 section
705+
sed -i '/address-family ipv6 unicast/a \ \ network '"${BGP_SERVER_NET_SUBNET_IPV6}"'' frr/frr.conf.tmpl
706+
fi
707+
708+
# Add route-reflector-client for IPv6 neighbors
709+
sed -i '/neighbor fc00.*remote-as 64512/a \ neighbor {{ . }} route-reflector-client' frr/frr.conf.tmpl
710+
fi
680711
./demo.sh
681712
popd || exit 1
713+
if [ "$KIND_IPV6_SUPPORT" == true ]; then
714+
# Enable IPv6 forwarding in FRR
715+
docker exec frr sysctl -w net.ipv6.conf.all.forwarding=1
716+
fi
717+
}
682718

683-
# this container will act as the gateway for the cluster and will masquerade
684-
# towards the external world
685-
$OCI_BIN exec frr iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
686-
# set default route
687-
FRR_IP=$($OCI_BIN inspect -f "{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" frr)
688-
KIND_NODES=$(kind_get_nodes)
689-
for n in $KIND_NODES; do
690-
$OCI_BIN exec "$n" ip route replace default via "$FRR_IP"
691-
done
719+
deploy_bgp_external_server() {
720+
# We create an external docker container that acts as the server (or client) outside the cluster
721+
# in the e2e tests that levergae router advertisements.
722+
# This container will be connected to the frr container deployed above to simulate a realistic
723+
# network topology
724+
# ----------------- ------------------ ---------------------
725+
# | | 172.26.0.0/16 | | 172.18.0.0/16 | ovn-control-plane |
726+
# | external |<------------- | FRR router |<------ KIND cluster -- ---------------------
727+
# | server | | | | ovn-worker | (client pod advertised
728+
# ----------------- ------------------ --------------------- using RouteAdvertisements
729+
# | ovn-worker2 | from default pod network)
730+
# ---------------------
731+
local ip_family ipv6_network
732+
if [ "$KIND_IPV4_SUPPORT" == true ] && [ "$KIND_IPV6_SUPPORT" == true ]; then
733+
ip_family="dual"
734+
ipv6_network="--ipv6 --subnet=${BGP_SERVER_NET_SUBNET_IPV6}"
735+
elif [ "$KIND_IPV6_SUPPORT" == true ]; then
736+
ip_family="ipv6"
737+
ipv6_network="--ipv6 --subnet=${BGP_SERVER_NET_SUBNET_IPV6}"
738+
else
739+
ip_family="ipv4"
740+
ipv6_network=""
741+
fi
742+
docker network create --subnet="${BGP_SERVER_NET_SUBNET_IPV4}" ${ipv6_network} --driver bridge bgpnet
743+
docker network connect bgpnet frr
744+
docker run --cap-add NET_ADMIN --user 0 -d --network bgpnet --rm --name bgpserver -p 8080:8080 registry.k8s.io/e2e-test-images/agnhost:2.45 netexec
745+
# let's make the bgp external server have its default route towards FRR router so that we don't need to add routes during tests back to the pods in the
746+
# cluster for return traffic
747+
local bgp_network_frr_v4 bgp_network_frr_v6
748+
bgp_network_frr_v4=$($OCI_BIN inspect -f '{{index .NetworkSettings.Networks "bgpnet" "IPAddress"}}' frr)
749+
echo "FRR kind network IPv4: ${bgp_network_frr_v4}"
750+
$OCI_BIN exec bgpserver ip route replace default via "$bgp_network_frr_v4"
751+
if [ "$KIND_IPV6_SUPPORT" == true ] ; then
752+
bgp_network_frr_v6=$($OCI_BIN inspect -f '{{index .NetworkSettings.Networks "bgpnet" "GlobalIPv6Address"}}' frr)
753+
echo "FRR kind network IPv6: ${bgp_network_frr_v6}"
754+
$OCI_BIN exec bgpserver ip -6 route replace default via "$bgp_network_frr_v6"
755+
fi
756+
}
757+
758+
destroy_bgp() {
759+
if docker ps --format '{{.Names}}' | grep -Eq '^bgpserver$'; then
760+
docker stop bgpserver
761+
fi
762+
if docker ps --format '{{.Names}}' | grep -Eq '^frr$'; then
763+
docker stop frr
764+
fi
765+
if docker network ls --format '{{.Name}}' | grep -q '^bgpnet$'; then
766+
docker network rm bgpnet
767+
fi
692768
}
693769

694770
install_ffr_k8s() {
@@ -703,9 +779,57 @@ install_ffr_k8s() {
703779
# apply a BGP peer configration with the external gateway that does not
704780
# exchange routes
705781
pushd "${FRR_TMP_DIR}"/frr-k8s/hack/demo/configs || exit 1
706-
sed 's/all$/filtered/g' receive_all.yaml > receive_filtered.yaml
782+
sed 's/mode: all/mode: filtered/g' receive_all.yaml > receive_filtered.yaml
783+
# Allow receiving the bgp external server's prefix
784+
sed -i '/mode: filtered/a\ prefixes:\n - prefix: '"${BGP_SERVER_NET_SUBNET_IPV4}"'' receive_filtered.yaml
785+
# If IPv6 is enabled, add the IPv6 prefix as well
786+
if [ "$KIND_IPV6_SUPPORT" == true ]; then
787+
# Find all line numbers where the IPv4 prefix is defined
788+
IPv6_LINE=" - prefix: ${BGP_SERVER_NET_SUBNET_IPV6}"
789+
# Process each occurrence of the IPv4 prefix
790+
for LINE_NUM in $(grep -n "prefix: ${BGP_SERVER_NET_SUBNET_IPV4}" receive_filtered.yaml | cut -d ':' -f 1); do
791+
# Insert the IPv6 prefix after each IPv4 prefix line
792+
sed -i "${LINE_NUM}a\\${IPv6_LINE}" receive_filtered.yaml
793+
done
794+
fi
707795
kubectl apply -f receive_filtered.yaml
708796
popd || exit 1
709797

710798
rm -rf "${FRR_TMP_DIR}"
799+
# Add routes for pod networks dynamically into the github runner for return traffic to pass back
800+
if [ -n "${JOB_NAME:-}" ] && [[ "$JOB_NAME" == *"shard-conformance"* ]] && [ "$ADVERTISE_DEFAULT_NETWORK" == "true" ]; then
801+
echo "Adding routes for Kubernetes pod networks..."
802+
NODES=$(kubectl get nodes -o jsonpath='{.items[*].metadata.name}')
803+
echo "Found nodes: $NODES"
804+
for node in $NODES; do
805+
# Get the addresses
806+
node_ips=$(kubectl get node $node -o jsonpath='{.status.addresses[?(@.type=="InternalIP")].address}')
807+
# Get subnet information
808+
subnet_json=$(kubectl get node $node -o jsonpath='{.metadata.annotations.k8s\.ovn\.org/node-subnets}')
809+
810+
if [ "$KIND_IPV4_SUPPORT" == true ]; then
811+
# Extract IPv4 address (first address)
812+
node_ipv4=$(echo "$node_ips" | awk '{print $1}')
813+
ipv4_subnet=$(echo "$subnet_json" | jq -r '.default[0]')
814+
815+
# Add IPv4 route
816+
if [ -n "$ipv4_subnet" ] && [ -n "$node_ipv4" ]; then
817+
echo "Adding IPv4 route for $node ($node_ipv4): $ipv4_subnet"
818+
sudo ip route add $ipv4_subnet via $node_ipv4
819+
fi
820+
fi
821+
822+
# Add IPv6 route if enabled
823+
if [ "$KIND_IPV6_SUPPORT" == true ]; then
824+
# Extract IPv6 address (second address, if present)
825+
node_ipv6=$(echo "$node_ips" | awk '{print $2}')
826+
ipv6_subnet=$(echo "$subnet_json" | jq -r '.default[1] // empty')
827+
828+
if [ -n "$ipv6_subnet" ] && [ -n "$node_ipv6" ]; then
829+
echo "Adding IPv6 route for $node ($node_ipv6): $ipv6_subnet"
830+
sudo ip -6 route add $ipv6_subnet via $node_ipv6
831+
fi
832+
fi
833+
done
834+
fi
711835
}

contrib/kind.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ delete() {
4545
if [ "$KIND_INSTALL_METALLB" == true ]; then
4646
destroy_metallb
4747
fi
48+
if [ "$ENABLE_ROUTE_ADVERTISEMENTS" == true ]; then
49+
destroy_bgp
50+
fi
4851
timeout 5 kubectl --kubeconfig "${KUBECONFIG}" delete namespace ovn-kubernetes || true
4952
sleep 5
5053
kind delete cluster --name "${KIND_CLUSTER_NAME:-ovn}"
@@ -78,6 +81,7 @@ usage() {
7881
echo " [-cm | --compact-mode]"
7982
echo " [-ic | --enable-interconnect]"
8083
echo " [-rae | --enable-route-advertisements]"
84+
echo " [-adv | --advertise-default-network]"
8185
echo " [--isolated]"
8286
echo " [-dns | --enable-dnsnameresolver]"
8387
echo " [-obs | --observability]"
@@ -147,6 +151,7 @@ usage() {
147151
echo "-dns | --enable-dnsnameresolver Enable DNSNameResolver for resolving the DNS names used in the DNS rules of EgressFirewall."
148152
echo "-obs | --observability Enable OVN Observability feature."
149153
echo "-rae | --enable-route-advertisements Enable route advertisements"
154+
echo "-adv | --advertise-default-network Applies a RouteAdvertisements configuration to advertise the default network on all nodes"
150155
echo ""
151156
}
152157

@@ -332,6 +337,8 @@ parse_args() {
332337
;;
333338
-rae | --route-advertisements-enable) ENABLE_ROUTE_ADVERTISEMENTS=true
334339
;;
340+
-adv | --advertise-default-network) ADVERTISE_DEFAULT_NETWORK=true
341+
;;
335342
-ic | --enable-interconnect ) OVN_ENABLE_INTERCONNECT=true
336343
;;
337344
--disable-ovnkube-identity) OVN_ENABLE_OVNKUBE_IDENTITY=false
@@ -422,6 +429,7 @@ print_params() {
422429
echo "ENABLE_MULTI_NET = $ENABLE_MULTI_NET"
423430
echo "ENABLE_NETWORK_SEGMENTATION= $ENABLE_NETWORK_SEGMENTATION"
424431
echo "ENABLE_ROUTE_ADVERTISEMENTS= $ENABLE_ROUTE_ADVERTISEMENTS"
432+
echo "ADVERTISE_DEFAULT_NETWORK = $ADVERTISE_DEFAULT_NETWORK"
425433
echo "OVN_ENABLE_INTERCONNECT = $OVN_ENABLE_INTERCONNECT"
426434
if [ "$OVN_ENABLE_INTERCONNECT" == true ]; then
427435
echo "KIND_NUM_NODES_PER_ZONE = $KIND_NUM_NODES_PER_ZONE"
@@ -581,6 +589,8 @@ set_default_params() {
581589
TRANSIT_SWITCH_SUBNET_IPV6=${TRANSIT_SWITCH_SUBNET_IPV6:-fd97::/64}
582590
METALLB_CLIENT_NET_SUBNET_IPV4=${METALLB_CLIENT_NET_SUBNET_IPV4:-172.22.0.0/16}
583591
METALLB_CLIENT_NET_SUBNET_IPV6=${METALLB_CLIENT_NET_SUBNET_IPV6:-fc00:f853:ccd:e792::/64}
592+
BGP_SERVER_NET_SUBNET_IPV4=${BGP_SERVER_NET_SUBNET_IPV4:-172.26.0.0/16}
593+
BGP_SERVER_NET_SUBNET_IPV6=${BGP_SERVER_NET_SUBNET_IPV6:-fc00:f853:ccd:e796::/64}
584594

585595
KIND_NUM_MASTER=1
586596
OVN_ENABLE_INTERCONNECT=${OVN_ENABLE_INTERCONNECT:-false}
@@ -634,6 +644,7 @@ set_default_params() {
634644
echo "Route advertisements requires interconnect to be enabled (-ic)"
635645
exit 1
636646
fi
647+
ADVERTISE_DEFAULT_NETWORK=${ADVERTISE_DEFAULT_NETWORK:-false}
637648
OVN_COMPACT_MODE=${OVN_COMPACT_MODE:-false}
638649
if [ "$OVN_COMPACT_MODE" == true ]; then
639650
KIND_NUM_WORKER=0
@@ -875,6 +886,7 @@ create_ovn_kube_manifests() {
875886
--multi-network-enable="${ENABLE_MULTI_NET}" \
876887
--network-segmentation-enable="${ENABLE_NETWORK_SEGMENTATION}" \
877888
--route-advertisements-enable="${ENABLE_ROUTE_ADVERTISEMENTS}" \
889+
--advertise-default-network="${ADVERTISE_DEFAULT_NETWORK}" \
878890
--ovnkube-metrics-scale-enable="${OVN_METRICS_SCALE_ENABLE}" \
879891
--compact-mode="${OVN_COMPACT_MODE}" \
880892
--enable-interconnect="${OVN_ENABLE_INTERCONNECT}" \
@@ -1176,6 +1188,7 @@ if [ "$OVN_ENABLE_DNSNAMERESOLVER" == true ]; then
11761188
fi
11771189
if [ "$ENABLE_ROUTE_ADVERTISEMENTS" == true ]; then
11781190
deploy_frr_external_container
1191+
deploy_bgp_external_server
11791192
fi
11801193
build_ovn_image
11811194
detect_apiserver_url

0 commit comments

Comments
 (0)