diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index 952f3d8906eab9ad1670266f0960dde0538d6d27..0e09a1af06080d27e201d9e3c761d5a1b4e4024c 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -464,6 +464,7 @@ enable_hyperv: "no"
 enable_influxdb: "{{ enable_monasca | bool }}"
 enable_ironic: "no"
 enable_ironic_ipxe: "no"
+enable_ironic_neutron_agent: "{{ enable_neutron | bool and enable_ironic | bool }}"
 enable_ironic_pxe_uefi: "no"
 enable_iscsid: "{{ (enable_cinder | bool and enable_cinder_backend_iscsi | bool) or enable_ironic | bool }}"
 enable_karbor: "no"
diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one
index 12c845f67d1da010b7cb816c41c6bd630fbc023f..c6907097ab7d359e36ca25279b7934b856d22d8c 100644
--- a/ansible/inventory/all-in-one
+++ b/ansible/inventory/all-in-one
@@ -311,6 +311,9 @@ neutron
 [neutron-infoblox-ipam-agent:children]
 neutron
 
+[ironic-neutron-agent:children]
+neutron
+
 # Ceph
 [ceph-mds:children]
 ceph
diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode
index c4c9848654900f99bacdbd2061e315b55ac72217..b796c2986a3cdc991bc1c0140b3fd68694a4ec00 100644
--- a/ansible/inventory/multinode
+++ b/ansible/inventory/multinode
@@ -330,6 +330,9 @@ neutron
 [neutron-infoblox-ipam-agent:children]
 neutron
 
+[ironic-neutron-agent:children]
+neutron
+
 # Ceph
 [ceph-mds:children]
 ceph
diff --git a/ansible/roles/neutron/defaults/main.yml b/ansible/roles/neutron/defaults/main.yml
index 70cfda2e5c5da0ef92ba35be34806d408a113af1..959efc41c97bd7cab4952bc54d9ddc348d0530c5 100644
--- a/ansible/roles/neutron/defaults/main.yml
+++ b/ansible/roles/neutron/defaults/main.yml
@@ -169,6 +169,17 @@ neutron_services:
       - "/etc/localtime:/etc/localtime:ro"
       - "/run:/run:shared"
       - "kolla_logs:/var/log/kolla/"
+  ironic-neutron-agent:
+    container_name: "ironic_neutron_agent"
+    image: "{{ ironic_neutron_agent_image_full }}"
+    privileged: False
+    enabled: "{{ enable_ironic_neutron_agent | bool }}"
+    group: "ironic-neutron-agent"
+    host_in_groups: "{{ inventory_hostname in groups['ironic-neutron-agent'] }}"
+    volumes:
+      - "{{ node_config_directory }}/ironic-neutron-agent/:{{ container_config_directory }}/:ro"
+      - "/etc/localtime:/etc/localtime:ro"
+      - "kolla_logs:/var/log/kolla/"
 
 
 ####################
@@ -225,6 +236,10 @@ neutron_infoblox_ipam_agent_image: "{{ docker_registry ~ '/' if docker_registry
 neutron_infoblox_ipam_agent_tag: "{{ neutron_tag }}"
 neutron_infoblox_ipam_agent_image_full: "{{ neutron_infoblox_ipam_agent_image }}:{{ neutron_infoblox_ipam_agent_tag }}"
 
+ironic_neutron_agent_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ neutron_install_type }}-ironic-neutron-agent"
+ironic_neutron_agent_tag: "{{ neutron_tag }}"
+ironic_neutron_agent_image_full: "{{ ironic_neutron_agent_image }}:{{ ironic_neutron_agent_tag }}"
+
 ####################
 # OpenStack
 ####################
diff --git a/ansible/roles/neutron/handlers/main.yml b/ansible/roles/neutron/handlers/main.yml
index fd85187f6b878e0d38044ed81ce51c12b42210c6..67e390d02c2188d8cd306cfb4987b0f9b47f067f 100644
--- a/ansible/roles/neutron/handlers/main.yml
+++ b/ansible/roles/neutron/handlers/main.yml
@@ -330,3 +330,27 @@
     - config_json | changed
       or neutron_conf | changed
       or neutron_ml2_conf | changed
+
+- name: Restart ironic-neutron-agent container
+  vars:
+    service_name: "ironic-neutron-agent"
+    service: "{{ neutron_services[service_name] }}"
+    config_json: "{{ neutron_config_jsons.results|selectattr('item.key', 'equalto', service_name)|first }}"
+    neutron_conf: "{{ neutron_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
+    neutron_ml2_conf: "{{ neutron_ml2_confs.results|selectattr('item.key', 'equalto', service_name)|first }}"
+    ironic_neutron_agent_container: "{{ check_neutron_containers.results|selectattr('item.key', 'equalto', service_name)|first }}"
+  become: true
+  kolla_docker:
+    action: "recreate_or_restart_container"
+    common_options: "{{ docker_common_options }}"
+    name: "{{ service.container_name }}"
+    image: "{{ service.image }}"
+    volumes: "{{ service.volumes }}"
+    privileged: "{{ service.privileged | default(False) }}"
+  when:
+    - action != "config"
+    - service.enabled | bool
+    - service.host_in_groups | bool
+    - config_json | changed
+      or neutron_conf | changed
+      or ironic_neutron_agent_ini | changed
diff --git a/ansible/roles/neutron/tasks/config.yml b/ansible/roles/neutron/tasks/config.yml
index f5b31535524871bb952a9ca31092cdbc28991aa5..6a44ff53ccf6d1e79f42896dde178ea0c9f19f62 100644
--- a/ansible/roles/neutron/tasks/config.yml
+++ b/ansible/roles/neutron/tasks/config.yml
@@ -50,6 +50,7 @@
   vars:
     service_name: "{{ item.key }}"
     services_need_neutron_conf:
+      - "ironic-neutron-agent"
       - "neutron-dhcp-agent"
       - "neutron-l3-agent"
       - "neutron-linuxbridge-agent"
@@ -305,6 +306,24 @@
   notify:
     - "Restart {{ service_name }} container"
 
+- name: Copying over ironic_neutron_agent.ini
+  become: true
+  vars:
+    service_name: "ironic-neutron-agent"
+    ironic_neutron_agent: "{{ neutron_services[service_name] }}"
+  merge_configs:
+    sources:
+      - "{{ role_path }}/templates/ironic_neutron_agent.ini.j2"
+      - "{{ node_custom_config }}/neutron/ironic_neutron_agent.ini"
+    dest: "{{ node_config_directory }}/{{ service_name }}/ironic_neutron_agent.ini"
+    mode: "0660"
+  register: ironic_neutron_agent_ini
+  when:
+    - ironic_neutron_agent.enabled | bool
+    - ironic_neutron_agent.host_in_groups | bool
+  notify:
+    - "Restart {{ service_name }} container"
+
 - name: Copying over bgp_dragent.ini
   become: true
   vars:
diff --git a/ansible/roles/neutron/tasks/deploy.yml b/ansible/roles/neutron/tasks/deploy.yml
index afd6f190973079d39cfed2489b156a468c95b575..6066a05c7ccc0c9dfcaad21eabe48c17f01f3816 100644
--- a/ansible/roles/neutron/tasks/deploy.yml
+++ b/ansible/roles/neutron/tasks/deploy.yml
@@ -1,5 +1,4 @@
 ---
-# enforce ironic usage only with openvswitch
 - include: ironic-check.yml
 
 - include: register.yml
diff --git a/ansible/roles/neutron/tasks/ironic-check.yml b/ansible/roles/neutron/tasks/ironic-check.yml
index a578ce2c72cc52064bc9bab86792cd31068e08f6..f22bf70b87c9483e71f0ef517a1f58ef48e40363 100644
--- a/ansible/roles/neutron/tasks/ironic-check.yml
+++ b/ansible/roles/neutron/tasks/ironic-check.yml
@@ -1,6 +1,5 @@
 ---
-# TODO(SamYaple): run verification checks at start of playbook
-- fail: msg="neutron_plugin_agent must use openvswitch with Ironic"
+- fail: msg="Ironic must be enabled when using networking-baremetal/ironic-neutron-agent"
   when:
-    - enable_ironic | bool
-    - neutron_plugin_agent != "openvswitch"
+    - enable_ironic_neutron_agent | bool
+    - not (enable_ironic | bool)
diff --git a/ansible/roles/neutron/templates/ironic-neutron-agent.json.j2 b/ansible/roles/neutron/templates/ironic-neutron-agent.json.j2
new file mode 100644
index 0000000000000000000000000000000000000000..33eca34527a66918efe1cafec00790506710d234
--- /dev/null
+++ b/ansible/roles/neutron/templates/ironic-neutron-agent.json.j2
@@ -0,0 +1,29 @@
+{
+    "command": "ironic-neutron-agent --config-dir /etc/neutron --config-file /etc/neutron/plugins/ml2/ironic_neutron_agent.ini --log-file /var/log/kolla/neutron/ironic_neutron_agent.log",
+    "config_files": [
+        {
+            "source": "{{ container_config_directory }}/neutron.conf",
+            "dest": "/etc/neutron/neutron.conf",
+            "owner": "neutron",
+            "perm": "0600"
+        },
+        {
+            "source": "{{ container_config_directory }}/ironic_neutron_agent.ini",
+            "dest": "/etc/neutron/plugins/ml2/ironic_neutron_agent.ini",
+            "owner": "neutron",
+            "perm": "0600"
+        }
+    ],
+    "permissions": [
+        {
+            "path": "/var/log/kolla/neutron",
+            "owner": "neutron:neutron",
+            "recurse": true
+        },
+        {
+            "path": "/var/lib/neutron/kolla",
+            "owner": "neutron:neutron",
+            "recurse": true
+        }
+    ]
+}
diff --git a/ansible/roles/neutron/templates/ironic_neutron_agent.ini.j2 b/ansible/roles/neutron/templates/ironic_neutron_agent.ini.j2
new file mode 100644
index 0000000000000000000000000000000000000000..5752d9edc51e5435b3018206db0e0a396033ba23
--- /dev/null
+++ b/ansible/roles/neutron/templates/ironic_neutron_agent.ini.j2
@@ -0,0 +1,9 @@
+[ironic]
+auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}
+auth_type = password
+project_domain_id = {{ default_project_domain_id }}
+user_domain_id = {{ default_user_domain_id }}
+project_name = service
+username = {{ neutron_keystone_user }}
+password = {{ neutron_keystone_password }}
+os_endpoint_type = internalURL
diff --git a/ansible/roles/neutron/templates/ml2_conf.ini.j2 b/ansible/roles/neutron/templates/ml2_conf.ini.j2
index f12b2420799fe6fae80aaabf4180260b0893eac9..e81a2e34ad95567f79b2632745f4415b18567d61 100644
--- a/ansible/roles/neutron/templates/ml2_conf.ini.j2
+++ b/ansible/roles/neutron/templates/ml2_conf.ini.j2
@@ -10,7 +10,7 @@ mechanism_drivers = openvswitch,hyperv
 {% elif enable_onos | bool %}
 mechanism_drivers = onos_ml2
 {% else %}
-mechanism_drivers = openvswitch,l2population
+mechanism_drivers = openvswitch,{% if enable_ironic_neutron_agent | bool %}baremetal,{% endif %}l2population
 {% endif %}
 {% elif neutron_plugin_agent == "linuxbridge" %}
 mechanism_drivers = linuxbridge,l2population
diff --git a/ansible/roles/openvswitch/tasks/deploy.yml b/ansible/roles/openvswitch/tasks/deploy.yml
index 3fa34a2afa76672c3f064783a0b6bd756725cedb..5aac9f5a7f854e831b74bae654cce2a9b0dd2861 100644
--- a/ansible/roles/openvswitch/tasks/deploy.yml
+++ b/ansible/roles/openvswitch/tasks/deploy.yml
@@ -1,7 +1,4 @@
 ---
-# enforce ironic usage only with openvswitch
-- include: ironic-check.yml
-
 - include: config.yml
 
 - name: Flush Handlers
diff --git a/ansible/roles/openvswitch/tasks/ironic-check.yml b/ansible/roles/openvswitch/tasks/ironic-check.yml
deleted file mode 100644
index a578ce2c72cc52064bc9bab86792cd31068e08f6..0000000000000000000000000000000000000000
--- a/ansible/roles/openvswitch/tasks/ironic-check.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-# TODO(SamYaple): run verification checks at start of playbook
-- fail: msg="neutron_plugin_agent must use openvswitch with Ironic"
-  when:
-    - enable_ironic | bool
-    - neutron_plugin_agent != "openvswitch"
diff --git a/ansible/site.yml b/ansible/site.yml
index 9447f581d46366e24cfd4e716667354d15e1e7e6..e6267b930839628ed11bb677cfe2eda46db1b935 100644
--- a/ansible/site.yml
+++ b/ansible/site.yml
@@ -404,6 +404,7 @@
     - neutron-dhcp-agent
     - neutron-l3-agent
     - neutron-lbaas-agent
+    - ironic-neutron-agent
     - neutron-metadata-agent
     - compute
     - manila-share
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
index 12f9febfd5ba086816d88e86b8b8f563c588b21a..4e48dc2a3a5c71ea4bf12ce90e71d51dc0428623 100644
--- a/etc/kolla/globals.yml
+++ b/etc/kolla/globals.yml
@@ -221,6 +221,7 @@ kolla_internal_vip_address: "10.10.10.254"
 #enable_influxdb: "no"
 #enable_ironic: "no"
 #enable_ironic_ipxe: "no"
+#enable_ironic_neutron_agent: "no"
 #enable_ironic_pxe_uefi: "no"
 #enable_kafka: "no"
 #enable_karbor: "no"
diff --git a/releasenotes/notes/support_ironic_neutron_agent-3eac1e71069ea845.yaml b/releasenotes/notes/support_ironic_neutron_agent-3eac1e71069ea845.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..bc8ed88f2bc41f5361c5354eab470667430e4a7f
--- /dev/null
+++ b/releasenotes/notes/support_ironic_neutron_agent-3eac1e71069ea845.yaml
@@ -0,0 +1,4 @@
+---
+features:
+  - Add support for configuration of the Ironic Neutron Agent, and the Neutron
+    networking-baremetal ML2 plugin.
diff --git a/tests/templates/inventory.j2 b/tests/templates/inventory.j2
index b1c75d65d532f734ee3da42cc10f3499b169b57a..61dcf28ec82680a4240e367787b1695f25f525d7 100644
--- a/tests/templates/inventory.j2
+++ b/tests/templates/inventory.j2
@@ -300,6 +300,9 @@ neutron
 [neutron-infoblox-ipam-agent:children]
 neutron
 
+[ironic-neutron-agent:children]
+neutron
+
 # Ceph
 [ceph-mds:children]
 ceph