From 885b97a6ecab5e2bb6083ba2300ce4732aa78417 Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Fri, 30 Jan 2009 15:47:38 -0800 Subject: [PATCH] turn on checksums in example csma-tap-bridge and tweaks to make ping demo work --- examples/csma-tap-bridge.cc | 16 ++++++++-- src/devices/csma/csma-net-device.cc | 29 ++++++++---------- src/devices/tap-bridge/tap-bridge.cc | 44 ++++++++++++++++----------- src/devices/tap-bridge/tap-creator.cc | 2 -- src/internet-stack/arp-header.cc | 31 ++++++++++++++----- src/internet-stack/arp-l3-protocol.cc | 17 ++++++++++- 6 files changed, 92 insertions(+), 47 deletions(-) diff --git a/examples/csma-tap-bridge.cc b/examples/csma-tap-bridge.cc index ccec5b052..ed957f215 100644 --- a/examples/csma-tap-bridge.cc +++ b/examples/csma-tap-bridge.cc @@ -71,8 +71,20 @@ main (int argc, char *argv[]) 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). diff --git a/src/devices/csma/csma-net-device.cc b/src/devices/csma/csma-net-device.cc index ae8e518f1..9999d6df2 100644 --- a/src/devices/csma/csma-net-device.cc +++ b/src/devices/csma/csma-net-device.cc @@ -656,27 +656,22 @@ CsmaNetDevice::Receive (Ptr packet, Ptr senderDevice) } else { + uint16_t protocol; // - // variable 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) + { + LlcSnapHeader llc; + packet->RemoveHeader (llc); + protocol = llc.GetType (); + } + else { - case DIX: 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; diff --git a/src/devices/tap-bridge/tap-bridge.cc b/src/devices/tap-bridge/tap-bridge.cc index 61b06fb5e..90666431f 100644 --- a/src/devices/tap-bridge/tap-bridge.cc +++ b/src/devices/tap-bridge/tap-bridge.cc @@ -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 @@ TapBridge::Filter (Ptr p, Address *src, Address *dst, uint16_t *type) // // 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 @@ TapBridge::Filter (Ptr p, Address *src, Address *dst, uint16_t *type) } // - // 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 @@ TapBridge::SetBridgedNetDevice (Ptr bridgedDevice) } // - // 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; @@ -745,6 +735,18 @@ TapBridge::ReceiveFromBridgedDevice ( Mac48Address from = Mac48Address::ConvertFrom (src); 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 @@ -755,12 +757,20 @@ TapBridge::ReceiveFromBridgedDevice ( // header, so we have to put one back on. // Ptr 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 ()); } diff --git a/src/devices/tap-bridge/tap-creator.cc b/src/devices/tap-bridge/tap-creator.cc index 0ba67a238..322364b3f 100644 --- a/src/devices/tap-bridge/tap-creator.cc +++ b/src/devices/tap-bridge/tap-creator.cc @@ -352,8 +352,6 @@ main (int argc, char *argv[]) opterr = 0; - gVerbose = true; - while ((c = getopt (argc, argv, "vd:g:i:m:n:p:")) != -1) { switch (c) diff --git a/src/internet-stack/arp-header.cc b/src/internet-stack/arp-header.cc index 073de046f..d8ff2c281 100644 --- a/src/internet-stack/arp-header.cc +++ b/src/internet-stack/arp-header.cc @@ -143,18 +143,33 @@ ArpHeader::Serialize (Buffer::Iterator start) const 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 (); } diff --git a/src/internet-stack/arp-l3-protocol.cc b/src/internet-stack/arp-l3-protocol.cc index 0b8c60cf8..0c867dbec 100644 --- a/src/internet-stack/arp-l3-protocol.cc +++ b/src/internet-stack/arp-l3-protocol.cc @@ -124,9 +124,24 @@ ArpL3Protocol::Receive(Ptr device, Ptr p, uint16_t prot Ptr packet = p->Copy (); + NS_LOG_LOGIC ("ARP: received packet of size "<< packet->GetSize ()); + Ptr 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="<GetId ()<<", got request from " <<