a basic untested ipv4 implementation
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 09 Feb 2007 17:54:49 +0100
changeset 236 5673656dc2e7
parent 235 190d5bef3254
child 237 6562b2679455
a basic untested ipv4 implementation
SConstruct
src/node/ipv4-interface.cc
src/node/ipv4-interface.h
src/node/ipv4-l3-protocol.cc
src/node/ipv4-l3-protocol.h
src/node/ipv4-l4-protocol.h
src/node/ipv4-route.cc
src/node/ipv4-route.h
src/node/l3-protocol.cc
src/node/l3-protocol.h
--- a/SConstruct	Thu Feb 08 16:01:58 2007 +0100
+++ b/SConstruct	Fri Feb 09 17:54:49 2007 +0100
@@ -154,12 +154,16 @@
     'ipv4-header.cc',
     'udp-header.cc',
     'ipv4-checksum.cc',
+    'ipv4-route.cc',
+    'ipv4-interface.cc',
+    'ipv4-l3-protocol.cc',
     ])
 node.add_headers ([
     'ipv4-address.h',
     'ipv4-header.h',
     'udp-header.h',
     'ipv4-checksum.h',
+    'ipv4-l3-protocol.h',
     ])
 node.add_inst_headers ([
     'node.h',
@@ -172,6 +176,8 @@
     'internet-node.h',
     'net-device.h',
     'mac-address.h',
+    'ipv4-route.h',
+    'ipv4-interface.h'
     ])
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-interface.cc	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv4-interface.h"
+#include "ipv4-address.h"
+#include "net-device.h"
+
+namespace ns3 {
+
+  /**
+   * By default, Ipv4 interface are created in the "down" state
+   * with ip address 192.168.0.1 and a matching mask. Before
+   * becoming useable, the user must invoke SetUp on them
+   * once the final Ipv4 address and mask has been set.
+   */
+Ipv4Interface::Ipv4Interface (NetDevice *nd) 
+  : m_netdevice (nd), 
+    m_ifup(false)
+{}
+
+Ipv4Interface::~Ipv4Interface ()
+{}
+
+NetDevice*
+Ipv4Interface::GetDevice (void) const
+{
+  return m_netdevice;
+}
+
+void 
+Ipv4Interface::SetAddress (Ipv4Address a)
+{
+  m_address = a;
+}
+void 
+Ipv4Interface::SetNetworkMask (Ipv4Mask mask)
+{
+  m_netmask = mask;
+}
+
+Ipv4Address
+Ipv4Interface::GetBroadcast (void) const
+{
+  uint32_t mask = m_netmask.GetHostOrder ();
+  uint32_t address = m_address.GetHostOrder ();
+  Ipv4Address broadcast = Ipv4Address (address | (~mask));
+  return broadcast;
+}
+Ipv4Mask 
+Ipv4Interface::GetNetworkMask (void) const
+{
+  return m_netmask;
+}
+Ipv4Address 
+Ipv4Interface::GetAddress (void) const
+{
+  return m_address;
+}
+
+uint16_t 
+Ipv4Interface::GetMtu (void) const
+{
+  if (m_netdevice == 0)
+    {
+      uint32_t mtu = (1<<16) - 1;
+      return mtu;
+    }
+  return m_netdevice->GetMtu ();
+}
+
+  /**
+   * These are IP interface states and may be distinct from 
+   * NetDevice states, such as found in real implementations
+   * (where the device may be down but IP interface state is still up).
+   */
+bool 
+Ipv4Interface::IsUp (void) const
+{
+  return m_ifup;
+}
+
+bool 
+Ipv4Interface::IsDown (void) const
+{
+  return !m_ifup;
+}
+
+void 
+Ipv4Interface::SetUp (void)
+{
+  m_ifup = true;
+}
+
+void 
+Ipv4Interface::SetDown (void)
+{
+  m_ifup = false;
+}
+
+// public wrapper on private virtual function
+void 
+Ipv4Interface::Send(Packet p, Ipv4Address dest)
+{
+  if (IsUp()) {
+    SendTo(p, dest);
+  }
+}
+
+}; // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-interface.h	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: 
+ *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ *  Tom Henderson <tomh@tomh.org>
+ */
+#ifndef IPV4_INTERFACE_H
+#define IPV4_INTERFACE_H
+
+#include <list>
+#include "ipv4-address.h"
+
+namespace ns3 {
+
+class NetDevice;
+class Packet;
+
+/**
+ * \brief The IPv4 representation of a network interface
+ *
+ * This class roughly corresponds to the struct in_device
+ * of Linux; the main purpose is to provide address-family
+ * specific information (addresses) about an interface.
+ *
+ * This class defines two APIs:
+ *  - the public API which is expected to be used by both 
+ *    the IPv4 layer and the user during forwarding and 
+ *    configuration.
+ *  - the private API which is expected to be implemented
+ *    by subclasses of this base class. One such subclass 
+ *    will be a Loopback interface which loops every
+ *    packet sent back to the ipv4 layer. Another such 
+ *    subclass typically contains the Ipv4 <-> MAC address
+ *    translation logic which will use most of the time the
+ *    ARP/RARP protocols.
+ */
+class Ipv4Interface 
+{
+public:
+  /**
+   * By default, Ipv4 interface are created in the "down" state
+   * with ip address 192.168.0.1 and a matching mask. Before
+   * becoming useable, the user must invoke SetUp on them
+   * once the final Ipv4 address and mask has been set.
+   */
+  Ipv4Interface (NetDevice *nd);
+  virtual ~Ipv4Interface();
+
+  NetDevice *GetDevice (void) const;
+
+  void SetAddress (Ipv4Address a);
+  void SetNetworkMask (Ipv4Mask mask);
+
+  Ipv4Address GetBroadcast (void) const;
+  Ipv4Mask GetNetworkMask (void) const;
+  Ipv4Address GetAddress (void) const;
+
+  /**
+   * This function a pass-through to NetDevice GetMtu, modulo
+   * the  LLC/SNAP header i.e., ipv4MTU = NetDeviceMtu - LLCSNAPSIZE
+   */
+  uint16_t GetMtu (void) const;
+
+  /**
+   * These are IP interface states and may be distinct from 
+   * NetDevice states, such as found in real implementations
+   * (where the device may be down but IP interface state is still up).
+   */
+  bool IsUp (void) const;
+  bool IsDown (void) const;
+  void SetUp (void);
+  void SetDown (void);
+
+  /**
+   * Packet typically received from above will require some
+   * handling before calling SendTo()
+   */ 
+  void Send(Packet p, Ipv4Address dest);
+
+
+ private:
+  virtual void SendTo (Packet p, Ipv4Address dest) = 0;
+  NetDevice* m_netdevice;
+  bool m_ifup;
+  Ipv4Address m_address;
+  Ipv4Mask m_netmask;
+};
+
+}; // namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-l3-protocol.cc	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,437 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//
+
+#include "ns3/packet.h"
+
+#include "ipv4-l3-protocol.h"
+#include "ipv4-l4-protocol.h"
+#include "ipv4-address.h"
+#include "ipv4-header.h"
+#include "ipv4-interface.h"
+#include "ipv4-route.h"
+// the two following headers are needed for Ipv4L3Protocol::ForwardUp
+#include "node.h"
+#include "ipv4-l4-demux.h"
+
+#define TRACE(x)
+
+namespace ns3 {
+
+Ipv4L3Protocol::Ipv4L3Protocol()
+  : L3Protocol (0x0800, 4),
+    m_nInterfaces (0),
+    m_defaultTtl (64),
+    m_identification (0),
+    m_defaultRoute (0)
+{}
+Ipv4L3Protocol::Ipv4L3Protocol(Ipv4L3Protocol const &o)
+  : L3Protocol (o),
+    m_nInterfaces (0),
+    m_defaultTtl (o.m_defaultTtl),
+    m_identification (o.m_identification),
+    m_defaultRoute (0)
+{
+  // We do not copy the list of interfaces or the routes
+  // purposedly.
+}
+Ipv4L3Protocol::~Ipv4L3Protocol ()
+{
+  // XXX I am not sure we are really allowed to do this here.
+  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+    {
+      delete (*i);
+    }
+  for (HostRoutesI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i = m_hostRoutes.erase (i)) 
+    {
+      delete (*i);
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j = m_networkRoutes.erase (j)) 
+    {
+      delete (*j);
+    }
+  delete m_defaultRoute;
+}
+
+void 
+Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
+{
+  m_defaultTtl = ttl;
+}
+    
+
+void 
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
+				Ipv4Address nextHop, 
+				uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
+  m_hostRoutes.push_back (route);
+}
+void 
+Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
+				uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateHostRouteTo (dest, interface);
+  m_hostRoutes.push_back (route);
+}
+void 
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
+				   Ipv4Mask networkMask, 
+				   Ipv4Address nextHop, 
+				   uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            nextHop,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+void 
+Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
+				   Ipv4Mask networkMask, 
+				   uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+void 
+Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, 
+				 uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
+  delete m_defaultRoute;
+  m_defaultRoute = route;
+}
+
+Ipv4Route *
+Ipv4L3Protocol::Lookup (Ipv4Address dest)
+{
+  for (HostRoutesCI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i++) 
+    {
+      assert ((*i)->IsHost ());
+      if ((*i)->GetDest ().IsEqual (dest)) 
+        {
+          return (*i);
+        }
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      assert ((*j)->IsNetwork ());
+      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
+      Ipv4Address entry = (*j)->GetDestNetwork ();
+      if (mask.IsMatch (dest, entry)) 
+        {
+          return (*j);
+        }
+    }
+  if (m_defaultRoute != 0) 
+    {
+      assert (m_defaultRoute->IsDefault ());
+      return m_defaultRoute;
+    }
+  return 0;
+}
+
+uint32_t 
+Ipv4L3Protocol::GetNRoutes (void)
+{
+  uint32_t n = 0;
+  if (m_defaultRoute != 0)
+    {
+      n++;
+    }
+  n += m_hostRoutes.size ();
+  n += m_networkRoutes.size ();
+  return n;
+}
+Ipv4Route *
+Ipv4L3Protocol::GetRoute (uint32_t index)
+{
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      return m_defaultRoute;
+    }
+  index--;
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesCI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              return *i;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          return *j;
+        }
+      tmp++;
+    }
+  assert (false);
+  // quiet compiler.
+  return 0;
+}
+void 
+Ipv4L3Protocol::RemoveRoute (uint32_t index)
+{
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  index--;
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              delete *i;
+              m_hostRoutes.erase (i);
+              return;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          delete *j;
+          m_networkRoutes.erase (j);
+          return;
+        }
+      tmp++;
+    }
+  assert (false);
+}
+
+
+uint32_t 
+Ipv4L3Protocol::AddInterface (Ipv4Interface *interface)
+{
+  uint32_t index = m_nInterfaces;
+  m_interfaces.push_back (interface);
+  m_nInterfaces++;
+  return index;
+}
+Ipv4Interface *
+Ipv4L3Protocol::GetInterface (uint32_t index)
+{
+  uint32_t tmp = 0;
+  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+    {
+      if (index == tmp) 
+	{
+	  return *i;
+	}
+      tmp++;
+    }
+  return 0;
+}
+uint32_t 
+Ipv4L3Protocol::GetNInterfaces (void) const
+{
+  return m_nInterfaces;
+}
+
+  
+
+Ipv4L3Protocol* 
+Ipv4L3Protocol::Copy() const
+{
+  return new Ipv4L3Protocol (*this);
+}
+void 
+Ipv4L3Protocol::Receive(Packet& packet, NetDevice &device)
+{
+  // XXX trace here.
+  Ipv4Header ipHeader;
+  packet.Peek (ipHeader);
+  packet.Remove (ipHeader);
+
+  if (!ipHeader.IsChecksumOk ()) 
+    {
+      return;
+    }
+
+  if (Forwarding (packet, ipHeader, device)) 
+    {
+      return;
+    }
+
+  ForwardUp (packet, ipHeader);
+}
+
+void 
+Ipv4L3Protocol::Send (Packet const &packet, 
+                      Ipv4Address source, 
+                      Ipv4Address destination,
+                      uint8_t protocol)
+{
+  Ipv4Header ipHeader;
+
+  ipHeader.SetSource (source);
+  ipHeader.SetDestination (destination);
+  ipHeader.SetProtocol (protocol);
+  ipHeader.SetPayloadSize (packet.GetSize ());
+  ipHeader.SetTtl (m_defaultTtl);
+  ipHeader.SetMayFragment ();
+  ipHeader.SetIdentification (m_identification);
+
+  m_identification ++;
+
+  // XXX Note here that in most ipv4 stacks in the world,
+  // the route calculation for an outgoing packet is not
+  // done in the ip layer. It is done within the application
+  // socket when the first packet is sent to avoid this
+  // costly lookup on a per-packet basis.
+  // That would require us to get the route from the packet,
+  // most likely with a packet tag. The higher layers do not
+  // do this yet for us.
+  Ipv4Route *route = Lookup (ipHeader.GetDestination ());
+  if (route == 0) 
+    {
+      TRACE ("not for me -- forwarding but no route to host. drop.");
+      return;
+    }
+
+  SendRealOut (packet, ipHeader, *route);
+}
+
+void
+Ipv4L3Protocol::SendRealOut (Packet const &p, Ipv4Header const &ip, Ipv4Route const &route)
+{
+  Packet packet = p;
+  packet.Add (ip);
+  Ipv4Interface *outInterface = GetInterface (route.GetInterface ());
+  assert (packet.GetSize () <= outInterface->GetMtu ());
+  // XXX log trace here.
+  if (route.IsGateway ()) 
+    {
+      outInterface->Send (packet, route.GetGateway ());
+    } 
+  else 
+    {
+      outInterface->Send (packet, ip.GetDestination ());
+    }
+}
+
+
+bool
+Ipv4L3Protocol::Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device)
+{
+  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+       i != m_interfaces.end (); i++) 
+    {
+      if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) 
+        {
+          TRACE ("for me 1");
+          return false;
+        }
+    }
+  
+  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+       i != m_interfaces.end (); i++) 
+    {
+      Ipv4Interface *interface = *i;
+      if (interface->GetDevice () == &device)
+	{
+	  if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) 
+	    {
+	      TRACE ("for me 2");
+	      return false;
+	    }
+	  break;
+	}
+    }
+      
+  if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetBroadcast ())) 
+    {
+      TRACE ("for me 3");
+      return false;
+    }
+  if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) 
+    {
+      TRACE ("for me 4");
+      return false;
+    }
+  if (ipHeader.GetTtl () == 1) 
+    {
+      // Should send ttl expired here
+      // XXX
+      TRACE ("not for me -- ttl expired. drop.");
+      return true;
+    }
+  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
+  Ipv4Route *route = Lookup (ipHeader.GetDestination ());
+  if (route == 0) 
+    {
+      TRACE ("not for me -- forwarding but no route to host. drop.");
+      return true;
+    }
+  TRACE ("not for me -- forwarding.");
+  SendRealOut (packet, ipHeader, *route);
+  return true;
+}
+
+
+void
+Ipv4L3Protocol::ForwardUp (Packet p, Ipv4Header const&ip)
+{
+  Ipv4L4Protocol *protocol = m_node->GetIpv4L4Demux ()->Lookup (ip.GetProtocol ());
+  protocol->Receive (p, ip.GetSource (), ip.GetDestination ());
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-l3-protocol.h	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,129 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//
+
+#ifndef IPV4_L3_PROTOCOL_H
+#define IPV4_L3_PROTOCOL_H
+
+#include <list>
+#include <stdint.h>
+#include "l3-protocol.h"
+#include "ipv4-address.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4Route;
+class Node;
+
+
+/**
+ * ::Send is always defined in subclasses.
+ */
+class Ipv4L3Protocol : public L3Protocol {
+public:
+  Ipv4L3Protocol();
+  Ipv4L3Protocol(Ipv4L3Protocol const &o);
+  virtual ~Ipv4L3Protocol ();
+
+  void SetDefaultTtl (uint8_t ttl);
+    
+  /* add route to host dest through host nextHop 
+   * on interface.
+   */
+  void AddHostRouteTo (Ipv4Address dest, 
+                       Ipv4Address nextHop, 
+                       uint32_t interface);
+  /* add route to host dest on interface.
+   */
+  void AddHostRouteTo (Ipv4Address dest, 
+                       uint32_t interface);
+  /* add route to network dest with netmask 
+   * through host nextHop on interface
+   */
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          Ipv4Address nextHop, 
+                          uint32_t interface);
+  /* add route to network dest with netmask 
+   * on interface
+   */
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          uint32_t interface);
+  /* set the default route to host nextHop on
+   * interface. 
+   */
+  void SetDefaultRoute (Ipv4Address nextHop, 
+                        uint32_t interface);
+
+  Ipv4Route *Lookup (Ipv4Address dest);
+
+  uint32_t GetNRoutes (void);
+  Ipv4Route *GetRoute (uint32_t i);
+  void RemoveRoute (uint32_t i);
+  
+  uint32_t AddInterface (Ipv4Interface *interface);
+  Ipv4Interface * GetInterface (uint32_t i);
+  uint32_t GetNInterfaces (void) const;
+  
+
+  virtual Ipv4L3Protocol* Copy() const;
+  /**
+   * Lower layer calls this method after calling L3Demux::Lookup
+   * The ARP subclass needs to know from which NetDevice this
+   * packet is coming to:
+   *    - implement a per-NetDevice ARP cache
+   *    - send back arp replies on the right device
+   */
+  virtual void Receive(Packet& p, NetDevice &device);
+
+ private:
+  void Send (Packet const &packet, Ipv4Address source, 
+	     Ipv4Address destination, uint8_t protocol);
+  void SendRealOut (Packet const &packet, Ipv4Header const &ip, Ipv4Route const &route);
+  bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device);
+  void ForwardUp (Packet p, Ipv4Header const&ip);
+
+  typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
+  typedef std::list<Ipv4Route *> HostRoutes;
+  typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
+  typedef std::list<Ipv4Route *>::iterator HostRoutesI;
+  typedef std::list<Ipv4Route *> NetworkRoutes;
+  typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
+  typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
+
+  Ipv4InterfaceList m_interfaces;
+  uint32_t m_nInterfaces;
+  uint8_t m_defaultTtl;
+  uint16_t m_identification;
+  HostRoutes m_hostRoutes;
+  NetworkRoutes m_networkRoutes;
+  Ipv4Route *m_defaultRoute;
+  Node *m_node;
+};
+
+} // Namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-route.cc	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,223 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv4-route.h"
+#include <cassert>
+
+namespace ns3 {
+
+/*****************************************************
+ *     Network Ipv4Route
+ *****************************************************/
+
+Ipv4Route::Ipv4Route ()
+{}
+Ipv4Route::Ipv4Route (Ipv4Route const &route)
+  : m_dest (route.m_dest),
+    m_destNetworkMask (route.m_destNetworkMask),
+    m_gateway (route.m_gateway),
+    m_interface (route.m_interface)
+{}
+
+Ipv4Route::Ipv4Route (Ipv4Address dest,
+                      Ipv4Address gateway,
+                      uint32_t interface)
+  : m_dest (dest),
+    m_destNetworkMask (Ipv4Mask::GetZero ()),
+    m_gateway (gateway),
+    m_interface (interface)
+{}
+Ipv4Route::Ipv4Route (Ipv4Address dest,
+                      uint32_t interface)
+  : m_dest (dest),
+    m_destNetworkMask (Ipv4Mask::GetZero ()),
+    m_gateway (Ipv4Address::GetZero ()),
+    m_interface (interface)
+{}
+Ipv4Route::Ipv4Route (Ipv4Address network,
+                      Ipv4Mask networkMask,
+                      Ipv4Address gateway,
+                      uint32_t interface)
+  : m_dest (network),
+    m_destNetworkMask (networkMask),
+    m_gateway (gateway),
+    m_interface (interface)
+{}
+Ipv4Route::Ipv4Route (Ipv4Address network,
+                      Ipv4Mask networkMask,
+                      uint32_t interface)
+  : m_dest (network),
+    m_destNetworkMask (networkMask),
+    m_gateway (Ipv4Address::GetZero ()),
+    m_interface (interface)
+{}
+
+bool 
+Ipv4Route::IsHost (void) const
+{
+  if (m_destNetworkMask.IsEqual (Ipv4Mask::GetZero ())) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+Ipv4Address 
+Ipv4Route::GetDest (void) const
+{
+  return m_dest;
+}
+bool 
+Ipv4Route::IsNetwork (void) const
+{
+  return !IsHost ();
+}
+bool 
+Ipv4Route::IsDefault (void) const
+{
+  if (m_dest.IsEqual (Ipv4Address::GetZero ())) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+Ipv4Address 
+Ipv4Route::GetDestNetwork (void) const
+{
+  return m_dest;
+}
+Ipv4Mask 
+Ipv4Route::GetDestNetworkMask (void) const
+{
+  return m_destNetworkMask;
+}
+bool 
+Ipv4Route::IsGateway (void) const
+{
+  if (m_gateway.IsEqual (Ipv4Address::GetZero ())) 
+    {
+      return false;
+    } 
+  else 
+    {
+      return true;
+    }
+}
+Ipv4Address 
+Ipv4Route::GetGateway (void) const
+{
+  return m_gateway;
+}
+uint32_t
+Ipv4Route::GetInterface (void) const
+{
+  return m_interface;
+}
+
+
+Ipv4Route 
+Ipv4Route::CreateHostRouteTo (Ipv4Address dest, 
+			      Ipv4Address nextHop, 
+			      uint32_t interface)
+{
+  return Ipv4Route (dest, nextHop, interface);
+}
+Ipv4Route 
+Ipv4Route::CreateHostRouteTo (Ipv4Address dest,
+			      uint32_t interface)
+{
+  return Ipv4Route (dest, interface);
+}
+Ipv4Route 
+Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, 
+				 Ipv4Mask networkMask, 
+				 Ipv4Address nextHop, 
+				 uint32_t interface)
+{
+  return Ipv4Route (network, networkMask, 
+                    nextHop, interface);
+}
+Ipv4Route 
+Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, 
+				 Ipv4Mask networkMask, 
+				 uint32_t interface)
+{
+  return Ipv4Route (network, networkMask, 
+                    interface);
+}
+Ipv4Route 
+Ipv4Route::CreateDefaultRoute (Ipv4Address nextHop, 
+			       uint32_t interface)
+{
+  return Ipv4Route (Ipv4Address::GetZero (), nextHop, interface);
+}
+
+
+std::ostream& operator<< (std::ostream& os, Ipv4Route const& route)
+{
+  if (route.IsDefault ())
+    {
+      assert (route.IsGateway ());
+      os << "default out=" << route.GetInterface () << ", next hop=" << route.GetGateway ();
+    }
+  else if (route.IsHost ())
+    {
+      if (route.IsGateway ())
+        {
+          os << "host="<< route.GetDest () << 
+            ", out=" << route.GetInterface () << 
+            ", next hop=" << route.GetGateway ();
+        }
+      else
+        {
+          os << "host="<< route.GetDest () << 
+            ", out=" << route.GetInterface ();
+        }
+    }
+  else if (route.IsNetwork ()) 
+    {
+      if (route.IsGateway ())
+        {
+          os << "network=" << route.GetDestNetwork () <<
+            ", mask=" << route.GetDestNetworkMask () <<
+            ",out=" << route.GetInterface () <<
+            ", next hop=" << route.GetGateway ();
+        }
+      else
+        {
+          os << "network=" << route.GetDestNetwork () <<
+            ", mask=" << route.GetDestNetworkMask () <<
+            ",out=" << route.GetInterface ();
+        }
+    }
+  else
+    {
+      assert (false);
+    }
+  return os;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-route.h	Fri Feb 09 17:54:49 2007 +0100
@@ -0,0 +1,89 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV4_ROUTE_H
+#define IPV4_ROUTE_H
+
+#include <list>
+#include <ostream>
+
+#include "ipv4-address.h"
+
+namespace ns3 {
+
+class Ipv4Route {
+public:
+  Ipv4Route ();
+  Ipv4Route (Ipv4Route const &route);
+
+  bool IsHost (void) const;
+  Ipv4Address GetDest (void) const;
+
+  bool IsNetwork (void) const;
+  Ipv4Address GetDestNetwork (void) const;
+  Ipv4Mask GetDestNetworkMask (void) const;
+
+  bool IsDefault (void) const;
+
+  bool IsGateway (void) const;
+  Ipv4Address GetGateway (void) const;
+
+  uint32_t GetInterface (void) const;
+
+  static Ipv4Route CreateHostRouteTo (Ipv4Address dest, 
+				      Ipv4Address nextHop, 
+				      uint32_t interface);
+  static Ipv4Route CreateHostRouteTo (Ipv4Address dest, 
+				      uint32_t interface);
+  static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, 
+					 Ipv4Mask networkMask, 
+					 Ipv4Address nextHop, 
+					 uint32_t interface);
+  static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, 
+					 Ipv4Mask networkMask, 
+					 uint32_t interface);
+  static Ipv4Route CreateDefaultRoute (Ipv4Address nextHop, 
+				       uint32_t interface);
+  
+private:
+  Ipv4Route (Ipv4Address network,
+	     Ipv4Mask mask,
+	     Ipv4Address gateway,
+	     uint32_t interface);
+  Ipv4Route (Ipv4Address dest,
+	     Ipv4Mask mask,
+	     uint32_t interface);
+  Ipv4Route (Ipv4Address dest,
+	     Ipv4Address gateway,
+	     uint32_t interface);
+  Ipv4Route (Ipv4Address dest,
+	     uint32_t interface);
+
+  Ipv4Address m_dest;
+  Ipv4Mask m_destNetworkMask;
+  Ipv4Address m_gateway;
+  uint32_t m_interface;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv4Route const& route);
+
+}//namespace ns3
+
+#endif /* IPV4_ROUTE_H */
--- a/src/node/l3-protocol.cc	Thu Feb 08 16:01:58 2007 +0100
+++ b/src/node/l3-protocol.cc	Fri Feb 09 17:54:49 2007 +0100
@@ -31,6 +31,10 @@
     : m_protocolNumber (protocolNumber),
       m_version (version)
 {}
+L3Protocol::L3Protocol (L3Protocol const &o)
+  : m_protocolNumber (o.m_protocolNumber),
+    m_version (o.m_version)
+{}
 L3Protocol::~L3Protocol ()
 {}
     
--- a/src/node/l3-protocol.h	Thu Feb 08 16:01:58 2007 +0100
+++ b/src/node/l3-protocol.h	Fri Feb 09 17:54:49 2007 +0100
@@ -37,6 +37,7 @@
 class L3Protocol {
 public:
   L3Protocol(int protocolNumber, int version);
+  L3Protocol (L3Protocol const &o);
   virtual ~L3Protocol ();
     
   int GetProtocolNumber (void) const;