diff --git a/inventory_provider/__init__.py b/inventory_provider/__init__.py
index 5767a1da9c37b94dbc8446877ce9d4772e6c4d3b..aa92cb410dffe41600160d1d94bd1b98e3f9a75d 100644
--- a/inventory_provider/__init__.py
+++ b/inventory_provider/__init__.py
@@ -78,6 +78,9 @@ def create_app():
     from inventory_provider.routes import msr
     app.register_blueprint(msr.routes, url_prefix='/msr')
 
+    from inventory_provider.routes import lnetd
+    app.register_blueprint(lnetd.routes, url_prefix='/LnetD')
+
     if app.config.get('ENABLE_TESTING_ROUTES', False):
         from inventory_provider.routes import testing
         app.register_blueprint(testing.routes, url_prefix='/testing')
diff --git a/inventory_provider/routes/common.py b/inventory_provider/routes/common.py
index af20bf9a4b614897a362e6e26b90ad2d24909795..56ed526edd5f5fa87a6b0c37947f73bf36fb8f73 100644
--- a/inventory_provider/routes/common.py
+++ b/inventory_provider/routes/common.py
@@ -252,3 +252,17 @@ def load_json_docs(config_params, key_pattern, num_threads=10):
 def load_xml_docs(config_params, key_pattern, num_threads=10):
     yield from _load_redis_docs(
         config_params, key_pattern, num_threads, doc_type=_DECODE_TYPE_XML)
+
+
+def load_snmp_indexes(hostname=None):
+    result = dict()
+    key_pattern = f'snmp-interfaces:{hostname}*' \
+        if hostname else 'snmp-interfaces:*'
+
+    for doc in load_json_docs(
+            config_params=current_app.config['INVENTORY_PROVIDER_CONFIG'],
+            key_pattern=key_pattern):
+        router = doc['key'][len('snmp-interfaces:'):]
+        result[router] = {e['name']: e for e in doc['value']}
+
+    return result
diff --git a/inventory_provider/routes/lnetd.py b/inventory_provider/routes/lnetd.py
new file mode 100644
index 0000000000000000000000000000000000000000..581fa5d546747ca35e5be60a64370f9ae2c99e46
--- /dev/null
+++ b/inventory_provider/routes/lnetd.py
@@ -0,0 +1,168 @@
+import json
+import logging
+import re
+
+from flask import Blueprint, Response, current_app, request
+
+from inventory_provider import juniper
+from inventory_provider.routes import common
+from inventory_provider.routes.common import _ignore_cache_or_retrieve
+
+logger = logging.getLogger(__name__)
+routes = Blueprint('lnetd-support-routes', __name__)
+
+Gb = 1 << 30
+
+INTERFACE_LIST_SCHEMA = {
+    '$schema': 'http://json-schema.org/draft-07/schema#',
+
+    'definitions': {
+
+        "ipv4-interface-address": {
+            "type": "string",
+            "pattern": r'^(\d+\.){3}\d+/\d+$'
+        },
+        "ipv6-interface-address": {
+            "type": "string",
+            "pattern": r'^[a-f\d:]+/\d+$'
+        },
+
+        'interface': {
+            'type': 'object',
+            'properties': {
+                'hostname': {'type': 'string'},
+                'interface': {'type': 'string'},
+                'ifIndex': {'type': 'integer', 'minimum': 1},
+                "ipv4": {
+                    "type": "array",
+                    "items": {"$ref": "#/definitions/ipv4-interface-address"}
+                },
+                "ipv6": {
+                    "type": "array",
+                    "items": {"$ref": "#/definitions/ipv6-interface-address"}
+                },
+            },
+            'required': ['hostname', 'interface', 'ifIndex', 'ipv4', 'ipv6'],
+            'additionalProperties': False
+        },
+    },
+
+    'type': 'array',
+    'items': {'$ref': '#/definitions/interface'}
+}
+
+
+
+def _add_snmp_indexes(interfaces, hostname=None):
+    """
+    generator that adds snmp ifIndex to each interface, if available
+    (only interfaces with an snmp index are yielded)
+
+    :param interfaces: result of _load_interfaces
+    :param hostname: hostname or None for all
+    :return: generator that yields interfaces with 'ifIndex' added
+    """
+    snmp_indexes = common.load_snmp_indexes(hostname)
+    for ifc in interfaces:
+
+        hostname = ifc['hostname']
+        if hostname not in snmp_indexes:
+            continue
+
+        interface = ifc['interface']
+        if interface not in snmp_indexes[hostname]:
+            continue
+
+        ifc['ifIndex'] = snmp_indexes[hostname][interface]['index']
+        yield ifc
+
+
+def _load_router_interfaces(hostname):
+    """
+    loads basic interface data for production & lab routers
+
+    :param hostname:
+    :return:
+    """
+    def _load_docs(key_pattern):
+
+        m = re.match(r'^(.*netconf:).+', key_pattern)
+        assert m  # sanity
+        key_prefix_len = len(m.group(1))
+        assert key_prefix_len >= len('netconf:')  # sanity
+
+        for doc in common.load_xml_docs(
+                config_params=current_app.config['INVENTORY_PROVIDER_CONFIG'],
+                key_pattern=key_pattern,
+                num_threads=10):
+
+            router = doc['key'][key_prefix_len:]
+
+            for ifc in juniper.list_interfaces(doc['value']):
+                if not ifc['description']:
+                    continue
+
+                yield {
+                    'hostname': router,
+                    'interface': ifc['name'],
+                    'ipv4': [],
+                    'ipv6': []
+                }
+
+    base_key_pattern = f'netconf:{hostname}*' if hostname else 'netconf:*'
+    yield from _load_docs(base_key_pattern)
+    yield from _load_docs(f'lab:{base_key_pattern}')
+
+
+def _load_interfaces(hostname=None):
+    """
+    prepares the result of a call to /interfaces
+
+    :param hostname: hostname or None for all
+    :return: generator yielding interface elements
+    """
+    basic_interfaces = _load_router_interfaces(hostname)
+    return _add_snmp_indexes(basic_interfaces, hostname)
+
+
+@routes.route("/interfaces", methods=['GET', 'POST'])
+@routes.route('/interfaces/<hostname>', methods=['GET', 'POST'])
+@common.require_accepts_json
+def interfaces(hostname=None):
+    """
+    Handler for `/poller/interfaces` and
+    `/poller/interfaces/<hostname>`
+    which returns information for either all interfaces
+    or those on the requested hostname.
+
+    The response is a list of information for all
+    interfaces that should be polled, including service
+    information and snmp information.
+
+    .. asjson::
+       inventory_provider.routes.poller.INTERFACE_LIST_SCHEMA
+
+    :param hostname: optional, if present should be a router hostname
+    :return:
+    """
+
+    cache_key = f'classifier-cache:lnetd-interfaces:{hostname}' \
+        if hostname else 'classifier-cache:lnetd-interfaces:all'
+
+    r = common.get_current_redis()
+
+    result = _ignore_cache_or_retrieve(request, cache_key, r)
+
+    if not result:
+        result = list(_load_interfaces(hostname))
+        if not result:
+            return Response(
+                response='no interfaces found',
+                status=404,
+                mimetype='text/html')
+
+        result = json.dumps(result)
+        # cache this data for the next call
+        r.set(cache_key, result.encode('utf-8'))
+
+    return Response(result, mimetype="application/json")
diff --git a/inventory_provider/routes/poller.py b/inventory_provider/routes/poller.py
index 73681162903e04ee84751946535c6a05e1c1526d..900fd11c08c439bab616242296fe4360b2c6f660 100644
--- a/inventory_provider/routes/poller.py
+++ b/inventory_provider/routes/poller.py
@@ -123,20 +123,6 @@ def after_request(resp):
     return common.after_request(resp)
 
 
-def _load_snmp_indexes(hostname=None):
-    result = dict()
-    key_pattern = f'snmp-interfaces:{hostname}*' \
-        if hostname else 'snmp-interfaces:*'
-
-    for doc in common.load_json_docs(
-            config_params=current_app.config['INVENTORY_PROVIDER_CONFIG'],
-            key_pattern=key_pattern):
-        router = doc['key'][len('snmp-interfaces:'):]
-        result[router] = {e['name']: e for e in doc['value']}
-
-    return result
-
-
 def _load_interface_bundles(hostname=None):
     result = dict()
 
@@ -295,7 +281,7 @@ def _add_snmp_indexes(interfaces, hostname=None):
     :param hostname: hostname or None for all
     :return: generator with 'snmp-index' optionally added to each element
     """
-    snmp_indexes = _load_snmp_indexes(hostname)
+    snmp_indexes = common.load_snmp_indexes(hostname)
     for ifc in interfaces:
         router_snmp = snmp_indexes.get(ifc['router'], None)
         if router_snmp and ifc['name'] in router_snmp:
diff --git a/test/test_general_lnetd_routes.py b/test/test_general_lnetd_routes.py
new file mode 100644
index 0000000000000000000000000000000000000000..359afebfc3d25eaae9f61bed7de31a92866519ad
--- /dev/null
+++ b/test/test_general_lnetd_routes.py
@@ -0,0 +1,20 @@
+import json
+import jsonschema
+from inventory_provider.routes import lnetd
+
+DEFAULT_REQUEST_HEADERS = {
+    "Accept": ["application/json"]
+}
+
+
+def test_get_all_interfaces(client):
+    rv = client.get(
+        '/LnetD/interfaces',
+        headers=DEFAULT_REQUEST_HEADERS)
+    assert rv.status_code == 200
+    assert rv.is_json
+    response_data = json.loads(rv.data.decode('utf-8'))
+    jsonschema.validate(response_data, lnetd.INTERFACE_LIST_SCHEMA)
+    response_routers = {ifc['hostname'] for ifc in response_data}
+    assert len(response_routers) > 1, \
+        'there should data from be lots of routers'