diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index f04a5bd7e06af5b65024b20a46a4e8652b41142d..5050b5eaf5f24e1065ed2f7ad4962df28b011b26 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -938,6 +938,10 @@ neutron_admin_endpoint: "{{ admin_protocol }}://{{ neutron_internal_fqdn | put_a
 neutron_internal_endpoint: "{{ internal_protocol }}://{{ neutron_internal_fqdn | put_address_in_context('url') }}:{{ neutron_server_port }}"
 neutron_public_endpoint: "{{ public_protocol }}://{{ neutron_external_fqdn | put_address_in_context('url') }}:{{ neutron_server_port }}"
 
+# SRIOV physnet:interface mappings when SRIOV is enabled
+# "sriovnet1" and tunnel_interface used here as placeholders
+neutron_sriov_physnet_mappings:
+  sriovnet1: "{{ tunnel_interface }}"
 
 #######################
 # Nova options
diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml
index 8703695b8b6128afe9a5577bcb026cdd2c326aa0..af3fd83343c4b124aa4ff2cea8a9bf3e13865af1 100644
--- a/ansible/roles/neutron/defaults/main.yml
+++ b/ansible/roles/neutron/defaults/main.yml
@@ -399,6 +399,8 @@ mechanism_drivers:
     enabled: "{{ neutron_plugin_agent != 'ovn' }}"
   - name: "ovn"
     enabled: "{{ neutron_plugin_agent == 'ovn' }}"
+  - name: "sriovnicswitch"
+    enabled: "{{ enable_neutron_sriov | bool }}"
 
 neutron_mechanism_drivers: "{{ mechanism_drivers | selectattr('enabled', 'equalto', true) | list }}"
 
@@ -473,6 +475,8 @@ agent_extensions:
     enabled: "{{ enable_neutron_qos | bool }}"
   - name: "sfc"
     enabled: "{{ enable_neutron_sfc | bool }}"
+  - name: "fdb"
+    enabled: "{{ enable_neutron_sriov | bool }}"
 
 neutron_agent_extensions: "{{ agent_extensions | selectattr('enabled', 'equalto', true) | list }}"
 
@@ -574,3 +578,8 @@ neutron_ks_users:
     user: "{{ neutron_keystone_user }}"
     password: "{{ neutron_keystone_password }}"
     role: "admin"
+
+####################
+# SRIOV
+####################
+neutron_sriov_physnets: "{{ neutron_sriov_physnet_mappings.items() | map('join', ':') | join(',') }}"
diff --git a/ansible/roles/neutron/templates/linuxbridge_agent.ini.j2 b/ansible/roles/neutron/templates/linuxbridge_agent.ini.j2
index 60c5923dda95659fcbf93a4ce6358f2a2f304059..f33a133b08780b077e078f7616b7a429d36217c0 100644
--- a/ansible/roles/neutron/templates/linuxbridge_agent.ini.j2
+++ b/ansible/roles/neutron/templates/linuxbridge_agent.ini.j2
@@ -12,3 +12,10 @@ firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
 [vxlan]
 l2_population = true
 local_ip = {{ tunnel_interface_address }}
+
+{% if enable_neutron_sriov | bool %}
+[FDB]
+# Allows instances using sriov ports to communicate with instances that do not.
+# See https://docs.openstack.org/neutron/latest/admin/config-sriov.html
+shared_physical_device_mappings = {{ neutron_sriov_physnets }}
+{% endif %}
diff --git a/ansible/roles/neutron/templates/openvswitch_agent.ini.j2 b/ansible/roles/neutron/templates/openvswitch_agent.ini.j2
index 23b6dc88568e7df2a3dd4758ce68b41a75eee701..851fb42e38dcc017dc6bf58ccb2737d2acf59ef4 100644
--- a/ansible/roles/neutron/templates/openvswitch_agent.ini.j2
+++ b/ansible/roles/neutron/templates/openvswitch_agent.ini.j2
@@ -23,3 +23,10 @@ local_ip = {{ tunnel_interface_address }}
 {% if enable_nova_fake | bool %}
 integration_bridge = br-int-{{ item }}
 {% endif %}
+
+{% if enable_neutron_sriov | bool %}
+[FDB]
+# Allows instances using sriov ports to communicate with instances that do not.
+# See https://docs.openstack.org/neutron/latest/admin/config-sriov.html
+shared_physical_device_mappings = {{ neutron_sriov_physnets }}
+{% endif %}
diff --git a/ansible/roles/neutron/templates/sriov_agent.ini.j2 b/ansible/roles/neutron/templates/sriov_agent.ini.j2
index 856e85df9ae3f03ea62ae963a7ce2b3d28432d89..683b2e80312869175f70dc97027a5b6e058cc43e 100644
--- a/ansible/roles/neutron/templates/sriov_agent.ini.j2
+++ b/ansible/roles/neutron/templates/sriov_agent.ini.j2
@@ -1,10 +1,9 @@
 [sriov_nic]
 # 'physical_device_mappings' is a comma separated list
 # Maps a physical network to network inferface used for SRIOV
-# "sriovnet1" and tunnel_interface used here as placeholders
 # This template should be modified for specific environments
 # See Official OpenStack SRIOV documentation for all available options
-physical_device_mappings = sriovnet1:{{ tunnel_interface }}
+physical_device_mappings = {{ neutron_sriov_physnets }}
 exclude_devices =
 
 [securitygroup]
diff --git a/ansible/roles/nova-cell/defaults/main.yml b/ansible/roles/nova-cell/defaults/main.yml
index 281b2a62022b42f5aec1d16f1077a33e5b06510b..387bf9cbf437e0a81335722ee64b8b2cc1e8208f 100644
--- a/ansible/roles/nova-cell/defaults/main.yml
+++ b/ansible/roles/nova-cell/defaults/main.yml
@@ -431,3 +431,9 @@ nova_source_version: "{{ kolla_source_version }}"
 ###################################
 
 enable_shared_var_lib_nova_mnt: "{{ enable_cinder_backend_nfs | bool or enable_cinder_backend_quobyte | bool }}"
+
+###################################
+# PCI passthrough whitelist
+###################################
+
+nova_pci_passthrough_whitelist: "{{ enable_neutron_sriov | bool | ternary(neutron_sriov_physnet_mappings | dict2items(key_name='physical_network', value_name='devname'), []) }}"
diff --git a/ansible/roles/nova-cell/templates/nova.conf.j2 b/ansible/roles/nova-cell/templates/nova.conf.j2
index 76da3c9155bc21e4f0eaa5a0b34ada1ec47d3c7b..e97e41900de1b8e0f6441ba7502f650419a38d49 100644
--- a/ansible/roles/nova-cell/templates/nova.conf.j2
+++ b/ansible/roles/nova-cell/templates/nova.conf.j2
@@ -244,3 +244,8 @@ disable_group_policy_check_upcall = true
 # info updates to the scheduler, so just disable it.
 track_instance_changes = false
 {% endif %}
+
+{% if nova_pci_passthrough_whitelist %}
+[pci]
+passthrough_whitelist = {{ nova_pci_passthrough_whitelist | to_json }}
+{% endif %}
diff --git a/doc/source/reference/networking/sriov.rst b/doc/source/reference/networking/sriov.rst
index 01653b347e481658d1713488409c007054d1a8ab..53d6db4564422a5d323361171b6dbcae1599d7ec 100644
--- a/doc/source/reference/networking/sriov.rst
+++ b/doc/source/reference/networking/sriov.rst
@@ -14,37 +14,41 @@ SRIOV requires specific NIC and BIOS configuration and is not supported on all
 platforms. Consult NIC and platform specific documentation for instructions
 on enablement.
 
-Modify the ``/etc/kolla/globals.yml`` file as the following example shows:
+Modify the ``/etc/kolla/globals.yml`` file as the following example
+shows which automatically appends ``sriovnicswitch`` to the
+``mechanism_drivers`` inside ``ml2_conf.ini``.
 
+.. path /etc/kolla/globals.yml
 .. code-block:: yaml
 
    enable_neutron_sriov: "yes"
 
-Modify the ``/etc/kolla/config/neutron/ml2_conf.ini`` file and add
-``sriovnicswitch`` to the ``mechanism_drivers``. Also, the provider
-networks used by SRIOV should be configured. Both flat and VLAN are configured
-with the same physical network name in this example:
+It is also a requirement to define physnet:interface mappings for all
+SRIOV devices as shown in the following example where ``sriovtenant1`` is the
+physnet mapped to ``ens785f0`` interface:
+
+.. path /etc/kolla/globals.yml
+.. code-block:: yaml
+
+   neutron_sriov_physnet_mappings:
+     sriovtenant1: ens785f0
+
+However, the provider networks using SRIOV should be configured.
+Both flat and VLAN are configured with the same physical network name
+in this example:
 
 .. path /etc/kolla/config/neutron/ml2_conf.ini
 .. code-block:: ini
 
-   [ml2]
-   mechanism_drivers = openvswitch,l2population,sriovnicswitch
-
    [ml2_type_vlan]
    network_vlan_ranges = sriovtenant1:1000:1009
 
    [ml2_type_flat]
    flat_networks = sriovtenant1
 
-Add ``PciPassthroughFilter`` to enabled_filters
-
-The ``PciPassthroughFilter``, which is required by Nova Scheduler service
-on the Controller, should be added to ``enabled_filters``
-
-Modify the ``/etc/kolla/config/nova.conf`` file and add
-``PciPassthroughFilter`` to ``enabled_filters``. this filter is
-required by The Nova Scheduler service on the controller node.
+Modify the ``nova.conf`` file and add ``PciPassthroughFilter`` to
+``enabled_filters``. This filter is required by the Nova Scheduler
+service on the controller node.
 
 .. path /etc/kolla/config/nova.conf
 .. code-block:: ini
@@ -53,24 +57,18 @@ required by The Nova Scheduler service on the controller node.
    enabled_filters = <existing filters>, PciPassthroughFilter
    available_filters = nova.scheduler.filters.all_filters
 
-Edit the ``/etc/kolla/config/nova.conf`` file and add PCI device whitelisting.
-this is needed by OpenStack Compute service(s) on the Compute.
-
-.. path /etc/kolla/config/nova.conf
-.. code-block:: ini
-
-   [pci]
-   passthrough_whitelist = [{"devname": "ens785f0", "physical_network": "sriovtenant1"}]
+PCI devices listed under ``neutron_sriov_physnet_mappings`` will be
+whitelisted on the Compute hosts inside ``nova.conf``.
 
-Modify the ``/etc/kolla/config/neutron/sriov_agent.ini`` file. Add physical
-network to interface mapping. Specific VFs can also be excluded here. Leaving
-blank means to enable all VFs for the interface:
+Physical network to interface mappings in ``neutron_sriov_physnet_mappings``
+will be automatically added to ``sriov_agent.ini``. Specific VFs can be
+excluded via ``excluded_devices``. However, leaving blank (default) leaves all
+VFs enabled:
 
 .. path /etc/kolla/config/neutron/sriov_agent.ini
 .. code-block:: ini
 
    [sriov_nic]
-   physical_device_mappings = sriovtenant1:ens785f0
    exclude_devices =
 
 Run deployment.