diff --git a/src/pathcomp/frontend/service/algorithms/_Algorithm.py b/src/pathcomp/frontend/service/algorithms/_Algorithm.py
index b6316774921171eb8ed6cf3faafd4b607bdcb831..0286e1420a6c96a140d39380a2fa35d24f991abf 100644
--- a/src/pathcomp/frontend/service/algorithms/_Algorithm.py
+++ b/src/pathcomp/frontend/service/algorithms/_Algorithm.py
@@ -15,13 +15,12 @@
 import json, logging, requests
 from typing import Dict, List, Optional, Tuple, Union
 from common.proto.context_pb2 import (
-    ConfigRule, Connection, Device, DeviceList, EndPointId, Link, LinkList, Service, ServiceStatusEnum,
-    ServiceTypeEnum)
+    Connection, Device, DeviceList, EndPointId, Link, LinkList, Service, ServiceStatusEnum, ServiceTypeEnum)
 from common.proto.pathcomp_pb2 import PathCompReply, PathCompRequest
-from common.tools.object_factory.ConfigRule import json_config_rule_set
 from pathcomp.frontend.Config import BACKEND_URL
-from pathcomp.frontend.service.algorithms.tools.ConstantsMappings import DEVICE_LAYER_TO_SERVICE_TYPE, DeviceLayerEnum
 from .tools.EroPathToHops import eropath_to_hops
+from .tools.ComposeConfigRules import (
+    compose_device_config_rules, compose_l2nm_config_rules, compose_l3nm_config_rules, compose_tapi_config_rules)
 from .tools.ComposeRequest import compose_device, compose_link, compose_service
 from .tools.ComputeSubServices import (
     convert_explicit_path_hops_to_connections, convert_explicit_path_hops_to_plain_connection)
@@ -78,6 +77,8 @@ class _Algorithm:
     def add_links(self, grpc_links : Union[List[Link], LinkList]) -> None:
         if isinstance(grpc_links, LinkList): grpc_links = grpc_links.links
         for grpc_link in grpc_links:
+            if 'mgmt' in grpc_link.name.lower(): continue
+
             json_link = compose_link(grpc_link)
             if len(json_link['link_endpoint_ids']) != 2: continue
             self.link_list.append(json_link)
@@ -148,9 +149,8 @@ class _Algorithm:
         return connection
 
     def add_service_to_reply(
-        self, reply : PathCompReply, context_uuid : str, service_uuid : str,
-        device_layer : Optional[DeviceLayerEnum] = None, path_hops : List[Dict] = [],
-        config_rules : List = []
+        self, reply : PathCompReply, context_uuid : str, service_uuid : str, service_type : ServiceTypeEnum,
+        path_hops : List[Dict] = [], config_rules : List = []
     ) -> Service:
         # TODO: implement support for multi-point services
         # Control deactivated to enable disjoint paths with multiple redundant endpoints on each side
@@ -159,44 +159,41 @@ class _Algorithm:
 
         service_key = (context_uuid, service_uuid)
         tuple_service = self.service_dict.get(service_key)
-        if tuple_service is not None:
-            service = reply.services.add()
-            service.CopyFrom(tuple_service[1])
+
+        service = reply.services.add()
+        service.service_id.context_id.context_uuid.uuid = context_uuid
+        service.service_id.service_uuid.uuid = service_uuid
+        service.service_type = service_type
+
+        if service_type == ServiceTypeEnum.SERVICETYPE_L2NM:
+            compose_l2nm_config_rules(config_rules, service.service_config.config_rules)
+        elif service_type == ServiceTypeEnum.SERVICETYPE_L3NM:
+            compose_l3nm_config_rules(config_rules, service.service_config.config_rules)
+        elif service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
+            compose_tapi_config_rules(config_rules, service.service_config.config_rules)
         else:
-            service = reply.services.add()
-            service.service_id.context_id.context_uuid.uuid = context_uuid
-            service.service_id.service_uuid.uuid = service_uuid
-
-            if device_layer is not None:
-                service_type = DEVICE_LAYER_TO_SERVICE_TYPE.get(device_layer.value)
-                if service_type is None:
-                    MSG = 'Unable to map DeviceLayer({:s}) to ServiceType'
-                    raise Exception(MSG.format(str(device_layer)))
-                service.service_type = service_type
-
-                if service_type == ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE:
-                    json_tapi_settings = {
-                        'capacity_value'  : 50.0,
-                        'capacity_unit'   : 'GHz',
-                        'layer_proto_name': 'PHOTONIC_MEDIA',
-                        'layer_proto_qual': 'tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC',
-                        'direction'       : 'UNIDIRECTIONAL',
-                    }
-                    config_rule = ConfigRule(**json_config_rule_set('/settings', json_tapi_settings))
-                    service.service_config.config_rules.append(config_rule)
-                else:
-                    service.service_config.config_rules.extend(config_rules)
+            MSG = 'Unhandled generic Config Rules for service {:s} {:s}'
+            self.logger.warning(MSG.format(str(service_uuid), str(ServiceTypeEnum.Name(service_type))))
 
-            service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED
+        compose_device_config_rules(config_rules, service.service_config.config_rules, path_hops)
+
+        if path_hops is not None and len(path_hops) > 0:
+            ingress_endpoint_id = service.service_endpoint_ids.add()
+            ingress_endpoint_id.device_id.device_uuid.uuid = path_hops[0]['device']
+            ingress_endpoint_id.endpoint_uuid.uuid = path_hops[0]['ingress_ep']
 
-            if path_hops is not None and len(path_hops) > 0:
-                ingress_endpoint_id = service.service_endpoint_ids.add()
-                ingress_endpoint_id.device_id.device_uuid.uuid = path_hops[0]['device']
-                ingress_endpoint_id.endpoint_uuid.uuid = path_hops[0]['ingress_ep']
+            egress_endpoint_id = service.service_endpoint_ids.add()
+            egress_endpoint_id.device_id.device_uuid.uuid = path_hops[-1]['device']
+            egress_endpoint_id.endpoint_uuid.uuid = path_hops[-1]['egress_ep']
 
-                egress_endpoint_id = service.service_endpoint_ids.add()
-                egress_endpoint_id.device_id.device_uuid.uuid = path_hops[-1]['device']
-                egress_endpoint_id.endpoint_uuid.uuid = path_hops[-1]['egress_ep']
+        if tuple_service is None:
+            service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED
+        else:
+            service.name = tuple_service[1].name
+            service.service_status.CopyFrom(tuple_service[1].service_status)
+            service.timestamp.CopyFrom(tuple_service[1].timestamp)
+            for constraint in tuple_service[1].service_constraints:
+                service.service_constraints.add().CopyFrom(constraint)
 
         return service
 
@@ -206,41 +203,54 @@ class _Algorithm:
         grpc_services : Dict[Tuple[str, str], Service] = {}
         grpc_connections : Dict[str, Connection] = {}
         for response in response_list:
-            service_id = response['serviceId']
-            context_uuid = service_id['contextId']
-            service_uuid = service_id['service_uuid']
-            service_key = (context_uuid, service_uuid)
-            upper_service = self.add_service_to_reply(reply, context_uuid, service_uuid)
-            grpc_services[service_key] = upper_service
+            orig_service_id = response['serviceId']
+            context_uuid = orig_service_id['contextId']
+            main_service_uuid = orig_service_id['service_uuid']
+            orig_service_key = (context_uuid, main_service_uuid)
+            _,grpc_orig_service = self.service_dict[orig_service_key]
+            main_service_type = grpc_orig_service.service_type
 
             no_path_issue = response.get('noPath', {}).get('issue')
             if no_path_issue is not None:
                 # no path found: leave connection with no endpoints
                 # no_path_issue == 1 => no path due to a constraint
+                grpc_services[service_key] = grpc_orig_service
                 continue
 
+            orig_config_rules = grpc_orig_service.service_config.config_rules
+
             for service_path_ero in response['path']:
+                self.logger.debug('service_path_ero["devices"] = {:s}'.format(str(service_path_ero['devices'])))
+                _endpoint_to_link_dict = {k:v[0] for k,v in self.endpoint_to_link_dict.items()}
+                self.logger.debug('self.endpoint_to_link_dict = {:s}'.format(str(_endpoint_to_link_dict)))
                 path_hops = eropath_to_hops(service_path_ero['devices'], self.endpoint_to_link_dict)
+                self.logger.debug('path_hops = {:s}'.format(str(path_hops)))
                 try:
-                    connections = convert_explicit_path_hops_to_connections(path_hops, self.device_dict, service_uuid)
+                    _device_dict = {k:v[0] for k,v in self.device_dict.items()}
+                    self.logger.debug('self.device_dict = {:s}'.format(str(_device_dict)))
+                    connections = convert_explicit_path_hops_to_connections(
+                        path_hops, self.device_dict, main_service_uuid, main_service_type)
+                    self.logger.debug('EXTRAPOLATED connections = {:s}'.format(str(connections)))
                 except: # pylint: disable=bare-except
-                    # if not able to extrapolate sub-services and sub-connections,
-                    # assume single service and single connection
-                    connections = convert_explicit_path_hops_to_plain_connection(path_hops, service_uuid)
+                    MSG = ' '.join([
+                        'Unable to Extrapolate sub-services and sub-connections.',
+                        'Assuming single-service and single-connection.',
+                    ])
+                    self.logger.exception(MSG)
+                    connections = convert_explicit_path_hops_to_plain_connection(
+                        path_hops, main_service_uuid, main_service_type)
+                    self.logger.debug('BASIC connections = {:s}'.format(str(connections)))
 
                 for connection in connections:
-                    connection_uuid,device_layer,path_hops,_ = connection
+                    connection_uuid,service_type,path_hops,_ = connection
                     service_key = (context_uuid, connection_uuid)
-                    grpc_service = grpc_services.get(service_key)
-                    if grpc_service is None:
-                        config_rules = upper_service.service_config.config_rules
-                        grpc_service = self.add_service_to_reply(
-                            reply, context_uuid, connection_uuid, device_layer=device_layer, path_hops=path_hops,
-                            config_rules=config_rules)
-                        grpc_services[service_key] = grpc_service
+                    grpc_service = self.add_service_to_reply(
+                        reply, context_uuid, connection_uuid, service_type, path_hops=path_hops,
+                        config_rules=orig_config_rules)
+                    grpc_services[service_key] = grpc_service
 
                 for connection in connections:
-                    connection_uuid,device_layer,path_hops,dependencies = connection
+                    connection_uuid,_,path_hops,dependencies = connection
 
                     service_key = (context_uuid, connection_uuid)
                     grpc_service = grpc_services.get(service_key)
@@ -251,8 +261,8 @@ class _Algorithm:
                     grpc_connection = self.add_connection_to_reply(reply, connection_uuid, grpc_service, path_hops)
                     grpc_connections[connection_uuid] = grpc_connection
 
-                    for service_uuid in dependencies:
-                        sub_service_key = (context_uuid, service_uuid)
+                    for sub_service_uuid in dependencies:
+                        sub_service_key = (context_uuid, sub_service_uuid)
                         grpc_sub_service = grpc_services.get(sub_service_key)
                         if grpc_sub_service is None:
                             raise Exception('Service({:s}) not found'.format(str(sub_service_key)))
diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py
new file mode 100644
index 0000000000000000000000000000000000000000..30845bb11f2b027d24da3e42e4e4fee12b7da1ba
--- /dev/null
+++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py
@@ -0,0 +1,89 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+#
+# 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.
+
+import json, re
+from typing import Dict, List, Optional
+from common.proto.context_pb2 import ConfigRule
+from common.tools.object_factory.ConfigRule import json_config_rule_set
+
+SETTINGS_RULE_NAME = '/settings'
+
+DEV_EP_SETTINGS = re.compile(r'\/device\[([^\]]+)\]\/endpoint\[([^\]]+)\]\/settings')
+
+L2NM_SETTINGS_FIELD_DEFAULTS = {
+    'encapsulation_type': 'dot1q',
+    'vlan_id'           : 100,
+    'mtu'               : 1450,
+}
+
+L3NM_SETTINGS_FIELD_DEFAULTS = {
+    'encapsulation_type': 'dot1q',
+    'vlan_id'           : 100,
+    'mtu'               : 1450,
+}
+
+TAPI_SETTINGS_FIELD_DEFAULTS = {
+    'capacity_value'  : 50.0,
+    'capacity_unit'   : 'GHz',
+    'layer_proto_name': 'PHOTONIC_MEDIA',
+    'layer_proto_qual': 'tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC',
+    'direction'       : 'UNIDIRECTIONAL',
+}
+
+def find_custom_config_rule(config_rules : List, resource_name : str) -> Optional[Dict]:
+    resource_value : Optional[Dict] = None
+    for config_rule in config_rules:
+        if config_rule.WhichOneof('config_rule') != 'custom': continue
+        if config_rule.custom.resource_key != resource_name: continue
+        resource_value = json.loads(config_rule.custom.resource_value)
+    return resource_value
+
+def compose_config_rules(
+    main_service_config_rules : List, subservice_config_rules : List, field_defaults : Dict
+) -> None:
+    settings = find_custom_config_rule(main_service_config_rules, SETTINGS_RULE_NAME)
+    if settings is None: return
+
+    json_settings = {}
+    for field_name,default_value in field_defaults.items():
+        json_settings[field_name] = settings.get(field_name, default_value)
+
+    config_rule = ConfigRule(**json_config_rule_set('/settings', json_settings))
+    subservice_config_rules.append(config_rule)
+
+def compose_l2nm_config_rules(main_service_config_rules : List, subservice_config_rules : List) -> None:
+    compose_config_rules(main_service_config_rules, subservice_config_rules, L2NM_SETTINGS_FIELD_DEFAULTS)
+
+def compose_l3nm_config_rules(main_service_config_rules : List, subservice_config_rules : List) -> None:
+    compose_config_rules(main_service_config_rules, subservice_config_rules, L3NM_SETTINGS_FIELD_DEFAULTS)
+
+def compose_tapi_config_rules(main_service_config_rules : List, subservice_config_rules : List) -> None:
+    compose_config_rules(main_service_config_rules, subservice_config_rules, TAPI_SETTINGS_FIELD_DEFAULTS)
+
+def compose_device_config_rules(config_rules : List, subservice_config_rules : List, path_hops : List) -> None:
+    endpoints_traversed = set()
+    for path_hop in path_hops:
+        device_uuid_or_name = path_hop['device']
+        endpoints_traversed.add((device_uuid_or_name, path_hop['ingress_ep']))
+        endpoints_traversed.add((device_uuid_or_name, path_hop['egress_ep']))
+
+    for config_rule in config_rules:
+        if config_rule.WhichOneof('config_rule') != 'custom': continue
+        match = DEV_EP_SETTINGS.match(config_rule.custom.resource_key)
+        if match is None: continue
+        device_uuid_or_name = match.group(1)
+        endpoint_uuid_or_name = match.group(2)
+        dev_ep_kep = (device_uuid_or_name, endpoint_uuid_or_name)
+        if dev_ep_kep not in endpoints_traversed: continue
+        subservice_config_rules.append(config_rule)
diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py b/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py
index b92a19b52c4887e01f7f1bc58de897c783683eeb..75701b99e327792f0e97068c25b594976e1ebc9e 100644
--- a/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py
+++ b/src/pathcomp/frontend/service/algorithms/tools/ComputeSubServices.py
@@ -30,56 +30,176 @@
 # ]
 #
 # connections=[
-#     (UUID('7548edf7-ee7c-4adf-ac0f-c7a0c0dfba8e'), <DeviceLayerEnum.OPTICAL_CONTROLLER: 1>, [
+#     (UUID('7548edf7-ee7c-4adf-ac0f-c7a0c0dfba8e'), ServiceTypeEnum.TAPI, [
 #             {'device': 'TN-OLS', 'ingress_ep': '833760219d0f', 'egress_ep': 'cf176771a4b9'}
 #         ], []),
-#     (UUID('c2e57966-5d82-4705-a5fe-44cf6487219e'), <DeviceLayerEnum.PACKET_DEVICE: 30>, [
+#     (UUID('c2e57966-5d82-4705-a5fe-44cf6487219e'), ServiceTypeEnum.L2NM, [
 #             {'device': 'CS1-GW1', 'ingress_ep': '10/1', 'egress_ep': '1/2'},
 #             {'device': 'TN-R2', 'ingress_ep': '1/2', 'egress_ep': '2/1'},
 #             {'device': 'TN-R3', 'ingress_ep': '2/1', 'egress_ep': '1/1'},
 #             {'device': 'CS2-GW1', 'ingress_ep': '1/1', 'egress_ep': '10/1'}
 #         ], [UUID('7548edf7-ee7c-4adf-ac0f-c7a0c0dfba8e')]),
-#     (UUID('1e205c82-f6ea-4977-9e97-dc27ef1f4802'), <DeviceLayerEnum.APPLICATION_DEVICE: 40>, [
+#     (UUID('1e205c82-f6ea-4977-9e97-dc27ef1f4802'), ServiceTypeEnum.L2NM, [
 #             {'device': 'DC1-GW', 'ingress_ep': 'int', 'egress_ep': 'eth1'},
 #             {'device': 'DC2-GW', 'ingress_ep': 'eth1', 'egress_ep': 'int'}
 #         ], [UUID('c2e57966-5d82-4705-a5fe-44cf6487219e')])
 # ]
 
-import queue, uuid
-from typing import Dict, List, Tuple
-from common.proto.context_pb2 import Device
-from .ConstantsMappings import DEVICE_TYPE_TO_LAYER, DeviceLayerEnum
+import enum, json, queue, uuid
+from typing import Dict, List, Optional, Tuple
+from common.DeviceTypes import DeviceTypeEnum
+from common.proto.context_pb2 import Device, ServiceTypeEnum
+
+class StackActionEnum(enum.Enum):
+    PATH_INGRESS         = 'ingress'
+    CREATE_CONNECTION    = 'create'
+    APPEND_PATH_HOP      = 'append'
+    CHAIN_CONNECTION     = 'chain'
+    TERMINATE_CONNECTION = 'terminate'
+
+def is_datacenter(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.DATACENTER, DeviceTypeEnum.EMULATED_DATACENTER}
+
+def is_packet_router(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.PACKET_ROUTER, DeviceTypeEnum.EMULATED_PACKET_ROUTER}
+
+def is_packet_switch(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.PACKET_SWITCH, DeviceTypeEnum.EMULATED_PACKET_SWITCH}
+
+def is_packet_device(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return is_packet_router(dev_type) or is_packet_switch(dev_type)
+
+def is_tfs_controller(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.TERAFLOWSDN_CONTROLLER}
+
+def is_mw_controller(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.MICROWAVE_RADIO_SYSTEM, DeviceTypeEnum.EMULATED_MICROWAVE_RADIO_SYSTEM}
+
+def is_ipm_controller(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.XR_CONSTELLATION, DeviceTypeEnum.EMULATED_XR_CONSTELLATION}
+
+def is_ols_controller(dev_type : Optional[DeviceTypeEnum]) -> bool:
+    return dev_type in {DeviceTypeEnum.OPEN_LINE_SYSTEM, DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM}
+
+def is_subdevice(dev_manager : Optional[str]) -> bool:
+    return dev_manager is not None
+
+def is_subdevice_equal(dev_manager_a : Optional[str], dev_manager_b : Optional[str]) -> bool:
+    if dev_manager_a is None and dev_manager_b is None: return True
+    if dev_manager_a is not None and dev_manager_b is not None: return dev_manager_a == dev_manager_b
+    return False
+
+def get_action(
+    prv_type : Optional[DeviceTypeEnum], prv_manager : Optional[str],
+    cur_type : DeviceTypeEnum, cur_manager : Optional[str]
+) -> StackActionEnum:
+    if prv_type is None:
+        return StackActionEnum.PATH_INGRESS
+
+    if is_datacenter(prv_type):
+        if is_packet_device(cur_type): return StackActionEnum.CREATE_CONNECTION
+        if is_tfs_controller(cur_type): return StackActionEnum.CREATE_CONNECTION
+
+    if is_packet_device(prv_type):
+        if is_datacenter(cur_type): return StackActionEnum.TERMINATE_CONNECTION
+        if is_packet_device(cur_type):
+            if is_subdevice_equal(cur_manager, prv_manager): return StackActionEnum.APPEND_PATH_HOP
+            if is_subdevice(prv_manager) and not is_subdevice(cur_manager): return StackActionEnum.TERMINATE_CONNECTION
+            if not is_subdevice(prv_manager) and is_subdevice(cur_manager): return StackActionEnum.CREATE_CONNECTION
+
+        if is_mw_controller(cur_type) and not is_subdevice(cur_manager): return StackActionEnum.CREATE_CONNECTION
+        if is_ols_controller(cur_type) and not is_subdevice(cur_manager): return StackActionEnum.CREATE_CONNECTION
+        if is_tfs_controller(cur_type) and is_subdevice(cur_manager): return StackActionEnum.CREATE_CONNECTION
+
+    if is_mw_controller(prv_type) or is_ols_controller(prv_type):
+        if is_packet_device(cur_type): return StackActionEnum.TERMINATE_CONNECTION
+
+    if is_tfs_controller(prv_type):
+        if is_tfs_controller(cur_type) and is_subdevice_equal(prv_manager, cur_manager): return StackActionEnum.APPEND_PATH_HOP
+        if is_datacenter(cur_type): return StackActionEnum.TERMINATE_CONNECTION
+        if is_packet_device(cur_type): return StackActionEnum.TERMINATE_CONNECTION
+        if is_mw_controller(cur_type) or is_ols_controller(cur_type): return StackActionEnum.CHAIN_CONNECTION
+
+    str_fields = ', '.join([
+        'prv_type={:s}'.format(str(prv_type)), 'prv_manager={:s}'.format(str(prv_manager)),
+        'cur_type={:s}'.format(str(cur_type)), 'cur_manager={:s}'.format(str(cur_manager)),
+    ])
+    raise Exception('Undefined Action for ({:s})'.format(str_fields))
+
+def get_device_manager_uuid(device : Device) -> Optional[str]:
+    for config_rule in device.device_config.config_rules:
+        if config_rule.WhichOneof('config_rule') != 'custom': continue
+        if config_rule.custom.resource_key != '_manager': continue
+        device_manager_id = json.loads(config_rule.custom.resource_value)
+        return device_manager_id['uuid']
+    return None
+
+def get_device_type(
+    grpc_device : Device, device_dict : Dict[str, Tuple[Dict, Device]], device_manager_uuid : Optional[str]
+) -> DeviceTypeEnum:
+    if device_manager_uuid is None:
+        return DeviceTypeEnum._value2member_map_[grpc_device.device_type] # pylint: disable=no-member
+    device_manager_tuple = device_dict.get(device_manager_uuid)
+    if device_manager_tuple is None: raise Exception('Device({:s}) not found'.format(str(device_manager_uuid)))
+    _,grpc_device = device_manager_tuple
+    return DeviceTypeEnum._value2member_map_[grpc_device.device_type] # pylint: disable=no-member
+
+SERVICE_TYPE_LXNM = {ServiceTypeEnum.SERVICETYPE_L3NM, ServiceTypeEnum.SERVICETYPE_L2NM}
+
+def get_service_type(device_type : DeviceTypeEnum, prv_service_type : ServiceTypeEnum) -> ServiceTypeEnum:
+    if is_tfs_controller(device_type) or is_packet_router(device_type):
+        if prv_service_type in SERVICE_TYPE_LXNM: return prv_service_type
+    if is_packet_switch(device_type) or is_mw_controller(device_type):
+        if prv_service_type == ServiceTypeEnum.SERVICETYPE_L2NM: return prv_service_type
+    if is_ols_controller(device_type) or is_ipm_controller(device_type):
+        return ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE
+
+    str_fields = ', '.join([
+        'device_type={:s}'.format(str(device_type)),
+    ])
+    raise Exception('Undefined Service Type for ({:s})'.format(str_fields))
 
 def convert_explicit_path_hops_to_connections(
-    path_hops : List[Dict], device_dict : Dict[str, Tuple[Dict, Device]], main_connection_uuid : str
-) -> List[Tuple[str, DeviceLayerEnum, List[str], List[str]]]:
+    path_hops : List[Dict], device_dict : Dict[str, Tuple[Dict, Device]],
+    main_service_uuid : str, main_service_type : ServiceTypeEnum
+) -> List[Tuple[str, int, List[str], List[str]]]:
 
     connection_stack = queue.LifoQueue()
-    connections : List[Tuple[str, DeviceLayerEnum, List[str], List[str]]] = list()
-    old_device_layer = None
-    last_device_uuid = None
+    connections : List[Tuple[str, int, List[str], List[str]]] = list()
+    prv_device_uuid = None
+    prv_device_type = None
+    prv_manager_uuid = None
+
     for path_hop in path_hops:
         device_uuid = path_hop['device']
-        if last_device_uuid == device_uuid: continue
+        if prv_device_uuid == device_uuid: continue
         device_tuple = device_dict.get(device_uuid)
         if device_tuple is None: raise Exception('Device({:s}) not found'.format(str(device_uuid)))
-        json_device,_ = device_tuple
-        device_type = json_device['device_type']
-        device_layer = DEVICE_TYPE_TO_LAYER.get(device_type)
-        if device_layer is None: raise Exception('Undefined Layer for DeviceType({:s})'.format(str(device_type)))
-
-        if old_device_layer is None:
-            # path ingress
-            connection_stack.put((main_connection_uuid, device_layer, [path_hop], []))
-        elif old_device_layer > device_layer:
-            # underlying connection begins
+        _,grpc_device = device_tuple
+
+        manager_uuid = get_device_manager_uuid(grpc_device)
+        device_type = get_device_type(grpc_device, device_dict, manager_uuid)
+        action = get_action(prv_device_type, prv_manager_uuid, device_type, manager_uuid)
+
+        if action == StackActionEnum.PATH_INGRESS:
+            connection_stack.put((main_service_uuid, main_service_type, [path_hop], []))
+        elif action == StackActionEnum.CREATE_CONNECTION:
             connection_uuid = str(uuid.uuid4())
-            connection_stack.put((connection_uuid, device_layer, [path_hop], []))
-        elif old_device_layer == device_layer:
-            # same connection continues
+            prv_service_type = connection_stack.queue[-1][1]
+            service_type = get_service_type(device_type, prv_service_type)
+            connection_stack.put((connection_uuid, service_type, [path_hop], []))
+        elif action == StackActionEnum.APPEND_PATH_HOP:
             connection_stack.queue[-1][2].append(path_hop)
-        elif old_device_layer < device_layer:
-            # underlying connection ended
+        elif action == StackActionEnum.CHAIN_CONNECTION:
+            connection = connection_stack.get()
+            connections.append(connection)
+            connection_stack.queue[-1][3].append(connection[0])
+
+            connection_uuid = str(uuid.uuid4())
+            prv_service_type = connection_stack.queue[-1][1]
+            service_type = get_service_type(device_type, prv_service_type)
+            connection_stack.put((connection_uuid, service_type, [path_hop], []))
+        elif action == StackActionEnum.TERMINATE_CONNECTION:
             connection = connection_stack.get()
             connections.append(connection)
             connection_stack.queue[-1][3].append(connection[0])
@@ -87,8 +207,9 @@ def convert_explicit_path_hops_to_connections(
         else:
             raise Exception('Uncontrolled condition')
 
-        old_device_layer = device_layer
-        last_device_uuid = device_uuid
+        prv_device_uuid = device_uuid
+        prv_device_type = device_type
+        prv_manager_uuid = manager_uuid
 
     # path egress
     connections.append(connection_stack.get())
@@ -96,17 +217,17 @@ def convert_explicit_path_hops_to_connections(
     return connections
 
 def convert_explicit_path_hops_to_plain_connection(
-    path_hops : List[Dict], main_connection_uuid : str
-) -> List[Tuple[str, DeviceLayerEnum, List[str], List[str]]]:
+    path_hops : List[Dict], main_service_uuid : str, main_service_type : ServiceTypeEnum
+) -> List[Tuple[str, int, List[str], List[str]]]:
 
-    connection : Tuple[str, DeviceLayerEnum, List[str], List[str]] = \
-        (main_connection_uuid, DeviceLayerEnum.PACKET_DEVICE, [], [])
+    connection : Tuple[str, int, List[str], List[str]] = \
+        (main_service_uuid, main_service_type, [], [])
 
-    last_device_uuid = None
+    prv_device_uuid = None
     for path_hop in path_hops:
         device_uuid = path_hop['device']
-        if last_device_uuid == device_uuid: continue
+        if prv_device_uuid == device_uuid: continue
         connection[2].append(path_hop)
-        last_device_uuid = device_uuid
+        prv_device_uuid = device_uuid
 
     return [connection]
diff --git a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
index cd1956a873dd2170c7a75db0c677db34162449ee..bd06e6ba19b3da9e2d38d5b83e1d7d3a806ff14f 100644
--- a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
+++ b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
@@ -13,8 +13,6 @@
 # limitations under the License.
 
 from enum import IntEnum
-from common.DeviceTypes import DeviceTypeEnum
-from common.proto.context_pb2 import ServiceTypeEnum
 
 class CapacityUnit(IntEnum):
     TB   = 0
@@ -66,50 +64,3 @@ class LinkForwardingDirection(IntEnum):
     BIDIRECTIONAL  = 0
     UNIDIRECTIONAL = 1
     UNKNOWN        = 2
-
-class DeviceLayerEnum(IntEnum):
-    APPLICATION_CONTROLLER = 41     # Layer 4 domain controller
-    APPLICATION_DEVICE     = 40     # Layer 4 domain device
-    PACKET_CONTROLLER      = 31     # Layer 3 domain controller
-    PACKET_DEVICE          = 30     # Layer 3 domain device
-    MAC_LAYER_CONTROLLER   = 21     # Layer 2 domain controller
-    MAC_LAYER_DEVICE       = 20     # Layer 2 domain device
-    OPTICAL_CONTROLLER     =  1     # Layer 0 domain controller
-    OPTICAL_DEVICE         =  0     # Layer 0 domain device
-
-DEVICE_TYPE_TO_LAYER = {
-    DeviceTypeEnum.EMULATED_DATACENTER.value             : DeviceLayerEnum.APPLICATION_DEVICE,
-    DeviceTypeEnum.DATACENTER.value                      : DeviceLayerEnum.APPLICATION_DEVICE,
-    DeviceTypeEnum.NETWORK.value                         : DeviceLayerEnum.APPLICATION_DEVICE,
-
-    DeviceTypeEnum.EMULATED_PACKET_ROUTER.value          : DeviceLayerEnum.PACKET_DEVICE,
-    DeviceTypeEnum.PACKET_ROUTER.value                   : DeviceLayerEnum.PACKET_DEVICE,
-    DeviceTypeEnum.EMULATED_PACKET_SWITCH.value          : DeviceLayerEnum.MAC_LAYER_DEVICE,
-    DeviceTypeEnum.PACKET_SWITCH.value                   : DeviceLayerEnum.MAC_LAYER_DEVICE,
-
-    DeviceTypeEnum.EMULATED_P4_SWITCH.value              : DeviceLayerEnum.MAC_LAYER_DEVICE,
-    DeviceTypeEnum.P4_SWITCH.value                       : DeviceLayerEnum.MAC_LAYER_DEVICE,
-
-    DeviceTypeEnum.EMULATED_MICROWAVE_RADIO_SYSTEM.value : DeviceLayerEnum.MAC_LAYER_CONTROLLER,
-    DeviceTypeEnum.MICROWAVE_RADIO_SYSTEM.value          : DeviceLayerEnum.MAC_LAYER_CONTROLLER,
-
-    DeviceTypeEnum.EMULATED_OPEN_LINE_SYSTEM.value       : DeviceLayerEnum.OPTICAL_CONTROLLER,
-    DeviceTypeEnum.OPEN_LINE_SYSTEM.value                : DeviceLayerEnum.OPTICAL_CONTROLLER,
-    DeviceTypeEnum.XR_CONSTELLATION.value                : DeviceLayerEnum.OPTICAL_CONTROLLER,
-
-    DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value          : DeviceLayerEnum.OPTICAL_DEVICE,
-    DeviceTypeEnum.OPTICAL_ROADM.value                   : DeviceLayerEnum.OPTICAL_DEVICE,
-    DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value    : DeviceLayerEnum.OPTICAL_DEVICE,
-    DeviceTypeEnum.OPTICAL_TRANSPONDER.value             : DeviceLayerEnum.OPTICAL_DEVICE,
-}
-
-DEVICE_LAYER_TO_SERVICE_TYPE = {
-    DeviceLayerEnum.APPLICATION_DEVICE.value   : ServiceTypeEnum.SERVICETYPE_L3NM,
-    DeviceLayerEnum.PACKET_DEVICE.value        : ServiceTypeEnum.SERVICETYPE_L3NM,
-
-    DeviceLayerEnum.MAC_LAYER_CONTROLLER.value : ServiceTypeEnum.SERVICETYPE_L2NM,
-    DeviceLayerEnum.MAC_LAYER_DEVICE.value     : ServiceTypeEnum.SERVICETYPE_L2NM,
-
-    DeviceLayerEnum.OPTICAL_CONTROLLER.value   : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE,
-    DeviceLayerEnum.OPTICAL_DEVICE.value       : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE,
-}