--- a/scratch/nsclick-test-full.cc Tue Jun 08 11:46:17 2010 +0530
+++ b/scratch/nsclick-test-full.cc Thu Jun 10 19:59:22 2010 +0530
@@ -6,6 +6,7 @@
#include "ns3/ipv4-click-routing.h"
#include "ns3/arp-l3-protocol.h"
#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv4-l3-click-protocol.h"
#include "ns3/udp-l4-protocol.h"
#include "ns3/tcp-l4-protocol.h"
@@ -49,7 +50,7 @@
node->AggregateObject (arp);
// Setup Ipv4L3Protocol
- Ptr<Ipv4L3Protocol> ipv4l3 = CreateObject<Ipv4L3Protocol> ();
+ Ptr<Ipv4L3ClickProtocol> ipv4l3 = CreateObject<Ipv4L3ClickProtocol> ();
node->AggregateObject (ipv4l3);
// Setup Click instance
@@ -88,6 +89,7 @@
Ptr<Ipv4> ipv4click = csmaNodes.Get (0)->GetObject<Ipv4> ();
Ptr<Ipv4ClickRouting> click = DynamicCast <Ipv4ClickRouting> (ipv4click->GetRoutingProtocol ());
+ click->SetClickRoutingTableElement ("u/rt");
click->DoStart ();
@@ -100,8 +102,8 @@
OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
onOffHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
onOffHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
- onOffHelper.SetAttribute ("PacketSize", UintegerValue (512));
- onOffHelper.SetAttribute ("MaxBytes", UintegerValue (513));
+// onOffHelper.SetAttribute ("PacketSize", UintegerValue (512));
+// onOffHelper.SetAttribute ("MaxBytes", UintegerValue (513));
ApplicationContainer appcont;
@@ -109,8 +111,8 @@
onOffHelper.SetAttribute ("Remote", remoteAddress);
appcont.Add (onOffHelper.Install (csmaNodes.Get (0)));
- appcont.Start (Seconds (40.0));
- appcont.Stop (Seconds (45.0));
+ appcont.Start (Seconds (5.0));
+ appcont.Stop (Seconds (10.0));
/*
TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
@@ -129,7 +131,7 @@
*/
csma.EnablePcap ("click-test", csmaDevices, false);
- Simulator::Stop (Seconds(50.0));
+ Simulator::Stop (Seconds(20.0));
Simulator::Run();
return 0;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l3-click-protocol.cc Thu Jun 10 19:59:22 2010 +0530
@@ -0,0 +1,727 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Lalith Suresh
+ *
+ * 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: Lalith Suresh <suresh.lalith@gmail.com>
+ */
+
+#include "ipv4-l3-click-protocol.h"
+#include "ns3/ipv4-click-routing.h"
+#include "ns3/node.h"
+#include "ns3/socket.h"
+
+#include "ipv4-raw-socket-impl.h"
+#include "arp-l3-protocol.h"
+#include "ipv4-l4-protocol.h"
+#include "icmpv4-l4-protocol.h"
+#include "loopback-net-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4L3ClickProtocol");
+
+namespace ns3 {
+
+const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
+
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4L3ClickProtocol);
+
+TypeId
+Ipv4L3ClickProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4L3ClickProtocol")
+ .SetParent<Ipv4> ()
+ .AddConstructor<Ipv4L3ClickProtocol> ()
+
+ ;
+ return tid;
+}
+
+Ipv4L3ClickProtocol::Ipv4L3ClickProtocol ()
+ : m_identification (0)
+{}
+
+Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol ()
+{}
+
+void
+Ipv4L3ClickProtocol::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ {
+ *i = 0;
+ }
+ m_protocols.clear ();
+
+ for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
+ {
+ *i = 0;
+ }
+ m_interfaces.clear ();
+ m_sockets.clear ();
+ m_node = 0;
+ m_routingProtocol = 0;
+ Object::DoDispose ();
+}
+
+void
+Ipv4L3ClickProtocol::NotifyNewAggregate ()
+{
+ if (m_node == 0)
+ {
+ Ptr<Node>node = this->GetObject<Node>();
+ // verify that it's a valid node and that
+ // the node has not been set before
+ if (node != 0)
+ {
+ this->SetNode (node);
+ }
+ }
+ Object::NotifyNewAggregate ();
+}
+
+void
+Ipv4L3ClickProtocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
+{
+ NS_LOG_FUNCTION (this);
+ m_routingProtocol = routingProtocol;
+ m_routingProtocol->SetIpv4 (this);
+}
+
+
+Ptr<Ipv4RoutingProtocol>
+Ipv4L3ClickProtocol::GetRoutingProtocol (void) const
+{
+ return m_routingProtocol;
+}
+
+Ptr<Ipv4Interface>
+Ipv4L3ClickProtocol::GetInterface (uint32_t index) const
+{
+ NS_LOG_FUNCTION (this << index);
+ if (index < m_interfaces.size ())
+ {
+ return m_interfaces[index];
+ }
+ return 0;
+}
+
+uint32_t
+Ipv4L3ClickProtocol::GetNInterfaces (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_interfaces.size ();
+}
+
+int32_t
+Ipv4L3ClickProtocol::GetInterfaceForAddress (
+ Ipv4Address address) const
+{
+ NS_LOG_FUNCTION (this << address);
+
+ int32_t interface = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, interface++)
+ {
+ for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
+ {
+ if ((*i)->GetAddress (j).GetLocal () == address)
+ {
+ return interface;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int32_t
+Ipv4L3ClickProtocol::GetInterfaceForPrefix (
+ Ipv4Address address,
+ Ipv4Mask mask) const
+{
+ NS_LOG_FUNCTION (this << address << mask);
+
+ int32_t interface = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, interface++)
+ {
+ for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
+ {
+ if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
+ {
+ return interface;
+ }
+ }
+ }
+
+ return -1;
+}
+
+int32_t
+Ipv4L3ClickProtocol::GetInterfaceForDevice (
+ Ptr<const NetDevice> device) const
+{
+ NS_LOG_FUNCTION (this << device->GetIfIndex());
+
+ int32_t interface = 0;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
+ i != m_interfaces.end ();
+ i++, interface++)
+ {
+ if ((*i)->GetDevice () == device)
+ {
+ return interface;
+ }
+ }
+
+ return -1;
+}
+
+bool
+Ipv4L3ClickProtocol::IsDestinationAddress (Ipv4Address address, uint32_t iif) const
+{
+ NS_LOG_FUNCTION (this << address << " " << iif);
+
+ // First check the incoming interface for a unicast address match
+ for (uint32_t i = 0; i < GetNAddresses (iif); i++)
+ {
+ Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
+ if (address == iaddr.GetLocal ())
+ {
+ NS_LOG_LOGIC ("For me (destination " << address << " match)");
+ return true;
+ }
+ if (address == iaddr.GetBroadcast ())
+ {
+ NS_LOG_LOGIC ("For me (interface broadcast address)");
+ return true;
+ }
+ }
+
+ if (address.IsMulticast ())
+ {
+#ifdef NOTYET
+ if (MulticastCheckGroup (iif, address ))
+#endif
+ if (true)
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
+ return true;
+ }
+ }
+
+ if (address.IsBroadcast ())
+ {
+ NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
+ return true;
+ }
+
+ if (GetWeakEsModel ()) // Check other interfaces
+ {
+ for (uint32_t j = 0; j < GetNInterfaces (); j++)
+ {
+ if (j == uint32_t (iif)) continue;
+ for (uint32_t i = 0; i < GetNAddresses (j); i++)
+ {
+ Ipv4InterfaceAddress iaddr = GetAddress (j, i);
+ if (address == iaddr.GetLocal ())
+ {
+ NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
+ return true;
+ }
+ // This is a small corner case: match another interface's broadcast address
+ if (address == iaddr.GetBroadcast ())
+ {
+ NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void
+Ipv4L3ClickProtocol::SetIpForward (bool forward)
+{
+ NS_LOG_FUNCTION (this << forward);
+ m_ipForward = forward;
+ for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
+ {
+ (*i)->SetForwarding (forward);
+ }
+}
+
+bool
+Ipv4L3ClickProtocol::GetIpForward (void) const
+{
+ return m_ipForward;
+}
+
+void
+Ipv4L3ClickProtocol::SetWeakEsModel (bool model)
+{
+ m_weakEsModel = model;
+}
+
+bool
+Ipv4L3ClickProtocol::GetWeakEsModel (void) const
+{
+ return m_weakEsModel;
+}
+
+Ptr<NetDevice>
+Ipv4L3ClickProtocol::GetNetDevice (uint32_t i)
+{
+ NS_LOG_FUNCTION (this << i);
+ return GetInterface (i)-> GetDevice ();
+}
+
+void
+Ipv4L3ClickProtocol::SetupLoopback (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
+ Ptr<LoopbackNetDevice> device = 0;
+ // First check whether an existing LoopbackNetDevice exists on the node
+ for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
+ {
+ if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
+ {
+ break;
+ }
+ }
+ if (device == 0)
+ {
+ device = CreateObject<LoopbackNetDevice> ();
+ m_node->AddDevice (device);
+ }
+ interface->SetDevice (device);
+ interface->SetNode (m_node);
+ Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
+ interface->AddAddress (ifaceAddr);
+ uint32_t index = AddIpv4Interface (interface);
+ Ptr<Node> node = GetObject<Node> ();
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
+ Ipv4L3ClickProtocol::PROT_NUMBER, device);
+ interface->SetUp ();
+ if (m_routingProtocol != 0)
+ {
+ m_routingProtocol->NotifyInterfaceUp (index);
+ }
+}
+
+Ptr<Socket>
+Ipv4L3ClickProtocol::CreateRawSocket (void)
+{
+ NS_LOG_FUNCTION (this);
+ Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
+ socket->SetNode (m_node);
+ m_sockets.push_back (socket);
+ return socket;
+}
+void
+Ipv4L3ClickProtocol::DeleteRawSocket (Ptr<Socket> socket)
+{
+ NS_LOG_FUNCTION (this << socket);
+ for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
+ {
+ if ((*i) == socket)
+ {
+ m_sockets.erase (i);
+ return;
+ }
+ }
+ return;
+}
+
+
+void
+Ipv4L3ClickProtocol::SetNode (Ptr<Node> node)
+{
+ m_node = node;
+ // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
+ SetupLoopback ();
+}
+
+bool
+Ipv4L3ClickProtocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
+{
+ NS_LOG_FUNCTION (this << i << address);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ bool retVal = interface->AddAddress (address);
+ if (m_routingProtocol != 0)
+ {
+ m_routingProtocol->NotifyAddAddress (i, address);
+ }
+ return retVal;
+}
+
+Ipv4InterfaceAddress
+Ipv4L3ClickProtocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
+{
+ NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
+ Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
+ return interface->GetAddress (addressIndex);
+}
+
+uint32_t
+Ipv4L3ClickProtocol::GetNAddresses (uint32_t interface) const
+{
+ NS_LOG_FUNCTION (this << interface);
+ Ptr<Ipv4Interface> iface = GetInterface (interface);
+ return iface->GetNAddresses ();
+}
+
+bool
+Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
+{
+ NS_LOG_FUNCTION (this << i << addressIndex);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
+ if (address != Ipv4InterfaceAddress ())
+ {
+ if (m_routingProtocol != 0)
+ {
+ m_routingProtocol->NotifyRemoveAddress (i, address);
+ }
+ return true;
+ }
+ return false;
+}
+
+Ipv4Address
+Ipv4L3ClickProtocol::SelectSourceAddress (Ptr<const NetDevice> device,
+ Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
+{
+ NS_LOG_FUNCTION (device << dst << scope);
+ Ipv4Address addr ("0.0.0.0");
+ Ipv4InterfaceAddress iaddr;
+ bool found = false;
+
+ if (device != 0)
+ {
+ int32_t i = GetInterfaceForDevice (device);
+ NS_ASSERT_MSG (i >= 0, "No device found on node");
+ for (uint32_t j = 0; j < GetNAddresses (i); j++)
+ {
+ iaddr = GetAddress (i, j);
+ if (iaddr.IsSecondary ()) continue;
+ if (iaddr.GetScope () > scope) continue;
+ if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
+ {
+ return iaddr.GetLocal ();
+ }
+ if (!found)
+ {
+ addr = iaddr.GetLocal ();
+ found = true;
+ }
+ }
+ }
+ if (found)
+ {
+ return addr;
+ }
+
+ // Iterate among all interfaces
+ for (uint32_t i = 0; i < GetNInterfaces (); i++)
+ {
+ for (uint32_t j = 0; j < GetNAddresses (i); j++)
+ {
+ iaddr = GetAddress (i, j);
+ if (iaddr.IsSecondary ()) continue;
+ if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
+ && iaddr.GetScope () <= scope)
+ {
+ return iaddr.GetLocal ();
+ }
+ }
+ }
+ NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
+ << scope << ", returning 0");
+ return addr;
+}
+
+void
+Ipv4L3ClickProtocol::SetMetric (uint32_t i, uint16_t metric)
+{
+ NS_LOG_FUNCTION (i << metric);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetMetric (metric);
+}
+
+uint16_t
+Ipv4L3ClickProtocol::GetMetric (uint32_t i) const
+{
+ NS_LOG_FUNCTION (i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetMetric ();
+}
+
+uint16_t
+Ipv4L3ClickProtocol::GetMtu (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->GetDevice ()->GetMtu ();
+}
+
+bool
+Ipv4L3ClickProtocol::IsUp (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ return interface->IsUp ();
+}
+
+void
+Ipv4L3ClickProtocol::SetUp (uint32_t i)
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetUp ();
+
+ if (m_routingProtocol != 0)
+ {
+ m_routingProtocol->NotifyInterfaceUp (i);
+ }
+}
+
+void
+Ipv4L3ClickProtocol::SetDown (uint32_t ifaceIndex)
+{
+ NS_LOG_FUNCTION (this << ifaceIndex);
+ Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
+ interface->SetDown ();
+
+ if (m_routingProtocol != 0)
+ {
+ m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
+ }
+}
+
+bool
+Ipv4L3ClickProtocol::IsForwarding (uint32_t i) const
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
+ return interface->IsForwarding ();
+}
+
+void
+Ipv4L3ClickProtocol::SetForwarding (uint32_t i, bool val)
+{
+ NS_LOG_FUNCTION (this << i);
+ Ptr<Ipv4Interface> interface = GetInterface (i);
+ interface->SetForwarding (val);
+}
+
+uint32_t
+Ipv4L3ClickProtocol::AddInterface (Ptr<NetDevice> device)
+{
+ NS_LOG_FUNCTION (this << &device);
+
+ Ptr<Node> node = GetObject<Node> ();
+
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
+ Ipv4L3ClickProtocol::PROT_NUMBER, device);
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
+ ArpL3Protocol::PROT_NUMBER, device);
+
+ Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
+ interface->SetNode (m_node);
+ interface->SetDevice (device);
+ interface->SetForwarding (m_ipForward);
+ return AddIpv4Interface (interface);
+}
+
+uint32_t
+Ipv4L3ClickProtocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
+{
+ NS_LOG_FUNCTION (this << interface);
+ uint32_t index = m_interfaces.size ();
+ m_interfaces.push_back (interface);
+ return index;
+}
+
+// XXX when should we set ip_id? check whether we are incrementing
+// m_identification on packets that may later be dropped in this stack
+// and whether that deviates from Linux
+Ipv4Header
+Ipv4L3ClickProtocol::BuildHeader (
+ Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol,
+ uint16_t payloadSize,
+ uint8_t ttl,
+ bool mayFragment)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ipv4Header ipHeader;
+ ipHeader.SetSource (source);
+ ipHeader.SetDestination (destination);
+ ipHeader.SetProtocol (protocol);
+ ipHeader.SetPayloadSize (payloadSize);
+ ipHeader.SetTtl (ttl);
+ if (mayFragment == true)
+ {
+ ipHeader.SetMayFragment ();
+ ipHeader.SetIdentification (m_identification);
+ m_identification ++;
+ }
+ else
+ {
+ ipHeader.SetDontFragment ();
+ // TBD: set to zero here; will cause traces to change
+ ipHeader.SetIdentification (m_identification);
+ m_identification ++;
+ }
+ if (Node::ChecksumEnabled ())
+ {
+ ipHeader.EnableChecksum ();
+ }
+ return ipHeader;
+}
+
+void
+Ipv4L3ClickProtocol::Send (Ptr<Packet> packet,
+ Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol,
+ Ptr<Ipv4Route> route)
+{
+ NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
+
+ Ipv4Header ipHeader;
+ bool mayFragment = true;
+ uint8_t ttl = m_defaultTtl;
+ SocketIpTtlTag tag;
+ bool found = packet->RemovePacketTag (tag);
+ if (found)
+ {
+ ttl = tag.GetTtl ();
+ }
+
+ ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+ Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (m_routingProtocol);
+ if (Node::ChecksumEnabled ())
+ {
+ ipHeader.EnableChecksum ();
+ }
+ packet->AddHeader (ipHeader);
+ click->Send (packet->Copy (), source, destination);
+ return;
+}
+void
+Ipv4L3ClickProtocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
+ const Address &to, NetDevice::PacketType packetType)
+{
+ Ptr<Packet> packet = p->Copy ();
+
+ Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (GetRoutingProtocol ());
+ click->Receive (packet->Copy (), Mac48Address::ConvertFrom (device->GetAddress ()), Mac48Address::ConvertFrom (to));
+
+}
+
+void
+Ipv4L3ClickProtocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
+{
+ NS_LOG_FUNCTION (this << packet << &ip);
+ Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
+
+ m_localDeliverTrace (ip, packet, iif);
+
+ Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
+ if (protocol != 0)
+ {
+ // we need to make a copy in the unlikely event we hit the
+ // RX_ENDPOINT_UNREACH codepath
+ Ptr<Packet> copy = p->Copy ();
+ enum Ipv4L4Protocol::RxStatus status =
+ protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
+ switch (status) {
+ case Ipv4L4Protocol::RX_OK:
+ // fall through
+ case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
+ // fall through
+ case Ipv4L4Protocol::RX_CSUM_FAILED:
+ break;
+ case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
+ if (ip.GetDestination ().IsBroadcast () == true ||
+ ip.GetDestination ().IsMulticast () == true)
+ {
+ break; // Do not reply to broadcast or multicast
+ }
+ // Another case to suppress ICMP is a subnet-directed broadcast
+ bool subnetDirected = false;
+ for (uint32_t i = 0; i < GetNAddresses (iif); i++)
+ {
+ Ipv4InterfaceAddress addr = GetAddress (iif, i);
+ if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination().CombineMask (addr.GetMask ()) &&
+ ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
+ {
+ subnetDirected = true;
+ }
+ }
+ if (subnetDirected == false)
+ {
+ GetIcmp ()->SendDestUnreachPort (ip, copy);
+ }
+ }
+ }
+}
+
+Ptr<Icmpv4L4Protocol>
+Ipv4L3ClickProtocol::GetIcmp (void) const
+{
+ Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
+ if (prot != 0)
+ {
+ return prot->GetObject<Icmpv4L4Protocol> ();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void
+Ipv4L3ClickProtocol::Insert(Ptr<Ipv4L4Protocol> protocol)
+{
+ m_protocols.push_back (protocol);
+}
+
+Ptr<Ipv4L4Protocol>
+Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
+{
+ for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ {
+ if ((*i)->GetProtocolNumber () == protocolNumber)
+ {
+ return *i;
+ }
+ }
+ return 0;
+}
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-l3-click-protocol.h Thu Jun 10 19:59:22 2010 +0530
@@ -0,0 +1,149 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Lalith Suresh
+ *
+ * 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: Lalith Suresh <suresh.lalith@gmail.com>
+ */
+
+#include "ns3/ipv4.h"
+#include "ns3/net-device.h"
+#include "ns3/packet.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/traced-callback.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/log.h"
+
+namespace ns3{
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4RoutingTableEntry;
+class Ipv4Route;
+class Node;
+class Socket;
+class Ipv4RawSocketImpl;
+class Ipv4L4Protocol;
+class Icmpv4L4Protocol;
+
+class Ipv4L3ClickProtocol : public Ipv4
+{
+public:
+ static TypeId GetTypeId (void);
+ static const uint16_t PROT_NUMBER;
+
+ Ipv4L3ClickProtocol();
+ virtual ~Ipv4L3ClickProtocol();
+
+ // functions defined in base class Ipv4
+
+ void SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol);
+ Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (void) const;
+
+ void Insert(Ptr<Ipv4L4Protocol> protocol);
+
+ uint32_t AddInterface (Ptr<NetDevice> device);
+ Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
+ uint32_t GetNInterfaces (void) const;
+
+ int32_t GetInterfaceForAddress (Ipv4Address addr) const;
+ int32_t GetInterfaceForPrefix (Ipv4Address addr, Ipv4Mask mask) const;
+ int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
+ bool IsDestinationAddress (Ipv4Address address, uint32_t iif) const;
+
+ Ptr<Ipv4L4Protocol> GetProtocol(int protocolNumber) const;
+
+ Ptr<NetDevice> GetNetDevice (uint32_t i);
+
+ bool AddAddress (uint32_t i, Ipv4InterfaceAddress address);
+ Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
+ uint32_t GetNAddresses (uint32_t interface) const;
+ bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex);
+ Ipv4Address SelectSourceAddress (Ptr<const NetDevice> device,
+ Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope);
+
+ uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
+ void SetNode (Ptr<Node> node);
+
+ void SetMetric (uint32_t i, uint16_t metric);
+ uint16_t GetMetric (uint32_t i) const;
+ uint16_t GetMtu (uint32_t i) const;
+ bool IsUp (uint32_t i) const;
+ void SetUp (uint32_t i);
+ void SetDown (uint32_t i);
+ bool IsForwarding (uint32_t i) const;
+ void SetForwarding (uint32_t i, bool val);
+
+ Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
+ void SetupLoopback (void);
+
+ Ptr<Socket> CreateRawSocket (void);
+ void DeleteRawSocket (Ptr<Socket> socket);
+
+ void Send (Ptr<Packet> packet, Ipv4Address source,
+ Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route);
+ void Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
+ const Address &to, NetDevice::PacketType packetType);
+
+ void LocalDeliver (Ptr<const Packet> p, Ipv4Header const&ip, uint32_t iif);
+
+protected:
+
+ virtual void DoDispose (void);
+ /**
+ * This function will notify other components connected to the node that a new stack member is now connected
+ * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+ */
+ virtual void NotifyNewAggregate ();
+
+private:
+ Ipv4Header BuildHeader (
+ Ipv4Address source,
+ Ipv4Address destination,
+ uint8_t protocol,
+ uint16_t payloadSize,
+ uint8_t ttl,
+ bool mayFragment);
+
+ virtual void SetIpForward (bool forward);
+ virtual bool GetIpForward (void) const;
+ virtual void SetWeakEsModel (bool model);
+ virtual bool GetWeakEsModel (void) const;
+
+ typedef std::vector<Ptr<Ipv4Interface> > Ipv4InterfaceList;
+ typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
+ typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
+
+ Ptr<Ipv4RoutingProtocol> m_routingProtocol;
+ bool m_ipForward;
+ bool m_weakEsModel;
+ L4List_t m_protocols;
+ Ipv4InterfaceList m_interfaces;
+ uint8_t m_defaultTtl;
+ uint16_t m_identification;
+
+ Ptr<Node> m_node;
+
+ TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_sendOutgoingTrace;
+ TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_unicastForwardTrace;
+ TracedCallback<const Ipv4Header &, Ptr<const Packet>, uint32_t> m_localDeliverTrace;
+
+ SocketList m_sockets;
+};
+
+} //namespace ns3
--- a/src/internet-stack/ipv4-l3-protocol.cc Tue Jun 08 11:46:17 2010 +0530
+++ b/src/internet-stack/ipv4-l3-protocol.cc Thu Jun 10 19:59:22 2010 +0530
@@ -32,7 +32,6 @@
#include "ns3/ipv4-header.h"
#include "ns3/boolean.h"
#include "ns3/ipv4-routing-table-entry.h"
-#include "ns3/ipv4-click-routing.h"
#include "loopback-net-device.h"
#include "arp-l3-protocol.h"
@@ -251,21 +250,10 @@
NS_LOG_FUNCTION (this << &device);
Ptr<Node> node = GetObject<Node> ();
-
- if (DynamicCast<Ipv4ClickRouting> (GetRoutingProtocol ()))
- {
- node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::ReceiveExternal, this),
- Ipv4L3Protocol::PROT_NUMBER, device);
- node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::ReceiveExternal, this),
- ArpL3Protocol::PROT_NUMBER, device);
- }
- else
- {
- node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
- Ipv4L3Protocol::PROT_NUMBER, device);
- node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
- ArpL3Protocol::PROT_NUMBER, device);
- }
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
+ Ipv4L3Protocol::PROT_NUMBER, device);
+ node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
+ ArpL3Protocol::PROT_NUMBER, device);
Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
interface->SetNode (m_node);
@@ -432,24 +420,6 @@
return false;
}
-void
-Ipv4L3Protocol::ReceiveExternal ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
- const Address &to, NetDevice::PacketType packetType)
-{
- Ptr<Packet> packet = p->Copy ();
-/*
- EthernetHeader ethHeader;
- ethHeader.SetSource (Mac48Address::ConvertFrom (from));
- ethHeader.SetDestination (Mac48Address::ConvertFrom (to));
- ethHeader.SetLengthType (protocol);
- packet->AddHeader (ethHeader);
-*/
- // If using an external router, we send the packet to it for handling.
- Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (GetRoutingProtocol ());
- click->Receive (packet->Copy (), Mac48Address::ConvertFrom (device->GetAddress ()), Mac48Address::ConvertFrom (to));
-}
-
-
void
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
@@ -562,18 +532,6 @@
ttl = tag.GetTtl ();
}
- if (DynamicCast<Ipv4ClickRouting> (m_routingProtocol))
- {
- Ipv4Header ipHeader;
- ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
- Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (m_routingProtocol);
- ipHeader.EnableChecksum ();
- packet->AddHeader (ipHeader);
- click->Send (packet->Copy (), source, destination);
- return;
- }
-
-
// Handle a few cases:
// 1) packet is destined to limited broadcast address
// 2) packet is destined to a subnet-directed broadcast address
@@ -832,12 +790,6 @@
}
void
-Ipv4L3Protocol::LocalDeliverFromExternal (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
-{
- LocalDeliver (packet, ip, iif);
-}
-
-void
Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
{
NS_LOG_FUNCTION (this << packet << &ip);
--- a/src/internet-stack/ipv4-l3-protocol.h Tue Jun 08 11:46:17 2010 +0530
+++ b/src/internet-stack/ipv4-l3-protocol.h Thu Jun 10 19:59:22 2010 +0530
@@ -150,11 +150,6 @@
void Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType);
- void ReceiveExternal( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
- const Address &to, NetDevice::PacketType packetType);
-
- void LocalDeliverFromExternal (Ptr<const Packet> p, Ipv4Header const&ip, uint32_t iif);
-
/**
* \param packet packet to send
* \param source source address of packet
--- a/src/internet-stack/tcp-l4-protocol.cc Tue Jun 08 11:46:17 2010 +0530
+++ b/src/internet-stack/tcp-l4-protocol.cc Thu Jun 10 19:59:22 2010 +0530
@@ -34,6 +34,7 @@
#include "ipv4-end-point-demux.h"
#include "ipv4-end-point.h"
#include "ipv4-l3-protocol.h"
+#include "ipv4-l3-click-protocol.h"
#include "tcp-socket-factory-impl.h"
#include "tcp-socket-impl.h"
#include "rtt-estimator.h"
@@ -379,11 +380,23 @@
Ptr<Node> node = this->GetObject<Node> ();
if (node != 0)
{
- Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (this->GetObject<Ipv4> ()))
+ isClickNode = true;
+
+ Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
if (ipv4 != 0)
{
this->SetNode (node);
- ipv4->Insert (this);
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Insert (this);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Insert (this);
+ }
Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
tcpFactory->SetTcp (this);
node->AggregateObject (tcpFactory);
@@ -575,8 +588,12 @@
packet->AddHeader (tcpHeader);
- Ptr<Ipv4L3Protocol> ipv4 =
- m_node->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (ipv4))
+ isClickNode = true;
+
if (ipv4 != 0)
{
// XXX We've already performed the route lookup in TcpSocketImpl
@@ -596,7 +613,15 @@
NS_LOG_ERROR ("No IPV4 Routing Protocol");
route = 0;
}
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
+
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
}
}
@@ -623,8 +648,12 @@
packet->AddHeader (outgoingHeader);
- Ptr<Ipv4L3Protocol> ipv4 =
- m_node->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (ipv4))
+ isClickNode = true;
+
if (ipv4 != 0)
{
// XXX We've already performed the route lookup in TcpSocketImpl
@@ -643,7 +672,15 @@
NS_LOG_ERROR ("No IPV4 Routing Protocol");
route = 0;
}
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
+
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
}
else
NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
--- a/src/internet-stack/udp-l4-protocol.cc Tue Jun 08 11:46:17 2010 +0530
+++ b/src/internet-stack/udp-l4-protocol.cc Thu Jun 10 19:59:22 2010 +0530
@@ -31,6 +31,7 @@
#include "ipv4-end-point-demux.h"
#include "ipv4-end-point.h"
#include "ipv4-l3-protocol.h"
+#include "ipv4-l3-click-protocol.h"
#include "udp-socket-impl.h"
NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol");
@@ -82,11 +83,24 @@
Ptr<Node> node = this->GetObject<Node> ();
if (node != 0)
{
- Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (this->GetObject<Ipv4> ()))
+ isClickNode = true;
+
+ Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
+
if (ipv4 != 0)
{
this->SetNode (node);
- ipv4->Insert (this);
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Insert (this);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Insert (this);
+ }
Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
udpFactory->SetUdp (this);
node->AggregateObject (udpFactory);
@@ -255,12 +269,24 @@
packet->AddHeader (udpHeader);
- Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (ipv4))
+ isClickNode = true;
+
if (ipv4 != 0)
{
NS_LOG_LOGIC ("Sending to IP");
// Send with null route
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER, 0);
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, 0);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, 0);
+ }
}
}
@@ -284,11 +310,23 @@
packet->AddHeader (udpHeader);
- Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+ bool isClickNode = false;
+ Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+ if (DynamicCast<Ipv4L3ClickProtocol> (ipv4))
+ isClickNode = true;
+
if (ipv4 != 0)
{
NS_LOG_LOGIC ("Sending to IP");
- ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ if (!isClickNode)
+ {
+ DynamicCast<Ipv4L3Protocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
+ else
+ {
+ DynamicCast<Ipv4L3ClickProtocol> (ipv4)->Send (packet, saddr, daddr, PROT_NUMBER, route);
+ }
}
}
--- a/src/internet-stack/wscript Tue Jun 08 11:46:17 2010 +0530
+++ b/src/internet-stack/wscript Thu Jun 10 19:59:22 2010 +0530
@@ -81,6 +81,7 @@
'tcp-header.cc',
'ipv4-interface.cc',
'ipv4-l3-protocol.cc',
+ 'ipv4-l3-click-protocol.cc',
'ipv4-end-point.cc',
'udp-l4-protocol.cc',
'tcp-l4-protocol.cc',
@@ -132,6 +133,7 @@
# used by routing
'ipv4-interface.h',
'ipv4-l3-protocol.h',
+ 'ipv4-l3-click-protocol.h',
'ipv6-l3-protocol.h',
'ipv6-extension-header.h',
'ipv6-option-header.h',
--- a/src/routing/click/ipv4-click-routing.cc Tue Jun 08 11:46:17 2010 +0530
+++ b/src/routing/click/ipv4-click-routing.cc Thu Jun 10 19:59:22 2010 +0530
@@ -27,8 +27,7 @@
#include "ns3/mac48-address.h"
#include "ns3/ethernet-header.h"
#include "ns3/ipv4-interface.h"
-#include "ns3/ipv4-l3-protocol.h"
-#include "ns3/arp-l3-protocol.h"
+#include "ns3/ipv4-l3-click-protocol.h"
#include "ns3/llc-snap-header.h"
#include "ipv4-click-routing.h"
@@ -256,14 +255,14 @@
if (ifid == 0)
{
NS_LOG_DEBUG ("Incoming packet from tap0. Sending Packet up the stack.");
- Ptr<Ipv4L3Protocol> ipv4l3 = DynamicCast<Ipv4L3Protocol> (m_ipv4);
+ Ptr<Ipv4L3ClickProtocol> ipv4l3 = DynamicCast<Ipv4L3ClickProtocol> (m_ipv4);
Ptr<Packet> p = Create<Packet> (data, len);
Ipv4Header ipHeader;
p->RemoveHeader (ipHeader);
- ipv4l3->LocalDeliverFromExternal (p, ipHeader, (uint32_t) ifid);
+ ipv4l3->LocalDeliver (p, ipHeader, (uint32_t) ifid);
}
else if (ifid)
{