]> git.llucax.com Git - z.facultad/75.74/practicos.git/commitdiff
Ya estamos fragmentando! (falta testing intensivo pero parece andar)
authorLeandro Lucarella <llucax@gmail.com>
Thu, 1 Jun 2006 21:20:57 +0000 (21:20 +0000)
committerLeandro Lucarella <llucax@gmail.com>
Thu, 1 Jun 2006 21:20:57 +0000 (21:20 +0000)
practicas/pipi/src/ipin.cpp
practicas/pipi/src/ipin.h
practicas/pipi/src/ipout.cpp
practicas/pipi/src/test_ipout.cpp

index b5d346fbf7b831d8c10b95d5939240237b984f23..2d94158fee63e24ba8dac46867d401f19ed9b8c0 100644 (file)
@@ -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;
     }
 }
index 2c86191a5c81e10dda26369566859f9c2f31538d..5d0d7a82cc279b056df1f874bdc475eaa743392f 100644 (file)
@@ -4,8 +4,9 @@
 #include "ipaddr.h"
 #include "ipheader.h"
 #include "dev.h"
-#include <iostream>
+#include <map>
 #include <string>
+#include <iostream>
 #include <stdexcept>
 
 /// 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);
 
index fb60ffd02ba32907187b253e46e29c679b6612d8..d673f8d133cb6c566b6c7f89bcd245a853d8c01e 100644 (file)
@@ -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;
 }
 
index dff222a011a0c951c2602444c185a6eae18f9428..e7eb9641ce03207b3acd9e8496bf86ef716f2068 100644 (file)
@@ -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";