From: Leandro Lucarella Date: Sun, 28 May 2006 18:45:52 +0000 (+0000) Subject: Base del TP de IP de distribuidos. X-Git-Tag: svn_import~76 X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/commitdiff_plain/3de68addc94548e2191d83b7aa4ebec21957391e?ds=sidebyside Base del TP de IP de distribuidos. --- diff --git a/practicas/pipi/ENUNCIADO b/practicas/pipi/ENUNCIADO new file mode 100644 index 0000000..cfd611c --- /dev/null +++ b/practicas/pipi/ENUNCIADO @@ -0,0 +1,41 @@ +Enunciado extraoficial + +Hay que hacer 2 procesos, uno que manda y otro que recibe IP, por cada +host/router. Todos los procesos que envian, ponen las cosas en una cola, todos +los que reciben, sacan de esa cola. Se usa como MAC la IP, y como ID del mensaje +de la cola (de esta manera cada proceso saca solo los "paquetes" con el ID/MAC +que le corresponda). + +1) Campos en IP + id de paquete + ip origen + ip destino + checksum (0/1, de juguete) + tamaño del paquete completo + ToS + Don't Fragment (0/1) + End (0/1) + offset + TTL + tamaño de este fragmento + tipo de payload (IP / ICMP) + (se que faltan algunos, si tienen algo mas, + completen) + +2) Casos de descarte de paquetes + Error de checksum (silencioso) + No hay buffer para fragmento (silencioso) + Un host que no rutea recibe un paquete para otro host + (silencioso) + No hay ruta (icmp) + DF == 1 y MTU < size (icmp) + TTL == 0 (icmp) + +3) Comportamiento del protocolo + Debe rutear (si es un router) + Debe fragmentar y reensamblar + Debe contemplar todos los casos de descarte de + paquetes anteriores escribiendo en un archivo + los paquetes descartados según corresponda + (silecioso, icmp). + diff --git a/practicas/pipi/src/Makefile b/practicas/pipi/src/Makefile new file mode 100644 index 0000000..aa8d258 --- /dev/null +++ b/practicas/pipi/src/Makefile @@ -0,0 +1,98 @@ +# Makefile de ejemplo para C++ +# +# Creado: jue abr 15 15:34:19 ART 2004 +# +# Copyleft 2004 - Leandro Lucarella, Bajo licencia GPL [http://www.gnu.org/] +# + +# CONFIGURACION +################ + +# Opciones para el compilador C/C++ en modo ansi. +CFLAGS = -Wall -ansi -pedantic-errors + +# Para que explote lo mas posible +#CFLAGS += -O3 -DNDEBUG + +# Para valgrind o debug +CFLAGS += -ggdb -DDEBUG + +# Opciones para el compilador C++. +CXXFLAGS = $(CFLAGS) -fno-inline + +# Opciones del enlazador. +#LDFLAGS= + +# Compilador. +CC=g++ + +# Programas +targets=test_send test_recv + +# Fuentes +fuentes ?= $(wildcard *.cpp) + + +# REGLAS +######### + +.PHONY: all clean + +all: $(targets) + +test_send: test_send.o media.o + +test_recv: test_recv.o media.o + +depend: + makedepend $(fuentes) + +clean: + @$(RM) -fv *.o $(targets) + +# DO NOT DELETE + +media.o: media.h frame.h /usr/include/unistd.h /usr/include/features.h +media.o: /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h +media.o: /usr/include/bits/posix_opt.h /usr/include/bits/types.h +media.o: /usr/include/bits/wordsize.h /usr/include/bits/typesizes.h +media.o: /usr/include/bits/confname.h /usr/include/getopt.h +media.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h +media.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h +media.o: /usr/include/bits/endian.h /usr/include/sys/select.h +media.o: /usr/include/bits/select.h /usr/include/bits/sigset.h +media.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h +media.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h +media.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h +media.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h +media.o: /usr/include/bits/msq.h +test_recv.o: ethernetframe.h frame.h media.h /usr/include/unistd.h +test_recv.o: /usr/include/features.h /usr/include/sys/cdefs.h +test_recv.o: /usr/include/gnu/stubs.h /usr/include/bits/posix_opt.h +test_recv.o: /usr/include/bits/types.h /usr/include/bits/wordsize.h +test_recv.o: /usr/include/bits/typesizes.h /usr/include/bits/confname.h +test_recv.o: /usr/include/getopt.h /usr/include/fcntl.h +test_recv.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h +test_recv.o: /usr/include/time.h /usr/include/endian.h +test_recv.o: /usr/include/bits/endian.h /usr/include/sys/select.h +test_recv.o: /usr/include/bits/select.h /usr/include/bits/sigset.h +test_recv.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h +test_recv.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h +test_recv.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h +test_recv.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h +test_recv.o: /usr/include/bits/msq.h dev.h +test_send.o: ethernetframe.h frame.h media.h /usr/include/unistd.h +test_send.o: /usr/include/features.h /usr/include/sys/cdefs.h +test_send.o: /usr/include/gnu/stubs.h /usr/include/bits/posix_opt.h +test_send.o: /usr/include/bits/types.h /usr/include/bits/wordsize.h +test_send.o: /usr/include/bits/typesizes.h /usr/include/bits/confname.h +test_send.o: /usr/include/getopt.h /usr/include/fcntl.h +test_send.o: /usr/include/bits/fcntl.h /usr/include/sys/types.h +test_send.o: /usr/include/time.h /usr/include/endian.h +test_send.o: /usr/include/bits/endian.h /usr/include/sys/select.h +test_send.o: /usr/include/bits/select.h /usr/include/bits/sigset.h +test_send.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h +test_send.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h +test_send.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h +test_send.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h +test_send.o: /usr/include/bits/msq.h dev.h diff --git a/practicas/pipi/src/dev.h b/practicas/pipi/src/dev.h new file mode 100644 index 0000000..d0acea6 --- /dev/null +++ b/practicas/pipi/src/dev.h @@ -0,0 +1,40 @@ +#ifndef _DEV_H_ +#define _DEV_H_ + +#include "frame.h" +#include "media.h" +#include + +/// Dispositivo de red (capa de enlace) +struct Dev +{ + + /// Dirección MAC + Frame::mac_type mac; + + /// Medio físico + Media& media; + + /// Constructor + Dev(const Frame::mac_type& mac, Media& media): + mac(mac), media(media) + {} + + /// Envía un frame + void send(const Frame& frame) throw (std::runtime_error) + { media.transmit(frame); } + + /// Recibe un frame + void recv(Frame& frame) throw (std::runtime_error) + { media.receive(frame); } + + // Nada de andar copiando placas... + private: + Dev(const Dev&); + Dev& operator=(const Dev&); + +}; + +#endif // _DEV_H_ + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/ethernetframe.h b/practicas/pipi/src/ethernetframe.h new file mode 100644 index 0000000..1205202 --- /dev/null +++ b/practicas/pipi/src/ethernetframe.h @@ -0,0 +1,61 @@ +#ifndef _ETHERNETFRAME_H_ +#define _ETHERNETFRAME_H_ + +#include "frame.h" +#include +#include + +/// Frame de la capa física (en este caso es un mensaje enviado a una cola) +template < size_t Size = 1500 > +struct EthernetFrame: Frame +{ + + // Atributos + mac_type _mac; + size_t _len; + char _frame[Size]; + + /// Constructor + EthernetFrame(const mac_type& mac): + _mac(mac) + {} + + /// Constructor + EthernetFrame(const mac_type& mac, const std::string& d) + throw (std::logic_error): _mac(mac) + { data(d); } + + /// Setea MAC + void mac(const mac_type& mac) + { _mac = mac; } + + /// Obtiene MAC + mac_type mac() const + { return _mac; } + + /// Obtiene longitud + size_t len() const + { return _len; } + + /// Obtiene tamaño + size_t size() const + { return Size; } + + /// Setea datos + void data(const std::string& d) throw (std::logic_error) + { + if (d.size() > Size) + throw std::logic_error("dato más grande que el frame"); + _len = d.size(); + memcpy(_frame, d.c_str(), _len); + } + + /// Obtiene datos + std::string data() const + { return _frame; } + +}; + +#endif // _ETHERNETFRAME_H_ + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/frame.h b/practicas/pipi/src/frame.h new file mode 100644 index 0000000..1e5fe99 --- /dev/null +++ b/practicas/pipi/src/frame.h @@ -0,0 +1,38 @@ +#ifndef _FRAME_H_ +#define _FRAME_H_ + +#include + +/// Frame de la capa física (en este caso es un mensaje enviado a una cola) +struct Frame +{ + + // Tipos + typedef long mac_type; + + /// Destructor + virtual ~Frame() {} + + /// Setea MAC + virtual void mac(const mac_type& mac) = 0; + + /// Obtiene MAC + virtual mac_type mac() const = 0; + + /// Obtiene la longitud real del frame + virtual size_t len() const = 0; + + /// Obtiene el tamaño máximo del frame (MTU) + virtual size_t size() const = 0; + + /// Setea datos + virtual void data(const std::string& data) = 0; + + /// Obtiene datos + virtual std::string data() const = 0; + +}; + +#endif // _FRAME_H_ + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/media.cpp b/practicas/pipi/src/media.cpp new file mode 100644 index 0000000..5a3077e --- /dev/null +++ b/practicas/pipi/src/media.cpp @@ -0,0 +1,25 @@ +#include "media.h" +#include + +Media::Media(key_t key) throw (std::runtime_error) +{ + que_id = msgget(key, 0666); // Debe estar previamente creada + if (que_id == -1) + throw std::runtime_error("No se pudo crear la cola"); +} + +void Media::transmit(const Frame& frame) +{ + std::cout << "tx -> msgtype = " << *(((int*)&frame)+1) << "\n"; + if (msgsnd(que_id, ((int*)&frame)+1, frame.size(), 0) == -1) + throw std::runtime_error("Error al poner en la cola"); +} + +void Media::receive(Frame& frame) +{ + std::cout << "rx -> msgtype = " << *(((int*)&frame)+1) << "\n"; + if (msgrcv(que_id, ((int*)&frame)+1, frame.size(), frame.mac(), 0) == -1) + throw std::runtime_error("Error al sacar de la cola"); +} + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/media.h b/practicas/pipi/src/media.h new file mode 100644 index 0000000..c679812 --- /dev/null +++ b/practicas/pipi/src/media.h @@ -0,0 +1,38 @@ +#ifndef _MEDIA_H_ +#define _MEDIA_H_ + +#include "frame.h" +#include +#include +#include +#include +#include +#include +#include + +/// Medio (o capa física + enlace), +struct Media +{ + + /// Identificador de la cola a usar + int que_id; + + /// Constructor + Media(key_t key) throw (std::runtime_error); + + /// Envía un frame + void transmit(const Frame& frame); + + /// Recibe un frame + void receive(Frame& frame); + + // Nada de andar copiando cables... + private: + Media(const Media&); + Media& operator=(const Media&); + +}; + +#endif // _MEDIA_H_ + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/test_recv.cpp b/practicas/pipi/src/test_recv.cpp new file mode 100644 index 0000000..b77b5f8 --- /dev/null +++ b/practicas/pipi/src/test_recv.cpp @@ -0,0 +1,28 @@ + +#include "ethernetframe.h" +#include "media.h" +#include "dev.h" +#include +#include +#include +#include +#include +#include + +int main() +{ + Media media(0xabcdef); + Dev dev(1234, media); + struct msqid_ds minfo; + for (msgctl(media.que_id, IPC_STAT, &minfo); minfo.msg_qnum; + msgctl(media.que_id, IPC_STAT, &minfo)) + { + std::cout << "Quedan " << minfo.msg_qnum << " mensajes en la cola\n"; + EthernetFrame<1500> f(1234); + dev.recv(f); + std::cout << f._mac << " " << f._len << " " << f._frame << "\n"; + } + return 0; +} + +// vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/test_send.cpp b/practicas/pipi/src/test_send.cpp new file mode 100644 index 0000000..559ad8c --- /dev/null +++ b/practicas/pipi/src/test_send.cpp @@ -0,0 +1,20 @@ + +#include "ethernetframe.h" +#include "media.h" +#include "dev.h" +#include +#include + +int main() +{ + int que_id = msgget(0xabcdef, IPC_CREAT | 0666); + assert(que_id != -1); + Media media(0xabcdef); + Dev dev(1234, media); + EthernetFrame<1500> f(1234, "hola mundo"); + dev.send(f); + std::cout << "Enviado '" << f._frame << "' a " << f._mac << "\n"; + return 0; +} + +// vim: set et sw=4 sts=4 :