From: Leandro Lucarella Date: Fri, 2 Jun 2006 06:06:37 +0000 (+0000) Subject: Forwarding casi implementado. Hay un bug cuando se usan distintos MTU que hay X-Git-Tag: svn_import~60 X-Git-Url: https://git.llucax.com/z.facultad/75.74/practicos.git/commitdiff_plain/093ef819f410add240cf97b72f9e7dcab5abd16c Forwarding casi implementado. Hay un bug cuando se usan distintos MTU que hay que resolver. Probablemente venga por un problema con la cola que se usa para pasar los paquetes a forwardear de un proceso a otro (IPIn a IPOut). --- diff --git a/practicas/pipi/rutas_ejemplo/route.txt b/practicas/pipi/rutas_ejemplo/route.txt new file mode 100644 index 0000000..3aae5e1 --- /dev/null +++ b/practicas/pipi/rutas_ejemplo/route.txt @@ -0,0 +1,3 @@ +10.10.10.1 0.0.0.0 0 +10.10.10.2 0.0.0.0 0 +10.10.10.3 10.10.10.5 0 diff --git a/practicas/pipi/rutas_ejemplo/route_10.10.10.1.txt b/practicas/pipi/rutas_ejemplo/route_10.10.10.1.txt new file mode 100644 index 0000000..cc877c8 --- /dev/null +++ b/practicas/pipi/rutas_ejemplo/route_10.10.10.1.txt @@ -0,0 +1,4 @@ +10.10.10.1 0.0.0.0 0 +10.10.10.2 0.0.0.0 0 +10.10.10.3 10.10.10.5 0 +10.10.10.5 0.0.0.0 0 diff --git a/practicas/pipi/rutas_ejemplo/route_10.10.10.2.txt b/practicas/pipi/rutas_ejemplo/route_10.10.10.2.txt new file mode 100644 index 0000000..cc877c8 --- /dev/null +++ b/practicas/pipi/rutas_ejemplo/route_10.10.10.2.txt @@ -0,0 +1,4 @@ +10.10.10.1 0.0.0.0 0 +10.10.10.2 0.0.0.0 0 +10.10.10.3 10.10.10.5 0 +10.10.10.5 0.0.0.0 0 diff --git a/practicas/pipi/rutas_ejemplo/route_10.10.10.3.txt b/practicas/pipi/rutas_ejemplo/route_10.10.10.3.txt new file mode 100644 index 0000000..11ff580 --- /dev/null +++ b/practicas/pipi/rutas_ejemplo/route_10.10.10.3.txt @@ -0,0 +1,4 @@ +10.10.10.1 10.10.10.5 0 +10.10.10.2 10.10.10.5 0 +10.10.10.3 0.0.0.0 0 +10.10.10.5 0.0.0.0 0 diff --git a/practicas/pipi/rutas_ejemplo/route_10.10.10.5.txt b/practicas/pipi/rutas_ejemplo/route_10.10.10.5.txt new file mode 100644 index 0000000..d57116e --- /dev/null +++ b/practicas/pipi/rutas_ejemplo/route_10.10.10.5.txt @@ -0,0 +1,4 @@ +10.10.10.1 0.0.0.0 0 +10.10.10.2 0.0.0.0 0 +10.10.10.3 0.0.0.0 0 +10.10.10.5 0.0.0.0 0 diff --git a/practicas/pipi/src/Makefile b/practicas/pipi/src/Makefile index a1538a7..58539ef 100644 --- a/practicas/pipi/src/Makefile +++ b/practicas/pipi/src/Makefile @@ -54,7 +54,7 @@ depend: @makedepend $(fuentes) > /dev/null 2>&1 clean: - @$(RM) -fv *.o $(targets) + @$(RM) -fv *.o Makefile.bak $(targets) # DO NOT DELETE @@ -83,6 +83,18 @@ ipout.o: ipout.h ipaddr.h ipheader.h /usr/include/stdint.h ipout.o: /usr/include/features.h /usr/include/sys/cdefs.h ipout.o: /usr/include/gnu/stubs.h /usr/include/bits/wchar.h ipout.o: /usr/include/bits/wordsize.h routetable.h dev.h +ipout.o: /usr/include/unistd.h /usr/include/bits/posix_opt.h +ipout.o: /usr/include/bits/types.h /usr/include/bits/typesizes.h +ipout.o: /usr/include/bits/confname.h /usr/include/getopt.h +ipout.o: /usr/include/fcntl.h /usr/include/bits/fcntl.h +ipout.o: /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h +ipout.o: /usr/include/bits/endian.h /usr/include/sys/select.h +ipout.o: /usr/include/bits/select.h /usr/include/bits/sigset.h +ipout.o: /usr/include/bits/time.h /usr/include/sys/sysmacros.h +ipout.o: /usr/include/bits/pthreadtypes.h /usr/include/bits/sched.h +ipout.o: /usr/include/sys/ipc.h /usr/include/bits/ipctypes.h +ipout.o: /usr/include/bits/ipc.h /usr/include/sys/msg.h +ipout.o: /usr/include/bits/msq.h routetable.o: routetable.h dev.h ipaddr.h test_ipaddr.o: ipaddr.h ipheader.h /usr/include/stdint.h test_ipaddr.o: /usr/include/features.h /usr/include/sys/cdefs.h diff --git a/practicas/pipi/src/ipaddr.cpp b/practicas/pipi/src/ipaddr.cpp index 1cdd573..7b153b2 100644 --- a/practicas/pipi/src/ipaddr.cpp +++ b/practicas/pipi/src/ipaddr.cpp @@ -42,6 +42,12 @@ IPAddr::IPAddr(const char* ip) throw (std::logic_error) } } +/// Constructor +//IPAddr::IPAddr(const std::string& ip) throw (std::logic_error) +//{ +// IPAddr(ip.c_str()); +//} + /// Operador de casteo a unsigned IPAddr::operator unsigned () const { diff --git a/practicas/pipi/src/ipaddr.h b/practicas/pipi/src/ipaddr.h index 19197a1..0c0c549 100644 --- a/practicas/pipi/src/ipaddr.h +++ b/practicas/pipi/src/ipaddr.h @@ -27,6 +27,9 @@ struct IPAddr /// Constructor IPAddr(const char* ip) throw (std::logic_error); + /// Constructor + //IPAddr(const std::string& ip) throw (std::logic_error); + /// Operador de casteo a unsigned operator unsigned () const; diff --git a/practicas/pipi/src/ipin.cpp b/practicas/pipi/src/ipin.cpp index 2d94158..a9029c6 100644 --- a/practicas/pipi/src/ipin.cpp +++ b/practicas/pipi/src/ipin.cpp @@ -3,9 +3,13 @@ #include "ipheader.h" /// Constructor -IPIn::IPIn(const IPAddr& ip, Dev& dev, std::ostream& log): - ip(ip), dev(dev), log(log) -{} +IPIn::IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router, + bool forward, std::ostream& log): + ip(ip), dev(dev), forward_que(forward_que), router(router), + forward(forward), log(log) +{ + if (router) forward = true; +} void IPIn::drop(const std::string& msg, const std::string& buf) { @@ -43,12 +47,25 @@ std::string IPIn::recv(uint8_t proto, IPAddr& src, IPAddr& dst) throw (std::runt drop("Mal checksum", iph); continue; } - //TODO forwarding (ponerlo en una cola para el proceso que manda) - if (iph.dst != ip) + // No es para nosotros y no forwardeamos + if (iph.dst != ip && !forward) { drop("No es para nosotros y no hacemos forward", iph); continue; } + // No es para nosotros pero forwardeamos + else if (iph.dst != ip) + { + forward_que.transmit(buf, ip); + continue; + } + // Es para nosotros pero somos router + else if (router) + { + drop("Es para nosotros pero somos un router", iph); + continue; + } + // Es para nosotros y somos un host // Guarda en buffer buffer[iph][iph.offset] = buf.substr(iph.header_len()); // Si tiene más fragmentos o es un protocolo distinto, sigo diff --git a/practicas/pipi/src/ipin.h b/practicas/pipi/src/ipin.h index 5d0d7a8..8620278 100644 --- a/practicas/pipi/src/ipin.h +++ b/practicas/pipi/src/ipin.h @@ -19,6 +19,15 @@ struct IPIn /// Dispositivo de red Dev& dev; + /// Cola para forwardear paquetes + Dev& forward_que; + + /// Indica si es un router + bool router; + + /// Indica si hace forwarding + bool forward; + /// Dispositivo de logging std::ostream& log; @@ -39,7 +48,8 @@ struct IPIn buffer_type buffer; /// Constructor - IPIn(const IPAddr& ip, Dev& dev, std::ostream& log = std::cout); + IPIn(const IPAddr& ip, Dev& dev, Dev& forward_que, bool router = false, + bool forward = false, std::ostream& log = std::cout); /// Descarta un paquete void drop(const std::string& msg, const std::string& buf); diff --git a/practicas/pipi/src/ipout.cpp b/practicas/pipi/src/ipout.cpp index e7e211b..cf5c28c 100644 --- a/practicas/pipi/src/ipout.cpp +++ b/practicas/pipi/src/ipout.cpp @@ -2,10 +2,15 @@ #include "ipout.h" #include "ipheader.h" #include +#include +#include +#include +#include +#include /// Constructor -IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log): - ip(ip), rtable(rtable), log(log) +IPOut::IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, std::ostream& log): + ip(ip), rtable(rtable), forward_que(forward_que), log(log) { } @@ -24,6 +29,17 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src, bool df, uint8_t ttl, uint16_t id) throw (std::runtime_error) { + // Mando todo lo que tengo para forwardear + while (to_forward()) + { + std::string buf = forward_que.receive(); + IPHeader iph(buf); +#ifdef DEBUG + log << "IPOut::send: A forwardear => IPHeader: " << iph << "\n"; +#endif + send(iph, buf.substr(iph.header_len())); + } + // Mando el paquete en sí // Armamos cabecera if (!src) src = ip; @@ -31,15 +47,21 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src, id = get_id(); IPHeader iph(4, IPHeader::header_len() + data.size(), id, df, 0, 0, ttl, proto, src, dst); + return send(iph, data); +} + +/// Envía un paquete IP +bool IPOut::send(IPHeader iph, std::string data) throw (std::runtime_error) +{ // Buscamos ruta - RouteTable::Route* r = rtable.get(dst); + RouteTable::Route* r = rtable.get(iph.dst); if (!r) { drop("No existe una ruta para el destino", iph); return false; } // No quieren fragmentar - if (df && (IPHeader::header_len() + data.size() > r->iface->mtu)) + if (iph.df && (IPHeader::header_len() + data.size() > r->iface->mtu)) { drop("Tamaño de paquete más grande que MTU y DF=1", iph); return false; @@ -63,7 +85,7 @@ bool IPOut::send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src, log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n"; log << "\tbuf (" << buf.size() << ") = " << buf << "\n"; #endif - r->iface->transmit(buf, r->gateway ? r->gateway : dst); + r->iface->transmit(buf, r->gateway ? r->gateway : IPAddr(iph.dst)); } return true; } @@ -74,4 +96,12 @@ uint16_t IPOut::get_id() const return time(NULL); } +/// Se fija si hay paquetes a forwardear (y devuelve cuantos hay) +unsigned IPOut::to_forward() +{ + struct msqid_ds minfo; + msgctl(forward_que.que_id, IPC_STAT, &minfo); + return minfo.msg_qnum; +} + // vim: set et sw=4 sts=4 : diff --git a/practicas/pipi/src/ipout.h b/practicas/pipi/src/ipout.h index ae88509..effe150 100644 --- a/practicas/pipi/src/ipout.h +++ b/practicas/pipi/src/ipout.h @@ -18,24 +18,34 @@ struct IPOut /// Dispositivo de logging RouteTable& rtable; + /// Cola para forwardear paquetes + Dev& forward_que; + /// Dispositivo de logging std::ostream& log; /// Constructor - IPOut(const IPAddr& ip, RouteTable& rtable, std::ostream& log = std::cout); + IPOut(const IPAddr& ip, RouteTable& rtable, Dev& forward_que, + std::ostream& log = std::cout); /// Descarta un paquete void drop(const std::string& msg, const std::string& buf); void drop(const std::string& msg, const IPHeader& iph); - /// Envía un paquete IP + /// Envía un paquete IP a armar (y forwardea los encolados, de haber) bool send(const std::string& data, uint8_t proto, IPAddr dst, IPAddr src = 0, bool df = 0, uint8_t ttl = 64, uint16_t id = 0) throw (std::runtime_error); + /// Envía un paquete IP ya armado + bool send(IPHeader iph, std::string data) throw (std::runtime_error); + /// Obtiene un identificador para el paquete uint16_t get_id() const; + /// Se fija si hay paquetes a forwardear (y devuelve cuantos hay) + unsigned to_forward(); + // Nada de andar copiando... private: IPOut(const IPOut&); diff --git a/practicas/pipi/src/routetable.cpp b/practicas/pipi/src/routetable.cpp index 66ccd80..4a043cd 100644 --- a/practicas/pipi/src/routetable.cpp +++ b/practicas/pipi/src/routetable.cpp @@ -1,4 +1,7 @@ #include "routetable.h" +#ifdef DEBUG +#include +#endif RouteTable::RouteTable(Dev& default_iface): default_iface(default_iface) { @@ -7,6 +10,10 @@ RouteTable::RouteTable(Dev& default_iface): default_iface(default_iface) void RouteTable::add(const IPAddr& net, const IPAddr& gw, unsigned metric, Dev& iface) { table[net] = Route(gw, metric, iface); +#ifdef DEBUG + std::cout << "Se agregó tabla para " << net << ": gw = " << gw + << ", metric = " << metric << "\n"; +#endif } void RouteTable::del(const IPAddr& net) diff --git a/practicas/pipi/src/test_ipin.cpp b/practicas/pipi/src/test_ipin.cpp index 01b19aa..a3c8e5f 100644 --- a/practicas/pipi/src/test_ipin.cpp +++ b/practicas/pipi/src/test_ipin.cpp @@ -10,12 +10,14 @@ #include #include -// Uso: ./test_ipin ip mtu proto queue_id +// Uso: ./test_ipin ip mtu router forward proto queue_id int main(int argc, char* argv[]) { IPAddr addr("10.10.10.1"); unsigned mtu = 25; + bool router = false; + bool forward = false; unsigned proto = 0; key_t queue_id = DEV_DEFAULT_KEY; if (argc > 1) @@ -23,11 +25,18 @@ int main(int argc, char* argv[]) if (argc > 2) mtu = atoi(argv[2]); if (argc > 3) - proto = atoi(argv[3]); + router = atoi(argv[3]); if (argc > 4) - queue_id = atoi(argv[4]); + forward = atoi(argv[4]); + if (argc > 5) + proto = atoi(argv[5]); + if (argc > 6) + queue_id = atoi(argv[6]); Dev dev(addr, mtu, queue_id); - IPIn ipin(addr, dev); + int que_id = msgget(queue_id+1, IPC_CREAT | 0666); + assert(que_id != -1); + Dev fwque(addr, mtu, queue_id+1); + IPIn ipin(addr, dev, fwque, router, forward); struct msqid_ds minfo; for (msgctl(dev.que_id, IPC_STAT, &minfo); minfo.msg_qnum; msgctl(dev.que_id, IPC_STAT, &minfo)) diff --git a/practicas/pipi/src/test_ipout.cpp b/practicas/pipi/src/test_ipout.cpp index acdb77f..ec4430f 100644 --- a/practicas/pipi/src/test_ipout.cpp +++ b/practicas/pipi/src/test_ipout.cpp @@ -4,6 +4,8 @@ #include "routetable.h" #include "dev.h" #include +#include +#include #include #include #include @@ -12,41 +14,63 @@ #include #include -// Uso: ./test_ipout ip dst msg mtu proto queue_id +// Uso: ./test_ipout ip dst mtu routes_file proto queue_id + +void add_routes(RouteTable& rt, std::istream& is, Dev& dev); int main(int argc, char* argv[]) { IPAddr addr("10.10.10.2"); IPAddr dst("10.10.10.1"); - std::string msg = "hola mundo"; unsigned mtu = 25; unsigned proto = 0; key_t queue_id = DEV_DEFAULT_KEY; + std::string fname = "route.txt"; if (argc > 1) addr = IPAddr(argv[1]); if (argc > 2) dst = IPAddr(argv[2]); if (argc > 3) - msg = argv[3]; + mtu = atoi(argv[3]); if (argc > 4) - mtu = atoi(argv[4]); + fname = argv[4]; if (argc > 5) proto = atoi(argv[5]); if (argc > 6) queue_id = atoi(argv[6]); - int que_id = msgget(queue_id, IPC_CREAT | 0666); - assert(que_id != -1); + int que_id = msgget(queue_id, IPC_CREAT | 0666); assert(que_id != -1); + que_id = msgget(queue_id+1, IPC_CREAT | 0666); assert(que_id != -1); + std::ifstream ifs(fname.c_str()); assert(ifs); Dev dev(addr, mtu, queue_id); + Dev fwque(addr, mtu, queue_id+1); RouteTable table(dev); - table.add("10.10.10.1", 0, 0, dev); - table.add("10.10.10.2", 0, 0, dev); - table.add("10.10.10.3", "10.10.10.10", 0, dev); - IPOut ipout(addr, table); - if (ipout.send(msg, proto, dst)) - std::cout << "Enviado '" << msg << "' a " << dst << "\n"; - else - std::cout << "NO SE PUDO ENVIAR '" << msg << "' a " << dst << "\n"; + add_routes(table, ifs, dev); + IPOut ipout(addr, table, fwque); + std::string msg; + while (std::getline(std::cin, msg)) + { + if (ipout.send(msg, proto, dst)) + std::cout << "Enviado '" << msg << "' a " << dst << "\n"; + else + std::cout << "NO SE PUDO ENVIAR '" << msg << "' a " << dst << "\n"; + } return 0; } +void add_routes(RouteTable& rt, std::istream& is, Dev& dev) +{ + std::string line; + while (std::getline(is, line)) + { + std::istringstream iss(line); + std::string net; + std::string gw; + unsigned metric; + iss >> net >> gw >> metric; + if (net == "0") net = "0.0.0.0"; + if (gw == "0") gw = "0.0.0.0"; + rt.add(net.c_str(), gw.c_str(), metric, dev); + } +} + // vim: set et sw=4 sts=4 :