=============================== 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`. En el directorio `rutas_ejemplo` contiene algunos archivos con descripciones de rutas de ejemplo para correr los programas. Uso === El trabajo tiene 2 programas de prueba principales: `test_ipin` y `test_ipout`, ambos generados en el directorio `src` luego de compilar el código. test_ipin --------- Este programa es el proceso que recibe paquetes IP y los procesa. Uso:: ./test_ipin [ip] [mtu] [router] [forward] [proto] [queue_id] ip IP que utiliza este proceso (default 10.10.10.1) mtu MTU de la capa física de este proceso (default 25) router 0 si es router, 1 si no lo es (default 0) forward 0 si puede hacer forwarding, 1 si no (default 0) proto Protocolo que transporta (default 0) 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`) test_ipout ---------- Este programa es el proceso que envía paquetes IP y rutea. Uso:: ./test_ipout [ip] [dst] [mtu] [routes_file] [proto] [queue_id] ip IP que utiliza este proceso (default 10.10.10.2) dst IP del destino al cual mandar paquetes (default 10.10.10.1) mtu MTU de la capa física de este proceso (default 25) 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) y métrica (todavía no se usa), separados por uno o más espacios o tabs (default `route.txt`) proto Protocolo que transporta (default 0) 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`) 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, 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 * 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 0 * 10.10.10.3 10.10.10.5 0 * 10.10.10.5 0.0.0.0 0 Envía "adios mundo cruel!!!" al host 10.10.10.3:: $ ./test_ipout 10.10.10.1 10.10.10.3 25 ../rutas_ejemplo/route_10.10.10.1.txt Se agregó tabla para 10.10.10.1: gw = 0.0.0.0, metric = 0 Se agregó tabla para 10.10.10.2: gw = 0.0.0.0, metric = 0 Se agregó tabla para 10.10.10.3: gw = 10.10.10.5, metric = 0 Se agregó tabla para 10.10.10.5: gw = 0.0.0.0, metric = 0 adios mundo cruel!!! IPOut::send: Fragmento 0 => IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3 data (5) = adios Dev::transmit(msgtype/mac = 168430085, size = 25) IPOut::send: Fragmento 0 => IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3 data (5) = mund Dev::transmit(msgtype/mac = 168430085, size = 25) IPOut::send: Fragmento 0 => IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3 data (5) = o cru Dev::transmit(msgtype/mac = 168430085, size = 25) IPOut::send: Fragmento 0 => IPHeader: version= total_len=25 id=56121 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=297 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! Dev::transmit(msgtype/mac = 168430085, size = 25) Enviado 'adios mundo cruel!!!' a 10.10.10.3 El proceso test_ipin de este host no tiene relevancia. Router 10.10.10.5 ----------------- Rutas: * 10.10.10.1 0.0.0.0 0 * 10.10.10.3 0.0.0.0 0 * 10.10.10.5 0.0.0.0 0 Recibe el mensaje:: $ ./test_ipin 10.10.10.5 25 1 1 Quedan 4 mensajes en la cola Dev::receive(msgtype/mac = 168430085, size = 25) IPIn::recv: IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3 data (5) = adios Dev::transmit(msgtype/mac = 168430085, size = 25) Dev::receive(msgtype/mac = 168430085, size = 25) IPIn::recv: IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3 data (5) = mund Dev::transmit(msgtype/mac = 168430085, size = 25) Dev::receive(msgtype/mac = 168430085, size = 25) IPIn::recv: IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3 data (5) = o cru Dev::transmit(msgtype/mac = 168430085, size = 25) Dev::receive(msgtype/mac = 168430085, size = 25) IPIn::recv: IPHeader: version= total_len=25 id=56121 DF=0 MF=0 offset=15 TTL=64 proto=0 checksum=297 src=10.10.10.1 dst=10.10.10.3 data (5) = el!!! Dev::transmit(msgtype/mac = 168430085, size = 25) Y lo forwardea (refragmentando porque tiene un MTU más pequeño):: $ ./test_ipout 10.10.10.5 10.10.10.1 23 ../rutas_ejemplo/route_10.10.10.5.txt Se agregó tabla para 10.10.10.1: gw = 0.0.0.0, metric = 0 Se agregó tabla para 10.10.10.2: gw = 0.0.0.0, metric = 0 Se agregó tabla para 10.10.10.3: gw = 0.0.0.0, metric = 0 Se agregó tabla para 10.10.10.5: gw = 0.0.0.0, metric = 0 a IPOut::send: Fragmento 0 => IPHeader: version= total_len=21 id=56140 DF=0 MF=0 offset=0 TTL=64 proto=0 checksum=194 src=10.10.10.5 dst=10.10.10.1 data (1) = a Dev::transmit(msgtype/mac = 168430081, size = 21) Enviado 'a' a 10.10.10.1 a Dev::receive(msgtype/mac = 168430085, size = 25) IPOut::send: A forwardear IPOut::send: Fragmento 0 => IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3 data (3) = adi Dev::transmit(msgtype/mac = 168430083, size = 23) IPOut::send: Fragmento 0 => IPHeader: version= total_len=37 id=56121 DF=0 MF=1 offset=3 TTL=64 proto=0 checksum=217 src=10.10.10.1 dst=10.10.10.3 data (2) = os Dev::transmit(msgtype/mac = 168430083, size = 22) Dev::receive(msgtype/mac = 168430085, size = 25) IPOut::send: A forwardear IPOut::send: Fragmento 0 => IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3 data (3) = mu Dev::transmit(msgtype/mac = 168430083, size = 23) IPOut::send: Fragmento 0 => IPHeader: version= total_len=32 id=56121 DF=0 MF=1 offset=8 TTL=64 proto=0 checksum=252 src=10.10.10.1 dst=10.10.10.3 data (2) = nd Dev::transmit(msgtype/mac = 168430083, size = 22) Dev::receive(msgtype/mac = 168430085, size = 25) IPOut::send: A forwardear IPOut::send: Fragmento 0 => IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3 data (3) = o c Dev::transmit(msgtype/mac = 168430083, size = 23) IPOut::send: Fragmento 0 => IPHeader: version= total_len=27 id=56121 DF=0 MF=1 offset=13 TTL=64 proto=0 checksum=287 src=10.10.10.1 dst=10.10.10.3 data (2) = ru Dev::transmit(msgtype/mac = 168430083, size = 22) Dev::receive(msgtype/mac = 168430085, size = 25) IPOut::send: A forwardear IPOut::send: Fragmento 0 => IPHeader: version= total_len=25 id=56121 DF=0 MF=1 offset=15 TTL=64 proto=0 checksum=301 src=10.10.10.1 dst=10.10.10.3 data (3) = el! Dev::transmit(msgtype/mac = 168430083, size = 23) IPOut::send: Fragmento 0 => IPHeader: version= total_len=22 id=56121 DF=0 MF=0 offset=18 TTL=64 proto=0 checksum=62 src=10.10.10.1 dst=10.10.10.3 data (2) = !! Dev::transmit(msgtype/mac = 168430083, size = 22) IPOut::send: Fragmento 0 => IPHeader: version= total_len=21 id=56147 DF=0 MF=0 offset=0 TTL=64 proto=0 checksum=201 src=10.10.10.5 dst=10.10.10.1 data (1) = a Dev::transmit(msgtype/mac = 168430081, size = 21) Enviado 'a' a 10.10.10.1 (notar que para que haga el forwarding se tuvo que enviar un paquete *dummy* para que busque en la cola de paquetes a forwardear (es un error de diseño que tendré que corregir de alguna forma) Host 10.10.10.3 --------------- Rutas: * 10.10.10.1 10.10.10.5 0 * 10.10.10.3 0.0.0.0 0 * 10.10.10.5 0.0.0.0 0 Finalmente este host recibe todos los fragmentos, reensabla y pasa el paquete completo a la capa superior:: $ ./test_ipin 10.10.10.3 23 Quedan 8 mensajes en la cola Dev::receive(msgtype/mac = 168430083, size = 23) IPIn::recv: IPHeader: version= total_len=40 id=56121 DF=0 MF=1 offset=0 TTL=64 proto=0 checksum=196 src=10.10.10.1 dst=10.10.10.3 data (3) = adi Dev::receive(msgtype/mac = 168430083, size = 22) IPIn::recv: IPHeader: version= total_len=37 id=56121 DF=0 MF=1 offset=3 TTL=64 proto=0 checksum=217 src=10.10.10.1 dst=10.10.10.3 data (2) = os Dev::receive(msgtype/mac = 168430083, size = 23) IPIn::recv: IPHeader: version= total_len=35 id=56121 DF=0 MF=1 offset=5 TTL=64 proto=0 checksum=231 src=10.10.10.1 dst=10.10.10.3 data (3) = mu Dev::receive(msgtype/mac = 168430083, size = 22) IPIn::recv: IPHeader: version= total_len=32 id=56121 DF=0 MF=1 offset=8 TTL=64 proto=0 checksum=252 src=10.10.10.1 dst=10.10.10.3 data (2) = nd Dev::receive(msgtype/mac = 168430083, size = 23) IPIn::recv: IPHeader: version= total_len=30 id=56121 DF=0 MF=1 offset=10 TTL=64 proto=0 checksum=266 src=10.10.10.1 dst=10.10.10.3 data (3) = o c Dev::receive(msgtype/mac = 168430083, size = 22) IPIn::recv: IPHeader: version= total_len=27 id=56121 DF=0 MF=1 offset=13 TTL=64 proto=0 checksum=287 src=10.10.10.1 dst=10.10.10.3 data (2) = ru Dev::receive(msgtype/mac = 168430083, size = 23) IPIn::recv: IPHeader: version= total_len=25 id=56121 DF=0 MF=1 offset=15 TTL=64 proto=0 checksum=301 src=10.10.10.1 dst=10.10.10.3 data (3) = el! Dev::receive(msgtype/mac = 168430083, size = 22) IPIn::recv: IPHeader: version= total_len=22 id=56121 DF=0 MF=0 offset=18 TTL=64 proto=0 checksum=62 src=10.10.10.1 dst=10.10.10.3 data (2) = !! IPIn::recv: Paquete completo: data = 'adios mundo cruel!!!' Recibido 'adios mundo cruel!!!' (len 20) de 10.10.10.1 para 10.10.10.3 (proto = 0) El proceso test_ipout de este host no tiene relevancia. .. vim: filetype=rst :