Resumen

  • RFC 3018 definió un espacio distribuido de 128 bits con instrucciones para leer, escribir, reservar, liberar y transferir control entre máquinas virtuales situadas en nodos distintos.
  • La transacción exigía ejecutar el conjunto completo o no ejecutarlo, pero el propio texto excluía la cancelación posterior y señalaba que un salto o una llamada podía no tener inversa. La atomicidad no era una prueba de restauración ni de resultado.

Había un instante en el que el receptor poseía todas las instrucciones y todavía no había hecho nada con ellas. En ese instante, cancelar era una operación concreta: identificar la cadena y borrarla. Un instante después, la misma cadena podía haber escrito memoria, liberado un bloque y creado un hilo en otra máquina.

Los dos instantes no eran equivalentes.

RFC 3018, publicado como Experimental en diciembre de 2000, lo reconocía con una precisión poco habitual. Su transacción debía ejecutar todas las instrucciones a la vez o ninguna. Pero no contemplaba cancelación después de ejecutar. Si una aplicación necesitaba deshacer, la máquina virtual debía aportar el mecanismo, porque podía haber instrucciones imposibles de cancelar, como una transferencia de control.

La propuesta era ambiciosa. Unified Memory Space Protocol Specification no se limitaba a pedir un servicio remoto. Construía un espacio de direcciones de 128 bits repartido entre nodos de Internet. El código podía leer y escribir memoria remota, reservarla, liberarla, mover código, comparar datos, invocar procedimientos de objetos o transferir la ejecución a una dirección de otro nodo.

La interfaz hacía parecer local la acción. La evidencia seguía siendo distribuida.

El puntero cruzaba la red, la custodia no

UMSP organizaba el cálculo en tres capas. El job era la aplicación distribuida. Cada nodo mantenía una tarea de ese job. Dentro de ella podían vivir varios hilos de control. Un Job Control Point, JCP, coordinaba las tareas y asignaba identificadores.

Eso daba una identidad común al trabajo, no una memoria físicamente común. El RFC dejaba la memoria local bajo la VM, no bajo el protocolo. La VM debía mantener la corrección de punteros, invalidarlos cuando terminaba una tarea y ordenar la ejecución. UMSP tampoco seguía los hilos de usuario.

La dirección de dieciséis octetos combinaba información de red, nodo y memoria local. Podía decir dónde apuntaba una operación. No decía quién conservaba el estado anterior, qué reloj ordenaba los cambios, cómo se recuperaba un bloque tras un reinicio ni quién certificaba que el código remoto había producido el efecto deseado.

Un salto a una dirección de otro nodo creaba un hilo nuevo allí. Un segmento continuo de código, sin embargo, no podía estar repartido entre nodos. La abstracción unía la nomenclatura y la interfaz; no eliminaba los límites de ejecución.

La cadena recorría varias realidades

El protocolo distinguía secuencias y transacciones. Una secuencia expresaba dependencia: la instrucción siguiente esperaba a la anterior, y un fallo cancelaba las posteriores. Una transacción podía agrupar instrucciones no relacionadas, con la regla de ejecutarlas todas juntas o no ejecutar ninguna.

Para llegar a esa decisión, primero había que transferir el conjunto. Su tamaño debía conocerse de antemano por las necesidades de buffering. _BEGIN_TR abría la cadena y _END_CHAIN indicaba que estaba completa.

Después el receptor debía decidir si esperaba. Con TRR=1, recibir el final liberaba automáticamente la transacción. Con TRR=0, quedaba almacenada hasta una orden EXEC_TR. Mientras no hubiera empezado, CANCEL_TR podía eliminar sus instrucciones sin restauración.

TRE añadía otra bifurcación. Un conjunto completo pero aún no ejecutado podía verse obligado a correr cuando terminaba su tiempo de vida o la sesión acababa de forma anormal. Con el valor contrario, se cancelaba. El reloj empezaba después de recibir toda la cadena y podía quedar sin límite.

Por eso una conexión rota no ofrece una sola interpretación. Puede haber interrumpido una transferencia parcial. Puede haber dejado un conjunto completo en espera. Puede haber ocurrido después de EXEC_TR. Incluso puede haber activado una política de ejecución por cierre anormal.

Un registro operativo debe separar al menos la huella del conjunto recibido, el estado listo, la causa de liberación o cancelación y la observación de cada efecto. Etiquetar todo como “commit” borra justo la información necesaria para recuperarse.

La atomicidad tenía una frontera temporal

En una base de datos, la palabra transacción suele despertar expectativas de aislamiento, persistencia y rollback. RFC 3018 no adoptó ese paquete semántico. Su afirmación era más concreta: el grupo de instrucciones debía comenzar como unidad o no comenzar.

Una vez en ejecución, el protocolo no conocía una inversa genérica. Una escritura puede ser leída de inmediato por otro hilo. Liberar memoria puede invalidar referencias que ya circulan. Un procedimiento de objeto puede enviar una orden fuera del job. Un CALL puede entrar en código con efectos propios. Un JUMP remoto puede crear un hilo que siga actuando aunque desaparezca la cadena original.

No basta con almacenar los bytes previos para deshacer ese mundo. Hace falta una compensación específica de la aplicación, y algunas acciones no admiten una compensación fiel.

Pensemos en una cadena que reserva memoria, instala código y salta hacia él. UMSP puede evitar que solo se ejecute la mitad del conjunto. Pero si el código nuevo publica un dato, modifica otro sistema o acciona un dispositivo, cancelar la cadena después no recupera el estado exterior.

La transacción controla la puerta de entrada. No controla todas las consecuencias que cruzan la puerta.

Un ACK de TCP no era un recibo de ejecución

RFC 3018 exigía TCP para el intercambio fiable y permitía UDP para datos que no necesitaran acuse. RFC 793 define un flujo de octetos fiable y ordenado y trata pérdidas, duplicados, daños y desorden. RFC 768 ofrece un servicio de datagramas mucho más delgado.

Esos contratos importan, pero habitan otra capa. TCP puede demostrar que el TCP receptor aceptó octetos. No demuestra que UMSP los validó, que pertenecían a la cadena correcta, que la VM usó la versión esperada de memoria o que el hilo remoto terminó con éxito.

RFC 1831, la especificación de ONC RPC, ofrece una comparación instructiva. Si llega una respuesta sobre TCP, el cliente puede inferir una ejecución bajo el modelo descrito. Si no llega respuesta, no puede suponer que el procedimiento no se ejecutó. El servidor puede haber actuado antes de fallar la conexión. El RFC también distingue las llamadas remotas de las locales por sus fallos, efectos laterales, rendimiento y autenticación.

UMSP presentaba algo aún más próximo al lenguaje de una CPU. Esa proximidad hacía fácil olvidar que una orden remota conserva la incertidumbre de una operación distribuida.

El JCP veía el ciclo de vida, no todos los efectos

El Job Control Point daba un centro al job. Asignaba el identificador global, controlaba el alta y la terminación de tareas y podía participar en la identificación de usuarios y la protección frente a ataques.

Pero el centro no controlaba la memoria de cada VM ni observaba necesariamente todo lo que hacía un hilo remoto. Un mensaje podía perderse después de la ejecución. Un nodo podía reiniciarse. Los identificadores locales podían reutilizarse bajo ciertas condiciones. Los punteros debían invalidarse fuera del protocolo.

Por tanto, “la tarea terminó” y “el resultado esperado ocurrió” son afirmaciones distintas. También lo son “el job terminó” y “todos los efectos externos fueron una sola vez”. El JCP era una autoridad de coordinación, no un testigo universal.

La seguridad quedó expresamente para una expansión

La sección de seguridad dice que las cuestiones de protección no se incorporaron al mecanismo mínimo para reducir su complejidad inicial. Lo que sigue son recomendaciones.

El texto propone usar protecciones de TCP/IP, cadenas con procesamiento especial para integridad o cifrado y parámetros de autenticación en cabeceras de extensión. Imagina autenticación entre los dos nodos y el JCP. Para el ataque intermediario, se apoya en rutas no coincidentes y reconoce que una pasarela común reduce la eficacia.

También identifica JUMP y CALL como fuentes potenciales de denegación de servicio y entrega a la VM la decisión sobre recursos. Descargar código activo perjudica la posición del cliente; ejecutar código del cliente exige endurecer el servidor.

El diagnóstico es útil. La construcción no está completa. No se especifican algoritmos, claves, autorización, protección contra replay, revocación ni trazabilidad suficientes para convertir una instrucción potente en una operación segura.

RFC 3552, posterior, presupone que un atacante en Internet puede leer, retirar, modificar o inyectar tráfico. Sirve como contraste analítico, no como regla retroactiva. Ayuda a ver por qué una topología recomendada y unas extensiones futuras no equivalen a una garantía actual.

Experimental no significaba estándar ni despliegue

RFC 2026 coloca las especificaciones Experimental fuera del standards track y aclara que no son Internet Standards. Pueden preservar trabajo de investigación o desarrollo. RFC 2119 y RFC 2234 aportaban el vocabulario normativo y la ABNF citados por RFC 3018.

El registro documental demuestra que UMSP fue descrito. No demuestra que se desplegara, que dos implementaciones interoperaran ni que ocurriera un incidente real. Cualquier relato de adopción necesitaría otras fuentes.

La historia que sí está en el texto es más precisa. El protocolo intentó ocultar la red bajo una memoria unificada y, al hacerlo, señaló las fronteras que seguían presentes. Una dirección común no fusionaba responsabilidades. Un conjunto recibido no era un conjunto liberado. Una liberación atómica no era un rollback. El final de un job no era el resultado observado.

Las ideas de Lu Heng funcionan aquí como lentes declaradas. Running-Code Primacy exige que la instrucción llegue al sistema operativo antes de convertirse en hecho. Reality Layers separa el mensaje, el buffer, la decisión, la ejecución y el resultado. Minimum Initial Specification permite un núcleo pequeño, pero no autoriza a inventar los contratos de seguridad, compensación y observación que faltan.

El paquete podía conservarse intacto. La realidad que desencadenaba no tenía por qué serlo.

Sources