=============================== Sistemas Distribuidos I (75.74) =============================== ---------------------------- Trabajo práctico de stack IP ---------------------------- :Author: Leandro Lucarella (77891) Organización ============ En el directorio `src` se encuentra el código fuente del trabajo, con su correspondiente `Makefile` para compilarlo tan solo ejecutando `make`. Dentro de este directorio hay también dos scripts de pruebas completas: `test.sh` (con 1 router) y `test2.sh` (con 2 routers). En el directorio `rutas_ejemplo` contiene algunos archivos con descripciones de rutas de ejemplo para correr los programas. Uso === El trabajo consta de un programa llamado `ip` (más algunas otras pruebas que no tiene relevancia). Este programa corre 3 procesos, uno que recibe paquetes IP otro que recibe entrada del usuario y envía paquetes IP y otro que redirecciona (forward) paquetes IP en caso de ser pertinente. Uso:: ./ip ip [router [forward [route_file [queue_id [proto]]]]] ip IP que utiliza este proceso router 0 si es router, 1 si no lo es (default 0) forward 0 si puede hacer forwarding, 1 si no (default 0) route_file Archivo con las rutas. El formato del archivo es una ruta por línea, cada línea se compone de red (por ahora sólo soporta IPs puntuales), gateway (si es cero es que están en la misma red), MTU y métrica (todavía no se usa), separados por uno o más espacios o tabs (default `route.txt`) queue_id Identificador de la cola a usar como medio físico, también establece el identificador de la cola a usar para comunicarse con el otro proceso (`test_ipout`) para hacer forwarding, que será queue_id + 1 (default `DEV_DEFAULT_KEY` obtenido de `dev.h`) proto Protocolo que transporta (default 0) El programa se queda esperando la entrada del usuario, y sale cuando está se termina (Ctrl-D). El formato de entrada es:: IP DESTINO MENSAJE Es decir, en una línea se pone la IP de destino y en la línea siguiente el mensaje. Para enviar otro mensaje, nuevamente se pone IP de destino en una línea y el mensaje en la siguiente. Diseño del trabajo ================== El trabajo fue desarrollado en C++, orientado a objetos. Se compone de las siguientes clases: Dev Encapsula la capa física y el dispositivo de red. Utiliza una cola como medio físico y el id representaría el cable (si 2 dispositivos tienen cola con id distinto serían como si no compartieran el mismo cable). Por simplicidad a la cola siempre se envía el tamaño del MTU completo pero se agrega una cabecera con el tamaño real del frame. IPAddr Clase auxiliar que encapsula una dirección IP. IPHeader Encapsula una cabecera IP. El cálculo de checksum se simplificó (haciendo una suma byte a byte de toda la cabecera) porque cumple con el objetivo didactico de todas maneras. RouteTable Encapsula una tabla de ruteo. Por falta de tiempo y simplicidad por ahora sólo soporta rutas a un sólo host (no a una red) pero es muy fácilmente extensible y transparente para el resto de las clases que la usan. Las rutas se componen de red (en realidad por ahora host), geteway, MTU, metrica y dispositivo de red por el cual salir (Dev). IPIn Es la clase encargada de recibir paquetes IP. Hace chequeos varios y descarta paquetes según los siguientes criterios: * Cabecera incompleta o no es IP * Versión IP incorrecta * Mal checksum * TTL=0 * No es para nosotros y no hacemos forward * Es para nosotros pero somos un router Si hace forwarding le pasa a IPOut el paquete por una cola y reensabla de ser necesario. IPOut Es la clase encargada de enviar paquetes IP. Tiene una RouteTable para hacer el ruteo y verifica si hay paquetes a forwardear antes de enviar lo que le piden. También fragmenta y puede "descartar" paquetes según estos criterios: * No existe una ruta para el destino * Tamaño de paquete más grande que MTU y DF=1 Ejemplo de corrida ================== Host 10.10.10.1 --------------- Rutas: * 10.10.10.1 0.0.0.0 35 0 * 10.10.10.3 10.10.10.5 35 1 * 10.10.10.5 0.0.0.0 35 0 Envía "adios mundo cruel!!!" al host 10.10.10.3:: $ (echo -e '10.10.10.3\nAdios mundo cruel!!!'; sleep 1) | ./ip 10.10.10.1 0 0 ../rutas_ejemplo/route_10.10.10.1.txt IPOut::send (10.10.10.1): Fragmento 0 => IPHeader: version=4 total_len=40 id=44919 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=214 src=10.10.10.1 dst=10.10.10.3 data (15) = Adios mundo cru IPOut::send (10.10.10.1): Fragmento 1 => IPHeader: version=4 total_len=25 id=44919 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=315 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! Enviado 'Adios mundo cruel!!!' a 10.10.10.3 Router 10.10.10.5 ----------------- Rutas: * 10.10.10.1 0.0.0.0 35 0 * 10.10.10.3 0.0.0.0 32 0 * 10.10.10.5 0.0.0.0 35 0 Recibe el mensaje:: $ ./ip 10.10.10.5 1 1 ../rutas_ejemplo/route_10.10.10.5.txt IPIn::recv (10.10.10.5): IPHeader: version=4 total_len=40 id=44919 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=214 src=10.10.10.1 dst=10.10.10.3 data (15) = Adios mundo cru IPIn::recv (10.10.10.5): IPHeader: version=4 total_len=25 id=44919 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=315 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! IPOut::forward_loop (10.10.10.5): A forwardear (id 44919) IPOut::send (10.10.10.5): Fragmento 0 => IPHeader: version=4 total_len=40 id=44919 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=214 src=10.10.10.1 dst=10.10.10.3 data (12) = Adios mundo IPOut::send (10.10.10.5): Fragmento 1 => IPHeader: version=4 total_len=28 id=44919 DF=0 MF=1 offset=12 TTL=64 proto=0 checksum=298 src=10.10.10.1 dst=10.10.10.3 data (3) = cru IPOut::forward_loop (10.10.10.5): A forwardear (id 44919) IPOut::send (10.10.10.5): Fragmento 0 => IPHeader: version=4 total_len=25 id=44919 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=315 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! Host 10.10.10.3 --------------- Rutas: * 10.10.10.1 10.10.10.5 32 1 * 10.10.10.3 0.0.0.0 32 0 * 10.10.10.5 0.0.0.0 32 0 Finalmente este host recibe todos los fragmentos, reensabla y pasa el paquete completo a la capa superior:: $ ./ip 10.10.10.3 0 0 ../rutas_ejemplo/route_10.10.10.3.txt IPIn::recv (10.10.10.3): IPHeader: version=4 total_len=40 id=44919 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=214 src=10.10.10.1 dst=10.10.10.3 data (12) = Adios mundo IPIn::recv (10.10.10.3): IPHeader: version=4 total_len=28 id=44919 DF=0 MF=1 offset=12 TTL=64 proto=0 checksum=298 src=10.10.10.1 dst=10.10.10.3 data (3) = cru IPIn::recv (10.10.10.3): IPHeader: version=4 total_len=25 id=44919 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=315 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! IPIn::recv (10.10.10.3): Paquete completo: data = 'Adios mundo cruel!!!' Recibido 'Adios mundo cruel!!!' (len 20) de 10.10.10.1 para 10.10.10.3 (proto = 0) .. vim: filetype=rst :