Cnet Simulación de redes de conmutación de paquetes SIMULADOR DE REDES CNET ............................................................................................................3 1. 2. INTRODUCCIÓN ...............................................................................................................................3 FICHERO DE TOPOLOGÍA ..................................................................................................................4 2.1. Atributos de nodo..................................................................................................................5 2.2. Atributos de link....................................................................................................................7 3. PROGRAMACIÓN CONDUCIDA POR EVENTOS ...................................................................................9 3.1. Lista de eventos.....................................................................................................................9 3.2. Funciones para el manejo de eventos...................................................................................9 3.3. Ejemplo de manejador de eventos ......................................................................................10 4. TEMPORIZADORES.........................................................................................................................11 5. FUNCIONES PROPORCIONADAS POR CNET......................................................................................12 5.1. Capa Aplicación .................................................................................................................12 5.1.1. 5.1.2. 5.2. 5.2.1. 5.2.2. 5.2.3. 5.3. 5.3.1. 5.3.2. Descripción .................................................................................................................................. 12 Funciones ..................................................................................................................................... 14 Capa Física.........................................................................................................................15 Descripción .................................................................................................................................. 15 Transmisión segura a través de la capa fisica ............................................................................... 16 Funciones ..................................................................................................................................... 16 Temporizadores ..................................................................................................................17 Descripción .................................................................................................................................. 17 Funciones ..................................................................................................................................... 18 5.4. Funciones para el manejo de eventos.................................................................................19 5.5. Funciones para traceado....................................................................................................19 5.6. Funciones para detección de errores .................................................................................19 5.7. Funciones varias.................................................................................................................20 6. COMPILACIÓN ...............................................................................................................................21 7. TIPOS DE NODO, EVENTOS Y ERRORES .........................................................................................25 7.1. Tipo CnetNodeType ............................................................................................................25 7.2. Tipo CnetEvent ...................................................................................................................25 7.3. Tipo CnetError ...................................................................................................................26 8. INFORMACIÓN ADICIONAL.............................................................................................................26 __________________________ Página: 2 SIMULADOR DE REDES CNET 1. Introducción El simulador de redes Cnet está desarrollado en torno al Modelo de Referencia OSI, permitiendo la experimentación y diseño de las capas intermedias del modelo de forma que los Niveles Físico y Aplicación son proporcionados por el propio Simulador. No obstante, la herramienta posibilita que programadores expertos puedan desarrollar sus propios Niveles Físico y Aplicación, de forma que se puedan aportar nuevas funcionalidades o características. Figura 1. Modelo de Referencia OSI Cnet soporta tanto los modos de visualización gráfico, bajo entorno Tcl/Tk y modo de visualización ASCII (texto). En el modo gráfico (Tcl/Tk), Cnet proporciona una representación global de la red, en formato gráfico, visualizando los nodos (host/routers) o enlaces (links), además de permitir una interacción con la simulación a través de la interface gráfica, permitiendo la modificación de diferentes atributos de los nodos y/o links, en tiempo de ejecución. Haciendo clic de ratón sobre los diferentes nodos y enlaces se despliegan otras ventanas, mostrando sus atributos del nodo, y sus datos estadísticos de simulación. De la misma forma, los atributos por defecto de la red pueden ser modificados mediante la selección o cambio de atributos globales, e incluso, provocar una re-inicialización de un nodo, fallo de hardware, etc. Una arquitectura de la simulación en Cnet se define mediante dos ficheros: fichero de topología y fichero de protocolo. • Fichero de Topología: Fichero de texto donde se describen los diferentes atributos de cada nodo, links, así como las diferentes conexiones entre los nodos de la red. La descripción de atributos puede ser de forma particular para cada nodo (o link) o de forma general para todos los elementos. __________________________ Página: 3 • Fichero de Protocolo: Fichero de texto de código ANSI-C donde se describe el protocolo a implementar, utilizando procedimientos, funciones y constantes proporcionados por Cnet, así como código de usuario en lenguaje C para desarrollos de protocolos particulares. Figura 2. Ejemplo de representación gráfica de topología. 2. Fichero de topología Pasamos a definir algunos conceptos que se utilizarán a continuación: • • Nodo: Cada uno de los elementos (dispositivos activos) de la red. Link (Enlace). Punto del nodo por donde conecta con el medio de transmisión. Los nodos pueden ser de dos tipos: host y router Los dispositivos tipo host son los que aceptan protocolos de usuario, están provistos de todas las capas, y en concreto de la Capa Aplicación, cuya misión es generar mensajes para enviarlos a la Capa Aplicación de otros host de la red. La capa Aplicación nunca genera mensajes para el propio nodo. Figura 3. Topología Multipunto vs Punto-a-Punto. Como se ha mencionado anteriormente, los nodos están provistos de links (enlaces) puntos de unión del nodo a los diferentes medios de transmisión. Los links se numeran a partir de 0 hasta el nº de links físicos reales del nodo, no obstante, el primer link 'real' es el 1, ya que el valor 0 se utiliza como LOOPBACK (retorno). __________________________ Página: 4 Cnet sólo soporta topologías formadas por nodos con enlaces punto-a-punto, no estando permitidos enlaces multipunto (difusión). Tanto los atributos de link como los atributos de nodo pueden ser definidos en el fichero de topología de forma global o de forma local. Los atributos globales son definidos en el cuerpo principal del fichero de topología y afectan a todos y cada uno de los elementos de la red: nodos y links. Los atributos locales son declarados individualmente para algún elemento (nodo o link), utilizando para ello llaves a modo del Lenguaje C, de forma que, un atributo declarado localmente afecta única y exclusivamente al elemento donde ha sido definido. messagerate = 100ms minmessagesize = 100 b maxmessagesize = 5 kb host Dublin { x=97, y=123 ostype = "linux" link to Paris { propagationdelay } link to London } host Paris { x=194, y=255 link to Dublin { propagationdelay } link to Amsterdam { propagationdelay } link to Vienna { propagationdelay } link to Madrid { propagationdelay } link to London { propagationdelay } } host London { x=189, y=102 link to Dublin link to Paris } host Amsterdam { x=294, y=176 link to Paris { propagationdelay } link to Vienna { propagationdelay } link to Munich { propagationdelay Atributos Globales = 50ms = 150ms = 100ms = 200ms = 80ms = 80ms = 125ms = 100ms = 100ms } } host Vienna { x=546, y=334 link to Amsterdam link to Venice link to Innsbruck link to Munich } host Rome { x=442, y=576 link to Venice link to Corsica link to Innsbruck } host Madrid { x=74, y=380 link to Paris link to Corsica } host Munich { x=461, y=145 link to Amsterdam link to Vienna link to Berlin } host Venice { x=487, y=416 link to Vienna link to Rome } host Innsbruck { x=404, y=356 link to Vienna link to Rome } host Corsica { x=264, y=455 link to Rome link to Madrid } host Berlin { x=639, y=238 link to Munich } Atributos Locales 2.1. Atributos de nodo Los atributos de los nodos se pueden mantener con los valores por defecto que proporciona Cnet, o bien pueden ser declarados en la simulación, para ello es necesario especificarlos en el Fichero de Topología. Además, algunos atributos, tanto de nodo como de links, pueden ser modificados en tiempo de ejecución. Algunos ejemplos de atributos son: • • • • Tasa de generación de mensajes Tamaño máximo / mínimo de mensajes Tasa de fallos / recuperación de nodos Etc. Como los atributos hacen referencia, básicamente, a unidades de tiempo, velocidad, etc., es necesario definir unos tipos básicos de uso en Cnet. __________________________ Página: 5 • • • • Los tiempos son manejados y almacenados en formato de milisegundos. En la declaración de atributos se pueden utilizar los sufijos: ms y s Los tamaños de datos son manejados y almacenados en formato de bytes. En la declaración de atributos se pueden utilizar los sufijos: bytes, Kbytes, KB y MB. Los atributos booleanos pueden tomar los valores: true, false y toggle. Los valores de string van entre comilla doble "". Atributo de Nodo Tipo de Dato Significado Ejemplo integer La dirección de cada nodo dentro de la red. Este valor esaddress = 238 único para cada nodo compile string Define el nombre del fichero fuente de protocolo paracompile = protocol.c stats.c -lm" cada nodo. messagerate time La razón a la que la Capa Aplicación puede generarmessagerate = 100ms mensajes nuevos para enviar. messagerate = 2s minmessagesize bytes Tamaño mínimo de mensaje generado por Capaminmessagesize = 100 bytes Aplicación minmessagesize = 4kb maxmessagesize bytes Tamaño máximo de los mensajes generados por Capamaxmessagesize = 200 bytes Aplicación maxmessagesize = 8kb nodemtbf time Tiempo entre fallos de hardware (promediado) nodemtbf = 600000ms nodemtbf = 1000s nodemttr time Tiempo de reparación fallo hardware (promediado) nodemttr = 5000ms nodemttr = 100s ostype string Nombre del sistema operativo que se ejecuta en el nodo,ostype = "linux" únicamente utilizado para mostrar el icono. Posibles valores: bsd, hurd, irix, linux, macintosh, nextstep,os2, solaris, winnt. outputfile string Fichero de salida para cada nodo. Si se utiliza comooutputfile = "prueba" atributo global, entonces outputfile indica el prefijo del fichero (igual que la opción -o). Cuando se utiliza como atributo local, outputfile indica el nombre de fichero completo. rebootnode string Función ANSI-C llamada cuando el nodo realiza unrebootnode = "mi_reboot_funcion" reboto. trace boolean Indicador de seguimiento de traza de la simulación trace = true winopen boolean Atributo booleano que indica si las ventanas de cadawinopen = false nodo se abrirán al arrancar. winx, winy integer Coordenadas de la ventana del nodo en entorno Tcl/Tk. winx = 100, winy = 200 x,y integer Coordenadas del icono del nodo en la ventana principal x = 80, y = 120 address __________________________ Página: 6 En tiempo de ejecución, el código C de protocolo de cada nodo tiene acceso a una estructura (previamente definida en cnet.h) y que contiene la descripción de atributos del nodo. Esta estructura tiene un carácter de 'solo lectura' y su contenido es actualizado por cada nodo a lo largo de la ejecución. typedef struct { CnetNodetype nodetype; /* Puede ser NT_HOST o NT_ROUTER */ int nodenumber; /* Rango de 0..NNODES-1 */ CnetAddr address; /* Posiblemente diferente a nodenumber */ char nodename / * Nombre del nodo */ int nlinks; /* Rango de 0 (=LOOPBACK) .. nlinks */ int minmessagesize; /* Tamaño minimo (en bytes) de los mensajes generados */ int maxmessagesize /* Tamaño máximo (en bytes) de los mensajes generados */ int messagerate; /* tasa de generación de mensajes (in ms) */ long time_in_ms /* Reloj con incremento monotónico */ struct { long sec; long msec; } time_of_day; /* Copia de la hora del sistema */ } CnetNodeinfo; CnetNodeinfo nodeinfo Como se ha indicado anteriormente, en todos y cada unos de los nodos, se realiza un duplicado del código C. Por tanto, en cada nodo está disponible la variable global CnetNodeinfo nodeinfo de forma que se pueden acceder de forma 'solo lectura' a los campos de la estructura de tipo CnetNodeinfo, donde se pueden obtener los diferentes atributos del nodo. 2.2. Atributos de link La red está formada por nodos, unidos entre sí mediante links punto-a-punto bidireccionales. Por defecto, los links se definen como no seguros, es decir, son susceptibles de pérdida de paquetes y producir errores en los mismos. De la misma forma que con los atributos del nodo, los valores iniciales de los atributos del link también se definen en el fichero de topología, no obstante, algunos de ellos se pueden cambiar en tipo de ejecución. Atributo de Link bandwidth Tipo de Dato Significado tasa de datos El ancho de banda (bandwidth) del link Ejemplos bandwidth = 100000bps bandwidth = 56Kbps costperbyte centimos Costo por byte a lo largo del link costperbyte = 1c costperframe centimos Costo por trama a lo largo del link costperframe = 5c Linkmtbf tiempo Promedio esperado de tiempo entre falloslinkmtbf = 50000ms hardware del enlace linkmtbf = 1000s Linkmttr tiempo Promedio esperado de tiempo en repararlinkmttr = 5000 ms fallos hardware del enlace linkmttr = 100s probframecorrupt probabilidad La probabilidad de que se produzca un errorprobframecorrupt = 3 en la trama a lo largo de la línea /* 1 / 8 */ probframeloss probabilidad La probabilidad de que se pierda la trama a loprobframecorrupt = 4 largo del link. / 1/16 */ propagationdelay tiempo Tiempo de propagación a lo largo del enlace. propagationdelay = 20ms propagationdelay = 1s __________________________ Página: 7 De la misma forma que con la estructura CnetNodeinfo, cada nodo tiene acceso, a través del protocolo en código C, a su propia estructura CnetLinkinfo, que contiene la descripción de los atributos de sus links. En este caso, también se trata de una estructura de carácter 'solo lectura' y sus valores son actualizados por cada nodo a lo largo de la ejecución. Por otro lado, la variable linkinfo es un vector de estructuras CnetLinkinfo, de forma que, a través de esta variable se puede acceder a todos los atributos de cada nodo, mediante los índices en orden creciente. Por ejemplo: linkinfo[0] ---> Atributos del enlace denominado LOOPBACK linkinfo[1] ---> Atributos del primer enlace físico link info[2] ---> Atributos del segundo enlace físico ... linkinfo[n] ---> Atributos del n enlace físico typedef struct { int linkup; int bandwidth; int propagationdelay int transmitbufsize int costperbyte int costperframe; } CnetLinkinfo; /* TRUE si el link está operativo */ /* bps */ /* in ms */ /* bytes */ /* $ */ /* $ */ CnetLinkinfo linkinfo; /* linkinfo[0]..linkinfo[nodeinfo.nlinks] */ Por ejemplo, para obtener el valor del ‘tiempo de propagación’ (propagationdelay) del primer link “real” de un nodo, se utilizará linkinfo[1].propagationdelay __________________________ Página: 8 3. Programación conducida por eventos Una de las características más potentes de Cnet radica en el uso de la Programación Conducida por Eventos. Podemos definir evento, como un suceso que ocurre, y el sistema informa de ello, pudiendo actuar en consecuencia. En el caso que nos ocupa, Cnet informa de que se ha producido un evento, los protocolos de usuario (código ANSI-C) están organizados para reconocer dichos eventos, y actuar según la especificación del protocolo. Como acciones o eventos modelizados por Cnet, tenemos: • • • • • • • • Un nodo hace reboot. Capa Aplicación tiene algún mensaje para enviar. Capa Física recibe una trama por algún link. Entrada de texto por teclado (Keyboard). Cambio de estado de algún link. Expiración de temporizador. Botón de debug. Caída controlada de algún nodo (shutdown). Todos estos eventos son del tipo CnetEvent, y son registrados con la función CNET_set_handler(). Además se puede realizar un seguimiento de los eventos con la función CNET_set_trace(). 3.1. Lista de eventos Una relación completa de todos los eventos utilizados por Cnet, podemos encontrarlos en la siguiente tabla: CnetEvent EV_NULL Descripción Uso exclusivo por Cnet. No se puede ser utilizado por los protocolos de usuario EV_REBOOT Evento generado cuando se reinicializa el sistema EV_SHUTDOWN Generado justo antes de terminar (de forma controlada) la ejecución del sistema EV_APPLICATIONREADY Generado cuando la Capa Aplicación tiene algún mensaje para enviar. EV_PHYSICALREADY Generado cuando llega una trama por algún link del dispositivo. EV_KEYBOARDREADY Generado cuando se introduce una línea desde teclado. EV_LINKSTATE Generado cuando un link cambia de estado (off/on, on/off). EV_DEBUG1...EV_DEBUG5 Generado cuando se presiona un botón debug (entorno X-Windows). EV_TIMER1...EV_TIMER10 Generado cuando algún temporizador expira su tiempo programado. 3.2. Funciones para el manejo de eventos Para implementar un Manejador de Eventos, el primer paso es asociar los distintos eventos al código de programa que se quiere ejecutar una vez generado el evento. Para el registro de eventos se utiliza la función: int CNET_set_handler(CnetEvent ev, void (*func)(),CnetData data) donde: • • • CnetEvent ev se trata de un evento del tipo CnetEvent, es decir, la razón por la que el manejador de eventos ha sido invocado, y correspondiente a uno de los eventos relacionados en la Tabla anterior Void (*func)() es un puntero a la función de usuario invocada una vez generado el evento. CnetData data consiste en cierta información especifica de usuario. __________________________ Página: 9 Las funciones manejadas por eventos son invocadas por Cnet, con tres parámetros: • El primero es del tipo evento (razón por la que el manejador ha sido invocado), es un valor del tipo CnetEvent de los listados en la Tabla de eventos. • El segundo parámetro es un temporizador único. • Y el tercer parámetro se puede utilizar para suministrar algún dato específico de usuario. Una vez tenemos identificado el evento de interés que nos informa de alguna acción sucedida en la simulación, y se ha asociado a la ejecución de algún procedimiento o función de usuario, ya está en condiciones de ser invocada por Cnet, debido a la ocurrencia de algún evento registrado. 3.3. Ejemplo de manejador de eventos En el siguiente fragmento de código C, implementa el manejador de eventos para controlar algunos eventos proporcionados por Cnet. El código del ejemplo muestra un par de eventos, en concreto aquellos que indican cuando la Capa Aplicación tiene un mensaje para enviar (EV_APLICATIONREADY), y cuando ha llegado una trama al nodo por algún link (EV_PHYSICALREADY). #include <cnet.h> void NuevoMensaje(CnetEvent ev, CnetTimer timer, CnetData data) { ... resultado = CNET_read_application( ... ); ... } void LlegaTrama(CnetEvent ev, CnetTimer timer, CnetData data) { ... resultado = CNET_read_physical ( ... ); ... } void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data) { ... resultado = CNET_set_handler(EV_APPLICATIONREADY, NuevoMensaje, 0); (1) resultado = CNET_set_handler(EV_PHYSICALREADY, LlegaTrama, 0); ... } El archivo de cabecera cnet.h contiene todas las tipos de datos, constantes y prototipos de funciones necesarias para el correcto funcionamiento de los protocolos de usuario. En el procedimiento reboot_node, es donde se realiza el registro de eventos (si no se especifica otra opción con la opción de compilador) , asociando un determinado evento con una acción a realizar. Así, mediante (1), el protocolo de usuario le está informado a Cnet que cuando se produzca el evento EV_APPLICATIONREADY (la capa aplicación tiene un mensaje para enviar), ejecute el procedimiento NuevoMensaje. De la misma manera, mediante la instrucción (2), se le está informado a Cnet que cuando llegue alguna trama por algún link del nodo (EV_PHYSICALREADY), ejecute el procedimiento asociado LlegaTrama, que contendrá el protocolo de usuario necesario para realizar las operaciones correspondientes. Hasta el momento sólo hemos utilizado los dos primeros parámetros del la función CNET_set_handler(), correspondientes al evento generado y el procedimiento de usuario asociado. Ésta función está provista de un tercer parámetro, del tipo CnetData, por el que se le pasa al Manejador de Eventos un cierto valor. Este parámetro será utilizado en el desarrollo de __________________________ Página: 10 protocolos avanzados, dónde será necesario pasar un determinado valor al Manejador de Eventos, por ejemplo, del tipo integer, puntero, etc. En concreto, para el manejo de funciones de time-out, donde se utilizan temporizadores de usuario, este parámetros se utiliza precisamente para informar del temporizador utilizado (EV_TIMER1...EV_TIMER10), necesario para realizar las operaciones de activado / desactivado de dicho temporizador. IMPORTANTE: Las funciones manejadas por eventos deben finalizar su ejecución completamente. Cada vez que son llamadas, deben de ejecutar sus instrucciones y simplemente salir (no devolver ningún valor). Las funciones manejadas por eventos deben ser del tipo void, esto es, no retornan ningún valor. En el caso de que una función manejada por evento no retorno, producirá el fallo total de la simulación, incluso del entorno gráfico, Cnet abortará la ejecución y será interrumpido invocando xterm. 4. Temporizadores Ya hemos introducido las funciones manejadas por eventos y la ejecución de procedimientos de usuario asociados a los distintos eventos de Cnet. Los temporizadores son un tipo especial de evento que proporciona Cnet, provocando la generación de un evento una vez finalizada o expirado el tiempo que previamente se había fijado. Cnet provee de 10 temporizadores de usuario, proporcionando un mecanismo de 'call-back' o vuelta al código de protocolo. De la misma forma que se declaran los distintos eventos en la función reboot_node, asociando dichos eventos a un procedimiento / función de protocolo, los eventos generados por los temporizadores también hay que declararlos en la inicialización del nodo, esto es, en la función reboot_node, asociando su evento (expiración del tiempo prefijado) a la ejecución de un determinado procedimiento / función de protocolo. Por ejemplo, el código de protocolo CNET_set_handler ( EV_TIMER1, MiProcedimientoTemporizador_Out, 0 ) ; asocia el evento EV_TIMER1 con el procedimiento MiProcedimientoTemporizador, de forma que una vez agotado el tiempo prefijado en el temporizador, se genera el evento EV_TIMER1, provocando la ejecución de la función MiProcedimientoTemporizador. De momento, hemos visto la forma de asociar un evento generado por temporizador con un procedimiento de protocolo, pero todavía no hemos visto la forma de activar un temporizador con un determinado valor, así como desactivarlo. Para la activación y desactivación de temporizadores, Cnet proporciona las siguientes funciones: CnetTimer CNET_start_timer(CnetEvent ev, long msec, CnetDada data) int CNET_stop_timer(CnetTimer timer) Vamos a detallar su funcionamiento mediante un ejemplo: void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data) { ... resultado = CNET_set_handler(EV_TIMER3, CodigoDeTimer, 0); ... } ... __________________________ Página: 11 ... void CodigoDeTimer( ... ) { ... Mitimer = CNET_start_timer(EV_TIMER3, 500 , 0); ... ... CNET_stop_timer(MiTimer); ... } ... ... En el código de protocolo anterior se ha declarado en el procedimiento de inicialización de nodo (reboot_node) el temporizador EV_TIMER3 y se ha asociado a la ejecución del procedimiento CodigoDeTimer, provocando que cuando se genere el evento, se ejecutará el código de programa que contiene CodigoDeTimer. Dentro de este procedimiento es precisamente donde han sido definidas las operaciones de activación / desactivación del temporizador MiTimer. 5. Funciones proporcionadas por Cnet 5.1. Capa Aplicación 5.1.1. Descripción En el Simulador Cnet, la Capa Aplicación es la encargada de generar mensajes que serán enviadas a las Capas Aplicación de nodos remotos, a través de la red y sus respectivos enlaces. NOTA: Capa Aplicación de un nodo nunca genera mensajes para el propio nodo, siempre van destinados aun nodo adyacente o remoto de la red. Los mensajes generados Capa Aplicación, son transparentes al usuario, por tanto, su contenido es irrelevante, no tanto como su destino y longitud. El destino de los mensajes viene determinado siempre por la dirección del dispositivo en la red (nunca por el número de nodo). Cnet informa al protocolo de usuario de que la Capa Aplicación tiene un mensaje para enviar, mediante el evento EV_APPLICATIONREADY y su función asociada correspondiente. El protocolo de usuario, realiza la lectura del mensaje generado por Capa Aplicación, mediante la función: Figura 5. Funciones CNET, protocolo de usuario y eventos. int CNET_read_application(CnetAddr *dest , char *msg , int *len) En el parámetro len, se le informa a la Capa Aplicación de la longitud máxima de mensaje que se está en disposición de leer. Una vez leído el mensaje generado por la Capa Aplicación, éste se guarda en la variable msg, y en el parámetro len se devuelve la longitud real del mensaje leído, y en la variable dest se almacena la dirección del nodo al cual va dirigido el mensaje. __________________________ Página: 12 NOTA: Hay que destacar que el mensaje generado es totalmente 'ilegible', tratándose de un cadena de caracteres, sin ningún sentido ni significado, de una longitud determinada. Una secuencia típica de lectura de mensaje es: char buffer[MAX_MESSAGE_SIZE]; CnetAddr dirdestino; int longitud; longitud = sizeof(buffer); resultado = CNET_read_application(&dirdestino, buffer, &longitud); /* ... a continuación ya se puede preparar el menaje para enviar al destino ....*/ Una vez alcanzado el nodo destino correcto, el mensaje debe ser entregado a la Capa Aplicación, utilizado la función: int CNET_write_application ( char *msg , int *len) Y de la misma forma, presentamos una secuencia típica de escritura en la Capa Aplicación del nodo destino: /*...... se recibe el mensaje desde otro nodo */ resultado = CNET_write_applicacion (buffer, &longitud); Como ya se ha indicado, la misión de la Capa Aplicación, básicamente, es generar mensajes que serán enviados a la Capa Aplicación de otros nodos remotos. En función del protocolo que se necesite implementar, de las necesidades de operación de la red, o de cualquier otra característica de la simulación, es muy posible que se plantee la necesidad de desactivar la generación de mensajes hacia algún nodo destino, hacia varios nodos destino e incluso, desactivar la generación de mensajes hacia todos los nodos destino. Para realizar estas operaciones se utilizan las funciones de Cnet: int CNET_enable_application(CnetAddr dirdestino); int CNET_disable_application(CnetAddr dirdestino); Por ejemplo, supongamos que el nodo con dirección 'nodo_i' está por algún motivo off-line u ocupado. El nodo que ha determinado esta situación, deberá desactivar el envío de mensajes hacia dicho nodo ocupado, con la sentencia: resultado = CNET_disble_application(nodo_i); de la misma forma, posteriormente, este nodo puede ser activado, de forma que se habilite el envío de paquetes hacia él, con la sentencia: resultado = CNET_enable_application(nodo_i); Una forma de habilitar el envío de mensajes hacia todos (a excepción del propio nodo, evidentemente), es utilizando la sentencia: resultado = CNET_enable_application(ALLNODES) esta función normalmente se ejecuta en la función reboot_node(). __________________________ Página: 13 5.1.2. Funciones int CNET_read_application ( CnetAddr *destino , char *mensaje, int *longitud ) ; Lectura de un mensaje de la Capa Aplicación. En la llamada, 'longitud' debe ser un puntero a entero indicando la longitud máxima (en bytes) que pueden ser copiados en 'mensaje'. El retorno de la función, 'longitud' será un puntero indicando la cantidad real de bytes copiados en 'mensaje'. La dirección del nodo destino en la red será copiado en 'destino'. Posibles errores: ER_BADSIZE, ER_NOTREADY, ER_NOTSUPPORTED. int CNET_write_application ( char *msg, int *len ) ; Ésta función se encarga de entregar la información a la Capa Aplicación del nodo al que va dirigido el mensaje. Realiza la entrega de un numero de bytes (len) a partir del puntero a msg. Cuando se realiza la llamada de CNET_write_application(), el parámetro len contiene el número de bytes que se tomarán de msg y que se van a entregar a la Capa Aplicación. Devuelve en el parámetro len un puntero a entero indicando el numero de bytes aceptados por la Capa Aplicación. Posibles errores: ER_BADARG, ER_BADSENDER, ER_BADSESSION, ER_BADSIZE, ER_CORRUPTDATA, ER_NOTFORME, ER_NOTREADY, ER_NOTSUPPORTED, ER_OUTOFSEQ. int CNET_enable_application ( CnetAddr destaddr ) ; Habilita la Capa Aplicación para generar mensajes destinados al nodo cuya dirección en la red es destaddr. Es posible utilizar la constante ALLNODES, que indica establecer la generación de mensajes para todos los nodos de la red. Al iniciar la simulación, la generación de mensajes por defectos está en modo 'deshabilitado'. Es necesario establecer la habilitación para iniciar la generación de mensajes hacia algún nodo, algún grupo de nodos o todos los nodos, dependiendo del valor del parámetro destaddr. Posibles errores: ER_NOTSUPPORTED. int CNET_disable_application ( CnetAddr destaddr ) ; Deshabilita la generación de nuevos mensajes de la Capa Aplicación hacia el nodo indicado por la dirección de red (destaddr). Al igual que con el parámetro anterior, se puede utilizar la constante ALLNODES para deshabilitar la generación de mensajes nuevos hacia todos los nodos de la red. Se utiliza la función CNET_disable_application(), en general, cuando hay que ralentizar o parar la generación de mensajes nuevos hacia algún nodo destino. Esta situación puede ser originada por varios motivos: saturación de nodo destino, estrategias de parada-y-espera, algoritmos de routing con envíos temporales de paquetes, etc. Posibles errores: ER_NOTSUPPORTED. __________________________ Página: 14 5.2. Capa Física 5.2.1. Descripción La Unidad de Datos utilizada a este nivel es el denominado Trama de Datos, o simplemente, trama. La Capa Física es el nivel del Modelo de Referencia OSI que está en contacto con el medio físico, esto es, el medio de transmisión, teniendo por misión la del envío de tramas a través del medio de transmisión que une dos nodos (recordamos en este punto que Cnet sólo permite enlaces punto-a-punto entre nodos), por tanto, la trama parte de un nodo origen y pasado un tiempo, y dependiendo de varios factores, alcanzará el destino en perfecto estado, o quizás alcance el destino pero con errores, e incluso, puede ser que la trama se pierda a lo largo del link, por motivos de ruidos, interferencias, etc, Los links de un nodo se numeran automáticamente, empezando por la secuencia 0 hasta n (número de links), siendo el primer link operativo el 1, ya que el link 0 está reservado para loopbak del nodo, esto es, link de retorno al nodo, de forma que cualquier trama que salga por e link 0 vuelve inmediatamente a la entrada del nodo. En virtud de realizar una simulación lo más realística posible, se han implementado varias características propias de los medios de transmisión reales, siendo posible establecer, entre otras: • Probabilidad de pérdida de tramas • Probabilidad de error en trama • Tiempo de propagación de la trama a lo largo del medio de transmisión. • Coste de la transmisión / byte • etc. A continuación vamos a ilustrar el uso de CNET_write_physical() y CNET_read_physical(), mediante el uso de un ejemplo. Cuando el protocolo de usuario necesita transmitir una trama a lo largo del medio de transmisión, es decir, a lo largo del link, tiene que realizar una escritura de la trama en el medio físico de transmisión. Para esta operación, Cnet implementa la función CNET_write_physical(), donde hay que indicar la longitud de la trama a escribir, mediante el parámetro correspondiente (int *len), devolviendo en el retorno, la cantidad de bytes reales que han sido aceptados por el medio físico. A continuación se presenta un fragmento de código, correspondiente a la escritura / lectura en el medio físico para una red compuesta por 2 nodos: ... char mitrama [MAX_MESSAGE_SIZE + MI_CABECERA ]; int longitud; ... /* preparar la trama para su posterior envío */ longitud = ...; resultado = CNET_write_physical(1,mitrama,&longitud); ... a continuación, la trama viajaría a través del medio físico de transmisión, hasta que alcanza el nodo destino. Una vez alcanzado el destino, el evento asociado a EV_PHYSICALREADY debe de ejecutar el código asociado para leer dicha trama del medio físico, llamando a la función CNET_read_physical(). A la vuelta de la llamada de la función, los parámetros contienen: nº de link por el que ha llegado la trama, longitud de trama leída y la trama propiamente dicha. De la misma forma, se presenta un fragmente de código para realizar la lectura de tramas del medio físico en una red formada por 2 nodos: ... char mi_trama [ 8 * K ]; int link, longitud; __________________________ Página: 15 longitud = sizeof(mi_trama); resultado = CNET_read_physical(&link, mi_trama, &longitud); ... /* procesar el contenido de la trama recibida */ 5.2.2. Transmisión segura a través de la capa fisica Como se ya se ha indicado, el medio físico no está exento tanto de agentes externos tales como ruidos, interferencias electromagnéticas, ruidos de intermodulación, etc., que pueden provocar errores en las tramas transmitidas, e incluso, pueden llegar a producir la pérdida total de la trama, bien porque no llegue al destino, o bien porque aun alcanzado el destino, tiene una cantidad de errores tan elevada que el receptor es incapaz de detectarla como trama. Para dotar a Cnet de una opción de transmisión segura, es decir, eliminar totalmente la probabilidad de errores de trasmisión y/o pérdidas de paquete, se proporciona una función adicional: int CNET_write_physical_reliable ( int link, char, int *len ) ; que tiene el mismo comportamiento que CNET_write_physical ( int link, char, int *len ) ; con la diferencia de que implementa un medio de transmisión 'totalmente seguro' eliminando por completo la probabilidad de producirse errores y/o pérdidas de tramas. Ésta opción es de utilidad cuando se están implementando protocolos de alto nivel (capas superiores de OSI) y no se desea tener en cuenta la Capa de Nivel de Enlace, por lo que se implementa una Capa de Enlace de Datos 'perfecta', ‘sin pérdida de datos’ Otra función disponible en Cnet correspondiente al Medio Físico es: CNET_write_direct ( CnetAddr destaddr, char *msg, int *len ) ; El objetivo de esta función es hacer un by-pass al Medio Físico, evitando cualquier error posible y/o pérdida de tramas. Para ello, envía el mensaje directamente al nodo destino, cuya dirección es especificado en el primer parámetro (destaddr). De esta forma se está consiguiendo implementar una Capa de Enlace de Datos y Red ¿¿perfectas??, eliminando a su vez tiempos y demoras en la transmisión de la trama a través del link. 5.2.3. Funciones int CNET_write_physical ( int link, char *trama , int *longitud ) ; Esta función toma un número de bytes contenido en el puntero a trama, y los pasa a la Capa Física, para que sean enviados hacia el destino a través de un determinado link. El link representa el medio físico de transmisión por el que se van a enviar los datos. Cada nodo tiene un número fijo de links, numerados de 0..n, siendo el 0 utilizado para loopback (retorno hacia el nodo), por lo que el primer nodo útil es el 1, el siguiente el número 2, y así sucesivamente. Al realizar la llamada, el parámetro int *longitud contiene la cantidad de bytes que se van a pasar al medio físico, a la vuelta, contiene el número de bytes aceptados por la Capa Física. __________________________ Página: 16 Posibles errores: ER_BADARG, ER_NOTREADY, ER_TOOBUSY. ER_BADLINK, ER_BADSIZE, ER_LINKDOWN, int CNET_write_physical_reliable ( int link , char *trama , int *len ) ; Esta función es idéntica a la anterior, CNET_write_physical(), pero garantiza un medio físico libre de errores de cualquier tipo (error y/o perdida de trama), proporcionando con ello una Capa de Enlace de Datos confiable. Posibles errores: ER_BADARG, ER_NOTREADY, ER_TOOBUSY. ER_BADLINK, ER_BADSIZE, ER_LINKDOWN, int CNET_write_direct ( CnetAddr destaddr, char *msg, int *len ) ; Ésta función es similar a CNET_write_physical_reliable(), con la diferencia de que se especifica la dirección del nodo destino (destaddr), proporcionando con ello funciones de red / routing confiables con paso de mensajes asíncrono). Los mensajes transmitidos con CNET_write_direct() se supone son enviados y recibidos siempre a través del link numero 1. Es posible utilizar la constante BROADCAST para especificar el envío de un mensaje a todos los nodos de la red, excepto al emisor, evidentemente. Posibles errores: ER_BADARG, ER_NOTREADY, ER_TOOBUSY. ER_BADLINK, ER_BADSIZE, ER_LINKDOWN, int CNET_read_physical ( int *link , char *trama , int *len ) ; Esta función acepta un número máximo de bytes del Nivel Físico y los guarda en la variable apuntada por trama. Se llama a la función indicando en el parámetro len la cantidad máxima de bytes que se pueden copiar en la variable trama. En el retorno, el parámetro len contiene la cantidad de bytes realmente leídos del Nivel Físico ( y copiados a trama). El parámetro link contiene el link (enlace del nodo al medio físico) por el que ha llegado la trama leída. Posibles errores: ER_BADARG, ER_BADSIZE, ER_CORRUPTDATA, ER_NOTREADY. 5.3. Temporizadores 5.3.1. Descripción El uso de temporizadores es muy utilizado en simulación, y en concreto, en el tema que nos ocupa de simulación de redes. Los temporizadores proporcionan un mecanismo de retorno al código de protocolo de usuario, ya que al especificar un tiempo de temporización o disparo y activar dicho temporizador, al expirar este tiempo, se genera el evento asociado, que producirá la ejecución de la función correspondiente, manejada por dicho evento. Cada temporizador declarado es necesario realizar una operación de 'arranque' (start) sobre él, para que inicie el contador de tiempo, si una vez arrancado, alcanza el tiempo fijado, genera un evento y ejecuta la función manejada por dicho evento, además de la re-inicialización del temporizador. Con la operación de 'parada' (stop), se detiene la ejecución de dicho temporizador, y su re-inicialización, de forma que, en la siguiente activación empezará con la cuenta de tiempo desde 0. __________________________ Página: 17 Cnet proporciona 10 colas de temporizador, asociados a otros tantos eventos de temporización: EV_TIMER1, ..., EV_TIMER10. No obstante, en cada cola de temporizador se pueden iniciar un número ilimitado de temporizadores, como se ilustra en el siguiente código: void timeouts(CnetEvent ev, CnetTimer timer, CnetData data) { int i = (int) data; printf(“ciclo número &d\n”,i); } void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data) { (void)CNET_set_handler(EV_TIMER3,timeouts,0); for ( i = 1 ; i<0 10 ; ++i) (void)CNET_start_timer(EV_TIMER3, i*1000L,(CnetData) i); } que producirá una salida idéntica al fragmento de código: void timeouts(CnetEvent ev, CnetTimer timer, CnetData data) { int i = (int) data; printf(“ciclo número &d\n”,i); if ( i < 10 ) (void) CNET_start_timer(EV_TIMER3, 1000L, (CnetData) i + 1); } void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data) { (void)CNET_set_handler(EV_TIMER3,timeouts,0); (void)CNET_start_timer(EV_TIMER3, 1000L,(CnetData) 1); } 5.3.2. Funciones CnetTimer CNET_start_timer ( CnetEvent ev, long msec, CnetData data ) ; Con esta función se establece un nuevo temporizador, cuyo tiempo de expiración será el indicado por el parámetro msec (indicado en milisegundos). El temporizador vendrá referido a una de las 10 colas de temporizador proporcionadas por Cnet, mediante el uso del parámetro ev, donde de establece dicha cola de temporizador EV_TIMER1...EV_TIMER10, y el evento asociado. El parámetro data se utiliza para pasar alguna información a la función manejada por el evento asociado al temporizador. La función devuelve la referencia al temporizador creado, que lo distingue del resto de temporizadores, y que se deberá utilizar para posteriores llamadas a este temporizador, como por ejemplo, para visualizar el valor de temporización o para pararlo. Si el sistema no puede crear el temporizador, devuelve NULLTIMER. Posibles errores: ER_BADARG. __________________________ Página: 18 int CNET_stop_timer ( CnetTimer timer ) ; Se utiliza esta función para parar un temporizador que previamente haya sido activado, y por supuesto, no haya expirado. Como parámetro se pasa la referencia obtenida con la función CNET_start_timer(). Posibles errores: ER_BADTIMER. int CNET_timer_data ( CNETTIMER timer, CNETDATA *data ) ; Esta función permite recuperar el valor que se le pasó al temporizador (timer) a través del parámetro Data. El temporizador no es cancelado y continua su ejecución normal. Posibles errores: ER_BADTIMER, ER_BADARG. 5.4. Funciones para el manejo de eventos int CNET_set_handler ( CnetEvent ev, void (*func)(), CnetData data ) ; Registra func como la función o procedimiento a ejecutar una vez se ha generado el evento ev. Posibles errores: ER_BADEVENT, ER_NOTSUPPORTED. int CNET_get_handler ( CnetEvent ev, void (**handler)(), CnetData *data ) ; Obtiene la dirección de la función que se ha registrado con el evento ev, para que se ejecute una vez ocurre dicho evento, junto con los datos de usuarios que se pasarán al manejador de eventos. Posibles errores: ER_BADEVENT, ER_NOTSUPPORTED. 5.5. Funciones para traceado int CNET_trace ( const char *, …); int CNET_trace_name ( void *addr, const char *name ); int CNET_set_trace (int eventmask ); int CNET_get_trace ( void ); 5.6. Funciones para detección de errores Para todas las funciones, acepta una posición de memoria unsigned char *addr y chequea el algoritmo de detección de errores para una longitud de bytes establecida en nbytes. Int checksum_internet ( unsigned short *addr, int nbytes ) unsigned short checksum_ccitt ( unsigned char *addr, int nbytes ) unsigned short checksum_crc16 ( unsigned char *addr, int nbytes ) unsigned short checksum_crc32 ( unsigned char *addr, int nbytes ) __________________________ Página: 19 5.7. Funciones varias Int CNET_read_keyboard (char *line, int *len ) Lee a través de teclado una cadena de longitud len, y guarda el contenido en *line. Devuelve el nº de bytes que han sido guardados en *line, que contendrá, al retorno, una cadena, terminada en NULL, y len contendrá strlen(line) + 1. Posibles errores: ER_BADSIZE, ER_NOTREADY, ER_NOTSUPPORTED. Int CNET_set_debug_string ( CnetEvent ev, char *str ) Cambia el mensaje del botón de debug (para EV_DEBUG1..EV_DEBUG5) a la cadena str. Si str es NULL o cadena vacía, entonces elimina el botón. Posibles errores: ER_BADEVENT. Int CNET_set_set_time_of_day ( long newsec, long newms ) __________________________ Página: 20 6. Compilación La operación de compilación consiste en construir y ejecutar una aplicación de simulación a partir de los ficheros fuentes. Los ficheros fuentes de Cnet son, básicamente: fichero de topología y fichero de protocolo de usuario (fichero ANSI-C). En la practica, es posible que sólo sea necesario especificar el fichero de topología, ya que éste deberá contener la descripción del fichero de protocolo a utilizar. La compilación de la aplicación se realiza en un terminal del sistema operativo, tanto en modo gráfico en modo carácter (ASCII). Dependiendo de las necesidades y los requisitos de la aplicación de simulación, Cnet proporciona una serie de opciones en la línea de comandos, específicos para diferentes tareas. En la figura 5 se observa el resultado de $ cnet en el terminal, dando como resultado, la lista de todas las opciones de la línea de comandos disponibles, y su explicación: Figura 5. Ejemplo de arranque de Cnet sin argumentos. -A <string> Especifica una ‘cadena de compilación’ donde se declara una nueva Capa Aplicación que será utilizada en la simulación. Por defecto, si no se especifica la opción –A, Cnet utiliza su Capa Aplicación interna. La Capa Aplicación que se utilice, ya sea la definida por defecto o bien una suministrada por el usuario, es utilizada tanto como fuente de mensajes (nodo origen) como sumidero o destino de mensajes (nodo destino). __________________________ Página: 21 -c Al iniciar Cnet, por defecto, cada nodo tiene un valor time_of_day (reloj) diferente al resto de los nodos. Si se especifica la opción –c, el reloj de todos los nodos se sincroniza en el inicio de la simulación. -C <string> Cadena que especifica el fichero de protocolo que utilizará cada nodo. Si no se especifica la opción –C, se supone por defecto la cadena “protocol.c”. -d Proporciona información de monitorización y diagnóstico al inicio la ejecución de Cnet. -e Las tramas pueden sufrir alteraciones u otras anomalías desde que son emitidas por el nodo origen y alcanzan el nodo destino. Las tramas erróneas no son detectadas por la Capa Física, y deben de ser detectado capas superiores. Si se especifica la opción –e, la función CNET_read_physical() detectará y comunicará la presencia de tramas erróneas, devolviendo el valor –1 , y estableciendo Cnet_errno a ER_CORRUPTDATA. -E <nevents> Petición de que Cnet sólo ejecute un determinado número de eventos. -f <secs> Establece la secuencia (en segundos) de refresco en el resumen de diagnóstico y estadístico proporcionado por Cnet. Se puede utilizar junto con las opciones –s y –z , de forma que se pueden proporcionar resultados acumulados estadísticos, de forma periódica. -F <file> Si Cnet ha sido compilado para ejecutarse bajo Tcl/Tk, entonces ‘file’ será suministrado por el intérprete Tcl. Si no se puede encontrar el fichero directamente en el directorio de trabajo, entonces se utilizará CNETPATH para buscar en otra ruta. -g Indica que se inicie la ejecución de la simulación tan pronto como la ventana principal aparezca, evidentemente, bajo entorno X-windows (gráfico). -k Utiliza el estilo antiguo especificado por Kernighan and Ritchie (K&R) C, para compilar los ficheros fuentes de usuario para la Capa Aplicación (-A), los protocolos de capas intermedias (C) y la Capa Física (-P). Por defecto, Cnet utiliza el compilador ANSI-C, gcc. -m <mins> Por defecto, el límite de tiempo de simulación está establecido en 3 minutos, para evitar una sobrecarga innecesaria de las máquinas de simulación. Con la opción –m se puede modificar el tiempo de simulación preestablecido. __________________________ Página: 22 -M <mins> Límite de la longitud de simulación a -M minutos de ‘tiempo simulado’. Esta opción se utiliza en combinación con –T. -n Esta opción indica a Cnet que analice el fichero de topología, compile y linke el código C necesario y termine, sin realizar la simulación. -N Proporciona el nº de nodos de la red en la variable C denominada NNODES. Hay que destacar que por defecto, cada nodo no conoce de cuantos nodos está formada la red, esto es, NNODES = 0. -o <prefijo> Todas las salidas de cada por el dispositivo estándar, esto es, printf(), puts() y putchar() las redirecciona a un fichero ASCII identificado por ‘prefijo’. Por ejemplo, si la red está formada por los nodos con nombres: nodo-1 y nodo-2, y se establece –o out, entonces, la salida de dichos nodos se redireccionará a los ficheros out.nodo-1 y out.nodo-2. -O Abre todas las ventanas de los nodos al iniciar la simulación. -P Con esta opción, se le indica a Cnet que únicamente construya y chequeo la coherencia de la topología de la red, imprime el resultado y termina. -P <string> Mediante –P <string>, se le especifica a Cnet que utiliza una nueva Capa Física. Si no se especifica la opción –P, se utiliza la Capa Física por defecto. El uso de alguna Capa Física específica se suele utilizar para enviar y chequear tramas erróneos, e incluso, pérdidas de tramas. -q Indica a Cnet que realice la ejecución ‘en silencio’, esto es, eliminando todas las salidas hacia el dispositivo de salida por defecto, esto es, elimina las instrucciones printf(), puts() y putchar(). Únicamente se mantienen las salidas producidas durante un evento EV_DEBUG? (botón) y las salidas hacia ficheros. -r <nnodes> Indica que se genere una red aleatoria, formada por nnodos. La generación aleatoria garantiza que la red es totalmente conectada. También se puede establecer la opción –r para proporcionar un fichero de topología. -R <función> __________________________ Página: 23 Especifica que se utiliza la función() como la primera función que se ejecuta cuando se reinicia cada nodo. Por defecto, se utiliza la función reboot_node(). -s Imprime un resumen de la actividad de la red justo antes de terminar Cnet. -S <seed> Proporciona la semilla para la generación de números aleatorios (utilizada para la generación de mensajes y tramas erróneas). La semilla debe ser un número entero. -t Representa todos los eventos generados por cada nodo de la red. Se envía al dispositivo estándar error, una descripción de las llamadas a las funciones, argumentos, retorno de las funciones, así como el valor cnet_errno. -T Por defecto, Cnet se ejecuta en ‘tiempo real’, esto es, el tiempo de simulación en la red es igual al tiempo real, una unidad de tiempo en la simulación es igual a una unidad de tiempo en la realidad. Esta especificación funciona bien para topologías en torno a los 20 nodos. Utilizando –T se obliga a Cnet a ignorar el Tiempo Real y se ejecuta como un simulador de Eventos Discretos Real, esto es, utilizando sus propias unidades de tiempo. -v Indica que utiliza un reporte de información ampliado de las acciones de Cnet. -X Deshabilita el soporte para X-windows (por defecto, se utilizan terminales ASCII). -z Visualiza estadísticas y resúmenes de eventos, incluso si los valores son 0. __________________________ Página: 24 7. Tipos de Nodo, Eventos y Errores 7.1. Tipo CnetNodeType Los nodos pueden ser Host o Router. El tipo de un nodo se puede determinar examinando el valor de nodeinfo.nodetype por ejemplo: if (nodeinfo.nodetype == NT_HOST) (void)CNET_set_handler(EV_APPLICATIONREADY,appl_ready,0); CnetNodeType Descripción NT_HOST El nodo es un Host, CON Capa Aplicación y Keyboard NT_ROUTER El nodo es un Router SIN Capa Aplicación ni Keyboard. IMPORTANTE: Las siguientes funciones sólo serán válidas para nodos del tipo NT_HOST: CNET_write_application(), CNET_read_application(),CNET_enable_application(), CNET_disable_application(), CNET_set_handler(EV_APPLICATIONLAYER,…) y CNET_set_hander(EV_KEYBOARDREADY,…). 7.2. Tipo CnetEvent Ya se ha visto en el Punto 3. __________________________ Página: 25 7.3. Tipo CnetError La mayoría de las funciones de la librería Cnet devuelven 0 para indicar no-error, o un valor –1 indicando error. La mayoría de los errores están recogidos en la variable global cnet_errno. Todos los valores de cnet_errno son una instancia del tipo enumerado CnetError. Los errores pueden ser reportados a stderr con cnet_perror() y acceder al texto del mensaje con el índice *cnet_errstr[] en la función (int) cnet_errno. Por ejemplo: If (CNET_write_application(msgbuffer, &msglength) != 0 ) { /* ha sucedido un error */ if (cnet_errno == ER_BADSESSION ) { /* hacer acciones oportunas */ .... } else { cnet_perror(“error escribiendo a Aplicación”); } } CnetError Descripción ER_OK No error ER_BADARG Argumento inválido ER_BADEVENT Evento inválido ER_BADLINK Número de link no válido ER_BADNODE Nodo no válido ER_BADSENDER Aplicación recibe mensaje procedente de nodo desconocido ER_BADSESSION Aplicación recibe mensaje procedente de sesión incorrecta ER_BADSIZE Longitud indicada no coincide con el tamaño ER_BADTIMER Temporizador inválido ER_CORRUPTDATA Intentando transmitir datos estropeados ER_LINKDOWN Intentando transmitir por un link que está down. ER_NOTFORME Aplicación recibe mensaje para dirigido a otro nodo ER_NOTREADY Servicio no disponible ER_NOTSUPPORTED Operación no válida para este tipo de nodo ER_OUTOFSEQ Aplicación recibe mensaje fuera de secuencia ER_TOOBUSY Link demasiado ocupado/congestionado 8. Información adicional Se puede obtener información adicional, así como descargar los fuentes del simulador y material auxiliar, en la página del profesor Dr. Chris Mcdonald. www.cs.uwa.edu.au/cnet/ __________________________ Página: 26