diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
index 23f61b492b63acd8176fa4aeafc475d71c63ead6..ed2f01af10a262a7f51f308563f1e823ba6f19ad 100644
--- a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_Service.py
@@ -20,6 +20,7 @@ from common.Constants import DEFAULT_CONTEXT_UUID
 from common.proto.context_pb2 import ServiceId, ServiceStatusEnum, SliceStatusEnum
 from context.client.ContextClient import ContextClient
 from service.client.ServiceClient import ServiceClient
+from slice.client.SliceClient import SliceClient
 from .tools.Authentication import HTTP_AUTH
 from .tools.ContextMethods import get_service, get_slice
 from .tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK, HTTP_SERVERERROR
@@ -32,11 +33,6 @@ class L2VPN_Service(Resource):
         LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id)))
         LOGGER.debug('Request: {:s}'.format(str(request)))
 
-        # TODO: HACK ECOC'22, to be corrected
-        response = jsonify({})
-        response.status_code = HTTP_OK
-        return response
-
         try:
             context_client = ContextClient()
 
@@ -60,7 +56,7 @@ class L2VPN_Service(Resource):
 
             raise Exception('VPN({:s}) not found in database'.format(str(vpn_id)))
         except Exception as e: # pylint: disable=broad-except
-            LOGGER.exception('Something went wrong Retrieving VPN({:s})'.format(str(request)))
+            LOGGER.exception('Something went wrong Retrieving VPN({:s})'.format(str(vpn_id)))
             response = jsonify({'error': str(e)})
             response.status_code = HTTP_SERVERERROR
         return response
@@ -70,18 +66,32 @@ class L2VPN_Service(Resource):
         LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id)))
         LOGGER.debug('Request: {:s}'.format(str(request)))
 
-        # pylint: disable=no-member
-        service_id_request = ServiceId()
-        service_id_request.context_id.context_uuid.uuid = DEFAULT_CONTEXT_UUID
-        service_id_request.service_uuid.uuid = vpn_id
-
         try:
-            service_client = ServiceClient()
-            service_client.DeleteService(service_id_request)
-            response = jsonify({})
-            response.status_code = HTTP_NOCONTENT
+            context_client = ContextClient()
+
+            target = get_service(context_client, vpn_id)
+            if target is not None:
+                if target.service_id.service_uuid.uuid != vpn_id: # pylint: disable=no-member
+                    raise Exception('Service retrieval failed. Wrong Service Id was returned')
+                service_client = ServiceClient()
+                service_client.DeleteService(target.service_id)
+                response = jsonify({})
+                response.status_code = HTTP_NOCONTENT
+                return response
+
+            target = get_slice(context_client, vpn_id)
+            if target is not None:
+                if target.slice_id.slice_uuid.uuid != vpn_id: # pylint: disable=no-member
+                    raise Exception('Slice retrieval failed. Wrong Slice Id was returned')
+                slice_client = SliceClient()
+                slice_client.DeleteSlice(target.slice_id)
+                response = jsonify({})
+                response.status_code = HTTP_NOCONTENT
+                return response
+
+            raise Exception('VPN({:s}) not found in database'.format(str(vpn_id)))
         except Exception as e: # pylint: disable=broad-except
-            LOGGER.exception('Something went wrong Deleting Service {:s}'.format(str(request)))
+            LOGGER.exception('Something went wrong Deleting VPN({:s})'.format(str(vpn_id)))
             response = jsonify({'error': str(e)})
             response.status_code = HTTP_SERVERERROR
         return response
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
index 2abeade30b8b5658bfd401820c71474ebfad85d5..4019099401316e943b8ae1ae1442deb6b1ec1722 100644
--- a/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_l2vpn/L2VPN_SiteNetworkAccesses.py
@@ -12,16 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import time, random
-from ctypes import Union
-import json, logging
-from typing import Dict
+import logging, random, time
+from typing import Dict, Optional, Union
 from flask import request
 from flask.json import jsonify
 from flask.wrappers import Response
 from flask_restful import Resource
 from werkzeug.exceptions import UnsupportedMediaType
-from common.proto.context_pb2 import ConfigActionEnum, Service, Slice
+from common.proto.context_pb2 import Service, Slice
+from common.tools.grpc.ConfigRules import update_config_rule_custom
+from common.tools.grpc.Constraints import (
+    update_constraint_custom, update_constraint_endpoint_location, update_constraint_endpoint_priority,
+    update_constraint_sla_availability)
+from common.tools.grpc.EndPointIds import update_endpoint_ids
 from common.tools.grpc.Tools import grpc_message_to_json_string
 from context.client.ContextClient import ContextClient
 from service.client.ServiceClient import ServiceClient
@@ -31,20 +34,32 @@ from .tools.Authentication import HTTP_AUTH
 from .tools.ContextMethods import get_service, get_slice
 from .tools.HttpStatusCodes import HTTP_NOCONTENT, HTTP_SERVERERROR
 from .tools.Validator import validate_message
-from .Constants import BEARER_MAPPINGS, DEFAULT_ADDRESS_FAMILIES, DEFAULT_BGP_AS, DEFAULT_BGP_ROUTE_TARGET, DEFAULT_MTU
+from .Constants import (
+    BEARER_MAPPINGS, DEFAULT_ADDRESS_FAMILIES, DEFAULT_BGP_AS, DEFAULT_BGP_ROUTE_TARGET, DEFAULT_MTU)
 
 LOGGER = logging.getLogger(__name__)
 
-def process_site_network_access(context_client : ContextClient, site_network_access : Dict) -> Service:
+def process_site_network_access(context_client : ContextClient, site_id : str, site_network_access : Dict) -> Service:
     vpn_id = site_network_access['vpn-attachment']['vpn-id']
-    cvlan_id = site_network_access['connection']['tagged-interface']['dot1q-vlan-tagged']['cvlan-id']
+    encapsulation_type = site_network_access['connection']['encapsulation-type']
+    cvlan_id = site_network_access['connection']['tagged-interface'][encapsulation_type]['cvlan-id']
+
     bearer_reference = site_network_access['bearer']['bearer-reference']
-    access_priority = site_network_access.get('availability', {}).get('access-priority')
-    single_active = site_network_access.get('availability', {}).get('single-active')
-    all_active = site_network_access.get('availability', {}).get('all-active')
+
+    access_priority : Optional[int] = site_network_access.get('availability', {}).get('access-priority')
+    single_active   : bool = len(site_network_access.get('availability', {}).get('single-active', [])) > 0
+    all_active      : bool = len(site_network_access.get('availability', {}).get('all-active', [])) > 0
+
     diversity_constraints = site_network_access.get('access-diversity', {}).get('constraints', {}).get('constraint', [])
-    # TODO: manage targets of constraints, right now, only type of constraint is considered
-    diversity_constraints = [constraint['constraint-type'] for constraint in diversity_constraints]
+    raise_if_differs = True
+    diversity_constraints = {
+        constraint['constraint-type']:([
+            target[0]
+            for target in constraint['target'].items()
+            if len(target[1]) == 1
+        ][0], raise_if_differs)
+        for constraint in diversity_constraints
+    }
 
     mapping = BEARER_MAPPINGS.get(bearer_reference)
     if mapping is None:
@@ -57,157 +72,61 @@ def process_site_network_access(context_client : ContextClient, site_network_acc
     if target is None: target = get_slice  (context_client, vpn_id)
     if target is None: raise Exception('VPN({:s}) not found in database'.format(str(vpn_id)))
 
-    # pylint: disable=no-member
-    endpoint_ids = target.service_endpoint_ids if isinstance(target, Service) else target.slice_endpoint_ids
-
-    for endpoint_id in endpoint_ids:
-        if endpoint_id.device_id.device_uuid.uuid != device_uuid: continue
-        if endpoint_id.endpoint_uuid.uuid != endpoint_uuid: continue
-        break   # found, do nothing
+    if isinstance(target, Service):
+        endpoint_ids = target.service_endpoint_ids        # pylint: disable=no-member
+        config_rules = target.service_config.config_rules # pylint: disable=no-member
+        constraints  = target.service_constraints         # pylint: disable=no-member
+    elif isinstance(target, Slice):
+        endpoint_ids = target.slice_endpoint_ids        # pylint: disable=no-member
+        config_rules = target.slice_config.config_rules # pylint: disable=no-member
+        constraints  = target.slice_constraints         # pylint: disable=no-member
     else:
-        # not found, add it
-        endpoint_id = endpoint_ids.add()
-        endpoint_id.device_id.device_uuid.uuid = device_uuid
-        endpoint_id.endpoint_uuid.uuid = endpoint_uuid
-
-    if isinstance(target, Slice): return target
-
-    for config_rule in target.service_config.config_rules:                  # pylint: disable=no-member
-        if config_rule.WhichOneof('config_rule') != 'custom': continue
-        if config_rule.custom.resource_key != '/settings': continue
-        json_settings = json.loads(config_rule.custom.resource_value)
+        raise Exception('Target({:s}) not supported'.format(str(target.__class__.__name__)))
 
-        if 'mtu' not in json_settings:                                      # missing, add it
-            json_settings['mtu'] = DEFAULT_MTU
-        elif json_settings['mtu'] != DEFAULT_MTU:                           # differs, raise exception
-            msg = 'Specified MTU({:s}) differs from Service MTU({:s})'
-            raise Exception(msg.format(str(json_settings['mtu']), str(DEFAULT_MTU)))
+    endpoint_id = update_endpoint_ids(endpoint_ids, device_uuid, endpoint_uuid)
 
-        if 'address_families' not in json_settings:                         # missing, add it
-            json_settings['address_families'] = DEFAULT_ADDRESS_FAMILIES
-        elif json_settings['address_families'] != DEFAULT_ADDRESS_FAMILIES: # differs, raise exception
-            msg = 'Specified AddressFamilies({:s}) differs from Service AddressFamilies({:s})'
-            raise Exception(msg.format(str(json_settings['address_families']), str(DEFAULT_ADDRESS_FAMILIES)))
-
-        if 'bgp_as' not in json_settings:                                   # missing, add it
-            json_settings['bgp_as'] = DEFAULT_BGP_AS
-        elif json_settings['bgp_as'] != DEFAULT_BGP_AS:                     # differs, raise exception
-            msg = 'Specified BgpAs({:s}) differs from Service BgpAs({:s})'
-            raise Exception(msg.format(str(json_settings['bgp_as']), str(DEFAULT_BGP_AS)))
-
-        if 'bgp_route_target' not in json_settings:                         # missing, add it
-            json_settings['bgp_route_target'] = DEFAULT_BGP_ROUTE_TARGET
-        elif json_settings['bgp_route_target'] != DEFAULT_BGP_ROUTE_TARGET: # differs, raise exception
-            msg = 'Specified BgpRouteTarget({:s}) differs from Service BgpRouteTarget({:s})'
-            raise Exception(msg.format(str(json_settings['bgp_route_target']), str(DEFAULT_BGP_ROUTE_TARGET)))
-
-        config_rule.custom.resource_value = json.dumps(json_settings, sort_keys=True)
-        break
-    else:
-        # not found, add it
-        config_rule = target.service_config.config_rules.add()              # pylint: disable=no-member
-        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
-        config_rule.custom.resource_key = '/settings'
-        config_rule.custom.resource_value = json.dumps({
-            'mtu'             : DEFAULT_MTU,
-            'address_families': DEFAULT_ADDRESS_FAMILIES,
-            'bgp_as'          : DEFAULT_BGP_AS,
-            'bgp_route_target': DEFAULT_BGP_ROUTE_TARGET,
-        }, sort_keys=True)
+    service_settings_key = '/settings'
+    update_config_rule_custom(config_rules, service_settings_key, {
+        'mtu'             : (DEFAULT_MTU,              True),
+        'address_families': (DEFAULT_ADDRESS_FAMILIES, True),
+        'bgp_as'          : (DEFAULT_BGP_AS,           True),
+        'bgp_route_target': (DEFAULT_BGP_ROUTE_TARGET, True),
+    })
 
     endpoint_settings_key = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid)
-    for config_rule in target.service_config.config_rules:                  # pylint: disable=no-member
-        if config_rule.WhichOneof('config_rule') != 'custom': continue
-        if config_rule.custom.resource_key != endpoint_settings_key: continue
-        json_settings = json.loads(config_rule.custom.resource_value)
-
-        if 'router_id' not in json_settings:                                # missing, add it
-            json_settings['router_id'] = router_id
-        elif json_settings['router_id'] != router_id:                       # differs, raise exception
-            msg = 'Specified RouterId({:s}) differs from Service RouterId({:s})'
-            raise Exception(msg.format(str(json_settings['router_id']), str(router_id)))
-
-        if 'route_distinguisher' not in json_settings:                      # missing, add it
-            json_settings['route_distinguisher'] = route_distinguisher
-        elif json_settings['route_distinguisher'] != route_distinguisher:   # differs, raise exception
-            msg = 'Specified RouteDistinguisher({:s}) differs from Service RouteDistinguisher({:s})'
-            raise Exception(msg.format(str(json_settings['route_distinguisher']), str(route_distinguisher)))
-
-        if 'sub_interface_index' not in json_settings:                      # missing, add it
-            json_settings['sub_interface_index'] = sub_if_index
-        elif json_settings['sub_interface_index'] != sub_if_index:   # differs, raise exception
-            msg = 'Specified SubInterfaceIndex({:s}) differs from Service SubInterfaceIndex({:s})'
-            raise Exception(msg.format(
-                str(json_settings['sub_interface_index']), str(sub_if_index)))
-
-        if 'vlan_id' not in json_settings:                                  # missing, add it
-            json_settings['vlan_id'] = cvlan_id
-        elif json_settings['vlan_id'] != cvlan_id:                          # differs, raise exception
-            msg = 'Specified VLANId({:s}) differs from Service VLANId({:s})'
-            raise Exception(msg.format(
-                str(json_settings['vlan_id']), str(cvlan_id)))
-
-        if address_ip is not None:
-            if 'address_ip' not in json_settings:                               # missing, add it
-                json_settings['address_ip'] = address_ip
-            elif json_settings['address_ip'] != address_ip:                     # differs, raise exception
-                msg = 'Specified AddressIP({:s}) differs from Service AddressIP({:s})'
-                raise Exception(msg.format(
-                    str(json_settings['address_ip']), str(address_ip)))
-
-        if address_prefix is not None:
-            if 'address_prefix' not in json_settings:                           # missing, add it
-                json_settings['address_prefix'] = address_prefix
-            elif json_settings['address_prefix'] != address_prefix:             # differs, raise exception
-                msg = 'Specified AddressPrefix({:s}) differs from Service AddressPrefix({:s})'
-                raise Exception(msg.format(
-                    str(json_settings['address_prefix']), str(address_prefix)))
-
-        if address_prefix is not None:
-            if 'address_prefix' not in json_settings:                           # missing, add it
-                json_settings['address_prefix'] = address_prefix
-            elif json_settings['address_prefix'] != address_prefix:             # differs, raise exception
-                msg = 'Specified AddressPrefix({:s}) differs from Service AddressPrefix({:s})'
-                raise Exception(msg.format(
-                    str(json_settings['address_prefix']), str(address_prefix)))
-
-        config_rule.custom.resource_value = json.dumps(json_settings, sort_keys=True)
-        break
-    else:
-        # not found, add it
-        config_rule = target.service_config.config_rules.add()              # pylint: disable=no-member
-        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
-        resource_value = {
-            'router_id': router_id,
-            'route_distinguisher': route_distinguisher,
-            'sub_interface_index': sub_if_index,
-            'vlan_id': cvlan_id,
-            'address_ip': address_ip,
-            'address_prefix': address_prefix,
-        }
-        if access_priority is not None: resource_value['access_priority'] = access_priority
-        if single_active is not None and len(single_active) > 0: resource_value['access_active'] = 'single'
-        if all_active is not None and len(all_active) > 0: resource_value['access_active'] = 'all'
-        config_rule.custom.resource_key = endpoint_settings_key
-        config_rule.custom.resource_value = json.dumps(resource_value, sort_keys=True)
-
-    for constraint in target.service_constraints:                           # pylint: disable=no-member
-        if constraint.constraint_type == 'diversity' and len(diversity_constraints) > 0:
-            constraint_value = set(json.loads(constraint.constraint_value))
-            constraint_value.update(diversity_constraints)
-            constraint.constraint_value = json.dumps(sorted(list(constraint_value)), sort_keys=True)
-            break
-    else:
-        # not found, and there are diversity constraints, add them
-        if len(diversity_constraints) > 0:
-            constraint = target.service_constraints.add()                   # pylint: disable=no-member
-            constraint.constraint_type = 'diversity'
-            constraint.constraint_value = json.dumps(sorted(list(diversity_constraints)), sort_keys=True)
+    field_updates = {
+        'router_id'          : (router_id,           True),
+        'route_distinguisher': (route_distinguisher, True),
+        'sub_interface_index': (sub_if_index,        True),
+        'vlan_id'            : (cvlan_id,            True),
+    }
+    if address_ip      is not None: field_updates['address_ip'     ] = (address_ip,      True)
+    if address_prefix  is not None: field_updates['address_prefix' ] = (address_prefix,  True)
+    update_config_rule_custom(config_rules, endpoint_settings_key, field_updates)
+
+    field_updates = {}
+    if len(diversity_constraints) > 0:
+        field_updates.update(diversity_constraints)
+    update_constraint_custom(constraints, 'diversity', field_updates)
+
+    update_constraint_endpoint_location(constraints, endpoint_id, region=site_id)
+    if access_priority is not None: update_constraint_endpoint_priority(constraints, endpoint_id, access_priority)
+    if single_active or all_active:
+        # assume 1 disjoint path per endpoint/location included in service/slice
+        location_endpoints = {}
+        for constraint in constraints:
+            if constraint.WhichOneof('constraint') != 'endpoint_location': continue
+            str_endpoint_id = grpc_message_to_json_string(constraint.endpoint_location.endpoint_id)
+            str_location_id = grpc_message_to_json_string(constraint.endpoint_location.location)
+            location_endpoints.setdefault(str_location_id, set()).add(str_endpoint_id)
+        num_endpoints_per_location = {len(endpoints) for endpoints in location_endpoints.values()}
+        num_disjoint_paths = min(num_endpoints_per_location)
+        update_constraint_sla_availability(constraints, num_disjoint_paths, all_active)
 
     return target
 
 def process_list_site_network_access(
-        context_client : ContextClient, service_client : ServiceClient, slice_client : SliceClient,
+        context_client : ContextClient, service_client : ServiceClient, slice_client : SliceClient, site_id : str,
         request_data : Dict
     ) -> Response:
 
@@ -216,7 +135,7 @@ def process_list_site_network_access(
 
     errors = []
     for site_network_access in request_data['ietf-l2vpn-svc:site-network-access']:
-        sna_request = process_site_network_access(context_client, site_network_access)
+        sna_request = process_site_network_access(context_client, site_id, site_network_access)
         LOGGER.debug('sna_request = {:s}'.format(grpc_message_to_json_string(sna_request)))
         try:
             if isinstance(sna_request, Service):
@@ -230,7 +149,7 @@ def process_list_site_network_access(
             else:
                 raise NotImplementedError('Support for Class({:s}) not implemented'.format(str(type(sna_request))))
         except Exception as e: # pylint: disable=broad-except
-            msg = 'Something went wrong Updating Service {:s}'
+            msg = 'Something went wrong Updating VPN {:s}'
             LOGGER.exception(msg.format(grpc_message_to_json_string(sna_request)))
             errors.append({'error': str(e)})
         time.sleep(random.random() / 10.0)
@@ -247,7 +166,7 @@ class L2VPN_SiteNetworkAccesses(Resource):
         context_client = ContextClient()
         service_client = ServiceClient()
         slice_client = SliceClient()
-        return process_list_site_network_access(context_client, service_client, slice_client, request.json)
+        return process_list_site_network_access(context_client, service_client, slice_client, site_id, request.json)
 
     @HTTP_AUTH.login_required
     def put(self, site_id : str):
@@ -256,4 +175,4 @@ class L2VPN_SiteNetworkAccesses(Resource):
         context_client = ContextClient()
         service_client = ServiceClient()
         slice_client = SliceClient()
-        return process_list_site_network_access(context_client, service_client, slice_client, request.json)
+        return process_list_site_network_access(context_client, service_client, slice_client, site_id, request.json)