diff --git a/src/applications/packet-sink/packet-sink.cc b/src/applications/packet-sink/packet-sink.cc index 4e0419096..3a86f5416 100644 --- a/src/applications/packet-sink/packet-sink.cc +++ b/src/applications/packet-sink/packet-sink.cc @@ -18,10 +18,12 @@ * Author: Tom Henderson (tomhend@u.washington.edu) */ #include "ns3/address.h" +#include "ns3/address-utils.h" #include "ns3/log.h" #include "ns3/inet-socket-address.h" #include "ns3/node.h" #include "ns3/socket.h" +#include "ns3/udp-socket.h" #include "ns3/simulator.h" #include "ns3/socket-factory.h" #include "ns3/packet.h" @@ -88,6 +90,19 @@ void PacketSink::StartApplication() // Called at time specified by Start m_socket = Socket::CreateSocket (GetNode(), m_tid); m_socket->Bind (m_local); m_socket->Listen (); + if (addressUtils::IsMulticast (m_local)) + { + Ptr udpSocket = DynamicCast (m_socket); + if (udpSocket) + { + // equivalent to setsockopt (MCAST_JOIN_GROUP) + udpSocket->MulticastJoinGroup (0, m_local); + } + else + { + NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket"); + } + } } m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this)); diff --git a/src/applications/udp-echo/udp-echo-server.cc b/src/applications/udp-echo/udp-echo-server.cc index bc05993cc..526a0ee6a 100644 --- a/src/applications/udp-echo/udp-echo-server.cc +++ b/src/applications/udp-echo/udp-echo-server.cc @@ -18,9 +18,11 @@ #include "ns3/log.h" #include "ns3/ipv4-address.h" +#include "ns3/address-utils.h" #include "ns3/nstime.h" #include "ns3/inet-socket-address.h" #include "ns3/socket.h" +#include "ns3/udp-socket.h" #include "ns3/simulator.h" #include "ns3/socket-factory.h" #include "ns3/packet.h" @@ -76,6 +78,19 @@ UdpEchoServer::StartApplication (void) m_socket = Socket::CreateSocket (GetNode(), tid); InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port); m_socket->Bind (local); + if (addressUtils::IsMulticast (m_local)) + { + Ptr udpSocket = DynamicCast (m_socket); + if (udpSocket) + { + // equivalent to setsockopt (MCAST_JOIN_GROUP) + udpSocket->MulticastJoinGroup (0, m_local); + } + else + { + NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket"); + } + } } m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this)); diff --git a/src/core/object.cc b/src/core/object.cc index e2a56d22a..26836db96 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -160,6 +160,24 @@ Object::AggregateObject (Ptr o) other->m_next = next; NS_ASSERT (CheckLoose ()); NS_ASSERT (o->CheckLoose ()); + // call NotifyNewAggregate in the listed chain + Object *currentObject = this; + do + { + // the NotifyNewAggregate of the current object implementation + // should be called on the next object in the linked chain + currentObject->NotifyNewAggregate (); + currentObject = currentObject->m_next; + } while (currentObject != this); +} +/** + * This function must be implemented in the stack that needs to notify + * other stacks connected to the node of their presence in the node. + */ +void +Object::NotifyNewAggregate () +{ + } Object::AggregateIterator diff --git a/src/core/object.h b/src/core/object.h index e746d7940..8cf1120d2 100644 --- a/src/core/object.h +++ b/src/core/object.h @@ -160,6 +160,13 @@ public: AggregateIterator GetAggregateIterator (void) const; protected: + /** + * This function is called by the AggregateObject on all the objects connected in the listed chain. + * This way the new object aggregated will be used if needed by the NotifyNewAggregate corresponding + * to each object connected in the listed chain. It should be implemented by objects needing an + * additional/special behavior when aggregated to another object. + */ + virtual void NotifyNewAggregate (); /** * This method is called by Object::Dispose or by the object's * destructor, whichever comes first. diff --git a/src/devices/tap-bridge/tap-bridge.cc b/src/devices/tap-bridge/tap-bridge.cc index aff3a8907..df422d15c 100644 --- a/src/devices/tap-bridge/tap-bridge.cc +++ b/src/devices/tap-bridge/tap-bridge.cc @@ -342,7 +342,7 @@ TapBridge::CreateTap (void) Ptr nd = GetBridgedNetDevice (); Ptr n = nd->GetNode (); Ptr ipv4 = n->GetObject (); - uint32_t index = ipv4->FindInterfaceForDevice (nd); + uint32_t index = ipv4->GetInterfaceForDevice (nd); if (ipv4->GetNAddresses (index) > 1) { NS_LOG_WARN ("Underlying bridged NetDevice has multiple IP addresses; using first one."); diff --git a/src/helper/internet-stack-helper.cc b/src/helper/internet-stack-helper.cc index e07c0fc0d..f99c38962 100644 --- a/src/helper/internet-stack-helper.cc +++ b/src/helper/internet-stack-helper.cc @@ -16,6 +16,136 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Mathieu Lacage + * Author: Faker Moatamri + */ + +/** + * \ingroup internetStack + * \defgroup internetStackModel Internet Stack Model + * + * \section internetStackTracingModel Tracing in the Internet Stack + * + * The internet stack provides a number of trace sources in its various + * protocol implementations. These trace sources can be hooked using your own + * custom trace code, or you can use our helper functions in some cases to + * arrange for tracing to be enabled. + * + * \subsection internetStackArpTracingModel Tracing in ARP + * + * ARP provides two trace hooks, one in the cache, and one in the layer three + * protocol. The trace accessor in the cache is given the name "Drop." When + * a packet is transmitted over an interface that requires ARP, it is first + * queued for transmission in the ARP cache until the required MAC address is + * resolved. There are a number of retries that may be done trying to get the + * address, and if the maximum retry count is exceeded the packet in question + * is dropped by ARP. The single trace hook in the ARP cache is called, + * + * - If an outbound packet is placed in the ARP cache pending address resolution + * and no resolution can be made within the maximum retry count, the outbound + * packet is dropped and this trace is fired; + * + * A second trace hook lives in the ARP L3 protocol (also named "Drop") and may + * be called for a number of reasons. + * + * - If an ARP reply is received for an entry that is not waiting for a reply, + * the ARP reply packet is dropped and this trace is fired; + * - If an ARP reply is received for a non-existant entry, the ARP reply packet + * is dropped and this trace is fired; + * - If an ARP cache entry is in the DEAD state (has timed out) and an ARP reply + * packet is received, the reply packet is dropped and this trace is fired. + * - Each ARP cache entry has a queue of pending packets. If the size of the + * queue is exceeded, the outbound packet is dropped and this trace is fired. + * + * \subsection internetStackIpv4TracingModel Tracing in IPv4 + * + * The IPv4 layer three protocol provides three trace hooks. These are the + * "Tx" (ns3::Ipv4L3Protocol::m_txTrace), "Rx" (ns3::Ipv4L3Protocol::m_rxTrace) + * and "Drop" (ns3::Ipv4L3Protocol::m_dropTrace) trace sources. + * + * The "Tx" trace is fired in a number of situations, all of which indicate that + * a given packet is about to be sent down to a given ns3::Ipv4Interface. + * + * - In the case of a packet destined for the broadcast address, the + * Ipv4InterfaceList is iterated and for every interface that is up and can + * fragment the packet or has a large enough MTU to transmit the packet, + * the trace is hit. See ns3::Ipv4L3Protocol::Send. + * + * - In the case of a packet that needs routing, the "Tx" trace may be fired + * just before a packet is sent to the interface appropriate to the default + * gateway. See ns3::Ipv4L3Protocol::SendRealOut. + * + * - Also in the case of a packet that needs routing, the "Tx" trace may be + * fired just before a packet is sent to the outgoing interface appropriate + * to the discovered route. See ns3::Ipv4L3Protocol::SendRealOut. + * + * The "Rx" trace is fired when a packet is passed from the device up to the + * ns3::Ipv4L3Protocol::Receive function. + * + * - In the receive function, the Ipv4InterfaceList is iterated, and if the + * Ipv4Interface corresponding to the receiving device is fount to be in the + * UP state, the trace is fired. + * + * The "Drop" trace is fired in any case where the packet is dropped (in both + * the transmit and receive paths). + * + * - In the ns3::Ipv4Interface::Receive function, the packet is dropped and the + * drop trace is hit if the interface corresponding to the receiving device + * is in the DOWN state. + * + * - Also in the ns3::Ipv4Interface::Receive function, the packet is dropped and + * the drop trace is hit if the checksum is found to be bad. + * + * - In ns3::Ipv4L3Protocol::Send, an outgoing packet bound for the broadcast + * address is dropped and the "Drop" trace is fired if the "don't fragement" + * bit is set and fragmentation is available and required. + * + * - Also in ns3::Ipv4L3Protocol::Send, an outgoing packet destined for the + * broadcast address is dropped and the "Drop" trace is hit if fragmentation + * is not available and is required (MTU < packet size). + * + * - In the case of a broadcast address, an outgoing packet is cloned for each + * outgoing interface. If any of the interfaces is in the DOWN state, the + * "Drop" trace event fires with a reference to the copied packet. + * + * - In the case of a packet requiring a route, an outgoing packet is dropped + * and the "Drop" trace event fires if no route to the remote host is found. + * + * - In ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed + * is dropped and the "Drop" trace is fired if the "don't fragement" bit is + * set and fragmentation is available and required. + * + * - Also in ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed + * is dropped and the "Drop" trace is hit if fragmentation is not available + * and is required (MTU < packet size). + * + * - An outgoing packet being routed is dropped and the "Drop" trace event fires + * if the required Ipv4Interface is in the DOWN state. + * + * - If a packet is being forwarded, and the TTL is exceeded (see + * ns3::Ipv4L3Protocol::DoForward), the packet is dropped and the "Drop" trace + * event is fired. + * + * \subsection internetStackNs3TCPTracingModel Tracing in ns-3 TCP + * + * There is currently one trace source in the ns-3 TCP implementation named + * "CongestionWindow" (see ns3::TcpSocketImpl::m_cWnd). This is set in a number + * of places (see file tcp-socket-impl.cc) whenever the value of the congestion + * window is changed. + * + * \subsection internetStackNscTCPTracingModel Tracing in NSC TCP + * + * There is currently one trace source in the Network Simulation Cradle TCP + * implementation named "CongestionWindow" (see ns3::NscTcpSocketImpl::m_cWnd). + * This is set in a number of places (see file nsc-tcp-socket-impl.cc) when + * the value of the cogestion window is initially set. Note that this is not + * instrumented from the underlying TCP implementaion. + * + * \subsection internetStackNs3UdpTracingModel Tracing in ns-3 UDP + * + * There is currently one trace source in the ns-3 UDP implementation named + * "Drop" (see ns3::UdpSocketImpl::m_dropTrace). This is set when a packet + * is received in ns3::UdpSocketImpl::ForwardUp and the receive buffer cannot + * accomodate the encapsulated data. */ #include "ns3/assert.h" @@ -24,10 +154,16 @@ #include "ns3/names.h" #include "ns3/ipv4.h" #include "internet-stack-helper.h" -#include "ns3/internet-stack.h" #include "ns3/packet-socket-factory.h" #include "ns3/config.h" #include "ns3/simulator.h" +#include "ns3/string.h" +#include "ns3/net-device.h" +#include "ns3/callback.h" +#include "ns3/node.h" +#include "ns3/core-config.h" +#include "ns3/ipv4-list-routing-impl.h" +#include "ns3/ipv4-static-routing-impl.h" #include namespace ns3 { @@ -35,8 +171,9 @@ namespace ns3 { std::vector InternetStackHelper::m_traces; std::string InternetStackHelper::m_pcapBaseFilename; -InternetStackHelper::InternetStackHelper() : m_nscLibrary("") +InternetStackHelper::InternetStackHelper () { + SetTcp ("ns3::TcpL4Protocol"); } void @@ -55,9 +192,16 @@ InternetStackHelper::Cleanup (void) } void -InternetStackHelper::SetNscStack(const std::string soname) +InternetStackHelper::SetTcp (const std::string tid) { - m_nscLibrary = soname; + m_tcpFactory.SetTypeId (tid); +} + +void +InternetStackHelper::SetTcp (std::string tid, std::string n0, const AttributeValue &v0) +{ + m_tcpFactory.SetTypeId (tid); + m_tcpFactory.Set (n0,v0); } void @@ -69,6 +213,15 @@ InternetStackHelper::Install (NodeContainer c) const } } +static void +CreateAndAggregateObjectFromTypeId (Ptr node, const std::string typeId) +{ + ObjectFactory factory; + factory.SetTypeId(typeId); + Ptr protocol = factory.Create (); + node->AggregateObject (protocol); +} + void InternetStackHelper::Install (Ptr node) const { @@ -79,17 +232,22 @@ InternetStackHelper::Install (Ptr node) const return; } - if (m_nscLibrary != "") - { - AddNscInternetStack (node, m_nscLibrary); - } - else - { - AddInternetStack (node); - } - + CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol"); + CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol"); + CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol"); + CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol"); + node->AggregateObject (m_tcpFactory.Create ()); Ptr factory = CreateObject (); node->AggregateObject (factory); + // Set routing + Ptr ipv4 = node->GetObject (); + // XXX cut this over to use of TypeIds and factories + Ptr ipv4RoutingImpl = CreateObject (); + Ptr ipv4staticRoutingImpl = CreateObject (); + ipv4staticRoutingImpl->SetNode (node); + ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0); + ipv4->SetRoutingProtocol (ipv4RoutingImpl); + ipv4RoutingImpl->SetNode (node); } void diff --git a/src/helper/internet-stack-helper.h b/src/helper/internet-stack-helper.h index fad54d1f4..49c8d0c23 100644 --- a/src/helper/internet-stack-helper.h +++ b/src/helper/internet-stack-helper.h @@ -25,9 +25,13 @@ #include "net-device-container.h" #include "ns3/pcap-writer.h" #include "ns3/packet.h" +#include "ns3/ptr.h" +#include "ns3/object-factory.h" namespace ns3 { +class Node; + /** * \brief aggregate IP/TCP/UDP functionality to existing Nodes. */ @@ -65,18 +69,32 @@ public: */ void Install (NodeContainer c) const; - /** - * \brief Enable or disable use of the Network Simulation Cradle stack. + /** + * \brief set the Tcp stack which will not need any other parameter. * - * Give the NSC stack a shared library file name to use when creating the - * statck implementation. By providing a non-empty string as a parameter, you - * select the NSC version of the stack. By providing an empty string, you - * select the ns-3 default version. + * This function sets up the tcp stack to the given TypeId. It should not be + * used for NSC stack setup because the nsc stack needs the Library attribute + * to be setup, please use instead the version that requires an attribute + * and a value. If you choose to use this function anyways to set nsc stack + * the default value for the linux library will be used: "liblinux2.6.26.so". * - * \param soname name of the shared library with the nsc tcp stack - * to use, e.g. 'liblinux2.6.26.so'. + * \param tid the type id, typically it is set to "ns3::TcpL4Protocol" */ - void SetNscStack(std::string soname); + void SetTcp(std::string tid); + + /** + * \brief This function is used to setup the Network Simulation Cradle stack with library value. + * + * Give the NSC stack a shared library file name to use when creating the + * stack implementation. The attr string is actually the attribute name to + * be setup and val is its value. The attribute is the stack implementation + * to be used and the value is the shared library name. + * + * \param tid The type id, for the case of nsc it would be "ns3::NscTcpL4Protocol" + * \param attr The attribute name that must be setup, for example "Library" + * \param val The attribute value, which will be in fact the shared library name (example:"liblinux2.6.26.so") + */ + void SetTcp (std::string tid, std::string attr, const AttributeValue &val); /** * \param os output stream @@ -113,7 +131,7 @@ public: static void EnablePcapAll (std::string filename); private: - std::string m_nscLibrary; + ObjectFactory m_tcpFactory; static void Cleanup (void); static void LogRxIp (std::string context, Ptr packet, uint32_t deviceId); static void LogTxIp (std::string context, Ptr packet, uint32_t deviceId); diff --git a/src/helper/ipv4-address-helper.cc b/src/helper/ipv4-address-helper.cc index d3c8b95b8..b0ae54691 100644 --- a/src/helper/ipv4-address-helper.cc +++ b/src/helper/ipv4-address-helper.cc @@ -131,7 +131,7 @@ Ipv4AddressHelper::Assign (const NetDeviceContainer &c) Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "Ipv4AddressHelper::Allocate(): Bad ipv4"); - int32_t interface = ipv4->FindInterfaceForDevice (device); + int32_t interface = ipv4->GetInterfaceForDevice (device); if (interface == -1) { interface = ipv4->AddInterface (device); diff --git a/src/helper/ipv4-interface-container.h b/src/helper/ipv4-interface-container.h index 143582f2e..dd495f3e2 100644 --- a/src/helper/ipv4-interface-container.h +++ b/src/helper/ipv4-interface-container.h @@ -41,7 +41,10 @@ public: Ipv4Address GetAddress (uint32_t i, uint32_t j = 0) const; void SetMetric (uint32_t i, uint16_t metric); - + /** + * \param ipv4 pointer to Ipv4 object + * \param interface interface index of the Ipv4Interface to add to the container + */ void Add (Ptr ipv4, uint32_t interface); void Add (std::string ipv4Name, uint32_t interface); diff --git a/src/helper/ipv4-static-routing-helper.cc b/src/helper/ipv4-static-routing-helper.cc new file mode 100644 index 000000000..d2eeb3186 --- /dev/null +++ b/src/helper/ipv4-static-routing-helper.cc @@ -0,0 +1,190 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ + +#include +#include "ns3/log.h" +#include "ns3/ptr.h" +#include "ns3/names.h" +#include "ns3/node.h" +#include "ns3/ipv4.h" +#include "ns3/ipv4-route.h" +#include "ns3/ipv4-list-routing.h" +#include "ns3/assert.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4-routing-protocol.h" +#include "ipv4-static-routing-helper.h" + +NS_LOG_COMPONENT_DEFINE("Ipv4StaticRoutingHelper"); + +namespace ns3 { + +Ptr +Ipv4StaticRoutingHelper::GetStaticRouting (Ptr ipv4) const +{ + NS_LOG_FUNCTION (this); + Ptr ipv4rp = ipv4->GetRoutingProtocol (); + NS_ASSERT_MSG (ipv4rp, "No routing protocol associated with Ipv4"); + if (DynamicCast (ipv4rp)) + { + NS_LOG_LOGIC ("Static routing found as the main IPv4 routing protocol."); + return DynamicCast (ipv4rp); + } + if (DynamicCast (ipv4rp)) + { + Ptr lrp = DynamicCast (ipv4rp); + int16_t priority; + for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) + { + NS_LOG_LOGIC ("Searching for static routing in list"); + Ptr temp = lrp->GetRoutingProtocol (i, priority); + if (DynamicCast (temp)) + { + NS_LOG_LOGIC ("Found static routing in list"); + return DynamicCast (temp); + } + } + } + NS_LOG_LOGIC ("Static routing not found"); + return 0; +} + +void +Ipv4StaticRoutingHelper::AddMulticastRoute ( + Ptr n, + Ipv4Address source, + Ipv4Address group, + Ptr input, + NetDeviceContainer output) +{ + Ptr ipv4 = n->GetObject (); + + // We need to convert the NetDeviceContainer to an array of interface + // numbers + std::vector outputInterfaces; + for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i) + { + Ptr nd = *i; + int32_t interface = ipv4->GetInterfaceForDevice (nd); + NS_ASSERT_MSG(interface >= 0, + "Ipv4StaticRoutingHelper::AddMulticastRoute(): " + "Expected an interface associated with the device nd"); + outputInterfaces.push_back(interface); + } + + int32_t inputInterface = ipv4->GetInterfaceForDevice (input); + NS_ASSERT_MSG(inputInterface >= 0, + "Ipv4StaticRoutingHelper::AddMulticastRoute(): " + "Expected an interface associated with the device input"); + Ipv4StaticRoutingHelper helper; + Ptr ipv4StaticRouting = helper.GetStaticRouting (ipv4); + if (!ipv4StaticRouting) + { + NS_ASSERT_MSG (ipv4StaticRouting, + "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): " + "Expected an Ipv4StaticRouting associated with this node"); + } + ipv4StaticRouting->AddMulticastRoute (source, group, inputInterface, outputInterfaces); +} + +void +Ipv4StaticRoutingHelper::AddMulticastRoute ( + Ptr n, + Ipv4Address source, + Ipv4Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + AddMulticastRoute (n, source, group, input, output); +} + +void +Ipv4StaticRoutingHelper::AddMulticastRoute ( + std::string nName, + Ipv4Address source, + Ipv4Address group, + Ptr input, + NetDeviceContainer output) +{ + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + +void +Ipv4StaticRoutingHelper::AddMulticastRoute ( + std::string nName, + Ipv4Address source, + Ipv4Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + +void +Ipv4StaticRoutingHelper::SetDefaultMulticastRoute ( + Ptr n, + Ptr nd) +{ + Ptr ipv4 = n->GetObject (); + int32_t interfaceSrc = ipv4->GetInterfaceForDevice (nd); + NS_ASSERT_MSG(interfaceSrc >= 0, + "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): " + "Expected an interface associated with the device"); + Ipv4StaticRoutingHelper helper; + Ptr ipv4StaticRouting = helper.GetStaticRouting (ipv4); + if (!ipv4StaticRouting) + { + NS_ASSERT_MSG (ipv4StaticRouting, + "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): " + "Expected an Ipv4StaticRouting associated with this node"); + } + ipv4StaticRouting->SetDefaultMulticastRoute (interfaceSrc); +} + +void +Ipv4StaticRoutingHelper::SetDefaultMulticastRoute ( + Ptr n, + std::string ndName) +{ + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); +} + +void +Ipv4StaticRoutingHelper::SetDefaultMulticastRoute ( + std::string nName, + Ptr nd) +{ + Ptr n = Names::Find (nName); + SetDefaultMulticastRoute (n, nd); +} + +void +Ipv4StaticRoutingHelper::SetDefaultMulticastRoute ( + std::string nName, + std::string ndName) +{ + Ptr n = Names::Find (nName); + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); +} + +}; // namespace ns3 diff --git a/src/helper/static-multicast-route-helper.h b/src/helper/ipv4-static-routing-helper.h similarity index 73% rename from src/helper/static-multicast-route-helper.h rename to src/helper/ipv4-static-routing-helper.h index 2d8586e0f..076bbde5a 100644 --- a/src/helper/static-multicast-route-helper.h +++ b/src/helper/ipv4-static-routing-helper.h @@ -1,6 +1,6 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2008 University of Washington + * Copyright (c) 2009 University of Washington * * 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 @@ -14,12 +14,13 @@ * 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: Tom Henderson */ -#ifndef STATIC_MULTICAST_ROUTE_HELPER_H -#define STATIC_MULTICAST_ROUTE_HELPER_H +#ifndef IPV4_STATIC_ROUTING_HELPER_H +#define IPV4_STATIC_ROUTING_HELPER_H + +#include "ns3/ipv4.h" +#include "ns3/ipv4-static-routing.h" #include "ns3/ptr.h" #include "ns3/ipv4-address.h" #include "ns3/node.h" @@ -29,10 +30,10 @@ namespace ns3 { -class StaticMulticastRouteHelper +class Ipv4StaticRoutingHelper { public: - StaticMulticastRouteHelper (); + Ptr GetStaticRouting (Ptr ipv4) const; void AddMulticastRoute (Ptr n, Ipv4Address source, Ipv4Address group, Ptr input, NetDeviceContainer output); @@ -43,15 +44,20 @@ public: void AddMulticastRoute (std::string nName, Ipv4Address source, Ipv4Address group, std::string inputName, NetDeviceContainer output); + /** + * \brief Add a default route to the static routing protocol to forward + * packets out a particular interface + * + * Functionally equivalent to: + * route add 224.0.0.0 netmask 240.0.0.0 dev nd + */ void SetDefaultMulticastRoute (Ptr n, Ptr nd); void SetDefaultMulticastRoute (Ptr n, std::string ndName); void SetDefaultMulticastRoute (std::string nName, Ptr nd); void SetDefaultMulticastRoute (std::string nName, std::string ndName); - void JoinMulticastGroup (Ptr n, Ipv4Address source, Ipv4Address group); - void JoinMulticastGroup (std::string nName, Ipv4Address source, Ipv4Address group); }; } // namespace ns3 -#endif /* STATIC_MULTICAST_ROUTE_HELPER_H */ +#endif /* IPV4_STATIC_ROUTING_HELPER_H */ diff --git a/src/helper/olsr-helper.cc b/src/helper/olsr-helper.cc index 58526d33a..c90897bf0 100644 --- a/src/helper/olsr-helper.cc +++ b/src/helper/olsr-helper.cc @@ -21,6 +21,7 @@ #include "ns3/olsr-routing-protocol.h" #include "ns3/node-list.h" #include "ns3/names.h" +#include "ns3/ipv4-list-routing.h" namespace ns3 { @@ -72,7 +73,9 @@ OlsrHelper::Install (Ptr node) Ptr agent = m_agentFactory.Create (); node->AggregateObject (agent); Ptr ipv4 = node->GetObject (); - ipv4->AddRoutingProtocol (agent, 10); + Ptr ipv4Routing = DynamicCast (ipv4->GetRoutingProtocol ()); + NS_ASSERT (ipv4Routing); + ipv4Routing->AddRoutingProtocol (agent, 10); agent->SetNode (node); agent->Start (); } diff --git a/src/helper/packet-sink-helper.cc b/src/helper/packet-sink-helper.cc index b0606af50..52873d850 100644 --- a/src/helper/packet-sink-helper.cc +++ b/src/helper/packet-sink-helper.cc @@ -38,22 +38,6 @@ PacketSinkHelper::SetAttribute (std::string name, const AttributeValue &value) m_factory.Set (name, value); } - -#if 0 -void -PacketSinkHelper::SetUdpLocal (Ipv4Address ip, uint16_t port) -{ - m_factory.Set ("Protocol", String ("ns3::UdpSocketFactory")); - m_factory.Set ("Local", Address (InetSocketAddress (ip, port))); -} -void -PacketSinkHelper::SetTcpLocal (Ipv4Address ip, uint16_t port) -{ - m_factory.Set ("Protocol", String ("ns3::TcpSocketFactory")); - m_factory.Set ("Local", Address (InetSocketAddress (ip, port))); -} -#endif - ApplicationContainer PacketSinkHelper::Install (Ptr node) const { diff --git a/src/helper/static-multicast-route-helper.cc b/src/helper/static-multicast-route-helper.cc deleted file mode 100644 index 3517b532a..000000000 --- a/src/helper/static-multicast-route-helper.cc +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2008 University of Washington - * - * 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: Tom Henderson - */ - -#include -#include "ns3/ptr.h" -#include "ns3/assert.h" -#include "ns3/ipv4-address.h" -#include "ns3/ipv4.h" -#include "ns3/names.h" -#include "static-multicast-route-helper.h" - -namespace ns3 { - -StaticMulticastRouteHelper::StaticMulticastRouteHelper () -{ -} - -void -StaticMulticastRouteHelper::AddMulticastRoute ( - Ptr n, - Ipv4Address source, - Ipv4Address group, - Ptr input, - NetDeviceContainer output) -{ - Ptr ipv4 = n->GetObject (); - - // We need to convert the NetDeviceContainer to an array of interface - std::vector outputInterfaces; - for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i) - { - Ptr nd = *i; - uint32_t ointerface = ipv4->FindInterfaceForDevice (nd); - outputInterfaces.push_back(ointerface); - } - uint32_t iinterface = ipv4->FindInterfaceForDevice (input); - ipv4->AddMulticastRoute (source, group, iinterface, outputInterfaces); -} - -void -StaticMulticastRouteHelper::AddMulticastRoute ( - Ptr n, - Ipv4Address source, - Ipv4Address group, - std::string inputName, - NetDeviceContainer output) -{ - Ptr input = Names::Find (inputName); - AddMulticastRoute (n, source, group, input, output); -} - -void -StaticMulticastRouteHelper::AddMulticastRoute ( - std::string nName, - Ipv4Address source, - Ipv4Address group, - Ptr input, - NetDeviceContainer output) -{ - Ptr n = Names::Find (nName); - AddMulticastRoute (n, source, group, input, output); -} - -void -StaticMulticastRouteHelper::AddMulticastRoute ( - std::string nName, - Ipv4Address source, - Ipv4Address group, - std::string inputName, - NetDeviceContainer output) -{ - Ptr input = Names::Find (inputName); - Ptr n = Names::Find (nName); - AddMulticastRoute (n, source, group, input, output); -} - -void -StaticMulticastRouteHelper::SetDefaultMulticastRoute ( - Ptr n, - Ptr nd) -{ - Ptr ipv4 = n->GetObject (); - uint32_t interfaceSrc = ipv4->FindInterfaceForDevice (nd); - ipv4->SetDefaultMulticastRoute (interfaceSrc); -} - -void -StaticMulticastRouteHelper::SetDefaultMulticastRoute ( - Ptr n, - std::string ndName) -{ - Ptr nd = Names::Find (ndName); - SetDefaultMulticastRoute (n, nd); -} - -void -StaticMulticastRouteHelper::SetDefaultMulticastRoute ( - std::string nName, - Ptr nd) -{ - Ptr n = Names::Find (nName); - SetDefaultMulticastRoute (n, nd); -} - -void -StaticMulticastRouteHelper::SetDefaultMulticastRoute ( - std::string nName, - std::string ndName) -{ - Ptr n = Names::Find (nName); - Ptr nd = Names::Find (ndName); - SetDefaultMulticastRoute (n, nd); -} - -void -StaticMulticastRouteHelper::JoinMulticastGroup ( - Ptr n, - Ipv4Address source, - Ipv4Address group) -{ - Ptr ipv4 = n->GetObject (); - ipv4->JoinMulticastGroup (source, group); -} - -void -StaticMulticastRouteHelper::JoinMulticastGroup ( - std::string nName, - Ipv4Address source, - Ipv4Address group) -{ - Ptr n = Names::Find (nName); - JoinMulticastGroup (n, source, group); -} - -} // namespace ns3 - diff --git a/src/helper/wscript b/src/helper/wscript index 97825f307..a9271dfef 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -7,12 +7,12 @@ def build(bld): 'net-device-container.cc', 'wifi-helper.cc', 'olsr-helper.cc', - 'static-multicast-route-helper.cc', 'point-to-point-helper.cc', 'csma-helper.cc', 'mobility-helper.cc', 'ns2-mobility-helper.cc', 'ipv4-address-helper.cc', + 'ipv4-static-routing-helper.cc', 'internet-stack-helper.cc', 'application-container.cc', 'on-off-helper.cc', @@ -34,12 +34,12 @@ def build(bld): 'net-device-container.h', 'wifi-helper.h', 'olsr-helper.h', - 'static-multicast-route-helper.h', 'point-to-point-helper.h', 'csma-helper.h', 'mobility-helper.h', 'ns2-mobility-helper.h', 'ipv4-address-helper.h', + 'ipv4-static-routing-helper.h', 'internet-stack-helper.h', 'application-container.h', 'on-off-helper.h', diff --git a/src/internet-stack/arp-ipv4-interface.cc b/src/internet-stack/arp-ipv4-interface.cc deleted file mode 100644 index 2c5a0c87a..000000000 --- a/src/internet-stack/arp-ipv4-interface.cc +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * 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 - * - * Authors: - * Mathieu Lacage , - */ - -#include "ns3/packet.h" -#include "ns3/log.h" -#include "ns3/node.h" -#include "ns3/net-device.h" -#include "ns3/address.h" -#include "ns3/pointer.h" - -#include "arp-ipv4-interface.h" -#include "ipv4-l3-protocol.h" -#include "arp-l3-protocol.h" -#include "arp-cache.h" - -NS_LOG_COMPONENT_DEFINE ("ArpIpv4Interface"); - -namespace ns3 { - -TypeId -ArpIpv4Interface::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::ArpIpv4Interface") - .SetParent () - .AddAttribute ("ArpCache", - "The arp cache for this ipv4 interface", - PointerValue (0), - MakePointerAccessor (&ArpIpv4Interface::m_cache), - MakePointerChecker ()) - ; - return tid; -} - -ArpIpv4Interface::ArpIpv4Interface () - : m_node (0), - m_device (0) -{ - NS_LOG_FUNCTION (this); -} - -ArpIpv4Interface::~ArpIpv4Interface () -{ - NS_LOG_FUNCTION (this); -} - -void -ArpIpv4Interface::DoDispose (void) -{ - NS_LOG_FUNCTION (this); - m_device = 0; - m_cache = 0; - Ipv4Interface::DoDispose (); -} - -void -ArpIpv4Interface::SetNode (Ptr node) -{ - m_node = node; - DoSetup (); -} -void -ArpIpv4Interface::SetDevice (Ptr device) -{ - m_device = device; - DoSetup (); -} - -Ptr -ArpIpv4Interface::GetDevice (void) const -{ - return m_device; -} - -void -ArpIpv4Interface::DoSetup (void) -{ - if (m_node == 0 || m_device == 0) - { - return; - } - Ptr arp = m_node->GetObject (); - m_cache = arp->CreateCache (m_device, this); -} - -void -ArpIpv4Interface::SendTo (Ptr p, Ipv4Address dest) -{ - NS_LOG_FUNCTION (this << p << dest); - - NS_ASSERT (GetDevice () != 0); - // XXX multi-address case - if (dest == GetAddress (0).GetLocal ()) - { - Ptr ipv4 = m_node->GetObject (); - - ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, - GetDevice ()->GetBroadcast (), - GetDevice ()->GetBroadcast (), - NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here - ); - return; - } - if (m_device->NeedsArp ()) - { - NS_LOG_LOGIC ("Needs ARP"); - Ptr arp = - m_node->GetObject (); - Address hardwareDestination; - bool found; - // XXX multi-address case - if (dest.IsBroadcast () || - dest.IsSubnetDirectedBroadcast (GetAddress (0).GetMask ()) ) - { - NS_LOG_LOGIC ("IsBroadcast"); - hardwareDestination = GetDevice ()->GetBroadcast (); - found = true; - } - else if (dest.IsMulticast ()) - { - NS_LOG_LOGIC ("IsMulticast"); - NS_ASSERT_MSG(GetDevice ()->IsMulticast (), - "ArpIpv4Interface::SendTo (): Sending multicast packet over " - "non-multicast device"); - - hardwareDestination = GetDevice ()->GetMulticast(dest); - found = true; - } - else - { - NS_LOG_LOGIC ("ARP Lookup"); - found = arp->Lookup (p, dest, GetDevice (), m_cache, &hardwareDestination); - } - - if (found) - { - NS_LOG_LOGIC ("Address Resolved. Send."); - GetDevice ()->Send (p, hardwareDestination, - Ipv4L3Protocol::PROT_NUMBER); - } - } - else - { - NS_LOG_LOGIC ("Doesn't need ARP"); - GetDevice ()->Send (p, GetDevice ()->GetBroadcast (), - Ipv4L3Protocol::PROT_NUMBER); - } -} - -}//namespace ns3 diff --git a/src/internet-stack/arp-ipv4-interface.h b/src/internet-stack/arp-ipv4-interface.h deleted file mode 100644 index 733e3b8ae..000000000 --- a/src/internet-stack/arp-ipv4-interface.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * 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 - * - * Authors: - * Mathieu Lacage , - */ -#ifndef ARP_IPV4_INTERFACE_H -#define ARP_IPV4_INTERFACE_H - -#include "ipv4-interface.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class Node; -class ArpCache; - -/** - * \ingroup arp - * \brief an Ipv4 Interface which uses ARP - * - * If you need to use ARP on top of a specific NetDevice, you - * can use this Ipv4Interface subclass to wrap it for the Ipv4 class - * when calling Ipv4::AggregateObject. - */ -class ArpIpv4Interface : public Ipv4Interface -{ -public: - static TypeId GetTypeId (void); - - ArpIpv4Interface (); - virtual ~ArpIpv4Interface (); - - void SetNode (Ptr node); - void SetDevice (Ptr device); - - virtual Ptr GetDevice (void) const; - -private: - virtual void SendTo (Ptr p, Ipv4Address dest); - virtual void DoDispose (void); - void DoSetup (void); - Ptr m_node; - Ptr m_device; - Ptr m_cache; -}; - -}//namespace ns3 - - -#endif /* ARP_IPV4_INTERFACE_H */ diff --git a/src/internet-stack/arp-l3-protocol.cc b/src/internet-stack/arp-l3-protocol.cc index 9f8e7787c..f0ff26da4 100644 --- a/src/internet-stack/arp-l3-protocol.cc +++ b/src/internet-stack/arp-l3-protocol.cc @@ -43,6 +43,7 @@ ArpL3Protocol::GetTypeId (void) { static TypeId tid = TypeId ("ns3::ArpL3Protocol") .SetParent () + .AddConstructor () .AddAttribute ("CacheList", "The list of ARP caches", ObjectVectorValue (), @@ -72,6 +73,23 @@ ArpL3Protocol::SetNode (Ptr node) m_node = node; } +/* + * This method is called by AddAgregate and completes the aggregation + * by setting the node in the ipv4 stack + */ +void +ArpL3Protocol::NotifyNewAggregate () +{ + Ptrnode = this->GetObject (); + //verify that it's a valid node and that + //the node was not set before + if (node!= 0 && m_node == 0) + { + this->SetNode (node); + } + Object::NotifyNewAggregate (); +} + void ArpL3Protocol::DoDispose (void) { diff --git a/src/internet-stack/arp-l3-protocol.h b/src/internet-stack/arp-l3-protocol.h index 9b46d71b6..7910d593a 100644 --- a/src/internet-stack/arp-l3-protocol.h +++ b/src/internet-stack/arp-l3-protocol.h @@ -78,6 +78,11 @@ public: Address *hardwareDestination); 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: typedef std::list > CacheList; Ptr FindCache (Ptr device); diff --git a/src/internet-stack/icmpv4-l4-protocol.cc b/src/internet-stack/icmpv4-l4-protocol.cc index 8ee8cbc57..49dfc2dcd 100644 --- a/src/internet-stack/icmpv4-l4-protocol.cc +++ b/src/internet-stack/icmpv4-l4-protocol.cc @@ -1,4 +1,5 @@ #include "icmpv4-l4-protocol.h" +#include "ipv4-raw-socket-factory-impl.h" #include "ipv4-interface.h" #include "ipv4-l3-protocol.h" #include "ns3/assert.h" @@ -6,6 +7,7 @@ #include "ns3/node.h" #include "ns3/packet.h" #include "ns3/boolean.h" +#include "ns3/ipv4-route.h" namespace ns3 { @@ -47,6 +49,27 @@ Icmpv4L4Protocol::SetNode (Ptr node) m_node = node; } +/* + * This method is called by AddAgregate and completes the aggregation + * by setting the node in the ICMP stack and adding ICMP factory to + * IPv4 stack connected to the node + */ +void +Icmpv4L4Protocol::NotifyNewAggregate () +{ + bool is_not_initialized = (m_node == 0); + Ptrnode = this->GetObject (); + Ptr ipv4 = this->GetObject (); + if (is_not_initialized && node!= 0 && ipv4 != 0) + { + this->SetNode (node); + ipv4->Insert (this); + Ptr rawFactory = CreateObject (); + ipv4->AggregateObject (rawFactory); + } + Object::NotifyNewAggregate (); +} + uint16_t Icmpv4L4Protocol::GetStaticProtocolNumber (void) { @@ -62,19 +85,27 @@ void Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address dest, uint8_t type, uint8_t code) { Ptr ipv4 = m_node->GetObject (); - uint32_t i; - if (!ipv4->GetInterfaceForDestination (dest, i)) + NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0); + Ipv4Header header; + header.SetDestination (dest); + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + if (route != 0) + { + NS_LOG_LOGIC ("Route exists"); + Ipv4Address source = route->GetSource (); + SendMessage (packet, source, dest, type, code, route); + } + else { NS_LOG_WARN ("drop icmp message"); - return; } - // XXX handle multi-address case - Ipv4Address source = ipv4->GetAddress (i, 0).GetLocal (); - SendMessage (packet, source, dest, type, code); } void -Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code) +Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr route) { Ptr ipv4 = m_node->GetObject (); Icmpv4Header icmp; @@ -85,7 +116,7 @@ Icmpv4L4Protocol::SendMessage (Ptr packet, Ipv4Address source, Ipv4Addre icmp.EnableChecksum (); } packet->AddHeader (icmp); - ipv4->Send (packet, source, dest, ICMP_PROTOCOL); + ipv4->Send (packet, source, dest, ICMP_PROTOCOL, route); } void Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header, @@ -140,7 +171,7 @@ Icmpv4L4Protocol::HandleEcho (Ptr p, Icmpv4Echo echo; p->RemoveHeader (echo); reply->AddHeader (echo); - SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0); + SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0, 0); } void Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp, diff --git a/src/internet-stack/icmpv4-l4-protocol.h b/src/internet-stack/icmpv4-l4-protocol.h index 71310f84d..d9f328c30 100644 --- a/src/internet-stack/icmpv4-l4-protocol.h +++ b/src/internet-stack/icmpv4-l4-protocol.h @@ -9,6 +9,7 @@ namespace ns3 { class Node; class Ipv4Interface; +class Ipv4Route; class Icmpv4L4Protocol : public Ipv4L4Protocol { @@ -29,7 +30,12 @@ public: void SendDestUnreachFragNeeded (Ipv4Header header, Ptr orgData, uint16_t nextHopMtu); void SendTimeExceededTtl (Ipv4Header header, Ptr orgData); void SendDestUnreachPort (Ipv4Header header, Ptr orgData); - +protected: + /* + * 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: void HandleEcho (Ptr p, Icmpv4Header header, @@ -46,7 +52,7 @@ private: void SendDestUnreach (Ipv4Header header, Ptr orgData, uint8_t code, uint16_t nextHopMtu); void SendMessage (Ptr packet, Ipv4Address dest, uint8_t type, uint8_t code); - void SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code); + void SendMessage (Ptr packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr route); void Forward (Ipv4Address source, Icmpv4Header icmp, uint32_t info, Ipv4Header ipHeader, const uint8_t payload[8]); diff --git a/src/internet-stack/internet-stack.cc b/src/internet-stack/internet-stack.cc deleted file mode 100644 index e02f24286..000000000 --- a/src/internet-stack/internet-stack.cc +++ /dev/null @@ -1,141 +0,0 @@ -// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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: George F. Riley -// - -#include "ns3/net-device.h" -#include "ns3/callback.h" -#include "ns3/node.h" -#include "ns3/core-config.h" - -#include "udp-l4-protocol.h" -#include "tcp-l4-protocol.h" -#include "ipv4-l3-protocol.h" -#include "arp-l3-protocol.h" -#include "udp-socket-factory-impl.h" -#include "tcp-socket-factory-impl.h" -#include "ipv4-raw-socket-factory-impl.h" -#include "icmpv4-l4-protocol.h" -#ifdef NETWORK_SIMULATION_CRADLE -#include "nsc-tcp-socket-factory-impl.h" -#include "nsc-tcp-l4-protocol.h" -#endif - -namespace ns3 { - -static void -AddArpStack (Ptr node) -{ - Ptr arp = CreateObject (); - arp->SetNode (node); - node->AggregateObject (arp); -} - -static void -AddUdpStack(Ptr node) -{ - Ptr ipv4 = node->GetObject (); - Ptr udp = CreateObject (); - udp->SetNode (node); - ipv4->Insert (udp); - node->AggregateObject (udp); - - Ptr udpFactory = CreateObject (); - udpFactory->SetUdp (udp); - node->AggregateObject (udpFactory); -} - -static void -AddIcmpStack (Ptr node) -{ - Ptr ipv4 = node->GetObject (); - Ptr icmp = CreateObject (); - icmp->SetNode (node); - ipv4->Insert (icmp); - node->AggregateObject (icmp); - - Ptr rawFactory = CreateObject (); - node->AggregateObject (rawFactory); -} - -static void -AddTcpStack(Ptr node) -{ - Ptr ipv4 = node->GetObject (); - Ptr tcp = CreateObject (); - tcp->SetNode (node); - ipv4->Insert (tcp); - node->AggregateObject (tcp); - - Ptr tcpFactory = CreateObject (); - tcpFactory->SetTcp (tcp); - node->AggregateObject (tcpFactory); -} - -static void -AddIpv4Stack(Ptr node) -{ - Ptr ipv4 = CreateObject (); - ipv4->SetNode (node); - node->AggregateObject (ipv4); -} - -void -AddInternetStack (Ptr node) -{ - AddArpStack (node); - AddIpv4Stack (node); - AddIcmpStack (node); - AddUdpStack (node); - AddTcpStack (node); -} - -#ifdef NETWORK_SIMULATION_CRADLE -static void -AddNscStack(Ptr node, const std::string &soname) -{ - Ptr ipv4 = node->GetObject (); - Ptr tcp = CreateObject (); - tcp->SetNscLibrary(soname); - tcp->SetNode (node); - ipv4->Insert (tcp); - node->AggregateObject (tcp); - - Ptr tcpFactory = CreateObject (); - tcpFactory->SetTcp (tcp); - node->AggregateObject (tcpFactory); -} - - -void -AddNscInternetStack (Ptr node, const std::string &soname) -{ - AddArpStack (node); - AddIpv4Stack (node); - AddIcmpStack (node); - AddUdpStack (node); - AddNscStack (node, soname); -} -#else -void -AddNscInternetStack (Ptr node, const std::string &soname) -{ - NS_FATAL_ERROR ("NSC Not enabled on this platform."); -} -#endif -}//namespace ns3 diff --git a/src/internet-stack/internet-stack.h b/src/internet-stack/internet-stack.h deleted file mode 100644 index 77c46660e..000000000 --- a/src/internet-stack/internet-stack.h +++ /dev/null @@ -1,163 +0,0 @@ -// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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: George F. Riley - -#ifndef INTERNET_STACK_H -#define INTERNET_STACK_H - -#include "ns3/ptr.h" - -/** - * \ingroup internetStack - * \defgroup internetStackModel Internet Stack Model - * - * \section internetStackTracingModel Tracing in the Internet Stack - * - * The internet stack provides a number of trace sources in its various - * protocol implementations. These trace sources can be hooked using your own - * custom trace code, or you can use our helper functions in some cases to - * arrange for tracing to be enabled. - * - * \subsection internetStackArpTracingModel Tracing in ARP - * - * ARP provides two trace hooks, one in the cache, and one in the layer three - * protocol. The trace accessor in the cache is given the name "Drop." When - * a packet is transmitted over an interface that requires ARP, it is first - * queued for transmission in the ARP cache until the required MAC address is - * resolved. There are a number of retries that may be done trying to get the - * address, and if the maximum retry count is exceeded the packet in question - * is dropped by ARP. The single trace hook in the ARP cache is called, - * - * - If an outbound packet is placed in the ARP cache pending address resolution - * and no resolution can be made within the maximum retry count, the outbound - * packet is dropped and this trace is fired; - * - * A second trace hook lives in the ARP L3 protocol (also named "Drop") and may - * be called for a number of reasons. - * - * - If an ARP reply is received for an entry that is not waiting for a reply, - * the ARP reply packet is dropped and this trace is fired; - * - If an ARP reply is received for a non-existant entry, the ARP reply packet - * is dropped and this trace is fired; - * - If an ARP cache entry is in the DEAD state (has timed out) and an ARP reply - * packet is received, the reply packet is dropped and this trace is fired. - * - Each ARP cache entry has a queue of pending packets. If the size of the - * queue is exceeded, the outbound packet is dropped and this trace is fired. - * - * \subsection internetStackIpv4TracingModel Tracing in IPv4 - * - * The IPv4 layer three protocol provides three trace hooks. These are the - * "Tx" (ns3::Ipv4L3Protocol::m_txTrace), "Rx" (ns3::Ipv4L3Protocol::m_rxTrace) - * and "Drop" (ns3::Ipv4L3Protocol::m_dropTrace) trace sources. - * - * The "Tx" trace is fired in a number of situations, all of which indicate that - * a given packet is about to be sent down to a given ns3::Ipv4Interface. - * - * - In the case of a packet destined for the broadcast address, the - * Ipv4InterfaceList is iterated and for every interface that is up and can - * fragment the packet or has a large enough MTU to transmit the packet, - * the trace is hit. See ns3::Ipv4L3Protocol::Send. - * - * - In the case of a packet that needs routing, the "Tx" trace may be fired - * just before a packet is sent to the interface appropriate to the default - * gateway. See ns3::Ipv4L3Protocol::SendRealOut. - * - * - Also in the case of a packet that needs routing, the "Tx" trace may be - * fired just before a packet is sent to the outgoing interface appropriate - * to the discovered route. See ns3::Ipv4L3Protocol::SendRealOut. - * - * The "Rx" trace is fired when a packet is passed from the device up to the - * ns3::Ipv4L3Protocol::Receive function. - * - * - In the receive function, the Ipv4InterfaceList is iterated, and if the - * Ipv4Interface corresponding to the receiving device is fount to be in the - * UP state, the trace is fired. - * - * The "Drop" trace is fired in any case where the packet is dropped (in both - * the transmit and receive paths). - * - * - In the ns3::Ipv4Interface::Receive function, the packet is dropped and the - * drop trace is hit if the interface corresponding to the receiving device - * is in the DOWN state. - * - * - Also in the ns3::Ipv4Interface::Receive function, the packet is dropped and - * the drop trace is hit if the checksum is found to be bad. - * - * - In ns3::Ipv4L3Protocol::Send, an outgoing packet bound for the broadcast - * address is dropped and the "Drop" trace is fired if the "don't fragement" - * bit is set and fragmentation is available and required. - * - * - Also in ns3::Ipv4L3Protocol::Send, an outgoing packet destined for the - * broadcast address is dropped and the "Drop" trace is hit if fragmentation - * is not available and is required (MTU < packet size). - * - * - In the case of a broadcast address, an outgoing packet is cloned for each - * outgoing interface. If any of the interfaces is in the DOWN state, the - * "Drop" trace event fires with a reference to the copied packet. - * - * - In the case of a packet requiring a route, an outgoing packet is dropped - * and the "Drop" trace event fires if no route to the remote host is found. - * - * - In ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed - * is dropped and the "Drop" trace is fired if the "don't fragement" bit is - * set and fragmentation is available and required. - * - * - Also in ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed - * is dropped and the "Drop" trace is hit if fragmentation is not available - * and is required (MTU < packet size). - * - * - An outgoing packet being routed is dropped and the "Drop" trace event fires - * if the required Ipv4Interface is in the DOWN state. - * - * - If a packet is being forwarded, and the TTL is exceeded (see - * ns3::Ipv4L3Protocol::DoForward), the packet is dropped and the "Drop" trace - * event is fired. - * - * \subsection internetStackNs3TCPTracingModel Tracing in ns-3 TCP - * - * There is currently one trace source in the ns-3 TCP implementation named - * "CongestionWindow" (see ns3::TcpSocketImpl::m_cWnd). This is set in a number - * of places (see file tcp-socket-impl.cc) whenever the value of the congestion - * window is changed. - * - * \subsection internetStackNscTCPTracingModel Tracing in NSC TCP - * - * There is currently one trace source in the Network Simulation Cradle TCP - * implementation named "CongestionWindow" (see ns3::NscTcpSocketImpl::m_cWnd). - * This is set in a number of places (see file nsc-tcp-socket-impl.cc) when - * the value of the cogestion window is initially set. Note that this is not - * instrumented from the underlying TCP implementaion. - * - * \subsection internetStackNs3UdpTracingModel Tracing in ns-3 UDP - * - * There is currently one trace source in the ns-3 UDP implementation named - * "Drop" (see ns3::UdpSocketImpl::m_dropTrace). This is set when a packet - * is received in ns3::UdpSocketImpl::ForwardUp and the receive buffer cannot - * accomodate the encapsulated data. - */ - -namespace ns3 { - -class Node; - -void AddInternetStack (Ptr node); -void AddNscInternetStack (Ptr node, const std::string &soname); - -}//namespace ns3 - -#endif /* INTERNET_STACK_H */ diff --git a/src/internet-stack/ipv4-global-routing.cc b/src/internet-stack/ipv4-global-routing.cc index 11a177a42..e6577ce34 100644 --- a/src/internet-stack/ipv4-global-routing.cc +++ b/src/internet-stack/ipv4-global-routing.cc @@ -18,9 +18,11 @@ #include "ns3/log.h" #include "ns3/object.h" -#include "ipv4-global-routing.h" #include "ns3/packet.h" #include "ns3/node.h" +#include "ns3/ipv4-route.h" +#include "ns3/ipv4-routing-table-entry.h" +#include "ipv4-global-routing.h" NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting"); @@ -42,14 +44,19 @@ Ipv4GlobalRouting::Ipv4GlobalRouting () NS_LOG_FUNCTION_NOARGS (); } +Ipv4GlobalRouting::~Ipv4GlobalRouting () +{ + NS_LOG_FUNCTION_NOARGS (); +} + void Ipv4GlobalRouting::AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, uint32_t interface) { NS_LOG_FUNCTION (dest << nextHop << interface); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, nextHop, interface); m_hostRoutes.push_back (route); } @@ -58,8 +65,8 @@ Ipv4GlobalRouting::AddHostRouteTo (Ipv4Address dest, uint32_t interface) { NS_LOG_FUNCTION (dest << interface); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, interface); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, interface); m_hostRoutes.push_back (route); } @@ -70,8 +77,8 @@ Ipv4GlobalRouting::AddNetworkRouteTo (Ipv4Address network, uint32_t interface) { NS_LOG_FUNCTION (network << networkMask << nextHop << interface); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkMask, nextHop, interface); @@ -84,17 +91,21 @@ Ipv4GlobalRouting::AddNetworkRouteTo (Ipv4Address network, uint32_t interface) { NS_LOG_FUNCTION (network << networkMask << interface); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkMask, interface); m_networkRoutes.push_back (route); } -Ipv4Route * +Ptr Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest) { NS_LOG_FUNCTION_NOARGS (); + Ptr rtentry = 0; + bool found = false; + Ipv4RoutingTableEntry* route = 0; + for (HostRoutesCI i = m_hostRoutes.begin (); i != m_hostRoutes.end (); i++) @@ -103,23 +114,45 @@ Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest) if ((*i)->GetDest ().IsEqual (dest)) { NS_LOG_LOGIC ("Found global host route" << *i); - return (*i); + route = (*i); + found = true; + break; } } - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) + if (found == false) { - NS_ASSERT ((*j)->IsNetwork ()); - Ipv4Mask mask = (*j)->GetDestNetworkMask (); - Ipv4Address entry = (*j)->GetDestNetwork (); - if (mask.IsMatch (dest, entry)) + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) { - NS_LOG_LOGIC ("Found global network route" << *j); - return (*j); + NS_ASSERT ((*j)->IsNetwork ()); + Ipv4Mask mask = (*j)->GetDestNetworkMask (); + Ipv4Address entry = (*j)->GetDestNetwork (); + if (mask.IsMatch (dest, entry)) + { + NS_LOG_LOGIC ("Found global network route" << *j); + route = (*j); + found = true; + break; + } } } - return 0; + if (found == true) + { + Ptr ipv4 = m_node->GetObject (); + rtentry = Create (); + rtentry->SetDestination (route->GetDest ()); + // XXX handle multi-address case + rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ()); + rtentry->SetGateway (route->GetGateway ()); + uint32_t interfaceIdx = route->GetInterface (); + rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx)); + return rtentry; + } + else + { + return 0; + } } uint32_t @@ -132,7 +165,7 @@ Ipv4GlobalRouting::GetNRoutes (void) return n; } -Ipv4Route * +Ipv4RoutingTableEntry * Ipv4GlobalRouting::GetRoute (uint32_t index) { NS_LOG_FUNCTION (index); @@ -207,70 +240,6 @@ Ipv4GlobalRouting::RemoveRoute (uint32_t index) NS_ASSERT (false); } -bool -Ipv4GlobalRouting::RequestRoute ( - uint32_t interface, - Ipv4Header const &ipHeader, - Ptr packet, - RouteReplyCallback routeReply) -{ - NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); - - NS_LOG_LOGIC ("source = " << ipHeader.GetSource ()); - - NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ()); - - if (ipHeader.GetDestination ().IsMulticast ()) - { - NS_LOG_LOGIC ("Multicast destination-- returning false"); - return false; // Let other routing protocols try to handle this - } - -// This is a unicast packet. Check to see if we have a route for it. -// - NS_LOG_LOGIC ("Unicast destination- looking up"); - Ipv4Route *route = LookupGlobal (ipHeader.GetDestination ()); - if (route != 0) - { - routeReply (true, *route, packet, ipHeader); - return true; - } - else - { - return false; // Let other routing protocols try to handle this - // route request. - } -} - -bool -Ipv4GlobalRouting::RequestInterface (Ipv4Address destination, uint32_t& interface) -{ - NS_LOG_FUNCTION (this << destination << &interface); -// -// First, see if this is a multicast packet we have a route for. If we -// have a route, then send the packet down each of the specified interfaces. -// - if (destination.IsMulticast ()) - { - NS_LOG_LOGIC ("Multicast destination-- returning false"); - return false; // Let other routing protocols try to handle this - } -// -// See if this is a unicast packet we have a route for. -// - NS_LOG_LOGIC ("Unicast destination- looking up"); - Ipv4Route *route = LookupGlobal (destination); - if (route) - { - interface = route->GetInterface (); - return true; - } - else - { - return false; - } -} - void Ipv4GlobalRouting::DoDispose (void) { @@ -290,4 +259,80 @@ Ipv4GlobalRouting::DoDispose (void) Ipv4RoutingProtocol::DoDispose (); } +Ptr +Ipv4GlobalRouting::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr) +{ + +// +// First, see if this is a multicast packet we have a route for. If we +// have a route, then send the packet down each of the specified interfaces. +// + if (header.GetDestination().IsMulticast ()) + { + NS_LOG_LOGIC ("Multicast destination-- returning false"); + return 0; // Let other routing protocols try to handle this + } +// +// See if this is a unicast packet we have a route for. +// + NS_LOG_LOGIC ("Unicast destination- looking up"); + Ptr rtentry = LookupGlobal (header.GetDestination()); + if (rtentry) + { + sockerr = Socket::ERROR_NOTERROR; + } + else + { + sockerr = Socket::ERROR_NOROUTETOHOST; + } + return rtentry; +} + +bool +Ipv4GlobalRouting::RouteInput (Ptr p, const Ipv4Header &ipHeader, Ptr idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) +{ + + NS_LOG_FUNCTION (this << p << ipHeader << ipHeader.GetSource () << ipHeader.GetDestination () << idev); + + if (ipHeader.GetDestination ().IsMulticast ()) + { + NS_LOG_LOGIC ("Multicast destination-- returning false"); + return false; // Let other routing protocols try to handle this + } + +// This is a unicast packet. Check to see if we have a route for it. +// + NS_LOG_LOGIC ("Unicast destination- looking up"); + Ptr rtentry = LookupGlobal (ipHeader.GetDestination ()); + if (rtentry != 0) + { + NS_LOG_LOGIC ("Found unicast destination- calling unicast callback"); + ucb (rtentry, p, ipHeader); + return true; + } + else + { + NS_LOG_LOGIC ("Did not find unicast destination- returning false"); + return false; // Let other routing protocols try to handle this + // route request. + } +} + +void +Ipv4GlobalRouting::SetNode (Ptr node) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = node; +} + +Ptr +Ipv4GlobalRouting::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + + + }//namespace ns3 diff --git a/src/internet-stack/ipv4-global-routing.h b/src/internet-stack/ipv4-global-routing.h index 9be7a03e5..ab040b068 100644 --- a/src/internet-stack/ipv4-global-routing.h +++ b/src/internet-stack/ipv4-global-routing.h @@ -26,6 +26,7 @@ #include "ns3/ipv4-header.h" #include "ns3/ptr.h" #include "ns3/ipv4.h" +#include "ns3/ipv4-routing-protocol.h" namespace ns3 { @@ -34,12 +35,13 @@ class NetDevice; class Ipv4Interface; class Ipv4Address; class Ipv4Header; -class Ipv4Route; +class Ipv4RoutingTableEntry; +class Ipv4MulticastRoutingTableEntry; class Node; /** - * @brief Global routing protocol for IP version 4 stacks. + * \brief Global routing protocol for IP version 4 stacks. * * In ns-3 we have the concept of a pluggable routing protocol. Routing * protocols are added to a list maintained by the Ipv4L3Protocol. Every @@ -60,126 +62,65 @@ class Node; * * This class deals with Ipv4 unicast routes only. * - * @see Ipv4RoutingProtocol - * @see GlobalRouteManager + * \see Ipv4RoutingProtocol + * \see GlobalRouteManager */ class Ipv4GlobalRouting : public Ipv4RoutingProtocol { public: static TypeId GetTypeId (void); /** - * @brief Construct an empty Ipv4GlobalRouting routing protocol, + * \brief Construct an empty Ipv4GlobalRouting routing protocol, * * The Ipv4GlobalRouting class supports host and network unicast routes. * This method initializes the lists containing these routes to empty. * - * @see Ipv4GlobalRouting + * \see Ipv4GlobalRouting */ Ipv4GlobalRouting (); + virtual ~Ipv4GlobalRouting (); + + virtual Ptr RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + + virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb); /** - * @brief Request that a check for a route bw performed and if a route is found - * that the packet be sent on its way using the pre-packaged send callback. + * \brief Add a host route to the global routing table. * - * The source and destination IP addresses for the packet in question are found - * in the provided Ipv4Header. There are two major processing forks depending - * on the type of destination address. - * - * If the destination address is unicast then the routing table is consulted - * for a route to the destination and if it is found, the routeReply callback - * is executed to send the packet (with the found route). - * - * If the destination address is a multicast, then the method will return - * false. - * - * @param interface The network interface index over which the packed was - * received. If the packet is from a local source, interface will be set to - * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY. - * @param ipHeader the Ipv4Header containing the source and destination IP - * addresses for the packet. - * @param packet The packet to be sent if a route is found. - * @param routeReply A callback that packaged up the call to actually send the - * packet. - * @return Returns true if a route is found and the packet has been sent, - * otherwise returns false indicating that the next routing protocol should - * be consulted. - * - * @see Ipv4GlobalRouting - * @see Ipv4RoutingProtocol - */ - virtual bool RequestRoute (uint32_t interface, - Ipv4Header const &ipHeader, - Ptr packet, - RouteReplyCallback routeReply); - -/** - * @brief Check to see if we can determine the interface index that will be - * used if a packet is sent to this destination. - * - * This method addresses a problem in the IP stack where a destination address - * must be present and checksummed into the IP header before the actual - * interface over which the packet is sent can be determined. The answer is - * to implement a known and intentional cross-layer violation. This is the - * endpoint of a call chain that started up quite high in the stack (sockets) - * and has found its way down to the Ipv4L3Protocol which is consulting the - * routing protocols for what they would do if presented with a packet of the - * given destination. - * - * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more - * contextual information that is useful for making a determination. - * - * This method will return false on a multicast address. - * - * @param destination The Ipv4Address if the destination of a hypothetical - * packet. This may be a multicast group address. - * @param interface A reference to the interface index over which a packet - * sent to this destination would be sent. - * @return Returns true if a route is found to the destination that involves - * a single output interface index, otherwise returns false indicating that - * the next routing protocol should be consulted. - * - * @see Ipv4GlobalRouting - * @see Ipv4RoutingProtocol - * @see Ipv4L3Protocol - */ - virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface); - -/** - * @brief Add a host route to the global routing table. - * - * @param dest The Ipv4Address destination for this route. - * @param nextHop The Ipv4Address of the next hop in the route. - * @param interface The network interface index used to send packets to the + * \param dest The Ipv4Address destination for this route. + * \param nextHop The Ipv4Address of the next hop in the route. + * \param interface The network interface index used to send packets to the * destination. * - * @see Ipv4Address + * \see Ipv4Address */ void AddHostRouteTo (Ipv4Address dest, Ipv4Address nextHop, uint32_t interface); /** - * @brief Add a host route to the global routing table. + * \brief Add a host route to the global routing table. * - * @param dest The Ipv4Address destination for this route. - * @param interface The network interface index used to send packets to the + * \param dest The Ipv4Address destination for this route. + * \param interface The network interface index used to send packets to the * destination. * - * @see Ipv4Address + * \see Ipv4Address */ void AddHostRouteTo (Ipv4Address dest, uint32_t interface); /** - * @brief Add a network route to the global routing table. + * \brief Add a network route to the global routing table. * - * @param network The Ipv4Address network for this route. - * @param networkMask The Ipv4Mask to extract the network. - * @param nextHop The next hop in the route to the destination network. - * @param interface The network interface index used to send packets to the + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param nextHop The next hop in the route to the destination network. + * \param interface The network interface index used to send packets to the * destination. * - * @see Ipv4Address + * \see Ipv4Address */ void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkMask, @@ -187,29 +128,29 @@ public: uint32_t interface); /** - * @brief Add a network route to the global routing table. + * \brief Add a network route to the global routing table. * - * @param network The Ipv4Address network for this route. - * @param networkMask The Ipv4Mask to extract the network. - * @param interface The network interface index used to send packets to the + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param interface The network interface index used to send packets to the * destination. * - * @see Ipv4Address + * \see Ipv4Address */ void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkMask, uint32_t interface); /** - * @brief Get the number of individual unicast routes that have been added + * \brief Get the number of individual unicast routes that have been added * to the routing table. * - * @warning The default route counts as one of the routes. + * \warning The default route counts as one of the routes. */ uint32_t GetNRoutes (void); /** - * @brief Get a route from the global unicast routing table. + * \brief Get a route from the global unicast routing table. * * Externally, the unicast global routing table appears simply as a table with * n entries. The one sublety of note is that if a default route has been set @@ -220,18 +161,18 @@ public: * Similarly, if the default route has been set, calling RemoveRoute (0) will * remove the default route. * - * @param i The index (into the routing table) of the route to retrieve. If + * \param i The index (into the routing table) of the route to retrieve. If * the default route has been set, it will occupy index zero. - * @return If route is set, a pointer to that Ipv4Route is returned, otherwise + * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise * a zero pointer is returned. * - * @see Ipv4Route - * @see Ipv4GlobalRouting::RemoveRoute + * \see Ipv4RoutingTableEntry + * \see Ipv4GlobalRouting::RemoveRoute */ - Ipv4Route *GetRoute (uint32_t i); + Ipv4RoutingTableEntry *GetRoute (uint32_t i); /** - * @brief Remove a route from the global unicast routing table. + * \brief Remove a route from the global unicast routing table. * * Externally, the unicast global routing table appears simply as a table with * n entries. The one sublety of note is that if a default route has been set @@ -239,30 +180,35 @@ public: * default route has been set, calling RemoveRoute (0) will remove the * default route. * - * @param i The index (into the routing table) of the route to remove. If + * \param i The index (into the routing table) of the route to remove. If * the default route has been set, it will occupy index zero. * - * @see Ipv4Route - * @see Ipv4GlobalRouting::GetRoute - * @see Ipv4GlobalRouting::AddRoute + * \see Ipv4RoutingTableEntry + * \see Ipv4GlobalRouting::GetRoute + * \see Ipv4GlobalRouting::AddRoute */ void RemoveRoute (uint32_t i); + void SetNode (Ptr node); + Ptr GetNode (void) const; + protected: void DoDispose (void); private: - typedef std::list HostRoutes; - typedef std::list::const_iterator HostRoutesCI; - typedef std::list::iterator HostRoutesI; - typedef std::list NetworkRoutes; - typedef std::list::const_iterator NetworkRoutesCI; - typedef std::list::iterator NetworkRoutesI; + typedef std::list HostRoutes; + typedef std::list::const_iterator HostRoutesCI; + typedef std::list::iterator HostRoutesI; + typedef std::list NetworkRoutes; + typedef std::list::const_iterator NetworkRoutesCI; + typedef std::list::iterator NetworkRoutesI; - Ipv4Route *LookupGlobal (Ipv4Address dest); + Ptr LookupGlobal (Ipv4Address dest); HostRoutes m_hostRoutes; NetworkRoutes m_networkRoutes; + + Ptr m_node; }; } // Namespace ns3 diff --git a/src/internet-stack/ipv4-interface.cc b/src/internet-stack/ipv4-interface.cc index 1bba30f39..a96fcf1fa 100644 --- a/src/internet-stack/ipv4-interface.cc +++ b/src/internet-stack/ipv4-interface.cc @@ -19,10 +19,16 @@ */ #include "ipv4-interface.h" +#include "loopback-net-device.h" #include "ns3/ipv4-address.h" +#include "ipv4-l3-protocol.h" +#include "arp-l3-protocol.h" +#include "arp-cache.h" #include "ns3/net-device.h" #include "ns3/log.h" #include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/pointer.h" NS_LOG_COMPONENT_DEFINE ("Ipv4Interface"); @@ -33,19 +39,27 @@ Ipv4Interface::GetTypeId (void) { static TypeId tid = TypeId ("ns3::Ipv4Interface") .SetParent () + .AddAttribute ("ArpCache", + "The arp cache for this ipv4 interface", + PointerValue (0), + MakePointerAccessor (&Ipv4Interface::m_cache), + MakePointerChecker ()) + ; ; return tid; } - /** - * By default, Ipv4 interface are created in the "down" state - * with ip address 192.168.0.1 and a matching mask. Before - * becoming useable, the user must invoke SetUp on them - * once the final Ipv4 address and mask has been set. - */ +/** + * By default, Ipv4 interface are created in the "down" state + * with no IP addresses. Before becoming useable, the user must + * invoke SetUp on them once an Ipv4 address and mask have been set. + */ Ipv4Interface::Ipv4Interface () - : m_ifup(false), - m_metric(1) + : m_ifup (false), + m_metric (1), + m_node (0), + m_device (0), + m_cache (0) { NS_LOG_FUNCTION (this); } @@ -59,9 +73,46 @@ void Ipv4Interface::DoDispose (void) { NS_LOG_FUNCTION_NOARGS (); + m_node = 0; + m_device = 0; Object::DoDispose (); } +void +Ipv4Interface::SetNode (Ptr node) +{ + m_node = node; + DoSetup (); +} + +void +Ipv4Interface::SetDevice (Ptr device) +{ + m_device = device; + DoSetup (); +} + +void +Ipv4Interface::DoSetup (void) +{ + if (m_node == 0 || m_device == 0) + { + return; + } + if (!m_device->NeedsArp ()) + { + return; + } + Ptr arp = m_node->GetObject (); + m_cache = arp->CreateCache (m_device, this); +} + +Ptr +Ipv4Interface::GetDevice (void) const +{ + return m_device; +} + void Ipv4Interface::SetMetric (uint16_t metric) { @@ -80,12 +131,7 @@ uint16_t Ipv4Interface::GetMtu (void) const { NS_LOG_FUNCTION_NOARGS (); - if (GetDevice () == 0) - { - uint32_t mtu = (1<<16) - 1; - return mtu; - } - return GetDevice ()->GetMtu (); + return m_device->GetMtu (); } /** @@ -121,15 +167,92 @@ Ipv4Interface::SetDown (void) m_ifup = false; } -// public wrapper on private virtual function -void -Ipv4Interface::Send(Ptr p, Ipv4Address dest) +void +Ipv4Interface::Send (Ptr p, Ipv4Address dest) { NS_LOG_FUNCTION_NOARGS (); - if (IsUp()) { - NS_LOG_LOGIC ("SendTo"); - SendTo(p, dest); - } + if (!IsUp()) + { + return; + } + // Check for a loopback device + if (DynamicCast (m_device)) + { + // XXX additional checks needed here (such as whether multicast + // goes to loopback)? + m_device->Send (p, m_device->GetBroadcast (), + Ipv4L3Protocol::PROT_NUMBER); + return; + } + // is this packet aimed at a local interface ? + for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i) + { + if (dest == (*i).GetLocal ()) + { + Ptr ipv4 = m_node->GetObject (); + + ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, + m_device->GetBroadcast (), + m_device->GetBroadcast (), + NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here + ); + return; + } + } + if (m_device->NeedsArp ()) + { + NS_LOG_LOGIC ("Needs ARP" << " " << dest); + Ptr arp = m_node->GetObject (); + Address hardwareDestination; + bool found = false; + if (dest.IsBroadcast ()) + { + NS_LOG_LOGIC ("All-network Broadcast"); + hardwareDestination = m_device->GetBroadcast (); + found = true; + } + else if (dest.IsMulticast ()) + { + NS_LOG_LOGIC ("IsMulticast"); + NS_ASSERT_MSG(m_device->IsMulticast (), + "ArpIpv4Interface::SendTo (): Sending multicast packet over " + "non-multicast device"); + + hardwareDestination = m_device->GetMulticast(dest); + found = true; + } + else + { + for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i) + { + if (dest.IsSubnetDirectedBroadcast ((*i).GetMask ())) + { + NS_LOG_LOGIC ("Subnetwork Broadcast"); + hardwareDestination = m_device->GetBroadcast (); + found = true; + break; + } + } + if (!found) + { + NS_LOG_LOGIC ("ARP Lookup"); + found = arp->Lookup (p, dest, m_device, m_cache, &hardwareDestination); + } + } + + if (found) + { + NS_LOG_LOGIC ("Address Resolved. Send."); + m_device ->Send (p, hardwareDestination, + Ipv4L3Protocol::PROT_NUMBER); + } + } + else + { + NS_LOG_LOGIC ("Doesn't need ARP"); + m_device->Send (p, m_device->GetBroadcast (), + Ipv4L3Protocol::PROT_NUMBER); + } } uint32_t diff --git a/src/internet-stack/ipv4-interface.h b/src/internet-stack/ipv4-interface.h index f41ff7583..3e5c5334f 100644 --- a/src/internet-stack/ipv4-interface.h +++ b/src/internet-stack/ipv4-interface.h @@ -32,6 +32,8 @@ namespace ns3 { class NetDevice; class Packet; +class Node; +class ArpCache; /** * \brief The IPv4 representation of a network interface @@ -40,26 +42,9 @@ class Packet; * of Linux; the main purpose is to provide address-family * specific information (addresses) about an interface. * - * This class defines two APIs: - * - the public API which is expected to be used by both - * the IPv4 layer and the user during forwarding and - * configuration. - * - the private API which is expected to be implemented - * by subclasses of this base class. One such subclass - * will be a Loopback interface which loops every - * packet sent back to the ipv4 layer. Another such - * subclass typically contains the Ipv4 <-> MAC address - * translation logic which will use most of the time the - * ARP/RARP protocols. - * * By default, Ipv4 interface are created in the "down" state - * with ip address 192.168.0.1 and a matching mask. Before - * becoming useable, the user must invoke SetUp on them - * once the final Ipv4 address and mask has been set. - * - * Subclasses must implement the two methods: - * - Ipv4Interface::SendTo - * - Ipv4Interface::GetDevice + * no IP addresses. Before becoming useable, the user must + * add an address of some type and invoke Setup on them. */ class Ipv4Interface : public Object { @@ -69,18 +54,29 @@ public: Ipv4Interface (); virtual ~Ipv4Interface(); + void SetNode (Ptr node); + void SetDevice (Ptr device); + /** - * \returns the underlying NetDevice. This method can return - * zero if this interface has no associated NetDevice. + * \returns the underlying NetDevice. This method cannot return zero. */ - virtual Ptr GetDevice (void) const = 0; + Ptr GetDevice (void) const; /** * \param metric configured routing metric (cost) of this interface + * + * Note: This is synonymous to the Metric value that ifconfig prints + * out. It is used by ns-3 global routing, but other routing daemons + * choose to ignore it. */ void SetMetric (uint16_t metric); + /** * \returns configured routing metric (cost) of this interface + * + * Note: This is synonymous to the Metric value that ifconfig prints + * out. It is used by ns-3 global routing, but other routing daemons + * may choose to ignore it. */ uint16_t GetMetric (void) const; @@ -88,6 +84,8 @@ public: * This function a pass-through to NetDevice GetMtu, modulo * the LLC/SNAP header i.e., ipv4MTU = NetDeviceMtu - LLCSNAPSIZE * \returns the Maximum Transmission Unit associated to this interface. + * + * XXX deprecated? This is duplicate API to GetDevice ()->GetMtu () */ uint16_t GetMtu (void) const; @@ -100,14 +98,17 @@ public: * \returns true if this interface is enabled, false otherwise. */ bool IsUp (void) const; + /** * \returns true if this interface is disabled, false otherwise. */ bool IsDown (void) const; + /** * Enable this interface */ void SetUp (void); + /** * Disable this interface */ @@ -147,16 +148,19 @@ public: protected: virtual void DoDispose (void); private: - virtual void SendTo (Ptr p, Ipv4Address dest) = 0; - bool m_ifup; - uint16_t m_metric; - + void DoSetup (void); typedef std::list Ipv4InterfaceAddressList; typedef std::list::const_iterator Ipv4InterfaceAddressListCI; typedef std::list::iterator Ipv4InterfaceAddressListI; + + bool m_ifup; + uint16_t m_metric; Ipv4InterfaceAddressList m_ifaddrs; + Ptr m_node; + Ptr m_device; + Ptr m_cache; }; -}; // namespace ns3 +} // namespace ns3 #endif diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 37562a71e..3caa7d2a6 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,75 +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->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 (); - } - } - - - // 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); - - if (destination.IsBroadcast ()) - { - ipHeader.SetTtl (1); - } - else if (found) - { - ipHeader.SetTtl (tag.GetTtl ()); + ttl = 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 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 ()) + + // 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) + + // 1) packet is destined to limited broadcast address + 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 @@ 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 (); @@ -885,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) @@ -905,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); } @@ -922,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); @@ -955,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); @@ -963,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); @@ -987,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 { @@ -1088,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); } } } @@ -1105,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; } @@ -1118,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/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index 943e816b9..a0d750224 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -29,7 +29,8 @@ #include "ns3/ipv4.h" #include "ns3/traced-callback.h" #include "ns3/ipv4-header.h" -#include "ipv4-static-routing.h" +#include "ns3/ipv4-routing-protocol.h" +#include "ipv4-static-routing-impl.h" namespace ns3 { @@ -38,6 +39,7 @@ class NetDevice; class Ipv4Interface; class Ipv4Address; class Ipv4Header; +class Ipv4RoutingTableEntry; class Ipv4Route; class Node; class Socket; @@ -64,6 +66,10 @@ public: void SetNode (Ptr node); + // functions defined in base class Ipv4 + void SetRoutingProtocol (Ptr routing); + Ptr GetRoutingProtocol (void) const; + Ptr CreateRawSocket (void); void DeleteRawSocket (Ptr socket); @@ -104,15 +110,6 @@ public: */ void SetDefaultTtl (uint8_t ttl); - /** - * \param device the device to match - * \returns the matching interface, zero if not found. - * - * Try to find an Ipv4Interface whose NetDevice is equal to - * the input NetDevice. - */ - Ptr FindInterfaceForDevice (Ptr device); - /** * Lower layer calls this method after calling L3Demux::Lookup * The ARP subclass needs to know from which NetDevice this @@ -128,64 +125,21 @@ public: * \param source source address of packet * \param destination address of packet * \param protocol number of packet + * \param route route entry * * Higher-level layers call this method to send a packet * down the stack to the MAC and PHY layers. */ void Send (Ptr packet, Ipv4Address source, - Ipv4Address destination, uint8_t protocol); - - - - void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); - void AddHostRouteTo (Ipv4Address dest, - uint32_t interface); - - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); - void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - - void Lookup (Ipv4Header const &ipHeader, - Ptr packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply); - - uint32_t GetNRoutes (void); - Ipv4Route GetRoute (uint32_t i); - void RemoveRoute (uint32_t i); - - void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces); - - void SetDefaultMulticastRoute (uint32_t onputInterface); - - uint32_t GetNMulticastRoutes (void) const; - Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; - - void RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface); - void RemoveMulticastRoute (uint32_t i); + Ipv4Address destination, uint8_t protocol, Ptr route); uint32_t AddInterface (Ptr device); Ptr GetInterface (uint32_t i) const; uint32_t GetNInterfaces (void) const; - uint32_t FindInterfaceForAddr (Ipv4Address addr) const; - uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const; - int32_t FindInterfaceForDevice (Ptr device) const; - - void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); - void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + int32_t GetInterfaceForAddress (Ipv4Address addr) const; + int32_t GetInterfaceForPrefix (Ipv4Address addr, Ipv4Mask mask) const; + int32_t GetInterfaceForDevice (Ptr device) const; uint32_t AddAddress (uint32_t i, Ipv4InterfaceAddress address); Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; @@ -193,9 +147,6 @@ public: void SetMetric (uint32_t i, uint16_t metric); uint16_t GetMetric (uint32_t i) const; - Ipv4Address GetSourceAddress (Ipv4Address destination) const; - bool GetInterfaceForDestination (Ipv4Address destination, - uint32_t& interface) const; uint16_t GetMtu (uint32_t i) const; bool IsUp (uint32_t i) const; void SetUp (uint32_t i); @@ -209,39 +160,52 @@ public: 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: Ipv4L3Protocol(const Ipv4L3Protocol &); Ipv4L3Protocol &operator = (const Ipv4L3Protocol &); - void Lookup (uint32_t interface, - Ipv4Header const &ipHeader, - Ptr packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply); - void SendRealOut (bool found, - Ipv4Route const &route, - Ptr packet, - Ipv4Header const &ipHeader); - bool Forwarding (uint32_t interface, - Ptr packet, - Ipv4Header &ipHeader, - Ptr device); - void ForwardUp (Ptr p, Ipv4Header const&ip, Ptr incomingInterface); + virtual void SetIpForward (bool forward); + virtual bool GetIpForward (void) const; + + Ipv4Header BuildHeader ( + Ipv4Address source, + Ipv4Address destination, + uint8_t protocol, + uint16_t payloadSize, + uint8_t ttl, + bool mayFragment); + + void + SendRealOut (Ptr route, + Ptr packet, + Ipv4Header const &ipHeader); + + void + IpForward (Ptr rtentry, + Ptr p, + const Ipv4Header &header); + + void + IpMulticastForward (Ptr mrtentry, + Ptr p, + const Ipv4Header &header); + + void LocalDeliver (Ptr p, Ipv4Header const&ip, uint32_t iif); uint32_t AddIpv4Interface (Ptr interface); void SetupLoopback (void); Ptr GetIcmp (void) const; bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const; - void DoForward (uint32_t interface, - Ptr packet, - Ipv4Header ipHeader); - typedef std::list > Ipv4InterfaceList; - typedef std::list > Ipv4MulticastGroupList; - typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; typedef std::list > SocketList; typedef std::list > L4List_t; + bool m_ipForward; L4List_t m_protocols; Ipv4InterfaceList m_interfaces; uint32_t m_nInterfaces; @@ -253,10 +217,8 @@ private: TracedCallback, uint32_t> m_rxTrace; TracedCallback > m_dropTrace; - Ipv4RoutingProtocolList m_routingProtocols; - - Ptr m_staticRouting; - Ipv4MulticastGroupList m_multicastGroups; + Ptr m_routingProtocol; + Ptr GetStaticRouting (void) const; SocketList m_sockets; }; diff --git a/src/internet-stack/ipv4-list-routing-impl.cc b/src/internet-stack/ipv4-list-routing-impl.cc new file mode 100644 index 000000000..539f4e976 --- /dev/null +++ b/src/internet-stack/ipv4-list-routing-impl.cc @@ -0,0 +1,270 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + * + */ + +#include "ns3/log.h" +#include "ns3/ipv4.h" +#include "ns3/ipv4-route.h" +#include "ns3/node.h" +#include "ns3/ipv4-static-routing.h" +#include "ipv4-list-routing-impl.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4ListRoutingImpl"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRoutingImpl); + +TypeId +Ipv4ListRoutingImpl::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4ListRoutingImpl") + .SetParent () + ; + return tid; +} + + +Ipv4ListRoutingImpl::Ipv4ListRoutingImpl () + : m_node (0) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +Ipv4ListRoutingImpl::~Ipv4ListRoutingImpl () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +Ipv4ListRoutingImpl::DoDispose (void) +{ + NS_LOG_FUNCTION_NOARGS (); + for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); rprotoIter++) + { + // Note: Calling dispose on these protocols causes memory leak + // The routing protocols should not maintain a pointer to + // this object, so Dispose() shouldn't be necessary. + (*rprotoIter).second = 0; + } + m_routingProtocols.clear (); + m_node = 0; +} + +Ptr +Ipv4ListRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif); + Ptr route; + + for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin (); + i != m_routingProtocols.end (); + i++) + { + NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first); + NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ()); + route = (*i).second->RouteOutput (header, oif, sockerr); + if (route) + { + NS_LOG_LOGIC ("Found route " << route); + sockerr = Socket::ERROR_NOTERROR; + return route; + } + } + NS_LOG_LOGIC ("Done checking " << GetTypeId ()); + NS_LOG_LOGIC (""); + sockerr = Socket::ERROR_NOROUTETOHOST; + return 0; +} + +// Patterned after Linux ip_route_input and ip_route_input_slow +bool +Ipv4ListRoutingImpl::RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) +{ + bool retVal = false; + NS_LOG_FUNCTION (p << header << idev); + NS_LOG_LOGIC ("RouteInput logic for node: " << m_node->GetId ()); + + Ptr ipv4 = m_node->GetObject (); + NS_ASSERT (ipv4); + uint32_t iif = ipv4->GetInterfaceForDevice (idev); + + // Multicast recognition; handle local delivery here + // + if (header.GetDestination().IsMulticast ()) + { +#ifdef NOTYET + if (ipv4->MulticastCheckGroup (iif, header.GetDestination ())) +#endif + if (true) + { + NS_LOG_LOGIC ("Multicast packet for me-- local deliver"); + Ptr packetCopy = p->Copy(); + // Here may want to disable lcb callback in recursive RouteInput + // call below + lcb (packetCopy, header, iif); + // Fall through-- we may also need to forward this + retVal = true; + } + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = + m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); + rprotoIter++) + { + NS_LOG_LOGIC ("Multicast packet for me-- trying to forward"); + if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb)) + { + retVal = true; + } + } + return retVal; + } + + if (header.GetDestination ().IsBroadcast ()) + { + NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)"); + // TODO: Local Deliver for broadcast + // TODO: Forward broadcast + } + + // TODO: Configurable option to enable RFC 1222 Strong End System Model + // Right now, we will be permissive and allow a source to send us + // a packet to one of our other interface addresses; that is, the + // destination unicast address does not match one of the iif addresses, + // but we check our other interfaces. This could be an option + // (to remove the outer loop immediately below and just check iif). + for (uint32_t j = 0; j < ipv4->GetNInterfaces (); j++) + { + for (uint32_t i = 0; i < ipv4->GetNAddresses (j); i++) + { + Ipv4InterfaceAddress iaddr = ipv4->GetAddress (j, i); + Ipv4Address addr = iaddr.GetLocal (); + if (addr.IsEqual (header.GetDestination ())) + { + if (j == iif) + { + NS_LOG_LOGIC ("For me (destination " << addr << " match)"); + } + else + { + NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ()); + } + lcb (p, header, iif); + return true; + } + if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ())) + { + NS_LOG_LOGIC ("For me (interface broadcast address)"); + lcb (p, header, iif); + return true; + } + NS_LOG_LOGIC ("Address "<< addr << " not a match"); + } + } + // Next, try to find a route + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = + m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); + rprotoIter++) + { + if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb)) + { + return true; + } + } + // No routing protocol has found a route. + return retVal; +} + +void +Ipv4ListRoutingImpl::AddRoutingProtocol (Ptr routingProtocol, int16_t priority) +{ + NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority); + m_routingProtocols.push_back + (std::pair > (-priority, routingProtocol)); + m_routingProtocols.sort (); +} + +uint32_t +Ipv4ListRoutingImpl::GetNRoutingProtocols (void) const +{ + NS_LOG_FUNCTION (this); + return m_routingProtocols.size (); +} + +Ptr +Ipv4ListRoutingImpl::GetRoutingProtocol (uint32_t index, int16_t& priority) const +{ + NS_LOG_FUNCTION (index); + if (index > m_routingProtocols.size ()) + { + NS_FATAL_ERROR ("Ipv4ListRoutingImpl::GetRoutingProtocol(): index " << index << " out of range"); + } + uint32_t i = 0; + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); rprotoIter++, i++) + { + if (i == index) + { + priority = (*rprotoIter).first; + return (*rprotoIter).second; + } + } + return 0; +} + +Ptr +Ipv4ListRoutingImpl::GetStaticRouting (void) const +{ + NS_LOG_FUNCTION (this); + Ipv4StaticRouting* srp; + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); rprotoIter++) + { + NS_LOG_LOGIC ("Searching for static routing"); + srp = dynamic_cast (PeekPointer((*rprotoIter).second)); + if (srp) + { + NS_LOG_LOGIC ("Found static routing"); + return Ptr (srp); + } + } + NS_LOG_LOGIC ("Static routing not found"); + return 0; + +} + +void +Ipv4ListRoutingImpl::SetNode (Ptr node) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = node; +} + +Ptr +Ipv4ListRoutingImpl::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + + +}//namespace ns3 diff --git a/src/internet-stack/ipv4-list-routing-impl.h b/src/internet-stack/ipv4-list-routing-impl.h new file mode 100644 index 000000000..b323ccae8 --- /dev/null +++ b/src/internet-stack/ipv4-list-routing-impl.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + * + */ + +#ifndef IPV4_LIST_ROUTING_IMPL_H +#define IPV4_LIST_ROUTING_IMPL_H + +#include +#include "ns3/ipv4-list-routing.h" + +namespace ns3 { + +class Ipv4StaticRouting; + +class Ipv4ListRoutingImpl : public Ipv4ListRouting +{ +public: + static TypeId GetTypeId (void); + + Ipv4ListRoutingImpl (); + ~Ipv4ListRoutingImpl (); + + virtual Ptr RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb); + + virtual void AddRoutingProtocol (Ptr routingProtocol, int16_t priority); + + virtual uint32_t GetNRoutingProtocols (void) const; + + virtual Ptr GetRoutingProtocol (uint32_t index, int16_t& priority) const; + virtual Ptr GetStaticRouting (void) const; + + + void SetNode (Ptr node); + Ptr GetNode (void) const; + +protected: + void DoDispose (void); +private: + typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; + Ipv4RoutingProtocolList m_routingProtocols; + Ptr m_node; + +}; + +} // Namespace ns3 + +#endif /* IPV4_LIST_ROUTING_IMPL_H */ diff --git a/src/internet-stack/ipv4-loopback-interface.cc b/src/internet-stack/ipv4-loopback-interface.cc deleted file mode 100644 index a87495009..000000000 --- a/src/internet-stack/ipv4-loopback-interface.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * 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 - * - * Authors: - * Mathieu Lacage , - */ - -#include "ns3/log.h" -#include "ns3/net-device.h" -#include "ns3/node.h" -#include "ns3/mac48-address.h" -#include "ns3/packet.h" -#include "ipv4-loopback-interface.h" -#include "ipv4-l3-protocol.h" - -NS_LOG_COMPONENT_DEFINE ("Ipv4LoopbackInterface"); - -namespace ns3 { - -TypeId -Ipv4LoopbackInterface::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::Ipv4LoopbackInterface") - .SetParent () - ; - return tid; -} - -Ipv4LoopbackInterface::Ipv4LoopbackInterface () - : m_node (0) -{ - NS_LOG_FUNCTION (this); -} - -Ipv4LoopbackInterface::~Ipv4LoopbackInterface () -{ - NS_LOG_FUNCTION (this); - NS_ASSERT (m_node != 0); -} - -Ptr -Ipv4LoopbackInterface::GetDevice (void) const -{ - return 0; -} - -void -Ipv4LoopbackInterface::SetNode (Ptr node) -{ - m_node = node; -} - -void -Ipv4LoopbackInterface::SendTo (Ptr packet, Ipv4Address dest) -{ - NS_LOG_FUNCTION (this << packet << dest); - - Ptr ipv4 = - m_node->GetObject (); - - ipv4->Receive (0, packet, Ipv4L3Protocol::PROT_NUMBER, - Mac48Address ("ff:ff:ff:ff:ff:ff"), - Mac48Address ("ff:ff:ff:ff:ff:ff"), - NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here - ); -} - -}//namespace ns3 diff --git a/src/internet-stack/ipv4-loopback-interface.h b/src/internet-stack/ipv4-loopback-interface.h deleted file mode 100644 index 23255386a..000000000 --- a/src/internet-stack/ipv4-loopback-interface.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2007 INRIA - * - * 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 - * - * Authors: - * Mathieu Lacage , - */ -#ifndef IPV4_LOOPBACK_INTERFACE_H -#define IPV4_LOOPBACK_INTERFACE_H - -#include "ipv4-interface.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class Node; -/** - * \brief An IPv4 loopback interface - */ -class Ipv4LoopbackInterface : public Ipv4Interface -{ -public: - static TypeId GetTypeId (void); - Ipv4LoopbackInterface (); - virtual ~Ipv4LoopbackInterface (); - - virtual Ptr GetDevice (void) const; - - void SetNode (Ptr node); - - private: - virtual void SendTo (Ptr p, Ipv4Address dest); - - Ptr m_node; -}; - -}//namespace ns3 - - -#endif /* IPV4_LOOPBACK_INTERFACE_H */ diff --git a/src/internet-stack/ipv4-raw-socket-impl.cc b/src/internet-stack/ipv4-raw-socket-impl.cc index bb1014eed..8ee040ad2 100644 --- a/src/internet-stack/ipv4-raw-socket-impl.cc +++ b/src/internet-stack/ipv4-raw-socket-impl.cc @@ -170,14 +170,24 @@ Ipv4RawSocketImpl::SendTo (Ptr p, uint32_t flags, InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress); Ptr ipv4 = m_node->GetObject (); Ipv4Address dst = ad.GetIpv4 (); - uint32_t localInterface; - if (ipv4->GetInterfaceForDestination(dst, localInterface)) + if (ipv4->GetRoutingProtocol ()) { - ipv4->Send (p, ipv4->GetSourceAddress (dst), dst, m_protocol); - } - else - { - NS_LOG_DEBUG ("dropped because no outgoing route."); + Ipv4Header header; + header.SetDestination (dst); + SocketErrno errno = ERROR_NOTERROR;; + 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"); + ipv4->Send (p, route->GetSource (), dst, m_protocol, route); + } + else + { + NS_LOG_DEBUG ("dropped because no outgoing route."); + } } return 0; } diff --git a/src/internet-stack/ipv4-raw-socket-impl.h b/src/internet-stack/ipv4-raw-socket-impl.h index 8e9e86af8..7d3784604 100644 --- a/src/internet-stack/ipv4-raw-socket-impl.h +++ b/src/internet-stack/ipv4-raw-socket-impl.h @@ -3,6 +3,7 @@ #include "ns3/socket.h" #include "ns3/ipv4-header.h" +#include "ns3/ipv4-route.h" #include namespace ns3 { diff --git a/src/internet-stack/ipv4-static-routing-impl.cc b/src/internet-stack/ipv4-static-routing-impl.cc new file mode 100644 index 000000000..ef15f5337f --- /dev/null +++ b/src/internet-stack/ipv4-static-routing-impl.cc @@ -0,0 +1,570 @@ +// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2006 Georgia Tech Research Corporation +// +// 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: George F. Riley +// Gustavo Carneiro + +#include "ns3/log.h" +#include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/ipv4-route.h" +#include "ipv4-static-routing-impl.h" +#include "ns3/ipv4-routing-table-entry.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRoutingImpl"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4StaticRoutingImpl); + +TypeId +Ipv4StaticRoutingImpl::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4StaticRoutingImpl") + .SetParent () + ; + return tid; +} + +Ipv4StaticRoutingImpl::Ipv4StaticRoutingImpl () +: m_defaultRoute (0), m_node (0) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +Ipv4StaticRoutingImpl::AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, nextHop, interface); + m_hostRoutes.push_back (route); +} + +void +Ipv4StaticRoutingImpl::AddHostRouteTo (Ipv4Address dest, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, interface); + m_hostRoutes.push_back (route); +} + +void +Ipv4StaticRoutingImpl::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, + networkMask, + nextHop, + interface); + m_networkRoutes.push_back (route); +} + +void +Ipv4StaticRoutingImpl::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, + networkMask, + interface); + m_networkRoutes.push_back (route); +} + +void +Ipv4StaticRoutingImpl::SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + *route = Ipv4RoutingTableEntry::CreateDefaultRoute (nextHop, interface); + delete m_defaultRoute; + m_defaultRoute = route; +} + +void +Ipv4StaticRoutingImpl::AddMulticastRoute(Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4MulticastRoutingTableEntry *route = new Ipv4MulticastRoutingTableEntry (); + *route = Ipv4MulticastRoutingTableEntry::CreateMulticastRoute (origin, group, + inputInterface, outputInterfaces); + m_multicastRoutes.push_back (route); +} + +// default multicast routes are stored as a network route +// these routes are _not_ consulted in the forwarding process-- only +// for originating packets +void +Ipv4StaticRoutingImpl::SetDefaultMulticastRoute(uint32_t outputInterface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry (); + Ipv4Address network = Ipv4Address ("224.0.0.0"); + Ipv4Mask networkMask = Ipv4Mask ("240.0.0.0"); + *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, + networkMask, + outputInterface); + m_networkRoutes.push_back (route); +} + +uint32_t +Ipv4StaticRoutingImpl::GetNMulticastRoutes (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_multicastRoutes.size (); +} + +Ipv4MulticastRoutingTableEntry +Ipv4StaticRoutingImpl::GetMulticastRoute (uint32_t index) const +{ + NS_LOG_FUNCTION_NOARGS (); + NS_ASSERT_MSG(index < m_multicastRoutes.size (), + "Ipv4StaticRoutingImpl::GetMulticastRoute (): Index out of range"); + + if (index < m_multicastRoutes.size ()) + { + uint32_t tmp = 0; + for (MulticastRoutesCI i = m_multicastRoutes.begin (); + i != m_multicastRoutes.end (); + i++) + { + if (tmp == index) + { + return *i; + } + tmp++; + } + } + return 0; +} + +bool +Ipv4StaticRoutingImpl::RemoveMulticastRoute(Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface) +{ + NS_LOG_FUNCTION_NOARGS (); + for (MulticastRoutesI i = m_multicastRoutes.begin (); + i != m_multicastRoutes.end (); + i++) + { + Ipv4MulticastRoutingTableEntry *route = *i; + if (origin == route->GetOrigin () && + group == route->GetGroup () && + inputInterface == route->GetInputInterface ()) + { + delete *i; + m_multicastRoutes.erase (i); + return true; + } + } + return false; +} + +void +Ipv4StaticRoutingImpl::RemoveMulticastRoute(uint32_t index) +{ + NS_LOG_FUNCTION_NOARGS (); + uint32_t tmp = 0; + for (MulticastRoutesI i = m_multicastRoutes.begin (); + i != m_multicastRoutes.end (); + i++) + { + if (tmp == index) + { + delete *i; + m_multicastRoutes.erase (i); + return; + } + tmp++; + } +} + +Ptr +Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr rtentry = 0; + for (HostRoutesCI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + NS_ASSERT ((*i)->IsHost ()); + if ((*i)->GetDest ().IsEqual (dest)) + { + NS_LOG_LOGIC ("Found global host route" << *i); + Ptr ipv4 = m_node->GetObject (); + Ipv4RoutingTableEntry* route = (*i); + rtentry = Create (); + rtentry->SetDestination (route->GetDest ()); + // XXX handle multi-address case + rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ()); + rtentry->SetGateway (route->GetGateway ()); + uint32_t interfaceIdx = route->GetInterface (); + rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx)); + return rtentry; + } + } + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + NS_ASSERT ((*j)->IsNetwork ()); + Ipv4Mask mask = (*j)->GetDestNetworkMask (); + Ipv4Address entry = (*j)->GetDestNetwork (); + if (mask.IsMatch (dest, entry)) + { + NS_LOG_LOGIC ("Found global network route" << *j); + Ptr ipv4 = m_node->GetObject (); + Ipv4RoutingTableEntry* route = (*j); + rtentry = Create (); + rtentry->SetDestination (route->GetDest ()); + // XXX handle multi-address case + rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ()); + rtentry->SetGateway (route->GetGateway ()); + uint32_t interfaceIdx = route->GetInterface (); + rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx)); + return rtentry; + } + } + if (m_defaultRoute != 0) + { + NS_ASSERT (m_defaultRoute->IsDefault ()); + NS_LOG_LOGIC ("Found global network route" << m_defaultRoute); + Ptr ipv4 = m_node->GetObject (); + Ipv4RoutingTableEntry* route = m_defaultRoute; + rtentry = Create (); + rtentry->SetDestination (route->GetDest ()); + // XXX handle multi-address case + rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ()); + rtentry->SetGateway (route->GetGateway ()); + uint32_t interfaceIdx = route->GetInterface (); + rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx)); + return rtentry; + } + return 0; +} + +Ptr +Ipv4StaticRoutingImpl::LookupStatic ( + Ipv4Address origin, + Ipv4Address group, + uint32_t interface) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr mrtentry = 0; + + for (MulticastRoutesI i = m_multicastRoutes.begin (); + i != m_multicastRoutes.end (); + i++) + { + Ipv4MulticastRoutingTableEntry *route = *i; +// +// We've been passed an origin address, a multicast group address and an +// interface index. We have to decide if the current route in the list is +// a match. +// +// The first case is the restrictive case where the origin, group and index +// matches. +// + if (origin == route->GetOrigin () && group == route->GetGroup ()) + { + // Skipping this case (SSM) for now + NS_LOG_LOGIC ("Found multicast source specific route" << *i); + } + if (group == route->GetGroup ()) + { + if (interface == Ipv4::IF_ANY || + interface == route->GetInputInterface ()) + { + NS_LOG_LOGIC ("Found multicast route" << *i); + Ptr ipv4 = m_node->GetObject (); + mrtentry = Create (); + mrtentry->SetGroup (route->GetGroup ()); + mrtentry->SetOrigin (route->GetOrigin ()); + mrtentry->SetParent (route->GetInputInterface ()); + for (uint32_t j = 0; j < route->GetNOutputInterfaces (); j++) + { + if (route->GetOutputInterface (j)) + { + NS_LOG_LOGIC ("Setting output interface index " << route->GetOutputInterface (j)); + mrtentry->SetOutputTtl (route->GetOutputInterface (j), Ipv4MulticastRoute::MAX_TTL - 1); + } + } + return mrtentry; + } + } + } + return mrtentry; +} + +uint32_t +Ipv4StaticRoutingImpl::GetNRoutes (void) +{ + NS_LOG_FUNCTION_NOARGS (); + uint32_t n = 0; + if (m_defaultRoute != 0) + { + n++; + } + n += m_hostRoutes.size (); + n += m_networkRoutes.size (); + return n; +} + +Ipv4RoutingTableEntry +Ipv4StaticRoutingImpl::GetDefaultRoute () +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_defaultRoute != 0) + { + return *m_defaultRoute; + } + else + { + return Ipv4RoutingTableEntry (); + } +} + +Ipv4RoutingTableEntry +Ipv4StaticRoutingImpl::GetRoute (uint32_t index) +{ + NS_LOG_FUNCTION_NOARGS (); + if (index == 0 && m_defaultRoute != 0) + { + return *m_defaultRoute; + } + if (index > 0 && m_defaultRoute != 0) + { + index--; + } + if (index < m_hostRoutes.size ()) + { + uint32_t tmp = 0; + for (HostRoutesCI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + if (tmp == index) + { + return *i; + } + tmp++; + } + } + index -= m_hostRoutes.size (); + uint32_t tmp = 0; + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + if (tmp == index) + { + return *j; + } + tmp++; + } + NS_ASSERT (false); + // quiet compiler. + return 0; +} +void +Ipv4StaticRoutingImpl::RemoveRoute (uint32_t index) +{ + NS_LOG_FUNCTION_NOARGS (); + if (index == 0 && m_defaultRoute != 0) + { + delete m_defaultRoute; + m_defaultRoute = 0; + } + if (index > 0 && m_defaultRoute != 0) + { + index--; + } + if (index < m_hostRoutes.size ()) + { + uint32_t tmp = 0; + for (HostRoutesI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i++) + { + if (tmp == index) + { + delete *i; + m_hostRoutes.erase (i); + return; + } + tmp++; + } + } + index -= m_hostRoutes.size (); + uint32_t tmp = 0; + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j++) + { + if (tmp == index) + { + delete *j; + m_networkRoutes.erase (j); + return; + } + tmp++; + } + NS_ASSERT (false); +} + +Ptr +Ipv4StaticRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header << oif); + Ipv4Address destination = header.GetDestination (); + Ptr rtentry = 0; + + // Multicast goes here + if (destination.IsMulticast ()) + { + // Note: Multicast routes for outbound packets are stored in the + // normal unicast table. An implication of this is that it is not + // possible to source multicast datagrams on multiple interfaces. + // This is a well-known property of sockets implementation on + // many Unix variants. + // So, we just log it and fall through to LookupStatic () + NS_LOG_LOGIC ("RouteOutput()::Multicast destination"); + } + rtentry = LookupStatic (destination); + if (rtentry) + { + sockerr = Socket::ERROR_NOTERROR; + } + else + { + sockerr = Socket::ERROR_NOROUTETOHOST; + } + return rtentry; +} + +// XXX this method not robust enough to work independent of ListRouting +bool +Ipv4StaticRoutingImpl::RouteInput (Ptr p, const Ipv4Header &ipHeader, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this << p << ipHeader << ipHeader.GetSource () << ipHeader.GetDestination () << idev); + Ptr ipv4 = m_node->GetObject (); + + if (ipHeader.GetDestination ().IsMulticast ()) + { + NS_LOG_LOGIC ("Multicast destination"); + Ptr mrtentry = LookupStatic(ipHeader.GetSource (), + ipHeader.GetDestination (), ipv4->GetInterfaceForDevice (idev)); + + if (mrtentry) + { + NS_LOG_LOGIC ("Multicast route found"); + mcb (mrtentry, p, ipHeader); // multicast forwarding callback + return true; + } + else + { + NS_LOG_LOGIC ("Multicast route not found"); + return false; // Let other routing protocols try to handle this + } + } +// +// This is a unicast packet. Check to see if we have a route for it. +// + NS_LOG_LOGIC ("Unicast destination"); + Ptr rtentry = LookupStatic (ipHeader.GetDestination ()); + if (rtentry != 0) + { + NS_LOG_LOGIC ("Found unicast destination- calling unicast callback"); + ucb (rtentry, p, ipHeader); // unicast forwarding callback + return true; + } + else + { + NS_LOG_LOGIC ("Did not find unicast destination- returning false"); + return false; // Let other routing protocols try to handle this + } +} + +Ipv4StaticRoutingImpl::~Ipv4StaticRoutingImpl () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +Ipv4StaticRoutingImpl::DoDispose (void) +{ + NS_LOG_FUNCTION_NOARGS (); + for (HostRoutesI i = m_hostRoutes.begin (); + i != m_hostRoutes.end (); + i = m_hostRoutes.erase (i)) + { + delete (*i); + } + for (NetworkRoutesI j = m_networkRoutes.begin (); + j != m_networkRoutes.end (); + j = m_networkRoutes.erase (j)) + { + delete (*j); + } + if (m_defaultRoute != 0) + { + delete m_defaultRoute; + m_defaultRoute = 0; + } + for (MulticastRoutesI i = m_multicastRoutes.begin (); + i != m_multicastRoutes.end (); + i = m_multicastRoutes.erase (i)) + { + delete (*i); + } + Ipv4RoutingProtocol::DoDispose (); +} + +void +Ipv4StaticRoutingImpl::SetNode (Ptr node) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = node; +} + +Ptr +Ipv4StaticRoutingImpl::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + + +}//namespace ns3 diff --git a/src/internet-stack/ipv4-static-routing-impl.h b/src/internet-stack/ipv4-static-routing-impl.h new file mode 100644 index 000000000..1bfca98ef --- /dev/null +++ b/src/internet-stack/ipv4-static-routing-impl.h @@ -0,0 +1,367 @@ +// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2006 Georgia Tech Research Corporation +// +// 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: George F. Riley +// Gustavo Carneiro +// + +#ifndef IPV4_STATIC_ROUTING_IMPL_H +#define IPV4_STATIC_ROUTING_IMPL_H + +#include +#include +#include "ns3/ipv4-address.h" +#include "ns3/ipv4-header.h" +#include "ns3/socket.h" +#include "ns3/ptr.h" +#include "ns3/ipv4.h" +#include "ns3/ipv4-static-routing.h" + +namespace ns3 { + +class Packet; +class NetDevice; +class Ipv4Interface; +class Ipv4Address; +class Ipv4Header; +class Ipv4RoutingTableEntry; +class Ipv4MulticastRoutingTableEntry; +class Node; + +class Ipv4StaticRoutingImpl : public Ipv4StaticRouting +{ +public: + static TypeId GetTypeId (void); + + Ipv4StaticRoutingImpl (); + virtual ~Ipv4StaticRoutingImpl (); + + virtual Ptr RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + + virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb); + +/** + * \brief Add a host route to the static routing table. + * + * \param dest The Ipv4Address destination for this route. + * \param nextHop The Ipv4Address of the next hop in the route. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + void AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface); +/** + * \brief Add a host route to the static routing table. + * + * \param dest The Ipv4Address destination for this route. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + void AddHostRouteTo (Ipv4Address dest, + uint32_t interface); + +/** + * \brief Add a network route to the static routing table. + * + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param nextHop The next hop in the route to the destination network. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface); + +/** + * \brief Add a network route to the static routing table. + * + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface); + +/** + * \brief Add a default route to the static routing table. + * + * This method tells the routing system what to do in the case where a specific + * route to a destination is not found. The system forwards packets to the + * specified node in the hope that it knows better how to route the packet. + * + * If the default route is set, it is returned as the selected route from + * LookupStatic irrespective of destination address if no specific route is + * found. + * + * \param nextHop The Ipv4Address to send packets to in the hope that they + * will be forwarded correctly. + * \param interface The network interface index used to send packets. + * + * \see Ipv4Address + * \see Ipv4StaticRouting::Lookup + */ + void SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface); + +/** + * \brief Get the number of individual unicast routes that have been added + * to the routing table. + * + * \warning The default route counts as one of the routes. + */ + uint32_t GetNRoutes (void); + +/** + * \brief Get the default route from the static routing table. + * + * \return If the default route is set, a pointer to that Ipv4RoutingTableEntry is + * returned, otherwise a zero pointer is returned. + * + * \see Ipv4RoutingTableEntry + */ + Ipv4RoutingTableEntry GetDefaultRoute (void); + +/** + * \brief Get a route from the static unicast routing table. + * + * Externally, the unicast static routing table appears simply as a table with + * n entries. The one sublety of note is that if a default route has been set + * it will appear as the zeroth entry in the table. This means that if you + * add only a default route, the table will have one entry that can be accessed + * either by explicity calling GetDefaultRoute () or by calling GetRoute (0). + * + * Similarly, if the default route has been set, calling RemoveRoute (0) will + * remove the default route. + * + * \param i The index (into the routing table) of the route to retrieve. If + * the default route has been set, it will occupy index zero. + * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise + * a zero pointer is returned. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::RemoveRoute + */ + Ipv4RoutingTableEntry GetRoute (uint32_t i); + +/** + * \brief Remove a route from the static unicast routing table. + * + * Externally, the unicast static routing table appears simply as a table with + * n entries. The one sublety of note is that if a default route has been set + * it will appear as the zeroth entry in the table. This means that if the + * default route has been set, calling RemoveRoute (0) will remove the + * default route. + * + * \param i The index (into the routing table) of the route to remove. If + * the default route has been set, it will occupy index zero. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::GetRoute + * \see Ipv4StaticRouting::AddRoute + */ + void RemoveRoute (uint32_t i); + +/** + * \brief Add a multicast route to the static routing table. + * + * A multicast route must specify an origin IP address, a multicast group and + * an input network interface index as conditions and provide a vector of + * output network interface indices over which packets matching the conditions + * are sent. + * + * Typically there are two main types of multicast routes: routes of the + * first kind are used during forwarding. All of the conditions must be + * exlicitly provided. The second kind of routes are used to get packets off + * of a local node. The difference is in the input interface. Routes for + * forwarding will always have an explicit input interface specified. Routes + * off of a node will always set the input interface to a wildcard specified + * by the index Ipv4RoutingProtocol::INTERFACE_ANY. + * + * For routes off of a local node wildcards may be used in the origin and + * multicast group addresses. The wildcard used for Ipv4Adresses is that + * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage + * of a wildcard allows one to specify default behavior to varying degrees. + * + * For example, making the origin address a wildcard, but leaving the + * multicast group specific allows one (in the case of a node with multiple + * interfaces) to create different routes using different output interfaces + * for each multicast group. + * + * If the origin and multicast addresses are made wildcards, you have created + * essentially a default multicast address that can forward to multiple + * interfaces. Compare this to the actual default multicast address that is + * limited to specifying a single output interface for compatibility with + * existing functionality in other systems. + * + * \param origin The Ipv4Address of the origin of packets for this route. May + * be Ipv4Address:GetAny for open groups. + * \param group The Ipv4Address of the multicast group or this route. + * \param inputInterface The input network interface index over which to + * expect packets destined for this route. May be + * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin. + * \param outputInterfaces A vector of network interface indices used to specify + * how to send packets to the destination(s). + * + * \see Ipv4Address + */ + void AddMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces); + +/** + * \brief Add a default multicast route to the static routing table. + * + * This is the multicast equivalent of the unicast version SetDefaultRoute. + * We tell the routing system what to do in the case where a specific route + * to a destination multicast group is not found. The system forwards + * packets out the specified interface in the hope that "something out there" + * knows better how to route the packet. This method is only used in + * initially sending packets off of a host. The default multicast route is + * not consulted during forwarding -- exact routes must be specified using + * AddMulticastRoute for that case. + * + * Since we're basically sending packets to some entity we think may know + * better what to do, we don't pay attention to "subtleties" like origin + * address, nor do we worry about forwarding out multiple interfaces. If the + * default multicast route is set, it is returned as the selected route from + * LookupStatic irrespective of origin or multicast group if another specific + * route is not found. + * + * \param outputInterface The network interface index used to specify where + * to send packets in the case of unknown routes. + * + * \see Ipv4Address + */ + void SetDefaultMulticastRoute (uint32_t outputInterface); + +/** + * \brief Get the number of individual multicast routes that have been added + * to the routing table. + * + * \warning The default multicast route counts as one of the routes. + */ + uint32_t GetNMulticastRoutes (void) const; + +/** + * \brief Get a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * + * \param i The index (into the routing table) of the multicast route to + * retrieve. + * \return If route \e i is set, a pointer to that Ipv4MulticastRoutingTableEntry is + * returned, otherwise a zero pointer is returned. + * + * \see Ipv4MulticastRoutingTableEntry + * \see Ipv4StaticRouting::RemoveRoute + */ + Ipv4MulticastRoutingTableEntry GetMulticastRoute (uint32_t i) const; + +/** + * \brief Remove a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * This method causes the multicast routing table to be searched for the first + * route that matches the parameters and removes it. + * + * Wildcards may be provided to this function, but the wildcards are used to + * exacly match wildcards in the routes (see AddMulticastRoute). That is, + * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not + * remove routes with any address in the origin, but will only remove routes + * with "0.0.0.0" set as the the origin. + * + * \param origin The IP address specified as the origin of packets for the + * route. + * \param group The IP address specified as the multicast group addres of + * the route. + * \param inputInterface The network interface index specified as the expected + * input interface for the route. + * \returns true if a route was found and removed, false otherwise. + * + * \see Ipv4MulticastRoutingTableEntry + * \see Ipv4StaticRouting::AddMulticastRoute + */ + bool RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface); + +/** + * \brief Remove a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * + * \param index The index (into the multicast routing table) of the route to + * remove. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::GetRoute + * \see Ipv4StaticRouting::AddRoute + */ + void RemoveMulticastRoute (uint32_t index); + + void SetNode (Ptr node); + Ptr GetNode (void) const; + +protected: + void DoDispose (void); + +private: + typedef std::list HostRoutes; + typedef std::list::const_iterator HostRoutesCI; + typedef std::list::iterator HostRoutesI; + typedef std::list NetworkRoutes; + typedef std::list::const_iterator NetworkRoutesCI; + typedef std::list::iterator NetworkRoutesI; + + typedef std::list MulticastRoutes; + typedef std::list::const_iterator MulticastRoutesCI; + typedef std::list::iterator MulticastRoutesI; + + Ptr LookupStatic (Ipv4Address dest); + Ptr LookupStatic (Ipv4Address origin, Ipv4Address group, + uint32_t interface); + + HostRoutes m_hostRoutes; + NetworkRoutes m_networkRoutes; + Ipv4RoutingTableEntry *m_defaultRoute; + MulticastRoutes m_multicastRoutes; + + Ptr m_node; +}; + +} // Namespace ns3 + +#endif /* IPV4_STATIC_ROUTING_IMPL_H */ diff --git a/src/internet-stack/ipv4-static-routing.cc b/src/internet-stack/ipv4-static-routing.cc deleted file mode 100644 index 744c3bc99..000000000 --- a/src/internet-stack/ipv4-static-routing.cc +++ /dev/null @@ -1,654 +0,0 @@ -// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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: George F. Riley -// Gustavo Carneiro - -#include "ns3/log.h" -#include "ipv4-static-routing.h" -#include "ns3/packet.h" - -NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRouting"); - -namespace ns3 { - -Ipv4StaticRouting::Ipv4StaticRouting () -: m_defaultRoute (0), m_defaultMulticastRoute (0) -{ - NS_LOG_FUNCTION_NOARGS (); -} - -void -Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface); - m_hostRoutes.push_back (route); -} - -void -Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateHostRouteTo (dest, interface); - m_hostRoutes.push_back (route); -} - -void -Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, - networkMask, - nextHop, - interface); - m_networkRoutes.push_back (route); -} - -void -Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateNetworkRouteTo (network, - networkMask, - interface); - m_networkRoutes.push_back (route); -} - -void -Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Route *route = new Ipv4Route (); - *route = Ipv4Route::CreateDefaultRoute (nextHop, interface); - delete m_defaultRoute; - m_defaultRoute = route; -} - -void -Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); - *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, - inputInterface, outputInterfaces); - m_multicastRoutes.push_back (route); -} - -void -Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface) -{ - NS_LOG_FUNCTION_NOARGS (); - Ipv4Address origin = Ipv4Address::GetAny (); - Ipv4Address group = Ipv4Address::GetAny (); - uint32_t inputInterface = Ipv4RoutingProtocol::INTERFACE_ANY; - - std::vector outputInterfaces (1); - outputInterfaces[0] = outputInterface; - - Ipv4MulticastRoute *route = new Ipv4MulticastRoute (); - *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, - inputInterface, outputInterfaces); - - delete m_defaultMulticastRoute; - m_defaultMulticastRoute = route; -} - -uint32_t -Ipv4StaticRouting::GetNMulticastRoutes (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0; -} - -Ipv4MulticastRoute * -Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const -{ - NS_LOG_FUNCTION_NOARGS (); - NS_ASSERT_MSG(index < m_multicastRoutes.size (), - "Ipv4StaticRouting::GetMulticastRoute (): Index out of range"); -// -// From an external point of view the default route appears to be in slot 0 -// of the routing table. The implementation, however, puts it in a separate -// place. So, if a client asks for index 0 and we have a default multicast -// route, we have to return it from that different place -// (m_defaultMulticastRoute). -// - if (index == 0 && m_defaultMulticastRoute != 0) - { - return m_defaultMulticastRoute; - } -// -// If there is a default multicast route present, a client will just assume -// that it is in slot zero and there is one "extra" zeroth route in the table. -// To return the correct indexed entry in our list, we have to decrement the -// index to take into account the default route not being in the actual list. -// Since we fell through to here, we've taken care of the case where the -// index was zero. -// - if (m_defaultMulticastRoute != 0) - { - NS_ASSERT(index > 0); - index--; - } - - if (index < m_multicastRoutes.size ()) - { - uint32_t tmp = 0; - for (MulticastRoutesCI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - if (tmp == index) - { - return *i; - } - tmp++; - } - } - return 0; -} - -Ipv4MulticastRoute * -Ipv4StaticRouting::GetDefaultMulticastRoute () const -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_defaultMulticastRoute != 0) - { - return m_defaultMulticastRoute; - } - return 0; -} - -bool -Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface) -{ - NS_LOG_FUNCTION_NOARGS (); - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - Ipv4MulticastRoute *route = *i; - if (origin == route->GetOrigin () && - group == route->GetGroup () && - inputInterface == route->GetInputInterface ()) - { - delete *i; - m_multicastRoutes.erase (i); - return true; - } - } - return false; -} - -void -Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index) -{ - NS_LOG_FUNCTION_NOARGS (); -// -// From an external point of view the default route appears to be in slot 0 -// of the routing table. The implementation, however, puts it in a separate -// place. So, if a client asks to delete index 0 and we have a default -// multicast route set, we have to delete it from that different place -// (m_defaultMulticastRoute). -// - if (index == 0 && m_defaultMulticastRoute != 0) - { - delete m_defaultMulticastRoute; - m_defaultMulticastRoute = 0; - } -// -// If there is a default multicast route present, a client will just assume -// that it is in slot zero and there is one "extra" zeroth route in the table. -// To return the correct indexed entry in our list, we have to decrement the -// index to take into account the default route not being in the actual list. -// Since we fell through to here, we've taken care of the case where the -// index was zero. -// - if (m_defaultMulticastRoute != 0) - { - NS_ASSERT(index > 0); - index--; - } - - uint32_t tmp = 0; - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - if (tmp == index) - { - delete *i; - m_multicastRoutes.erase (i); - return; - } - tmp++; - } -} - -Ipv4Route * -Ipv4StaticRouting::LookupStatic (Ipv4Address dest) -{ - NS_LOG_FUNCTION_NOARGS (); - for (HostRoutesCI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) - { - NS_ASSERT ((*i)->IsHost ()); - if ((*i)->GetDest ().IsEqual (dest)) - { - return (*i); - } - } - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - NS_ASSERT ((*j)->IsNetwork ()); - Ipv4Mask mask = (*j)->GetDestNetworkMask (); - Ipv4Address entry = (*j)->GetDestNetwork (); - if (mask.IsMatch (dest, entry)) - { - return (*j); - } - } - if (m_defaultRoute != 0) - { - NS_ASSERT (m_defaultRoute->IsDefault ()); - return m_defaultRoute; - } - return 0; -} - -Ipv4MulticastRoute * -Ipv4StaticRouting::LookupStatic ( - Ipv4Address origin, - Ipv4Address group, - uint32_t interface) -{ - NS_LOG_FUNCTION_NOARGS (); -// -// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching -// scheme. -// - Ipv4Address wildcard = Ipv4Address::GetAny (); - - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - Ipv4MulticastRoute *route = *i; -// -// We've been passed an origin address, a multicast group address and an -// interface index. We have to decide if the current route in the list is -// a match. -// -// The first case is the restrictive case where the origin, group and index -// matches. This picks up exact routes during forwarded and exact routes from -// the local node (in which case the interface is a wildcard). -// - if (origin == route->GetOrigin () && group == route->GetGroup ()) - { - if (interface == Ipv4RoutingProtocol::INTERFACE_ANY || - interface == route->GetInputInterface ()) - { - return *i; - } - } - } -// -// If the input interface index is not a wildcard (that means that the packet -// did not originally come from this node), we're done. We don't -// just happily forward packets we don't really know what to do with. -// Multicast storms are not generally considered a good thing. -// - if (interface != Ipv4RoutingProtocol::INTERFACE_ANY) - { - return 0; - } -// -// Now, we're going to get a litle less restricive. This only applies in the -// case where the packet in question is coming from the local node. In order -// to avoid dependencies on the order in which routes were added, we will -// actually walk the list two more times, the first time looking for routes -// with a single wildcard, and the last time looking for the first route -// with two wildcards. -// - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - Ipv4MulticastRoute *route = *i; -// -// Here we will ignore the origin. We know that a single source address must -// be picked for a packet, but we may want to send multicast packets out -// multiple interfaces. To support this case, a user would need to add -// a Multicast route with the route's origin set to wildcard. N.B As a -// result, packets sourced from a node with multiple interface may have a -// source IP address different from that of the interface actually used to -// send the packet. -// - if (route->GetOrigin () == wildcard && group == route->GetGroup ()) - { - return *i; - } - } -// -// Finally we want to allow users to specify a default route that specifies -// sending all multicast packets out multiple interfaces. The standard -// default multicast route is patterned after other systems and limits the -// number of outputs to one. If, however a client manually adds a multicast -// route with the origin, the multicast group and the input interface index -// all set to wildcard, she has created a default route with multiple output -// interfaces. -// - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i++) - { - Ipv4MulticastRoute *route = *i; - - if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard) - { - return *i; - } - } -// -// We also allow users to specify a typical default multicast route. This -// default route is limited to specifying a single output interface. -// - if (m_defaultMulticastRoute != 0) - { - return m_defaultMulticastRoute; - } - - return 0; -} - -uint32_t -Ipv4StaticRouting::GetNRoutes (void) -{ - NS_LOG_FUNCTION_NOARGS (); - uint32_t n = 0; - if (m_defaultRoute != 0) - { - n++; - } - n += m_hostRoutes.size (); - n += m_networkRoutes.size (); - return n; -} - -Ipv4Route * -Ipv4StaticRouting::GetDefaultRoute () -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_defaultRoute != 0) - { - return m_defaultRoute; - } - else - { - return 0; - } -} - -Ipv4Route * -Ipv4StaticRouting::GetRoute (uint32_t index) -{ - NS_LOG_FUNCTION_NOARGS (); - if (index == 0 && m_defaultRoute != 0) - { - return m_defaultRoute; - } - if (index > 0 && m_defaultRoute != 0) - { - index--; - } - if (index < m_hostRoutes.size ()) - { - uint32_t tmp = 0; - for (HostRoutesCI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) - { - if (tmp == index) - { - return *i; - } - tmp++; - } - } - index -= m_hostRoutes.size (); - uint32_t tmp = 0; - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - if (tmp == index) - { - return *j; - } - tmp++; - } - NS_ASSERT (false); - // quiet compiler. - return 0; -} -void -Ipv4StaticRouting::RemoveRoute (uint32_t index) -{ - NS_LOG_FUNCTION_NOARGS (); - if (index == 0 && m_defaultRoute != 0) - { - delete m_defaultRoute; - m_defaultRoute = 0; - } - if (index > 0 && m_defaultRoute != 0) - { - index--; - } - if (index < m_hostRoutes.size ()) - { - uint32_t tmp = 0; - for (HostRoutesI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i++) - { - if (tmp == index) - { - delete *i; - m_hostRoutes.erase (i); - return; - } - tmp++; - } - } - index -= m_hostRoutes.size (); - uint32_t tmp = 0; - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j++) - { - if (tmp == index) - { - delete *j; - m_networkRoutes.erase (j); - return; - } - tmp++; - } - NS_ASSERT (false); -} - -bool -Ipv4StaticRouting::RequestRoute ( - uint32_t interface, - Ipv4Header const &ipHeader, - Ptr packet, - RouteReplyCallback routeReply) -{ - NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply); - - NS_LOG_LOGIC ("source = " << ipHeader.GetSource ()); - - NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ()); - - if (ipHeader.GetDestination ().IsMulticast ()) - { - NS_LOG_LOGIC ("Multicast destination"); - - Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (), - ipHeader.GetDestination (), interface); - - if (mRoute) - { - NS_LOG_LOGIC ("Multicast route found"); - - for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i) - { - Ptr p = packet->Copy (); - Ipv4Header h = ipHeader; - Ipv4Route route = - Ipv4Route::CreateHostRouteTo(h.GetDestination (), - mRoute->GetOutputInterface(i)); - NS_LOG_LOGIC ( "Send via interface " << - mRoute->GetOutputInterface(i)); - routeReply (true, route, p, h); - } - return true; - } - return false; // Let other routing protocols try to handle this - } -// -// This is a unicast packet. Check to see if we have a route for it. -// - NS_LOG_LOGIC ("Unicast destination"); - Ipv4Route *route = LookupStatic (ipHeader.GetDestination ()); - if (route != 0) - { - routeReply (true, *route, packet, ipHeader); - return true; - } - else - { - return false; // Let other routing protocols try to handle this - // route request. - } -} - -bool -Ipv4StaticRouting::RequestInterface (Ipv4Address destination, uint32_t& interface) -{ - NS_LOG_FUNCTION (this << destination << &interface); -// -// First, see if this is a multicast packet we have a route for. If we -// have a route, then send the packet down each of the specified interfaces. -// - if (destination.IsMulticast ()) - { - NS_LOG_LOGIC ("Multicast destination"); - - Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (), - destination, Ipv4RoutingProtocol::INTERFACE_ANY); - - if (mRoute) - { - NS_LOG_LOGIC ("Multicast route found"); - - if (mRoute->GetNOutputInterfaces () != 1) - { - NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring."); - return false; - } - - interface = mRoute->GetOutputInterface(0); - NS_LOG_LOGIC ("Found interface " << interface); - return true; - } - return false; // Let other routing protocols try to handle this - } -// -// See if this is a unicast packet we have a route for. -// - NS_LOG_LOGIC ("Unicast destination"); - Ipv4Route *route = LookupStatic (destination); - if (route) - { - interface = route->GetInterface (); - return true; - } - else - { - return false; - } -} - -void -Ipv4StaticRouting::DoDispose (void) -{ - NS_LOG_FUNCTION_NOARGS (); - for (HostRoutesI i = m_hostRoutes.begin (); - i != m_hostRoutes.end (); - i = m_hostRoutes.erase (i)) - { - delete (*i); - } - for (NetworkRoutesI j = m_networkRoutes.begin (); - j != m_networkRoutes.end (); - j = m_networkRoutes.erase (j)) - { - delete (*j); - } - if (m_defaultRoute != 0) - { - delete m_defaultRoute; - m_defaultRoute = 0; - } - for (MulticastRoutesI i = m_multicastRoutes.begin (); - i != m_multicastRoutes.end (); - i = m_multicastRoutes.erase (i)) - { - delete (*i); - } - if (m_defaultMulticastRoute != 0) - { - delete m_defaultMulticastRoute; - m_defaultMulticastRoute = 0; - } - Ipv4RoutingProtocol::DoDispose (); -} - -}//namespace ns3 diff --git a/src/internet-stack/ipv4-static-routing.h b/src/internet-stack/ipv4-static-routing.h deleted file mode 100644 index 128fc7d2d..000000000 --- a/src/internet-stack/ipv4-static-routing.h +++ /dev/null @@ -1,506 +0,0 @@ -// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- -// -// Copyright (c) 2006 Georgia Tech Research Corporation -// -// 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: George F. Riley -// Gustavo Carneiro -// - -#ifndef IPV4_STATIC_ROUTING_H -#define IPV4_STATIC_ROUTING_H - -#include -#include -#include "ns3/ipv4-address.h" -#include "ns3/ipv4-header.h" -#include "ns3/ptr.h" -#include "ns3/ipv4.h" - -namespace ns3 { - -class Packet; -class NetDevice; -class Ipv4Interface; -class Ipv4Address; -class Ipv4Header; -class Ipv4Route; -class Node; - - -/** - * @brief Static routing protocol for IP version 4 stacks. - * - * In ns-3 we have the concept of a pluggable routing protocol. Routing - * protocols are added to a list maintained by the Ipv4L3Protocol. Every - * stack gets one routing protocol for free -- the Ipv4StaticRouting routing - * protocol is added in the constructor of the Ipv4L3Protocol (this is the - * piece of code that implements the functionality of the IP layer). - * - * The Ipv4StaticRouting class inherits from the abstract base class - * Ipv4RoutingProtocol that defines the interface methods that a routing - * protocol must support. - * - * When a packet arrives in the Ipv4L3Protocol for transmission, it comes - * either from a local source via Ipv4L3Protocol::Send or from a remote - * source via Ipv4L3Protocol::Forwarding. In both cases, a function is called - * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet. - * - * The lookup function iterates through the list of routing protocols asking - * each to see if it can find a route and send the packet. A callback is - * provided during each of these calls that should be considered a pre- - * packaged send call. This is done to allow asynchronous calls into - * routing subsystems in order to support on-demand routing, for example. The - * method for requesting this operation is Ipv4StaticRouting::RequestRoute for - * the static routing protocol. - * - * Each routing protocol is also free to implement its own methods for managing - * routes which you will find below. This class manages a set of "static" or - * manually configured routes for host, network and multicast routes. - * - * @see Ipv4RoutingProtocol - * @see Ipv4L3Protocol::AddRoutingProtocol - * @see Ipv4L3Protocol::Ipv4L3Protocol - */ -class Ipv4StaticRouting : public Ipv4RoutingProtocol -{ -public: -/** - * @brief Construct an empty Ipv4StaticRouting routing protocol, - * @internal - * - * The Ipv4StaticRouting class supports host, network and multicast routes. - * This method initializes the lists containing these routes to empty. - * - * @see Ipv4StaticRouting - */ - Ipv4StaticRouting (); - -/** - * @brief Request that a check for a route bw performed and if a route is found - * that the packet be sent on its way using the pre-packaged send callback. - * - * The source and destination IP addresses for the packet in question are found - * in the provided Ipv4Header. There are two major processing forks depending - * on the type of destination address. - * - * If the destination address is unicast then the routing table is consulted - * for a route to the destination and if it is found, the routeReply callback - * is executed to send the packet (with the found route). - * - * If the destination address is a multicast, then the exact processing steps - * depend on whether or not the packet has been sourced locally. This is - * determined by the parameter interface. This is the interface index over which - * this packet was received. If the packet has not been received over a - * network interface, this index will be set to - * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY (a very large number). In that case, - * we want to avoid the requirement that an explicit route out of each node - * must be set, so we don't do anything here. - * - * If the packet is a multicast destination and has been received over a - * network interface, a call to this method implies that the packet is being - * forwarded. In that case, there must be an explicit route out of the node. - * A multicast route references the source address, the destination address - * (the multicast group) and the input interface in order to find a route. - * We consult the multicast routing table and, if a route is found, send the - * packet out of as many interfaces as required using the provided callback - * (think of it as a pre-packaged send call). - * - * @param interface The network interface index over which the packed was - * received. If the packet is from a local source, interface will be set to - * Ipv4RoutingProtocol::INTERFACE_ANY. - * @param ipHeader the Ipv4Header containing the source and destination IP - * addresses for the packet. - * @param packet The packet to be sent if a route is found. - * @param routeReply A callback that packaged up the call to actually send the - * packet. - * @return Returns true if a route is found and the packet has been sent, - * otherwise returns false indicating that the next routing protocol should - * be consulted. In practice, the static routing protocol is the last chance - * protocol. - * - * @see Ipv4StaticRouting - * @see Ipv4RoutingProtocol - */ - virtual bool RequestRoute (uint32_t interface, - Ipv4Header const &ipHeader, - Ptr packet, - RouteReplyCallback routeReply); - -/** - * @brief Check to see if we can determine the interface index that will be - * used if a packet is sent to this destination. - * - * This method addresses a problem in the IP stack where a destination address - * must be present and checksummed into the IP header before the actual - * interface over which the packet is sent can be determined. The answer is - * to implement a known and intentional cross-layer violation. This is the - * endpoint of a call chain that started up quite high in the stack (sockets) - * and has found its way down to the Ipv4L3Protocol which is consulting the - * routing protocols for what they would do if presented with a packet of the - * given destination. - * - * Note that the a single interface index is returned. This means that if - * the destination address is a multicast, and an explicit route is present - * that includeds multiple output interfaces, that route cannot be used. - * - * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more - * contextual information that is useful for making a determination. - * - * @param destination The Ipv4Address if the destination of a hypothetical - * packet. This may be a multicast group address. - * @param interface A reference to the interface index over which a packet - * sent to this destination would be sent. - * @return Returns true if a route is found to the destination that involves - * a single output interface index, otherwise returns false indicating that - * the next routing protocol should be consulted. In practice, the static - * routing protocol is the last chance protocol. - * - * @see Ipv4StaticRouting - * @see Ipv4RoutingProtocol - * @see Ipv4L3Protocol - */ - virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface); - -/** - * @brief Add a host route to the static routing table. - * - * @param dest The Ipv4Address destination for this route. - * @param nextHop The Ipv4Address of the next hop in the route. - * @param interface The network interface index used to send packets to the - * destination. - * - * @see Ipv4Address - */ - void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); -/** - * @brief Add a host route to the static routing table. - * - * @param dest The Ipv4Address destination for this route. - * @param interface The network interface index used to send packets to the - * destination. - * - * @see Ipv4Address - */ - void AddHostRouteTo (Ipv4Address dest, - uint32_t interface); - -/** - * @brief Add a network route to the static routing table. - * - * @param network The Ipv4Address network for this route. - * @param networkMask The Ipv4Mask to extract the network. - * @param nextHop The next hop in the route to the destination network. - * @param interface The network interface index used to send packets to the - * destination. - * - * @see Ipv4Address - */ - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); - -/** - * @brief Add a network route to the static routing table. - * - * @param network The Ipv4Address network for this route. - * @param networkMask The Ipv4Mask to extract the network. - * @param interface The network interface index used to send packets to the - * destination. - * - * @see Ipv4Address - */ - void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); - -/** - * @brief Add a default route to the static routing table. - * - * This method tells the routing system what to do in the case where a specific - * route to a destination is not found. The system forwards packets to the - * specified node in the hope that it knows better how to route the packet. - * - * If the default route is set, it is returned as the selected route from - * LookupStatic irrespective of destination address if no specific route is - * found. - * - * @param nextHop The Ipv4Address to send packets to in the hope that they - * will be forwarded correctly. - * @param interface The network interface index used to send packets. - * - * @see Ipv4Address - * @see Ipv4StaticRouting::Lookup - */ - void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - -/** - * @brief Get the number of individual unicast routes that have been added - * to the routing table. - * - * @warning The default route counts as one of the routes. - */ - uint32_t GetNRoutes (void); - -/** - * @brief Get the default route from the static routing table. - * - * @return If the default route is set, a pointer to that Ipv4Route is - * returned, otherwise a zero pointer is returned. - * - * @see Ipv4Route - */ - Ipv4Route *GetDefaultRoute (void); - -/** - * @brief Get a route from the static unicast routing table. - * - * Externally, the unicast static routing table appears simply as a table with - * n entries. The one sublety of note is that if a default route has been set - * it will appear as the zeroth entry in the table. This means that if you - * add only a default route, the table will have one entry that can be accessed - * either by explicity calling GetDefaultRoute () or by calling GetRoute (0). - * - * Similarly, if the default route has been set, calling RemoveRoute (0) will - * remove the default route. - * - * @param i The index (into the routing table) of the route to retrieve. If - * the default route has been set, it will occupy index zero. - * @return If route is set, a pointer to that Ipv4Route is returned, otherwise - * a zero pointer is returned. - * - * @see Ipv4Route - * @see Ipv4StaticRouting::RemoveRoute - */ - Ipv4Route *GetRoute (uint32_t i); - -/** - * @brief Remove a route from the static unicast routing table. - * - * Externally, the unicast static routing table appears simply as a table with - * n entries. The one sublety of note is that if a default route has been set - * it will appear as the zeroth entry in the table. This means that if the - * default route has been set, calling RemoveRoute (0) will remove the - * default route. - * - * @param i The index (into the routing table) of the route to remove. If - * the default route has been set, it will occupy index zero. - * - * @see Ipv4Route - * @see Ipv4StaticRouting::GetRoute - * @see Ipv4StaticRouting::AddRoute - */ - void RemoveRoute (uint32_t i); - -/** - * @brief Add a multicast route to the static routing table. - * - * A multicast route must specify an origin IP address, a multicast group and - * an input network interface index as conditions and provide a vector of - * output network interface indices over which packets matching the conditions - * are sent. - * - * Typically there are two main types of multicast routes: routes of the - * first kind are used during forwarding. All of the conditions must be - * exlicitly provided. The second kind of routes are used to get packets off - * of a local node. The difference is in the input interface. Routes for - * forwarding will always have an explicit input interface specified. Routes - * off of a node will always set the input interface to a wildcard specified - * by the index Ipv4RoutingProtocol::INTERFACE_ANY. - * - * For routes off of a local node wildcards may be used in the origin and - * multicast group addresses. The wildcard used for Ipv4Adresses is that - * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage - * of a wildcard allows one to specify default behavior to varying degrees. - * - * For example, making the origin address a wildcard, but leaving the - * multicast group specific allows one (in the case of a node with multiple - * interfaces) to create different routes using different output interfaces - * for each multicast group. - * - * If the origin and multicast addresses are made wildcards, you have created - * essentially a default multicast address that can forward to multiple - * interfaces. Compare this to the actual default multicast address that is - * limited to specifying a single output interface for compatibility with - * existing functionality in other systems. - * - * @param origin The Ipv4Address of the origin of packets for this route. May - * be Ipv4Address:GetAny for open groups. - * @param group The Ipv4Address of the multicast group or this route. - * @param inputInterface The input network interface index over which to - * expect packets destined for this route. May be - * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin. - * @param outputInterfaces A vector of network interface indices used to specify - * how to send packets to the destination(s). - * - * @see Ipv4Address - */ - void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces); - -/** - * @brief Add a default multicast route to the static routing table. - * - * This is the multicast equivalent of the unicast version SetDefaultRoute. - * We tell the routing system what to do in the case where a specific route - * to a destination multicast group is not found. The system forwards - * packets out the specified interface in the hope that "something out there" - * knows better how to route the packet. This method is only used in - * initially sending packets off of a host. The default multicast route is - * not consulted during forwarding -- exact routes must be specified using - * AddMulticastRoute for that case. - * - * Since we're basically sending packets to some entity we think may know - * better what to do, we don't pay attention to "subtleties" like origin - * address, nor do we worry about forwarding out multiple interfaces. If the - * default multicast route is set, it is returned as the selected route from - * LookupStatic irrespective of origin or multicast group if another specific - * route is not found. - * - * @param outputInterface The network interface index used to specify where - * to send packets in the case of unknown routes. - * - * @see Ipv4Address - */ - void SetDefaultMulticastRoute (uint32_t outputInterface); - -/** - * @brief Get the number of individual multicast routes that have been added - * to the routing table. - * - * @warning The default multicast route counts as one of the routes. - */ - uint32_t GetNMulticastRoutes (void) const; - -/** - * @brief Get a route from the static multicast routing table. - * - * Externally, the multicast static routing table appears simply as a table - * with n entries. The one sublety of note is that if a default route has - * been set it will appear as the zeroth entry in the table. This means that - * if you add only a default route, the table will have one entry that can be - * accessed either by explicity calling GetDefaultMulticastRoute () or by - * calling GetMulticastRoute (0). - * - * Similarly, if the default route has been set, calling - * RemoveMulticastRoute (0) will remove the default route. - * - * @param i The index (into the routing table) of the multicast route to - * retrieve. If the default route has been set, it will occupy index zero. - * @return If route \e i is set, a pointer to that Ipv4MulticastRoute is - * returned, otherwise a zero pointer is returned. - * - * @see Ipv4MulticastRoute - * @see Ipv4StaticRouting::RemoveRoute - */ - Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const; - -/** - * @brief Get the default multicast route from the static routing table. - * - * @return If the default route is set, a pointer to that Ipv4MulticastRoute is - * returned, otherwise a zero pointer is returned. - * - * @see Ipv4Route - */ - Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const; - -/** - * @brief Remove a route from the static multicast routing table. - * - * Externally, the multicast static routing table appears simply as a table - * with n entries. The one sublety of note is that if a default multicast - * route has been set it will appear as the zeroth entry in the table. This - * means that the default route may be removed by calling this method with - * appropriate wildcard parameters. - * - * This method causes the multicast routing table to be searched for the first - * route that matches the parameters and removes it. - * - * Wildcards may be provided to this function, but the wildcards are used to - * exacly match wildcards in the routes (see AddMulticastRoute). That is, - * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not - * remove routes with any address in the origin, but will only remove routes - * with "0.0.0.0" set as the the origin. - * - * @param origin The IP address specified as the origin of packets for the - * route. - * @param group The IP address specified as the multicast group addres of - * the route. - * @param inputInterface The network interface index specified as the expected - * input interface for the route. - * @returns true if a route was found and removed, false otherwise. - * - * @see Ipv4MulticastRoute - * @see Ipv4StaticRouting::AddMulticastRoute - */ - bool RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface); - -/** - * @brief Remove a route from the static multicast routing table. - * - * Externally, the multicast static routing table appears simply as a table - * with n entries. The one sublety of note is that if a default multicast - * route has been set it will appear as the zeroth entry in the table. This - * means that if the default route has been set, calling - * RemoveMulticastRoute (0) will remove the default route. - * - * @param index The index (into the multicast routing table) of the route to - * remove. If the default route has been set, it will occupy index zero. - * - * @see Ipv4Route - * @see Ipv4StaticRouting::GetRoute - * @see Ipv4StaticRouting::AddRoute - */ - void RemoveMulticastRoute (uint32_t index); - -protected: - void DoDispose (void); - -private: - typedef std::list HostRoutes; - typedef std::list::const_iterator HostRoutesCI; - typedef std::list::iterator HostRoutesI; - typedef std::list NetworkRoutes; - typedef std::list::const_iterator NetworkRoutesCI; - typedef std::list::iterator NetworkRoutesI; - - typedef std::list MulticastRoutes; - typedef std::list::const_iterator MulticastRoutesCI; - typedef std::list::iterator MulticastRoutesI; - - Ipv4Route *LookupStatic (Ipv4Address dest); - Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group, - uint32_t interface); - - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; - Ipv4Route *m_defaultRoute; - Ipv4MulticastRoute *m_defaultMulticastRoute; - MulticastRoutes m_multicastRoutes; -}; - -} // Namespace ns3 - -#endif /* IPV4_STATIC_ROUTING_H */ diff --git a/src/internet-stack/loopback-net-device.cc b/src/internet-stack/loopback-net-device.cc new file mode 100644 index 000000000..8a06540a6 --- /dev/null +++ b/src/internet-stack/loopback-net-device.cc @@ -0,0 +1,234 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * 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: Mathieu Lacage + */ +#include "loopback-net-device.h" +#include "ns3/log.h" +#include "ns3/channel.h" +#include "ns3/node.h" +#include "ns3/packet.h" + +NS_LOG_COMPONENT_DEFINE ("LoopbackNetDevice"); + +namespace ns3 { + +TypeId +LoopbackNetDevice::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::LoopbackNetDevice") + .SetParent () + .AddConstructor () + ; + return tid; +} + +LoopbackNetDevice::LoopbackNetDevice () + : m_node (0), + m_mtu (0xffff), + m_ifIndex (0), + m_address (Mac48Address ("00:00:00:00:00:00")) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +LoopbackNetDevice::Receive (Ptr packet, uint16_t protocol, + Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (packet << " " << protocol << " " << to << " " << from); + NetDevice::PacketType packetType; + if (to == m_address) + { + packetType = NetDevice::PACKET_HOST; + } + else if (to.IsBroadcast ()) + { + packetType = NetDevice::PACKET_HOST; + } + else if (to.IsGroup ()) + { + packetType = NetDevice::PACKET_MULTICAST; + } + else + { + packetType = NetDevice::PACKET_OTHERHOST; + } + m_rxCallback (this, packet, protocol, from); + if (!m_promiscCallback.IsNull ()) + { + m_promiscCallback (this, packet, protocol, from, to, packetType); + } +} + +void +LoopbackNetDevice::SetIfIndex(const uint32_t index) +{ + m_ifIndex = index; +} + +uint32_t +LoopbackNetDevice::GetIfIndex(void) const +{ + return m_ifIndex; +} + +Ptr +LoopbackNetDevice::GetChannel (void) const +{ + return 0; +} + +Address +LoopbackNetDevice::GetAddress (void) const +{ + return m_address; +} + +bool +LoopbackNetDevice::SetMtu (const uint16_t mtu) +{ + m_mtu = mtu; + return true; +} + +uint16_t +LoopbackNetDevice::GetMtu (void) const +{ + return m_mtu; +} + +bool +LoopbackNetDevice::IsLinkUp (void) const +{ + return true; +} + +void +LoopbackNetDevice::SetLinkChangeCallback (Callback callback) +{} + +bool +LoopbackNetDevice::IsBroadcast (void) const +{ + return true; +} + +Address +LoopbackNetDevice::GetBroadcast (void) const +{ + // This is typically set to all zeros rather than all ones in real systems + return Mac48Address ("00:00:00:00:00:00"); +} + +bool +LoopbackNetDevice::IsMulticast (void) const +{ + // Multicast loopback will need to be supported for outgoing + // datagrams but this will probably be handled in multicast sockets + return false; +} + +Address +LoopbackNetDevice::GetMulticast (Ipv4Address multicastGroup) const +{ + return Mac48Address::GetMulticast (multicastGroup); +} + +Address LoopbackNetDevice::GetMulticast (Ipv6Address addr) const +{ + return Mac48Address::GetMulticast (addr); +} + +bool +LoopbackNetDevice::IsPointToPoint (void) const +{ + return false; +} + +bool +LoopbackNetDevice::IsBridge (void) const +{ + return false; +} + +bool +LoopbackNetDevice::Send (Ptr packet, const Address& dest, uint16_t protocolNumber) +{ + NS_LOG_FUNCTION (packet << " " << dest << " " << protocolNumber); + Mac48Address to = Mac48Address::ConvertFrom (dest); + NS_ASSERT_MSG (to == GetBroadcast () || to == m_address, "Invalid destination address"); + Receive (packet, protocolNumber, to, m_address); + return true; +} + +bool +LoopbackNetDevice::SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber) +{ + NS_LOG_FUNCTION (packet << " " << source << " " << dest << " " << protocolNumber); + Mac48Address to = Mac48Address::ConvertFrom (dest); + Mac48Address from = Mac48Address::ConvertFrom (source); + NS_ASSERT_MSG (to.IsBroadcast () || to == m_address, "Invalid destination address"); + Receive (packet, protocolNumber, to, from); + return true; +} + +Ptr +LoopbackNetDevice::GetNode (void) const +{ + return m_node; +} + +void +LoopbackNetDevice::SetNode (Ptr node) +{ + m_node = node; +} + +bool +LoopbackNetDevice::NeedsArp (void) const +{ + return false; +} + +void +LoopbackNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb) +{ + m_rxCallback = cb; +} + +void +LoopbackNetDevice::DoDispose (void) +{ + m_node = 0; + NetDevice::DoDispose (); +} + + +void +LoopbackNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb) +{ + m_promiscCallback = cb; +} + +bool +LoopbackNetDevice::SupportsSendFrom (void) const +{ + return true; +} + +} // namespace ns3 diff --git a/src/internet-stack/loopback-net-device.h b/src/internet-stack/loopback-net-device.h new file mode 100644 index 000000000..de1af2874 --- /dev/null +++ b/src/internet-stack/loopback-net-device.h @@ -0,0 +1,85 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2008 INRIA + * + * 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: Mathieu Lacage + */ +#ifndef LOOPBACK_NET_DEVICE_H +#define LOOPBACK_NET_DEVICE_H + +#include "ns3/net-device.h" +#include "ns3/mac48-address.h" +#include +#include + +namespace ns3 { + +class Node; + +/** + * \ingroup netdevice + * + * \brief Virtual network interface that loops back any data sent to it to + * be immediately received on the same interface + */ +class LoopbackNetDevice : public NetDevice +{ +public: + static TypeId GetTypeId (void); + LoopbackNetDevice (); + + // inherited from NetDevice base class. + virtual void SetIfIndex(const uint32_t index); + virtual uint32_t GetIfIndex(void) const; + virtual Ptr GetChannel (void) const; + virtual Address GetAddress (void) const; + virtual bool SetMtu (const uint16_t mtu); + virtual uint16_t GetMtu (void) const; + virtual bool IsLinkUp (void) const; + virtual void SetLinkChangeCallback (Callback callback); + virtual bool IsBroadcast (void) const; + virtual Address GetBroadcast (void) const; + virtual bool IsMulticast (void) const; + virtual Address GetMulticast (Ipv4Address multicastGroup) const; + virtual bool IsPointToPoint (void) const; + virtual bool IsBridge (void) const; + virtual bool Send(Ptr packet, const Address& dest, uint16_t protocolNumber); + virtual bool SendFrom(Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); + virtual Ptr GetNode (void) const; + virtual void SetNode (Ptr node); + virtual bool NeedsArp (void) const; + virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb); + + virtual Address GetMulticast (Ipv6Address addr) const; + + virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb); + virtual bool SupportsSendFrom (void) const; + +protected: + virtual void DoDispose (void); +private: + void Receive (Ptr packet, uint16_t protocol, Mac48Address to, Mac48Address from); + NetDevice::ReceiveCallback m_rxCallback; + NetDevice::PromiscReceiveCallback m_promiscCallback; + Ptr m_node; + uint16_t m_mtu; + uint32_t m_ifIndex; + Mac48Address m_address; +}; + +} // namespace ns3 + +#endif /* LOOPBACK_NET_DEVICE_H */ diff --git a/src/internet-stack/nsc-tcp-l4-protocol.cc b/src/internet-stack/nsc-tcp-l4-protocol.cc index b22e0670d..514d4c245 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.cc +++ b/src/internet-stack/nsc-tcp-l4-protocol.cc @@ -23,15 +23,17 @@ #include "ns3/packet.h" #include "ns3/node.h" +#include "ns3/ipv4-route.h" #include "ns3/object-vector.h" - +#include "ns3/string.h" #include "tcp-header.h" #include "ipv4-end-point-demux.h" #include "ipv4-end-point.h" #include "ipv4-l3-protocol.h" #include "nsc-tcp-l4-protocol.h" #include "nsc-sysctl.h" +#include "nsc-tcp-socket-factory-impl.h" #include "tcp-typedefs.h" @@ -65,7 +67,7 @@ NscTcpL4Protocol::GetTypeId (void) { static TypeId tid = TypeId ("ns3::NscTcpL4Protocol") .SetParent () - + .AddConstructor() .AddAttribute ("RttEstimatorFactory", "How RttEstimator objects are created.", ObjectFactoryValue (GetDefaultRttEstimatorFactory ()), @@ -75,6 +77,12 @@ NscTcpL4Protocol::GetTypeId (void) ObjectVectorValue (), MakeObjectVectorAccessor (&NscTcpL4Protocol::m_sockets), MakeObjectVectorChecker ()) + .AddAttribute ("Library", + "Set the linux library to be used to create the stack", + TypeId::ATTR_GET|TypeId::ATTR_CONSTRUCT, + StringValue("liblinux2.6.26.so"), + MakeStringAccessor (&NscTcpL4Protocol::GetNscLibrary,&NscTcpL4Protocol::SetNscLibrary), + MakeStringChecker ()) ; return tid; } @@ -101,13 +109,22 @@ NscTcpL4Protocol::~NscTcpL4Protocol () void NscTcpL4Protocol::SetNscLibrary(const std::string &soname) -{ - NS_ASSERT(!m_dlopenHandle); - m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW); - if (m_dlopenHandle == NULL) - NS_FATAL_ERROR (dlerror()); +{ + if (soname!="") + { + m_nscLibrary = soname; + NS_ASSERT(!m_dlopenHandle); + m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW); + if (m_dlopenHandle == NULL) + NS_FATAL_ERROR (dlerror()); + } } +std::string +NscTcpL4Protocol::GetNscLibrary () const +{ + return m_nscLibrary; +} void NscTcpL4Protocol::SetNode (Ptr node) { @@ -144,6 +161,23 @@ NscTcpL4Protocol::SetNode (Ptr node) Simulator::ScheduleNow (&NscTcpL4Protocol::AddInterface, this); } +void +NscTcpL4Protocol::NotifyNewAggregate () +{ + bool is_not_initialized = (m_node == 0); + Ptrnode = this->GetObject (); + Ptr ipv4 = this->GetObject (); + if (is_not_initialized && node!= 0 && ipv4 != 0) + { + this->SetNode (node); + ipv4->Insert (this); + Ptr tcpFactory = CreateObject (); + tcpFactory->SetTcp (this); + node->AggregateObject (tcpFactory); + } + Object::NotifyNewAggregate (); +} + int NscTcpL4Protocol::GetProtocolNumber (void) const { @@ -302,7 +336,7 @@ void NscTcpL4Protocol::send_callback(const void* data, int datalen) Ptr ipv4 = m_node->GetObject (); NS_ASSERT_MSG (ipv4, "nsc callback invoked, but node has no ipv4 object"); - ipv4->Send (p, saddr, daddr, PROT_NUMBER); + ipv4->Send (p, saddr, daddr, PROT_NUMBER, 0); m_nscStack->if_send_finish(0); } diff --git a/src/internet-stack/nsc-tcp-l4-protocol.h b/src/internet-stack/nsc-tcp-l4-protocol.h index 22e799463..c099dfc13 100644 --- a/src/internet-stack/nsc-tcp-l4-protocol.h +++ b/src/internet-stack/nsc-tcp-l4-protocol.h @@ -54,8 +54,8 @@ public: virtual ~NscTcpL4Protocol (); void SetNode (Ptr node); - void SetNscLibrary(const std::string &lib); - + void SetNscLibrary (const std::string &lib); + std::string GetNscLibrary (void) const; virtual int GetProtocolNumber (void) const; virtual int GetVersion (void) const; @@ -105,6 +105,7 @@ public: protected: virtual void DoDispose (void); + virtual void NotifyNewAggregate (); private: Ptr m_node; Ipv4EndPointDemux *m_endPoints; @@ -116,6 +117,7 @@ private: friend class NscTcpSocketImpl; INetStack* m_nscStack; void *m_dlopenHandle; + std::string m_nscLibrary; Timer m_softTimer; std::vector > m_sockets; }; diff --git a/src/internet-stack/tcp-l4-protocol.cc b/src/internet-stack/tcp-l4-protocol.cc index 2e046b7a3..92d0e2543 100644 --- a/src/internet-stack/tcp-l4-protocol.cc +++ b/src/internet-stack/tcp-l4-protocol.cc @@ -26,12 +26,14 @@ #include "ns3/packet.h" #include "ns3/node.h" +#include "ns3/ipv4-route.h" #include "tcp-l4-protocol.h" #include "tcp-header.h" #include "ipv4-end-point-demux.h" #include "ipv4-end-point.h" #include "ipv4-l3-protocol.h" +#include "tcp-socket-factory-impl.h" #include "tcp-typedefs.h" @@ -324,6 +326,7 @@ TcpL4Protocol::GetTypeId (void) { static TypeId tid = TypeId ("ns3::TcpL4Protocol") .SetParent () + .AddConstructor () .AddAttribute ("RttEstimatorFactory", "How RttEstimator objects are created.", ObjectFactoryValue (GetDefaultRttEstimatorFactory ()), @@ -360,6 +363,28 @@ TcpL4Protocol::SetNode (Ptr node) m_node = node; } +/* + * This method is called by AddAgregate and completes the aggregation + * by setting the node in the TCP stack, link it to the ipv4 stack and + * adding TCP socket factory to the node. + */ +void +TcpL4Protocol::NotifyNewAggregate () +{ + bool is_not_initialized = (m_node == 0); + Ptrnode = this->GetObject (); + Ptr ipv4 = this->GetObject (); + if (is_not_initialized && node!= 0 && ipv4 != 0) + { + this->SetNode (node); + ipv4->Insert (this); + Ptr tcpFactory = CreateObject (); + tcpFactory->SetTcp (this); + node->AggregateObject (tcpFactory); + } + Object::NotifyNewAggregate (); +} + int TcpL4Protocol::GetProtocolNumber (void) const { @@ -520,7 +545,15 @@ TcpL4Protocol::Send (Ptr packet, m_node->GetObject (); if (ipv4 != 0) { - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + // XXX We've already performed the route lookup in TcpSocketImpl + // should be cached. + Ipv4Header header; + header.SetDestination (daddr); + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route); } } @@ -550,7 +583,15 @@ TcpL4Protocol::SendPacket (Ptr packet, TcpHeader outgoingHeader, m_node->GetObject (); if (ipv4 != 0) { - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + // XXX We've already performed the route lookup in TcpSocketImpl + // should be cached. + Ipv4Header header; + header.SetDestination (daddr); + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route); } else NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface"); diff --git a/src/internet-stack/tcp-l4-protocol.h b/src/internet-stack/tcp-l4-protocol.h index 0d33031e5..f0e7e73b3 100644 --- a/src/internet-stack/tcp-l4-protocol.h +++ b/src/internet-stack/tcp-l4-protocol.h @@ -109,6 +109,11 @@ public: 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: Ptr m_node; Ipv4EndPointDemux *m_endPoints; diff --git a/src/internet-stack/tcp-socket-impl.cc b/src/internet-stack/tcp-socket-impl.cc index 27349cc18..ae9ec0f18 100644 --- a/src/internet-stack/tcp-socket-impl.cc +++ b/src/internet-stack/tcp-socket-impl.cc @@ -23,6 +23,8 @@ #include "ns3/inet-socket-address.h" #include "ns3/log.h" #include "ns3/ipv4.h" +#include "ns3/ipv4-interface-address.h" +#include "ns3/ipv4-route.h" #include "tcp-socket-impl.h" #include "tcp-l4-protocol.h" #include "ipv4-end-point.h" @@ -327,6 +329,9 @@ int TcpSocketImpl::Connect (const Address & address) { NS_LOG_FUNCTION (this << address); + + Ptr ipv4 = m_node->GetObject (); + if (m_endPoint == 0) { if (Bind () == -1) @@ -340,17 +345,31 @@ TcpSocketImpl::Connect (const Address & address) m_remoteAddress = transport.GetIpv4 (); m_remotePort = transport.GetPort (); - uint32_t localInterface; - Ptr ipv4 = m_node->GetObject (); - - if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) + if (ipv4->GetRoutingProtocol () != 0) { - m_endPoint->SetLocalAddress (ipv4->GetSourceAddress (m_remoteAddress)); + Ipv4Header header; + header.SetDestination (m_remoteAddress); + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + // XXX here, cache the route in the endpoint? + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + if (route != 0) + { + NS_LOG_LOGIC ("Route exists"); + m_endPoint->SetLocalAddress (route->GetSource ()); + } + else + { + NS_LOG_LOGIC ("TcpSocketImpl::Connect(): Route to " << m_remoteAddress << " does not exist"); + NS_LOG_ERROR (errno); + m_errno = errno; + return -1; + } } else { - m_errno = ERROR_NOROUTETOHOST; - return -1; + NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node"); } Actions_t action = ProcessEvent (APP_CONNECT); @@ -794,8 +813,8 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, const Address& fromAddress) { NS_LOG_FUNCTION (this << a << p << fromAddress); - uint32_t localInterface; Ptr ipv4 = m_node->GetObject (); + switch (a) { case ACK_TX: @@ -807,12 +826,6 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, break; case SYN_ACK_TX: NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX"); -// m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort (); -// m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (); -// if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) -// { -// m_localAddress = ipv4->GetAddress (localInterface); -// } if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl { NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this); @@ -827,20 +840,37 @@ bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, p, tcpHeader,fromAddress); return true; } - // This is the cloned endpoint - NS_ASSERT (m_state == SYN_RCVD); - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); - if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface)) - { - m_localAddress = ipv4->GetSourceAddress (m_remoteAddress); - m_endPoint->SetLocalAddress (m_localAddress); - // Leave local addr in the portmap to any, as the path from - // remote can change and packets can arrive on different interfaces - //m_endPoint->SetLocalAddress (Ipv4Address::GetAny()); - } - // TCP SYN consumes one byte - m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); - SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); + // This is the cloned endpoint + m_endPoint->SetPeer (m_remoteAddress, m_remotePort); + + // Look up the source address + if (ipv4->GetRoutingProtocol () != 0) + { + Ipv4Header header; + Socket::SocketErrno errno; + Ptr route; + uint32_t oif = 0; //specify non-zero if bound to a source address + header.SetDestination (m_remoteAddress); + route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); + if (route != 0) + { + NS_LOG_LOGIC ("Route exists"); + m_endPoint->SetLocalAddress (route->GetSource ()); + } + else + { + NS_LOG_ERROR (errno); + m_errno = errno; + return -1; + } + } + else + { + NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node"); + } + // TCP SYN consumes one byte + m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); + SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); break; case ACK_TX_1: NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1"); @@ -1683,309 +1713,4 @@ TcpSocketImpl::GetDelAckMaxCount (void) const }//namespace ns3 -#ifdef RUN_SELF_TESTS -#include "ns3/test.h" -#include "ns3/socket-factory.h" -#include "ns3/tcp-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 "ns3/config.h" -#include "internet-stack.h" -#include - -namespace ns3 { - -class TcpSocketImplTest: public Test -{ - public: - TcpSocketImplTest (); - virtual bool RunTests (void); - private: - //test 1, which sends string "Hello world" server->client - void Test1 (void); - void Test1_HandleConnectionCreated (Ptr, const Address &); - void Test1_HandleRecv (Ptr sock); - - //test 2, which sends a number of bytes server->client - void Test2 (uint32_t payloadSize); - void Test2_HandleConnectionCreated (Ptr, const Address &); - void Test2_HandleRecv (Ptr sock); - uint32_t test2_payloadSize; - - //test 3, which makes sure the rx buffer is finite - void Test3 (uint32_t payloadSize); - void Test3_HandleConnectionCreated (Ptr, const Address &); - void Test3_HandleRecv (Ptr sock); - uint32_t test3_payloadSize; - - //helpers to make topology construction easier - Ptr CreateInternetNode (); - Ptr AddSimpleNetDevice (Ptr,const char*,const char*); - void SetupDefaultSim (); - - //reset all of the below state for another run - void Reset (); - - //all of the state this class needs; basically both ends of the connection, - //and this test kind of acts as an single application running on both nodes - //simultaneously - Ptr node0; - Ptr node1; - Ptr dev0; - Ptr dev1; - Ptr channel; - Ptr listeningSock; - Ptr sock0; - Ptr sock1; - uint32_t rxBytes0; - uint32_t rxBytes1; - - uint8_t* rxPayload; - - bool result; -}; - -TcpSocketImplTest::TcpSocketImplTest () - : Test ("TcpSocketImpl"), - rxBytes0 (0), - rxBytes1 (0), - rxPayload (0), - result (true) -{ -} - -bool -TcpSocketImplTest::RunTests (void) -{ - Test1(); - if (!result) return false; - Test2(600); - if (!result) return false; - Test3(20000); - return result; -} - -//----------------------------------------------------------------------------- -//test 1----------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void -TcpSocketImplTest::Test1 () -{ - SetupDefaultSim (); - listeningSock->SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test1_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == 13); - result = result && (strcmp((const char*) rxPayload,"Hello World!") == 0); - - Reset (); -} - -void -TcpSocketImplTest::Test1_HandleConnectionCreated (Ptr s, const Address & addr) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - const uint8_t* hello = (uint8_t*)"Hello World!"; - Ptr p = Create (hello, 13); - sock0->Send(p); - - sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); -} - -void -TcpSocketImplTest::Test1_HandleRecv (Ptr sock) -{ - NS_ASSERT (sock == sock0 || sock == sock1); - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - if (sock == sock1) - { - rxBytes1 += sz; - rxPayload = new uint8_t[sz]; - memcpy (rxPayload, p->PeekData(), sz); - } - else - { - NS_FATAL_ERROR ("Recv from unknown socket "<SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test2_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == test2_payloadSize); - - Reset (); -} - -void -TcpSocketImplTest::Test2_HandleConnectionCreated (Ptr s, const Address & addr) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - Ptr p = Create (test2_payloadSize); - sock0->Send(p); - - sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); -} - -void -TcpSocketImplTest::Test2_HandleRecv (Ptr sock) -{ - NS_ASSERT (sock == sock0 || sock == sock1); - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - if (sock == sock1) - { - rxBytes1 += sz; - } - else - { - NS_FATAL_ERROR ("Not supposed to be back traffic in test 2..."<SetAcceptCallback - (MakeNullCallback, const Address &> (), - MakeCallback(&TcpSocketImplTest::Test3_HandleConnectionCreated,this)); - sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test3_HandleRecv, this)); - - Simulator::Run (); - Simulator::Destroy (); - - result = result && (rxBytes1 == test3_payloadSize); - - Reset(); -} -void -TcpSocketImplTest::Test3_HandleConnectionCreated (Ptr s, const Address &) -{ - NS_ASSERT(s != listeningSock); - NS_ASSERT(sock0 == 0); - sock0 = s; - Ptr p = Create (test3_payloadSize); - sock0->Send(p); -} -void -TcpSocketImplTest::Test3_HandleRecv (Ptr sock) -{ - NS_ASSERT_MSG (sock == sock1, "Not supposed to be back traffic in test 3... "); - if(sock->GetRxAvailable() >= 10000 ) //perform batch reads every 10000 bytes - { - Ptr p = sock->Recv(); - uint32_t sz = p->GetSize(); - rxBytes1 += sz; - } -} - -//----------------------------------------------------------------------------- -//helpers---------------------------------------------------------------------- -//----------------------------------------------------------------------------- -Ptr -TcpSocketImplTest::CreateInternetNode () -{ - Ptr node = CreateObject (); - AddInternetStack (node); - return node; -} - -Ptr -TcpSocketImplTest::AddSimpleNetDevice (Ptr node, const char* ipaddr, const char* netmask) -{ - Ptr dev = CreateObject (); - dev->SetAddress (Mac48Address::Allocate ()); - node->AddDevice (dev); - Ptr ipv4 = node->GetObject (); - uint32_t ndid = ipv4->AddInterface (dev); - Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask)); - ipv4->AddAddress (ndid, ipv4Addr); - ipv4->SetUp (ndid); - return dev; -} - -void -TcpSocketImplTest::SetupDefaultSim () -{ - const char* netmask = "255.255.255.0"; - const char* ipaddr0 = "192.168.1.1"; - const char* ipaddr1 = "192.168.1.2"; - node0 = CreateInternetNode (); - node1 = CreateInternetNode (); - dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask); - dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask); - - channel = CreateObject (); - dev0->SetChannel (channel); - dev1->SetChannel (channel); - - Ptr sockFactory0 = node0->GetObject (); - Ptr sockFactory1 = node1->GetObject (); - - listeningSock = sockFactory0->CreateSocket(); - sock1 = sockFactory1->CreateSocket(); - - uint16_t port = 50000; - InetSocketAddress serverlocaladdr (Ipv4Address::GetAny(), port); - InetSocketAddress serverremoteaddr (Ipv4Address(ipaddr0), port); - - listeningSock->Bind(serverlocaladdr); - listeningSock->Listen (); - - sock1->Connect(serverremoteaddr); -} - -void -TcpSocketImplTest::Reset () -{ - node0 = 0; - node1 = 0; - dev0 = 0; - dev1 = 0; - channel = 0; - listeningSock = 0; - sock0 = 0; - sock1 = 0; - rxBytes0 = 0; - rxBytes1 = 0; - delete[] rxPayload; - rxPayload = 0; -} - -static TcpSocketImplTest gTcpSocketImplTest; - -}//namespace ns3 - -#endif /* RUN_SELF_TESTS */ diff --git a/src/internet-stack/tcp-test.cc b/src/internet-stack/tcp-test.cc new file mode 100644 index 000000000..1d83e08d8 --- /dev/null +++ b/src/internet-stack/tcp-test.cc @@ -0,0 +1,369 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Georgia Tech Research Corporation + * + * 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: Raj Bhattacharjea + */ +/** + * This is the test code for tcp-socket-impl.cc, it was moved out of tcp-socket-impl.cc + * to be in an independent file for clarity purposes. + */ +#ifdef RUN_SELF_TESTS + +#include "ns3/test.h" +#include "ns3/socket-factory.h" +#include "ns3/tcp-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 "ns3/config.h" +#include "ipv4-end-point.h" +#include "arp-l3-protocol.h" +#include "ipv4-l3-protocol.h" +#include "icmpv4-l4-protocol.h" +#include "udp-l4-protocol.h" +#include "tcp-l4-protocol.h" +#include "ipv4-static-routing-impl.h" +#include "ipv4-list-routing-impl.h" + +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" + +#include + +namespace ns3 { + +static void +AddInternetStack (Ptr node) +{ + //ARP + Ptr arp = CreateObject (); + node->AggregateObject(arp); + //IPV4 + Ptr ipv4 = CreateObject (); + //Routing for Ipv4 + //Routing for Ipv4 + Ptr ipv4RoutingImpl = CreateObject (); + ipv4->SetRoutingProtocol (ipv4RoutingImpl); + ipv4RoutingImpl->SetNode (node); + Ptr ipv4staticRoutingImpl = CreateObject (); + ipv4staticRoutingImpl->SetNode (node); + ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0); + node->AggregateObject(ipv4); + //ICMP + Ptr icmp = CreateObject (); + node->AggregateObject(icmp); + //UDP + Ptr udp = CreateObject (); + node->AggregateObject(udp); + //TCP + Ptr tcp = CreateObject (); + node->AggregateObject(tcp); +} + +class TcpSocketImplTest: public Test +{ + public: + TcpSocketImplTest (); + virtual bool RunTests (void); + private: + //test 1, which sends string "Hello world" server->client + void Test1 (void); + void Test1_HandleConnectionCreated (Ptr, const Address &); + void Test1_HandleRecv (Ptr sock); + + //test 2, which sends a number of bytes server->client + void Test2 (uint32_t payloadSize); + void Test2_HandleConnectionCreated (Ptr, const Address &); + void Test2_HandleRecv (Ptr sock); + uint32_t test2_payloadSize; + + //test 3, which makes sure the rx buffer is finite + void Test3 (uint32_t payloadSize); + void Test3_HandleConnectionCreated (Ptr, const Address &); + void Test3_HandleRecv (Ptr sock); + uint32_t test3_payloadSize; + + //helpers to make topology construction easier + Ptr CreateInternetNode (); + Ptr AddSimpleNetDevice (Ptr,const char*,const char*); + void SetupDefaultSim (); + + //reset all of the below state for another run + void Reset (); + + //all of the state this class needs; basically both ends of the connection, + //and this test kind of acts as an single application running on both nodes + //simultaneously + Ptr node0; + Ptr node1; + Ptr dev0; + Ptr dev1; + Ptr channel; + Ptr listeningSock; + Ptr sock0; + Ptr sock1; + uint32_t rxBytes0; + uint32_t rxBytes1; + + uint8_t* rxPayload; + + bool result; +}; + +TcpSocketImplTest::TcpSocketImplTest () + : Test ("TcpSocketImpl"), + rxBytes0 (0), + rxBytes1 (0), + rxPayload (0), + result (true) +{ +} + +bool +TcpSocketImplTest::RunTests (void) +{ + Test1(); + if (!result) return false; + Test2(600); + if (!result) return false; + Test3(20000); + return result; +} + +//----------------------------------------------------------------------------- +//test 1----------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void +TcpSocketImplTest::Test1 () +{ + SetupDefaultSim (); + listeningSock->SetAcceptCallback + (MakeNullCallback, const Address &> (), + MakeCallback(&TcpSocketImplTest::Test1_HandleConnectionCreated,this)); + sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); + + Simulator::Run (); + Simulator::Destroy (); + + result = result && (rxBytes1 == 13); + result = result && (strcmp((const char*) rxPayload,"Hello World!") == 0); + + Reset (); +} + +void +TcpSocketImplTest::Test1_HandleConnectionCreated (Ptr s, const Address & addr) +{ + NS_ASSERT(s != listeningSock); + NS_ASSERT(sock0 == 0); + sock0 = s; + const uint8_t* hello = (uint8_t*)"Hello World!"; + Ptr p = Create (hello, 13); + sock0->Send(p); + + sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this)); +} + +void +TcpSocketImplTest::Test1_HandleRecv (Ptr sock) +{ + NS_ASSERT (sock == sock0 || sock == sock1); + Ptr p = sock->Recv(); + uint32_t sz = p->GetSize(); + if (sock == sock1) + { + rxBytes1 += sz; + rxPayload = new uint8_t[sz]; + memcpy (rxPayload, p->PeekData(), sz); + } + else + { + NS_FATAL_ERROR ("Recv from unknown socket "<SetAcceptCallback + (MakeNullCallback, const Address &> (), + MakeCallback(&TcpSocketImplTest::Test2_HandleConnectionCreated,this)); + sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); + + Simulator::Run (); + Simulator::Destroy (); + + result = result && (rxBytes1 == test2_payloadSize); + + Reset (); +} + +void +TcpSocketImplTest::Test2_HandleConnectionCreated (Ptr s, const Address & addr) +{ + NS_ASSERT(s != listeningSock); + NS_ASSERT(sock0 == 0); + sock0 = s; + Ptr p = Create (test2_payloadSize); + sock0->Send(p); + + sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this)); +} + +void +TcpSocketImplTest::Test2_HandleRecv (Ptr sock) +{ + NS_ASSERT (sock == sock0 || sock == sock1); + Ptr p = sock->Recv(); + uint32_t sz = p->GetSize(); + if (sock == sock1) + { + rxBytes1 += sz; + } + else + { + NS_FATAL_ERROR ("Not supposed to be back traffic in test 2..."<SetAcceptCallback + (MakeNullCallback, const Address &> (), + MakeCallback(&TcpSocketImplTest::Test3_HandleConnectionCreated,this)); + sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test3_HandleRecv, this)); + + Simulator::Run (); + Simulator::Destroy (); + + result = result && (rxBytes1 == test3_payloadSize); + + Reset(); +} +void +TcpSocketImplTest::Test3_HandleConnectionCreated (Ptr s, const Address &) +{ + NS_ASSERT(s != listeningSock); + NS_ASSERT(sock0 == 0); + sock0 = s; + Ptr p = Create (test3_payloadSize); + sock0->Send(p); +} +void +TcpSocketImplTest::Test3_HandleRecv (Ptr sock) +{ + NS_ASSERT_MSG (sock == sock1, "Not supposed to be back traffic in test 3... "); + if(sock->GetRxAvailable() >= 10000 ) //perform batch reads every 10000 bytes + { + Ptr p = sock->Recv(); + uint32_t sz = p->GetSize(); + rxBytes1 += sz; + } +} + +//----------------------------------------------------------------------------- +//helpers---------------------------------------------------------------------- +//----------------------------------------------------------------------------- +Ptr +TcpSocketImplTest::CreateInternetNode () +{ + Ptr node = CreateObject (); + AddInternetStack (node); + return node; +} + +Ptr +TcpSocketImplTest::AddSimpleNetDevice (Ptr node, const char* ipaddr, const char* netmask) +{ + Ptr dev = CreateObject (); + dev->SetAddress (Mac48Address::Allocate ()); + node->AddDevice (dev); + Ptr ipv4 = node->GetObject (); + uint32_t ndid = ipv4->AddInterface (dev); + Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask)); + ipv4->AddAddress (ndid, ipv4Addr); + ipv4->SetUp (ndid); + return dev; +} + +void +TcpSocketImplTest::SetupDefaultSim () +{ + const char* netmask = "255.255.255.0"; + const char* ipaddr0 = "192.168.1.1"; + const char* ipaddr1 = "192.168.1.2"; + node0 = CreateInternetNode (); + node1 = CreateInternetNode (); + dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask); + dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask); + + channel = CreateObject (); + dev0->SetChannel (channel); + dev1->SetChannel (channel); + + Ptr sockFactory0 = node0->GetObject (); + Ptr sockFactory1 = node1->GetObject (); + + listeningSock = sockFactory0->CreateSocket(); + sock1 = sockFactory1->CreateSocket(); + + uint16_t port = 50000; + InetSocketAddress serverlocaladdr (Ipv4Address::GetAny(), port); + InetSocketAddress serverremoteaddr (Ipv4Address(ipaddr0), port); + + listeningSock->Bind(serverlocaladdr); + listeningSock->Listen (); + + sock1->Connect(serverremoteaddr); +} + +void +TcpSocketImplTest::Reset () +{ + node0 = 0; + node1 = 0; + dev0 = 0; + dev1 = 0; + channel = 0; + listeningSock = 0; + sock0 = 0; + sock1 = 0; + rxBytes0 = 0; + rxBytes1 = 0; + delete[] rxPayload; + rxPayload = 0; +} + +static TcpSocketImplTest gTcpSocketImplTest; + +}//namespace ns3 + +#endif /* RUN_SELF_TESTS */ + diff --git a/src/internet-stack/udp-l4-protocol.cc b/src/internet-stack/udp-l4-protocol.cc index 9d5480bb9..f65a4228b 100644 --- a/src/internet-stack/udp-l4-protocol.cc +++ b/src/internet-stack/udp-l4-protocol.cc @@ -23,9 +23,11 @@ #include "ns3/packet.h" #include "ns3/node.h" #include "ns3/boolean.h" +#include "ns3/ipv4-route.h" #include "udp-l4-protocol.h" #include "udp-header.h" +#include "udp-socket-factory-impl.h" #include "ipv4-end-point-demux.h" #include "ipv4-end-point.h" #include "ipv4-l3-protocol.h" @@ -72,6 +74,28 @@ UdpL4Protocol::SetNode (Ptr node) m_node = node; } +/* + * This method is called by AddAgregate and completes the aggregation + * by setting the node in the udp stack and link it to the ipv4 object + * present in the node along with the socket factory + */ +void +UdpL4Protocol::NotifyNewAggregate () +{ + bool is_not_initialized = (m_node == 0); + Ptrnode = this->GetObject (); + Ptr ipv4 = this->GetObject (); + if (is_not_initialized && node!= 0 && ipv4 != 0) + { + this->SetNode (node); + ipv4->Insert (this); + Ptr udpFactory = CreateObject (); + udpFactory->SetUdp (this); + node->AggregateObject (udpFactory); + } + Object::NotifyNewAggregate (); +} + int UdpL4Protocol::GetProtocolNumber (void) const { @@ -200,6 +224,7 @@ UdpL4Protocol::Receive(Ptr packet, source, udpHeader.GetSourcePort (), interface); if (endPoints.empty ()) { + NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH"); return Ipv4L4Protocol::RX_ENDPOINT_UNREACH; } for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); @@ -234,7 +259,36 @@ UdpL4Protocol::Send (Ptr packet, if (ipv4 != 0) { NS_LOG_LOGIC ("Sending to IP"); - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + // Send with null route + ipv4->Send (packet, saddr, daddr, PROT_NUMBER, 0); + } +} + +void +UdpL4Protocol::Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport, Ptr route) +{ + NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport); + + UdpHeader udpHeader; + if(m_calcChecksum) + { + udpHeader.EnableChecksums(); + udpHeader.InitializeChecksum (saddr, + daddr, + PROT_NUMBER); + } + udpHeader.SetDestinationPort (dport); + udpHeader.SetSourcePort (sport); + + packet->AddHeader (udpHeader); + + Ptr ipv4 = m_node->GetObject (); + if (ipv4 != 0) + { + NS_LOG_LOGIC ("Sending to IP"); + ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route); } } diff --git a/src/internet-stack/udp-l4-protocol.h b/src/internet-stack/udp-l4-protocol.h index 0028be49b..faf406ed6 100644 --- a/src/internet-stack/udp-l4-protocol.h +++ b/src/internet-stack/udp-l4-protocol.h @@ -33,6 +33,7 @@ namespace ns3 { class Node; class Socket; +class Ipv4Route; /** * \ingroup udp * \brief Implementation of the UDP protocol @@ -76,6 +77,9 @@ public: void Send (Ptr packet, Ipv4Address saddr, Ipv4Address daddr, uint16_t sport, uint16_t dport); + void Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport, Ptr route); /** * \brief Receive a packet up the protocol stack * \param p The Packet to dump the contents into @@ -106,6 +110,11 @@ public: const uint8_t payload[8]); 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: Ptr m_node; Ipv4EndPointDemux *m_endPoints; diff --git a/src/internet-stack/udp-socket-impl.cc b/src/internet-stack/udp-socket-impl.cc index d3cd35a42..350197720 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,7 +321,6 @@ 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; @@ -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 { @@ -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) { @@ -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->RemoveAllTags (); - m_receivedPacket2->RemoveAllTags (); - - // 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->RemoveAllTags (); - m_receivedPacket2->RemoveAllTags (); - - // 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->RemoveAllTags (); - m_receivedPacket2->RemoveAllTags (); - - Simulator::Destroy (); - - return result; -} - -static UdpSocketImplTest gUdpSocketImplTest; - -}; // namespace ns3 - -#endif /* RUN_SELF_TESTS */ diff --git a/src/internet-stack/udp-socket-impl.h b/src/internet-stack/udp-socket-impl.h index f591ce548..e671adbd5 100644 --- a/src/internet-stack/udp-socket-impl.h +++ b/src/internet-stack/udp-socket-impl.h @@ -75,15 +75,21 @@ public: virtual Ptr RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress); virtual int GetSockName (Address &address) const; + virtual int MulticastJoinGroup (uint32_t interfaceIndex, const Address &groupAddress); + virtual int MulticastLeaveGroup (uint32_t interfaceIndex, const Address &groupAddress); private: // Attributes set through UdpSocket base class virtual void SetRcvBufSize (uint32_t size); virtual uint32_t GetRcvBufSize (void) const; - virtual void SetIpTtl (uint32_t ipTtl); - virtual uint32_t GetIpTtl (void) const; - virtual void SetIpMulticastTtl (uint32_t ipTtl); - virtual uint32_t GetIpMulticastTtl (void) const; + virtual void SetIpTtl (uint8_t ipTtl); + virtual uint8_t GetIpTtl (void) const; + virtual void SetIpMulticastTtl (uint8_t ipTtl); + virtual uint8_t GetIpMulticastTtl (void) const; + virtual void SetIpMulticastIf (int32_t ipIf); + virtual int32_t GetIpMulticastIf (void) const; + virtual void SetIpMulticastLoop (bool loop); + virtual bool GetIpMulticastLoop (void) const; virtual void SetMtuDiscover (bool discover); virtual bool GetMtuDiscover (void) const; @@ -117,8 +123,10 @@ private: // Socket attributes uint32_t m_rcvBufSize; - uint32_t m_ipTtl; - uint32_t m_ipMulticastTtl; + uint8_t m_ipTtl; + uint8_t m_ipMulticastTtl; + int32_t m_ipMulticastIf; + bool m_ipMulticastLoop; bool m_mtuDiscover; Callback m_icmpCallback; }; diff --git a/src/internet-stack/udp-test.cc b/src/internet-stack/udp-test.cc new file mode 100644 index 000000000..777d959c4 --- /dev/null +++ b/src/internet-stack/udp-test.cc @@ -0,0 +1,266 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 Georgia Tech Research Corporation + * + * 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: Raj Bhattacharjea + */ +/** + * This is the test code for udp-socket-impl.cc, it was moved out of udp-socket-impl.cc to + * be in an independent file for clarity purposes. + */ +#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 "ns3/socket.h" + +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" + +#include "arp-l3-protocol.h" +#include "ipv4-l3-protocol.h" +#include "icmpv4-l4-protocol.h" +#include "udp-l4-protocol.h" +#include "tcp-l4-protocol.h" +#include "ipv4-list-routing-impl.h" +#include "ipv4-static-routing-impl.h" + +#include +#include +namespace ns3 { + +static void +AddInternetStack (Ptr node) +{ + //ARP + Ptr arp = CreateObject (); + node->AggregateObject(arp); + //IPV4 + Ptr ipv4 = CreateObject (); + //Routing for Ipv4 + Ptr ipv4RoutingImpl = CreateObject (); + ipv4->SetRoutingProtocol (ipv4RoutingImpl); + ipv4RoutingImpl->SetNode (node); + Ptr ipv4staticRoutingImpl = CreateObject (); + ipv4staticRoutingImpl->SetNode (node); + ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0); + node->AggregateObject(ipv4); + //ICMP + Ptr icmp = CreateObject (); + node->AggregateObject(icmp); + //UDP + Ptr udp = CreateObject (); + node->AggregateObject(udp); + //TCP + Ptr tcp = CreateObject (); + node->AggregateObject(tcp); +} + + +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->RemoveAllTags (); + m_receivedPacket2->RemoveAllTags (); + + // 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->RemoveAllTags (); + m_receivedPacket2->RemoveAllTags (); + + // 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->RemoveAllTags (); + m_receivedPacket2->RemoveAllTags (); + + Simulator::Destroy (); + + return result; +} + +static UdpSocketImplTest gUdpSocketImplTest; + +}; // namespace ns3 + +#endif /* RUN_SELF_TESTS */ diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index 0a48079fe..16eb5a5fd 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -72,23 +72,23 @@ def configure(conf): def build(bld): obj = bld.create_ns3_module('internet-stack', ['node']) obj.source = [ - 'internet-stack.cc', + 'tcp-test.cc', + 'udp-test.cc', 'ipv4-l4-protocol.cc', 'udp-header.cc', 'tcp-header.cc', 'ipv4-checksum.cc', 'ipv4-interface.cc', 'ipv4-l3-protocol.cc', - 'ipv4-static-routing.cc', + 'ipv4-static-routing-impl.cc', + 'ipv4-list-routing-impl.cc', 'ipv4-global-routing.cc', 'ipv4-end-point.cc', 'udp-l4-protocol.cc', 'tcp-l4-protocol.cc', 'arp-header.cc', 'arp-cache.cc', - 'arp-ipv4-interface.cc', 'arp-l3-protocol.cc', - 'ipv4-loopback-interface.cc', 'udp-socket-impl.cc', 'tcp-socket-impl.cc', 'ipv4-end-point-demux.cc', @@ -101,16 +101,18 @@ def build(bld): 'ipv4-raw-socket-impl.cc', 'icmpv4.cc', 'icmpv4-l4-protocol.cc', + 'loopback-net-device.cc', ] headers = bld.new_task_gen('ns3header') headers.module = 'internet-stack' headers.source = [ - 'internet-stack.h', 'udp-header.h', 'tcp-header.h', 'sequence-number.h', 'ipv4-global-routing.h', + 'ipv4-list-routing-impl.h', + 'ipv4-static-routing-impl.h', 'icmpv4.h', ] diff --git a/src/node/address-utils.cc b/src/node/address-utils.cc index 97f60c30a..500d74322 100644 --- a/src/node/address-utils.cc +++ b/src/node/address-utils.cc @@ -18,6 +18,7 @@ * Author: Mathieu Lacage */ #include "address-utils.h" +#include "inet-socket-address.h" namespace ns3 { @@ -67,4 +68,20 @@ void ReadFrom (Buffer::Iterator &i, Mac48Address &ad) ad.CopyFrom (mac); } +namespace addressUtils { + +bool IsMulticast (const Address &ad) +{ + if (InetSocketAddress::IsMatchingType (ad)) + { + InetSocketAddress inetAddr = InetSocketAddress::ConvertFrom (ad); + Ipv4Address ipv4 = inetAddr.GetIpv4 (); + return ipv4.IsMulticast (); + } + // IPv6 case can go here, in future + return false; +} + +} // namespace addressUtils + } // namespace ns3 diff --git a/src/node/address-utils.h b/src/node/address-utils.h index 4aaece935..0067f79d9 100644 --- a/src/node/address-utils.h +++ b/src/node/address-utils.h @@ -38,6 +38,14 @@ void ReadFrom (Buffer::Iterator &i, Ipv6Address &ad); void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len); void ReadFrom (Buffer::Iterator &i, Mac48Address &ad); +namespace addressUtils { + +/** + * \brief Address family-independent test for a multicast address + */ +bool IsMulticast (const Address &ad); +}; + }; #endif /* ADDRESS_UTILS_H */ diff --git a/src/node/ipv4-address.cc b/src/node/ipv4-address.cc index a169f4e27..28d26838d 100644 --- a/src/node/ipv4-address.cc +++ b/src/node/ipv4-address.cc @@ -55,6 +55,7 @@ AsciiToIpv4Host (char const *address) namespace ns3 { + Ipv4Mask::Ipv4Mask () : m_mask (0x66666666) {} diff --git a/src/node/ipv4-list-routing.cc b/src/node/ipv4-list-routing.cc new file mode 100644 index 000000000..beedb12dd --- /dev/null +++ b/src/node/ipv4-list-routing.cc @@ -0,0 +1,34 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ + +#include "ipv4-list-routing.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRouting); + +TypeId +Ipv4ListRouting::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4ListRouting") + .SetParent () + ; + return tid; +} + +} // namespace ns3 diff --git a/src/node/ipv4-list-routing.h b/src/node/ipv4-list-routing.h new file mode 100644 index 000000000..f330bb7ad --- /dev/null +++ b/src/node/ipv4-list-routing.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ + +#ifndef IPV4_LIST_ROUTING_H +#define IPV4_LIST_ROUTING_H + +#include "ipv4-routing-protocol.h" + +namespace ns3 { + +/** + * \ingroup ipv4 + */ + +/** + * This class is a specialization of Ipv4RoutingProtocol that allows + * other instances of Ipv4RoutingProtocol to be inserted in a + * prioritized list. Routing protocols in the list are consulted one + * by one, from highest to lowest proirity, until a routing protocol + * is found that will take the packet (this corresponds to a non-zero + * return value to RouteOutput, or a return value of true to RouteInput). + * The order by which routing protocols with the same priority value + * are consulted is undefined. + * + */ +class Ipv4ListRouting : public Ipv4RoutingProtocol +{ +public: + static TypeId GetTypeId (void); + /** + * \brief Register a new routing protocol to be used in this IPv4 stack + * + * \param routingProtocol new routing protocol implementation object + * \param priority priority to give to this routing protocol. + * Values may range between -32768 and +32767. + */ + virtual void AddRoutingProtocol (Ptr routingProtocol, int16_t priority) = 0; + + virtual uint32_t GetNRoutingProtocols (void) const = 0; + + virtual Ptr GetRoutingProtocol (uint32_t index, int16_t& priority) const = 0; +}; + +} //namespace ns3 + +#endif /* IPV4_LIST_ROUTING_H */ diff --git a/src/node/ipv4-route.cc b/src/node/ipv4-route.cc index 001039060..d4134ae33 100644 --- a/src/node/ipv4-route.cc +++ b/src/node/ipv4-route.cc @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2005 INRIA + * Copyright (c) 2009 University of Washington * * 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 @@ -15,259 +15,85 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Author: Mathieu Lacage */ #include "ipv4-route.h" +#include "net-device.h" #include "ns3/assert.h" namespace ns3 { -/***************************************************** - * Network Ipv4Route - *****************************************************/ - Ipv4Route::Ipv4Route () {} -Ipv4Route::Ipv4Route (Ipv4Route const &route) - : m_dest (route.m_dest), - m_destNetworkMask (route.m_destNetworkMask), - m_gateway (route.m_gateway), - m_interface (route.m_interface) -{} - -Ipv4Route::Ipv4Route (Ipv4Route const *route) - : m_dest (route->m_dest), - m_destNetworkMask (route->m_destNetworkMask), - m_gateway (route->m_gateway), - m_interface (route->m_interface) -{} - -Ipv4Route::Ipv4Route (Ipv4Address dest, - Ipv4Address gateway, - uint32_t interface) - : m_dest (dest), - m_destNetworkMask (Ipv4Mask::GetZero ()), - m_gateway (gateway), - m_interface (interface) -{} -Ipv4Route::Ipv4Route (Ipv4Address dest, - uint32_t interface) - : m_dest (dest), - m_destNetworkMask (Ipv4Mask::GetZero ()), - m_gateway (Ipv4Address::GetZero ()), - m_interface (interface) -{} -Ipv4Route::Ipv4Route (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address gateway, - uint32_t interface) - : m_dest (network), - m_destNetworkMask (networkMask), - m_gateway (gateway), - m_interface (interface) -{} -Ipv4Route::Ipv4Route (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) - : m_dest (network), - m_destNetworkMask (networkMask), - m_gateway (Ipv4Address::GetZero ()), - m_interface (interface) -{} - -bool -Ipv4Route::IsHost (void) const +void +Ipv4Route::SetDestination (Ipv4Address dest) { - if (m_destNetworkMask.IsEqual (Ipv4Mask::GetZero ())) - { - return true; - } - else - { - return false; - } + m_dest = dest; } + Ipv4Address -Ipv4Route::GetDest (void) const +Ipv4Route::GetDestination (void) const { return m_dest; } -bool -Ipv4Route::IsNetwork (void) const + +void +Ipv4Route::SetSource (Ipv4Address src) { - return !IsHost (); -} -bool -Ipv4Route::IsDefault (void) const -{ - if (m_dest.IsEqual (Ipv4Address::GetZero ())) - { - return true; - } - else - { - return false; - } + m_source = src; } + Ipv4Address -Ipv4Route::GetDestNetwork (void) const +Ipv4Route::GetSource (void) const { - return m_dest; + return m_source; } -Ipv4Mask -Ipv4Route::GetDestNetworkMask (void) const + +void +Ipv4Route::SetGateway (Ipv4Address gw) { - return m_destNetworkMask; -} -bool -Ipv4Route::IsGateway (void) const -{ - if (m_gateway.IsEqual (Ipv4Address::GetZero ())) - { - return false; - } - else - { - return true; - } + m_gateway = gw; } + Ipv4Address Ipv4Route::GetGateway (void) const { return m_gateway; } -uint32_t -Ipv4Route::GetInterface (void) const + +void +Ipv4Route::SetOutputDevice (Ptr outputDevice) { - return m_interface; + m_outputDevice = outputDevice; } -Ipv4Route -Ipv4Route::CreateHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) +Ptr +Ipv4Route::GetOutputDevice (void) const { - return Ipv4Route (dest, nextHop, interface); + return m_outputDevice; } -Ipv4Route -Ipv4Route::CreateHostRouteTo (Ipv4Address dest, - uint32_t interface) -{ - return Ipv4Route (dest, interface); -} -Ipv4Route -Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) -{ - return Ipv4Route (network, networkMask, - nextHop, interface); -} -Ipv4Route -Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) -{ - return Ipv4Route (network, networkMask, - interface); -} -Ipv4Route -Ipv4Route::CreateDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -{ - return Ipv4Route (Ipv4Address::GetZero (), nextHop, interface); -} - std::ostream& operator<< (std::ostream& os, Ipv4Route const& route) { - if (route.IsDefault ()) - { - NS_ASSERT (route.IsGateway ()); - os << "default out=" << route.GetInterface () << ", next hop=" << route.GetGateway (); - } - else if (route.IsHost ()) - { - if (route.IsGateway ()) - { - os << "host="<< route.GetDest () << - ", out=" << route.GetInterface () << - ", next hop=" << route.GetGateway (); - } - else - { - os << "host="<< route.GetDest () << - ", out=" << route.GetInterface (); - } - } - else if (route.IsNetwork ()) - { - if (route.IsGateway ()) - { - os << "network=" << route.GetDestNetwork () << - ", mask=" << route.GetDestNetworkMask () << - ",out=" << route.GetInterface () << - ", next hop=" << route.GetGateway (); - } - else - { - os << "network=" << route.GetDestNetwork () << - ", mask=" << route.GetDestNetworkMask () << - ",out=" << route.GetInterface (); - } - } - else - { - NS_ASSERT (false); - } - return os; + os << "source=" << route.GetSource () << " dest="<< route.GetDestination () <<" gw=" << route.GetGateway (); + return os; } -/***************************************************** - * Ipv4MulticastRoute - *****************************************************/ - Ipv4MulticastRoute::Ipv4MulticastRoute () { + uint32_t initial_ttl = MAX_TTL; + // Initialize array to MAX_TTL, which means that all interfaces are "off" + for (uint32_t i = 0; i < MAX_INTERFACES; i++) + { + m_ttls.push_back(initial_ttl); + } } -Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const &route) -: - m_origin (route.m_origin), - m_group (route.m_group), - m_inputInterface (route.m_inputInterface), - m_outputInterfaces (route.m_outputInterfaces) +void +Ipv4MulticastRoute::SetGroup (const Ipv4Address group) { -} - -Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const *route) -: - m_origin (route->m_origin), - m_group (route->m_group), - m_inputInterface (route->m_inputInterface), - m_outputInterfaces (route->m_outputInterfaces) -{ -} - -Ipv4MulticastRoute::Ipv4MulticastRoute ( - Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) -{ - m_origin = origin; m_group = group; - m_inputInterface = inputInterface; - m_outputInterfaces = outputInterfaces; -} - -Ipv4Address -Ipv4MulticastRoute::GetOrigin (void) const -{ - return m_origin; } Ipv4Address @@ -276,58 +102,40 @@ Ipv4MulticastRoute::GetGroup (void) const return m_group; } +void +Ipv4MulticastRoute::SetOrigin (const Ipv4Address origin) +{ + m_origin = origin; +} + +Ipv4Address +Ipv4MulticastRoute::GetOrigin (void) const +{ + return m_origin; +} + +void +Ipv4MulticastRoute::SetParent (uint32_t parent) +{ + m_parent = parent; +} + uint32_t -Ipv4MulticastRoute::GetInputInterface (void) const +Ipv4MulticastRoute::GetParent (void) const { - return m_inputInterface; + return m_parent; +} + +void +Ipv4MulticastRoute::SetOutputTtl (uint32_t oif, uint32_t ttl) +{ + m_ttls[oif] = ttl; } uint32_t -Ipv4MulticastRoute::GetNOutputInterfaces (void) const +Ipv4MulticastRoute::GetOutputTtl (uint32_t oif) const { - return m_outputInterfaces.size (); -} - -uint32_t -Ipv4MulticastRoute::GetOutputInterface (uint32_t n) const -{ - NS_ASSERT_MSG(n < m_outputInterfaces.size (), - "Ipv4MulticastRoute::GetOutputInterface (): index out of bounds"); - - return m_outputInterfaces[n]; -} - -std::vector -Ipv4MulticastRoute::GetOutputInterfaces (void) const -{ - return m_outputInterfaces; -} - -Ipv4MulticastRoute -Ipv4MulticastRoute::CreateMulticastRoute ( - Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) -{ - return Ipv4MulticastRoute (origin, group, inputInterface, outputInterfaces); -} - -std::ostream& -operator<< (std::ostream& os, Ipv4MulticastRoute const& route) -{ - os << "origin=" << route.GetOrigin () << - ", group=" << route.GetGroup () << - ", input interface=" << route.GetInputInterface () << - ", output interfaces="; - - for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i) - { - os << route.GetOutputInterface (i) << " "; - - } - - return os; + return m_ttls[oif]; } }//namespace ns3 diff --git a/src/node/ipv4-route.h b/src/node/ipv4-route.h index 6f2ce0349..fdf9c49eb 100644 --- a/src/node/ipv4-route.h +++ b/src/node/ipv4-route.h @@ -1,6 +1,6 @@ /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* - * Copyright (c) 2005 INRIA + * Copyright (c) 2009 University of Washington * * 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 @@ -15,7 +15,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * Author: Mathieu Lacage */ #ifndef IPV4_ROUTE_H #define IPV4_ROUTE_H @@ -24,157 +23,82 @@ #include #include +#include "ns3/ref-count-base.h" #include "ipv4-address.h" namespace ns3 { + +class NetDevice; + /** - * \ingroup ipv4 - * \brief A record of an IPv4 route + *\brief Ipv4 route cache entry (similar to Linux struct rtable) + * + * In the future, we will add other entries from struct dst_entry, struct rtable, and struct dst_ops as needed. */ -class Ipv4Route { +class Ipv4Route : public RefCountBase { public: - /** - * \brief This constructor does nothing - */ Ipv4Route (); - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4Route (Ipv4Route const &route); + void SetDestination (Ipv4Address dest); + Ipv4Address GetDestination (void) const; - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4Route (Ipv4Route const *route); + void SetSource (Ipv4Address src); + Ipv4Address GetSource (void) const; - bool IsHost (void) const; - /** - * \return The IPv4 address of the destination of this route - */ - Ipv4Address GetDest (void) const; - - bool IsNetwork (void) const; - Ipv4Address GetDestNetwork (void) const; - Ipv4Mask GetDestNetworkMask (void) const; - /** - * \return True if this route is a default route; false otherwise - */ - bool IsDefault (void) const; - - bool IsGateway (void) const; + void SetGateway (Ipv4Address gw); Ipv4Address GetGateway (void) const; - uint32_t GetInterface (void) const; + // dst_entry.dev + void SetOutputDevice (Ptr outputDevice); + Ptr GetOutputDevice (void) const; + +#ifdef NOTYET + // rtable.idev + void SetInputIfIndex (uint32_t iif); + uint32_t GetInputIfIndex (void) const; +#endif - static Ipv4Route CreateHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); - static Ipv4Route CreateHostRouteTo (Ipv4Address dest, - uint32_t interface); - static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); - static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); - static Ipv4Route CreateDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - private: - Ipv4Route (Ipv4Address network, - Ipv4Mask mask, - Ipv4Address gateway, - uint32_t interface); - Ipv4Route (Ipv4Address dest, - Ipv4Mask mask, - uint32_t interface); - Ipv4Route (Ipv4Address dest, - Ipv4Address gateway, - uint32_t interface); - Ipv4Route (Ipv4Address dest, - uint32_t interface); - Ipv4Address m_dest; - Ipv4Mask m_destNetworkMask; + Ipv4Address m_source; Ipv4Address m_gateway; - uint32_t m_interface; + Ptr m_outputDevice; +#ifdef NOTYET + uint32_t m_inputIfIndex; +#endif }; std::ostream& operator<< (std::ostream& os, Ipv4Route const& route); /** - * \ingroup ipv4 - * \brief A record of an IPv4 multicast route + *\brief Ipv4 multicast route cache entry (similar to Linux struct mfc_cache) */ -class Ipv4MulticastRoute { +class Ipv4MulticastRoute : public RefCountBase { public: - /** - * \brief This constructor does nothing - */ Ipv4MulticastRoute (); - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4MulticastRoute (Ipv4MulticastRoute const &route); + void SetGroup (const Ipv4Address group); + Ipv4Address GetGroup (void) const; - /** - * \brief Copy Constructor - * \param route The route to copy - */ - Ipv4MulticastRoute (Ipv4MulticastRoute const *route); + void SetOrigin (const Ipv4Address group); + Ipv4Address GetOrigin (void) const; + + void SetParent (uint32_t iif); + uint32_t GetParent (void) const; - /** - * \return The IPv4 address of the source of this route - */ - Ipv4Address GetOrigin (void) const; - - /** - * \return The IPv4 address of the multicast group of this route - */ - Ipv4Address GetGroup (void) const; - - /** - * \return The IPv4 address of the input interface of this route - */ - uint32_t GetInputInterface (void) const; - - /** - * \return The number of output interfaces of this route - */ - uint32_t GetNOutputInterfaces (void) const; - - /** - * \return A specified output interface. - */ - uint32_t GetOutputInterface (uint32_t n) const; - - /** - * \return A vector of all of the output interfaces of this route. - */ - std::vector GetOutputInterfaces (void) const; - - static Ipv4MulticastRoute CreateMulticastRoute (Ipv4Address origin, - Ipv4Address group, uint32_t inputInterface, - std::vector outputInterfaces); + void SetOutputTtl (uint32_t oif, uint32_t ttl); + uint32_t GetOutputTtl (uint32_t oif) const; + + static const uint32_t MAX_INTERFACES = 16; + static const uint32_t MAX_TTL = 255; private: - Ipv4MulticastRoute (Ipv4Address origin, Ipv4Address group, - uint32_t inputInterface, std::vector outputInterfaces); - - Ipv4Address m_origin; - Ipv4Address m_group; - uint32_t m_inputInterface; - std::vector m_outputInterfaces; + Ipv4Address m_group; // Group + Ipv4Address m_origin; // Source of packet + uint32_t m_parent; // Source interface + std::vector m_ttls; }; -std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoute const& route); - }//namespace ns3 #endif /* IPV4_ROUTE_H */ diff --git a/src/node/ipv4-routing-protocol.cc b/src/node/ipv4-routing-protocol.cc new file mode 100644 index 000000000..d983e0284 --- /dev/null +++ b/src/node/ipv4-routing-protocol.cc @@ -0,0 +1,35 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ + +#include "ns3/assert.h" +#include "ipv4-route.h" +#include "ipv4-routing-protocol.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4RoutingProtocol); + +TypeId Ipv4RoutingProtocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4RoutingProtocol") + .SetParent () + ; + return tid; +} + +}//namespace ns3 diff --git a/src/node/ipv4-routing-protocol.h b/src/node/ipv4-routing-protocol.h new file mode 100644 index 000000000..17f0c38b2 --- /dev/null +++ b/src/node/ipv4-routing-protocol.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ +#ifndef IPV4_ROUTING_PROTOCOL_H +#define IPV4_ROUTING_PROTOCOL_H + +#include "ns3/packet.h" +#include "ns3/callback.h" +#include "ns3/object.h" +#include "ns3/socket.h" +#include "ipv4-header.h" + +namespace ns3 { + +class Ipv4MulticastRoute; +class Ipv4Route; +class NetDevice; + +/** + * \ingroup ipv4 + * Abstract base class for Ipv4 routing protocols. Defines two + * virtual functions for packet routing and forwarding. The first, + * RouteOutput(), is used for locally originated packets, and the second, + * RouteInput(), is used for forwarding and/or delivering received packets. + * Also defines the signatures of four callbacks used in RouteInput(). + * + */ +class Ipv4RoutingProtocol : public Object +{ +public: + static TypeId GetTypeId (void); + + typedef Callback, Ptr, const Ipv4Header &> UnicastForwardCallback; + typedef Callback, Ptr, const Ipv4Header &> MulticastForwardCallback; + typedef Callback, const Ipv4Header &, uint32_t > LocalDeliverCallback; + typedef Callback, const Ipv4Header &> ErrorCallback; + + /** + * \brief Query routing cache for an existing route, for an outbound packet + * + * This lookup is used by transport protocols. It does not cause any + * packet to be forwarded, and is synchronous. Can be used for + * multicast or unicast. The Linux equivalent is ip_route_output() + * + * \param header input parameter (used to form key to search for the route) + * \param oif Output interface index. May be zero, or may be bound via + * socket options to a particular output interface. + * \param sockerr Output parameter; socket errno + * + * \returns a code that indicates what happened in the lookup + */ + virtual Ptr RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr) = 0; + + /** + * \brief Route an input packet (to be forwarded or locally delivered) + * + * This lookup is used in the forwarding process. The packet is + * handed over to the Ipv4RoutingProtocol, and will get forwarded onward + * by one of the callbacks. The Linux equivalent is ip_route_input(). + * There are four valid outcomes, and a matching callbacks to handle each. + * + * \param p received packet + * \param header input parameter used to form a search key for a route + * \param idev Pointer to ingress network device + * \param ucb Callback for the case in which the packet is to be forwarded + * as unicast + * \param mcb Callback for the case in which the packet is to be forwarded + * as multicast + * \param lcb Callback for the case in which the packet is to be locally + * delivered + * \param ecb Callback to call if there is an error in forwarding + * \returns true if the Ipv4RoutingProtocol takes responsibility for + * forwarding or delivering the packet, false otherwise + */ + virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) = 0; +}; + +} //namespace ns3 + +#endif /* IPV4_ROUTING_PROTOCOL_H */ diff --git a/src/node/ipv4-routing-table-entry.cc b/src/node/ipv4-routing-table-entry.cc new file mode 100644 index 000000000..d30832a3d --- /dev/null +++ b/src/node/ipv4-routing-table-entry.cc @@ -0,0 +1,333 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * + * 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: Mathieu Lacage + */ + +#include "ipv4-routing-table-entry.h" +#include "ns3/assert.h" + +namespace ns3 { + +/***************************************************** + * Network Ipv4RoutingTableEntry + *****************************************************/ + +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry () +{} + +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const &route) + : m_dest (route.m_dest), + m_destNetworkMask (route.m_destNetworkMask), + m_gateway (route.m_gateway), + m_interface (route.m_interface) +{} + +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const *route) + : m_dest (route->m_dest), + m_destNetworkMask (route->m_destNetworkMask), + m_gateway (route->m_gateway), + m_interface (route->m_interface) +{} + +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address dest, + Ipv4Address gateway, + uint32_t interface) + : m_dest (dest), + m_destNetworkMask (Ipv4Mask::GetZero ()), + m_gateway (gateway), + m_interface (interface) +{} +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address dest, + uint32_t interface) + : m_dest (dest), + m_destNetworkMask (Ipv4Mask::GetZero ()), + m_gateway (Ipv4Address::GetZero ()), + m_interface (interface) +{} +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address gateway, + uint32_t interface) + : m_dest (network), + m_destNetworkMask (networkMask), + m_gateway (gateway), + m_interface (interface) +{} +Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) + : m_dest (network), + m_destNetworkMask (networkMask), + m_gateway (Ipv4Address::GetZero ()), + m_interface (interface) +{} + +bool +Ipv4RoutingTableEntry::IsHost (void) const +{ + if (m_destNetworkMask.IsEqual (Ipv4Mask::GetZero ())) + { + return true; + } + else + { + return false; + } +} +Ipv4Address +Ipv4RoutingTableEntry::GetDest (void) const +{ + return m_dest; +} +bool +Ipv4RoutingTableEntry::IsNetwork (void) const +{ + return !IsHost (); +} +bool +Ipv4RoutingTableEntry::IsDefault (void) const +{ + if (m_dest.IsEqual (Ipv4Address::GetZero ())) + { + return true; + } + else + { + return false; + } +} +Ipv4Address +Ipv4RoutingTableEntry::GetDestNetwork (void) const +{ + return m_dest; +} +Ipv4Mask +Ipv4RoutingTableEntry::GetDestNetworkMask (void) const +{ + return m_destNetworkMask; +} +bool +Ipv4RoutingTableEntry::IsGateway (void) const +{ + if (m_gateway.IsEqual (Ipv4Address::GetZero ())) + { + return false; + } + else + { + return true; + } +} +Ipv4Address +Ipv4RoutingTableEntry::GetGateway (void) const +{ + return m_gateway; +} +uint32_t +Ipv4RoutingTableEntry::GetInterface (void) const +{ + return m_interface; +} + +Ipv4RoutingTableEntry +Ipv4RoutingTableEntry::CreateHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) +{ + return Ipv4RoutingTableEntry (dest, nextHop, interface); +} +Ipv4RoutingTableEntry +Ipv4RoutingTableEntry::CreateHostRouteTo (Ipv4Address dest, + uint32_t interface) +{ + return Ipv4RoutingTableEntry (dest, interface); +} +Ipv4RoutingTableEntry +Ipv4RoutingTableEntry::CreateNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) +{ + return Ipv4RoutingTableEntry (network, networkMask, + nextHop, interface); +} +Ipv4RoutingTableEntry +Ipv4RoutingTableEntry::CreateNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) +{ + return Ipv4RoutingTableEntry (network, networkMask, + interface); +} +Ipv4RoutingTableEntry +Ipv4RoutingTableEntry::CreateDefaultRoute (Ipv4Address nextHop, + uint32_t interface) +{ + return Ipv4RoutingTableEntry (Ipv4Address::GetZero (), nextHop, interface); +} + + +std::ostream& operator<< (std::ostream& os, Ipv4RoutingTableEntry const& route) +{ + if (route.IsDefault ()) + { + NS_ASSERT (route.IsGateway ()); + os << "default out=" << route.GetInterface () << ", next hop=" << route.GetGateway (); + } + else if (route.IsHost ()) + { + if (route.IsGateway ()) + { + os << "host="<< route.GetDest () << + ", out=" << route.GetInterface () << + ", next hop=" << route.GetGateway (); + } + else + { + os << "host="<< route.GetDest () << + ", out=" << route.GetInterface (); + } + } + else if (route.IsNetwork ()) + { + if (route.IsGateway ()) + { + os << "network=" << route.GetDestNetwork () << + ", mask=" << route.GetDestNetworkMask () << + ",out=" << route.GetInterface () << + ", next hop=" << route.GetGateway (); + } + else + { + os << "network=" << route.GetDestNetwork () << + ", mask=" << route.GetDestNetworkMask () << + ",out=" << route.GetInterface (); + } + } + else + { + NS_ASSERT (false); + } + return os; +} + +/***************************************************** + * Ipv4MulticastRoutingTableEntry + *****************************************************/ + +Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry () +{ +} + +Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const &route) +: + m_origin (route.m_origin), + m_group (route.m_group), + m_inputInterface (route.m_inputInterface), + m_outputInterfaces (route.m_outputInterfaces) +{ +} + +Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const *route) +: + m_origin (route->m_origin), + m_group (route->m_group), + m_inputInterface (route->m_inputInterface), + m_outputInterfaces (route->m_outputInterfaces) +{ +} + +Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry ( + Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) +{ + m_origin = origin; + m_group = group; + m_inputInterface = inputInterface; + m_outputInterfaces = outputInterfaces; +} + +Ipv4Address +Ipv4MulticastRoutingTableEntry::GetOrigin (void) const +{ + return m_origin; +} + +Ipv4Address +Ipv4MulticastRoutingTableEntry::GetGroup (void) const +{ + return m_group; +} + +uint32_t +Ipv4MulticastRoutingTableEntry::GetInputInterface (void) const +{ + return m_inputInterface; +} + +uint32_t +Ipv4MulticastRoutingTableEntry::GetNOutputInterfaces (void) const +{ + return m_outputInterfaces.size (); +} + +uint32_t +Ipv4MulticastRoutingTableEntry::GetOutputInterface (uint32_t n) const +{ + NS_ASSERT_MSG(n < m_outputInterfaces.size (), + "Ipv4MulticastRoutingTableEntry::GetOutputInterface (): index out of bounds"); + + return m_outputInterfaces[n]; +} + +std::vector +Ipv4MulticastRoutingTableEntry::GetOutputInterfaces (void) const +{ + return m_outputInterfaces; +} + +Ipv4MulticastRoutingTableEntry +Ipv4MulticastRoutingTableEntry::CreateMulticastRoute ( + Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) +{ + return Ipv4MulticastRoutingTableEntry (origin, group, inputInterface, outputInterfaces); +} + +std::ostream& +operator<< (std::ostream& os, Ipv4MulticastRoutingTableEntry const& route) +{ + os << "origin=" << route.GetOrigin () << + ", group=" << route.GetGroup () << + ", input interface=" << route.GetInputInterface () << + ", output interfaces="; + + for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i) + { + os << route.GetOutputInterface (i) << " "; + + } + + return os; +} + +}//namespace ns3 diff --git a/src/node/ipv4-routing-table-entry.h b/src/node/ipv4-routing-table-entry.h new file mode 100644 index 000000000..7e84f14ab --- /dev/null +++ b/src/node/ipv4-routing-table-entry.h @@ -0,0 +1,181 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005 INRIA + * + * 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: Mathieu Lacage + */ +#ifndef IPV4_ROUTING_TABLE_ENTRY_H +#define IPV4_ROUTING_TABLE_ENTRY_H + +#include +#include +#include + +#include "ns3/ipv4-address.h" + +namespace ns3 { + +/** + * \ingroup internetStack + * \brief A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting + */ +class Ipv4RoutingTableEntry { +public: + /** + * \brief This constructor does nothing + */ + Ipv4RoutingTableEntry (); + + /** + * \brief Copy Constructor + * \param route The route to copy + */ + Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const &route); + + /** + * \brief Copy Constructor + * \param route The route to copy + */ + Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const *route); + + bool IsHost (void) const; + /** + * \return The IPv4 address of the destination of this route + */ + Ipv4Address GetDest (void) const; + + bool IsNetwork (void) const; + Ipv4Address GetDestNetwork (void) const; + Ipv4Mask GetDestNetworkMask (void) const; + /** + * \return True if this route is a default route; false otherwise + */ + bool IsDefault (void) const; + + bool IsGateway (void) const; + Ipv4Address GetGateway (void) const; + + uint32_t GetInterface (void) const; + + static Ipv4RoutingTableEntry CreateHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface); + static Ipv4RoutingTableEntry CreateHostRouteTo (Ipv4Address dest, + uint32_t interface); + static Ipv4RoutingTableEntry CreateNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface); + static Ipv4RoutingTableEntry CreateNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface); + static Ipv4RoutingTableEntry CreateDefaultRoute (Ipv4Address nextHop, + uint32_t interface); + +private: + Ipv4RoutingTableEntry (Ipv4Address network, + Ipv4Mask mask, + Ipv4Address gateway, + uint32_t interface); + Ipv4RoutingTableEntry (Ipv4Address dest, + Ipv4Mask mask, + uint32_t interface); + Ipv4RoutingTableEntry (Ipv4Address dest, + Ipv4Address gateway, + uint32_t interface); + Ipv4RoutingTableEntry (Ipv4Address dest, + uint32_t interface); + + Ipv4Address m_dest; + Ipv4Mask m_destNetworkMask; + Ipv4Address m_gateway; + uint32_t m_interface; +}; + +std::ostream& operator<< (std::ostream& os, Ipv4RoutingTableEntry const& route); + +/** + * \ingroup internetStack + * \brief A record of an IPv4 multicast route for Ipv4GlobalRouting and Ipv4StaticRouting + */ +class Ipv4MulticastRoutingTableEntry { +public: + /** + * \brief This constructor does nothing + */ + Ipv4MulticastRoutingTableEntry (); + + /** + * \brief Copy Constructor + * \param route The route to copy + */ + Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const &route); + + /** + * \brief Copy Constructor + * \param route The route to copy + */ + Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const *route); + + /** + * \return The IPv4 address of the source of this route + */ + Ipv4Address GetOrigin (void) const; + + /** + * \return The IPv4 address of the multicast group of this route + */ + Ipv4Address GetGroup (void) const; + + /** + * \return The IPv4 address of the input interface of this route + */ + uint32_t GetInputInterface (void) const; + + /** + * \return The number of output interfaces of this route + */ + uint32_t GetNOutputInterfaces (void) const; + + /** + * \return A specified output interface. + */ + uint32_t GetOutputInterface (uint32_t n) const; + + /** + * \return A vector of all of the output interfaces of this route. + */ + std::vector GetOutputInterfaces (void) const; + + static Ipv4MulticastRoutingTableEntry CreateMulticastRoute (Ipv4Address origin, + Ipv4Address group, uint32_t inputInterface, + std::vector outputInterfaces); + +private: + Ipv4MulticastRoutingTableEntry (Ipv4Address origin, Ipv4Address group, + uint32_t inputInterface, std::vector outputInterfaces); + + Ipv4Address m_origin; + Ipv4Address m_group; + uint32_t m_inputInterface; + std::vector m_outputInterfaces; +}; + +std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoutingTableEntry const& route); + +}//namespace ns3 + +#endif /* IPV4_ROUTING_TABLE_ENTRY_H */ diff --git a/src/node/ipv4-static-routing.cc b/src/node/ipv4-static-routing.cc new file mode 100644 index 000000000..512d1e04f --- /dev/null +++ b/src/node/ipv4-static-routing.cc @@ -0,0 +1,34 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 University of Washington + * + * 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 + */ + +#include "ipv4-static-routing.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4StaticRouting); + +TypeId +Ipv4StaticRouting::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4StaticRouting") + .SetParent () + ; + return tid; +} + +} // namespace ns3 diff --git a/src/node/ipv4-static-routing.h b/src/node/ipv4-static-routing.h new file mode 100644 index 000000000..95e06d18a --- /dev/null +++ b/src/node/ipv4-static-routing.h @@ -0,0 +1,366 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 Georgia Tech Research Corporation + * + * 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: George F. Riley + * Gustavo Carneiro + */ + +#ifndef IPV4_STATIC_ROUTING_H +#define IPV4_STATIC_ROUTING_H + +#include +#include +#include "ns3/ipv4-address.h" +#include "ns3/ipv4-header.h" +#include "ns3/socket.h" +#include "ns3/ptr.h" +#include "ns3/ipv4.h" +#include "ns3/ipv4-routing-protocol.h" + +namespace ns3 { + +class Packet; +class NetDevice; +class Ipv4Interface; +class Ipv4Address; +class Ipv4Header; +class Node; + +class Ipv4RoutingTableEntry; +class Ipv4MulticastRoutingTableEntry; + +/** + * \brief Static routing protocol for IP version 4 stacks. + * + * In ns-3 we have the concept of a pluggable routing protocol. Routing + * protocols are added to a list maintained by the Ipv4L3Protocol. Every + * stack gets one routing protocol for free -- the Ipv4StaticRouting routing + * protocol is added in the constructor of the Ipv4L3Protocol (this is the + * piece of code that implements the functionality of the IP layer). + * + * The Ipv4StaticRouting class inherits from the abstract base class + * Ipv4RoutingProtocol that defines the interface methods that a routing + * protocol must support. + * + * When a packet arrives in the Ipv4L3Protocol for transmission, it comes + * either from a local source via Ipv4L3Protocol::Send or from a remote + * source via Ipv4L3Protocol::Forwarding. In both cases, a function is called + * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet. + * + * The lookup function iterates through the list of routing protocols asking + * each to see if it can find a route and send the packet. A callback is + * provided during each of these calls that should be considered a pre- + * packaged send call. This is done to allow asynchronous calls into + * routing subsystems in order to support on-demand routing, for example. The + * method for requesting this operation is Ipv4StaticRouting::RequestRoute for + * the static routing protocol. + * + * Each routing protocol is also free to implement its own methods for managing + * routes which you will find below. This class manages a set of "static" or + * manually configured routes for host, network and multicast routes. + * + * \see Ipv4RoutingProtocol + * \see Ipv4L3Protocol::AddRoutingProtocol + * \see Ipv4L3Protocol::Ipv4L3Protocol + */ +class Ipv4StaticRouting : public Ipv4RoutingProtocol +{ +public: + static TypeId GetTypeId (void); + +/** + * \brief Add a host route to the static routing table. + * + * \param dest The Ipv4Address destination for this route. + * \param nextHop The Ipv4Address of the next hop in the route. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + virtual void AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) = 0; +/** + * \brief Add a host route to the static routing table. + * + * \param dest The Ipv4Address destination for this route. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + virtual void AddHostRouteTo (Ipv4Address dest, uint32_t interface) = 0; + +/** + * \brief Add a network route to the static routing table. + * + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param nextHop The next hop in the route to the destination network. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + virtual void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) = 0; + +/** + * \brief Add a network route to the static routing table. + * + * \param network The Ipv4Address network for this route. + * \param networkMask The Ipv4Mask to extract the network. + * \param interface The network interface index used to send packets to the + * destination. + * + * \see Ipv4Address + */ + virtual void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) = 0; + +/** + * \brief Add a default route to the static routing table. + * + * This method tells the routing system what to do in the case where a specific + * route to a destination is not found. The system forwards packets to the + * specified node in the hope that it knows better how to route the packet. + * + * If the default route is set, it is returned as the selected route from + * LookupStatic irrespective of destination address if no specific route is + * found. + * + * \param nextHop The Ipv4Address to send packets to in the hope that they + * will be forwarded correctly. + * \param interface The network interface index used to send packets. + * + * \see Ipv4Address + * \see Ipv4StaticRouting::Lookup + */ + virtual void SetDefaultRoute (Ipv4Address nextHop, uint32_t interface) = 0; + +/** + * \brief Get the number of individual unicast routes that have been added + * to the routing table. + * + * \warning The default route counts as one of the routes. + */ + virtual uint32_t GetNRoutes (void) = 0; + +/** + * \brief Get the default route from the static routing table. + * + * \return If the default route is set, a pointer to that Ipv4RoutingTableEntry is + * returned, otherwise a zero pointer is returned. + * + * \see Ipv4RoutingTableEntry + */ + virtual Ipv4RoutingTableEntry GetDefaultRoute (void) = 0; + +/** + * \brief Get a route from the static unicast routing table. + * + * Externally, the unicast static routing table appears simply as a table with + * n entries. The one sublety of note is that if a default route has been set + * it will appear as the zeroth entry in the table. This means that if you + * add only a default route, the table will have one entry that can be accessed + * either by explicity calling GetDefaultRoute () or by calling GetRoute (0). + * + * Similarly, if the default route has been set, calling RemoveRoute (0) will + * remove the default route. + * + * \param i The index (into the routing table) of the route to retrieve. If + * the default route has been set, it will occupy index zero. + * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise + * a zero pointer is returned. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::RemoveRoute + */ + virtual Ipv4RoutingTableEntry GetRoute (uint32_t i) = 0; + +/** + * \brief Remove a route from the static unicast routing table. + * + * Externally, the unicast static routing table appears simply as a table with + * n entries. The one sublety of note is that if a default route has been set + * it will appear as the zeroth entry in the table. This means that if the + * default route has been set, calling RemoveRoute (0) will remove the + * default route. + * + * \param i The index (into the routing table) of the route to remove. If + * the default route has been set, it will occupy index zero. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::GetRoute + * \see Ipv4StaticRouting::AddRoute + */ + virtual void RemoveRoute (uint32_t i) = 0; + +/** + * \brief Add a multicast route to the static routing table. + * + * A multicast route must specify an origin IP address, a multicast group and + * an input network interface index as conditions and provide a vector of + * output network interface indices over which packets matching the conditions + * are sent. + * + * Typically there are two main types of multicast routes: routes of the + * first kind are used during forwarding. All of the conditions must be + * exlicitly provided. The second kind of routes are used to get packets off + * of a local node. The difference is in the input interface. Routes for + * forwarding will always have an explicit input interface specified. Routes + * off of a node will always set the input interface to a wildcard specified + * by the index Ipv4RoutingProtocol::INTERFACE_ANY. + * + * For routes off of a local node wildcards may be used in the origin and + * multicast group addresses. The wildcard used for Ipv4Adresses is that + * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0". Usage + * of a wildcard allows one to specify default behavior to varying degrees. + * + * For example, making the origin address a wildcard, but leaving the + * multicast group specific allows one (in the case of a node with multiple + * interfaces) to create different routes using different output interfaces + * for each multicast group. + * + * If the origin and multicast addresses are made wildcards, you have created + * essentially a default multicast address that can forward to multiple + * interfaces. Compare this to the actual default multicast address that is + * limited to specifying a single output interface for compatibility with + * existing functionality in other systems. + * + * \param origin The Ipv4Address of the origin of packets for this route. May + * be Ipv4Address:GetAny for open groups. + * \param group The Ipv4Address of the multicast group or this route. + * \param inputInterface The input network interface index over which to + * expect packets destined for this route. May be + * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin. + * \param outputInterfaces A vector of network interface indices used to specify + * how to send packets to the destination(s). + * + * \see Ipv4Address + */ + virtual void AddMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) = 0; + +/** + * \brief Add a default multicast route to the static routing table. + * + * This is the multicast equivalent of the unicast version SetDefaultRoute. + * We tell the routing system what to do in the case where a specific route + * to a destination multicast group is not found. The system forwards + * packets out the specified interface in the hope that "something out there" + * knows better how to route the packet. This method is only used in + * initially sending packets off of a host. The default multicast route is + * not consulted during forwarding -- exact routes must be specified using + * AddMulticastRoute for that case. + * + * Since we're basically sending packets to some entity we think may know + * better what to do, we don't pay attention to "subtleties" like origin + * address, nor do we worry about forwarding out multiple interfaces. If the + * default multicast route is set, it is returned as the selected route from + * LookupStatic irrespective of origin or multicast group if another specific + * route is not found. + * + * \param outputInterface The network interface index used to specify where + * to send packets in the case of unknown routes. + * + * \see Ipv4Address + */ + virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0; + +/** + * \brief Get the number of individual multicast routes that have been added + * to the routing table. + * + * \warning The default multicast route counts as one of the routes. + */ + virtual uint32_t GetNMulticastRoutes (void) const = 0; + +/** + * \brief Get a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * + * \param i The index (into the routing table) of the multicast route to + * retrieve. + * \return If route \e i is set, a pointer to that Ipv4MulticastRoutingTableEntry is + * returned, otherwise a zero pointer is returned. + * + * \see Ipv4MulticastRoutingTableEntry + * \see Ipv4StaticRouting::RemoveRoute + */ + virtual Ipv4MulticastRoutingTableEntry GetMulticastRoute (uint32_t i) const = 0; + +/** + * \brief Remove a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * This method causes the multicast routing table to be searched for the first + * route that matches the parameters and removes it. + * + * Wildcards may be provided to this function, but the wildcards are used to + * exacly match wildcards in the routes (see AddMulticastRoute). That is, + * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not + * remove routes with any address in the origin, but will only remove routes + * with "0.0.0.0" set as the the origin. + * + * \param origin The IP address specified as the origin of packets for the + * route. + * \param group The IP address specified as the multicast group addres of + * the route. + * \param inputInterface The network interface index specified as the expected + * input interface for the route. + * \returns true if a route was found and removed, false otherwise. + * + * \see Ipv4MulticastRoutingTableEntry + * \see Ipv4StaticRouting::AddMulticastRoute + */ + virtual bool RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface) = 0; + +/** + * \brief Remove a route from the static multicast routing table. + * + * Externally, the multicast static routing table appears simply as a table + * with n entries. + * + * \param index The index (into the multicast routing table) of the route to + * remove. + * + * \see Ipv4RoutingTableEntry + * \see Ipv4StaticRouting::GetRoute + * \see Ipv4StaticRouting::AddRoute + */ + virtual void RemoveMulticastRoute (uint32_t index) = 0; + + virtual void SetNode (Ptr node) = 0; + virtual Ptr GetNode (void) const = 0; + +}; + +} // Namespace ns3 + +#endif /* IPV4_STATIC_ROUTING_H */ diff --git a/src/node/ipv4.cc b/src/node/ipv4.cc index c1139c1b6..8bf9a32f2 100644 --- a/src/node/ipv4.cc +++ b/src/node/ipv4.cc @@ -20,6 +20,7 @@ #include "ns3/assert.h" #include "ns3/node.h" +#include "ns3/boolean.h" #include "ipv4.h" namespace ns3 { @@ -30,7 +31,20 @@ TypeId Ipv4::GetTypeId (void) { static TypeId tid = TypeId ("ns3::Ipv4") - .SetParent (); + .SetParent () + .AddAttribute ("IpForward", "If enabled, node can act as unicast router.", + BooleanValue (true), + MakeBooleanAccessor (&Ipv4::SetIpForward, + &Ipv4::GetIpForward), + MakeBooleanChecker ()) +#if 0 + .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.", + BooleanValue (false), + MakeBooleanAccessor (&UdpSocket::SetMtuDiscover, + &UdpSocket::GetMtuDiscover), + MakeBooleanChecker ()) +#endif + ; return tid; } @@ -40,23 +54,4 @@ Ipv4::Ipv4 () Ipv4::~Ipv4 () {} -uint32_t -Ipv4::GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask) -{ - for (uint32_t i = 0; i < GetNInterfaces (); i++) - { - for (uint32_t j = 0; j < GetNAddresses (i); j++) - { - Ipv4InterfaceAddress ipv4InAddr = GetAddress (i, j); - if (ipv4InAddr.GetLocal ().CombineMask(mask) == addr.CombineMask(mask) ) - { - return i; - } - } - } - // Mapping not found - NS_ASSERT_MSG (false, "Ipv4::GetInterfaceByAddress failed"); - return 0; -} - } // namespace ns3 diff --git a/src/node/ipv4.h b/src/node/ipv4.h index 95972770d..771c33130 100644 --- a/src/node/ipv4.h +++ b/src/node/ipv4.h @@ -21,19 +21,18 @@ #define IPV4_H #include -#include "ns3/ipv4-address.h" -#include "ns3/ipv4-interface-address.h" #include "ns3/object.h" +#include "ns3/socket.h" #include "ns3/callback.h" -#include "ipv4-route.h" +#include "ipv4-routing-protocol.h" +#include "ipv4-address.h" +#include "ipv4-interface-address.h" namespace ns3 { class Node; class NetDevice; class Packet; -class Ipv4Route; -class Ipv4Header; /** * \ingroup node @@ -41,129 +40,35 @@ class Ipv4Header; */ /** - * \ingroup ipv4 + * \brief Access to the Ipv4 forwarding table, interfaces, and configuration * - * \brief Base class for IPv4 routing protocols. - * - * This class represents the interface between the IPv4 routing core - * and a specific IPv4 routing protocol. The interface is - * asynchronous (callback based) in order to support reactive routing - * protocols (e.g. AODV). - */ -class Ipv4RoutingProtocol : public Object -{ -public: - // void (*RouteReply) (bool found, Ipv4Route route, Packet packet, Ipv4Header const &ipHeader); - - - /** - * \brief Callback to be invoked when route discovery is completed - * - * \param bool flag indicating whether a route was actually found; - * when this is false, the Ipv4Route parameter is ignored - * - * \param Ipv4Route the route found - * - * \param Packet the packet for which a route was requested; can be - * modified by the routing protocol - * - * \param Ipv4Header the IP header supplied to the route request - * method (possibly modified in case a new routing header is - * inserted and consequently the protocol type has to change). - * - */ - typedef Callback, const Ipv4Header&> RouteReplyCallback; - - /** - * \brief Request that a packet be routed. - * - * \param interface The interface index on which the packet was received. - * \param ipHeader IP header of the packet - * \param packet packet that is being sent or forwarded - * \param routeReply callback that will receive the route reply - * - * \returns true if the routing protocol should be able to get the - * route, false otherwise. - * - * This method is called whenever a node's IPv4 forwarding engine - * needs to lookup a route for a given packet and IP header. - * - * The routing protocol implementation may determine immediately it - * should not be handling this particular the route request. For - * instance, a routing protocol may decline to search for routes for - * certain classes of addresses, like link-local. In this case, - * RequestRoute() should return false and the routeReply callback - * must not be invoked. - * - * If the routing protocol implementation assumes that it can provide - * the requested route, then it should return true, and the - * routeReply callback must be invoked, either immediately before - * returning true (synchronously), or in the future (asynchronous). - * The routing protocol may use any information available in the IP - * header and packet as routing key, although most routing protocols - * use only the destination address (as given by - * ipHeader.GetDestination ()). The routing protocol is also - * allowed to add a new header to the packet, which will appear - * immediately after the IP header, although most routing do not - * insert any extra header. - * - * Multicast routing is expected to be supported in this method. If a - * multicast route is encountered, all routes to a given multicast - * destination will be serviced by cloning the packet and calling the - * route reply callback once for each outgoing interface in the route. - */ - virtual bool RequestRoute (uint32_t interface, - const Ipv4Header &ipHeader, - Ptr packet, - RouteReplyCallback routeReply) = 0; - -/** - * \brief Synchronously check to see if we can determine the interface index - * that will be used if a packet is sent to this destination. - * - * This method addresses a problem in the IP stack where a destination address - * must be present and checksummed into the IP header before the actual - * interface over which the packet is sent can be determined. The answer is - * to implement a known and intentional cross-layer violation. This is the - * endpoint of a call chain that started up quite high in the stack (sockets) - * and has found its way down to the Ipv4L3Protocol which is consulting the - * routing protocols for what they would do if presented with a packet of the - * given destination. - * - * Note that the a single interface index is returned. This means that if - * the destination address is a multicast, and an explicit route is present - * that includeds multiple output interfaces, that route cannot be used. + * This class defines the API to manipulate the following aspects of + * the Ipv4 implementation: + * -# set/get an Ipv4RoutingProtocol + * -# register a NetDevice for use by the Ipv4 layer (basically, to + * create Ipv4-related state such as addressing and neighbor cache that + * is associated with a NetDevice) + * -# manipulate the status of the NetDevice from the Ipv4 perspective, + * such as marking it as Up or Down, + * -# adding, deleting, and getting addresses associated to the Ipv4 + * interfaces. + * -# exporting Ipv4 configuration attributes * - * If there are multiple paths out of the node, the resolution is performed - * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more - * contextual information that is useful for making a determination. + * Each NetDevice has conceptually a single Ipv4 interface associated + * with it (the corresponding structure in the Linux Ipv4 implementation + * is struct in_device). Each interface may have one or more Ipv4 + * addresses associated with it. Each Ipv4 address may have different + * subnet mask, scope, etc., so all of this per-address information + * is stored in an Ipv4InterfaceAddress class (the corresponding + * structure in Linux is struct in_ifaddr) * - * \param destination The Ipv4Address if the destination of a hypothetical - * packet. This may be a multicast group address. - * \param interface A reference to the interface index over which a packet - * sent to this destination would be sent. - * \return Returns true if a route is found to the destination that involves - * a single output interface index, otherwise false. + * Ipv4 attributes such as whether IP forwarding is enabled and disabled + * are also stored in this class + * + * TO DO: Add API to allow access to the Ipv4 neighbor table * - * \see Ipv4StaticRouting * \see Ipv4RoutingProtocol - * \see Ipv4L3Protocol - */ - virtual bool RequestInterface (Ipv4Address destination, - uint32_t& interface) = 0; - - static const uint32_t INTERFACE_ANY = 0xffffffff; -}; - -/** - * \brief Access to the Ipv4 forwarding table and to the ipv4 interfaces - * - * This class allows you to create ipv4 interfaces based on a NetDevice. - * Multiple interfaces can be created for a single NetDevice, hence - * achieving multihoming. - * - * This class also allows you to control the content of the ipv4 - * forwarding table. + * \see Ipv4InterfaceAddress */ class Ipv4 : public Object { @@ -173,143 +78,27 @@ public: virtual ~Ipv4 (); /** - * \brief Register a new routing protocol to be used in this IPv4 stack + * \brief Register a new routing protocol to be used by this Ipv4 stack + * + * This call will replace any routing protocol that has been previously + * registered. If you want to add multiple routing protocols, you must + * add them to a Ipv4ListRoutingProtocol directly. * - * \param routingProtocol new routing protocol implementation object - * \param priority priority to give to this routing protocol. - * Values may range between -32768 and +32767. The priority 0 - * corresponds to static routing table lookups, higher values have - * more priority. The order by which routing protocols with the - * same priority value are consulted is undefined. + * \param routing smart pointer to Ipv4RoutingProtocol object */ - virtual void AddRoutingProtocol (Ptr routingProtocol, - int16_t priority) = 0; - - /** - * \param dest destination address - * \param nextHop address of next hop. - * \param interface interface of next hop. - * - * Add route to host dest through host nextHop - * on interface. - */ - virtual void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) = 0; - /** - * \param dest destination address - * \param interface of next hop - * - * add route to host dest on interface. - */ - virtual void AddHostRouteTo (Ipv4Address dest, - uint32_t interface) = 0; + virtual void SetRoutingProtocol (Ptr routingProtocol) = 0; /** - * \param network destination network - * \param networkMask netmask of destination network - * \param nextHop address of next hop - * \param interface interface of next hop + * \brief Get the routing protocol to be used by this Ipv4 stack * - * add route to network dest with netmask - * through host nextHop on interface + * \returns smart pointer to Ipv4RoutingProtocol object, or null pointer if none */ - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) = 0; + virtual Ptr GetRoutingProtocol (void) const = 0; /** - * \param network destination network - * \param networkMask netmask of destination network - * \param interface interface of next hop - * - * add route to network dest with netmask - * on interface - */ - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) = 0; - /** - * \param nextHop address of default next hop - * \param interface interface of default next hop. - * - * set the default route to host nextHop on - * interface. - */ - virtual void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) = 0; - - /** - * \returns the number of entries in the routing table. - */ - virtual uint32_t GetNRoutes (void) = 0; - - /** - * \param i index of route to return - * \returns the route whose index is i - */ - virtual Ipv4Route GetRoute (uint32_t i) = 0; - - /** - * \param i index of route to remove from routing table. - */ - virtual void RemoveRoute (uint32_t i) = 0; - - /** - * \brief Add a static multicast route for a given multicast source and - * group. - * - * \param origin The Ipv4 address of the multicast source. - * \param group The multicast group address. - * \param inputInterface The interface index over which the packet arrived. - * \param outputInterfaces The list of output interface indices over which - * the packet should be sent (excluding the inputInterface). - */ - virtual void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) = 0; - /** - * \brief Remove a static multicast route for a given multicast source and - * group. - * - * \param origin The Ipv4 address of the multicast source. - * \param group The multicast group address. - * \param inputInterface The interface index over which the packet arrived. - */ - virtual void RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface) = 0; - - /** - * \brief Set the default static multicast route. - * - * \param outputInterface The network output interface index over which - * packets without specific routes should be sent. - */ - virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0; - - /** - * \returns the number of entries in the multicast routing table. - */ - virtual uint32_t GetNMulticastRoutes (void) const = 0; - - /** - * \param i index of route to return - * \returns the route whose index is i - */ - virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const = 0; - - /** - * \param i index of route to remove from routing table. - */ - virtual void RemoveMulticastRoute (uint32_t i) = 0; - - /** - * \param device device to add to the list of ipv4 interfaces + * \param device device to add to the list of Ipv4 interfaces * which can be used as output interfaces during packet forwarding. - * \returns the index of the ipv4 interface added. + * \returns the index of the Ipv4 interface added. * * Once a device has been added, it can never be removed: if you want * to disable it, you can invoke Ipv4::SetDown which will @@ -323,73 +112,50 @@ public: virtual uint32_t GetNInterfaces (void) const = 0; /** - * \brief Find and return the interface ID of the interface that has been + * \brief Return the interface number of the interface that has been * assigned the specified IP address. - * \param addr The IP address assigned to the interface of interest. - * \returns The index of the ipv4 interface with the given address. * - * Each IP interface has an IP address associated with it. It is often - * useful to search the list of interfaces for one that corresponds to - * a known IP Address. This call takes an IP address as a parameter and - * returns the interface index of the first interface that has been assigned - * that address. If the address is not found, this function asserts. + * \param address The IP address being searched for + * \returns The interface number of the Ipv4 interface with the given + * address or -1 if not found. + * + * Each IP interface has one or more IP addresses associated with it. + * This method searches the list of interfaces for one that holds a + * particular address. This call takes an IP address as a parameter and + * returns the interface number of the first interface that has been assigned + * that address, or -1 if not found. There must be an exact match. */ - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0; + virtual int32_t GetInterfaceForAddress (Ipv4Address address) const = 0; /** - * \brief Find and return the interface ID of the interface that has been - * assigned the specified (masked) IP address. - * \param addr The IP address assigned to the interface of interest. - * \param mask The address mask to be used in address matching. - * \returns The index of the ipv4 interface with the given address. + * \brief Return the interface number of first interface found that + * has an Ipv4 address within the prefix specified by the input + * address and mask parameters * - * Each IP interface has an IP address associated with it. It is often - * useful to search the list of interfaces for one that corresponds to - * a known IP Address. This call takes an IP address and an IP address - * mask as parameters and returns the interface index of the first interface - * that matches the masked IP address. + * \param addr The IP address assigned to the interface of interest. + * \returns The interface number of the Ipv4 interface with the given + * address or -1 if not found. + * + * Each IP interface has one or more IP addresses associated with it. + * This method searches the list of interfaces for the first one found + * that holds an address that is included within the prefix + * formed by the input address and mask parameters. The value -1 is + * returned if no match is found. */ - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, + virtual int32_t GetInterfaceForPrefix (Ipv4Address address, Ipv4Mask mask) const = 0; /** - * \brief Find and return the interface ID of the interface that has been - * associated with the specified (masked) NetDevice - * \param nd The net device of the interface of interest. - * \returns The index of the ipv4 interface associated with the given net - * device or -1 if not found. - * - * Each IP interface is associated with a net device. It is often - * useful to search the list of interfaces for one that corresponds to - * a known net device. This call takes an smart pointer to a net device - * and returns the interface index of the first interface that matches the - * net device. + * \param interface The interface number of an Ipv4 interface. + * \returns The NetDevice associated with the Ipv4 interface number. */ - virtual int32_t FindInterfaceForDevice(Ptr nd) const = 0; + virtual Ptr GetNetDevice (uint32_t interface) = 0; /** - * \param i index of ipv4 interface - * \returns the NetDevice associated with the ipv4 interface index + * \param device The NetDevice for an Ipv4Interface + * \returns The interface number of an Ipv4 interface or -1 if not found. */ - virtual Ptr GetNetDevice (uint32_t i) = 0; - - /** - * \brief Join a multicast group for a given multicast source and - * group. - * - * \param origin The Ipv4 address of the multicast source. - * \param group The multicast group address. - */ - virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0; - - /** - * \brief Leave a multicast group for a given multicast source and - * group. - * - * \param origin The Ipv4 address of the multicast source. - * \param group The multicast group address. - */ - virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0; + virtual int32_t GetInterfaceForDevice (Ptr device) const = 0; /** * \param interface Interface number of an Ipv4 interface @@ -406,86 +172,61 @@ public: /** * \param interface Interface number of an Ipv4 interface - * \param addressIndex index of Ipv4InterfaceAddress + * \param addressIndex index of Ipv4InterfaceAddress * \returns the Ipv4InterfaceAddress associated to the interface and addresIndex */ virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0; /** - * \param i index of ipv4 interface + * \param interface The interface number of an Ipv4 interface * \param metric routing metric (cost) associated to the underlying - * ipv4 interface + * Ipv4 interface */ - virtual void SetMetric (uint32_t i, uint16_t metric) = 0; + virtual void SetMetric (uint32_t interface, uint16_t metric) = 0; /** - * \param i index of ipv4 interface + * \param interface The interface number of an Ipv4 interface * \returns routing metric (cost) associated to the underlying - * ipv4 interface + * Ipv4 interface */ - virtual uint16_t GetMetric (uint32_t i) const = 0; + virtual uint16_t GetMetric (uint32_t interface) const = 0; /** - * \param destination The IP address of a hypothetical destination. - * \returns The IP address assigned to the interface that will be used - * if we were to send a packet to destination. - * - * Note that the broadcast address for this interface may be fetched - * from the Ipv4Address object returned here using - * Ipv4Address::GetSubnetDirectedBroadcast(mask), where the mask for - * the interface may be retrived using Ipv4::GetNetworkMask(i). - */ - virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0; - - /** - * \param dest The IP address of a hypothetical destination. - * \param interface filled in with the interface index that will be used to - * send a packet to the hypothetical destination. - * \returns true if a single interface can be identified, false otherwise. - */ - virtual bool GetInterfaceForDestination (Ipv4Address dest, - uint32_t &interface) const = 0; - - /** - * \param i index of ipv4 interface + * \param interface Interface number of Ipv4 interface * \returns the Maximum Transmission Unit (in bytes) associated - * to the underlying ipv4 interface + * to the underlying Ipv4 interface */ - virtual uint16_t GetMtu (uint32_t i) const = 0; + virtual uint16_t GetMtu (uint32_t interface) const = 0; /** - * \param i index of ipv4 interface + * \param interface Interface number of Ipv4 interface * \returns true if the underlying interface is in the "up" state, * false otherwise. */ - virtual bool IsUp (uint32_t i) const = 0; + virtual bool IsUp (uint32_t interface) const = 0; /** - * \param i index of ipv4 interface + * \param i interface Interface number of Ipv4 interface * * Set the interface into the "up" state. In this state, it is - * considered valid during ipv4 forwarding. + * considered valid during Ipv4 forwarding. */ - virtual void SetUp (uint32_t i) = 0; + virtual void SetUp (uint32_t interface) = 0; /** - * \param i index of ipv4 interface + * \param interface Interface number of Ipv4 interface * * Set the interface into the "down" state. In this state, it is - * ignored during ipv4 forwarding. + * ignored during Ipv4 forwarding. */ - virtual void SetDown (uint32_t i) = 0; + virtual void SetDown (uint32_t interface) = 0; - /** - * \brief Convenience function to return the interface corresponding - * to the Ipv4Address provided - * - * \param addr Ipv4Address - * \param mask corresponding Ipv4Mask - * \returns interface corresponding to a/amask - */ - virtual uint32_t GetInterfaceByAddress (Ipv4Address addr, - Ipv4Mask mask = Ipv4Mask("255.255.255.255")); + static const uint32_t IF_ANY = 0xffffffff; + +private: + // Indirect the Ipv4 attributes through private pure virtual methods + virtual void SetIpForward (bool forward) = 0; + virtual bool GetIpForward (void) const = 0; }; } // namespace ns3 diff --git a/src/node/udp-socket.cc b/src/node/udp-socket.cc index 25ceacae6..c9f370662 100644 --- a/src/node/udp-socket.cc +++ b/src/node/udp-socket.cc @@ -21,6 +21,7 @@ #include "ns3/object.h" #include "ns3/log.h" #include "ns3/uinteger.h" +#include "ns3/integer.h" #include "ns3/boolean.h" #include "ns3/trace-source-accessor.h" #include "udp-socket.h" @@ -47,13 +48,25 @@ UdpSocket::GetTypeId (void) UintegerValue (0), MakeUintegerAccessor (&UdpSocket::GetIpTtl, &UdpSocket::SetIpTtl), - MakeUintegerChecker ()) + MakeUintegerChecker ()) .AddAttribute ("IpMulticastTtl", "socket-specific TTL for multicast IP packets (if non-zero)", UintegerValue (0), MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl, &UdpSocket::SetIpMulticastTtl), - MakeUintegerChecker ()) + MakeUintegerChecker ()) + .AddAttribute ("IpMulticastIf", + "interface index for outgoing multicast on this socket; -1 indicates to use default interface", + IntegerValue (-1), + MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl, + &UdpSocket::SetIpMulticastTtl), + MakeIntegerChecker ()) + .AddAttribute ("IpMulticastLoop", + "whether outgoing multicast sent also to loopback interface", + BooleanValue (false), + MakeUintegerAccessor (&UdpSocket::GetIpMulticastLoop, + &UdpSocket::SetIpMulticastLoop), + MakeBooleanChecker ()) .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.", BooleanValue (false), MakeBooleanAccessor (&UdpSocket::SetMtuDiscover, diff --git a/src/node/udp-socket.h b/src/node/udp-socket.h index 4d44549ed..ed6d412da 100644 --- a/src/node/udp-socket.h +++ b/src/node/udp-socket.h @@ -40,7 +40,8 @@ class Packet; * \brief (abstract) base class of all UdpSockets * * This class exists solely for hosting UdpSocket attributes that can - * be reused across different implementations. + * be reused across different implementations, and for declaring + * UDP-specific multicast API. */ class UdpSocket : public Socket { @@ -50,14 +51,64 @@ public: UdpSocket (void); virtual ~UdpSocket (void); + /** + * \brief Corresponds to socket option MCAST_JOIN_GROUP + * + * \param interface interface number, or 0 + * \param groupAddress multicast group address + * \returns on success, zero is returned. On error, -1 is returned, + * and errno is set appropriately + * + * Enable reception of multicast datagrams for this socket on the + * interface number specified. If zero is specified as + * the interface, then a single local interface is chosen by + * system. In the future, this function will generate trigger IGMP + * joins as necessary when IGMP is implemented, but for now, this + * just enables multicast datagram reception in the system if not already + * enabled for this interface/groupAddress combination. + * + * \attention IGMP is not yet implemented in ns-3 + * + * This function may be called repeatedly on a given socket but each + * join must be for a different multicast address, or for the same + * multicast address but on a different interface from previous joins. + * This enables host multihoming, and the ability to join the same + * group on different interfaces. + */ + virtual int MulticastJoinGroup (uint32_t interface, const Address &groupAddress) = 0; + + /** + * \brief Corresponds to socket option MCAST_LEAVE_GROUP + * + * \param interface interface number, or 0 + * \param groupAddress multicast group address + * \returns on success, zero is returned. On error, -1 is returned, + * and errno is set appropriately + * + * Disable reception of multicast datagrams for this socket on the + * interface number specified. If zero is specified as + * the interfaceIndex, then a single local interface is chosen by + * system. In the future, this function will generate trigger IGMP + * leaves as necessary when IGMP is implemented, but for now, this + * just disables multicast datagram reception in the system if this + * socket is the last for this interface/groupAddress combination. + * + * \attention IGMP is not yet implemented in ns-3 + */ + virtual int MulticastLeaveGroup (uint32_t interface, const Address &groupAddress) = 0; + private: // Indirect the attribute setting and getting through private virtual methods virtual void SetRcvBufSize (uint32_t size) = 0; virtual uint32_t GetRcvBufSize (void) const = 0; - virtual void SetIpTtl (uint32_t ipTtl) = 0; - virtual uint32_t GetIpTtl (void) const = 0; - virtual void SetIpMulticastTtl (uint32_t ipTtl) = 0; - virtual uint32_t GetIpMulticastTtl (void) const = 0; + virtual void SetIpTtl (uint8_t ipTtl) = 0; + virtual uint8_t GetIpTtl (void) const = 0; + virtual void SetIpMulticastTtl (uint8_t ipTtl) = 0; + virtual uint8_t GetIpMulticastTtl (void) const = 0; + virtual void SetIpMulticastIf (int32_t ipIf) = 0; + virtual int32_t GetIpMulticastIf (void) const = 0; + virtual void SetIpMulticastLoop (bool loop) = 0; + virtual bool GetIpMulticastLoop (void) const = 0; virtual void SetMtuDiscover (bool discover) = 0; virtual bool GetMtuDiscover (void) const = 0; }; diff --git a/src/node/wscript b/src/node/wscript index 8ed3c8c64..1cb0b9f9c 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -19,6 +19,10 @@ def build(bld): 'ethernet-header.cc', 'ethernet-trailer.cc', 'ipv4-route.cc', + 'ipv4-routing-protocol.cc', + 'ipv4-list-routing.cc', + 'ipv4-static-routing.cc', + 'ipv4-routing-table-entry.cc', 'queue.cc', 'drop-tail-queue.cc', 'channel.cc', @@ -52,11 +56,16 @@ def build(bld): 'packet-socket-address.h', 'node.h', 'ipv4-address.h', + 'ipv4-interface-address.h', 'ipv4-address-generator.h', 'ipv4-header.h', 'net-device.h', 'address-utils.h', 'ipv4-route.h', + 'ipv4-routing-protocol.h', + 'ipv4-list-routing.h', + 'ipv4-static-routing.h', + 'ipv4-routing-table-entry.h', 'queue.h', 'drop-tail-queue.h', 'llc-snap-header.h', diff --git a/src/routing/global-routing/global-route-manager-impl.cc b/src/routing/global-routing/global-route-manager-impl.cc index 2735d5ecf..a5e29a059 100644 --- a/src/routing/global-routing/global-route-manager-impl.cc +++ b/src/routing/global-routing/global-route-manager-impl.cc @@ -31,6 +31,8 @@ #include "ns3/node-list.h" #include "ns3/ipv4.h" #include "ns3/ipv4-global-routing.h" +#include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-list-routing.h" #include "global-router-interface.h" #include "global-route-manager-impl.h" #include "candidate-queue.h" @@ -154,7 +156,7 @@ SPFVertex::GetDistanceFromRoot (void) const } void -SPFVertex::SetOutgoingInterfaceId (uint32_t id) +SPFVertex::SetOutgoingInterfaceId (int32_t id) { NS_LOG_FUNCTION (id); m_rootOif = id; @@ -414,15 +416,22 @@ GlobalRouteManagerImpl::SelectRouterNodes () NS_LOG_LOGIC ("Adding GlobalRouting Protocol to node " << node->GetId ()); Ptr globalRouting = CreateObject (); + globalRouting->SetNode (node); + // Here, we check whether there is an existing Ipv4RoutingProtocol object + // to add this protocol to. + Ptr ipv4 = node->GetObject (); + NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): GetObject for interface failed"); + // Now, we add this to an Ipv4ListRouting object. + // XXX in the future, we may want to allow this to be added to Ipv4 + // directly + Ptr ipv4ListRouting = DynamicCast (ipv4->GetRoutingProtocol ()); + NS_ASSERT_MSG (ipv4ListRouting, "GlobalRouteManagerImpl::SelectRouterNodes (): Ipv4ListRouting not found"); // This is the object that will keep the global routes. We insert it // at slightly higher priority than static routing (which is at zero). // This means that global routes (e.g. host routes) will be consulted // before static routes - Ptr ipv4 = node->GetObject (); - NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): " - "GetObject for interface failed"); // XXX make the below priority value an attribute - ipv4->AddRoutingProtocol (globalRouting, 3); + ipv4ListRouting->AddRoutingProtocol (globalRouting, 3); // Locally cache the globalRouting pointer; we'll need it later // when we add routes AddGlobalRoutingProtocol (node->GetId (), globalRouting); @@ -451,8 +460,10 @@ GlobalRouteManagerImpl::SelectRouterNodes (NodeContainer c) Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): " "GetObject for interface failed"); + Ptr ipv4ListRouting = DynamicCast (ipv4->GetRoutingProtocol ()); + NS_ASSERT_MSG (ipv4ListRouting, "GlobalRouteManagerImpl::SelectRouterNodes (): Ipv4ListRouting not found"); // XXX make the below priority value an attribute - ipv4->AddRoutingProtocol (globalRouting, 3); + ipv4ListRouting->AddRoutingProtocol (globalRouting, 3); // Locally cache the globalRouting pointer; we'll need it later // when we add routes AddGlobalRoutingProtocol (node->GetId (), globalRouting); @@ -1344,16 +1355,32 @@ GlobalRouteManagerImpl::SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* // Ptr gr = GetGlobalRoutingProtocol (node->GetId ()); NS_ASSERT (gr); - gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ()); + if (v->GetOutgoingInterfaceId () >= 0) + { + gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ()); + NS_LOG_LOGIC ("Node " << node->GetId () << + " add network route to " << tempip << + " using next hop " << v->GetNextHop () << + " via interface " << v->GetOutgoingInterfaceId ()); + } + else + { + NS_LOG_LOGIC ("Node " << node->GetId () << + " NOT able to add network route to " << tempip << + " using next hop " << v->GetNextHop () << + " since outgoing interface id is negative"); + } return; } // if } // for } // -// Return the interface index corresponding to a given IP address -// This is a wrapper around GetInterfaceByIpv4Address(), but we first +// Return the interface number corresponding to a given IP address and mask +// This is a wrapper around GetInterfaceForPrefix(), but we first // have to find the right node pointer to pass to that function. +// If no such interface is found, return -1 (note: unit test framework +// for routing assumes -1 to be a legal return value) // uint32_t GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask) @@ -1400,19 +1427,29 @@ GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask) Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): " - "QI for interface failed"); + "GetObject for interface failed"); // // Look through the interfaces on this node for one that has the IP address // we're looking for. If we find one, return the corresponding interface -// index. +// index, or -1 if not found. // - return (ipv4->GetInterfaceByAddress (a, amask) ); + int32_t interface = ipv4->GetInterfaceForPrefix (a, amask); + +#if 0 + if (interface < 0) + { + NS_FATAL_ERROR ("GlobalRouteManagerImpl::FindOutgoingInterfaceId(): " + "Expected an interface associated with address a:" << a); + } +#endif + return interface; } } // // Couldn't find it. // - return 0; + NS_LOG_LOGIC ("FindOutgoingInterfaceId():Can't find root node " << routerId); + return -1; } // @@ -1459,8 +1496,8 @@ GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v) Ptr node = *i; // // The router ID is accessible through the GlobalRouter interface, so we need -// to QI for that interface. If there's no GlobalRouter interface, the node -// in question cannot be the router we want, so we continue. +// to GetObject for that interface. If there's no GlobalRouter interface, +// the node in question cannot be the router we want, so we continue. // Ptr rtr = node->GetObject (); @@ -1482,14 +1519,14 @@ GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v) { NS_LOG_LOGIC ("Setting routes for node " << node->GetId ()); // -// Routing information is updated using the Ipv4 interface. We need to QI -// for that interface. If the node is acting as an IP version 4 router, it -// should absolutely have an Ipv4 interface. +// Routing information is updated using the Ipv4 interface. We need to +// GetObject for that interface. If the node is acting as an IP version 4 +// router, it should absolutely have an Ipv4 interface. // Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SPFIntraAddRouter (): " - "QI for interface failed"); + "GetObject for interface failed"); // // Get the Global Router Link State Advertisement from the vertex we're // adding the routes to. The LSA will have a number of attached Global Router @@ -1542,8 +1579,22 @@ GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v) // Ptr gr = GetGlobalRoutingProtocol (node->GetId ()); NS_ASSERT (gr); - gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (), - v->GetOutgoingInterfaceId ()); + if (v->GetOutgoingInterfaceId () >= 0) + { + gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (), + v->GetOutgoingInterfaceId ()); + NS_LOG_LOGIC ("Node " << node->GetId () << + " adding host route to " << lr->GetLinkData () << + " using next hop " << v->GetNextHop () << + " and outgoing interface " << v->GetOutgoingInterfaceId ()); + } + else + { + NS_LOG_LOGIC ("Node " << node->GetId () << + " NOT able to add host route to " << lr->GetLinkData () << + " using next hop " << v->GetNextHop () << + " since outgoing interface id is negative"); + } } // // Done adding the routes for the selected node. @@ -1580,8 +1631,8 @@ GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v) Ptr node = *i; // // The router ID is accessible through the GlobalRouter interface, so we need -// to QI for that interface. If there's no GlobalRouter interface, the node -// in question cannot be the router we want, so we continue. +// to GetObject for that interface. If there's no GlobalRouter interface, +// the node in question cannot be the router we want, so we continue. // Ptr rtr = node->GetObject (); @@ -1603,14 +1654,14 @@ GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v) { NS_LOG_LOGIC ("setting routes for node " << node->GetId ()); // -// Routing information is updated using the Ipv4 interface. We need to QI -// for that interface. If the node is acting as an IP version 4 router, it -// should absolutely have an Ipv4 interface. +// Routing information is updated using the Ipv4 interface. We need to +// GetObject for that interface. If the node is acting as an IP version 4 +// router, it should absolutely have an Ipv4 interface. // Ptr ipv4 = node->GetObject (); NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SPFIntraAddTransit (): " - "QI for interface failed"); + "GetObject for interface failed"); // // Get the Global Router Link State Advertisement from the vertex we're // adding the routes to. The LSA will have a number of attached Global Router @@ -1626,12 +1677,22 @@ GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v) tempip = tempip.CombineMask (tempmask); Ptr gr = GetGlobalRoutingProtocol (node->GetId ()); NS_ASSERT (gr); - gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), - v->GetOutgoingInterfaceId ()); - NS_LOG_LOGIC ("Node " << node->GetId () << - " add network route to " << tempip << - " using next hop " << v->GetNextHop () << - " via interface " << v->GetOutgoingInterfaceId ()); + if (v->GetOutgoingInterfaceId () >= 0) + { + gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), + v->GetOutgoingInterfaceId ()); + NS_LOG_LOGIC ("Node " << node->GetId () << + " add network route to " << tempip << + " using next hop " << v->GetNextHop () << + " via interface " << v->GetOutgoingInterfaceId ()); + } + else + { + NS_LOG_LOGIC ("Node " << node->GetId () << + " NOT able to add network route to " << tempip << + " using next hop " << v->GetNextHop () << + " since outgoing interface id is negative"); + } } } } diff --git a/src/routing/global-routing/global-route-manager-impl.h b/src/routing/global-routing/global-route-manager-impl.h index 65a79800d..2ae8406e0 100644 --- a/src/routing/global-routing/global-route-manager-impl.h +++ b/src/routing/global-routing/global-route-manager-impl.h @@ -337,7 +337,7 @@ public: * @param id The interface index to use when forwarding packets to the host or * network represented by "this" SPFVertex. */ - void SetOutgoingInterfaceId (uint32_t id); + void SetOutgoingInterfaceId (int32_t id); /** * @brief Get the IP address that should be used to begin forwarding packets @@ -569,7 +569,7 @@ private: Ipv4Address m_vertexId; GlobalRoutingLSA* m_lsa; uint32_t m_distanceFromRoot; - uint32_t m_rootOif; + int32_t m_rootOif; Ipv4Address m_nextHop; SPFVertex* m_parent; typedef std::list ListOfSPFVertex_t; diff --git a/src/routing/olsr/olsr-routing-protocol.cc b/src/routing/olsr/olsr-routing-protocol.cc index 36cff48e9..6eb0034bd 100644 --- a/src/routing/olsr/olsr-routing-protocol.cc +++ b/src/routing/olsr/olsr-routing-protocol.cc @@ -40,6 +40,8 @@ #include "ns3/log.h" #include "ns3/random-variable.h" #include "ns3/inet-socket-address.h" +#include "ns3/ipv4-routing-protocol.h" +#include "ns3/ipv4-route.h" #include "ns3/boolean.h" #include "ns3/uinteger.h" #include "ns3/enum.h" @@ -722,7 +724,7 @@ RoutingProtocol::MprComputation() os << "]"; NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ()); } -#endif +#endif //NS3_LOG_ENABLE m_state.SetMprSet (mprSet); } @@ -1024,7 +1026,7 @@ RoutingProtocol::ProcessHello (const olsr::MessageHeader &msg, } NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress); } -#endif +#endif // NS3_LOG_ENABLE PopulateNeighborSet (msg, hello); PopulateTwoHopNeighborSet (msg, hello); @@ -1041,7 +1043,7 @@ RoutingProtocol::ProcessHello (const olsr::MessageHeader &msg, } NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress); } -#endif +#endif // NS3_LOG_ENABLE MprComputation (); PopulateMprSelectorSet (msg, hello); @@ -1139,7 +1141,7 @@ RoutingProtocol::ProcessTc (const olsr::MessageHeader &msg, } NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress); } -#endif +#endif // NS3_LOG_ENABLE } /// @@ -1631,7 +1633,7 @@ RoutingProtocol::LinkSensing (const olsr::MessageHeader &msg, << lt << " (" << linkTypeName << ") and Neighbor Type " << nt << " (" << neighborTypeName << ")"); -#endif +#endif // NS3_LOG_ENABLE // We must not process invalid advertised links if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) || @@ -1755,7 +1757,7 @@ RoutingProtocol::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg, : "(invalid value)"); NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType=" << neighborType << " (" << neighborTypeName << ")"); -#endif +#endif // NS3_LOG_ENABLE for (std::vector::const_iterator nb2hop_addr_iter = linkMessage->neighborInterfaceAddresses.begin (); @@ -2038,7 +2040,7 @@ RoutingProtocol::LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness) { #ifdef NS3_LOG_ENABLE int statusBefore = nb_tuple->status; -#endif +#endif // NS3_LOG_ENABLE if (tuple.symTime >= Simulator::Now ()) { nb_tuple->status = NeighborTuple::STATUS_SYM; @@ -2547,65 +2549,105 @@ RoutingProtocol::FindSendEntry (RoutingTableEntry const &entry, return true; } - -bool -RoutingProtocol::RequestRoute (uint32_t ifIndex, - const Ipv4Header &ipHeader, - Ptr packet, - RouteReplyCallback routeReply) -{ +Ptr +RoutingProtocol::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject ()->GetId() << " " << header.GetDestination () << " " << oif); + // TBD: oif is unused; can be used to restrict the outgoing interface + // of the found route if application bound to a source interface + Ptr rtentry; RoutingTableEntry entry1, entry2; - if (Lookup (ipHeader.GetDestination (), entry1)) + if (Lookup (header.GetDestination (), entry1) != 0) { + bool foundSendEntry = FindSendEntry (entry1, entry2); + if (!foundSendEntry) + { + NS_FATAL_ERROR ("FindSendEntry failure"); + } + rtentry = Create (); + rtentry->SetDestination (header.GetDestination ()); + uint32_t interfaceIdx = entry2.interface; + // the source address is the interface address that matches + // the destination address (when multiple are present on the + // outgoing interface, one is selected via scoping rules) + NS_ASSERT (m_ipv4); + uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceIdx); + NS_ASSERT (numOifAddresses > 0); + Ipv4InterfaceAddress ifAddr; + if (numOifAddresses == 1) { + ifAddr = m_ipv4->GetAddress (interfaceIdx, 0); + } else { + NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and OLSR"); + } + rtentry->SetSource (ifAddr.GetLocal ()); + rtentry->SetGateway (entry2.nextAddr); + rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx)); + sockerr = Socket::ERROR_NOTERROR; + NS_LOG_DEBUG ("Olsr node " << m_mainAddress + << ": RouteRequest for dest=" << header.GetDestination () + << " --> nextHop=" << entry2.nextAddr + << " interface=" << entry2.interface); NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination () << " via nh " << rtentry->GetGateway () << " with source addr " << rtentry->GetSource () << " and output dev " << rtentry->GetOutputDevice()); + } + else + { + sockerr = Socket::ERROR_NOROUTETOHOST; + } + return rtentry; +} + +bool RoutingProtocol::RouteInput (Ptr p, + const Ipv4Header &header, Ptr idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject ()->GetId() << " " << header.GetDestination ()); + + Ptr rtentry; + RoutingTableEntry entry1, entry2; + if (Lookup (header.GetDestination (), entry1)) + { bool foundSendEntry = FindSendEntry (entry1, entry2); if (!foundSendEntry) NS_FATAL_ERROR ("FindSendEntry failure"); - - Ipv4Route route = Ipv4Route::CreateHostRouteTo - (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface); - + rtentry = Create (); + rtentry->SetDestination (header.GetDestination ()); + uint32_t interfaceIdx = entry2.interface; + // the source address is the interface address that matches + // the destination address (when multiple are present on the + // outgoing interface, one is selected via scoping rules) + NS_ASSERT (m_ipv4); + uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceIdx); + NS_ASSERT (numOifAddresses > 0); + Ipv4InterfaceAddress ifAddr; + if (numOifAddresses == 1) { + ifAddr = m_ipv4->GetAddress (interfaceIdx, 0); + } else { + NS_FATAL_ERROR ("XXX Not implemented yet: IP aliasing and OLSR"); + } + rtentry->SetSource (ifAddr.GetLocal ()); + rtentry->SetGateway (entry2.nextAddr); + rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx)); + NS_LOG_DEBUG ("Olsr node " << m_mainAddress - << ": RouteRequest for dest=" << ipHeader.GetDestination () - << " --> nestHop=" << entry2.nextAddr + << ": RouteRequest for dest=" << header.GetDestination () + << " --> nextHop=" << entry2.nextAddr << " interface=" << entry2.interface); - routeReply (true, route, packet, ipHeader); + ucb (rtentry, p, header); return true; } else { #ifdef NS3_LOG_ENABLE - NS_LOG_DEBUG ("Olsr node " << m_mainAddress - << ": RouteRequest for dest=" << ipHeader.GetDestination () - << " --> NOT FOUND; ** Dumping routing table..."); - for (std::map::const_iterator iter = m_table.begin (); + NS_LOG_DEBUG ("Olsr node " << m_mainAddress + << ": RouteRequest for dest=" << header.GetDestination () + << " --> NOT FOUND; ** Dumping routing table..."); for (std::map::const_iterator iter = m_table.begin (); iter != m_table.end (); iter++) - { - NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr + { NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr << " via interface " << iter->second.interface); } - + NS_LOG_DEBUG ("** Routing table dump end."); -#endif - return false; - } -} - -bool -RoutingProtocol::RequestInterface (Ipv4Address destination, - uint32_t& ifIndex) -{ - RoutingTableEntry entry1, entry2; - if (Lookup (destination, entry1)) - { - bool foundSendEntry = FindSendEntry (entry1, entry2); - if (!foundSendEntry) - NS_FATAL_ERROR ("FindSendEntry failure"); - ifIndex = entry2.interface; - return true; - } - else - { +#endif // NS3_LOG_ENABLE return false; } } diff --git a/src/routing/olsr/olsr-routing-protocol.h b/src/routing/olsr/olsr-routing-protocol.h index 0cf742789..0724a2b95 100644 --- a/src/routing/olsr/olsr-routing-protocol.h +++ b/src/routing/olsr/olsr-routing-protocol.h @@ -121,13 +121,10 @@ private: RoutingTableEntry &outEntry) const; // From Ipv4RoutingProtocol - virtual bool RequestRoute (uint32_t ifIndex, - const Ipv4Header &ipHeader, - Ptr packet, - RouteReplyCallback routeReply); - virtual bool RequestInterface (Ipv4Address destination, - uint32_t& ifIndex); - + virtual Ptr RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb); void DoDispose (); diff --git a/utils/python-unit-tests.py b/utils/python-unit-tests.py index a08f668fe..0d99c6a17 100644 --- a/utils/python-unit-tests.py +++ b/utils/python-unit-tests.py @@ -62,7 +62,8 @@ class TestSimulator(unittest.TestCase): def testSocket(self): node = ns3.Node() - ns3.AddInternetStack(node) + internet = ns3.InternetStackHelper() + internet.Install(node) self._received_packet = None def rx_callback(socket):