diff --git a/src/device/service/drivers/oc_driver/OCDriver.py b/src/device/service/drivers/oc_driver/OCDriver.py
index 8d437ccc8dd3b92d246db20127bc916c3b8ec5b4..c5a2439589fb5bab4874929a6850e19b22306f80 100644
--- a/src/device/service/drivers/oc_driver/OCDriver.py
+++ b/src/device/service/drivers/oc_driver/OCDriver.py
@@ -12,9 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import time
 import json
-import logging, pytz, queue, re, threading
-#import lxml.etree as ET
+import logging, pytz, re, threading
 from typing import Any, List, Tuple, Union
 from apscheduler.executors.pool import ThreadPoolExecutor
 from apscheduler.jobstores.memory import MemoryJobStore
@@ -22,12 +22,11 @@ from apscheduler.schedulers.background import BackgroundScheduler
 from ncclient.manager import Manager, connect_ssh
 from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
 from common.tools.client.RetryDecorator import delay_exponential
-from common.type_checkers.Checkers import  chk_type
+from common.type_checkers.Checkers import chk_length, chk_string, chk_type
 from device.service.driver_api.Exceptions import UnsupportedResourceKeyException
 from device.service.driver_api._Driver import _Driver
-from device.service.driver_api.AnyTreeTools import TreeNode
+from .templates import compose_config, cli_compose_config, ufi_interface, cisco_interface
 from .templates.VPN.common import seperate_port_config
-#from .Tools import xml_pretty_print, xml_to_dict, xml_to_file
 from .templates.VPN.roadms import (
     create_optical_band, disable_media_channel, delete_optical_band, create_media_channel_v2
 )
@@ -36,11 +35,10 @@ from .RetryDecorator import retry
 from context.client.ContextClient import ContextClient
 from common.proto.context_pb2 import OpticalConfig
 from .templates.discovery_tool.transponders import  transponder_values_extractor
-from .templates.discovery_tool.roadms import roadm_values_extractor, extract_media_channels
+from .templates.discovery_tool.roadms import roadm_values_extractor
 from .templates.discovery_tool.open_roadm import openroadm_values_extractor
 from .templates.VPN.openroadm import network_media_channel_handler
 
-
 DEBUG_MODE = False
 logging.getLogger('ncclient.manager').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING)
 logging.getLogger('ncclient.transport.ssh').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING)
@@ -51,9 +49,6 @@ logging.getLogger('monitoring-client').setLevel(logging.INFO if DEBUG_MODE else
 RE_GET_ENDPOINT_FROM_INTERFACE_KEY = re.compile(r'.*interface\[([^\]]+)\].*')
 RE_GET_ENDPOINT_FROM_INTERFACE_XPATH = re.compile(r".*interface\[oci\:name\='([^\]]+)'\].*")
 
-# Collection of samples through NetConf is very slow and each request collects all the data.
-# Populate a cache periodically (when first interface is interrogated).
-# Evict data after some seconds, when data is considered as outdated
 
 SAMPLE_EVICTION_SECONDS = 30.0 # seconds
 SAMPLE_RESOURCE_KEY = 'interfaces/interface/state/counters'
@@ -200,6 +195,65 @@ def edit_config(
 
         #results[i] = True
             results.append(result)
+    
+    if netconf_handler.vendor == "CISCO":
+        if "L2VSI" in resources[0][1]:
+            #Configure by CLI
+            logger.warning("CLI Configuration")
+            cli_compose_config(resources, delete=delete, host= netconf_handler._NetconfSessionHandler__address, user=netconf_handler._NetconfSessionHandler__username, passw=netconf_handler._NetconfSessionHandler__password)        
+            for i,resource in enumerate(resources):
+                results.append(True)
+        else: 
+            logger.warning("CLI Configuration CISCO INTERFACE")
+            cisco_interface(resources, delete=delete, host= netconf_handler._NetconfSessionHandler__address, user=netconf_handler._NetconfSessionHandler__username, passw=netconf_handler._NetconfSessionHandler__password)        
+            for i,resource in enumerate(resources):
+                results.append(True)
+    elif netconf_handler.vendor == "UFISPACE": 
+        #Configure by CLI
+        logger.warning("CLI Configuration: {:s}".format(resources))
+        ufi_interface(resources, delete=delete, host= netconf_handler._NetconfSessionHandler__address, user=netconf_handler._NetconfSessionHandler__username, passw=netconf_handler._NetconfSessionHandler__password)        
+        for i,resource in enumerate(resources):
+            results.append(True)
+    else:
+        for i,resource in enumerate(resources):
+            str_resource_name = 'resources[#{:d}]'.format(i)
+            try:
+                logger.debug('[{:s}] resource = {:s}'.format(str_method, str(resource)))
+                chk_type(str_resource_name, resource, (list, tuple))
+                chk_length(str_resource_name, resource, min_length=2, max_length=2)
+                resource_key,resource_value = resource
+                chk_string(str_resource_name + '.key', resource_key, allow_empty=False)
+                str_config_messages = compose_config(                                                                          # get template for configuration
+                    resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer=netconf_handler.message_renderer)
+                for str_config_message in str_config_messages:                                                                 # configuration of the received templates 
+                    if str_config_message is None: raise UnsupportedResourceKeyException(resource_key)
+                    logger.debug('[{:s}] str_config_message[{:d}] = {:s}'.format(
+                    str_method, len(str_config_message), str(str_config_message)))
+                    netconf_handler.edit_config(                                                                               # configure the device
+                        config=str_config_message, target=target, default_operation=default_operation,
+                        test_option=test_option, error_option=error_option, format=format)
+                    if commit_per_rule:
+                        netconf_handler.commit()                                                                               # configuration commit
+                    if 'table_connections' in resource_key:
+                        time.sleep(5) # CPU usage might exceed critical level after route redistribution, BGP daemon needs time to reload
+                
+                #results[i] = True
+                results.append(True)
+            except Exception as e: # pylint: disable=broad-except
+                str_operation = 'preparing' if target == 'candidate' else ('deleting' if delete else 'setting')
+                msg = '[{:s}] Exception {:s} {:s}: {:s}'
+                logger.exception(msg.format(str_method, str_operation, str_resource_name, str(resource)))
+                #results[i] = e # if validation fails, store the exception
+                results.append(e)
+
+        if not commit_per_rule:
+            try:
+                netconf_handler.commit()
+            except Exception as e: # pylint: disable=broad-except
+                msg = '[{:s}] Exception committing: {:s}'
+                str_operation = 'preparing' if target == 'candidate' else ('deleting' if delete else 'setting')
+                logger.exception(msg.format(str_method, str_operation, str(resources)))
+                results = [e for _ in resources] # if commit fails, set exception in each resource
 
     return results         
 
diff --git a/src/device/service/drivers/oc_driver/templates/IP_LINK/IP_LINK_multivendor.py b/src/device/service/drivers/oc_driver/templates/IP_LINK/IP_LINK_multivendor.py
new file mode 100755
index 0000000000000000000000000000000000000000..f4f6ad4dd0000e6b78352a129c87dc0c56aa7d53
--- /dev/null
+++ b/src/device/service/drivers/oc_driver/templates/IP_LINK/IP_LINK_multivendor.py
@@ -0,0 +1,59 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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.
+
+from yattag import Doc, indent
+
+def ip_link_mgmt(data,vendor, delete):
+    doc, tag, text = Doc().tagtext()
+
+    ID    = data['endpoint_id']['endpoint_uuid']['uuid']
+    DATA  = data["rule_set"]
+    
+    with tag('interfaces', xmlns="http://openconfig.net/yang/interfaces"):
+        if delete == True: 
+            with tag('interface' ,'xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'):
+                with tag('name'):text(ID)
+        else:
+            with tag('interface'):
+                with tag('name'):text(ID)
+                with tag('config'):
+                    with tag('name'):text(ID)
+                    with tag('type', 'xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type"'):text('ianaift:l3ipvlan')
+                    with tag('enabled'):text('true')    
+                with tag('subinterfaces'):
+                    with tag('subinterface'):
+                        if vendor is None or vendor == 'ADVA':
+                            with tag('index'): text('0')
+                        with tag('config'):
+                            with tag('index'): text('0')
+                            if vendor == 'ADVA' and not 'vlan'in data: 
+                                with tag('untagged-allowed', 'xmlns="http://www.advaoptical.com/cim/adva-dnos-oc-interfaces"'):text('true')
+                        with tag('vlan',  xmlns="http://openconfig.net/yang/vlan"):
+                            with tag('match'):
+                                with tag('single-tagged'):
+                                    with tag('config'):
+                                        with tag('vlan-id'):text(DATA['vlan'])
+                        with tag('ipv4',  xmlns="http://openconfig.net/yang/interfaces/ip"):
+                            with tag('addresses'):
+                                with tag('address'):
+                                    with tag('ip'):text(DATA['ip'])
+                                    with tag('config'):
+                                        with tag('ip'):text(DATA['ip'])
+                                        with tag('prefix-length'):text(DATA['mask'])
+    result = indent(
+        doc.getvalue(),
+        indentation = ' '*2,
+        newline = '\r\n'
+    )
+    return result
\ No newline at end of file
diff --git a/src/device/service/drivers/oc_driver/templates/Tools.py b/src/device/service/drivers/oc_driver/templates/Tools.py
index 71f827dfe80a5064723e1287ae4419f1d38bde5e..eeb3b253c6704f861d0d9d94d8e35331a27a245b 100644
--- a/src/device/service/drivers/oc_driver/templates/Tools.py
+++ b/src/device/service/drivers/oc_driver/templates/Tools.py
@@ -13,12 +13,10 @@
 # limitations under the License.
 
 import re,logging
-import json
 import lxml.etree as ET
-from typing import Collection, Dict, Any
+from typing import Collection, Dict
+from .IP_LINK.IP_LINK_multivendor import ip_link_mgmt
 
-from yattag import Doc, indent
-from .VPN.physical import create_optical_channel
 
 def add_value_from_tag(target : Dict, field_name: str, field_value : ET.Element, cast=None) -> None:
     if isinstance(field_value,str) or field_value is None or field_value.text is None: return
@@ -49,14 +47,12 @@ def add_value_from_collection(target : Dict, field_name: str, field_value : Coll
 # Return:
   [dict] Set of templates generated according to the configuration rule
 """
-def generate_templates(resource_key: str, resource_value: str, channel:str) -> str:    # template management to be configured
+def generate_templates(resource_key: str, resource_value: str, delete: bool,vendor:str) -> str:    # template management to be configured
 
     result_templates = []
-    data={}
-    data['name']=channel
-    data['resource_key']=resource_key
-    data['value']=resource_value
-    #result_templates.append(create_physical_config(data))
+    list_resource_key = resource_key.split("/")                                         # the rule resource key management
+    if "ip_link" in list_resource_key[1]:                                      # network instance rules management
+        result_templates.append(ip_link_mgmt(resource_value,vendor,delete))
 
     return result_templates
 
diff --git a/src/device/service/drivers/oc_driver/templates/__init__.py b/src/device/service/drivers/oc_driver/templates/__init__.py
index 53d5157f750bfb085125cbd33faff1cec5924e14..2c83aee416b5f44ba03d804a1a6c0fb5bc127f50 100644
--- a/src/device/service/drivers/oc_driver/templates/__init__.py
+++ b/src/device/service/drivers/oc_driver/templates/__init__.py
@@ -12,3 +12,288 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import json, logging, lxml.etree as ET, re
+import time
+from typing import Any, Dict, Optional
+from jinja2 import Environment, PackageLoader, select_autoescape
+import paramiko
+from .Tools import generate_templates
+
+LOGGER = logging.getLogger(__name__)
+
+
+
+LOGGER = logging.getLogger(__name__)
+RE_REMOVE_FILTERS = re.compile(r'\[[^\]]+\]')
+RE_REMOVE_FILTERS_2 = re.compile(r'\/[a-z]+:')
+EMPTY_CONFIG = '<config></config>'
+EMPTY_FILTER = '<filter></filter>'
+JINJA_ENV = Environment(loader=PackageLoader('device.service.drivers.openconfig'), autoescape=select_autoescape())
+
+"""
+# Method Name: compose_config
+  
+# Parameters:
+  - resource_key:    [str]  Variable to identify the rule to be executed.
+  - resource_value:  [str]  Variable with the configuration parameters of the rule to be executed.
+  - delete:          [bool] Variable to identify whether to create or delete the rule.
+  - vendor:          [str]  Variable to identify the vendor of the equipment to be configured.
+  - message_renderer [str]  Variable to dientify template generation method. Can be "jinja" or "pyangbind".
+  
+# Functionality:
+  This method calls the function obtains the equipment configuration template according to the value of the variable "message_renderer".
+  Depending on the value of this variable, it gets the template with "jinja" or "pyangbind". 
+  
+# Return:
+  [dict] Set of templates obtained according to the configuration method
+"""
+
+def compose_config( # template generation
+    resource_key : str, resource_value : str, delete : bool = False, vendor : Optional[str] = None, message_renderer = str
+) -> str:
+
+    if (message_renderer == "pyangbind"):
+        templates = (generate_templates(resource_key, resource_value, delete, vendor))
+        return [
+            '<config>{:s}</config>'.format(template) # format correction
+            for template in templates
+            ]
+
+    elif (message_renderer == "jinja"):
+        templates = []
+        template_name = '{:s}/edit_config.xml'.format(RE_REMOVE_FILTERS.sub('', resource_key))
+        templates.append(JINJA_ENV.get_template(template_name))
+        data : Dict[str, Any] = json.loads(resource_value)
+
+        operation = 'delete' if delete else 'merge' # others
+        #operation = 'delete' if delete else '' # ipinfusion?
+
+        return [
+            '<config>{:s}</config>'.format(
+            template.render(**data, operation=operation, vendor=vendor).strip())
+            for template in templates
+            ]
+        
+    else:
+        raise ValueError('Invalid message_renderer value: {}'.format(message_renderer)) 
+
+"""
+# Method Name: cli_compose_config
+  
+# Parameters:
+  - resource_key:    [str]  Variable to identify the rule to be executed.
+  - resource_value:  [str]  Variable with the configuration parameters of the rule to be executed.
+  - delete:          [bool] Variable to identify whether to create or delete the rule.
+  - vendor:          [str]  Variable to identify the vendor of the equipment to be configured.
+  - message_renderer [str]  Variable to dientify template generation method. Can be "jinja" or "pyangbind".
+  
+# Functionality:
+  This method calls the function obtains the equipment configuration template according to the value of the variable "message_renderer".
+  Depending on the value of this variable, it gets the template with "jinja" or "pyangbind". 
+  
+# Return:
+  [dict] Set of templates obtained according to the configuration method
+"""
+
+def cli_compose_config(resources, delete: bool, host: str, user: str, passw: str):     #Method used for configuring via CLI directly L2VPN in CISCO devices
+      
+    key_value_data = {}
+
+    for path, json_str in resources:
+        key_value_data[path] = json_str
+
+    # Iterate through the resources and extract parameter values dynamically
+    for path, json_str in resources:
+        data = json.loads(json_str)
+        if 'VC_ID' in data:            vc_id = data['VC_ID']
+        if 'connection_point' in data: connection_point = data['connection_point']
+        if 'remote_system' in data:    remote_system = data['remote_system']
+        if 'interface' in data:
+            interface = data['interface']
+            interface = interface.split("-")                       #New Line To Avoid Bad Endpoint Name In CISCO
+            interface = interface[1]
+        if 'vlan_id' in data:          vlan_id = data['vlan_id']
+        if 'name' in data:             ni_name = data['name']
+        if 'type' in data:             ni_type = data['type']
+        if 'index' in data:            subif_index = data['index']
+        if 'description' in data:      description = data['description']
+        else:                          description = " "
+      
+    # initialize the SSH client
+    ssh_client = paramiko.SSHClient()
+    ssh_client.load_system_host_keys()
+    # add to known hosts
+    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+        
+    try:
+        ssh_client.connect(hostname=host, username=user, password=passw, look_for_keys=False)
+        #print("Connection successful")
+        LOGGER.warning("Connection successful")
+    except:
+        #print("[!] Cannot connect to the SSH Server")
+        LOGGER.warning("[!] Cannot connect to the SSH Server")
+        exit()
+        
+    try:
+        # Open an SSH shell
+        channel = ssh_client.invoke_shell()
+        channel.send('enable\n')
+        time.sleep(1)
+        channel.send('conf term\n')
+        time.sleep(0.1)
+        channel.send(f"interface {interface} l2transport\n")
+        time.sleep(0.1)
+        channel.send('description l2vpn_vpws_example\n')
+        time.sleep(0.1)
+        channel.send(f"encapsulation dot1q {vlan_id}\n")
+        time.sleep(0.1)
+        channel.send('mtu 9088\n')
+        time.sleep(0.1)
+        channel.send('commit\n')
+        time.sleep(0.1)
+        
+        channel.send('l2vpn\n')
+        time.sleep(0.1)
+        channel.send('load-balancing flow src-dst-ip\n')
+        time.sleep(0.1)
+        channel.send('pw-class l2vpn_vpws_profile_example\n')
+        time.sleep(0.1)
+        channel.send('encapsulation mpls\n')
+        time.sleep(0.1)
+        channel.send('transport-mode vlan passthrough\n')
+        time.sleep(0.1)
+        channel.send('control-word\n')
+        time.sleep(0.1)
+        channel.send('exit\n')
+        time.sleep(0.1)
+        channel.send('l2vpn\n')
+        time.sleep(0.1)
+        channel.send('xconnect group l2vpn_vpws_group_example\n')
+        time.sleep(0.1)
+        channel.send(f"p2p {ni_name}\n")
+        time.sleep(0.1)
+        channel.send(f"interface {interface}\n")                                #Ignore the VlanID because the interface already includes the vlanid tag
+        time.sleep(0.1)
+        channel.send(f"neighbor ipv4 {remote_system} pw-id {vc_id}\n")
+        time.sleep(0.1)
+        channel.send('pw-class l2vpn_vpws_profile_example\n')
+        time.sleep(0.1)
+        channel.send('exit\n')
+        time.sleep(0.1)
+        channel.send(f"description {description}\n")
+        time.sleep(0.1)
+        channel.send('commit\n')
+        time.sleep(0.1) 
+        # Capturar la salida del comando
+        output = channel.recv(65535).decode('utf-8')
+        #print(output)
+        LOGGER.warning(output)
+        # Close the SSH shell
+        channel.close()
+
+    except Exception as e:
+        LOGGER.exception(f"Error with the CLI configuration: {e}")
+
+    # Close the SSH client
+    ssh_client.close()
+    
+def ufi_interface(resources, delete: bool, host: str, user: str, passw: str):     #Method used for configuring via CLI directly L2VPN in CISCO devices
+
+    key_value_data = {}
+
+    for path, json_str in resources:
+        key_value_data[path] = json_str
+
+    # initialize the SSH client
+    ssh_client = paramiko.SSHClient()
+    ssh_client.load_system_host_keys()
+    # add to known hosts
+    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+    try:
+        ssh_client.connect(hostname=host, username=user, password=passw, look_for_keys=False)
+        LOGGER.warning("Connection successful")
+    except:
+        LOGGER.warning("[!] Cannot connect to the SSH Server")
+        exit()
+    interface = 'ge100-0/0/3/1'  
+    ip = '1.1.1.1'
+    mask = '24'
+    vlan = '1212'
+    try:
+        # Open an SSH shell
+        channel = ssh_client.invoke_shell()
+        time.sleep(5)
+        channel.send('config\n')
+        time.sleep(1)
+        channel.send(f'interfaces {interface} \n')
+        time.sleep(1)
+        channel.send('admin-state enabled \n')
+        time.sleep(1)
+        channel.send(f'ipv4-address {ip}/{mask} \n')
+        time.sleep(1)
+        channel.send(f'vlan-id {vlan} \n')
+        time.sleep(1)
+        channel.send('commit\n')
+        time.sleep(1)
+
+        output = channel.recv(65535).decode('utf-8')
+        LOGGER.warning(output)
+        # Close the SSH shell
+        channel.close()
+
+    except Exception as e:
+        LOGGER.exception(f"Error with the CLI configuration: {e}")
+
+    # Close the SSH client
+    ssh_client.close()
+
+def cisco_interface(resources, delete: bool, host: str, user: str, passw: str):     #Method used for configuring via CLI directly L2VPN in CISCO devices
+
+    key_value_data = {}
+    for path, json_str in resources:
+        key_value_data[path] = json_str
+
+    # initialize the SSH client
+    ssh_client = paramiko.SSHClient()
+    ssh_client.load_system_host_keys()
+    # add to known hosts
+    ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+    try:
+        ssh_client.connect(hostname=host, username=user, password=passw, look_for_keys=False)
+        LOGGER.warning("Connection successful")
+    except:
+        LOGGER.warning("[!] Cannot connect to the SSH Server")
+        exit()
+    interface = 'FourHundredGigE0/0/0/10.1212'  
+    ip = '1.1.1.1'
+    mask = '24'
+    vlan = '1212'
+    try:
+        # Open an SSH shell
+        channel = ssh_client.invoke_shell()
+        time.sleep(1)
+        channel.send('config\n')
+        time.sleep(0.1)
+        channel.send(f'interface {interface} \n')
+        time.sleep(0.1)
+        channel.send('no shutdown\n')
+        time.sleep(0.1)
+        channel.send(f'ipv4 address {ip}/{mask} \n')
+        time.sleep(0.1)
+        channel.send(f'encapsulation dot1q {vlan} \n')
+        time.sleep(0.1)
+        channel.send('commit\n')
+        time.sleep(0.1)
+
+        output = channel.recv(65535).decode('utf-8')
+        LOGGER.warning(output)
+        # Close the SSH shell
+        channel.close()
+
+    except Exception as e:
+        LOGGER.exception(f"Error with the CLI configuration: {e}")
+
+    # Close the SSH client
+    ssh_client.close()  
diff --git a/src/service/service/service_handlers/__init__.py b/src/service/service/service_handlers/__init__.py
index c2961192931670a87691a077e127d74a445a923a..dac6656107055656595a14e8b8dabfe8555daad2 100644
--- a/src/service/service/service_handlers/__init__.py
+++ b/src/service/service/service_handlers/__init__.py
@@ -115,6 +115,12 @@ SERVICE_HANDLERS = [
             FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_OPENCONFIG,
         }
     ]),
+    (IP_LinkServiceHandler, [
+        {
+            FilterFieldEnum.SERVICE_TYPE  : ServiceTypeEnum.SERVICETYPE_IPLINK,
+            FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_OC,
+        }
+    ]),
     (QKDServiceHandler, [
         {
             FilterFieldEnum.SERVICE_TYPE  : ServiceTypeEnum.SERVICETYPE_QKD,
diff --git a/src/service/service/service_handlers/ip_link/IP_LinkServiceHandler.py b/src/service/service/service_handlers/ip_link/IP_LinkServiceHandler.py
index cbb42a5c89c8db32c327e13122b219c1c1ec3c55..d02f71bc73821da9e2690bd888e49244bd3c002f 100644
--- a/src/service/service/service_handlers/ip_link/IP_LinkServiceHandler.py
+++ b/src/service/service/service_handlers/ip_link/IP_LinkServiceHandler.py
@@ -43,9 +43,6 @@ class IP_LinkServiceHandler(_ServiceHandler):
         chk_type('endpoints', endpoints, list)
         if len(endpoints) == 0: return []
 
-        service_uuid = self.__service.service_id.service_uuid.uuid
-        settings = self.__settings_handler.get('/settings')
-
         results = []
         for endpoint in endpoints:
             try:
diff --git a/src/service/service/service_handlers/oc/ConfigRules.py b/src/service/service/service_handlers/oc/ConfigRules.py
new file mode 100644
index 0000000000000000000000000000000000000000..e2de985b15494f55923749a4d09f3febfe66c917
--- /dev/null
+++ b/src/service/service/service_handlers/oc/ConfigRules.py
@@ -0,0 +1,57 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (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 logging
+from typing import Any, Dict, List, Optional, Tuple
+from service.service.service_handler_api.AnyTreeTools import TreeNode
+LOGGER = logging.getLogger(__name__)
+
+def get_value(field_name : str, *containers, default=None) -> Optional[Any]:
+    if len(containers) == 0: raise Exception('No containers specified')
+    for container in containers:
+        if field_name not in container: continue
+        return container[field_name]
+    return default
+
+def setup_config_rules(
+    endpoint_name : str,  endpoint_ip_link : List [Tuple]
+) -> List[Dict]:
+
+    json_config_rules = [
+    ]
+    
+    for res_key, res_value in endpoint_ip_link:
+        json_config_rules.append(
+               {'action': 1, 'ip_link': res_value}
+            )
+
+    return json_config_rules
+
+def teardown_config_rules(
+    service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str,
+    service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode
+) -> List[Dict]:
+
+    if service_settings  is None: return []
+    if device_settings   is None: return []
+    if endpoint_settings is None: return []
+
+    json_settings          : Dict = service_settings.value
+    json_device_settings   : Dict = device_settings.value
+    json_endpoint_settings : Dict = endpoint_settings.value
+
+    settings = (json_settings, json_endpoint_settings, json_device_settings)
+
+    json_config_rules = []
+    return json_config_rules
diff --git a/src/service/service/service_handlers/oc/OCServiceHandler.py b/src/service/service/service_handlers/oc/OCServiceHandler.py
index 462685c3d1e40dd7af9a2f5dc297a2ae06d02588..49212d1aa5e82097627709dc77fe6d99914b6d98 100644
--- a/src/service/service/service_handlers/oc/OCServiceHandler.py
+++ b/src/service/service/service_handlers/oc/OCServiceHandler.py
@@ -15,16 +15,17 @@
 import json, logging
 from typing import Any, List, Optional, Tuple, Union
 from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
-from common.proto.context_pb2 import DeviceId, Service
+from common.proto.context_pb2 import ConfigRule, DeviceId, Service
 from common.tools.object_factory.Device import json_device_id
 from common.type_checkers.Checkers import chk_type
 from common.DeviceTypes import DeviceTypeEnum
-from service.service.service_handler_api.Tools import get_endpoint_matching
+from service.service.service_handler_api.Tools import get_device_endpoint_uuids, get_endpoint_matching
 from service.service.service_handler_api._ServiceHandler import _ServiceHandler
 from service.service.service_handler_api.SettingsHandler import SettingsHandler
 from service.service.task_scheduler.TaskExecutor import TaskExecutor
+from .ConfigRules import setup_config_rules, teardown_config_rules
 from .OCTools import (
-    convert_endpoints_to_flows, endpoints_to_flows,
+    convert_endpoints_to_flows
     #handle_flows_names, check_media_channel_existance
 )
 
@@ -68,6 +69,28 @@ class OCServiceHandler(_ServiceHandler):
         #handled_flows=handle_flows_names(flows=flows,task_executor=self.__task_executor)
 
         results = []
+        for endpoint in endpoints:
+            try:
+                device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
+
+                device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
+                endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
+                endpoint_ip_link = self.__settings_handler.get_endpoint_ip_link(device_obj, endpoint_obj)
+                endpoint_name = endpoint_obj.name
+                json_config_rules = setup_config_rules(
+                    endpoint_name, endpoint_ip_link)
+
+                if len(json_config_rules) > 0:
+                    del device_obj.device_config.config_rules[:]
+                    for json_config_rule in json_config_rules:
+                        device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule))
+                    self.__task_executor.configure_device(device_obj)
+
+                results.append(True)
+            except Exception as e: # pylint: disable=broad-except
+                LOGGER.exception('Unable to SetEndpoint({:s})'.format(str(endpoint)))
+                results.append(e)
+
         LOGGER.info(f"flows {flows} ")
         LOGGER.info(f"settings {settings} ")
         
@@ -102,6 +125,32 @@ class OCServiceHandler(_ServiceHandler):
             settings = self.__settings_handler.get('/settings')  
 
         results = []
+
+        for endpoint in endpoints:
+            try:
+                device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
+
+                device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
+                device_settings = self.__settings_handler.get_device_settings(device_obj)
+                endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
+                endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj)
+                endpoint_name = endpoint_obj.name
+
+                json_config_rules = teardown_config_rules(
+                    service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name,
+                    settings, device_settings, endpoint_settings)
+
+                if len(json_config_rules) > 0:
+                    del device_obj.device_config.config_rules[:]
+                    for json_config_rule in json_config_rules:
+                        device_obj.device_config.config_rules.append(ConfigRule(**json_config_rule))
+                    self.__task_executor.configure_device(device_obj)
+
+                results.append(True)
+            except Exception as e: # pylint: disable=broad-except
+                LOGGER.exception('Unable to DeleteEndpoint({:s})'.format(str(endpoint)))
+                results.append(e)
+
         for device_uuid, dev_flows in flows.items():
             try:
                 channel_indexes= []