diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/EstructuraIntermedia.json b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/EstructuraIntermedia.json
new file mode 100644
index 0000000000000000000000000000000000000000..e57011be614cc6af8bc011b4fd8581e86f0856c5
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/EstructuraIntermedia.json
@@ -0,0 +1,231 @@
+{
+   "l3vpn-svc": {
+      "vpn-services": {
+         "vpn-service": [
+            {
+               "vpn-id": "vpn2"
+            }
+         ]
+      },
+      "sites": {
+         "site": [
+            {
+               "site-id": "site_OLT",
+               "locations": {
+                  "location": [
+                     {
+                        "location-id": "OLT"
+                     }
+                  ]
+               },
+               "devices": {
+                  "device": [
+                     {
+                        "device-id": "128.32.33.5",
+                        "location": "OLT"
+                     }
+                  ]
+               },
+               "management": {
+                  "type": "ietf-l3vpn-svc:provider-managed"
+               },
+               "routing-protocols": {
+                  "routing-protocol": [
+                     {
+                        "type": "ietf-l3vpn-svc:static",
+                        "static": {
+                           "cascaded-lan-prefixes": {
+                              "ipv4-lan-prefixes": [
+                                 {
+                                    "lan": "128.32.10.0/24",
+                                    "next-hop": "128.32.33.2",
+                                    "lan-tag": "vlan31"
+                                 },
+                                 {
+                                    "lan": "128.32.20.0/24",
+                                    "next-hop": "128.32.33.2",
+                                    "lan-tag": "vlan31"
+                                 }
+                              ]
+                           }
+                        }
+                     }
+                  ]
+               },
+               "site-network-accesses": {
+                  "site-network-access": [
+                     {
+                        "site-network-access-id": "500",
+                        "site-network-access-type": "ietf-l3vpn-svc:multipoint",
+                        "device-reference": "128.32.33.5",
+                        "ip-connection": {
+                           "ipv4": {
+                              "address-allocation-type": "ietf-l3vpn-svc:static-address",
+                              "addresses": {
+                                 "provider-address": "128.32.33.254",
+                                 "customer-address": "128.32.33.2",
+                                 "prefix-length": 24
+                              }
+                           }
+                        },
+                        "service": {
+                           "svc-input-bandwidth": 1000000000,
+                           "svc-output-bandwidth": 1000000000,
+                           "svc-mtu": 1500,
+                           "qos": {
+                              "qos-profile": {
+                                 "classes": {
+                                    "class": [
+                                       {
+                                          "class-id": "qos-realtime",
+                                          "direction": "ietf-l3vpn-svc:both",
+                                          "latency": {
+                                             "latency-boundary": 10
+                                          },
+                                          "bandwidth": {
+                                             "guaranteed-bw-percent": 100.0
+                                          }
+                                       }
+                                    ]
+                                 }
+                              }
+                           }
+                        },
+                        "routing-protocols": {
+                           "routing-protocol": [
+                              {
+                                 "type": "ietf-l3vpn-svc:static",
+                                 "static": {
+                                    "cascaded-lan-prefixes": {
+                                       "ipv4-lan-prefixes": [
+                                          {
+                                             "lan": "172.1.201.0/24",
+                                             "next-hop": "128.32.33.254",
+                                             "lan-tag": "vlan31"
+                                          }
+                                       ]
+                                    }
+                                 }
+                              }
+                           ]
+                        },
+                        "vpn-attachment": {
+                           "vpn-id": "vpn2",
+                           "site-role": "ietf-l3vpn-svc:spoke-role"
+                        }
+                     }
+                  ]
+               }
+            },
+            {
+               "site-id": "site_POP",
+               "locations": {
+                  "location": [
+                     {
+                        "location-id": "POP"
+                     }
+                  ]
+               },
+               "devices": {
+                  "device": [
+                     {
+                        "device-id": "172.10.33.5",
+                        "location": "POP"
+                     }
+                  ]
+               },
+               "management": {
+                  "type": "ietf-l3vpn-svc:provider-managed"
+               },
+               "routing-protocols": {
+                  "routing-protocol": [
+                     {
+                        "type": "ietf-l3vpn-svc:static",
+                        "static": {
+                           "cascaded-lan-prefixes": {
+                              "ipv4-lan-prefixes": [
+                                 {
+                                    "lan": "172.1.201.0/24",
+                                    "next-hop": "172.10.33.2",
+                                    "lan-tag": "vlan201"
+                                 }
+                              ]
+                           }
+                        }
+                     }
+                  ]
+               },
+               "site-network-accesses": {
+                  "site-network-access": [
+                     {
+                        "site-network-access-id": "500",
+                        "site-network-access-type": "ietf-l3vpn-svc:multipoint",
+                        "device-reference": "172.10.33.5",
+                        "ip-connection": {
+                           "ipv4": {
+                              "address-allocation-type": "ietf-l3vpn-svc:static-address",
+                              "addresses": {
+                                 "provider-address": "172.10.33.254",
+                                 "customer-address": "172.10.33.2",
+                                 "prefix-length": 24
+                              }
+                           }
+                        },
+                        "service": {
+                           "svc-input-bandwidth": 1000000000,
+                           "svc-output-bandwidth": 1000000000,
+                           "svc-mtu": 1500,
+                           "qos": {
+                              "qos-profile": {
+                                 "classes": {
+                                    "class": [
+                                       {
+                                          "class-id": "qos-realtime",
+                                          "direction": "ietf-l3vpn-svc:both",
+                                          "latency": {
+                                             "latency-boundary": 10
+                                          },
+                                          "bandwidth": {
+                                             "guaranteed-bw-percent": 100.0
+                                          }
+                                       }
+                                    ]
+                                 }
+                              }
+                           }
+                        },
+                        "routing-protocols": {
+                           "routing-protocol": [
+                              {
+                                 "type": "ietf-l3vpn-svc:static",
+                                 "static": {
+                                    "cascaded-lan-prefixes": {
+                                       "ipv4-lan-prefixes": [
+                                          {
+                                             "lan": "128.32.10.0/24",
+                                             "next-hop": "172.10.33.254",
+                                             "lan-tag": "vlan201"
+                                          },
+                                          {
+                                             "lan": "128.32.20.0/24",
+                                             "next-hop": "172.10.33.254",
+                                             "lan-tag": "vlan201"
+                                          }
+                                       ]
+                                    }
+                                 }
+                              }
+                           ]
+                        },
+                        "vpn-attachment": {
+                           "vpn-id": "vpn2",
+                           "site-role": "ietf-l3vpn-svc:hub-role"
+                        }
+                     }
+                  ]
+               }
+            }
+         ]
+      }
+   }
+}
\ No newline at end of file
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py
index 80c7b32ddf6cabf8a6c124ec20ddae2f5cd181ad..72e042760b4a3d1b3437d495d89392fc77564ea5 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/Handlers.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging, netaddr
+import logging, netaddr, json
 from typing import Dict, List, Optional, Tuple
 from common.Constants import DEFAULT_CONTEXT_NAME
 from common.proto.context_pb2 import Service, ServiceStatusEnum, ServiceTypeEnum
@@ -26,6 +26,9 @@ from common.tools.grpc.EndPointIds import update_endpoint_ids
 from context.client.ContextClient import ContextClient
 from service.client.ServiceClient import ServiceClient
 
+from .ReadServiceFunctionDefinition import ReadServiceFunctionDefinition
+from .WriteNetworkFunctionDefinition import WriteNetworkFunctionDefinition
+
 LOGGER = logging.getLogger(__name__)
 
 def create_service(
@@ -209,3 +212,55 @@ def process_site(site : Dict, errors : List[Dict]) -> None:
     network_accesses : List[Dict] = site['site-network-accesses']['site-network-access']
     for network_access in network_accesses:
         process_site_network_access(site_id, network_access, site_static_routing, errors)
+        
+        
+def convert_l3sm_to_l3nm():
+    jsonRequest = open("/home/ubuntu/tfs-ctrl/src/nbi/tests/ietf_l3vpn_req_svc1.json", "r") #devuelve un file-object. "r" es por reading
+    output_file_path = "/home/ubuntu/tfs-ctrl/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/EstructuraIntermedia.json"
+    jsonRequestData : str = jsonRequest.read() #jsonRequestData es de tipo str. Para leer el contenido, usamos read()
+
+    jParse : Dict = json.loads(jsonRequestData) #jParse es de tipo Dict. esto va a parsear jsonRequetData.
+                        #cuando obtengamos el valor de una clave, y ese valor sea un array [], el tipo será 'list'
+                        #in order to convert a jsonObject to an string, you can use .dumps
+
+    ietf_l3vpn : Dict  = jParse['ietf-l3vpn-svc:l3vpn-svc']
+
+    vpn_services : Dict = ietf_l3vpn['vpn-services']
+    #print(vpn_services)
+    # vpn_service = vpn_services['vpn-service'] #ahora, al ser vpn-service un array, creo que la variable vpn_service es de tipo 'list'
+
+    # print(type(vpn_service)) #list
+    # print("VPN_SERVICE: " + str(vpn_service))
+    # print(vpn_service[0])
+    # print(vpn_service[0]['vpn-id'])
+
+    bd : Dict[any, any] = {} #Base datos de variables del JSON
+
+    #vpn_id = MiClase.readVpnServices(vpn_services) #vpn_id es variable de tipo List[str] con todas las vpn posibles
+
+    #try:
+    bd = ReadServiceFunctionDefinition.writeVpnServices( ReadServiceFunctionDefinition.readVpnServices(vpn_services) , bd)
+    #print(json.dumps(bd, indent=2))
+
+    sites : List = ietf_l3vpn['sites']['site'] #En sites se almacena el valor de la clave 'sites'.
+    #print(json.dumps(sites, indent=2))
+
+    #### PEQUEÑA CHAPUZA PARA CUANDO SOLO HAY UNA VPN ####
+    lista_VPNs : list = bd["VPN_IDs"]
+    bd["VPNs_Dict"][lista_VPNs[0]].update(ReadServiceFunctionDefinition.readSiteArray(sites, bd)) #vpn1.update Updatea el valor de vpn1
+    ####  #  ####
+
+
+    # except Exception as e: #En principio llegaran valueError o NoJSONFieldException
+    #     print(e)
+
+    #print(json.dumps(bd, indent=2))
+
+    #YANG SUITE ENTRADA, SERVICE ->creo que IETF-NBI-TEF-DECEMBER-23; ietf-l3vpn-svc; edit-config; none selected
+    #YANG SUITE SALIDA, RED (RFC9182) -> IETF-NBI-TEF-DECEMBER-23; ietf-l3vpn-ntw; edit-config; none selected
+    #Codigo para crear archivo .json de salida
+    with open(output_file_path, 'w') as json_file:
+        json.dump(bd, json_file, indent=3)
+        
+    jsonL3VPN_net : Dict = WriteNetworkFunctionDefinition.write()
+    # print(json.dumps(jsonL3VPN_net, indent = 3))
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
index 22f01031c3d994d859314f83fae56379c2a4cba3..6bd57c8238c1af63ed3f504593f3c70cf8a68cc6 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
@@ -11,9 +11,8 @@
 # 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, logging
 
+import logging
 from typing import Dict, List
 from flask import request
 from flask.json import jsonify
@@ -24,11 +23,6 @@ from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
 from .Handlers import process_site, process_vpn_service
 from .YangValidator import YangValidator
 
-# from FunctionDefinition import FunctionDefinition
-# from FunctionDefinitionNetwork import FunctionDefinitionNetwork
-# import FunctionDefinition
-# import FunctionDefinitionNetwork
-
 LOGGER = logging.getLogger(__name__)
 
 class L3VPN_Services(Resource):
@@ -38,16 +32,9 @@ class L3VPN_Services(Resource):
 
     @HTTP_AUTH.login_required
     def post(self):
-        
-        jsonAValidar = open("/home/ubuntu/Documents/json1.json", "r")
-        jsonAValidarData : str = jsonAValidar.read()
-        jsonAValidarDict : Dict = json.loads(jsonAValidarData) 
-        output_file_path = "/home/ubuntu/Documents/EstructuraIntermedia.json"
-        
         if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
         request_data : Dict = request.json
-        # LOGGER.debug('Request: {:s}'.format(str(request_data)))
-        LOGGER.debug('Request: {:s}'.format(str(jsonAValidarDict)))
+        LOGGER.debug('Request: {:s}'.format(str(request_data)))
 
         errors = list()
         if 'ietf-l3vpn-svc:l3vpn-services' in request_data:
@@ -79,53 +66,15 @@ class L3VPN_Services(Resource):
 
     def _process_l3vpn(self, request_data : Dict) -> List[Dict]:
         yang_validator = YangValidator('ietf-l3vpn-svc')
-        request_data = yang_validator.parse_to_dict(jsonAValidarDict)
+        request_data = yang_validator.parse_to_dict(request_data)
         yang_validator.destroy()
 
-        #se supone que a partir de aqui ya ha validado
-        
-        jParse = jsonAValidarDict
-
-        ietf_l3vpn : Dict  = jParse['ietf-l3vpn-svc:l3vpn-svc']
-
-        vpn_services : Dict = ietf_l3vpn['vpn-services']
-        
-        bd : Dict[any, any] = {} #Base datos de variables del JSON
-
-        bd = FunctionDefinition.writeVpnServices( FunctionDefinition.readVpnServices(vpn_services) , bd)
-        
-        sites : List = ietf_l3vpn['sites']['site'] #En sites se almacena el valor de la clave 'sites'.
-       
-        #### FUNCIONA SOLO CON 1 VPN ####
-        lista_VPNs = bd["VPN_IDs"]
-        bd["VPNs_Dict"][lista_VPNs[0]].update(FunctionDefinition.readSiteArray(sites, bd))
-        ####  ---------------------  ####
-
-        with open(output_file_path, 'w') as json_file:
-            json.dump(bd, json_file, indent=3)
-            
-        jsonL3VPN_net : Dict = FunctionDefinitionNetwork.write()
-        # print(json.dumps(jsonL3VPN_net, indent = 3))
-
-
-
-
-
-
-
-
-        ######
-
-        errors = []
+        errors = list()
 
-        # for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
-        #     process_vpn_service(vpn_service, errors)
+        for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
+            process_vpn_service(vpn_service, errors)
 
-        # for site in request_data['l3vpn-svc']['sites']['site']:
-        #     process_site(site, errors)
+        for site in request_data['l3vpn-svc']['sites']['site']:
+            process_site(site, errors)
 
-        # response = jsonify(errors)
-        # response.status_code = HTTP_CREATED if len(errors) == 0 else HTTP_SERVERERROR
-        # return response
-    
         return errors
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/ReadServiceFunctionDefinition.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/ReadServiceFunctionDefinition.py
new file mode 100644
index 0000000000000000000000000000000000000000..3218a18ddd2d5205c170723b2adaaadf323caddd
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/ReadServiceFunctionDefinition.py
@@ -0,0 +1,418 @@
+from typing import Dict, List
+
+class ReadServiceFunctionDefinition:
+        
+    #Metodo para leer el campo vpn-services
+    @staticmethod  
+    def readVpnServices(vpnServicesALeer: Dict) -> List:
+        # Acceder al campo 'vpn-service' que es un array de Dict con un campo vpn-id
+        vpn_service_list = vpnServicesALeer.get('vpn-service', [])#Utilizar get para manejar casos donde 'vpn-service' no está presente
+        vpn_ids = [] #Array con todos los ID de cada VPN
+        
+        # Iterar sobre los elementos de la lista
+        for vpn_serviceEnFor in vpn_service_list:
+            vpn_id : str = vpn_serviceEnFor.get('vpn-id') #obtengo vpn-id del json iterando
+            # baseDatos["vpn-id_" + str(i)] = vpn_id  # Utilizar f-strings para formatear las claves
+            vpn_ids.append(vpn_id)
+            
+        return vpn_ids
+    
+    #Metodo para escribir en la baseDatos lo leido en vpn-services
+    @staticmethod
+    def writeVpnServices(listaVPNs : List, baseDatos : Dict) -> Dict:
+        
+        baseDatos["VPN_IDs"] = listaVPNs
+        #baseDatos.update({"VPN_IDs": vpn_ids}) #ambas lineas son validas para añadir al Dict
+        baseDatos["VPNs_Dict"] = {}
+        #Obtengo cada vpn-id del array y lo meto en VPNs_Dict
+        for clave in baseDatos["VPN_IDs"]:
+            baseDatos["VPNs_Dict"][clave] = {}#ya tengo un Dict asociado a cada clave
+            
+        return baseDatos #devuelve la baseDatos pasada por argumento pero actualizada
+                    
+    #Lee el array site
+    @staticmethod
+    def readSiteArray(site: List, baseDatos: Dict) -> Dict:
+        print("Elementos en site: " + str(len(site)))
+        temp : Dict = {} #Diccionario temporal que guarda el ultimo site leido
+        temp2 : Dict = {} #Diccionario temporal que registra todos los sites leidos
+        lista_SitesID = [] #lista que almacenara los IDs de cada site del array
+        i = 1
+        for siteElement in site:
+            temp = ReadServiceFunctionDefinition.readSiteElement(lista_SitesID, siteElement) #Leo un site y me quedo con ID y Dict
+            temp2.update({lista_SitesID[-1] : temp}) # Almaceno esos datos en temp2
+            i += 1            
+        
+        res : Dict = {}
+        res["sitesIDs"] = lista_SitesID
+        res["sites_Dict"] = temp2 # A sites_Dict se le añaden todos los sites
+        return res
+            
+    #Lee un site
+    @staticmethod
+    def readSiteElement(listaID: List, siteElement: Dict) -> Dict:
+        res: Dict = {}
+        listaID.append(siteElement.get('site-id'))
+        res.update({"site-id": siteElement.get('site-id')})
+        res.update({"management": siteElement.get("management")}) #revistar si está bien
+        res.update({"locations":siteElement.get("locations")})
+        res.update({"devices": ReadServiceFunctionDefinition.readDevices(siteElement.get('devices'))})
+        res.update({"routing-protocol" : ReadServiceFunctionDefinition.readRoutingProtocols(siteElement.get('routing-protocols'))})
+        res.update({"site-network-accesses" : ReadServiceFunctionDefinition.readSiteNetworkAccesses(siteElement.get('site-network-accesses'))})
+        print("readSiteElement Finiquitaoooo")
+        return res
+    #FALTAN MUCHOS CAMPOS A LEER EN site, como site-diversity, maximum-routes, security, service, traffic-protection
+
+    #Lee array de Devices. Si hay más de un device, cambiar código
+    @staticmethod
+    def readDevices(devices: Dict) -> Dict:
+        res: Dict = {}
+        devices_list: List = devices.get('device', [])  # Cambié 'devices' por 'device' aquí
+        if len(devices_list) > 1:
+            i: int = 1
+            for eachDevice in devices_list:
+                res.update({f"device-id {i}": eachDevice.get('device-id')})
+                i += 1
+        elif len(devices_list) == 1:
+            res.update({"device-id": devices_list[0].get('device-id')})
+        return res
+
+    @staticmethod
+    def readRoutingProtocols(routingProtocols : Dict) -> Dict:
+        res : Dict = {} #todo el dict routing-protocols
+        rpArray : List = routingProtocols.get("routing-protocol") #el array routing-protocol           
+        res.update({"type":rpArray[0].get("type")})#escribo el tipo en el diccionario
+        tipoRoutingProtocol : str = rpArray[0].get("type")#obtiene string "ietf-l3vpn-svc:static"
+        tipoResumido : str = tipoRoutingProtocol.split(":")[1] #se queda con la palabra, ospf, bgp, static,... sin el ietf...
+        #print("El tipo de routingProtocol es: "+ str(tipoResumido))
+        def case1():            
+            ospfEntrada : Dict = rpArray[0].get("ospf",{}) #Funciona solo en caso de que el array tenga un elemento
+            ospfIntermedio : Dict = {}
+            ospfIntermedio.update({"address-family":ospfEntrada.get("address-family",{})})
+            ospfIntermedio.update({"area-address":ospfEntrada.get("area-address",{})})
+            ospfIntermedio.update({"metric":ospfEntrada.get("metric",{})})
+            arrayShamLinksEntrada : List = ospfEntrada.get("sham-links",[]) #el array
+            shamLinksFinal : Dict = {}
+            arrayShamLinksFinal : List = []
+            for elemento in arrayShamLinksEntrada:
+                shamLinksFinal.update({"target-site":elemento.get("target-site")})
+                shamLinksFinal.update({"metric":elemento.get("metric")})
+                arrayShamLinksFinal.append(shamLinksFinal)
+                
+            ospfIntermedio.update({"sham-links":shamLinksFinal})
+                        
+            res.update({"ospf":ospfIntermedio})
+        
+        def case2():
+            bgpEntrada : Dict = rpArray[0].get("bgp",{})
+            bgpSalida : Dict = {}
+            bgpSalida.update({"autonomous-system":bgpEntrada.get("autonomous-system")})
+            bgpSalida.update({"address-family":bgpEntrada.get("address-family")})
+            res.update({"bgp":bgpSalida})
+        
+        def case3(): #SIMPLEMENTE COPIA, NO LEE. A IMPLEMENTAR
+            cascadedDict: Dict = rpArray[0].get("static", {}).get("cascaded-lan-prefixes", {})
+            valueRoutingProtocol = cascadedDict
+            res.update({"static":valueRoutingProtocol})   
+            print("se ha copiado 'static' pero no se ha leido, falta implementar")        
+             
+        def case4():
+            ripEntrada : Dict = rpArray[0].get("rip",{})
+            ripSalida : Dict = {}
+            ripSalida.update({"address-family":ripEntrada.get("address-family")})
+            res.update({"rip":ripSalida})
+            
+        def case5():
+            vrrpEntrada : Dict = rpArray[0].get("vrrp",{})
+            vrrpSalida : Dict = {}
+            vrrpSalida.update({"address-family":vrrpEntrada.get("address-family")})
+            res.update({"vrrp":vrrpSalida})        
+        
+        def default():
+            #return ValueError(f"Tipo de protocolo no compatible: {tipoResumido}")
+            print("TIPO DE PROTOCOLO NO VALIDO")
+        
+        switch = {
+            "ospf": case1,
+            "bgp": case2,
+            "static": case3,
+            "rip":case4,
+            "vrrp": case5
+        }
+        #res.update({tipoResumido: switch.get(tipoResumido, default)()})
+        switch.get(tipoResumido)()
+        # print("_______________________d____________"+str(res))
+        print("read Routing Protocols finished")
+        return res
+    
+    
+    @staticmethod
+    def readSiteNetworkAccesses(siteNetworkAccesses : Dict) -> Dict:
+        siteNetworkAccessArray : List = siteNetworkAccesses.get("site-network-access")
+        res : Dict = {}
+        arrayDeIDs : List = []
+        for siteNetworkAccess in siteNetworkAccessArray:
+            variableIncial : str = siteNetworkAccess.get("site-network-access-id")
+            variableIncial = variableIncial.replace(" ", "-")#ESTO LO HAGO PARA QUE NO HAYA PROBLEMAS CON LOS ESPACIOS A LA HORA DE LEER EL JSON
+            arrayDeIDs.append(variableIncial)
+        res.update({"site-network-accesses-IDs":arrayDeIDs})
+        dictSiteNetworkAccesses : Dict = {}
+        
+        for site in arrayDeIDs:
+            dictDeCadaID : Dict = {}
+            
+            # try:
+            dictDeCadaID.update({"site-network-access-type":siteNetworkAccess.get("site-network-access-type")})
+            dictDeCadaID.update({"device-reference":siteNetworkAccess.get("device-reference")})
+            dictDeCadaID.update({"site-role":siteNetworkAccess.get("vpn-attachment", {}).get("site-role")}) 
+            #dictDeCadaID.update({"location-flavor" : FunctionDefinition.readLocationFlavor(siteNetworkAccess.get("location-flavor"))}) DE MOMENTO DA ERROR PORQUE ESE CAMPO NO EXISTE
+            #dictDeCadaID.update({"access-diversity" : FunctionDefinition.readAccessDiversity(siteNetworkAccess.get("access-diversity"))}) CAMPO NO EXISTE AUN
+            #dictDeCadaID.update({"bearer" : FunctionDefinition.readBearer(siteNetworkAccess.get("bearer"))}) CAMPO NO EXISTE AUN
+            dictDeCadaID.update({"ip-connection":ReadServiceFunctionDefinition.readIpConnection(siteNetworkAccess.get("ip-connection"))})
+            dictDeCadaID.update({"routing-protocols":ReadServiceFunctionDefinition.readRoutingProtocols(siteNetworkAccess.get("routing-protocols"))})
+            dictDeCadaID.update({"service":ReadServiceFunctionDefinition.readService(siteNetworkAccess.get("service"))})
+            # except NoJSONFieldException as e:
+            #     print(e)
+                
+            dictSiteNetworkAccesses.update({site:dictDeCadaID})
+        print("readSiteNetworkAccesses finiquitaoo")
+        res.update({"site-network-accesses-Dict": dictSiteNetworkAccesses})       
+        return res
+    
+    @staticmethod
+    def readLocationFlavor(locationFlavor : Dict) -> Dict:
+        res : Dict = {}
+        
+        if "location" in locationFlavor:
+            res.update({"location-reference":locationFlavor.get("location", {}).get("location-reference")})
+        elif "device" in locationFlavor:
+            res.update({"device-reference":locationFlavor.get("device", {}).get("device-reference")})
+        # else:
+            # raise NoJSONFieldException("location-flavor")
+            
+        return res
+        
+    @staticmethod
+    def readAccessDiversity(accessDiversity : Dict) -> Dict:
+        res : Dict = {}
+        arrayGroupsIni : List = accessDiversity.get("groups",{}).get("group") #obtengo el array de objetos
+        arrayGroupsIDs : List = []
+        for groupId in arrayGroupsIni:
+            arrayGroupsIDs.append(groupId.get("group-id"))             
+        res.update({"groups":arrayGroupsIDs})
+        
+        arrayConstraintsIni : List = accessDiversity.get("constraints", {}).get("constraint")
+        arrayConstraintsFin : List = []
+        for constraint in arrayConstraintsIni: #recordar que constraint es un objeto dentro del array arrayConstraintsIni
+            dictConstraint : Dict = {}
+            dictConstraint.update({"constraint-type" : constraint.get("constraint-type")})
+            dictTargetFlavor : Dict = constraint.get("target", {}).get("target-flavor")
+            
+            if "id" in dictTargetFlavor:
+                dictConstraint.update({"target-flavor": dictTargetFlavor.get("id")})
+            elif "all-accesses" in dictTargetFlavor:
+                dictConstraint.update({"target-flavor": dictTargetFlavor.get("all-accesses")})
+            elif "all-groups" in dictTargetFlavor:
+                dictConstraint.update({"target-flavor": dictTargetFlavor.get("all-groups")}) 
+            # else:
+            #     raise NoJSONFieldException("read-access-divesity>constraints>constraint>target>target-flavor")               
+            arrayConstraintsFin.append(dictConstraint)
+            
+        res.update({"constraints":arrayConstraintsFin})       
+        return res
+
+    @staticmethod
+    def readBearer(bearer : Dict) -> Dict:
+        res : Dict = {}
+        
+        res.update({"always-on":bearer.get("always-on")})
+        res.update({"bearer-reference":bearer.get("bearer-reference")})
+        res.update({"requested-type":bearer.get("requested-type",{}).get("requested-type")})
+        res.update({"strict":bearer.get("requested-type",{}).get("strict")})       
+        
+        return res
+    
+    @staticmethod
+    def readIpConnection(ipConnection : Dict) -> Dict: #IPV4 E IPV6 TIENEN LOS MISMOS CAMPOS
+        res : Dict = {}
+        if ipConnection.get("ipv4") is not None:
+            res.update({"ipv4": ReadServiceFunctionDefinition.readIpv4_Ipv6(ipConnection.get("ipv4"))})
+        elif ipConnection.get("ipv6") is not None:
+            res.update({"ipv6":ReadServiceFunctionDefinition.readIpv4_Ipv6(ipConnection.get("ipv6"))}) 
+        # else:
+        #     raise NoJSONFieldException("ip-connection>ipv4/6")
+            
+        bfd : Dict = ipConnection.get("oam",{}).get("bfd")
+        if bfd is not None:
+            oamFinal : Dict = {}
+            oamFinal.update({"enabled":bfd.get("enabled")})
+            holdtime : Dict = bfd.get("holdtime")
+            holdtimeFinal : Dict = {}
+            if "fixed" in holdtime:
+                holdtimeFinal.update({"fixed":holdtime.get("fixed")})
+            elif "profile" in holdtime:
+                holdtimeFinal.update({"profile":holdtime.get("profile")})
+            # else:
+            #     raise NoJSONFieldException("oam>bfd>holdtime")
+            
+            oamFinal.update({"holdtime":holdtimeFinal})
+            res.update({"oam":oamFinal})
+        
+        return res
+    
+    @staticmethod
+    def readIpv4_Ipv6(ipv : Dict) -> Dict :
+        res : Dict = {}
+        
+        res.update({"address-allocation-type":ipv.get("address-allocation-type")})
+        
+        providerDHCP : Dict = ipv.get("provider-dhcp") #None si no existe ese campo, puede mejorarse eficiencia
+        if providerDHCP is not None:            
+            providerDHCPFinal : Dict = {}        
+            providerDHCPFinal.update({"provider-dhcp":providerDHCP.get("provider-address")})
+            providerDHCPFinal.update({"prefix-length":providerDHCP.get("prefix-lenght")})
+            addressAsign : Dict = providerDHCP.get("address-asign")
+            addressAsignFinal : Dict = {}
+            if "number" in addressAsign:
+                addressAsignFinal.update({"number":addressAsign.get("number")})
+            elif "explicit" in addressAsign:
+                addressAsignFinal.update({"explicit":addressAsign.get("explicit")})
+            # else:
+            #     raise NoJSONFieldException("ipv4/6>address-asign")
+            
+            providerDHCPFinal.update({"address-asign":addressAsignFinal})         
+            res.update({"provider-dhcp":providerDHCPFinal})
+        
+        
+        dhcpRelay : Dict = ipv.get("dhcp-relay")
+        if dhcpRelay is not None:
+            dhcpRelayFinal : Dict = {}
+            dhcpRelayFinal.update({"provider-address":dhcpRelay.get("provider-address")})
+            dhcpRelayFinal.update({"prefix-lenght":dhcpRelay.get("prefix-lenght")})
+            dhcpRelayFinal.update({"server-ip-address":dhcpRelay.get("customer-dhcp-servers",{}).get("server-ip-address")})
+            res.update({"dhcp-relay":dhcpRelayFinal})
+        
+        addresses : Dict = ipv.get("addresses")
+        if addresses is not None:
+            addressesFinal : Dict = {}
+            addressesFinal.update({"provider-address":addresses.get("provider-address")})
+            addressesFinal.update({"customer-address":addresses.get("customer-address")})
+            addressesFinal.update({"prefixe-length":addresses.get("prefixe-length")})
+            res.update({"addresses":addressesFinal})
+        
+        return res
+    
+    # @staticmethod
+    # def readSecurity(security : Dict) -> Dict:
+    #     res : Dict = {}
+        
+    #     res.update({"authentication" : security.get("authentication")})
+    #     encryption : Dict = security.get("encryption")
+    #     encryptionFinal : Dict = {}
+        
+        
+    #     return res
+    
+    #readService todavía me da error
+    @staticmethod
+    def readService(service : Dict) -> Dict :
+        res : Dict = {}
+        #try:                
+        res.update({"svc-mtu":service.get("svc-mtu")})
+        res.update({"svc-input-bandwidth":service.get("svc-input-bandwidth")})
+        res.update({"svc-output-bandwidth":service.get("svc-output-bandwidth")})
+        qos : Dict = service.get("qos")
+        
+        class_id = qos["qos-profile"]["classes"]["class"][0]["class-id"]
+        direction = qos["qos-profile"]["classes"]["class"][0]["direction"]
+        latency_boundary = qos["qos-profile"]["classes"]["class"][0]["latency"]["latency-boundary"]
+        guaranteed_bw_percent = qos["qos-profile"]["classes"]["class"][0]["bandwidth"]["guaranteed-bw-percent"]
+
+        res.update({"class-id":class_id})
+        res.update({"direction":direction})
+        res.update({"latency-boundary":latency_boundary})
+        res.update({"guaranteed-bw-percent":guaranteed_bw_percent})
+        
+        #Clase que lee el campo custom varias lineas mas adelante
+        
+        def readCustom (custom : Dict) -> Dict: #custom es un Dict que es: {classes: [class-id: *, ..., latency: {flavor:{lowest:*///boundary:*}}],[...],[...]}
+            res : Dict = {}
+                        
+            arrayClassesEntrada : List = custom.get("class") #un array con elementos indeterminados
+            arrayClassesFinal : List = []
+            
+            for elementEntrada in arrayClassesEntrada:
+                elementFinal : Dict = {}
+                elementFinal.update({"class-id":elementEntrada.get("class-id")})
+                elementFinal.update({"direction":elementEntrada.get("direction")})
+                elementFinal.update({"rate-limit":elementEntrada.get("rate-limit")})
+                #Campo latency--->
+                    #latency: {
+                    #     flavor:{
+                    #         lowest:*
+                    #         o quizás
+                    #         boundary:*
+                    #     }
+                    # }
+                                    
+                latency : Dict = elementEntrada.get("latency")
+                jitter : Dict = elementEntrada.get("jitter")
+                if latency is not None:
+                    if "use-lowest-latency" in latency:
+                        elementFinal.update({"latency-flavor-lowest":latency.get("use-lowest-latency")})
+                    elif "latency-boundary" in latency:
+                        elementFinal.update({"latency-flavor-boundary":latency.get("latency-boundary")})
+                elif jitter is not None:
+                    if "use-lowest-jitter" in jitter:
+                        elementFinal.update({"jitter-flavor-lowest":jitter.get("use-lowest-jiter")})
+                    elif "latency-boundary" in jitter:
+                        elementFinal.update({"jitter-flavor-boundary":jitter.get("latency-boundary")})
+                    else:
+                        print("Debe haber un campo lowest o boundary dentro de jitter>flavor")
+                else:
+                    print("FALTAN CAMPOS EN CUSTOM")
+                
+                bandwidthEntrada : Dict = elementEntrada.get("bandwidth")
+                bandwidthSalida : Dict = {}
+                bandwidthSalida.update({"guaranteed-bw-percent":bandwidthEntrada.get("guaranteed-bw-percent")})
+                bandwidthSalida.update({"end-to-end":bandwidthEntrada.get("end-to-end")})
+                elementFinal.update({"bandwidth":bandwidthSalida})
+                
+                arrayClassesFinal.append(elementFinal)
+                
+        #     res.update({"latency-flavor":arrayClassesFinal})
+        #     return res
+        #     #END READCUSTOM
+        
+        # qosProfileEntrada : Dict = qos.get("qos-profile")
+        # qosProfileFin : Dict = {}
+                
+        # if "profile" in qosProfileEntrada:
+        #     qosProfileFin.update({"standard-profile":qosProfileEntrada.get("standard")})
+        # elif "classes" in qosProfileEntrada:
+        #     qosProfileFin.update({"custom-classes":readCustom(qosProfileEntrada.get("classes"))})
+        # else:
+        #     print("falta campo en qos>qos-profile")
+        #     #raise NoJSONFieldException("qos>qos-profile")
+                    
+        # res.update({"qos-profile":qosProfileFin})
+        # res.update({"carrierscarrier":qos.get("carrierscarrier")})
+        # multicastEntrada : Dict = qos.get("multicast")
+        # multicastSalida : Dict = {}
+        # multicastSalida.update({"multicast-site-type":multicastEntrada.get("multicast-site-type")})
+        # multicastAddressSalida : Dict = {}
+        # multicastAddressSalida.update({"ipv4":multicastEntrada.get("multicast-address-family", {}).get("ipv4")})
+        # multicastAddressSalida.update({"ipv6":multicastEntrada.get("multicast-address-family", {}).get("ipv6")})
+        # multicastSalida.update({"multicast-address-family":multicastAddressSalida})
+        # multicastSalida.update({"protocol-type":multicastEntrada.get("protocol-type")})
+        
+        # res.update({"multicast":multicastSalida})
+            
+        # # except KeyError:
+        # #     print("falta alguna clave en service")
+        # # except NoJSONFieldException as e:
+        # #     print(e)        
+        # # finally:  
+        return res
+    
+    
\ No newline at end of file
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/FunctionDefinitionNetwork.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/WriteNetworkFunctionDefinition.py
similarity index 88%
rename from src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/FunctionDefinitionNetwork.py
rename to src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/WriteNetworkFunctionDefinition.py
index 940fd00c9c1489e2a7d1446b3c32cf4c7d2db10b..5c22de56dee9140467fb747c4d43db2a3ab25bcc 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/FunctionDefinitionNetwork.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/WriteNetworkFunctionDefinition.py
@@ -1,22 +1,24 @@
 from typing import Dict, List
-import json
+import json, os
 
-class FunctionDefinitionNetwork:
+class WriteNetworkFunctionDefinition:
     
-    jsonEstructuraIntermedia = open("/home/ubuntu/Documents/EstructuraIntermedia.json", "r")
+    input_file_path : str ="/home/ubuntu/Documents/EstructuraIntermedia.json"
     output_file_path = "/home/ubuntu/Documents/L3VPN_ntw.json"
+    
+    jsonEstructuraIntermedia = open(input_file_path, "r")
     jsonEstructuraIntermediaData : str = jsonEstructuraIntermedia.read()
     jsonEstIntDict : Dict = json.loads(jsonEstructuraIntermediaData)    
     
     @staticmethod
     def numberVpnIDs() -> int :
-        vpnIDs : List = FunctionDefinitionNetwork.jsonEstIntDict["VPN_IDs"]
+        vpnIDs : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPN_IDs"]
         return len(vpnIDs)
     
     #Este metodo devuelve el numero de sites, y es necesario porque el numero de sites es el numero de nodes
     @staticmethod
     def numberSitesIDS() -> int :
-        sitesIDs : List = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
+        sitesIDs : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
         return len(sitesIDs)
             
     @staticmethod
@@ -24,7 +26,7 @@ class FunctionDefinitionNetwork:
         
         jsonNet : Dict = {}
         jsonNet.update({"vpn-service":{}}) #no tenemos en cuenta que puede haber más de 1 VPN. Codigo valido para 1 VPN solo
-        vpn_id : str = FunctionDefinitionNetwork.jsonEstIntDict["VPN_IDs"][0].split("vpn")[1] #obtengo el numero de vpn_id
+        vpn_id : str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPN_IDs"][0].split("vpn")[1] #obtengo el numero de vpn_id
         jsonNet["vpn-service"]["vpn-id"] = vpn_id #de momento solo 1 vpn
         # jsonNet["vpn-service"]["customer-name"] = "_"
         # jsonNet["vpn-service"]["parent-service-id"] = "_"
@@ -33,24 +35,24 @@ class FunctionDefinitionNetwork:
         jsonNet["vpn-service"]["vpn-nodes"] = {}
         
         arrayVpnNode : List = []
-        print(FunctionDefinitionNetwork.numberSitesIDS())
-        for numeroDeNode in range(FunctionDefinitionNetwork.numberSitesIDS()):
+        print(WriteNetworkFunctionDefinition.numberSitesIDS())
+        for numeroDeNode in range(WriteNetworkFunctionDefinition.numberSitesIDS()):
           
-            sites : List = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
+            sites : List = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"]
             
-            site: str = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"][numeroDeNode]
-            service_access: str = FunctionDefinitionNetwork.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sites_Dict"][sites[numeroDeNode]]["site-network-accesses"]["site-network-accesses-IDs"][0]
+            site: str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sitesIDs"][numeroDeNode]
+            service_access: str = WriteNetworkFunctionDefinition.jsonEstIntDict["VPNs_Dict"]["vpn1"]["sites_Dict"][sites[numeroDeNode]]["site-network-accesses"]["site-network-accesses-IDs"][0]
             
             #con los siguientes ifs hago que las politicas cambien de lugar, uno si y uno no constantemente
             if numeroDeNode % 2 is 0:
-                arrayVpnNode.append(FunctionDefinitionNetwork.writeNode(FunctionDefinitionNetwork.jsonEstIntDict,site,service_access,numeroDeNode, 0))
+                arrayVpnNode.append(WriteNetworkFunctionDefinition.writeNode(WriteNetworkFunctionDefinition.jsonEstIntDict,site,service_access,numeroDeNode, 0))
             if numeroDeNode % 2 is not 0:
-                arrayVpnNode.append(FunctionDefinitionNetwork.writeNode(FunctionDefinitionNetwork.jsonEstIntDict,site,service_access,numeroDeNode, 1))
+                arrayVpnNode.append(WriteNetworkFunctionDefinition.writeNode(WriteNetworkFunctionDefinition.jsonEstIntDict,site,service_access,numeroDeNode, 1))
 
         jsonNet["vpn-service"]["vpn-nodes"]["vpn-node"] = arrayVpnNode
                 
         #Codigo para crear el archivo y escribir el json en el
-        with open(FunctionDefinitionNetwork.output_file_path, 'w') as json_file:
+        with open(WriteNetworkFunctionDefinition.output_file_path, 'w') as json_file:
             json.dump(jsonNet, json_file, indent = 3)
             
         return jsonNet
@@ -133,7 +135,7 @@ class FunctionDefinitionNetwork:
             }           
         }
         vpnNetworkAccessElement.update({"status":status})
-        vpnNetworkAccessElement.update({"connection":FunctionDefinitionNetwork.writeConnection()})
+        vpnNetworkAccessElement.update({"connection":WriteNetworkFunctionDefinition.writeConnection()})
                       
         vpn_id : str = jsonEstDict["VPN_IDs"][0]#valido cuando solo hay una VPN.
                                                                                                                                                                             #de momento no IPv6, campo vacio, solo IPv4
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/orignal_L3VPN_Services b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/orignal_L3VPN_Services
new file mode 100644
index 0000000000000000000000000000000000000000..6bd57c8238c1af63ed3f504593f3c70cf8a68cc6
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/orignal_L3VPN_Services
@@ -0,0 +1,80 @@
+# 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 logging
+from typing import Dict, List
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+from nbi.service.rest_server.nbi_plugins.tools.HttpStatusCodes import HTTP_CREATED, HTTP_SERVERERROR
+from nbi.service.rest_server.nbi_plugins.tools.Authentication import HTTP_AUTH
+from .Handlers import process_site, process_vpn_service
+from .YangValidator import YangValidator
+
+LOGGER = logging.getLogger(__name__)
+
+class L3VPN_Services(Resource):
+    @HTTP_AUTH.login_required
+    def get(self):
+        return {}
+
+    @HTTP_AUTH.login_required
+    def post(self):
+        if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
+        request_data : Dict = request.json
+        LOGGER.debug('Request: {:s}'.format(str(request_data)))
+
+        errors = list()
+        if 'ietf-l3vpn-svc:l3vpn-services' in request_data:
+            # processing multiple L3VPN service requests formatted as:
+            #{
+            #  "ietf-l3vpn-svc:l3vpn-services": {
+            #    "l3vpn-svc": [
+            #      {
+            #        "service-id": "vpn1",
+            #        "vpn-services": {
+            #          "vpn-service": [
+            for l3vpn_svc in request_data['ietf-l3vpn-svc:l3vpn-services']['l3vpn-svc']:
+                l3vpn_svc.pop('service-id', None)
+                l3vpn_svc_request_data = {'ietf-l3vpn-svc:l3vpn-svc': l3vpn_svc}
+                errors.extend(self._process_l3vpn(l3vpn_svc_request_data))
+        elif 'ietf-l3vpn-svc:l3vpn-svc' in request_data:
+            # processing single (standard) L3VPN service request formatted as:
+            #{
+            #  "ietf-l3vpn-svc:l3vpn-svc": {
+            #    "vpn-services": {
+            #      "vpn-service": [
+            errors.extend(self._process_l3vpn(request_data))
+        else:
+            errors.append('unexpected request: {:s}'.format(str(request_data)))
+
+        response = jsonify(errors)
+        response.status_code = HTTP_CREATED if len(errors) == 0 else HTTP_SERVERERROR
+        return response
+
+    def _process_l3vpn(self, request_data : Dict) -> List[Dict]:
+        yang_validator = YangValidator('ietf-l3vpn-svc')
+        request_data = yang_validator.parse_to_dict(request_data)
+        yang_validator.destroy()
+
+        errors = list()
+
+        for vpn_service in request_data['l3vpn-svc']['vpn-services']['vpn-service']:
+            process_vpn_service(vpn_service, errors)
+
+        for site in request_data['l3vpn-svc']['sites']['site']:
+            process_site(site, errors)
+
+        return errors