From 0e01e058a142eaf4cded020cc280ce6251fdb9b1 Mon Sep 17 00:00:00 2001
From: Michael Polenchuk <mpolenchuk@mirantis.com>
Date: Thu, 27 Jun 2019 13:40:13 +0400
Subject: [PATCH] [neutron] Bring in bgpvpn/bagpipe support

BGP-MPLS VPN extension allows attachment of Neutron networks and/or
routers to VPNs built in carrier provided WANs using these standard
protocols.

Change-Id: Ib0ec8cb22e9c113d4be1c992d895b565db5e30b0
---
 .../bin/_neutron-bagpipe-bgp-init.sh.tpl      |  40 ++++
 .../templates/bin/_neutron-bagpipe-bgp.sh.tpl |  20 ++
 neutron/templates/configmap-bin.yaml          |   4 +
 neutron/templates/configmap-etc.yaml          |   1 +
 neutron/templates/daemonset-bagpipe-bgp.yaml  | 175 ++++++++++++++++++
 neutron/values.yaml                           |  77 ++++++++
 .../values_overrides/pike-ubuntu_xenial.yaml  |   1 +
 .../queens-ubuntu_xenial.yaml                 |   1 +
 .../values_overrides/rocky-opensuse_15.yaml   |   1 +
 .../values_overrides/rocky-ubuntu_bionic.yaml |   1 +
 .../values_overrides/rocky-ubuntu_xenial.yaml |   1 +
 .../backends/networking/bagpipe_bgp.yaml      |  34 ++++
 12 files changed, 356 insertions(+)
 create mode 100644 neutron/templates/bin/_neutron-bagpipe-bgp-init.sh.tpl
 create mode 100644 neutron/templates/bin/_neutron-bagpipe-bgp.sh.tpl
 create mode 100644 neutron/templates/daemonset-bagpipe-bgp.yaml
 create mode 100644 tools/overrides/backends/networking/bagpipe_bgp.yaml

diff --git a/neutron/templates/bin/_neutron-bagpipe-bgp-init.sh.tpl b/neutron/templates/bin/_neutron-bagpipe-bgp-init.sh.tpl
new file mode 100644
index 0000000000..5df2cecdf9
--- /dev/null
+++ b/neutron/templates/bin/_neutron-bagpipe-bgp-init.sh.tpl
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+{{/*
+Copyright 2019 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+set -ex
+
+{{- if (has "openvswitch" .Values.network.backend) }}
+chown neutron: /run/openvswitch/db.sock
+{{- end }}
+
+# handle any bridge mappings
+for bmap in `sed 's/[{}"]//g' /tmp/auto_bridge_add | tr "," "\n"`; do
+  bridge=${bmap%:*}
+  iface=${bmap#*:}
+{{- if (has "openvswitch" .Values.network.backend) }}
+  ovs-vsctl --no-wait --may-exist add-br $bridge
+  if [ -n "$iface" -a "$iface" != "null" ]; then
+    ovs-vsctl --no-wait --may-exist add-port $bridge $iface
+    ip link set dev $iface up
+  fi
+{{- else if (has "linuxbridge" .Values.network.backend) }}
+  set +e; ip link add name $bridge type bridge; set -e
+  ip link set dev $bridge up
+  [ -n "$iface" -a "$iface" != "null" ] && ip link set dev $iface master $bridge
+{{- end }}
+done
diff --git a/neutron/templates/bin/_neutron-bagpipe-bgp.sh.tpl b/neutron/templates/bin/_neutron-bagpipe-bgp.sh.tpl
new file mode 100644
index 0000000000..bbb5c6c979
--- /dev/null
+++ b/neutron/templates/bin/_neutron-bagpipe-bgp.sh.tpl
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+{{/*
+Copyright 2019 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+set -x
+exec bagpipe-bgp
diff --git a/neutron/templates/configmap-bin.yaml b/neutron/templates/configmap-bin.yaml
index 1e03ce3cb7..d36cb1b857 100644
--- a/neutron/templates/configmap-bin.yaml
+++ b/neutron/templates/configmap-bin.yaml
@@ -73,6 +73,10 @@ data:
 {{ tuple "bin/_neutron-sriov-agent-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
   neutron-l2gw-agent.sh: |
 {{ tuple "bin/_neutron-l2gw-agent.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  neutron-bagpipe-bgp.sh: |
+{{ tuple "bin/_neutron-bagpipe-bgp.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  neutron-bagpipe-bgp-init.sh: |
+{{ tuple "bin/_neutron-bagpipe-bgp-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
   neutron-server.sh: |
 {{ tuple "bin/_neutron-server.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
   rabbit-init.sh: |
diff --git a/neutron/templates/configmap-etc.yaml b/neutron/templates/configmap-etc.yaml
index 251e51b34f..b07f16fb05 100644
--- a/neutron/templates/configmap-etc.yaml
+++ b/neutron/templates/configmap-etc.yaml
@@ -196,6 +196,7 @@ data:
   openvswitch_agent.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.openvswitch_agent | b64enc }}
   sriov_agent.ini: {{ include "helm-toolkit.utils.to_oslo_conf" $envAll.Values.conf.plugins.sriov_agent | b64enc }}
   l2gw_agent.ini: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.l2gateway_agent | b64enc) }}
+  bagpipe_bgp.conf: {{ default "\"\"" (include "helm-toolkit.utils.to_oslo_conf" .Values.conf.bagpipe_bgp | b64enc) }}
   dnsmasq.conf: ""
   neutron_sudoers: {{ $envAll.Values.conf.neutron_sudoers | b64enc }}
   rootwrap.conf: {{ $envAll.Values.conf.rootwrap | b64enc }}
diff --git a/neutron/templates/daemonset-bagpipe-bgp.yaml b/neutron/templates/daemonset-bagpipe-bgp.yaml
new file mode 100644
index 0000000000..458c40f0db
--- /dev/null
+++ b/neutron/templates/daemonset-bagpipe-bgp.yaml
@@ -0,0 +1,175 @@
+{{/*
+Copyright 2019 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- define "neutron.bagpipe_bgp.daemonset" }}
+{{- $daemonset := index . 0 }}
+{{- $configMapName := index . 1 }}
+{{- $serviceAccountName := index . 2 }}
+{{- $envAll := index . 3 }}
+{{- with $envAll }}
+
+{{- $mounts_neutron_bagpipe_bgp := .Values.pod.mounts.bagpipe_bgp.bagpipe_bgp }}
+{{- $mounts_neutron_bagpipe_bgp_init := .Values.pod.mounts.bagpipe_bgp.init_container }}
+
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  name: bagpipe-bgp
+  annotations:
+    {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }}
+  labels:
+{{ tuple $envAll "neutron" "bagpipe-bgp" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  selector:
+    matchLabels:
+{{ tuple $envAll "neutron" "bagpipe-bgp" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 6 }}
+{{ tuple $envAll "bagpipe_bgp" | include "helm-toolkit.snippets.kubernetes_upgrades_daemonset" | indent 2 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "neutron" "bagpipe-bgp" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+      annotations:
+{{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" | indent 8 }}
+        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
+        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
+    spec:
+{{ dict "envAll" $envAll "application" "neutron_bagpipe_bgp" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 6 }}
+      serviceAccountName: {{ $serviceAccountName }}
+      nodeSelector:
+        {{ .Values.labels.bagpipe_bgp.node_selector_key }}: {{ .Values.labels.bagpipe_bgp.node_selector_value }}
+      dnsPolicy: ClusterFirstWithHostNet
+      hostNetwork: true
+      {{- if or ( gt .Capabilities.KubeVersion.Major "1" ) ( ge .Capabilities.KubeVersion.Minor "10" ) }}
+      shareProcessNamespace: true
+      {{- else }}
+      hostPID: true
+      {{- end }}
+      initContainers:
+{{ tuple $envAll "pod_dependency" $mounts_neutron_bagpipe_bgp_init | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+        - name: neutron-bagpipe-bgp-init
+{{ tuple $envAll "neutron_bagpipe_bgp" | include "helm-toolkit.snippets.image" | indent 10 }}
+          securityContext:
+            privileged: true
+            runAsUser: 0
+          command:
+            - /tmp/neutron-bagpipe-bgp-init.sh
+          volumeMounts:
+            - name: pod-tmp
+              mountPath: /tmp
+            - name: neutron-bin
+              mountPath: /tmp/neutron-bagpipe-bgp-init.sh
+              subPath: neutron-bagpipe-bgp-init.sh
+              readOnly: true
+            - name: run
+              mountPath: /run
+      containers:
+        - name: neutron-bagpipe-bgp
+{{ tuple $envAll "neutron_bagpipe_bgp" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.agent.bagpipe_bgp | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+{{ dict "envAll" $envAll "application" "neutron_bagpipe_bgp" "container" "neutron_bagpipe_bgp" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 10 }}
+          readinessProbe:
+            tcpSocket:
+              port: {{ tuple "network" "internal" "api" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+          livenessProbe:
+            tcpSocket:
+              port: {{ tuple "network" "internal" "api" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+            initialDelaySeconds: 60
+          command:
+            - /tmp/neutron-bagpipe-bgp.sh
+          volumeMounts:
+            - name: pod-tmp
+              mountPath: /tmp
+            - name: pod-var-neutron
+              mountPath: /var/lib/neutron
+            - name: neutron-bin
+              mountPath: /tmp/neutron-bagpipe-bgp.sh
+              subPath: neutron-bagpipe-bgp.sh
+              readOnly: true
+            - name: neutron-bin
+              mountPath: /tmp/health-probe.py
+              subPath: health-probe.py
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /tmp/auto_bridge_add
+              subPath: auto_bridge_add
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /etc/bagpipe-bgp/bgp.conf
+              subPath: bagpipe_bgp.conf
+              readOnly: true
+            - name: neutron-etc
+              # NOTE (Portdirect): We mount here to override Kollas
+              # custom sudoers file when using Kolla images, this
+              # location will also work fine for other images.
+              mountPath: /etc/sudoers.d/kolla_neutron_sudoers
+              subPath: neutron_sudoers
+              readOnly: true
+            - name: neutron-etc
+              mountPath: /etc/neutron/rootwrap.conf
+              subPath: rootwrap.conf
+              readOnly: true
+            {{- range $key, $value := $envAll.Values.conf.rootwrap_filters }}
+            {{- if ( has "bagpipe_bgp" $value.pods ) }}
+            {{- $filePrefix := replace "_" "-"  $key }}
+            {{- $rootwrapFile := printf "/etc/neutron/rootwrap.d/%s.filters" $filePrefix }}
+            - name: neutron-etc
+              mountPath: {{ $rootwrapFile }}
+              subPath: {{ base $rootwrapFile }}
+              readOnly: true
+            {{- end }}
+            {{- end }}
+            - name: libmodules
+              mountPath: /lib/modules
+              readOnly: true
+            - name: run
+              mountPath: /run
+{{ if $mounts_neutron_bagpipe_bgp.volumeMounts }}{{ toYaml $mounts_neutron_bagpipe_bgp.volumeMounts | indent 12 }}{{ end }}
+      volumes:
+        - name: pod-tmp
+          emptyDir: {}
+        - name: pod-var-neutron
+          emptyDir: {}
+        - name: neutron-bin
+          configMap:
+            name: neutron-bin
+            defaultMode: 0555
+        - name: neutron-etc
+          secret:
+            secretName: {{ $configMapName }}
+            defaultMode: 0444
+        - name: libmodules
+          hostPath:
+            path: /lib/modules
+        - name: run
+          hostPath:
+            path: /run
+{{ if $mounts_neutron_bagpipe_bgp.volumes }}{{ toYaml $mounts_neutron_bagpipe_bgp.volumes | indent 8 }}{{ end }}
+{{- end }}
+{{- end }}
+
+{{- if .Values.manifests.daemonset_bagpipe_bgp }}
+{{- $envAll := . }}
+{{- $daemonset := "bagpipe-bgp" }}
+{{- $configMapName := "neutron-etc" }}
+{{- $serviceAccountName := "neutron-bagpipe-bgp" }}
+{{- $dependencyOpts := dict "envAll" $envAll "dependencyMixinParam" $envAll.Values.network.backend "dependencyKey" "bagpipe_bgp" -}}
+{{- $_ := include "helm-toolkit.utils.dependency_resolver" $dependencyOpts | toString | fromYaml }}
+{{ tuple $envAll "pod_dependency" $serviceAccountName | include "helm-toolkit.snippets.kubernetes_pod_rbac_serviceaccount" }}
+{{- $daemonset_yaml := list $daemonset $configMapName $serviceAccountName . | include "neutron.bagpipe_bgp.daemonset" | toString | fromYaml }}
+{{- $configmap_yaml := "neutron.configmap.etc" }}
+{{- list $daemonset $daemonset_yaml $configmap_yaml $configMapName . | include "helm-toolkit.utils.daemonset_overrides" }}
+{{- end }}
diff --git a/neutron/values.yaml b/neutron/values.yaml
index c139b13682..88058d562c 100644
--- a/neutron/values.yaml
+++ b/neutron/values.yaml
@@ -39,6 +39,7 @@ images:
     neutron_linuxbridge_agent: docker.io/openstackhelm/neutron:ocata-ubuntu_xenial
     neutron_sriov_agent: docker.io/openstackhelm/neutron:ocata-18.04-sriov
     neutron_sriov_agent_init: docker.io/openstackhelm/neutron:ocata-18.04-sriov
+    neutron_bagpipe_bgp: docker.io/openstackhelm/neutron:ocata-ubuntu_xenial
     dep_check: quay.io/stackanetes/kubernetes-entrypoint:v0.3.1
     image_repo_sync: docker.io/docker:17.07.0
   pull_policy: "IfNotPresent"
@@ -78,6 +79,9 @@ labels:
   sriov:
     node_selector_key: sriov
     node_selector_value: enabled
+  bagpipe_bgp:
+    node_selector_key: openstack-compute-node
+    node_selector_value: enabled
   server:
     node_selector_key: openstack-control-plane
     node_selector_value: enabled
@@ -139,6 +143,7 @@ dependencies:
     targeted:
       sriov: {}
       l2gateway: {}
+      bagpipe_bgp: {}
       openvswitch:
         dhcp:
           pod:
@@ -392,6 +397,13 @@ pod:
     neutron_l2gw_agent:
       pod:
         runAsUser: 42424
+    neutron_bagpipe_bgp:
+      pod:
+        runAsUser: 42424
+      container:
+        neutron_bagpipe_bgp:
+          readOnlyRootFilesystem: true
+          privileged: true
     neutron_l3_agent:
       pod:
         runAsUser: 42424
@@ -489,6 +501,11 @@ pod:
       neutron_l2gw_agent:
         volumeMounts:
         volumes:
+    bagpipe_bgp:
+      init_container: null
+      bagpipe_bgp:
+        volumeMounts:
+        volumes:
     neutron_tests:
       init_container: null
       neutron_tests:
@@ -601,6 +618,13 @@ pod:
         limits:
           memory: "1024Mi"
           cpu: "2000m"
+      bagpipe_bgp:
+        requests:
+          memory: "128Mi"
+          cpu: "100m"
+        limits:
+          memory: "1024Mi"
+          cpu: "2000m"
     server:
       requests:
         memory: "128Mi"
@@ -1646,6 +1670,57 @@ conf:
         # This is needed to allow taas to insert/remove vlan id to the
         # target vf under /sys/class/net/[device-name]/device/sriov/[vf-index]/[mirror]
         i40e_sysfs_command: RegExpFilter, i40e_sysfs_command, root, i40e_sysfs_command, \w+, .+, .+
+    linux_vxlan:
+      pods:
+        - bagpipe_bgp
+      content: |
+        # bagpipe-bgp-rootwrap command filters for nodes on which bagpipe-bgp is
+        # expected to control VXLAN Linux Bridge dataplane
+        #
+        # This file should be owned by (and only-writeable by) the root user
+
+        # format seems to be
+        # cmd-name: filter-name, raw-command, user, args
+
+        [Filters]
+
+        #
+        modprobe: CommandFilter, modprobe, root
+
+        #
+        brctl: CommandFilter, brctl, root
+        bridge: CommandFilter, bridge, root
+
+        # ip_lib
+        ip: IpFilter, ip, root
+        ip_exec: IpNetnsExecFilter, ip, root
+
+        # shell (for piped commands)
+        sh: CommandFilter, sh, root
+    mpls_ovs_dataplane:
+      pods:
+        - bagpipe_bgp
+      content: |
+        # bagpipe-bgp-rootwrap command filters for nodes on which bagpipe-bgp is
+        # expected to control MPLS OpenVSwitch dataplane
+        #
+        # This file should be owned by (and only-writeable by) the root user
+
+        # format seems to be
+        # cmd-name: filter-name, raw-command, user, args
+
+        [Filters]
+
+        # openvswitch
+        ovs-vsctl: CommandFilter, ovs-vsctl, root
+        ovs-ofctl: CommandFilter, ovs-ofctl, root
+
+        # ip_lib
+        ip: IpFilter, ip, root
+        ip_exec: IpNetnsExecFilter, ip, root
+
+        # shell (for piped commands)
+        sh: CommandFilter, sh, root
   neutron:
     DEFAULT:
       log_config_append: /etc/neutron/logging.conf
@@ -1834,6 +1909,7 @@ conf:
     cache:
       enabled: true
       backend: dogpile.cache.memcached
+  bagpipe_bgp: {}
 
   rabbitmq:
     #NOTE(rk760n): adding rmq policy to mirror messages from notification queues and set expiration time for the ones
@@ -2104,6 +2180,7 @@ manifests:
   daemonset_ovs_agent: true
   daemonset_sriov_agent: true
   daemonset_l2gw_agent: false
+  daemonset_bagpipe_bgp: false
   deployment_server: true
   ingress_server: true
   job_bootstrap: true
diff --git a/neutron/values_overrides/pike-ubuntu_xenial.yaml b/neutron/values_overrides/pike-ubuntu_xenial.yaml
index 90158f8969..8458fc05ad 100644
--- a/neutron/values_overrides/pike-ubuntu_xenial.yaml
+++ b/neutron/values_overrides/pike-ubuntu_xenial.yaml
@@ -15,3 +15,4 @@ images:
     neutron_metadata: "docker.io/openstackhelm/neutron:pike-ubuntu_xenial"
     neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:pike-ubuntu_xenial"
     neutron_server: "docker.io/openstackhelm/neutron:pike-ubuntu_xenial"
+    neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:pike-ubuntu_xenial"
diff --git a/neutron/values_overrides/queens-ubuntu_xenial.yaml b/neutron/values_overrides/queens-ubuntu_xenial.yaml
index 1d0c32eeab..ef332bc235 100644
--- a/neutron/values_overrides/queens-ubuntu_xenial.yaml
+++ b/neutron/values_overrides/queens-ubuntu_xenial.yaml
@@ -15,3 +15,4 @@ images:
     neutron_metadata: "docker.io/openstackhelm/neutron:queens-ubuntu_xenial"
     neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:queens-ubuntu_xenial"
     neutron_server: "docker.io/openstackhelm/neutron:queens-ubuntu_xenial"
+    neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:queens-ubuntu_xenial"
diff --git a/neutron/values_overrides/rocky-opensuse_15.yaml b/neutron/values_overrides/rocky-opensuse_15.yaml
index 72f5de80f4..1dd621ac0f 100644
--- a/neutron/values_overrides/rocky-opensuse_15.yaml
+++ b/neutron/values_overrides/rocky-opensuse_15.yaml
@@ -15,3 +15,4 @@ images:
     neutron_metadata: "docker.io/openstackhelm/neutron:rocky-opensuse_15"
     neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:rocky-opensuse_15"
     neutron_server: "docker.io/openstackhelm/neutron:rocky-opensuse_15"
+    neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:rocky-opensuse_15"
diff --git a/neutron/values_overrides/rocky-ubuntu_bionic.yaml b/neutron/values_overrides/rocky-ubuntu_bionic.yaml
index f5c20ff90e..3e2598ae81 100644
--- a/neutron/values_overrides/rocky-ubuntu_bionic.yaml
+++ b/neutron/values_overrides/rocky-ubuntu_bionic.yaml
@@ -15,3 +15,4 @@ images:
     neutron_metadata: "docker.io/openstackhelm/neutron:rocky-ubuntu_bionic"
     neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:rocky-ubuntu_bionic"
     neutron_server: "docker.io/openstackhelm/neutron:rocky-ubuntu_bionic"
+    neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:rocky-ubuntu_bionic"
diff --git a/neutron/values_overrides/rocky-ubuntu_xenial.yaml b/neutron/values_overrides/rocky-ubuntu_xenial.yaml
index 78e677ca10..0335527d46 100644
--- a/neutron/values_overrides/rocky-ubuntu_xenial.yaml
+++ b/neutron/values_overrides/rocky-ubuntu_xenial.yaml
@@ -15,3 +15,4 @@ images:
     neutron_metadata: "docker.io/openstackhelm/neutron:rocky-ubuntu_xenial"
     neutron_openvswitch_agent: "docker.io/openstackhelm/neutron:rocky-ubuntu_xenial"
     neutron_server: "docker.io/openstackhelm/neutron:rocky-ubuntu_xenial"
+    neutron_bagpipe_bgp: "docker.io/openstackhelm/neutron:rocky-ubuntu_xenial"
diff --git a/tools/overrides/backends/networking/bagpipe_bgp.yaml b/tools/overrides/backends/networking/bagpipe_bgp.yaml
new file mode 100644
index 0000000000..7a82e29f45
--- /dev/null
+++ b/tools/overrides/backends/networking/bagpipe_bgp.yaml
@@ -0,0 +1,34 @@
+---
+conf:
+  neutron:
+    DEFAULT:
+      service_plugins: router, bgpvpn
+    service_providers:
+      # BGPVPN:OpenContrail:networking_bgpvpn.neutron.services.service_drivers.opencontrail.opencontrail.OpenContrailBGPVPNDriver:default
+      # BGPVPN:OpenDaylight:networking_odl.bgpvpn.odl_v2.OpenDaylightBgpvpnDriver:default
+      service_provider: BGPVPN:BaGPipe:networking_bgpvpn.neutron.services.service_drivers.bagpipe.bagpipe_v2.BaGPipeBGPVPNDriver:default
+  plugins:
+    openvswitch_agent:
+      agent:
+        extensions: bagpipe_bgpvpn
+  bagpipe_bgp:
+    bgp:
+      local_address: 192.168.143.88 # IP address for mpls/gre tunnels
+      peers: 192.168.143.96 # IP addresses of BGP peers
+      my_as: 23242 # Autonomous System number
+      enable_rtc: true # Enable RT Constraint (RFC4684)
+    common:
+      root_helper: sudo /var/lib/openstack/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
+    api:
+      host: localhost
+      port: 8082
+    dataplane_driver_ipvpn:
+      dataplane_driver: ovs
+      ovs_bridge: br-mpls
+      mpls_interface: '*gre*'
+      proxy_arp: false
+  auto_bridge_add:
+    br-mpls: null
+
+manifests:
+  daemonset_bagpipe_bgp: true