ENSC 427: COMMUNICATION NETWORKS
SPRING 2023

FINAL PROJECT
Performance Analysis of TCP and UDP over 5G Network
https://www.sfu.ca/~crosenau/

Chris Rosenauer

310400868

crosenau@sfu.ca

Ramanpreet Kaur

301406640

rka66@sfu.ca

Group 5


Table of Contents

Table of Contents        

1 Abstract        

2 Background and Introduction        

3 Literature review        

4 Implementation        

4.1 Network Topology        

4.2 Network Implementation        

4.3 Tracing Implementation        

5 Results        

6 Discussion        

7 Conclusion        

8 Acknowledgements        

9 References        

10 Group Contributions        

Appendix A: TCP Simulation Source Code        

Appendix B: UDP Simulation Source Code        


1 Abstract

5G or the fifth-generation cellular network is the successor to 4G networks that use mmWave technology to achieve high throughputs (around 10 Gbps). In this paper, we will simulate a 5G network over an ns-3 simulator and study the performance of the User Datagram Protocol (UDP) and Transmission Control Protocol (TCP). The ns-3 simulator is highly customizable as it offers a cross-layer design that helps test new 5G protocols [4]. Although many performance metrics exist today, we will use delay, jitter, throughput, and packet loss to compare the performance of these two protocols. Some advantages of TCP vs UDP are known, such as reliable transmission in TCP and low delay in UDP over 4G and wired networks [5]. These characteristics will be analyzed to check whether 5G simulated networks are suitable for data transmission [5].


2 Background and Introduction

In this project, we analyze and discuss the performance of TCP and UDP over 5G networks using the metrics of delay, jitter, throughput, and packet loss. 5G is the latest generation of mobile networking technology and boasts higher throughput and lower latency than previous technologies such as 4G [7]. We test 5G’s performance claims by simulating and analyzing TCP and UDP packets over a 5G network using ns-3 and comparing our results to the same performance metrics observed from 4G network simulations.

The simulations in this paper are implemented using the mmWave ns-3 module. mmWave is an open-source fork of ns-3 that enables packet-level simulations and allows users throughput and latency analysis at different layers. It supports many features such as: a wide range of wireless models, measured traces, customized MAC and PHY layers, connectivity with LTE base stations, etc. In terms of internet protocol traffic, TCP and UDP are widely used protocols and they’re both used based on the set of advantages and challenges that they bring. TCP is a connection-oriented protocol that offers congestion control, and flow control and is reliable in terms of in-order delivery of the streams of the segments. Whereas UDP is a simple connectionless protocol that offers fast service but packets may be lost and delivered out of order. [8]

As 5G is becoming an integral part of internet traffic and is an up-and-coming technology, this report will analyze the results obtained from the simulations and what scenarios will be fit for which protocol in 5G.

The simulation for each UDP and TCP will be carried out for the same network topology and traced using the same methodology.  Different tracing methods were analyzed and ASCIIHelper was used to trace outputs for TCP data and UDP.

3 Literature review

In [3], the authors discuss the expansion of the wireless networks to 4th generation (LTE) and how in addition to UDP, which is the main video streaming protocol, other protocols TCP, DCCP, and SCTP are also utilized to deal with increased internet traffic. Furthermore, the performance of these transport protocols is compared with each other to determine the best protocol for the 4th generation network.

In [4], the role that mmWave technology plays in increasing the throughputs of 5G networks is discussed along with how mmWave technology is administered in each of the layers. The implementation of the mmWave module and its various channel models in ns-3 is also discussed in depth as ns-3 is especially useful in cross-layer design which we will be using when we will be building our 5G network in ns-3.

Similar to [3], [5] also discusses the performance of different transport layer protocols with a focus on SCTP(Stream Control Transmission Protocol)  in a wired network simulated via ns-2.35. However, the goal of this paper is to study the services(connection orientation, flow, congestion control, etc.) provided by SCTP on how this protocol works on delays that TCP faces and the unreliability that UDP has. This paper uses the same performance metrics we plan to use for our analysis(Packet Loss Rate, delay, and throughput).

In previous studies, there was no error modeled in the network simulations. In [6], various causes of error such as radio hardware, device drivers, and network protocols) are examined in a Wireless LAN.

4 Implementation

4.1 Network Topology

Figure 1: Network Topology of the Simulation

The simulated network was constructed with three nodes: a remote host which sends TCP and UDP packets, a user equipment node (UE) which receives said TCP and UDP packets, and an eNodeB which facilitates the transfer of TCP and UDP packets between the remote host and the UE nodes. Connections between nodes are bi-directional, however only TCP takes advantage of this directionality.

4.2 Network Implementation

        The simulation was implemented using mmWave version 4.0 for ns-3.33. The simulation encompasses two scripts: one for the TCP simulation, one for the UDP simulation. Both of these simulations have a common structure and many common elements. The remote hosts of both networks utilize a custom application class MyApp to send packets at a constant rate. The MyApp class attempts to send 5,000,000 1,400 B packets at a rate of 500 Mbps. However, the rate at which these packets, and the number of packets that are actually sent rely on network’s implementation and the simulation time, respectively. The networks are connected using the classes: PointToPointHelper, Ipv4StaticRoutingHelper. Additionally, PacketSinkHelper is used with either the TCPSocketFactory, or UDPSocketFactory depending on the simulation.

LteRlcUm MaxTxBufferSize

10 MB

LteRlcAm MaxTxBufferSize

10 MB

LteRlcUmLowLat MaxTxBufferSize

10 MB

TcpL4Protocol  SocketType

TCP Cubic

TcpSocketBase MinRto

200 ms

Ipv4L3Protocol FragmentExpirationTimeout

0.2 s

TcpSocket SegmentSize

2500 B

TcpSocket DelAckCount

1

TcpSocket SndBufSize

12.5 MB

TcpSocket RcvBufSize

12.5 MB

mmWave Scheduler Type

MmWaveFlexTtiMacScheduler

PointToPointHelper Data Rate

100 Gb/s

PointToPointHelper Maximum Transmission Unit

1500 B

PointToPointHelper Delay

1 us

Channel Error Rate

0.00001

eNodeB Mobility Model

ConstantPositionMobilityModel

ue Mobility Model

ConstantPositionMobilityModel

Table 1: TCP Simulation Network Parameters

LteRlcUm MaxTxBufferSize

10 MB

LteRlcAm MaxTxBufferSize

10 MB

LteRlcUmLowLat MaxTxBufferSize

10 MB

Ipv4L3Protocol FragmentExpirationTimeout

0.2 s

UdpSocket RcvBufSize

12.5 MB

mmWave Scheduler Type

MmWaveFlexTtiMacScheduler

Channel Error Rate

0.00001

eNodeB Mobility Model

ConstantPositionMobilityModel

ue Mobility Model

ConstantPositionMobilityModel

Table 2: UDP Simulation Network Parameters

        For further details about the TCP and UDP network’s simulations see Appendix A: TCP Simulation Source Code, and Appendix B: UDP Simulation Source Code.

4.3 Tracing Implementation

        Tracing for both TCP and UDP was in part facilitated with ns-3’s AsciiTraceHelper. However, the tracing specifics for the TCP and UDP scripts differ greatly.

        TCP tracing was facilitated through ns-3’s tracing callback functionality. Tracing functions were added to trace changes in the TCP network’s round-trip-time, window size, and to trace when packets were dropped in the network. The TCP throughput was calculated using the following formula for average throughput:

Delay and jitter were derived from the trace round trip time. Packets dropped were directly measured using the packet dropped tracing data.

        UDP tracing was facilitated in part through ns-3’s tracing callback functionality. Tracing functions were added to record information when packets were dropped in the network, and when packets were received by the user equipment. Additionally, the packet sending function in the remote hosts MyApp class was expanded to record packet information upon sending a packet. Packets dropped were directly measured using the packet dropped tracing data. Throughput, delay, and jitter measurements required additional logic, and the UDP network helpers we used contained no convenient way of obtaining these metrics. The MyApp class stores UDP packet information upon sending said packets. Such information includes a unique identifier for each packet, the time the packet was sent, and the packet’s size. When the packet is received by the user equipment, the stored packet information is updated to include the time the packet was received. To facilitate the packet’s unique identifier we stored an integer in the packet’s payload. This integer increments with every packet sent. We were forced to this payload-stored identifier approach as ns-3’s packet UID proved unreliable for tracing packets of a multi-node network. Delay and jitter were derived from the difference in time between the packet being sent and received. Throughput was derived from the packet’s size and the duration taken to deliver the packet from the sender to the receiver.

5 Results

5G network simulation to analyze jitter, loss, delay, and throughput using the mmWave module was done.

An instance of ASCIITraceHelper is used to create various text files of information for various events in both of the simulations. Text files for window size, round trip time (RTT), and Drop packet are generated for TCP. Text files for receiver data packets and Drop packets are generated for UDP.

This data is then used to measure Throughput, Packet Loss, delay, and jitter. The graphs for each of the performance metrics are given below for each of the protocols.

Figure 2: Throughput of TCP Packets Over Simulation Duration

Figure 3: Throughput of UDP Packets Over Simulation Duration

Figure 4: Cumulative TCP Packet Loss Over Simulation Duration

Figure 5: Cumulative UDP Packet Loss Over Simulation Duration

Figure 6: Delay of TCP Packets Over Simulation Duration

Figure 7: Delay of TCP Packets Over Simulation Duration

Figure 7: Jitter of TCP Packets Over Simulation Duration

Figure 8: Jitter of UDP Packets Over Simulation Duration


Metric

TCP

UDP

Mean Throughput (kbps)

35.3

662

Loss (packets)

29

5031

Mean Delay (seconds)

0.0118

0.00021

Mean Jitter (milliseconds)

0.0625

0.0414

Table 3: Measured Performance Metrics of TCP and UDP

        From our traced results, TCP has a surprisingly low throughput. Both TCP and UDP have some loss, with UDP’s loss being considerably higher. UDP has a significantly lower delay compared to TCP. Finally, both TCP and UDP have comparable jitter.

6 Discussion

Metric

TCP (5G)

UDP (5G)

TCP (4G) [3]

UDP (4G) [3]

Mean Throughput (kbps)

35.3

662

3780

3520

Loss (packets)

29

5031

8

18

Mean Delay (seconds)

0.0118

0.00021

5.5

5.3

Mean Jitter (milliseconds)

0.0625

0.0414

1.4

1.5

Table 4: Comparison of TCP and UDP Performance Metrics Over 5G and 4G Networks

        Performance data for TCP and UDP networks was derived from Nor et al. [3]. Compared to 4G, the throughput of TCP and UDP over 5G is surprisingly low. Both TCP and UDP experience a higher loss over 5G networks, however, the loss of UDP packets saw a considerably larger increase compared to TCP. From these results, applications that require the low-latency transfer of information and have little need for data correctness or low packet loss. Video calls may be an application that is better suited for 5G compared to 4G. However, based on our results, applications that require large throughput may not be suited for 5G.

        The performance metrics gathered on our 5G simulation differs greatly from the 4G network performance metrics. This discrepancy could be due to differences in the network. The data used by Nor et al. was gathered using a simulation of multiple nodes sending and receiving data. This increase of nodes may have increased the throughput of the network and would explain the significantly lower throughput of our results. Additionally, the larger throughput requirements of the network created by Nor et al. may contribute to the 4G performance metrics’ larger delay and jitter.

        In hindsight, our simulation could be improved to better emulate a real 5G network. Such improvements include: adding background traffic to the network, or emulating traffic being sent from and/or to multiple nodes. Additionally, if this simulation were to be repeated it may be advantageous to de-develop the UDP simulation using classes which facilitate the tracing the UDP throughput, delay, and jitter as the tools we used in this simulation had no such functionality.

7 Conclusion

5G network simulation was done using the ns-3 mmWave module. TCP and UDP packets were sent over this network with the same topology. To trace the results, ASCIIHelper was implemented for TCP  and UDP. Specifically for the UDP simulation, workarounds were required to trace UDP data as the UDP packets’ unique ID was unreliable for the purpose of mapping sent packets to received packets. The results and discussion of results were done from the graphs generated by the Matlab functions that analyzed the data. These results were then compared to 4G results from Nor et al.[3] and conclusions were made about 5G.

For future work, protocols such as ICMP, HTTP, and DNS from other layers could be analyzed. Furthermore, the impact of multiple users on a single network can be studied. Spatial distance and physical simulation parameters on these simulations can also be studied for further analysis.


8 Acknowledgements

Our network was developed using modules provided by mmWave version 4.0 for ns-3.33. Both our TCP and UDP simulation networks were created using example code provided by mmWave. Particularly, the script mmwave-tcp-example.cc.

Additionally, we would like to thank this class’ TA, Soroush Oraki. During the creation of our simulation scripts we had difficulty tracing UDP packets and their corresponding data. Soroush helped us properly trace UDP packets within our network.


9 References

[1]

J. P. Postel, “Transmission control protocol,” RFC Editor, September-1981. [Online]. Available: https://www.rfc-editor.org/rfc/rfc793. [Accessed: 21-Feb-2023].

[2]

J. P. Postel, “User Datagram protocol,” RFC Editor, 28-Aug-1980. [Online]. Available: https://www.rfc-editor.org/rfc/rfc768.. [Accessed: 21-Feb-2023].

[3]

S. A. Nor, R. Alubady, and W. A. Kamil, “Simulated performance of TCP, SCTP, DCCP and UDP protocols over 4G network,” Procedia Computer Science, 23-Aug-2017. [Online]. Available: https://www.sciencedirect.com/science/article/pii/S1877050917311754. [Accessed: 21-Feb-2023].

[4]

M. Mezzavilla et al., "End-to-End Simulation of 5G mmWave Networks," in IEEE Communications Surveys & Tutorials, vol. 20, no. 3, pp. 2237-2263, third quarter 2018, doi: 10.1109/COMST.2018.2828880.

[5]

D. Madhuri and P. C. Reddy, "Performance comparison of TCP, UDP, and SCTP in a wired network," 2016 International Conference on Communication and Electronics Systems (ICCES), Coimbatore, India, 2016, pp. 1-6, doi: 10.1109/CESYS.2016.7889934

[6]

G. Xylomenos and G. C. Polyzos, "TCP and UDP performance over a wireless LAN," IEEE INFOCOM '99. Conference on Computer Communications. Proceedings. Eighteenth Annual Joint Conference of the IEEE Computer and Communications Societies. The Future is Now (Cat. No.99CH36320), New York, NY, USA, 1999, pp. 439-446 vol.2, doi: 10.1109/INFCOM.1999.751376.

[7]

Qualcomm. (n.d.). What is 5g: Everything you need to know About 5G: 5G FAQ: Qualcomm. Wireless Technology & Innovation. Retrieved March 11, 2023, from https://www.qualcomm.com/5g/what-is-5g

[8]        

Kurose, J.F. and Ross, K.W. (2021) “Transport Layer,” in Computer networking: A top-down approach. Hoboken: Pearson, pp. 194–230.


10 Group Contributions

Contribution Item

Team Member Contribution (Percentage)

Chris Rosenauer

Ramanpreet Kaur

References and Literature Review

30%

70%

Project Website

100%

0%

Simulation Scenarios, Implementation, and Discussion of Simulated Results

70%

30%

Project Presentation

40%

60%

Written Final Report

40%

60%


Appendix A: TCP Simulation Source Code

// adapted from mmWave's mmwave-tcp-example.cc

#include <map>

#include "ns3/internet-module.h"

#include "ns3/mobility-module.h"

#include "ns3/applications-module.h"

#include "ns3/config-store-module.h"

#include "ns3/command-line.h"

#include "ns3/point-to-point-helper.h"

#include "ns3/mmwave-helper.h"

#include "ns3/mmwave-point-to-point-epc-helper.h"

#include "ns3/error-model.h"

using namespace ns3;

using namespace mmwave;

/**

 * A script to simulate the DOWNLINK TCP data over mmWave links

 * with the mmWave devices and the LTE EPC.

 */

NS_LOG_COMPONENT_DEFINE ("mmWaveTCPExample");

struct TracingStruct

{

    double m_timeSent;

    double m_timeReceived;

    uint32_t m_sentSize;

    uint32_t m_receivedSize;

};

std::map<SpectrumModelUid_t, TracingStruct> tracingMap;

class MyApp : public Application

{

public:

  MyApp ();

  MyApp (Ptr<OutputStreamWrapper> stream);

  virtual ~MyApp ();

  void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate);

private:

  virtual void StartApplication (void);

  virtual void StopApplication (void);

  void ScheduleTx (void);

  void SendPacket (void);

  Ptr<Socket>     m_socket;

  Address         m_peer;

  uint32_t        m_packetSize;

  uint32_t        m_nPackets;

  DataRate        m_dataRate;

  EventId         m_sendEvent;

  bool            m_running;

  uint32_t        m_packetsSent;

};

MyApp::MyApp ()

  :

    m_socket (0),

    m_peer (),

    m_packetSize (0),

    m_nPackets (0),

    m_dataRate (0),

    m_sendEvent (),

    m_running (false),

    m_packetsSent (0)

{

}

MyApp::MyApp (Ptr<OutputStreamWrapper> stream)

  :

    m_socket (0),

    m_peer (),

    m_packetSize (0),

    m_nPackets (0),

    m_dataRate (0),

    m_sendEvent (),

    m_running (false),

    m_packetsSent (0)

{

}

MyApp::~MyApp ()

{

  m_socket = 0;

}

void

MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate)

{

  m_socket = socket;

  m_peer = address;

  m_packetSize = packetSize;

  m_nPackets = nPackets;

  m_dataRate = dataRate;

}

void

MyApp::StartApplication (void)

{

  m_running = true;

  m_packetsSent = 0;

  m_socket->Bind ();

  m_socket->Connect (m_peer);

  SendPacket ();

}

void

MyApp::StopApplication (void)

{

  m_running = false;

  if (m_sendEvent.IsRunning ())

  {

    Simulator::Cancel (m_sendEvent);

  }

  if (m_socket)

  {

    m_socket->Close ();

  }

  // output tracing data

}

void

MyApp::SendPacket (void)

{

  static int send_num = 1;

  Ptr<Packet> packet = Create<Packet> (m_packetSize);

  m_socket->Send (packet);

  NS_LOG_DEBUG ("Sending:    " << send_num++ << "\t" << Simulator::Now ().GetSeconds ());

  if (++m_packetsSent < m_nPackets)

    {

      ScheduleTx ();

    }

}

// packet sent by ip

static void Tx (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> packet, const Address &to)

{

  *stream->GetStream() << Simulator::Now ().GetSeconds () << "," <<  packet->GetUid() << "," << packet->GetSize() << std::endl;

}

// packet received by ip

static void Rx (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> packet, const Address &from)

{

  *stream->GetStream() << Simulator::Now ().GetSeconds () << "," << packet->GetUid() << "," << packet->GetSize() << std::endl;

}

static void

RttChange (Ptr<OutputStreamWrapper> stream, Time oldRtt, Time newRtt)

{

  *stream->GetStream () << Simulator::Now ().GetSeconds () << "," << newRtt.GetSeconds () << std::endl;

}

static unsigned dropCount = 0;

// packet dropped

static void PhyRxDrop (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> packet)

{

  *stream->GetStream() << Simulator::Now ().GetSeconds () << "," <<  packet->GetUid() << "," << ++dropCount << std::endl;

}

void

MyApp::ScheduleTx (void)

{

  if (m_running)

    {

      Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));

      m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);

    }

}

static void

CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)

{

  *stream->GetStream () << Simulator::Now ().GetSeconds () << "," << newCwnd << std::endl;

}

int

main (int argc, char *argv[])

{

  Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

  Config::SetDefault ("ns3::LteRlcAm::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

  Config::SetDefault ("ns3::LteRlcUmLowLat::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

 

  // TCP settings

  Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpCubic::GetTypeId ()));

  Config::SetDefault ("ns3::TcpSocketBase::MinRto", TimeValue (MilliSeconds (200)));

  Config::SetDefault ("ns3::Ipv4L3Protocol::FragmentExpirationTimeout", TimeValue (Seconds (0.2)));

  Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (2500));

  Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));

  Config::SetDefault ("ns3::TcpSocket::SndBufSize", UintegerValue (131072*100));

  Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (131072*100));

   

  // set to false to use the 3GPP radiation pattern (proper configuration of the bearing and downtilt angles is needed)

  Config::SetDefault ("ns3::ThreeGppAntennaArrayModel::IsotropicElements", BooleanValue (true));

 

  double stopTime = 8;

  double simStopTime = 10;

  Ipv4Address remoteHostAddr;

  // Command line arguments

  CommandLine cmd;

  cmd.Parse (argc, argv);

  Ptr<MmWaveHelper> mmwaveHelper = CreateObject<MmWaveHelper> ();

  mmwaveHelper->SetSchedulerType ("ns3::MmWaveFlexTtiMacScheduler");

  Ptr<MmWavePointToPointEpcHelper>  epcHelper = CreateObject<MmWavePointToPointEpcHelper> ();

  mmwaveHelper->SetEpcHelper (epcHelper);

  ConfigStore inputConfig;

  inputConfig.ConfigureDefaults ();

  // parse again so you can override default values from the command line

  cmd.Parse (argc, argv);

  Ptr<Node> pgw = epcHelper->GetPgwNode ();

  // Create a single RemoteHost

  NodeContainer remoteHostContainer;

  remoteHostContainer.Create (1);

  Ptr<Node> remoteHost = remoteHostContainer.Get (0);

  InternetStackHelper internet;

  internet.Install (remoteHostContainer);

  // Create the Internet

  PointToPointHelper p2ph;

  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));

  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));

  p2ph.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));

  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);

  // create error rate for the enb

  Ptr<RateErrorModel> em = CreateObject<RateErrorModel>();

  em->SetAttribute("ErrorRate", DoubleValue(0.00001));

  internetDevices.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(em));

  Ipv4AddressHelper ipv4h;

  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");

  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);

  // interface 0 is localhost, 1 is the p2p device

  remoteHostAddr = internetIpIfaces.GetAddress (1);

  Ipv4StaticRoutingHelper ipv4RoutingHelper;

  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());

  remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);

  NodeContainer ueNodes;

  NodeContainer enbNodes;

  ueNodes.Create (1);

  enbNodes.Create (1);

  // Install Mobility Model

  MobilityHelper enbmobility;

  Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator> ();

  enbPositionAlloc->Add (Vector (0.0, 0.0, 25.0));

  enbmobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");

  enbmobility.SetPositionAllocator (enbPositionAlloc);

  enbmobility.Install (enbNodes);

  MobilityHelper uemobility;

  Ptr<ListPositionAllocator> uePositionAlloc = CreateObject<ListPositionAllocator> ();

  uePositionAlloc->Add (Vector (30.0, 0.0, 1.8));

  uemobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");

  uemobility.SetPositionAllocator (uePositionAlloc);

  uemobility.Install (ueNodes);

  // Install LTE Devices to the nodes

  NetDeviceContainer enbDevs = mmwaveHelper->InstallEnbDevice (enbNodes);

  NetDeviceContainer ueDevs = mmwaveHelper->InstallUeDevice (ueNodes);

  // Install the IP stack on the UEs

  // Assign IP address to UEs, and install applications

  internet.Install (ueNodes);

  Ipv4InterfaceContainer ueIpIface;

  ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));

  mmwaveHelper->AttachToClosestEnb (ueDevs, enbDevs);

  mmwaveHelper->EnableTraces ();

  // Set the default gateway for the UE

  Ptr<Node> ueNode = ueNodes.Get (0);

  Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());

  ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);

  // Install and start applications on UEs and remote host

  uint16_t sinkPort = 20000;

  Address sinkAddress (InetSocketAddress (ueIpIface.GetAddress (0), sinkPort));

  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));

  ApplicationContainer sinkApps = packetSinkHelper.Install (ueNodes.Get (0));

  sinkApps.Start (Seconds (0.));

  sinkApps.Stop (Seconds (simStopTime));

  Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (remoteHostContainer.Get (0), TcpSocketFactory::GetTypeId ());

  AsciiTraceHelper asciisenderTraceHelper;

  Ptr<MyApp> app = CreateObject<MyApp> ();

  app->Setup (ns3TcpSocket, sinkAddress, 1400, 5000000, DataRate ("500Mb/s"));

  remoteHostContainer.Get (0)->AddApplication (app);

  AsciiTraceHelper asciiTraceHelper;

  Ptr<OutputStreamWrapper> stream1 = asciiTraceHelper.CreateFileStream ("427-tcp-window.txt");

  ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream1));

  Ptr<OutputStreamWrapper> stream2 = asciiTraceHelper.CreateFileStream ("427-tcp-receiver-data.txt");

  sinkApps.Get (0)->TraceConnectWithoutContext ("Rx",MakeBoundCallback (&Rx, stream2));

  Ptr<OutputStreamWrapper> stream3 = asciiTraceHelper.CreateFileStream ("427-tcp-RTT.txt");

  remoteHostContainer.Get(0)->TraceConnectWithoutContext ("Tx",MakeBoundCallback (&Tx, stream3));

  ns3TcpSocket->TraceConnectWithoutContext ("RTT", MakeBoundCallback (&RttChange, stream3));

  Ptr<OutputStreamWrapper> stream4 = asciiTraceHelper.CreateFileStream ("427-tcp-drop-data.txt");

  internetDevices.Get(0)->TraceConnectWithoutContext ("PhyRxDrop",MakeBoundCallback (&PhyRxDrop, stream4));

  app->SetStartTime (Seconds (0.1));

  app->SetStopTime (Seconds (stopTime));

  p2ph.EnablePcapAll ("427-sgi-capture");

  Simulator::Stop (Seconds (simStopTime));

  Simulator::Run ();

  Simulator::Destroy ();

  return 0;

}


Appendix B: UDP Simulation Source Code

// adapted from mmWave's mmwave-tcp-example.cc

#include <map>

#include "ns3/internet-module.h"

#include "ns3/mobility-module.h"

#include "ns3/applications-module.h"

#include "ns3/config-store-module.h"

#include "ns3/command-line.h"

#include "ns3/point-to-point-helper.h"

#include "ns3/mmwave-helper.h"

#include "ns3/mmwave-point-to-point-epc-helper.h"

#include "ns3/error-model.h"

using namespace ns3;

using namespace mmwave;

/**

 * A script to simulate the DOWNLINK UDP data over mmWave links

 * with the mmWave devices and the LTE EPC.

 */

NS_LOG_COMPONENT_DEFINE ("mmWaveUDPExample");

AsciiTraceHelper asciiTraceHelper;

Ptr<OutputStreamWrapper> stream3 = asciiTraceHelper.CreateFileStream("427-udp-sender-data.txt");

struct TracingStruct

{

    double m_timeSent;

    double m_timeReceived;

    uint32_t m_sent;

};

// not all the tracing data!

TracingStruct tracingMap[5000000];

class MyApp : public Application

{

public:

  MyApp ();

  MyApp (Ptr<OutputStreamWrapper> stream);

  virtual ~MyApp ();

  void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate);

private:

  virtual void StartApplication (void);

  virtual void StopApplication (void);

  void ScheduleTx (void);

  void SendPacket (void);

  Ptr<Socket>     m_socket;

  Address         m_peer;

  uint32_t        m_packetSize;

  uint32_t        m_nPackets;

  DataRate        m_dataRate;

  EventId         m_sendEvent;

  bool            m_running;

  uint32_t        m_packetsSent;

};

MyApp::MyApp ()

  :

    m_socket (0),

    m_peer (),

    m_packetSize (0),

    m_nPackets (0),

    m_dataRate (0),

    m_sendEvent (),

    m_running (false),

    m_packetsSent (0)

{

}

MyApp::MyApp (Ptr<OutputStreamWrapper> stream)

  :

    m_socket (0),

    m_peer (),

    m_packetSize (0),

    m_nPackets (0),

    m_dataRate (0),

    m_sendEvent (),

    m_running (false),

    m_packetsSent (0)

{

}

MyApp::~MyApp ()

{

  m_socket = 0;

}

void

MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate)

{

  m_socket = socket;

  m_peer = address;

  m_packetSize = packetSize;

  m_nPackets = nPackets;

  m_dataRate = dataRate;

}

void

MyApp::StartApplication (void)

{

  m_running = true;

  m_packetsSent = 0;

  m_socket->Bind ();

  m_socket->Connect (m_peer);

  SendPacket ();

}

void

MyApp::StopApplication (void)

{

  m_running = false;

  if (m_sendEvent.IsRunning ())

  {

    Simulator::Cancel (m_sendEvent);

  }

  if (m_socket)

  {

    m_socket->Close ();

  }

  // output tracing data

}

static int senderPacketNumber = 0;

int dummyBuffer [1400 / 4];

void

MyApp::SendPacket (void)

{

  static int send_num = 1;

  dummyBuffer[0] = senderPacketNumber;

  Ptr<Packet> packet = Create<Packet> ( (uint8_t*) dummyBuffer, m_packetSize);

  m_socket->Send (packet);

  NS_LOG_DEBUG ("Sending:    " << send_num++ << "\t" << Simulator::Now ().GetSeconds ());

  // packet->Print(*stream3->GetStream());

  // *stream3->GetStream() << std::endl;

  TracingStruct tracingStruct;

  tracingStruct.m_sent = 1400;

  tracingStruct.m_timeSent = Simulator::Now ().GetSeconds ();

  tracingStruct.m_timeReceived = -1.0;

  tracingMap[senderPacketNumber] = tracingStruct;

  *stream3->GetStream() << Simulator::Now ().GetSeconds () << "," <<  senderPacketNumber << "," << packet->GetSize() << std::endl;

  senderPacketNumber++;

  if (++m_packetsSent < m_nPackets)

    {

      ScheduleTx ();

    }

}

// packet received by ip

static void Rx (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> packet, const Address &from)

{

  uint32_t receiverBuffer[1400 / 4];

  packet->CopyData((uint8_t*)receiverBuffer, 1400);

  uint32_t packetNumber = 0;

  /*

    Part of a workaround to trace UDP packets. Due to the structure of our network, we cannot use the packet's UID to trace the packet.

        As such, we store an identifier of the packet in the packet's payload. We unpack this identifier up receiving the packet and use it

        to track which packets get to the destination at which times.

  */

  for(int i = 0; i < 1400/4; ++i)

  {

    if(receiverBuffer[i] != 0)

    {

      packetNumber = receiverBuffer[i];

      break;

    }

  }

  TracingStruct tracingStruct = tracingMap[packetNumber];

  tracingStruct.m_timeReceived = Simulator::Now ().GetSeconds ();

  double delay = tracingStruct.m_timeReceived - tracingStruct.m_timeSent;

  double throughPut = tracingStruct.m_sent / delay;

  *stream->GetStream() << tracingStruct.m_timeReceived << "," << throughPut << "," << delay << std::endl;

}

static unsigned dropCount = 0;

// packet dropped

static void PhyRxDrop (Ptr<OutputStreamWrapper> stream, Ptr<const Packet> packet)

{

  *stream->GetStream() << Simulator::Now ().GetSeconds () << "," <<  packet->GetUid() << "," << ++dropCount << std::endl;

}

void

MyApp::ScheduleTx (void)

{

  if (m_running)

    {

      Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));

      m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);

    }

}

int

main (int argc, char *argv[])

{

  for (int i = 0 ; i < 1400/4; ++i)

  {

    dummyBuffer[i] = 0;

  }

  Config::SetDefault ("ns3::LteRlcUm::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

  Config::SetDefault ("ns3::LteRlcAm::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

  Config::SetDefault ("ns3::LteRlcUmLowLat::MaxTxBufferSize", UintegerValue (10 * 1024 * 1024));

 

  //UDP Settings

  Config::SetDefault("ns3::Ipv4L3Protocol::FragmentExpirationTimeout", TimeValue(Seconds(0.2)));

  Config::SetDefault("ns3::UdpSocket::RcvBufSize", UintegerValue(131072 * 100));

 

  // set to false to use the 3GPP radiation pattern (proper configuration of the bearing and downtilt angles is needed)

  Config::SetDefault ("ns3::ThreeGppAntennaArrayModel::IsotropicElements", BooleanValue (true));

 

  double stopTime = 8;

  double simStopTime = 10;

  Ipv4Address remoteHostAddr;

  // Command line arguments

  CommandLine cmd;

  cmd.Parse (argc, argv);

  Ptr<MmWaveHelper> mmwaveHelper = CreateObject<MmWaveHelper> ();

  mmwaveHelper->SetSchedulerType ("ns3::MmWaveFlexTtiMacScheduler");

  Ptr<MmWavePointToPointEpcHelper>  epcHelper = CreateObject<MmWavePointToPointEpcHelper> ();

  mmwaveHelper->SetEpcHelper (epcHelper);

  ConfigStore inputConfig;

  inputConfig.ConfigureDefaults ();

  // parse again so you can override default values from the command line

  cmd.Parse (argc, argv);

  Ptr<Node> pgw = epcHelper->GetPgwNode ();

  // Create a single RemoteHost

  NodeContainer remoteHostContainer;

  remoteHostContainer.Create (1);

  Ptr<Node> remoteHost = remoteHostContainer.Get (0);

  InternetStackHelper internet;

  internet.Install (remoteHostContainer);

  // Create the Internet

  PointToPointHelper p2ph;

  p2ph.SetDeviceAttribute ("DataRate", DataRateValue (DataRate ("100Gb/s")));

  p2ph.SetDeviceAttribute ("Mtu", UintegerValue (1500));

  p2ph.SetChannelAttribute ("Delay", TimeValue (MicroSeconds (1)));

  NetDeviceContainer internetDevices = p2ph.Install (pgw, remoteHost);

  // create error rate for the enb

  Ptr<RateErrorModel> em = CreateObject<RateErrorModel>();

  em->SetAttribute("ErrorRate", DoubleValue(0.00001));

  internetDevices.Get(0)->SetAttribute("ReceiveErrorModel", PointerValue(em));

  Ipv4AddressHelper ipv4h;

  ipv4h.SetBase ("1.0.0.0", "255.0.0.0");

  Ipv4InterfaceContainer internetIpIfaces = ipv4h.Assign (internetDevices);

  // interface 0 is localhost, 1 is the p2p device

  remoteHostAddr = internetIpIfaces.GetAddress (1);

  Ipv4StaticRoutingHelper ipv4RoutingHelper;

  Ptr<Ipv4StaticRouting> remoteHostStaticRouting = ipv4RoutingHelper.GetStaticRouting (remoteHost->GetObject<Ipv4> ());

  remoteHostStaticRouting->AddNetworkRouteTo (Ipv4Address ("7.0.0.0"), Ipv4Mask ("255.0.0.0"), 1);

  NodeContainer ueNodes;

  NodeContainer enbNodes;

  ueNodes.Create (1);

  enbNodes.Create (1);

  // Install Mobility Model

  MobilityHelper enbmobility;

  Ptr<ListPositionAllocator> enbPositionAlloc = CreateObject<ListPositionAllocator> ();

  enbPositionAlloc->Add (Vector (0.0, 0.0, 25.0));

  enbmobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");

  enbmobility.SetPositionAllocator (enbPositionAlloc);

  enbmobility.Install (enbNodes);

  MobilityHelper uemobility;

  Ptr<ListPositionAllocator> uePositionAlloc = CreateObject<ListPositionAllocator> ();

  uePositionAlloc->Add (Vector (30.0, 0.0, 1.8));

  uemobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");

  uemobility.SetPositionAllocator (uePositionAlloc);

  uemobility.Install (ueNodes);

  // Install LTE Devices to the nodes

  NetDeviceContainer enbDevs = mmwaveHelper->InstallEnbDevice (enbNodes);

  NetDeviceContainer ueDevs = mmwaveHelper->InstallUeDevice (ueNodes);

  // Install the IP stack on the UEs

  // Assign IP address to UEs, and install applications

  internet.Install (ueNodes);

  Ipv4InterfaceContainer ueIpIface;

  ueIpIface = epcHelper->AssignUeIpv4Address (NetDeviceContainer (ueDevs));

  mmwaveHelper->AttachToClosestEnb (ueDevs, enbDevs);

  mmwaveHelper->EnableTraces ();

  // Set the default gateway for the UE

  Ptr<Node> ueNode = ueNodes.Get (0);

  Ptr<Ipv4StaticRouting> ueStaticRouting = ipv4RoutingHelper.GetStaticRouting (ueNode->GetObject<Ipv4> ());

  ueStaticRouting->SetDefaultRoute (epcHelper->GetUeDefaultGatewayAddress (), 1);

  // Install and start applications on UEs and remote host

  uint16_t sinkPort = 20000;

  Address sinkAddress (InetSocketAddress (ueIpIface.GetAddress (0), sinkPort));

  PacketSinkHelper packetSinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));

  ApplicationContainer sinkApps = packetSinkHelper.Install (ueNodes.Get (0));

  sinkApps.Start (Seconds (0.));

  sinkApps.Stop (Seconds (simStopTime));

  Ptr<Socket> ns3UdpSocket = Socket::CreateSocket (remoteHostContainer.Get (0), UdpSocketFactory::GetTypeId ());

  AsciiTraceHelper asciisenderTraceHelper;

  Ptr<MyApp> app = CreateObject<MyApp> ();

  app->Setup (ns3UdpSocket, sinkAddress, 1400, 5000000, DataRate ("500Mb/s"));

  remoteHostContainer.Get (0)->AddApplication (app);

 

  AsciiTraceHelper asciiTraceHelper;

  Ptr<OutputStreamWrapper> stream2 = asciiTraceHelper.CreateFileStream ("427-udp-receiver-data.txt");

  sinkApps.Get (0)->TraceConnectWithoutContext ("Rx",MakeBoundCallback (&Rx, stream2));

 

  Ptr<OutputStreamWrapper> stream4 = asciiTraceHelper.CreateFileStream ("427-udp-drop-data.txt");

  internetDevices.Get(0)->TraceConnectWithoutContext ("PhyRxDrop",MakeBoundCallback (&PhyRxDrop, stream4));

 

  app->SetStartTime (Seconds (0.1));

  app->SetStopTime (Seconds (stopTime));

  p2ph.EnablePcapAll ("427-sgi-capture1");

  Simulator::Stop (Seconds (simStopTime));

  Simulator::Run ();

  Simulator::Destroy ();

  return 0;

}