diff --git a/examples/csma-tap-bridge.cc b/examples/csma-tap-bridge.cc index 64a93c5f8..ccec5b052 100644 --- a/examples/csma-tap-bridge.cc +++ b/examples/csma-tap-bridge.cc @@ -147,38 +147,17 @@ main (int argc, char *argv[]) bridge.SetAttribute ("DeviceName", StringValue ("right")); bridge.Install (nodes.Get (3), devices.Get (3)); -#if 0 - // - // Testing only -- send a packet from an internal node to an external node - // - uint32_t packetSize = 1024; - uint32_t maxPacketCount = 100; - Time interPacketInterval = Seconds (1.); - UdpEchoClientHelper client (interfaces.GetAddress (0), 9); - client.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount)); - client.SetAttribute ("Interval", TimeValue (interPacketInterval)); - client.SetAttribute ("PacketSize", UintegerValue (packetSize)); - ApplicationContainer apps = client.Install (nodes.Get (1)); - apps.Start (Seconds (2.0)); - apps.Stop (Seconds (10.0)); -#endif - // // Configure tracing of all enqueue, dequeue, and NetDevice receive events. // -#if 0 NS_LOG_INFO ("Configure Tracing."); - std::ofstream ascii; - ascii.open ("csma-tap-bridge.tr"); - CsmaHelper::EnableAsciiAll (ascii); CsmaHelper::EnablePcapAll ("csma-tap-bridge"); -#endif // // Now, do the actual simulation. Run for a few minutes to allow the user a chance // to run some applications on the Linux hosts. // - Simulator::Stop (Seconds (3. * 60.)); + Simulator::Stop (Seconds (60.)); NS_LOG_INFO ("Run Simulation."); Simulator::Run (); Simulator::Destroy (); diff --git a/src/devices/tap-bridge/tap-bridge.cc b/src/devices/tap-bridge/tap-bridge.cc index 12965c6a2..61b06fb5e 100644 --- a/src/devices/tap-bridge/tap-bridge.cc +++ b/src/devices/tap-bridge/tap-bridge.cc @@ -24,6 +24,7 @@ #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" #include "ns3/string.h" @@ -598,22 +599,100 @@ TapBridge::ForwardToBridgedDevice (uint8_t *buf, uint32_t len) buf = 0; // - // Checksum the packet + // Make sure the packet we received is reasonable enough for the rest of the + // system to handle and get it ready to be injected directly into an ns-3 + // device. What should come back is a packet with the Ethernet header + // (and possibly an LLC header as well) stripped off. // - EthernetTrailer trailer; - packet->RemoveTrailer (trailer); - trailer.CheckFcs (packet); + Address src, dst; + uint16_t type; + + NS_LOG_LOGIC ("Received packet from tap device"); + + Ptr p = Filter (packet, &src, &dst, &type); + if (p == 0) + { + NS_LOG_LOGIC ("Discarding packet as unfit for ns-3 consumption"); + return; + } + + NS_LOG_LOGIC ("Pkt source is " << src); + NS_LOG_LOGIC ("Pkt destination is " << dst); + NS_LOG_LOGIC ("Pkt LengthType is " << type); + + NS_LOG_LOGIC ("Forwarding packet"); + m_bridgedDevice->SendFrom (packet, src, dst, type); +} + +Ptr +TapBridge::Filter (Ptr p, Address *src, Address *dst, uint16_t *type) +{ + NS_LOG_FUNCTION (p); + uint32_t pktSize; // - // Get rid of the MAC header + // 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 + // 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); - packet->RemoveHeader (header); + if (pktSize < header.GetSerializedSize ()) + { + return 0; + } + + p->RemoveHeader (header); NS_LOG_LOGIC ("Pkt source is " << header.GetSource ()); NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ()); + NS_LOG_LOGIC ("Pkt LengthType is " << header.GetLengthType ()); - m_bridgedDevice->SendFrom (packet, header.GetSource (), header.GetDestination (), 0x800); + // + // 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. + // + if (header.GetLengthType () <= 1500) + { + *src = header.GetSource (); + *dst = header.GetDestination (); + + pktSize = p->GetSize (); + LlcSnapHeader llc; + if (pktSize < llc.GetSerializedSize ()) + { + return 0; + } + + p->RemoveHeader (llc); + *type = llc.GetType (); + } + else + { + *src = header.GetSource (); + *dst = header.GetDestination (); + *type = header.GetLengthType (); + } + + // + // 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. + // + return p; } Ptr @@ -626,7 +705,7 @@ TapBridge::GetBridgedNetDevice (void) void TapBridge::SetBridgedNetDevice (Ptr bridgedDevice) { - NS_LOG_FUNCTION_NOARGS (); + NS_LOG_FUNCTION (bridgedDevice); NS_ASSERT_MSG (m_node != 0, "TapBridge::SetBridgedDevice: Bridge not installed in a node"); NS_ASSERT_MSG (bridgedDevice != this, "TapBridge::SetBridgedDevice: Cannot bridge to self"); diff --git a/src/devices/tap-bridge/tap-bridge.h b/src/devices/tap-bridge/tap-bridge.h index 5115df26e..a71be3ee3 100644 --- a/src/devices/tap-bridge/tap-bridge.h +++ b/src/devices/tap-bridge/tap-bridge.h @@ -168,8 +168,19 @@ private: */ void ReadThread (void); + /* + * Forward a packet received from the tap device to the bridged ns-3 + * device + */ void ForwardToBridgedDevice (uint8_t *buf, uint32_t len); + /** + * The host we are bridged to is in the evil real world. Do some sanity + * checking on a received packet to make sure it isn't too evil for our + * poor naive virginal simulator to handle. + */ + Ptr Filter (Ptr packet, Address *src, Address *dst, uint16_t *type); + NetDevice::ReceiveCallback m_rxCallback; NetDevice::PromiscReceiveCallback m_promiscRxCallback;