turn on checksums in example csma-tap-bridge and tweaks to make ping demo work
authorCraig Dowell <craigdo@ee.washington.edu>
Fri, 30 Jan 2009 15:47:38 -0800
changeset 4170 8e5bdeb6a71b
parent 4169 d966e2ded46d
child 4171 902589866374
turn on checksums in example csma-tap-bridge and tweaks to make ping demo work
examples/csma-tap-bridge.cc
src/devices/csma/csma-net-device.cc
src/devices/tap-bridge/tap-bridge.cc
src/devices/tap-bridge/tap-creator.cc
src/internet-stack/arp-header.cc
src/internet-stack/arp-l3-protocol.cc
--- a/examples/csma-tap-bridge.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/examples/csma-tap-bridge.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -71,8 +71,20 @@
   CommandLine cmd;
   cmd.Parse (argc, argv);
 
-  GlobalValue::Bind ("SimulatorImplementationType", 
-    StringValue ("ns3::RealtimeSimulatorImpl"));
+  //
+  // We need to enable the real-time simulator since we are going to be
+  // talking to the "real world."
+  GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
+
+  // 
+  // Also, since the whole point of this exercise is to exchange packets
+  // with hosts running in the real world, we are going to need to enable
+  // checksums.
+  //
+  Config::SetDefault ("ns3::Ipv4L3Protocol::CalcChecksum", BooleanValue (true)); 
+  Config::SetDefault ("ns3::Icmpv4L4Protocol::CalcChecksum", BooleanValue (true)); 
+  Config::SetDefault ("ns3::TcpL4Protocol::CalcChecksum", BooleanValue (true)); 
+  Config::SetDefault ("ns3::UdpL4Protocol::CalcChecksum", BooleanValue (true)); 
 
   //
   // Create the nodes required by the topology (shown above).
--- a/src/devices/csma/csma-net-device.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/src/devices/csma/csma-net-device.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -656,27 +656,22 @@
     }
   else
     {
+      uint16_t protocol;
       //
-      // variable <protocol> must be initialized to avoid a compiler warning in the RAW case that breaks the optimized build.
+      // If the length/type is less than 1500, it corresponds to a length 
+      // interpretation packet.  In this case, it is an 802.3 packet and 
+      // will also have an 802.2 LLC header.  If greater than 1500, we
+      // find the protocol number (Ethernet type) directly.
       //
-      uint16_t protocol = 0;
-
-      switch (m_encapMode)
+      if (header.GetLengthType () <= 1500)
         {
-        case DIX:
+          LlcSnapHeader llc;
+          packet->RemoveHeader (llc);
+          protocol = llc.GetType ();
+        }
+      else
+        {
           protocol = header.GetLengthType ();
-          break;
-        case LLC: 
-          {
-            LlcSnapHeader llc;
-            packet->RemoveHeader (llc);
-            protocol = llc.GetType ();
-          } 
-          break;
-        case ILLEGAL:
-        default:
-          NS_FATAL_ERROR ("CsmaNetDevice::Receive(): Unknown packet encapsulation mode");
-          break;
         }
 
       PacketType packetType;
--- a/src/devices/tap-bridge/tap-bridge.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/src/devices/tap-bridge/tap-bridge.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -23,7 +23,6 @@
 #include "ns3/channel.h"
 #include "ns3/packet.h"
 #include "ns3/ethernet-header.h"
-#include "ns3/ethernet-trailer.h"
 #include "ns3/llc-snap-header.h"
 #include "ns3/log.h"
 #include "ns3/boolean.h"
@@ -633,21 +632,10 @@
   //
   // We have a candidate packet for injection into ns-3.  We expect that since
   // it came over a socket that provides Ethernet packets, it sould be big 
-  // enough to hold an EthernetTrailer.  If it can't, we signify the packet 
+  // enough to hold an EthernetHeader.  If it can't, we signify the packet 
   // should be filtered out by returning 0.
   //
   pktSize = p->GetSize ();
-  EthernetTrailer trailer;
-  if (pktSize < trailer.GetSerializedSize ())
-    {
-      return 0;
-    }
-  p->RemoveTrailer (trailer);
-
-  //
-  // We also expect that it will have an Ethernet header on it.
-  //
-  pktSize = p->GetSize ();
   EthernetHeader header (false);
   if (pktSize < header.GetSerializedSize ())
     {
@@ -689,8 +677,9 @@
     }
 
   //
-  // What we give back is a packet without the Ethernet header and trailer
-  // on it, that is fit to give directly to the bridged net device.
+  // What we give back is a packet without the Ethernet header (nor the 
+  // possible llc/snap header) on it.  We think it is ready to send on
+  // out the bridged net device.
   //
   return p;
 }
@@ -722,7 +711,8 @@
     }
 
   //
-  // Tell the bridged device to forward its received packets here.
+  // Tell the bridged device to forward its received packets here.  We use the 
+  // promiscuous mode hook to get both the source and destination addresses.
   //
   m_node->RegisterProtocolHandler (MakeCallback (&TapBridge::ReceiveFromBridgedDevice, this), 0, bridgedDevice, true);
   m_bridgedDevice = bridgedDevice;
@@ -746,6 +736,18 @@
   Mac48Address to = Mac48Address::ConvertFrom (dst);
 
   //
+  // We hooked the promiscuous mode protocol handler so we could get the 
+  // destination address of the actual packet.  This means we will be getting
+  // PACKET_OTHERHOST packets (not broadcast, not multicast, not unicast to 
+  // this device, but to some other address).  We don't want to forward those
+  // PACKET_OTHERHOST packets so just ignore them
+  //
+  if (packetType == PACKET_OTHERHOST)
+    {
+      return;
+    }
+
+  //
   // We have received a packet from the ns-3 net device that has been associated
   // with this bridge.  We want to take these bits and send them off to the 
   // Tap device on the Linux host.  Once we do this, the bits in the packet will
@@ -755,12 +757,20 @@
   // header, so we have to put one back on.
   //
   Ptr<Packet> p = packet->Copy ();
+
+
   EthernetHeader header = EthernetHeader (false);
   header.SetSource (from);
   header.SetDestination (to);
-  header.SetLengthType (0x800);
+  header.SetLengthType (protocol);
   p->AddHeader (header);
 
+  NS_LOG_LOGIC ("Writing packet to Linux host");
+  NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
+  NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
+  NS_LOG_LOGIC ("Pkt LengthType is " << header.GetLengthType ());
+  NS_LOG_LOGIC ("Pkt size is " << p->GetSize ());
+
   write (m_sock, p->PeekData (), p->GetSize ());
 }
 
--- a/src/devices/tap-bridge/tap-creator.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/src/devices/tap-bridge/tap-creator.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -352,8 +352,6 @@
 
   opterr = 0;
 
-  gVerbose = true;
-
   while ((c = getopt (argc, argv, "vd:g:i:m:n:p:")) != -1)
     {
       switch (c)
--- a/src/internet-stack/arp-header.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/src/internet-stack/arp-header.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -143,18 +143,33 @@
   WriteTo (i, m_macDest);
   WriteTo (i, m_ipv4Dest);
 }
+
 uint32_t
 ArpHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
-  i.Next (2+2);
-  uint32_t hardwareAddressLen = i.ReadU8 ();
-  i.Next (1);
-  m_type = i.ReadNtohU16 ();
-  ReadFrom (i, m_macSource, hardwareAddressLen);
-  ReadFrom (i, m_ipv4Source);
-  ReadFrom (i, m_macDest, hardwareAddressLen);
-  ReadFrom (i, m_ipv4Dest);
+  uint32_t hardwareType = i.ReadNtohU16 ();      // Read HRD
+  uint32_t protocolType = i.ReadNtohU16 ();      // Read PRO
+  uint32_t hardwareAddressLen = i.ReadU8 ();     // Read HLN
+  uint32_t protocolAddressLen = i.ReadU8 ();     // Read PLN
+
+  hardwareType = hardwareType;
+  //
+  // It is implicit here that we have a protocol type of 0x800 (IP).
+  // It is also implicit here that we are using Ipv4 (PLN == 4).
+  // If this isn't the case, we need to return an error since we don't want to 
+  // be too fragile if we get connected to real networks.
+  //
+  if (protocolType != 0x800 || protocolAddressLen != 4)
+    {
+      return 0;
+    }
+
+  m_type = i.ReadNtohU16 ();                     // Read OP
+  ReadFrom (i, m_macSource, hardwareAddressLen); // Read SHA (size HLN)
+  ReadFrom (i, m_ipv4Source);                    // Read SPA (size PLN == 4)
+  ReadFrom (i, m_macDest, hardwareAddressLen);   // Read THA (size HLN)
+  ReadFrom (i, m_ipv4Dest);                      // Read TPA (size PLN == 4)
   return GetSerializedSize ();
 }
 
--- a/src/internet-stack/arp-l3-protocol.cc	Thu Jan 29 16:16:10 2009 -0800
+++ b/src/internet-stack/arp-l3-protocol.cc	Fri Jan 30 15:47:38 2009 -0800
@@ -124,9 +124,24 @@
 
   Ptr<Packet> packet = p->Copy ();
 
+  NS_LOG_LOGIC ("ARP: received packet of size "<< packet->GetSize ());
+
   Ptr<ArpCache> cache = FindCache (device);
+
+  // 
+  // If we're connected to a real world network, then some of the fields sizes 
+  // in an ARP packet can vary in ways not seen in simulations.  We need to be
+  // able to detect ARP packets with headers we don't recongnize and not process
+  // them instead of crashing.  The ArpHeader will return 0 if it can't deal
+  // with the received header.
+  //
   ArpHeader arp;
-  packet->RemoveHeader (arp);
+  uint32_t size = packet->RemoveHeader (arp);
+  if (size == 0)
+    {
+      NS_LOG_LOGIC ("ARP: Cannot remove ARP header");
+      return;
+    }
   
   NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
             " node="<<m_node->GetId ()<<", got request from " <<