|
|
|
1 |
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
2 |
/* |
3 |
* Copyright (c) 2016 Natale Patriciello <natale.patriciello@gmail.com> |
4 |
* |
5 |
* This program is free software; you can redistribute it and/or modify |
6 |
* it under the terms of the GNU General Public License version 2 as |
7 |
* published by the Free Software Foundation; |
8 |
* |
9 |
* This program is distributed in the hope that it will be useful, |
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
* GNU General Public License for more details. |
13 |
* |
14 |
* You should have received a copy of the GNU General Public License |
15 |
* along with this program; if not, write to the Free Software |
16 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 |
* |
18 |
*/ |
19 |
|
20 |
#include "../internet/test/tcp-general-test.h" |
21 |
#include "ns3/point-to-point-module.h" |
22 |
#include "ns3/antenna-module.h" |
23 |
|
24 |
#include "ns3/propagation-module.h" |
25 |
#include "ns3/mobility-module.h" |
26 |
#include "ns3/test.h" |
27 |
#include "ns3/internet-module.h" |
28 |
#include "ns3/node-container.h" |
29 |
#include "ns3/tcp-socket-base.h" |
30 |
#include "ns3/simple-net-device-helper.h" |
31 |
#include "ns3/ipv4-address-helper.h" |
32 |
#include "ns3/internet-stack-helper.h" |
33 |
#include "ns3/log.h" |
34 |
#include "ns3/tcp-l4-protocol.h" |
35 |
#include "../internet/model/ipv4-end-point.h" |
36 |
#include "../internet/model/ipv6-end-point.h" |
37 |
#include "ns3/lte-module.h" |
38 |
|
39 |
namespace ns3 { |
40 |
|
41 |
NS_LOG_COMPONENT_DEFINE ("TcpBufferSizeTestSuite"); |
42 |
|
43 |
class TcpSocketHighBuf : public TcpSocketMsgBase |
44 |
{ |
45 |
public: |
46 |
static TypeId GetTypeId (); |
47 |
TcpSocketHighBuf () : TcpSocketMsgBase () { } |
48 |
TcpSocketHighBuf (const TcpSocketHighBuf &other) : TcpSocketMsgBase (other) { } |
49 |
|
50 |
protected: |
51 |
virtual void ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader); |
52 |
virtual Ptr<TcpSocketBase> Fork (void) { return CopyObject<TcpSocketHighBuf> (this); } |
53 |
}; |
54 |
|
55 |
TypeId |
56 |
TcpSocketHighBuf::GetTypeId (void) |
57 |
{ |
58 |
static TypeId tid = TypeId ("ns3::TcpSocketHighBuf") |
59 |
.SetParent<TcpSocketMsgBase> () |
60 |
.SetGroupName ("Internet") |
61 |
.AddConstructor<TcpSocketHighBuf> () |
62 |
; |
63 |
return tid; |
64 |
} |
65 |
|
66 |
void |
67 |
TcpSocketHighBuf::ReceivedData (Ptr<Packet> p, const TcpHeader& tcpHeader) |
68 |
{ |
69 |
NS_LOG_FUNCTION (this << tcpHeader); |
70 |
NS_LOG_DEBUG ("Data segment, seq=" << tcpHeader.GetSequenceNumber () << |
71 |
" pkt size=" << p->GetSize () ); |
72 |
|
73 |
// Put into Rx buffer |
74 |
SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence (); |
75 |
if (!m_rxBuffer->Add (p, tcpHeader)) |
76 |
{ // Insert failed: No data or RX buffer full |
77 |
SendEmptyPacket (TcpHeader::ACK); |
78 |
return; |
79 |
} |
80 |
// Now send a new ACK packet acknowledging all received and delivered data |
81 |
if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ()) |
82 |
{ // A gap exists in the buffer, or we filled a gap: Always ACK |
83 |
SendEmptyPacket (TcpHeader::ACK); |
84 |
} |
85 |
else |
86 |
{ // In-sequence packet: ACK if delayed ack count allows |
87 |
if (++m_delAckCount >= m_delAckMaxCount) |
88 |
{ |
89 |
m_delAckEvent.Cancel (); |
90 |
m_delAckCount = 0; |
91 |
SendEmptyPacket (TcpHeader::ACK); |
92 |
} |
93 |
else if (m_delAckEvent.IsExpired ()) |
94 |
{ |
95 |
m_delAckEvent = Simulator::Schedule (m_delAckTimeout, |
96 |
&TcpSocketHighBuf::DelAckTimeout, this); |
97 |
NS_LOG_LOGIC (this << " scheduled delayed ACK at " << |
98 |
(Simulator::Now () + Simulator::GetDelayLeft (m_delAckEvent)).GetSeconds ()); |
99 |
} |
100 |
} |
101 |
// Notify app to receive if necessary |
102 |
if (expectedSeq < m_rxBuffer->NextRxSequence ()) |
103 |
{ // NextRxSeq advanced, we have something to send to the app |
104 |
if (!m_shutdownRecv && m_rxBuffer->Available () > 4000000) |
105 |
{ |
106 |
NotifyDataRecv (); |
107 |
} |
108 |
else |
109 |
{ |
110 |
NS_LOG_DEBUG ("Queueing " << m_rxBuffer->Available () << " bytes"); |
111 |
} |
112 |
// Handle exceptions |
113 |
if (m_closeNotified) |
114 |
{ |
115 |
NS_LOG_WARN ("Why TCP " << this << " got data after close notification?"); |
116 |
} |
117 |
// If we received FIN before and now completed all "holes" in rx buffer, |
118 |
// invoke peer close procedure |
119 |
if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0) |
120 |
{ |
121 |
DoPeerClose (); |
122 |
} |
123 |
} |
124 |
} |
125 |
|
126 |
class TcpBufferSizeTest : public TcpGeneralTest |
127 |
{ |
128 |
public: |
129 |
TcpBufferSizeTest (const std::string &desc); |
130 |
|
131 |
protected: |
132 |
virtual Ptr<TcpSocketMsgBase> CreateReceiverSocket (Ptr<Node> node); |
133 |
virtual Ptr<TcpSocketMsgBase> CreateSenderSocket (Ptr<Node> node); |
134 |
void ConfigureEnvironment (); |
135 |
void ConfigureProperties (); |
136 |
virtual Ipv4Address MakeEnvironment (Ptr<Node> sender, Ptr<Node> receiver); |
137 |
}; |
138 |
|
139 |
TcpBufferSizeTest::TcpBufferSizeTest (const std::string &desc) |
140 |
: TcpGeneralTest (desc) |
141 |
{ |
142 |
} |
143 |
|
144 |
void |
145 |
TcpBufferSizeTest::ConfigureEnvironment () |
146 |
{ |
147 |
NS_LOG_FUNCTION (this); |
148 |
TcpGeneralTest::ConfigureEnvironment (); |
149 |
SetPropagationDelay (MilliSeconds (50)); |
150 |
SetAppPktSize (1340); |
151 |
SetAppPktCount (60000); |
152 |
SetConnectTime (Seconds (4.0)); |
153 |
} |
154 |
|
155 |
void |
156 |
TcpBufferSizeTest::ConfigureProperties () |
157 |
{ |
158 |
TcpGeneralTest::ConfigureProperties (); |
159 |
SetRcvBufSize (RECEIVER, 6000000); |
160 |
SetSegmentSize (SENDER, 1340); |
161 |
SetSegmentSize (RECEIVER, 1340); |
162 |
} |
163 |
|
164 |
Ptr<TcpSocketMsgBase> |
165 |
TcpBufferSizeTest::CreateReceiverSocket (Ptr<Node> node) |
166 |
{ |
167 |
return CreateSocket (node, TcpSocketHighBuf::GetTypeId (), m_congControlTypeId); |
168 |
} |
169 |
|
170 |
Ptr<TcpSocketMsgBase> |
171 |
TcpBufferSizeTest::CreateSenderSocket (Ptr<Node> node) |
172 |
{ |
173 |
return CreateSocket (node, TcpSocketHighBuf::GetTypeId (), m_congControlTypeId); |
174 |
} |
175 |
|
176 |
static void |
177 |
SetNodeProperties (Ptr<Node> node, double x, double y, double z, const std::string &name) |
178 |
{ |
179 |
Ptr<ConstantPositionMobilityModel> loc = node->GetObject<ConstantPositionMobilityModel> (); |
180 |
if (loc == 0) |
181 |
{ |
182 |
loc = CreateObject<ConstantPositionMobilityModel> (); |
183 |
node->AggregateObject (loc); |
184 |
} |
185 |
loc->SetPosition (Vector3D (x, y, z)); // 5, 2 |
186 |
Names::Add (name, node); |
187 |
} |
188 |
|
189 |
static Ipv4InterfaceContainer |
190 |
BuildIpv4LAN (NetDeviceContainer &devs, const std::string &baseAddr = "10.0.0.0") |
191 |
{ |
192 |
static Ipv4AddressHelper address; |
193 |
address.SetBase (baseAddr.c_str (), "255.255.0.0"); |
194 |
address.NewNetwork (); |
195 |
|
196 |
return address.Assign (devs); |
197 |
} |
198 |
|
199 |
Ipv4Address |
200 |
TcpBufferSizeTest::MakeEnvironment (Ptr<Node> sender, Ptr<Node> receiver) |
201 |
{ |
202 |
static Ptr<LteHelper> lteHelper = CreateObject<LteHelper> (); |
203 |
static Ptr<PointToPointEpcHelper> epcHelper = CreateObject<PointToPointEpcHelper> (); |
204 |
lteHelper->SetEpcHelper (epcHelper); |
205 |
|
206 |
lteHelper->SetEnbAntennaModelType ("ns3::IsotropicAntennaModel"); |
207 |
lteHelper->SetEnbDeviceAttribute ("UlBandwidth", UintegerValue (100)); |
208 |
lteHelper->SetEnbDeviceAttribute ("DlBandwidth", UintegerValue (100)); |
209 |
lteHelper->SetEnbDeviceAttribute ("DlEarfcn", UintegerValue (1575)); |
210 |
lteHelper->SetEnbDeviceAttribute ("UlEarfcn", UintegerValue (19575)); |
211 |
lteHelper->SetUeAntennaModelType ("ns3::IsotropicAntennaModel"); |
212 |
lteHelper->SetUeDeviceAttribute ("DlEarfcn", UintegerValue (1575)); |
213 |
lteHelper->SetPathlossModelType ("ns3::OkumuraHataPropagationLossModel"); |
214 |
lteHelper->SetPathlossModelAttribute ("Environment", EnumValue (UrbanEnvironment)); |
215 |
lteHelper->SetPathlossModelAttribute ("CitySize", EnumValue (MediumCity)); |
216 |
lteHelper->SetSchedulerType ("ns3::PfFfMacScheduler"); |
217 |
|
218 |
Ptr<Node> pgw = epcHelper->GetPgwNode (); |
219 |
|
220 |
SetNodeProperties (pgw, 50, 20, 2, "pgw"); |
221 |
|
222 |
// Create a single RemoteHost |
223 |
NodeContainer remoteHostContainer; |
224 |
remoteHostContainer.Add (receiver); |
225 |
Ptr<Node> remoteHost = remoteHostContainer.Get (0); |
226 |
InternetStackHelper internet; |
227 |
internet.Install (remoteHostContainer); |
228 |
|
229 |
//add a position to the Remote Host node |
230 |
SetNodeProperties (remoteHost, 70, 20, 2, "remote"); |
231 |
|
232 |
// Create the Internet |
233 |
PointToPointHelper p2ph; |
234 |
p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("500Mb/s"))); |
235 |
p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500)); |
236 |
p2ph.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (5))); |
237 |
|
238 |
NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost); |
239 |
Ipv4AddressHelper ipv4h; |
240 |
ipv4h.SetBase ("1.0.0.0", "255.0.0.0"); |
241 |
Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices); |
242 |
|
243 |
Ipv4StaticRoutingHelper ipv4RoutingHelper; |
244 |
Ptr<Ipv4StaticRouting> remoteHostStaticRouting; |
245 |
|
246 |
remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ()); |
247 |
|
248 |
remoteHostStaticRouting->SetDefaultRoute (internetIpIfaces.GetAddress (0), 1); |
249 |
|
250 |
// Create the ENBs and set position |
251 |
NodeContainer enbNodes; |
252 |
enbNodes.Create (1); |
253 |
for (uint32_t i = 0; i < 1; ++i) |
254 |
{ |
255 |
std::stringstream n; |
256 |
n << "ENB" << i+1; |
257 |
SetNodeProperties (enbNodes.Get (i), 10, 10, 2, n.str ()); |
258 |
} |
259 |
|
260 |
// Create the UEs and set position |
261 |
NodeContainer ueNodes; |
262 |
ueNodes.Add (sender); |
263 |
for (uint32_t i = 0; i < 1; ++i) |
264 |
{ |
265 |
std::stringstream n; |
266 |
n << "UE" << i+1; |
267 |
SetNodeProperties (ueNodes.Get (i), 9, 10, 2, n.str ()); |
268 |
} |
269 |
|
270 |
NetDeviceContainer enbDevices = lteHelper->InstallEnbDevice (enbNodes); |
271 |
NetDeviceContainer ueDevices = lteHelper->InstallUeDevice (ueNodes); |
272 |
|
273 |
NetDeviceContainer::Iterator it; |
274 |
for (it = enbDevices.Begin (); it != enbDevices.End (); ++it) |
275 |
{ |
276 |
Ptr<LteEnbNetDevice> dev = DynamicCast<LteEnbNetDevice> (*it); |
277 |
NS_ASSERT (dev != 0); |
278 |
|
279 |
dev->GetPhy ()->SetTxPower (23.0); |
280 |
dev->GetRrc ()->SetSrsPeriodicity (80); |
281 |
} |
282 |
|
283 |
InternetStackHelper stack; |
284 |
stack.Install (ueNodes); |
285 |
|
286 |
Ipv4InterfaceContainer ueIpIface; |
287 |
ueIpIface = epcHelper->AssignUeIpv4Address (ueDevices); |
288 |
|
289 |
for (it = ueDevices.Begin (); it != ueDevices.End (); ++it) |
290 |
{ |
291 |
Ptr<LteUeNetDevice> dev = DynamicCast<LteUeNetDevice> (*it); |
292 |
|
293 |
dev->GetPhy ()->SetTxPower (23.0); |
294 |
} |
295 |
|
296 |
lteHelper->AttachToClosestEnb (ueDevices, enbDevices); |
297 |
|
298 |
|
299 |
for (uint32_t i = 0; i < ueNodes.GetN (); ++i) |
300 |
{ |
301 |
Ptr<Node> ue = ueNodes.Get (i); |
302 |
Ptr<Ipv4StaticRouting> ueStaticRouting; |
303 |
ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ue->GetObject<Ipv4> ()); |
304 |
|
305 |
// 0 is Loopback, 1 is LteUeNetDevice |
306 |
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); |
307 |
} |
308 |
|
309 |
BuildIpv4LAN (ueDevices, "192.168.0.0"); |
310 |
|
311 |
{ |
312 |
Ptr<Ipv4StaticRouting> ueStaticRouting; |
313 |
ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ()); |
314 |
|
315 |
// 0 is Loopback, 1 is LteUeNetDevice |
316 |
ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1); |
317 |
} |
318 |
|
319 |
return internetIpIfaces.GetAddress (1); |
320 |
} |
321 |
|
322 |
|
323 |
//----------------------------------------------------------------------------- |
324 |
|
325 |
static class TcpBufferSizeTestSuite : public TestSuite |
326 |
{ |
327 |
public: |
328 |
TcpBufferSizeTestSuite () : TestSuite ("tcp-buffer-size-test", UNIT) |
329 |
{ |
330 |
AddTestCase (new TcpBufferSizeTest ("Some data exchanged"), |
331 |
TestCase::QUICK); |
332 |
} |
333 |
} g_tcpBufferSizeTestSuite; |
334 |
|
335 |
} // namespace ns3 |