+===============================
+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 :