--- a/src/internet-stack/ipv4-l3-protocol.cc Thu May 28 20:16:56 2009 +0200
+++ b/src/internet-stack/ipv4-l3-protocol.cc Thu May 28 21:37:25 2009 -0700
@@ -31,14 +31,16 @@
#include "ns3/object-vector.h"
#include "ns3/ipv4-header.h"
#include "ns3/boolean.h"
+#include "ns3/ipv4-routing-table-entry.h"
+#include "ns3/ipv4-static-routing.h"
+
+#include "loopback-net-device.h"
#include "arp-l3-protocol.h"
-
#include "ipv4-l3-protocol.h"
#include "ipv4-l4-protocol.h"
+#include "ipv4-list-routing-impl.h"
#include "icmpv4-l4-protocol.h"
#include "ipv4-interface.h"
-#include "ipv4-loopback-interface.h"
-#include "arp-ipv4-interface.h"
#include "ipv4-raw-socket-impl.h"
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
@@ -83,8 +85,6 @@
m_identification (0)
{
NS_LOG_FUNCTION_NOARGS ();
- m_staticRouting = CreateObject<Ipv4StaticRouting> ();
- AddRoutingProtocol (m_staticRouting, 0);
}
Ipv4L3Protocol::~Ipv4L3Protocol ()
@@ -119,6 +119,7 @@
Ipv4L3Protocol::SetNode (Ptr<Node> node)
{
m_node = node;
+ // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
SetupLoopback ();
}
@@ -145,18 +146,48 @@
}
return;
}
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the ipv4 stack
+ */
+void
+Ipv4L3Protocol::NotifyNewAggregate ()
+{
+ 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 && m_node == 0)
+ {
+ this->SetNode (node);
+ }
+ Object::NotifyNewAggregate ();
+}
+
+void
+Ipv4L3Protocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routing)
+{
+ NS_LOG_FUNCTION (this);
+ m_routingProtocol = routing;
+ // XXX should check all interfaces to see if any were set to Up state
+ // prior to a routing protocol being added
+ if (GetStaticRouting () != 0)
+ {
+ GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), 0);
+ }
+}
+
+
+Ptr<Ipv4RoutingProtocol>
+Ipv4L3Protocol::GetRoutingProtocol (void) const
+{
+ return m_routingProtocol;
+}
void
Ipv4L3Protocol::DoDispose (void)
{
NS_LOG_FUNCTION (this);
-
- for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
- {
- *i = 0;
- }
-
- for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
{
*i = 0;
}
@@ -167,10 +198,12 @@
*i = 0;
}
m_interfaces.clear ();
- m_routingProtocols.clear ();
m_node = 0;
- m_staticRouting->Dispose ();
- m_staticRouting = 0;
+ if (m_routingProtocol)
+ {
+ m_routingProtocol->Dispose ();
+ m_routingProtocol = 0;
+ }
Object::DoDispose ();
}
@@ -179,12 +212,33 @@
{
NS_LOG_FUNCTION_NOARGS ();
- Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
+ 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);
- AddHostRouteTo (Ipv4Address::GetLoopback (), index);
+ Ptr<Node> node = GetObject<Node> ();
+ node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
+ Ipv4L3Protocol::PROT_NUMBER, device);
+ if (GetStaticRouting () != 0)
+ {
+ GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), index);
+ }
interface->SetUp ();
}
@@ -195,192 +249,24 @@
m_defaultTtl = ttl;
}
-
-void
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << dest << nextHop << interface);
- m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << dest << interface);
- m_staticRouting->AddHostRouteTo (dest, interface);
-}
-
-void
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
- m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network,
- Ipv4Mask networkMask,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << network << networkMask << interface);
- m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
-}
-
-void
-Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop,
- uint32_t interface)
-{
- NS_LOG_FUNCTION (this << nextHop << interface);
- m_staticRouting->SetDefaultRoute (nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::Lookup (
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
- NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
-
- Lookup (Ipv4RoutingProtocol::INTERFACE_ANY, ipHeader, packet, routeReply);
-}
-
-void
-Ipv4L3Protocol::Lookup (
- uint32_t interface,
- Ipv4Header const &ipHeader,
- Ptr<Packet> packet,
- Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
- NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
-
- for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
- m_routingProtocols.begin ();
- rprotoIter != m_routingProtocols.end ();
- rprotoIter++)
- {
- NS_LOG_LOGIC ("Requesting route");
- if ((*rprotoIter).second->RequestRoute (interface, ipHeader, packet,
- routeReply))
- return;
- }
-
- if (ipHeader.GetDestination ().IsMulticast () &&
- interface == Ipv4RoutingProtocol::INTERFACE_ANY)
- {
- NS_LOG_LOGIC ("Multicast destination with local source");
-//
-// We have a multicast packet originating from the current node and were not
-// able to send it using the usual RequestRoute process. Since the usual
-// process includes trying to use a default multicast route, this means that
-// there was no specific route out of the node found, and there was no default
-// multicast route set.
-//
-// The fallback position is to look for a default unicast route and use that
-// to get the packet off the node if we have one.
-//
- Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
- if (route)
- {
- NS_LOG_LOGIC ("Local source. Using unicast default route for "
- "multicast packet");
-
- routeReply (true, *route, packet, ipHeader);
- return;
- }
- }
-//
-// No route found
-//
- routeReply (false, Ipv4Route (), packet, ipHeader);
-}
-
-void
-Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
- int16_t priority)
-{
- NS_LOG_FUNCTION (this << &routingProtocol << priority);
- m_routingProtocols.push_back
- (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
- m_routingProtocols.sort ();
-}
-
-uint32_t
-Ipv4L3Protocol::GetNRoutes (void)
+// XXX need to remove dependencies on Ipv4StaticRouting from this class
+Ptr<Ipv4StaticRouting>
+Ipv4L3Protocol::GetStaticRouting (void) const
{
NS_LOG_FUNCTION_NOARGS ();
- return m_staticRouting->GetNRoutes ();
-}
-
-Ipv4Route
-Ipv4L3Protocol::GetRoute (uint32_t index)
-{
- NS_LOG_FUNCTION_NOARGS ();
- return *m_staticRouting->GetRoute (index);
-}
-
-void
-Ipv4L3Protocol::RemoveRoute (uint32_t index)
-{
- NS_LOG_FUNCTION (this << index);
- m_staticRouting->RemoveRoute (index);
-}
-
-void
-Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface,
- std::vector<uint32_t> outputInterfaces)
-{
- NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
-
- m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
- outputInterfaces);
-}
-
-void
-Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
-{
- NS_LOG_FUNCTION (this << outputInterface);
-
- m_staticRouting->SetDefaultMulticastRoute (outputInterface);
-}
-
-uint32_t
-Ipv4L3Protocol::GetNMulticastRoutes (void) const
-{
- NS_LOG_FUNCTION_NOARGS ();
- return m_staticRouting->GetNMulticastRoutes ();
-}
-
-Ipv4MulticastRoute
-Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
-{
- NS_LOG_FUNCTION (this << index);
- return *m_staticRouting->GetMulticastRoute (index);
-}
-
-void
-Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
- Ipv4Address group,
- uint32_t inputInterface)
-{
- NS_LOG_FUNCTION (this << origin << group << inputInterface);
- m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
-}
-
-void
-Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
-{
- NS_LOG_FUNCTION (this << index);
- m_staticRouting->RemoveMulticastRoute (index);
+ Ptr<Ipv4StaticRouting> staticRouting;
+ if (m_routingProtocol != 0)
+ {
+ Ptr<Ipv4StaticRoutingImpl> sr = DynamicCast<Ipv4StaticRoutingImpl> (m_routingProtocol);
+ if (sr != 0)
+ {
+ return sr;
+ }
+ Ptr<Ipv4ListRoutingImpl> lr = DynamicCast<Ipv4ListRoutingImpl> (m_routingProtocol);
+ NS_ASSERT (lr);
+ staticRouting = lr->GetStaticRouting ();
+ }
+ return staticRouting;
}
uint32_t
@@ -394,7 +280,7 @@
node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
ArpL3Protocol::PROT_NUMBER, device);
- Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
+ Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
interface->SetNode (m_node);
interface->SetDevice (device);
return AddIpv4Interface (interface);
@@ -433,60 +319,60 @@
return m_nInterfaces;
}
-uint32_t
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
+int32_t
+Ipv4L3Protocol::GetInterfaceForAddress (
+ Ipv4Address address) const
{
- NS_LOG_FUNCTION (this << addr);
+ NS_LOG_FUNCTION (this << address);
- uint32_t interface = 0;
+ 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++)
+ for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
{
- if ((*i)->GetAddress (j).GetLocal () == addr)
+ if ((*i)->GetAddress (j).GetLocal () == address)
{
return interface;
}
}
}
- NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
- "Interface not found for IP address " << addr);
- return 0;
+ return -1;
}
-uint32_t
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
+int32_t
+Ipv4L3Protocol::GetInterfaceForPrefix (
+ Ipv4Address address,
+ Ipv4Mask mask) const
{
- NS_LOG_FUNCTION (this << addr << mask);
+ NS_LOG_FUNCTION (this << address << mask);
- uint32_t interface = 0;
+ 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) == addr.CombineMask (mask))
+ if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
{
return interface;
}
}
}
- NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
- "Interface not found for masked IP address");
- return 0;
+ return -1;
}
int32_t
-Ipv4L3Protocol::FindInterfaceForDevice (Ptr<NetDevice> device) const
+Ipv4L3Protocol::GetInterfaceForDevice (
+ Ptr<const NetDevice> device) const
{
- NS_LOG_FUNCTION (this << device);
+ NS_LOG_FUNCTION (this << device->GetIfIndex());
- uint32_t interface = 0;
+ int32_t interface = 0;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
i++, interface++)
@@ -500,31 +386,18 @@
return -1;
}
-Ptr<Ipv4Interface>
-Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
-{
- NS_LOG_FUNCTION (this << &device);
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
- {
- if ((*i)->GetDevice () == device)
- {
- return *i;
- }
- }
- return 0;
-}
-
void
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
NS_LOG_FUNCTION (this << &device << p << protocol << from);
- NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
+ NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
+ m_node->GetId ());
+ uint32_t interface = 0;
Ptr<Packet> packet = p->Copy ();
- uint32_t index = 0;
Ptr<Ipv4Interface> ipv4Interface;
for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
i != m_interfaces.end ();
@@ -535,9 +408,9 @@
{
if (ipv4Interface->IsUp ())
{
- m_rxTrace (packet, index);
+ m_rxTrace (packet, interface);
break;
- }
+ }
else
{
NS_LOG_LOGIC ("Dropping received packet-- interface is down");
@@ -545,8 +418,9 @@
return;
}
}
- index++;
+ interface++;
}
+
Ipv4Header ipHeader;
if (m_calcChecksum)
{
@@ -566,12 +440,13 @@
socket->ForwardUp (packet, ipHeader, device);
}
- if (Forwarding (index, packet, ipHeader, device))
- {
- return;
- }
+ m_routingProtocol->RouteInput (packet, ipHeader, device,
+ MakeCallback (&Ipv4L3Protocol::IpForward, this),
+ MakeCallback (&Ipv4L3Protocol::IpMulticastForward, this),
+ MakeCallback (&Ipv4L3Protocol::LocalDeliver, this),
+ MakeNullCallback <void, Ptr<const Packet>, const Ipv4Header &> ()
+ );
- ForwardUp (packet, ipHeader, ipv4Interface);
}
Ptr<Icmpv4L4Protocol>
@@ -598,75 +473,35 @@
Ipv4L3Protocol::Send (Ptr<Packet> packet,
Ipv4Address source,
Ipv4Address destination,
- uint8_t protocol)
+ uint8_t protocol,
+ Ptr<Ipv4Route> route)
{
- NS_LOG_FUNCTION (this << packet << source << destination << protocol);
+ NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
Ipv4Header ipHeader;
-
- if (m_calcChecksum)
- {
- ipHeader.EnableChecksum ();
- }
-
- ipHeader.SetSource (source);
- ipHeader.SetDestination (destination);
- ipHeader.SetProtocol (protocol);
- ipHeader.SetPayloadSize (packet->GetSize ());
- ipHeader.SetIdentification (m_identification);
-
- m_identification ++;
-
- SocketSetDontFragmentTag dfTag;
- bool found = packet->FindFirstMatchingTag (dfTag);
+ bool mayFragment = true;
+ uint8_t ttl = m_defaultTtl;
+ SocketIpTtlTag tag;
+ bool found = packet->FindFirstMatchingTag (tag);
if (found)
{
- if (dfTag.IsEnabled ())
- {
- ipHeader.SetDontFragment ();
- }
- else
- {
- ipHeader.SetMayFragment ();
- }
+ ttl = tag.GetTtl ();
+ // XXX remove tag here?
}
+
+ // Handle a few cases:
+ // 1) packet is destined to limited broadcast address
+ // 2) packet is destined to a subnet-directed broadcast address
+ // 3) packet is not broadcast, and is passed in with a route entry
+ // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
+ // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
-
- // Set TTL to 1 if it is a broadcast packet of any type. Otherwise,
- // possibly override the default TTL if the packet is tagged
- SocketIpTtlTag tag;
- found = packet->FindFirstMatchingTag (tag);
-
+ // 1) packet is destined to limited broadcast address
if (destination.IsBroadcast ())
{
- ipHeader.SetTtl (1);
- }
- else if (found)
- {
- ipHeader.SetTtl (tag.GetTtl ());
- // XXX remove tag here?
- }
- else
- {
- ipHeader.SetTtl (m_defaultTtl);
- uint32_t ifaceIndex = 0;
- for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
- ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
- {
- Ptr<Ipv4Interface> outInterface = *ifaceIter;
- // XXX this logic might not be completely correct for multi-addressed interface
- for (uint32_t j = 0; j < outInterface->GetNAddresses(); j++)
- {
- if (destination.IsSubnetDirectedBroadcast (
- outInterface->GetAddress (j).GetMask ()))
- {
- ipHeader.SetTtl (1);
- }
- }
- }
- }
- if (destination.IsBroadcast ())
- {
+ NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
+ ttl = 1;
+ ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
uint32_t ifaceIndex = 0;
for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
@@ -674,209 +509,216 @@
Ptr<Ipv4Interface> outInterface = *ifaceIter;
Ptr<Packet> packetCopy = packet->Copy ();
+ NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
packetCopy->AddHeader (ipHeader);
- // XXX Handle multiple address on interface
- if (packetCopy->GetSize () > outInterface->GetMtu () &&
- ipHeader.IsDontFragment () &&
- IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
- {
- Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
- NS_ASSERT (icmp != 0);
- icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ());
- m_dropTrace (packetCopy);
- }
- else if (packet->GetSize () > outInterface->GetMtu () &&
- !ipHeader.IsDontFragment ())
+ m_txTrace (packetCopy, ifaceIndex);
+ outInterface->Send (packetCopy, destination);
+ }
+ return;
+ }
+
+ // 2) check: packet is destined to a subnet-directed broadcast address
+ uint32_t ifaceIndex = 0;
+ for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+ ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+ {
+ Ptr<Ipv4Interface> outInterface = *ifaceIter;
+ for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
+ {
+ Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
+ NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
+ if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
+ destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
{
- NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
- m_dropTrace (packet);
- }
- else
- {
- NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
- if (outInterface->IsUp ())
- {
- m_txTrace (packetCopy, ifaceIndex);
- outInterface->Send (packetCopy, destination);
- }
- else
- {
- m_dropTrace (packetCopy);
- }
+ NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
+ ttl = 1;
+ ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+ Ptr<Packet> packetCopy = packet->Copy ();
+ packetCopy->AddHeader (ipHeader);
+ m_txTrace (packetCopy, ifaceIndex);
+ outInterface->Send (packetCopy, destination);
+ return;
}
}
}
+
+ // 3) packet is not broadcast, and is passed in with a route entry
+ // with a valid Ipv4Address as the gateway
+ if (route && route->GetGateway () != Ipv4Address ())
+ {
+ NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
+ ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+ SendRealOut (route, packet, ipHeader);
+ return;
+ }
+ // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
+ if (route && route->GetGateway () != Ipv4Address ())
+ {
+ // This could arise because the synchronous RouteOutput() call
+ // returned to the transport protocol with a source address but
+ // there was no next hop available yet (since a route may need
+ // to be queried). So, call asynchronous version of RouteOutput?
+ NS_FATAL_ERROR("XXX This case not yet implemented");
+ }
+ // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
+ NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: passed in with no route " << destination);
+ Socket::SocketErrno errno;
+ uint32_t oif = 0; // unused for now
+ ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+ Ptr<Ipv4Route> newRoute = m_routingProtocol->RouteOutput (ipHeader, oif, errno);
+ if (newRoute)
+ {
+ SendRealOut (newRoute, packet, ipHeader);
+ }
else
{
- // 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.
- Lookup (ipHeader, packet,
- MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+ NS_LOG_WARN ("No route to host. Drop.");
+ m_dropTrace (packet);
}
}
+// 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
+Ipv4L3Protocol::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 (m_calcChecksum)
+ {
+ ipHeader.EnableChecksum ();
+ }
+ return ipHeader;
+}
+
void
-Ipv4L3Protocol::SendRealOut (bool found,
- Ipv4Route const &route,
+Ipv4L3Protocol::SendRealOut (Ptr<Ipv4Route> route,
Ptr<Packet> packet,
Ipv4Header const &ipHeader)
{
- NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
+ NS_LOG_FUNCTION (this << packet << &ipHeader);
+ // We add a header regardless of whether there is a route, since
+ // we may want to drop trace
packet->AddHeader (ipHeader);
- if (!found)
+ if (route == 0)
{
NS_LOG_WARN ("No route to host. Drop.");
m_dropTrace (packet);
return;
}
- NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
+ Ptr<NetDevice> outDev = route->GetOutputDevice ();
+ int32_t interface = GetInterfaceForDevice (outDev);
+ NS_ASSERT (interface >= 0);
+ Ptr<Ipv4Interface> outInterface = GetInterface (interface);
+ NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
- Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
- // XXX handle multiple address on interface
- if (packet->GetSize () > outInterface->GetMtu () &&
- ipHeader.IsDontFragment () &&
- IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
- {
- NS_LOG_LOGIC ("Too big: need fragmentation but not allowed");
- Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
- NS_ASSERT (icmp != 0);
- Ptr<Packet> copyNoHeader = packet->Copy ();
- Ipv4Header tmp;
- copyNoHeader->RemoveHeader (tmp);
- icmp->SendDestUnreachFragNeeded (ipHeader, copyNoHeader, outInterface->GetMtu ());
- m_dropTrace (packet);
- }
- else if (packet->GetSize () > outInterface->GetMtu () &&
- !ipHeader.IsDontFragment ())
- {
- NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
- m_dropTrace (packet);
- }
- else
+ NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
+ if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
{
- if (route.IsGateway ())
+ if (outInterface->IsUp ())
+ {
+ NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
+ m_txTrace (packet, interface);
+ outInterface->Send (packet, route->GetGateway ());
+ }
+ else
{
- if (outInterface->IsUp ())
- {
- NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
- m_txTrace (packet, route.GetInterface ());
- outInterface->Send (packet, route.GetGateway ());
- }
- else
- {
- NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
- m_dropTrace (packet);
- }
- }
- else
+ NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
+ m_dropTrace (packet);
+ }
+ }
+ else
+ {
+ if (outInterface->IsUp ())
{
- if (outInterface->IsUp ())
- {
- NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
- m_txTrace (packet, route.GetInterface ());
- outInterface->Send (packet, ipHeader.GetDestination ());
- }
- else
- {
- NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
- m_dropTrace (packet);
- }
+ NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
+ m_txTrace (packet, interface);
+ outInterface->Send (packet, ipHeader.GetDestination ());
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
+ m_dropTrace (packet);
}
}
}
-bool
-Ipv4L3Protocol::Forwarding (
- uint32_t interface,
- Ptr<Packet> packet,
- Ipv4Header &ipHeader,
- Ptr<NetDevice> device)
+// This function analogous to Linux ip_mr_forward()
+void
+Ipv4L3Protocol::IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv4Header &header)
{
- NS_LOG_FUNCTION (interface << packet << &ipHeader<< device);
- NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
-
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end (); i++)
+ NS_LOG_FUNCTION (mrtentry << p << header);
+ NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
+ // The output interfaces we could forward this onto are encoded
+ // in the OutputTtl of the Ipv4MulticastRoute
+ for (uint32_t i = 0; i < Ipv4MulticastRoute::MAX_INTERFACES; i++)
{
- for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
+ if (mrtentry->GetOutputTtl (i) < Ipv4MulticastRoute::MAX_TTL)
{
- if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ()))
+ Ptr<Packet> packet = p->Copy ();
+ Ipv4Header h = header;
+ h.SetTtl (header.GetTtl () - 1);
+ if (h.GetTtl () == 0)
{
- NS_LOG_LOGIC ("For me (destination match)");
- return false;
+ NS_LOG_WARN ("TTL exceeded. Drop.");
+ m_dropTrace (packet);
+ return;
}
+ NS_LOG_LOGIC ("Forward multicast via interface " << i);
+ Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
+ rtentry->SetSource (h.GetSource ());
+ rtentry->SetDestination (h.GetDestination ());
+ rtentry->SetGateway (Ipv4Address::GetAny ());
+ rtentry->SetOutputDevice (GetNetDevice (i));
+ SendRealOut (rtentry, packet, h);
+ return;
}
}
-
- for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
- i != m_interfaces.end (); i++)
- {
- Ptr<Ipv4Interface> interface = *i;
- if (interface->GetDevice () == device)
- {
- // XXX multi-address case
- if (ipHeader.GetDestination ().IsEqual (interface->GetAddress (0).GetBroadcast ()))
- {
- NS_LOG_LOGIC ("For me (interface broadcast address)");
- return false;
- }
- break;
- }
- }
-
- if (ipHeader.GetDestination ().IsBroadcast ())
- {
- NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
- return false;
- }
-
- if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ()))
- {
- NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
- return false;
- }
-//
-// If this is a to a multicast address and this node is a member of the
-// indicated group we need to return false so the multicast is forwarded up.
-//
- for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
- i != m_multicastGroups.end (); i++)
- {
- if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
- (*i).second.IsEqual (ipHeader.GetDestination ()))
- {
- NS_LOG_LOGIC ("For me (Joined multicast group)");
- // We forward with a packet copy, since forwarding may change
- // the packet, affecting our local delivery
- NS_LOG_LOGIC ("Forwarding (multicast).");
- DoForward (interface, packet->Copy (), ipHeader);
- return false;
- }
- }
-
- DoForward (interface, packet, ipHeader);
- return true;
}
+// This function analogous to Linux ip_forward()
void
-Ipv4L3Protocol::DoForward (uint32_t interface,
- Ptr<Packet> packet,
- Ipv4Header ipHeader)
+Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ipv4Header &header)
{
- NS_LOG_FUNCTION (this << interface << packet << ipHeader);
-
+ NS_LOG_FUNCTION (rtentry << p << header);
+ NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
+ // Forwarding
+ Ipv4Header ipHeader = header;
+ Ptr<Packet> packet = p->Copy ();
ipHeader.SetTtl (ipHeader.GetTtl () - 1);
// XXX handle multi-interfaces
if (ipHeader.GetTtl () == 0)
{
+ Ptr<NetDevice> outDev = rtentry->GetOutputDevice ();
+ int32_t interface = GetInterfaceForDevice (outDev);
+ NS_ASSERT (interface >= 0);
if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ()))
{
Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
@@ -885,18 +727,15 @@
NS_LOG_WARN ("TTL exceeded. Drop.");
m_dropTrace (packet);
return;
- }
- NS_LOG_LOGIC ("Not for me, forwarding.");
- Lookup (interface, ipHeader, packet,
- MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+ }
+ SendRealOut (rtentry, packet, ipHeader);
}
-
void
-Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
- Ptr<Ipv4Interface> incomingInterface)
+Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
{
- NS_LOG_FUNCTION (this << p << &ip);
+ NS_LOG_FUNCTION (this << packet << &ip);
+ Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
if (protocol != 0)
@@ -905,15 +744,15 @@
// RX_ENDPOINT_UNREACH codepath
Ptr<Packet> copy = p->Copy ();
enum Ipv4L4Protocol::RxStatus status =
- protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
+ protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
switch (status) {
case Ipv4L4Protocol::RX_OK:
// fall through
case Ipv4L4Protocol::RX_CSUM_FAILED:
break;
case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
- // XXX handle multi-interface case
- if (IsUnicast (ip.GetDestination (), incomingInterface->GetAddress (0).GetMask ()))
+ // XXX handle multi-interfaces
+ if (IsUnicast (ip.GetDestination (), GetInterface (iif)->GetAddress (0).GetMask ()))
{
GetIcmp ()->SendDestUnreachPort (ip, copy);
}
@@ -922,32 +761,7 @@
}
}
-void
-Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- NS_LOG_FUNCTION (this << origin << group);
- m_multicastGroups.push_back(
- std::pair<Ipv4Address, Ipv4Address> (origin, group));
-}
-
-void
-Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
- NS_LOG_FUNCTION (this << origin << group);
-
- for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
- i != m_multicastGroups.end ();
- i++)
- {
- if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
- {
- m_multicastGroups.erase (i);
- return;
- }
- }
-}
-
-uint32_t
+uint32_t
Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
{
NS_LOG_FUNCTION (this << i << address);
@@ -955,7 +769,7 @@
return interface->AddAddress (address);
}
-Ipv4InterfaceAddress
+Ipv4InterfaceAddress
Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
{
NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
@@ -963,7 +777,7 @@
return interface->GetAddress (addressIndex);
}
-uint32_t
+uint32_t
Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
{
NS_LOG_FUNCTION (this << interface);
@@ -987,76 +801,6 @@
return interface->GetMetric ();
}
-bool
-Ipv4L3Protocol::GetInterfaceForDestination (
- Ipv4Address destination, uint32_t& interface) const
-{
- NS_LOG_FUNCTION (this << destination << &interface);
-//
-// The first thing we do in trying to determine a source address is to
-// consult the routing protocols. These will also check for a default route
-// if one has been set.
-//
- for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
- i != m_routingProtocols.end ();
- i++)
- {
- NS_LOG_LOGIC ("Requesting Source Address");
- uint32_t interfaceTmp;
-
- if ((*i).second->RequestInterface (destination, interfaceTmp))
- {
- NS_LOG_LOGIC ("Found interface " << interfaceTmp);
- interface = interfaceTmp;
- return true;
- }
- }
-//
-// If there's no routing table entry telling us what *single* interface will
-// be used to send a packet to this destination, we'll have to just pick one.
-// If there's only one interface on this node, a good answer isn't very hard
-// to come up with. Before jumping to any conclusions, remember that the
-// zeroth interface is the loopback interface, so what we actually want is
-// a situation where there are exactly two interfaces on the node, in which
-// case interface one is the "single" interface connected to the outside world.
-//
- if (GetNInterfaces () == 2)
- {
- NS_LOG_LOGIC ("One Interface. Using interface 1.");
- interface = 1;
- return true;
- }
-//
-// If we fall through to here, we have a node with multiple interfaces and
-// no routes to guide us in determining what interface to choose. Either
-// no default route was found (for unicast or multicast), or in the case of a
-// multicast, the default route contained multiple outbound interfaces.
-//
-// The fallback position is to just get the unicast default route and use
-// the outgoing interface specified there. We don't want to leave the source
-// address unset, so we just assert here.
-//
-// N.B. that in the case of a multicast with a route containing multiple
-// outgoing interfaces, the source address of packets from that node will be
-// set to the IP address of the interface set in the default unicast route.
-// Also, in the case of a broadcast, the same will be true.
-//
- NS_LOG_LOGIC ("Using default unicast route");
- Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
- if (route == NULL)
- {
- NS_LOG_LOGIC ("Ipv4L3Protocol::GetInterfaceForDestination (): "
- "Unable to determine outbound interface. No default route set");
- return false;
- }
-
- interface = route->GetInterface ();
-
- NS_LOG_LOGIC ("Default route specifies interface " << interface);
- return true;
-}
-
uint16_t
Ipv4L3Protocol::GetMtu (uint32_t i) const
{
@@ -1088,7 +832,9 @@
if (((interface->GetAddress (j).GetLocal ()) != (Ipv4Address ()))
&& (interface->GetAddress (j).GetMask ()) != (Ipv4Mask ()))
{
- AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()), interface->GetAddress (j).GetMask (), i);
+ NS_ASSERT_MSG (GetStaticRouting(), "SetUp:: No static routing");
+ GetStaticRouting ()->AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()),
+ interface->GetAddress (j).GetMask (), i);
}
}
}
@@ -1105,12 +851,12 @@
while (modified)
{
modified = false;
- for (uint32_t i = 0; i < GetNRoutes (); i++)
+ for (uint32_t i = 0; i < GetStaticRouting ()->GetNRoutes (); i++)
{
- Ipv4Route route = GetRoute (i);
+ Ipv4RoutingTableEntry route = GetStaticRouting ()->GetRoute (i);
if (route.GetInterface () == ifaceIndex)
{
- RemoveRoute (i);
+ GetStaticRouting ()->RemoveRoute (i);
modified = true;
break;
}
@@ -1118,43 +864,23 @@
}
}
-// Note: This method will be removed in Ipv4 routing work
-Ipv4Address
-Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const
-{
- uint32_t interface = 0xffffffff;
-
- bool result = GetInterfaceForDestination (destination, interface);
-
- if (result)
- {
- // if multiple addresses exist, search for the first one on the same subnet
- for (uint32_t i = 0; i < GetNAddresses (interface); i++)
- {
- Ipv4InterfaceAddress ipv4InAddr = GetAddress (interface, i);
- if (ipv4InAddr.GetLocal().CombineMask(ipv4InAddr.GetMask ()) == destination.CombineMask (ipv4InAddr.GetMask ()))
- {
- return ipv4InAddr.GetLocal ();
- }
- }
- // Destination is off-link, so return first address.
- return GetAddress (interface, 0).GetLocal ();
- }
- else
- {
-//
-// If we can't find any address, just leave it 0.0.0.0
-//
- return Ipv4Address::GetAny ();
- }
-}
-
Ptr<NetDevice>
Ipv4L3Protocol::GetNetDevice (uint32_t i)
{
return GetInterface (i)-> GetDevice ();
}
+void
+Ipv4L3Protocol::SetIpForward (bool forward)
+{
+ m_ipForward = forward;
+}
+
+bool
+Ipv4L3Protocol::GetIpForward (void) const
+{
+ return m_ipForward;
+}
}//namespace ns3