View | Details | Raw Unified | Return to bug 227
Collapse All | Expand All

(-)a/examples/tcp-large-transfer.cc (-85 / +91 lines)
 Lines 25-36    Link Here 
25
// - Tracing of queues and packet receptions to file 
25
// - Tracing of queues and packet receptions to file 
26
//   "tcp-large-transfer.tr"
26
//   "tcp-large-transfer.tr"
27
// - pcap traces also generated in the following files
27
// - pcap traces also generated in the following files
28
//   "tcp-large-transfer.pcap-$n-$i" where n and i represent node and interface numbers respectively
28
//   "tcp-large-transfer-$n-$i.pcap" where n and i represent node and interface
29
// numbers respectively
29
//  Usage (e.g.): ./waf --run tcp-large-transfer
30
//  Usage (e.g.): ./waf --run tcp-large-transfer
30
31
31
//XXX this isn't working as described right now
32
//it is just blasting away for 10 seconds, with no fixed amount of data
33
//being sent
34
32
35
#include <ctype.h>
33
#include <ctype.h>
36
#include <iostream>
34
#include <iostream>
 Lines 48-84   using namespace ns3; Link Here 
48
46
49
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
47
NS_LOG_COMPONENT_DEFINE ("TcpLargeTransfer");
50
48
51
void 
49
// The number of bytes to send in this simulation.
52
ApplicationTraceSink (Ptr<const Packet> packet,
50
static uint32_t txBytes = 2000000;
53
                      const Address &addr)
51
54
{
52
// These are for starting the writing process, and handling the sending 
55
// g_log is not declared in optimized builds
53
// socket's notification upcalls (events).  These two together more or less
56
// should convert this to use of some other flag than the logging system
54
// implement a sending "Application", although not a proper ns3::Application
57
#ifdef NS3_LOG_ENABLE
55
// subclass.
58
  if (!g_log.IsNoneEnabled ()) {
56
59
    if (InetSocketAddress::IsMatchingType (addr) )
57
void StartFlow(Ptr<Socket>, Ipv4Address, uint16_t);
60
      {
61
      InetSocketAddress address = InetSocketAddress::ConvertFrom (addr);
62
        std::cout << "PacketSink received size " << 
63
        packet->GetSize () << " at time " << 
64
        Simulator::Now ().GetSeconds () << " from address: " << 
65
        address.GetIpv4 () << std::endl;
66
        char buf[2000]; 
67
        memcpy(buf, packet->PeekData (), packet->GetSize ());
68
        for (uint32_t i=0; i < packet->GetSize (); i++)
69
          {
70
            std::cout << buf[i];
71
            if (i && i % 60 == 0) 
72
              std::cout << std::endl; 
73
          }
74
        std::cout << std::endl << std::endl;
75
    }
76
  }
77
#endif
78
}
79
80
void CloseConnection (Ptr<Socket> localSocket);
81
void StartFlow(Ptr<Socket>, uint32_t, Ipv4Address, uint16_t);
82
void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
58
void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
83
59
84
int main (int argc, char *argv[])
60
int main (int argc, char *argv[])
 Lines 101-127   int main (int argc, char *argv[]) Link Here 
101
  CommandLine cmd;
77
  CommandLine cmd;
102
  cmd.Parse (argc, argv);
78
  cmd.Parse (argc, argv);
103
79
104
  // Here, we will explicitly create three nodes. 
80
  // Here, we will explicitly create three nodes.  The first container contains
105
  NodeContainer c0;
81
  // nodes 0 and 1 from the diagram above, and the second one contains nodes
106
  c0.Create (2);
82
  // 1 and 2.  This reflects the channel connectivity, and will be used to
107
83
  // install the network interfaces and connect them with a channel.
108
  NodeContainer c1;
84
  NodeContainer n0n1;
109
  c1.Add (c0.Get (1));
85
  n0n1.Create (2);
110
  c1.Create (1);
86
87
  NodeContainer n1n2;
88
  n1n2.Add (n0n1.Get (1));
89
  n1n2.Create (1);
111
90
112
  // We create the channels first without any IP addressing information
91
  // We create the channels first without any IP addressing information
92
  // First make and configure the helper, so that it will put the appropriate
93
  // parameters on the network interfaces and channels we are about to install.
113
  PointToPointHelper p2p;
94
  PointToPointHelper p2p;
114
  p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate(10000000)));
95
  p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate(10000000)));
115
  p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds(10)));
96
  p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds(10)));
116
  NetDeviceContainer dev0 = p2p.Install (c0);
97
117
  NetDeviceContainer dev1 = p2p.Install (c1);
98
  // And then install devices and channels connecting our topology.
118
99
  NetDeviceContainer dev0 = p2p.Install (n0n1);
119
  // add ip/tcp stack to nodes.
100
  NetDeviceContainer dev1 = p2p.Install (n1n2);
120
  NodeContainer c = NodeContainer (c0, c1.Get (1));
101
102
  // Now add ip/tcp stack to all nodes.
103
  NodeContainer allNodes = NodeContainer (n0n1, n1n2.Get (1));
121
  InternetStackHelper internet;
104
  InternetStackHelper internet;
122
  internet.Install (c);
105
  internet.Install (allNodes);
123
106
124
  // Later, we add IP addresses.  
107
  // Later, we add IP addresses.
125
  Ipv4AddressHelper ipv4;
108
  Ipv4AddressHelper ipv4;
126
  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
109
  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
127
  ipv4.Assign (dev0);
110
  ipv4.Assign (dev0);
 Lines 133-214   int main (int argc, char *argv[]) Link Here 
133
116
134
  ///////////////////////////////////////////////////////////////////////////
117
  ///////////////////////////////////////////////////////////////////////////
135
  // Simulation 1
118
  // Simulation 1
136
  // 
119
  //
137
  // Send 2000000 bytes over a connection to server port 50000 at time 0
120
  // Send 2000000 bytes over a connection to server port 50000 at time 0
138
  // Should observe SYN exchange, a lot of data segments, and FIN exchange
121
  // Should observe SYN exchange, a lot of data segments and ACKS, and FIN 
122
  // exchange.  FIN exchange isn't quite compliant with TCP spec (see release
123
  // notes for more info)
139
  //
124
  //
140
  ///////////////////////////////////////////////////////////////////////////
125
  ///////////////////////////////////////////////////////////////////////////
141
126
142
  int nBytes = 2000000;
143
  uint16_t servPort = 50000;
127
  uint16_t servPort = 50000;
144
128
145
  // Create a packet sink to receive these packets
129
  // Create a packet sink to receive these packets on n2...
146
  PacketSinkHelper sink ("ns3::TcpSocketFactory",
130
  PacketSinkHelper sink ("ns3::TcpSocketFactory",
147
                         InetSocketAddress (Ipv4Address::GetAny (), servPort));
131
                         InetSocketAddress (Ipv4Address::GetAny (), servPort));
148
132
149
  ApplicationContainer apps = sink.Install (c1.Get (1));
133
  ApplicationContainer apps = sink.Install (n1n2.Get (1));
150
  apps.Start (Seconds (0.0));
134
  apps.Start (Seconds (0.0));
151
135
152
  // and generate traffic to remote sink.
136
  // Create a source to send packets from n0.  Instead of a full Application
153
  //TypeId tid = TypeId::LookupByName ("ns3::TcpSocketFactory");
137
  // and the helper APIs you might see in other example files, this example
154
  Ptr<Socket> localSocket = Socket::CreateSocket (c0.Get (0), TcpSocketFactory::GetTypeId ());
138
  // will use sockets directly and register some socket callbacks as a sending
139
  // "Application".
140
141
  // Create and bind the socket...
142
  Ptr<Socket> localSocket =
143
      Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId ());
155
  localSocket->Bind ();
144
  localSocket->Bind ();
156
  Simulator::ScheduleNow (&StartFlow, localSocket, nBytes,
145
146
  // ...and schedule the sending "Application"; This is similar to what an 
147
  // ns3::Application subclass would do internally.
148
  Simulator::ScheduleNow (&StartFlow, localSocket,
157
                          ipInterfs.GetAddress (1), servPort);
149
                          ipInterfs.GetAddress (1), servPort);
158
150
159
  Config::ConnectWithoutContext ("/NodeList/*/ApplicationList/*/Rx", 
151
  // One can toggle the comment for the following line on or off to see the
160
                   MakeCallback (&ApplicationTraceSink));
152
  // effects of finite send buffer modelling.  One can also change the size of
161
153
  // said buffer.
154
155
  //localSocket->SetAttribute("SndBufSize", UintegerValue(4096));
156
157
  //Ask for ASCII and pcap traces of network traffic
162
  std::ofstream ascii;
158
  std::ofstream ascii;
163
  ascii.open ("tcp-large-transfer.tr");
159
  ascii.open ("tcp-large-transfer.tr");
164
  PointToPointHelper::EnableAsciiAll (ascii);
160
  PointToPointHelper::EnableAsciiAll (ascii);
165
161
166
  PointToPointHelper::EnablePcapAll ("tcp-large-transfer");
162
  PointToPointHelper::EnablePcapAll ("tcp-large-transfer");
167
163
164
  // Finally, set up the simulator to run.  The 1000 second hard limit is a
165
  // failsafe in case some change above causes the simulation to never end
168
  Simulator::Stop (Seconds(1000));
166
  Simulator::Stop (Seconds(1000));
169
  Simulator::Run ();
167
  Simulator::Run ();
170
  Simulator::Destroy ();
168
  Simulator::Destroy ();
171
}
169
}
172
170
173
void CloseConnection (Ptr<Socket> localSocket)
171
174
{
172
//-----------------------------------------------------------------------------
175
  localSocket->Close ();
173
//-----------------------------------------------------------------------------
176
}
174
//-----------------------------------------------------------------------------
177
175
//begin implementation of sending "Application"
178
void StartFlow(Ptr<Socket> localSocket, uint32_t nBytes, 
176
void StartFlow(Ptr<Socket> localSocket,
179
               Ipv4Address servAddress,
177
               Ipv4Address servAddress,
180
               uint16_t servPort)
178
               uint16_t servPort)
181
{
179
{
182
 // NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
180
  NS_LOG_LOGIC("Starting flow at time " <<  Simulator::Now ().GetSeconds ());
183
  localSocket->Connect (InetSocketAddress (servAddress, servPort));//connect
181
  localSocket->Connect (InetSocketAddress (servAddress, servPort));//connect
184
  localSocket->SetConnectCallback (MakeCallback (&CloseConnection),
182
185
                                   Callback<void, Ptr<Socket> > ());
183
  // tell the tcp implementation to call WriteUntilBufferFull again
186
  //we want to close as soon as the connection is established
184
  // if we blocked and new tx buffer space becomes available
187
  //the tcp state machine and outgoing buffer will assure that
188
  //all of the data is delivered
189
  localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
185
  localSocket->SetSendCallback (MakeCallback (&WriteUntilBufferFull));
190
  WriteUntilBufferFull (localSocket, nBytes);
186
  WriteUntilBufferFull (localSocket, txBytes);
191
}
187
}
192
188
193
void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t nBytes)
189
void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace)
194
{
190
{
195
  // Perform series of 1040 byte writes (this is a multiple of 26 since
191
  // Perform series of 1040 byte writes (this is a multiple of 26 since
196
  // we want to detect data splicing in the output stream)
192
  // we want to detect data splicing in the output stream)
197
  uint32_t writeSize = 1040;
193
  uint32_t writeSize = 1040;
198
  uint8_t data[writeSize];
194
  uint8_t data[writeSize];
199
  while (nBytes > 0) {
195
200
    uint32_t curSize= nBytes > writeSize ? writeSize : nBytes;
196
  while (txBytes > 0) {
197
    uint32_t curSize= txBytes > writeSize ? writeSize : txBytes;
198
    if (curSize > txSpace)
199
      curSize = txSpace;
201
    for(uint32_t i = 0; i < curSize; ++i)
200
    for(uint32_t i = 0; i < curSize; ++i)
202
    {
201
    {
203
      char m = toascii (97 + i % 26);
202
      char m = toascii (97 + i % 26);
204
      data[i] = m;
203
      data[i] = m;
205
    }
204
    }
206
    uint32_t amountSent = localSocket->Send (data, curSize, 0);
205
    int amountSent = localSocket->Send (data, curSize, 0);
207
    if(amountSent < curSize)
206
    if(amountSent < 0)
208
      {
207
      {
209
        std::cout << "Socket blocking, returning" << std::endl;
208
        // we will be called again when new tx space becomes available.
209
        std::cout << "Socket blocking, " << txBytes << " left to write, returning" << std::endl;
210
        return;
210
        return;
211
      }
211
      }
212
    nBytes -= curSize;
212
    txBytes -= curSize;
213
    if (amountSent != (int)curSize)
214
      {
215
        std::cout << "Short Write, returning" << std::endl;
216
        return;
217
      }
213
  }
218
  }
214
}
219
  localSocket->Close ();
220
}

Return to bug 227