|
|
|
|
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 |