From 69eb2191f205d59ea48700ea7830a08f64dfa691 Mon Sep 17 00:00:00 2001 From: Pavel Boyko Date: Fri, 29 May 2009 16:40:24 +0400 Subject: [PATCH] Correct merge + Tag -> ByteTag changes --- src/internet-stack/ipv4-l3-protocol.cc | 981 +++++++++---------------- src/internet-stack/tcp-socket-impl.cc | 16 +- src/internet-stack/udp-socket-impl.cc | 314 +++----- 3 files changed, 455 insertions(+), 856 deletions(-) diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 425858baf..645f56887 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -31,14 +31,16 @@ #include "ns3/object-vector.h" #include "ns3/ipv4-header.h" #include "ns3/boolean.h" -#include "arp-l3-protocol.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 @@ Ipv4L3Protocol::Ipv4L3Protocol() m_identification (0) { NS_LOG_FUNCTION_NOARGS (); - m_staticRouting = CreateObject (); - AddRoutingProtocol (m_staticRouting, 0); } Ipv4L3Protocol::~Ipv4L3Protocol () @@ -119,6 +119,7 @@ void Ipv4L3Protocol::SetNode (Ptr node) { m_node = node; + // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it SetupLoopback (); } @@ -145,18 +146,48 @@ Ipv4L3Protocol::DeleteRawSocket (Ptr socket) } return; } +/* + * This method is called by AddAgregate and completes the aggregation + * by setting the node in the ipv4 stack + */ +void +Ipv4L3Protocol::NotifyNewAggregate () +{ + Ptrnode = this->GetObject(); + // 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 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 +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 @@ Ipv4L3Protocol::DoDispose (void) *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 @@ Ipv4L3Protocol::SetupLoopback (void) { NS_LOG_FUNCTION_NOARGS (); - Ptr interface = CreateObject (); + Ptr interface = CreateObject (); + Ptr 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 (m_node->GetDevice (i))) + { + break; + } + } + if (device == 0) + { + device = CreateObject (); + 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 = GetObject (); + node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), + Ipv4L3Protocol::PROT_NUMBER, device); + if (GetStaticRouting () != 0) + { + GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), index); + } interface->SetUp (); } @@ -195,192 +249,24 @@ Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) m_defaultTtl = ttl; } - -void -Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) +// XXX need to remove dependencies on Ipv4StaticRouting from this class +Ptr +Ipv4L3Protocol::GetStaticRouting (void) const { - 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, - 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, - 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_FUNCTION_NOARGS (); + Ptr staticRouting; + if (m_routingProtocol != 0) { - 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) + Ptr sr = DynamicCast (m_routingProtocol); + if (sr != 0) { - NS_LOG_LOGIC ("Local source. Using unicast default route for " - "multicast packet"); - - routeReply (true, *route, packet, ipHeader); - return; + return sr; } + Ptr lr = DynamicCast (m_routingProtocol); + NS_ASSERT (lr); + staticRouting = lr->GetStaticRouting (); } -// -// No route found -// - routeReply (false, Ipv4Route (), packet, ipHeader); -} - -void -Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, - int16_t priority) -{ - NS_LOG_FUNCTION (this << &routingProtocol << priority); - m_routingProtocols.push_back - (std::pair > (-priority, routingProtocol)); - m_routingProtocols.sort (); -} - -uint32_t -Ipv4L3Protocol::GetNRoutes (void) -{ - 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 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); + return staticRouting; } uint32_t @@ -394,7 +280,7 @@ Ipv4L3Protocol::AddInterface (Ptr device) node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject ())), ArpL3Protocol::PROT_NUMBER, device); - Ptr interface = CreateObject (); + Ptr interface = CreateObject (); interface->SetNode (m_node); interface->SetDevice (device); return AddIpv4Interface (interface); @@ -433,60 +319,60 @@ Ipv4L3Protocol::GetNInterfaces (void) const 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; - 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 () == addr) - { - return interface; - } - } - } - - NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): " - "Interface not found for IP address " << addr); - return 0; -} - -uint32_t -Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const -{ - NS_LOG_FUNCTION (this << addr << 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 () == address) { return interface; } } } - NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " - "Interface not found for masked IP address"); - return 0; + return -1; } int32_t -Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) const +Ipv4L3Protocol::GetInterfaceForPrefix ( + Ipv4Address address, + Ipv4Mask mask) const { - NS_LOG_FUNCTION (this << device); + 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) == address.CombineMask (mask)) + { + return interface; + } + } + } + + return -1; +} + +int32_t +Ipv4L3Protocol::GetInterfaceForDevice ( + Ptr 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++) @@ -500,31 +386,18 @@ Ipv4L3Protocol::FindInterfaceForDevice (Ptr device) const return -1; } -Ptr -Ipv4L3Protocol::FindInterfaceForDevice (Ptr 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 device, Ptr 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 = p->Copy (); - uint32_t index = 0; Ptr ipv4Interface; for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); @@ -535,9 +408,9 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr { 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 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr return; } } - index++; + interface++; } + Ipv4Header ipHeader; if (m_calcChecksum) { @@ -566,12 +440,13 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr 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 , const Ipv4Header &> () + ); - ForwardUp (packet, ipHeader, ipv4Interface); } Ptr @@ -598,74 +473,35 @@ void Ipv4L3Protocol::Send (Ptr packet, Ipv4Address source, Ipv4Address destination, - uint8_t protocol) + uint8_t protocol, + Ptr 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->RemovePacketTag (dfTag); + bool mayFragment = true; + uint8_t ttl = m_defaultTtl; + SocketIpTtlTag tag; + bool found = packet->FindFirstMatchingByteTag (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->RemovePacketTag (tag); - + // 1) packet is destined to limited broadcast address if (destination.IsBroadcast ()) { - ipHeader.SetTtl (1); - } - else if (found) - { - ipHeader.SetTtl (tag.GetTtl ()); - } - else - { - ipHeader.SetTtl (m_defaultTtl); - uint32_t ifaceIndex = 0; - for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); - ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) - { - Ptr 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++) @@ -673,209 +509,216 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr outInterface = *ifaceIter; Ptr 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 ())) + 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 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 ()) ) { - Ptr icmp = GetIcmp (); - NS_ASSERT (icmp != 0); - icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ()); - m_dropTrace (packetCopy); - } - 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 (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 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 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 route, Ptr 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 outDev = route->GetOutputDevice (); + int32_t interface = GetInterfaceForDevice (outDev); + NS_ASSERT (interface >= 0); + Ptr outInterface = GetInterface (interface); + NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface); - Ptr 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_ASSERT (packet->GetSize () <= outInterface->GetMtu ()); + if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0"))) { - NS_LOG_LOGIC ("Too big: need fragmentation but not allowed"); - Ptr icmp = GetIcmp (); - NS_ASSERT (icmp != 0); - Ptr 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 - { - if (route.IsGateway ()) + if (outInterface->IsUp ()) { - 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 ("Send to gateway " << route->GetGateway ()); + m_txTrace (packet, interface); + outInterface->Send (packet, route->GetGateway ()); + } + else { - 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 ("Dropping-- outgoing interface is down: " << route->GetGateway ()); + m_dropTrace (packet); + } + } + else + { + if (outInterface->IsUp ()) + { + 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, - Ipv4Header &ipHeader, - Ptr device) -{ - 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++) - { - for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) - { - if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ())) - { - NS_LOG_LOGIC ("For me (destination match)"); - return false; - } - } - } - - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); i++) - { - Ptr 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_mr_forward() void -Ipv4L3Protocol::DoForward (uint32_t interface, - Ptr packet, - Ipv4Header ipHeader) +Ipv4L3Protocol::IpMulticastForward (Ptr mrtentry, Ptr p, const Ipv4Header &header) { - NS_LOG_FUNCTION (this << interface << packet << ipHeader); + 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++) + { + if (mrtentry->GetOutputTtl (i) < Ipv4MulticastRoute::MAX_TTL) + { + Ptr packet = p->Copy (); + Ipv4Header h = header; + h.SetTtl (header.GetTtl () - 1); + if (h.GetTtl () == 0) + { + NS_LOG_WARN ("TTL exceeded. Drop."); + m_dropTrace (packet); + return; + } + NS_LOG_LOGIC ("Forward multicast via interface " << i); + Ptr rtentry = Create (); + rtentry->SetSource (h.GetSource ()); + rtentry->SetDestination (h.GetDestination ()); + rtentry->SetGateway (Ipv4Address::GetAny ()); + rtentry->SetOutputDevice (GetNetDevice (i)); + SendRealOut (rtentry, packet, h); + return; + } + } +} +// This function analogous to Linux ip_forward() +void +Ipv4L3Protocol::IpForward (Ptr rtentry, Ptr p, const Ipv4Header &header) +{ + NS_LOG_FUNCTION (rtentry << p << header); + NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ()); + // Forwarding + Ipv4Header ipHeader = header; + Ptr packet = p->Copy (); ipHeader.SetTtl (ipHeader.GetTtl () - 1); // XXX handle multi-interfaces if (ipHeader.GetTtl () == 0) { + Ptr outDev = rtentry->GetOutputDevice (); + int32_t interface = GetInterfaceForDevice (outDev); + NS_ASSERT (interface >= 0); if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ())) { Ptr icmp = GetIcmp (); @@ -884,18 +727,15 @@ Ipv4L3Protocol::DoForward (uint32_t interface, 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 p, Ipv4Header const&ip, - Ptr incomingInterface) +Ipv4L3Protocol::LocalDeliver (Ptr packet, Ipv4Header const&ip, uint32_t iif) { - NS_LOG_FUNCTION (this << p << &ip); + NS_LOG_FUNCTION (this << packet << &ip); + Ptr p = packet->Copy (); // need to pass a non-const packet up Ptr protocol = GetProtocol (ip.GetProtocol ()); if (protocol != 0) @@ -904,15 +744,15 @@ Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, // RX_ENDPOINT_UNREACH codepath Ptr 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); } @@ -921,32 +761,7 @@ Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, } } -void -Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) -{ - NS_LOG_FUNCTION (this << origin << group); - m_multicastGroups.push_back( - std::pair (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); @@ -954,7 +769,7 @@ Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address) return interface->AddAddress (address); } -Ipv4InterfaceAddress +Ipv4InterfaceAddress Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const { NS_LOG_FUNCTION (this << interfaceIndex << addressIndex); @@ -962,7 +777,7 @@ Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) cons return interface->GetAddress (addressIndex); } -uint32_t +uint32_t Ipv4L3Protocol::GetNAddresses (uint32_t interface) const { NS_LOG_FUNCTION (this << interface); @@ -986,76 +801,6 @@ Ipv4L3Protocol::GetMetric (uint32_t i) const 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 { @@ -1087,7 +832,9 @@ Ipv4L3Protocol::SetUp (uint32_t i) 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); } } } @@ -1104,12 +851,12 @@ Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) 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; } @@ -1117,43 +864,23 @@ Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) } } -// 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 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 diff --git a/src/internet-stack/tcp-socket-impl.cc b/src/internet-stack/tcp-socket-impl.cc index f02dc4e97..72581214a 100644 --- a/src/internet-stack/tcp-socket-impl.cc +++ b/src/internet-stack/tcp-socket-impl.cc @@ -563,9 +563,6 @@ TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) m_rxBufSize += i->second->GetSize()-avail; } } - SocketAddressTag tag; - tag.SetAddress (InetSocketAddress (m_remoteAddress, m_remotePort)); - outPacket->AddPacketTag (tag); return outPacket; } @@ -580,7 +577,7 @@ TcpSocketImpl::GetRxAvailable (void) const Ptr TcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, - Address &fromAddress) + Address &fromAddress) { NS_LOG_FUNCTION (this << maxSize << flags); Ptr packet = Recv (maxSize, flags); @@ -589,7 +586,7 @@ TcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, { SocketAddressTag tag; bool found; - found = packet->PeekPacketTag (tag); + found = packet->FindFirstMatchingByteTag (tag); NS_ASSERT (found); fromAddress = tag.GetAddress (); } @@ -1199,6 +1196,9 @@ void TcpSocketImpl::NewRx (Ptr p, p = p->CreateFragment (0,s); m_nextRxSequence += s; // Advance next expected sequence NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence ); + SocketAddressTag tag; + tag.SetAddress (fromAddress); + p->AddByteTag (tag); //buffer this, it'll be read by call to Recv UnAckData_t::iterator i = m_bufferedData.find (tcpHeader.GetSequenceNumber () ); @@ -1266,6 +1266,9 @@ void TcpSocketImpl::NewRx (Ptr p, } } // Save for later delivery + SocketAddressTag tag; + tag.SetAddress (fromAddress); + p->AddByteTag (tag); m_bufferedData[startSeq] = p; i = m_bufferedData.find (startSeq); next = i; @@ -1292,6 +1295,9 @@ void TcpSocketImpl::NewRx (Ptr p, p = p->CreateFragment (m_nextRxSequence - tcpHeader.GetSequenceNumber (),s); SequenceNumber start = m_nextRxSequence; m_nextRxSequence += s; // Advance next expected sequence + SocketAddressTag tag; + tag.SetAddress (fromAddress); + p->AddByteTag (tag); //buffer the new fragment, it'll be read by call to Recv UnAckData_t::iterator i = m_bufferedData.find (start); if (i != m_bufferedData.end () ) //we found it already in the buffer diff --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index 82e27c333..14c166f14 100644 --- a/src/internet-stack/udp-socket-impl.cc +++ b/src/internet-stack/udp-socket-impl.cc @@ -23,6 +23,8 @@ #include "ns3/inet-socket-address.h" #include "ns3/ipv4-route.h" #include "ns3/ipv4.h" +#include "ns3/ipv4-header.h" +#include "ns3/ipv4-routing-protocol.h" #include "ns3/udp-socket-factory.h" #include "ns3/trace-source-accessor.h" #include "udp-socket-impl.h" @@ -70,6 +72,7 @@ UdpSocketImpl::~UdpSocketImpl () { NS_LOG_FUNCTION_NOARGS (); + // XXX todo: leave any multicast groups that have been joined m_node = 0; if (m_endPoint != 0) { @@ -308,7 +311,6 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) return -1; } - uint32_t localInterface; Ptr ipv4 = m_node->GetObject (); // Locally override the IP TTL for this socket @@ -319,22 +321,21 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) // irrespective of what is set in these socket options. So, this tagging // may end up setting the TTL of a limited broadcast packet to be // the same as a unicast, but it will be fixed further down the stack - //NS_LOG_UNCOND ("IPttl: " << m_ipTtl); if (m_ipMulticastTtl != 0 && dest.IsMulticast ()) { SocketIpTtlTag tag; tag.SetTtl (m_ipMulticastTtl); - p->AddPacketTag (tag); + p->AddByteTag (tag); } else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ()) { SocketIpTtlTag tag; tag.SetTtl (m_ipTtl); - p->AddPacketTag (tag); + p->AddByteTag (tag); } { SocketSetDontFragmentTag tag; - bool found = p->RemovePacketTag (tag); + bool found = p->FindFirstMatchingByteTag (tag); if (!found) { if (m_mtuDiscover) @@ -345,7 +346,7 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) { tag.Disable (); } - p->AddPacketTag (tag); + p->AddByteTag (tag); } } // @@ -391,14 +392,31 @@ UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) NS_LOG_LOGIC ("Limited broadcast end."); return p->GetSize(); } - else if (ipv4->GetInterfaceForDestination(dest, localInterface)) + else if (ipv4->GetRoutingProtocol () != 0) { - NS_LOG_LOGIC ("Route exists"); - m_udp->Send (p->Copy (), ipv4->GetSourceAddress (dest), dest, - m_endPoint->GetLocalPort (), port); - NotifyDataSent (p->GetSize ()); - NotifySend (GetTxAvailable ()); - return p->GetSize();; + Ipv4Header header; + header.SetDestination (dest); + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + // TBD-- we could cache the route and just check its validity + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + if (route != 0) + { + NS_LOG_LOGIC ("Route exists"); + header.SetSource (route->GetSource ()); + m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (), + m_endPoint->GetLocalPort (), port, route); + NotifyDataSent (p->GetSize ()); + return p->GetSize(); + } + else + { + NS_LOG_LOGIC ("No route to destination"); + NS_LOG_ERROR (errno); + m_errno = errno; + return -1; + } } else { @@ -464,7 +482,7 @@ UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) Ptr UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, - Address &fromAddress) + Address &fromAddress) { NS_LOG_FUNCTION (this << maxSize << flags); Ptr packet = Recv (maxSize, flags); @@ -472,7 +490,7 @@ UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, { SocketAddressTag tag; bool found; - found = packet->PeekPacketTag (tag); + found = packet->FindFirstMatchingByteTag (tag); NS_ASSERT (found); fromAddress = tag.GetAddress (); } @@ -494,6 +512,34 @@ UdpSocketImpl::GetSockName (Address &address) const return 0; } +int +UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress) +{ + NS_LOG_FUNCTION (interface << groupAddress); + /* + 1) sanity check interface + 2) sanity check that it has not been called yet on this interface/group + 3) determine address family of groupAddress + 4) locally store a list of (interface, groupAddress) + 5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup () + */ + return 0; +} + +int +UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress) +{ + NS_LOG_FUNCTION (interface << groupAddress); + /* + 1) sanity check interface + 2) determine address family of groupAddress + 3) delete from local list of (interface, groupAddress); raise a LOG_WARN + if not already present (but return 0) + 5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup () + */ + return 0; +} + void UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) { @@ -508,7 +554,7 @@ UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) Address address = InetSocketAddress (ipv4, port); SocketAddressTag tag; tag.SetAddress (address); - packet->AddPacketTag (tag); + packet->AddByteTag (tag); m_deliveryQueue.push (packet); m_rxAvailable += packet->GetSize (); NotifyDataRecv (); @@ -552,29 +598,53 @@ UdpSocketImpl::GetRcvBufSize (void) const } void -UdpSocketImpl::SetIpTtl (uint32_t ipTtl) +UdpSocketImpl::SetIpTtl (uint8_t ipTtl) { m_ipTtl = ipTtl; } -uint32_t +uint8_t UdpSocketImpl::GetIpTtl (void) const { return m_ipTtl; } void -UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl) +UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl) { m_ipMulticastTtl = ipTtl; } -uint32_t +uint8_t UdpSocketImpl::GetIpMulticastTtl (void) const { return m_ipMulticastTtl; } +void +UdpSocketImpl::SetIpMulticastIf (int32_t ipIf) +{ + m_ipMulticastIf = ipIf; +} + +int32_t +UdpSocketImpl::GetIpMulticastIf (void) const +{ + return m_ipMulticastIf; +} + +void +UdpSocketImpl::SetIpMulticastLoop (bool loop) +{ + m_ipMulticastLoop = loop; +} + +bool +UdpSocketImpl::GetIpMulticastLoop (void) const +{ + return m_ipMulticastLoop; +} + void UdpSocketImpl::SetMtuDiscover (bool discover) { @@ -588,207 +658,3 @@ UdpSocketImpl::GetMtuDiscover (void) const } //namespace ns3 - - -#ifdef RUN_SELF_TESTS - -#include "ns3/test.h" -#include "ns3/socket-factory.h" -#include "ns3/udp-socket-factory.h" -#include "ns3/simulator.h" -#include "ns3/simple-channel.h" -#include "ns3/simple-net-device.h" -#include "ns3/drop-tail-queue.h" -#include "internet-stack.h" -#include - -namespace ns3 { - -class UdpSocketImplTest: public Test -{ - Ptr m_receivedPacket; - Ptr m_receivedPacket2; - -public: - virtual bool RunTests (void); - UdpSocketImplTest (); - - void ReceivePacket (Ptr socket, Ptr packet, const Address &from); - void ReceivePacket2 (Ptr socket, Ptr packet, const Address &from); - void ReceivePkt (Ptr socket); - void ReceivePkt2 (Ptr socket); -}; - - -UdpSocketImplTest::UdpSocketImplTest () - : Test ("UdpSocketImpl") -{ -} - -void UdpSocketImplTest::ReceivePacket (Ptr socket, Ptr packet, const Address &from) -{ - m_receivedPacket = packet; -} - -void UdpSocketImplTest::ReceivePacket2 (Ptr socket, Ptr packet, const Address &from) -{ - m_receivedPacket2 = packet; -} - -void UdpSocketImplTest::ReceivePkt (Ptr socket) -{ - uint32_t availableData; - availableData = socket->GetRxAvailable (); - m_receivedPacket = socket->Recv (std::numeric_limits::max(), 0); - NS_ASSERT (availableData == m_receivedPacket->GetSize ()); -} - -void UdpSocketImplTest::ReceivePkt2 (Ptr socket) -{ - uint32_t availableData; - availableData = socket->GetRxAvailable (); - m_receivedPacket2 = socket->Recv (std::numeric_limits::max(), 0); - NS_ASSERT (availableData == m_receivedPacket2->GetSize ()); -} - -bool -UdpSocketImplTest::RunTests (void) -{ - bool result = true; - - // Create topology - - // Receiver Node - Ptr rxNode = CreateObject (); - AddInternetStack (rxNode); - Ptr rxDev1, rxDev2; - { // first interface - rxDev1 = CreateObject (); - rxDev1->SetAddress (Mac48Address::Allocate ()); - rxNode->AddDevice (rxDev1); - Ptr ipv4 = rxNode->GetObject (); - uint32_t netdev_idx = ipv4->AddInterface (rxDev1); - Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U)); - ipv4->AddAddress (netdev_idx, ipv4Addr); - ipv4->SetUp (netdev_idx); - } - - { // second interface - rxDev2 = CreateObject (); - rxDev2->SetAddress (Mac48Address::Allocate ()); - rxNode->AddDevice (rxDev2); - Ptr ipv4 = rxNode->GetObject (); - uint32_t netdev_idx = ipv4->AddInterface (rxDev2); - Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U)); - ipv4->AddAddress (netdev_idx, ipv4Addr); - ipv4->SetUp (netdev_idx); - } - - // Sender Node - Ptr txNode = CreateObject (); - AddInternetStack (txNode); - Ptr txDev1; - { - txDev1 = CreateObject (); - txDev1->SetAddress (Mac48Address::Allocate ()); - txNode->AddDevice (txDev1); - Ptr ipv4 = txNode->GetObject (); - uint32_t netdev_idx = ipv4->AddInterface (txDev1); - Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U)); - ipv4->AddAddress (netdev_idx, ipv4Addr); - ipv4->SetUp (netdev_idx); - } - Ptr txDev2; - { - txDev2 = CreateObject (); - txDev2->SetAddress (Mac48Address::Allocate ()); - txNode->AddDevice (txDev2); - Ptr ipv4 = txNode->GetObject (); - uint32_t netdev_idx = ipv4->AddInterface (txDev2); - Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U)); - ipv4->AddAddress (netdev_idx, ipv4Addr); - ipv4->SetUp (netdev_idx); - } - - // link the two nodes - Ptr channel1 = CreateObject (); - rxDev1->SetChannel (channel1); - txDev1->SetChannel (channel1); - - Ptr channel2 = CreateObject (); - rxDev2->SetChannel (channel2); - txDev2->SetChannel (channel2); - - - // Create the UDP sockets - Ptr rxSocketFactory = rxNode->GetObject (); - Ptr rxSocket = rxSocketFactory->CreateSocket (); - NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0); - rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this)); - - Ptr rxSocket2 = rxSocketFactory->CreateSocket (); - rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this)); - NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0); - - Ptr txSocketFactory = txNode->GetObject (); - Ptr txSocket = txSocketFactory->CreateSocket (); - - // ------ Now the tests ------------ - - // Unicast test - m_receivedPacket = Create (); - m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), 0, - InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123); - Simulator::Run (); - NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); - NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it - - m_receivedPacket->RemoveAllPacketTags (); - m_receivedPacket2->RemoveAllPacketTags (); - - // Simple broadcast test - - m_receivedPacket = Create (); - m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create (123), 0, - InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); - Simulator::Run (); - NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); - // second socket should not receive it (it is bound specifically to the second interface's address - NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); - - m_receivedPacket->RemoveAllPacketTags (); - m_receivedPacket2->RemoveAllPacketTags (); - - // Broadcast test with multiple receiving sockets - - // When receiving broadcast packets, all sockets sockets bound to - // the address/port should receive a copy of the same packet -- if - // the socket address matches. - rxSocket2->Dispose (); - rxSocket2 = rxSocketFactory->CreateSocket (); - rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this)); - NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0); - - m_receivedPacket = Create (); - m_receivedPacket2 = Create (); - NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create (123), 0, -InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123); - Simulator::Run (); - NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123); - NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123); - - m_receivedPacket->RemoveAllPacketTags (); - m_receivedPacket2->RemoveAllPacketTags (); - - Simulator::Destroy (); - - return result; -} - -static UdpSocketImplTest gUdpSocketImplTest; - -}; // namespace ns3 - -#endif /* RUN_SELF_TESTS */