diff --git a/ci/roles/router/tasks/main.yml b/ci/roles/router/tasks/main.yml
index 32c8fc68ca048bdfd5047333b9bff2b398877bdc..afbe654f28ae060ea9f572bcd74db7371f25a864 100644
--- a/ci/roles/router/tasks/main.yml
+++ b/ci/roles/router/tasks/main.yml
@@ -74,10 +74,21 @@
 - name: Verify routers info
   assert:
     that:
+      - info.routers|length == 1
       - info.routers.0.name == router_name
-      - (info.routers.0.interfaces_info|length) == 0
       - info.routers.0.is_admin_state_up
 
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
+
+- name: Verify router ports
+  assert:
+    that: ports.ports|length == 0
+
 - name: Update router (add interface)
   openstack.cloud.router:
      cloud: "{{ cloud }}"
@@ -109,13 +120,26 @@
   assert:
     that:
       - info.routers.0.name == router_name
-      - (info.routers.0.interfaces_info|length) == 1
       - info.routers.0.is_admin_state_up
 
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
+
+- name: Verify router ports
+  assert:
+    that:
+      - ports.ports|length == 1
+      - (ports.ports.0.fixed_ips|map(attribute='ip_address')|sort|list == ['10.7.7.1']) or
+        ports.ports.0.fixed_ips|length > 0
+
 - name: Verify existence of return values
   assert:
     that: item in info.routers[0]
-  loop: "{{ expected_fields + ['interfaces_info'] }}"
+  loop: "{{ expected_fields }}"
 
 - name: Gather routers info with filters
   openstack.cloud.routers_info:
@@ -130,7 +154,6 @@
     that:
       - info.routers.0.name == router_name
       - info.routers.0.id == router.router.id
-      - (info.routers.0.interfaces_info|length) == 1
 
 - name: Gather routers info with other filters
   openstack.cloud.routers_info:
@@ -184,10 +207,22 @@
 - name: Verify routers info
   assert:
     that:
+      - info.routers|length == 1
       - info.routers.0.name == router_name
       - info.routers.0.id == router.router.id
-      - (info.routers.0.interfaces_info|length) == 3
-      - info.routers.0.interfaces_info|map(attribute='ip_address')|sort|list ==
+
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
+
+- name: Verify router ports
+  assert:
+    that:
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 3
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
         ['10.10.10.1', '10.8.8.1', '10.9.9.1']
 
 - name: Update router (remove interfaces)
@@ -222,8 +257,19 @@
     that:
       - info.routers.0.name == router_name
       - info.routers.0.id == router.router.id
-      - (info.routers.0.interfaces_info|length) == 1
-      - info.routers.0.interfaces_info|map(attribute='ip_address')|sort|list ==
+
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
+
+- name: Verify router ports
+  assert:
+    that:
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 1
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
         ['10.10.10.1']
 
 - name: Update router (replace interfaces)
@@ -236,18 +282,18 @@
            subnet: shade_subnet1
            portip: 10.7.7.1
 
-- name: Gather routers info
-  openstack.cloud.routers_info:
-     cloud: "{{ cloud }}"
-     name: "{{ router_name }}"
-  register: info
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
 
-- name: Verify routers info
+- name: Verify router ports
   assert:
     that:
-      - info.routers.0.name == router_name
-      - (info.routers.0.interfaces_info|length) == 1
-      - info.routers.0.interfaces_info|map(attribute='ip_address')|sort|list ==
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 1
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
         ['10.7.7.1']
 
 - name: Update router (replace interfaces) again
@@ -265,20 +311,19 @@
   assert:
     that: router is not changed
 
-- name: Gather routers info
-  openstack.cloud.routers_info:
-     cloud: "{{ cloud }}"
-     name: "{{ router_name }}"
-     filters:
-       is_admin_state_up: true
-  register: info
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
 
-- name: Verify routers info
+- name: Verify router ports
   assert:
     that:
-      - info.routers.0.name == router_name
-      - (info.routers.0.interfaces_info|length) == 1
-      - info.routers.0.interfaces_info.0.ip_address == '10.7.7.1'
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 1
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
+        ['10.7.7.1']
 
 # Admin operation
 - name: Create external network
@@ -323,7 +368,18 @@
   assert:
     that:
       - info.routers.0.name == router_name
-      - (info.routers.0.interfaces_info|length) == 1
+
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
+
+- name: Verify router ports
+  assert:
+    that:
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 1
 
 - name: Update router (change external fixed ips)
   openstack.cloud.router:
@@ -558,15 +614,19 @@
   assert:
     that: router is changed
 
-- name: Gather routers info
-  openstack.cloud.routers_info:
-     cloud: "{{ cloud }}"
-     name: "{{ router_name }}"
-  register: info
+- name: List ports of router
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ router.router.id }}"
+  register: ports
 
-- name: Verify routers info
+- name: Verify router ports
   assert:
-    that: "'10.7.7.42' in info.routers[0].interfaces_info|map(attribute='ip_address')"
+    that:
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|list|length == 1
+      - ports.ports|rejectattr('device_owner', 'equalto', 'network:router_gateway')|sum(attribute='fixed_ips', start=[])|map(attribute='ip_address')|sort|list ==
+        ['10.7.7.42']
 
 - name: Unset portip in already assigned subnet
   openstack.cloud.router:
@@ -582,6 +642,58 @@
   assert:
     that: router is not changed
 
+- name: List all routers
+  openstack.cloud.routers_info:
+     cloud: "{{ cloud }}"
+  register: routers
+
+- name: List ports of all routers
+  loop: "{{ routers.routers }}"
+  openstack.cloud.port_info:
+    cloud: "{{ cloud }}"
+    filters:
+      device_id: "{{ item['id'] }}"
+  register: ports
+
+- name: Transform ports for interfaces_info entries
+  loop: "{{ ports.results|map(attribute='ports')|list }}"
+  set_fact:
+    interfaces_info: |-
+        {% for port in item %}
+        {% if port.device_owner != "network:router_gateway" %}
+        {% for fixed_ip in port['fixed_ips'] %}
+        - port_id: {{ port.id }}
+          ip_address: {{ fixed_ip.ip_address }}
+          subnet_id: {{ fixed_ip.subnet_id }}
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+  register: interfaces
+
+- name: Combine router and interfaces_info entries
+  loop: "{{
+      routers.routers|zip(interfaces.results|map(attribute='ansible_facts'))|list
+  }}"
+  set_fact:
+    # underscore prefix to prevent overwriting facts outside of loop
+    _router: "{{
+        item.0|combine({'interfaces_info': (item.1.interfaces_info|from_yaml) })
+    }}"
+  register: routers
+
+- name: Remove set_fact artifacts from routers
+  set_fact:
+    routers: "{{ {
+        'routers': routers.results|map(attribute='ansible_facts._router')|list
+    } }}"
+
+- debug: var=routers
+
+- name: Assert our router's interfaces_info
+  assert:
+    that:
+      - routers.routers|selectattr('id', 'equalto', router.router.id)|list|length == 1
+
 # Cleanup environment
 
 - name: Delete router
diff --git a/plugins/modules/routers_info.py b/plugins/modules/routers_info.py
index 22ac68ebe37f8e5c6640aa169e9a1ef55f793a9a..4683e9b1d79f9f14fb7717999e6d3ddbc085836e 100644
--- a/plugins/modules/routers_info.py
+++ b/plugins/modules/routers_info.py
@@ -19,14 +19,15 @@ options:
      type: str
    filters:
      description:
-        - A dictionary of meta data to use for further filtering.  Elements of
+        - A dictionary of meta data to use for further filtering. Elements of
           this dictionary may be additional dictionaries.
      required: false
      type: dict
      suboptions:
        project_id:
          description:
-           - Filter the list result by the ID of the project that owns the resource.
+           - Filter the list result by the ID of the project that owns the
+             resource.
          type: str
          aliases:
            - tenant_id
@@ -36,11 +37,13 @@ options:
          type: str
        description:
          description:
-           - Filter the list result by the human-readable description of the resource.
+           - Filter the list result by the human-readable description of the
+             resource.
          type: str
        is_admin_state_up:
          description:
-           - Filter the list result by the administrative state of the resource, which is up (true) or down (false).
+           - Filter the list result by the administrative state of the
+             resource, which is up (true) or down (false).
          type: bool
        revision_number:
          description:
@@ -48,7 +51,8 @@ options:
          type: int
        tags:
          description:
-           - A list of tags to filter the list result by. Resources that match all tags in this list will be returned.
+           - A list of tags to filter the list result by. Resources that match
+             all tags in this list will be returned.
          type: list
          elements: str
 requirements:
@@ -100,6 +104,68 @@ EXAMPLES = '''
 - name: Show openstack routers
   debug:
     msg: "{{ result.routers }}"
+
+- name: List all routers
+  openstack.cloud.routers_info:
+     cloud: devstack
+  register: routers
+
+- name: List ports of first router
+  openstack.cloud.port_info:
+    cloud: devstack
+    filters:
+      device_id: "{{ routers[0].router.id }}"
+  register: ports
+
+- name: Show first router's fixed ips
+  debug:
+    msg: "{{ ports.ports
+        |rejectattr('device_owner', 'equalto', 'network:router_gateway')
+        |sum(attribute='fixed_ips', start=[])
+        |map(attribute='ip_address')
+        |sort|list }}"
+
+- name: List ports of all routers
+  loop: "{{ routers.routers }}"
+  openstack.cloud.port_info:
+    cloud: devstack
+    filters:
+      device_id: "{{ item['id'] }}"
+  register: ports
+
+- name: Transform ports for interfaces_info entries
+  loop: "{{ ports.results|map(attribute='ports')|list }}"
+  set_fact:
+    interfaces_info: |-
+        {% for port in item %}
+        {% if port.device_owner != "network:router_gateway" %}
+        {% for fixed_ip in port['fixed_ips'] %}
+        - port_id: {{ port.id }}
+          ip_address: {{ fixed_ip.ip_address }}
+          subnet_id: {{ fixed_ip.subnet_id }}
+        {% endfor %}
+        {% endif %}
+        {% endfor %}
+  register: interfaces
+
+- name: Combine router and interfaces_info entries
+  loop: "{{
+      routers.routers|zip(interfaces.results|map(attribute='ansible_facts'))|list
+  }}"
+  set_fact:
+    # underscore prefix to prevent overwriting facts outside of loop
+    _router: "{{
+        item.0|combine({'interfaces_info': item.1.interfaces_info|from_yaml})
+    }}"
+  register: routers
+
+- name: Remove set_fact artifacts from routers
+  set_fact:
+    routers: "{{ {
+        'routers': routers.results|map(attribute='ansible_facts._router')|list
+    } }}"
+
+- debug: var=routers
 '''
 
 RETURN = '''
@@ -137,10 +203,6 @@ routers:
             description: Unique UUID.
             returned: success
             type: str
-        interfaces_info:
-            description: List of connected interfaces.
-            returned: success
-            type: list
         is_admin_state_up:
             description: Network administrative state
             returned: success
@@ -206,21 +268,6 @@ class RouterInfoModule(OpenStackModule):
             for router in self.conn.search_routers(
                 name_or_id=self.params['name'],
                 filters=self.params['filters'])]
-
-        # append interfaces_info attribute for backward compatibility
-        for router in routers:
-            interfaces_info = []
-            for port in self.conn.list_router_interfaces(router):
-                if port.device_owner != "network:router_gateway":
-                    for ip_spec in port.fixed_ips:
-                        int_info = {
-                            'port_id': port.id,
-                            'ip_address': ip_spec.get('ip_address'),
-                            'subnet_id': ip_spec.get('subnet_id')
-                        }
-                        interfaces_info.append(int_info)
-            router['interfaces_info'] = interfaces_info
-
         self.exit(changed=False, routers=routers)
 
 
diff --git a/tests/unit/modules/cloud/openstack/test_routers_info.py b/tests/unit/modules/cloud/openstack/test_routers_info.py
index 0259889463a666b0fe8f041a758307ece3b718a6..9ccf9db9309a415153310fa85e49769a8033079f 100644
--- a/tests/unit/modules/cloud/openstack/test_routers_info.py
+++ b/tests/unit/modules/cloud/openstack/test_routers_info.py
@@ -1,10 +1,8 @@
 
 import munch
 
-from mock import patch
-
 from ansible_collections.openstack.cloud.plugins.modules import routers_info
-from ansible_collections.openstack.cloud.tests.unit.modules.utils import set_module_args, ModuleTestCase, AnsibleExitJson
+from ansible_collections.openstack.cloud.tests.unit.modules.utils import ModuleTestCase
 
 
 def openstack_cloud_from_module(module, **kwargs):
@@ -108,64 +106,17 @@ class FakeCloud(object):
         ]
 
         if name_or_id is not None:
-            return [munch.Munch(router) for router in test_routers if router["name"] == name_or_id]
+            return [munch.Munch(router) for router in test_routers
+                    if router["name"] == name_or_id]
         else:
             return [munch.Munch(router) for router in test_routers]
 
-    def list_router_interfaces(self, router):
-        test_ports = [
-            {
-                "device_id": "d3f70ce4-7ab1-46a7-9bec-498c9d8a2483",
-                "device_owner": "network:router_interface",
-                "fixed_ips": [
-                    {
-                        "ip_address": "192.168.1.254",
-                        "subnet_id": "0624c75f-0574-41b5-a8d1-92e6e3a9e51d"
-                    }
-                ],
-                "id": "92eeeca3-225d-46b8-a857-ede6c4f05484",
-            },
-            {
-                "device_id": "b869307c-a1f9-4956-a993-8a90fc7cc01d",
-                "device_owner": "network:router_gateway",
-                "fixed_ips": [
-                    {
-                        "ip_address": "172.24.4.10",
-                        "subnet_id": "b42b8057-5b3b-4aa3-949a-eaaee2032462"
-                    },
-                ],
-                "id": "ab45060c-98fd-42a3-a1aa-8d5a03554bef",
-            },
-            {
-                "device_id": "98bce30e-c912-4490-85eb-b22d650721e6",
-                "device_owner": "network:router_interface",
-                "fixed_ips": [
-                    {
-                        "ip_address": "192.168.1.1",
-                        "subnet_id": "0624c75f-0574-41b5-a8d1-92e6e3a9e51d"
-                    }
-                ],
-                "id": "c9fb53f1-d43e-4588-a223-0e8bf8a79715",
-            },
-            {
-                "device_id": "98bce30e-c912-4490-85eb-b22d650721e6",
-                "device_owner": "network:router_gateway",
-                "fixed_ips": [
-                    {
-                        "ip_address": "172.24.4.234",
-                        "subnet_id": "b42b8057-5b3b-4aa3-949a-eaaee2032462"
-                    },
-                ],
-                "id": "0271878e-4be8-433c-acdc-52823b41bcbf",
-            },
-        ]
-        return [munch.Munch(port) for port in test_ports if port["device_id"] == router.id]
-
 
 class TestRoutersInfo(ModuleTestCase):
     '''This class calls the main function of the
     openstack.cloud.routers_info module.
     '''
+
     def setUp(self):
         super(TestRoutersInfo, self).setUp()
         self.module = routers_info
@@ -174,33 +125,3 @@ class TestRoutersInfo(ModuleTestCase):
         with self.assertRaises(exit_exc) as exc:
             self.module.main()
         return exc.exception.args[0]
-
-    @patch('ansible_collections.openstack.cloud.plugins.modules.routers_info.openstack_cloud_from_module', side_effect=openstack_cloud_from_module)
-    def test_main_with_router_interface(self, *args):
-
-        set_module_args({'name': 'router1'})
-        result = self.module_main(AnsibleExitJson)
-        self.assertIs(type(result.get('openstack_routers')[0].get('interfaces_info')), list)
-        self.assertEqual(len(result.get('openstack_routers')[0].get('interfaces_info')), 1)
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('port_id'), '92eeeca3-225d-46b8-a857-ede6c4f05484')
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('ip_address'), '192.168.1.254')
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('subnet_id'), '0624c75f-0574-41b5-a8d1-92e6e3a9e51d')
-
-    @patch('ansible_collections.openstack.cloud.plugins.modules.routers_info.openstack_cloud_from_module', side_effect=openstack_cloud_from_module)
-    def test_main_with_router_gateway(self, *args):
-
-        set_module_args({'name': 'router2'})
-        result = self.module_main(AnsibleExitJson)
-        self.assertIs(type(result.get('openstack_routers')[0].get('interfaces_info')), list)
-        self.assertEqual(len(result.get('openstack_routers')[0].get('interfaces_info')), 0)
-
-    @patch('ansible_collections.openstack.cloud.plugins.modules.routers_info.openstack_cloud_from_module', side_effect=openstack_cloud_from_module)
-    def test_main_with_router_interface_and_router_gateway(self, *args):
-
-        set_module_args({'name': 'router3'})
-        result = self.module_main(AnsibleExitJson)
-        self.assertIs(type(result.get('openstack_routers')[0].get('interfaces_info')), list)
-        self.assertEqual(len(result.get('openstack_routers')[0].get('interfaces_info')), 1)
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('port_id'), 'c9fb53f1-d43e-4588-a223-0e8bf8a79715')
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('ip_address'), '192.168.1.1')
-        self.assertEqual(result.get('openstack_routers')[0].get('interfaces_info')[0].get('subnet_id'), '0624c75f-0574-41b5-a8d1-92e6e3a9e51d')