--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tcp-2way.cc Fri Jul 11 18:15:52 2008 +0100
@@ -0,0 +1,785 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2007 University of Washington
+ * Copyright 2007 Georgia Tech Research Corporation
+ * Copyright 2008 Sandia 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
+ *
+ *
+ * Sandia is a multiprogram laboratory operated by Sandia
+ * Corporation, a Lockheed Martin Company, for the United States
+ * Department of Energy's National Nuclear Security Administration
+ * under Contract DE-AC04-94AL85000.
+ *
+ * Author: David Evensky, Sandia National Labs
+ *
+ * includes GPL'ed ns-3-dev code from:
+ * udp-echo, // ??, (c) U. Wash. 2007
+ * tcp-large-transfer // ??
+ * packet-sink // Tom Henderson, (c) U. Wash. 2007
+ * onoff // George F. Riley, (c) GT Res Corp. 2007
+ */
+
+
+/* NOTE
+This isn't really an example file, so don't look to closely at it as a starting
+script. It is here for validation of the TCP model.
+*/
+
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <iomanip>
+#include <map>
+
+#include "ns3/core-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/node-module.h"
+#include "ns3/global-route-manager.h"
+#include "ns3/simulator-module.h"
+#include "ns3/log.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("tcp-2way");
+
+//----------defines-------------------------------------------------------------
+//define to print more debugging info.
+#define VERBOSE_TESTING
+
+/* define to die because Socket::Recv() is told to
+ * only read an "undesired" number of bytes
+ * fails NS_ASSERT in HandleRead because rx_addr_tag
+ * tag isn't there.
+ */
+//#define TOO_SMALL_BUG
+
+//define to print this pointer in NS_LOG_FUNCTION
+//#define PRINT_THIS
+
+/*define to print packet info in HandleRead
+ *expected output is of the form:
+ *536:P{536} *bytes from 10.1.0.2 [02-06-0a:01:00:02:20:00] <0|536|884018>
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * | | | | | | | |
+ * | | | | | | | +bytes left
+ * | | | | | | | to read in
+ * | | | | | | | sent buffer
+ * | | | | | | +bytes read in
+ * | | | | | | this packet if
+ * | | | | | | header read,
+ * | | | | | | prints size
+ * | | | | | | in ()
+ * | | | | | +bytes cur. packet
+ * | | | | | left to process
+ * | | | | +mac addr of sender
+ * | | | +IP addr of sender
+ * | | +print '*' while processing first chunk in a received packet.
+ * | | if there are multiple small sent packets, these can appear in
+ * | | a single packet, and are processed by a do {} while() loop.
+ * | +rle output of packet::PeekData(), in this case filled with 536 bytes
+ * | filled with the letter 'P' (brought to you by the letter 'Q' and the
+ * | number '9' :-))
+ * + packet::GetSize()
+ *
+ * If there is a header it will look more like:
+ * 536:N{317}@B.{6}HELLOP{206} *bytes from 10.1.0.2 [02-06-0a:01:00:02:20:00]\
+ * <219|317|0>
+ * 536:N{317}@B.{6}HELLOP{206} bytes from 10.1.0.2 [02-06-0a:01:00:02:20:00]\
+ * <0|206(13)|999794> (ArchHeader=HELLO:1000000)
+ * where you can see that this first packet includes 317 bytes from the
+ * previous send packet (filled with N) and 13 bytes of header before the 206
+ * bytes of payload (filled with P).
+ */
+
+#define RECV_PRINT
+
+// dcl non-method functions....
+std::string rle(const uint8_t *, int );
+std::ofstream fileOut("tcp-2way.out");
+
+//----------class ArchHeader dcl and definition---------------------------------
+/*
+ * ArchHeader: A toy header that holds a string
+ * and a uint32_t. The string is an abitrary label
+ * and the int is used as the length of the payload.
+ */
+
+class ArchHeader : public Header {
+public:
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator) const;
+ virtual uint32_t Deserialize (Buffer::Iterator);
+ virtual void Print (std::ostream &) const;
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+
+ // accessor functions.....
+ void SetIntValue (uint32_t);
+ uint32_t GetIntValue (void) const;
+ void SetStrValue (const std::string &s);
+ std::string GetStrValue (void) const;
+private:
+ uint32_t int_value;
+ std::string str_value;
+};
+
+
+TypeId
+ArchHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ArchHeader")
+ .AddConstructor<ArchHeader> () // NOTE: Required for ????
+ .SetParent<Header> () // ditto
+ ;
+ return tid;
+}
+
+TypeId
+ArchHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+ArchHeader::GetSerializedSize (void) const
+{
+ return 2*sizeof (uint32_t) + str_value.size (); // int, str len & bytes
+}
+
+void
+ArchHeader::Serialize (Buffer::Iterator i) const
+{
+ i.WriteU32 (int_value);
+ uint32_t str_len = str_value.size ();
+ i.WriteU32 (str_len);
+ for (uint32_t j = 0; j < str_value.size (); j++)
+ i.WriteU8 (str_value[j]);
+}
+
+uint32_t
+ArchHeader::Deserialize (Buffer::Iterator i)
+{
+ int_value = i.ReadU32 ();
+ uint32_t str_len = i.ReadU32 ();
+ str_value.reserve (str_len);
+ for (uint32_t j = 0; j < str_len; j++) {
+ char v = i.ReadU8 ();
+ str_value.push_back (v);
+ }
+ return 2*sizeof (uint32_t) + str_value.size ();
+}
+
+
+void
+ArchHeader::SetIntValue (uint32_t v_)
+{
+ int_value = v_;
+}
+
+uint32_t
+ArchHeader::GetIntValue (void) const
+{
+ return int_value;
+}
+
+void
+ArchHeader::SetStrValue (const std::string &s)
+{
+ str_value = s;
+}
+
+std::string
+ArchHeader::GetStrValue (void) const
+{
+ return str_value;
+}
+
+void
+ArchHeader::Print (std::ostream &os) const
+{
+ os << "(ArchHeader=" << str_value << ":" << int_value << ")";
+}
+
+//----------class TalkerApp dcl and definition----------------------------------
+/*
+ * TalkerApp:
+ * An an Application that can serve as both Rx and Tx side.
+ * and is configured by ConfRecv/ConfSend and driven by
+ * ScheduleSendPacket. Becareful not to try to send a packet
+ * from the Rx side to the Tx side (back channel) before the
+ * connection is setup, which has to be from the Tx to the Rx
+ * (the forward channel).
+ */
+
+class TalkerApp : public Application {
+public:
+ TalkerApp ();
+ virtual ~TalkerApp ();
+ void ConfRecv (Ptr<Node>,const Address &);
+ void ConfSend (Ptr<Node>,const Address &);
+ void ScheduleSendPacket(const Time ,const char , const uint32_t size );
+
+protected:
+ virtual void DoDispose (void);
+private:
+ virtual void StartApplication (void);
+ virtual void StopApplication (void);
+
+ void StartApplicationRecv (void);
+ void StartApplicationSend (void);
+
+ void HandleRead (Ptr<Socket>);
+ void SendPacket (std::string,char,uint32_t);
+
+ void CloseConnection (Ptr<Socket> socket);
+ void ConnectionSucceeded (Ptr<Socket>);
+ void ConnectionFailed (Ptr<Socket>);
+ bool ConnectionRequested (Ptr<Socket>, const Address &);
+ void ConnectionCreated (Ptr<Socket>, const Address &);
+
+
+ bool verbose;
+ Ptr<Socket> m_socket;
+ Ptr<Socket> m_servsocket;
+ Address m_local;
+ Address m_remote;
+ int i_am_listener;
+ typedef std::map<Ptr<Socket>, uint32_t>::iterator left_to_read_iterator_type;
+ std::map<Ptr<Socket>, uint32_t> m_left_to_read;
+};
+
+class TalkerApp_sub : public TalkerApp {
+public:
+ int foo(void);
+};
+
+int
+TalkerApp_sub::foo(void) {return 0;}
+
+TalkerApp::TalkerApp () :
+ verbose (false),
+ m_socket (0),
+ m_servsocket (0),
+ i_am_listener (0)
+{}
+
+TalkerApp::~TalkerApp ()
+{}
+
+void
+TalkerApp::DoDispose (void)
+{
+ m_socket = 0;
+ m_servsocket = 0;
+ Application::DoDispose ();
+}
+
+
+void
+TalkerApp::CloseConnection (Ptr<Socket> sock)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << sock
+ );
+ sock->Close ();
+}
+
+void
+TalkerApp::ConnectionSucceeded (Ptr<Socket> sock)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << sock
+
+ );
+}
+
+void
+TalkerApp::ConnectionFailed (Ptr<Socket> sock)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << sock
+ );
+}
+
+bool
+TalkerApp::ConnectionRequested (Ptr<Socket> sock, const Address &addr)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << sock
+ << addr
+ );
+ return true;
+}
+
+void
+TalkerApp::ConnectionCreated (Ptr<Socket> sock, const Address &addr)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << sock
+ << addr
+ );
+ m_socket = sock;
+ m_socket->SetRecvCallback(MakeCallback (&TalkerApp::HandleRead, this));
+}
+
+void
+TalkerApp::ScheduleSendPacket (const Time dt,const char fill,
+ const uint32_t size)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << dt
+ << fill
+ << size
+ );
+ Simulator::Schedule(dt,&TalkerApp::SendPacket, this,
+ std::string("HELLO"),fill,size);
+}
+
+
+void
+TalkerApp::StartApplication ()
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ );
+ if (i_am_listener)
+ StartApplicationRecv ();
+ else
+ StartApplicationSend ();
+}
+
+void
+TalkerApp::StartApplicationSend ()
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ );
+
+ if (!m_socket) {
+ m_socket = Socket::CreateSocket (GetNode (),
+ TcpSocketFactory::GetTypeId ());
+ m_socket->Bind ();
+ }
+
+ m_socket->Connect (m_remote);
+ m_socket->SetConnectCallback
+ (
+ MakeCallback (&TalkerApp::ConnectionSucceeded,this),
+ MakeCallback (&TalkerApp::ConnectionFailed,this)
+ );
+ m_socket->SetRecvCallback (MakeCallback (&TalkerApp::HandleRead, this));
+}
+
+void
+TalkerApp::StartApplicationRecv ()
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ );
+ if (!m_servsocket) {
+ m_servsocket = Socket::CreateSocket (GetNode (),
+ TcpSocketFactory::GetTypeId ());
+ m_servsocket->Bind (m_local);
+ m_servsocket->Listen (0);
+ }
+
+ m_servsocket->SetAcceptCallback
+ (
+ MakeCallback (&TalkerApp::ConnectionRequested,this),
+ MakeCallback (&TalkerApp::ConnectionCreated,this)
+ );
+}
+
+void
+TalkerApp::ConfRecv (Ptr<Node> node, const Address &addr)
+{
+ i_am_listener = 1;
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << node
+ << addr
+ );
+ m_local = addr;
+ node->AddApplication (this);
+}
+
+void
+TalkerApp::ConfSend (Ptr<Node> node, const Address &addr)
+{
+ i_am_listener = 0;
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << node
+ << addr
+ );
+ m_remote = addr;
+ node->AddApplication (this);
+}
+
+
+void
+TalkerApp::SendPacket (std::string label,char fill,uint32_t payloadsize)
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ << label
+ << fill
+ << payloadsize
+ );
+
+#if 0
+ Ptr<Packet> p = Create<Packet> (payloadsize); // zero byte filled packet.
+#else
+ uint8_t *buf = (uint8_t *) malloc(payloadsize*sizeof(uint8_t));
+ memset(buf,fill,payloadsize);
+ Ptr<Packet> p = Create<Packet> (buf,payloadsize); // filled packet.
+ free(buf);
+#endif
+ if (verbose) {
+ p->Print (fileOut << "Before Marking|");
+ fileOut << std::endl;
+ }
+
+ ArchHeader hdr;
+ hdr.SetStrValue (label);
+ hdr.SetIntValue (p->GetSize());
+ p->AddHeader (hdr);
+ if (verbose) {
+ p->Print(fileOut << "After Header Marking|");
+ fileOut << std::endl;
+ }
+
+ m_socket->Send (p);
+}
+
+void
+TalkerApp::StopApplication ()
+{
+ NS_LOG_FUNCTION ((i_am_listener ? "Server|" : "Client|")
+#ifdef PRINT_THIS
+ << this
+#endif
+ );
+ if (m_socket)
+ m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+}
+
+void
+TalkerApp::HandleRead (Ptr<Socket> socket)
+{
+ left_to_read_iterator_type iter = m_left_to_read.find (socket);
+ if (iter == m_left_to_read.end ())
+ m_left_to_read[socket] = 0;
+
+ std::ostringstream pretty;
+ pretty << (i_am_listener ? "Server" : "Client")
+ << (iter == m_left_to_read.end () ?
+ "(new)" : "(old)")
+ << "|";
+
+ NS_LOG_FUNCTION ( pretty.str ()
+#ifdef PRINT_THIS
+ << this
+#endif
+ << socket
+ );
+ /*
+ * NOTE: I can crash with the # bytes == 500 rather than 536
+ * which seems to be the default MTU
+ */
+
+#ifdef TOO_SMALL_BUG
+ const uint32_t number_of_bytes_willing_to_read = 500;
+#else
+ const uint32_t number_of_bytes_willing_to_read = 536;
+#endif
+ const uint32_t unused_flags = 0;
+
+ Ptr<Packet> packet;
+ while (packet = socket->Recv (number_of_bytes_willing_to_read,
+ unused_flags) ){
+ std::string raw_rle = rle(packet->PeekData(),
+ packet->GetSize());
+ SocketAddressTag rx_addr_tag;
+ bool found;
+ found = packet->FindFirstMatchingTag (rx_addr_tag);
+ NS_ASSERT (found);
+ Address from = rx_addr_tag.GetAddress ();
+ // XXX packet->RemoveTag (tag);
+ if (InetSocketAddress::IsMatchingType (from)) {
+ InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
+
+#ifdef VERBOSE_TESTING
+ packet->Print (fileOut << "Packet Dump: ");
+ fileOut << std::endl;
+#endif
+
+
+ bool freshly_in_the_loop = true;
+ do {
+#if defined(RECV_PRINT)
+ fileOut
+ << raw_rle // <length>:<rle of packet->PeekBuffer>
+ << (freshly_in_the_loop ? " *" : " ") /* used to see if the do while
+ * does anything */
+ << "bytes from "
+ << address.GetIpv4 () << " [" << address << "] ";
+#endif
+ freshly_in_the_loop = false;
+ int header_bytes = 0;
+ ArchHeader* hdr = 0; // sadly, can't be a Ptr<>
+ if (
+ (m_left_to_read[socket] == 0)
+ ) {
+ hdr = new ArchHeader;
+ if (packet->RemoveHeader (*hdr)) {
+ m_left_to_read[socket] = hdr->GetIntValue ();
+ header_bytes = hdr->GetSerializedSize ();
+ } else {
+ ; // never get here, ns3 dumps if no header is there.
+ }
+ }
+ uint32_t num_bytes_processed = 0;
+ if (m_left_to_read[socket] <= packet->GetSize ()) {
+ packet->RemoveAtStart (m_left_to_read[socket]);
+ num_bytes_processed = m_left_to_read[socket];
+ m_left_to_read[socket] = 0;
+
+ } else {
+ m_left_to_read[socket] -= packet->GetSize ();
+ num_bytes_processed = packet->GetSize ();
+ packet->RemoveAtStart (packet->GetSize ());
+ }
+
+#if defined(RECV_PRINT)
+ fileOut
+ << "<"
+ << packet->GetSize ()
+ << "|"
+ << num_bytes_processed
+ ;
+ if (header_bytes)
+ fileOut
+ << "("
+ << header_bytes
+ << ")"
+ ;
+ fileOut
+ << "|"
+ << m_left_to_read[socket]
+ << ">";
+#ifdef VERBOSE_TESTING
+ if (hdr)
+ hdr->Print(fileOut << " ");
+#endif
+ fileOut << std::endl;
+#endif
+ if (hdr)
+ delete hdr; // free what we new....
+ } while (
+ packet->GetSize ()
+ );
+ } else {
+ fileOut << "not a match in HandleRead" << std::endl;
+ }
+
+ }
+}
+
+//---------------Non-member functions-------------------------------------------
+/*
+ * returns a string containing the length of the buffer,
+ * followed by an run length encoded version of the buffer
+ * un-printables are represented by '.' (i.e. special_marker
+ * const).
+ */
+std::string rle(const uint8_t *buf, int buflen) {
+
+ int justify = 5;
+ std::ostringstream o;
+ const uint8_t min_rep = 3;
+ uint8_t cur_char = 0;
+ const uint8_t special_marker = '.';
+ int cur_cnt = 0;
+ if (justify) {
+ o << std::setw(justify) << std::right << buflen << ":";
+ } else {
+ o << buflen << ":";
+ }
+
+ for (int i = 0; i < buflen; i++) {
+ if (
+ (!isprint(buf[i]) && cur_char == special_marker) ||
+ (buf[i] == cur_char)
+ )
+ cur_cnt++;
+ else {
+ if (cur_cnt >= min_rep)
+ o << (isprint(cur_char) ? static_cast<char>(cur_char) : '.') << "{"
+ << cur_cnt << "}";
+ else
+ for (int irep=0; irep < cur_cnt; irep++)
+ o << (isprint(cur_char) ? static_cast<char>(cur_char) : '.');
+ if (isprint(buf[i]))
+ cur_char = buf[i];
+ else
+ cur_char = special_marker;
+ cur_cnt = 1;
+ }
+ }
+ if (cur_cnt >= min_rep)
+ o << (isprint(cur_char) ? static_cast<char>(cur_char) : '.') << "{"
+ << cur_cnt << "}";
+ else
+ for (int irep=0; irep < cur_cnt; irep++)
+ o << (isprint(cur_char) ? static_cast<char>(cur_char) : '.');
+ return o.str();
+}
+
+//---------------Main-----------------------------------------------------------
+int
+main (int argc, char *argv[]) {
+
+ std::clog.rdbuf (fileOut.rdbuf ()); /* till we can do this in ns3::log
+ * without this ns3 logging messages
+ * are far away from normal output
+ */
+
+#ifdef VERBOSE_TESTING
+ LogComponentEnable ("tcp-2way",LOG_LEVEL_ALL);
+#endif
+
+ RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
+ Packet::EnableMetadata ();
+
+ // boilerplate: "c0[0]" is Tx, "c0[1]" is Rx.
+ NodeContainer c0;
+ c0.Create (2);
+
+ // We create the channels first without any IP addressing information
+ PointToPointHelper p2p;
+ p2p.SetDeviceAttribute ("DataRate",DataRateValue (DataRate (10000000)));
+ p2p.SetChannelAttribute ("Delay",TimeValue (MilliSeconds (10)));
+ NetDeviceContainer dev0 = p2p.Install (c0);
+
+ // add ip/tcp stack to nodes.
+ InternetStackHelper internet;
+ internet.Install (c0);
+
+ // Later, we add IP addresses.
+ Ipv4AddressHelper ipv4;
+ ipv4.SetBase ("10.1.0.0", "255.255.255.0");
+ Ipv4InterfaceContainer ifaces = ipv4.Assign (dev0);
+
+ // Configure the apps.
+ uint16_t servPort = 32;
+
+
+ // setup Rx side using ns3::Node "c0[1]" to listen for ANY:servPort
+ Ptr<TalkerApp> sink = CreateObject<TalkerApp_sub>();
+ sink->ConfRecv (c0.Get (1),
+ InetSocketAddress (Ipv4Address::GetAny (), servPort));
+ sink->Start (Seconds (0.0)); // somehow we get by without a Stop. bad form?
+
+ // setup Tx side using ns3::Node "c0[0]" to talk to "c0[1]":servPort
+ Ptr<TalkerApp> source = CreateObject<TalkerApp_sub>();
+ source->ConfSend (c0.Get (0),
+ InetSocketAddress (ifaces.GetAddress (1),
+ servPort));
+ source->Start (Seconds (0.0));
+
+ // 10 sec is an eternity for this case, we should be done by then.
+ Simulator::Stop (Seconds (10));
+
+
+ // For regression use only output ascii and pcap traces.
+#ifdef REGRESSION_MODE
+ std::ofstream ascii;
+ ascii.open ("tcp-2way.tr");
+ PointToPointHelper::EnableAsciiAll (ascii);
+ PointToPointHelper::EnablePcapAll ("tcp-2way");
+#endif
+
+ /*
+ * Now lets schedule some packets and go. For scheduling packets
+ * we have to be careful not to do the backchannel too early or
+ * we try to use a socket that doesn't yet exist since on the Rx
+ * side the socket is created as part of the normal Tx->Rx connection
+ * setup.
+ *
+ * The delay of 40ms was by trial and error and seems good enough. It
+ * would be nice to know what the bounds are and why....
+ */
+
+ char tagchar = 'A'; // the fill character in case we fill in SendPacket.
+
+ Time d2t = MilliSeconds(40); /* rate to change time offset (dt) so packets
+ * are sent in order (Tx->Rx, Rx->Tx for a given
+ * size over a range of sizes).*/
+
+ Time dt = MilliSeconds(0); /* ns3 doesn't take absolute times, but times
+ * relative to Simulator::Now() */
+
+ uint32_t size = 0;
+ source->ScheduleSendPacket (dt, tagchar, size);
+ dt += d2t;
+ ++tagchar;
+ sink->ScheduleSendPacket (dt, tagchar, size);
+ for (size = 1; size <= 1000000; size *= 10) {
+ dt += d2t;
+ ++tagchar;
+ source->ScheduleSendPacket (dt, tagchar, size);
+ dt += d2t;
+ ++tagchar;
+ sink->ScheduleSendPacket (dt, tagchar, size);
+ }
+
+ // Release the Hounds!!
+ Simulator::Run ();
+ Simulator::Destroy ();
+ fileOut.close();
+}
--- a/examples/wscript Wed Jul 09 18:50:28 2008 +0100
+++ b/examples/wscript Fri Jul 11 18:15:52 2008 +0100
@@ -56,6 +56,10 @@
['point-to-point', 'internet-stack'])
obj.source = 'tcp-errors.cc'
+ obj = bld.create_ns3_program('tcp-2way',
+ ['point-to-point', 'internet-stack'])
+ obj.source = 'tcp-2way.cc'
+
obj = bld.create_ns3_program('tcp-star-server',
['point-to-point', 'internet-stack'])
obj.source = 'tcp-star-server.cc'
--- a/src/common/buffer.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/common/buffer.cc Fri Jul 11 18:15:52 2008 +0100
@@ -1128,6 +1128,12 @@
return ~sum;
}
+uint32_t
+Buffer::Iterator::GetSize (void) const
+{
+ return m_dataEnd - m_dataStart;
+}
+
} // namespace ns3
--- a/src/common/buffer.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/common/buffer.h Fri Jul 11 18:15:52 2008 +0100
@@ -358,6 +358,11 @@
*/
uint16_t CalculateIpChecksum(uint16_t size, uint32_t initialChecksum);
+ /**
+ * \returns the size of the underlying buffer we are iterating
+ */
+ uint32_t GetSize (void) const;
+
private:
friend class Buffer;
Iterator (Buffer const*buffer);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/deprecated.h Fri Jul 11 18:15:52 2008 +0100
@@ -0,0 +1,10 @@
+#ifndef NS3_DEPRECATED_H
+#define NS3_DEPRECATED_H
+
+#ifdef __GNUC__
+#define NS_DEPRECATED __attribute__ ((deprecated))
+#else
+#define NS_DEPRECATED
+#endif
+
+#endif /* NS3_DEPRECATED_H */
--- a/src/core/wscript Wed Jul 09 18:50:28 2008 +0100
+++ b/src/core/wscript Fri Jul 11 18:15:52 2008 +0100
@@ -110,5 +110,6 @@
'trace-source-accessor.h',
'config.h',
'object-vector.h',
+ 'deprecated.h'
]
--- a/src/helper/csma-helper.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/helper/csma-helper.cc Fri Jul 11 18:15:52 2008 +0100
@@ -64,6 +64,17 @@
}
void
+CsmaHelper::SetDeviceParameter (std::string n1, const AttributeValue &v1)
+{
+ SetDeviceAttribute (n1, v1);
+}
+void
+CsmaHelper::SetChannelParameter (std::string n1, const AttributeValue &v1)
+{
+ SetChannelAttribute (n1, v1);
+}
+
+void
CsmaHelper::EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid)
{
std::ostringstream oss;
--- a/src/helper/csma-helper.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/helper/csma-helper.h Fri Jul 11 18:15:52 2008 +0100
@@ -27,6 +27,7 @@
#include "ns3/net-device-container.h"
#include "ns3/node-container.h"
#include "ns3/csma-channel.h"
+#include "ns3/deprecated.h"
namespace ns3 {
@@ -79,6 +80,9 @@
*/
void SetChannelAttribute (std::string n1, const AttributeValue &v1);
+ void SetDeviceParameter (std::string n1, const AttributeValue &v1) NS_DEPRECATED;
+ void SetChannelParameter (std::string n1, const AttributeValue &v1) NS_DEPRECATED;
+
/**
* \param filename filename prefix to use for pcap files.
* \param nodeid the id of the node to generate pcap output for.
--- a/src/helper/point-to-point-helper.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/helper/point-to-point-helper.cc Fri Jul 11 18:15:52 2008 +0100
@@ -64,6 +64,17 @@
}
void
+PointToPointHelper::SetDeviceParameter (std::string name, const AttributeValue &value)
+{
+ SetDeviceAttribute (name, value);
+}
+void
+PointToPointHelper::SetChannelParameter (std::string name, const AttributeValue &value)
+{
+ SetChannelAttribute (name, value);
+}
+
+void
PointToPointHelper::EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid)
{
std::ostringstream oss;
--- a/src/helper/point-to-point-helper.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/helper/point-to-point-helper.h Fri Jul 11 18:15:52 2008 +0100
@@ -23,6 +23,7 @@
#include "ns3/object-factory.h"
#include "ns3/net-device-container.h"
#include "ns3/node-container.h"
+#include "ns3/deprecated.h"
#include <string>
namespace ns3 {
@@ -78,6 +79,9 @@
*/
void SetChannelAttribute (std::string name, const AttributeValue &value);
+ void SetDeviceParameter (std::string name, const AttributeValue &value) NS_DEPRECATED;
+ void SetChannelParameter (std::string name, const AttributeValue &value) NS_DEPRECATED;
+
/**
* \param filename filename prefix to use for pcap files.
* \param nodeid the id of the node to generate pcap output for.
--- a/src/internet-stack/tcp-header.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/tcp-header.cc Fri Jul 11 18:15:52 2008 +0100
@@ -23,6 +23,7 @@
#include "tcp-socket-impl.h"
#include "tcp-header.h"
#include "ns3/buffer.h"
+#include "ns3/address-utils.h"
namespace ns3 {
@@ -37,8 +38,6 @@
m_flags (0),
m_windowSize (0xffff),
m_urgentPointer (0),
- m_initialChecksum(0),
- m_checksum (0),
m_calcChecksum(false),
m_goodChecksum(true)
{}
@@ -52,11 +51,6 @@
m_calcChecksum = true;
}
-void TcpHeader::SetPayloadSize(uint16_t payloadSize)
-{
- m_payloadSize = payloadSize;
-}
-
void TcpHeader::SetSourcePort (uint16_t port)
{
m_sourcePort = port;
@@ -85,10 +79,6 @@
{
m_windowSize = windowSize;
}
-void TcpHeader::SetChecksum (uint16_t checksum)
-{
- m_checksum = checksum;
-}
void TcpHeader::SetUrgentPointer (uint16_t urgentPointer)
{
m_urgentPointer = urgentPointer;
@@ -122,10 +112,6 @@
{
return m_windowSize;
}
-uint16_t TcpHeader::GetChecksum () const
-{
- return m_checksum;
-}
uint16_t TcpHeader::GetUrgentPointer () const
{
return m_urgentPointer;
@@ -133,29 +119,31 @@
void
TcpHeader::InitializeChecksum (Ipv4Address source,
- Ipv4Address destination,
- uint8_t protocol)
+ Ipv4Address destination,
+ uint8_t protocol)
{
- Buffer buf = Buffer(12);
- uint8_t tmp[4];
- Buffer::Iterator it;
- uint16_t tcpLength = m_payloadSize + GetSerializedSize();
-
- buf.AddAtStart(12);
- it = buf.Begin();
+ m_source = source;
+ m_destination = destination;
+ m_protocol = protocol;
+}
- source.Serialize(tmp);
- it.Write(tmp, 4); /* source IP address */
- destination.Serialize(tmp);
- it.Write(tmp, 4); /* destination IP address */
- it.WriteU8(0); /* protocol */
- it.WriteU8(protocol); /* protocol */
- it.WriteU8(tcpLength >> 8); /* length */
- it.WriteU8(tcpLength & 0xff); /* length */
+uint16_t
+TcpHeader::CalculateHeaderChecksum (uint16_t size) const
+{
+ Buffer buf = Buffer (12);
+ buf.AddAtStart (12);
+ Buffer::Iterator it = buf.Begin ();
- it = buf.Begin();
+ WriteTo (it, m_source);
+ WriteTo (it, m_destination);
+ it.WriteU8 (0); /* protocol */
+ it.WriteU8 (m_protocol); /* protocol */
+ it.WriteU8 (size >> 8); /* length */
+ it.WriteU8 (size & 0xff); /* length */
+
+ it = buf.Begin ();
/* we don't CompleteChecksum ( ~ ) now */
- m_initialChecksum = ~(it.CalculateIpChecksum(12));
+ return ~(it.CalculateIpChecksum (12));
}
bool
@@ -219,7 +207,6 @@
void TcpHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
- uint16_t tcpLength = m_payloadSize + GetSerializedSize();
i.WriteHtonU16 (m_sourcePort);
i.WriteHtonU16 (m_destinationPort);
i.WriteHtonU32 (m_sequenceNumber);
@@ -231,8 +218,9 @@
if(m_calcChecksum)
{
+ uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
- uint16_t checksum = i.CalculateIpChecksum(tcpLength, m_initialChecksum);
+ uint16_t checksum = i.CalculateIpChecksum(start.GetSize (), headerChecksum);
i = start;
i.Next(16);
@@ -250,16 +238,16 @@
m_flags = field & 0x3F;
m_length = field>>12;
m_windowSize = i.ReadNtohU16 ();
- m_checksum = i.ReadU16 ();
+ i.Next (2);
m_urgentPointer = i.ReadNtohU16 ();
if(m_calcChecksum)
- {
+ {
+ uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
- uint16_t checksum = i.CalculateIpChecksum(m_payloadSize + GetSerializedSize(), m_initialChecksum);
-
+ uint16_t checksum = i.CalculateIpChecksum(start.GetSize (), headerChecksum);
m_goodChecksum = (checksum == 0);
- }
+ }
return GetSerializedSize ();
}
--- a/src/internet-stack/tcp-header.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/tcp-header.h Fri Jul 11 18:15:52 2008 +0100
@@ -78,10 +78,6 @@
*/
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);
@@ -117,10 +113,6 @@
*/
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;
@@ -151,17 +143,13 @@
virtual uint32_t Deserialize (Buffer::Iterator start);
/**
- * \param size The payload size in bytes
- */
- void SetPayloadSize (uint16_t size);
-
- /**
* \brief Is the TCP checksum correct ?
* \returns true if the checksum is correct, false otherwise.
*/
bool IsChecksumOk (void) const;
private:
+ uint16_t CalculateHeaderChecksum (uint16_t size) const;
uint16_t m_sourcePort;
uint16_t m_destinationPort;
uint32_t m_sequenceNumber;
@@ -170,13 +158,14 @@
uint8_t m_flags; // really a uint6_t
uint16_t m_windowSize;
uint16_t m_urgentPointer;
- uint16_t m_payloadSize;
+
+ Ipv4Address m_source;
+ Ipv4Address m_destination;
+ uint8_t m_protocol;
+
uint16_t m_initialChecksum;
- uint16_t m_checksum;
-
bool m_calcChecksum;
bool m_goodChecksum;
-
};
}; // namespace ns3
--- a/src/internet-stack/tcp-l4-protocol.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/tcp-l4-protocol.cc Fri Jul 11 18:15:52 2008 +0100
@@ -448,6 +448,7 @@
if(m_calcChecksum)
{
tcpHeader.EnableChecksums();
+ tcpHeader.InitializeChecksum (source, destination, PROT_NUMBER);
}
packet->PeekHeader (tcpHeader);
@@ -495,7 +496,6 @@
TcpHeader tcpHeader;
tcpHeader.SetDestinationPort (dport);
tcpHeader.SetSourcePort (sport);
- tcpHeader.SetPayloadSize(packet->GetSize());
if(m_calcChecksum)
{
tcpHeader.EnableChecksums();
@@ -529,7 +529,6 @@
// XXX outgoingHeader cannot be logged
outgoingHeader.SetLength (5); //header length in units of 32bit words
- outgoingHeader.SetPayloadSize(packet->GetSize());
/* outgoingHeader.SetUrgentPointer (0); //XXX */
if(m_calcChecksum)
{
--- a/src/internet-stack/tcp-socket-impl.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/tcp-socket-impl.h Fri Jul 11 18:15:52 2008 +0100
@@ -50,7 +50,13 @@
* This class contains an implementation of TCP Tahoe, as well as a sockets
* interface for talking to TCP. Features include connection orientation,
* reliability through cumulative acknowledgements, congestion and flow
- * control. Finite send/receive buffer semantics are modeled.
+ * control. Finite send buffer semantics are modeled, but as of yet, finite
+ * receive buffer modelling is unimplemented.
+ *
+ * The closedown of these sockets is as of yet not compliant with the relevent
+ * RFCs, i.e. the FIN handshaking isn't correct. While this is visible at the
+ * PCAP tracing level, it has no effect on the statistics users are interested
+ * in, i.e. throughput, delay, etc. of actual payload data.
*
* Asynchronous callbacks to provide notifications to higher layers that a
* protocol event has occured, such as space freeing up in the send buffer
--- a/src/internet-stack/udp-header.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/udp-header.cc Fri Jul 11 18:15:52 2008 +0100
@@ -19,6 +19,7 @@
*/
#include "udp-header.h"
+#include "ns3/address-utils.h"
namespace ns3 {
@@ -32,8 +33,6 @@
: m_sourcePort (0xfffd),
m_destinationPort (0xfffd),
m_payloadSize (0xfffd),
- m_initialChecksum (0),
- m_checksum(0),
m_calcChecksum(false),
m_goodChecksum(true)
{}
@@ -71,35 +70,31 @@
return m_destinationPort;
}
void
-UdpHeader::SetPayloadSize (uint16_t size)
-{
- m_payloadSize = size;
-}
-void
UdpHeader::InitializeChecksum (Ipv4Address source,
Ipv4Address destination,
uint8_t protocol)
{
- Buffer buf = Buffer(12);
- uint8_t tmp[4];
- Buffer::Iterator it;
- uint16_t udpLength = m_payloadSize + GetSerializedSize();
-
- buf.AddAtStart(12);
- it = buf.Begin();
+ m_source = source;
+ m_destination = destination;
+ m_protocol = protocol;
+}
+uint16_t
+UdpHeader::CalculateHeaderChecksum (uint16_t size) const
+{
+ Buffer buf = Buffer (12);
+ buf.AddAtStart (12);
+ Buffer::Iterator it = buf.Begin ();
- source.Serialize(tmp);
- it.Write(tmp, 4); /* source IP address */
- destination.Serialize(tmp);
- it.Write(tmp, 4); /* destination IP address */
- it.WriteU8(0); /* protocol */
- it.WriteU8(protocol); /* protocol */
- it.WriteU8(udpLength >> 8); /* length */
- it.WriteU8(udpLength & 0xff); /* length */
+ WriteTo (it, m_source);
+ WriteTo (it, m_destination);
+ it.WriteU8 (0); /* protocol */
+ it.WriteU8 (m_protocol); /* protocol */
+ it.WriteU8 (size >> 8); /* length */
+ it.WriteU8 (size & 0xff); /* length */
- it = buf.Begin();
+ it = buf.Begin ();
/* we don't CompleteChecksum ( ~ ) now */
- m_initialChecksum = ~(it.CalculateIpChecksum(12));
+ return ~(it.CalculateIpChecksum (12));
}
bool
@@ -142,17 +137,17 @@
UdpHeader::Serialize (Buffer::Iterator start) const
{
Buffer::Iterator i = start;
- uint16_t udpLength = m_payloadSize + GetSerializedSize();
i.WriteHtonU16 (m_sourcePort);
i.WriteHtonU16 (m_destinationPort);
- i.WriteHtonU16 (udpLength);
+ i.WriteHtonU16 (start.GetSize ());
i.WriteU16 (0);
if (m_calcChecksum)
{
+ uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
- uint16_t checksum = i.CalculateIpChecksum(udpLength, m_initialChecksum);
+ uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
i = start;
i.Next(6);
@@ -166,12 +161,13 @@
m_sourcePort = i.ReadNtohU16 ();
m_destinationPort = i.ReadNtohU16 ();
m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
- m_checksum = i.ReadU16();
+ i.Next (2);
if(m_calcChecksum)
{
+ uint16_t headerChecksum = CalculateHeaderChecksum (start.GetSize ());
i = start;
- uint16_t checksum = i.CalculateIpChecksum(m_payloadSize + GetSerializedSize(), m_initialChecksum);
+ uint16_t checksum = i.CalculateIpChecksum (start.GetSize (), headerChecksum);
m_goodChecksum = (checksum == 0);
}
--- a/src/internet-stack/udp-header.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/udp-header.h Fri Jul 11 18:15:52 2008 +0100
@@ -66,10 +66,6 @@
* \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
@@ -100,12 +96,14 @@
bool IsChecksumOk (void) const;
private:
+ uint16_t CalculateHeaderChecksum (uint16_t size) const;
uint16_t m_sourcePort;
uint16_t m_destinationPort;
uint16_t m_payloadSize;
- uint16_t m_initialChecksum;
- uint16_t m_checksum;
+ Ipv4Address m_source;
+ Ipv4Address m_destination;
+ uint8_t m_protocol;
bool m_calcChecksum;
bool m_goodChecksum;
};
--- a/src/internet-stack/udp-l4-protocol.cc Wed Jul 09 18:50:28 2008 +0100
+++ b/src/internet-stack/udp-l4-protocol.cc Fri Jul 11 18:15:52 2008 +0100
@@ -163,7 +163,6 @@
udpHeader.EnableChecksums();
}
- udpHeader.SetPayloadSize (packet->GetSize () - udpHeader.GetSerializedSize ());
udpHeader.InitializeChecksum (source, destination, PROT_NUMBER);
packet->RemoveHeader (udpHeader);
@@ -195,13 +194,12 @@
if(m_calcChecksum)
{
udpHeader.EnableChecksums();
+ udpHeader.InitializeChecksum (saddr,
+ daddr,
+ PROT_NUMBER);
}
udpHeader.SetDestinationPort (dport);
udpHeader.SetSourcePort (sport);
- udpHeader.SetPayloadSize (packet->GetSize ());
- udpHeader.InitializeChecksum (saddr,
- daddr,
- PROT_NUMBER);
packet->AddHeader (udpHeader);
--- a/src/node/tcp-socket-factory.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/node/tcp-socket-factory.h Fri Jul 11 18:15:52 2008 +0100
@@ -48,8 +48,6 @@
public:
static TypeId GetTypeId (void);
- virtual Ptr<Socket> CreateSocket (void) = 0;
-
};
} // namespace ns3
--- a/src/node/udp-socket-factory.h Wed Jul 09 18:50:28 2008 +0100
+++ b/src/node/udp-socket-factory.h Fri Jul 11 18:15:52 2008 +0100
@@ -42,14 +42,6 @@
public:
static TypeId GetTypeId (void);
- /**
- * \return smart pointer to Socket
- *
- * API for creating socket instances; must be implemented by UDP
- * implementations..
- */
- virtual Ptr<Socket> CreateSocket (void) = 0;
-
};
} // namespace ns3
--- a/wscript Wed Jul 09 18:50:28 2008 +0100
+++ b/wscript Fri Jul 11 18:15:52 2008 +0100
@@ -197,7 +197,7 @@
if (os.path.basename(conf.env['CXX']).startswith("g++")
and 'CXXFLAGS' not in os.environ):
- variant_env.append_value('CXXFLAGS', ['-Werror'])
+ variant_env.append_value('CXXFLAGS', ['-Werror', '-Wno-error=deprecated-declarations'])
if 'debug' in Params.g_options.debug_level.lower():
variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')