# HG changeset patch # User Mathieu Lacage # Date 1213051222 25200 # Node ID 8c0ab08144e69a3ba502481d1c12cf54e18caddc # Parent 43b3f8ecd86dd83799f84c7a430b32552a98aa38 bug 186: internet-node directory must be renamed to internet-stack diff -r 43b3f8ecd86d -r 8c0ab08144e6 doc/modules --- a/doc/modules Mon Jun 09 11:39:29 2008 -0700 +++ b/doc/modules Mon Jun 09 15:40:22 2008 -0700 @@ -42,13 +42,12 @@ * * @defgroup devices Devices * - * @defgroup internetNode InternetNode + * @defgroup internetStack InternetStack * - * The "internet-node" module contains a set of classes which implement the - * APIs defined in the "node" module: - * - an Ipv4/Udp stack with socket support + * The "internet-stack" module contains: + * - an Ipv4 stack * - an ARP module - * - an InternetNode class which is a Node subclass. + * - a UDP and a TCP implementation * * @defgroup helper Helpers * diff -r 43b3f8ecd86d -r 8c0ab08144e6 examples/wscript --- a/examples/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/examples/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -3,51 +3,51 @@ def build(bld): obj = bld.create_ns3_program('mixed-wireless', - ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-node']) + ['core', 'simulator', 'mobility', 'wifi', 'point-to-point', 'internet-stack']) obj.source = 'mixed-wireless.cc' obj = bld.create_ns3_program('simple-global-routing', - ['point-to-point', 'internet-node', 'global-routing']) + ['point-to-point', 'internet-stack', 'global-routing']) obj.source = 'simple-global-routing.cc' obj = bld.create_ns3_program('simple-alternate-routing', - ['point-to-point', 'internet-node', 'global-routing']) + ['point-to-point', 'internet-stack', 'global-routing']) obj.source = 'simple-alternate-routing.cc' obj = bld.create_ns3_program('simple-error-model', - ['point-to-point', 'internet-node']) + ['point-to-point', 'internet-stack']) obj.source = 'simple-error-model.cc' obj = bld.create_ns3_program('csma-one-subnet', - ['csma', 'internet-node']) + ['csma', 'internet-stack']) obj.source = 'csma-one-subnet.cc' obj = bld.create_ns3_program('udp-echo', - ['csma', 'internet-node']) + ['csma', 'internet-stack']) obj.source = 'udp-echo.cc' obj = bld.create_ns3_program('csma-broadcast', - ['csma', 'internet-node']) + ['csma', 'internet-stack']) obj.source = 'csma-broadcast.cc' obj = bld.create_ns3_program('csma-packet-socket', - ['csma', 'internet-node']) + ['csma', 'internet-stack']) obj.source = 'csma-packet-socket.cc' obj = bld.create_ns3_program('csma-multicast', - ['csma', 'internet-node']) + ['csma', 'internet-stack']) obj.source = 'csma-multicast.cc' obj = bld.create_ns3_program( 'mixed-global-routing', - ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd']) + ['point-to-point', 'internet-stack', 'global-routing' , 'csma-cd']) obj.source = 'mixed-global-routing.cc' obj = bld.create_ns3_program('simple-point-to-point-olsr', - ['point-to-point', 'internet-node', 'olsr']) + ['point-to-point', 'internet-stack', 'olsr']) obj.source = 'simple-point-to-point-olsr.cc' obj = bld.create_ns3_program('tcp-large-transfer', - ['point-to-point', 'internet-node']) + ['point-to-point', 'internet-stack']) obj.source = 'tcp-large-transfer.cc' obj = bld.create_ns3_program('wifi-adhoc', diff -r 43b3f8ecd86d -r 8c0ab08144e6 samples/wscript --- a/samples/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/samples/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -20,11 +20,11 @@ obj.source = 'main-test.cc' obj = bld.create_ns3_program('main-simple', - ['node', 'internet-node', 'onoff']) + ['node', 'internet-stack', 'onoff']) obj.source = 'main-simple.cc' obj = bld.create_ns3_program('main-grid-topology', - ['core', 'simulator', 'mobility', 'internet-node']) + ['core', 'simulator', 'mobility', 'internet-stack']) obj.source = 'main-grid-topology.cc' obj = bld.create_ns3_program('main-random-topology', diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/applications/udp-echo/wscript --- a/src/applications/udp-echo/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/src/applications/udp-echo/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - module = bld.create_ns3_module('udp-echo', ['internet-node']) + module = bld.create_ns3_module('udp-echo', ['internet-stack']) module.source = [ 'udp-echo-client.cc', 'udp-echo-server.cc', diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/helper/wscript --- a/src/helper/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/src/helper/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - helper = bld.create_ns3_module('helper', ['internet-node', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo']) + helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo']) helper.source = [ 'node-container.cc', 'net-device-container.cc', diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-cache.cc --- a/src/internet-node/arp-cache.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,287 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2006 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 "ns3/assert.h" -#include "ns3/packet.h" -#include "ns3/simulator.h" -#include "ns3/uinteger.h" -#include "ns3/log.h" - -#include "arp-cache.h" -#include "arp-header.h" -#include "ipv4-interface.h" - -NS_LOG_COMPONENT_DEFINE ("ArpCache"); - -namespace ns3 { - -TypeId -ArpCache::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::ArpCache") - .SetParent () - .AddAttribute ("AliveTimeout", - "When this timeout expires, the matching cache entry needs refreshing", - TimeValue (Seconds (120)), - MakeTimeAccessor (&ArpCache::m_aliveTimeout), - MakeTimeChecker ()) - .AddAttribute ("DeadTimeout", - "When this timeout expires, a new attempt to resolve the matching entry is made", - TimeValue (Seconds (100)), - MakeTimeAccessor (&ArpCache::m_deadTimeout), - MakeTimeChecker ()) - .AddAttribute ("WaitReplyTimeout", - "When this timeout expires, the matching cache entry is marked dead", - TimeValue (Seconds (1)), - MakeTimeAccessor (&ArpCache::m_waitReplyTimeout), - MakeTimeChecker ()) - .AddAttribute ("PendingQueueSize", - "The size of the queue for packets pending an arp reply.", - UintegerValue (3), - MakeUintegerAccessor (&ArpCache::m_pendingQueueSize), - MakeUintegerChecker ()) - ; - return tid; -} - -ArpCache::ArpCache () - : m_device (0), - m_interface (0) -{ - NS_LOG_FUNCTION (this); -} - -ArpCache::~ArpCache () -{ - NS_LOG_FUNCTION (this); -} - -void -ArpCache::DoDispose (void) -{ - NS_LOG_FUNCTION (this); - Flush (); - m_device = 0; - m_interface = 0; - Object::DoDispose (); -} - -void -ArpCache::SetDevice (Ptr device, Ptr interface) -{ - m_device = device; - m_interface = interface; -} - -Ptr -ArpCache::GetDevice (void) const -{ - return m_device; -} - -Ptr -ArpCache::GetInterface (void) const -{ - return m_interface; -} - -void -ArpCache::SetAliveTimeout (Time aliveTimeout) -{ - m_aliveTimeout = aliveTimeout; -} -void -ArpCache::SetDeadTimeout (Time deadTimeout) -{ - m_deadTimeout = deadTimeout; -} -void -ArpCache::SetWaitReplyTimeout (Time waitReplyTimeout) -{ - m_waitReplyTimeout = waitReplyTimeout; -} - -Time -ArpCache::GetAliveTimeout (void) const -{ - return m_aliveTimeout; -} -Time -ArpCache::GetDeadTimeout (void) const -{ - return m_deadTimeout; -} -Time -ArpCache::GetWaitReplyTimeout (void) const -{ - return m_waitReplyTimeout; -} - -void -ArpCache::Flush (void) -{ - for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++) - { - delete (*i).second; - } - m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ()); -} - -ArpCache::Entry * -ArpCache::Lookup (Ipv4Address to) -{ - if (m_arpCache.find (to) != m_arpCache.end ()) - { - ArpCache::Entry *entry = m_arpCache[to]; - return entry; - } - return 0; -} - -ArpCache::Entry * -ArpCache::Add (Ipv4Address to) -{ - NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ()); - - ArpCache::Entry *entry = new ArpCache::Entry (this); - m_arpCache[to] = entry; - return entry; -} - -ArpCache::Entry::Entry (ArpCache *arp) - : m_arp (arp), - m_state (ALIVE) -{} - - -bool -ArpCache::Entry::IsDead (void) -{ - return (m_state == DEAD)?true:false; -} -bool -ArpCache::Entry::IsAlive (void) -{ - return (m_state == ALIVE)?true:false; -} -bool -ArpCache::Entry::IsWaitReply (void) -{ - return (m_state == WAIT_REPLY)?true:false; -} - - -void -ArpCache::Entry::MarkDead (void) -{ - m_state = DEAD; - UpdateSeen (); -} -void -ArpCache::Entry::MarkAlive (Address macAddress) -{ - NS_ASSERT (m_state == WAIT_REPLY); - m_macAddress = macAddress; - m_state = ALIVE; - UpdateSeen (); -} - -bool -ArpCache::Entry::UpdateWaitReply (Ptr waiting) -{ - NS_ASSERT (m_state == WAIT_REPLY); - /* We are already waiting for an answer so - * we dump the previously waiting packet and - * replace it with this one. - */ - if (m_pending.size () >= m_arp->m_pendingQueueSize) - { - return false; - } - m_pending.push_back (waiting); - return true; -} -void -ArpCache::Entry::MarkWaitReply (Ptr waiting) -{ - NS_ASSERT (m_state == ALIVE || m_state == DEAD); - NS_ASSERT (m_pending.empty ()); - m_state = WAIT_REPLY; - m_pending.push_back (waiting); - UpdateSeen (); -} - -Address -ArpCache::Entry::GetMacAddress (void) -{ - NS_ASSERT (m_state == ALIVE); - return m_macAddress; -} -bool -ArpCache::Entry::IsExpired (void) -{ - Time timeout; - switch (m_state) { - case ArpCache::Entry::WAIT_REPLY: - timeout = m_arp->GetWaitReplyTimeout (); - break; - case ArpCache::Entry::DEAD: - timeout = m_arp->GetDeadTimeout (); - break; - case ArpCache::Entry::ALIVE: - timeout = m_arp->GetAliveTimeout (); - break; - default: - NS_ASSERT (false); - timeout = Seconds (0); - /* NOTREACHED */ - break; - } - Time delta = Simulator::Now () - m_lastSeen; - if (delta >= timeout) - { - return true; - } - else - { - return false; - } -} -Ptr -ArpCache::Entry::DequeuePending (void) -{ - if (m_pending.empty ()) - { - return 0; - } - else - { - Ptr p = m_pending.front (); - m_pending.pop_front (); - return p; - } -} -void -ArpCache::Entry::UpdateSeen (void) -{ - m_lastSeen = Simulator::Now (); -} - -} // namespace ns3 - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-cache.h --- a/src/internet-node/arp-cache.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2006 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 ARP_CACHE_H -#define ARP_CACHE_H - -#include -#include -#include "ns3/packet.h" -#include "ns3/nstime.h" -#include "ns3/net-device.h" -#include "ns3/ipv4-address.h" -#include "ns3/address.h" -#include "ns3/ptr.h" -#include "ns3/object.h" -#include "sgi-hashmap.h" - -namespace ns3 { - -class NetDevice; -class Ipv4Interface; - -/** - * \brief An ARP cache - * - * A cached lookup table for translating layer 3 addresses to layer 2. - * This implementation does lookups from IPv4 to a MAC address - */ -class ArpCache : public Object -{ -public: - static TypeId GetTypeId (void); - class Entry; - ArpCache (); - ~ArpCache (); - - /** - * \param device The hardware NetDevice associated with this ARP chache - * \param interface the Ipv4Interface associated with this ARP chache - */ - void SetDevice (Ptr device, Ptr interface); - /** - * \return The NetDevice that this ARP cache is associated with - */ - Ptr GetDevice (void) const; - /** - * \return the Ipv4Interface that this ARP cache is associated with - */ - Ptr GetInterface (void) const; - - void SetAliveTimeout (Time aliveTimeout); - void SetDeadTimeout (Time deadTimeout); - void SetWaitReplyTimeout (Time waitReplyTimeout); - Time GetAliveTimeout (void) const; - Time GetDeadTimeout (void) const; - Time GetWaitReplyTimeout (void) const; - - /** - * \brief Do lookup in the ARP chache against an IP address - * \param destination The destination IPv4 address to lookup the MAC address - * of - * \return An ArpCache::Entry with info about layer 2 - */ - ArpCache::Entry *Lookup (Ipv4Address destination); - /** - * \brief Add an Ipv4Address to this ARP cache - */ - ArpCache::Entry *Add (Ipv4Address to); - /** - * \brief Clear the ArpCache of all entries - */ - void Flush (void); - - /** - * \brief A record that that holds information about an ArpCache entry - */ - class Entry { - public: - /** - * \brief Constructor - * \param arp The ArpCache this entry belongs to - */ - Entry (ArpCache *arp); - - /** - * \brief Changes the state of this entry to dead - */ - void MarkDead (void); - /** - * \param macAddress - */ - void MarkAlive (Address macAddress); - /** - * \param waiting - */ - void MarkWaitReply (Ptr waiting); - /** - * \param waiting - * \return - */ - bool UpdateWaitReply (Ptr waiting); - /** - * \return True if the state of this entry is dead; false otherwise. - */ - bool IsDead (void); - /** - * \return True if the state of this entry is alive; false otherwise. - */ - bool IsAlive (void); - /** - * \return True if the state of this entry is wait_reply; false otherwise. - */ - bool IsWaitReply (void); - - /** - * \return The MacAddress of this entry - */ - Address GetMacAddress (void); - /** - * \return True if this entry has timedout; false otherwise. - */ - bool IsExpired (void); - - /** - * \returns 0 is no packet is pending, the next packet to send if - * packets are pending. - */ - Ptr DequeuePending (void); - private: - enum ArpCacheEntryState_e { - ALIVE, - WAIT_REPLY, - DEAD - }; - - void UpdateSeen (void); - ArpCache *m_arp; - ArpCacheEntryState_e m_state; - Time m_lastSeen; - Address m_macAddress; - std::list > m_pending; - }; - -private: - typedef sgi::hash_map Cache; - typedef sgi::hash_map::iterator CacheI; - - virtual void DoDispose (void); - - Ptr m_device; - Ptr m_interface; - Time m_aliveTimeout; - Time m_deadTimeout; - Time m_waitReplyTimeout; - uint32_t m_pendingQueueSize; - Cache m_arpCache; -}; - - -}; // namespace ns3 - -#endif /* ARP_CACHE_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-header.cc --- a/src/internet-node/arp-header.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* -*- 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 "ns3/assert.h" -#include "ns3/address-utils.h" -#include "arp-header.h" - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (ArpHeader); - -void -ArpHeader::SetRequest (Address sourceHardwareAddress, - Ipv4Address sourceProtocolAddress, - Address destinationHardwareAddress, - Ipv4Address destinationProtocolAddress) -{ - m_type = ARP_TYPE_REQUEST; - m_macSource = sourceHardwareAddress; - m_macDest = destinationHardwareAddress; - m_ipv4Source = sourceProtocolAddress; - m_ipv4Dest = destinationProtocolAddress; -} -void -ArpHeader::SetReply (Address sourceHardwareAddress, - Ipv4Address sourceProtocolAddress, - Address destinationHardwareAddress, - Ipv4Address destinationProtocolAddress) -{ - m_type = ARP_TYPE_REPLY; - m_macSource = sourceHardwareAddress; - m_macDest = destinationHardwareAddress; - m_ipv4Source = sourceProtocolAddress; - m_ipv4Dest = destinationProtocolAddress; -} -bool -ArpHeader::IsRequest (void) const -{ - return (m_type == ARP_TYPE_REQUEST)?true:false; -} -bool -ArpHeader::IsReply (void) const -{ - return (m_type == ARP_TYPE_REPLY)?true:false; -} -Address -ArpHeader::GetSourceHardwareAddress (void) -{ - return m_macSource; -} -Address -ArpHeader::GetDestinationHardwareAddress (void) -{ - return m_macDest; -} -Ipv4Address -ArpHeader::GetSourceIpv4Address (void) -{ - return m_ipv4Source; -} -Ipv4Address -ArpHeader::GetDestinationIpv4Address (void) -{ - return m_ipv4Dest; -} - - -TypeId -ArpHeader::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::ArpHeader") - .SetParent
() - .AddConstructor () - ; - return tid; -} -TypeId -ArpHeader::GetInstanceTypeId (void) const -{ - return GetTypeId (); -} -void -ArpHeader::Print (std::ostream &os) const -{ - if (IsRequest ()) - { - os << "request " - << "source mac: " << m_macSource << " " - << "source ipv4: " << m_ipv4Source << " " - << "dest ipv4: " << m_ipv4Dest - ; - } - else - { - NS_ASSERT (IsReply ()); - os << "reply " - << "source mac: " << m_macSource << " " - << "source ipv4: " << m_ipv4Source << " " - << "dest mac: " << m_macDest << " " - << "dest ipv4: " < - */ - -#ifndef ARP_HEADER_H -#define ARP_HEADER_H - -#include "ns3/header.h" -#include "ns3/address.h" -#include "ns3/ipv4-address.h" -#include - -namespace ns3 { -/** - * \brief The packet header for an ARP packet - */ -class ArpHeader : public Header -{ -public: - void SetRequest (Address sourceHardwareAddress, - Ipv4Address sourceProtocolAddress, - Address destinationHardwareAddress, - Ipv4Address destinationProtocolAddress); - void SetReply (Address sourceHardwareAddress, - Ipv4Address sourceProtocolAddress, - Address destinationHardwareAddress, - Ipv4Address destinationProtocolAddress); - bool IsRequest (void) const; - bool IsReply (void) const; - Address GetSourceHardwareAddress (void); - Address GetDestinationHardwareAddress (void); - Ipv4Address GetSourceIpv4Address (void); - Ipv4Address GetDestinationIpv4Address (void); - - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - virtual void Print (std::ostream &os) const; - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (Buffer::Iterator start) const; - virtual uint32_t Deserialize (Buffer::Iterator start); - - enum ArpType_e { - ARP_TYPE_REQUEST = 1, - ARP_TYPE_REPLY = 2 - }; - uint16_t m_type; - Address m_macSource; - Address m_macDest; - Ipv4Address m_ipv4Source; - Ipv4Address m_ipv4Dest; -}; - -}; // namespace ns3 - -#endif /* ARP_HEADER_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-ipv4-interface.cc --- a/src/internet-node/arp-ipv4-interface.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +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_node = 0; - 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); - if (m_device->NeedsArp ()) - { - NS_LOG_LOGIC ("Needs ARP"); - Ptr arp = - m_node->GetObject (); - Address hardwareDestination; - bool found; - - if (dest.IsBroadcast () || - dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) ) - { - 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 ()->MakeMulticastAddress(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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-ipv4-interface.h --- a/src/internet-node/arp-ipv4-interface.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +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; - -/** - * \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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-l3-protocol.cc --- a/src/internet-node/arp-l3-protocol.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,303 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2006 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 "ns3/packet.h" -#include "ns3/log.h" -#include "ns3/node.h" -#include "ns3/net-device.h" -#include "ns3/object-vector.h" -#include "ns3/trace-source-accessor.h" - -#include "ipv4-l3-protocol.h" -#include "arp-l3-protocol.h" -#include "arp-header.h" -#include "arp-cache.h" -#include "ipv4-interface.h" - -NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol"); - -namespace ns3 { - -const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806; - -NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol); - -TypeId -ArpL3Protocol::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::ArpL3Protocol") - .SetParent () - .AddAttribute ("CacheList", - "The list of ARP caches", - ObjectVectorValue (), - MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList), - MakeObjectVectorChecker ()) - .AddTraceSource ("Drop", - "Packet dropped because not enough room in pending queue for a specific cache entry.", - MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace)) - ; - return tid; -} - -ArpL3Protocol::ArpL3Protocol () -{ - NS_LOG_FUNCTION (this); -} - -ArpL3Protocol::~ArpL3Protocol () -{ - NS_LOG_FUNCTION (this); -} - -void -ArpL3Protocol::SetNode (Ptr node) -{ - m_node = node; -} - -void -ArpL3Protocol::DoDispose (void) -{ - NS_LOG_FUNCTION (this); - for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i) - { - Ptr cache = *i; - cache->Dispose (); - } - m_cacheList.clear (); - m_node = 0; - Object::DoDispose (); -} - -Ptr -ArpL3Protocol::CreateCache (Ptr device, Ptr interface) -{ - Ptr ipv4 = m_node->GetObject (); - Ptr cache = CreateObject (); - cache->SetDevice (device, interface); - NS_ASSERT (device->IsBroadcast ()); - device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache)); - m_cacheList.push_back (cache); - return cache; -} - -Ptr -ArpL3Protocol::FindCache (Ptr device) -{ - NS_LOG_FUNCTION_NOARGS (); - for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++) - { - if ((*i)->GetDevice () == device) - { - return *i; - } - } - NS_ASSERT (false); - // quiet compiler - return 0; -} - -void -ArpL3Protocol::Receive(Ptr device, Ptr packet, uint16_t protocol, const Address &from) -{ - NS_LOG_FUNCTION_NOARGS (); - Ptr cache = FindCache (device); - ArpHeader arp; - packet->RemoveHeader (arp); - - NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << - " node="<GetId ()<<", got request from " << - arp.GetSourceIpv4Address () << " for address " << - arp.GetDestinationIpv4Address () << "; we have address " << - cache->GetInterface ()->GetAddress ()); - - /** - * Note: we do not update the ARP cache when we receive an ARP request - * from an unknown node. See bug #107 - */ - - if (arp.IsRequest () && - arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) - { - NS_LOG_LOGIC ("node="<GetId () <<", got request from " << - arp.GetSourceIpv4Address () << " -- send reply"); - SendArpReply (cache, arp.GetSourceIpv4Address (), - arp.GetSourceHardwareAddress ()); - } - else if (arp.IsReply () && - arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) && - arp.GetDestinationHardwareAddress () == device->GetAddress ()) - { - Ipv4Address from = arp.GetSourceIpv4Address (); - ArpCache::Entry *entry = cache->Lookup (from); - if (entry != 0) - { - if (entry->IsWaitReply ()) - { - NS_LOG_LOGIC ("node="<GetId ()<<", got reply from " << - arp.GetSourceIpv4Address () - << " for waiting entry -- flush"); - Address from_mac = arp.GetSourceHardwareAddress (); - entry->MarkAlive (from_mac); - Ptr pending = entry->DequeuePending(); - while (pending != 0) - { - cache->GetInterface ()->Send (pending, - arp.GetSourceIpv4Address ()); - pending = entry->DequeuePending(); - } - } - else - { - // ignore this reply which might well be an attempt - // at poisening my arp cache. - NS_LOG_LOGIC("node="<GetId ()<<", got reply from " << - arp.GetSourceIpv4Address () << - " for non-waiting entry -- drop"); - m_dropTrace (packet); - } - } - else - { - NS_LOG_LOGIC ("node="<GetId ()<<", got reply for unknown entry -- drop"); - m_dropTrace (packet); - } - } - else - { - NS_LOG_LOGIC ("node="<GetId ()<<", got request from " << - arp.GetSourceIpv4Address () << " for unknown address " << - arp.GetDestinationIpv4Address () << " -- drop"); - } -} -bool -ArpL3Protocol::Lookup (Ptr packet, Ipv4Address destination, - Ptr device, - Ptr cache, - Address *hardwareDestination) -{ - NS_LOG_FUNCTION_NOARGS (); - ArpCache::Entry *entry = cache->Lookup (destination); - if (entry != 0) - { - if (entry->IsExpired ()) - { - if (entry->IsDead ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", dead entry for " << destination << " expired -- send arp request"); - entry->MarkWaitReply (packet); - SendArpRequest (cache, destination); - } - else if (entry->IsAlive ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", alive entry for " << destination << " expired -- send arp request"); - entry->MarkWaitReply (packet); - SendArpRequest (cache, destination); - } - else if (entry->IsWaitReply ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", wait reply for " << destination << " expired -- drop"); - entry->MarkDead (); - Ptr pending = entry->DequeuePending(); - while (pending != 0) - { - m_dropTrace (pending); - pending = entry->DequeuePending(); - } - m_dropTrace (packet); - } - } - else - { - if (entry->IsDead ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", dead entry for " << destination << " valid -- drop"); - m_dropTrace (packet); - } - else if (entry->IsAlive ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", alive entry for " << destination << " valid -- send"); - *hardwareDestination = entry->GetMacAddress (); - return true; - } - else if (entry->IsWaitReply ()) - { - NS_LOG_LOGIC ("node="<GetId ()<< - ", wait reply for " << destination << " valid -- drop previous"); - if (!entry->UpdateWaitReply (packet)) - { - m_dropTrace (packet); - } - } - } - } - else - { - // This is our first attempt to transmit data to this destination. - NS_LOG_LOGIC ("node="<GetId ()<< - ", no entry for " << destination << " -- send arp request"); - entry = cache->Add (destination); - entry->MarkWaitReply (packet); - SendArpRequest (cache, destination); - } - return false; -} - -void -ArpL3Protocol::SendArpRequest (Ptr cache, Ipv4Address to) -{ - NS_LOG_FUNCTION_NOARGS (); - ArpHeader arp; - NS_LOG_LOGIC ("ARP: sending request from node "<GetId ()<< - " || src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << - " || dst: " << cache->GetDevice ()->GetBroadcast () << - " / " << to); - arp.SetRequest (cache->GetDevice ()->GetAddress (), - cache->GetInterface ()->GetAddress (), - cache->GetDevice ()->GetBroadcast (), - to); - Ptr packet = Create (); - packet->AddHeader (arp); - cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER); -} - -void -ArpL3Protocol::SendArpReply (Ptr cache, Ipv4Address toIp, Address toMac) -{ - NS_LOG_FUNCTION_NOARGS (); - ArpHeader arp; - NS_LOG_LOGIC ("ARP: sending reply from node "<GetId ()<< - "|| src: " << cache->GetDevice ()->GetAddress () << - " / " << cache->GetInterface ()->GetAddress () << - " || dst: " << toMac << " / " << toIp); - arp.SetReply (cache->GetDevice ()->GetAddress (), - cache->GetInterface ()->GetAddress (), - toMac, toIp); - Ptr packet = Create (); - packet->AddHeader (arp); - cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER); -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/arp-l3-protocol.h --- a/src/internet-node/arp-l3-protocol.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2006 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 ARP_L3_PROTOCOL_H -#define ARP_L3_PROTOCOL_H - -#include -#include "ns3/ipv4-address.h" -#include "ns3/address.h" -#include "ns3/ptr.h" -#include "ns3/traced-callback.h" - -#include "ipv4-interface.h" - -namespace ns3 { - -class ArpCache; -class NetDevice; -class Node; -class Packet; - -/** - * \brief An implementation of the ARP protocol - */ -class ArpL3Protocol : public Object -{ -public: - static TypeId GetTypeId (void); - static const uint16_t PROT_NUMBER; - - ArpL3Protocol (); - virtual ~ArpL3Protocol (); - - void SetNode (Ptr node); - - Ptr CreateCache (Ptr device, Ptr interface); - - /** - * \brief Recieve a packet - */ - void Receive(Ptr device, Ptr p, uint16_t protocol, const Address &from); - /** - * \brief Perform an ARP lookup - * \param p - * \param destination - * \param device - * \param cache - * \param hardwareDestination - * \return - */ - bool Lookup (Ptr p, Ipv4Address destination, - Ptr device, - Ptr cache, - Address *hardwareDestination); -protected: - virtual void DoDispose (void); -private: - typedef std::list > CacheList; - Ptr FindCache (Ptr device); - void SendArpRequest (Ptrcache, Ipv4Address to); - void SendArpReply (Ptr cache, Ipv4Address toIp, Address toMac); - CacheList m_cacheList; - Ptr m_node; - TracedCallback > m_dropTrace; -}; - -}//namespace ns3 - - -#endif /* ARP_L3_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/internet-stack.cc --- a/src/internet-node/internet-stack.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +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 "ipv4-l4-demux.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-impl.h" - -namespace ns3 { - -void -AddInternetStack (Ptr node) -{ - Ptr ipv4 = CreateObject (); - Ptr arp = CreateObject (); - ipv4->SetNode (node); - arp->SetNode (node); - - Ptr ipv4L4Demux = CreateObject (); - Ptr udp = CreateObject (); - Ptr tcp = CreateObject (); - - ipv4L4Demux->SetNode (node); - udp->SetNode (node); - tcp->SetNode (node); - - ipv4L4Demux->Insert (udp); - ipv4L4Demux->Insert (tcp); - - Ptr udpFactory = CreateObject (); - Ptr tcpFactory = CreateObject (); - Ptr ipv4Impl = CreateObject (); - - udpFactory->SetUdp (udp); - tcpFactory->SetTcp (tcp); - ipv4Impl->SetIpv4 (ipv4); - - node->AggregateObject (ipv4); - node->AggregateObject (arp); - node->AggregateObject (ipv4Impl); - node->AggregateObject (udpFactory); - node->AggregateObject (tcpFactory); - node->AggregateObject (ipv4L4Demux); -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/internet-stack.h --- a/src/internet-node/internet-stack.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +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" - -namespace ns3 { - -class Node; - -void AddInternetStack (Ptr node); - -}//namespace ns3 - -#endif /* INTERNET_STACK_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-checksum.cc --- a/src/internet-node/ipv4-checksum.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,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 - * - * Author: Mathieu Lacage - */ -#include "ipv4-checksum.h" - -namespace ns3 { - -uint16_t -Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size) -{ - /* see RFC 1071 to understand this code. */ - uint32_t sum = checksum; - uint16_t *data = (uint16_t *) buffer; - for (uint16_t i = 0; i < (size/2); i++) { - sum += data[i]; - } - if ((size % 2) != 0) { - uint8_t tmpBuf[2]; - tmpBuf[0] = buffer[size-1]; - tmpBuf[1] = 0; - data = (uint16_t *)tmpBuf; - sum += *data; - } - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); - } - return sum; -} - -uint16_t -Ipv4ChecksumComplete (uint16_t checksum) -{ - return ~checksum; -} - -}; //namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-checksum.h --- a/src/internet-node/ipv4-checksum.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,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 - * - * Author: Mathieu Lacage - */ -#ifndef IPV4_CHECKSUM_H -#define IPV4_CHECKSUM_H - -#include - -namespace ns3 { - -uint16_t Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size); - -uint16_t Ipv4ChecksumComplete (uint16_t checksum); - -}; //namespace ns3 - -#endif /* IPV4_CHECKSUM_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-end-point-demux.cc --- a/src/internet-node/ipv4-end-point-demux.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,293 +0,0 @@ -/* -*- 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-end-point-demux.h" -#include "ipv4-end-point.h" -#include "ns3/log.h" - -namespace ns3{ - -NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux"); - -Ipv4EndPointDemux::Ipv4EndPointDemux () - : m_ephemeral (49152) -{ - NS_LOG_FUNCTION_NOARGS (); -} - -Ipv4EndPointDemux::~Ipv4EndPointDemux () -{ - NS_LOG_FUNCTION_NOARGS (); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - Ipv4EndPoint *endPoint = *i; - delete endPoint; - } - m_endPoints.clear (); -} - -bool -Ipv4EndPointDemux::LookupPortLocal (uint16_t port) -{ - NS_LOG_FUNCTION_NOARGS (); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - if ((*i)->GetLocalPort () == port) - { - return true; - } - } - return false; -} - -bool -Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port) -{ - NS_LOG_FUNCTION_NOARGS (); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - if ((*i)->GetLocalPort () == port && - (*i)->GetLocalAddress () == addr) - { - return true; - } - } - return false; -} - -Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (void) -{ - NS_LOG_FUNCTION_NOARGS (); - uint16_t port = AllocateEphemeralPort (); - if (port == 0) - { - NS_LOG_WARN ("Ephemeral port allocation failed."); - return 0; - } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port); - m_endPoints.push_back (endPoint); - NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); - return endPoint; -} - -Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (Ipv4Address address) -{ - NS_LOG_FUNCTION (this << address); - uint16_t port = AllocateEphemeralPort (); - if (port == 0) - { - NS_LOG_WARN ("Ephemeral port allocation failed."); - return 0; - } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); - m_endPoints.push_back (endPoint); - NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); - return endPoint; -} - -Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (uint16_t port) -{ - NS_LOG_FUNCTION (this << port); - - return Allocate (Ipv4Address::GetAny (), port); -} - -Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port) -{ - NS_LOG_FUNCTION (this << address << port); - if (LookupLocal (address, port)) - { - NS_LOG_WARN ("Duplicate address/port; failing."); - return 0; - } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); - m_endPoints.push_back (endPoint); - NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); - return endPoint; -} - -Ipv4EndPoint * -Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) -{ - NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - if ((*i)->GetLocalPort () == localPort && - (*i)->GetLocalAddress () == localAddress && - (*i)->GetPeerPort () == peerPort && - (*i)->GetPeerAddress () == peerAddress) - { - NS_LOG_WARN ("No way we can allocate this end-point."); - /* no way we can allocate this end-point. */ - return 0; - } - } - Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort); - endPoint->SetPeer (peerAddress, peerPort); - m_endPoints.push_back (endPoint); - - NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); - - return endPoint; -} - -void -Ipv4EndPointDemux::DeAllocate (Ipv4EndPoint *endPoint) -{ - NS_LOG_FUNCTION_NOARGS (); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - if (*i == endPoint) - { - delete endPoint; - m_endPoints.erase (i); - break; - } - } -} - -/* - * If we have an exact match, we return it. - * Otherwise, if we find a generic match, we return it. - * Otherwise, we return 0. - */ -Ipv4EndPointDemux::EndPoints -Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, - Ipv4Address saddr, uint16_t sport, - Ptr incomingInterface) -{ - NS_LOG_FUNCTION_NOARGS (); - EndPoints retval1; // Matches exact on local port, wildcards on others - EndPoints retval2; // Matches exact on local port/adder, wildcards on others - EndPoints retval3; // Matches all but local address - EndPoints retval4; // Exact match on all 4 - - NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface); - NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr); - for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) - { - Ipv4EndPoint* endP = *i; - NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort () - << " daddr=" << endP->GetLocalAddress () - << " sport=" << endP->GetPeerPort () - << " saddr=" << endP->GetPeerAddress ()); - if (endP->GetLocalPort () != dport) - { - NS_LOG_LOGIC ("Skipping endpoint " << &endP - << " because endpoint dport " - << endP->GetLocalPort () - << " does not match packet dport " << dport); - continue; - } - bool isBroadcast = (daddr.IsBroadcast () || - daddr.IsSubnetDirectedBroadcast ( - incomingInterface->GetNetworkMask ())); - Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (); - NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast); - bool localAddressMatchesWildCard = - endP->GetLocalAddress() == Ipv4Address::GetAny(); - bool localAddressMatchesExact = endP->GetLocalAddress () == daddr; - - if (isBroadcast) - { - NS_LOG_DEBUG("Found bcast, localaddr " << endP->GetLocalAddress()); - } - - if (isBroadcast && (endP->GetLocalAddress() != Ipv4Address::GetAny())) - { - localAddressMatchesExact = (endP->GetLocalAddress () == - incomingInterfaceAddr); - } - // if no match here, keep looking - if (!(localAddressMatchesExact || localAddressMatchesWildCard)) - continue; - bool remotePeerMatchesExact = endP->GetPeerPort () == sport; - bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0; - bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr; - bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == - Ipv4Address::GetAny(); - // If remote does not match either with exact or wildcard, - // skip this one - if (!(remotePeerMatchesExact || remotePeerMatchesWildCard)) - continue; - if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard)) - continue; - - // Now figure out which return list to add this one to - if (localAddressMatchesWildCard && - remotePeerMatchesWildCard && - remoteAddressMatchesWildCard) - { // Only local port matches exactly - retval1.push_back(endP); - } - if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&& - remotePeerMatchesWildCard && - remoteAddressMatchesWildCard) - { // Only local port and local address matches exactly - retval2.push_back(endP); - } - if (localAddressMatchesWildCard && - remotePeerMatchesExact && - remoteAddressMatchesExact) - { // All but local address - retval3.push_back(endP); - } - if (localAddressMatchesExact && - remotePeerMatchesExact && - remoteAddressMatchesExact) - { // All 4 match - retval4.push_back(endP); - } - } - - // Here we find the most exact match - if (!retval4.empty()) return retval4; - if (!retval3.empty()) return retval3; - if (!retval2.empty()) return retval2; - return retval1; // might be empty if no matches -} - -uint16_t -Ipv4EndPointDemux::AllocateEphemeralPort (void) -{ - NS_LOG_FUNCTION_NOARGS (); - uint16_t port = m_ephemeral; - do - { - port++; - if (port == 65535) - { - port = 49152; - } - if (!LookupPortLocal (port)) - { - return port; - } - } while (port != m_ephemeral); - return 0; -} - -} //namespace ns3 - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-end-point-demux.h --- a/src/internet-node/ipv4-end-point-demux.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* -*- 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_END_POINT_DEMUX_H -#define IPV4_END_POINT_DEMUX_H - -#include -#include -#include "ns3/ipv4-address.h" -#include "ipv4-interface.h" - -namespace ns3 { - -class Ipv4EndPoint; - -class Ipv4EndPointDemux { -public: - typedef std::list EndPoints; - typedef std::list::iterator EndPointsI; - - Ipv4EndPointDemux (); - ~Ipv4EndPointDemux (); - - bool LookupPortLocal (uint16_t port); - bool LookupLocal (Ipv4Address addr, uint16_t port); - EndPoints Lookup (Ipv4Address daddr, - uint16_t dport, - Ipv4Address saddr, - uint16_t sport, - Ptr incomingInterface); - - Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); - Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address localAddress, - uint16_t localPort, - Ipv4Address peerAddress, - uint16_t peerPort); - - void DeAllocate (Ipv4EndPoint *endPoint); - - private: - uint16_t AllocateEphemeralPort (void); - - uint16_t m_ephemeral; - EndPoints m_endPoints; -}; - -} // namespace ns3 - -#endif /* IPV4_END_POINTS_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-end-point.cc --- a/src/internet-node/ipv4-end-point.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* -*- 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-end-point.h" -#include "ns3/packet.h" - -namespace ns3 { - -Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port) - : m_localAddr (address), - m_localPort (port), - m_peerAddr (Ipv4Address::GetAny ()), - m_peerPort (0) -{} -Ipv4EndPoint::~Ipv4EndPoint () -{ - if (!m_destroyCallback.IsNull ()) - { - m_destroyCallback (); - } -} - -Ipv4Address -Ipv4EndPoint::GetLocalAddress (void) -{ - return m_localAddr; -} - -void -Ipv4EndPoint::SetLocalAddress (Ipv4Address address) -{ - m_localAddr = address; -} - -uint16_t -Ipv4EndPoint::GetLocalPort (void) -{ - return m_localPort; -} -Ipv4Address -Ipv4EndPoint::GetPeerAddress (void) -{ - return m_peerAddr; -} -uint16_t -Ipv4EndPoint::GetPeerPort (void) -{ - return m_peerPort; -} -void -Ipv4EndPoint::SetPeer (Ipv4Address address, uint16_t port) -{ - m_peerAddr = address; - m_peerPort = port; -} - -void -Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, uint16_t> callback) -{ - m_rxCallback = callback; -} - -void -Ipv4EndPoint::SetDestroyCallback (Callback callback) -{ - m_destroyCallback = callback; -} - -void -Ipv4EndPoint::ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport) -{ - if (!m_rxCallback.IsNull ()) - { - m_rxCallback (p, saddr, sport); - } -} - - - -}; // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-end-point.h --- a/src/internet-node/ipv4-end-point.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* -*- 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_END_POINT_H -#define IPV4_END_POINT_H - -#include -#include "ns3/ipv4-address.h" -#include "ns3/callback.h" - -namespace ns3 { - -class Header; -class Packet; - -class Ipv4EndPoint { -public: - Ipv4EndPoint (Ipv4Address address, uint16_t port); - ~Ipv4EndPoint (); - - Ipv4Address GetLocalAddress (void); - void SetLocalAddress (Ipv4Address address); - uint16_t GetLocalPort (void); - Ipv4Address GetPeerAddress (void); - uint16_t GetPeerPort (void); - - void SetPeer (Ipv4Address address, uint16_t port); - - void SetRxCallback (Callback, Ipv4Address, uint16_t> callback); - void SetDestroyCallback (Callback callback); - - void ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport); - -private: - Ipv4Address m_localAddr; - uint16_t m_localPort; - Ipv4Address m_peerAddr; - uint16_t m_peerPort; - Callback, Ipv4Address, uint16_t> m_rxCallback; - Callback m_destroyCallback; -}; - -}; // namespace ns3 - - -#endif /* IPV4_END_POINT_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-impl.cc --- a/src/internet-node/ipv4-impl.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +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 - * - * Author: Mathieu Lacage - */ -#include "ipv4-impl.h" -#include "ipv4-l3-protocol.h" -#include "ipv4-interface.h" -#include "ns3/assert.h" -#include "ns3/net-device.h" - -namespace ns3 { - -Ipv4Impl::Ipv4Impl () - : m_ipv4 (0) -{} -Ipv4Impl::~Ipv4Impl () -{ - NS_ASSERT (m_ipv4 == 0); -} -void -Ipv4Impl::SetIpv4 (Ptr ipv4) -{ - m_ipv4 = ipv4; -} -void -Ipv4Impl::DoDispose (void) -{ - m_ipv4 = 0; -} - -void -Ipv4Impl::AddRoutingProtocol (Ptr routingProtocol, - int16_t priority) -{ - m_ipv4->AddRoutingProtocol (routingProtocol, priority); -} - -void -Ipv4Impl::AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->AddHostRouteTo (dest, nextHop, interface); -} -void -Ipv4Impl::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) -{ - m_ipv4->AddHostRouteTo (dest, interface); -} -void -Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->AddNetworkRouteTo (network, networkMask, nextHop, interface); -} -void -Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) -{ - m_ipv4->AddNetworkRouteTo (network, networkMask, interface); -} -void -Ipv4Impl::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -{ - m_ipv4->SetDefaultRoute (nextHop, interface); -} -uint32_t -Ipv4Impl::GetNRoutes (void) -{ - return m_ipv4->GetNRoutes (); -} -Ipv4Route -Ipv4Impl::GetRoute (uint32_t i) -{ - return *m_ipv4->GetRoute (i); -} -void -Ipv4Impl::RemoveRoute (uint32_t i) -{ - return m_ipv4->RemoveRoute (i); -} - -void -Ipv4Impl::AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces) -{ - m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces); -} - -void -Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface) -{ - m_ipv4->SetDefaultMulticastRoute (outputInterface); -} - -uint32_t -Ipv4Impl::GetNMulticastRoutes (void) const -{ - return m_ipv4->GetNMulticastRoutes (); -} - -Ipv4MulticastRoute -Ipv4Impl::GetMulticastRoute (uint32_t i) const -{ - return *m_ipv4->GetMulticastRoute (i); -} - -void -Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface) -{ - m_ipv4->RemoveMulticastRoute (origin, group, inputInterface); -} - -void -Ipv4Impl::RemoveMulticastRoute (uint32_t i) -{ - return m_ipv4->RemoveMulticastRoute (i); -} - -uint32_t -Ipv4Impl::AddInterface (Ptr device) -{ - return m_ipv4->AddInterface (device); -} - -uint32_t -Ipv4Impl::GetNInterfaces (void) -{ - return m_ipv4->GetNInterfaces (); -} - -uint32_t -Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const -{ - return m_ipv4->FindInterfaceForAddr (addr); -} - -uint32_t -Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const -{ - return m_ipv4->FindInterfaceForAddr (addr, mask); -} - -int32_t -Ipv4Impl::FindInterfaceForDevice (Ptr device) const -{ - return m_ipv4->FindInterfaceIndexForDevice (device); -} - -Ptr -Ipv4Impl::GetNetDevice (uint32_t i) -{ - return m_ipv4->GetInterface (i)-> GetDevice (); -} - -void -Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) -{ - m_ipv4->JoinMulticastGroup(origin, group); -} - -void -Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) -{ - m_ipv4->LeaveMulticastGroup(origin, group); -} - -void -Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address) -{ - m_ipv4->SetAddress (i, address); -} -void -Ipv4Impl::SetNetworkMask (uint32_t i, Ipv4Mask mask) -{ - m_ipv4->SetNetworkMask (i, mask); -} -Ipv4Mask -Ipv4Impl::GetNetworkMask (uint32_t i) const -{ - return m_ipv4->GetNetworkMask (i); -} - -Ipv4Address -Ipv4Impl::GetAddress (uint32_t i) const -{ - return m_ipv4->GetAddress (i); -} - -void -Ipv4Impl::SetMetric (uint32_t i, uint16_t metric) -{ - m_ipv4->SetMetric (i, metric); -} - -uint16_t -Ipv4Impl::GetMetric (uint32_t i) const -{ - return m_ipv4->GetMetric (i); -} - -bool -Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const -{ - return m_ipv4->GetIfIndexForDestination (dest, ifIndex); -} - -Ipv4Address -Ipv4Impl::GetSourceAddress (Ipv4Address destination) const -{ - uint32_t ifIndex = 0xffffffff; - - bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); - - if (result) - { - return m_ipv4->GetAddress (ifIndex); - } - else - { -// -// If we can't find any address, just leave it 0.0.0.0 -// - return Ipv4Address::GetAny (); - } -} - -uint16_t -Ipv4Impl::GetMtu (uint32_t i) const -{ - return m_ipv4->GetMtu (i); -} -bool -Ipv4Impl::IsUp (uint32_t i) const -{ - return m_ipv4->IsUp (i); -} -void -Ipv4Impl::SetUp (uint32_t i) -{ - m_ipv4->SetUp (i); -} -void -Ipv4Impl::SetDown (uint32_t i) -{ - m_ipv4->SetDown (i); -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-impl.h --- a/src/internet-node/ipv4-impl.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +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 - * - * Author: Mathieu Lacage - */ -#ifndef IPV4_IMPL_H -#define IPV4_IMPL_H - -#include "ns3/ipv4.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class Ipv4L3Protocol; - -class Ipv4Impl : public Ipv4 -{ -public: - Ipv4Impl (); - - virtual ~Ipv4Impl (); - - void SetIpv4 (Ptr ipv4); - - virtual void AddRoutingProtocol (Ptr routingProtocol, - int16_t priority); - - virtual void AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface); - virtual void AddHostRouteTo (Ipv4Address dest, - uint32_t interface); - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface); - virtual void AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface); - virtual void SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface); - virtual uint32_t GetNRoutes (void); - virtual Ipv4Route GetRoute (uint32_t i); - virtual void RemoveRoute (uint32_t i); - - - virtual void AddMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface, - std::vector outputInterfaces); - - virtual void SetDefaultMulticastRoute (uint32_t outputInterface); - - virtual uint32_t GetNMulticastRoutes (void) const; - virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; - - virtual void RemoveMulticastRoute (Ipv4Address origin, - Ipv4Address group, - uint32_t inputInterface); - virtual void RemoveMulticastRoute (uint32_t i); - - virtual uint32_t AddInterface (Ptr device); - virtual uint32_t GetNInterfaces (void); - - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const; - virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, - Ipv4Mask mask) const; - - virtual int32_t FindInterfaceForDevice (Ptr device) const; - - virtual Ptr GetNetDevice(uint32_t i); - - virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); - virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); - - virtual void SetAddress (uint32_t i, Ipv4Address address); - virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); - virtual Ipv4Mask GetNetworkMask (uint32_t t) const; - virtual Ipv4Address GetAddress (uint32_t i) const; - virtual void SetMetric (uint32_t i, uint16_t metric); - virtual uint16_t GetMetric (uint32_t i) const; - virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; - virtual bool GetIfIndexForDestination (Ipv4Address dest, - uint32_t &ifIndex) const; - - virtual uint16_t GetMtu (uint32_t i) const; - virtual bool IsUp (uint32_t i) const; - virtual void SetUp (uint32_t i); - virtual void SetDown (uint32_t i); -protected: - virtual void DoDispose (void); -private: - Ptr m_ipv4; -}; - -} // namespace ns3 - -#endif /* IPV4_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-interface.cc --- a/src/internet-node/ipv4-interface.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,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 - * - * Author: Mathieu Lacage - */ - -#include "ipv4-interface.h" -#include "ns3/ipv4-address.h" -#include "ns3/net-device.h" -#include "ns3/log.h" -#include "ns3/packet.h" - -NS_LOG_COMPONENT_DEFINE ("Ipv4Interface"); - -namespace ns3 { - -TypeId -Ipv4Interface::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::Ipv4Interface") - .SetParent () - ; - 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. - */ -Ipv4Interface::Ipv4Interface () - : m_ifup(false), - m_metric(1) -{ - NS_LOG_FUNCTION (this); -} - -Ipv4Interface::~Ipv4Interface () -{ - NS_LOG_FUNCTION_NOARGS (); -} - -void -Ipv4Interface::DoDispose (void) -{ - NS_LOG_FUNCTION_NOARGS (); - Object::DoDispose (); -} - -void -Ipv4Interface::SetAddress (Ipv4Address a) -{ - NS_LOG_FUNCTION (this << a); - m_address = a; -} - -void -Ipv4Interface::SetNetworkMask (Ipv4Mask mask) -{ - NS_LOG_FUNCTION (this << mask); - m_netmask = mask; -} - -Ipv4Address -Ipv4Interface::GetBroadcast (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - uint32_t mask = m_netmask.Get (); - uint32_t address = m_address.Get (); - Ipv4Address broadcast = Ipv4Address (address | (~mask)); - return broadcast; -} - -Ipv4Mask -Ipv4Interface::GetNetworkMask (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_netmask; -} - -void -Ipv4Interface::SetMetric (uint16_t metric) -{ - NS_LOG_FUNCTION (metric); - m_metric = metric; -} - -uint16_t -Ipv4Interface::GetMetric (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_metric; -} - -Ipv4Address -Ipv4Interface::GetAddress (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_address; -} - -uint16_t -Ipv4Interface::GetMtu (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - if (GetDevice () == 0) - { - uint32_t mtu = (1<<16) - 1; - return mtu; - } - return GetDevice ()->GetMtu (); -} - -/** - * These are IP interface states and may be distinct from - * NetDevice states, such as found in real implementations - * (where the device may be down but IP interface state is still up). - */ -bool -Ipv4Interface::IsUp (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_ifup; -} - -bool -Ipv4Interface::IsDown (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return !m_ifup; -} - -void -Ipv4Interface::SetUp (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_ifup = true; -} - -void -Ipv4Interface::SetDown (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_ifup = false; -} - -// public wrapper on private virtual function -void -Ipv4Interface::Send(Ptr p, Ipv4Address dest) -{ - NS_LOG_FUNCTION_NOARGS (); - if (IsUp()) { - NS_LOG_LOGIC ("SendTo"); - SendTo(p, dest); - } -} - -}; // namespace ns3 - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-interface.h --- a/src/internet-node/ipv4-interface.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,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 , - * Tom Henderson - */ -#ifndef IPV4_INTERFACE_H -#define IPV4_INTERFACE_H - -#include -#include "ns3/ipv4-address.h" -#include "ns3/ptr.h" -#include "ns3/object.h" - -namespace ns3 { - -class NetDevice; -class Packet; - -/** - * \brief The IPv4 representation of a network interface - * - * This class roughly corresponds to the struct in_device - * 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 - */ -class Ipv4Interface : public Object -{ -public: - static TypeId GetTypeId (void); - - Ipv4Interface (); - virtual ~Ipv4Interface(); - - /** - * \returns the underlying NetDevice. This method can return - * zero if this interface has no associated NetDevice. - */ - virtual Ptr GetDevice (void) const = 0; - - /** - * \param a set the ipv4 address of this interface. - */ - void SetAddress (Ipv4Address a); - /** - * \param mask set the ipv4 netmask of this interface. - */ - void SetNetworkMask (Ipv4Mask mask); - - /** - * \returns the broadcast ipv4 address associated to this interface - */ - Ipv4Address GetBroadcast (void) const; - /** - * \returns the ipv4 netmask of this interface - */ - Ipv4Mask GetNetworkMask (void) const; - /** - * \param metric configured routing metric (cost) of this interface - */ - void SetMetric (uint16_t metric); - /** - * \returns configured routing metric (cost) of this interface - */ - uint16_t GetMetric (void) const; - /** - * \returns the ipv4 address of this interface - */ - Ipv4Address GetAddress (void) const; - - /** - * 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. - */ - uint16_t GetMtu (void) const; - - /** - * These are IP interface states and may be distinct from - * NetDevice states, such as found in real implementations - * (where the device may be down but IP interface state is still up). - */ - /** - * \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 - */ - void SetDown (void); - - /** - * \param p packet to send - * \param dest next hop address of packet. - * - * This method will eventually call the private - * SendTo method which must be implemented by subclasses. - */ - void Send(Ptr p, Ipv4Address dest); - -protected: - virtual void DoDispose (void); -private: - virtual void SendTo (Ptr p, Ipv4Address dest) = 0; - bool m_ifup; - Ipv4Address m_address; - Ipv4Mask m_netmask; - uint16_t m_metric; -}; - -}; // namespace ns3 - -#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l3-protocol.cc --- a/src/internet-node/ipv4-l3-protocol.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,906 +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/packet.h" -#include "ns3/log.h" -#include "ns3/callback.h" -#include "ns3/ipv4-address.h" -#include "ns3/ipv4-route.h" -#include "ns3/node.h" -#include "ns3/socket.h" -#include "ns3/net-device.h" -#include "ns3/uinteger.h" -#include "ns3/trace-source-accessor.h" -#include "ns3/object-vector.h" -#include "ns3/ipv4-header.h" -#include "ns3/boolean.h" -#include "arp-l3-protocol.h" - -#include "ipv4-l3-protocol.h" -#include "ipv4-l4-protocol.h" -#include "ipv4-interface.h" -#include "ipv4-loopback-interface.h" -#include "arp-ipv4-interface.h" -#include "ipv4-l4-demux.h" - -NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol"); - -namespace ns3 { - -const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800; - -NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol); - -TypeId -Ipv4L3Protocol::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") - .SetParent () - .AddConstructor () - .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.", - UintegerValue (64), - MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl), - MakeUintegerChecker ()) - .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets" - " and verify the checksum of incoming packets.", - BooleanValue (false), - MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum), - MakeBooleanChecker ()) - .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.", - MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace)) - .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.", - MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace)) - .AddTraceSource ("Drop", "Drop ipv4 packet", - MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace)) - .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.", - ObjectVectorValue (), - MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), - MakeObjectVectorChecker ()) - ; - return tid; -} - -Ipv4L3Protocol::Ipv4L3Protocol() - : m_nInterfaces (0), - m_identification (0) -{ - NS_LOG_FUNCTION_NOARGS (); - m_staticRouting = CreateObject (); - AddRoutingProtocol (m_staticRouting, 0); -} - -Ipv4L3Protocol::~Ipv4L3Protocol () -{ - NS_LOG_FUNCTION (this); -} - -void -Ipv4L3Protocol::SetNode (Ptr node) -{ - m_node = node; - SetupLoopback (); -} - -void -Ipv4L3Protocol::DoDispose (void) -{ - NS_LOG_FUNCTION (this); - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i) - { - Ptr interface = *i; - interface->Dispose (); - } - m_interfaces.clear (); - m_node = 0; - m_staticRouting->Dispose (); - m_staticRouting = 0; - Object::DoDispose (); -} - -void -Ipv4L3Protocol::SetupLoopback (void) -{ - NS_LOG_FUNCTION_NOARGS (); - - Ptr interface = CreateObject (); - interface->SetNode (m_node); - interface->SetAddress (Ipv4Address::GetLoopback ()); - interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); - uint32_t index = AddIpv4Interface (interface); - AddHostRouteTo (Ipv4Address::GetLoopback (), index); - interface->SetUp (); -} - -void -Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) -{ - NS_LOG_FUNCTION_NOARGS (); - m_defaultTtl = ttl; -} - - -void -Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, - Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION (this << dest << nextHop << interface); - m_staticRouting->AddHostRouteTo (dest, nextHop, interface); -} - -void -Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, - uint32_t interface) -{ - NS_LOG_FUNCTION (this << dest << interface); - m_staticRouting->AddHostRouteTo (dest, interface); -} - -void -Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface); - m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface); -} - -void -Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, - Ipv4Mask networkMask, - uint32_t interface) -{ - NS_LOG_FUNCTION (this << network << networkMask << interface); - m_staticRouting->AddNetworkRouteTo (network, networkMask, interface); -} - -void -Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, - uint32_t interface) -{ - NS_LOG_FUNCTION (this << nextHop << interface); - m_staticRouting->SetDefaultRoute (nextHop, interface); -} - -void -Ipv4L3Protocol::Lookup ( - Ipv4Header const &ipHeader, - Ptr packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) -{ - NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply); - - Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); -} - -void -Ipv4L3Protocol::Lookup ( - uint32_t ifIndex, - Ipv4Header const &ipHeader, - Ptr packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply) -{ - NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); - - for (Ipv4RoutingProtocolList::const_iterator rprotoIter = - m_routingProtocols.begin (); - rprotoIter != m_routingProtocols.end (); - rprotoIter++) - { - NS_LOG_LOGIC ("Requesting route"); - if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, - routeReply)) - return; - } - - if (ipHeader.GetDestination ().IsMulticast () && - ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) - { - NS_LOG_LOGIC ("Multicast destination with local source"); -// -// We have a multicast packet originating from the current node and were not -// able to send it using the usual RequestRoute process. Since the usual -// process includes trying to use a default multicast route, this means that -// there was no specific route out of the node found, and there was no default -// multicast route set. -// -// The fallback position is to look for a default unicast route and use that -// to get the packet off the node if we have one. -// - Ipv4Route *route = m_staticRouting->GetDefaultRoute (); - - if (route) - { - NS_LOG_LOGIC ("Local source. Using unicast default route for " - "multicast packet"); - - routeReply (true, *route, packet, ipHeader); - return; - } - } -// -// No route found -// - routeReply (false, Ipv4Route (), packet, ipHeader); -} - -void -Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, - int 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); -} - -uint32_t -Ipv4L3Protocol::AddInterface (Ptr device) -{ - NS_LOG_FUNCTION (this << &device); - - Ptr node = GetObject (); - node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), - Ipv4L3Protocol::PROT_NUMBER, device); - node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject ())), - ArpL3Protocol::PROT_NUMBER, device); - - Ptr interface = CreateObject (); - interface->SetNode (m_node); - interface->SetDevice (device); - return AddIpv4Interface (interface); -} - -uint32_t -Ipv4L3Protocol::AddIpv4Interface (Ptrinterface) -{ - NS_LOG_FUNCTION (this << interface); - uint32_t index = m_nInterfaces; - m_interfaces.push_back (interface); - m_nInterfaces++; - return index; -} - -Ptr -Ipv4L3Protocol::GetInterface (uint32_t index) const -{ - NS_LOG_FUNCTION (this << index); - uint32_t tmp = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) - { - if (index == tmp) - { - return *i; - } - tmp++; - } - return 0; -} - -uint32_t -Ipv4L3Protocol::GetNInterfaces (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_nInterfaces; -} - -uint32_t -Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const -{ - NS_LOG_FUNCTION (this << addr); - - uint32_t ifIndex = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); - i++, ifIndex++) - { - if ((*i)->GetAddress () == addr) - { - return ifIndex; - } - } - - 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 ifIndex = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); - i++, ifIndex++) - { - if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) - { - return ifIndex; - } - } - - NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " - "Interface not found for masked IP address"); - return 0; -} - -int32_t -Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr device) const -{ - NS_LOG_FUNCTION (this << device); - - uint32_t ifIndex = 0; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); - i++, ifIndex++) - { - if ((*i)->GetDevice () == device) - { - return ifIndex; - } - } - - 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 packet, uint16_t protocol, const Address &from) -{ - NS_LOG_FUNCTION (this << &device << packet << protocol << from); - - NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ()); - - uint32_t index = 0; - Ptr ipv4Interface; - for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); - i != m_interfaces.end (); - i++) - { - ipv4Interface = *i; - if (ipv4Interface->GetDevice () == device) - { - m_rxTrace (packet, index); - break; - } - index++; - } - Ipv4Header ipHeader; - if (m_calcChecksum) - { - ipHeader.EnableChecksum (); - } - packet->RemoveHeader (ipHeader); - - if (!ipHeader.IsChecksumOk ()) - { - m_dropTrace (packet); - return; - } - - if (Forwarding (index, packet, ipHeader, device)) - { - return; - } - - ForwardUp (packet, ipHeader, ipv4Interface); -} - - -void -Ipv4L3Protocol::Send (Ptr packet, - Ipv4Address source, - Ipv4Address destination, - uint8_t protocol) -{ - NS_LOG_FUNCTION (this << packet << source << destination << protocol); - - Ipv4Header ipHeader; - - if (m_calcChecksum) - { - ipHeader.EnableChecksum (); - } - - ipHeader.SetSource (source); - ipHeader.SetDestination (destination); - ipHeader.SetProtocol (protocol); - ipHeader.SetPayloadSize (packet->GetSize ()); - ipHeader.SetTtl (m_defaultTtl); - ipHeader.SetMayFragment (); - ipHeader.SetIdentification (m_identification); - - m_identification ++; - - // 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; - bool found = packet->FindFirstMatchingTag (tag); - - if (destination.IsBroadcast ()) - { - ipHeader.SetTtl (1); - } - else if (found) - { - ipHeader.SetTtl (tag.GetTtl ()); - // XXX remove tag here? - } - else - { - uint32_t ifaceIndex = 0; - for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); - ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) - { - Ptr outInterface = *ifaceIter; - if (destination.IsSubnetDirectedBroadcast ( - outInterface->GetNetworkMask ())) - { - ipHeader.SetTtl (1); - } - } - } - if (destination.IsBroadcast ()) - { - uint32_t ifaceIndex = 0; - for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); - ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) - { - Ptr outInterface = *ifaceIter; - Ptr packetCopy = packet->Copy (); - - NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ()); - packetCopy->AddHeader (ipHeader); - m_txTrace (packetCopy, ifaceIndex); - outInterface->Send (packetCopy, destination); - } - } - 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)); - } -} - -void -Ipv4L3Protocol::SendRealOut (bool found, - Ipv4Route const &route, - Ptr packet, - Ipv4Header const &ipHeader) -{ - NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader); - - packet->AddHeader (ipHeader); - if (!found) - { - NS_LOG_WARN ("No route to host. Drop."); - m_dropTrace (packet); - return; - } - - NS_LOG_LOGIC ("Send via interface " << route.GetInterface ()); - - Ptr outInterface = GetInterface (route.GetInterface ()); - NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ()); - m_txTrace (packet, route.GetInterface ()); - if (route.IsGateway ()) - { - NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ()); - outInterface->Send (packet, route.GetGateway ()); - } - else - { - NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); - outInterface->Send (packet, ipHeader.GetDestination ()); - } -} - -bool -Ipv4L3Protocol::Forwarding ( - uint32_t ifIndex, - Ptr packet, - Ipv4Header &ipHeader, - Ptr device) -{ - NS_LOG_FUNCTION (ifIndex << 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++) - { - if ((*i)->GetAddress ().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) - { - if (ipHeader.GetDestination ().IsEqual (interface->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 (ipHeader.GetTtl () == 1) - { - // Should send ttl expired here - // XXX - NS_LOG_LOGIC ("Not for me (TTL expired). Drop"); - m_dropTrace (packet); - return true; - } - ipHeader.SetTtl (ipHeader.GetTtl () - 1); - -// -// 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)."); - Lookup (ifIndex, ipHeader, packet->Copy (), - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); - return false; - } - } - NS_LOG_LOGIC ("Not for me, forwarding."); - Lookup (ifIndex, ipHeader, packet, - MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); - - return true; -} - -void -Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, - Ptr incomingInterface) -{ - NS_LOG_FUNCTION (this << p << &ip); - - Ptr demux = m_node->GetObject (); - Ptr protocol = demux->GetProtocol (ip.GetProtocol ()); - protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); -} - -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; - } - } -} - -void -Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) -{ - NS_LOG_FUNCTION (this << i << address); - Ptr interface = GetInterface (i); - interface->SetAddress (address); -} - -void -Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) -{ - NS_LOG_FUNCTION (this << i << mask); - Ptr interface = GetInterface (i); - interface->SetNetworkMask (mask); -} - -Ipv4Mask -Ipv4L3Protocol::GetNetworkMask (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->GetNetworkMask (); -} - -Ipv4Address -Ipv4L3Protocol::GetAddress (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->GetAddress (); -} - -void -Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric) -{ - NS_LOG_FUNCTION (i << metric); - Ptr interface = GetInterface (i); - interface->SetMetric (metric); -} - -uint16_t -Ipv4L3Protocol::GetMetric (uint32_t i) const -{ - NS_LOG_FUNCTION (i); - Ptr interface = GetInterface (i); - return interface->GetMetric (); -} - -bool -Ipv4L3Protocol::GetIfIndexForDestination ( - Ipv4Address destination, uint32_t& ifIndex) const -{ - NS_LOG_FUNCTION (this << destination << &ifIndex); -// -// 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 ifIndexTmp; - - if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) - { - NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp); - ifIndex = ifIndexTmp; - 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."); - ifIndex = 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::GetIfIndexForDestination (): " - "Unable to determine outbound interface. No default route set"); - return false; - } - - ifIndex = route->GetInterface (); - - NS_LOG_LOGIC ("Default route specifies interface " << ifIndex); - return true; -} - -uint16_t -Ipv4L3Protocol::GetMtu (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->GetMtu (); -} - -bool -Ipv4L3Protocol::IsUp (uint32_t i) const -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - return interface->IsUp (); -} - -void -Ipv4L3Protocol::SetUp (uint32_t i) -{ - NS_LOG_FUNCTION (this << i); - Ptr interface = GetInterface (i); - interface->SetUp (); - - // If interface address and network mask have been set, add a route - // to the network of the interface (like e.g. ifconfig does on a - // Linux box) - if ((interface->GetAddress ()) != (Ipv4Address ()) - && (interface->GetNetworkMask ()) != (Ipv4Mask ())) - { - AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()), - interface->GetNetworkMask (), i); - } -} - -void -Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) -{ - NS_LOG_FUNCTION (this << ifaceIndex); - Ptr interface = GetInterface (ifaceIndex); - interface->SetDown (); - - // Remove all routes that are going through this interface - bool modified = true; - while (modified) - { - modified = false; - for (uint32_t i = 0; i < GetNRoutes (); i++) - { - Ipv4Route *route = GetRoute (i); - if (route->GetInterface () == ifaceIndex) - { - RemoveRoute (i); - modified = true; - break; - } - } - } -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l3-protocol.h --- a/src/internet-node/ipv4-l3-protocol.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +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 IPV4_L3_PROTOCOL_H -#define IPV4_L3_PROTOCOL_H - -#include -#include -#include "ns3/ipv4-address.h" -#include "ns3/ptr.h" -#include "ns3/ipv4.h" -#include "ns3/traced-callback.h" -#include "ns3/ipv4-header.h" -#include "ipv4-static-routing.h" - -namespace ns3 { - -class Packet; -class NetDevice; -class Ipv4Interface; -class Ipv4Address; -class Ipv4Header; -class Ipv4Route; -class Node; - - -/** - * \brief Implement the Ipv4 layer. - */ -class Ipv4L3Protocol : public Object -{ -public: - static TypeId GetTypeId (void); - static const uint16_t PROT_NUMBER; - - Ipv4L3Protocol(); - virtual ~Ipv4L3Protocol (); - - void SetNode (Ptr node); - - /** - * \param ttl default ttl to use - * - * When we need to send an ipv4 packet, we use this default - * ttl value. - */ - 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 - * packet is coming to: - * - implement a per-NetDevice ARP cache - * - send back arp replies on the right device - */ - void Receive( Ptr device, Ptr p, uint16_t protocol, const Address &from); - - /** - * \param packet packet to send - * \param source source address of packet - * \param destination address of packet - * \param protocol number of packet - * - * 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); - - 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 FindInterfaceIndexForDevice (Ptr device) const; - - void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); - void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); - - void SetAddress (uint32_t i, Ipv4Address address); - void SetNetworkMask (uint32_t i, Ipv4Mask mask); - Ipv4Mask GetNetworkMask (uint32_t t) const; - Ipv4Address GetAddress (uint32_t i) const; - void SetMetric (uint32_t i, uint16_t metric); - uint16_t GetMetric (uint32_t i) const; - bool GetIfIndexForDestination (Ipv4Address destination, - uint32_t& ifIndex) const; - uint16_t GetMtu (uint32_t i) const; - bool IsUp (uint32_t i) const; - void SetUp (uint32_t i); - void SetDown (uint32_t i); - - void AddRoutingProtocol (Ptr routingProtocol, - int priority); - -protected: - - virtual void DoDispose (void); - -private: - void Lookup (uint32_t ifIndex, - Ipv4Header const &ipHeader, - Ptr packet, - Ipv4RoutingProtocol::RouteReplyCallback routeReply); - - void SendRealOut (bool found, - Ipv4Route const &route, - Ptr packet, - Ipv4Header const &ipHeader); - bool Forwarding (uint32_t ifIndex, - Ptr packet, - Ipv4Header &ipHeader, - Ptr device); - void ForwardUp (Ptr p, Ipv4Header const&ip, Ptr incomingInterface); - uint32_t AddIpv4Interface (Ptr interface); - void SetupLoopback (void); - - typedef std::list > Ipv4InterfaceList; - typedef std::list > - Ipv4MulticastGroupList; - typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; - - Ipv4InterfaceList m_interfaces; - uint32_t m_nInterfaces; - uint8_t m_defaultTtl; - bool m_calcChecksum; - uint16_t m_identification; - Ptr m_node; - TracedCallback, uint32_t> m_txTrace; - TracedCallback, uint32_t> m_rxTrace; - TracedCallback > m_dropTrace; - - Ipv4RoutingProtocolList m_routingProtocols; - - Ptr m_staticRouting; - Ipv4MulticastGroupList m_multicastGroups; -}; - -} // Namespace ns3 - -#endif /* IPV4_L3_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l4-demux.cc --- a/src/internet-node/ipv4-l4-demux.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +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 -// - -// Define the layer 4 demultiplexer object for ns3. -// George F. Riley, Georgia Tech, Fall 2006 - -#include -#include "ns3/node.h" -#include "ns3/object-vector.h" -#include "ipv4-l4-demux.h" -#include "ipv4-l4-protocol.h" - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Demux); - -TypeId -Ipv4L4Demux::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::Ipv4L4Demux") - .SetParent () - .AddAttribute ("Protocols", "The set of protocols registered with this demux.", - ObjectVectorValue (), - MakeObjectVectorAccessor (&Ipv4L4Demux::m_protocols), - MakeObjectVectorChecker ()) - ; - return tid; -} - -Ipv4L4Demux::Ipv4L4Demux () -{} - -Ipv4L4Demux::~Ipv4L4Demux() -{} - -void -Ipv4L4Demux::SetNode (Ptr node) -{ - m_node = node; -} - -void -Ipv4L4Demux::DoDispose (void) -{ - for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) - { - (*i)->Dispose (); - *i = 0; - } - m_protocols.clear (); - m_node = 0; - Object::DoDispose (); -} - -void -Ipv4L4Demux::Insert(Ptr protocol) -{ - m_protocols.push_back (protocol); -} -Ptr -Ipv4L4Demux::GetProtocol(int protocolNumber) -{ - for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) - { - if ((*i)->GetProtocolNumber () == protocolNumber) - { - return *i; - } - } - return 0; -} -void -Ipv4L4Demux::Remove (Ptr protocol) -{ - m_protocols.remove (protocol); -} - - - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l4-demux.h --- a/src/internet-node/ipv4-l4-demux.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +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 -// - -// Define the layer 4 demultiplexer object for ns3. -// George F. Riley, Georgia Tech, Fall 2006 - -#ifndef IPV4_L4_DEMUX_H -#define IPV4_L4_DEMUX_H - -#include -#include "ns3/object.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class Ipv4L4Protocol; -class Node; - -/** - * \brief L4 Ipv4 Demux - */ -class Ipv4L4Demux : public Object -{ -public: - static TypeId GetTypeId (void); - Ipv4L4Demux (); - virtual ~Ipv4L4Demux(); - - void SetNode (Ptr node); - - /** - * \param protocol a template for the protocol to add to this L4 Demux. - * \returns the L4Protocol effectively added. - * - * Invoke Copy on the input template to get a copy of the input - * protocol which can be used on the Node on which this L4 Demux - * is running. The new L4Protocol is registered internally as - * a working L4 Protocol and returned from this method. - * The caller does not get ownership of the returned pointer. - */ - void Insert(Ptr protocol); - /** - * \param protocolNumber number of protocol to lookup - * in this L4 Demux - * \returns a matching L4 Protocol - * - * This method is typically called by lower layers - * to forward packets up the stack to the right protocol. - * It is also called from NodeImpl::GetUdp for example. - */ - Ptr GetProtocol(int protocolNumber); - /** - * \param protocol protocol to remove from this demux. - * - * The input value to this method should be the value - * returned from the Ipv4L4Protocol::Insert method. - */ - void Remove (Ptr protocol); -protected: - virtual void DoDispose (void); -private: - typedef std::list > L4List_t; - L4List_t m_protocols; - Ptr m_node; -}; - -} //namespace ns3 -#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l4-protocol.cc --- a/src/internet-node/ipv4-l4-protocol.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +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 -// - -// NS3 - Layer 4 Protocol base class -// George F. Riley, Georgia Tech, Spring 2007 - -#include "ipv4-l4-protocol.h" -#include "ns3/uinteger.h" - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol); - -TypeId -Ipv4L4Protocol::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::Ipv4L4Protocol") - .SetParent () - .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.", - UintegerValue (0), - MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber), - MakeUintegerChecker ()) - .AddAttribute ("Version", "The version of the protocol.", - UintegerValue (0), - MakeUintegerAccessor (&Ipv4L4Protocol::GetVersion), - MakeUintegerChecker ()) - ; - return tid; -} - -Ipv4L4Protocol::~Ipv4L4Protocol () -{} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-l4-protocol.h --- a/src/internet-node/ipv4-l4-protocol.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +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 -// - -// NS3 - Layer 4 Protocol base class -// George F. Riley, Georgia Tech, Spring 2007 - -#ifndef IPV4_L4_PROTOCOL_H -#define IPV4_L4_PROTOCOL_H - -#include "ns3/object.h" -#include "ipv4-interface.h" - -namespace ns3 { - -class Packet; -class Ipv4Address; - -/** - * \brief L4 Protocol base class - * - * If you want to implement a new L4 protocol, all you have to do is - * implement a subclass of this base class and add it to an L4Demux. - */ -class Ipv4L4Protocol : public Object -{ -public: - static TypeId GetTypeId (void); - - virtual ~Ipv4L4Protocol (); - - /** - * \returns the protocol number of this protocol. - */ - virtual int GetProtocolNumber (void) const = 0; - /** - * \returns the version number of this protocol. - */ - virtual int GetVersion (void) const = 0; - - /** - * \param p packet to forward up - * \param source source address of packet received - * \param destination address of packet received - * \param incomingInterface the Ipv4Interface on which the packet arrived - * - * Called from lower-level layers to send the packet up - * in the stack. - */ - virtual void Receive(Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface) = 0; -}; - -} // Namespace ns3 - -#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-loopback-interface.cc --- a/src/internet-node/ipv4-loopback-interface.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +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")); -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-loopback-interface.h --- a/src/internet-node/ipv4-loopback-interface.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-static-routing.cc --- a/src/internet-node/ipv4-static-routing.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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::IF_INDEX_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 ifIndex) -{ - 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 ifIndex is a wildcard). -// - if (origin == route->GetOrigin () && group == route->GetGroup ()) - { - if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || - ifIndex == 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 (ifIndex != Ipv4RoutingProtocol::IF_INDEX_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 ifIndex, - Ipv4Header const &ipHeader, - Ptr packet, - RouteReplyCallback routeReply) -{ - NS_LOG_FUNCTION (this << ifIndex << &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 (), ifIndex); - - 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::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) -{ - NS_LOG_FUNCTION (this << destination << &ifIndex); -// -// 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::IF_INDEX_ANY); - - if (mRoute) - { - NS_LOG_LOGIC ("Multicast route found"); - - if (mRoute->GetNOutputInterfaces () != 1) - { - NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring."); - return false; - } - - ifIndex = mRoute->GetOutputInterface(0); - NS_LOG_LOGIC ("Found ifIndex " << ifIndex); - 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) - { - ifIndex = 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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/ipv4-static-routing.h --- a/src/internet-node/ipv4-static-routing.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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 ifIndex. 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::IF_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 ifIndex The network interface index over which the packed was - * received. If the packet is from a local source, ifIndex will be set to - * Ipv4RoutingProtocol::IF_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. In practice, the static routing protocol is the last chance - * protocol. - * - * @see Ipv4StaticRouting - * @see Ipv4RoutingProtocol - */ - virtual bool RequestRoute (uint32_t ifIndex, - 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::GetIfIndexforDestination 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 ifIndex 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 RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); - -/** - * @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::IF_INDEX_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::IF_INDEX_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 ifIndex); - - HostRoutes m_hostRoutes; - NetworkRoutes m_networkRoutes; - Ipv4Route *m_defaultRoute; - Ipv4MulticastRoute *m_defaultMulticastRoute; - MulticastRoutes m_multicastRoutes; -}; - -} // Namespace ns3 - -#endif /* IPV4_STATIC_ROUTING_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/pending-data.cc --- a/src/internet-node/pending-data.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +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: Rajib Bhattacharjea -// - - -// This is a port of Data PDU Headers from: -// Georgia Tech Network Simulator -// George F. Riley. Georgia Tech, Spring 2002 - -#include -#include - -#include - -#include "pending-data.h" -#include "ns3/fatal-error.h" -namespace ns3 -{ - -PendingData::PendingData () : size (0), data (0), - msgSize (0), responseSize (0) -{ -} - -PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp) - : size (s), data (0), msgSize (msg), responseSize (resp) -{ - if (d) - { - data.push_back (Create (d, size)); - } -} - -PendingData::PendingData(const std::string& s) - : size (s.length () + 1), data (0), - msgSize (0), responseSize (0) -{ - data.push_back (Create ((uint8_t*)s.c_str(), size)); -} - -PendingData::PendingData(const PendingData& c) - : size (c.Size ()), data (c.data), - msgSize (c.msgSize), responseSize (c.responseSize) -{ -} - -PendingData::~PendingData() -{ -} - -PendingData* PendingData::Copy () const -{ - return new PendingData (*this); -}; - -PendingData* PendingData::CopyS (uint32_t s) -{ // Copy, but with new size (assumes no associated data); - return new PendingData (s, 0, msgSize, responseSize); -} - -PendingData* PendingData::CopySD (uint32_t s, uint8_t* d) -{ // Copy, but with new size (assumes no associated data); - return new PendingData (s, d, msgSize, responseSize); -} - -void PendingData::Clear () -{ // Remove all pending data - data.clear(); - size = 0; -} - -void PendingData::Add (uint32_t s, const uint8_t* d) -{ - if (d == 0) - { - data.push_back(Create (d,s)); - } - else - { - data.push_back(Create (s)); - } - size += s; -} - -void PendingData::Add (Ptr p) -{ - data.push_back(p); - size += p->GetSize(); -} - -uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o) -{ - uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data - return SizeFromOffset (o1); // Amount of data after offset -} - -uint32_t PendingData::SizeFromOffset (uint32_t o) -{ // Find out how much data is available from offset - if (o > size) return 0; // No data at requested offset - return size - o; // Available data after offset -} - -uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o) -{ // f is the first sequence number in this data, o is offset sequence - if (o < f) - { - return 0; // HuH? Shouldn't happen - } - return o - f; -} - -Ptr PendingData::CopyFromOffset (uint32_t s, uint32_t o) -{ // Make a copy of data from starting position "o" for "s" bytes - // Return NULL if results in zero length data - uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data - if (s1 == 0) - { - return 0; // No data requested - } - if (data.size() != 0) - { // Actual data exists, make copy and return it - uint32_t count = 0; - std::vector >::size_type begin = 0; - bool beginFound = false; - std::vector >::size_type end = 0; - Ptr outPacket; - Ptr endFragment; - for (std::vector >::size_type i=0;iGetSize(); - if (!beginFound) - { - if (count > o) - { - if (count >= o + s1) //then just copy within this packet - { - Ptr toFragment = data[i]; - uint32_t packetStart = count - toFragment->GetSize(); - uint32_t packetOffset = o - packetStart; - outPacket = toFragment->CreateFragment (packetOffset, s1); - return outPacket; - } - begin = i; - beginFound = true; - Ptr toFragment = data[begin]; - uint32_t packetStart = count - toFragment->GetSize(); - uint32_t packetOffset = o - packetStart; - uint32_t fragmentLength = count - o; - outPacket = toFragment->CreateFragment (packetOffset, fragmentLength); - } - } - else - { - if (count >= o + s1) - { - end = i; - Ptr toFragment = data[end]; - uint32_t packetStart = count - toFragment->GetSize(); - uint32_t fragmentLength = o + s1 - packetStart; - endFragment = toFragment->CreateFragment(0, fragmentLength); - break; - } - } - } - for (std::vector >::size_type i=begin+1;iAddAtEnd (data[i]); - } - outPacket->AddAtEnd(endFragment); - NS_ASSERT(outPacket->GetSize() == s1); - return outPacket; - } - else - { // No actual data, just return dummy-data packet of correct size - return Create (s1); - } -} - -Ptr PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o) -{ - return CopyFromOffset (s, OffsetFromSeq(f,o)); -} - -}//namepsace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/pending-data.h --- a/src/internet-node/pending-data.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +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: Rajib Bhattacharjea -// - -// Georgia Tech Network Simulator - Data Descriptors -// George F. Riley. Georgia Tech, Spring 2002 - -#ifndef __datapdu_h__ -#define __datapdu_h__ - -#include "ns3/packet.h" -#include "pending-data.h" -#include "sequence-number.h" - -#include "ns3/ptr.h" -namespace ns3 -{ -class Packet; -//Doc:ClassXRef -class PendingData { -public: - PendingData (); - PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0); - PendingData (const std::string&); // Construct from string - PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer - PendingData (const PendingData&); // Copy constructor - virtual ~PendingData (); // Destructor - uint32_t Size () const { return size;} - // Serialization - uint32_t SSize (); // Size needed for serialization - uint8_t* Serialize (uint8_t*, uint32_t&); // Serialize to a buffer - uint8_t* Construct (uint8_t*, uint32_t&); // Construct from buffer - virtual void Clear ();// Remove all associated data - virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end - virtual void Add (Ptr p); - // Inquire available data from (f,o) sequence pair - virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&); - // Inquire available data from offset - virtual uint32_t SizeFromOffset (uint32_t); - // Available size from sequence difference - virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&); - virtual Ptr CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret packet - // Copy data, size, offset specified by sequence difference - virtual Ptr CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&); - PendingData* Copy () const; // Create a copy of this header - PendingData* CopyS (uint32_t); // Copy with new size - PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data -public: - uint32_t size; // Number of data bytes - std::vector > data; // Corresponding data (may be null) - // The next two fields allow simulated applications to exchange some info - uint32_t msgSize; // Total size of message - uint32_t responseSize;// Size of response requested -}; - -}//namepsace ns3 -#endif - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/rtt-estimator.cc --- a/src/internet-node/rtt-estimator.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,235 +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: Rajib Bhattacharjea -// - - -// Ported from: -// Georgia Tech Network Simulator - Round Trip Time Estimation Class -// George F. Riley. Georgia Tech, Spring 2002 - -// Implements several variations of round trip time estimators - -#include - -#include "rtt-estimator.h" -#include "ns3/simulator.h" -#include "ns3/double.h" - -namespace ns3{ - -NS_OBJECT_ENSURE_REGISTERED (RttEstimator); - -//RttEstimator iid -TypeId -RttEstimator::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::RttEstimator") - .SetParent () - .AddAttribute ("MaxMultiplier", - "XXX", - DoubleValue (64.0), - MakeDoubleAccessor (&RttEstimator::m_maxMultiplier), - MakeDoubleChecker ()) - .AddAttribute ("InitialEstimation", - "XXX", - TimeValue (Seconds (1.0)), - MakeTimeAccessor (&RttEstimator::est), - MakeTimeChecker ()) - ; - return tid; -} - -//RttHistory methods -RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t) - : seq (s), count (c), time (t), retx (false) - { - } - -RttHistory::RttHistory (const RttHistory& h) - : seq (h.seq), count (h.count), time (h.time), retx (h.retx) - { - } - -// Base class methods - -RttEstimator::RttEstimator () : next (1), history (), - nSamples (0), multiplier (1.0) -{ - //note next=1 everywhere since first segment will have sequence 1 -} - -RttEstimator::RttEstimator(const RttEstimator& c) - : Object (c), next(c.next), history(c.history), - m_maxMultiplier (c.m_maxMultiplier), est(c.est), nSamples(c.nSamples), - multiplier(c.multiplier) -{} - -RttEstimator::~RttEstimator () -{ -} - -void RttEstimator::SentSeq (SequenceNumber s, uint32_t c) -{ // Note that a particular sequence has been sent - if (s == next) - { // This is the next expected one, just log at end - history.push_back (RttHistory (s, c, Simulator::Now () )); - next = s + SequenceNumber (c); // Update next expected - } - else - { // This is a retransmit, find in list and mark as re-tx - for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i) - { - if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count)))) - { // Found it - i->retx = true; - // One final test..be sure this re-tx does not extend "next" - if ((s + SequenceNumber (c)) > next) - { - next = s + SequenceNumber (c); - i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist - } - break; - } - } - } -} - -Time RttEstimator::AckSeq (SequenceNumber a) -{ // An ack has been received, calculate rtt and log this measurement - // Note we use a linear search (O(n)) for this since for the common - // case the ack'ed packet will be at the head of the list - Time m = Seconds (0.0); - if (history.size () == 0) return (m); // No pending history, just exit - RttHistory& h = history.front (); - if (!h.retx && a >= (h.seq + SequenceNumber (h.count))) - { // Ok to use this sample - m = Simulator::Now () - h.time; // Elapsed time - Measurement(m); // Log the measurement - ResetMultiplier(); // Reset multiplier on valid measurement - } - // Now delete all ack history with seq <= ack - while(history.size() > 0) - { - RttHistory& h = history.front (); - if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing - history.pop_front (); // Remove - } - return m; -} - -void RttEstimator::ClearSent () -{ // Clear all history entries - next = 1; - history.clear (); -} - -void RttEstimator::IncreaseMultiplier () -{ - double a; - a = multiplier * 2.0; - double b; - b = m_maxMultiplier * 2.0; - multiplier = std::min (multiplier * 2.0, m_maxMultiplier); -} - -void RttEstimator::ResetMultiplier () -{ - multiplier = 1.0; -} - -void RttEstimator::Reset () -{ // Reset to initial state - next = 1; - est = Seconds (1.0); // XXX: we should go back to the 'initial value' here. Need to add support in Object for this. - history.clear (); // Remove all info from the history - nSamples = 0; - ResetMultiplier (); -} - - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Mean-Deviation Estimator - -NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation); - -TypeId -RttMeanDeviation::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::RttMeanDeviation") - .SetParent () - .AddConstructor () - .AddAttribute ("Gain", - "XXX", - DoubleValue (0.1), - MakeDoubleAccessor (&RttMeanDeviation::gain), - MakeDoubleChecker ()) - ; - return tid; -} - -RttMeanDeviation::RttMeanDeviation() : - variance (ns3::Seconds(0)) -{ -} - -RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c) - : RttEstimator (c), gain (c.gain), variance (c.variance) -{ -} - -void RttMeanDeviation::Measurement (Time m) -{ - if (nSamples) - { // Not first - Time err = m - est; - est = est + Scalar (gain) * err; // estimated rtt - err = Abs (err); // absolute value of error - variance = variance + Scalar (gain) * (err - variance); // variance of rtt - } - else - { // First sample - est = m; // Set estimate to current - //variance = m / 2; // And variance to current / 2 - variance = m; // try this - } - nSamples++; -} - -Time RttMeanDeviation::RetransmitTimeout () -{ - // If not enough samples, justjust return 2 times estimate - //if (nSamples < 2) return est * 2; - if (variance < est / Scalar (4.0)) - return est * Scalar (2 * multiplier); // At least twice current est - return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson -} - -Ptr RttMeanDeviation::Copy () const -{ - return CopyObject (this); -} - -void RttMeanDeviation::Reset () -{ // Reset to initial state - variance = Seconds (0.0); - RttEstimator::Reset (); -} -}//namepsace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/rtt-estimator.h --- a/src/internet-node/rtt-estimator.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +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: Rajib Bhattacharjea -// - -// Georgia Tech Network Simulator - Round Trip Time Estimation Class -// George F. Riley. Georgia Tech, Spring 2002 - -// Implements several variations of round trip time estimators - -#ifndef __rtt_estimator_h__ -#define __rtt_estimator_h__ - -#include -#include "sequence-number.h" -#include "ns3/nstime.h" -#include "ns3/object.h" - -namespace ns3 { - -class RttHistory { -public: - RttHistory (SequenceNumber s, uint32_t c, Time t); - RttHistory (const RttHistory& h); // Copy constructor -public: - SequenceNumber seq; // First sequence number in packet sent - uint32_t count; // Number of bytes sent - Time time; // Time this one was sent - bool retx; // True if this has been retransmitted -}; - -typedef std::deque RttHistory_t; - -class RttEstimator : public Object { // Base class for all RTT Estimators -public: - static TypeId GetTypeId (void); - - RttEstimator(); - RttEstimator(const RttEstimator&); // Copy constructor - virtual ~RttEstimator(); - - virtual void SentSeq(SequenceNumber, uint32_t); - virtual Time AckSeq(SequenceNumber); - virtual void ClearSent(); - virtual void Measurement(Time t) = 0; - virtual Time Estimate() = 0; - virtual Time RetransmitTimeout() = 0; - void Init(SequenceNumber s) { next = s;} - virtual Ptr Copy() const = 0; - virtual void IncreaseMultiplier(); - virtual void ResetMultiplier(); - virtual void Reset(); - -private: - SequenceNumber next; // Next expected sequence to be sent - RttHistory_t history; // List of sent packet - double m_maxMultiplier; -public: - Time est; // Current estimate - uint32_t nSamples;// Number of samples - double multiplier; // RTO Multiplier -}; - -// The "Mean-Deviation" estimator, as discussed by Van Jacobson -// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A - - //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator - //Doc:Class as described by Van Jacobson - //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A -class RttMeanDeviation : public RttEstimator { -public : - static TypeId GetTypeId (void); - - RttMeanDeviation (); - - - //Doc:Method - RttMeanDeviation (const RttMeanDeviation&); // Copy constructor - //Doc:Desc Copy constructor. - //Doc:Arg1 {\tt RttMeanDeviation} object to copy. - - void Measurement (Time); - Time Estimate () { return est;} - Time Variance () { return variance;} - Time RetransmitTimeout (); - Ptr Copy () const; - void Reset (); - void Gain (double g) { gain = g;} - -public: - double gain; // Filter gain - Time variance; // Current variance -}; -}//namespace ns3 -#endif - - - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/sequence-number.cc --- a/src/internet-node/sequence-number.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +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: Rajib Bhattacharjea -// - - -// Ported from: -// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers -// George F. Riley. Georgia Tech, Spring 2002 - -// Class to manage arithmetic operations on sequence numbers (mod 2^32) - -#include "sequence-number.h" - -bool operator< (const SequenceNumber l, const SequenceNumber r) -{ // Account for 32 bit rollover - if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover - return l.seq < r.seq; -} - -bool operator<= (const SequenceNumber l, const SequenceNumber r) -{ // Account for 32 bit rollover - if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover - return l.seq <= r.seq; -} - -bool operator> (const SequenceNumber l, const SequenceNumber r) -{ // Account for 32 bit rollover - if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover - return l.seq > r.seq; -} - -bool operator>= (const SequenceNumber l, const SequenceNumber r) -{ // Account for 32 bit rollover - if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover - return l.seq >= r.seq; -} - -// Non-Member Arithmetic operators -SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r) -{ - return SequenceNumber (l.seq + r.seq); -} - -SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r) -{ // This assumes l is always bigger than r (allows for rollover) - if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq); - return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1); // Adjust for rollover -} - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/sequence-number.h --- a/src/internet-node/sequence-number.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +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: Rajib Bhattacharjea -// - -// Ported from: -// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers -// George F. Riley. Georgia Tech, Spring 2002 - -// Class to manage arithmetic operations on sequence numbers (mod 2^32) - -#ifndef __seq_h__ -#define __seq_h__ - -#include - -#define MAX_SEQ ((uint32_t)0xffffffff) - -class SequenceNumber { -public: - SequenceNumber () : seq(0) { } - SequenceNumber (const uint32_t s) : seq (s) { } - - operator uint32_t () const { return seq;} - - SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;} - - SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;} - SequenceNumber operator++ () { seq++; return *this;} - SequenceNumber operator++ (int) { SequenceNumber ss (seq); seq++; return ss;} - SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;} - SequenceNumber operator-- () { seq--; return *this;} - SequenceNumber operator-- (int) { SequenceNumber ss (seq); seq--; return ss;} -public: - uint32_t seq; -}; - -// Comparison operators - -bool operator< (const SequenceNumber l, const SequenceNumber r); -bool operator<= (const SequenceNumber l, const SequenceNumber r); -bool operator> (const SequenceNumber l, const SequenceNumber r); -bool operator>= (const SequenceNumber l, const SequenceNumber r); - -// Non-member arithmetic operators -SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r); -SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r); - -#endif - - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/sgi-hashmap.h --- a/src/internet-node/sgi-hashmap.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* This code snippet was ripped out of the gcc - * documentation and slightly modified to work - * with gcc 4.x - */ -#ifndef SGI_HASHMAP_H -#define SGI_HASHMAP_H - -/* To use gcc extensions. - */ -#ifdef __GNUC__ - #if __GNUC__ < 3 - #include -namespace sgi { using ::hash_map; }; // inherit globals - #else - #if __GNUC__ < 4 - #include - #if __GNUC_MINOR__ == 0 -namespace sgi = std; // GCC 3.0 - #else -namespace sgi = ::__gnu_cxx; // GCC 3.1 and later - #endif - #else // gcc 4.x and later - #include - namespace sgi = ::__gnu_cxx; - #endif - #endif -#else // ... there are other compilers, right? -namespace sgi = std; -#endif - - -#endif /* SGI_HASHMAP_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-header.cc --- a/src/internet-node/tcp-header.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -/* -*- 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 - */ - -#include -#include -#include "tcp-socket-impl.h" -#include "tcp-header.h" -#include "ns3/buffer.h" - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (TcpHeader); - -bool TcpHeader::m_calcChecksum = false; - -TcpHeader::TcpHeader () - : m_sourcePort (0), - m_destinationPort (0), - m_sequenceNumber (0), - m_ackNumber (0), - m_length (5), - m_flags (0), - m_windowSize (0xffff), - m_checksum (0), - m_urgentPointer (0) -{} - -TcpHeader::~TcpHeader () -{} - -void -TcpHeader::EnableChecksums (void) -{ - m_calcChecksum = true; -} - -void TcpHeader::SetSourcePort (uint16_t port) -{ - m_sourcePort = port; -} -void TcpHeader::SetDestinationPort (uint16_t port) -{ - m_destinationPort = port; -} -void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber) -{ - m_sequenceNumber = sequenceNumber; -} -void TcpHeader::SetAckNumber (SequenceNumber ackNumber) -{ - m_ackNumber = ackNumber; -} -void TcpHeader::SetLength (uint8_t length) -{ - m_length = length; -} -void TcpHeader::SetFlags (uint8_t flags) -{ - m_flags = flags; -} -void TcpHeader::SetWindowSize (uint16_t windowSize) -{ - m_windowSize = windowSize; -} -void TcpHeader::SetChecksum (uint16_t checksum) -{ - m_checksum = checksum; -} -void TcpHeader::SetUrgentPointer (uint16_t urgentPointer) -{ - m_urgentPointer = urgentPointer; -} - -uint16_t TcpHeader::GetSourcePort () const -{ - return m_sourcePort; -} -uint16_t TcpHeader::GetDestinationPort () const -{ - return m_destinationPort; -} -SequenceNumber TcpHeader::GetSequenceNumber () const -{ - return m_sequenceNumber; -} -SequenceNumber TcpHeader::GetAckNumber () const -{ - return m_ackNumber; -} -uint8_t TcpHeader::GetLength () const -{ - return m_length; -} -uint8_t TcpHeader::GetFlags () const -{ - return m_flags; -} -uint16_t TcpHeader::GetWindowSize () const -{ - return m_windowSize; -} -uint16_t TcpHeader::GetChecksum () const -{ - return m_checksum; -} -uint16_t TcpHeader::GetUrgentPointer () const -{ - return m_urgentPointer; -} - -void -TcpHeader::InitializeChecksum (Ipv4Address source, - Ipv4Address destination, - uint8_t protocol) -{ - m_checksum = 0; -//XXX requires peeking into IP to get length of the TCP segment -} - -TypeId -TcpHeader::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::TcpHeader") - .SetParent
() - .AddConstructor () - ; - return tid; -} -TypeId -TcpHeader::GetInstanceTypeId (void) const -{ - return GetTypeId (); -} -void TcpHeader::Print (std::ostream &os) const -{ - os << m_sourcePort << " > " << m_destinationPort; - if(m_flags!=0) - { - os<<" ["; - if((m_flags & FIN) != 0) - { - os<<" FIN "; - } - if((m_flags & SYN) != 0) - { - os<<" SYN "; - } - if((m_flags & RST) != 0) - { - os<<" RST "; - } - if((m_flags & PSH) != 0) - { - os<<" PSH "; - } - if((m_flags & ACK) != 0) - { - os<<" ACK "; - } - if((m_flags & URG) != 0) - { - os<<" URG "; - } - os<<"]"; - } - os<<" Seq="< - */ - -#ifndef TCP_HEADER_H -#define TCP_HEADER_H - -#include -#include "ns3/header.h" -#include "ns3/buffer.h" -#include "ns3/tcp-socket-factory.h" -#include "ns3/ipv4-address.h" -#include "ns3/sequence-number.h" - -namespace ns3 { - -class TcpHeader : public Header -{ -public: - TcpHeader (); - virtual ~TcpHeader (); - - /** - * \brief Enable checksum calculation for TCP (XXX currently has no effect) - */ - static void EnableChecksums (void); -//Setters - /** - * \param port The source port for this TcpHeader - */ - void SetSourcePort (uint16_t port); - /** - * \param port the destination port for this TcpHeader - */ - void SetDestinationPort (uint16_t port); - /** - * \param sequenceNumber the sequence number for this TcpHeader - */ - void SetSequenceNumber (SequenceNumber sequenceNumber); - /** - * \param ackNumber the ACK number for this TcpHeader - */ - void SetAckNumber (SequenceNumber ackNumber); - /** - * \param length the length of this TcpHeader - */ - void SetLength (uint8_t length); - /** - * \param flags the flags for this TcpHeader - */ - void SetFlags (uint8_t flags); - /** - * \param windowSize the window size for this TcpHeader - */ - void SetWindowSize (uint16_t windowSize); - /** - * \param checksum the checksum for this TcpHeader - */ - void SetChecksum (uint16_t checksum); - /** - * \param urgentPointer the urgent pointer for this TcpHeader - */ - void SetUrgentPointer (uint16_t urgentPointer); - - -//Getters - /** - * \return The source port for this TcpHeader - */ - uint16_t GetSourcePort () const; - /** - * \return the destination port for this TcpHeader - */ - uint16_t GetDestinationPort () const; - /** - * \return the sequence number for this TcpHeader - */ - SequenceNumber GetSequenceNumber () const; - /** - * \return the ACK number for this TcpHeader - */ - SequenceNumber GetAckNumber () const; - /** - * \return the length of this TcpHeader - */ - uint8_t GetLength () const; - /** - * \return the flags for this TcpHeader - */ - uint8_t GetFlags () const; - /** - * \return the window size for this TcpHeader - */ - uint16_t GetWindowSize () const; - /** - * \return the checksum for this TcpHeader - */ - uint16_t GetChecksum () const; - /** - * \return the urgent pointer for this TcpHeader - */ - uint16_t GetUrgentPointer () const; - - /** - * \param source the ip source to use in the underlying - * ip packet. - * \param destination the ip destination to use in the - * underlying ip packet. - * \param protocol the protocol number to use in the underlying - * ip packet. - * - * If you want to use tcp checksums, you should call this - * method prior to adding the header to a packet. - */ - void InitializeChecksum (Ipv4Address source, - Ipv4Address destination, - uint8_t protocol); - - typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16, - URG = 32} Flags_t; - - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - virtual void Print (std::ostream &os) const; - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (Buffer::Iterator start) const; - virtual uint32_t Deserialize (Buffer::Iterator start); - -private: - uint16_t m_sourcePort; - uint16_t m_destinationPort; - uint32_t m_sequenceNumber; - uint32_t m_ackNumber; - uint8_t m_length; // really a uint4_t - uint8_t m_flags; // really a uint6_t - uint16_t m_windowSize; - uint16_t m_checksum; - uint16_t m_urgentPointer; - - static bool m_calcChecksum; -}; - -}; // namespace ns3 - -#endif /* TCP_HEADER */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-l4-protocol.cc --- a/src/internet-node/tcp-l4-protocol.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,526 +0,0 @@ -/* -*- 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 - */ - -#include "ns3/assert.h" -#include "ns3/log.h" -#include "ns3/nstime.h" - -#include "ns3/packet.h" -#include "ns3/node.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-impl.h" - -#include "tcp-typedefs.h" - -#include -#include -#include - -NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol"); - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol); - -//State Machine things -------------------------------------------------------- -TcpStateMachine::TcpStateMachine() - : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)), - eV (MAX_FLAGS) -{ - NS_LOG_FUNCTION_NOARGS (); - - // Create the state table - // Closed state - aT[CLOSED][APP_LISTEN] = SA (LISTEN, NO_ACT); - aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX); - aT[CLOSED][APP_SEND] = SA (CLOSED, RST_TX); - aT[CLOSED][SEQ_RECV] = SA (CLOSED, NO_ACT); - aT[CLOSED][APP_CLOSE] = SA (CLOSED, NO_ACT); - aT[CLOSED][TIMEOUT] = SA (CLOSED, RST_TX); - aT[CLOSED][ACK_RX] = SA (CLOSED, RST_TX); - aT[CLOSED][SYN_RX] = SA (CLOSED, RST_TX); - aT[CLOSED][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[CLOSED][FIN_RX] = SA (CLOSED, RST_TX); - aT[CLOSED][FIN_ACK_RX] = SA (CLOSED, RST_TX); - aT[CLOSED][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[CLOSED][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // Listen State - // For the listen state, anything other than CONNECT or SEND - // is simply ignored....this likely indicates the child TCP - // has finished and issued unbind call, but the remote end - // has not yet closed. - aT[LISTEN][APP_LISTEN] = SA (LISTEN, NO_ACT); - aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX); - aT[LISTEN][APP_SEND] = SA (SYN_SENT, SYN_TX); - aT[LISTEN][SEQ_RECV] = SA (LISTEN, NO_ACT); - aT[LISTEN][APP_CLOSE] = SA (CLOSED, NO_ACT); - aT[LISTEN][TIMEOUT] = SA (LISTEN, NO_ACT); - aT[LISTEN][ACK_RX] = SA (LISTEN, NO_ACT); - aT[LISTEN][SYN_RX] = SA (LISTEN, SYN_ACK_TX);//stay in listen and fork - aT[LISTEN][SYN_ACK_RX] = SA (LISTEN, NO_ACT); - aT[LISTEN][FIN_RX] = SA (LISTEN, NO_ACT); - aT[LISTEN][FIN_ACK_RX] = SA (LISTEN, NO_ACT); - aT[LISTEN][RST_RX] = SA (LISTEN, NO_ACT); - aT[LISTEN][BAD_FLAGS] = SA (LISTEN, NO_ACT); - - // Syn Sent State - aT[SYN_SENT][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT, SYN_TX); - aT[SYN_SENT][APP_SEND] = SA (SYN_SENT, NO_ACT); - aT[SYN_SENT][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX); - aT[SYN_SENT][APP_CLOSE] = SA (CLOSED, RST_TX); - aT[SYN_SENT][TIMEOUT] = SA (CLOSED, NO_ACT); - aT[SYN_SENT][ACK_RX] = SA (SYN_SENT, NO_ACT); - aT[SYN_SENT][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); - aT[SYN_SENT][SYN_ACK_RX] = SA (ESTABLISHED, ACK_TX_1); - aT[SYN_SENT][FIN_RX] = SA (CLOSED, RST_TX); - aT[SYN_SENT][FIN_ACK_RX] = SA (CLOSED, RST_TX); - aT[SYN_SENT][RST_RX] = SA (CLOSED, APP_NOTIFY); - aT[SYN_SENT][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // Syn Recvd State - aT[SYN_RCVD][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][APP_SEND] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX); - aT[SYN_RCVD][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX); - aT[SYN_RCVD][TIMEOUT] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][ACK_RX] = SA (ESTABLISHED, SERV_NOTIFY); - aT[SYN_RCVD][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); - aT[SYN_RCVD][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][FIN_RX] = SA (CLOSED, RST_TX); - aT[SYN_RCVD][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE); - aT[SYN_RCVD][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[SYN_RCVD][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // Established State - aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED, RST_TX); - aT[ESTABLISHED][APP_SEND] = SA (ESTABLISHED,TX_DATA); - aT[ESTABLISHED][SEQ_RECV] = SA (ESTABLISHED,NEW_SEQ_RX); - aT[ESTABLISHED][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX); - aT[ESTABLISHED][TIMEOUT] = SA (ESTABLISHED,RETX); - aT[ESTABLISHED][ACK_RX] = SA (ESTABLISHED,NEW_ACK); - aT[ESTABLISHED][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); - aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT); - aT[ESTABLISHED][FIN_RX] = SA (CLOSE_WAIT, PEER_CLOSE); - aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE); - aT[ESTABLISHED][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[ESTABLISHED][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // Close Wait State - aT[CLOSE_WAIT][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT, SYN_TX); - aT[CLOSE_WAIT][APP_SEND] = SA (CLOSE_WAIT, TX_DATA); - aT[CLOSE_WAIT][SEQ_RECV] = SA (CLOSE_WAIT, NEW_SEQ_RX); - aT[CLOSE_WAIT][APP_CLOSE] = SA (LAST_ACK, FIN_ACK_TX); - aT[CLOSE_WAIT][TIMEOUT] = SA (CLOSE_WAIT, NO_ACT); - aT[CLOSE_WAIT][ACK_RX] = SA (CLOSE_WAIT, NO_ACT); - aT[CLOSE_WAIT][SYN_RX] = SA (CLOSED, RST_TX); - aT[CLOSE_WAIT][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[CLOSE_WAIT][FIN_RX] = SA (CLOSE_WAIT, ACK_TX); - aT[CLOSE_WAIT][FIN_ACK_RX] = SA (CLOSE_WAIT, ACK_TX); - aT[CLOSE_WAIT][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[CLOSE_WAIT][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // Close Last Ack State - aT[LAST_ACK][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT, SYN_TX); - aT[LAST_ACK][APP_SEND] = SA (CLOSED, RST_TX); - aT[LAST_ACK][SEQ_RECV] = SA (LAST_ACK, NEW_SEQ_RX); - aT[LAST_ACK][APP_CLOSE] = SA (CLOSED, NO_ACT); - aT[LAST_ACK][TIMEOUT] = SA (CLOSED, NO_ACT); - aT[LAST_ACK][ACK_RX] = SA (CLOSED, APP_CLOSED); - aT[LAST_ACK][SYN_RX] = SA (CLOSED, RST_TX); - aT[LAST_ACK][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[LAST_ACK][FIN_RX] = SA (LAST_ACK, FIN_ACK_TX); - aT[LAST_ACK][FIN_ACK_RX] = SA (CLOSED, NO_ACT); - aT[LAST_ACK][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[LAST_ACK][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // FIN_WAIT_1 state - aT[FIN_WAIT_1][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_1][APP_SEND] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_1][SEQ_RECV] = SA (FIN_WAIT_1, NEW_SEQ_RX); - aT[FIN_WAIT_1][APP_CLOSE] = SA (FIN_WAIT_1, NO_ACT); - aT[FIN_WAIT_1][TIMEOUT] = SA (FIN_WAIT_1, NO_ACT); - aT[FIN_WAIT_1][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK); - aT[FIN_WAIT_1][SYN_RX] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_1][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_1][FIN_RX] = SA (CLOSING, ACK_TX); - aT[FIN_WAIT_1][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX); - aT[FIN_WAIT_1][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[FIN_WAIT_1][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // FIN_WAIT_2 state - aT[FIN_WAIT_2][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_2][APP_SEND] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_2][SEQ_RECV] = SA (FIN_WAIT_2, NEW_SEQ_RX); - aT[FIN_WAIT_2][APP_CLOSE] = SA (FIN_WAIT_2, NO_ACT); - aT[FIN_WAIT_2][TIMEOUT] = SA (FIN_WAIT_2, NO_ACT); - aT[FIN_WAIT_2][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK); - aT[FIN_WAIT_2][SYN_RX] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_2][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[FIN_WAIT_2][FIN_RX] = SA (TIMED_WAIT, ACK_TX); - aT[FIN_WAIT_2][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX); - aT[FIN_WAIT_2][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[FIN_WAIT_2][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // CLOSING state - aT[CLOSING][APP_LISTEN] = SA (CLOSED, RST_TX); - aT[CLOSING][APP_CONNECT] = SA (CLOSED, RST_TX); - aT[CLOSING][APP_SEND] = SA (CLOSED, RST_TX); - aT[CLOSING][SEQ_RECV] = SA (CLOSED, RST_TX); - aT[CLOSING][APP_CLOSE] = SA (CLOSED, RST_TX); - aT[CLOSING][TIMEOUT] = SA (CLOSING, NO_ACT); - aT[CLOSING][ACK_RX] = SA (TIMED_WAIT, NO_ACT); - aT[CLOSING][SYN_RX] = SA (CLOSED, RST_TX); - aT[CLOSING][SYN_ACK_RX] = SA (CLOSED, RST_TX); - aT[CLOSING][FIN_RX] = SA (CLOSED, ACK_TX); - aT[CLOSING][FIN_ACK_RX] = SA (CLOSED, ACK_TX); - aT[CLOSING][RST_RX] = SA (CLOSED, CANCEL_TM); - aT[CLOSING][BAD_FLAGS] = SA (CLOSED, RST_TX); - - // TIMED_WAIT state - aT[TIMED_WAIT][APP_LISTEN] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][APP_SEND] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][SEQ_RECV] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][APP_CLOSE] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][TIMEOUT] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][ACK_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][SYN_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][SYN_ACK_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][FIN_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][FIN_ACK_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][RST_RX] = SA (TIMED_WAIT, NO_ACT); - aT[TIMED_WAIT][BAD_FLAGS] = SA (TIMED_WAIT, NO_ACT); - - // Create the flags lookup table - eV[ 0x00] = SEQ_RECV; // No flags - eV[ 0x01] = FIN_RX; // Fin - eV[ 0x02] = SYN_RX; // Syn - eV[ 0x03] = BAD_FLAGS; // Illegal - eV[ 0x04] = RST_RX; // Rst - eV[ 0x05] = BAD_FLAGS; // Illegal - eV[ 0x06] = BAD_FLAGS; // Illegal - eV[ 0x07] = BAD_FLAGS; // Illegal - eV[ 0x08] = SEQ_RECV; // Psh flag is not used - eV[ 0x09] = FIN_RX; // Fin - eV[ 0x0a] = SYN_RX; // Syn - eV[ 0x0b] = BAD_FLAGS; // Illegal - eV[ 0x0c] = RST_RX; // Rst - eV[ 0x0d] = BAD_FLAGS; // Illegal - eV[ 0x0e] = BAD_FLAGS; // Illegal - eV[ 0x0f] = BAD_FLAGS; // Illegal - eV[ 0x10] = ACK_RX; // Ack - eV[ 0x11] = FIN_ACK_RX;// Fin/Ack - eV[ 0x12] = SYN_ACK_RX;// Syn/Ack - eV[ 0x13] = BAD_FLAGS; // Illegal - eV[ 0x14] = RST_RX; // Rst - eV[ 0x15] = BAD_FLAGS; // Illegal - eV[ 0x16] = BAD_FLAGS; // Illegal - eV[ 0x17] = BAD_FLAGS; // Illegal - eV[ 0x18] = ACK_RX; // Ack - eV[ 0x19] = FIN_ACK_RX;// Fin/Ack - eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack - eV[ 0x1b] = BAD_FLAGS; // Illegal - eV[ 0x1c] = RST_RX; // Rst - eV[ 0x1d] = BAD_FLAGS; // Illegal - eV[ 0x1e] = BAD_FLAGS; // Illegal - eV[ 0x1f] = BAD_FLAGS; // Illegal - eV[ 0x20] = SEQ_RECV; // No flags (Urgent not presently used) - eV[ 0x21] = FIN_RX; // Fin - eV[ 0x22] = SYN_RX; // Syn - eV[ 0x23] = BAD_FLAGS; // Illegal - eV[ 0x24] = RST_RX; // Rst - eV[ 0x25] = BAD_FLAGS; // Illegal - eV[ 0x26] = BAD_FLAGS; // Illegal - eV[ 0x27] = BAD_FLAGS; // Illegal - eV[ 0x28] = SEQ_RECV; // Psh flag is not used - eV[ 0x29] = FIN_RX; // Fin - eV[ 0x2a] = SYN_RX; // Syn - eV[ 0x2b] = BAD_FLAGS; // Illegal - eV[ 0x2c] = RST_RX; // Rst - eV[ 0x2d] = BAD_FLAGS; // Illegal - eV[ 0x2e] = BAD_FLAGS; // Illegal - eV[ 0x2f] = BAD_FLAGS; // Illegal - eV[ 0x30] = ACK_RX; // Ack (Urgent not used) - eV[ 0x31] = FIN_ACK_RX;// Fin/Ack - eV[ 0x32] = SYN_ACK_RX;// Syn/Ack - eV[ 0x33] = BAD_FLAGS; // Illegal - eV[ 0x34] = RST_RX; // Rst - eV[ 0x35] = BAD_FLAGS; // Illegal - eV[ 0x36] = BAD_FLAGS; // Illegal - eV[ 0x37] = BAD_FLAGS; // Illegal - eV[ 0x38] = ACK_RX; // Ack - eV[ 0x39] = FIN_ACK_RX;// Fin/Ack - eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack - eV[ 0x3b] = BAD_FLAGS; // Illegal - eV[ 0x3c] = RST_RX; // Rst - eV[ 0x3d] = BAD_FLAGS; // Illegal - eV[ 0x3e] = BAD_FLAGS; // Illegal - eV[ 0x3f] = BAD_FLAGS; // Illegal -} - -SA TcpStateMachine::Lookup (States_t s, Events_t e) -{ - NS_LOG_FUNCTION (this << s << e); - return aT[s][e]; -} - -Events_t TcpStateMachine::FlagsEvent (uint8_t f) -{ - NS_LOG_FUNCTION (this << f); - // Lookup event from flags - if (f >= MAX_FLAGS) return BAD_FLAGS; - return eV[f]; // Look up flags event -} - -static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine - -//TcpL4Protocol stuff---------------------------------------------------------- - - -/* see http://www.iana.org/assignments/protocol-numbers */ -const uint8_t TcpL4Protocol::PROT_NUMBER = 6; - -ObjectFactory -TcpL4Protocol::GetDefaultRttEstimatorFactory (void) -{ - ObjectFactory factory; - factory.SetTypeId (RttMeanDeviation::GetTypeId ()); - return factory; -} - -TypeId -TcpL4Protocol::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::TcpL4Protocol") - .SetParent () - .AddAttribute ("RttEstimatorFactory", - "How RttEstimator objects are created.", - ObjectFactoryValue (GetDefaultRttEstimatorFactory ()), - MakeObjectFactoryAccessor (&TcpL4Protocol::m_rttFactory), - MakeObjectFactoryChecker ()) - ; - return tid; -} - -TcpL4Protocol::TcpL4Protocol () - : m_endPoints (new Ipv4EndPointDemux ()) -{ - NS_LOG_FUNCTION_NOARGS (); - NS_LOG_LOGIC("Made a TcpL4Protocol "< node) -{ - m_node = node; -} - -int -TcpL4Protocol::GetProtocolNumber (void) const -{ - return PROT_NUMBER; -} -int -TcpL4Protocol::GetVersion (void) const -{ - return 2; -} - -void -TcpL4Protocol::DoDispose (void) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_endPoints != 0) - { - delete m_endPoints; - m_endPoints = 0; - } - m_node = 0; - Ipv4L4Protocol::DoDispose (); -} - -Ptr -TcpL4Protocol::CreateSocket (void) -{ - NS_LOG_FUNCTION_NOARGS (); - Ptr rtt = m_rttFactory.Create (); - Ptr socket = CreateObject (); - socket->SetNode (m_node); - socket->SetTcp (this); - socket->SetRtt (rtt); - return socket; -} - -Ipv4EndPoint * -TcpL4Protocol::Allocate (void) -{ - NS_LOG_FUNCTION_NOARGS (); - return m_endPoints->Allocate (); -} - -Ipv4EndPoint * -TcpL4Protocol::Allocate (Ipv4Address address) -{ - NS_LOG_FUNCTION (this << address); - return m_endPoints->Allocate (address); -} - -Ipv4EndPoint * -TcpL4Protocol::Allocate (uint16_t port) -{ - NS_LOG_FUNCTION (this << port); - return m_endPoints->Allocate (port); -} - -Ipv4EndPoint * -TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port) -{ - NS_LOG_FUNCTION (this << address << port); - return m_endPoints->Allocate (address, port); -} - -Ipv4EndPoint * -TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) -{ - NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); - return m_endPoints->Allocate (localAddress, localPort, - peerAddress, peerPort); -} - -void -TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) -{ - NS_LOG_FUNCTION (this << endPoint); - m_endPoints->DeAllocate (endPoint); -} - -void -TcpL4Protocol::Receive (Ptr packet, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface) -{ - NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface); - - TcpHeader tcpHeader; - //these two do a peek, so that the packet can be forwarded up - packet->RemoveHeader (tcpHeader); - NS_LOG_LOGIC("TcpL4Protocol " << this - << " receiving seq " << tcpHeader.GetSequenceNumber() - << " ack " << tcpHeader.GetAckNumber() - << " flags "<< std::hex << (int)tcpHeader.GetFlags() << std::dec - << " data size " << packet->GetSize()); - packet->AddHeader (tcpHeader); - NS_LOG_LOGIC ("TcpL4Protocol "<Lookup (destination, tcpHeader.GetDestinationPort (), - source, tcpHeader.GetSourcePort (),incomingInterface); - if (endPoints.empty ()) - { - NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<ForwardUp (packet, source, tcpHeader.GetSourcePort ()); -} - -void -TcpL4Protocol::Send (Ptr packet, - Ipv4Address saddr, Ipv4Address daddr, - uint16_t sport, uint16_t dport) -{ - NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport); - - TcpHeader tcpHeader; - tcpHeader.SetDestinationPort (dport); - tcpHeader.SetSourcePort (sport); - tcpHeader.InitializeChecksum (saddr, - daddr, - PROT_NUMBER); - tcpHeader.SetFlags (TcpHeader::ACK); - tcpHeader.SetAckNumber (0); - - packet->AddHeader (tcpHeader); - - Ptr ipv4 = - m_node->GetObject (); - if (ipv4 != 0) - { - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); - } -} - -void -TcpL4Protocol::SendPacket (Ptr packet, TcpHeader outgoingHeader, - Ipv4Address saddr, Ipv4Address daddr) -{ - NS_LOG_LOGIC("TcpL4Protocol " << this - << " sending seq " << outgoingHeader.GetSequenceNumber() - << " ack " << outgoingHeader.GetAckNumber() - << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec - << " data size " << packet->GetSize()); - NS_LOG_FUNCTION (this << packet << saddr << daddr); - // XXX outgoingHeader cannot be logged - - outgoingHeader.SetLength (5); //header length in units of 32bit words - outgoingHeader.SetChecksum (0); //XXX - outgoingHeader.SetUrgentPointer (0); //XXX - - packet->AddHeader (outgoingHeader); - - Ptr ipv4 = - m_node->GetObject (); - if (ipv4 != 0) - { - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); - } - else - NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface"); -} - -}; // namespace ns3 - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-l4-protocol.h --- a/src/internet-node/tcp-l4-protocol.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* -*- 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 - */ - -#ifndef TCP_L4_PROTOCOL_H -#define TCP_L4_PROTOCOL_H - -#include - -#include "ns3/packet.h" -#include "ns3/ipv4-address.h" -#include "ns3/ptr.h" -#include "ns3/object-factory.h" -#include "ipv4-end-point-demux.h" -#include "ipv4-l4-protocol.h" -#include "ipv4-interface.h" - -#include "tcp-header.h" -#include "tcp-typedefs.h" - -namespace ns3 { - -class Node; -class Socket; -class TcpHeader; -/** - * \brief Implementation of the TCP protocol - */ -class TcpL4Protocol : public Ipv4L4Protocol { -public: - static TypeId GetTypeId (void); - static const uint8_t PROT_NUMBER; - /** - * \brief Constructor - */ - TcpL4Protocol (); - virtual ~TcpL4Protocol (); - - void SetNode (Ptr node); - - virtual int GetProtocolNumber (void) const; - virtual int GetVersion (void) const; - - /** - * \return A smart Socket pointer to a TcpSocketImpl, allocated by this instance - * of the TCP protocol - */ - Ptr CreateSocket (void); - - Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); - Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort); - - void DeAllocate (Ipv4EndPoint *endPoint); - -// // called by TcpSocketImpl. -// bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr, -// uint16_t sport, uint16_t dport); - - /** - * \brief Send a packet via TCP - * \param packet The packet to send - * \param saddr The source Ipv4Address - * \param daddr The destination Ipv4Address - * \param sport The source port number - * \param dport The destination port number - */ - void Send (Ptr packet, - Ipv4Address saddr, Ipv4Address daddr, - uint16_t sport, uint16_t dport); - /** - * \brief Recieve a packet up the protocol stack - * \param p The Packet to dump the contents into - * \param source The source's Ipv4Address - * \param destination The destinations Ipv4Address - * \param incomingInterface The Ipv4Interface it was received on - */ - virtual void Receive (Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr incomingInterface); - -protected: - virtual void DoDispose (void); -private: - Ptr m_node; - Ipv4EndPointDemux *m_endPoints; - ObjectFactory m_rttFactory; -private: - friend class TcpSocketImpl; - void SendPacket (Ptr, TcpHeader, - Ipv4Address, Ipv4Address); - static ObjectFactory GetDefaultRttEstimatorFactory (void); -}; - -}; // namespace ns3 - -#endif /* TCP_L4_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-socket-factory-impl.cc --- a/src/internet-node/tcp-socket-factory-impl.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* -*- 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 - */ -#include "tcp-socket-factory-impl.h" -#include "tcp-l4-protocol.h" -#include "ns3/socket.h" -#include "ns3/assert.h" - -namespace ns3 { - -TcpSocketFactoryImpl::TcpSocketFactoryImpl () - : m_tcp (0) -{} -TcpSocketFactoryImpl::~TcpSocketFactoryImpl () -{ - NS_ASSERT (m_tcp == 0); -} - -void -TcpSocketFactoryImpl::SetTcp (Ptr tcp) -{ - m_tcp = tcp; -} - -Ptr -TcpSocketFactoryImpl::CreateSocket (void) -{ - return m_tcp->CreateSocket (); -} - -void -TcpSocketFactoryImpl::DoDispose (void) -{ - m_tcp = 0; - TcpSocketFactory::DoDispose (); -} - -} // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-socket-factory-impl.h --- a/src/internet-node/tcp-socket-factory-impl.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* -*- 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 - */ -#ifndef TCP_SOCKET_FACTORY_IMPL_H -#define TCP_SOCKET_FACTORY_IMPL_H - -#include "ns3/tcp-socket-factory.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class TcpL4Protocol; - -/** - * \ingroup internetNode - * \defgroup Tcp Tcp - */ -/** - * \ingroup Tcp - * \section Tcp Overview - * - * The TCP code in ns3::InternetNode is ported from the - * - * Georgia Tech Network Simulator (GTNetS). - * - * Most of the logic is in class ns3::TcpSocketImpl. - */ -class TcpSocketFactoryImpl : public TcpSocketFactory -{ -public: - TcpSocketFactoryImpl (); - virtual ~TcpSocketFactoryImpl (); - - void SetTcp (Ptr tcp); - - virtual Ptr CreateSocket (void); - -protected: - virtual void DoDispose (void); -private: - Ptr m_tcp; -}; - -} // namespace ns3 - -#endif /* TCP_SOCKET_FACTORY_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-socket-impl.cc --- a/src/internet-node/tcp-socket-impl.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1448 +0,0 @@ -/* -*- 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 - */ - - -#include "ns3/node.h" -#include "ns3/inet-socket-address.h" -#include "ns3/log.h" -#include "ns3/ipv4.h" -#include "tcp-socket-impl.h" -#include "tcp-l4-protocol.h" -#include "ipv4-end-point.h" -#include "ipv4-l4-demux.h" -#include "ns3/simulation-singleton.h" -#include "tcp-typedefs.h" -#include "ns3/simulator.h" -#include "ns3/packet.h" -#include "ns3/uinteger.h" -#include "ns3/trace-source-accessor.h" - -#include - -NS_LOG_COMPONENT_DEFINE ("TcpSocketImpl"); - -using namespace std; - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (TcpSocketImpl); - -TypeId -TcpSocketImpl::GetTypeId () -{ - static TypeId tid = TypeId("ns3::TcpSocketImpl") - .SetParent () - .AddTraceSource ("CongestionWindow", - "The TCP connection's congestion window", - MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd)) - ; - return tid; -} - - TcpSocketImpl::TcpSocketImpl () - : m_skipRetxResched (false), - m_dupAckCount (0), - m_delAckCount (0), - m_endPoint (0), - m_node (0), - m_tcp (0), - m_errno (ERROR_NOTERROR), - m_shutdownSend (false), - m_shutdownRecv (false), - m_connected (false), - m_state (CLOSED), - m_closeNotified (false), - m_closeRequestNotified (false), - m_closeOnEmpty (false), - m_pendingClose (false), - m_nextTxSequence (0), - m_highTxMark (0), - m_highestRxAck (0), - m_lastRxAck (0), - m_nextRxSequence (0), - m_pendingData (0), - m_rtt (0), - m_lastMeasuredRtt (Seconds(0.0)), - m_rxAvailable (0), - m_wouldBlock (false) -{ - NS_LOG_FUNCTION (this); -} - -TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock) - : TcpSocket(sock), //copy the base class callbacks - m_skipRetxResched (sock.m_skipRetxResched), - m_dupAckCount (sock.m_dupAckCount), - m_delAckCount (0), - m_delAckMaxCount (sock.m_delAckMaxCount), - m_delAckTimeout (sock.m_delAckTimeout), - m_endPoint (0), - m_node (sock.m_node), - m_tcp (sock.m_tcp), - m_remoteAddress (sock.m_remoteAddress), - m_remotePort (sock.m_remotePort), - m_localAddress (sock.m_localAddress), - m_localPort (sock.m_localPort), - m_errno (sock.m_errno), - m_shutdownSend (sock.m_shutdownSend), - m_shutdownRecv (sock.m_shutdownRecv), - m_connected (sock.m_connected), - m_state (sock.m_state), - m_closeNotified (sock.m_closeNotified), - m_closeRequestNotified (sock.m_closeRequestNotified), - m_closeOnEmpty (sock.m_closeOnEmpty), - m_pendingClose (sock.m_pendingClose), - m_nextTxSequence (sock.m_nextTxSequence), - m_highTxMark (sock.m_highTxMark), - m_highestRxAck (sock.m_highestRxAck), - m_lastRxAck (sock.m_lastRxAck), - m_nextRxSequence (sock.m_nextRxSequence), - m_pendingData (0), - m_segmentSize (sock.m_segmentSize), - m_rxWindowSize (sock.m_rxWindowSize), - m_advertisedWindowSize (sock.m_advertisedWindowSize), - m_cWnd (sock.m_cWnd), - m_ssThresh (sock.m_ssThresh), - m_initialCWnd (sock.m_initialCWnd), - m_rtt (0), - m_lastMeasuredRtt (Seconds(0.0)), - m_cnTimeout (sock.m_cnTimeout), - m_cnCount (sock.m_cnCount), - m_rxAvailable (0), - m_wouldBlock (false), - m_sndBufSize (sock.m_sndBufSize), - m_rcvBufSize(sock.m_rcvBufSize) -{ - NS_LOG_FUNCTION_NOARGS (); - NS_LOG_LOGIC("Invoked the copy constructor"); - //copy the pending data if necessary - if(sock.m_pendingData) - { - m_pendingData = sock.m_pendingData->Copy(); - } - //copy the rtt if necessary - if (sock.m_rtt) - { - m_rtt = sock.m_rtt->Copy(); - } - //can't "copy" the endpoint just yes, must do this when we know the peer info - //too; this is in SYN_ACK_TX -} - -TcpSocketImpl::~TcpSocketImpl () -{ - NS_LOG_FUNCTION(this); - m_node = 0; - if (m_endPoint != 0) - { - NS_ASSERT (m_tcp != 0); - /** - * Note that this piece of code is a bit tricky: - * when DeAllocate is called, it will call into - * Ipv4EndPointDemux::Deallocate which triggers - * a delete of the associated endPoint which triggers - * in turn a call to the method ::Destroy below - * will will zero the m_endPoint field. - */ - NS_ASSERT (m_endPoint != 0); - m_tcp->DeAllocate (m_endPoint); - NS_ASSERT (m_endPoint == 0); - } - m_tcp = 0; - delete m_pendingData; //prevents leak - m_pendingData = 0; -} - -void -TcpSocketImpl::SetNode (Ptr node) -{ - m_node = node; - // Initialize some variables - m_cWnd = m_initialCWnd * m_segmentSize; - m_rxWindowSize = m_advertisedWindowSize; -} - -void -TcpSocketImpl::SetTcp (Ptr tcp) -{ - m_tcp = tcp; -} -void -TcpSocketImpl::SetRtt (Ptr rtt) -{ - m_rtt = rtt; -} - - -enum Socket::SocketErrno -TcpSocketImpl::GetErrno (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_errno; -} - -Ptr -TcpSocketImpl::GetNode (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_node; -} - -void -TcpSocketImpl::Destroy (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_node = 0; - m_endPoint = 0; - m_tcp = 0; - m_retxEvent.Cancel (); -} -int -TcpSocketImpl::FinishBind (void) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_endPoint == 0) - { - return -1; - } - m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); - m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); - m_localAddress = m_endPoint->GetLocalAddress (); - m_localPort = m_endPoint->GetLocalPort (); - return 0; -} - -int -TcpSocketImpl::Bind (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_endPoint = m_tcp->Allocate (); - return FinishBind (); -} -int -TcpSocketImpl::Bind (const Address &address) -{ - NS_LOG_FUNCTION (this<Allocate (); - NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (port); - NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (ipv4); - NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (ipv4, port); - NS_LOG_LOGIC ("TcpSocketImpl "<Size() != 0) - { // App close with pending data must wait until all data transmitted - m_closeOnEmpty = true; - NS_LOG_LOGIC("Socket " << this << - " deferring close, state " << m_state); - return 0; - } - - Actions_t action = ProcessEvent (APP_CLOSE); - ProcessAction (action); - ShutdownSend (); - return 0; -} - -int -TcpSocketImpl::Connect (const Address & address) -{ - NS_LOG_FUNCTION (this << address); - if (m_endPoint == 0) - { - if (Bind () == -1) - { - NS_ASSERT (m_endPoint == 0); - return -1; - } - NS_ASSERT (m_endPoint != 0); - } - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - m_remoteAddress = transport.GetIpv4 (); - m_remotePort = transport.GetPort (); - - uint32_t localIfIndex; - Ptr ipv4 = m_node->GetObject (); - - if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) - { - m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex)); - } - else - { - m_errno = ERROR_NOROUTETOHOST; - return -1; - } - - Actions_t action = ProcessEvent (APP_CONNECT); - bool success = ProcessAction (action); - if (success) - { - return 0; - } - return -1; -} -int -TcpSocketImpl::Send (const Ptr p) //p here is just data, no headers -{ - NS_LOG_FUNCTION (this << p); - if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT) - { - if (p->GetSize() > GetTxAvailable ()) - { - m_wouldBlock = true; - m_errno = ERROR_MSGSIZE; - return -1; - } - if (!m_pendingData) - { - m_pendingData = new PendingData (); // Create if non-existent - m_firstPendingSequence = m_nextTxSequence; // Note seq of first - } - //PendingData::Add stores a copy of the Ptr p - m_pendingData->Add (p); - NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() << - " state " << m_state); - Actions_t action = ProcessEvent (APP_SEND); - NS_LOG_DEBUG(" action " << action); - if (!ProcessAction (action)) - { - return -1; // Failed, return zero - } - return p->GetSize(); - } - else - { - m_errno = ERROR_NOTCONN; - return -1; - } -} - -int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size) -{ - return Send (Create (buf, size)); -} - -int TcpSocketImpl::DoSendTo (Ptr p, const Address &address) -{ - NS_LOG_FUNCTION (this << p << address); - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); - return DoSendTo (p, ipv4, port); -} - -int TcpSocketImpl::DoSendTo (Ptr p, Ipv4Address ipv4, uint16_t port) -{ - NS_LOG_FUNCTION (this << p << ipv4 << port); - if (m_endPoint == 0) - { - if (Bind () == -1) - { - NS_ASSERT (m_endPoint == 0); - return -1; - } - NS_ASSERT (m_endPoint != 0); - } - if (m_shutdownSend) - { - m_errno = ERROR_SHUTDOWN; - return -1; - } - m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4, - m_endPoint->GetLocalPort (), port); - NotifyDataSent (p->GetSize ()); - return 0; -} - -int -TcpSocketImpl::SendTo (Ptr p, const Address &address) -{ - NS_LOG_FUNCTION (this << address << p); - if (!m_connected) - { - m_errno = ERROR_NOTCONN; - return -1; - } - else - { - return Send (p); //drop the address according to BSD manpages - } -} - -uint32_t -TcpSocketImpl::GetTxAvailable (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_pendingData != 0) - { - uint32_t unAckedDataSize = - m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck); - NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error - return m_sndBufSize-unAckedDataSize; - } - else - { - return m_sndBufSize; - } -} - -int -TcpSocketImpl::Listen (uint32_t q) -{ - NS_LOG_FUNCTION (this << q); - Actions_t action = ProcessEvent (APP_LISTEN); - ProcessAction (action); - return 0; -} - -Ptr -TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) -{ - NS_LOG_FUNCTION_NOARGS (); - if(m_bufferedData.empty()) - { - return 0; - } - UnAckData_t out; //serves as buffer to return up to the user - UnAckData_t::iterator i; - while (!m_bufferedData.empty ()) - { // Check the buffered data for delivery - NS_LOG_LOGIC("TCP " << this << " bufferedData.size() " - << m_bufferedData.size () - << " time " << Simulator::Now ()); - i = m_bufferedData.begin (); - SequenceNumber s1 = 0; - if (i->first > m_nextRxSequence) - { - break; // we're done, no more in-sequence data exits - } - else // (i->first <= m_nextRxSequence) - { // Two cases here. - // 1) seq + length > nextRxSeq, can deliver partial - // 2) seq + length <= nextRxSeq, deliver whole - s1 = i->second->GetSize (); - if (i->first + s1 > m_nextRxSequence) - { // Remove partial data to prepare for delivery - uint32_t avail = s1 + i->first - m_nextRxSequence; - i->second = i->second->CreateFragment (0, avail); - } - // else this packet is okay to deliver whole - // so don't do anything else and output it - out[i->first] = i->second; - } - m_rxAvailable -= i->second->GetSize (); - m_bufferedData.erase (i); // Remove from list - } - if (out.size() == 0) - { - return 0; - } - Ptr outPacket = Create(); - for(i = out.begin(); i!=out.end(); ++i) - { - if (outPacket->GetSize() + i->second->GetSize() <= maxSize ) - { - outPacket->AddAtEnd(i->second); - } - else - { - //only append as much as will fit - uint32_t avail = maxSize - outPacket->GetSize(); - outPacket->AddAtEnd(i->second->CreateFragment(0,avail)); - //put the rest back into the buffer - m_bufferedData[i->first+SequenceNumber(avail)] - = i->second->CreateFragment(avail,i->second->GetSize()-avail); - m_rxAvailable += i->second->GetSize()-avail; - } - } - return outPacket; -} - -uint32_t -TcpSocketImpl::GetRxAvailable (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - // We separately maintain this state to avoid walking the queue - // every time this might be called - return m_rxAvailable; -} - -void -TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) -{ - NS_LOG_DEBUG("Socket " << this << " got forward up" << - " dport " << m_endPoint->GetLocalPort() << - " daddr " << m_endPoint->GetLocalAddress() << - " sport " << m_endPoint->GetPeerPort() << - " saddr " << m_endPoint->GetPeerAddress()); - - NS_LOG_FUNCTION (this << packet << ipv4 << port); - if (m_shutdownRecv) - { - return; - } - TcpHeader tcpHeader; - packet->RemoveHeader (tcpHeader); - - if (tcpHeader.GetFlags () & TcpHeader::ACK) - { - Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () ); - if (m != Seconds (0.0)) - { - m_lastMeasuredRtt = m; - } - } - - Events_t event = SimulationSingleton::Get ()->FlagsEvent (tcpHeader.GetFlags () ); - Actions_t action = ProcessEvent (event); //updates the state - Address address = InetSocketAddress (ipv4, port); - NS_LOG_DEBUG("Socket " << this << - " processing pkt action, " << action << - " current state " << m_state); - ProcessPacketAction (action, packet, tcpHeader, address); -} - -Actions_t TcpSocketImpl::ProcessEvent (Events_t e) -{ - NS_LOG_FUNCTION (this << e); - States_t saveState = m_state; - NS_LOG_LOGIC ("TcpSocketImpl " << this << " processing event " << e); - // simulation singleton is a way to get a single global static instance of a - // class intended to be a singleton; see simulation-singleton.h - SA stateAction = SimulationSingleton::Get ()->Lookup (m_state,e); - // debug - if (stateAction.action == RST_TX) - { - NS_LOG_LOGIC ("TcpSocketImpl " << this << " sending RST from state " - << saveState << " event " << e); - } - bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED - && e != TIMEOUT); - m_state = stateAction.state; - NS_LOG_LOGIC ("TcpSocketImpl " << this << " moved from state " << saveState - << " to state " <SetPeer (m_remoteAddress, m_remotePort); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); - } - - if (needCloseNotify && !m_closeNotified) - { - NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from " - << m_state << " event " << e << " closeNot " << m_closeNotified - << " action " << stateAction.action); - NotifyCloseCompleted (); - m_closeNotified = true; - NS_LOG_LOGIC ("TcpSocketImpl " << this << " calling Closed from PE" - << " origState " << saveState - << " event " << e); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from " - << m_state << " event " << e - << " set CloseNotif "); - } - return stateAction.action; -} - -void TcpSocketImpl::SendEmptyPacket (uint8_t flags) -{ - NS_LOG_FUNCTION (this << flags); - Ptr p = Create (); - TcpHeader header; - - header.SetFlags (flags); - header.SetSequenceNumber (m_nextTxSequence); - header.SetAckNumber (m_nextRxSequence); - header.SetSourcePort (m_endPoint->GetLocalPort ()); - header.SetDestinationPort (m_remotePort); - header.SetWindowSize (m_advertisedWindowSize); - m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), - m_remoteAddress); - Time rto = m_rtt->RetransmitTimeout (); - if (flags & TcpHeader::SYN) - { - rto = m_cnTimeout; - m_cnTimeout = m_cnTimeout + m_cnTimeout; - m_cnCount--; - } - if (m_retxEvent.IsExpired () ) //no outstanding timer - { - NS_LOG_LOGIC ("Schedule retransmission timeout at time " - << Simulator::Now ().GetSeconds () << " to expire at time " - << (Simulator::Now () + rto).GetSeconds ()); - m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this); - } -} - -bool TcpSocketImpl::ProcessAction (Actions_t a) -{ // These actions do not require a packet or any TCP Headers - NS_LOG_FUNCTION (this << a); - switch (a) - { - case NO_ACT: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT"); - break; - case ACK_TX: - SendEmptyPacket (TcpHeader::ACK); - break; - case ACK_TX_1: - NS_ASSERT (false); // This should be processed in ProcessPacketAction - break; - case RST_TX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RST_TX"); - SendEmptyPacket (TcpHeader::RST); - break; - case SYN_TX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_TX"); - // TCP SYN Flag consumes one byte - // is the above correct? we're SENDING a syn, not acking back -- Raj - // commented out for now - // m_nextTxSequence+= 1; - SendEmptyPacket (TcpHeader::SYN); - break; - case SYN_ACK_TX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX"); - // TCP SYN Flag consumes one byte - ++m_nextRxSequence; - SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); - break; - case FIN_TX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_TX"); - SendEmptyPacket (TcpHeader::FIN); - break; - case FIN_ACK_TX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_ACK_TX"); - SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK); - break; - case NEW_ACK: - NS_ASSERT (false); // This should be processed in ProcessPacketAction - break; - case NEW_SEQ_RX: - NS_ASSERT (false); // This should be processed in ProcessPacketAction - break; - case RETX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RETX"); - break; - case TX_DATA: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action TX_DATA"); - SendPendingData (); - break; - case PEER_CLOSE: - NS_ASSERT (false); // This should be processed in ProcessPacketAction - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action PEER_CLOSE"); - break; - case APP_CLOSED: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_CLOSED"); - break; - case CANCEL_TM: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action CANCEL_TM"); - break; - case APP_NOTIFY: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_NOTIFY"); - break; - case SERV_NOTIFY: - NS_ASSERT (false); // This should be processed in ProcessPacketAction - break; - case LAST_ACTION: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action LAST_ACTION"); - break; - } - return true; -} - -bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, - const TcpHeader& tcpHeader, - const Address& fromAddress) -{ - NS_LOG_FUNCTION (this << a << p << fromAddress); - uint32_t localIfIndex; - Ptr ipv4 = m_node->GetObject (); - switch (a) - { - 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->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) -// { -// m_localAddress = ipv4->GetAddress (localIfIndex); -// } - 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); - //notify the server that we got a SYN - // If server refuses connection do nothing - if (!NotifyConnectionRequest(fromAddress)) return true; - // Clone the socket - Ptr newSock = Copy (); - NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock); - //this listening socket should do nothing more - Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock, - p, tcpHeader,fromAddress); - return true; - } - // This is the cloned endpoint - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); - if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) - { - m_localAddress = ipv4->GetAddress (localIfIndex); - 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); - break; - case ACK_TX_1: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1"); - // TCP SYN consumes one byte - m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); - m_nextTxSequence = tcpHeader.GetAckNumber (); - m_firstPendingSequence = m_nextTxSequence; //bug 166 - NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" << - " nextRxSeq " << m_nextRxSequence); - SendEmptyPacket (TcpHeader::ACK); - m_rxWindowSize = tcpHeader.GetWindowSize (); - if (tcpHeader.GetAckNumber () > m_highestRxAck) - { - m_highestRxAck = tcpHeader.GetAckNumber (); - // Data freed from the send buffer; notify any blocked sender - if (m_wouldBlock) - { - NotifySend (GetTxAvailable ()); - m_wouldBlock = false; - } - } - SendPendingData (); - break; - case NEW_ACK: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_ACK_TX"); - if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing - { - break; - } - if (tcpHeader.GetAckNumber () == m_highestRxAck && - tcpHeader.GetAckNumber () < m_nextTxSequence) - { - DupAck (tcpHeader, ++m_dupAckCount); - break; - } - if (tcpHeader.GetAckNumber () > m_highestRxAck) - { - m_dupAckCount = 0; - } - NewAck (tcpHeader.GetAckNumber ()); - break; - case NEW_SEQ_RX: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX"); - NewRx (p, tcpHeader, fromAddress); // Process new data received - break; - case PEER_CLOSE: - { - // First we have to be sure the FIN packet was not received - // out of sequence. If so, note pending close and process - // new sequence rx - if (tcpHeader.GetSequenceNumber () != m_nextRxSequence) - { // process close later - m_pendingClose = true; - NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose" - << " rxseq " << tcpHeader.GetSequenceNumber () - << " nextRxSeq " << m_nextRxSequence); - NewRx (p, tcpHeader, fromAddress); - return true; - } - // Now we need to see if any data came with the FIN - // if so, call NewRx - if (p->GetSize () != 0) - { - NewRx (p, tcpHeader, fromAddress); - } - States_t saveState = m_state; // Used to see if app responds - NS_LOG_LOGIC ("TcpSocketImpl " << this - << " peer close, state " << m_state); - if (!m_closeRequestNotified) - { - NS_LOG_LOGIC ("TCP " << this - << " calling AppCloseRequest"); - NotifyCloseRequested(); - m_closeRequestNotified = true; - } - NS_LOG_LOGIC ("TcpSocketImpl " << this - << " peer close, state after " << m_state); - if (m_state == saveState) - { // Need to ack, the application will close later - SendEmptyPacket (TcpHeader::ACK); -// // Also need to re-tx the ack if we - } - if (m_state == LAST_ACK) - { - NS_LOG_LOGIC ("TcpSocketImpl " << this << " scheduling LATO1"); - m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (), - &TcpSocketImpl::LastAckTimeout,this); - } - break; - } - case SERV_NOTIFY: - NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY"); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); - NotifyNewConnectionCreated (this, fromAddress); - m_connected = true; // ! This is bogus; fix when we clone the tcp - m_endPoint->SetPeer (m_remoteAddress, m_remotePort); - //treat the connection orientation final ack as a newack - CommonNewAck (tcpHeader.GetAckNumber (), true); - break; - default: - break; - } - return true; -} - -void TcpSocketImpl::CompleteFork(Ptr p, const TcpHeader& h, const Address& fromAddress) -{ - // Get port and address from peer (connecting host) - m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort (); - m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (); - m_endPoint = m_tcp->Allocate (m_localAddress, - m_localPort, - m_remoteAddress, - m_remotePort); - //the cloned socket with be in listen state, so manually change state - m_state = SYN_RCVD; - //equivalent to FinishBind - m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); - m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); - ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress); - } - -void TcpSocketImpl::ConnectionSucceeded() -{ // We would preferred to have scheduled an event directly to - // NotifyConnectionSucceeded, but (sigh) these are protected - // and we can get the address of it :( - NotifyConnectionSucceeded(); -} - -bool TcpSocketImpl::SendPendingData (bool withAck) -{ - NS_LOG_FUNCTION (this << withAck); - NS_LOG_LOGIC ("ENTERING SendPendingData"); - if (!m_pendingData) - { - return false; // No data exists - } - uint32_t nPacketsSent = 0; - while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence)) - { - uint32_t w = AvailableWindow ();// Get available window size - NS_LOG_LOGIC ("TcpSocketImpl " << this << " SendPendingData" - << " w " << w - << " rxwin " << m_rxWindowSize - << " cWnd " << m_cWnd - << " segsize " << m_segmentSize - << " nextTxSeq " << m_nextTxSequence - << " highestRxAck " << m_highestRxAck - << " pd->Size " << m_pendingData->Size () - << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence)); - - if (w < m_segmentSize && m_pendingData->Size () > w) - { - break; // No more - } - uint32_t s = std::min (w, m_segmentSize); // Send no more than window - Ptr p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence, - m_nextTxSequence); - NS_LOG_LOGIC("TcpSocketImpl " << this << " SendPendingData" - << " txseq " << m_nextTxSequence - << " s " << s - << " datasize " << p->GetSize() ); - uint8_t flags = 0; - if (withAck) - { - flags |= TcpHeader::ACK; - } - uint32_t sz = p->GetSize (); // Size of packet - uint32_t remainingData = m_pendingData->SizeFromSeq( - m_firstPendingSequence, - m_nextTxSequence + SequenceNumber (sz)); - if (m_closeOnEmpty && (remainingData == 0)) - { - flags = TcpHeader::FIN; - m_state = FIN_WAIT_1; - } - - TcpHeader header; - header.SetFlags (flags); - header.SetSequenceNumber (m_nextTxSequence); - header.SetAckNumber (m_nextRxSequence); - header.SetSourcePort (m_endPoint->GetLocalPort()); - header.SetDestinationPort (m_remotePort); - if (m_shutdownSend) - { - m_errno = ERROR_SHUTDOWN; - return -1; - } - - - if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit - { - Time rto = m_rtt->RetransmitTimeout (); - NS_LOG_LOGIC ("SendPendingData Schedule retransmission timeout at time " << - Simulator::Now ().GetSeconds () << " to expire at time " << - (Simulator::Now () + rto).GetSeconds () ); - m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this); - } - NS_LOG_LOGIC ("About to send a packet with flags: " << flags); - m_tcp->SendPacket (p, header, - m_endPoint->GetLocalAddress (), - m_remoteAddress); - m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT - // Notify the application - Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, p->GetSize ()); - nPacketsSent++; // Count sent this loop - m_nextTxSequence += sz; // Advance next tx sequence - // Note the high water mark - m_highTxMark = std::max (m_nextTxSequence, m_highTxMark); - } - NS_LOG_LOGIC ("SendPendingData Sent "<0); -} - -uint32_t TcpSocketImpl::UnAckDataCount () -{ - NS_LOG_FUNCTION_NOARGS (); - return m_nextTxSequence - m_highestRxAck; -} - -uint32_t TcpSocketImpl::BytesInFlight () -{ - NS_LOG_FUNCTION_NOARGS (); - return m_highTxMark - m_highestRxAck; -} - -uint32_t TcpSocketImpl::Window () -{ - NS_LOG_FUNCTION_NOARGS (); - NS_LOG_LOGIC ("TcpSocketImpl::Window() "< p, - const TcpHeader& tcpHeader, - const Address& fromAddress) -{ - NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx," - << " seq " << tcpHeader.GetSequenceNumber() - << " ack " << tcpHeader.GetAckNumber() - << " p.size is " << p->GetSize () ); - NS_LOG_DEBUG ("TcpSocketImpl " << this << - " NewRx," << - " seq " << tcpHeader.GetSequenceNumber() << - " ack " << tcpHeader.GetAckNumber() << - " p.size is " << p->GetSize()); - States_t origState = m_state; - uint32_t s = p->GetSize (); // Size of associated data - if (s == 0) - {// Nothing to do if no associated data - return; - } - // Log sequence received if enabled - // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber); - // Three possibilities - // 1) Received seq is expected, buffer this, update rxAvailable, and ack - // 2) Received seq is < expected, just re-ack previous - // 3) Received seq is > expected, just re-ack previous and buffer data - if (tcpHeader.GetSequenceNumber () == m_nextRxSequence) - { // If seq is expected seq - // 1) Update nextRxSeq - // 2) Buffer this packet so Recv can read it - // 3) Send the ack - m_nextRxSequence += s; // Advance next expected sequence - //bytesReceived += s; // Statistics - NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence ); - SocketRxAddressTag tag; - tag.SetAddress (fromAddress); - p->AddTag (tag); - //buffer this, it'll be read by call to Recv - UnAckData_t::iterator i = - m_bufferedData.find (tcpHeader.GetSequenceNumber () ); - if (i != m_bufferedData.end () ) //we found it already in the buffer - { - i->second = 0; // relase reference to already buffered - } - // Save for later delivery - m_bufferedData[tcpHeader.GetSequenceNumber () ] = p; - m_rxAvailable += p->GetSize (); - //putting this into the buffer might have filled in a sequence gap - //so we have to iterate through the list to find the largest contiguous - //sequenced chunk, and update m_rxAvailable appropriately - i = m_bufferedData.find (tcpHeader.GetSequenceNumber () ); - UnAckData_t::iterator next = i; - next++; - while(next != m_bufferedData.end()) - { - if(i->first + SequenceNumber(i->second->GetSize ()) == next->first) - { - //next packet is in sequence, count it - m_rxAvailable += next->second->GetSize(); - m_nextRxSequence += next->second->GetSize(); - } - else - { - break; //no more in this contiguous chunk - } - ++i; - ++next; - } - NotifyDataRecv (); - if (m_closeNotified) - { - NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif"); - } - NS_LOG_LOGIC ("TcpSocketImpl " << this << " adv rxseq by " << s); - if (m_pendingClose || (origState > ESTABLISHED)) - { // See if we can close now - if (m_bufferedData.empty()) - { - ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress); - } - } - } - else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence) - { // Need to buffer this one - NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () ); - UnAckData_t::iterator i = - m_bufferedData.find (tcpHeader.GetSequenceNumber () ); - if (i != m_bufferedData.end () ) - { - i->second = 0; // relase reference to already buffered - } - // Save for later delivery - SocketRxAddressTag tag; - tag.SetAddress (fromAddress); - p->AddTag (tag); - m_bufferedData[tcpHeader.GetSequenceNumber () ] = p; - } - else - { // debug - NS_LOG_LOGIC("TCP " << this - << " got seq " << tcpHeader.GetSequenceNumber () - << " expected " << m_nextRxSequence - << " flags " << tcpHeader.GetFlags ()); - } - // Now send a new ack packet acknowledging all received and delivered data - if(++m_delAckCount >= m_delAckMaxCount) - { - m_delAckEvent.Cancel(); - m_delAckCount = 0; - SendEmptyPacket (TcpHeader::ACK); - } - else - { - m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketImpl::DelAckTimeout, this); - } -} - -void TcpSocketImpl::DelAckTimeout () -{ - m_delAckCount = 0; - SendEmptyPacket (TcpHeader::ACK); -} - -void TcpSocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer) -{ // CommonNewAck is called only for "New" (non-duplicate) acks - // and MUST be called by any subclass, from the NewAck function - // Always cancel any pending re-tx timer on new acknowledgement - NS_LOG_FUNCTION (this << ack << skipTimer); - //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl)); - if (!skipTimer) - { - m_retxEvent.Cancel (); - //On recieving a "New" ack we restart retransmission timer .. RFC 2988 - Time rto = m_rtt->RetransmitTimeout (); - NS_LOG_LOGIC ("Schedule retransmission timeout at time " - << Simulator::Now ().GetSeconds () << " to expire at time " - << (Simulator::Now () + rto).GetSeconds ()); - m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this); - } - NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack - << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed - m_highestRxAck = ack; // Note the highest recieved Ack - if (m_wouldBlock) - { - // m_highestRxAck advancing means some data was acked, and the size - // of free space in the buffer has increased - NotifySend (GetTxAvailable ()); - m_wouldBlock = false; - } - if (ack > m_nextTxSequence) - { - m_nextTxSequence = ack; // If advanced - } - // See if all pending ack'ed; if so we can delete the data - if (m_pendingData) - { // Data exists, see if can be deleted - if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0) - { // All pending acked, can be deleted - m_pendingData->Clear (); - delete m_pendingData; - m_pendingData = 0; - // Insure no re-tx timer - m_retxEvent.Cancel (); - } - } - // Try to send more data - SendPendingData(); -} - -Ptr TcpSocketImpl::Copy () -{ - return CopyObject (this); -} - -void TcpSocketImpl::NewAck (SequenceNumber seq) -{ // New acknowledgement up to sequence number "seq" - // Adjust congestion window in response to new ack's received - NS_LOG_FUNCTION (this << seq); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewAck " - << " seq " << seq - << " cWnd " << m_cWnd - << " ssThresh " << m_ssThresh); - if (m_cWnd < m_ssThresh) - { // Slow start mode, add one segSize to cWnd - m_cWnd += m_segmentSize; - NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewCWnd SlowStart, cWnd " << m_cWnd - << " sst " << m_ssThresh); - } - else - { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd - double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd.Get(); - if (adder < 1.0) - { - adder = 1.0; - } - m_cWnd += (uint32_t) adder; - NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd - << " sst " << m_ssThresh); - } - CommonNewAck (seq, false); // Complete newAck processing -} - -void TcpSocketImpl::DupAck (const TcpHeader& t, uint32_t count) -{ - NS_LOG_FUNCTION (this << "t " << count); - NS_LOG_LOGIC ("TcpSocketImpl " << this << " DupAck " << t.GetAckNumber () - << ", count " << count - << ", time " << Simulator::Now ()); - if (count == 3) - { // Count of three indicates triple duplicate ack - m_ssThresh = Window () / 2; // Per RFC2581 - m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize); - NS_LOG_LOGIC("TcpSocketImpl " << this << "Tahoe TDA, time " << Simulator::Now () - << " seq " << t.GetAckNumber () - << " in flight " << BytesInFlight () - << " new ssthresh " << m_ssThresh); - - m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart) - // For Tahoe, we also reset nextTxSeq - m_nextTxSequence = m_highestRxAck; - SendPendingData (); - } -} - -void TcpSocketImpl::ReTxTimeout () -{ // Retransmit timeout - NS_LOG_FUNCTION (this); - m_ssThresh = Window () / 2; // Per RFC2581 - m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize); - // Set cWnd to segSize on timeout, per rfc2581 - // Collapse congestion window (re-enter slowstart) - m_cWnd = m_segmentSize; - m_nextTxSequence = m_highestRxAck; // Start from highest Ack - m_rtt->IncreaseMultiplier (); // DoubleValue timeout value for next retx timer - Retransmit (); // Retransmit the packet -} - -void TcpSocketImpl::LastAckTimeout () -{ - m_lastAckEvent.Cancel (); - if (m_state == LAST_ACK) - { - Actions_t action = ProcessEvent (TIMEOUT); - ProcessAction (action); - } - if (!m_closeNotified) - { - m_closeNotified = true; - } -} - -void TcpSocketImpl::Retransmit () -{ - NS_LOG_FUNCTION (this); - uint8_t flags = TcpHeader::NONE; - if (m_state == SYN_SENT) - { - if (m_cnCount > 0) - { - SendEmptyPacket (TcpHeader::SYN); - return; - } - else - { - NotifyConnectionFailed (); - return; - } - } - if (!m_pendingData) - { - if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) - { // Must have lost FIN, re-send - SendEmptyPacket (TcpHeader::FIN); - } - return; - } - Ptr p = m_pendingData->CopyFromSeq (m_segmentSize, - m_firstPendingSequence, - m_highestRxAck); - // Calculate remaining data for COE check - uint32_t remainingData = m_pendingData->SizeFromSeq ( - m_firstPendingSequence, - m_nextTxSequence + SequenceNumber(p->GetSize ())); - if (m_closeOnEmpty && remainingData == 0) - { // Add the FIN flag - flags = flags | TcpHeader::FIN; - } - - NS_LOG_LOGIC ("TcpSocketImpl " << this << " retxing seq " << m_highestRxAck); - if (m_retxEvent.IsExpired () ) - { - Time rto = m_rtt->RetransmitTimeout (); - NS_LOG_LOGIC ("Schedule retransmission timeout at time " - << Simulator::Now ().GetSeconds () << " to expire at time " - << (Simulator::Now () + rto).GetSeconds ()); - m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this); - } - m_rtt->SentSeq (m_highestRxAck,p->GetSize ()); - // And send the packet - TcpHeader tcpHeader; - tcpHeader.SetSequenceNumber (m_nextTxSequence); - tcpHeader.SetAckNumber (m_nextRxSequence); - tcpHeader.SetSourcePort (m_endPoint->GetLocalPort()); - tcpHeader.SetDestinationPort (m_remotePort); - tcpHeader.SetFlags (flags); - tcpHeader.SetWindowSize (m_advertisedWindowSize); - - m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), - m_remoteAddress); -} - -void -TcpSocketImpl::SetSndBufSize (uint32_t size) -{ - m_sndBufSize = size; -} - -uint32_t -TcpSocketImpl::GetSndBufSize (void) const -{ - return m_sndBufSize; -} - -void -TcpSocketImpl::SetRcvBufSize (uint32_t size) -{ - m_rcvBufSize = size; -} - -uint32_t -TcpSocketImpl::GetRcvBufSize (void) const -{ - return m_rcvBufSize; -} - -void -TcpSocketImpl::SetSegSize (uint32_t size) -{ - m_segmentSize = size; -} - -uint32_t -TcpSocketImpl::GetSegSize (void) const -{ - return m_segmentSize; -} - -void -TcpSocketImpl::SetAdvWin (uint32_t window) -{ - m_advertisedWindowSize = window; -} - -uint32_t -TcpSocketImpl::GetAdvWin (void) const -{ - return m_advertisedWindowSize; -} - -void -TcpSocketImpl::SetSSThresh (uint32_t threshold) -{ - m_ssThresh = threshold; -} - -uint32_t -TcpSocketImpl::GetSSThresh (void) const -{ - return m_ssThresh; -} - -void -TcpSocketImpl::SetInitialCwnd (uint32_t cwnd) -{ - m_initialCWnd = cwnd; -} - -uint32_t -TcpSocketImpl::GetInitialCwnd (void) const -{ - return m_initialCWnd; -} - -void -TcpSocketImpl::SetConnTimeout (Time timeout) -{ - m_cnTimeout = timeout; -} - -Time -TcpSocketImpl::GetConnTimeout (void) const -{ - return m_cnTimeout; -} - -void -TcpSocketImpl::SetConnCount (uint32_t count) -{ - m_cnCount = count; -} - -uint32_t -TcpSocketImpl::GetConnCount (void) const -{ - return m_cnCount; -} - -void -TcpSocketImpl::SetDelAckTimeout (Time timeout) -{ - m_delAckTimeout = timeout; -} - -Time -TcpSocketImpl::GetDelAckTimeout (void) const -{ - return m_delAckTimeout; -} - -void -TcpSocketImpl::SetDelAckMaxCount (uint32_t count) -{ - m_delAckMaxCount = count; -} - -uint32_t -TcpSocketImpl::GetDelAckMaxCount (void) const -{ - return m_delAckMaxCount; -} - -}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-socket-impl.h --- a/src/internet-node/tcp-socket-impl.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* -*- 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 - */ -#ifndef TCP_SOCKET_IMPL_H -#define TCP_SOCKET_IMPL_H - -#include -#include -#include "ns3/callback.h" -#include "ns3/traced-value.h" -#include "ns3/tcp-socket.h" -#include "ns3/ptr.h" -#include "ns3/ipv4-address.h" -#include "ns3/event-id.h" -#include "tcp-typedefs.h" -#include "pending-data.h" -#include "sequence-number.h" -#include "rtt-estimator.h" - - -namespace ns3 { - -class Ipv4EndPoint; -class Node; -class Packet; -class TcpL4Protocol; -class TcpHeader; - -class TcpSocketImpl : public TcpSocket -{ -public: - static TypeId GetTypeId (void); - /** - * Create an unbound tcp socket. - */ - TcpSocketImpl (); - TcpSocketImpl (const TcpSocketImpl& sock); - virtual ~TcpSocketImpl (); - - void SetNode (Ptr node); - void SetTcp (Ptr tcp); - void SetRtt (Ptr rtt); - - virtual enum SocketErrno GetErrno (void) const; - virtual Ptr GetNode (void) const; - virtual int Bind (void); - virtual int Bind (const Address &address); - virtual int Close (void); - virtual int ShutdownSend (void); - virtual int ShutdownRecv (void); - virtual int Connect(const Address &address); - virtual int Send (Ptr p); - virtual int Send (const uint8_t* buf, uint32_t size); - virtual int SendTo(Ptr p, const Address &address); - virtual uint32_t GetTxAvailable (void) const; - virtual int Listen(uint32_t queueLimit); - - virtual Ptr Recv (uint32_t maxSize, uint32_t flags); - virtual uint32_t GetRxAvailable (void) const; - -private: - friend class Tcp; - // invoked by Tcp class - int FinishBind (void); - void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); - void Destroy (void); - int DoSendTo (Ptr p, const Address &daddr); - int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); - void SendEmptyPacket(uint8_t flags); - //methods for state - bool ProcessAction (Actions_t a); - bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader, - Ipv4Address saddr, Ipv4Address daddr); - bool ProcessPacketAction (Actions_t a, Ptr p, - const TcpHeader& tcpHeader, - const Address& fromAddress); - Actions_t ProcessEvent (Events_t e); - bool SendPendingData(bool withAck = false); - void CompleteFork(Ptr, const TcpHeader&, const Address& fromAddress); - void ConnectionSucceeded(); - - //methods for window management - virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes - virtual uint32_t BytesInFlight(); // Return total bytes in flight - virtual uint32_t Window(); // Return window size (integer) - virtual uint32_t AvailableWindow();// Return unfilled portion of window - - // Manage data tx/rx - void NewRx (Ptr, const TcpHeader&, const Address&); - // XXX This should be virtual and overridden - Ptr Copy (); - void NewAck (SequenceNumber seq); - // XXX This should be virtual and overridden - void DupAck (const TcpHeader& t, uint32_t count); - void ReTxTimeout (); - void DelAckTimeout (); - void LastAckTimeout (); - void Retransmit (); - void CommonNewAck (SequenceNumber seq, bool skipTimer = false); - - // attribute related - virtual void SetSndBufSize (uint32_t size); - virtual uint32_t GetSndBufSize (void) const; - virtual void SetRcvBufSize (uint32_t size); - virtual uint32_t GetRcvBufSize (void) const; - virtual void SetSegSize (uint32_t size); - virtual uint32_t GetSegSize (void) const; - virtual void SetAdvWin (uint32_t window); - virtual uint32_t GetAdvWin (void) const; - virtual void SetSSThresh (uint32_t threshold); - virtual uint32_t GetSSThresh (void) const; - virtual void SetInitialCwnd (uint32_t cwnd); - virtual uint32_t GetInitialCwnd (void) const; - virtual void SetConnTimeout (Time timeout); - virtual Time GetConnTimeout (void) const; - virtual void SetConnCount (uint32_t count); - virtual uint32_t GetConnCount (void) const; - virtual void SetDelAckTimeout (Time timeout); - virtual Time GetDelAckTimeout (void) const; - virtual void SetDelAckMaxCount (uint32_t count); - virtual uint32_t GetDelAckMaxCount (void) const; - - bool m_skipRetxResched; - uint32_t m_dupAckCount; - EventId m_retxEvent; - EventId m_lastAckEvent; - - EventId m_delAckEvent; - uint32_t m_delAckCount; - uint32_t m_delAckMaxCount; - Time m_delAckTimeout; - - Ipv4EndPoint *m_endPoint; - Ptr m_node; - Ptr m_tcp; - Ipv4Address m_remoteAddress; - uint16_t m_remotePort; - //these two are so that the socket/endpoint cloning works - Ipv4Address m_localAddress; - uint16_t m_localPort; - enum SocketErrno m_errno; - bool m_shutdownSend; - bool m_shutdownRecv; - bool m_connected; - - //manage the state infomation - States_t m_state; - bool m_closeNotified; - bool m_closeRequestNotified; - bool m_closeOnEmpty; - bool m_pendingClose; - - - //sequence info, sender side - SequenceNumber m_nextTxSequence; - SequenceNumber m_highTxMark; - SequenceNumber m_highestRxAck; - SequenceNumber m_lastRxAck; - - //sequence info, reciever side - SequenceNumber m_nextRxSequence; - - //history data - //this is the incoming data buffer which sorts out of sequence data - UnAckData_t m_bufferedData; - //this is kind of the tx buffer - PendingData* m_pendingData; - SequenceNumber m_firstPendingSequence; - - // Window management - uint32_t m_segmentSize; //SegmentSize - uint32_t m_rxWindowSize; - uint32_t m_advertisedWindowSize; //Window to advertise - TracedValue m_cWnd; //Congestion window - uint32_t m_ssThresh; //Slow Start Threshold - uint32_t m_initialCWnd; //Initial cWnd value - - // Round trip time estimation - Ptr m_rtt; - Time m_lastMeasuredRtt; - - // Timer-related members - Time m_cnTimeout; - uint32_t m_cnCount; - - // Temporary queue for delivering data to application - uint32_t m_rxAvailable; - - bool m_wouldBlock; // set to true whenever socket would block on send() - - // Attributes - uint32_t m_sndBufSize; // buffer limit for the outgoing queue - uint32_t m_rcvBufSize; // maximum receive socket buffer size -}; - -}//namespace ns3 - -#endif /* TCP_SOCKET_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/tcp-typedefs.h --- a/src/internet-node/tcp-typedefs.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/* -*- 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 - * typedefs for tcp state machine - */ - -#include -#include -#include "sequence-number.h" - -#ifndef TCP_TYPEDEFS_H -#define TCP_TYPEDEFS_H - -namespace ns3 { - -typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t; // Flags are 6 bits - -typedef enum { - CLOSED, // 0 - LISTEN, // 1 - SYN_SENT, // 2 - SYN_RCVD, // 3 - ESTABLISHED, // 4 - CLOSE_WAIT, // 5 - LAST_ACK, // 6 - FIN_WAIT_1, // 7 - FIN_WAIT_2, // 8 - CLOSING, // 9 - TIMED_WAIT, // 10 - LAST_STATE } States_t; - -typedef enum { - APP_LISTEN, // 0 - APP_CONNECT, // 1 - APP_SEND, // 2 - SEQ_RECV, // 3 - APP_CLOSE, // 4 - TIMEOUT, // 5 - ACK_RX, // 6 - SYN_RX, // 7 - SYN_ACK_RX, // 8 - FIN_RX, // 9 - FIN_ACK_RX, // 10 - RST_RX, // 11 - BAD_FLAGS, // 12 - LAST_EVENT } Events_t; - -typedef enum { - NO_ACT, // 0 - ACK_TX, // 1 - ACK_TX_1, // ACK response to syn - RST_TX, // 2 - SYN_TX, // 3 - SYN_ACK_TX, // 4 - FIN_TX, // 5 - FIN_ACK_TX, // 6 - NEW_ACK, // 7 - NEW_SEQ_RX, // 8 - RETX, // 9 - TX_DATA, // 10 - PEER_CLOSE, // 11 - APP_CLOSED, // 12 - CANCEL_TM, // 13 - APP_NOTIFY, // 14 - Notify app that connection failed - SERV_NOTIFY, // 15 - Notify server tcp that connection completed - LAST_ACTION } Actions_t; - -class SA // State/Action pair -{ -public: - SA () : state (LAST_STATE), action (LAST_ACTION) { } - SA (States_t s, Actions_t a) : state (s), action (a) { } -public: - States_t state; - Actions_t action; -}; -typedef std::vector StateActionVec_t; -typedef std::vector StateActions_t; // One per current state -typedef std::vector EventVec_t; // For flag events lookup - -//type for managing buffered out of sequence data -typedef std::map > UnAckData_t; - -class TcpStateMachine { - public: - TcpStateMachine (); - SA Lookup (States_t, Events_t); - Events_t FlagsEvent (uint8_t); // Lookup event from flags - - public: - StateActions_t aT; // Action table - EventVec_t eV; // Flags event lookup -}; - -}//namespace ns3 -#endif //TCP_TYPEDEFS_H diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-header.cc --- a/src/internet-node/udp-header.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -/* -*- 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 "udp-header.h" -#include "ipv4-checksum.h" - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (UdpHeader); - -bool UdpHeader::m_calcChecksum = false; - -/* The magic values below are used only for debugging. - * They can be used to easily detect memory corruption - * problems so you can see the patterns in memory. - */ -UdpHeader::UdpHeader () - : m_sourcePort (0xfffd), - m_destinationPort (0xfffd), - m_payloadSize (0xfffd), - m_initialChecksum (0) -{} -UdpHeader::~UdpHeader () -{ - m_sourcePort = 0xfffe; - m_destinationPort = 0xfffe; - m_payloadSize = 0xfffe; -} - -void -UdpHeader::EnableChecksums (void) -{ - m_calcChecksum = true; -} - -void -UdpHeader::SetDestinationPort (uint16_t port) -{ - m_destinationPort = port; -} -void -UdpHeader::SetSourcePort (uint16_t port) -{ - m_sourcePort = port; -} -uint16_t -UdpHeader::GetSourcePort (void) const -{ - return m_sourcePort; -} -uint16_t -UdpHeader::GetDestinationPort (void) const -{ - return m_destinationPort; -} -void -UdpHeader::SetPayloadSize (uint16_t size) -{ - m_payloadSize = size; -} -void -UdpHeader::InitializeChecksum (Ipv4Address source, - Ipv4Address destination, - uint8_t protocol) -{ - uint8_t buf[12]; - source.Serialize (buf); - destination.Serialize (buf+4); - buf[8] = 0; - buf[9] = protocol; - uint16_t udpLength = m_payloadSize + GetSerializedSize (); - buf[10] = udpLength >> 8; - buf[11] = udpLength & 0xff; - - m_initialChecksum = Ipv4ChecksumCalculate (0, buf, 12); -} - -TypeId -UdpHeader::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::UdpHeader") - .SetParent
() - .AddConstructor () - ; - return tid; -} -TypeId -UdpHeader::GetInstanceTypeId (void) const -{ - return GetTypeId (); -} -void -UdpHeader::Print (std::ostream &os) const -{ - os << "length: " << m_payloadSize + GetSerializedSize () - << " " - << m_sourcePort << " > " << m_destinationPort - ; -} - -uint32_t -UdpHeader::GetSerializedSize (void) const -{ - return 8; -} - -void -UdpHeader::Serialize (Buffer::Iterator start) const -{ - Buffer::Iterator i = start; - i.WriteHtonU16 (m_sourcePort); - i.WriteHtonU16 (m_destinationPort); - i.WriteHtonU16 (m_payloadSize + GetSerializedSize ()); - i.WriteU16 (0); - - if (m_calcChecksum) - { -#if 0 - //XXXX - uint16_t checksum = Ipv4ChecksumCalculate (m_initialChecksum, - buffer->PeekData (), - GetSerializedSize () + m_payloadSize); - checksum = Ipv4ChecksumComplete (checksum); - i = buffer->Begin (); - i.Next (6); - i.WriteU16 (checksum); -#endif - } -} -uint32_t -UdpHeader::Deserialize (Buffer::Iterator start) -{ - Buffer::Iterator i = start; - m_sourcePort = i.ReadNtohU16 (); - m_destinationPort = i.ReadNtohU16 (); - m_payloadSize = i.ReadNtohU16 () - GetSerializedSize (); - if (m_calcChecksum) - { - // XXX verify checksum. - } - return GetSerializedSize (); -} - - -}; // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-header.h --- a/src/internet-node/udp-header.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* -*- 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 UDP_HEADER_H -#define UDP_HEADER_H - -#include -#include -#include "ns3/header.h" -#include "ns3/ipv4-address.h" - -namespace ns3 { -/** - * \brief Packet header for UDP packets - */ -class UdpHeader : public Header -{ -public: - - /** - * \brief Constructor - * - * Creates a null header - */ - UdpHeader (); - ~UdpHeader (); - - /** - * \brief Enable checksum calculation for UDP (XXX currently has no effect) - */ - static void EnableChecksums (void); - /** - * \param port the destination port for this UdpHeader - */ - void SetDestinationPort (uint16_t port); - /** - * \param port The source port for this UdpHeader - */ - void SetSourcePort (uint16_t port); - /** - * \return The source port for this UdpHeader - */ - uint16_t GetSourcePort (void) const; - /** - * \return the destination port for this UdpHeader - */ - uint16_t GetDestinationPort (void) const; - /** - * \param size The payload size in bytes - */ - void SetPayloadSize (uint16_t size); - - /** - * \param source the ip source to use in the underlying - * ip packet. - * \param destination the ip destination to use in the - * underlying ip packet. - * \param protocol the protocol number to use in the underlying - * ip packet. - * - * If you want to use udp checksums, you should call this - * method prior to adding the header to a packet. - */ - void InitializeChecksum (Ipv4Address source, - Ipv4Address destination, - uint8_t protocol); - - static TypeId GetTypeId (void); - virtual TypeId GetInstanceTypeId (void) const; - virtual void Print (std::ostream &os) const; - virtual uint32_t GetSerializedSize (void) const; - virtual void Serialize (Buffer::Iterator start) const; - virtual uint32_t Deserialize (Buffer::Iterator start); - -private: - uint16_t m_sourcePort; - uint16_t m_destinationPort; - uint16_t m_payloadSize; - uint16_t m_initialChecksum; - - static bool m_calcChecksum; -}; - -} // namespace ns3 - -#endif /* UDP_HEADER */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-l4-protocol.cc --- a/src/internet-node/udp-l4-protocol.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/* -*- 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 "ns3/log.h" -#include "ns3/assert.h" -#include "ns3/packet.h" -#include "ns3/node.h" - -#include "udp-l4-protocol.h" -#include "udp-header.h" -#include "ipv4-end-point-demux.h" -#include "ipv4-end-point.h" -#include "ipv4-l3-protocol.h" -#include "udp-socket-impl.h" - -NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol"); - -namespace ns3 { - -NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol); - -/* see http://www.iana.org/assignments/protocol-numbers */ -const uint8_t UdpL4Protocol::PROT_NUMBER = 17; - -TypeId -UdpL4Protocol::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::UdpL4Protocol") - .SetParent () - .AddConstructor () - ; - return tid; -} - -UdpL4Protocol::UdpL4Protocol () - : m_endPoints (new Ipv4EndPointDemux ()) -{ - NS_LOG_FUNCTION_NOARGS (); -} - -UdpL4Protocol::~UdpL4Protocol () -{ - NS_LOG_FUNCTION_NOARGS (); -} - -void -UdpL4Protocol::SetNode (Ptr node) -{ - m_node = node; -} - -int -UdpL4Protocol::GetProtocolNumber (void) const -{ - return PROT_NUMBER; -} -int -UdpL4Protocol::GetVersion (void) const -{ - return 2; -} - - -void -UdpL4Protocol::DoDispose (void) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_endPoints != 0) - { - delete m_endPoints; - m_endPoints = 0; - } - m_node = 0; - Ipv4L4Protocol::DoDispose (); -} - -Ptr -UdpL4Protocol::CreateSocket (void) -{ - NS_LOG_FUNCTION_NOARGS (); - Ptr socket = CreateObject (); - socket->SetNode (m_node); - socket->SetUdp (this); - return socket; -} - -Ipv4EndPoint * -UdpL4Protocol::Allocate (void) -{ - NS_LOG_FUNCTION_NOARGS (); - return m_endPoints->Allocate (); -} - -Ipv4EndPoint * -UdpL4Protocol::Allocate (Ipv4Address address) -{ - NS_LOG_FUNCTION (this << address); - return m_endPoints->Allocate (address); -} - -Ipv4EndPoint * -UdpL4Protocol::Allocate (uint16_t port) -{ - NS_LOG_FUNCTION (this << port); - return m_endPoints->Allocate (port); -} - -Ipv4EndPoint * -UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port) -{ - NS_LOG_FUNCTION (this << address << port); - return m_endPoints->Allocate (address, port); -} -Ipv4EndPoint * -UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort) -{ - NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); - return m_endPoints->Allocate (localAddress, localPort, - peerAddress, peerPort); -} - -void -UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) -{ - NS_LOG_FUNCTION (this << endPoint); - m_endPoints->DeAllocate (endPoint); -} - -void -UdpL4Protocol::Receive(Ptr packet, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr interface) -{ - NS_LOG_FUNCTION (this << packet << source << destination); - - UdpHeader udpHeader; - packet->RemoveHeader (udpHeader); - Ipv4EndPointDemux::EndPoints endPoints = - m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (), - source, udpHeader.GetSourcePort (), interface); - for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); - endPoint != endPoints.end (); endPoint++) - { - (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ()); - } -} - -void -UdpL4Protocol::Send (Ptr packet, - Ipv4Address saddr, Ipv4Address daddr, - uint16_t sport, uint16_t dport) -{ - NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport); - - UdpHeader udpHeader; - udpHeader.SetDestinationPort (dport); - udpHeader.SetSourcePort (sport); - udpHeader.SetPayloadSize (packet->GetSize ()); - udpHeader.InitializeChecksum (saddr, - daddr, - PROT_NUMBER); - - packet->AddHeader (udpHeader); - - Ptr ipv4 = m_node->GetObject (); - if (ipv4 != 0) - { - NS_LOG_LOGIC ("Sending to IP"); - ipv4->Send (packet, saddr, daddr, PROT_NUMBER); - } -} - - -}; // namespace ns3 - diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-l4-protocol.h --- a/src/internet-node/udp-l4-protocol.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2005,2006,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 - * - * Author: Mathieu Lacage - */ - -#ifndef UDP_L4_PROTOCOL_H -#define UDP_L4_PROTOCOL_H - -#include - -#include "ns3/packet.h" -#include "ns3/ipv4-address.h" -#include "ns3/ptr.h" -#include "ipv4-end-point-demux.h" -#include "ipv4-l4-protocol.h" - -namespace ns3 { - -class Node; -class Socket; -/** - * \brief Implementation of the UDP protocol - */ -class UdpL4Protocol : public Ipv4L4Protocol { -public: - static TypeId GetTypeId (void); - static const uint8_t PROT_NUMBER; - - UdpL4Protocol (); - virtual ~UdpL4Protocol (); - - void SetNode (Ptr node); - - virtual int GetProtocolNumber (void) const; - virtual int GetVersion (void) const; - - /** - * \return A smart Socket pointer to a UdpSocket, allocated by this instance - * of the UDP protocol - */ - Ptr CreateSocket (void); - - Ipv4EndPoint *Allocate (void); - Ipv4EndPoint *Allocate (Ipv4Address address); - Ipv4EndPoint *Allocate (uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); - Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, - Ipv4Address peerAddress, uint16_t peerPort); - - void DeAllocate (Ipv4EndPoint *endPoint); - - // called by UdpSocket. - /** - * \brief Send a packet via UDP - * \param packet The packet to send - * \param saddr The source Ipv4Address - * \param daddr The destination Ipv4Address - * \param sport The source port number - * \param dport The destination port number - */ - void Send (Ptr packet, - Ipv4Address saddr, Ipv4Address daddr, - uint16_t sport, uint16_t dport); - /** - * \brief Receive a packet up the protocol stack - * \param p The Packet to dump the contents into - * \param source The source's Ipv4Address - * \param destination The destinations Ipv4Address - * \param interface the interface from which the packet is coming. - */ - // inherited from Ipv4L4Protocol - virtual void Receive(Ptr p, - Ipv4Address const &source, - Ipv4Address const &destination, - Ptr interface); -protected: - virtual void DoDispose (void); -private: - Ptr m_node; - Ipv4EndPointDemux *m_endPoints; -}; - -}; // namespace ns3 - -#endif /* UDP_L4_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-socket-factory-impl.cc --- a/src/internet-node/udp-socket-factory-impl.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +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 - * - * Author: Mathieu Lacage - */ -#include "udp-socket-factory-impl.h" -#include "udp-l4-protocol.h" -#include "ns3/socket.h" -#include "ns3/assert.h" - -namespace ns3 { - -UdpSocketFactoryImpl::UdpSocketFactoryImpl () - : m_udp (0) -{} -UdpSocketFactoryImpl::~UdpSocketFactoryImpl () -{ - NS_ASSERT (m_udp == 0); -} - -void -UdpSocketFactoryImpl::SetUdp (Ptr udp) -{ - m_udp = udp; -} - -Ptr -UdpSocketFactoryImpl::CreateSocket (void) -{ - return m_udp->CreateSocket (); -} - -void -UdpSocketFactoryImpl::DoDispose (void) -{ - m_udp = 0; - UdpSocketFactory::DoDispose (); -} - -} // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-socket-factory-impl.h --- a/src/internet-node/udp-socket-factory-impl.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +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 - * - * Author: Mathieu Lacage - */ -#ifndef UDP_SOCKET_FACTORY_IMPL_H -#define UDP_SOCKET_FACTORY_IMPL_H - -#include "ns3/udp-socket-factory.h" -#include "ns3/ptr.h" - -namespace ns3 { - -class UdpL4Protocol; - -/** - * \brief Object to create UDP socket instances - * \internal - * - * This class implements the API for creating UDP sockets. - * It is a socket factory (deriving from class SocketFactory). - */ -class UdpSocketFactoryImpl : public UdpSocketFactory -{ -public: - UdpSocketFactoryImpl (); - virtual ~UdpSocketFactoryImpl (); - - void SetUdp (Ptr udp); - - /** - * \brief Implements a method to create a Udp-based socket and return - * a base class smart pointer to the socket. - * \internal - * - * \return smart pointer to Socket - */ - virtual Ptr CreateSocket (void); - -protected: - virtual void DoDispose (void); -private: - Ptr m_udp; -}; - -} // namespace ns3 - -#endif /* UDP_SOCKET_FACTORY_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-socket-impl.cc --- a/src/internet-node/udp-socket-impl.cc Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,694 +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 - * - * Author: Mathieu Lacage - */ - -#include "ns3/log.h" -#include "ns3/node.h" -#include "ns3/inet-socket-address.h" -#include "ns3/ipv4-route.h" -#include "ns3/ipv4.h" -#include "ns3/udp-socket-factory.h" -#include "ns3/trace-source-accessor.h" -#include "ns3/uinteger.h" -#include "ns3/boolean.h" -#include "udp-socket-impl.h" -#include "udp-l4-protocol.h" -#include "ipv4-end-point.h" -#include "ipv4-l4-demux.h" - -NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl"); - -namespace ns3 { - -static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507; - -// Add attributes generic to all UdpSockets to base class UdpSocket -TypeId -UdpSocketImpl::GetTypeId (void) -{ - static TypeId tid = TypeId ("ns3::UdpSocketImpl") - .SetParent () - .AddConstructor () - .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow", - MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace)) - ; - return tid; -} - -UdpSocketImpl::UdpSocketImpl () - : m_endPoint (0), - m_node (0), - m_udp (0), - m_errno (ERROR_NOTERROR), - m_shutdownSend (false), - m_shutdownRecv (false), - m_connected (false), - m_rxAvailable (0) -{ - NS_LOG_FUNCTION_NOARGS (); -} - -UdpSocketImpl::~UdpSocketImpl () -{ - NS_LOG_FUNCTION_NOARGS (); - - m_node = 0; - if (m_endPoint != 0) - { - NS_ASSERT (m_udp != 0); - /** - * Note that this piece of code is a bit tricky: - * when DeAllocate is called, it will call into - * Ipv4EndPointDemux::Deallocate which triggers - * a delete of the associated endPoint which triggers - * in turn a call to the method ::Destroy below - * will will zero the m_endPoint field. - */ - NS_ASSERT (m_endPoint != 0); - m_udp->DeAllocate (m_endPoint); - NS_ASSERT (m_endPoint == 0); - } - m_udp = 0; -} - -void -UdpSocketImpl::SetNode (Ptr node) -{ - NS_LOG_FUNCTION_NOARGS (); - m_node = node; - -} -void -UdpSocketImpl::SetUdp (Ptr udp) -{ - NS_LOG_FUNCTION_NOARGS (); - m_udp = udp; -} - - -enum Socket::SocketErrno -UdpSocketImpl::GetErrno (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_errno; -} - -Ptr -UdpSocketImpl::GetNode (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - return m_node; -} - -void -UdpSocketImpl::Destroy (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_node = 0; - m_endPoint = 0; - m_udp = 0; -} - -int -UdpSocketImpl::FinishBind (void) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_endPoint == 0) - { - return -1; - } - m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr (this))); - m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr (this))); - return 0; -} - -int -UdpSocketImpl::Bind (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_endPoint = m_udp->Allocate (); - return FinishBind (); -} - -int -UdpSocketImpl::Bind (const Address &address) -{ - NS_LOG_FUNCTION (this << address); - - if (!InetSocketAddress::IsMatchingType (address)) - { - NS_LOG_ERROR ("Not IsMatchingType"); - return ERROR_INVAL; - } - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); - if (ipv4 == Ipv4Address::GetAny () && port == 0) - { - m_endPoint = m_udp->Allocate (); - } - else if (ipv4 == Ipv4Address::GetAny () && port != 0) - { - m_endPoint = m_udp->Allocate (port); - } - else if (ipv4 != Ipv4Address::GetAny () && port == 0) - { - m_endPoint = m_udp->Allocate (ipv4); - } - else if (ipv4 != Ipv4Address::GetAny () && port != 0) - { - m_endPoint = m_udp->Allocate (ipv4, port); - } - - return FinishBind (); -} - -int -UdpSocketImpl::ShutdownSend (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_shutdownSend = true; - return 0; -} - -int -UdpSocketImpl::ShutdownRecv (void) -{ - NS_LOG_FUNCTION_NOARGS (); - m_shutdownRecv = false; - return 0; -} - -int -UdpSocketImpl::Close(void) -{ - NS_LOG_FUNCTION_NOARGS (); - NotifyCloseCompleted (); - return 0; -} - -int -UdpSocketImpl::Connect(const Address & address) -{ - NS_LOG_FUNCTION (this << address); - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - m_defaultAddress = transport.GetIpv4 (); - m_defaultPort = transport.GetPort (); - NotifyConnectionSucceeded (); - m_connected = true; - - return 0; -} - -int -UdpSocketImpl::Listen (uint32_t queueLimit) -{ - m_errno = Socket::ERROR_OPNOTSUPP; - return -1; -} - -int -UdpSocketImpl::Send (Ptr p) -{ - NS_LOG_FUNCTION (this << p); - - if (!m_connected) - { - m_errno = ERROR_NOTCONN; - return -1; - } - return DoSend (p); -} - -int -UdpSocketImpl::DoSend (Ptr p) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_endPoint == 0) - { - if (Bind () == -1) - { - NS_ASSERT (m_endPoint == 0); - return -1; - } - NS_ASSERT (m_endPoint != 0); - } - if (m_shutdownSend) - { - m_errno = ERROR_SHUTDOWN; - return -1; - } - - return DoSendTo (p, m_defaultAddress, m_defaultPort); -} - -int -UdpSocketImpl::DoSendTo (Ptr p, const Address &address) -{ - NS_LOG_FUNCTION (this << p << address); - - if (!m_connected) - { - NS_LOG_LOGIC ("Not connected"); - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); - return DoSendTo (p, ipv4, port); - } - else - { - // connected UDP socket must use default addresses - NS_LOG_LOGIC ("Connected"); - return DoSendTo (p, m_defaultAddress, m_defaultPort); - } -} - -int -UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) -{ - NS_LOG_FUNCTION (this << p << dest << port); - - if (m_endPoint == 0) - { - if (Bind () == -1) - { - NS_ASSERT (m_endPoint == 0); - return -1; - } - NS_ASSERT (m_endPoint != 0); - } - if (m_shutdownSend) - { - m_errno = ERROR_SHUTDOWN; - return -1; - } - - if (p->GetSize () > GetTxAvailable () ) - { - m_errno = ERROR_MSGSIZE; - return -1; - } - - uint32_t localIfIndex; - Ptr ipv4 = m_node->GetObject (); - - // Locally override the IP TTL for this socket - // We cannot directly modify the TTL at this stage, so we set a Packet tag - // The destination can be either multicast, unicast/anycast, or - // either all-hosts broadcast or limited (subnet-directed) broadcast. - // For the latter two broadcast types, the TTL will later be set to one - // irrespective of what is set in these socket options. So, this tagging - // may end up setting the TTL of a limited broadcast packet to be - // the same as a unicast, but it will be fixed further down the stack - //NS_LOG_UNCOND ("IPttl: " << m_ipTtl); - if (m_ipMulticastTtl != 0 && dest.IsMulticast ()) - { - SocketIpTtlTag tag; - tag.SetTtl (m_ipMulticastTtl); - p->AddTag (tag); - } - else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ()) - { - SocketIpTtlTag tag; - tag.SetTtl (m_ipTtl); - p->AddTag (tag); - } - // - // If dest is sent to the limited broadcast address (all ones), - // convert it to send a copy of the packet out of every interface - // - if (dest.IsBroadcast ()) - { - NS_LOG_LOGIC ("Limited broadcast start."); - for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ ) - { - Ipv4Address addri = ipv4->GetAddress (i); - Ipv4Mask maski = ipv4->GetNetworkMask (i); - Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski); - NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast - << " (mask is " << maski << ")"); - m_udp->Send (p->Copy (), addri, bcast, - m_endPoint->GetLocalPort (), port); - NotifyDataSent (p->GetSize ()); - } - NS_LOG_LOGIC ("Limited broadcast end."); - return p->GetSize(); - } - else if (ipv4->GetIfIndexForDestination(dest, localIfIndex)) - { - NS_LOG_LOGIC ("Route exists"); - m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest, - m_endPoint->GetLocalPort (), port); - NotifyDataSent (p->GetSize ()); - return p->GetSize();; - } - else - { - NS_LOG_ERROR ("ERROR_NOROUTETOHOST"); - m_errno = ERROR_NOROUTETOHOST; - return -1; - } - - return 0; -} - -// XXX maximum message size for UDP broadcast is limited by MTU -// size of underlying link; we are not checking that now. -uint32_t -UdpSocketImpl::GetTxAvailable (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - // No finite send buffer is modelled, but we must respect - // the maximum size of an IP datagram (65535 bytes - headers). - return MAX_IPV4_UDP_DATAGRAM_SIZE; -} - -int -UdpSocketImpl::SendTo (Ptr p, const Address &address) -{ - NS_LOG_FUNCTION (this << address << p); - InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); - Ipv4Address ipv4 = transport.GetIpv4 (); - uint16_t port = transport.GetPort (); - return DoSendTo (p, ipv4, port); -} - -Ptr -UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) -{ - NS_LOG_FUNCTION_NOARGS (); - if (m_deliveryQueue.empty() ) - { - return 0; - } - Ptr p = m_deliveryQueue.front (); - if (p->GetSize () <= maxSize) - { - m_deliveryQueue.pop (); - m_rxAvailable -= p->GetSize (); - } - else - { - p = 0; - } - return p; -} - -uint32_t -UdpSocketImpl::GetRxAvailable (void) const -{ - NS_LOG_FUNCTION_NOARGS (); - // We separately maintain this state to avoid walking the queue - // every time this might be called - return m_rxAvailable; -} - -void -UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) -{ - NS_LOG_FUNCTION (this << packet << ipv4 << port); - - if (m_shutdownRecv) - { - return; - } - if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) - { - Address address = InetSocketAddress (ipv4, port); - SocketRxAddressTag tag; - tag.SetAddress (address); - packet->AddTag (tag); - m_deliveryQueue.push (packet); - m_rxAvailable += packet->GetSize (); - NotifyDataRecv (); - } - else - { - // In general, this case should not occur unless the - // receiving application reads data from this socket slowly - // in comparison to the arrival rate - // - // drop and trace packet - NS_LOG_WARN ("No receive buffer space available. Drop."); - m_dropTrace (packet); - } -} - - -void -UdpSocketImpl::SetRcvBufSize (uint32_t size) -{ - m_rcvBufSize = size; -} - -uint32_t -UdpSocketImpl::GetRcvBufSize (void) const -{ - return m_rcvBufSize; -} - -void -UdpSocketImpl::SetIpTtl (uint32_t ipTtl) -{ - m_ipTtl = ipTtl; -} - -uint32_t -UdpSocketImpl::GetIpTtl (void) const -{ - return m_ipTtl; -} - -void -UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl) -{ - m_ipMulticastTtl = ipTtl; -} - -uint32_t -UdpSocketImpl::GetIpMulticastTtl (void) const -{ - return m_ipMulticastTtl; -} - -} //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); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - 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); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - 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); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - 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); - ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2")); - ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); - 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), - 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), - 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), -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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/udp-socket-impl.h --- a/src/internet-node/udp-socket-impl.h Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +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 - * - * Author: Mathieu Lacage - */ -#ifndef UDP_SOCKET_IMPL_H -#define UDP_SOCKET_IMPL_H - -#include -#include -#include "ns3/callback.h" -#include "ns3/traced-callback.h" -#include "ns3/socket.h" -#include "ns3/ptr.h" -#include "ns3/ipv4-address.h" -#include "ns3/udp-socket.h" - -namespace ns3 { - -class Ipv4EndPoint; -class Node; -class Packet; -class UdpL4Protocol; - -class UdpSocketImpl : public UdpSocket -{ -public: - static TypeId GetTypeId (void); - /** - * Create an unbound udp socket. - */ - UdpSocketImpl (); - virtual ~UdpSocketImpl (); - - void SetNode (Ptr node); - void SetUdp (Ptr udp); - - virtual enum SocketErrno GetErrno (void) const; - virtual Ptr GetNode (void) const; - virtual int Bind (void); - virtual int Bind (const Address &address); - virtual int Close (void); - virtual int ShutdownSend (void); - virtual int ShutdownRecv (void); - virtual int Connect(const Address &address); - virtual int Listen (uint32_t queueLimit); - virtual int Send (Ptr p); - virtual int SendTo (Ptr p, const Address &address); - virtual uint32_t GetTxAvailable (void) const; - - virtual Ptr Recv (uint32_t maxSize, uint32_t flags); - virtual uint32_t GetRxAvailable (void) const; - -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; - - friend class UdpSocketFactory; - // invoked by Udp class - int FinishBind (void); - void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); - void Destroy (void); - int DoSend (Ptr p); - int DoSendTo (Ptr p, const Address &daddr); - int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); - - Ipv4EndPoint *m_endPoint; - Ptr m_node; - Ptr m_udp; - Ipv4Address m_defaultAddress; - uint16_t m_defaultPort; - Callback,uint32_t,const Address &> m_dummyRxCallback; - Callback,uint8_t const*,uint32_t,const Address &> m_rxCallback; - TracedCallback > m_dropTrace; - - enum SocketErrno m_errno; - bool m_shutdownSend; - bool m_shutdownRecv; - bool m_connected; - - std::queue > m_deliveryQueue; - uint32_t m_rxAvailable; - - // Socket attributes - uint32_t m_rcvBufSize; - uint32_t m_ipTtl; - uint32_t m_ipMulticastTtl; - -}; - -}//namespace ns3 - -#endif /* UDP_SOCKET_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/waf --- a/src/internet-node/waf Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -exec "`dirname "$0"`"/../../waf "$@" \ No newline at end of file diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-node/wscript --- a/src/internet-node/wscript Mon Jun 09 11:39:29 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- - - -def build(bld): - obj = bld.create_ns3_module('internet-node', ['node']) - obj.source = [ - 'internet-stack.cc', - 'ipv4-l4-demux.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-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', - 'ipv4-impl.cc', - 'udp-socket-factory-impl.cc', - 'tcp-socket-factory-impl.cc', - 'pending-data.cc', - 'sequence-number.cc', - 'rtt-estimator.cc', - ] - - headers = bld.create_obj('ns3header') - headers.module = 'internet-node' - headers.source = [ - 'internet-stack.h', - 'udp-header.h', - 'tcp-header.h', - 'sequence-number.h', - ] diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-cache.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-cache.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,287 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 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 "ns3/assert.h" +#include "ns3/packet.h" +#include "ns3/simulator.h" +#include "ns3/uinteger.h" +#include "ns3/log.h" + +#include "arp-cache.h" +#include "arp-header.h" +#include "ipv4-interface.h" + +NS_LOG_COMPONENT_DEFINE ("ArpCache"); + +namespace ns3 { + +TypeId +ArpCache::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::ArpCache") + .SetParent () + .AddAttribute ("AliveTimeout", + "When this timeout expires, the matching cache entry needs refreshing", + TimeValue (Seconds (120)), + MakeTimeAccessor (&ArpCache::m_aliveTimeout), + MakeTimeChecker ()) + .AddAttribute ("DeadTimeout", + "When this timeout expires, a new attempt to resolve the matching entry is made", + TimeValue (Seconds (100)), + MakeTimeAccessor (&ArpCache::m_deadTimeout), + MakeTimeChecker ()) + .AddAttribute ("WaitReplyTimeout", + "When this timeout expires, the matching cache entry is marked dead", + TimeValue (Seconds (1)), + MakeTimeAccessor (&ArpCache::m_waitReplyTimeout), + MakeTimeChecker ()) + .AddAttribute ("PendingQueueSize", + "The size of the queue for packets pending an arp reply.", + UintegerValue (3), + MakeUintegerAccessor (&ArpCache::m_pendingQueueSize), + MakeUintegerChecker ()) + ; + return tid; +} + +ArpCache::ArpCache () + : m_device (0), + m_interface (0) +{ + NS_LOG_FUNCTION (this); +} + +ArpCache::~ArpCache () +{ + NS_LOG_FUNCTION (this); +} + +void +ArpCache::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + Flush (); + m_device = 0; + m_interface = 0; + Object::DoDispose (); +} + +void +ArpCache::SetDevice (Ptr device, Ptr interface) +{ + m_device = device; + m_interface = interface; +} + +Ptr +ArpCache::GetDevice (void) const +{ + return m_device; +} + +Ptr +ArpCache::GetInterface (void) const +{ + return m_interface; +} + +void +ArpCache::SetAliveTimeout (Time aliveTimeout) +{ + m_aliveTimeout = aliveTimeout; +} +void +ArpCache::SetDeadTimeout (Time deadTimeout) +{ + m_deadTimeout = deadTimeout; +} +void +ArpCache::SetWaitReplyTimeout (Time waitReplyTimeout) +{ + m_waitReplyTimeout = waitReplyTimeout; +} + +Time +ArpCache::GetAliveTimeout (void) const +{ + return m_aliveTimeout; +} +Time +ArpCache::GetDeadTimeout (void) const +{ + return m_deadTimeout; +} +Time +ArpCache::GetWaitReplyTimeout (void) const +{ + return m_waitReplyTimeout; +} + +void +ArpCache::Flush (void) +{ + for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++) + { + delete (*i).second; + } + m_arpCache.erase (m_arpCache.begin (), m_arpCache.end ()); +} + +ArpCache::Entry * +ArpCache::Lookup (Ipv4Address to) +{ + if (m_arpCache.find (to) != m_arpCache.end ()) + { + ArpCache::Entry *entry = m_arpCache[to]; + return entry; + } + return 0; +} + +ArpCache::Entry * +ArpCache::Add (Ipv4Address to) +{ + NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ()); + + ArpCache::Entry *entry = new ArpCache::Entry (this); + m_arpCache[to] = entry; + return entry; +} + +ArpCache::Entry::Entry (ArpCache *arp) + : m_arp (arp), + m_state (ALIVE) +{} + + +bool +ArpCache::Entry::IsDead (void) +{ + return (m_state == DEAD)?true:false; +} +bool +ArpCache::Entry::IsAlive (void) +{ + return (m_state == ALIVE)?true:false; +} +bool +ArpCache::Entry::IsWaitReply (void) +{ + return (m_state == WAIT_REPLY)?true:false; +} + + +void +ArpCache::Entry::MarkDead (void) +{ + m_state = DEAD; + UpdateSeen (); +} +void +ArpCache::Entry::MarkAlive (Address macAddress) +{ + NS_ASSERT (m_state == WAIT_REPLY); + m_macAddress = macAddress; + m_state = ALIVE; + UpdateSeen (); +} + +bool +ArpCache::Entry::UpdateWaitReply (Ptr waiting) +{ + NS_ASSERT (m_state == WAIT_REPLY); + /* We are already waiting for an answer so + * we dump the previously waiting packet and + * replace it with this one. + */ + if (m_pending.size () >= m_arp->m_pendingQueueSize) + { + return false; + } + m_pending.push_back (waiting); + return true; +} +void +ArpCache::Entry::MarkWaitReply (Ptr waiting) +{ + NS_ASSERT (m_state == ALIVE || m_state == DEAD); + NS_ASSERT (m_pending.empty ()); + m_state = WAIT_REPLY; + m_pending.push_back (waiting); + UpdateSeen (); +} + +Address +ArpCache::Entry::GetMacAddress (void) +{ + NS_ASSERT (m_state == ALIVE); + return m_macAddress; +} +bool +ArpCache::Entry::IsExpired (void) +{ + Time timeout; + switch (m_state) { + case ArpCache::Entry::WAIT_REPLY: + timeout = m_arp->GetWaitReplyTimeout (); + break; + case ArpCache::Entry::DEAD: + timeout = m_arp->GetDeadTimeout (); + break; + case ArpCache::Entry::ALIVE: + timeout = m_arp->GetAliveTimeout (); + break; + default: + NS_ASSERT (false); + timeout = Seconds (0); + /* NOTREACHED */ + break; + } + Time delta = Simulator::Now () - m_lastSeen; + if (delta >= timeout) + { + return true; + } + else + { + return false; + } +} +Ptr +ArpCache::Entry::DequeuePending (void) +{ + if (m_pending.empty ()) + { + return 0; + } + else + { + Ptr p = m_pending.front (); + m_pending.pop_front (); + return p; + } +} +void +ArpCache::Entry::UpdateSeen (void) +{ + m_lastSeen = Simulator::Now (); +} + +} // namespace ns3 + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-cache.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-cache.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,178 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 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 ARP_CACHE_H +#define ARP_CACHE_H + +#include +#include +#include "ns3/packet.h" +#include "ns3/nstime.h" +#include "ns3/net-device.h" +#include "ns3/ipv4-address.h" +#include "ns3/address.h" +#include "ns3/ptr.h" +#include "ns3/object.h" +#include "sgi-hashmap.h" + +namespace ns3 { + +class NetDevice; +class Ipv4Interface; + +/** + * \brief An ARP cache + * + * A cached lookup table for translating layer 3 addresses to layer 2. + * This implementation does lookups from IPv4 to a MAC address + */ +class ArpCache : public Object +{ +public: + static TypeId GetTypeId (void); + class Entry; + ArpCache (); + ~ArpCache (); + + /** + * \param device The hardware NetDevice associated with this ARP chache + * \param interface the Ipv4Interface associated with this ARP chache + */ + void SetDevice (Ptr device, Ptr interface); + /** + * \return The NetDevice that this ARP cache is associated with + */ + Ptr GetDevice (void) const; + /** + * \return the Ipv4Interface that this ARP cache is associated with + */ + Ptr GetInterface (void) const; + + void SetAliveTimeout (Time aliveTimeout); + void SetDeadTimeout (Time deadTimeout); + void SetWaitReplyTimeout (Time waitReplyTimeout); + Time GetAliveTimeout (void) const; + Time GetDeadTimeout (void) const; + Time GetWaitReplyTimeout (void) const; + + /** + * \brief Do lookup in the ARP chache against an IP address + * \param destination The destination IPv4 address to lookup the MAC address + * of + * \return An ArpCache::Entry with info about layer 2 + */ + ArpCache::Entry *Lookup (Ipv4Address destination); + /** + * \brief Add an Ipv4Address to this ARP cache + */ + ArpCache::Entry *Add (Ipv4Address to); + /** + * \brief Clear the ArpCache of all entries + */ + void Flush (void); + + /** + * \brief A record that that holds information about an ArpCache entry + */ + class Entry { + public: + /** + * \brief Constructor + * \param arp The ArpCache this entry belongs to + */ + Entry (ArpCache *arp); + + /** + * \brief Changes the state of this entry to dead + */ + void MarkDead (void); + /** + * \param macAddress + */ + void MarkAlive (Address macAddress); + /** + * \param waiting + */ + void MarkWaitReply (Ptr waiting); + /** + * \param waiting + * \return + */ + bool UpdateWaitReply (Ptr waiting); + /** + * \return True if the state of this entry is dead; false otherwise. + */ + bool IsDead (void); + /** + * \return True if the state of this entry is alive; false otherwise. + */ + bool IsAlive (void); + /** + * \return True if the state of this entry is wait_reply; false otherwise. + */ + bool IsWaitReply (void); + + /** + * \return The MacAddress of this entry + */ + Address GetMacAddress (void); + /** + * \return True if this entry has timedout; false otherwise. + */ + bool IsExpired (void); + + /** + * \returns 0 is no packet is pending, the next packet to send if + * packets are pending. + */ + Ptr DequeuePending (void); + private: + enum ArpCacheEntryState_e { + ALIVE, + WAIT_REPLY, + DEAD + }; + + void UpdateSeen (void); + ArpCache *m_arp; + ArpCacheEntryState_e m_state; + Time m_lastSeen; + Address m_macAddress; + std::list > m_pending; + }; + +private: + typedef sgi::hash_map Cache; + typedef sgi::hash_map::iterator CacheI; + + virtual void DoDispose (void); + + Ptr m_device; + Ptr m_interface; + Time m_aliveTimeout; + Time m_deadTimeout; + Time m_waitReplyTimeout; + uint32_t m_pendingQueueSize; + Cache m_arpCache; +}; + + +}; // namespace ns3 + +#endif /* ARP_CACHE_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-header.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-header.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,161 @@ +/* -*- 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 "ns3/assert.h" +#include "ns3/address-utils.h" +#include "arp-header.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (ArpHeader); + +void +ArpHeader::SetRequest (Address sourceHardwareAddress, + Ipv4Address sourceProtocolAddress, + Address destinationHardwareAddress, + Ipv4Address destinationProtocolAddress) +{ + m_type = ARP_TYPE_REQUEST; + m_macSource = sourceHardwareAddress; + m_macDest = destinationHardwareAddress; + m_ipv4Source = sourceProtocolAddress; + m_ipv4Dest = destinationProtocolAddress; +} +void +ArpHeader::SetReply (Address sourceHardwareAddress, + Ipv4Address sourceProtocolAddress, + Address destinationHardwareAddress, + Ipv4Address destinationProtocolAddress) +{ + m_type = ARP_TYPE_REPLY; + m_macSource = sourceHardwareAddress; + m_macDest = destinationHardwareAddress; + m_ipv4Source = sourceProtocolAddress; + m_ipv4Dest = destinationProtocolAddress; +} +bool +ArpHeader::IsRequest (void) const +{ + return (m_type == ARP_TYPE_REQUEST)?true:false; +} +bool +ArpHeader::IsReply (void) const +{ + return (m_type == ARP_TYPE_REPLY)?true:false; +} +Address +ArpHeader::GetSourceHardwareAddress (void) +{ + return m_macSource; +} +Address +ArpHeader::GetDestinationHardwareAddress (void) +{ + return m_macDest; +} +Ipv4Address +ArpHeader::GetSourceIpv4Address (void) +{ + return m_ipv4Source; +} +Ipv4Address +ArpHeader::GetDestinationIpv4Address (void) +{ + return m_ipv4Dest; +} + + +TypeId +ArpHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::ArpHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} +TypeId +ArpHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +void +ArpHeader::Print (std::ostream &os) const +{ + if (IsRequest ()) + { + os << "request " + << "source mac: " << m_macSource << " " + << "source ipv4: " << m_ipv4Source << " " + << "dest ipv4: " << m_ipv4Dest + ; + } + else + { + NS_ASSERT (IsReply ()); + os << "reply " + << "source mac: " << m_macSource << " " + << "source ipv4: " << m_ipv4Source << " " + << "dest mac: " << m_macDest << " " + << "dest ipv4: " < + */ + +#ifndef ARP_HEADER_H +#define ARP_HEADER_H + +#include "ns3/header.h" +#include "ns3/address.h" +#include "ns3/ipv4-address.h" +#include + +namespace ns3 { +/** + * \brief The packet header for an ARP packet + */ +class ArpHeader : public Header +{ +public: + void SetRequest (Address sourceHardwareAddress, + Ipv4Address sourceProtocolAddress, + Address destinationHardwareAddress, + Ipv4Address destinationProtocolAddress); + void SetReply (Address sourceHardwareAddress, + Ipv4Address sourceProtocolAddress, + Address destinationHardwareAddress, + Ipv4Address destinationProtocolAddress); + bool IsRequest (void) const; + bool IsReply (void) const; + Address GetSourceHardwareAddress (void); + Address GetDestinationHardwareAddress (void); + Ipv4Address GetSourceIpv4Address (void); + Ipv4Address GetDestinationIpv4Address (void); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual void Print (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + + enum ArpType_e { + ARP_TYPE_REQUEST = 1, + ARP_TYPE_REPLY = 2 + }; + uint16_t m_type; + Address m_macSource; + Address m_macDest; + Ipv4Address m_ipv4Source; + Ipv4Address m_ipv4Dest; +}; + +}; // namespace ns3 + +#endif /* ARP_HEADER_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-ipv4-interface.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-ipv4-interface.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,156 @@ +/* -*- 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_node = 0; + 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); + if (m_device->NeedsArp ()) + { + NS_LOG_LOGIC ("Needs ARP"); + Ptr arp = + m_node->GetObject (); + Address hardwareDestination; + bool found; + + if (dest.IsBroadcast () || + dest.IsSubnetDirectedBroadcast (GetNetworkMask ()) ) + { + 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 ()->MakeMulticastAddress(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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-ipv4-interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-ipv4-interface.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,64 @@ +/* -*- 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; + +/** + * \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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-l3-protocol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-l3-protocol.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,303 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 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 "ns3/packet.h" +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/net-device.h" +#include "ns3/object-vector.h" +#include "ns3/trace-source-accessor.h" + +#include "ipv4-l3-protocol.h" +#include "arp-l3-protocol.h" +#include "arp-header.h" +#include "arp-cache.h" +#include "ipv4-interface.h" + +NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol"); + +namespace ns3 { + +const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806; + +NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol); + +TypeId +ArpL3Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::ArpL3Protocol") + .SetParent () + .AddAttribute ("CacheList", + "The list of ARP caches", + ObjectVectorValue (), + MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList), + MakeObjectVectorChecker ()) + .AddTraceSource ("Drop", + "Packet dropped because not enough room in pending queue for a specific cache entry.", + MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace)) + ; + return tid; +} + +ArpL3Protocol::ArpL3Protocol () +{ + NS_LOG_FUNCTION (this); +} + +ArpL3Protocol::~ArpL3Protocol () +{ + NS_LOG_FUNCTION (this); +} + +void +ArpL3Protocol::SetNode (Ptr node) +{ + m_node = node; +} + +void +ArpL3Protocol::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i) + { + Ptr cache = *i; + cache->Dispose (); + } + m_cacheList.clear (); + m_node = 0; + Object::DoDispose (); +} + +Ptr +ArpL3Protocol::CreateCache (Ptr device, Ptr interface) +{ + Ptr ipv4 = m_node->GetObject (); + Ptr cache = CreateObject (); + cache->SetDevice (device, interface); + NS_ASSERT (device->IsBroadcast ()); + device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache)); + m_cacheList.push_back (cache); + return cache; +} + +Ptr +ArpL3Protocol::FindCache (Ptr device) +{ + NS_LOG_FUNCTION_NOARGS (); + for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++) + { + if ((*i)->GetDevice () == device) + { + return *i; + } + } + NS_ASSERT (false); + // quiet compiler + return 0; +} + +void +ArpL3Protocol::Receive(Ptr device, Ptr packet, uint16_t protocol, const Address &from) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr cache = FindCache (device); + ArpHeader arp; + packet->RemoveHeader (arp); + + NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") << + " node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for address " << + arp.GetDestinationIpv4Address () << "; we have address " << + cache->GetInterface ()->GetAddress ()); + + /** + * Note: we do not update the ARP cache when we receive an ARP request + * from an unknown node. See bug #107 + */ + + if (arp.IsRequest () && + arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) + { + NS_LOG_LOGIC ("node="<GetId () <<", got request from " << + arp.GetSourceIpv4Address () << " -- send reply"); + SendArpReply (cache, arp.GetSourceIpv4Address (), + arp.GetSourceHardwareAddress ()); + } + else if (arp.IsReply () && + arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) && + arp.GetDestinationHardwareAddress () == device->GetAddress ()) + { + Ipv4Address from = arp.GetSourceIpv4Address (); + ArpCache::Entry *entry = cache->Lookup (from); + if (entry != 0) + { + if (entry->IsWaitReply ()) + { + NS_LOG_LOGIC ("node="<GetId ()<<", got reply from " << + arp.GetSourceIpv4Address () + << " for waiting entry -- flush"); + Address from_mac = arp.GetSourceHardwareAddress (); + entry->MarkAlive (from_mac); + Ptr pending = entry->DequeuePending(); + while (pending != 0) + { + cache->GetInterface ()->Send (pending, + arp.GetSourceIpv4Address ()); + pending = entry->DequeuePending(); + } + } + else + { + // ignore this reply which might well be an attempt + // at poisening my arp cache. + NS_LOG_LOGIC("node="<GetId ()<<", got reply from " << + arp.GetSourceIpv4Address () << + " for non-waiting entry -- drop"); + m_dropTrace (packet); + } + } + else + { + NS_LOG_LOGIC ("node="<GetId ()<<", got reply for unknown entry -- drop"); + m_dropTrace (packet); + } + } + else + { + NS_LOG_LOGIC ("node="<GetId ()<<", got request from " << + arp.GetSourceIpv4Address () << " for unknown address " << + arp.GetDestinationIpv4Address () << " -- drop"); + } +} +bool +ArpL3Protocol::Lookup (Ptr packet, Ipv4Address destination, + Ptr device, + Ptr cache, + Address *hardwareDestination) +{ + NS_LOG_FUNCTION_NOARGS (); + ArpCache::Entry *entry = cache->Lookup (destination); + if (entry != 0) + { + if (entry->IsExpired ()) + { + if (entry->IsDead ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", dead entry for " << destination << " expired -- send arp request"); + entry->MarkWaitReply (packet); + SendArpRequest (cache, destination); + } + else if (entry->IsAlive ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", alive entry for " << destination << " expired -- send arp request"); + entry->MarkWaitReply (packet); + SendArpRequest (cache, destination); + } + else if (entry->IsWaitReply ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", wait reply for " << destination << " expired -- drop"); + entry->MarkDead (); + Ptr pending = entry->DequeuePending(); + while (pending != 0) + { + m_dropTrace (pending); + pending = entry->DequeuePending(); + } + m_dropTrace (packet); + } + } + else + { + if (entry->IsDead ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", dead entry for " << destination << " valid -- drop"); + m_dropTrace (packet); + } + else if (entry->IsAlive ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", alive entry for " << destination << " valid -- send"); + *hardwareDestination = entry->GetMacAddress (); + return true; + } + else if (entry->IsWaitReply ()) + { + NS_LOG_LOGIC ("node="<GetId ()<< + ", wait reply for " << destination << " valid -- drop previous"); + if (!entry->UpdateWaitReply (packet)) + { + m_dropTrace (packet); + } + } + } + } + else + { + // This is our first attempt to transmit data to this destination. + NS_LOG_LOGIC ("node="<GetId ()<< + ", no entry for " << destination << " -- send arp request"); + entry = cache->Add (destination); + entry->MarkWaitReply (packet); + SendArpRequest (cache, destination); + } + return false; +} + +void +ArpL3Protocol::SendArpRequest (Ptr cache, Ipv4Address to) +{ + NS_LOG_FUNCTION_NOARGS (); + ArpHeader arp; + NS_LOG_LOGIC ("ARP: sending request from node "<GetId ()<< + " || src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << cache->GetDevice ()->GetBroadcast () << + " / " << to); + arp.SetRequest (cache->GetDevice ()->GetAddress (), + cache->GetInterface ()->GetAddress (), + cache->GetDevice ()->GetBroadcast (), + to); + Ptr packet = Create (); + packet->AddHeader (arp); + cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER); +} + +void +ArpL3Protocol::SendArpReply (Ptr cache, Ipv4Address toIp, Address toMac) +{ + NS_LOG_FUNCTION_NOARGS (); + ArpHeader arp; + NS_LOG_LOGIC ("ARP: sending reply from node "<GetId ()<< + "|| src: " << cache->GetDevice ()->GetAddress () << + " / " << cache->GetInterface ()->GetAddress () << + " || dst: " << toMac << " / " << toIp); + arp.SetReply (cache->GetDevice ()->GetAddress (), + cache->GetInterface ()->GetAddress (), + toMac, toIp); + Ptr packet = Create (); + packet->AddHeader (arp); + cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER); +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/arp-l3-protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/arp-l3-protocol.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,86 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2006 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 ARP_L3_PROTOCOL_H +#define ARP_L3_PROTOCOL_H + +#include +#include "ns3/ipv4-address.h" +#include "ns3/address.h" +#include "ns3/ptr.h" +#include "ns3/traced-callback.h" + +#include "ipv4-interface.h" + +namespace ns3 { + +class ArpCache; +class NetDevice; +class Node; +class Packet; + +/** + * \brief An implementation of the ARP protocol + */ +class ArpL3Protocol : public Object +{ +public: + static TypeId GetTypeId (void); + static const uint16_t PROT_NUMBER; + + ArpL3Protocol (); + virtual ~ArpL3Protocol (); + + void SetNode (Ptr node); + + Ptr CreateCache (Ptr device, Ptr interface); + + /** + * \brief Recieve a packet + */ + void Receive(Ptr device, Ptr p, uint16_t protocol, const Address &from); + /** + * \brief Perform an ARP lookup + * \param p + * \param destination + * \param device + * \param cache + * \param hardwareDestination + * \return + */ + bool Lookup (Ptr p, Ipv4Address destination, + Ptr device, + Ptr cache, + Address *hardwareDestination); +protected: + virtual void DoDispose (void); +private: + typedef std::list > CacheList; + Ptr FindCache (Ptr device); + void SendArpRequest (Ptrcache, Ipv4Address to); + void SendArpReply (Ptr cache, Ipv4Address toIp, Address toMac); + CacheList m_cacheList; + Ptr m_node; + TracedCallback > m_dropTrace; +}; + +}//namespace ns3 + + +#endif /* ARP_L3_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/internet-stack.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/internet-stack.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,71 @@ +// -*- 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 "ipv4-l4-demux.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-impl.h" + +namespace ns3 { + +void +AddInternetStack (Ptr node) +{ + Ptr ipv4 = CreateObject (); + Ptr arp = CreateObject (); + ipv4->SetNode (node); + arp->SetNode (node); + + Ptr ipv4L4Demux = CreateObject (); + Ptr udp = CreateObject (); + Ptr tcp = CreateObject (); + + ipv4L4Demux->SetNode (node); + udp->SetNode (node); + tcp->SetNode (node); + + ipv4L4Demux->Insert (udp); + ipv4L4Demux->Insert (tcp); + + Ptr udpFactory = CreateObject (); + Ptr tcpFactory = CreateObject (); + Ptr ipv4Impl = CreateObject (); + + udpFactory->SetUdp (udp); + tcpFactory->SetTcp (tcp); + ipv4Impl->SetIpv4 (ipv4); + + node->AggregateObject (ipv4); + node->AggregateObject (arp); + node->AggregateObject (ipv4Impl); + node->AggregateObject (udpFactory); + node->AggregateObject (tcpFactory); + node->AggregateObject (ipv4L4Demux); +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/internet-stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/internet-stack.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,33 @@ +// -*- 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" + +namespace ns3 { + +class Node; + +void AddInternetStack (Ptr node); + +}//namespace ns3 + +#endif /* INTERNET_STACK_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-checksum.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-checksum.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,52 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,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 + * + * Author: Mathieu Lacage + */ +#include "ipv4-checksum.h" + +namespace ns3 { + +uint16_t +Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size) +{ + /* see RFC 1071 to understand this code. */ + uint32_t sum = checksum; + uint16_t *data = (uint16_t *) buffer; + for (uint16_t i = 0; i < (size/2); i++) { + sum += data[i]; + } + if ((size % 2) != 0) { + uint8_t tmpBuf[2]; + tmpBuf[0] = buffer[size-1]; + tmpBuf[1] = 0; + data = (uint16_t *)tmpBuf; + sum += *data; + } + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } + return sum; +} + +uint16_t +Ipv4ChecksumComplete (uint16_t checksum) +{ + return ~checksum; +} + +}; //namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-checksum.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-checksum.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,33 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,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 + * + * Author: Mathieu Lacage + */ +#ifndef IPV4_CHECKSUM_H +#define IPV4_CHECKSUM_H + +#include + +namespace ns3 { + +uint16_t Ipv4ChecksumCalculate (uint16_t checksum, uint8_t *buffer, uint16_t size); + +uint16_t Ipv4ChecksumComplete (uint16_t checksum); + +}; //namespace ns3 + +#endif /* IPV4_CHECKSUM_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-end-point-demux.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-end-point-demux.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,293 @@ +/* -*- 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-end-point-demux.h" +#include "ipv4-end-point.h" +#include "ns3/log.h" + +namespace ns3{ + +NS_LOG_COMPONENT_DEFINE ("Ipv4EndPointDemux"); + +Ipv4EndPointDemux::Ipv4EndPointDemux () + : m_ephemeral (49152) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +Ipv4EndPointDemux::~Ipv4EndPointDemux () +{ + NS_LOG_FUNCTION_NOARGS (); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + Ipv4EndPoint *endPoint = *i; + delete endPoint; + } + m_endPoints.clear (); +} + +bool +Ipv4EndPointDemux::LookupPortLocal (uint16_t port) +{ + NS_LOG_FUNCTION_NOARGS (); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + if ((*i)->GetLocalPort () == port) + { + return true; + } + } + return false; +} + +bool +Ipv4EndPointDemux::LookupLocal (Ipv4Address addr, uint16_t port) +{ + NS_LOG_FUNCTION_NOARGS (); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + if ((*i)->GetLocalPort () == port && + (*i)->GetLocalAddress () == addr) + { + return true; + } + } + return false; +} + +Ipv4EndPoint * +Ipv4EndPointDemux::Allocate (void) +{ + NS_LOG_FUNCTION_NOARGS (); + uint16_t port = AllocateEphemeralPort (); + if (port == 0) + { + NS_LOG_WARN ("Ephemeral port allocation failed."); + return 0; + } + Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port); + m_endPoints.push_back (endPoint); + NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); + return endPoint; +} + +Ipv4EndPoint * +Ipv4EndPointDemux::Allocate (Ipv4Address address) +{ + NS_LOG_FUNCTION (this << address); + uint16_t port = AllocateEphemeralPort (); + if (port == 0) + { + NS_LOG_WARN ("Ephemeral port allocation failed."); + return 0; + } + Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); + m_endPoints.push_back (endPoint); + NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); + return endPoint; +} + +Ipv4EndPoint * +Ipv4EndPointDemux::Allocate (uint16_t port) +{ + NS_LOG_FUNCTION (this << port); + + return Allocate (Ipv4Address::GetAny (), port); +} + +Ipv4EndPoint * +Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port) +{ + NS_LOG_FUNCTION (this << address << port); + if (LookupLocal (address, port)) + { + NS_LOG_WARN ("Duplicate address/port; failing."); + return 0; + } + Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port); + m_endPoints.push_back (endPoint); + NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); + return endPoint; +} + +Ipv4EndPoint * +Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort, + Ipv4Address peerAddress, uint16_t peerPort) +{ + NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + if ((*i)->GetLocalPort () == localPort && + (*i)->GetLocalAddress () == localAddress && + (*i)->GetPeerPort () == peerPort && + (*i)->GetPeerAddress () == peerAddress) + { + NS_LOG_WARN ("No way we can allocate this end-point."); + /* no way we can allocate this end-point. */ + return 0; + } + } + Ipv4EndPoint *endPoint = new Ipv4EndPoint (localAddress, localPort); + endPoint->SetPeer (peerAddress, peerPort); + m_endPoints.push_back (endPoint); + + NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints."); + + return endPoint; +} + +void +Ipv4EndPointDemux::DeAllocate (Ipv4EndPoint *endPoint) +{ + NS_LOG_FUNCTION_NOARGS (); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + if (*i == endPoint) + { + delete endPoint; + m_endPoints.erase (i); + break; + } + } +} + +/* + * If we have an exact match, we return it. + * Otherwise, if we find a generic match, we return it. + * Otherwise, we return 0. + */ +Ipv4EndPointDemux::EndPoints +Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, + Ipv4Address saddr, uint16_t sport, + Ptr incomingInterface) +{ + NS_LOG_FUNCTION_NOARGS (); + EndPoints retval1; // Matches exact on local port, wildcards on others + EndPoints retval2; // Matches exact on local port/adder, wildcards on others + EndPoints retval3; // Matches all but local address + EndPoints retval4; // Exact match on all 4 + + NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface); + NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr); + for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) + { + Ipv4EndPoint* endP = *i; + NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort () + << " daddr=" << endP->GetLocalAddress () + << " sport=" << endP->GetPeerPort () + << " saddr=" << endP->GetPeerAddress ()); + if (endP->GetLocalPort () != dport) + { + NS_LOG_LOGIC ("Skipping endpoint " << &endP + << " because endpoint dport " + << endP->GetLocalPort () + << " does not match packet dport " << dport); + continue; + } + bool isBroadcast = (daddr.IsBroadcast () || + daddr.IsSubnetDirectedBroadcast ( + incomingInterface->GetNetworkMask ())); + Ipv4Address incomingInterfaceAddr = incomingInterface->GetAddress (); + NS_LOG_DEBUG ("dest addr " << daddr << " broadcast? " << isBroadcast); + bool localAddressMatchesWildCard = + endP->GetLocalAddress() == Ipv4Address::GetAny(); + bool localAddressMatchesExact = endP->GetLocalAddress () == daddr; + + if (isBroadcast) + { + NS_LOG_DEBUG("Found bcast, localaddr " << endP->GetLocalAddress()); + } + + if (isBroadcast && (endP->GetLocalAddress() != Ipv4Address::GetAny())) + { + localAddressMatchesExact = (endP->GetLocalAddress () == + incomingInterfaceAddr); + } + // if no match here, keep looking + if (!(localAddressMatchesExact || localAddressMatchesWildCard)) + continue; + bool remotePeerMatchesExact = endP->GetPeerPort () == sport; + bool remotePeerMatchesWildCard = endP->GetPeerPort() == 0; + bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr; + bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == + Ipv4Address::GetAny(); + // If remote does not match either with exact or wildcard, + // skip this one + if (!(remotePeerMatchesExact || remotePeerMatchesWildCard)) + continue; + if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard)) + continue; + + // Now figure out which return list to add this one to + if (localAddressMatchesWildCard && + remotePeerMatchesWildCard && + remoteAddressMatchesWildCard) + { // Only local port matches exactly + retval1.push_back(endP); + } + if ((localAddressMatchesExact || (isBroadcast && localAddressMatchesWildCard))&& + remotePeerMatchesWildCard && + remoteAddressMatchesWildCard) + { // Only local port and local address matches exactly + retval2.push_back(endP); + } + if (localAddressMatchesWildCard && + remotePeerMatchesExact && + remoteAddressMatchesExact) + { // All but local address + retval3.push_back(endP); + } + if (localAddressMatchesExact && + remotePeerMatchesExact && + remoteAddressMatchesExact) + { // All 4 match + retval4.push_back(endP); + } + } + + // Here we find the most exact match + if (!retval4.empty()) return retval4; + if (!retval3.empty()) return retval3; + if (!retval2.empty()) return retval2; + return retval1; // might be empty if no matches +} + +uint16_t +Ipv4EndPointDemux::AllocateEphemeralPort (void) +{ + NS_LOG_FUNCTION_NOARGS (); + uint16_t port = m_ephemeral; + do + { + port++; + if (port == 65535) + { + port = 49152; + } + if (!LookupPortLocal (port)) + { + return port; + } + } while (port != m_ephemeral); + return 0; +} + +} //namespace ns3 + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-end-point-demux.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-end-point-demux.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,69 @@ +/* -*- 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_END_POINT_DEMUX_H +#define IPV4_END_POINT_DEMUX_H + +#include +#include +#include "ns3/ipv4-address.h" +#include "ipv4-interface.h" + +namespace ns3 { + +class Ipv4EndPoint; + +class Ipv4EndPointDemux { +public: + typedef std::list EndPoints; + typedef std::list::iterator EndPointsI; + + Ipv4EndPointDemux (); + ~Ipv4EndPointDemux (); + + bool LookupPortLocal (uint16_t port); + bool LookupLocal (Ipv4Address addr, uint16_t port); + EndPoints Lookup (Ipv4Address daddr, + uint16_t dport, + Ipv4Address saddr, + uint16_t sport, + Ptr incomingInterface); + + Ipv4EndPoint *Allocate (void); + Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address localAddress, + uint16_t localPort, + Ipv4Address peerAddress, + uint16_t peerPort); + + void DeAllocate (Ipv4EndPoint *endPoint); + + private: + uint16_t AllocateEphemeralPort (void); + + uint16_t m_ephemeral; + EndPoints m_endPoints; +}; + +} // namespace ns3 + +#endif /* IPV4_END_POINTS_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-end-point.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-end-point.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,97 @@ +/* -*- 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-end-point.h" +#include "ns3/packet.h" + +namespace ns3 { + +Ipv4EndPoint::Ipv4EndPoint (Ipv4Address address, uint16_t port) + : m_localAddr (address), + m_localPort (port), + m_peerAddr (Ipv4Address::GetAny ()), + m_peerPort (0) +{} +Ipv4EndPoint::~Ipv4EndPoint () +{ + if (!m_destroyCallback.IsNull ()) + { + m_destroyCallback (); + } +} + +Ipv4Address +Ipv4EndPoint::GetLocalAddress (void) +{ + return m_localAddr; +} + +void +Ipv4EndPoint::SetLocalAddress (Ipv4Address address) +{ + m_localAddr = address; +} + +uint16_t +Ipv4EndPoint::GetLocalPort (void) +{ + return m_localPort; +} +Ipv4Address +Ipv4EndPoint::GetPeerAddress (void) +{ + return m_peerAddr; +} +uint16_t +Ipv4EndPoint::GetPeerPort (void) +{ + return m_peerPort; +} +void +Ipv4EndPoint::SetPeer (Ipv4Address address, uint16_t port) +{ + m_peerAddr = address; + m_peerPort = port; +} + +void +Ipv4EndPoint::SetRxCallback (Callback, Ipv4Address, uint16_t> callback) +{ + m_rxCallback = callback; +} + +void +Ipv4EndPoint::SetDestroyCallback (Callback callback) +{ + m_destroyCallback = callback; +} + +void +Ipv4EndPoint::ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport) +{ + if (!m_rxCallback.IsNull ()) + { + m_rxCallback (p, saddr, sport); + } +} + + + +}; // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-end-point.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-end-point.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,63 @@ +/* -*- 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_END_POINT_H +#define IPV4_END_POINT_H + +#include +#include "ns3/ipv4-address.h" +#include "ns3/callback.h" + +namespace ns3 { + +class Header; +class Packet; + +class Ipv4EndPoint { +public: + Ipv4EndPoint (Ipv4Address address, uint16_t port); + ~Ipv4EndPoint (); + + Ipv4Address GetLocalAddress (void); + void SetLocalAddress (Ipv4Address address); + uint16_t GetLocalPort (void); + Ipv4Address GetPeerAddress (void); + uint16_t GetPeerPort (void); + + void SetPeer (Ipv4Address address, uint16_t port); + + void SetRxCallback (Callback, Ipv4Address, uint16_t> callback); + void SetDestroyCallback (Callback callback); + + void ForwardUp (Ptr p, Ipv4Address saddr, uint16_t sport); + +private: + Ipv4Address m_localAddr; + uint16_t m_localPort; + Ipv4Address m_peerAddr; + uint16_t m_peerPort; + Callback, Ipv4Address, uint16_t> m_rxCallback; + Callback m_destroyCallback; +}; + +}; // namespace ns3 + + +#endif /* IPV4_END_POINT_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-impl.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,273 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ +#include "ipv4-impl.h" +#include "ipv4-l3-protocol.h" +#include "ipv4-interface.h" +#include "ns3/assert.h" +#include "ns3/net-device.h" + +namespace ns3 { + +Ipv4Impl::Ipv4Impl () + : m_ipv4 (0) +{} +Ipv4Impl::~Ipv4Impl () +{ + NS_ASSERT (m_ipv4 == 0); +} +void +Ipv4Impl::SetIpv4 (Ptr ipv4) +{ + m_ipv4 = ipv4; +} +void +Ipv4Impl::DoDispose (void) +{ + m_ipv4 = 0; +} + +void +Ipv4Impl::AddRoutingProtocol (Ptr routingProtocol, + int16_t priority) +{ + m_ipv4->AddRoutingProtocol (routingProtocol, priority); +} + +void +Ipv4Impl::AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) +{ + m_ipv4->AddHostRouteTo (dest, nextHop, interface); +} +void +Ipv4Impl::AddHostRouteTo (Ipv4Address dest, + uint32_t interface) +{ + m_ipv4->AddHostRouteTo (dest, interface); +} +void +Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) +{ + m_ipv4->AddNetworkRouteTo (network, networkMask, nextHop, interface); +} +void +Ipv4Impl::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) +{ + m_ipv4->AddNetworkRouteTo (network, networkMask, interface); +} +void +Ipv4Impl::SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface) +{ + m_ipv4->SetDefaultRoute (nextHop, interface); +} +uint32_t +Ipv4Impl::GetNRoutes (void) +{ + return m_ipv4->GetNRoutes (); +} +Ipv4Route +Ipv4Impl::GetRoute (uint32_t i) +{ + return *m_ipv4->GetRoute (i); +} +void +Ipv4Impl::RemoveRoute (uint32_t i) +{ + return m_ipv4->RemoveRoute (i); +} + +void +Ipv4Impl::AddMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces) +{ + m_ipv4->AddMulticastRoute (origin, group, inputInterface, outputInterfaces); +} + +void +Ipv4Impl::SetDefaultMulticastRoute (uint32_t outputInterface) +{ + m_ipv4->SetDefaultMulticastRoute (outputInterface); +} + +uint32_t +Ipv4Impl::GetNMulticastRoutes (void) const +{ + return m_ipv4->GetNMulticastRoutes (); +} + +Ipv4MulticastRoute +Ipv4Impl::GetMulticastRoute (uint32_t i) const +{ + return *m_ipv4->GetMulticastRoute (i); +} + +void +Ipv4Impl::RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface) +{ + m_ipv4->RemoveMulticastRoute (origin, group, inputInterface); +} + +void +Ipv4Impl::RemoveMulticastRoute (uint32_t i) +{ + return m_ipv4->RemoveMulticastRoute (i); +} + +uint32_t +Ipv4Impl::AddInterface (Ptr device) +{ + return m_ipv4->AddInterface (device); +} + +uint32_t +Ipv4Impl::GetNInterfaces (void) +{ + return m_ipv4->GetNInterfaces (); +} + +uint32_t +Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr) const +{ + return m_ipv4->FindInterfaceForAddr (addr); +} + +uint32_t +Ipv4Impl::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const +{ + return m_ipv4->FindInterfaceForAddr (addr, mask); +} + +int32_t +Ipv4Impl::FindInterfaceForDevice (Ptr device) const +{ + return m_ipv4->FindInterfaceIndexForDevice (device); +} + +Ptr +Ipv4Impl::GetNetDevice (uint32_t i) +{ + return m_ipv4->GetInterface (i)-> GetDevice (); +} + +void +Ipv4Impl::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) +{ + m_ipv4->JoinMulticastGroup(origin, group); +} + +void +Ipv4Impl::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) +{ + m_ipv4->LeaveMulticastGroup(origin, group); +} + +void +Ipv4Impl::SetAddress (uint32_t i, Ipv4Address address) +{ + m_ipv4->SetAddress (i, address); +} +void +Ipv4Impl::SetNetworkMask (uint32_t i, Ipv4Mask mask) +{ + m_ipv4->SetNetworkMask (i, mask); +} +Ipv4Mask +Ipv4Impl::GetNetworkMask (uint32_t i) const +{ + return m_ipv4->GetNetworkMask (i); +} + +Ipv4Address +Ipv4Impl::GetAddress (uint32_t i) const +{ + return m_ipv4->GetAddress (i); +} + +void +Ipv4Impl::SetMetric (uint32_t i, uint16_t metric) +{ + m_ipv4->SetMetric (i, metric); +} + +uint16_t +Ipv4Impl::GetMetric (uint32_t i) const +{ + return m_ipv4->GetMetric (i); +} + +bool +Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const +{ + return m_ipv4->GetIfIndexForDestination (dest, ifIndex); +} + +Ipv4Address +Ipv4Impl::GetSourceAddress (Ipv4Address destination) const +{ + uint32_t ifIndex = 0xffffffff; + + bool result = m_ipv4->GetIfIndexForDestination (destination, ifIndex); + + if (result) + { + return m_ipv4->GetAddress (ifIndex); + } + else + { +// +// If we can't find any address, just leave it 0.0.0.0 +// + return Ipv4Address::GetAny (); + } +} + +uint16_t +Ipv4Impl::GetMtu (uint32_t i) const +{ + return m_ipv4->GetMtu (i); +} +bool +Ipv4Impl::IsUp (uint32_t i) const +{ + return m_ipv4->IsUp (i); +} +void +Ipv4Impl::SetUp (uint32_t i) +{ + m_ipv4->SetUp (i); +} +void +Ipv4Impl::SetDown (uint32_t i) +{ + m_ipv4->SetDown (i); +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-impl.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,112 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ +#ifndef IPV4_IMPL_H +#define IPV4_IMPL_H + +#include "ns3/ipv4.h" +#include "ns3/ptr.h" + +namespace ns3 { + +class Ipv4L3Protocol; + +class Ipv4Impl : public Ipv4 +{ +public: + Ipv4Impl (); + + virtual ~Ipv4Impl (); + + void SetIpv4 (Ptr ipv4); + + virtual void AddRoutingProtocol (Ptr routingProtocol, + int16_t priority); + + virtual void AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface); + virtual void AddHostRouteTo (Ipv4Address dest, + uint32_t interface); + virtual void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface); + virtual void AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface); + virtual void SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface); + virtual uint32_t GetNRoutes (void); + virtual Ipv4Route GetRoute (uint32_t i); + virtual void RemoveRoute (uint32_t i); + + + virtual void AddMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface, + std::vector outputInterfaces); + + virtual void SetDefaultMulticastRoute (uint32_t outputInterface); + + virtual uint32_t GetNMulticastRoutes (void) const; + virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const; + + virtual void RemoveMulticastRoute (Ipv4Address origin, + Ipv4Address group, + uint32_t inputInterface); + virtual void RemoveMulticastRoute (uint32_t i); + + virtual uint32_t AddInterface (Ptr device); + virtual uint32_t GetNInterfaces (void); + + virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const; + virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, + Ipv4Mask mask) const; + + virtual int32_t FindInterfaceForDevice (Ptr device) const; + + virtual Ptr GetNetDevice(uint32_t i); + + virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); + virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + + virtual void SetAddress (uint32_t i, Ipv4Address address); + virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask); + virtual Ipv4Mask GetNetworkMask (uint32_t t) const; + virtual Ipv4Address GetAddress (uint32_t i) const; + virtual void SetMetric (uint32_t i, uint16_t metric); + virtual uint16_t GetMetric (uint32_t i) const; + virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const; + virtual bool GetIfIndexForDestination (Ipv4Address dest, + uint32_t &ifIndex) const; + + virtual uint16_t GetMtu (uint32_t i) const; + virtual bool IsUp (uint32_t i) const; + virtual void SetUp (uint32_t i); + virtual void SetDown (uint32_t i); +protected: + virtual void DoDispose (void); +private: + Ptr m_ipv4; +}; + +} // namespace ns3 + +#endif /* IPV4_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-interface.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-interface.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,174 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,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 + * + * Author: Mathieu Lacage + */ + +#include "ipv4-interface.h" +#include "ns3/ipv4-address.h" +#include "ns3/net-device.h" +#include "ns3/log.h" +#include "ns3/packet.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4Interface"); + +namespace ns3 { + +TypeId +Ipv4Interface::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4Interface") + .SetParent () + ; + 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. + */ +Ipv4Interface::Ipv4Interface () + : m_ifup(false), + m_metric(1) +{ + NS_LOG_FUNCTION (this); +} + +Ipv4Interface::~Ipv4Interface () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +Ipv4Interface::DoDispose (void) +{ + NS_LOG_FUNCTION_NOARGS (); + Object::DoDispose (); +} + +void +Ipv4Interface::SetAddress (Ipv4Address a) +{ + NS_LOG_FUNCTION (this << a); + m_address = a; +} + +void +Ipv4Interface::SetNetworkMask (Ipv4Mask mask) +{ + NS_LOG_FUNCTION (this << mask); + m_netmask = mask; +} + +Ipv4Address +Ipv4Interface::GetBroadcast (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + uint32_t mask = m_netmask.Get (); + uint32_t address = m_address.Get (); + Ipv4Address broadcast = Ipv4Address (address | (~mask)); + return broadcast; +} + +Ipv4Mask +Ipv4Interface::GetNetworkMask (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_netmask; +} + +void +Ipv4Interface::SetMetric (uint16_t metric) +{ + NS_LOG_FUNCTION (metric); + m_metric = metric; +} + +uint16_t +Ipv4Interface::GetMetric (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_metric; +} + +Ipv4Address +Ipv4Interface::GetAddress (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_address; +} + +uint16_t +Ipv4Interface::GetMtu (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + if (GetDevice () == 0) + { + uint32_t mtu = (1<<16) - 1; + return mtu; + } + return GetDevice ()->GetMtu (); +} + +/** + * These are IP interface states and may be distinct from + * NetDevice states, such as found in real implementations + * (where the device may be down but IP interface state is still up). + */ +bool +Ipv4Interface::IsUp (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_ifup; +} + +bool +Ipv4Interface::IsDown (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return !m_ifup; +} + +void +Ipv4Interface::SetUp (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_ifup = true; +} + +void +Ipv4Interface::SetDown (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_ifup = false; +} + +// public wrapper on private virtual function +void +Ipv4Interface::Send(Ptr p, Ipv4Address dest) +{ + NS_LOG_FUNCTION_NOARGS (); + if (IsUp()) { + NS_LOG_LOGIC ("SendTo"); + SendTo(p, dest); + } +} + +}; // namespace ns3 + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-interface.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,156 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,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 , + * Tom Henderson + */ +#ifndef IPV4_INTERFACE_H +#define IPV4_INTERFACE_H + +#include +#include "ns3/ipv4-address.h" +#include "ns3/ptr.h" +#include "ns3/object.h" + +namespace ns3 { + +class NetDevice; +class Packet; + +/** + * \brief The IPv4 representation of a network interface + * + * This class roughly corresponds to the struct in_device + * 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 + */ +class Ipv4Interface : public Object +{ +public: + static TypeId GetTypeId (void); + + Ipv4Interface (); + virtual ~Ipv4Interface(); + + /** + * \returns the underlying NetDevice. This method can return + * zero if this interface has no associated NetDevice. + */ + virtual Ptr GetDevice (void) const = 0; + + /** + * \param a set the ipv4 address of this interface. + */ + void SetAddress (Ipv4Address a); + /** + * \param mask set the ipv4 netmask of this interface. + */ + void SetNetworkMask (Ipv4Mask mask); + + /** + * \returns the broadcast ipv4 address associated to this interface + */ + Ipv4Address GetBroadcast (void) const; + /** + * \returns the ipv4 netmask of this interface + */ + Ipv4Mask GetNetworkMask (void) const; + /** + * \param metric configured routing metric (cost) of this interface + */ + void SetMetric (uint16_t metric); + /** + * \returns configured routing metric (cost) of this interface + */ + uint16_t GetMetric (void) const; + /** + * \returns the ipv4 address of this interface + */ + Ipv4Address GetAddress (void) const; + + /** + * 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. + */ + uint16_t GetMtu (void) const; + + /** + * These are IP interface states and may be distinct from + * NetDevice states, such as found in real implementations + * (where the device may be down but IP interface state is still up). + */ + /** + * \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 + */ + void SetDown (void); + + /** + * \param p packet to send + * \param dest next hop address of packet. + * + * This method will eventually call the private + * SendTo method which must be implemented by subclasses. + */ + void Send(Ptr p, Ipv4Address dest); + +protected: + virtual void DoDispose (void); +private: + virtual void SendTo (Ptr p, Ipv4Address dest) = 0; + bool m_ifup; + Ipv4Address m_address; + Ipv4Mask m_netmask; + uint16_t m_metric; +}; + +}; // namespace ns3 + +#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l3-protocol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l3-protocol.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,906 @@ +// -*- 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/packet.h" +#include "ns3/log.h" +#include "ns3/callback.h" +#include "ns3/ipv4-address.h" +#include "ns3/ipv4-route.h" +#include "ns3/node.h" +#include "ns3/socket.h" +#include "ns3/net-device.h" +#include "ns3/uinteger.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/object-vector.h" +#include "ns3/ipv4-header.h" +#include "ns3/boolean.h" +#include "arp-l3-protocol.h" + +#include "ipv4-l3-protocol.h" +#include "ipv4-l4-protocol.h" +#include "ipv4-interface.h" +#include "ipv4-loopback-interface.h" +#include "arp-ipv4-interface.h" +#include "ipv4-l4-demux.h" + +NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol"); + +namespace ns3 { + +const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800; + +NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol); + +TypeId +Ipv4L3Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4L3Protocol") + .SetParent () + .AddConstructor () + .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.", + UintegerValue (64), + MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl), + MakeUintegerChecker ()) + .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets" + " and verify the checksum of incoming packets.", + BooleanValue (false), + MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum), + MakeBooleanChecker ()) + .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace)) + .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace)) + .AddTraceSource ("Drop", "Drop ipv4 packet", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace)) + .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.", + ObjectVectorValue (), + MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), + MakeObjectVectorChecker ()) + ; + return tid; +} + +Ipv4L3Protocol::Ipv4L3Protocol() + : m_nInterfaces (0), + m_identification (0) +{ + NS_LOG_FUNCTION_NOARGS (); + m_staticRouting = CreateObject (); + AddRoutingProtocol (m_staticRouting, 0); +} + +Ipv4L3Protocol::~Ipv4L3Protocol () +{ + NS_LOG_FUNCTION (this); +} + +void +Ipv4L3Protocol::SetNode (Ptr node) +{ + m_node = node; + SetupLoopback (); +} + +void +Ipv4L3Protocol::DoDispose (void) +{ + NS_LOG_FUNCTION (this); + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i) + { + Ptr interface = *i; + interface->Dispose (); + } + m_interfaces.clear (); + m_node = 0; + m_staticRouting->Dispose (); + m_staticRouting = 0; + Object::DoDispose (); +} + +void +Ipv4L3Protocol::SetupLoopback (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + Ptr interface = CreateObject (); + interface->SetNode (m_node); + interface->SetAddress (Ipv4Address::GetLoopback ()); + interface->SetNetworkMask (Ipv4Mask::GetLoopback ()); + uint32_t index = AddIpv4Interface (interface); + AddHostRouteTo (Ipv4Address::GetLoopback (), index); + interface->SetUp (); +} + +void +Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl) +{ + NS_LOG_FUNCTION_NOARGS (); + m_defaultTtl = ttl; +} + + +void +Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, + Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION (this << dest << nextHop << interface); + m_staticRouting->AddHostRouteTo (dest, nextHop, interface); +} + +void +Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, + uint32_t interface) +{ + NS_LOG_FUNCTION (this << dest << interface); + m_staticRouting->AddHostRouteTo (dest, interface); +} + +void +Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface); + m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface); +} + +void +Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, + Ipv4Mask networkMask, + uint32_t interface) +{ + NS_LOG_FUNCTION (this << network << networkMask << interface); + m_staticRouting->AddNetworkRouteTo (network, networkMask, interface); +} + +void +Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, + uint32_t interface) +{ + NS_LOG_FUNCTION (this << nextHop << interface); + m_staticRouting->SetDefaultRoute (nextHop, interface); +} + +void +Ipv4L3Protocol::Lookup ( + Ipv4Header const &ipHeader, + Ptr packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) +{ + NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply); + + Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply); +} + +void +Ipv4L3Protocol::Lookup ( + uint32_t ifIndex, + Ipv4Header const &ipHeader, + Ptr packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply) +{ + NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply); + + for (Ipv4RoutingProtocolList::const_iterator rprotoIter = + m_routingProtocols.begin (); + rprotoIter != m_routingProtocols.end (); + rprotoIter++) + { + NS_LOG_LOGIC ("Requesting route"); + if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, + routeReply)) + return; + } + + if (ipHeader.GetDestination ().IsMulticast () && + ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY) + { + NS_LOG_LOGIC ("Multicast destination with local source"); +// +// We have a multicast packet originating from the current node and were not +// able to send it using the usual RequestRoute process. Since the usual +// process includes trying to use a default multicast route, this means that +// there was no specific route out of the node found, and there was no default +// multicast route set. +// +// The fallback position is to look for a default unicast route and use that +// to get the packet off the node if we have one. +// + Ipv4Route *route = m_staticRouting->GetDefaultRoute (); + + if (route) + { + NS_LOG_LOGIC ("Local source. Using unicast default route for " + "multicast packet"); + + routeReply (true, *route, packet, ipHeader); + return; + } + } +// +// No route found +// + routeReply (false, Ipv4Route (), packet, ipHeader); +} + +void +Ipv4L3Protocol::AddRoutingProtocol (Ptr routingProtocol, + int 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); +} + +uint32_t +Ipv4L3Protocol::AddInterface (Ptr device) +{ + NS_LOG_FUNCTION (this << &device); + + Ptr node = GetObject (); + node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), + Ipv4L3Protocol::PROT_NUMBER, device); + node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject ())), + ArpL3Protocol::PROT_NUMBER, device); + + Ptr interface = CreateObject (); + interface->SetNode (m_node); + interface->SetDevice (device); + return AddIpv4Interface (interface); +} + +uint32_t +Ipv4L3Protocol::AddIpv4Interface (Ptrinterface) +{ + NS_LOG_FUNCTION (this << interface); + uint32_t index = m_nInterfaces; + m_interfaces.push_back (interface); + m_nInterfaces++; + return index; +} + +Ptr +Ipv4L3Protocol::GetInterface (uint32_t index) const +{ + NS_LOG_FUNCTION (this << index); + uint32_t tmp = 0; + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++) + { + if (index == tmp) + { + return *i; + } + tmp++; + } + return 0; +} + +uint32_t +Ipv4L3Protocol::GetNInterfaces (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_nInterfaces; +} + +uint32_t +Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const +{ + NS_LOG_FUNCTION (this << addr); + + uint32_t ifIndex = 0; + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++, ifIndex++) + { + if ((*i)->GetAddress () == addr) + { + return ifIndex; + } + } + + 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 ifIndex = 0; + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++, ifIndex++) + { + if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask)) + { + return ifIndex; + } + } + + NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): " + "Interface not found for masked IP address"); + return 0; +} + +int32_t +Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr device) const +{ + NS_LOG_FUNCTION (this << device); + + uint32_t ifIndex = 0; + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++, ifIndex++) + { + if ((*i)->GetDevice () == device) + { + return ifIndex; + } + } + + 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 packet, uint16_t protocol, const Address &from) +{ + NS_LOG_FUNCTION (this << &device << packet << protocol << from); + + NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ()); + + uint32_t index = 0; + Ptr ipv4Interface; + for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); + i != m_interfaces.end (); + i++) + { + ipv4Interface = *i; + if (ipv4Interface->GetDevice () == device) + { + m_rxTrace (packet, index); + break; + } + index++; + } + Ipv4Header ipHeader; + if (m_calcChecksum) + { + ipHeader.EnableChecksum (); + } + packet->RemoveHeader (ipHeader); + + if (!ipHeader.IsChecksumOk ()) + { + m_dropTrace (packet); + return; + } + + if (Forwarding (index, packet, ipHeader, device)) + { + return; + } + + ForwardUp (packet, ipHeader, ipv4Interface); +} + + +void +Ipv4L3Protocol::Send (Ptr packet, + Ipv4Address source, + Ipv4Address destination, + uint8_t protocol) +{ + NS_LOG_FUNCTION (this << packet << source << destination << protocol); + + Ipv4Header ipHeader; + + if (m_calcChecksum) + { + ipHeader.EnableChecksum (); + } + + ipHeader.SetSource (source); + ipHeader.SetDestination (destination); + ipHeader.SetProtocol (protocol); + ipHeader.SetPayloadSize (packet->GetSize ()); + ipHeader.SetTtl (m_defaultTtl); + ipHeader.SetMayFragment (); + ipHeader.SetIdentification (m_identification); + + m_identification ++; + + // 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; + bool found = packet->FindFirstMatchingTag (tag); + + if (destination.IsBroadcast ()) + { + ipHeader.SetTtl (1); + } + else if (found) + { + ipHeader.SetTtl (tag.GetTtl ()); + // XXX remove tag here? + } + else + { + uint32_t ifaceIndex = 0; + for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); + ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) + { + Ptr outInterface = *ifaceIter; + if (destination.IsSubnetDirectedBroadcast ( + outInterface->GetNetworkMask ())) + { + ipHeader.SetTtl (1); + } + } + } + if (destination.IsBroadcast ()) + { + uint32_t ifaceIndex = 0; + for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin (); + ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++) + { + Ptr outInterface = *ifaceIter; + Ptr packetCopy = packet->Copy (); + + NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ()); + packetCopy->AddHeader (ipHeader); + m_txTrace (packetCopy, ifaceIndex); + outInterface->Send (packetCopy, destination); + } + } + 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)); + } +} + +void +Ipv4L3Protocol::SendRealOut (bool found, + Ipv4Route const &route, + Ptr packet, + Ipv4Header const &ipHeader) +{ + NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader); + + packet->AddHeader (ipHeader); + if (!found) + { + NS_LOG_WARN ("No route to host. Drop."); + m_dropTrace (packet); + return; + } + + NS_LOG_LOGIC ("Send via interface " << route.GetInterface ()); + + Ptr outInterface = GetInterface (route.GetInterface ()); + NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ()); + m_txTrace (packet, route.GetInterface ()); + if (route.IsGateway ()) + { + NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ()); + outInterface->Send (packet, route.GetGateway ()); + } + else + { + NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ()); + outInterface->Send (packet, ipHeader.GetDestination ()); + } +} + +bool +Ipv4L3Protocol::Forwarding ( + uint32_t ifIndex, + Ptr packet, + Ipv4Header &ipHeader, + Ptr device) +{ + NS_LOG_FUNCTION (ifIndex << 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++) + { + if ((*i)->GetAddress ().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) + { + if (ipHeader.GetDestination ().IsEqual (interface->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 (ipHeader.GetTtl () == 1) + { + // Should send ttl expired here + // XXX + NS_LOG_LOGIC ("Not for me (TTL expired). Drop"); + m_dropTrace (packet); + return true; + } + ipHeader.SetTtl (ipHeader.GetTtl () - 1); + +// +// 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)."); + Lookup (ifIndex, ipHeader, packet->Copy (), + MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); + return false; + } + } + NS_LOG_LOGIC ("Not for me, forwarding."); + Lookup (ifIndex, ipHeader, packet, + MakeCallback (&Ipv4L3Protocol::SendRealOut, this)); + + return true; +} + +void +Ipv4L3Protocol::ForwardUp (Ptr p, Ipv4Header const&ip, + Ptr incomingInterface) +{ + NS_LOG_FUNCTION (this << p << &ip); + + Ptr demux = m_node->GetObject (); + Ptr protocol = demux->GetProtocol (ip.GetProtocol ()); + protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface); +} + +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; + } + } +} + +void +Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address) +{ + NS_LOG_FUNCTION (this << i << address); + Ptr interface = GetInterface (i); + interface->SetAddress (address); +} + +void +Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask) +{ + NS_LOG_FUNCTION (this << i << mask); + Ptr interface = GetInterface (i); + interface->SetNetworkMask (mask); +} + +Ipv4Mask +Ipv4L3Protocol::GetNetworkMask (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->GetNetworkMask (); +} + +Ipv4Address +Ipv4L3Protocol::GetAddress (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->GetAddress (); +} + +void +Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric) +{ + NS_LOG_FUNCTION (i << metric); + Ptr interface = GetInterface (i); + interface->SetMetric (metric); +} + +uint16_t +Ipv4L3Protocol::GetMetric (uint32_t i) const +{ + NS_LOG_FUNCTION (i); + Ptr interface = GetInterface (i); + return interface->GetMetric (); +} + +bool +Ipv4L3Protocol::GetIfIndexForDestination ( + Ipv4Address destination, uint32_t& ifIndex) const +{ + NS_LOG_FUNCTION (this << destination << &ifIndex); +// +// 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 ifIndexTmp; + + if ((*i).second->RequestIfIndex (destination, ifIndexTmp)) + { + NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp); + ifIndex = ifIndexTmp; + 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."); + ifIndex = 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::GetIfIndexForDestination (): " + "Unable to determine outbound interface. No default route set"); + return false; + } + + ifIndex = route->GetInterface (); + + NS_LOG_LOGIC ("Default route specifies interface " << ifIndex); + return true; +} + +uint16_t +Ipv4L3Protocol::GetMtu (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->GetMtu (); +} + +bool +Ipv4L3Protocol::IsUp (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->IsUp (); +} + +void +Ipv4L3Protocol::SetUp (uint32_t i) +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + interface->SetUp (); + + // If interface address and network mask have been set, add a route + // to the network of the interface (like e.g. ifconfig does on a + // Linux box) + if ((interface->GetAddress ()) != (Ipv4Address ()) + && (interface->GetNetworkMask ()) != (Ipv4Mask ())) + { + AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()), + interface->GetNetworkMask (), i); + } +} + +void +Ipv4L3Protocol::SetDown (uint32_t ifaceIndex) +{ + NS_LOG_FUNCTION (this << ifaceIndex); + Ptr interface = GetInterface (ifaceIndex); + interface->SetDown (); + + // Remove all routes that are going through this interface + bool modified = true; + while (modified) + { + modified = false; + for (uint32_t i = 0; i < GetNRoutes (); i++) + { + Ipv4Route *route = GetRoute (i); + if (route->GetInterface () == ifaceIndex) + { + RemoveRoute (i); + modified = true; + break; + } + } + } +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l3-protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l3-protocol.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,209 @@ +// -*- 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 IPV4_L3_PROTOCOL_H +#define IPV4_L3_PROTOCOL_H + +#include +#include +#include "ns3/ipv4-address.h" +#include "ns3/ptr.h" +#include "ns3/ipv4.h" +#include "ns3/traced-callback.h" +#include "ns3/ipv4-header.h" +#include "ipv4-static-routing.h" + +namespace ns3 { + +class Packet; +class NetDevice; +class Ipv4Interface; +class Ipv4Address; +class Ipv4Header; +class Ipv4Route; +class Node; + + +/** + * \brief Implement the Ipv4 layer. + */ +class Ipv4L3Protocol : public Object +{ +public: + static TypeId GetTypeId (void); + static const uint16_t PROT_NUMBER; + + Ipv4L3Protocol(); + virtual ~Ipv4L3Protocol (); + + void SetNode (Ptr node); + + /** + * \param ttl default ttl to use + * + * When we need to send an ipv4 packet, we use this default + * ttl value. + */ + 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 + * packet is coming to: + * - implement a per-NetDevice ARP cache + * - send back arp replies on the right device + */ + void Receive( Ptr device, Ptr p, uint16_t protocol, const Address &from); + + /** + * \param packet packet to send + * \param source source address of packet + * \param destination address of packet + * \param protocol number of packet + * + * 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); + + 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 FindInterfaceIndexForDevice (Ptr device) const; + + void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group); + void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group); + + void SetAddress (uint32_t i, Ipv4Address address); + void SetNetworkMask (uint32_t i, Ipv4Mask mask); + Ipv4Mask GetNetworkMask (uint32_t t) const; + Ipv4Address GetAddress (uint32_t i) const; + void SetMetric (uint32_t i, uint16_t metric); + uint16_t GetMetric (uint32_t i) const; + bool GetIfIndexForDestination (Ipv4Address destination, + uint32_t& ifIndex) const; + uint16_t GetMtu (uint32_t i) const; + bool IsUp (uint32_t i) const; + void SetUp (uint32_t i); + void SetDown (uint32_t i); + + void AddRoutingProtocol (Ptr routingProtocol, + int priority); + +protected: + + virtual void DoDispose (void); + +private: + void Lookup (uint32_t ifIndex, + Ipv4Header const &ipHeader, + Ptr packet, + Ipv4RoutingProtocol::RouteReplyCallback routeReply); + + void SendRealOut (bool found, + Ipv4Route const &route, + Ptr packet, + Ipv4Header const &ipHeader); + bool Forwarding (uint32_t ifIndex, + Ptr packet, + Ipv4Header &ipHeader, + Ptr device); + void ForwardUp (Ptr p, Ipv4Header const&ip, Ptr incomingInterface); + uint32_t AddIpv4Interface (Ptr interface); + void SetupLoopback (void); + + typedef std::list > Ipv4InterfaceList; + typedef std::list > + Ipv4MulticastGroupList; + typedef std::list< std::pair< int, Ptr > > Ipv4RoutingProtocolList; + + Ipv4InterfaceList m_interfaces; + uint32_t m_nInterfaces; + uint8_t m_defaultTtl; + bool m_calcChecksum; + uint16_t m_identification; + Ptr m_node; + TracedCallback, uint32_t> m_txTrace; + TracedCallback, uint32_t> m_rxTrace; + TracedCallback > m_dropTrace; + + Ipv4RoutingProtocolList m_routingProtocols; + + Ptr m_staticRouting; + Ipv4MulticastGroupList m_multicastGroups; +}; + +} // Namespace ns3 + +#endif /* IPV4_L3_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l4-demux.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l4-demux.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,97 @@ +// -*- 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 +// + +// Define the layer 4 demultiplexer object for ns3. +// George F. Riley, Georgia Tech, Fall 2006 + +#include +#include "ns3/node.h" +#include "ns3/object-vector.h" +#include "ipv4-l4-demux.h" +#include "ipv4-l4-protocol.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Demux); + +TypeId +Ipv4L4Demux::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4L4Demux") + .SetParent () + .AddAttribute ("Protocols", "The set of protocols registered with this demux.", + ObjectVectorValue (), + MakeObjectVectorAccessor (&Ipv4L4Demux::m_protocols), + MakeObjectVectorChecker ()) + ; + return tid; +} + +Ipv4L4Demux::Ipv4L4Demux () +{} + +Ipv4L4Demux::~Ipv4L4Demux() +{} + +void +Ipv4L4Demux::SetNode (Ptr node) +{ + m_node = node; +} + +void +Ipv4L4Demux::DoDispose (void) +{ + for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) + { + (*i)->Dispose (); + *i = 0; + } + m_protocols.clear (); + m_node = 0; + Object::DoDispose (); +} + +void +Ipv4L4Demux::Insert(Ptr protocol) +{ + m_protocols.push_back (protocol); +} +Ptr +Ipv4L4Demux::GetProtocol(int protocolNumber) +{ + for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i) + { + if ((*i)->GetProtocolNumber () == protocolNumber) + { + return *i; + } + } + return 0; +} +void +Ipv4L4Demux::Remove (Ptr protocol) +{ + m_protocols.remove (protocol); +} + + + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l4-demux.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l4-demux.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,85 @@ +// -*- 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 +// + +// Define the layer 4 demultiplexer object for ns3. +// George F. Riley, Georgia Tech, Fall 2006 + +#ifndef IPV4_L4_DEMUX_H +#define IPV4_L4_DEMUX_H + +#include +#include "ns3/object.h" +#include "ns3/ptr.h" + +namespace ns3 { + +class Ipv4L4Protocol; +class Node; + +/** + * \brief L4 Ipv4 Demux + */ +class Ipv4L4Demux : public Object +{ +public: + static TypeId GetTypeId (void); + Ipv4L4Demux (); + virtual ~Ipv4L4Demux(); + + void SetNode (Ptr node); + + /** + * \param protocol a template for the protocol to add to this L4 Demux. + * \returns the L4Protocol effectively added. + * + * Invoke Copy on the input template to get a copy of the input + * protocol which can be used on the Node on which this L4 Demux + * is running. The new L4Protocol is registered internally as + * a working L4 Protocol and returned from this method. + * The caller does not get ownership of the returned pointer. + */ + void Insert(Ptr protocol); + /** + * \param protocolNumber number of protocol to lookup + * in this L4 Demux + * \returns a matching L4 Protocol + * + * This method is typically called by lower layers + * to forward packets up the stack to the right protocol. + * It is also called from NodeImpl::GetUdp for example. + */ + Ptr GetProtocol(int protocolNumber); + /** + * \param protocol protocol to remove from this demux. + * + * The input value to this method should be the value + * returned from the Ipv4L4Protocol::Insert method. + */ + void Remove (Ptr protocol); +protected: + virtual void DoDispose (void); +private: + typedef std::list > L4List_t; + L4List_t m_protocols; + Ptr m_node; +}; + +} //namespace ns3 +#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l4-protocol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l4-protocol.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,51 @@ +// -*- 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 +// + +// NS3 - Layer 4 Protocol base class +// George F. Riley, Georgia Tech, Spring 2007 + +#include "ipv4-l4-protocol.h" +#include "ns3/uinteger.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol); + +TypeId +Ipv4L4Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::Ipv4L4Protocol") + .SetParent () + .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber), + MakeUintegerChecker ()) + .AddAttribute ("Version", "The version of the protocol.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv4L4Protocol::GetVersion), + MakeUintegerChecker ()) + ; + return tid; +} + +Ipv4L4Protocol::~Ipv4L4Protocol () +{} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-l4-protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-l4-protocol.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,74 @@ +// -*- 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 +// + +// NS3 - Layer 4 Protocol base class +// George F. Riley, Georgia Tech, Spring 2007 + +#ifndef IPV4_L4_PROTOCOL_H +#define IPV4_L4_PROTOCOL_H + +#include "ns3/object.h" +#include "ipv4-interface.h" + +namespace ns3 { + +class Packet; +class Ipv4Address; + +/** + * \brief L4 Protocol base class + * + * If you want to implement a new L4 protocol, all you have to do is + * implement a subclass of this base class and add it to an L4Demux. + */ +class Ipv4L4Protocol : public Object +{ +public: + static TypeId GetTypeId (void); + + virtual ~Ipv4L4Protocol (); + + /** + * \returns the protocol number of this protocol. + */ + virtual int GetProtocolNumber (void) const = 0; + /** + * \returns the version number of this protocol. + */ + virtual int GetVersion (void) const = 0; + + /** + * \param p packet to forward up + * \param source source address of packet received + * \param destination address of packet received + * \param incomingInterface the Ipv4Interface on which the packet arrived + * + * Called from lower-level layers to send the packet up + * in the stack. + */ + virtual void Receive(Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface) = 0; +}; + +} // Namespace ns3 + +#endif diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-loopback-interface.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-loopback-interface.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,79 @@ +/* -*- 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")); +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-loopback-interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-loopback-interface.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,53 @@ +/* -*- 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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-static-routing.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-static-routing.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,654 @@ +// -*- 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::IF_INDEX_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 ifIndex) +{ + 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 ifIndex is a wildcard). +// + if (origin == route->GetOrigin () && group == route->GetGroup ()) + { + if (ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY || + ifIndex == 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 (ifIndex != Ipv4RoutingProtocol::IF_INDEX_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 ifIndex, + Ipv4Header const &ipHeader, + Ptr packet, + RouteReplyCallback routeReply) +{ + NS_LOG_FUNCTION (this << ifIndex << &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 (), ifIndex); + + 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::RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex) +{ + NS_LOG_FUNCTION (this << destination << &ifIndex); +// +// 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::IF_INDEX_ANY); + + if (mRoute) + { + NS_LOG_LOGIC ("Multicast route found"); + + if (mRoute->GetNOutputInterfaces () != 1) + { + NS_LOG_LOGIC ("Route is to multiple interfaces. Ignoring."); + return false; + } + + ifIndex = mRoute->GetOutputInterface(0); + NS_LOG_LOGIC ("Found ifIndex " << ifIndex); + 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) + { + ifIndex = 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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/ipv4-static-routing.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/ipv4-static-routing.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,506 @@ +// -*- 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 ifIndex. 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::IF_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 ifIndex The network interface index over which the packed was + * received. If the packet is from a local source, ifIndex will be set to + * Ipv4RoutingProtocol::IF_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. In practice, the static routing protocol is the last chance + * protocol. + * + * @see Ipv4StaticRouting + * @see Ipv4RoutingProtocol + */ + virtual bool RequestRoute (uint32_t ifIndex, + 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::GetIfIndexforDestination 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 ifIndex 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 RequestIfIndex (Ipv4Address destination, uint32_t& ifIndex); + +/** + * @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::IF_INDEX_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::IF_INDEX_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 ifIndex); + + HostRoutes m_hostRoutes; + NetworkRoutes m_networkRoutes; + Ipv4Route *m_defaultRoute; + Ipv4MulticastRoute *m_defaultMulticastRoute; + MulticastRoutes m_multicastRoutes; +}; + +} // Namespace ns3 + +#endif /* IPV4_STATIC_ROUTING_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/pending-data.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/pending-data.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,200 @@ +/* -*- 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: Rajib Bhattacharjea +// + + +// This is a port of Data PDU Headers from: +// Georgia Tech Network Simulator +// George F. Riley. Georgia Tech, Spring 2002 + +#include +#include + +#include + +#include "pending-data.h" +#include "ns3/fatal-error.h" +namespace ns3 +{ + +PendingData::PendingData () : size (0), data (0), + msgSize (0), responseSize (0) +{ +} + +PendingData::PendingData (uint32_t s, uint8_t* d, uint32_t msg, uint32_t resp) + : size (s), data (0), msgSize (msg), responseSize (resp) +{ + if (d) + { + data.push_back (Create (d, size)); + } +} + +PendingData::PendingData(const std::string& s) + : size (s.length () + 1), data (0), + msgSize (0), responseSize (0) +{ + data.push_back (Create ((uint8_t*)s.c_str(), size)); +} + +PendingData::PendingData(const PendingData& c) + : size (c.Size ()), data (c.data), + msgSize (c.msgSize), responseSize (c.responseSize) +{ +} + +PendingData::~PendingData() +{ +} + +PendingData* PendingData::Copy () const +{ + return new PendingData (*this); +}; + +PendingData* PendingData::CopyS (uint32_t s) +{ // Copy, but with new size (assumes no associated data); + return new PendingData (s, 0, msgSize, responseSize); +} + +PendingData* PendingData::CopySD (uint32_t s, uint8_t* d) +{ // Copy, but with new size (assumes no associated data); + return new PendingData (s, d, msgSize, responseSize); +} + +void PendingData::Clear () +{ // Remove all pending data + data.clear(); + size = 0; +} + +void PendingData::Add (uint32_t s, const uint8_t* d) +{ + if (d == 0) + { + data.push_back(Create (d,s)); + } + else + { + data.push_back(Create (s)); + } + size += s; +} + +void PendingData::Add (Ptr p) +{ + data.push_back(p); + size += p->GetSize(); +} + +uint32_t PendingData::SizeFromSeq (const SequenceNumber& f, const SequenceNumber& o) +{ + uint32_t o1 = OffsetFromSeq (f,o); // Offset to start of unused data + return SizeFromOffset (o1); // Amount of data after offset +} + +uint32_t PendingData::SizeFromOffset (uint32_t o) +{ // Find out how much data is available from offset + if (o > size) return 0; // No data at requested offset + return size - o; // Available data after offset +} + +uint32_t PendingData::OffsetFromSeq (const SequenceNumber& f, const SequenceNumber& o) +{ // f is the first sequence number in this data, o is offset sequence + if (o < f) + { + return 0; // HuH? Shouldn't happen + } + return o - f; +} + +Ptr PendingData::CopyFromOffset (uint32_t s, uint32_t o) +{ // Make a copy of data from starting position "o" for "s" bytes + // Return NULL if results in zero length data + uint32_t s1 = std::min (s, SizeFromOffset (o)); // Insure not beyond end of data + if (s1 == 0) + { + return 0; // No data requested + } + if (data.size() != 0) + { // Actual data exists, make copy and return it + uint32_t count = 0; + std::vector >::size_type begin = 0; + bool beginFound = false; + std::vector >::size_type end = 0; + Ptr outPacket; + Ptr endFragment; + for (std::vector >::size_type i=0;iGetSize(); + if (!beginFound) + { + if (count > o) + { + if (count >= o + s1) //then just copy within this packet + { + Ptr toFragment = data[i]; + uint32_t packetStart = count - toFragment->GetSize(); + uint32_t packetOffset = o - packetStart; + outPacket = toFragment->CreateFragment (packetOffset, s1); + return outPacket; + } + begin = i; + beginFound = true; + Ptr toFragment = data[begin]; + uint32_t packetStart = count - toFragment->GetSize(); + uint32_t packetOffset = o - packetStart; + uint32_t fragmentLength = count - o; + outPacket = toFragment->CreateFragment (packetOffset, fragmentLength); + } + } + else + { + if (count >= o + s1) + { + end = i; + Ptr toFragment = data[end]; + uint32_t packetStart = count - toFragment->GetSize(); + uint32_t fragmentLength = o + s1 - packetStart; + endFragment = toFragment->CreateFragment(0, fragmentLength); + break; + } + } + } + for (std::vector >::size_type i=begin+1;iAddAtEnd (data[i]); + } + outPacket->AddAtEnd(endFragment); + NS_ASSERT(outPacket->GetSize() == s1); + return outPacket; + } + else + { // No actual data, just return dummy-data packet of correct size + return Create (s1); + } +} + +Ptr PendingData::CopyFromSeq (uint32_t s, const SequenceNumber& f, const SequenceNumber& o) +{ + return CopyFromOffset (s, OffsetFromSeq(f,o)); +} + +}//namepsace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/pending-data.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/pending-data.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,74 @@ +/* -*- 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: Rajib Bhattacharjea +// + +// Georgia Tech Network Simulator - Data Descriptors +// George F. Riley. Georgia Tech, Spring 2002 + +#ifndef __datapdu_h__ +#define __datapdu_h__ + +#include "ns3/packet.h" +#include "pending-data.h" +#include "sequence-number.h" + +#include "ns3/ptr.h" +namespace ns3 +{ +class Packet; +//Doc:ClassXRef +class PendingData { +public: + PendingData (); + PendingData (uint32_t s, uint8_t* d = NULL, uint32_t msg = 0, uint32_t resp = 0); + PendingData (const std::string&); // Construct from string + PendingData (uint8_t*, uint32_t&, Packet*); // Construct from serialized buffer + PendingData (const PendingData&); // Copy constructor + virtual ~PendingData (); // Destructor + uint32_t Size () const { return size;} + // Serialization + uint32_t SSize (); // Size needed for serialization + uint8_t* Serialize (uint8_t*, uint32_t&); // Serialize to a buffer + uint8_t* Construct (uint8_t*, uint32_t&); // Construct from buffer + virtual void Clear ();// Remove all associated data + virtual void Add (uint32_t s, const uint8_t* d = 0);// Add some data to end + virtual void Add (Ptr p); + // Inquire available data from (f,o) sequence pair + virtual uint32_t SizeFromSeq (const SequenceNumber&, const SequenceNumber&); + // Inquire available data from offset + virtual uint32_t SizeFromOffset (uint32_t); + // Available size from sequence difference + virtual uint32_t OffsetFromSeq (const SequenceNumber&, const SequenceNumber&); + virtual Ptr CopyFromOffset (uint32_t, uint32_t); // Size, offset, ret packet + // Copy data, size, offset specified by sequence difference + virtual Ptr CopyFromSeq (uint32_t, const SequenceNumber&, const SequenceNumber&); + PendingData* Copy () const; // Create a copy of this header + PendingData* CopyS (uint32_t); // Copy with new size + PendingData* CopySD (uint32_t, uint8_t*); // Copy with new size, new data +public: + uint32_t size; // Number of data bytes + std::vector > data; // Corresponding data (may be null) + // The next two fields allow simulated applications to exchange some info + uint32_t msgSize; // Total size of message + uint32_t responseSize;// Size of response requested +}; + +}//namepsace ns3 +#endif + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/rtt-estimator.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/rtt-estimator.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,235 @@ +/* -*- 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: Rajib Bhattacharjea +// + + +// Ported from: +// Georgia Tech Network Simulator - Round Trip Time Estimation Class +// George F. Riley. Georgia Tech, Spring 2002 + +// Implements several variations of round trip time estimators + +#include + +#include "rtt-estimator.h" +#include "ns3/simulator.h" +#include "ns3/double.h" + +namespace ns3{ + +NS_OBJECT_ENSURE_REGISTERED (RttEstimator); + +//RttEstimator iid +TypeId +RttEstimator::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RttEstimator") + .SetParent () + .AddAttribute ("MaxMultiplier", + "XXX", + DoubleValue (64.0), + MakeDoubleAccessor (&RttEstimator::m_maxMultiplier), + MakeDoubleChecker ()) + .AddAttribute ("InitialEstimation", + "XXX", + TimeValue (Seconds (1.0)), + MakeTimeAccessor (&RttEstimator::est), + MakeTimeChecker ()) + ; + return tid; +} + +//RttHistory methods +RttHistory::RttHistory (SequenceNumber s, uint32_t c, Time t) + : seq (s), count (c), time (t), retx (false) + { + } + +RttHistory::RttHistory (const RttHistory& h) + : seq (h.seq), count (h.count), time (h.time), retx (h.retx) + { + } + +// Base class methods + +RttEstimator::RttEstimator () : next (1), history (), + nSamples (0), multiplier (1.0) +{ + //note next=1 everywhere since first segment will have sequence 1 +} + +RttEstimator::RttEstimator(const RttEstimator& c) + : Object (c), next(c.next), history(c.history), + m_maxMultiplier (c.m_maxMultiplier), est(c.est), nSamples(c.nSamples), + multiplier(c.multiplier) +{} + +RttEstimator::~RttEstimator () +{ +} + +void RttEstimator::SentSeq (SequenceNumber s, uint32_t c) +{ // Note that a particular sequence has been sent + if (s == next) + { // This is the next expected one, just log at end + history.push_back (RttHistory (s, c, Simulator::Now () )); + next = s + SequenceNumber (c); // Update next expected + } + else + { // This is a retransmit, find in list and mark as re-tx + for (RttHistory_t::iterator i = history.begin (); i != history.end (); ++i) + { + if ((s >= i->seq) && (s < (i->seq + SequenceNumber (i->count)))) + { // Found it + i->retx = true; + // One final test..be sure this re-tx does not extend "next" + if ((s + SequenceNumber (c)) > next) + { + next = s + SequenceNumber (c); + i->count = ((s + SequenceNumber (c)) - i->seq); // And update count in hist + } + break; + } + } + } +} + +Time RttEstimator::AckSeq (SequenceNumber a) +{ // An ack has been received, calculate rtt and log this measurement + // Note we use a linear search (O(n)) for this since for the common + // case the ack'ed packet will be at the head of the list + Time m = Seconds (0.0); + if (history.size () == 0) return (m); // No pending history, just exit + RttHistory& h = history.front (); + if (!h.retx && a >= (h.seq + SequenceNumber (h.count))) + { // Ok to use this sample + m = Simulator::Now () - h.time; // Elapsed time + Measurement(m); // Log the measurement + ResetMultiplier(); // Reset multiplier on valid measurement + } + // Now delete all ack history with seq <= ack + while(history.size() > 0) + { + RttHistory& h = history.front (); + if ((h.seq + SequenceNumber(h.count)) > a) break; // Done removing + history.pop_front (); // Remove + } + return m; +} + +void RttEstimator::ClearSent () +{ // Clear all history entries + next = 1; + history.clear (); +} + +void RttEstimator::IncreaseMultiplier () +{ + double a; + a = multiplier * 2.0; + double b; + b = m_maxMultiplier * 2.0; + multiplier = std::min (multiplier * 2.0, m_maxMultiplier); +} + +void RttEstimator::ResetMultiplier () +{ + multiplier = 1.0; +} + +void RttEstimator::Reset () +{ // Reset to initial state + next = 1; + est = Seconds (1.0); // XXX: we should go back to the 'initial value' here. Need to add support in Object for this. + history.clear (); // Remove all info from the history + nSamples = 0; + ResetMultiplier (); +} + + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Mean-Deviation Estimator + +NS_OBJECT_ENSURE_REGISTERED (RttMeanDeviation); + +TypeId +RttMeanDeviation::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RttMeanDeviation") + .SetParent () + .AddConstructor () + .AddAttribute ("Gain", + "XXX", + DoubleValue (0.1), + MakeDoubleAccessor (&RttMeanDeviation::gain), + MakeDoubleChecker ()) + ; + return tid; +} + +RttMeanDeviation::RttMeanDeviation() : + variance (ns3::Seconds(0)) +{ +} + +RttMeanDeviation::RttMeanDeviation (const RttMeanDeviation& c) + : RttEstimator (c), gain (c.gain), variance (c.variance) +{ +} + +void RttMeanDeviation::Measurement (Time m) +{ + if (nSamples) + { // Not first + Time err = m - est; + est = est + Scalar (gain) * err; // estimated rtt + err = Abs (err); // absolute value of error + variance = variance + Scalar (gain) * (err - variance); // variance of rtt + } + else + { // First sample + est = m; // Set estimate to current + //variance = m / 2; // And variance to current / 2 + variance = m; // try this + } + nSamples++; +} + +Time RttMeanDeviation::RetransmitTimeout () +{ + // If not enough samples, justjust return 2 times estimate + //if (nSamples < 2) return est * 2; + if (variance < est / Scalar (4.0)) + return est * Scalar (2 * multiplier); // At least twice current est + return (est + Scalar (4) * variance) * Scalar (multiplier); // As suggested by Jacobson +} + +Ptr RttMeanDeviation::Copy () const +{ + return CopyObject (this); +} + +void RttMeanDeviation::Reset () +{ // Reset to initial state + variance = Seconds (0.0); + RttEstimator::Reset (); +} +}//namepsace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/rtt-estimator.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/rtt-estimator.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,113 @@ +/* -*- 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: Rajib Bhattacharjea +// + +// Georgia Tech Network Simulator - Round Trip Time Estimation Class +// George F. Riley. Georgia Tech, Spring 2002 + +// Implements several variations of round trip time estimators + +#ifndef __rtt_estimator_h__ +#define __rtt_estimator_h__ + +#include +#include "sequence-number.h" +#include "ns3/nstime.h" +#include "ns3/object.h" + +namespace ns3 { + +class RttHistory { +public: + RttHistory (SequenceNumber s, uint32_t c, Time t); + RttHistory (const RttHistory& h); // Copy constructor +public: + SequenceNumber seq; // First sequence number in packet sent + uint32_t count; // Number of bytes sent + Time time; // Time this one was sent + bool retx; // True if this has been retransmitted +}; + +typedef std::deque RttHistory_t; + +class RttEstimator : public Object { // Base class for all RTT Estimators +public: + static TypeId GetTypeId (void); + + RttEstimator(); + RttEstimator(const RttEstimator&); // Copy constructor + virtual ~RttEstimator(); + + virtual void SentSeq(SequenceNumber, uint32_t); + virtual Time AckSeq(SequenceNumber); + virtual void ClearSent(); + virtual void Measurement(Time t) = 0; + virtual Time Estimate() = 0; + virtual Time RetransmitTimeout() = 0; + void Init(SequenceNumber s) { next = s;} + virtual Ptr Copy() const = 0; + virtual void IncreaseMultiplier(); + virtual void ResetMultiplier(); + virtual void Reset(); + +private: + SequenceNumber next; // Next expected sequence to be sent + RttHistory_t history; // List of sent packet + double m_maxMultiplier; +public: + Time est; // Current estimate + uint32_t nSamples;// Number of samples + double multiplier; // RTO Multiplier +}; + +// The "Mean-Deviation" estimator, as discussed by Van Jacobson +// "Congestion Avoidance and Control", SIGCOMM 88, Appendix A + + //Doc:Class Class {\tt RttMeanDeviation} implements the "Mean--Deviation" estimator + //Doc:Class as described by Van Jacobson + //Doc:Class "Congestion Avoidance and Control", SIGCOMM 88, Appendix A +class RttMeanDeviation : public RttEstimator { +public : + static TypeId GetTypeId (void); + + RttMeanDeviation (); + + + //Doc:Method + RttMeanDeviation (const RttMeanDeviation&); // Copy constructor + //Doc:Desc Copy constructor. + //Doc:Arg1 {\tt RttMeanDeviation} object to copy. + + void Measurement (Time); + Time Estimate () { return est;} + Time Variance () { return variance;} + Time RetransmitTimeout (); + Ptr Copy () const; + void Reset (); + void Gain (double g) { gain = g;} + +public: + double gain; // Filter gain + Time variance; // Current variance +}; +}//namespace ns3 +#endif + + + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/sequence-number.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/sequence-number.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,65 @@ +/* -*- 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: Rajib Bhattacharjea +// + + +// Ported from: +// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers +// George F. Riley. Georgia Tech, Spring 2002 + +// Class to manage arithmetic operations on sequence numbers (mod 2^32) + +#include "sequence-number.h" + +bool operator< (const SequenceNumber l, const SequenceNumber r) +{ // Account for 32 bit rollover + if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover + return l.seq < r.seq; +} + +bool operator<= (const SequenceNumber l, const SequenceNumber r) +{ // Account for 32 bit rollover + if (l.seq > 0xc0000000 && r.seq < 0x40000000) return true; // Rollover + return l.seq <= r.seq; +} + +bool operator> (const SequenceNumber l, const SequenceNumber r) +{ // Account for 32 bit rollover + if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover + return l.seq > r.seq; +} + +bool operator>= (const SequenceNumber l, const SequenceNumber r) +{ // Account for 32 bit rollover + if (l.seq > 0xc0000000 && r.seq < 0x40000000) return false; // Rollover + return l.seq >= r.seq; +} + +// Non-Member Arithmetic operators +SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r) +{ + return SequenceNumber (l.seq + r.seq); +} + +SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r) +{ // This assumes l is always bigger than r (allows for rollover) + if (l.seq >= r.seq) return SequenceNumber (l.seq-r.seq); + return SequenceNumber ((MAX_SEQ - r.seq) + l.seq + 1); // Adjust for rollover +} + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/sequence-number.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/sequence-number.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,66 @@ +/* -*- 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: Rajib Bhattacharjea +// + +// Ported from: +// Georgia Tech Network Simulator - Manage 32 bit unsigned sequence numbers +// George F. Riley. Georgia Tech, Spring 2002 + +// Class to manage arithmetic operations on sequence numbers (mod 2^32) + +#ifndef __seq_h__ +#define __seq_h__ + +#include + +#define MAX_SEQ ((uint32_t)0xffffffff) + +class SequenceNumber { +public: + SequenceNumber () : seq(0) { } + SequenceNumber (const uint32_t s) : seq (s) { } + + operator uint32_t () const { return seq;} + + SequenceNumber& operator= (const uint32_t s) { seq = s; return *this;} + + SequenceNumber& operator+= (const uint32_t s) { seq += s; return *this;} + SequenceNumber operator++ () { seq++; return *this;} + SequenceNumber operator++ (int) { SequenceNumber ss (seq); seq++; return ss;} + SequenceNumber& operator-= (const uint32_t s) { seq -= s; return *this;} + SequenceNumber operator-- () { seq--; return *this;} + SequenceNumber operator-- (int) { SequenceNumber ss (seq); seq--; return ss;} +public: + uint32_t seq; +}; + +// Comparison operators + +bool operator< (const SequenceNumber l, const SequenceNumber r); +bool operator<= (const SequenceNumber l, const SequenceNumber r); +bool operator> (const SequenceNumber l, const SequenceNumber r); +bool operator>= (const SequenceNumber l, const SequenceNumber r); + +// Non-member arithmetic operators +SequenceNumber operator+ (const SequenceNumber l, const SequenceNumber r); +SequenceNumber operator- (const SequenceNumber l, const SequenceNumber r); + +#endif + + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/sgi-hashmap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/sgi-hashmap.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,32 @@ +/* This code snippet was ripped out of the gcc + * documentation and slightly modified to work + * with gcc 4.x + */ +#ifndef SGI_HASHMAP_H +#define SGI_HASHMAP_H + +/* To use gcc extensions. + */ +#ifdef __GNUC__ + #if __GNUC__ < 3 + #include +namespace sgi { using ::hash_map; }; // inherit globals + #else + #if __GNUC__ < 4 + #include + #if __GNUC_MINOR__ == 0 +namespace sgi = std; // GCC 3.0 + #else +namespace sgi = ::__gnu_cxx; // GCC 3.1 and later + #endif + #else // gcc 4.x and later + #include + namespace sgi = ::__gnu_cxx; + #endif + #endif +#else // ... there are other compilers, right? +namespace sgi = std; +#endif + + +#endif /* SGI_HASHMAP_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-header.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-header.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,217 @@ +/* -*- 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 + */ + +#include +#include +#include "tcp-socket-impl.h" +#include "tcp-header.h" +#include "ns3/buffer.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (TcpHeader); + +bool TcpHeader::m_calcChecksum = false; + +TcpHeader::TcpHeader () + : m_sourcePort (0), + m_destinationPort (0), + m_sequenceNumber (0), + m_ackNumber (0), + m_length (5), + m_flags (0), + m_windowSize (0xffff), + m_checksum (0), + m_urgentPointer (0) +{} + +TcpHeader::~TcpHeader () +{} + +void +TcpHeader::EnableChecksums (void) +{ + m_calcChecksum = true; +} + +void TcpHeader::SetSourcePort (uint16_t port) +{ + m_sourcePort = port; +} +void TcpHeader::SetDestinationPort (uint16_t port) +{ + m_destinationPort = port; +} +void TcpHeader::SetSequenceNumber (SequenceNumber sequenceNumber) +{ + m_sequenceNumber = sequenceNumber; +} +void TcpHeader::SetAckNumber (SequenceNumber ackNumber) +{ + m_ackNumber = ackNumber; +} +void TcpHeader::SetLength (uint8_t length) +{ + m_length = length; +} +void TcpHeader::SetFlags (uint8_t flags) +{ + m_flags = flags; +} +void TcpHeader::SetWindowSize (uint16_t windowSize) +{ + m_windowSize = windowSize; +} +void TcpHeader::SetChecksum (uint16_t checksum) +{ + m_checksum = checksum; +} +void TcpHeader::SetUrgentPointer (uint16_t urgentPointer) +{ + m_urgentPointer = urgentPointer; +} + +uint16_t TcpHeader::GetSourcePort () const +{ + return m_sourcePort; +} +uint16_t TcpHeader::GetDestinationPort () const +{ + return m_destinationPort; +} +SequenceNumber TcpHeader::GetSequenceNumber () const +{ + return m_sequenceNumber; +} +SequenceNumber TcpHeader::GetAckNumber () const +{ + return m_ackNumber; +} +uint8_t TcpHeader::GetLength () const +{ + return m_length; +} +uint8_t TcpHeader::GetFlags () const +{ + return m_flags; +} +uint16_t TcpHeader::GetWindowSize () const +{ + return m_windowSize; +} +uint16_t TcpHeader::GetChecksum () const +{ + return m_checksum; +} +uint16_t TcpHeader::GetUrgentPointer () const +{ + return m_urgentPointer; +} + +void +TcpHeader::InitializeChecksum (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol) +{ + m_checksum = 0; +//XXX requires peeking into IP to get length of the TCP segment +} + +TypeId +TcpHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::TcpHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} +TypeId +TcpHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +void TcpHeader::Print (std::ostream &os) const +{ + os << m_sourcePort << " > " << m_destinationPort; + if(m_flags!=0) + { + os<<" ["; + if((m_flags & FIN) != 0) + { + os<<" FIN "; + } + if((m_flags & SYN) != 0) + { + os<<" SYN "; + } + if((m_flags & RST) != 0) + { + os<<" RST "; + } + if((m_flags & PSH) != 0) + { + os<<" PSH "; + } + if((m_flags & ACK) != 0) + { + os<<" ACK "; + } + if((m_flags & URG) != 0) + { + os<<" URG "; + } + os<<"]"; + } + os<<" Seq="< + */ + +#ifndef TCP_HEADER_H +#define TCP_HEADER_H + +#include +#include "ns3/header.h" +#include "ns3/buffer.h" +#include "ns3/tcp-socket-factory.h" +#include "ns3/ipv4-address.h" +#include "ns3/sequence-number.h" + +namespace ns3 { + +class TcpHeader : public Header +{ +public: + TcpHeader (); + virtual ~TcpHeader (); + + /** + * \brief Enable checksum calculation for TCP (XXX currently has no effect) + */ + static void EnableChecksums (void); +//Setters + /** + * \param port The source port for this TcpHeader + */ + void SetSourcePort (uint16_t port); + /** + * \param port the destination port for this TcpHeader + */ + void SetDestinationPort (uint16_t port); + /** + * \param sequenceNumber the sequence number for this TcpHeader + */ + void SetSequenceNumber (SequenceNumber sequenceNumber); + /** + * \param ackNumber the ACK number for this TcpHeader + */ + void SetAckNumber (SequenceNumber ackNumber); + /** + * \param length the length of this TcpHeader + */ + void SetLength (uint8_t length); + /** + * \param flags the flags for this TcpHeader + */ + void SetFlags (uint8_t flags); + /** + * \param windowSize the window size for this TcpHeader + */ + void SetWindowSize (uint16_t windowSize); + /** + * \param checksum the checksum for this TcpHeader + */ + void SetChecksum (uint16_t checksum); + /** + * \param urgentPointer the urgent pointer for this TcpHeader + */ + void SetUrgentPointer (uint16_t urgentPointer); + + +//Getters + /** + * \return The source port for this TcpHeader + */ + uint16_t GetSourcePort () const; + /** + * \return the destination port for this TcpHeader + */ + uint16_t GetDestinationPort () const; + /** + * \return the sequence number for this TcpHeader + */ + SequenceNumber GetSequenceNumber () const; + /** + * \return the ACK number for this TcpHeader + */ + SequenceNumber GetAckNumber () const; + /** + * \return the length of this TcpHeader + */ + uint8_t GetLength () const; + /** + * \return the flags for this TcpHeader + */ + uint8_t GetFlags () const; + /** + * \return the window size for this TcpHeader + */ + uint16_t GetWindowSize () const; + /** + * \return the checksum for this TcpHeader + */ + uint16_t GetChecksum () const; + /** + * \return the urgent pointer for this TcpHeader + */ + uint16_t GetUrgentPointer () const; + + /** + * \param source the ip source to use in the underlying + * ip packet. + * \param destination the ip destination to use in the + * underlying ip packet. + * \param protocol the protocol number to use in the underlying + * ip packet. + * + * If you want to use tcp checksums, you should call this + * method prior to adding the header to a packet. + */ + void InitializeChecksum (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol); + + typedef enum { NONE = 0, FIN = 1, SYN = 2, RST = 4, PSH = 8, ACK = 16, + URG = 32} Flags_t; + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual void Print (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + +private: + uint16_t m_sourcePort; + uint16_t m_destinationPort; + uint32_t m_sequenceNumber; + uint32_t m_ackNumber; + uint8_t m_length; // really a uint4_t + uint8_t m_flags; // really a uint6_t + uint16_t m_windowSize; + uint16_t m_checksum; + uint16_t m_urgentPointer; + + static bool m_calcChecksum; +}; + +}; // namespace ns3 + +#endif /* TCP_HEADER */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-l4-protocol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-l4-protocol.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,526 @@ +/* -*- 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 + */ + +#include "ns3/assert.h" +#include "ns3/log.h" +#include "ns3/nstime.h" + +#include "ns3/packet.h" +#include "ns3/node.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-impl.h" + +#include "tcp-typedefs.h" + +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("TcpL4Protocol"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol); + +//State Machine things -------------------------------------------------------- +TcpStateMachine::TcpStateMachine() + : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)), + eV (MAX_FLAGS) +{ + NS_LOG_FUNCTION_NOARGS (); + + // Create the state table + // Closed state + aT[CLOSED][APP_LISTEN] = SA (LISTEN, NO_ACT); + aT[CLOSED][APP_CONNECT] = SA (SYN_SENT, SYN_TX); + aT[CLOSED][APP_SEND] = SA (CLOSED, RST_TX); + aT[CLOSED][SEQ_RECV] = SA (CLOSED, NO_ACT); + aT[CLOSED][APP_CLOSE] = SA (CLOSED, NO_ACT); + aT[CLOSED][TIMEOUT] = SA (CLOSED, RST_TX); + aT[CLOSED][ACK_RX] = SA (CLOSED, RST_TX); + aT[CLOSED][SYN_RX] = SA (CLOSED, RST_TX); + aT[CLOSED][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[CLOSED][FIN_RX] = SA (CLOSED, RST_TX); + aT[CLOSED][FIN_ACK_RX] = SA (CLOSED, RST_TX); + aT[CLOSED][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[CLOSED][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // Listen State + // For the listen state, anything other than CONNECT or SEND + // is simply ignored....this likely indicates the child TCP + // has finished and issued unbind call, but the remote end + // has not yet closed. + aT[LISTEN][APP_LISTEN] = SA (LISTEN, NO_ACT); + aT[LISTEN][APP_CONNECT] = SA (SYN_SENT, SYN_TX); + aT[LISTEN][APP_SEND] = SA (SYN_SENT, SYN_TX); + aT[LISTEN][SEQ_RECV] = SA (LISTEN, NO_ACT); + aT[LISTEN][APP_CLOSE] = SA (CLOSED, NO_ACT); + aT[LISTEN][TIMEOUT] = SA (LISTEN, NO_ACT); + aT[LISTEN][ACK_RX] = SA (LISTEN, NO_ACT); + aT[LISTEN][SYN_RX] = SA (LISTEN, SYN_ACK_TX);//stay in listen and fork + aT[LISTEN][SYN_ACK_RX] = SA (LISTEN, NO_ACT); + aT[LISTEN][FIN_RX] = SA (LISTEN, NO_ACT); + aT[LISTEN][FIN_ACK_RX] = SA (LISTEN, NO_ACT); + aT[LISTEN][RST_RX] = SA (LISTEN, NO_ACT); + aT[LISTEN][BAD_FLAGS] = SA (LISTEN, NO_ACT); + + // Syn Sent State + aT[SYN_SENT][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[SYN_SENT][APP_CONNECT] = SA (SYN_SENT, SYN_TX); + aT[SYN_SENT][APP_SEND] = SA (SYN_SENT, NO_ACT); + aT[SYN_SENT][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX); + aT[SYN_SENT][APP_CLOSE] = SA (CLOSED, RST_TX); + aT[SYN_SENT][TIMEOUT] = SA (CLOSED, NO_ACT); + aT[SYN_SENT][ACK_RX] = SA (SYN_SENT, NO_ACT); + aT[SYN_SENT][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); + aT[SYN_SENT][SYN_ACK_RX] = SA (ESTABLISHED, ACK_TX_1); + aT[SYN_SENT][FIN_RX] = SA (CLOSED, RST_TX); + aT[SYN_SENT][FIN_ACK_RX] = SA (CLOSED, RST_TX); + aT[SYN_SENT][RST_RX] = SA (CLOSED, APP_NOTIFY); + aT[SYN_SENT][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // Syn Recvd State + aT[SYN_RCVD][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][APP_CONNECT] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][APP_SEND] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][SEQ_RECV] = SA (ESTABLISHED, NEW_SEQ_RX); + aT[SYN_RCVD][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX); + aT[SYN_RCVD][TIMEOUT] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][ACK_RX] = SA (ESTABLISHED, SERV_NOTIFY); + aT[SYN_RCVD][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); + aT[SYN_RCVD][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][FIN_RX] = SA (CLOSED, RST_TX); + aT[SYN_RCVD][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE); + aT[SYN_RCVD][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[SYN_RCVD][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // Established State + aT[ESTABLISHED][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[ESTABLISHED][APP_CONNECT]= SA (CLOSED, RST_TX); + aT[ESTABLISHED][APP_SEND] = SA (ESTABLISHED,TX_DATA); + aT[ESTABLISHED][SEQ_RECV] = SA (ESTABLISHED,NEW_SEQ_RX); + aT[ESTABLISHED][APP_CLOSE] = SA (FIN_WAIT_1, FIN_TX); + aT[ESTABLISHED][TIMEOUT] = SA (ESTABLISHED,RETX); + aT[ESTABLISHED][ACK_RX] = SA (ESTABLISHED,NEW_ACK); + aT[ESTABLISHED][SYN_RX] = SA (SYN_RCVD, SYN_ACK_TX); + aT[ESTABLISHED][SYN_ACK_RX] = SA (ESTABLISHED,NO_ACT); + aT[ESTABLISHED][FIN_RX] = SA (CLOSE_WAIT, PEER_CLOSE); + aT[ESTABLISHED][FIN_ACK_RX] = SA (CLOSE_WAIT, PEER_CLOSE); + aT[ESTABLISHED][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[ESTABLISHED][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // Close Wait State + aT[CLOSE_WAIT][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[CLOSE_WAIT][APP_CONNECT] = SA (SYN_SENT, SYN_TX); + aT[CLOSE_WAIT][APP_SEND] = SA (CLOSE_WAIT, TX_DATA); + aT[CLOSE_WAIT][SEQ_RECV] = SA (CLOSE_WAIT, NEW_SEQ_RX); + aT[CLOSE_WAIT][APP_CLOSE] = SA (LAST_ACK, FIN_ACK_TX); + aT[CLOSE_WAIT][TIMEOUT] = SA (CLOSE_WAIT, NO_ACT); + aT[CLOSE_WAIT][ACK_RX] = SA (CLOSE_WAIT, NO_ACT); + aT[CLOSE_WAIT][SYN_RX] = SA (CLOSED, RST_TX); + aT[CLOSE_WAIT][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[CLOSE_WAIT][FIN_RX] = SA (CLOSE_WAIT, ACK_TX); + aT[CLOSE_WAIT][FIN_ACK_RX] = SA (CLOSE_WAIT, ACK_TX); + aT[CLOSE_WAIT][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[CLOSE_WAIT][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // Close Last Ack State + aT[LAST_ACK][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[LAST_ACK][APP_CONNECT] = SA (SYN_SENT, SYN_TX); + aT[LAST_ACK][APP_SEND] = SA (CLOSED, RST_TX); + aT[LAST_ACK][SEQ_RECV] = SA (LAST_ACK, NEW_SEQ_RX); + aT[LAST_ACK][APP_CLOSE] = SA (CLOSED, NO_ACT); + aT[LAST_ACK][TIMEOUT] = SA (CLOSED, NO_ACT); + aT[LAST_ACK][ACK_RX] = SA (CLOSED, APP_CLOSED); + aT[LAST_ACK][SYN_RX] = SA (CLOSED, RST_TX); + aT[LAST_ACK][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[LAST_ACK][FIN_RX] = SA (LAST_ACK, FIN_ACK_TX); + aT[LAST_ACK][FIN_ACK_RX] = SA (CLOSED, NO_ACT); + aT[LAST_ACK][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[LAST_ACK][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // FIN_WAIT_1 state + aT[FIN_WAIT_1][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_1][APP_CONNECT] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_1][APP_SEND] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_1][SEQ_RECV] = SA (FIN_WAIT_1, NEW_SEQ_RX); + aT[FIN_WAIT_1][APP_CLOSE] = SA (FIN_WAIT_1, NO_ACT); + aT[FIN_WAIT_1][TIMEOUT] = SA (FIN_WAIT_1, NO_ACT); + aT[FIN_WAIT_1][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK); + aT[FIN_WAIT_1][SYN_RX] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_1][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_1][FIN_RX] = SA (CLOSING, ACK_TX); + aT[FIN_WAIT_1][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX); + aT[FIN_WAIT_1][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[FIN_WAIT_1][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // FIN_WAIT_2 state + aT[FIN_WAIT_2][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_2][APP_CONNECT] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_2][APP_SEND] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_2][SEQ_RECV] = SA (FIN_WAIT_2, NEW_SEQ_RX); + aT[FIN_WAIT_2][APP_CLOSE] = SA (FIN_WAIT_2, NO_ACT); + aT[FIN_WAIT_2][TIMEOUT] = SA (FIN_WAIT_2, NO_ACT); + aT[FIN_WAIT_2][ACK_RX] = SA (FIN_WAIT_2, NEW_ACK); + aT[FIN_WAIT_2][SYN_RX] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_2][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[FIN_WAIT_2][FIN_RX] = SA (TIMED_WAIT, ACK_TX); + aT[FIN_WAIT_2][FIN_ACK_RX] = SA (TIMED_WAIT, ACK_TX); + aT[FIN_WAIT_2][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[FIN_WAIT_2][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // CLOSING state + aT[CLOSING][APP_LISTEN] = SA (CLOSED, RST_TX); + aT[CLOSING][APP_CONNECT] = SA (CLOSED, RST_TX); + aT[CLOSING][APP_SEND] = SA (CLOSED, RST_TX); + aT[CLOSING][SEQ_RECV] = SA (CLOSED, RST_TX); + aT[CLOSING][APP_CLOSE] = SA (CLOSED, RST_TX); + aT[CLOSING][TIMEOUT] = SA (CLOSING, NO_ACT); + aT[CLOSING][ACK_RX] = SA (TIMED_WAIT, NO_ACT); + aT[CLOSING][SYN_RX] = SA (CLOSED, RST_TX); + aT[CLOSING][SYN_ACK_RX] = SA (CLOSED, RST_TX); + aT[CLOSING][FIN_RX] = SA (CLOSED, ACK_TX); + aT[CLOSING][FIN_ACK_RX] = SA (CLOSED, ACK_TX); + aT[CLOSING][RST_RX] = SA (CLOSED, CANCEL_TM); + aT[CLOSING][BAD_FLAGS] = SA (CLOSED, RST_TX); + + // TIMED_WAIT state + aT[TIMED_WAIT][APP_LISTEN] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][APP_CONNECT] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][APP_SEND] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][SEQ_RECV] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][APP_CLOSE] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][TIMEOUT] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][ACK_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][SYN_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][SYN_ACK_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][FIN_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][FIN_ACK_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][RST_RX] = SA (TIMED_WAIT, NO_ACT); + aT[TIMED_WAIT][BAD_FLAGS] = SA (TIMED_WAIT, NO_ACT); + + // Create the flags lookup table + eV[ 0x00] = SEQ_RECV; // No flags + eV[ 0x01] = FIN_RX; // Fin + eV[ 0x02] = SYN_RX; // Syn + eV[ 0x03] = BAD_FLAGS; // Illegal + eV[ 0x04] = RST_RX; // Rst + eV[ 0x05] = BAD_FLAGS; // Illegal + eV[ 0x06] = BAD_FLAGS; // Illegal + eV[ 0x07] = BAD_FLAGS; // Illegal + eV[ 0x08] = SEQ_RECV; // Psh flag is not used + eV[ 0x09] = FIN_RX; // Fin + eV[ 0x0a] = SYN_RX; // Syn + eV[ 0x0b] = BAD_FLAGS; // Illegal + eV[ 0x0c] = RST_RX; // Rst + eV[ 0x0d] = BAD_FLAGS; // Illegal + eV[ 0x0e] = BAD_FLAGS; // Illegal + eV[ 0x0f] = BAD_FLAGS; // Illegal + eV[ 0x10] = ACK_RX; // Ack + eV[ 0x11] = FIN_ACK_RX;// Fin/Ack + eV[ 0x12] = SYN_ACK_RX;// Syn/Ack + eV[ 0x13] = BAD_FLAGS; // Illegal + eV[ 0x14] = RST_RX; // Rst + eV[ 0x15] = BAD_FLAGS; // Illegal + eV[ 0x16] = BAD_FLAGS; // Illegal + eV[ 0x17] = BAD_FLAGS; // Illegal + eV[ 0x18] = ACK_RX; // Ack + eV[ 0x19] = FIN_ACK_RX;// Fin/Ack + eV[ 0x1a] = SYN_ACK_RX;// Syn/Ack + eV[ 0x1b] = BAD_FLAGS; // Illegal + eV[ 0x1c] = RST_RX; // Rst + eV[ 0x1d] = BAD_FLAGS; // Illegal + eV[ 0x1e] = BAD_FLAGS; // Illegal + eV[ 0x1f] = BAD_FLAGS; // Illegal + eV[ 0x20] = SEQ_RECV; // No flags (Urgent not presently used) + eV[ 0x21] = FIN_RX; // Fin + eV[ 0x22] = SYN_RX; // Syn + eV[ 0x23] = BAD_FLAGS; // Illegal + eV[ 0x24] = RST_RX; // Rst + eV[ 0x25] = BAD_FLAGS; // Illegal + eV[ 0x26] = BAD_FLAGS; // Illegal + eV[ 0x27] = BAD_FLAGS; // Illegal + eV[ 0x28] = SEQ_RECV; // Psh flag is not used + eV[ 0x29] = FIN_RX; // Fin + eV[ 0x2a] = SYN_RX; // Syn + eV[ 0x2b] = BAD_FLAGS; // Illegal + eV[ 0x2c] = RST_RX; // Rst + eV[ 0x2d] = BAD_FLAGS; // Illegal + eV[ 0x2e] = BAD_FLAGS; // Illegal + eV[ 0x2f] = BAD_FLAGS; // Illegal + eV[ 0x30] = ACK_RX; // Ack (Urgent not used) + eV[ 0x31] = FIN_ACK_RX;// Fin/Ack + eV[ 0x32] = SYN_ACK_RX;// Syn/Ack + eV[ 0x33] = BAD_FLAGS; // Illegal + eV[ 0x34] = RST_RX; // Rst + eV[ 0x35] = BAD_FLAGS; // Illegal + eV[ 0x36] = BAD_FLAGS; // Illegal + eV[ 0x37] = BAD_FLAGS; // Illegal + eV[ 0x38] = ACK_RX; // Ack + eV[ 0x39] = FIN_ACK_RX;// Fin/Ack + eV[ 0x3a] = SYN_ACK_RX;// Syn/Ack + eV[ 0x3b] = BAD_FLAGS; // Illegal + eV[ 0x3c] = RST_RX; // Rst + eV[ 0x3d] = BAD_FLAGS; // Illegal + eV[ 0x3e] = BAD_FLAGS; // Illegal + eV[ 0x3f] = BAD_FLAGS; // Illegal +} + +SA TcpStateMachine::Lookup (States_t s, Events_t e) +{ + NS_LOG_FUNCTION (this << s << e); + return aT[s][e]; +} + +Events_t TcpStateMachine::FlagsEvent (uint8_t f) +{ + NS_LOG_FUNCTION (this << f); + // Lookup event from flags + if (f >= MAX_FLAGS) return BAD_FLAGS; + return eV[f]; // Look up flags event +} + +static TcpStateMachine tcpStateMachine; //only instance of a TcpStateMachine + +//TcpL4Protocol stuff---------------------------------------------------------- + + +/* see http://www.iana.org/assignments/protocol-numbers */ +const uint8_t TcpL4Protocol::PROT_NUMBER = 6; + +ObjectFactory +TcpL4Protocol::GetDefaultRttEstimatorFactory (void) +{ + ObjectFactory factory; + factory.SetTypeId (RttMeanDeviation::GetTypeId ()); + return factory; +} + +TypeId +TcpL4Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::TcpL4Protocol") + .SetParent () + .AddAttribute ("RttEstimatorFactory", + "How RttEstimator objects are created.", + ObjectFactoryValue (GetDefaultRttEstimatorFactory ()), + MakeObjectFactoryAccessor (&TcpL4Protocol::m_rttFactory), + MakeObjectFactoryChecker ()) + ; + return tid; +} + +TcpL4Protocol::TcpL4Protocol () + : m_endPoints (new Ipv4EndPointDemux ()) +{ + NS_LOG_FUNCTION_NOARGS (); + NS_LOG_LOGIC("Made a TcpL4Protocol "< node) +{ + m_node = node; +} + +int +TcpL4Protocol::GetProtocolNumber (void) const +{ + return PROT_NUMBER; +} +int +TcpL4Protocol::GetVersion (void) const +{ + return 2; +} + +void +TcpL4Protocol::DoDispose (void) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_endPoints != 0) + { + delete m_endPoints; + m_endPoints = 0; + } + m_node = 0; + Ipv4L4Protocol::DoDispose (); +} + +Ptr +TcpL4Protocol::CreateSocket (void) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr rtt = m_rttFactory.Create (); + Ptr socket = CreateObject (); + socket->SetNode (m_node); + socket->SetTcp (this); + socket->SetRtt (rtt); + return socket; +} + +Ipv4EndPoint * +TcpL4Protocol::Allocate (void) +{ + NS_LOG_FUNCTION_NOARGS (); + return m_endPoints->Allocate (); +} + +Ipv4EndPoint * +TcpL4Protocol::Allocate (Ipv4Address address) +{ + NS_LOG_FUNCTION (this << address); + return m_endPoints->Allocate (address); +} + +Ipv4EndPoint * +TcpL4Protocol::Allocate (uint16_t port) +{ + NS_LOG_FUNCTION (this << port); + return m_endPoints->Allocate (port); +} + +Ipv4EndPoint * +TcpL4Protocol::Allocate (Ipv4Address address, uint16_t port) +{ + NS_LOG_FUNCTION (this << address << port); + return m_endPoints->Allocate (address, port); +} + +Ipv4EndPoint * +TcpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, + Ipv4Address peerAddress, uint16_t peerPort) +{ + NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); + return m_endPoints->Allocate (localAddress, localPort, + peerAddress, peerPort); +} + +void +TcpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) +{ + NS_LOG_FUNCTION (this << endPoint); + m_endPoints->DeAllocate (endPoint); +} + +void +TcpL4Protocol::Receive (Ptr packet, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface) +{ + NS_LOG_FUNCTION (this << packet << source << destination << incomingInterface); + + TcpHeader tcpHeader; + //these two do a peek, so that the packet can be forwarded up + packet->RemoveHeader (tcpHeader); + NS_LOG_LOGIC("TcpL4Protocol " << this + << " receiving seq " << tcpHeader.GetSequenceNumber() + << " ack " << tcpHeader.GetAckNumber() + << " flags "<< std::hex << (int)tcpHeader.GetFlags() << std::dec + << " data size " << packet->GetSize()); + packet->AddHeader (tcpHeader); + NS_LOG_LOGIC ("TcpL4Protocol "<Lookup (destination, tcpHeader.GetDestinationPort (), + source, tcpHeader.GetSourcePort (),incomingInterface); + if (endPoints.empty ()) + { + NS_LOG_LOGIC (" No endpoints matched on TcpL4Protocol "<ForwardUp (packet, source, tcpHeader.GetSourcePort ()); +} + +void +TcpL4Protocol::Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport) +{ + NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport); + + TcpHeader tcpHeader; + tcpHeader.SetDestinationPort (dport); + tcpHeader.SetSourcePort (sport); + tcpHeader.InitializeChecksum (saddr, + daddr, + PROT_NUMBER); + tcpHeader.SetFlags (TcpHeader::ACK); + tcpHeader.SetAckNumber (0); + + packet->AddHeader (tcpHeader); + + Ptr ipv4 = + m_node->GetObject (); + if (ipv4 != 0) + { + ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + } +} + +void +TcpL4Protocol::SendPacket (Ptr packet, TcpHeader outgoingHeader, + Ipv4Address saddr, Ipv4Address daddr) +{ + NS_LOG_LOGIC("TcpL4Protocol " << this + << " sending seq " << outgoingHeader.GetSequenceNumber() + << " ack " << outgoingHeader.GetAckNumber() + << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec + << " data size " << packet->GetSize()); + NS_LOG_FUNCTION (this << packet << saddr << daddr); + // XXX outgoingHeader cannot be logged + + outgoingHeader.SetLength (5); //header length in units of 32bit words + outgoingHeader.SetChecksum (0); //XXX + outgoingHeader.SetUrgentPointer (0); //XXX + + packet->AddHeader (outgoingHeader); + + Ptr ipv4 = + m_node->GetObject (); + if (ipv4 != 0) + { + ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + } + else + NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface"); +} + +}; // namespace ns3 + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-l4-protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-l4-protocol.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,117 @@ +/* -*- 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 + */ + +#ifndef TCP_L4_PROTOCOL_H +#define TCP_L4_PROTOCOL_H + +#include + +#include "ns3/packet.h" +#include "ns3/ipv4-address.h" +#include "ns3/ptr.h" +#include "ns3/object-factory.h" +#include "ipv4-end-point-demux.h" +#include "ipv4-l4-protocol.h" +#include "ipv4-interface.h" + +#include "tcp-header.h" +#include "tcp-typedefs.h" + +namespace ns3 { + +class Node; +class Socket; +class TcpHeader; +/** + * \brief Implementation of the TCP protocol + */ +class TcpL4Protocol : public Ipv4L4Protocol { +public: + static TypeId GetTypeId (void); + static const uint8_t PROT_NUMBER; + /** + * \brief Constructor + */ + TcpL4Protocol (); + virtual ~TcpL4Protocol (); + + void SetNode (Ptr node); + + virtual int GetProtocolNumber (void) const; + virtual int GetVersion (void) const; + + /** + * \return A smart Socket pointer to a TcpSocketImpl, allocated by this instance + * of the TCP protocol + */ + Ptr CreateSocket (void); + + Ipv4EndPoint *Allocate (void); + Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, + Ipv4Address peerAddress, uint16_t peerPort); + + void DeAllocate (Ipv4EndPoint *endPoint); + +// // called by TcpSocketImpl. +// bool Connect (const Ipv4Address& saddr, const Ipv4Address& daddr, +// uint16_t sport, uint16_t dport); + + /** + * \brief Send a packet via TCP + * \param packet The packet to send + * \param saddr The source Ipv4Address + * \param daddr The destination Ipv4Address + * \param sport The source port number + * \param dport The destination port number + */ + void Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport); + /** + * \brief Recieve a packet up the protocol stack + * \param p The Packet to dump the contents into + * \param source The source's Ipv4Address + * \param destination The destinations Ipv4Address + * \param incomingInterface The Ipv4Interface it was received on + */ + virtual void Receive (Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr incomingInterface); + +protected: + virtual void DoDispose (void); +private: + Ptr m_node; + Ipv4EndPointDemux *m_endPoints; + ObjectFactory m_rttFactory; +private: + friend class TcpSocketImpl; + void SendPacket (Ptr, TcpHeader, + Ipv4Address, Ipv4Address); + static ObjectFactory GetDefaultRttEstimatorFactory (void); +}; + +}; // namespace ns3 + +#endif /* TCP_L4_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-socket-factory-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-socket-factory-impl.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,54 @@ +/* -*- 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 + */ +#include "tcp-socket-factory-impl.h" +#include "tcp-l4-protocol.h" +#include "ns3/socket.h" +#include "ns3/assert.h" + +namespace ns3 { + +TcpSocketFactoryImpl::TcpSocketFactoryImpl () + : m_tcp (0) +{} +TcpSocketFactoryImpl::~TcpSocketFactoryImpl () +{ + NS_ASSERT (m_tcp == 0); +} + +void +TcpSocketFactoryImpl::SetTcp (Ptr tcp) +{ + m_tcp = tcp; +} + +Ptr +TcpSocketFactoryImpl::CreateSocket (void) +{ + return m_tcp->CreateSocket (); +} + +void +TcpSocketFactoryImpl::DoDispose (void) +{ + m_tcp = 0; + TcpSocketFactory::DoDispose (); +} + +} // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-socket-factory-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-socket-factory-impl.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,62 @@ +/* -*- 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 + */ +#ifndef TCP_SOCKET_FACTORY_IMPL_H +#define TCP_SOCKET_FACTORY_IMPL_H + +#include "ns3/tcp-socket-factory.h" +#include "ns3/ptr.h" + +namespace ns3 { + +class TcpL4Protocol; + +/** + * \ingroup internetNode + * \defgroup Tcp Tcp + */ +/** + * \ingroup Tcp + * \section Tcp Overview + * + * The TCP code in ns3::InternetNode is ported from the + * + * Georgia Tech Network Simulator (GTNetS). + * + * Most of the logic is in class ns3::TcpSocketImpl. + */ +class TcpSocketFactoryImpl : public TcpSocketFactory +{ +public: + TcpSocketFactoryImpl (); + virtual ~TcpSocketFactoryImpl (); + + void SetTcp (Ptr tcp); + + virtual Ptr CreateSocket (void); + +protected: + virtual void DoDispose (void); +private: + Ptr m_tcp; +}; + +} // namespace ns3 + +#endif /* TCP_SOCKET_FACTORY_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-socket-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-socket-impl.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,1448 @@ +/* -*- 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 + */ + + +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" +#include "ns3/log.h" +#include "ns3/ipv4.h" +#include "tcp-socket-impl.h" +#include "tcp-l4-protocol.h" +#include "ipv4-end-point.h" +#include "ipv4-l4-demux.h" +#include "ns3/simulation-singleton.h" +#include "tcp-typedefs.h" +#include "ns3/simulator.h" +#include "ns3/packet.h" +#include "ns3/uinteger.h" +#include "ns3/trace-source-accessor.h" + +#include + +NS_LOG_COMPONENT_DEFINE ("TcpSocketImpl"); + +using namespace std; + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (TcpSocketImpl); + +TypeId +TcpSocketImpl::GetTypeId () +{ + static TypeId tid = TypeId("ns3::TcpSocketImpl") + .SetParent () + .AddTraceSource ("CongestionWindow", + "The TCP connection's congestion window", + MakeTraceSourceAccessor (&TcpSocketImpl::m_cWnd)) + ; + return tid; +} + + TcpSocketImpl::TcpSocketImpl () + : m_skipRetxResched (false), + m_dupAckCount (0), + m_delAckCount (0), + m_endPoint (0), + m_node (0), + m_tcp (0), + m_errno (ERROR_NOTERROR), + m_shutdownSend (false), + m_shutdownRecv (false), + m_connected (false), + m_state (CLOSED), + m_closeNotified (false), + m_closeRequestNotified (false), + m_closeOnEmpty (false), + m_pendingClose (false), + m_nextTxSequence (0), + m_highTxMark (0), + m_highestRxAck (0), + m_lastRxAck (0), + m_nextRxSequence (0), + m_pendingData (0), + m_rtt (0), + m_lastMeasuredRtt (Seconds(0.0)), + m_rxAvailable (0), + m_wouldBlock (false) +{ + NS_LOG_FUNCTION (this); +} + +TcpSocketImpl::TcpSocketImpl(const TcpSocketImpl& sock) + : TcpSocket(sock), //copy the base class callbacks + m_skipRetxResched (sock.m_skipRetxResched), + m_dupAckCount (sock.m_dupAckCount), + m_delAckCount (0), + m_delAckMaxCount (sock.m_delAckMaxCount), + m_delAckTimeout (sock.m_delAckTimeout), + m_endPoint (0), + m_node (sock.m_node), + m_tcp (sock.m_tcp), + m_remoteAddress (sock.m_remoteAddress), + m_remotePort (sock.m_remotePort), + m_localAddress (sock.m_localAddress), + m_localPort (sock.m_localPort), + m_errno (sock.m_errno), + m_shutdownSend (sock.m_shutdownSend), + m_shutdownRecv (sock.m_shutdownRecv), + m_connected (sock.m_connected), + m_state (sock.m_state), + m_closeNotified (sock.m_closeNotified), + m_closeRequestNotified (sock.m_closeRequestNotified), + m_closeOnEmpty (sock.m_closeOnEmpty), + m_pendingClose (sock.m_pendingClose), + m_nextTxSequence (sock.m_nextTxSequence), + m_highTxMark (sock.m_highTxMark), + m_highestRxAck (sock.m_highestRxAck), + m_lastRxAck (sock.m_lastRxAck), + m_nextRxSequence (sock.m_nextRxSequence), + m_pendingData (0), + m_segmentSize (sock.m_segmentSize), + m_rxWindowSize (sock.m_rxWindowSize), + m_advertisedWindowSize (sock.m_advertisedWindowSize), + m_cWnd (sock.m_cWnd), + m_ssThresh (sock.m_ssThresh), + m_initialCWnd (sock.m_initialCWnd), + m_rtt (0), + m_lastMeasuredRtt (Seconds(0.0)), + m_cnTimeout (sock.m_cnTimeout), + m_cnCount (sock.m_cnCount), + m_rxAvailable (0), + m_wouldBlock (false), + m_sndBufSize (sock.m_sndBufSize), + m_rcvBufSize(sock.m_rcvBufSize) +{ + NS_LOG_FUNCTION_NOARGS (); + NS_LOG_LOGIC("Invoked the copy constructor"); + //copy the pending data if necessary + if(sock.m_pendingData) + { + m_pendingData = sock.m_pendingData->Copy(); + } + //copy the rtt if necessary + if (sock.m_rtt) + { + m_rtt = sock.m_rtt->Copy(); + } + //can't "copy" the endpoint just yes, must do this when we know the peer info + //too; this is in SYN_ACK_TX +} + +TcpSocketImpl::~TcpSocketImpl () +{ + NS_LOG_FUNCTION(this); + m_node = 0; + if (m_endPoint != 0) + { + NS_ASSERT (m_tcp != 0); + /** + * Note that this piece of code is a bit tricky: + * when DeAllocate is called, it will call into + * Ipv4EndPointDemux::Deallocate which triggers + * a delete of the associated endPoint which triggers + * in turn a call to the method ::Destroy below + * will will zero the m_endPoint field. + */ + NS_ASSERT (m_endPoint != 0); + m_tcp->DeAllocate (m_endPoint); + NS_ASSERT (m_endPoint == 0); + } + m_tcp = 0; + delete m_pendingData; //prevents leak + m_pendingData = 0; +} + +void +TcpSocketImpl::SetNode (Ptr node) +{ + m_node = node; + // Initialize some variables + m_cWnd = m_initialCWnd * m_segmentSize; + m_rxWindowSize = m_advertisedWindowSize; +} + +void +TcpSocketImpl::SetTcp (Ptr tcp) +{ + m_tcp = tcp; +} +void +TcpSocketImpl::SetRtt (Ptr rtt) +{ + m_rtt = rtt; +} + + +enum Socket::SocketErrno +TcpSocketImpl::GetErrno (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_errno; +} + +Ptr +TcpSocketImpl::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + +void +TcpSocketImpl::Destroy (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = 0; + m_endPoint = 0; + m_tcp = 0; + m_retxEvent.Cancel (); +} +int +TcpSocketImpl::FinishBind (void) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_endPoint == 0) + { + return -1; + } + m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); + m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); + m_localAddress = m_endPoint->GetLocalAddress (); + m_localPort = m_endPoint->GetLocalPort (); + return 0; +} + +int +TcpSocketImpl::Bind (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_endPoint = m_tcp->Allocate (); + return FinishBind (); +} +int +TcpSocketImpl::Bind (const Address &address) +{ + NS_LOG_FUNCTION (this<Allocate (); + NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (port); + NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (ipv4); + NS_LOG_LOGIC ("TcpSocketImpl "<Allocate (ipv4, port); + NS_LOG_LOGIC ("TcpSocketImpl "<Size() != 0) + { // App close with pending data must wait until all data transmitted + m_closeOnEmpty = true; + NS_LOG_LOGIC("Socket " << this << + " deferring close, state " << m_state); + return 0; + } + + Actions_t action = ProcessEvent (APP_CLOSE); + ProcessAction (action); + ShutdownSend (); + return 0; +} + +int +TcpSocketImpl::Connect (const Address & address) +{ + NS_LOG_FUNCTION (this << address); + if (m_endPoint == 0) + { + if (Bind () == -1) + { + NS_ASSERT (m_endPoint == 0); + return -1; + } + NS_ASSERT (m_endPoint != 0); + } + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + m_remoteAddress = transport.GetIpv4 (); + m_remotePort = transport.GetPort (); + + uint32_t localIfIndex; + Ptr ipv4 = m_node->GetObject (); + + if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) + { + m_endPoint->SetLocalAddress (ipv4->GetAddress (localIfIndex)); + } + else + { + m_errno = ERROR_NOROUTETOHOST; + return -1; + } + + Actions_t action = ProcessEvent (APP_CONNECT); + bool success = ProcessAction (action); + if (success) + { + return 0; + } + return -1; +} +int +TcpSocketImpl::Send (const Ptr p) //p here is just data, no headers +{ + NS_LOG_FUNCTION (this << p); + if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT) + { + if (p->GetSize() > GetTxAvailable ()) + { + m_wouldBlock = true; + m_errno = ERROR_MSGSIZE; + return -1; + } + if (!m_pendingData) + { + m_pendingData = new PendingData (); // Create if non-existent + m_firstPendingSequence = m_nextTxSequence; // Note seq of first + } + //PendingData::Add stores a copy of the Ptr p + m_pendingData->Add (p); + NS_LOG_DEBUG("TcpSock::Send, pdsize " << m_pendingData->Size() << + " state " << m_state); + Actions_t action = ProcessEvent (APP_SEND); + NS_LOG_DEBUG(" action " << action); + if (!ProcessAction (action)) + { + return -1; // Failed, return zero + } + return p->GetSize(); + } + else + { + m_errno = ERROR_NOTCONN; + return -1; + } +} + +int TcpSocketImpl::Send (const uint8_t* buf, uint32_t size) +{ + return Send (Create (buf, size)); +} + +int TcpSocketImpl::DoSendTo (Ptr p, const Address &address) +{ + NS_LOG_FUNCTION (this << p << address); + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + Ipv4Address ipv4 = transport.GetIpv4 (); + uint16_t port = transport.GetPort (); + return DoSendTo (p, ipv4, port); +} + +int TcpSocketImpl::DoSendTo (Ptr p, Ipv4Address ipv4, uint16_t port) +{ + NS_LOG_FUNCTION (this << p << ipv4 << port); + if (m_endPoint == 0) + { + if (Bind () == -1) + { + NS_ASSERT (m_endPoint == 0); + return -1; + } + NS_ASSERT (m_endPoint != 0); + } + if (m_shutdownSend) + { + m_errno = ERROR_SHUTDOWN; + return -1; + } + m_tcp->Send (p, m_endPoint->GetLocalAddress (), ipv4, + m_endPoint->GetLocalPort (), port); + NotifyDataSent (p->GetSize ()); + return 0; +} + +int +TcpSocketImpl::SendTo (Ptr p, const Address &address) +{ + NS_LOG_FUNCTION (this << address << p); + if (!m_connected) + { + m_errno = ERROR_NOTCONN; + return -1; + } + else + { + return Send (p); //drop the address according to BSD manpages + } +} + +uint32_t +TcpSocketImpl::GetTxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_pendingData != 0) + { + uint32_t unAckedDataSize = + m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck); + NS_ASSERT (m_sndBufSize >= unAckedDataSize); //else a logical error + return m_sndBufSize-unAckedDataSize; + } + else + { + return m_sndBufSize; + } +} + +int +TcpSocketImpl::Listen (uint32_t q) +{ + NS_LOG_FUNCTION (this << q); + Actions_t action = ProcessEvent (APP_LISTEN); + ProcessAction (action); + return 0; +} + +Ptr +TcpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) +{ + NS_LOG_FUNCTION_NOARGS (); + if(m_bufferedData.empty()) + { + return 0; + } + UnAckData_t out; //serves as buffer to return up to the user + UnAckData_t::iterator i; + while (!m_bufferedData.empty ()) + { // Check the buffered data for delivery + NS_LOG_LOGIC("TCP " << this << " bufferedData.size() " + << m_bufferedData.size () + << " time " << Simulator::Now ()); + i = m_bufferedData.begin (); + SequenceNumber s1 = 0; + if (i->first > m_nextRxSequence) + { + break; // we're done, no more in-sequence data exits + } + else // (i->first <= m_nextRxSequence) + { // Two cases here. + // 1) seq + length > nextRxSeq, can deliver partial + // 2) seq + length <= nextRxSeq, deliver whole + s1 = i->second->GetSize (); + if (i->first + s1 > m_nextRxSequence) + { // Remove partial data to prepare for delivery + uint32_t avail = s1 + i->first - m_nextRxSequence; + i->second = i->second->CreateFragment (0, avail); + } + // else this packet is okay to deliver whole + // so don't do anything else and output it + out[i->first] = i->second; + } + m_rxAvailable -= i->second->GetSize (); + m_bufferedData.erase (i); // Remove from list + } + if (out.size() == 0) + { + return 0; + } + Ptr outPacket = Create(); + for(i = out.begin(); i!=out.end(); ++i) + { + if (outPacket->GetSize() + i->second->GetSize() <= maxSize ) + { + outPacket->AddAtEnd(i->second); + } + else + { + //only append as much as will fit + uint32_t avail = maxSize - outPacket->GetSize(); + outPacket->AddAtEnd(i->second->CreateFragment(0,avail)); + //put the rest back into the buffer + m_bufferedData[i->first+SequenceNumber(avail)] + = i->second->CreateFragment(avail,i->second->GetSize()-avail); + m_rxAvailable += i->second->GetSize()-avail; + } + } + return outPacket; +} + +uint32_t +TcpSocketImpl::GetRxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + // We separately maintain this state to avoid walking the queue + // every time this might be called + return m_rxAvailable; +} + +void +TcpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) +{ + NS_LOG_DEBUG("Socket " << this << " got forward up" << + " dport " << m_endPoint->GetLocalPort() << + " daddr " << m_endPoint->GetLocalAddress() << + " sport " << m_endPoint->GetPeerPort() << + " saddr " << m_endPoint->GetPeerAddress()); + + NS_LOG_FUNCTION (this << packet << ipv4 << port); + if (m_shutdownRecv) + { + return; + } + TcpHeader tcpHeader; + packet->RemoveHeader (tcpHeader); + + if (tcpHeader.GetFlags () & TcpHeader::ACK) + { + Time m = m_rtt->AckSeq (tcpHeader.GetAckNumber () ); + if (m != Seconds (0.0)) + { + m_lastMeasuredRtt = m; + } + } + + Events_t event = SimulationSingleton::Get ()->FlagsEvent (tcpHeader.GetFlags () ); + Actions_t action = ProcessEvent (event); //updates the state + Address address = InetSocketAddress (ipv4, port); + NS_LOG_DEBUG("Socket " << this << + " processing pkt action, " << action << + " current state " << m_state); + ProcessPacketAction (action, packet, tcpHeader, address); +} + +Actions_t TcpSocketImpl::ProcessEvent (Events_t e) +{ + NS_LOG_FUNCTION (this << e); + States_t saveState = m_state; + NS_LOG_LOGIC ("TcpSocketImpl " << this << " processing event " << e); + // simulation singleton is a way to get a single global static instance of a + // class intended to be a singleton; see simulation-singleton.h + SA stateAction = SimulationSingleton::Get ()->Lookup (m_state,e); + // debug + if (stateAction.action == RST_TX) + { + NS_LOG_LOGIC ("TcpSocketImpl " << this << " sending RST from state " + << saveState << " event " << e); + } + bool needCloseNotify = (stateAction.state == CLOSED && m_state != CLOSED + && e != TIMEOUT); + m_state = stateAction.state; + NS_LOG_LOGIC ("TcpSocketImpl " << this << " moved from state " << saveState + << " to state " <SetPeer (m_remoteAddress, m_remotePort); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); + } + + if (needCloseNotify && !m_closeNotified) + { + NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from " + << m_state << " event " << e << " closeNot " << m_closeNotified + << " action " << stateAction.action); + NotifyCloseCompleted (); + m_closeNotified = true; + NS_LOG_LOGIC ("TcpSocketImpl " << this << " calling Closed from PE" + << " origState " << saveState + << " event " << e); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " transition to CLOSED from " + << m_state << " event " << e + << " set CloseNotif "); + } + return stateAction.action; +} + +void TcpSocketImpl::SendEmptyPacket (uint8_t flags) +{ + NS_LOG_FUNCTION (this << flags); + Ptr p = Create (); + TcpHeader header; + + header.SetFlags (flags); + header.SetSequenceNumber (m_nextTxSequence); + header.SetAckNumber (m_nextRxSequence); + header.SetSourcePort (m_endPoint->GetLocalPort ()); + header.SetDestinationPort (m_remotePort); + header.SetWindowSize (m_advertisedWindowSize); + m_tcp->SendPacket (p, header, m_endPoint->GetLocalAddress (), + m_remoteAddress); + Time rto = m_rtt->RetransmitTimeout (); + if (flags & TcpHeader::SYN) + { + rto = m_cnTimeout; + m_cnTimeout = m_cnTimeout + m_cnTimeout; + m_cnCount--; + } + if (m_retxEvent.IsExpired () ) //no outstanding timer + { + NS_LOG_LOGIC ("Schedule retransmission timeout at time " + << Simulator::Now ().GetSeconds () << " to expire at time " + << (Simulator::Now () + rto).GetSeconds ()); + m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this); + } +} + +bool TcpSocketImpl::ProcessAction (Actions_t a) +{ // These actions do not require a packet or any TCP Headers + NS_LOG_FUNCTION (this << a); + switch (a) + { + case NO_ACT: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action: NO_ACT"); + break; + case ACK_TX: + SendEmptyPacket (TcpHeader::ACK); + break; + case ACK_TX_1: + NS_ASSERT (false); // This should be processed in ProcessPacketAction + break; + case RST_TX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RST_TX"); + SendEmptyPacket (TcpHeader::RST); + break; + case SYN_TX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_TX"); + // TCP SYN Flag consumes one byte + // is the above correct? we're SENDING a syn, not acking back -- Raj + // commented out for now + // m_nextTxSequence+= 1; + SendEmptyPacket (TcpHeader::SYN); + break; + case SYN_ACK_TX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX"); + // TCP SYN Flag consumes one byte + ++m_nextRxSequence; + SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); + break; + case FIN_TX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_TX"); + SendEmptyPacket (TcpHeader::FIN); + break; + case FIN_ACK_TX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action FIN_ACK_TX"); + SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK); + break; + case NEW_ACK: + NS_ASSERT (false); // This should be processed in ProcessPacketAction + break; + case NEW_SEQ_RX: + NS_ASSERT (false); // This should be processed in ProcessPacketAction + break; + case RETX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action RETX"); + break; + case TX_DATA: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action TX_DATA"); + SendPendingData (); + break; + case PEER_CLOSE: + NS_ASSERT (false); // This should be processed in ProcessPacketAction + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action PEER_CLOSE"); + break; + case APP_CLOSED: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_CLOSED"); + break; + case CANCEL_TM: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action CANCEL_TM"); + break; + case APP_NOTIFY: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action APP_NOTIFY"); + break; + case SERV_NOTIFY: + NS_ASSERT (false); // This should be processed in ProcessPacketAction + break; + case LAST_ACTION: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action LAST_ACTION"); + break; + } + return true; +} + +bool TcpSocketImpl::ProcessPacketAction (Actions_t a, Ptr p, + const TcpHeader& tcpHeader, + const Address& fromAddress) +{ + NS_LOG_FUNCTION (this << a << p << fromAddress); + uint32_t localIfIndex; + Ptr ipv4 = m_node->GetObject (); + switch (a) + { + 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->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) +// { +// m_localAddress = ipv4->GetAddress (localIfIndex); +// } + 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); + //notify the server that we got a SYN + // If server refuses connection do nothing + if (!NotifyConnectionRequest(fromAddress)) return true; + // Clone the socket + Ptr newSock = Copy (); + NS_LOG_LOGIC ("Cloned a TcpSocketImpl " << newSock); + //this listening socket should do nothing more + Simulator::ScheduleNow (&TcpSocketImpl::CompleteFork, newSock, + p, tcpHeader,fromAddress); + return true; + } + // This is the cloned endpoint + m_endPoint->SetPeer (m_remoteAddress, m_remotePort); + if (ipv4->GetIfIndexForDestination (m_remoteAddress, localIfIndex)) + { + m_localAddress = ipv4->GetAddress (localIfIndex); + 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); + break; + case ACK_TX_1: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1"); + // TCP SYN consumes one byte + m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1); + m_nextTxSequence = tcpHeader.GetAckNumber (); + m_firstPendingSequence = m_nextTxSequence; //bug 166 + NS_LOG_DEBUG ("TcpSocketImpl " << this << " ACK_TX_1" << + " nextRxSeq " << m_nextRxSequence); + SendEmptyPacket (TcpHeader::ACK); + m_rxWindowSize = tcpHeader.GetWindowSize (); + if (tcpHeader.GetAckNumber () > m_highestRxAck) + { + m_highestRxAck = tcpHeader.GetAckNumber (); + // Data freed from the send buffer; notify any blocked sender + if (m_wouldBlock) + { + NotifySend (GetTxAvailable ()); + m_wouldBlock = false; + } + } + SendPendingData (); + break; + case NEW_ACK: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_ACK_TX"); + if (tcpHeader.GetAckNumber () < m_highestRxAck) //old ack, do nothing + { + break; + } + if (tcpHeader.GetAckNumber () == m_highestRxAck && + tcpHeader.GetAckNumber () < m_nextTxSequence) + { + DupAck (tcpHeader, ++m_dupAckCount); + break; + } + if (tcpHeader.GetAckNumber () > m_highestRxAck) + { + m_dupAckCount = 0; + } + NewAck (tcpHeader.GetAckNumber ()); + break; + case NEW_SEQ_RX: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action NEW_SEQ_RX"); + NewRx (p, tcpHeader, fromAddress); // Process new data received + break; + case PEER_CLOSE: + { + // First we have to be sure the FIN packet was not received + // out of sequence. If so, note pending close and process + // new sequence rx + if (tcpHeader.GetSequenceNumber () != m_nextRxSequence) + { // process close later + m_pendingClose = true; + NS_LOG_LOGIC ("TcpSocketImpl " << this << " setting pendingClose" + << " rxseq " << tcpHeader.GetSequenceNumber () + << " nextRxSeq " << m_nextRxSequence); + NewRx (p, tcpHeader, fromAddress); + return true; + } + // Now we need to see if any data came with the FIN + // if so, call NewRx + if (p->GetSize () != 0) + { + NewRx (p, tcpHeader, fromAddress); + } + States_t saveState = m_state; // Used to see if app responds + NS_LOG_LOGIC ("TcpSocketImpl " << this + << " peer close, state " << m_state); + if (!m_closeRequestNotified) + { + NS_LOG_LOGIC ("TCP " << this + << " calling AppCloseRequest"); + NotifyCloseRequested(); + m_closeRequestNotified = true; + } + NS_LOG_LOGIC ("TcpSocketImpl " << this + << " peer close, state after " << m_state); + if (m_state == saveState) + { // Need to ack, the application will close later + SendEmptyPacket (TcpHeader::ACK); +// // Also need to re-tx the ack if we + } + if (m_state == LAST_ACK) + { + NS_LOG_LOGIC ("TcpSocketImpl " << this << " scheduling LATO1"); + m_lastAckEvent = Simulator::Schedule (m_rtt->RetransmitTimeout (), + &TcpSocketImpl::LastAckTimeout,this); + } + break; + } + case SERV_NOTIFY: + NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SERV_NOTIFY"); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " Connected!"); + NotifyNewConnectionCreated (this, fromAddress); + m_connected = true; // ! This is bogus; fix when we clone the tcp + m_endPoint->SetPeer (m_remoteAddress, m_remotePort); + //treat the connection orientation final ack as a newack + CommonNewAck (tcpHeader.GetAckNumber (), true); + break; + default: + break; + } + return true; +} + +void TcpSocketImpl::CompleteFork(Ptr p, const TcpHeader& h, const Address& fromAddress) +{ + // Get port and address from peer (connecting host) + m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort (); + m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (); + m_endPoint = m_tcp->Allocate (m_localAddress, + m_localPort, + m_remoteAddress, + m_remotePort); + //the cloned socket with be in listen state, so manually change state + m_state = SYN_RCVD; + //equivalent to FinishBind + m_endPoint->SetRxCallback (MakeCallback (&TcpSocketImpl::ForwardUp, Ptr(this))); + m_endPoint->SetDestroyCallback (MakeCallback (&TcpSocketImpl::Destroy, Ptr(this))); + ProcessPacketAction(SYN_ACK_TX, p, h, fromAddress); + } + +void TcpSocketImpl::ConnectionSucceeded() +{ // We would preferred to have scheduled an event directly to + // NotifyConnectionSucceeded, but (sigh) these are protected + // and we can get the address of it :( + NotifyConnectionSucceeded(); +} + +bool TcpSocketImpl::SendPendingData (bool withAck) +{ + NS_LOG_FUNCTION (this << withAck); + NS_LOG_LOGIC ("ENTERING SendPendingData"); + if (!m_pendingData) + { + return false; // No data exists + } + uint32_t nPacketsSent = 0; + while (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence)) + { + uint32_t w = AvailableWindow ();// Get available window size + NS_LOG_LOGIC ("TcpSocketImpl " << this << " SendPendingData" + << " w " << w + << " rxwin " << m_rxWindowSize + << " cWnd " << m_cWnd + << " segsize " << m_segmentSize + << " nextTxSeq " << m_nextTxSequence + << " highestRxAck " << m_highestRxAck + << " pd->Size " << m_pendingData->Size () + << " pd->SFS " << m_pendingData->SizeFromSeq (m_firstPendingSequence, m_nextTxSequence)); + + if (w < m_segmentSize && m_pendingData->Size () > w) + { + break; // No more + } + uint32_t s = std::min (w, m_segmentSize); // Send no more than window + Ptr p = m_pendingData->CopyFromSeq (s, m_firstPendingSequence, + m_nextTxSequence); + NS_LOG_LOGIC("TcpSocketImpl " << this << " SendPendingData" + << " txseq " << m_nextTxSequence + << " s " << s + << " datasize " << p->GetSize() ); + uint8_t flags = 0; + if (withAck) + { + flags |= TcpHeader::ACK; + } + uint32_t sz = p->GetSize (); // Size of packet + uint32_t remainingData = m_pendingData->SizeFromSeq( + m_firstPendingSequence, + m_nextTxSequence + SequenceNumber (sz)); + if (m_closeOnEmpty && (remainingData == 0)) + { + flags = TcpHeader::FIN; + m_state = FIN_WAIT_1; + } + + TcpHeader header; + header.SetFlags (flags); + header.SetSequenceNumber (m_nextTxSequence); + header.SetAckNumber (m_nextRxSequence); + header.SetSourcePort (m_endPoint->GetLocalPort()); + header.SetDestinationPort (m_remotePort); + if (m_shutdownSend) + { + m_errno = ERROR_SHUTDOWN; + return -1; + } + + + if (m_retxEvent.IsExpired () ) //go ahead and schedule the retransmit + { + Time rto = m_rtt->RetransmitTimeout (); + NS_LOG_LOGIC ("SendPendingData Schedule retransmission timeout at time " << + Simulator::Now ().GetSeconds () << " to expire at time " << + (Simulator::Now () + rto).GetSeconds () ); + m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this); + } + NS_LOG_LOGIC ("About to send a packet with flags: " << flags); + m_tcp->SendPacket (p, header, + m_endPoint->GetLocalAddress (), + m_remoteAddress); + m_rtt->SentSeq(m_nextTxSequence, sz); // notify the RTT + // Notify the application + Simulator::ScheduleNow(&TcpSocketImpl::NotifyDataSent, this, p->GetSize ()); + nPacketsSent++; // Count sent this loop + m_nextTxSequence += sz; // Advance next tx sequence + // Note the high water mark + m_highTxMark = std::max (m_nextTxSequence, m_highTxMark); + } + NS_LOG_LOGIC ("SendPendingData Sent "<0); +} + +uint32_t TcpSocketImpl::UnAckDataCount () +{ + NS_LOG_FUNCTION_NOARGS (); + return m_nextTxSequence - m_highestRxAck; +} + +uint32_t TcpSocketImpl::BytesInFlight () +{ + NS_LOG_FUNCTION_NOARGS (); + return m_highTxMark - m_highestRxAck; +} + +uint32_t TcpSocketImpl::Window () +{ + NS_LOG_FUNCTION_NOARGS (); + NS_LOG_LOGIC ("TcpSocketImpl::Window() "< p, + const TcpHeader& tcpHeader, + const Address& fromAddress) +{ + NS_LOG_FUNCTION (this << p << "tcpHeader " << fromAddress); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewRx," + << " seq " << tcpHeader.GetSequenceNumber() + << " ack " << tcpHeader.GetAckNumber() + << " p.size is " << p->GetSize () ); + NS_LOG_DEBUG ("TcpSocketImpl " << this << + " NewRx," << + " seq " << tcpHeader.GetSequenceNumber() << + " ack " << tcpHeader.GetAckNumber() << + " p.size is " << p->GetSize()); + States_t origState = m_state; + uint32_t s = p->GetSize (); // Size of associated data + if (s == 0) + {// Nothing to do if no associated data + return; + } + // Log sequence received if enabled + // NoteTimeSeq(LOG_SEQ_RX, h->sequenceNumber); + // Three possibilities + // 1) Received seq is expected, buffer this, update rxAvailable, and ack + // 2) Received seq is < expected, just re-ack previous + // 3) Received seq is > expected, just re-ack previous and buffer data + if (tcpHeader.GetSequenceNumber () == m_nextRxSequence) + { // If seq is expected seq + // 1) Update nextRxSeq + // 2) Buffer this packet so Recv can read it + // 3) Send the ack + m_nextRxSequence += s; // Advance next expected sequence + //bytesReceived += s; // Statistics + NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence ); + SocketRxAddressTag tag; + tag.SetAddress (fromAddress); + p->AddTag (tag); + //buffer this, it'll be read by call to Recv + UnAckData_t::iterator i = + m_bufferedData.find (tcpHeader.GetSequenceNumber () ); + if (i != m_bufferedData.end () ) //we found it already in the buffer + { + i->second = 0; // relase reference to already buffered + } + // Save for later delivery + m_bufferedData[tcpHeader.GetSequenceNumber () ] = p; + m_rxAvailable += p->GetSize (); + //putting this into the buffer might have filled in a sequence gap + //so we have to iterate through the list to find the largest contiguous + //sequenced chunk, and update m_rxAvailable appropriately + i = m_bufferedData.find (tcpHeader.GetSequenceNumber () ); + UnAckData_t::iterator next = i; + next++; + while(next != m_bufferedData.end()) + { + if(i->first + SequenceNumber(i->second->GetSize ()) == next->first) + { + //next packet is in sequence, count it + m_rxAvailable += next->second->GetSize(); + m_nextRxSequence += next->second->GetSize(); + } + else + { + break; //no more in this contiguous chunk + } + ++i; + ++next; + } + NotifyDataRecv (); + if (m_closeNotified) + { + NS_LOG_LOGIC ("Tcp " << this << " HuH? Got data after closeNotif"); + } + NS_LOG_LOGIC ("TcpSocketImpl " << this << " adv rxseq by " << s); + if (m_pendingClose || (origState > ESTABLISHED)) + { // See if we can close now + if (m_bufferedData.empty()) + { + ProcessPacketAction (PEER_CLOSE, p, tcpHeader, fromAddress); + } + } + } + else if (SequenceNumber (tcpHeader.GetSequenceNumber ()) >= m_nextRxSequence) + { // Need to buffer this one + NS_LOG_LOGIC ("Case 2, buffering " << tcpHeader.GetSequenceNumber () ); + UnAckData_t::iterator i = + m_bufferedData.find (tcpHeader.GetSequenceNumber () ); + if (i != m_bufferedData.end () ) + { + i->second = 0; // relase reference to already buffered + } + // Save for later delivery + SocketRxAddressTag tag; + tag.SetAddress (fromAddress); + p->AddTag (tag); + m_bufferedData[tcpHeader.GetSequenceNumber () ] = p; + } + else + { // debug + NS_LOG_LOGIC("TCP " << this + << " got seq " << tcpHeader.GetSequenceNumber () + << " expected " << m_nextRxSequence + << " flags " << tcpHeader.GetFlags ()); + } + // Now send a new ack packet acknowledging all received and delivered data + if(++m_delAckCount >= m_delAckMaxCount) + { + m_delAckEvent.Cancel(); + m_delAckCount = 0; + SendEmptyPacket (TcpHeader::ACK); + } + else + { + m_delAckEvent = Simulator::Schedule (m_delAckTimeout, &TcpSocketImpl::DelAckTimeout, this); + } +} + +void TcpSocketImpl::DelAckTimeout () +{ + m_delAckCount = 0; + SendEmptyPacket (TcpHeader::ACK); +} + +void TcpSocketImpl::CommonNewAck (SequenceNumber ack, bool skipTimer) +{ // CommonNewAck is called only for "New" (non-duplicate) acks + // and MUST be called by any subclass, from the NewAck function + // Always cancel any pending re-tx timer on new acknowledgement + NS_LOG_FUNCTION (this << ack << skipTimer); + //DEBUG(1,(cout << "TCP " << this << "Cancelling retx timer " << endl)); + if (!skipTimer) + { + m_retxEvent.Cancel (); + //On recieving a "New" ack we restart retransmission timer .. RFC 2988 + Time rto = m_rtt->RetransmitTimeout (); + NS_LOG_LOGIC ("Schedule retransmission timeout at time " + << Simulator::Now ().GetSeconds () << " to expire at time " + << (Simulator::Now () + rto).GetSeconds ()); + m_retxEvent = Simulator::Schedule (rto, &TcpSocketImpl::ReTxTimeout, this); + } + NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack + << " numberAck " << (ack - m_highestRxAck)); // Number bytes ack'ed + m_highestRxAck = ack; // Note the highest recieved Ack + if (m_wouldBlock) + { + // m_highestRxAck advancing means some data was acked, and the size + // of free space in the buffer has increased + NotifySend (GetTxAvailable ()); + m_wouldBlock = false; + } + if (ack > m_nextTxSequence) + { + m_nextTxSequence = ack; // If advanced + } + // See if all pending ack'ed; if so we can delete the data + if (m_pendingData) + { // Data exists, see if can be deleted + if (m_pendingData->SizeFromSeq (m_firstPendingSequence, m_highestRxAck) == 0) + { // All pending acked, can be deleted + m_pendingData->Clear (); + delete m_pendingData; + m_pendingData = 0; + // Insure no re-tx timer + m_retxEvent.Cancel (); + } + } + // Try to send more data + SendPendingData(); +} + +Ptr TcpSocketImpl::Copy () +{ + return CopyObject (this); +} + +void TcpSocketImpl::NewAck (SequenceNumber seq) +{ // New acknowledgement up to sequence number "seq" + // Adjust congestion window in response to new ack's received + NS_LOG_FUNCTION (this << seq); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewAck " + << " seq " << seq + << " cWnd " << m_cWnd + << " ssThresh " << m_ssThresh); + if (m_cWnd < m_ssThresh) + { // Slow start mode, add one segSize to cWnd + m_cWnd += m_segmentSize; + NS_LOG_LOGIC ("TcpSocketImpl " << this << " NewCWnd SlowStart, cWnd " << m_cWnd + << " sst " << m_ssThresh); + } + else + { // Congestion avoidance mode, adjust by (ackBytes*segSize) / cWnd + double adder = ((double) m_segmentSize * m_segmentSize) / m_cWnd.Get(); + if (adder < 1.0) + { + adder = 1.0; + } + m_cWnd += (uint32_t) adder; + NS_LOG_LOGIC ("NewCWnd CongAvoid, cWnd " << m_cWnd + << " sst " << m_ssThresh); + } + CommonNewAck (seq, false); // Complete newAck processing +} + +void TcpSocketImpl::DupAck (const TcpHeader& t, uint32_t count) +{ + NS_LOG_FUNCTION (this << "t " << count); + NS_LOG_LOGIC ("TcpSocketImpl " << this << " DupAck " << t.GetAckNumber () + << ", count " << count + << ", time " << Simulator::Now ()); + if (count == 3) + { // Count of three indicates triple duplicate ack + m_ssThresh = Window () / 2; // Per RFC2581 + m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize); + NS_LOG_LOGIC("TcpSocketImpl " << this << "Tahoe TDA, time " << Simulator::Now () + << " seq " << t.GetAckNumber () + << " in flight " << BytesInFlight () + << " new ssthresh " << m_ssThresh); + + m_cWnd = m_segmentSize; // Collapse cwnd (re-enter slowstart) + // For Tahoe, we also reset nextTxSeq + m_nextTxSequence = m_highestRxAck; + SendPendingData (); + } +} + +void TcpSocketImpl::ReTxTimeout () +{ // Retransmit timeout + NS_LOG_FUNCTION (this); + m_ssThresh = Window () / 2; // Per RFC2581 + m_ssThresh = std::max (m_ssThresh, 2 * m_segmentSize); + // Set cWnd to segSize on timeout, per rfc2581 + // Collapse congestion window (re-enter slowstart) + m_cWnd = m_segmentSize; + m_nextTxSequence = m_highestRxAck; // Start from highest Ack + m_rtt->IncreaseMultiplier (); // DoubleValue timeout value for next retx timer + Retransmit (); // Retransmit the packet +} + +void TcpSocketImpl::LastAckTimeout () +{ + m_lastAckEvent.Cancel (); + if (m_state == LAST_ACK) + { + Actions_t action = ProcessEvent (TIMEOUT); + ProcessAction (action); + } + if (!m_closeNotified) + { + m_closeNotified = true; + } +} + +void TcpSocketImpl::Retransmit () +{ + NS_LOG_FUNCTION (this); + uint8_t flags = TcpHeader::NONE; + if (m_state == SYN_SENT) + { + if (m_cnCount > 0) + { + SendEmptyPacket (TcpHeader::SYN); + return; + } + else + { + NotifyConnectionFailed (); + return; + } + } + if (!m_pendingData) + { + if (m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) + { // Must have lost FIN, re-send + SendEmptyPacket (TcpHeader::FIN); + } + return; + } + Ptr p = m_pendingData->CopyFromSeq (m_segmentSize, + m_firstPendingSequence, + m_highestRxAck); + // Calculate remaining data for COE check + uint32_t remainingData = m_pendingData->SizeFromSeq ( + m_firstPendingSequence, + m_nextTxSequence + SequenceNumber(p->GetSize ())); + if (m_closeOnEmpty && remainingData == 0) + { // Add the FIN flag + flags = flags | TcpHeader::FIN; + } + + NS_LOG_LOGIC ("TcpSocketImpl " << this << " retxing seq " << m_highestRxAck); + if (m_retxEvent.IsExpired () ) + { + Time rto = m_rtt->RetransmitTimeout (); + NS_LOG_LOGIC ("Schedule retransmission timeout at time " + << Simulator::Now ().GetSeconds () << " to expire at time " + << (Simulator::Now () + rto).GetSeconds ()); + m_retxEvent = Simulator::Schedule (rto,&TcpSocketImpl::ReTxTimeout,this); + } + m_rtt->SentSeq (m_highestRxAck,p->GetSize ()); + // And send the packet + TcpHeader tcpHeader; + tcpHeader.SetSequenceNumber (m_nextTxSequence); + tcpHeader.SetAckNumber (m_nextRxSequence); + tcpHeader.SetSourcePort (m_endPoint->GetLocalPort()); + tcpHeader.SetDestinationPort (m_remotePort); + tcpHeader.SetFlags (flags); + tcpHeader.SetWindowSize (m_advertisedWindowSize); + + m_tcp->SendPacket (p, tcpHeader, m_endPoint->GetLocalAddress (), + m_remoteAddress); +} + +void +TcpSocketImpl::SetSndBufSize (uint32_t size) +{ + m_sndBufSize = size; +} + +uint32_t +TcpSocketImpl::GetSndBufSize (void) const +{ + return m_sndBufSize; +} + +void +TcpSocketImpl::SetRcvBufSize (uint32_t size) +{ + m_rcvBufSize = size; +} + +uint32_t +TcpSocketImpl::GetRcvBufSize (void) const +{ + return m_rcvBufSize; +} + +void +TcpSocketImpl::SetSegSize (uint32_t size) +{ + m_segmentSize = size; +} + +uint32_t +TcpSocketImpl::GetSegSize (void) const +{ + return m_segmentSize; +} + +void +TcpSocketImpl::SetAdvWin (uint32_t window) +{ + m_advertisedWindowSize = window; +} + +uint32_t +TcpSocketImpl::GetAdvWin (void) const +{ + return m_advertisedWindowSize; +} + +void +TcpSocketImpl::SetSSThresh (uint32_t threshold) +{ + m_ssThresh = threshold; +} + +uint32_t +TcpSocketImpl::GetSSThresh (void) const +{ + return m_ssThresh; +} + +void +TcpSocketImpl::SetInitialCwnd (uint32_t cwnd) +{ + m_initialCWnd = cwnd; +} + +uint32_t +TcpSocketImpl::GetInitialCwnd (void) const +{ + return m_initialCWnd; +} + +void +TcpSocketImpl::SetConnTimeout (Time timeout) +{ + m_cnTimeout = timeout; +} + +Time +TcpSocketImpl::GetConnTimeout (void) const +{ + return m_cnTimeout; +} + +void +TcpSocketImpl::SetConnCount (uint32_t count) +{ + m_cnCount = count; +} + +uint32_t +TcpSocketImpl::GetConnCount (void) const +{ + return m_cnCount; +} + +void +TcpSocketImpl::SetDelAckTimeout (Time timeout) +{ + m_delAckTimeout = timeout; +} + +Time +TcpSocketImpl::GetDelAckTimeout (void) const +{ + return m_delAckTimeout; +} + +void +TcpSocketImpl::SetDelAckMaxCount (uint32_t count) +{ + m_delAckMaxCount = count; +} + +uint32_t +TcpSocketImpl::GetDelAckMaxCount (void) const +{ + return m_delAckMaxCount; +} + +}//namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-socket-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-socket-impl.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,214 @@ +/* -*- 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 + */ +#ifndef TCP_SOCKET_IMPL_H +#define TCP_SOCKET_IMPL_H + +#include +#include +#include "ns3/callback.h" +#include "ns3/traced-value.h" +#include "ns3/tcp-socket.h" +#include "ns3/ptr.h" +#include "ns3/ipv4-address.h" +#include "ns3/event-id.h" +#include "tcp-typedefs.h" +#include "pending-data.h" +#include "sequence-number.h" +#include "rtt-estimator.h" + + +namespace ns3 { + +class Ipv4EndPoint; +class Node; +class Packet; +class TcpL4Protocol; +class TcpHeader; + +class TcpSocketImpl : public TcpSocket +{ +public: + static TypeId GetTypeId (void); + /** + * Create an unbound tcp socket. + */ + TcpSocketImpl (); + TcpSocketImpl (const TcpSocketImpl& sock); + virtual ~TcpSocketImpl (); + + void SetNode (Ptr node); + void SetTcp (Ptr tcp); + void SetRtt (Ptr rtt); + + virtual enum SocketErrno GetErrno (void) const; + virtual Ptr GetNode (void) const; + virtual int Bind (void); + virtual int Bind (const Address &address); + virtual int Close (void); + virtual int ShutdownSend (void); + virtual int ShutdownRecv (void); + virtual int Connect(const Address &address); + virtual int Send (Ptr p); + virtual int Send (const uint8_t* buf, uint32_t size); + virtual int SendTo(Ptr p, const Address &address); + virtual uint32_t GetTxAvailable (void) const; + virtual int Listen(uint32_t queueLimit); + + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual uint32_t GetRxAvailable (void) const; + +private: + friend class Tcp; + // invoked by Tcp class + int FinishBind (void); + void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); + void Destroy (void); + int DoSendTo (Ptr p, const Address &daddr); + int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); + void SendEmptyPacket(uint8_t flags); + //methods for state + bool ProcessAction (Actions_t a); + bool ProcessAction (Actions_t a, const TcpHeader& tcpHeader, + Ipv4Address saddr, Ipv4Address daddr); + bool ProcessPacketAction (Actions_t a, Ptr p, + const TcpHeader& tcpHeader, + const Address& fromAddress); + Actions_t ProcessEvent (Events_t e); + bool SendPendingData(bool withAck = false); + void CompleteFork(Ptr, const TcpHeader&, const Address& fromAddress); + void ConnectionSucceeded(); + + //methods for window management + virtual uint32_t UnAckDataCount(); // Return count of number of unacked bytes + virtual uint32_t BytesInFlight(); // Return total bytes in flight + virtual uint32_t Window(); // Return window size (integer) + virtual uint32_t AvailableWindow();// Return unfilled portion of window + + // Manage data tx/rx + void NewRx (Ptr, const TcpHeader&, const Address&); + // XXX This should be virtual and overridden + Ptr Copy (); + void NewAck (SequenceNumber seq); + // XXX This should be virtual and overridden + void DupAck (const TcpHeader& t, uint32_t count); + void ReTxTimeout (); + void DelAckTimeout (); + void LastAckTimeout (); + void Retransmit (); + void CommonNewAck (SequenceNumber seq, bool skipTimer = false); + + // attribute related + virtual void SetSndBufSize (uint32_t size); + virtual uint32_t GetSndBufSize (void) const; + virtual void SetRcvBufSize (uint32_t size); + virtual uint32_t GetRcvBufSize (void) const; + virtual void SetSegSize (uint32_t size); + virtual uint32_t GetSegSize (void) const; + virtual void SetAdvWin (uint32_t window); + virtual uint32_t GetAdvWin (void) const; + virtual void SetSSThresh (uint32_t threshold); + virtual uint32_t GetSSThresh (void) const; + virtual void SetInitialCwnd (uint32_t cwnd); + virtual uint32_t GetInitialCwnd (void) const; + virtual void SetConnTimeout (Time timeout); + virtual Time GetConnTimeout (void) const; + virtual void SetConnCount (uint32_t count); + virtual uint32_t GetConnCount (void) const; + virtual void SetDelAckTimeout (Time timeout); + virtual Time GetDelAckTimeout (void) const; + virtual void SetDelAckMaxCount (uint32_t count); + virtual uint32_t GetDelAckMaxCount (void) const; + + bool m_skipRetxResched; + uint32_t m_dupAckCount; + EventId m_retxEvent; + EventId m_lastAckEvent; + + EventId m_delAckEvent; + uint32_t m_delAckCount; + uint32_t m_delAckMaxCount; + Time m_delAckTimeout; + + Ipv4EndPoint *m_endPoint; + Ptr m_node; + Ptr m_tcp; + Ipv4Address m_remoteAddress; + uint16_t m_remotePort; + //these two are so that the socket/endpoint cloning works + Ipv4Address m_localAddress; + uint16_t m_localPort; + enum SocketErrno m_errno; + bool m_shutdownSend; + bool m_shutdownRecv; + bool m_connected; + + //manage the state infomation + States_t m_state; + bool m_closeNotified; + bool m_closeRequestNotified; + bool m_closeOnEmpty; + bool m_pendingClose; + + + //sequence info, sender side + SequenceNumber m_nextTxSequence; + SequenceNumber m_highTxMark; + SequenceNumber m_highestRxAck; + SequenceNumber m_lastRxAck; + + //sequence info, reciever side + SequenceNumber m_nextRxSequence; + + //history data + //this is the incoming data buffer which sorts out of sequence data + UnAckData_t m_bufferedData; + //this is kind of the tx buffer + PendingData* m_pendingData; + SequenceNumber m_firstPendingSequence; + + // Window management + uint32_t m_segmentSize; //SegmentSize + uint32_t m_rxWindowSize; + uint32_t m_advertisedWindowSize; //Window to advertise + TracedValue m_cWnd; //Congestion window + uint32_t m_ssThresh; //Slow Start Threshold + uint32_t m_initialCWnd; //Initial cWnd value + + // Round trip time estimation + Ptr m_rtt; + Time m_lastMeasuredRtt; + + // Timer-related members + Time m_cnTimeout; + uint32_t m_cnCount; + + // Temporary queue for delivering data to application + uint32_t m_rxAvailable; + + bool m_wouldBlock; // set to true whenever socket would block on send() + + // Attributes + uint32_t m_sndBufSize; // buffer limit for the outgoing queue + uint32_t m_rcvBufSize; // maximum receive socket buffer size +}; + +}//namespace ns3 + +#endif /* TCP_SOCKET_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/tcp-typedefs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/tcp-typedefs.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,111 @@ +/* -*- 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 + * typedefs for tcp state machine + */ + +#include +#include +#include "sequence-number.h" + +#ifndef TCP_TYPEDEFS_H +#define TCP_TYPEDEFS_H + +namespace ns3 { + +typedef enum { MAX_FLAGS = 0x40 } TCPMaxFlags_t; // Flags are 6 bits + +typedef enum { + CLOSED, // 0 + LISTEN, // 1 + SYN_SENT, // 2 + SYN_RCVD, // 3 + ESTABLISHED, // 4 + CLOSE_WAIT, // 5 + LAST_ACK, // 6 + FIN_WAIT_1, // 7 + FIN_WAIT_2, // 8 + CLOSING, // 9 + TIMED_WAIT, // 10 + LAST_STATE } States_t; + +typedef enum { + APP_LISTEN, // 0 + APP_CONNECT, // 1 + APP_SEND, // 2 + SEQ_RECV, // 3 + APP_CLOSE, // 4 + TIMEOUT, // 5 + ACK_RX, // 6 + SYN_RX, // 7 + SYN_ACK_RX, // 8 + FIN_RX, // 9 + FIN_ACK_RX, // 10 + RST_RX, // 11 + BAD_FLAGS, // 12 + LAST_EVENT } Events_t; + +typedef enum { + NO_ACT, // 0 + ACK_TX, // 1 + ACK_TX_1, // ACK response to syn + RST_TX, // 2 + SYN_TX, // 3 + SYN_ACK_TX, // 4 + FIN_TX, // 5 + FIN_ACK_TX, // 6 + NEW_ACK, // 7 + NEW_SEQ_RX, // 8 + RETX, // 9 + TX_DATA, // 10 + PEER_CLOSE, // 11 + APP_CLOSED, // 12 + CANCEL_TM, // 13 + APP_NOTIFY, // 14 - Notify app that connection failed + SERV_NOTIFY, // 15 - Notify server tcp that connection completed + LAST_ACTION } Actions_t; + +class SA // State/Action pair +{ +public: + SA () : state (LAST_STATE), action (LAST_ACTION) { } + SA (States_t s, Actions_t a) : state (s), action (a) { } +public: + States_t state; + Actions_t action; +}; +typedef std::vector StateActionVec_t; +typedef std::vector StateActions_t; // One per current state +typedef std::vector EventVec_t; // For flag events lookup + +//type for managing buffered out of sequence data +typedef std::map > UnAckData_t; + +class TcpStateMachine { + public: + TcpStateMachine (); + SA Lookup (States_t, Events_t); + Events_t FlagsEvent (uint8_t); // Lookup event from flags + + public: + StateActions_t aT; // Action table + EventVec_t eV; // Flags event lookup +}; + +}//namespace ns3 +#endif //TCP_TYPEDEFS_H diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-header.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-header.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,162 @@ +/* -*- 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 "udp-header.h" +#include "ipv4-checksum.h" + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (UdpHeader); + +bool UdpHeader::m_calcChecksum = false; + +/* The magic values below are used only for debugging. + * They can be used to easily detect memory corruption + * problems so you can see the patterns in memory. + */ +UdpHeader::UdpHeader () + : m_sourcePort (0xfffd), + m_destinationPort (0xfffd), + m_payloadSize (0xfffd), + m_initialChecksum (0) +{} +UdpHeader::~UdpHeader () +{ + m_sourcePort = 0xfffe; + m_destinationPort = 0xfffe; + m_payloadSize = 0xfffe; +} + +void +UdpHeader::EnableChecksums (void) +{ + m_calcChecksum = true; +} + +void +UdpHeader::SetDestinationPort (uint16_t port) +{ + m_destinationPort = port; +} +void +UdpHeader::SetSourcePort (uint16_t port) +{ + m_sourcePort = port; +} +uint16_t +UdpHeader::GetSourcePort (void) const +{ + return m_sourcePort; +} +uint16_t +UdpHeader::GetDestinationPort (void) const +{ + return m_destinationPort; +} +void +UdpHeader::SetPayloadSize (uint16_t size) +{ + m_payloadSize = size; +} +void +UdpHeader::InitializeChecksum (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol) +{ + uint8_t buf[12]; + source.Serialize (buf); + destination.Serialize (buf+4); + buf[8] = 0; + buf[9] = protocol; + uint16_t udpLength = m_payloadSize + GetSerializedSize (); + buf[10] = udpLength >> 8; + buf[11] = udpLength & 0xff; + + m_initialChecksum = Ipv4ChecksumCalculate (0, buf, 12); +} + +TypeId +UdpHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::UdpHeader") + .SetParent
() + .AddConstructor () + ; + return tid; +} +TypeId +UdpHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} +void +UdpHeader::Print (std::ostream &os) const +{ + os << "length: " << m_payloadSize + GetSerializedSize () + << " " + << m_sourcePort << " > " << m_destinationPort + ; +} + +uint32_t +UdpHeader::GetSerializedSize (void) const +{ + return 8; +} + +void +UdpHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + i.WriteHtonU16 (m_sourcePort); + i.WriteHtonU16 (m_destinationPort); + i.WriteHtonU16 (m_payloadSize + GetSerializedSize ()); + i.WriteU16 (0); + + if (m_calcChecksum) + { +#if 0 + //XXXX + uint16_t checksum = Ipv4ChecksumCalculate (m_initialChecksum, + buffer->PeekData (), + GetSerializedSize () + m_payloadSize); + checksum = Ipv4ChecksumComplete (checksum); + i = buffer->Begin (); + i.Next (6); + i.WriteU16 (checksum); +#endif + } +} +uint32_t +UdpHeader::Deserialize (Buffer::Iterator start) +{ + Buffer::Iterator i = start; + m_sourcePort = i.ReadNtohU16 (); + m_destinationPort = i.ReadNtohU16 (); + m_payloadSize = i.ReadNtohU16 () - GetSerializedSize (); + if (m_calcChecksum) + { + // XXX verify checksum. + } + return GetSerializedSize (); +} + + +}; // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-header.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-header.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,103 @@ +/* -*- 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 UDP_HEADER_H +#define UDP_HEADER_H + +#include +#include +#include "ns3/header.h" +#include "ns3/ipv4-address.h" + +namespace ns3 { +/** + * \brief Packet header for UDP packets + */ +class UdpHeader : public Header +{ +public: + + /** + * \brief Constructor + * + * Creates a null header + */ + UdpHeader (); + ~UdpHeader (); + + /** + * \brief Enable checksum calculation for UDP (XXX currently has no effect) + */ + static void EnableChecksums (void); + /** + * \param port the destination port for this UdpHeader + */ + void SetDestinationPort (uint16_t port); + /** + * \param port The source port for this UdpHeader + */ + void SetSourcePort (uint16_t port); + /** + * \return The source port for this UdpHeader + */ + uint16_t GetSourcePort (void) const; + /** + * \return the destination port for this UdpHeader + */ + uint16_t GetDestinationPort (void) const; + /** + * \param size The payload size in bytes + */ + void SetPayloadSize (uint16_t size); + + /** + * \param source the ip source to use in the underlying + * ip packet. + * \param destination the ip destination to use in the + * underlying ip packet. + * \param protocol the protocol number to use in the underlying + * ip packet. + * + * If you want to use udp checksums, you should call this + * method prior to adding the header to a packet. + */ + void InitializeChecksum (Ipv4Address source, + Ipv4Address destination, + uint8_t protocol); + + static TypeId GetTypeId (void); + virtual TypeId GetInstanceTypeId (void) const; + virtual void Print (std::ostream &os) const; + virtual uint32_t GetSerializedSize (void) const; + virtual void Serialize (Buffer::Iterator start) const; + virtual uint32_t Deserialize (Buffer::Iterator start); + +private: + uint16_t m_sourcePort; + uint16_t m_destinationPort; + uint16_t m_payloadSize; + uint16_t m_initialChecksum; + + static bool m_calcChecksum; +}; + +} // namespace ns3 + +#endif /* UDP_HEADER */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-l4-protocol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-l4-protocol.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,194 @@ +/* -*- 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 "ns3/log.h" +#include "ns3/assert.h" +#include "ns3/packet.h" +#include "ns3/node.h" + +#include "udp-l4-protocol.h" +#include "udp-header.h" +#include "ipv4-end-point-demux.h" +#include "ipv4-end-point.h" +#include "ipv4-l3-protocol.h" +#include "udp-socket-impl.h" + +NS_LOG_COMPONENT_DEFINE ("UdpL4Protocol"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol); + +/* see http://www.iana.org/assignments/protocol-numbers */ +const uint8_t UdpL4Protocol::PROT_NUMBER = 17; + +TypeId +UdpL4Protocol::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::UdpL4Protocol") + .SetParent () + .AddConstructor () + ; + return tid; +} + +UdpL4Protocol::UdpL4Protocol () + : m_endPoints (new Ipv4EndPointDemux ()) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +UdpL4Protocol::~UdpL4Protocol () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +UdpL4Protocol::SetNode (Ptr node) +{ + m_node = node; +} + +int +UdpL4Protocol::GetProtocolNumber (void) const +{ + return PROT_NUMBER; +} +int +UdpL4Protocol::GetVersion (void) const +{ + return 2; +} + + +void +UdpL4Protocol::DoDispose (void) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_endPoints != 0) + { + delete m_endPoints; + m_endPoints = 0; + } + m_node = 0; + Ipv4L4Protocol::DoDispose (); +} + +Ptr +UdpL4Protocol::CreateSocket (void) +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr socket = CreateObject (); + socket->SetNode (m_node); + socket->SetUdp (this); + return socket; +} + +Ipv4EndPoint * +UdpL4Protocol::Allocate (void) +{ + NS_LOG_FUNCTION_NOARGS (); + return m_endPoints->Allocate (); +} + +Ipv4EndPoint * +UdpL4Protocol::Allocate (Ipv4Address address) +{ + NS_LOG_FUNCTION (this << address); + return m_endPoints->Allocate (address); +} + +Ipv4EndPoint * +UdpL4Protocol::Allocate (uint16_t port) +{ + NS_LOG_FUNCTION (this << port); + return m_endPoints->Allocate (port); +} + +Ipv4EndPoint * +UdpL4Protocol::Allocate (Ipv4Address address, uint16_t port) +{ + NS_LOG_FUNCTION (this << address << port); + return m_endPoints->Allocate (address, port); +} +Ipv4EndPoint * +UdpL4Protocol::Allocate (Ipv4Address localAddress, uint16_t localPort, + Ipv4Address peerAddress, uint16_t peerPort) +{ + NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort); + return m_endPoints->Allocate (localAddress, localPort, + peerAddress, peerPort); +} + +void +UdpL4Protocol::DeAllocate (Ipv4EndPoint *endPoint) +{ + NS_LOG_FUNCTION (this << endPoint); + m_endPoints->DeAllocate (endPoint); +} + +void +UdpL4Protocol::Receive(Ptr packet, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << source << destination); + + UdpHeader udpHeader; + packet->RemoveHeader (udpHeader); + Ipv4EndPointDemux::EndPoints endPoints = + m_endPoints->Lookup (destination, udpHeader.GetDestinationPort (), + source, udpHeader.GetSourcePort (), interface); + for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin (); + endPoint != endPoints.end (); endPoint++) + { + (*endPoint)->ForwardUp (packet->Copy (), source, udpHeader.GetSourcePort ()); + } +} + +void +UdpL4Protocol::Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport) +{ + NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport); + + UdpHeader udpHeader; + udpHeader.SetDestinationPort (dport); + udpHeader.SetSourcePort (sport); + udpHeader.SetPayloadSize (packet->GetSize ()); + udpHeader.InitializeChecksum (saddr, + daddr, + PROT_NUMBER); + + packet->AddHeader (udpHeader); + + Ptr ipv4 = m_node->GetObject (); + if (ipv4 != 0) + { + NS_LOG_LOGIC ("Sending to IP"); + ipv4->Send (packet, saddr, daddr, PROT_NUMBER); + } +} + + +}; // namespace ns3 + diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-l4-protocol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-l4-protocol.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,100 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2005,2006,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 + * + * Author: Mathieu Lacage + */ + +#ifndef UDP_L4_PROTOCOL_H +#define UDP_L4_PROTOCOL_H + +#include + +#include "ns3/packet.h" +#include "ns3/ipv4-address.h" +#include "ns3/ptr.h" +#include "ipv4-end-point-demux.h" +#include "ipv4-l4-protocol.h" + +namespace ns3 { + +class Node; +class Socket; +/** + * \brief Implementation of the UDP protocol + */ +class UdpL4Protocol : public Ipv4L4Protocol { +public: + static TypeId GetTypeId (void); + static const uint8_t PROT_NUMBER; + + UdpL4Protocol (); + virtual ~UdpL4Protocol (); + + void SetNode (Ptr node); + + virtual int GetProtocolNumber (void) const; + virtual int GetVersion (void) const; + + /** + * \return A smart Socket pointer to a UdpSocket, allocated by this instance + * of the UDP protocol + */ + Ptr CreateSocket (void); + + Ipv4EndPoint *Allocate (void); + Ipv4EndPoint *Allocate (Ipv4Address address); + Ipv4EndPoint *Allocate (uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address address, uint16_t port); + Ipv4EndPoint *Allocate (Ipv4Address localAddress, uint16_t localPort, + Ipv4Address peerAddress, uint16_t peerPort); + + void DeAllocate (Ipv4EndPoint *endPoint); + + // called by UdpSocket. + /** + * \brief Send a packet via UDP + * \param packet The packet to send + * \param saddr The source Ipv4Address + * \param daddr The destination Ipv4Address + * \param sport The source port number + * \param dport The destination port number + */ + void Send (Ptr packet, + Ipv4Address saddr, Ipv4Address daddr, + uint16_t sport, uint16_t dport); + /** + * \brief Receive a packet up the protocol stack + * \param p The Packet to dump the contents into + * \param source The source's Ipv4Address + * \param destination The destinations Ipv4Address + * \param interface the interface from which the packet is coming. + */ + // inherited from Ipv4L4Protocol + virtual void Receive(Ptr p, + Ipv4Address const &source, + Ipv4Address const &destination, + Ptr interface); +protected: + virtual void DoDispose (void); +private: + Ptr m_node; + Ipv4EndPointDemux *m_endPoints; +}; + +}; // namespace ns3 + +#endif /* UDP_L4_PROTOCOL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-socket-factory-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-socket-factory-impl.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,54 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ +#include "udp-socket-factory-impl.h" +#include "udp-l4-protocol.h" +#include "ns3/socket.h" +#include "ns3/assert.h" + +namespace ns3 { + +UdpSocketFactoryImpl::UdpSocketFactoryImpl () + : m_udp (0) +{} +UdpSocketFactoryImpl::~UdpSocketFactoryImpl () +{ + NS_ASSERT (m_udp == 0); +} + +void +UdpSocketFactoryImpl::SetUdp (Ptr udp) +{ + m_udp = udp; +} + +Ptr +UdpSocketFactoryImpl::CreateSocket (void) +{ + return m_udp->CreateSocket (); +} + +void +UdpSocketFactoryImpl::DoDispose (void) +{ + m_udp = 0; + UdpSocketFactory::DoDispose (); +} + +} // namespace ns3 diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-socket-factory-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-socket-factory-impl.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,62 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ +#ifndef UDP_SOCKET_FACTORY_IMPL_H +#define UDP_SOCKET_FACTORY_IMPL_H + +#include "ns3/udp-socket-factory.h" +#include "ns3/ptr.h" + +namespace ns3 { + +class UdpL4Protocol; + +/** + * \brief Object to create UDP socket instances + * \internal + * + * This class implements the API for creating UDP sockets. + * It is a socket factory (deriving from class SocketFactory). + */ +class UdpSocketFactoryImpl : public UdpSocketFactory +{ +public: + UdpSocketFactoryImpl (); + virtual ~UdpSocketFactoryImpl (); + + void SetUdp (Ptr udp); + + /** + * \brief Implements a method to create a Udp-based socket and return + * a base class smart pointer to the socket. + * \internal + * + * \return smart pointer to Socket + */ + virtual Ptr CreateSocket (void); + +protected: + virtual void DoDispose (void); +private: + Ptr m_udp; +}; + +} // namespace ns3 + +#endif /* UDP_SOCKET_FACTORY_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-socket-impl.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-socket-impl.cc Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,694 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ + +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" +#include "ns3/ipv4-route.h" +#include "ns3/ipv4.h" +#include "ns3/udp-socket-factory.h" +#include "ns3/trace-source-accessor.h" +#include "ns3/uinteger.h" +#include "ns3/boolean.h" +#include "udp-socket-impl.h" +#include "udp-l4-protocol.h" +#include "ipv4-end-point.h" +#include "ipv4-l4-demux.h" + +NS_LOG_COMPONENT_DEFINE ("UdpSocketImpl"); + +namespace ns3 { + +static const uint32_t MAX_IPV4_UDP_DATAGRAM_SIZE = 65507; + +// Add attributes generic to all UdpSockets to base class UdpSocket +TypeId +UdpSocketImpl::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::UdpSocketImpl") + .SetParent () + .AddConstructor () + .AddTraceSource ("Drop", "Drop UDP packet due to receive buffer overflow", + MakeTraceSourceAccessor (&UdpSocketImpl::m_dropTrace)) + ; + return tid; +} + +UdpSocketImpl::UdpSocketImpl () + : m_endPoint (0), + m_node (0), + m_udp (0), + m_errno (ERROR_NOTERROR), + m_shutdownSend (false), + m_shutdownRecv (false), + m_connected (false), + m_rxAvailable (0) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +UdpSocketImpl::~UdpSocketImpl () +{ + NS_LOG_FUNCTION_NOARGS (); + + m_node = 0; + if (m_endPoint != 0) + { + NS_ASSERT (m_udp != 0); + /** + * Note that this piece of code is a bit tricky: + * when DeAllocate is called, it will call into + * Ipv4EndPointDemux::Deallocate which triggers + * a delete of the associated endPoint which triggers + * in turn a call to the method ::Destroy below + * will will zero the m_endPoint field. + */ + NS_ASSERT (m_endPoint != 0); + m_udp->DeAllocate (m_endPoint); + NS_ASSERT (m_endPoint == 0); + } + m_udp = 0; +} + +void +UdpSocketImpl::SetNode (Ptr node) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = node; + +} +void +UdpSocketImpl::SetUdp (Ptr udp) +{ + NS_LOG_FUNCTION_NOARGS (); + m_udp = udp; +} + + +enum Socket::SocketErrno +UdpSocketImpl::GetErrno (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_errno; +} + +Ptr +UdpSocketImpl::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + +void +UdpSocketImpl::Destroy (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_node = 0; + m_endPoint = 0; + m_udp = 0; +} + +int +UdpSocketImpl::FinishBind (void) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_endPoint == 0) + { + return -1; + } + m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr (this))); + m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr (this))); + return 0; +} + +int +UdpSocketImpl::Bind (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_endPoint = m_udp->Allocate (); + return FinishBind (); +} + +int +UdpSocketImpl::Bind (const Address &address) +{ + NS_LOG_FUNCTION (this << address); + + if (!InetSocketAddress::IsMatchingType (address)) + { + NS_LOG_ERROR ("Not IsMatchingType"); + return ERROR_INVAL; + } + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + Ipv4Address ipv4 = transport.GetIpv4 (); + uint16_t port = transport.GetPort (); + if (ipv4 == Ipv4Address::GetAny () && port == 0) + { + m_endPoint = m_udp->Allocate (); + } + else if (ipv4 == Ipv4Address::GetAny () && port != 0) + { + m_endPoint = m_udp->Allocate (port); + } + else if (ipv4 != Ipv4Address::GetAny () && port == 0) + { + m_endPoint = m_udp->Allocate (ipv4); + } + else if (ipv4 != Ipv4Address::GetAny () && port != 0) + { + m_endPoint = m_udp->Allocate (ipv4, port); + } + + return FinishBind (); +} + +int +UdpSocketImpl::ShutdownSend (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_shutdownSend = true; + return 0; +} + +int +UdpSocketImpl::ShutdownRecv (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_shutdownRecv = false; + return 0; +} + +int +UdpSocketImpl::Close(void) +{ + NS_LOG_FUNCTION_NOARGS (); + NotifyCloseCompleted (); + return 0; +} + +int +UdpSocketImpl::Connect(const Address & address) +{ + NS_LOG_FUNCTION (this << address); + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + m_defaultAddress = transport.GetIpv4 (); + m_defaultPort = transport.GetPort (); + NotifyConnectionSucceeded (); + m_connected = true; + + return 0; +} + +int +UdpSocketImpl::Listen (uint32_t queueLimit) +{ + m_errno = Socket::ERROR_OPNOTSUPP; + return -1; +} + +int +UdpSocketImpl::Send (Ptr p) +{ + NS_LOG_FUNCTION (this << p); + + if (!m_connected) + { + m_errno = ERROR_NOTCONN; + return -1; + } + return DoSend (p); +} + +int +UdpSocketImpl::DoSend (Ptr p) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_endPoint == 0) + { + if (Bind () == -1) + { + NS_ASSERT (m_endPoint == 0); + return -1; + } + NS_ASSERT (m_endPoint != 0); + } + if (m_shutdownSend) + { + m_errno = ERROR_SHUTDOWN; + return -1; + } + + return DoSendTo (p, m_defaultAddress, m_defaultPort); +} + +int +UdpSocketImpl::DoSendTo (Ptr p, const Address &address) +{ + NS_LOG_FUNCTION (this << p << address); + + if (!m_connected) + { + NS_LOG_LOGIC ("Not connected"); + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + Ipv4Address ipv4 = transport.GetIpv4 (); + uint16_t port = transport.GetPort (); + return DoSendTo (p, ipv4, port); + } + else + { + // connected UDP socket must use default addresses + NS_LOG_LOGIC ("Connected"); + return DoSendTo (p, m_defaultAddress, m_defaultPort); + } +} + +int +UdpSocketImpl::DoSendTo (Ptr p, Ipv4Address dest, uint16_t port) +{ + NS_LOG_FUNCTION (this << p << dest << port); + + if (m_endPoint == 0) + { + if (Bind () == -1) + { + NS_ASSERT (m_endPoint == 0); + return -1; + } + NS_ASSERT (m_endPoint != 0); + } + if (m_shutdownSend) + { + m_errno = ERROR_SHUTDOWN; + return -1; + } + + if (p->GetSize () > GetTxAvailable () ) + { + m_errno = ERROR_MSGSIZE; + return -1; + } + + uint32_t localIfIndex; + Ptr ipv4 = m_node->GetObject (); + + // Locally override the IP TTL for this socket + // We cannot directly modify the TTL at this stage, so we set a Packet tag + // The destination can be either multicast, unicast/anycast, or + // either all-hosts broadcast or limited (subnet-directed) broadcast. + // For the latter two broadcast types, the TTL will later be set to one + // irrespective of what is set in these socket options. So, this tagging + // may end up setting the TTL of a limited broadcast packet to be + // the same as a unicast, but it will be fixed further down the stack + //NS_LOG_UNCOND ("IPttl: " << m_ipTtl); + if (m_ipMulticastTtl != 0 && dest.IsMulticast ()) + { + SocketIpTtlTag tag; + tag.SetTtl (m_ipMulticastTtl); + p->AddTag (tag); + } + else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ()) + { + SocketIpTtlTag tag; + tag.SetTtl (m_ipTtl); + p->AddTag (tag); + } + // + // If dest is sent to the limited broadcast address (all ones), + // convert it to send a copy of the packet out of every interface + // + if (dest.IsBroadcast ()) + { + NS_LOG_LOGIC ("Limited broadcast start."); + for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++ ) + { + Ipv4Address addri = ipv4->GetAddress (i); + Ipv4Mask maski = ipv4->GetNetworkMask (i); + Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski); + NS_LOG_LOGIC ("Sending one copy from " << addri << " to " << bcast + << " (mask is " << maski << ")"); + m_udp->Send (p->Copy (), addri, bcast, + m_endPoint->GetLocalPort (), port); + NotifyDataSent (p->GetSize ()); + } + NS_LOG_LOGIC ("Limited broadcast end."); + return p->GetSize(); + } + else if (ipv4->GetIfIndexForDestination(dest, localIfIndex)) + { + NS_LOG_LOGIC ("Route exists"); + m_udp->Send (p->Copy (), ipv4->GetAddress (localIfIndex), dest, + m_endPoint->GetLocalPort (), port); + NotifyDataSent (p->GetSize ()); + return p->GetSize();; + } + else + { + NS_LOG_ERROR ("ERROR_NOROUTETOHOST"); + m_errno = ERROR_NOROUTETOHOST; + return -1; + } + + return 0; +} + +// XXX maximum message size for UDP broadcast is limited by MTU +// size of underlying link; we are not checking that now. +uint32_t +UdpSocketImpl::GetTxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + // No finite send buffer is modelled, but we must respect + // the maximum size of an IP datagram (65535 bytes - headers). + return MAX_IPV4_UDP_DATAGRAM_SIZE; +} + +int +UdpSocketImpl::SendTo (Ptr p, const Address &address) +{ + NS_LOG_FUNCTION (this << address << p); + InetSocketAddress transport = InetSocketAddress::ConvertFrom (address); + Ipv4Address ipv4 = transport.GetIpv4 (); + uint16_t port = transport.GetPort (); + return DoSendTo (p, ipv4, port); +} + +Ptr +UdpSocketImpl::Recv (uint32_t maxSize, uint32_t flags) +{ + NS_LOG_FUNCTION_NOARGS (); + if (m_deliveryQueue.empty() ) + { + return 0; + } + Ptr p = m_deliveryQueue.front (); + if (p->GetSize () <= maxSize) + { + m_deliveryQueue.pop (); + m_rxAvailable -= p->GetSize (); + } + else + { + p = 0; + } + return p; +} + +uint32_t +UdpSocketImpl::GetRxAvailable (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + // We separately maintain this state to avoid walking the queue + // every time this might be called + return m_rxAvailable; +} + +void +UdpSocketImpl::ForwardUp (Ptr packet, Ipv4Address ipv4, uint16_t port) +{ + NS_LOG_FUNCTION (this << packet << ipv4 << port); + + if (m_shutdownRecv) + { + return; + } + if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize) + { + Address address = InetSocketAddress (ipv4, port); + SocketRxAddressTag tag; + tag.SetAddress (address); + packet->AddTag (tag); + m_deliveryQueue.push (packet); + m_rxAvailable += packet->GetSize (); + NotifyDataRecv (); + } + else + { + // In general, this case should not occur unless the + // receiving application reads data from this socket slowly + // in comparison to the arrival rate + // + // drop and trace packet + NS_LOG_WARN ("No receive buffer space available. Drop."); + m_dropTrace (packet); + } +} + + +void +UdpSocketImpl::SetRcvBufSize (uint32_t size) +{ + m_rcvBufSize = size; +} + +uint32_t +UdpSocketImpl::GetRcvBufSize (void) const +{ + return m_rcvBufSize; +} + +void +UdpSocketImpl::SetIpTtl (uint32_t ipTtl) +{ + m_ipTtl = ipTtl; +} + +uint32_t +UdpSocketImpl::GetIpTtl (void) const +{ + return m_ipTtl; +} + +void +UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl) +{ + m_ipMulticastTtl = ipTtl; +} + +uint32_t +UdpSocketImpl::GetIpMulticastTtl (void) const +{ + return m_ipMulticastTtl; +} + +} //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); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.1")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + 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); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.1")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + 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); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.0.2")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + 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); + ipv4->SetAddress (netdev_idx, Ipv4Address ("10.0.1.2")); + ipv4->SetNetworkMask (netdev_idx, Ipv4Mask (0xffff0000U)); + 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), + 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), + 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), +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 -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/udp-socket-impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/udp-socket-impl.h Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,112 @@ +/* -*- 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 + * + * Author: Mathieu Lacage + */ +#ifndef UDP_SOCKET_IMPL_H +#define UDP_SOCKET_IMPL_H + +#include +#include +#include "ns3/callback.h" +#include "ns3/traced-callback.h" +#include "ns3/socket.h" +#include "ns3/ptr.h" +#include "ns3/ipv4-address.h" +#include "ns3/udp-socket.h" + +namespace ns3 { + +class Ipv4EndPoint; +class Node; +class Packet; +class UdpL4Protocol; + +class UdpSocketImpl : public UdpSocket +{ +public: + static TypeId GetTypeId (void); + /** + * Create an unbound udp socket. + */ + UdpSocketImpl (); + virtual ~UdpSocketImpl (); + + void SetNode (Ptr node); + void SetUdp (Ptr udp); + + virtual enum SocketErrno GetErrno (void) const; + virtual Ptr GetNode (void) const; + virtual int Bind (void); + virtual int Bind (const Address &address); + virtual int Close (void); + virtual int ShutdownSend (void); + virtual int ShutdownRecv (void); + virtual int Connect(const Address &address); + virtual int Listen (uint32_t queueLimit); + virtual int Send (Ptr p); + virtual int SendTo (Ptr p, const Address &address); + virtual uint32_t GetTxAvailable (void) const; + + virtual Ptr Recv (uint32_t maxSize, uint32_t flags); + virtual uint32_t GetRxAvailable (void) const; + +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; + + friend class UdpSocketFactory; + // invoked by Udp class + int FinishBind (void); + void ForwardUp (Ptr p, Ipv4Address ipv4, uint16_t port); + void Destroy (void); + int DoSend (Ptr p); + int DoSendTo (Ptr p, const Address &daddr); + int DoSendTo (Ptr p, Ipv4Address daddr, uint16_t dport); + + Ipv4EndPoint *m_endPoint; + Ptr m_node; + Ptr m_udp; + Ipv4Address m_defaultAddress; + uint16_t m_defaultPort; + Callback,uint32_t,const Address &> m_dummyRxCallback; + Callback,uint8_t const*,uint32_t,const Address &> m_rxCallback; + TracedCallback > m_dropTrace; + + enum SocketErrno m_errno; + bool m_shutdownSend; + bool m_shutdownRecv; + bool m_connected; + + std::queue > m_deliveryQueue; + uint32_t m_rxAvailable; + + // Socket attributes + uint32_t m_rcvBufSize; + uint32_t m_ipTtl; + uint32_t m_ipMulticastTtl; + +}; + +}//namespace ns3 + +#endif /* UDP_SOCKET_IMPL_H */ diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/waf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/waf Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,1 @@ +exec "`dirname "$0"`"/../../waf "$@" \ No newline at end of file diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/internet-stack/wscript --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/internet-stack/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -0,0 +1,42 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + + +def build(bld): + obj = bld.create_ns3_module('internet-stack', ['node']) + obj.source = [ + 'internet-stack.cc', + 'ipv4-l4-demux.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-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', + 'ipv4-impl.cc', + 'udp-socket-factory-impl.cc', + 'tcp-socket-factory-impl.cc', + 'pending-data.cc', + 'sequence-number.cc', + 'rtt-estimator.cc', + ] + + headers = bld.create_obj('ns3header') + headers.module = 'internet-stack' + headers.source = [ + 'internet-stack.h', + 'udp-header.h', + 'tcp-header.h', + 'sequence-number.h', + ] diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/routing/olsr/wscript --- a/src/routing/olsr/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/src/routing/olsr/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -1,7 +1,7 @@ ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- def build(bld): - module = bld.create_ns3_module('olsr', ['internet-node', 'contrib']) + module = bld.create_ns3_module('olsr', ['internet-stack', 'contrib']) module.includes = '.' module.source = [ 'olsr-header.cc', diff -r 43b3f8ecd86d -r 8c0ab08144e6 src/wscript --- a/src/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/src/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -16,7 +16,7 @@ 'simulator', 'contrib', 'node', - 'internet-node', + 'internet-stack', 'devices/point-to-point', 'devices/csma', 'applications/onoff', diff -r 43b3f8ecd86d -r 8c0ab08144e6 tutorial/wscript --- a/tutorial/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/tutorial/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -4,29 +4,29 @@ obj = bld.create_ns3_program('hello-simulator', ['simulator']) obj.source = 'hello-simulator.cc' - obj = bld.create_ns3_program('tutorial-csma-echo', ['internet-node', 'csma']) + obj = bld.create_ns3_program('tutorial-csma-echo', ['internet-stack', 'csma']) obj.source = 'tutorial-csma-echo.cc' - obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', ['internet-node', 'csma']) + obj = bld.create_ns3_program('tutorial-csma-echo-ascii-trace', ['internet-stack', 'csma']) obj.source = 'tutorial-csma-echo-ascii-trace.cc' - obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', ['internet-node', 'csma']) + obj = bld.create_ns3_program('tutorial-csma-echo-pcap-trace', ['internet-stack', 'csma']) obj.source = 'tutorial-csma-echo-pcap-trace.cc' - obj = bld.create_ns3_program('tutorial-point-to-point', ['internet-node', 'point-to-point']) + obj = bld.create_ns3_program('tutorial-point-to-point', ['internet-stack', 'point-to-point']) obj.source = 'tutorial-point-to-point.cc' - obj = bld.create_ns3_program('tutorial-star', ['internet-node', 'point-to-point']) + obj = bld.create_ns3_program('tutorial-star', ['internet-stack', 'point-to-point']) obj.source = ['tutorial-star.cc'] - obj = bld.create_ns3_program('tutorial-star-routing', ['internet-node', 'point-to-point']) + obj = bld.create_ns3_program('tutorial-star-routing', ['internet-stack', 'point-to-point']) obj.source = ['tutorial-star-routing.cc'] - obj = bld.create_ns3_program('tutorial-linear-dumbbell', ['internet-node', 'point-to-point']) + obj = bld.create_ns3_program('tutorial-linear-dumbbell', ['internet-stack', 'point-to-point']) obj.source = 'tutorial-linear-dumbbell.cc' obj = bld.create_ns3_program('testipv4', ['node']) obj.source = ['testipv4.cc'] - obj = bld.create_ns3_program('tutorial-bus-network', ['internet-node']) + obj = bld.create_ns3_program('tutorial-bus-network', ['internet-stack']) obj.source = ['tutorial-bus-network.cc'] diff -r 43b3f8ecd86d -r 8c0ab08144e6 utils/wscript --- a/utils/wscript Mon Jun 09 11:39:29 2008 -0700 +++ b/utils/wscript Mon Jun 09 15:40:22 2008 -0700 @@ -28,14 +28,14 @@ obj.source = 'replay-simulation.cc' obj = bld.create_ns3_program('print-introspected-doxygen', - ['internet-node', 'csma-cd', 'point-to-point']) + ['internet-stack', 'csma-cd', 'point-to-point']) obj.source = 'print-introspected-doxygen.cc' # XXX: disable mobility visualizer code temporarily. env['ENABLE_MOBILITY_VISUALIZER'] = '' if env['ENABLE_MOBILITY_VISUALIZER']: obj = bld.create_ns3_program('mobility-visualizer', - ['internet-node', 'mobility']) + ['internet-stack', 'mobility']) obj.source = ['mobility-visualizer-model.cc', 'mobility-visualizer-view.cc'] obj.uselib = 'MOBILITY_VISUALIZER' if os.path.basename(obj.env['CXX']).startswith("g++"):