From 51f24d14e8c4c52776a98c8e2aaacf95f90ad1f4 Mon Sep 17 00:00:00 2001 From: Leandro Lucarella Date: Thu, 1 Jun 2006 21:20:57 +0000 Subject: [PATCH] Ya estamos fragmentando! (falta testing intensivo pero parece andar) --- practicas/pipi/src/ipin.cpp | 23 +++++++++++++++++------ practicas/pipi/src/ipin.h | 19 ++++++++++++++++++- practicas/pipi/src/ipout.cpp | 30 ++++++++++++++++++++++-------- practicas/pipi/src/test_ipout.cpp | 2 +- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/practicas/pipi/src/ipin.cpp b/practicas/pipi/src/ipin.cpp index b5d346f..2d94158 100644 --- a/practicas/pipi/src/ipin.cpp +++ b/practicas/pipi/src/ipin.cpp @@ -43,21 +43,32 @@ 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) + //TODO forwarding (ponerlo en una cola para el proceso que manda) if (iph.dst != ip) { drop("No es para nosotros y no hacemos forward", iph); continue; } - //TODO a un buffer - if (iph.proto != proto) - { - drop("No es el protocolo pedido", iph); + // Guarda en buffer + buffer[iph][iph.offset] = buf.substr(iph.header_len()); + // Si tiene más fragmentos o es un protocolo distinto, sigo + if (iph.mf || (iph.proto != proto)) continue; + // No hay más fragmentos, reensamblamos (de ser necesario) + std::string data; + for (offsetmap_type::iterator i = buffer[iph].begin(); + i != buffer[iph].end(); ++i) + { + //TODO chequear que los fragmentos estén todos + data += i->second; } +#ifdef DEBUG + log << "IPIn::recv: Paquete completo: data = '" << data << "'\n"; +#endif + buffer.erase(iph); + //TODO faltaría limpiar fragmentos viejos cada tanto (timer?) src = iph.src; dst = iph.dst; - std::string data = buf.substr(iph.header_len()); return data; } } diff --git a/practicas/pipi/src/ipin.h b/practicas/pipi/src/ipin.h index 2c86191..5d0d7a8 100644 --- a/practicas/pipi/src/ipin.h +++ b/practicas/pipi/src/ipin.h @@ -4,8 +4,9 @@ #include "ipaddr.h" #include "ipheader.h" #include "dev.h" -#include +#include #include +#include #include /// IP de recepción @@ -21,6 +22,22 @@ struct IPIn /// Dispositivo de logging std::ostream& log; + /// Buffers de recepción + struct BufferKey + { + uint16_t id; + uint32_t src, dst; + uint8_t proto; + BufferKey(const IPHeader& h): + id(h.id), src(h.src), dst(h.dst), proto(h.proto) + {} + bool operator< (const BufferKey& b) const + { return id < b.id && src < b.src && dst < b.dst && proto < b.proto; } + }; + typedef std::map< uint16_t, std::string > offsetmap_type; + typedef std::map< BufferKey, offsetmap_type > buffer_type; + buffer_type buffer; + /// Constructor IPIn(const IPAddr& ip, Dev& dev, std::ostream& log = std::cout); diff --git a/practicas/pipi/src/ipout.cpp b/practicas/pipi/src/ipout.cpp index fb60ffd..d673f8d 100644 --- a/practicas/pipi/src/ipout.cpp +++ b/practicas/pipi/src/ipout.cpp @@ -23,10 +23,10 @@ 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) { - // TODO fragmentar - if (IPHeader::header_len() + data.size() > dev.mtu) + // No quieren fragmentar + if (df && (IPHeader::header_len() + data.size() > dev.mtu)) { - drop("Tamaño de paquete más grande que MTU", data); + drop("Tamaño de paquete más grande que MTU y DF=1", data); return false; } if (!src) @@ -35,13 +35,27 @@ 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); - std::string buf((char*) &iph, sizeof(IPHeader)); - buf += data; + // Fragmenta (de ser necesario) + int max_payload = dev.mtu - IPHeader::header_len(); + int cant_frag = data.size() / max_payload; + if (data.size() % max_payload) + ++cant_frag; + for (int i = 0; i < cant_frag; ++i) + { + IPHeader iph2 = iph; + if (i != (cant_frag - 1)) + iph2.mf = 1; + iph2.offset += i * max_payload; + iph2.total_len -= i * max_payload; + iph2.do_checksum(); + std::string buf((char*) &iph2, sizeof(IPHeader)); + buf += data.substr(i * max_payload, max_payload); #ifdef DEBUG - log << "IPOut::send: IPHeader: " << iph << "\n"; - log << "IPOut::send: buf = " << buf << "\n"; + log << "IPOut::send: Fragmento 0 => IPHeader: " << iph2 << "\n"; + log << "\tbuf (" << buf.size() << ") = " << buf << "\n"; #endif - dev.transmit(buf, dst /*TODO rutear */); + dev.transmit(buf, dst); + } return true; } diff --git a/practicas/pipi/src/test_ipout.cpp b/practicas/pipi/src/test_ipout.cpp index dff222a..e7eb964 100644 --- a/practicas/pipi/src/test_ipout.cpp +++ b/practicas/pipi/src/test_ipout.cpp @@ -15,7 +15,7 @@ int main() int que_id = msgget(DEV_DEFAULT_KEY, IPC_CREAT | 0666); assert(que_id != -1); IPAddr addr("10.10.10.2"); - Dev dev(addr); + Dev dev(addr, 25); IPOut ipout(addr, dev); if (ipout.send("hola mundo", 0, IPAddr("10.10.10.1"))) std::cout << "Enviado 'hola mundo' a 10.10.10.1\n"; -- 2.43.0