├── CMakeLists.txt ├── README.md ├── doc ├── Makefile └── source │ ├── bursty-framework.rst │ └── conf.py ├── examples ├── CMakeLists.txt ├── bursty-application-example.cc ├── sample-mixture-random-variable.cc ├── sem-simulations.py ├── stats-calculator-example.cc ├── trace-file-burst-application-example.cc ├── vr-app-n-stas.cc └── vr-application-example.cc ├── helper ├── burst-sink-helper.cc ├── burst-sink-helper.h ├── bursty-app-stats-calculator.cc ├── bursty-app-stats-calculator.h ├── bursty-helper.cc └── bursty-helper.h └── model ├── BurstGeneratorTraces ├── README.md ├── ge_cities_10mbps_30fps.csv ├── ge_cities_10mbps_60fps.csv ├── ge_cities_20mbps_30fps.csv ├── ge_cities_20mbps_60fps.csv ├── ge_cities_30mbps_30fps.csv ├── ge_cities_30mbps_60fps.csv ├── ge_cities_40mbps_30fps.csv ├── ge_cities_40mbps_60fps.csv ├── ge_cities_50mbps_30fps.csv ├── ge_cities_50mbps_60fps.csv ├── ge_tour_10mbps_30fps.csv ├── ge_tour_10mbps_60fps.csv ├── ge_tour_20mbps_30fps.csv ├── ge_tour_20mbps_60fps.csv ├── ge_tour_30mbps_30fps.csv ├── ge_tour_30mbps_60fps.csv ├── ge_tour_40mbps_30fps.csv ├── ge_tour_40mbps_60fps.csv ├── ge_tour_50mbps_30fps.csv ├── ge_tour_50mbps_60fps.csv ├── mc_10mbps_30fps.csv ├── mc_10mbps_60fps.csv ├── mc_20mbps_30fps.csv ├── mc_20mbps_60fps.csv ├── mc_30mbps_30fps.csv ├── mc_30mbps_60fps.csv ├── mc_40mbps_30fps.csv ├── mc_40mbps_60fps.csv ├── mc_50mbps_30fps.csv ├── mc_50mbps_60fps.csv ├── vp_10mbps_30fps.csv ├── vp_10mbps_60fps.csv ├── vp_20mbps_30fps.csv ├── vp_20mbps_60fps.csv ├── vp_30mbps_30fps.csv ├── vp_30mbps_60fps.csv ├── vp_40mbps_30fps.csv ├── vp_40mbps_60fps.csv ├── vp_50mbps_30fps.csv └── vp_50mbps_60fps.csv ├── burst-generator.cc ├── burst-generator.h ├── burst-sink.cc ├── burst-sink.h ├── bursty-application.cc ├── bursty-application.h ├── my-random-variable-stream.cc ├── my-random-variable-stream.h ├── seq-ts-size-frag-header.cc ├── seq-ts-size-frag-header.h ├── simple-burst-generator.cc ├── simple-burst-generator.h ├── trace-file-burst-generator.cc ├── trace-file-burst-generator.h ├── vr-burst-generator.cc └── vr-burst-generator.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | build_lib( 2 | LIBNAME vr-app 3 | SOURCE_FILES model/burst-generator.cc 4 | model/burst-sink.cc 5 | model/bursty-application.cc 6 | model/my-random-variable-stream.cc 7 | model/seq-ts-size-frag-header.cc 8 | model/simple-burst-generator.cc 9 | model/trace-file-burst-generator.cc 10 | model/vr-burst-generator.cc 11 | helper/bursty-helper.cc 12 | helper/burst-sink-helper.cc 13 | helper/bursty-app-stats-calculator.cc 14 | HEADER_FILES model/burst-generator.h 15 | model/burst-sink.h 16 | model/bursty-application.h 17 | model/my-random-variable-stream.h 18 | model/seq-ts-size-frag-header.h 19 | model/simple-burst-generator.h 20 | model/trace-file-burst-generator.h 21 | model/vr-burst-generator.h 22 | helper/bursty-helper.h 23 | helper/burst-sink-helper.h 24 | helper/bursty-app-stats-calculator.h 25 | LIBRARIES_TO_LINK ${libcore} 26 | ${libapplications} 27 | ${libpoint-to-point} 28 | ${libinternet} 29 | ) 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | VR traffic model for ns-3 2 | ========================= 3 | 4 | **NOTE:** You can find detailed information about this module in the referenced papers below. 5 | 6 | Examples of usage for the newly introduced features can be found in the ``examples/`` folder. 7 | 8 | ## Features 9 | 10 | This module comprises the following features: 11 | 12 | * Adds `BurstyApplication` and `BurstSink` as ns-3 applications: they allow to model complex applications by sending large data packets over UDP sockets, fragmenting them into bursts of smaller packets, and reassembling the packets at the receiver, if possible 13 | * A tracing system allows to obtain burst-level and fragment-level information at both the transmitter and receiver side 14 | * Models Virtual Reality traffic sources with realistic head movements in popular VR applications 15 | * 40 of the acquired VR traffic traces can be found in [model/BurstGeneratorTraces/](model/BurstGeneratorTraces/) and can be used directly in a simulation, using the `TraceFileBurstGenerator`. More information can be found in the folder and in the documentation. 16 | * Additional traffic models can be implemented by simply extending the `BurstGenerator` interface 17 | 18 | Future releases will aim to: 19 | * Model second-order statistics for VR traffic 20 | * Include a head-rotation model, coupled with the VR traffic generator 21 | * Optionally include sound traffic in the VR traffic generator, other than video traffic 22 | * Optionally include uplink/downlink control packets for the VR traffic model 23 | * Improve `BurstSink` to also include some form of forward error correction 24 | 25 | More information can be found in the reference paper(s). 26 | 27 | ## Install 28 | 29 | ### Prerequisites ### 30 | 31 | To run simulations using this module, you will need to install ns-3, and clone 32 | this repository inside the `contrib` directory. 33 | Required dependencies include git and a build environment. 34 | 35 | #### Installing dependencies #### 36 | 37 | Please refer to [the ns-3 wiki](https://www.nsnam.org/wiki/Installation) for instructions on how to set up your system to install ns-3. 38 | 39 | Please check the [releases](https://github.com/signetlabdei/ns-3-vr-app/releases) for further information about dependencies. 40 | 41 | #### Downloading ##### 42 | 43 | First, clone the main ns-3 repository: 44 | 45 | ```bash 46 | git clone https://gitlab.com/nsnam/ns-3-dev ns-3-dev 47 | ``` 48 | 49 | Then, clone the vr-app module: 50 | ```bash 51 | git clone https://github.com/signetlabdei/ns-3-vr-app ns-3-dev/contrib/vr-app 52 | ``` 53 | 54 | ### Compilation ### 55 | 56 | Configure and build ns-3 from the `ns-3-dev` folder: 57 | 58 | ```bash 59 | ./ns3 configure --enable-tests --enable-examples 60 | ./ns3 build 61 | ``` 62 | 63 | This module does not provide Python bindings at the moment. 64 | 65 | ### Documentation ### 66 | 67 | To compile the documentation, please follow the instructions from the [ns-3 manual](https://www.nsnam.org/docs/manual/html/documentation.html). 68 | 69 | Basic steps: 70 | 71 | 1. Install the documentation-specific dependencies as described in the [ns-3 installation guide](https://www.nsnam.org/wiki/Installation) 72 | 1. You might need to fix the ImageMagick permissions for ghostscript files 73 | 74 | Compiling standalone documentation: 75 | 76 | 1. Run in your terminal, in the ns-3 root folder, `make -C contrib/vr-app/doc html` 77 | 1. Open with your browser the file `contrib/vr-app/doc/models/build/html/bursty-framework.html` to visualize the documentation of the model 78 | 79 | 80 | ## Reference papers 81 | 82 | * M. Lecci, M. Drago, A. Zanella, M. Zorzi, "An Open Framework for Analyzing and Modeling XR Network Traffic," in IEEE Access, vol. 9, pp. 129782-129795, 2021. Open Access DOI: [10.1109/ACCESS.2021.3113162](https://doi.org/10.1109/ACCESS.2021.3113162). 83 | * M. Lecci, A. Zanella, M. Zorzi, "An ns-3 Implementation of a Bursty Traffic Framework for Virtual Reality Sources," Workshop on ns-3 (WNS3), Jun. 2021, Virtual Event, USA, Open access DOI: [10.1145/3460797.3460807](https://doi.org/10.1145/3460797.3460807). -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | EPSTOPDF = epstopdf 2 | DIA = dia 3 | DOT = dot 4 | CONVERT = convert -density 250 5 | 6 | 7 | SOURCE = source 8 | FIGURES = $(SOURCE)/figures 9 | 10 | # specify dia figures from which .png and .pdf figures need to be built 11 | 12 | IMAGES_DIA = \ 13 | 14 | # specify eps figures from which .png and .pdf figures need to be built 15 | 16 | IMAGES_EPS = \ 17 | 18 | # rescale pdf figures as necessary 19 | 20 | IMAGES_NOBUILD = 21 | # IMAGES_NOBUILD = $(FIGURES)/fading_pedestrian.png \ 22 | 23 | IMAGES_BUILD = \ 24 | ${IMAGES_DIA:.dia=.eps} \ 25 | ${IMAGES_DIA:.dia=.png} \ 26 | ${IMAGES_DIA:.dia=.pdf} \ 27 | ${IMAGES_EPS:.eps=.png} \ 28 | ${IMAGES_EPS:.eps=.pdf} 29 | 30 | 31 | IMAGES = $(IMAGES_NOBUILD) $(IMAGES_BUILD) 32 | 33 | RESCALE = ../../../utils/rescale-pdf.sh 34 | 35 | %.eps : %.dia; $(DIA) -t eps $< -e $@ 36 | %.png : %.dia; $(DIA) -t png $< -e $@ 37 | %.png : %.eps; $(CONVERT) $< $@ 38 | %.pdf : %.eps 39 | $(EPSTOPDF) $< -o=$@ 40 | if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi 41 | 42 | 43 | # You can set these variables from the command line. 44 | SPHINXOPTS = 45 | SPHINXBUILD = sphinx-build 46 | PAPER = 47 | BUILDDIR = build 48 | 49 | # Internal variables. 50 | PAPEROPT_a4 = -D latex_paper_size=a4 51 | PAPEROPT_letter = -D latex_paper_size=letter 52 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE) 53 | 54 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 55 | 56 | help: 57 | @echo "Please use \`make ' where is one of" 58 | @echo " html to make standalone HTML files" 59 | @echo " dirhtml to make HTML files named index.html in directories" 60 | @echo " singlehtml to make a single large HTML file" 61 | @echo " pickle to make pickle files" 62 | @echo " json to make JSON files" 63 | @echo " htmlhelp to make HTML files and a HTML help project" 64 | @echo " qthelp to make HTML files and a qthelp project" 65 | @echo " devhelp to make HTML files and a Devhelp project" 66 | @echo " epub to make an epub" 67 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 68 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 69 | @echo " text to make text files" 70 | @echo " man to make manual pages" 71 | @echo " changes to make an overview of all changed/added/deprecated items" 72 | @echo " linkcheck to check all external links for integrity" 73 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 74 | 75 | clean: 76 | -rm -rf $(BUILDDIR)/* 77 | -rm -f $(IMAGES_BUILD) 78 | 79 | 80 | images: $(IMAGES_NOBUILD) $(IMAGES_BUILD) 81 | 82 | frag: pickle 83 | @if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi 84 | pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle > navigation.xml && popd 85 | cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag 86 | 87 | html: $(IMAGES) 88 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 89 | @echo 90 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 91 | 92 | dirhtml: $(IMAGES) 93 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 94 | @echo 95 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 96 | 97 | singlehtml: $(IMAGES) 98 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 99 | @echo 100 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 101 | 102 | pickle: $(IMAGES) 103 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 104 | @echo 105 | @echo "Build finished; now you can process the pickle files." 106 | 107 | json: $(IMAGES) 108 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 109 | @echo 110 | @echo "Build finished; now you can process the JSON files." 111 | 112 | htmlhelp: $(IMAGES) 113 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 114 | @echo 115 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 116 | ".hhp project file in $(BUILDDIR)/htmlhelp." 117 | 118 | qthelp: $(IMAGES) 119 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 120 | @echo 121 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 122 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 123 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ns-3.qhcp" 124 | @echo "To view the help file:" 125 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ns-3.qhc" 126 | 127 | devhelp: $(IMAGES) 128 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 129 | @echo 130 | @echo "Build finished." 131 | @echo "To view the help file:" 132 | @echo "# mkdir -p $$HOME/.local/share/devhelp/ns-3" 133 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ns-3" 134 | @echo "# devhelp" 135 | 136 | epub: $(IMAGES) 137 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 138 | @echo 139 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 140 | 141 | latex: $(IMAGES) 142 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 143 | @echo 144 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 145 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 146 | "(use \`make latexpdf' here to do that automatically)." 147 | 148 | latexpdf: $(IMAGES) 149 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 150 | @echo "Running LaTeX files through pdflatex..." 151 | make -C $(BUILDDIR)/latex all-pdf 152 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 153 | 154 | text: $(IMAGES) 155 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 156 | @echo 157 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 158 | 159 | man: $(IMAGES) 160 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 161 | @echo 162 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 163 | 164 | changes: $(IMAGES) 165 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 166 | @echo 167 | @echo "The overview file is in $(BUILDDIR)/changes." 168 | 169 | linkcheck: $(IMAGEs) 170 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 171 | @echo 172 | @echo "Link check complete; look for any errors in the above output " \ 173 | "or in $(BUILDDIR)/linkcheck/output.txt." 174 | 175 | doctest: $(IMAGES) 176 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 177 | @echo "Testing of doctests in the sources finished, look at the " \ 178 | "results in $(BUILDDIR)/doctest/output.txt." 179 | -------------------------------------------------------------------------------- /doc/source/bursty-framework.rst: -------------------------------------------------------------------------------- 1 | Bursty Framework 2 | ---------------- 3 | 4 | The framework aims at supporting large packets sent across a network, fragmented into bursts of multiple smaller packets. 5 | 6 | 7 | Model Description 8 | ***************** 9 | 10 | This model is described in `[WNS3-2021]`_ and was later improved in `[Access21]`_. 11 | It was originally designed to model an Virtual Reality traffic source, although the bursty framework is more general. 12 | 13 | 14 | Design 15 | ====== 16 | 17 | Packets are generated by a class extending the ``BurstGenerator`` interface, fragmented into packet bursts by ``BurstyApplication``, and finally received by a ``BurstSink``. 18 | The framework is similar to ``OnOffApplication``-``PacketSink``, but generalized to support large packets fragmented into bursts. 19 | 20 | Burst Generator description 21 | ########################### 22 | 23 | The ``BurstGenerator`` interface defines two methods that child classes have to extend, namely ``GenerateBurst`` and ``HasNextBurst``. 24 | The former generates a packet size and period, while the latter makes sure whether it is possible to generate an additional burst. 25 | 26 | The framework comes with three generators already implemented: 27 | 28 | - ``SimpleBurstGenerator``: the user can specify ``RandomVariableStream`` for the packet size and period. 29 | - ``TraceFileBurstGenerator``: traffic trace files are imported and executed in ns-3, allowing the user to import real traffic traces into its simulations. Some traces representing a VR traffic source are included. 30 | - ``VrBurstGenerator``: implements a traffic model able to simulate VR traffic sources, as described in `[Access21]`_. The model is based on over 4 hours of acquisitions while playing three different applications targeting different types of interactions. Specifically: 31 | 32 | #. *Minecraft*: an extremely popular game, with the mod *Vivecraft* enabling both room-scale or seated VR experiences. The user can explore by walking or swimming, and interact with the virtual world by cutting trees, digging holes, crafting tools, etc. 33 | #. *Virus Popper*: during this fast-paced educational game, many cartoony-looking viruses swarm a virtual room, and the user has to attack them with cleaning tools for survival. 34 | #. *Google Earth VR - Tour*: the VR version of Google earth, allowing you to explore the world with satellite imagery, 3D terrain of the entire globe, and 3D buildings in hundreds of cities around the world. The SteamVR application allows you to make tours, teleporting the user all around the world every few seconds. 35 | #. *Google Earth VR - Cities*: in this case, a more interactive experience is yielded, allowing the user to fully explore cities or landmarks for as long as they want. 36 | 37 | Please note that *Google Earth VR* was used in two different ways, thus allowing us to analyze two different versions of a same application. 38 | 39 | Bursty Application description 40 | ############################## 41 | 42 | The ``BurstyApplication`` generates packet bursts based on the information yielded by the attached ``BurstGenerator``. 43 | A ``SeqTsSizeFragHeader`` is attached to each fragment, with information on its transmission time, the burst sequence number, the fragment sequence number, the total burst size, and the total number of fragments of the burst. 44 | This information is then used by the ``BurstSink`` to re-aggregate the burst into a single packet, if possible. 45 | 46 | Traces are fired for each transmitted fragment and burst. 47 | 48 | Burst Sink description 49 | ###################### 50 | 51 | The ``BurstSink`` tries to re-aggregate fragments into the original packet. 52 | It assumes that the burst transmission duration is relatively small compared to the burst period, and does not perform any Forward Error Correction (FEC). 53 | 54 | To do so, it gathers information from SeqTsSizeFragHeader, which all received packets should have. 55 | It then proceeds as follows: 56 | 57 | - Being based on a UDP socket, packets might arrive out-of-order. Within a burst, BurstSink will reorder the received packets. 58 | - While receiving burst n, if a fragment from burst kn is received, burst n is discarded and burst k will start being buffered. 60 | - If all fragments from a burst are received, the burst is successfully received. 61 | 62 | Traces are fired for each received fragment and burst successfully received. 63 | 64 | 65 | Usage 66 | ***** 67 | 68 | This section is principally concerned with the usage of your model, using the public API. Focus first on most common usage patterns, then go into more advanced topics. 69 | 70 | Building New Module 71 | =================== 72 | 73 | First, clone the main ns-3 repository, e.g.,: 74 | 75 | ``git clone https://gitlab.com/nsnam/ns-3-dev ns-3-dev`` 76 | 77 | Then, clone the bursty framework module into the ``contrib/`` folder: 78 | 79 | ``git clone https://github.com/signetlabdei/ns-3-vr-app ns-3-dev/contrib/vr-app`` 80 | 81 | Configure and build ns-3 from the `ns-3-dev` folder: 82 | 83 | | ``./waf configure --enable-tests --enable-examples`` 84 | | ``./waf build`` 85 | 86 | This module does not provide Python bindings at the moment. 87 | 88 | 89 | Setting up a scenario 90 | ===================== 91 | 92 | Please reference the examples to understand how to set up a scenario. 93 | 94 | 95 | Examples 96 | ======== 97 | 98 | For more information, please check the the source files of the provided examples. 99 | 100 | Troubleshooting 101 | =============== 102 | 103 | For any problem with the module, please open an issue. The maintainers will do their best to provide technical support! 104 | 105 | 106 | 107 | References 108 | ********** 109 | 110 | .. _`[WNS3-2021]`: 111 | 112 | [WNS3-2021] Mattia Lecci, Andrea Zanella, Michele Zorzi, "An ns-3 Implementation of a Bursty Traffic Framework for Virtual Reality Sources," in Workshop on ns-3 (WNS3), Jun. 2021, Virtual Event, US. DOI: `10.1145/3460797.3460807 `_. 113 | 114 | .. _`[Access21]`: 115 | 116 | [Access21] Mattia Lecci, Matteo Drago, Andrea Zanella, Michele Zorzi, "An Open Framework for Analyzing and Modeling XR Network Traffic," in IEEE Access, vol. 9, pp. 129782-129795, 2021. DOI: `10.1109/ACCESS.2021.3113162 `_. -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # ns-3 documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Dec 14 09:00:39 2010. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = ['sphinx.ext.imgmath'] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ['_templates'] 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The encoding of source files. 37 | #source_encoding = 'utf-8-sig' 38 | 39 | # The master toctree document. 40 | master_doc = 'bursty-framework' 41 | 42 | # General information about the project. 43 | project = u'ns-3' 44 | copyright = u'ns-3 project' 45 | 46 | # The version info for the project you're documenting, acts as replacement for 47 | # |version| and |release|, also used in various other places throughout the 48 | # built documents. 49 | # 50 | # The short X.Y version. 51 | version = 'ns-3-dev' 52 | # The full version, including alpha/beta/rc tags. 53 | release = 'ns-3-dev' 54 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation 56 | # for a list of supported languages. 57 | #language = None 58 | 59 | # There are two options for replacing |today|: either, you set today to some 60 | # non-false value, then it is used: 61 | #today = '' 62 | # Else, today_fmt is used as the format for a strftime call. 63 | #today_fmt = '%B %d, %Y' 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | exclude_patterns = [] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. See the documentation for 93 | # a list of builtin themes. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | #html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_domain_indices = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 153 | #html_show_sphinx = True 154 | 155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 156 | #html_show_copyright = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = None 165 | 166 | # Output file base name for HTML help builder. 167 | #htmlhelp_basename = 'ns-3doc' 168 | 169 | 170 | # -- Options for LaTeX output -------------------------------------------------- 171 | 172 | # The paper size ('letter' or 'a4'). 173 | #latex_paper_size = 'letter' 174 | 175 | # The font size ('10pt', '11pt' or '12pt'). 176 | #latex_font_size = '10pt' 177 | 178 | # Grouping the document tree into LaTeX files. List of tuples 179 | # (source start file, target name, title, author, documentclass [howto/manual]). 180 | latex_documents = [ 181 | # ('bursty-framework-testing', 'bursty-framework-doc-testing.tex', u'bursty-framework Testing Documentation', u'ns-3 project', 'manual'), 182 | # ('bursty-framework-design', 'bursty-framework-doc-design.tex', u'bursty-framework Design Documentation', u'ns-3 project', 'manual'), 183 | # ('bursty-framework-user', 'bursty-framework-doc-user.tex', u'bursty-framework User Documentation', u'ns-3 project', 'manual'), 184 | ('bursty-framework', 'bursty-framework-module-doc.tex', u'The ns-3 bursty-framework Module Documentation', u'ns-3 project', 'manual'), 185 | ] 186 | 187 | # The name of an image file (relative to this directory) to place at the top of 188 | # the title page. 189 | #latex_logo = None 190 | 191 | # For "manual" documents, if this is true, then toplevel headings are parts, 192 | # not chapters. 193 | #latex_use_parts = False 194 | 195 | # If true, show page references after internal links. 196 | #latex_show_pagerefs = False 197 | 198 | # If true, show URL addresses after external links. 199 | #latex_show_urls = False 200 | 201 | # Additional stuff for the LaTeX preamble. 202 | #latex_preamble = '' 203 | 204 | # Documents to append as an appendix to all manuals. 205 | #latex_appendices = [] 206 | 207 | # If false, no module index is generated. 208 | #latex_domain_indices = True 209 | 210 | 211 | 212 | # add page breaks in the pdf. Level 1 is for top-level sections, level 2 for subsections, and so on. 213 | pdf_break_level = 4 214 | 215 | 216 | # -- Options for manual page output -------------------------------------------- 217 | 218 | # One entry per manual page. List of tuples 219 | # (source start file, name, description, authors, manual section). 220 | man_pages = [ 221 | ('index', 'ns-3-model-library', u'ns-3 Model Library', 222 | [u'ns-3 project'], 1) 223 | ] -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | build_lib_example( 2 | NAME sample-mixture-random-variable 3 | SOURCE_FILES sample-mixture-random-variable.cc 4 | LIBRARIES_TO_LINK ${libvr-app} 5 | ${libapplications} 6 | ) 7 | 8 | build_lib_example( 9 | NAME bursty-application-example 10 | SOURCE_FILES bursty-application-example.cc 11 | LIBRARIES_TO_LINK ${libvr-app} 12 | ${libapplications} 13 | ${libpoint-to-point} 14 | ${libinternet} 15 | ${libnetwork} 16 | ) 17 | 18 | build_lib_example( 19 | NAME vr-application-example 20 | SOURCE_FILES vr-application-example.cc 21 | LIBRARIES_TO_LINK ${libvr-app} 22 | ${libapplications} 23 | ${libpoint-to-point} 24 | ${libinternet} 25 | ${libnetwork} 26 | ) 27 | 28 | build_lib_example( 29 | NAME trace-file-burst-application-example 30 | SOURCE_FILES trace-file-burst-application-example.cc 31 | LIBRARIES_TO_LINK ${libvr-app} 32 | ${libapplications} 33 | ${libpoint-to-point} 34 | ${libinternet} 35 | ${libnetwork} 36 | ) 37 | 38 | build_lib_example( 39 | NAME vr-app-n-stas 40 | SOURCE_FILES vr-app-n-stas.cc 41 | LIBRARIES_TO_LINK ${libvr-app} 42 | ${libapplications} 43 | ${libcore} 44 | ${libwifi} 45 | ) 46 | 47 | build_lib_example( 48 | NAME stats-calculator-example 49 | SOURCE_FILES stats-calculator-example.cc 50 | LIBRARIES_TO_LINK ${libvr-app} 51 | ${libapplications} 52 | ${libcore} 53 | ${libwifi} 54 | ) -------------------------------------------------------------------------------- /examples/bursty-application-example.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include "ns3/core-module.h" 22 | #include "ns3/network-module.h" 23 | #include "ns3/internet-module.h" 24 | #include "ns3/point-to-point-module.h" 25 | #include "ns3/applications-module.h" 26 | 27 | #include "ns3/seq-ts-size-frag-header.h" 28 | #include "ns3/bursty-helper.h" 29 | #include "ns3/burst-sink-helper.h" 30 | 31 | /** 32 | * An example of how the BurstyApplication works. 33 | * Traces for RX/TX fragments/bursts are extracted as well as the setup of 34 | * a BurstyApplication with a SimpleBurstGenerator. 35 | */ 36 | 37 | using namespace ns3; 38 | 39 | NS_LOG_COMPONENT_DEFINE ("BurstyApplicationExample"); 40 | 41 | std::string 42 | AddressToString (const Address &addr) 43 | { 44 | std::stringstream addressStr; 45 | addressStr << InetSocketAddress::ConvertFrom (addr).GetIpv4 () << ":" 46 | << InetSocketAddress::ConvertFrom (addr).GetPort (); 47 | return addressStr.str (); 48 | } 49 | 50 | void 51 | FragmentTx (Ptr fragment, const Address &from, const Address &to, 52 | const SeqTsSizeFragHeader &header) 53 | { 54 | NS_LOG_INFO ("Sent fragment " << header.GetFragSeq () << "/" << header.GetFrags () 55 | << " of burst seq=" << header.GetSeq () 56 | << " of header.GetSize ()=" << header.GetSize () 57 | << " (fragment->GetSize ()=" << fragment->GetSize () 58 | << ") bytes from " << AddressToString (from) << " to " 59 | << AddressToString (to) << " at " << header.GetTs ().As (Time::S)); 60 | } 61 | 62 | void 63 | FragmentRx (Ptr fragment, const Address &from, const Address &to, 64 | const SeqTsSizeFragHeader &header) 65 | { 66 | NS_LOG_INFO ("Received fragment " 67 | << header.GetFragSeq () << "/" << header.GetFrags () << " of burst seq=" 68 | << header.GetSeq () << " of header.GetSize ()=" << header.GetSize () 69 | << " (fragment->GetSize ()=" << fragment->GetSize () << ") bytes from " 70 | << AddressToString (from) << " to " << AddressToString (to) << " at " 71 | << header.GetTs ().As (Time::S)); 72 | } 73 | 74 | void 75 | BurstTx (Ptr burst, const Address &from, const Address &to, 76 | const SeqTsSizeFragHeader &header) 77 | { 78 | NS_LOG_INFO ("Sent burst seq=" << header.GetSeq () << " of header.GetSize ()=" 79 | << header.GetSize () << " (burst->GetSize ()=" << burst->GetSize () 80 | << ") bytes from " << AddressToString (from) << " to " 81 | << AddressToString (to) << " at " << header.GetTs ().As (Time::S)); 82 | } 83 | 84 | void 85 | BurstRx (Ptr burst, const Address &from, const Address &to, 86 | const SeqTsSizeFragHeader &header) 87 | { 88 | NS_LOG_INFO ("Received burst seq=" 89 | << header.GetSeq () << " of header.GetSize ()=" << header.GetSize () 90 | << " (burst->GetSize ()=" << burst->GetSize () << ") bytes from " 91 | << AddressToString (from) << " to " << AddressToString (to) << " at " 92 | << header.GetTs ().As (Time::S)); 93 | } 94 | 95 | int 96 | main (int argc, char *argv[]) 97 | { 98 | double simTimeSec = 10; 99 | CommandLine cmd (__FILE__); 100 | cmd.AddValue ("SimulationTime", "Length of simulation in seconds.", simTimeSec); 101 | cmd.Parse (argc, argv); 102 | 103 | Time::SetResolution (Time::NS); 104 | LogComponentEnableAll (LOG_PREFIX_TIME); 105 | LogComponentEnable ("BurstyApplicationExample", LOG_INFO); 106 | 107 | // Setup two nodes 108 | NodeContainer nodes; 109 | nodes.Create (2); 110 | 111 | PointToPointHelper pointToPoint; 112 | pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 113 | pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 114 | 115 | NetDeviceContainer devices; 116 | devices = pointToPoint.Install (nodes); 117 | 118 | InternetStackHelper stack; 119 | stack.Install (nodes); 120 | 121 | uint16_t portNumber = 50000; 122 | 123 | Ipv4AddressHelper address; 124 | address.SetBase ("10.1.1.0", "255.255.255.0"); 125 | Ipv4InterfaceContainer interfaces = address.Assign (devices); 126 | 127 | Ipv4Address serverAddress = interfaces.GetAddress (0); 128 | Ipv4Address sinkAddress = Ipv4Address::GetAny (); // 0.0.0.0 129 | 130 | // Create bursty application helper 131 | BurstyHelper burstyHelper ("ns3::UdpSocketFactory", InetSocketAddress (serverAddress, portNumber)); 132 | burstyHelper.SetAttribute ("FragmentSize", UintegerValue (1200)); 133 | burstyHelper.SetBurstGenerator ("ns3::SimpleBurstGenerator", 134 | "PeriodRv", StringValue ("ns3::ConstantRandomVariable[Constant=100e-3]"), 135 | "BurstSizeRv", StringValue ("ns3::ConstantRandomVariable[Constant=10e3]")); 136 | 137 | // Install bursty application 138 | ApplicationContainer serverApps = burstyHelper.Install (nodes.Get (1)); 139 | Ptr burstyApp = serverApps.Get (0)->GetObject (); 140 | 141 | // Example of connecting to the trace sources 142 | burstyApp->TraceConnectWithoutContext ("FragmentTx", MakeCallback (&FragmentTx)); 143 | burstyApp->TraceConnectWithoutContext ("BurstTx", MakeCallback (&BurstTx)); 144 | 145 | // Create burst sink helper 146 | BurstSinkHelper burstSinkHelper ("ns3::UdpSocketFactory", 147 | InetSocketAddress (sinkAddress, portNumber)); 148 | 149 | // Install burst sink 150 | ApplicationContainer clientApps = burstSinkHelper.Install (nodes.Get (0)); 151 | Ptr burstSink = clientApps.Get (0)->GetObject (); 152 | 153 | // Example of connecting to the trace sources 154 | burstSink->TraceConnectWithoutContext ("BurstRx", MakeCallback (&BurstRx)); 155 | burstSink->TraceConnectWithoutContext ("FragmentRx", MakeCallback (&FragmentRx)); 156 | 157 | // Stop bursty app after simTimeSec 158 | serverApps.Stop (Seconds (simTimeSec)); 159 | Simulator::Run (); 160 | Simulator::Destroy (); 161 | 162 | // Stats 163 | std::cout << "Total RX bursts: " << burstyApp->GetTotalTxBursts () << "/" 164 | << burstSink->GetTotalRxBursts () << std::endl; 165 | std::cout << "Total RX fragments: " << burstyApp->GetTotalTxFragments () << "/" 166 | << burstSink->GetTotalRxFragments () << std::endl; 167 | std::cout << "Total RX bytes: " << burstyApp->GetTotalTxBytes () << "/" 168 | << burstSink->GetTotalRxBytes () << std::endl; 169 | 170 | return 0; 171 | } 172 | -------------------------------------------------------------------------------- /examples/sample-mixture-random-variable.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #include "ns3/simulator.h" 20 | #include "ns3/nstime.h" 21 | #include "ns3/double.h" 22 | #include "ns3/object-factory.h" 23 | #include "ns3/command-line.h" 24 | #include "ns3/random-variable-stream.h" 25 | #include "ns3/my-random-variable-stream.h" 26 | #include 27 | #include 28 | 29 | /** 30 | * \file 31 | * \ingroup core-examples 32 | * \ingroup randomvariable 33 | * Example program illustrating use of ns3::MixtureRandomVariable 34 | */ 35 | 36 | using namespace ns3; 37 | 38 | int 39 | main (int argc, char *argv[]) 40 | { 41 | uint32_t nSamples = 1000000; 42 | 43 | CommandLine cmd (__FILE__); 44 | cmd.AddValue ("nSamples", "Number of samples", nSamples); 45 | cmd.Parse (argc, argv); 46 | 47 | Ptr x = CreateObject (); 48 | 49 | // setup weights cdf 50 | std::vector w{0.7, 1.0}; // p1 = 0.7, p2 = 0.3 51 | // setup random variables 52 | std::vector> rvs; 53 | rvs.push_back (CreateObjectWithAttributes ("Mean", DoubleValue (5), 54 | "Variance", DoubleValue (1))); 55 | rvs.push_back (CreateObjectWithAttributes ("Mean", DoubleValue (10), 56 | "Variance", DoubleValue (4))); 57 | 58 | x->SetRvs (w, rvs); 59 | 60 | for (uint32_t i = 0; i < nSamples; i++) 61 | { 62 | std::cout << x->GetValue () << std::endl; 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /examples/sem-simulations.py: -------------------------------------------------------------------------------- 1 | # AUTHOR(S): 2 | # Mattia Lecci 3 | # 4 | # University of Padova (UNIPD), Italy 5 | # Information Engineering Department (DEI) 6 | # SIGNET Research Group @ http://signet.dei.unipd.it/ 7 | # 8 | # Date: December 2020 9 | 10 | import sem 11 | import os 12 | import sys 13 | import argparse 14 | from collections import OrderedDict 15 | import numpy as np 16 | from matplotlib import pyplot as plt 17 | import copy 18 | import tikzplotlib 19 | 20 | sys.stdout.flush() 21 | 22 | # SEM script that generates the plots of the reference paper. 23 | # For further information please check the reference paper (see README.md). 24 | 25 | def remove_simulations(broken_results): 26 | print("Removing broken simulations") 27 | # TODO test map(campaign.db.delete_result, broken_results.flatten()) 28 | for result in broken_results.flatten(): 29 | if result: 30 | print("removing ", str(result['meta']['id'])) 31 | campaign.db.delete_result(result) 32 | # write updated database to disk 33 | campaign.db.write_to_disk() 34 | 35 | 36 | def check_stderr(result): 37 | if len(result['output']['stderr']) > 0: 38 | print('Invalid simulation: ', result['meta']['id'], file=sys.stderr) 39 | return result 40 | else: 41 | return [] 42 | 43 | 44 | def compute_avg_burst_thr_mbps(results): 45 | # print("id:", results['meta']['id']) 46 | trace = results['output']['burstTrace.csv'] 47 | 48 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize 49 | delays = np.array([float(row.split(',')[4]) * 8 / 1e6 # Mb 50 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 51 | 52 | if len(delays) > 0: 53 | delay = np.sum(delays) / results['params']['simulationTime'] 54 | else: 55 | delay = 0 56 | 57 | # print(delay) 58 | 59 | return delay 60 | 61 | 62 | def compute_avg_burst_delay_ms(results): 63 | # print("id:", results['meta']['id']) 64 | trace = results['output']['burstTrace.csv'] 65 | 66 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize 67 | delays = np.array([(float(row.split(',')[2]) - float(row.split(',')[1])) / 1e6 # ms 68 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 69 | 70 | if len(delays) > 0: 71 | delay = np.mean(delays) 72 | else: 73 | delay = 0 74 | 75 | # print(delay) 76 | 77 | return delay 78 | 79 | 80 | def compute_95perc_burst_delay_ms(results): 81 | # print("id:", results['meta']['id']) 82 | trace = results['output']['burstTrace.csv'] 83 | 84 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize 85 | delays = np.array([(float(row.split(',')[2]) - float(row.split(',')[1])) / 1e6 # ms 86 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 87 | 88 | if len(delays) > 0: 89 | delay = np.percentile(delays, 95) 90 | else: 91 | delay = 0 92 | 93 | # print(delay) 94 | 95 | return delay 96 | 97 | 98 | def compute_burst_succ_rate(results): 99 | # print("id:", results['meta']['id']) 100 | trace = results['output']['txBurstsBySta.csv'] 101 | tot_tx = np.sum([float(n) for n in trace.split('\n')[:-1]]) 102 | 103 | trace = results['output']['rxBursts.csv'] 104 | tot_rx = float(trace.rstrip('\n')) 105 | 106 | 107 | if tot_rx > 0: 108 | succ = tot_rx / tot_tx 109 | else: 110 | succ = 0 111 | 112 | return succ 113 | 114 | 115 | def compute_avg_fragment_thr_mbps(results): 116 | # print("id:", results['meta']['id']) 117 | trace = results['output']['fragmentTrace.csv'] 118 | 119 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,FragSeq,TotFrags,FragSize 120 | delays = np.array([float(row.split(',')[-1]) * 8 / 1e6 # Mb 121 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 122 | 123 | if len(delays) > 0: 124 | delay = np.sum(delays) / results['params']['simulationTime'] 125 | else: 126 | delay = 0 127 | 128 | # print(delay) 129 | 130 | return delay 131 | 132 | 133 | def compute_avg_fragment_delay_ms(results): 134 | # print("id:", results['meta']['id']) 135 | trace = results['output']['fragmentTrace.csv'] 136 | 137 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize 138 | delays = np.array([(float(row.split(',')[2]) - float(row.split(',')[1])) / 1e6 # ms 139 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 140 | 141 | if len(delays) > 0: 142 | delay = np.mean(delays) 143 | else: 144 | delay = 0 145 | 146 | # print(delay) 147 | 148 | return delay 149 | 150 | 151 | def compute_95perc_fragment_delay_ms(results): 152 | # print("id:", results['meta']['id']) 153 | trace = results['output']['fragmentTrace.csv'] 154 | 155 | # SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize 156 | delays = np.array([(float(row.split(',')[2]) - float(row.split(',')[1])) / 1e6 # ms 157 | for i, row in enumerate(trace.split('\n')[:-1]) if (i > 0)]) 158 | 159 | if len(delays) > 0: 160 | delay = np.percentile(delays, 95) 161 | else: 162 | delay = 0 163 | 164 | # print(delay) 165 | 166 | return delay 167 | 168 | 169 | def compute_fragment_succ_rate(results): 170 | # print("id:", results['meta']['id']) 171 | trace = results['output']['txFragmentsBySta.csv'] 172 | tot_tx = np.sum([float(n) for n in trace.split('\n')[:-1]]) 173 | 174 | trace = results['output']['rxFragments.csv'] 175 | tot_rx = float(trace.rstrip('\n')) 176 | 177 | if tot_rx > 0: 178 | succ = tot_rx / tot_tx 179 | else: 180 | succ = 0 181 | 182 | return succ 183 | 184 | 185 | def plot_line_metric(campaign, parameter_space, result_parsing_function, runs, xx, hue_var, xlabel, ylabel, filename, ylim=None, xscale="linear", yscale="linear"): 186 | print("Plotting (line): ", os.path.join(img_dir, filename)) 187 | metric = campaign.get_results_as_xarray(parameter_space, 188 | result_parsing_function, 189 | xlabel, 190 | runs) 191 | # average over numRuns and squeeze 192 | metric_mean = metric.reduce(np.mean, 'runs').squeeze() 193 | metric_ci95 = metric.reduce(np.std, 'runs').squeeze() * 1.96 / np.sqrt(runs) 194 | 195 | fig = plt.figure() 196 | for val in metric_mean.coords[hue_var].values: 197 | plt.errorbar(xx, metric_mean.sel({hue_var: val}), 198 | yerr=metric_ci95.sel({hue_var: val}), 199 | label=f"{hue_var}={val}") 200 | plt.xscale(xscale) 201 | plt.yscale(yscale) 202 | plt.xlabel(xlabel) 203 | plt.ylabel(ylabel) 204 | plt.ylim(ylim) 205 | plt.legend() 206 | plt.grid() 207 | fig.savefig(os.path.join(img_dir, filename + ".png")) 208 | try: 209 | tikzplotlib.save(os.path.join(img_dir, filename + ".tex")) 210 | except Exception as e: 211 | print("Did not convert to tikz, error occurred: ", e) 212 | plt.close(fig) 213 | 214 | 215 | ############### 216 | # Main script # 217 | ############### 218 | if __name__ == '__main__': 219 | parser = argparse.ArgumentParser() 220 | parser.add_argument("--cores", 221 | help="Value of sem.parallelrunner.MAX_PARALLEL_PROCESSES. Default: 1", 222 | type=int, 223 | default=1) 224 | parser.add_argument("--numRuns", 225 | help="The number of runs per simulation. Default: 50", 226 | type=int, 227 | default=50) 228 | parser.add_argument("--campaignName", 229 | help="MANDATORY parameter for the campaign name. Suggested: commit hash", 230 | default=None) 231 | parser.add_argument("--paramSet", 232 | help="MANDATORY parameter set", 233 | default=None) 234 | parser.add_argument("--frameRate", 235 | help="Frame rate. Default: 60", 236 | default=60) 237 | args = parser.parse_args() 238 | 239 | assert args.campaignName is not None, "Undefined parameter --campaignName" 240 | assert args.paramSet is not None, "Undefined parameter --paramSet" 241 | print(f'Starting sem simulation with {args.cores} core(s)...') 242 | 243 | sem.parallelrunner.MAX_PARALLEL_PROCESSES = args.cores 244 | ns_path = os.path.dirname(os.path.realpath(__file__)) 245 | campaign_name = args.campaignName 246 | script = "vr-app-n-stas" 247 | campaign_dir = os.path.join(ns_path, "campaigns", f"{campaign_name}-{args.paramSet}") 248 | img_dir = os.path.join(ns_path, 'campaigns-img', f"{campaign_name}-{args.paramSet}") 249 | 250 | # Set up campaign 251 | campaign = sem.CampaignManager.new( 252 | ns_path, script, campaign_dir, 253 | overwrite=False, 254 | runner_type="ParallelRunner", 255 | optimized=True, 256 | check_repo=False 257 | ) 258 | 259 | print("campaign: " + str(campaign)) 260 | 261 | # Need to create the img/ folder after setting up a new campaign 262 | os.makedirs(img_dir, exist_ok=True) 263 | 264 | # Set up baseline parameters 265 | if args.paramSet == "nStas": 266 | param_combination = OrderedDict({ 267 | "appRate": "50Mbps", 268 | "frameRate": args.frameRate, 269 | "burstGeneratorType": ["model", "trace", "deterministic"], 270 | "nStas": list(range(1, 8+1)), 271 | "simulationTime": 10, 272 | "RngRun": list(range(args.numRuns)) 273 | }) 274 | 275 | elif args.paramSet == "appRate": 276 | param_combination = OrderedDict({ 277 | "appRate": [f"{rate}Mbps" for rate in range(10, 50+1, 10)], 278 | "frameRate": args.frameRate, 279 | "burstGeneratorType": ["model", "trace", "deterministic"], 280 | "nStas": 1, 281 | "simulationTime": 10, 282 | "RngRun": list(range(args.numRuns)) 283 | }) 284 | else: 285 | raise ValueError(f"paramSet={args.paramSet} not recognized") 286 | 287 | campaign.run_missing_simulations(param_combination) 288 | 289 | # try to fix broken results 290 | broken_results = campaign.get_results_as_numpy_array(param_combination, 291 | check_stderr, 292 | args.numRuns) 293 | # remove_simulations(broken_results) 294 | # campaign.run_missing_simulations(param_combination) 295 | 296 | # remove RngRun: in contrast with get results 297 | param_combination.pop("RngRun") 298 | 299 | # Plots 300 | plot_line_metric(campaign=campaign, 301 | parameter_space=param_combination, 302 | result_parsing_function=compute_avg_burst_thr_mbps, 303 | runs=args.numRuns, 304 | xx=param_combination[args.paramSet], 305 | hue_var="burstGeneratorType", 306 | xlabel=args.paramSet, 307 | ylabel='Avg. Burst Throughput [Mbps]', 308 | filename='avg_burst_thr_mbps') 309 | 310 | plot_line_metric(campaign=campaign, 311 | parameter_space=param_combination, 312 | result_parsing_function=compute_avg_burst_delay_ms, 313 | runs=args.numRuns, 314 | xx=param_combination[args.paramSet], 315 | hue_var="burstGeneratorType", 316 | xlabel=args.paramSet, 317 | ylabel='Avg. Burst Delay [ms]', 318 | filename='avg_burst_delay_ms') 319 | 320 | plot_line_metric(campaign=campaign, 321 | parameter_space=param_combination, 322 | result_parsing_function=compute_95perc_burst_delay_ms, 323 | runs=args.numRuns, 324 | xx=param_combination[args.paramSet], 325 | hue_var="burstGeneratorType", 326 | xlabel=args.paramSet, 327 | ylabel='95th perc. Burst Delay [ms]', 328 | filename='95perc_burst_delay_ms') 329 | 330 | plot_line_metric(campaign=campaign, 331 | parameter_space=param_combination, 332 | result_parsing_function=compute_burst_succ_rate, 333 | runs=args.numRuns, 334 | xx=param_combination[args.paramSet], 335 | hue_var="burstGeneratorType", 336 | xlabel=args.paramSet, 337 | ylabel='Burst Succ. Rate', 338 | filename='burst_succ_rate') 339 | 340 | plot_line_metric(campaign=campaign, 341 | parameter_space=param_combination, 342 | result_parsing_function=compute_avg_fragment_thr_mbps, 343 | runs=args.numRuns, 344 | xx=param_combination[args.paramSet], 345 | hue_var="burstGeneratorType", 346 | xlabel=args.paramSet, 347 | ylabel='Avg. Fragment Throughput [Mbps]', 348 | filename='avg_fragment_thr_mbps') 349 | 350 | plot_line_metric(campaign=campaign, 351 | parameter_space=param_combination, 352 | result_parsing_function=compute_avg_fragment_delay_ms, 353 | runs=args.numRuns, 354 | xx=param_combination[args.paramSet], 355 | hue_var="burstGeneratorType", 356 | xlabel=args.paramSet, 357 | ylabel='Avg. Fragment Delay [ms]', 358 | filename='avg_fragment_delay_ms') 359 | 360 | plot_line_metric(campaign=campaign, 361 | parameter_space=param_combination, 362 | result_parsing_function=compute_95perc_fragment_delay_ms, 363 | runs=args.numRuns, 364 | xx=param_combination[args.paramSet], 365 | hue_var="burstGeneratorType", 366 | xlabel=args.paramSet, 367 | ylabel='95th perc. Fragment Delay [ms]', 368 | filename='95perc_fragment_delay_ms') 369 | 370 | plot_line_metric(campaign=campaign, 371 | parameter_space=param_combination, 372 | result_parsing_function=compute_fragment_succ_rate, 373 | runs=args.numRuns, 374 | xx=param_combination[args.paramSet], 375 | hue_var="burstGeneratorType", 376 | xlabel=args.paramSet, 377 | ylabel='Fragment Succ. Rate', 378 | filename='fragment_succ_rate') 379 | 380 | -------------------------------------------------------------------------------- /examples/stats-calculator-example.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include "ns3/core-module.h" 22 | #include "ns3/network-module.h" 23 | #include "ns3/internet-module.h" 24 | #include "ns3/point-to-point-module.h" 25 | #include "ns3/applications-module.h" 26 | 27 | #include "ns3/seq-ts-size-frag-header.h" 28 | #include "ns3/bursty-helper.h" 29 | #include "ns3/burst-sink-helper.h" 30 | #include "ns3/bursty-app-stats-calculator.h" 31 | 32 | /** 33 | * An example on how to use the BurstyAppStatsCalculator. 34 | * Example based on bursty-application-example. 35 | */ 36 | 37 | using namespace ns3; 38 | 39 | NS_LOG_COMPONENT_DEFINE ("BurstyApplicationExample"); 40 | 41 | std::string 42 | AddressToString (const Address &addr) 43 | { 44 | std::stringstream addressStr; 45 | addressStr << InetSocketAddress::ConvertFrom (addr).GetIpv4 () << ":" 46 | << InetSocketAddress::ConvertFrom (addr).GetPort (); 47 | return addressStr.str (); 48 | } 49 | 50 | void 51 | BurstTx(uint32_t nodeId, 52 | Ptr statsCalculator, 53 | Ptr burst, 54 | const Address& from, 55 | const Address& to, 56 | const SeqTsSizeFragHeader& header) 57 | { 58 | NS_LOG_INFO ("Sent burst seq=" << header.GetSeq () << " of header.GetSize ()=" 59 | << header.GetSize () << " (burst->GetSize ()=" << burst->GetSize () 60 | << ") bytes from " << AddressToString (from) << " to " 61 | << AddressToString (to) << " at " << header.GetTs ().As (Time::S)); 62 | statsCalculator->TxBurst(nodeId, burst, from, to, header); 63 | } 64 | 65 | void 66 | BurstRx(uint32_t nodeId, 67 | Ptr statsCalculator, 68 | Ptr burst, 69 | const Address& from, 70 | const Address& to, 71 | const SeqTsSizeFragHeader& header) 72 | { 73 | NS_LOG_INFO ("Received burst seq=" 74 | << header.GetSeq () << " of header.GetSize ()=" << header.GetSize () 75 | << " (burst->GetSize ()=" << burst->GetSize () << ") bytes from " 76 | << AddressToString (from) << " to " << AddressToString (to) << " at " 77 | << header.GetTs ().As (Time::S)); 78 | 79 | statsCalculator->RxBurst(nodeId, burst, from, to, header); 80 | } 81 | 82 | int 83 | main (int argc, char *argv[]) 84 | { 85 | double simTimeSec = 10; 86 | CommandLine cmd (__FILE__); 87 | cmd.AddValue ("SimulationTime", "Length of simulation in seconds.", simTimeSec); 88 | cmd.Parse (argc, argv); 89 | 90 | Time::SetResolution (Time::NS); 91 | LogComponentEnableAll (LOG_PREFIX_TIME); 92 | LogComponentEnable ("BurstyApplicationExample", LOG_INFO); 93 | 94 | Config::SetDefault("ns3::BurstyAppStatsCalculator::EpochDuration", TimeValue(Seconds(0.1))); 95 | Config::SetDefault("ns3::BurstyAppStatsCalculator::WriteToFile", BooleanValue(true)); 96 | 97 | // Setup two nodes 98 | NodeContainer nodes; 99 | nodes.Create (2); 100 | 101 | PointToPointHelper pointToPoint; 102 | pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps")); 103 | pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 104 | 105 | NetDeviceContainer devices; 106 | devices = pointToPoint.Install (nodes); 107 | 108 | InternetStackHelper stack; 109 | stack.Install (nodes); 110 | 111 | uint16_t portNumber = 50000; 112 | 113 | Ipv4AddressHelper address; 114 | address.SetBase ("10.1.1.0", "255.255.255.0"); 115 | Ipv4InterfaceContainer interfaces = address.Assign (devices); 116 | 117 | Ipv4Address serverAddress = interfaces.GetAddress (0); 118 | Ipv4Address sinkAddress = Ipv4Address::GetAny (); // 0.0.0.0 119 | 120 | // Create bursty application helper 121 | BurstyHelper burstyHelper ("ns3::UdpSocketFactory", InetSocketAddress (serverAddress, portNumber)); 122 | burstyHelper.SetAttribute ("FragmentSize", UintegerValue (1200)); 123 | burstyHelper.SetBurstGenerator ("ns3::SimpleBurstGenerator", 124 | "PeriodRv", StringValue ("ns3::ConstantRandomVariable[Constant=100e-3]"), 125 | "BurstSizeRv", StringValue ("ns3::ConstantRandomVariable[Constant=10e3]")); 126 | 127 | // Install bursty application 128 | ApplicationContainer serverApps = burstyHelper.Install (nodes.Get (1)); 129 | Ptr burstyApp = serverApps.Get (0)->GetObject (); 130 | Ptr statsCalculator = CreateObject(); 131 | 132 | // Example of connecting to the trace sources 133 | burstyApp->TraceConnectWithoutContext ("BurstTx", MakeBoundCallback (&BurstTx, nodes.Get (1)->GetId (), statsCalculator)); 134 | 135 | // Create burst sink helper 136 | BurstSinkHelper burstSinkHelper ("ns3::UdpSocketFactory", 137 | InetSocketAddress (sinkAddress, portNumber)); 138 | 139 | // Install burst sink 140 | ApplicationContainer clientApps = burstSinkHelper.Install (nodes.Get (0)); 141 | Ptr burstSink = clientApps.Get (0)->GetObject (); 142 | 143 | // Example of connecting to the trace sources 144 | burstSink->TraceConnectWithoutContext("BurstRx", MakeBoundCallback(&BurstRx, nodes.Get (0)->GetId (), statsCalculator)); 145 | 146 | // Stop bursty app after simTimeSec 147 | serverApps.Stop (Seconds (simTimeSec)); 148 | Simulator::Stop (Seconds(simTimeSec)); 149 | Simulator::Run (); 150 | Simulator::Destroy (); 151 | 152 | // Stats 153 | std::cout << "Total RX bursts: " << burstyApp->GetTotalTxBursts () << "/" 154 | << burstSink->GetTotalRxBursts () << std::endl; 155 | std::cout << "Total RX fragments: " << burstyApp->GetTotalTxFragments () << "/" 156 | << burstSink->GetTotalRxFragments () << std::endl; 157 | std::cout << "Total RX bytes: " << burstyApp->GetTotalTxBytes () << "/" 158 | << burstSink->GetTotalRxBytes () << std::endl; 159 | 160 | return 0; 161 | } 162 | -------------------------------------------------------------------------------- /examples/trace-file-burst-application-example.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include 22 | #include "ns3/core-module.h" 23 | #include "ns3/network-module.h" 24 | #include "ns3/internet-module.h" 25 | #include "ns3/point-to-point-module.h" 26 | #include "ns3/applications-module.h" 27 | 28 | #include "ns3/seq-ts-size-frag-header.h" 29 | #include "ns3/bursty-helper.h" 30 | #include "ns3/burst-sink-helper.h" 31 | #include "ns3/trace-file-burst-generator.h" 32 | 33 | /** 34 | * Example of BurstyApplication using a TraceFileBurstGenerator. 35 | * Some example traces are provided, obtained from a real VR source. 36 | * Please read the reference paper for further information (see README.md). 37 | */ 38 | 39 | using namespace ns3; 40 | 41 | NS_LOG_COMPONENT_DEFINE ("BurstyApplicationExample"); 42 | 43 | std::string 44 | AddressToString (const Address &addr) 45 | { 46 | std::stringstream addressStr; 47 | addressStr << InetSocketAddress::ConvertFrom (addr).GetIpv4 () << ":" 48 | << InetSocketAddress::ConvertFrom (addr).GetPort (); 49 | return addressStr.str (); 50 | } 51 | 52 | void 53 | BurstRx (Ptr burst, const Address &from, const Address &to, 54 | const SeqTsSizeFragHeader &header) 55 | { 56 | NS_LOG_INFO ("Received burst seq=" << header.GetSeq () << " of " << header.GetSize () 57 | << " bytes transmitted at " << std::setprecision (9) 58 | << header.GetTs ().As (Time::S)); 59 | } 60 | 61 | int 62 | main (int argc, char *argv[]) 63 | { 64 | std::string traceFolder = "contrib/vr-app/model/BurstGeneratorTraces/"; // example traces can be found here 65 | std::string traceFile = "ge_cities_20mbps_30fps.csv"; 66 | double startTime = 0; 67 | double simTime = 20; 68 | 69 | CommandLine cmd (__FILE__); 70 | cmd.AddValue ("traceFolder", "The folder containing the trace.", traceFolder); 71 | cmd.AddValue ("traceFile", "The trace file name.", traceFile); 72 | cmd.AddValue ("startTime", "The start time offset of the trace [s].", startTime); 73 | cmd.AddValue ("simTime", "Length of simulation [s].", simTime); 74 | cmd.Parse (argc, argv); 75 | 76 | Time::SetResolution (Time::NS); 77 | LogComponentEnableAll (LOG_PREFIX_TIME); 78 | LogComponentEnable ("BurstyApplicationExample", LOG_INFO); 79 | 80 | // Setup two nodes 81 | NodeContainer nodes; 82 | nodes.Create (2); 83 | 84 | PointToPointHelper pointToPoint; 85 | pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("100Mbps")); 86 | pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 87 | 88 | NetDeviceContainer devices; 89 | devices = pointToPoint.Install (nodes); 90 | 91 | InternetStackHelper stack; 92 | stack.Install (nodes); 93 | 94 | uint16_t portNumber = 50000; 95 | 96 | Ipv4AddressHelper address; 97 | address.SetBase ("10.1.1.0", "255.255.255.0"); 98 | Ipv4InterfaceContainer interfaces = address.Assign (devices); 99 | 100 | Ipv4Address serverAddress = interfaces.GetAddress (0); 101 | Ipv4Address sinkAddress = Ipv4Address::GetAny (); // 0.0.0.0 102 | 103 | // Create bursty application helper 104 | BurstyHelper burstyHelper ("ns3::UdpSocketFactory", 105 | InetSocketAddress (serverAddress, portNumber)); 106 | burstyHelper.SetAttribute ("FragmentSize", UintegerValue (1200)); 107 | burstyHelper.SetBurstGenerator ("ns3::TraceFileBurstGenerator", 108 | "TraceFile", StringValue (traceFolder + traceFile), 109 | "StartTime", DoubleValue (startTime)); 110 | 111 | // Install bursty application 112 | ApplicationContainer serverApps = burstyHelper.Install (nodes.Get (1)); 113 | Ptr burstyApp = serverApps.Get (0)->GetObject (); 114 | 115 | // Extract TraceFileBurstGenerator and check if able to fill the entire simulation 116 | PointerValue val; 117 | burstyApp->GetAttribute ("BurstGenerator", val); 118 | Ptr tfbg = DynamicCast (val.GetObject ()); 119 | NS_ASSERT_MSG (tfbg, "The bursty application should be a TraceFileBurstGenerator"); 120 | 121 | if (startTime + simTime > tfbg->GetTraceDuration ()) 122 | { 123 | NS_LOG_WARN ("The trace file will end before the simulation ends. Please choose a different " 124 | << "start time, a longer trace, or reduce the simulation duration."); 125 | } 126 | 127 | // Create burst sink helper 128 | BurstSinkHelper burstSinkHelper ("ns3::UdpSocketFactory", 129 | InetSocketAddress (sinkAddress, portNumber)); 130 | 131 | // Install HTTP client 132 | ApplicationContainer clientApps = burstSinkHelper.Install (nodes.Get (0)); 133 | Ptr burstSink = clientApps.Get (0)->GetObject (); 134 | 135 | // Example of connecting to the trace sources 136 | burstSink->TraceConnectWithoutContext ("BurstRx", MakeCallback (&BurstRx)); 137 | 138 | // TraceFileBurstGenerator stops automatically, but we add an early stop to make the example quicker 139 | serverApps.Stop (Seconds (simTime)); 140 | Simulator::Run (); 141 | Simulator::Destroy (); 142 | 143 | // Stats 144 | std::cout << "Total RX bursts: " << burstyApp->GetTotalTxBursts () << "/" 145 | << burstSink->GetTotalRxBursts () << std::endl; 146 | std::cout << "Total RX fragments: " << burstyApp->GetTotalTxFragments () << "/" 147 | << burstSink->GetTotalRxFragments () << std::endl; 148 | std::cout << "Total RX bytes: " << burstyApp->GetTotalTxBytes () << "/" 149 | << burstSink->GetTotalRxBytes () << std::endl; 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /examples/vr-app-n-stas.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include 22 | #include "ns3/command-line.h" 23 | #include "ns3/config.h" 24 | #include "ns3/uinteger.h" 25 | #include "ns3/boolean.h" 26 | #include "ns3/double.h" 27 | #include "ns3/string.h" 28 | #include "ns3/pointer.h" 29 | #include "ns3/log.h" 30 | #include "ns3/yans-wifi-helper.h" 31 | #include "ns3/ssid.h" 32 | #include "ns3/mobility-helper.h" 33 | #include "ns3/internet-stack-helper.h" 34 | #include "ns3/ipv4-address-helper.h" 35 | #include "ns3/bursty-helper.h" 36 | #include "ns3/burst-sink-helper.h" 37 | #include "ns3/trace-file-burst-generator.h" 38 | #include "ns3/yans-wifi-channel.h" 39 | #include "ns3/trace-helper.h" 40 | #include "ns3/system-path.h" 41 | 42 | // This example was built starting from examples/wireless/wifi-simple-ht-hidden-stations.cc 43 | // 44 | // Network topology: `nStas` are equally spaced over a circle of radius `distance` from the AP. 45 | // Example with 2 nodes: 46 | // 47 | // n1 48 | // | 49 | // * 50 | // 51 | // AP 52 | // 53 | // * 54 | // | 55 | // n2 56 | // 57 | // The results of this script are shown in the first reference paper (see README.md). 58 | 59 | using namespace ns3; 60 | 61 | NS_LOG_COMPONENT_DEFINE ("VrAppNStas"); 62 | 63 | std::vector 64 | SplitString (const std::string &str, char delimiter) 65 | { 66 | std::stringstream ss (str); 67 | std::string token; 68 | std::vector container; 69 | 70 | while (getline (ss, token, delimiter)) 71 | { 72 | container.push_back (token); 73 | } 74 | return container; 75 | } 76 | 77 | std::string 78 | GetInputPath () 79 | { 80 | std::string systemPath = SystemPath::FindSelfDirectory (); 81 | std::vector pathComponents = SplitString (systemPath, '/'); 82 | 83 | std::string inputPath = "/"; 84 | std::string dir; 85 | for (size_t i = 0; i < pathComponents.size (); ++i) 86 | { 87 | dir = pathComponents.at (i); 88 | if (dir == "") 89 | continue; 90 | inputPath += dir + "/"; 91 | if (dir == "ns-3-dev") 92 | break; 93 | } 94 | return inputPath; 95 | } 96 | 97 | std::string 98 | AddressToString (const Address &addr) 99 | { 100 | std::stringstream addressStr; 101 | addressStr << InetSocketAddress::ConvertFrom (addr).GetIpv4 (); 102 | return addressStr.str (); 103 | } 104 | 105 | void 106 | BurstRx (Ptr traceFile, Ptr burst, const Address &from, 107 | const Address &to, const SeqTsSizeFragHeader &header) 108 | { 109 | *traceFile->GetStream () << AddressToString (from) << "," 110 | << header.GetTs ().GetNanoSeconds () << "," 111 | << Simulator::Now ().GetNanoSeconds () << "," 112 | << header.GetSeq () << "," 113 | << header.GetSize () << "\n"; 114 | } 115 | 116 | void 117 | FragmentRx (Ptr traceFile, Ptr fragment, const Address &from, 118 | const Address &to, const SeqTsSizeFragHeader &header) 119 | { 120 | *traceFile->GetStream () << AddressToString (from) << "," 121 | << header.GetTs ().GetNanoSeconds () << "," 122 | << Simulator::Now ().GetNanoSeconds () << "," 123 | << header.GetSeq () << "," 124 | << header.GetFragSeq () << "," 125 | << header.GetFrags () << "," 126 | << fragment->GetSize () << "\n"; 127 | } 128 | 129 | int 130 | main (int argc, char *argv[]) 131 | { 132 | uint32_t nStas = 2; // the number of STAs around the AP 133 | double distance = 1; // the distance from the AP [m] 134 | std::string appRate = "50Mbps"; // the app target data rate 135 | double frameRate = 60; // the app frame rate [FPS] 136 | std::string vrAppName = "VirusPopper"; // the app name 137 | std::string burstGeneratorType = "model"; // type of burst generator {"model", "trace", "deterministic"} 138 | double simulationTime = 10; // simulation time in seconds 139 | 140 | CommandLine cmd (__FILE__); 141 | cmd.AddValue ("nStas", "the number of STAs around the AP", nStas); 142 | // cmd.AddValue ("distance", "the distance from the AP [m]", distance); 143 | cmd.AddValue ("appRate", "the app target data rate", appRate); 144 | cmd.AddValue ("frameRate", "the app frame rate [FPS]", frameRate); 145 | cmd.AddValue ("vrAppName", "the app name", vrAppName); 146 | cmd.AddValue ("burstGeneratorType", 147 | "type of burst generator {\"model\", \"trace\", \"deterministic\"}", 148 | burstGeneratorType); 149 | cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime); 150 | cmd.Parse (argc, argv); 151 | 152 | uint32_t fragmentSize = 1472; //bytes 153 | uint32_t channelWidth = 160; // MHz 154 | double frequency = 5; // GHz 155 | bool sgi = true; // Use short guard interval 156 | 157 | LogComponentEnableAll (LOG_PREFIX_ALL); 158 | LogComponentEnable ("VrAppNStas", LOG_INFO); 159 | LogComponentEnable ("BurstSink", LOG_INFO); 160 | 161 | // Disable RTS/CTS 162 | Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("999999")); 163 | 164 | NodeContainer wifiStaNodes; 165 | wifiStaNodes.Create (nStas); 166 | NodeContainer wifiApNode; 167 | wifiApNode.Create (1); 168 | 169 | WifiHelper wifi; 170 | wifi.SetStandard (WIFI_STANDARD_80211ac); 171 | wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", 172 | "DataMode", StringValue ("VhtMcs9"), 173 | "ControlMode", StringValue ("VhtMcs0")); 174 | 175 | YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); 176 | YansWifiPhyHelper phy; 177 | phy.SetChannel (channel.Create ()); 178 | 179 | if (frequency != 5) 180 | { 181 | NS_ABORT_MSG("Frequency=" << frequency << "GHz not supported by this wifi standard."); 182 | } 183 | 184 | phy.Set("ChannelSettings", 185 | StringValue(std::string("{0, ") + std::to_string(channelWidth) + ", BAND_5GHZ, 0}")); 186 | 187 | WifiMacHelper mac; 188 | Ssid ssid = Ssid ("vr-app-n-stas"); 189 | mac.SetType ("ns3::StaWifiMac", 190 | "Ssid", SsidValue (ssid)); 191 | 192 | NetDeviceContainer staDevices; 193 | staDevices = wifi.Install (phy, mac, wifiStaNodes); 194 | 195 | mac.SetType ("ns3::ApWifiMac", 196 | "Ssid", SsidValue (ssid), 197 | "EnableBeaconJitter", BooleanValue (false)); 198 | 199 | NetDeviceContainer apDevice; 200 | apDevice = wifi.Install (phy, mac, wifiApNode); 201 | 202 | Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported", BooleanValue (sgi)); 203 | // Setting mobility model 204 | MobilityHelper mobility; 205 | Ptr positionAlloc = CreateObject (); 206 | 207 | // AP is in the center 208 | positionAlloc->Add (Vector (0.0, 0.0, 0.0)); 209 | 210 | // STAs around the AP in a circle of fixed radius 211 | double dTheta = 2 * M_PI / nStas; 212 | for (uint32_t i = 0; i < nStas; i++) 213 | { 214 | positionAlloc->Add (Vector (std::cos (i * dTheta) * distance, 215 | std::sin (i * dTheta) * distance, 216 | 0.0)); 217 | } 218 | mobility.SetPositionAllocator (positionAlloc); 219 | 220 | mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); 221 | 222 | mobility.Install (wifiApNode); 223 | mobility.Install (wifiStaNodes); 224 | 225 | // Internet stack 226 | InternetStackHelper stack; 227 | stack.Install (wifiApNode); 228 | stack.Install (wifiStaNodes); 229 | 230 | Ipv4AddressHelper address; 231 | address.SetBase ("192.168.1.0", "255.255.255.0"); 232 | Ipv4InterfaceContainer StaInterface; 233 | StaInterface = address.Assign (staDevices); 234 | Ipv4InterfaceContainer ApInterface; 235 | ApInterface = address.Assign (apDevice); 236 | 237 | // Setting applications 238 | uint16_t port = 50000; 239 | BurstSinkHelper server ("ns3::UdpSocketFactory", 240 | InetSocketAddress (Ipv4Address::GetAny (), port)); 241 | ApplicationContainer serverApp = server.Install (wifiApNode); 242 | serverApp.Start (Seconds (0.0)); 243 | serverApp.Stop (Seconds (simulationTime + 1)); 244 | 245 | BurstyHelper client ("ns3::UdpSocketFactory", 246 | InetSocketAddress (ApInterface.GetAddress (0), port)); 247 | client.SetAttribute ("FragmentSize", UintegerValue (fragmentSize)); 248 | 249 | if (burstGeneratorType == "model") 250 | { 251 | NS_LOG_DEBUG ("VR generator with framerate=" << frameRate << ", appRate=" << appRate << ", vrAppName=" << vrAppName); 252 | 253 | client.SetBurstGenerator ("ns3::VrBurstGenerator", 254 | "FrameRate", DoubleValue (frameRate), 255 | "TargetDataRate", DataRateValue (DataRate (appRate)), 256 | "VrAppName", StringValue (vrAppName)); 257 | } 258 | else if (burstGeneratorType == "trace") 259 | { 260 | uint32_t dataRateMbps = uint32_t (DataRate (appRate).GetBitRate () / 1e6); 261 | std::string appAbbrev; 262 | if (vrAppName == "VirusPopper") 263 | { 264 | appAbbrev = "vp"; 265 | } 266 | else if (vrAppName == "Minecraft") 267 | { 268 | appAbbrev = "mc"; 269 | } 270 | else if (vrAppName == "GoogleEarthVrCities") 271 | { 272 | appAbbrev = "ge_cities"; 273 | } 274 | else if (vrAppName == "GoogleEarthVrTour") 275 | { 276 | appAbbrev = "ge_tour"; 277 | } 278 | else 279 | { 280 | NS_ABORT_MSG ("vrAppName=" << vrAppName << " was not recognized"); 281 | } 282 | 283 | std::ostringstream filenameSs; 284 | filenameSs << GetInputPath () << "contrib/vr-app/model/BurstGeneratorTraces/" 285 | << appAbbrev << "_" 286 | << dataRateMbps << "mbps_" 287 | << uint32_t (frameRate) << "fps.csv"; 288 | 289 | NS_LOG_DEBUG ("Trace file generator with filename=" << filenameSs.str ()); 290 | 291 | client.SetBurstGenerator ("ns3::TraceFileBurstGenerator", 292 | "TraceFile", StringValue (filenameSs.str ())); 293 | } 294 | else if (burstGeneratorType == "deterministic") 295 | { 296 | double avgPeriod = 1 / frameRate; 297 | double avgBurstSize = DataRate (appRate).GetBitRate () / 8.0 / frameRate; 298 | 299 | std::ostringstream periodSs; 300 | periodSs << "ns3::ConstantRandomVariable[Constant=" << avgPeriod << "]"; 301 | std::ostringstream burstSizeSs; 302 | burstSizeSs << "ns3::ConstantRandomVariable[Constant=" << avgBurstSize << "]"; 303 | 304 | NS_LOG_DEBUG ("Simple generator with period=" << periodSs.str () 305 | << ", burstSize=" << burstSizeSs.str ()); 306 | 307 | client.SetBurstGenerator ("ns3::SimpleBurstGenerator", 308 | "PeriodRv", StringValue (periodSs.str ()), 309 | "BurstSizeRv", StringValue (burstSizeSs.str ())); 310 | } 311 | else 312 | { 313 | NS_FATAL_ERROR ("burstGeneratorType=" << burstGeneratorType << " not recognized"); 314 | } 315 | 316 | // Saturated UDP traffic from stations to AP 317 | ApplicationContainer clientApps = client.Install (wifiStaNodes); 318 | Ptr x = CreateObjectWithAttributes ( 319 | "Min", DoubleValue (0), "Max", DoubleValue (1)); 320 | Ptr y = CreateObject (); 321 | for (uint32_t i = 0; i < nStas; i++) 322 | { 323 | Time startTime = Seconds (x->GetValue ()); 324 | NS_LOG_UNCOND ("STA" << i << " will start at " << startTime.As (Time::S)); 325 | Ptr app = DynamicCast (clientApps.Get (i)); 326 | app->SetStartTime (startTime); 327 | 328 | // decouple trace file burst generators 329 | PointerValue val; 330 | app->GetAttribute ("BurstGenerator", val); 331 | Ptr tfbg = DynamicCast (val.GetObject ()); 332 | if (tfbg) 333 | { 334 | NS_ABORT_MSG_IF (tfbg->GetTraceDuration () < simulationTime, 335 | "Trace too short for this simulation"); 336 | 337 | double traceStartTime = y->GetValue (0, tfbg->GetTraceDuration () - simulationTime); 338 | NS_LOG_UNCOND ("STA" << i << " will start its trace from " << traceStartTime); 339 | tfbg->SetAttribute ("StartTime", DoubleValue (traceStartTime)); 340 | } 341 | } 342 | clientApps.Stop (Seconds (simulationTime + 1)); 343 | 344 | // Setup traces 345 | AsciiTraceHelper ascii; 346 | Ptr burstTrace = ascii.CreateFileStream ("burstTrace.csv"); 347 | *burstTrace->GetStream () << "SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,BurstSize" << std::endl; 348 | Ptr fragmentTrace = ascii.CreateFileStream ("fragmentTrace.csv"); 349 | *fragmentTrace->GetStream () 350 | << "SrcAddress,TxTime_ns,RxTime_ns,BurstSeq,FragSeq,TotFrags,FragSize" << std::endl; 351 | 352 | DynamicCast (serverApp.Get (0)) 353 | ->TraceConnectWithoutContext ("BurstRx", MakeBoundCallback (&BurstRx, burstTrace)); 354 | DynamicCast (serverApp.Get (0)) 355 | ->TraceConnectWithoutContext ("FragmentRx", MakeBoundCallback (&FragmentRx, fragmentTrace)); 356 | 357 | // Start simulation 358 | Simulator::Stop (Seconds (simulationTime + 1)); 359 | Simulator::Run (); 360 | 361 | // burst info 362 | Ptr txBurstsBySta = ascii.CreateFileStream ("txBurstsBySta.csv"); 363 | Ptr rxBursts = ascii.CreateFileStream ("rxBursts.csv"); 364 | 365 | uint64_t totBurstSent = 0; 366 | for (uint32_t i = 0; i < nStas; i++) 367 | { 368 | uint64_t burstsSent = 369 | DynamicCast (clientApps.Get (i))->GetTotalTxBursts (); 370 | totBurstSent += burstsSent; 371 | 372 | std::cout << "burstsSent(" << i << ")=" << burstsSent << ", "; 373 | *txBurstsBySta->GetStream () << burstsSent << std::endl; 374 | } 375 | uint64_t burstsReceived = DynamicCast (serverApp.Get (0))->GetTotalRxBursts (); 376 | 377 | std::cout << "burstsReceived=" << burstsReceived << " (" 378 | << double (burstsReceived) / totBurstSent * 100 << "%)" << std::endl; 379 | *rxBursts->GetStream () << burstsReceived << std::endl; 380 | 381 | // fragment info 382 | Ptr txFragmentsBySta = ascii.CreateFileStream ("txFragmentsBySta.csv"); 383 | Ptr rxFragments = ascii.CreateFileStream ("rxFragments.csv"); 384 | 385 | uint64_t totFragmentSent = 0; 386 | for (uint32_t i = 0; i < nStas; i++) 387 | { 388 | uint64_t fragmentsSent = 389 | DynamicCast (clientApps.Get (i))->GetTotalTxFragments (); 390 | totFragmentSent += fragmentsSent; 391 | 392 | std::cout << "fragmentsSent(" << i << ")=" << fragmentsSent << ", "; 393 | *txFragmentsBySta->GetStream () << fragmentsSent << std::endl; 394 | } 395 | uint64_t fragmentsReceived = DynamicCast (serverApp.Get (0))->GetTotalRxFragments (); 396 | 397 | std::cout << "fragmentsReceived=" << fragmentsReceived << " (" 398 | << double (fragmentsReceived) / totFragmentSent * 100 << "%)" << std::endl; 399 | *rxFragments->GetStream () << fragmentsReceived << std::endl; 400 | 401 | Simulator::Destroy (); 402 | 403 | return 0; 404 | } 405 | -------------------------------------------------------------------------------- /examples/vr-application-example.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include 22 | #include "ns3/core-module.h" 23 | #include "ns3/network-module.h" 24 | #include "ns3/internet-module.h" 25 | #include "ns3/point-to-point-module.h" 26 | #include "ns3/applications-module.h" 27 | 28 | #include "ns3/seq-ts-size-frag-header.h" 29 | #include "ns3/bursty-helper.h" 30 | #include "ns3/burst-sink-helper.h" 31 | #include "ns3/vr-burst-generator.h" 32 | 33 | using namespace ns3; 34 | 35 | /** 36 | * An example of synthetic traces for VR applications. 37 | * For further information please check the reference paper (see README.md). 38 | */ 39 | 40 | NS_LOG_COMPONENT_DEFINE ("BurstyApplicationExample"); 41 | 42 | std::string 43 | AddressToString (const Address &addr) 44 | { 45 | std::stringstream addressStr; 46 | addressStr << InetSocketAddress::ConvertFrom (addr).GetIpv4 () << ":" 47 | << InetSocketAddress::ConvertFrom (addr).GetPort (); 48 | return addressStr.str (); 49 | } 50 | 51 | void 52 | BurstRx (Ptr burst, const Address &from, const Address &to, 53 | const SeqTsSizeFragHeader &header) 54 | { 55 | NS_LOG_INFO ("Received burst seq=" << header.GetSeq () << " of " << header.GetSize () 56 | << " bytes transmitted at " << std::setprecision (9) 57 | << header.GetTs ().As (Time::S)); 58 | } 59 | 60 | int 61 | main (int argc, char *argv[]) 62 | { 63 | double simTime = 20; 64 | double frameRate = 30; 65 | std::string targetDataRate = "40Mbps"; 66 | std::string vrAppName = "VirusPopper"; 67 | 68 | CommandLine cmd (__FILE__); 69 | cmd.AddValue ("frameRate", "VR application frame rate [FPS].", frameRate); 70 | cmd.AddValue ("targetDataRate", "Target data rate of the VR application.", targetDataRate); 71 | cmd.AddValue ("vrAppName", "The VR application on which the model is based upon.", vrAppName); 72 | cmd.AddValue ("simTime", "Length of simulation [s].", simTime); 73 | cmd.Parse (argc, argv); 74 | 75 | Time::SetResolution (Time::NS); 76 | LogComponentEnableAll (LOG_PREFIX_TIME); 77 | LogComponentEnable ("BurstyApplicationExample", LOG_INFO); 78 | 79 | // Setup two nodes 80 | NodeContainer nodes; 81 | nodes.Create (2); 82 | 83 | PointToPointHelper pointToPoint; 84 | pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("100Mbps")); 85 | pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms")); 86 | 87 | NetDeviceContainer devices; 88 | devices = pointToPoint.Install (nodes); 89 | 90 | InternetStackHelper stack; 91 | stack.Install (nodes); 92 | 93 | uint16_t portNumber = 50000; 94 | 95 | Ipv4AddressHelper address; 96 | address.SetBase ("10.1.1.0", "255.255.255.0"); 97 | Ipv4InterfaceContainer interfaces = address.Assign (devices); 98 | 99 | Ipv4Address serverAddress = interfaces.GetAddress (0); 100 | Ipv4Address sinkAddress = Ipv4Address::GetAny (); // 0.0.0.0 101 | 102 | // Create bursty application helper 103 | BurstyHelper burstyHelper ("ns3::UdpSocketFactory", 104 | InetSocketAddress (serverAddress, portNumber)); 105 | burstyHelper.SetAttribute ("FragmentSize", UintegerValue (1200)); 106 | burstyHelper.SetBurstGenerator ("ns3::VrBurstGenerator", 107 | "FrameRate", DoubleValue (frameRate), 108 | "TargetDataRate", DataRateValue (DataRate (targetDataRate)), 109 | "VrAppName", StringValue(vrAppName)); 110 | 111 | // Install bursty application 112 | ApplicationContainer serverApps = burstyHelper.Install (nodes.Get (1)); 113 | Ptr burstyApp = serverApps.Get (0)->GetObject (); 114 | 115 | // Create burst sink helper 116 | BurstSinkHelper burstSinkHelper ("ns3::UdpSocketFactory", 117 | InetSocketAddress (sinkAddress, portNumber)); 118 | 119 | // Install HTTP client 120 | ApplicationContainer clientApps = burstSinkHelper.Install (nodes.Get (0)); 121 | Ptr burstSink = clientApps.Get (0)->GetObject (); 122 | 123 | // Example of connecting to the trace sources 124 | burstSink->TraceConnectWithoutContext ("BurstRx", MakeCallback (&BurstRx)); 125 | 126 | // Stop bursty app after simTime 127 | serverApps.Stop (Seconds (simTime)); 128 | Simulator::Run (); 129 | Simulator::Destroy (); 130 | 131 | // Stats 132 | std::cout << "Total RX bursts: " << burstyApp->GetTotalTxBursts () << "/" 133 | << burstSink->GetTotalRxBursts () << std::endl; 134 | std::cout << "Total RX fragments: " << burstyApp->GetTotalTxFragments () << "/" 135 | << burstSink->GetTotalRxFragments () << std::endl; 136 | std::cout << "Total RX bytes: " << burstyApp->GetTotalTxBytes () << "/" 137 | << burstSink->GetTotalRxBytes () << std::endl; 138 | 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /helper/burst-sink-helper.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #include "burst-sink-helper.h" 21 | #include "ns3/string.h" 22 | #include "ns3/inet-socket-address.h" 23 | #include "ns3/names.h" 24 | 25 | namespace ns3 { 26 | 27 | BurstSinkHelper::BurstSinkHelper (std::string protocol, Address address) 28 | { 29 | m_factory.SetTypeId ("ns3::BurstSink"); 30 | m_factory.Set ("Protocol", StringValue (protocol)); 31 | m_factory.Set ("Local", AddressValue (address)); 32 | } 33 | 34 | void 35 | BurstSinkHelper::SetAttribute (std::string name, const AttributeValue &value) 36 | { 37 | m_factory.Set (name, value); 38 | } 39 | 40 | ApplicationContainer 41 | BurstSinkHelper::Install (Ptr node) const 42 | { 43 | return ApplicationContainer (InstallPriv (node)); 44 | } 45 | 46 | ApplicationContainer 47 | BurstSinkHelper::Install (std::string nodeName) const 48 | { 49 | Ptr node = Names::Find (nodeName); 50 | return ApplicationContainer (InstallPriv (node)); 51 | } 52 | 53 | ApplicationContainer 54 | BurstSinkHelper::Install (NodeContainer c) const 55 | { 56 | ApplicationContainer apps; 57 | for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) 58 | { 59 | apps.Add (InstallPriv (*i)); 60 | } 61 | 62 | return apps; 63 | } 64 | 65 | Ptr 66 | BurstSinkHelper::InstallPriv (Ptr node) const 67 | { 68 | Ptr app = m_factory.Create (); 69 | node->AddApplication (app); 70 | 71 | return app; 72 | } 73 | 74 | } // namespace ns3 75 | -------------------------------------------------------------------------------- /helper/burst-sink-helper.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | #ifndef BURST_SINK_HELPER_H 20 | #define BURST_SINK_HELPER_H 21 | 22 | #include "ns3/object-factory.h" 23 | #include "ns3/ipv4-address.h" 24 | #include "ns3/node-container.h" 25 | #include "ns3/application-container.h" 26 | #include "ns3/burst-sink.h" 27 | 28 | 29 | namespace ns3 { 30 | 31 | /** 32 | * \ingroup burstsink 33 | * \brief A helper to make it easier to instantiate an ns3::BurstSink on a set of nodes. 34 | */ 35 | class BurstSinkHelper 36 | { 37 | public: 38 | /** 39 | * Create a BurstSinkHelper to make it easier to work with BurstyApplications 40 | * 41 | * \param protocol the name of the protocol to use to receive traffic 42 | * This string identifies the socket factory type used to create 43 | * sockets for the applications. A typical value would be 44 | * ns3::UdpSocketFactory. 45 | * \param address the address of the sink, 46 | * 47 | */ 48 | BurstSinkHelper (std::string protocol, Address address); 49 | 50 | /** 51 | * Helper function used to set the underlying application attributes. 52 | * 53 | * \param name the name of the application attribute to set 54 | * \param value the value of the application attribute to set 55 | */ 56 | void SetAttribute (std::string name, const AttributeValue &value); 57 | 58 | /** 59 | * Install an ns3::BurstyApplication on each node of the input container 60 | * configured with all the attributes set with SetAttribute. 61 | * 62 | * \param c NodeContainer of the set of nodes on which a BurstyApplication 63 | * will be installed. 64 | * \returns Container of Ptr to the applications installed. 65 | */ 66 | ApplicationContainer Install (NodeContainer c) const; 67 | 68 | /** 69 | * Install an ns3::BurstyApplication on each node of the input container 70 | * configured with all the attributes set with SetAttribute. 71 | * 72 | * \param node The node on which a BurstyApplication will be installed. 73 | * \returns Container of Ptr to the applications installed. 74 | */ 75 | ApplicationContainer Install (Ptr node) const; 76 | 77 | /** 78 | * Install an ns3::BurstyApplication on each node of the input container 79 | * configured with all the attributes set with SetAttribute. 80 | * 81 | * \param nodeName The name of the node on which a BurstyApplication will be installed. 82 | * \returns Container of Ptr to the applications installed. 83 | */ 84 | ApplicationContainer Install (std::string nodeName) const; 85 | 86 | private: 87 | /** 88 | * Install an ns3::BurstSink on the node configured with all the 89 | * attributes set with SetAttribute. 90 | * 91 | * \param node The node on which an BurstSink will be installed. 92 | * \returns Ptr to the application installed. 93 | */ 94 | Ptr InstallPriv (Ptr node) const; 95 | ObjectFactory m_factory; //!< Object factory. 96 | }; 97 | 98 | } // namespace ns3 99 | 100 | #endif /* BURST_SINK_HELPER_H */ 101 | -------------------------------------------------------------------------------- /helper/bursty-app-stats-calculator.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | */ 18 | 19 | #include 20 | #include "bursty-app-stats-calculator.h" 21 | #include "ns3/string.h" 22 | #include "ns3/nstime.h" 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "ns3/network-module.h" 29 | #include "ns3/internet-module.h" 30 | #include "ns3/seq-ts-size-frag-header.h" 31 | 32 | using namespace ns3; 33 | 34 | NS_LOG_COMPONENT_DEFINE ("BurstyAppStatsCalculator"); 35 | 36 | NS_OBJECT_ENSURE_REGISTERED (BurstyAppStatsCalculator); 37 | 38 | BurstyAppStatsCalculator::BurstyAppStatsCalculator () 39 | : m_firstWrite (true), 40 | m_pendingOutput (false), 41 | m_aggregatedStats (true) 42 | { 43 | NS_LOG_FUNCTION (this); 44 | } 45 | 46 | BurstyAppStatsCalculator::~BurstyAppStatsCalculator () 47 | { 48 | NS_LOG_FUNCTION (this); 49 | } 50 | 51 | TypeId 52 | BurstyAppStatsCalculator::GetTypeId (void) 53 | { 54 | static TypeId tid = 55 | TypeId ("ns3::BurstyAppStatsCalculator") 56 | .SetParent () 57 | .SetGroupName ("Applications") 58 | .AddConstructor () 59 | .AddAttribute ("StartTime", "Start time of the on going epoch.", TimeValue (Seconds (0.)), 60 | MakeTimeAccessor (&BurstyAppStatsCalculator::SetStartTime, 61 | &BurstyAppStatsCalculator::GetStartTime), 62 | MakeTimeChecker ()) 63 | .AddAttribute ("EpochDuration", "Epoch duration.", TimeValue (Seconds (0.25)), 64 | MakeTimeAccessor (&BurstyAppStatsCalculator::GetEpoch, 65 | &BurstyAppStatsCalculator::SetEpoch), 66 | MakeTimeChecker ()) 67 | .AddAttribute ("OutputFilename", 68 | "Name of the file where the downlink results will be saved.", 69 | StringValue ("AppStats.txt"), 70 | MakeStringAccessor (&BurstyAppStatsCalculator::SetOutputFilename, 71 | &BurstyAppStatsCalculator::GetOutputFilename), 72 | MakeStringChecker ()) 73 | .AddAttribute ("AggregatedStats", 74 | "Choice to show the results aggregated of disaggregated. As of now, " 75 | "non-aggregated stats are not supported", 76 | BooleanValue (true), 77 | MakeBooleanAccessor (&BurstyAppStatsCalculator::m_aggregatedStats), 78 | MakeBooleanChecker ()) 79 | .AddAttribute ("ManualUpdate", 80 | "Choice to perform manual statistics update, e.g., triggered by an " 81 | "external class.", 82 | BooleanValue (false), 83 | MakeBooleanAccessor (&BurstyAppStatsCalculator::GetManualUpdate, 84 | &BurstyAppStatsCalculator::SetManualUpdate), 85 | MakeBooleanChecker ()) 86 | .AddAttribute ("WriteToFile", 87 | "Choice to write stats to file besides computing and exchange them " 88 | "with external classes", 89 | BooleanValue (false), 90 | MakeBooleanAccessor (&BurstyAppStatsCalculator::m_writeToFile), 91 | MakeBooleanChecker ()); 92 | return tid; 93 | } 94 | 95 | void 96 | BurstyAppStatsCalculator::DoDispose () 97 | { 98 | NS_LOG_FUNCTION (this); 99 | } 100 | 101 | void 102 | BurstyAppStatsCalculator::SetStartTime (Time t) 103 | { 104 | m_startTime = t; 105 | if (m_aggregatedStats) 106 | { 107 | RescheduleEndEpoch (); 108 | } 109 | } 110 | 111 | Time 112 | BurstyAppStatsCalculator::GetStartTime () const 113 | { 114 | return m_startTime; 115 | } 116 | 117 | void 118 | BurstyAppStatsCalculator::SetEpoch (Time e) 119 | { 120 | m_epochDuration = e; 121 | if (m_aggregatedStats) 122 | { 123 | RescheduleEndEpoch (); 124 | } 125 | } 126 | 127 | Time 128 | BurstyAppStatsCalculator::GetEpoch () const 129 | { 130 | return m_epochDuration; 131 | } 132 | 133 | void 134 | BurstyAppStatsCalculator::SetManualUpdate (bool u) 135 | { 136 | NS_LOG_FUNCTION (this); 137 | m_manualUpdate = u; 138 | if (m_manualUpdate) 139 | { 140 | NS_LOG_UNCOND ("Cancel EndEpoch event"); 141 | m_endEpochEvent.Cancel (); 142 | } 143 | } 144 | 145 | bool 146 | BurstyAppStatsCalculator::GetManualUpdate () const 147 | { 148 | NS_LOG_FUNCTION (this); 149 | return m_manualUpdate; 150 | } 151 | 152 | void 153 | BurstyAppStatsCalculator::TxBurst (uint32_t nodeId, Ptr burst, const Address &from, const Address &to, const SeqTsSizeFragHeader &header) 154 | { 155 | NS_LOG_FUNCTION(this << " TxBurst nodeId=" << nodeId << " burst seq=" << header.GetSeq () << " of " << header.GetSize () 156 | << " bytes transmitted at " << std::setprecision (9) 157 | << header.GetTs ().As (Time::S)); 158 | 159 | if (m_aggregatedStats) 160 | { 161 | if (Simulator::Now () >= m_startTime) 162 | { 163 | m_txBursts[nodeId]++; 164 | m_txData[nodeId] += header.GetSize (); 165 | } 166 | m_pendingOutput = true; 167 | } 168 | } 169 | 170 | void 171 | BurstyAppStatsCalculator::RxBurst (uint32_t nodeId, Ptr burst, const Address &from, const Address &to, const SeqTsSizeFragHeader &header) 172 | { 173 | NS_LOG_FUNCTION (this << " RxBurst nodeId=" << nodeId << " burst seq=" << header.GetSeq () << " of " << header.GetSize () 174 | << " bytes transmitted at " << std::setprecision (9) 175 | << header.GetTs ().As (Time::S)); 176 | if (m_aggregatedStats) 177 | { 178 | if (Simulator::Now () >= m_startTime) 179 | { 180 | m_rxBursts[nodeId]++; 181 | m_rxData[nodeId] += header.GetSize (); 182 | 183 | auto it = m_delay.find (nodeId); 184 | if (it == m_delay.end ()) 185 | { 186 | NS_LOG_DEBUG (this << " Creating delay stats calculator for node " << nodeId); 187 | m_delay[nodeId] = CreateObject> (); 188 | } 189 | 190 | uint64_t delay = Simulator::Now().GetNanoSeconds() - header.GetTs ().GetNanoSeconds(); 191 | m_delay[nodeId]->Update (delay); 192 | } 193 | m_pendingOutput = true; 194 | } 195 | } 196 | 197 | std::map 198 | BurstyAppStatsCalculator::ReadResults (void) 199 | { 200 | NS_LOG_FUNCTION (this); 201 | 202 | // Get the list of node IDs 203 | std::vector nodeIdsVector; 204 | for (auto it = m_txBursts.begin (); it != m_txBursts.end (); ++it) 205 | { 206 | if (find (nodeIdsVector.begin (), nodeIdsVector.end (), (*it).first) == nodeIdsVector.end ()) 207 | { 208 | nodeIdsVector.push_back ((*it).first); 209 | } 210 | } 211 | 212 | std::map results; 213 | for (auto it = nodeIdsVector.begin (); it != nodeIdsVector.end (); 214 | ++it) 215 | { 216 | AppResults item; 217 | uint32_t nodeId = *it; 218 | item.imsi = nodeId; 219 | 220 | item.txBursts = m_txBursts[nodeId]; 221 | item.txData = m_txData[nodeId]; 222 | 223 | item.rxBursts = m_rxBursts[nodeId]; 224 | item.rxData = m_rxData[nodeId]; 225 | 226 | auto iter = m_delay.find (nodeId); 227 | 228 | // if no delay info have been recorded yet, put it to zero 229 | if (iter == m_delay.end ()) 230 | { 231 | item.delayMean = 0.0; 232 | item.delayStdev = 0.0; 233 | item.delayMin = 0.0; 234 | item.delayMax = 0.0; 235 | } 236 | else 237 | { 238 | item.delayMean = m_delay[nodeId]->getMean (); 239 | item.delayStdev = m_delay[nodeId]->getStddev (); 240 | item.delayMin = m_delay[nodeId]->getMin (); 241 | item.delayMax = m_delay[nodeId]->getMax (); 242 | } 243 | results.insert (std::make_pair (item.imsi, item)); 244 | } 245 | if (m_writeToFile) 246 | { 247 | ShowResults (); 248 | } 249 | ResetResults (); 250 | return results; 251 | } 252 | 253 | void 254 | BurstyAppStatsCalculator::ShowResults (void) 255 | { 256 | std::ofstream outFile; 257 | 258 | if (m_firstWrite == true) 259 | { 260 | outFile.open (GetOutputFilename ().c_str ()); 261 | if (!outFile.is_open ()) 262 | { 263 | NS_LOG_ERROR ("Can't open file " << GetOutputFilename ().c_str ()); 264 | return; 265 | } 266 | 267 | m_firstWrite = false; 268 | outFile << "start\tend\tNodeId\tnTxBursts\tTxBytes\tnRxBursts\tRxBytes\tdelay\tstdDev\tmin\tmax\t"; 269 | outFile << std::endl; 270 | } 271 | else 272 | { 273 | outFile.open (GetOutputFilename ().c_str (), std::ios_base::app); 274 | if (!outFile.is_open ()) 275 | { 276 | NS_LOG_ERROR ("Can't open file " << GetOutputFilename ().c_str ()); 277 | return; 278 | } 279 | } 280 | 281 | WriteResults (outFile); 282 | m_pendingOutput = false; 283 | } 284 | 285 | void 286 | BurstyAppStatsCalculator::WriteResults (std::ofstream &outFile) 287 | { 288 | NS_LOG_FUNCTION (this); 289 | 290 | // Get the list of node IDs 291 | 292 | std::vector nodeIdsVector; 293 | for (auto it = m_txBursts.begin (); it != m_txBursts.end (); ++it) 294 | { 295 | if (find (nodeIdsVector.begin (), nodeIdsVector.end (), (*it).first) == nodeIdsVector.end ()) 296 | { 297 | nodeIdsVector.push_back ((*it).first); 298 | } 299 | } 300 | 301 | // Check if there is some ID missing 302 | for (auto it = m_rxBursts.begin (); it != m_rxBursts.end (); ++it) 303 | { 304 | if (find (nodeIdsVector.begin (), nodeIdsVector.end (), (*it).first) == nodeIdsVector.end ()) 305 | { 306 | nodeIdsVector.push_back ((*it).first); 307 | } 308 | } 309 | 310 | Time endTime; 311 | if (m_manualUpdate) 312 | { 313 | endTime = Simulator::Now (); 314 | } 315 | else 316 | { 317 | endTime = m_startTime + m_epochDuration; 318 | } 319 | 320 | for (auto it = nodeIdsVector.begin (); it != nodeIdsVector.end (); 321 | ++it) 322 | { 323 | uint32_t nodeId = *it; 324 | outFile << m_startTime.GetNanoSeconds () / 1.0e9 << "\t"; 325 | outFile << endTime.GetNanoSeconds () / 1.0e9 << "\t"; 326 | 327 | outFile << nodeId << "\t"; 328 | 329 | outFile << m_txBursts[nodeId] << "\t"; 330 | outFile << m_txData[nodeId] << "\t"; 331 | 332 | outFile << m_rxBursts[nodeId] << "\t"; 333 | outFile << m_rxData[nodeId] << "\t"; 334 | 335 | auto iter = m_delay.find (nodeId); 336 | 337 | // if no delay info have been recorded yet, put it to zero 338 | if (iter == m_delay.end ()) 339 | { 340 | outFile << 0.0 << "\t"; 341 | outFile << 0.0 << "\t"; 342 | outFile << 0.0 << "\t"; 343 | outFile << 0.0 << "\t"; 344 | } 345 | else 346 | { 347 | outFile << m_delay[nodeId]->getMean () << "\t"; 348 | outFile << m_delay[nodeId]->getStddev () << "\t"; 349 | outFile << m_delay[nodeId]->getMin () << "\t"; 350 | outFile << m_delay[nodeId]->getMax () << "\t"; 351 | } 352 | 353 | 354 | outFile << std::endl; 355 | } 356 | 357 | outFile.close (); 358 | } 359 | 360 | void 361 | BurstyAppStatsCalculator::ResetResults (void) 362 | { 363 | NS_LOG_FUNCTION (this); 364 | 365 | m_rxBursts.erase (m_rxBursts.begin (), m_rxBursts.end ()); 366 | m_txBursts.erase (m_txBursts.begin (), m_txBursts.end ()); 367 | 368 | m_txData.erase (m_txData.begin (), m_txData.end ()); 369 | m_rxData.erase (m_rxData.begin (), m_rxData.end ()); 370 | 371 | m_delay.erase (m_delay.begin (), m_delay.end ()); 372 | } 373 | 374 | void 375 | BurstyAppStatsCalculator::RescheduleEndEpoch (void) 376 | { 377 | NS_LOG_FUNCTION (this); 378 | m_endEpochEvent.Cancel (); 379 | NS_ASSERT (Simulator::Now ().GetMilliSeconds () == 0); // below event time assumes this 380 | m_endEpochEvent = Simulator::Schedule (m_startTime + m_epochDuration, &BurstyAppStatsCalculator::EndEpoch, this); 381 | } 382 | 383 | void 384 | BurstyAppStatsCalculator::EndEpoch (void) 385 | { 386 | NS_LOG_FUNCTION (this); 387 | ShowResults (); 388 | ResetResults (); 389 | m_startTime += m_epochDuration; 390 | m_endEpochEvent = Simulator::Schedule (m_epochDuration, &BurstyAppStatsCalculator::EndEpoch, this); 391 | } 392 | 393 | void 394 | BurstyAppStatsCalculator::SetOutputFilename (std::string filename) 395 | { 396 | m_outputFilename = filename; 397 | } 398 | 399 | std::string 400 | BurstyAppStatsCalculator::GetOutputFilename (void) const 401 | { 402 | return m_outputFilename; 403 | } 404 | -------------------------------------------------------------------------------- /helper/bursty-app-stats-calculator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * This program is free software; you can redistribute it and/or modify 4 | * it under the terms of the GNU General Public License version 2 as 5 | * published by the Free Software Foundation; 6 | * 7 | * This program is distributed in the hope that it will be useful, 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | * GNU General Public License for more details. 11 | * 12 | * You should have received a copy of the GNU General Public License 13 | * along with this program; if not, write to the Free Software 14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15 | * 16 | */ 17 | 18 | #ifndef BURSTY_APP_STATS_CALCULATOR_H_ 19 | #define BURSTY_APP_STATS_CALCULATOR_H_ 20 | 21 | #include "ns3/basic-data-calculators.h" 22 | #include "ns3/internet-module.h" 23 | #include "ns3/lte-common.h" 24 | #include "ns3/network-module.h" 25 | #include "ns3/object.h" 26 | #include "ns3/seq-ts-size-frag-header.h" 27 | #include "ns3/uinteger.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | namespace ns3 34 | { 35 | 36 | struct AppResults 37 | { 38 | uint16_t imsi; 39 | uint16_t txBursts; 40 | uint32_t txData; 41 | uint16_t rxBursts; 42 | uint32_t rxData; 43 | double delayMean; 44 | double delayStdev; 45 | double delayMin; 46 | double delayMax; 47 | }; 48 | 49 | /** 50 | * \ingroup application 51 | * 52 | */ 53 | class BurstyAppStatsCalculator : public Object 54 | { 55 | public: 56 | /** 57 | * Class constructor 58 | */ 59 | BurstyAppStatsCalculator(); 60 | 61 | /** 62 | * Class constructor 63 | */ 64 | BurstyAppStatsCalculator(std::string protocolType); 65 | 66 | /** 67 | * Class destructor 68 | */ 69 | virtual ~BurstyAppStatsCalculator(); 70 | 71 | // Inherited from ns3::Object 72 | /** 73 | * Register this type. 74 | * \return The object TypeId. 75 | */ 76 | static TypeId GetTypeId(void); 77 | void DoDispose(); 78 | 79 | /** 80 | * 81 | * \param e the epoch duration 82 | */ 83 | void SetEpoch(Time e); 84 | 85 | /** 86 | * 87 | * \return the epoch duration 88 | */ 89 | Time GetEpoch() const; 90 | 91 | /** 92 | * 93 | * \param t the value of the StartTime attribute 94 | */ 95 | void SetStartTime(Time t); 96 | 97 | /** 98 | * 99 | * \return the value of the StartTime attribute 100 | */ 101 | Time GetStartTime() const; 102 | 103 | /** 104 | * Reschedules EndEpoch event. Usually used after 105 | * execution of SetStartTime() or SetEpoch() 106 | */ 107 | void RescheduleEndEpoch(); 108 | 109 | /** 110 | * 111 | * \param u set the update mode (true if manual, automatic otherwise) 112 | */ 113 | void SetManualUpdate(bool u); 114 | 115 | /** 116 | * 117 | * \return whether the update is manual or not 118 | */ 119 | bool GetManualUpdate() const; 120 | 121 | /** 122 | * Notifies the stats calculator that a burst of packets has been transmitted. 123 | * \param nodeId ID of the node sending the burst 124 | * \param burst packet representing the complete burst 125 | * \param from address of the transmitting terminal 126 | * \param to address of the receiving terminal 127 | * \param header burst header containing trasmission information 128 | */ 129 | void TxBurst(uint32_t nodeId, 130 | Ptr burst, 131 | const Address& from, 132 | const Address& to, 133 | const SeqTsSizeFragHeader& header); 134 | 135 | /** 136 | * Notifies the stats calculator that a burst of packets has been transmitted. 137 | * \param nodeId ID of the node receiving the burst 138 | * \param burst packet representing the complete burst 139 | * \param from address of the transmitting terminal 140 | * \param to address of the receiving terminal 141 | * \param header burst header containing trasmission information 142 | */ 143 | void RxBurst(uint32_t nodeId, 144 | Ptr burst, 145 | const Address& from, 146 | const Address& to, 147 | const SeqTsSizeFragHeader& header); 148 | 149 | /** 150 | * 151 | */ 152 | std::map ReadResults(void); 153 | 154 | /** 155 | * Called after each epoch to write collected 156 | * statistics to output files. During first call 157 | * it opens output files and write columns descriptions. 158 | * During next calls it opens output files in append mode. 159 | */ 160 | void ShowResults(void); 161 | 162 | /** 163 | * Writes collected statistics to output file and closes it. 164 | * @param outFile ofstream for statistics 165 | */ 166 | void WriteResults(std::ofstream& outFile); 167 | 168 | /** 169 | * Erases collected statistics 170 | */ 171 | void ResetResults(); 172 | 173 | /** 174 | * 175 | * \param filename name of the output file 176 | */ 177 | void SetOutputFilename(std::string filename); 178 | 179 | /** 180 | * 181 | * \return name of the output file 182 | */ 183 | std::string GetOutputFilename() const; 184 | 185 | private: 186 | /** 187 | * Function called in every endEpochEvent. It calls 188 | * ShowResults() to write statistics to output files 189 | * and ResetResults() to clear collected statistics. 190 | */ 191 | void EndEpoch(void); 192 | 193 | EventId m_endEpochEvent; //!< Event id for next end epoch event 194 | Time m_startTime; //!< Start time of the on going epoch 195 | Time m_epochDuration; //!< Epoch duration 196 | 197 | bool m_firstWrite; //! true if output files have not been opened yet 198 | bool m_pendingOutput; //!< true if any output is pending 199 | bool m_aggregatedStats; //!< true if results are shown aggregated 200 | bool m_manualUpdate; //!< true if update is triggered by external entity (such as RAN-AI) 201 | bool m_writeToFile; //!< determine if the traces must be output to file or just evaluated and 202 | //!< exchanged with external classes 203 | 204 | std::map 205 | m_txBursts; //!< number of bursts sent in a specific epoch per node ID 206 | std::map m_txData; //!< number of bytes sent in a specific epoch per node ID 207 | 208 | std::map 209 | m_rxBursts; //!< number of bursts received in a specific epoch per node ID 210 | std::map 211 | m_rxData; //!< number of bytes received in a specific epoch per node ID 212 | 213 | std::map>> 214 | m_delay; //!< delay statistics calculator for a specific epoch, per node ID 215 | 216 | std::string m_outputFilename; //!< name of the output file 217 | }; 218 | 219 | } // namespace ns3 220 | 221 | #endif /* BURSTY_APP_STATS_CALCULATOR_H_ */ 222 | -------------------------------------------------------------------------------- /helper/bursty-helper.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | #include "bursty-helper.h" 21 | #include "ns3/inet-socket-address.h" 22 | #include "ns3/packet-socket-address.h" 23 | #include "ns3/string.h" 24 | #include "ns3/pointer.h" 25 | #include "ns3/data-rate.h" 26 | #include "ns3/uinteger.h" 27 | #include "ns3/names.h" 28 | #include "ns3/random-variable-stream.h" 29 | #include "ns3/bursty-application.h" 30 | #include "ns3/simple-burst-generator.h" 31 | #include "ns3/vr-burst-generator.h" 32 | 33 | namespace ns3 { 34 | 35 | BurstyHelper::BurstyHelper (std::string protocol, Address address) 36 | { 37 | m_burstyApplicationFactory.SetTypeId ("ns3::BurstyApplication"); 38 | m_burstyApplicationFactory.Set ("Protocol", StringValue (protocol)); 39 | m_burstyApplicationFactory.Set ("Remote", AddressValue (address)); 40 | } 41 | 42 | void 43 | BurstyHelper::SetAttribute (std::string name, const AttributeValue &value) 44 | { 45 | m_burstyApplicationFactory.Set (name, value); 46 | } 47 | 48 | void 49 | BurstyHelper::SetBurstGenerator (std::string type, 50 | std::string n1, const AttributeValue &v1, 51 | std::string n2, const AttributeValue &v2, 52 | std::string n3, const AttributeValue &v3, 53 | std::string n4, const AttributeValue &v4) 54 | { 55 | m_burstGeneratorFactory.SetTypeId (type); 56 | m_burstGeneratorFactory.Set (n1, v1); 57 | m_burstGeneratorFactory.Set (n2, v2); 58 | m_burstGeneratorFactory.Set (n3, v3); 59 | m_burstGeneratorFactory.Set (n4, v4); 60 | } 61 | 62 | void 63 | BurstyHelper::SetBurstGeneratorAttribute (std::string name, const AttributeValue &value) 64 | { 65 | m_burstGeneratorFactory.Set (name, value); 66 | } 67 | 68 | ApplicationContainer 69 | BurstyHelper::Install (Ptr node) const 70 | { 71 | return ApplicationContainer (InstallPriv (node)); 72 | } 73 | 74 | ApplicationContainer 75 | BurstyHelper::Install (std::string nodeName) const 76 | { 77 | Ptr node = Names::Find (nodeName); 78 | return ApplicationContainer (InstallPriv (node)); 79 | } 80 | 81 | ApplicationContainer 82 | BurstyHelper::Install (NodeContainer c) const 83 | { 84 | ApplicationContainer apps; 85 | for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) 86 | { 87 | apps.Add (InstallPriv (*i)); 88 | } 89 | 90 | return apps; 91 | } 92 | 93 | Ptr 94 | BurstyHelper::InstallPriv (Ptr node) const 95 | { 96 | Ptr app = m_burstyApplicationFactory.Create (); 97 | Ptr generator = m_burstGeneratorFactory.Create (); 98 | 99 | app->SetAttribute ("BurstGenerator", PointerValue (generator)); 100 | node->AddApplication (app); 101 | 102 | return app; 103 | } 104 | 105 | int64_t 106 | BurstyHelper::AssignStreams (NodeContainer c, int64_t stream) 107 | { 108 | int64_t currentStream = stream; 109 | Ptr node; 110 | for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) 111 | { 112 | node = (*i); 113 | for (uint32_t j = 0; j < node->GetNApplications (); j++) 114 | { 115 | Ptr app = DynamicCast (node->GetApplication (j)); 116 | if (app) 117 | { 118 | Ptr simpleGenerator = 119 | DynamicCast (app->GetBurstGenerator ()); // TODO improve 120 | if (simpleGenerator) 121 | { 122 | currentStream += simpleGenerator->AssignStreams (currentStream); 123 | } 124 | Ptr vrGenerator = 125 | DynamicCast (app->GetBurstGenerator ()); // TODO improve 126 | if (vrGenerator) 127 | { 128 | currentStream += vrGenerator->AssignStreams (currentStream); 129 | } 130 | } 131 | } 132 | } 133 | return (currentStream - stream); 134 | } 135 | 136 | } // namespace ns3 137 | -------------------------------------------------------------------------------- /helper/bursty-helper.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | #ifndef BURSTY_HELPER_H 21 | #define BURSTY_HELPER_H 22 | 23 | #include 24 | #include 25 | #include "ns3/object-factory.h" 26 | #include "ns3/address.h" 27 | #include "ns3/attribute.h" 28 | #include "ns3/net-device.h" 29 | #include "ns3/node-container.h" 30 | #include "ns3/application-container.h" 31 | #include "ns3/bursty-application.h" 32 | 33 | namespace ns3 { 34 | 35 | class DataRate; 36 | 37 | /** 38 | * \ingroup bursty 39 | * \brief A helper to make it easier to instantiate an ns3::BurstyApplication 40 | * on a set of nodes. 41 | */ 42 | class BurstyHelper 43 | { 44 | public: 45 | /** 46 | * Create an BurstyHelper to make it easier to work with BurstyApplications 47 | * 48 | * \param protocol the name of the protocol to use to send traffic 49 | * by the applications. This string identifies the socket 50 | * factory type used to create sockets for the applications. 51 | * A typical value would be ns3::UdpSocketFactory. 52 | * \param address the address of the remote node to send traffic 53 | * to. 54 | */ 55 | BurstyHelper (std::string protocol, Address address); 56 | 57 | /** 58 | * Helper function used to set the underlying application attributes. 59 | * 60 | * \param name the name of the application attribute to set 61 | * \param value the value of the application attribute to set 62 | */ 63 | void SetAttribute (std::string name, const AttributeValue &value); 64 | 65 | /** 66 | * Each BurstyApplication must have a BurstGenerator. 67 | * This method allows one to set the type of the BurstGenerator that is automatically 68 | * created when the application is created and attached to a node. 69 | * 70 | * \param type the type of BurstGenerator 71 | * \param n1 the name of the attribute to set on the BurstGenerator 72 | * \param v1 the value of the attribute to set on the BurstGenerator 73 | * \param n2 the name of the attribute to set on the BurstGenerator 74 | * \param v2 the value of the attribute to set on the BurstGenerator 75 | * \param n3 the name of the attribute to set on the BurstGenerator 76 | * \param v3 the value of the attribute to set on the BurstGenerator 77 | * \param n4 the name of the attribute to set on the BurstGenerator 78 | * \param v4 the value of the attribute to set on the BurstGenerator 79 | * 80 | * Set the type of BurstGenerator to create and associated to each 81 | * BurstApplication created through BurstyHelper::Install. 82 | */ 83 | void SetBurstGenerator (std::string type, 84 | std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (), 85 | std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (), 86 | std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (), 87 | std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue ()); 88 | 89 | /** 90 | * \param n1 the name of the attribute to set 91 | * \param v1 the value of the attribute to set 92 | * 93 | * Set these attributes on each ns3::BurstGenerator created 94 | * by BurstyHelper::Install 95 | */ 96 | void SetBurstGeneratorAttribute (std::string n1, const AttributeValue &v1); 97 | 98 | /** 99 | * Install an ns3::BurstyApplication on each node of the input container 100 | * configured with all the attributes set with SetAttribute. 101 | * 102 | * \param c NodeContainer of the set of nodes on which an BurstyApplication 103 | * will be installed. 104 | * \returns Container of Ptr to the applications installed. 105 | */ 106 | ApplicationContainer Install (NodeContainer c) const; 107 | 108 | /** 109 | * Install an ns3::BurstyApplication on the node configured with all the 110 | * attributes set with SetAttribute. 111 | * 112 | * \param node The node on which an BurstyApplication will be installed. 113 | * \returns Container of Ptr to the applications installed. 114 | */ 115 | ApplicationContainer Install (Ptr node) const; 116 | 117 | /** 118 | * Install an ns3::BurstyApplication on the node configured with all the 119 | * attributes set with SetAttribute. 120 | * 121 | * \param nodeName The node on which an BurstyApplication will be installed. 122 | * \returns Container of Ptr to the applications installed. 123 | */ 124 | ApplicationContainer Install (std::string nodeName) const; 125 | 126 | /** 127 | * Assign a fixed random variable stream number to the random variables 128 | * used by this model. Return the number of streams (possibly zero) that 129 | * have been assigned. The Install() method should have previously been 130 | * called by the user. 131 | * 132 | * \param stream first stream index to use 133 | * \param c NodeContainer of the set of nodes for which the BurstyApplication 134 | * should be modified to use a fixed stream 135 | * \return the number of stream indices assigned by this helper 136 | */ 137 | int64_t AssignStreams (NodeContainer c, int64_t stream); 138 | 139 | private: 140 | /** 141 | * Install an ns3::BurstyApplication on the node configured with all the 142 | * attributes set with SetAttribute. 143 | * 144 | * \param node The node on which an BurstyApplication will be installed. 145 | * \returns Ptr to the application installed. 146 | */ 147 | Ptr InstallPriv (Ptr node) const; 148 | 149 | ObjectFactory m_burstyApplicationFactory; //!< BurstyApplication factory 150 | ObjectFactory m_burstGeneratorFactory; //!< BurstGenerator factory 151 | }; 152 | 153 | } // namespace ns3 154 | 155 | #endif /* BURSTY_HELPER_H */ 156 | -------------------------------------------------------------------------------- /model/BurstGeneratorTraces/README.md: -------------------------------------------------------------------------------- 1 | Traces present a consistent naming scheme: `{appName}_{dataRate}mbps_{frameRate}fps.csv`. 2 | Specifically: 3 | * `appName`: an indication of the name of the streamed application. Specifically, 4 | - `vp` stands for _Virus Popper_ 5 | - `mc` stands for _Minecraft_ 6 | - `ge_cities` stands for _Google Earth VR - Cities_ 7 | - `ge_tour` stands for _Google Earth VR - Tour_ 8 | * `dataRate`: the target data rate 9 | * `frameRate`: the target frame rate 10 | 11 | Some additional meta data might be found in the commented header of the `.csv` file. 12 | 13 | For further information please check the reference paper: 14 | * M. Lecci, M. Drago, A. Zanella, M. Zorzi, "An Open Framework for Analyzing and Modeling XR Network Traffic," in IEEE Access, vol. 9, pp. 129782-129795, 2021. Open Access DOI: [10.1109/ACCESS.2021.3113162](https://doi.org/10.1109/ACCESS.2021.3113162). 15 | 16 | NOTE: `.csv` traces are based on acquisitions of real VR traffic streaming. Target data and frame rate are only indicative and may vary over time as well as in average. -------------------------------------------------------------------------------- /model/burst-generator.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include 22 | #include "burst-generator.h" 23 | 24 | namespace ns3 { 25 | 26 | NS_LOG_COMPONENT_DEFINE ("BurstGenerator"); 27 | 28 | NS_OBJECT_ENSURE_REGISTERED (BurstGenerator); 29 | 30 | BurstGenerator::BurstGenerator () 31 | { 32 | } 33 | 34 | BurstGenerator::~BurstGenerator () 35 | { 36 | } 37 | 38 | TypeId 39 | BurstGenerator::GetTypeId () 40 | { 41 | static TypeId tid = TypeId ("ns3::BurstGenerator") 42 | .SetParent () 43 | .SetGroupName("Applications") 44 | ; 45 | return tid; 46 | } 47 | 48 | void 49 | BurstGenerator::DoDispose () 50 | { 51 | // chain up 52 | Object::DoDispose (); 53 | } 54 | 55 | } // namespace ns3 56 | -------------------------------------------------------------------------------- /model/burst-generator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef BURST_GENERATOR_H 21 | #define BURST_GENERATOR_H 22 | 23 | #include 24 | 25 | namespace ns3 { 26 | 27 | class Time; 28 | 29 | /** 30 | * \ingroup applications 31 | * 32 | * \brief Virtual interface for burst generators. 33 | * 34 | * A virtual interface defining the API for burst generators. 35 | * Burst generators are thought to be used by BurstyApplication, 36 | * although their interface might be re-used by other applications. 37 | * 38 | * The interface defines two purely virtual methods: 39 | * - GenerateBurst: generates a new burst, returning its total burst 40 | * size and the time before the next burst 41 | * - HasNextBurst: to check whether GenerateBurst can be safely called. 42 | * 43 | * The interface is meant to allow for great flexibility in its child 44 | * classes: such classes can include complex behavior, such as arbitrary 45 | * probability distributions for burst size and period, correlations 46 | * among successive burst sizes and periods, cross-correlation between 47 | * burst size and period, etc. 48 | * 49 | */ 50 | class BurstGenerator : public Object 51 | { 52 | public: 53 | BurstGenerator (); 54 | virtual ~BurstGenerator (); 55 | 56 | /** 57 | * \brief Get the type ID. 58 | * \return the object TypeId 59 | */ 60 | static TypeId GetTypeId (); 61 | 62 | /** 63 | * Generate the next burst, composed of a burst size, expressed in Bytes, 64 | * and a time before the next burst. 65 | * 66 | * \return pair with burst size [B] and the time before the next burst 67 | */ 68 | virtual std::pair GenerateBurst (void) = 0; 69 | 70 | /** 71 | * Check whether a next burst can be generated. 72 | * If not, an error may occur. 73 | * 74 | * \return true if a new burst can be generated 75 | */ 76 | virtual bool HasNextBurst (void) = 0; 77 | 78 | protected: 79 | virtual void DoDispose (void) override; 80 | }; 81 | 82 | } // namespace ns3 83 | 84 | #endif // BURST_GENERATOR_H 85 | -------------------------------------------------------------------------------- /model/burst-sink.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | #include "ns3/address.h" 21 | #include "ns3/address-utils.h" 22 | #include "ns3/log.h" 23 | #include "ns3/inet-socket-address.h" 24 | #include "ns3/inet6-socket-address.h" 25 | #include "ns3/node.h" 26 | #include "ns3/socket.h" 27 | #include "ns3/udp-socket.h" 28 | #include "ns3/simulator.h" 29 | #include "ns3/socket-factory.h" 30 | #include "ns3/packet.h" 31 | #include "ns3/trace-source-accessor.h" 32 | #include "ns3/udp-socket-factory.h" 33 | #include "burst-sink.h" 34 | #include "ns3/boolean.h" 35 | 36 | namespace ns3 { 37 | 38 | NS_LOG_COMPONENT_DEFINE ("BurstSink"); 39 | 40 | NS_OBJECT_ENSURE_REGISTERED (BurstSink); 41 | 42 | TypeId 43 | BurstSink::GetTypeId (void) 44 | { 45 | static TypeId tid = TypeId ("ns3::BurstSink") 46 | .SetParent () 47 | .SetGroupName ("Applications") 48 | .AddConstructor () 49 | .AddAttribute ("Local", 50 | "The Address on which to Bind the rx socket.", 51 | AddressValue (), 52 | MakeAddressAccessor (&BurstSink::m_local), 53 | MakeAddressChecker ()) 54 | .AddAttribute ("Protocol", 55 | "The type id of the protocol to use for the rx socket.", 56 | TypeIdValue (UdpSocketFactory::GetTypeId ()), 57 | MakeTypeIdAccessor (&BurstSink::m_tid), 58 | MakeTypeIdChecker ()) 59 | .AddTraceSource ("FragmentRx", 60 | "A fragment has been received", 61 | MakeTraceSourceAccessor (&BurstSink::m_rxFragmentTrace), 62 | "ns3::BurstSink::SeqTsSizeFragCallback") 63 | .AddTraceSource ("BurstRx", "A burst has been successfully received", 64 | MakeTraceSourceAccessor (&BurstSink::m_rxBurstTrace), 65 | "ns3::BurstSink::SeqTsSizeFragCallback") 66 | ; 67 | return tid; 68 | } 69 | 70 | BurstSink::BurstSink () 71 | { 72 | NS_LOG_FUNCTION (this); 73 | } 74 | 75 | BurstSink::~BurstSink () 76 | { 77 | NS_LOG_FUNCTION (this); 78 | } 79 | 80 | uint64_t 81 | BurstSink::GetTotalRxBytes () const 82 | { 83 | NS_LOG_FUNCTION (this); 84 | return m_totRxBytes; 85 | } 86 | 87 | uint64_t 88 | BurstSink::GetTotalRxFragments () const 89 | { 90 | NS_LOG_FUNCTION (this); 91 | return m_totRxFragments; 92 | } 93 | 94 | uint64_t 95 | BurstSink::GetTotalRxBursts () const 96 | { 97 | NS_LOG_FUNCTION (this); 98 | return m_totRxBursts; 99 | } 100 | 101 | Ptr 102 | BurstSink::GetListeningSocket (void) const 103 | { 104 | NS_LOG_FUNCTION (this); 105 | return m_socket; 106 | } 107 | 108 | std::list> 109 | BurstSink::GetAcceptedSockets (void) const 110 | { 111 | NS_LOG_FUNCTION (this); 112 | return m_socketList; 113 | } 114 | 115 | void 116 | BurstSink::DoDispose (void) 117 | { 118 | NS_LOG_FUNCTION (this); 119 | m_socket = 0; 120 | m_socketList.clear (); 121 | 122 | // chain up 123 | Application::DoDispose (); 124 | } 125 | 126 | // Application Methods 127 | void 128 | BurstSink::StartApplication () // Called at time specified by Start 129 | { 130 | NS_LOG_FUNCTION (this); 131 | // Create the socket if not already 132 | if (!m_socket) 133 | { 134 | m_socket = Socket::CreateSocket (GetNode (), m_tid); 135 | if (m_socket->Bind (m_local) == -1) 136 | { 137 | NS_FATAL_ERROR ("Failed to bind socket"); 138 | } 139 | m_socket->Listen (); 140 | m_socket->ShutdownSend (); 141 | if (addressUtils::IsMulticast (m_local)) 142 | { 143 | Ptr udpSocket = DynamicCast (m_socket); 144 | if (udpSocket) 145 | { 146 | // equivalent to setsockopt (MCAST_JOIN_GROUP) 147 | udpSocket->MulticastJoinGroup (0, m_local); 148 | } 149 | else 150 | { 151 | NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket"); 152 | } 153 | } 154 | } 155 | 156 | m_socket->SetRecvCallback (MakeCallback (&BurstSink::HandleRead, this)); 157 | m_socket->SetAcceptCallback (MakeNullCallback, const Address &> (), 158 | MakeCallback (&BurstSink::HandleAccept, this)); 159 | m_socket->SetCloseCallbacks (MakeCallback (&BurstSink::HandlePeerClose, this), 160 | MakeCallback (&BurstSink::HandlePeerError, this)); 161 | } 162 | 163 | void 164 | BurstSink::StopApplication () // Called at time specified by Stop 165 | { 166 | NS_LOG_FUNCTION (this); 167 | while (!m_socketList.empty ()) //these are accepted sockets, close them 168 | { 169 | Ptr acceptedSocket = m_socketList.front (); 170 | m_socketList.pop_front (); 171 | acceptedSocket->Close (); 172 | } 173 | if (m_socket) 174 | { 175 | m_socket->Close (); 176 | m_socket->SetRecvCallback (MakeNullCallback> ()); 177 | } 178 | } 179 | 180 | void 181 | BurstSink::HandleRead (Ptr socket) 182 | { 183 | NS_LOG_FUNCTION (this << socket); 184 | Ptr fragment; 185 | Address from; 186 | Address localAddress; 187 | while ((fragment = socket->RecvFrom (from))) 188 | { 189 | if (fragment->GetSize () == 0) 190 | { //EOF 191 | break; 192 | } 193 | m_totRxBytes += fragment->GetSize (); 194 | 195 | std::stringstream addressStr; 196 | if (InetSocketAddress::IsMatchingType (from)) 197 | { 198 | addressStr << InetSocketAddress::ConvertFrom (from).GetIpv4 () << " port " 199 | << InetSocketAddress::ConvertFrom (from).GetPort (); 200 | } 201 | else if (Inet6SocketAddress::IsMatchingType (from)) 202 | { 203 | addressStr << Inet6SocketAddress::ConvertFrom (from).GetIpv6 () << " port " 204 | << Inet6SocketAddress::ConvertFrom (from).GetPort (); 205 | } 206 | else 207 | { 208 | addressStr << "UNKNOWN ADDRESS TYPE"; 209 | } 210 | 211 | NS_LOG_INFO ("At time " << Simulator::Now ().As (Time::S) << " burst sink received " 212 | << fragment->GetSize () << " bytes from " << addressStr.str () 213 | << " total Rx " << m_totRxBytes << " bytes"); 214 | 215 | socket->GetSockName (localAddress); 216 | 217 | // handle received fragment 218 | auto itBuffer = m_burstHandlerMap.find (from); // rename m_burstBufferMap, itBuffer 219 | if (itBuffer == m_burstHandlerMap.end ()) 220 | { 221 | NS_LOG_LOGIC ("New stream from " << from); 222 | itBuffer = m_burstHandlerMap.insert (std::make_pair (from, BurstHandler ())).first; 223 | } 224 | FragmentReceived (itBuffer->second, fragment, from, localAddress); 225 | } 226 | } 227 | 228 | void 229 | BurstSink::FragmentReceived (BurstHandler &burstHandler, const Ptr &f, const Address &from, 230 | const Address &localAddress) 231 | { 232 | NS_LOG_FUNCTION (this << f); 233 | 234 | SeqTsSizeFragHeader header; 235 | f->PeekHeader (header); 236 | NS_ABORT_IF (header.GetSize () == 0); 237 | 238 | m_totRxFragments++; 239 | m_rxFragmentTrace (f, from, localAddress, 240 | header); // TODO should fragment still include header in trace? 241 | 242 | NS_LOG_DEBUG ("Get BurstHandler for from=" 243 | << from << " with m_currentBurstSeq=" << burstHandler.m_currentBurstSeq 244 | << ", m_fragmentsMerged=" << burstHandler.m_fragmentsMerged 245 | << ", m_unorderedFragments.size ()=" << burstHandler.m_unorderedFragments.size () 246 | << ", m_burstBuffer.GetSize ()=" << burstHandler.m_burstBuffer->GetSize () 247 | << ", for fragment with header: " << header); 248 | 249 | if (header.GetSeq () < burstHandler.m_currentBurstSeq) 250 | { 251 | NS_LOG_LOGIC ("Ignoring fragment from previous burst. Fragment burst seq=" 252 | << header.GetSeq () 253 | << ", current burst seq=" << burstHandler.m_currentBurstSeq); 254 | return; 255 | } 256 | 257 | if (header.GetSeq () > burstHandler.m_currentBurstSeq) 258 | { 259 | // fragment of new burst: discard previous burst if incomplete 260 | NS_LOG_LOGIC ("Start mering new burst seq " 261 | << header.GetSeq () << " (previous=" << burstHandler.m_currentBurstSeq << ")"); 262 | 263 | burstHandler.m_currentBurstSeq = header.GetSeq (); 264 | burstHandler.m_fragmentsMerged = 0; 265 | burstHandler.m_unorderedFragments.clear (); 266 | burstHandler.m_burstBuffer = Create (0); 267 | } 268 | 269 | if (header.GetSeq () == burstHandler.m_currentBurstSeq) 270 | { 271 | // fragment of current burst 272 | NS_ASSERT_MSG (header.GetFragSeq () >= burstHandler.m_fragmentsMerged, 273 | header.GetFragSeq () << " >= " << burstHandler.m_fragmentsMerged); 274 | 275 | NS_LOG_DEBUG ("fragment sequence=" << header.GetFragSeq () << ", fragments merged=" 276 | << burstHandler.m_fragmentsMerged); 277 | if (header.GetFragSeq () == burstHandler.m_fragmentsMerged) 278 | { 279 | // following packet: merge it 280 | f->RemoveHeader (header); 281 | burstHandler.m_burstBuffer->AddAtEnd (f); 282 | burstHandler.m_fragmentsMerged++; 283 | NS_LOG_LOGIC ("Fragments merged " << burstHandler.m_fragmentsMerged << "/" 284 | << header.GetFrags () << " for burst " 285 | << header.GetSeq ()); 286 | 287 | // if present, merge following unordered fragments 288 | auto nextFragmentIt = burstHandler.m_unorderedFragments.begin (); 289 | while (nextFragmentIt != 290 | burstHandler.m_unorderedFragments.end () && // there are unordered packets 291 | nextFragmentIt->first == 292 | burstHandler.m_fragmentsMerged) // the following fragment was already received 293 | { 294 | Ptr storedFragment = nextFragmentIt->second; 295 | storedFragment->RemoveHeader (header); 296 | burstHandler.m_burstBuffer->AddAtEnd (storedFragment); 297 | burstHandler.m_fragmentsMerged++; 298 | NS_LOG_LOGIC ("Unordered fragments merged " << burstHandler.m_fragmentsMerged << "/" 299 | << header.GetFrags () << " for burst " 300 | << header.GetSeq ()); 301 | 302 | nextFragmentIt = burstHandler.m_unorderedFragments.erase (nextFragmentIt); 303 | } 304 | } 305 | else 306 | { 307 | // add to unordered fragments buffer 308 | NS_LOG_LOGIC ("Add unordered fragment " << header.GetFragSeq () << " of burst " 309 | << header.GetSeq () << " to buffer "); 310 | burstHandler.m_unorderedFragments.insert ( 311 | std::pair> (header.GetFragSeq (), f)); 312 | } 313 | } 314 | 315 | // check if burst is complete 316 | if (burstHandler.m_fragmentsMerged == header.GetFrags ()) 317 | { 318 | // all fragments have been merged 319 | NS_ASSERT_MSG (burstHandler.m_burstBuffer->GetSize () == header.GetSize (), 320 | burstHandler.m_burstBuffer->GetSize () << " == " << header.GetSize ()); 321 | 322 | NS_LOG_LOGIC ("Burst received: " << header.GetFrags () << " fragments for a total of " 323 | << header.GetSize () << " B"); 324 | m_totRxBursts++; 325 | m_rxBurstTrace (burstHandler.m_burstBuffer, from, localAddress, 326 | header); // TODO header size does not include payload, why? 327 | } 328 | } 329 | 330 | void 331 | BurstSink::HandlePeerClose (Ptr socket) 332 | { 333 | NS_LOG_FUNCTION (this << socket); 334 | } 335 | 336 | void 337 | BurstSink::HandlePeerError (Ptr socket) 338 | { 339 | NS_LOG_FUNCTION (this << socket); 340 | } 341 | 342 | void 343 | BurstSink::HandleAccept (Ptr s, const Address &from) 344 | { 345 | NS_LOG_FUNCTION (this << s << from); 346 | s->SetRecvCallback (MakeCallback (&BurstSink::HandleRead, this)); 347 | m_socketList.push_back (s); 348 | } 349 | 350 | } // Namespace ns3 351 | -------------------------------------------------------------------------------- /model/burst-sink.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef BURST_SINK_H 21 | #define BURST_SINK_H 22 | 23 | #include "ns3/application.h" 24 | #include "ns3/event-id.h" 25 | #include "ns3/ptr.h" 26 | #include "ns3/traced-callback.h" 27 | #include "ns3/address.h" 28 | #include "ns3/inet-socket-address.h" 29 | #include "ns3/socket.h" 30 | #include "ns3/seq-ts-size-frag-header.h" 31 | #include 32 | 33 | namespace ns3 { 34 | 35 | class Address; 36 | class Socket; 37 | class Packet; 38 | 39 | /** 40 | * \ingroup applications 41 | * \defgroup burstsink BurstSink 42 | * 43 | * This application was written to complement BurstyApplication. 44 | */ 45 | 46 | /** 47 | * \ingroup burstsink 48 | * 49 | * \brief Receives and consume traffic generated from a BurstyApplication 50 | * to an IP address and port 51 | * 52 | * This application was based on PacketSink, and modified to accept traffic 53 | * generated by BurstyApplication. 54 | * The application assumes to be on top of a UDP socket, thus receiving UDP 55 | * datagrams rather than bytestreams. 56 | * 57 | * The sink tries to aggregate single packets (fragments) into a single packet 58 | * burst. To do so, it gathers information from SeqTsSizeFragHeader, which all 59 | * received packets should have. 60 | * It then makes the following assumptions: 61 | * - Being based on a UDP socket, packets might arrive out-of-order. Within a 62 | * burst, BurstSink will reorder the received packets. 63 | * - While receiving burst n, if a fragment from burst kn is received, 66 | * burst n is discarded and burst k will start being buffered. 67 | * - If all fragments from a burst are received, the burst is successfully 68 | * received. 69 | * 70 | * Traces are sent when a fragment is received and when a whole burst is 71 | * successfully received. 72 | * 73 | */ 74 | class BurstSink : public Application 75 | { 76 | public: 77 | /** 78 | * \brief Get the type ID. 79 | * \return the object TypeId 80 | */ 81 | static TypeId GetTypeId (void); 82 | 83 | BurstSink (); 84 | virtual ~BurstSink (); 85 | 86 | /** 87 | * \return the total bytes received in this sink app 88 | */ 89 | uint64_t GetTotalRxBytes () const; 90 | 91 | /** 92 | * \return the total fragments received in this sink app 93 | */ 94 | uint64_t GetTotalRxFragments () const; 95 | 96 | /** 97 | * \return the total bursts received in this sink app 98 | */ 99 | uint64_t GetTotalRxBursts () const; 100 | 101 | /** 102 | * \return pointer to listening socket 103 | */ 104 | Ptr GetListeningSocket (void) const; 105 | 106 | /** 107 | * \return list of pointers to accepted sockets 108 | */ 109 | std::list> GetAcceptedSockets (void) const; 110 | 111 | /** 112 | * TracedCallback signature for a reception with addresses and SeqTsSizeFragHeader 113 | * 114 | * \param f The fragment received (without the SeqTsSize header) 115 | * \param from From address 116 | * \param to Local address 117 | * \param header The SeqTsSize header 118 | */ 119 | typedef void (*SeqTsSizeFragCallback) (Ptr f, const Address &from, 120 | const Address &to, const SeqTsSizeFragHeader &header); 121 | 122 | protected: 123 | virtual void DoDispose (void); 124 | 125 | private: 126 | // inherited from Application base class. 127 | virtual void StartApplication (void); // Called at time specified by Start 128 | virtual void StopApplication (void); // Called at time specified by Stop 129 | 130 | /** 131 | * \brief Handle a fragment received by the application 132 | * \param socket the receiving socket 133 | */ 134 | void HandleRead (Ptr socket); 135 | /** 136 | * \brief Handle an incoming connection 137 | * \param socket the incoming connection socket 138 | * \param from the address the connection is from 139 | */ 140 | void HandleAccept (Ptr socket, const Address &from); 141 | /** 142 | * \brief Handle a connection close 143 | * \param socket the connected socket 144 | */ 145 | void HandlePeerClose (Ptr socket); 146 | /** 147 | * \brief Handle a connection error 148 | * \param socket the connected socket 149 | */ 150 | void HandlePeerError (Ptr socket); 151 | 152 | /** 153 | * \brief Simple burst handler 154 | * Contains information regarding the current burst sequence number 155 | */ 156 | struct BurstHandler 157 | { 158 | uint64_t m_currentBurstSeq{0}; //!< Current burst sequence number 159 | uint16_t m_fragmentsMerged{0}; //!< Number of ordered fragments received and merged for the current burst 160 | std::map> m_unorderedFragments; //!< The fragments received out-of-order, still to be merged 161 | Ptr m_burstBuffer{Create (0)}; //!< The buffer containing the ordered received fragments 162 | }; 163 | 164 | /** 165 | * \brief Fragment received: assemble byte stream to extract SeqTsSizeFragHeader 166 | * \param f received fragment 167 | * \param from from address 168 | * \param localAddress local address 169 | * 170 | * The method assembles a received byte stream and extracts SeqTsSizeFragHeader 171 | * instances from the stream to export in a trace source. 172 | */ 173 | void FragmentReceived (BurstHandler &burstHandler, const Ptr &f, const Address &from, 174 | const Address &localAddress); 175 | 176 | /** 177 | * \brief Hashing for the Address class 178 | * Needed to make Address the key of a map. 179 | */ 180 | struct AddressHash 181 | { 182 | /** 183 | * \brief operator () 184 | * \param x the address of which calculate the hash 185 | * \return the hash of x 186 | * 187 | * Should this method go in address.h? 188 | * 189 | * It calculates the hash taking the uint32_t hash value of the ipv4 address. 190 | * It works only for InetSocketAddresses (Ipv4 version) 191 | */ 192 | size_t 193 | operator() (const Address &x) const 194 | { 195 | NS_ABORT_IF (!InetSocketAddress::IsMatchingType (x)); 196 | InetSocketAddress a = InetSocketAddress::ConvertFrom (x); 197 | return std::hash () (a.GetIpv4 ().Get ()); 198 | } 199 | }; 200 | 201 | std::unordered_map m_burstHandlerMap; //!< Map of BurstHandlers, assuming a user only has one data stream 202 | 203 | // In the case of TCP, each socket accept returns a new socket, so the 204 | // listening socket is stored separately from the accepted sockets 205 | Ptr m_socket{0}; //!< Listening socket 206 | std::list> m_socketList; //!< the accepted sockets 207 | Address m_local; //!< Local address to bind to 208 | TypeId m_tid; //!< Protocol TypeId 209 | uint64_t m_totRxBursts{0}; //!< Total bursts received 210 | uint64_t m_totRxFragments{0}; //!< Total fragments received 211 | uint64_t m_totRxBytes{0}; //!< Total bytes received 212 | 213 | // Traced Callback 214 | /// Callback for tracing the fragment Rx events, includes source, destination addresses, and headers 215 | TracedCallback, const Address &, const Address &, const SeqTsSizeFragHeader &> 216 | m_rxFragmentTrace; 217 | /// Callbacks for tracing the burst Rx events, includes source, destination addresses, and headers 218 | TracedCallback, const Address &, const Address &, const SeqTsSizeFragHeader &> 219 | m_rxBurstTrace; 220 | }; 221 | 222 | } // namespace ns3 223 | 224 | #endif /* BURST_SINK_H */ 225 | -------------------------------------------------------------------------------- /model/bursty-application.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | // 3 | // Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | // University of Padova 5 | // 6 | // This program is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License version 2 as 8 | // published by the Free Software Foundation; 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | // 19 | 20 | #include "ns3/log.h" 21 | #include "ns3/address.h" 22 | #include "ns3/inet-socket-address.h" 23 | #include "ns3/inet6-socket-address.h" 24 | #include "ns3/packet-socket-address.h" 25 | #include "ns3/node.h" 26 | #include "ns3/nstime.h" 27 | #include "ns3/data-rate.h" 28 | #include "ns3/random-variable-stream.h" 29 | #include "ns3/socket.h" 30 | #include "ns3/simulator.h" 31 | #include "ns3/socket-factory.h" 32 | #include "ns3/packet.h" 33 | #include "ns3/uinteger.h" 34 | #include "ns3/trace-source-accessor.h" 35 | #include "ns3/udp-socket-factory.h" 36 | #include "ns3/pointer.h" 37 | #include "ns3/boolean.h" 38 | #include "ns3/burst-generator.h" 39 | #include "bursty-application.h" 40 | 41 | namespace ns3 { 42 | 43 | NS_LOG_COMPONENT_DEFINE ("BurstyApplication"); 44 | 45 | NS_OBJECT_ENSURE_REGISTERED (BurstyApplication); 46 | 47 | TypeId 48 | BurstyApplication::GetTypeId (void) 49 | { 50 | static TypeId tid = TypeId ("ns3::BurstyApplication") 51 | .SetParent () 52 | .SetGroupName ("Applications") 53 | .AddConstructor () 54 | .AddAttribute ("FragmentSize", "The size of packets sent in a burst including SeqTsSizeFragHeader", 55 | UintegerValue (1200), 56 | MakeUintegerAccessor (&BurstyApplication::m_fragSize), 57 | MakeUintegerChecker (1)) 58 | .AddAttribute ("Remote", "The address of the destination", 59 | AddressValue (), 60 | MakeAddressAccessor (&BurstyApplication::m_peer), 61 | MakeAddressChecker ()) 62 | .AddAttribute ("Local", 63 | "The Address on which to bind the socket. If not set, it is generated automatically.", 64 | AddressValue (), 65 | MakeAddressAccessor (&BurstyApplication::m_local), 66 | MakeAddressChecker ()) 67 | .AddAttribute ("BurstGenerator", "The BurstGenerator used by this application", 68 | PointerValue (0), 69 | MakePointerAccessor (&BurstyApplication::m_burstGenerator), 70 | MakePointerChecker ()) 71 | .AddAttribute ("Protocol", "The type of protocol to use. This should be " 72 | "a subclass of ns3::SocketFactory", 73 | TypeIdValue (UdpSocketFactory::GetTypeId ()), 74 | MakeTypeIdAccessor (&BurstyApplication::m_socketTid), 75 | MakeTypeIdChecker ()) 76 | .AddTraceSource ("FragmentTx", "A fragment of the burst is sent", 77 | MakeTraceSourceAccessor (&BurstyApplication::m_txFragmentTrace), 78 | "ns3::BurstSink::SeqTsSizeFragCallback") 79 | .AddTraceSource ("BurstTx", "A burst of packet is created and sent", 80 | MakeTraceSourceAccessor (&BurstyApplication::m_txBurstTrace), 81 | "ns3::BurstSink::SeqTsSizeFragCallback") 82 | ; 83 | return tid; 84 | } 85 | 86 | BurstyApplication::BurstyApplication () 87 | : m_socket (0), m_connected (false), m_totTxBursts (0), m_totTxFragments (0), m_totTxBytes (0) 88 | { 89 | NS_LOG_FUNCTION (this); 90 | } 91 | 92 | BurstyApplication::~BurstyApplication () 93 | { 94 | NS_LOG_FUNCTION (this); 95 | } 96 | 97 | Ptr 98 | BurstyApplication::GetSocket (void) const 99 | { 100 | NS_LOG_FUNCTION (this); 101 | return m_socket; 102 | } 103 | 104 | Ptr 105 | BurstyApplication::GetBurstGenerator (void) const 106 | { 107 | return m_burstGenerator; 108 | } 109 | 110 | void 111 | BurstyApplication::DoDispose (void) 112 | { 113 | NS_LOG_FUNCTION (this); 114 | 115 | CancelEvents (); 116 | m_socket = 0; 117 | m_burstGenerator = 0; 118 | 119 | // chain up 120 | Application::DoDispose (); 121 | } 122 | 123 | void 124 | BurstyApplication::StartApplication () 125 | { 126 | NS_LOG_FUNCTION (this); 127 | 128 | // Create the socket if not already 129 | if (!m_socket) 130 | { 131 | m_socket = Socket::CreateSocket (GetNode (), m_socketTid); 132 | int ret = -1; 133 | 134 | if (!m_local.IsInvalid ()) 135 | { 136 | NS_ABORT_MSG_IF ((Inet6SocketAddress::IsMatchingType (m_peer) && 137 | InetSocketAddress::IsMatchingType (m_local)) || 138 | (InetSocketAddress::IsMatchingType (m_peer) && 139 | Inet6SocketAddress::IsMatchingType (m_local)), 140 | "Incompatible peer and local address IP version"); 141 | ret = m_socket->Bind (m_local); 142 | } 143 | else 144 | { 145 | if (Inet6SocketAddress::IsMatchingType (m_peer)) 146 | { 147 | ret = m_socket->Bind6 (); 148 | } 149 | else if (InetSocketAddress::IsMatchingType (m_peer) || 150 | PacketSocketAddress::IsMatchingType (m_peer)) 151 | { 152 | ret = m_socket->Bind (); 153 | } 154 | } 155 | 156 | if (ret == -1) 157 | { 158 | NS_FATAL_ERROR ("Failed to bind socket"); 159 | } 160 | 161 | m_socket->Connect (m_peer); 162 | m_socket->SetAllowBroadcast (true); 163 | m_socket->ShutdownRecv (); 164 | 165 | m_socket->SetConnectCallback (MakeCallback (&BurstyApplication::ConnectionSucceeded, this), 166 | MakeCallback (&BurstyApplication::ConnectionFailed, this)); 167 | } 168 | 169 | // Ensure no pending event 170 | CancelEvents (); 171 | SendBurst (); 172 | } 173 | 174 | void 175 | BurstyApplication::StopApplication () 176 | { 177 | NS_LOG_FUNCTION (this); 178 | 179 | CancelEvents (); 180 | if (m_socket) 181 | { 182 | m_socket->Close (); 183 | } 184 | else 185 | { 186 | NS_LOG_WARN ("BurstyApplication found null socket to close in StopApplication"); 187 | } 188 | } 189 | 190 | void 191 | BurstyApplication::CancelEvents () 192 | { 193 | NS_LOG_FUNCTION (this); 194 | 195 | // Cancel next burst event 196 | Simulator::Cancel (m_nextBurstEvent); 197 | } 198 | 199 | void 200 | BurstyApplication::SendBurst () 201 | { 202 | NS_LOG_FUNCTION (this); 203 | NS_ASSERT (m_nextBurstEvent.IsExpired ()); 204 | 205 | // get burst info 206 | uint32_t burstSize = 0; 207 | Time period; 208 | // packets must be at least as big as the header 209 | while (burstSize < 24) // TODO: find a way to improve this 210 | { 211 | if (!m_burstGenerator->HasNextBurst ()) 212 | { 213 | NS_LOG_LOGIC ("Burst generator has no next burst: stopping application"); 214 | StopApplication (); 215 | return; 216 | } 217 | 218 | std::tie (burstSize, period) = m_burstGenerator->GenerateBurst (); 219 | NS_LOG_DEBUG ("Generated burstSize=" << burstSize << ", period=" << period.As (Time::MS)); 220 | } 221 | 222 | NS_ASSERT_MSG (period.IsPositive (), 223 | "Period must be non-negative, instead found period=" << period.As (Time::S)); 224 | 225 | // send packets for current burst 226 | SendFragmentedBurst (burstSize); 227 | 228 | // schedule next burst 229 | NS_LOG_DEBUG ("Next burst scheduled in " << period.As (Time::S)); 230 | m_nextBurstEvent = Simulator::Schedule (period, &BurstyApplication::SendBurst, this); 231 | } 232 | 233 | void 234 | BurstyApplication::SendFragmentedBurst (uint32_t burstSize) 235 | { 236 | NS_LOG_FUNCTION (this << burstSize); 237 | 238 | // prepare header 239 | SeqTsSizeFragHeader hdrTmp; 240 | 241 | NS_ABORT_MSG_IF (burstSize < hdrTmp.GetSerializedSize (), 242 | burstSize << " < " << hdrTmp.GetSerializedSize ()); 243 | NS_ABORT_MSG_IF (m_fragSize < hdrTmp.GetSerializedSize (), 244 | m_fragSize << " < " << hdrTmp.GetSerializedSize ()); 245 | 246 | // compute number of fragments and sizes 247 | uint32_t numFullFrags = burstSize / m_fragSize; // integer division 248 | uint32_t lastFragSize = burstSize % m_fragSize; // modulo 249 | 250 | uint32_t secondToLastFragSize = 0; 251 | if (numFullFrags > 0) 252 | { 253 | // if there is at least one full fragment, there exist a second-to-last of full size 254 | secondToLastFragSize = m_fragSize; 255 | numFullFrags--; 256 | } 257 | if (secondToLastFragSize > 0 && // there exist a second-to-last fragment 258 | lastFragSize > 0 && // last smaller fragment is needed 259 | lastFragSize < hdrTmp.GetSerializedSize ()) // the last fragment is below the minimum size 260 | { 261 | // reduce second-to-last fragment to make last fragment of minimum size 262 | secondToLastFragSize = m_fragSize + lastFragSize - hdrTmp.GetSerializedSize (); 263 | lastFragSize = hdrTmp.GetSerializedSize (); // TODO packet with no payload: might be a problem 264 | } 265 | NS_ABORT_MSG_IF (0 < secondToLastFragSize && secondToLastFragSize < hdrTmp.GetSerializedSize (), 266 | secondToLastFragSize << " < " << hdrTmp.GetSerializedSize ()); 267 | NS_ABORT_MSG_IF (0 < lastFragSize && lastFragSize < hdrTmp.GetSerializedSize (), 268 | lastFragSize << " < " << hdrTmp.GetSerializedSize ()); 269 | 270 | // total number of fragments 271 | uint32_t totFrags = numFullFrags; 272 | if (secondToLastFragSize > 0) 273 | { 274 | totFrags++; 275 | } 276 | if (lastFragSize > 0) 277 | { 278 | totFrags++; 279 | } 280 | uint64_t burstPayload = burstSize - (hdrTmp.GetSerializedSize () * totFrags); 281 | uint64_t fullFragmentPayload = m_fragSize - hdrTmp.GetSerializedSize (); 282 | NS_LOG_DEBUG ("Current burst size: " << burstSize << " B: " << totFrags 283 | << " fragments with total payload " << burstPayload << " B. " 284 | << "Sending fragments: " << numFullFrags << " x " 285 | << m_fragSize << "B, + " << secondToLastFragSize << " B + " 286 | << lastFragSize << " B"); 287 | 288 | Ptr burst = Create (burstPayload); 289 | // Trace before adding header, for consistency with BurstSink 290 | Address from, to; 291 | m_socket->GetSockName (from); 292 | m_socket->GetPeerName (to); 293 | 294 | // TODO improve 295 | hdrTmp.SetSeq (m_totTxBursts); 296 | hdrTmp.SetSize (burstPayload); 297 | hdrTmp.SetFrags (totFrags); 298 | hdrTmp.SetFragSeq (0); 299 | 300 | m_txBurstTrace (burst, from, to, hdrTmp); 301 | 302 | uint64_t fragmentStart = 0; 303 | uint16_t fragmentSeq = 0; 304 | for (uint32_t i = 0; i < numFullFrags; i++) 305 | { 306 | Ptr fragment = burst->CreateFragment (fragmentStart, fullFragmentPayload); 307 | fragmentStart += fullFragmentPayload; 308 | SendFragment (fragment, burstPayload, totFrags, fragmentSeq++); 309 | } 310 | 311 | if (secondToLastFragSize > 0) 312 | { 313 | uint64_t secondToLastFragPayload = secondToLastFragSize - hdrTmp.GetSerializedSize (); 314 | Ptr fragment = burst->CreateFragment (fragmentStart, secondToLastFragPayload); 315 | fragmentStart += secondToLastFragPayload; 316 | SendFragment (fragment, burstPayload, totFrags, fragmentSeq++); 317 | } 318 | 319 | if (lastFragSize > 0) 320 | { 321 | uint64_t lastFragPayload = lastFragSize - hdrTmp.GetSerializedSize (); 322 | Ptr fragment = burst->CreateFragment (fragmentStart, lastFragPayload); 323 | fragmentStart += lastFragPayload; 324 | SendFragment (fragment, burstPayload, totFrags, fragmentSeq++); 325 | } 326 | 327 | NS_ASSERT (fragmentStart == burst->GetSize ()); 328 | 329 | m_totTxBursts++; 330 | } 331 | 332 | void 333 | BurstyApplication::SendFragment (Ptr fragment, uint64_t burstSize, uint16_t totFrags, 334 | uint16_t fragmentSeq) 335 | { 336 | NS_LOG_FUNCTION (this << fragment << burstSize << totFrags << fragmentSeq); 337 | 338 | SeqTsSizeFragHeader header; 339 | header.SetSeq (m_totTxBursts); 340 | header.SetSize (burstSize); 341 | header.SetFrags (totFrags); 342 | header.SetFragSeq (fragmentSeq); 343 | fragment->AddHeader (header); 344 | 345 | uint32_t fragmentSize = fragment->GetSize (); 346 | int actual = m_socket->Send (fragment); 347 | if (uint32_t (actual) == fragmentSize) 348 | { 349 | Address from, to; 350 | m_socket->GetSockName (from); 351 | m_socket->GetPeerName (to); 352 | 353 | m_txFragmentTrace (fragment, from, to, 354 | header); // TODO should fragment already include header in trace? 355 | m_totTxFragments++; 356 | m_totTxBytes += fragmentSize; 357 | 358 | std::stringstream addressStr; 359 | if (InetSocketAddress::IsMatchingType (m_peer)) 360 | { 361 | addressStr << InetSocketAddress::ConvertFrom (m_peer).GetIpv4 () << " port " 362 | << InetSocketAddress::ConvertFrom (m_peer).GetPort (); 363 | } 364 | else if (Inet6SocketAddress::IsMatchingType (m_peer)) 365 | { 366 | addressStr << Inet6SocketAddress::ConvertFrom (m_peer).GetIpv6 () << " port " 367 | << Inet6SocketAddress::ConvertFrom (m_peer).GetPort (); 368 | } 369 | else 370 | { 371 | addressStr << "UNKNOWN ADDRESS TYPE"; 372 | } 373 | 374 | NS_LOG_INFO ("At time " << Simulator::Now ().As (Time::S) 375 | << " bursty application sent fragment of " << fragment->GetSize () 376 | << " bytes to " << addressStr.str () << " with header=" << header); 377 | } 378 | else 379 | { 380 | NS_LOG_DEBUG ("Unable to send fragment: fragment size=" << fragment->GetSize () 381 | << ", socket sent=" << actual 382 | << "; ignoring unexpected behavior"); 383 | } 384 | } 385 | 386 | void 387 | BurstyApplication::ConnectionSucceeded (Ptr socket) 388 | { 389 | NS_LOG_FUNCTION (this << socket); 390 | m_connected = true; 391 | } 392 | 393 | void 394 | BurstyApplication::ConnectionFailed (Ptr socket) 395 | { 396 | NS_LOG_FUNCTION (this << socket); 397 | NS_FATAL_ERROR ("Can't connect"); 398 | } 399 | 400 | uint64_t 401 | BurstyApplication::GetTotalTxBursts (void) const 402 | { 403 | return m_totTxBursts; 404 | } 405 | 406 | uint64_t 407 | BurstyApplication::GetTotalTxFragments (void) const 408 | { 409 | return m_totTxFragments; 410 | } 411 | 412 | uint64_t 413 | BurstyApplication::GetTotalTxBytes (void) const 414 | { 415 | return m_totTxBytes; 416 | } 417 | 418 | } // Namespace ns3 419 | -------------------------------------------------------------------------------- /model/bursty-application.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | // 3 | // Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | // University of Padova 5 | // 6 | // This program is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License version 2 as 8 | // published by the Free Software Foundation; 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | // 19 | 20 | #ifndef BURSTY_APPLICATION_H 21 | #define BURSTY_APPLICATION_H 22 | 23 | #include "ns3/address.h" 24 | #include "ns3/application.h" 25 | #include "ns3/event-id.h" 26 | #include "ns3/ptr.h" 27 | #include "ns3/data-rate.h" 28 | #include "ns3/traced-callback.h" 29 | #include "ns3/seq-ts-size-frag-header.h" 30 | 31 | namespace ns3 { 32 | 33 | class Address; 34 | class RandomVariableStream; 35 | class Socket; 36 | class BurstGenerator; 37 | 38 | /** 39 | * \ingroup applications 40 | * \defgroup bursty BurstyApplication 41 | * 42 | * This traffic generator supports large packets to be sent into smaller 43 | * packet (fragment) bursts. 44 | * The fragment size can be chosen arbitrarily, although it usually set 45 | * to match the MTU of the chosen network. 46 | * The burst size and period are controlled by a class extending the 47 | * BurstGenerator interface. 48 | * 49 | */ 50 | /** 51 | * \ingroup bursty 52 | * 53 | * \brief Generate traffic to a single destination in bursty fashion. 54 | * 55 | * This traffic generator supports large packets to be sent into smaller 56 | * packet (fragment) bursts. 57 | * The fragment size can be chosen arbitrarily, although it usually set 58 | * to match the MTU of the chosen network. 59 | * The burst size and period are controlled by a class extending the 60 | * BurstGenerator interface. 61 | * 62 | * This application assumes to operate on top of a UDP socket, sending 63 | * data to a BurstSink. 64 | * These two classes coexist, one fragmenting a large packet into a burst 65 | * of smaller fragments, the other by re-assembling the fragments into 66 | * the full packet. 67 | * 68 | * Fragments have all the same length, which can be set via its attribute. 69 | * The last two segments of the burst might be shorter: the last one 70 | * because it represents the remainder of the burst size with respect to 71 | * the maximum frame size, the second to last because packets cannot be 72 | * smaller that the SeqTsSizeFragHeader size. If the last fragment is 73 | * too short, the second to last fragment is shortened in order to 74 | * increase the size of the last fragment. 75 | * Also, if a BurstGenerator generates a burst of size less than the 76 | * SeqTsSizeFragHeader size, the burst is discarded and a new burst is 77 | * queried to the generator. 78 | * 79 | */ 80 | class BurstyApplication : public Application 81 | { 82 | public: 83 | /** 84 | * \brief Get the type ID. 85 | * \return the object TypeId 86 | */ 87 | static TypeId GetTypeId (void); 88 | 89 | BurstyApplication (); 90 | 91 | virtual ~BurstyApplication (); 92 | 93 | /** 94 | * \brief Return a pointer to associated socket. 95 | * \return pointer to associated socket 96 | */ 97 | Ptr GetSocket (void) const; 98 | 99 | /** 100 | * \brief Returns a pointer to the associated BurstGenerator 101 | * \return pointer to associated BurstGenerator 102 | */ 103 | Ptr GetBurstGenerator (void) const; 104 | 105 | /** 106 | * \brief Return the total number of transmitted bursts. 107 | * \return number of transmitted bursts 108 | */ 109 | uint64_t GetTotalTxBursts (void) const; 110 | 111 | /** 112 | * \brief Return the total number of transmitted fragments. 113 | * \return number of transmitted fragments 114 | */ 115 | uint64_t GetTotalTxFragments (void) const; 116 | 117 | /** 118 | * \brief Return the total number of transmitted bytes. 119 | * \return number of transmitted bytes 120 | */ 121 | uint64_t GetTotalTxBytes (void) const; 122 | 123 | protected: 124 | virtual void DoDispose (void); 125 | 126 | private: 127 | // inherited from Application base class. 128 | virtual void StartApplication (void); // Called at time specified by Start 129 | virtual void StopApplication (void); // Called at time specified by Stop 130 | 131 | //helpers 132 | /** 133 | * \brief Cancel all pending events. 134 | */ 135 | void CancelEvents (); 136 | 137 | // Event handlers 138 | /** 139 | * \brief Sends a packet burst and schedules the next one 140 | */ 141 | void SendBurst (); 142 | 143 | /** 144 | * \brief Send burst fragmented into multiple packets 145 | * \param burstSize the size of the burst in Bytes 146 | */ 147 | void SendFragmentedBurst (uint32_t burstSize); 148 | 149 | /** 150 | * \brief Send a single fragment 151 | * \param fragment the fragment to send 152 | * \param burstSize size of the entire burst in bytes 153 | * \param totFrags the number of fragments composing the burst 154 | * \param fragmentSeq the sequence number of the fragment 155 | */ 156 | void SendFragment (Ptr fragment, uint64_t burstSize, uint16_t totFrags, 157 | uint16_t fragmentSeq); 158 | 159 | /** 160 | * \brief Handle a Connection Succeed event 161 | * \param socket the connected socket 162 | */ 163 | void ConnectionSucceeded (Ptr socket); 164 | 165 | /** 166 | * \brief Handle a Connection Failed event 167 | * \param socket the not connected socket 168 | */ 169 | void ConnectionFailed (Ptr socket); 170 | 171 | Ptr m_socket; //!< Associated socket 172 | Address m_peer; //!< Peer address 173 | Address m_local; //!< Local address to bind to 174 | bool m_connected; //!< True if connected 175 | Ptr m_burstGenerator; //!< Burst generator class 176 | uint32_t m_fragSize; //!< Size of fragments including SeqTsSizeFragHeader 177 | EventId m_nextBurstEvent; //!< Event id for the next packet burst 178 | TypeId m_socketTid; //!< Type of the socket used 179 | uint64_t m_totTxBursts; //!< Total bursts sent 180 | uint64_t m_totTxFragments; //!< Total fragments sent 181 | uint64_t m_totTxBytes; //!< Total bytes sent 182 | 183 | // Traced Callbacks 184 | /// Callback for transmitted burst 185 | TracedCallback, const Address &, const Address &, const SeqTsSizeFragHeader &> 186 | m_txBurstTrace; 187 | /// Callback for transmitted fragment 188 | TracedCallback, const Address &, const Address &, const SeqTsSizeFragHeader &> 189 | m_txFragmentTrace; 190 | }; 191 | 192 | } // namespace ns3 193 | 194 | #endif /* BURSTY_APPLICATION_H */ 195 | -------------------------------------------------------------------------------- /model/my-random-variable-stream.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | #include "my-random-variable-stream.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include // upper_bound 35 | 36 | namespace ns3 { 37 | 38 | NS_LOG_COMPONENT_DEFINE ("MyRandomVariableStream"); 39 | 40 | NS_OBJECT_ENSURE_REGISTERED (LogisticRandomVariable); 41 | 42 | const double LogisticRandomVariable::INFINITE_VALUE = 1e307; 43 | 44 | TypeId 45 | LogisticRandomVariable::GetTypeId (void) 46 | { 47 | static TypeId tid = 48 | TypeId ("ns3::LogisticRandomVariable") 49 | .SetParent () 50 | .SetGroupName ("Core") 51 | .AddConstructor () 52 | .AddAttribute ("Location", "The location value for the logistic distribution returned by this RNG stream.", 53 | DoubleValue (0.0), 54 | MakeDoubleAccessor (&LogisticRandomVariable::m_location), 55 | MakeDoubleChecker ()) 56 | .AddAttribute ("Scale", "The scale value for the logistic distribution returned by this RNG stream.", 57 | DoubleValue (1.0), 58 | MakeDoubleAccessor (&LogisticRandomVariable::m_scale), 59 | MakeDoubleChecker ()) 60 | .AddAttribute ("Bound", "The bound on the values returned by this RNG stream.", 61 | DoubleValue (INFINITE_VALUE), 62 | MakeDoubleAccessor (&LogisticRandomVariable::m_bound), 63 | MakeDoubleChecker ()); 64 | return tid; 65 | } 66 | LogisticRandomVariable::LogisticRandomVariable () 67 | { 68 | // m_location, m_scale, and m_bound are initialized after constructor 69 | // by attributes 70 | NS_LOG_FUNCTION (this); 71 | } 72 | 73 | double 74 | LogisticRandomVariable::GetLocation (void) const 75 | { 76 | NS_LOG_FUNCTION (this); 77 | return m_location; 78 | } 79 | double 80 | LogisticRandomVariable::GetScale (void) const 81 | { 82 | NS_LOG_FUNCTION (this); 83 | return m_scale; 84 | } 85 | double 86 | LogisticRandomVariable::GetBound (void) const 87 | { 88 | NS_LOG_FUNCTION (this); 89 | return m_bound; 90 | } 91 | 92 | double 93 | LogisticRandomVariable::GetValue (double location, double scale, double bound) 94 | { 95 | NS_LOG_FUNCTION (this << location << scale << bound); 96 | 97 | while (1) 98 | { 99 | // Get a uniform random variable in [0,1]. 100 | double v = Peek ()->RandU01 (); 101 | if (IsAntithetic ()) 102 | { 103 | v = (1 - v); 104 | } 105 | 106 | // Calculate the logistic random variable. 107 | double x = location + scale * std::log (v / (1 - v)); 108 | 109 | // Use this value if it's acceptable. 110 | if (std::fabs (x - m_location) <= bound) 111 | { 112 | return x; 113 | } 114 | } 115 | } 116 | 117 | uint32_t 118 | LogisticRandomVariable::GetInteger (uint32_t location, uint32_t scale, uint32_t bound) 119 | { 120 | NS_LOG_FUNCTION (this << location << scale << bound); 121 | return static_cast (GetValue (location, scale, bound)); 122 | } 123 | 124 | double 125 | LogisticRandomVariable::GetValue (void) 126 | { 127 | NS_LOG_FUNCTION (this); 128 | return GetValue (m_location, m_scale, m_bound); 129 | } 130 | uint32_t 131 | LogisticRandomVariable::GetInteger (void) 132 | { 133 | NS_LOG_FUNCTION (this); 134 | return (uint32_t) GetValue (m_location, m_scale, m_bound); 135 | } 136 | 137 | NS_OBJECT_ENSURE_REGISTERED (MixtureRandomVariable); 138 | 139 | TypeId 140 | MixtureRandomVariable::GetTypeId (void) 141 | { 142 | static TypeId tid = TypeId ("ns3::MixtureRandomVariable") 143 | .SetParent () 144 | .SetGroupName ("Core") 145 | .AddConstructor (); 146 | return tid; 147 | } 148 | 149 | MixtureRandomVariable::MixtureRandomVariable (void) 150 | { 151 | NS_LOG_FUNCTION (this); 152 | } 153 | 154 | MixtureRandomVariable::~MixtureRandomVariable (void) 155 | { 156 | NS_LOG_FUNCTION (this); 157 | m_wCdf = 0; 158 | m_rvs.clear (); 159 | } 160 | 161 | void 162 | MixtureRandomVariable::SetRvs (std::vector weightsCdf, 163 | std::vector> rvs) 164 | { 165 | NS_LOG_FUNCTION (this); 166 | NS_ABORT_MSG_IF (weightsCdf.size () != rvs.size (), 167 | "CDF of weights and random variables must have the same size"); 168 | 169 | m_rvs = rvs; 170 | 171 | // create empirical random variable to ease the extraction of m_rvs 172 | m_wCdf = 173 | CreateObjectWithAttributes ("Interpolate", BooleanValue (false)); 174 | for (uint32_t i = 0; i < weightsCdf.size (); i++) 175 | { 176 | m_wCdf->CDF (i, weightsCdf[i]); 177 | } 178 | } 179 | 180 | uint32_t 181 | MixtureRandomVariable::GetInteger (void) 182 | { 183 | NS_LOG_FUNCTION (this); 184 | return static_cast (GetValue ()); 185 | } 186 | 187 | double 188 | MixtureRandomVariable::GetValue (void) 189 | { 190 | NS_LOG_FUNCTION (this); 191 | 192 | uint32_t rvIdx = m_wCdf->GetInteger (); 193 | double value = m_rvs[rvIdx]->GetValue (); 194 | 195 | return value; 196 | } 197 | 198 | } // namespace ns3 199 | -------------------------------------------------------------------------------- /model/my-random-variable-stream.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | #ifndef MY_RANDOM_VARIABLE_STREAM_H 21 | #define MY_RANDOM_VARIABLE_STREAM_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace ns3 { 30 | /** 31 | * \ingroup randomvariable 32 | * \brief The logistic distribution Random Number Generator (RNG). 33 | * 34 | * This class supports the creation of objects that return random numbers 35 | * from a fixed logistic distribution. 36 | * 37 | * The density probability function is defined over the interval (\f$-\infty\f$,\f$+\infty\f$) 38 | * as: \f$ \frac{e^{-(x-\mu)/s}}{s(1 + e^{-(x-\mu)/s})} \f$ 39 | * where \f$ location = \mu \f$ and \f$ scale = s \f$ 40 | * 41 | * Since logistic distributions can theoretically return unbounded 42 | * values, it is sometimes useful to specify a fixed bound. The 43 | * LogisticRandomVariable is bounded symmetrically about the mean (location) by 44 | * this bound, i.e. its values are confined to the interval 45 | * [\f$mean-bound\f$,\f$mean+bound\f$]. 46 | * 47 | * Here is an example of how to use this class: 48 | * \code 49 | * double location = 5.0; 50 | * double scale = 2.0; 51 | * 52 | * Ptr x = CreateObject (); 53 | * x->SetAttribute ("Location", DoubleValue (location)); 54 | * x->SetAttribute ("Scale", DoubleValue (scale)); 55 | * 56 | * // The expected value for the mean of the values returned by a 57 | * // logistic distributed random variable is equal to location. 58 | * double value = x->GetValue (); 59 | * \endcode 60 | */ 61 | class LogisticRandomVariable : public RandomVariableStream 62 | { 63 | public: 64 | /** Large constant to bound the range. */ 65 | static const double INFINITE_VALUE; 66 | 67 | /** 68 | * \brief Register this type. 69 | * \return The object TypeId. 70 | */ 71 | static TypeId GetTypeId (void); 72 | 73 | /** 74 | * \brief Creates a laplace distribution RNG with the default 75 | * values for the location and scale. 76 | */ 77 | LogisticRandomVariable (); 78 | 79 | /** 80 | * Get the location parameter of the distribution 81 | * \return the location parameter 82 | */ 83 | double GetLocation (void) const; 84 | 85 | /** 86 | * Get the scale parameter of the distribution 87 | * \return the scale parameter 88 | */ 89 | double GetScale (void) const; 90 | 91 | /** 92 | * \brief Returns the bound on values that can be returned by this RNG stream. 93 | * \return The bound on values that can be returned by this RNG stream. 94 | */ 95 | double GetBound (void) const; 96 | 97 | /** 98 | * \brief Get the next random value, as a double within the specified bound 99 | * \f$[location - bound, location + max]\f$. 100 | * 101 | * \param location the location of the logistic random variable 102 | * \param scale the scale of the logistic random variable 103 | * \param bound the bound of the logistic random variable 104 | * \return A floating point random value. 105 | */ 106 | double GetValue (double location, double scale, 107 | double bound = LogisticRandomVariable::INFINITE_VALUE); 108 | 109 | /** 110 | * \brief Get the next random value, as an unsigned integer within the specified bound 111 | * \f$[location - bound, location + max]\f$. 112 | * 113 | * \param location the location of the logistic random variable 114 | * \param scale the scale of the logistic random variable 115 | * \param bound the bound of the logistic random variable 116 | * \return A random unsigned integer value. 117 | */ 118 | uint32_t GetInteger (uint32_t location, uint32_t scale, uint32_t bound); 119 | 120 | // Inherited from RandomVariableStream 121 | /** 122 | * \brief Get the next random value as a double drawn from the distribution. 123 | * \return A floating point random value. 124 | */ 125 | virtual double GetValue (void) override; 126 | /** 127 | * \brief Get the next random value as an unsigned integer drawn from the distribution. 128 | * \return A random unsigned integer value. 129 | */ 130 | virtual uint32_t GetInteger (void) override; 131 | 132 | private: 133 | double m_location; //!< The location value of the logistic distribution. 134 | double m_scale; //!< The scale of the logistic distribution. 135 | double m_bound; //!< The bound on values that can be returned by this RNG stream. 136 | 137 | }; // class LogisticRandomVariable 138 | 139 | /** 140 | * \ingroup randomvariable 141 | * \brief The mixture Random Number Generator (RNG). 142 | * 143 | * A mixture distribution is the probability distribution of a random 144 | * variable that is derived from a collection of other random variables 145 | * as follows: first, a random variable is selected by chance from the 146 | * collection according to given probabilities of selection, and then 147 | * the value of the selected random variable is realized. 148 | * 149 | * Here is an example of how to use this class: 150 | * \code 151 | * // setup weights cdf 152 | * std::vector weightsCdf {0.7, 1.0}; // p1 = 0.7, p2 = 0.3 153 | * // setup random variables 154 | * std::vector > rvs; 155 | * rvs.push_back (CreateObjectWithAttributes ("Mean", DoubleValue (5), "Variance", DoubleValue (1))); 156 | * rvs.push_back (CreateObjectWithAttributes ("Mean", DoubleValue (10), "Variance", DoubleValue (4))); 157 | * 158 | * Ptr x = CreateObject (); 159 | * x->SetRvs (weightsCdf, rvs); 160 | * double value = x->GetValue (); 161 | * \endcode 162 | */ 163 | class MixtureRandomVariable : public RandomVariableStream 164 | { 165 | public: 166 | /** 167 | * \brief Register this type. 168 | * \return The object TypeId. 169 | */ 170 | static TypeId GetTypeId (void); 171 | 172 | /** 173 | * \brief Creates an empty mixture distribution RNG 174 | */ 175 | MixtureRandomVariable (); 176 | ~MixtureRandomVariable (); 177 | 178 | /** 179 | * Set the random variables and their respective probabilities as weights of a CDF. 180 | * Check the documentation of EmpiricalRandomVariable for more information regarding weightsCdf. 181 | * 182 | * \param weightsCdf the cumulative distribution function of the mixture of random variables 183 | * \param rvs the RandomVariableStreams to draw from 184 | */ 185 | void SetRvs (std::vector weightsCdf, std::vector > rvs); 186 | 187 | // Inherited from RandomVariableStream 188 | /** 189 | * \brief Get the next random value as a double drawn from the distribution. 190 | * \return A floating point random value. 191 | */ 192 | virtual double GetValue (void) override; 193 | /** 194 | * \brief Get the next random value as an unsigned integer drawn from the distribution. 195 | * \return A random unsigned integer value. 196 | */ 197 | virtual uint32_t GetInteger (void) override; 198 | 199 | private: 200 | Ptr m_wCdf{0}; //!< The random variable that extracts the index of one of the RandomVariablStreams 201 | std::vector> m_rvs; //!< The vector of RandomVariableStreams to draw from 202 | 203 | }; // class MixtureRandomVariable 204 | 205 | } // namespace ns3 206 | 207 | #endif /* MY_RANDOM_VARIABLE_STREAM_H */ 208 | -------------------------------------------------------------------------------- /model/seq-ts-size-frag-header.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | */ 20 | 21 | #include "ns3/log.h" 22 | #include "seq-ts-size-frag-header.h" 23 | 24 | namespace ns3 { 25 | 26 | NS_LOG_COMPONENT_DEFINE ("SeqTsSizeFragHeader"); 27 | 28 | NS_OBJECT_ENSURE_REGISTERED (SeqTsSizeFragHeader); 29 | 30 | SeqTsSizeFragHeader::SeqTsSizeFragHeader () : SeqTsSizeHeader () 31 | { 32 | NS_LOG_FUNCTION (this); 33 | } 34 | 35 | TypeId 36 | SeqTsSizeFragHeader::GetTypeId (void) 37 | { 38 | static TypeId tid = TypeId ("ns3::SeqTsSizeFragHeader") 39 | .SetParent () 40 | .SetGroupName ("Applications") 41 | .AddConstructor (); 42 | return tid; 43 | } 44 | 45 | TypeId 46 | SeqTsSizeFragHeader::GetInstanceTypeId (void) const 47 | { 48 | return GetTypeId (); 49 | } 50 | 51 | void 52 | SeqTsSizeFragHeader::SetFragSeq (uint16_t fragSeq) 53 | { 54 | m_fragSeq = fragSeq; 55 | } 56 | 57 | uint16_t 58 | SeqTsSizeFragHeader::GetFragSeq (void) const 59 | { 60 | return m_fragSeq; 61 | } 62 | 63 | void 64 | SeqTsSizeFragHeader::SetFrags (uint16_t frags) 65 | { 66 | m_frags = frags; 67 | } 68 | 69 | uint16_t 70 | SeqTsSizeFragHeader::GetFrags (void) const 71 | { 72 | return m_frags; 73 | } 74 | 75 | void 76 | SeqTsSizeFragHeader::Print (std::ostream &os) const 77 | { 78 | NS_LOG_FUNCTION (this << &os); 79 | os << "(fragSeq=" << m_fragSeq << ", frags=" << m_frags << ") AND "; 80 | SeqTsSizeHeader::Print (os); 81 | } 82 | 83 | uint32_t 84 | SeqTsSizeFragHeader::GetSerializedSize (void) const 85 | { 86 | return SeqTsSizeHeader::GetSerializedSize () + 4; 87 | } 88 | 89 | void 90 | SeqTsSizeFragHeader::Serialize (Buffer::Iterator start) const 91 | { 92 | NS_LOG_FUNCTION (this << &start); 93 | Buffer::Iterator i = start; 94 | i.WriteHtonU16 (m_fragSeq); 95 | i.WriteHtonU16 (m_frags); 96 | SeqTsSizeHeader::Serialize (i); 97 | } 98 | 99 | uint32_t 100 | SeqTsSizeFragHeader::Deserialize (Buffer::Iterator start) 101 | { 102 | NS_LOG_FUNCTION (this << &start); 103 | Buffer::Iterator i = start; 104 | m_fragSeq = i.ReadNtohU16 (); 105 | m_frags = i.ReadNtohU16 (); 106 | SeqTsSizeHeader::Deserialize (i); 107 | return GetSerializedSize (); 108 | } 109 | 110 | } // namespace ns3 111 | -------------------------------------------------------------------------------- /model/seq-ts-size-frag-header.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef SEQ_TS_SIZE_FRAG_HEADER_H 21 | #define SEQ_TS_SIZE_FRAG_HEADER_H 22 | 23 | #include 24 | 25 | namespace ns3 { 26 | /** 27 | * \ingroup applications 28 | * \brief Header with a sequence, a timestamp, a size, a fragment sequence and a number of fragments attribute 29 | * 30 | * This header adds a fragment sequence and a number of fragments attribute to the (burst) sequence number, 31 | * the timestamp and the size of class \c SeqTsSizeFragHeader. 32 | * Fragment sequence and number of fragments can be used to track large fragments packets over protocols 33 | * not guaranteeing packet ordering, e.g., BurstyApplication over UDP. 34 | * 35 | * \sa ns3::SeqTsHeader 36 | */ 37 | class SeqTsSizeFragHeader : public SeqTsSizeHeader 38 | { 39 | public: 40 | /** 41 | * \brief Get the type ID. 42 | * \return the object TypeId 43 | */ 44 | static TypeId GetTypeId (void); 45 | 46 | /** 47 | * \brief constructor 48 | */ 49 | SeqTsSizeFragHeader (); 50 | 51 | /** 52 | * \brief Set the sequence number of the fragment 53 | * \param size sequence number of the fragment 54 | */ 55 | void SetFragSeq (uint16_t fragSeq); 56 | 57 | /** 58 | * \brief Get the sequence number of the fragment 59 | * \return the sequence number of the fragment 60 | */ 61 | uint16_t GetFragSeq (void) const; 62 | 63 | /** 64 | * \brief Set the total number fragments in the burst 65 | * \param frags the total number of fragments in the burst 66 | */ 67 | void SetFrags (uint16_t frags); 68 | 69 | /** 70 | * \brief Get the total number of fragments in the burst 71 | * \return the total number of fragments in the burst 72 | */ 73 | uint16_t GetFrags (void) const; 74 | 75 | // Inherited 76 | virtual TypeId GetInstanceTypeId (void) const override; 77 | virtual void Print (std::ostream &os) const override; 78 | virtual uint32_t GetSerializedSize (void) const override; 79 | virtual void Serialize (Buffer::Iterator start) const override; 80 | virtual uint32_t Deserialize (Buffer::Iterator start) override; 81 | 82 | private: 83 | uint16_t m_fragSeq{0}; //!< The sequence number of the fragment 84 | uint16_t m_frags{0}; //!< The total number of fragments in the burst 85 | }; 86 | 87 | } // namespace ns3 88 | 89 | #endif /* SEQ_TS_SIZE_FRAG_HEADER_H */ 90 | -------------------------------------------------------------------------------- /model/simple-burst-generator.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | // 3 | // Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | // University of Padova 5 | // 6 | // This program is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License version 2 as 8 | // published by the Free Software Foundation; 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | // 19 | 20 | #include "ns3/log.h" 21 | #include "ns3/random-variable-stream.h" 22 | #include "ns3/string.h" 23 | #include "ns3/pointer.h" 24 | #include "ns3/nstime.h" 25 | #include "simple-burst-generator.h" 26 | 27 | namespace ns3 { 28 | 29 | NS_LOG_COMPONENT_DEFINE ("SimpleBurstGenerator"); 30 | 31 | NS_OBJECT_ENSURE_REGISTERED (SimpleBurstGenerator); 32 | 33 | TypeId 34 | SimpleBurstGenerator::GetTypeId (void) 35 | { 36 | static TypeId tid = 37 | TypeId ("ns3::SimpleBurstGenerator") 38 | .SetParent () 39 | .SetGroupName ("Applications") 40 | .AddConstructor () 41 | .AddAttribute ("PeriodRv", 42 | "A RandomVariableStream used to pick the duration of the period [s].", 43 | StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"), 44 | MakePointerAccessor (&SimpleBurstGenerator::m_periodRv), 45 | MakePointerChecker ()) 46 | .AddAttribute ("BurstSizeRv", 47 | "A RandomVariableStream used to pick the size of the burst [B].", 48 | StringValue ("ns3::ConstantRandomVariable[Constant=1e6]"), 49 | MakePointerAccessor (&SimpleBurstGenerator::m_burstSizeRv), 50 | MakePointerChecker ()); 51 | return tid; 52 | } 53 | 54 | SimpleBurstGenerator::SimpleBurstGenerator () 55 | { 56 | NS_LOG_FUNCTION (this); 57 | } 58 | 59 | SimpleBurstGenerator::~SimpleBurstGenerator () 60 | { 61 | NS_LOG_FUNCTION (this); 62 | } 63 | 64 | int64_t 65 | SimpleBurstGenerator::AssignStreams (int64_t stream) 66 | { 67 | NS_LOG_FUNCTION (this << stream); 68 | m_periodRv->SetStream (stream); 69 | m_burstSizeRv->SetStream (stream + 1); 70 | return 2; 71 | } 72 | 73 | void 74 | SimpleBurstGenerator::DoDispose (void) 75 | { 76 | NS_LOG_FUNCTION (this); 77 | 78 | m_periodRv = 0; 79 | m_burstSizeRv = 0; 80 | 81 | // chain up 82 | BurstGenerator::DoDispose (); 83 | } 84 | 85 | bool 86 | SimpleBurstGenerator::HasNextBurst (void) 87 | { 88 | NS_LOG_FUNCTION (this); 89 | // this burst generator has no limits on the number of bursts 90 | return true; 91 | } 92 | 93 | std::pair 94 | SimpleBurstGenerator::GenerateBurst () 95 | { 96 | NS_LOG_FUNCTION (this); 97 | 98 | // sample current burst size 99 | // NOTE: limited to 4 GB per burst by GetInteger 100 | uint32_t burstSize = m_burstSizeRv->GetInteger (); 101 | 102 | // sample period before next burst 103 | Time period = Seconds (m_periodRv->GetValue ()); 104 | NS_ABORT_MSG_IF (!period.IsPositive (), 105 | "Period must be non-negative, instead found period=" << period.As (Time::S)); 106 | 107 | NS_LOG_DEBUG ("Burst size: " << burstSize << " B, period: " << period.As (Time::S)); 108 | return std::make_pair (burstSize, period); 109 | } 110 | 111 | } // Namespace ns3 112 | -------------------------------------------------------------------------------- /model/simple-burst-generator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef SIMPLE_BURST_GENERATOR_H 21 | #define SIMPLE_BURST_GENERATOR_H 22 | 23 | #include 24 | 25 | namespace ns3 { 26 | 27 | class RandomVariableStream; 28 | 29 | /** 30 | * \ingroup applications 31 | * 32 | * \brief Simple burst generator 33 | * 34 | * This burst generator implements the BurstGenerator interface. 35 | * While being simple, it allows the user to customize the distributions 36 | * of the burst size and period with independent RandomVariableStreams. 37 | * 38 | */ 39 | class SimpleBurstGenerator : public BurstGenerator 40 | { 41 | public: 42 | SimpleBurstGenerator (); 43 | virtual ~SimpleBurstGenerator (); 44 | 45 | // inherited from Object 46 | static TypeId GetTypeId (); 47 | 48 | // inherited from BurstGenerator 49 | virtual std::pair GenerateBurst (void) override; 50 | /** 51 | * \brief This generator has not limits 52 | * \return always true 53 | */ 54 | virtual bool HasNextBurst (void) override; 55 | 56 | /** 57 | * \brief Assign a fixed random variable stream number to the random variables 58 | * used by this model. 59 | * 60 | * \param stream first stream index to use 61 | * \return the number of stream indices assigned by this model 62 | */ 63 | int64_t AssignStreams (int64_t stream); 64 | 65 | protected: 66 | virtual void DoDispose (void) override; 67 | 68 | private: 69 | Ptr m_periodRv{0}; //!< rng for period duration [s] 70 | Ptr m_burstSizeRv{0}; //!< rng for burst size [B] 71 | }; 72 | 73 | } // namespace ns3 74 | 75 | #endif // SIMPLE_BURST_GENERATOR_H 76 | -------------------------------------------------------------------------------- /model/trace-file-burst-generator.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | // 3 | // 4 | // Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 5 | // University of Padova 6 | // 7 | // This program is free software; you can redistribute it and/or modify 8 | // it under the terms of the GNU General Public License version 2 as 9 | // published by the Free Software Foundation; 10 | // 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | // 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | // 20 | 21 | #include "ns3/log.h" 22 | #include "ns3/random-variable-stream.h" 23 | #include "ns3/string.h" 24 | #include "ns3/double.h" 25 | #include "ns3/nstime.h" 26 | #include "ns3/csv-reader.h" 27 | #include "trace-file-burst-generator.h" 28 | 29 | namespace ns3 { 30 | 31 | NS_LOG_COMPONENT_DEFINE ("TraceFileBurstGenerator"); 32 | 33 | NS_OBJECT_ENSURE_REGISTERED (TraceFileBurstGenerator); 34 | 35 | TypeId 36 | TraceFileBurstGenerator::GetTypeId (void) 37 | { 38 | static TypeId tid = 39 | TypeId ("ns3::TraceFileBurstGenerator") 40 | .SetParent () 41 | .SetGroupName ("Applications") 42 | .AddConstructor () 43 | .AddAttribute ("TraceFile", 44 | "The path to the trace file", 45 | StringValue (""), 46 | MakeStringAccessor (&TraceFileBurstGenerator::GetTraceFile, 47 | &TraceFileBurstGenerator::SetTraceFile), 48 | MakeStringChecker ()) 49 | .AddAttribute ("StartTime", 50 | "The trace will only generate traced traffic after a start time offset [s]", 51 | DoubleValue (0.0), 52 | MakeDoubleAccessor (&TraceFileBurstGenerator::GetStartTime, 53 | &TraceFileBurstGenerator::SetStartTime), 54 | MakeDoubleChecker (0.0)); 55 | return tid; 56 | } 57 | 58 | TraceFileBurstGenerator::TraceFileBurstGenerator () 59 | { 60 | NS_LOG_FUNCTION (this); 61 | } 62 | 63 | TraceFileBurstGenerator::~TraceFileBurstGenerator () 64 | { 65 | NS_LOG_FUNCTION (this); 66 | } 67 | 68 | void 69 | TraceFileBurstGenerator::DoDispose (void) 70 | { 71 | NS_LOG_FUNCTION (this); 72 | 73 | ClearBurstQueue (); 74 | 75 | // chain up 76 | BurstGenerator::DoDispose (); 77 | } 78 | 79 | void 80 | TraceFileBurstGenerator::SetStartTime (double startTime) 81 | { 82 | NS_LOG_FUNCTION (this << startTime); 83 | if (startTime != m_startTime) 84 | { 85 | m_startTime = startTime; 86 | m_isFinalized = false; 87 | } 88 | } 89 | 90 | double 91 | TraceFileBurstGenerator::GetStartTime (void) const 92 | { 93 | return m_startTime; 94 | } 95 | 96 | void 97 | TraceFileBurstGenerator::SetTraceFile (std::string traceFile) 98 | { 99 | NS_LOG_FUNCTION (this << traceFile); 100 | if (traceFile != m_traceFile) 101 | { 102 | m_traceFile = traceFile; 103 | m_isFinalized = false; 104 | } 105 | } 106 | 107 | std::string 108 | TraceFileBurstGenerator::GetTraceFile (void) const 109 | { 110 | return m_traceFile; 111 | } 112 | 113 | double 114 | TraceFileBurstGenerator::GetTraceDuration (void) 115 | { 116 | if (!m_isFinalized) 117 | { 118 | ImportTrace (); 119 | } 120 | 121 | return m_traceDuration; 122 | } 123 | 124 | bool 125 | TraceFileBurstGenerator::HasNextBurst (void) 126 | { 127 | NS_LOG_FUNCTION (this); 128 | if (!m_isFinalized) 129 | { 130 | ImportTrace (); 131 | } 132 | 133 | return !m_burstQueue.empty (); 134 | } 135 | 136 | std::pair 137 | TraceFileBurstGenerator::GenerateBurst () 138 | { 139 | NS_LOG_FUNCTION (this); 140 | if (!m_isFinalized) 141 | { 142 | ImportTrace (); 143 | } 144 | 145 | NS_ABORT_MSG_IF (m_burstQueue.empty (), "All bursts from the trace have already been generated, " 146 | "you should have checked if HasNextBurst"); 147 | 148 | std::pair burst = m_burstQueue.front (); 149 | m_burstQueue.pop (); 150 | NS_LOG_DEBUG ("Generated std::pair(" << burst.first << ", " << burst.second << "); " 151 | << m_burstQueue.size () 152 | << " more bursts excluding the current one"); 153 | return burst; 154 | } 155 | 156 | void 157 | TraceFileBurstGenerator::ClearBurstQueue (void) 158 | { 159 | NS_LOG_FUNCTION (this); 160 | std::queue> empty; 161 | std::swap (m_burstQueue, empty); 162 | } 163 | 164 | void 165 | TraceFileBurstGenerator::ImportTrace (void) 166 | { 167 | NS_LOG_FUNCTION (this); 168 | 169 | // extract trace from file 170 | CsvReader csv (m_traceFile); 171 | 172 | ClearBurstQueue (); 173 | m_traceDuration = 0; 174 | double cumulativeStartTime = 0; 175 | uint32_t burstSize; 176 | double period; 177 | while (csv.FetchNextRow ()) 178 | { 179 | // Ignore blank lines 180 | if (csv.IsBlankRow ()) 181 | { 182 | continue; 183 | } 184 | 185 | // Expecting burst size and period to next burst 186 | bool ok = csv.GetValue (0, burstSize); 187 | ok |= csv.GetValue (1, period); 188 | NS_ABORT_MSG_IF (!ok, "Something went wrong on line " << csv.RowNumber () << " of file " 189 | << m_traceFile); 190 | NS_ABORT_MSG_IF (period < 0, "Period to next burst should be non-negative, instead found: " 191 | << period << " on line " << csv.RowNumber ()); 192 | 193 | // Ignore bursts before m_startTime 194 | if (cumulativeStartTime >= m_startTime) 195 | { 196 | m_burstQueue.push (std::make_pair (burstSize, Seconds (period))); 197 | m_traceDuration += period; 198 | } 199 | cumulativeStartTime += period; 200 | } // while FetchNextRow 201 | 202 | m_isFinalized = true; 203 | NS_LOG_INFO ("Parsed " << m_burstQueue.size () << " bursts from file " << m_traceFile); 204 | } 205 | 206 | } // Namespace ns3 207 | -------------------------------------------------------------------------------- /model/trace-file-burst-generator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef TRACE_FILE_BURST_GENERATOR_H 21 | #define TRACE_FILE_BURST_GENERATOR_H 22 | 23 | #include 24 | #include 25 | 26 | namespace ns3 { 27 | 28 | class Time; 29 | 30 | /** 31 | * \ingroup applications 32 | * 33 | * \brief Reads a traffic trace file to generate bursts 34 | * 35 | * The generator reads a trace file and generates bursts accordingly. 36 | * A trace file should be formatted following the guidelines given 37 | * by the documentation of ns3::CsvReader. 38 | * 39 | * If the same trace file is used by multiple users in the same network, 40 | * the generated bursts can be decoupled by assigning different 41 | * StartTimes to different users, if the trace is long enough with respect 42 | * to the simulation duration. 43 | * 44 | */ 45 | class TraceFileBurstGenerator : public BurstGenerator 46 | { 47 | public: 48 | TraceFileBurstGenerator (); 49 | virtual ~TraceFileBurstGenerator (); 50 | 51 | // inherited from Object 52 | static TypeId GetTypeId (); 53 | 54 | // inherited from BurstGenerator 55 | virtual std::pair GenerateBurst (void) override; 56 | /** 57 | * \brief Returns true while more bursts are present in the trace 58 | * \return false when the end of the trace is reached 59 | */ 60 | virtual bool HasNextBurst (void) override; 61 | 62 | /** 63 | * \brief Returns the duration of the imported trace starting from the StartTime attribute 64 | * \return the duration of the trace 65 | */ 66 | double GetTraceDuration (void); 67 | 68 | protected: 69 | virtual void DoDispose (void) override; 70 | 71 | private: 72 | // Private attribute accessors 73 | void SetStartTime (double startTime); 74 | double GetStartTime (void) const; 75 | 76 | void SetTraceFile (std::string traceFile); 77 | std::string GetTraceFile (void) const; 78 | 79 | /** 80 | * Clears the burst queue 81 | */ 82 | void ClearBurstQueue (void); 83 | 84 | /** 85 | * Import the trace file into the burst queue 86 | */ 87 | void ImportTrace (void); 88 | 89 | std::string m_traceFile{""}; //!< The name of the trace file 90 | double m_startTime{0.0}; //!< The trace will only generate traced traffic after a start time offset 91 | double m_traceDuration{-1.0}; //!< The duration of the trace file considering the start time 92 | bool m_isFinalized{false}; //!< The generator is finalized only once ImportTrace ends with no errors 93 | std::queue> m_burstQueue; //!< The burst information read from the trace 94 | }; 95 | 96 | } // namespace ns3 97 | 98 | #endif // TRACE_FILE_BURST_GENERATOR_H 99 | -------------------------------------------------------------------------------- /model/vr-burst-generator.cc: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | // 3 | // Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | // University of Padova 5 | // 6 | // This program is free software; you can redistribute it and/or modify 7 | // it under the terms of the GNU General Public License version 2 as 8 | // published by the Free Software Foundation; 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program; if not, write to the Free Software 17 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | // 19 | 20 | #include "ns3/log.h" 21 | #include "ns3/random-variable-stream.h" 22 | #include "ns3/double.h" 23 | #include "ns3/data-rate.h" 24 | #include "ns3/enum.h" 25 | #include "ns3/nstime.h" 26 | #include "ns3/object-factory.h" 27 | #include "vr-burst-generator.h" 28 | #include 29 | 30 | namespace ns3 { 31 | 32 | NS_LOG_COMPONENT_DEFINE ("VrBurstGenerator"); 33 | 34 | NS_OBJECT_ENSURE_REGISTERED (VrBurstGenerator); 35 | 36 | TypeId 37 | VrBurstGenerator::GetTypeId (void) 38 | { 39 | static TypeId tid = 40 | TypeId ("ns3::VrBurstGenerator") 41 | .SetParent () 42 | .SetGroupName ("Applications") 43 | .AddConstructor () 44 | .AddAttribute ("FrameRate", 45 | "The frame rate of the VR application [FPS]. " 46 | "Only 30 and 60 FPS are currently supported.", 47 | DoubleValue (60), 48 | MakeDoubleAccessor (&VrBurstGenerator::SetFrameRate, 49 | &VrBurstGenerator::GetFrameRate), 50 | MakeDoubleChecker (0)) 51 | .AddAttribute ("TargetDataRate", 52 | "The target data rate that the VR application will try to achieve.", 53 | DataRateValue (DataRate ("20Mbps")), 54 | MakeDataRateAccessor (&VrBurstGenerator::SetTargetDataRate, 55 | &VrBurstGenerator::GetTargetDataRate), 56 | MakeDataRateChecker ()) 57 | .AddAttribute ("VrAppName", 58 | "The VR application on which the model is based upon. Check the documentation for further information.", 59 | EnumValue (VrAppName::VirusPopper), 60 | MakeEnumAccessor (&VrBurstGenerator::m_appName), 61 | MakeEnumChecker (VrAppName::VirusPopper, "VirusPopper", 62 | VrAppName::Minecraft, "Minecraft", 63 | VrAppName::GoogleEarthVrCities, "GoogleEarthVrCities", 64 | VrAppName::GoogleEarthVrTour, "GoogleEarthVrTour")); 65 | return tid; 66 | } 67 | 68 | VrBurstGenerator::VrBurstGenerator () 69 | { 70 | NS_LOG_FUNCTION (this); 71 | } 72 | 73 | VrBurstGenerator::~VrBurstGenerator () 74 | { 75 | NS_LOG_FUNCTION (this); 76 | } 77 | 78 | int64_t 79 | VrBurstGenerator::AssignStreams (int64_t stream) 80 | { 81 | NS_LOG_FUNCTION (this << stream); 82 | m_periodRv->SetStream (stream); 83 | m_frameSizeRv->SetStream (stream + 1); 84 | return 2; 85 | } 86 | 87 | void 88 | VrBurstGenerator::DoDispose (void) 89 | { 90 | NS_LOG_FUNCTION (this); 91 | 92 | m_periodRv = 0; 93 | m_frameSizeRv = 0; 94 | 95 | // chain up 96 | BurstGenerator::DoDispose (); 97 | } 98 | 99 | void 100 | VrBurstGenerator::SetFrameRate (double frameRate) 101 | { 102 | NS_LOG_FUNCTION (this << frameRate); 103 | 104 | NS_ABORT_MSG_UNLESS (frameRate == 30 || frameRate == 60, 105 | "Frame rate must be either 30 or 60 FPS, instead frameRate=" << frameRate); 106 | m_frameRate = frameRate; 107 | 108 | SetupModel (); 109 | } 110 | 111 | double 112 | VrBurstGenerator::GetFrameRate (void) const 113 | { 114 | return m_frameRate; 115 | } 116 | 117 | void 118 | VrBurstGenerator::SetTargetDataRate (DataRate targetDataRate) 119 | { 120 | NS_LOG_FUNCTION (this << targetDataRate); 121 | 122 | NS_ABORT_MSG_IF (targetDataRate.GetBitRate () <= 0, 123 | "Target data rate must be positive, instead: " << targetDataRate); 124 | m_targetDataRate = targetDataRate; 125 | 126 | SetupModel (); 127 | } 128 | 129 | DataRate 130 | VrBurstGenerator::GetTargetDataRate (void) const 131 | { 132 | return m_targetDataRate; 133 | } 134 | 135 | void 136 | VrBurstGenerator::SetVrAppName (VrBurstGenerator::VrAppName vrAppName) 137 | { 138 | NS_LOG_FUNCTION (this << vrAppName); 139 | 140 | m_appName = vrAppName; 141 | SetupModel (); 142 | } 143 | 144 | VrBurstGenerator::VrAppName 145 | VrBurstGenerator::GetVrAppName (void) const 146 | { 147 | return m_appName; 148 | } 149 | 150 | bool 151 | VrBurstGenerator::HasNextBurst (void) 152 | { 153 | NS_LOG_FUNCTION (this); 154 | // this burst generator has no limits on the number of bursts 155 | return true; 156 | } 157 | 158 | std::pair 159 | VrBurstGenerator::GenerateBurst () 160 | { 161 | NS_LOG_FUNCTION (this); 162 | 163 | // sample current frame size 164 | uint32_t frameSize = m_frameSizeRv->GetInteger (); 165 | 166 | // sample period before next frame 167 | Time period = Seconds (m_periodRv->GetValue ()); 168 | NS_ABORT_MSG_IF (!period.IsPositive (), 169 | "Period must be non-negative, instead found period=" << period.As (Time::S)); 170 | 171 | NS_LOG_DEBUG ("Frame size: " << frameSize << " B, period: " << period.As (Time::S)); 172 | return std::make_pair (frameSize, period); 173 | } 174 | 175 | void 176 | VrBurstGenerator::SetupModel () 177 | { 178 | NS_LOG_FUNCTION (this); 179 | 180 | double alpha{0}; 181 | double beta{0}; 182 | double gamma{0}; 183 | double delta{0}; 184 | double epsilon{0}; 185 | 186 | switch (m_appName) 187 | { 188 | case VrAppName::VirusPopper: 189 | alpha = 0.17843005544386825; 190 | beta = -0.24033549; 191 | if (m_frameRate == 60) 192 | { 193 | gamma = 0.03720502322046791; 194 | } 195 | else if (m_frameRate == 30) 196 | { 197 | delta = 0.014333111298430356; 198 | epsilon = 0.17636808; 199 | } 200 | else 201 | { 202 | NS_ABORT_MSG ("Unexpected frame rate: " << m_frameRate); 203 | } 204 | break; 205 | 206 | case VrAppName::Minecraft: 207 | alpha = 0.18570635904452573; 208 | beta = -0.18721216; 209 | if (m_frameRate == 60) 210 | { 211 | gamma = 0.07132669841811076; 212 | } 213 | else if (m_frameRate == 30) 214 | { 215 | delta = 0.024192743507827373; 216 | epsilon = 0.22666163; 217 | } 218 | else 219 | { 220 | NS_ABORT_MSG ("Unexpected frame rate: " << m_frameRate); 221 | } 222 | break; 223 | 224 | case VrAppName::GoogleEarthVrCities: 225 | alpha = 0.259684566301378; 226 | beta = -0.25390119; 227 | if (m_frameRate == 60) 228 | { 229 | gamma = 0.034571656202610615; 230 | } 231 | else if (m_frameRate == 30) 232 | { 233 | delta = 0.008953037116942649; 234 | epsilon = 0.3119082; 235 | } 236 | else 237 | { 238 | NS_ABORT_MSG ("Unexpected frame rate: " << m_frameRate); 239 | } 240 | break; 241 | 242 | case VrAppName::GoogleEarthVrTour: 243 | alpha = 0.25541435742159037; 244 | beta = -0.20308171; 245 | if (m_frameRate == 60) 246 | { 247 | gamma = 0.03468230656563422; 248 | } 249 | else if (m_frameRate == 30) 250 | { 251 | delta = 0.010559650431826953; 252 | epsilon = 0.27560183; 253 | } 254 | else 255 | { 256 | NS_ABORT_MSG ("Unexpected frame rate: " << m_frameRate); 257 | } 258 | break; 259 | 260 | default: 261 | NS_ABORT_MSG ("m_appName was not recognized"); 262 | break; 263 | } 264 | 265 | double fsAvg = m_targetDataRate.GetBitRate () / 8.0 / m_frameRate; // expected frame size [B] 266 | double ifiAvg = 1.0 / m_frameRate; // expected inter frame interarrival [s] 267 | double targetRate_mbps = m_targetDataRate.GetBitRate () / 1e6; 268 | 269 | // Model frame size stats 270 | double fsDispersion = alpha * std::pow (targetRate_mbps, beta); 271 | double fsScale = fsAvg * fsDispersion; 272 | NS_LOG_DEBUG ("Frame size: loc=" << fsAvg << ", scale=" << fsScale 273 | << " (dispersion=" << fsDispersion << ")"); 274 | 275 | m_frameSizeRv = CreateObjectWithAttributes ("Location", DoubleValue (fsAvg), 276 | "Scale", DoubleValue (fsScale), 277 | "Bound", DoubleValue (fsAvg)); 278 | 279 | // Model IFI stats 280 | double ifiDispersion; 281 | if (m_frameRate == 60) 282 | { 283 | ifiDispersion = gamma; 284 | } 285 | else if (m_frameRate == 30) 286 | { 287 | ifiDispersion = delta * std::pow (targetRate_mbps, epsilon); 288 | } 289 | else 290 | { 291 | NS_ABORT_MSG ("Unexpected frame rate: " << m_frameRate); 292 | } 293 | double ifiScale = ifiAvg * ifiDispersion; 294 | NS_LOG_DEBUG ("IFI: loc=" << ifiAvg << ", scale=" << ifiScale 295 | << " (dispersion=" << ifiDispersion << ")"); 296 | 297 | m_periodRv = CreateObjectWithAttributes ("Location", DoubleValue (ifiAvg), 298 | "Scale", DoubleValue (ifiScale), 299 | "Bound", DoubleValue (ifiAvg)); 300 | } 301 | 302 | } // Namespace ns3 303 | -------------------------------------------------------------------------------- /model/vr-burst-generator.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 | /* 3 | * Copyright (c) 2021 SIGNET Lab, Department of Information Engineering, 4 | * University of Padova 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation; 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef VR_BURST_GENERATOR_H 21 | #define VR_BURST_GENERATOR_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace ns3 { 28 | 29 | /** 30 | * \ingroup applications 31 | * 32 | * \brief VR burst generator 33 | * 34 | * This burst generator creates synthetic traces, aiming to 35 | * emulate the traffic from a Virtual Reality (VR) application. 36 | * 37 | * The user can set a frame rate and the target data rate 38 | * of the application. 39 | * Further details on the model used can be found in the reference 40 | * paper (see README.md). 41 | * 42 | */ 43 | class VrBurstGenerator : public BurstGenerator 44 | { 45 | public: 46 | 47 | /** 48 | * Different VR applications can be choosen. 49 | * Please check the documentation for further information. 50 | */ 51 | enum VrAppName{ 52 | VirusPopper = 0, 53 | Minecraft, 54 | GoogleEarthVrCities, 55 | GoogleEarthVrTour 56 | }; 57 | 58 | VrBurstGenerator (); 59 | virtual ~VrBurstGenerator (); 60 | 61 | // inherited from Object 62 | static TypeId GetTypeId (); 63 | 64 | // inherited from BurstGenerator 65 | virtual std::pair GenerateBurst (void) override; 66 | /** 67 | * \brief This generator has not limits 68 | * \return always true 69 | */ 70 | virtual bool HasNextBurst (void) override; 71 | 72 | /** 73 | * \brief Assign a fixed random variable stream number to the random variables 74 | * used by this model. 75 | * 76 | * \param stream first stream index to use 77 | * \return the number of stream indices assigned by this model 78 | */ 79 | int64_t AssignStreams (int64_t stream); 80 | 81 | // Set/Get app parameters 82 | /** 83 | * Set the frame rate of the VR application 84 | * \param frameRate the frame rate in FPS 85 | */ 86 | void SetFrameRate (double frameRate); 87 | /** 88 | * Get the frame rate of the VR application 89 | * \return the frame rate in FPS 90 | */ 91 | double GetFrameRate (void) const; 92 | 93 | /** 94 | * Set the target data rate of the VR application 95 | * \param targetDataRate the target data rate 96 | */ 97 | void SetTargetDataRate (DataRate targetDataRate); 98 | /** 99 | * Get the target data rate of the VR application 100 | * \return the target data rate 101 | */ 102 | DataRate GetTargetDataRate (void) const; 103 | 104 | /** 105 | * Set the app name of the VR application 106 | * \param vrAppName the app name 107 | */ 108 | void SetVrAppName (VrAppName vrAppName); 109 | /** 110 | * Get the app name of the VR application 111 | * \return the app name 112 | */ 113 | VrAppName GetVrAppName (void) const; 114 | 115 | protected: 116 | virtual void DoDispose (void) override; 117 | 118 | private: 119 | /** 120 | * Setup the random variables generating the burst parameters 121 | * according to the frame rate and the target data rate. 122 | * 123 | * For further information, please check the reference paper (see README.md). 124 | */ 125 | void SetupModel (void); 126 | 127 | double m_frameRate{60}; //!< The frame rate of the VR application [FPS] 128 | DataRate m_targetDataRate{50}; //!< The target data rate of the VR application 129 | VrAppName m_appName{VirusPopper}; //!< The name of the VR application 130 | 131 | Ptr m_periodRv{0}; //!< RNG for period duration [s] 132 | Ptr m_frameSizeRv{0}; //!< RNG for frame size [B] 133 | }; 134 | 135 | } // namespace ns3 136 | 137 | #endif // VR_BURST_GENERATOR_H 138 | --------------------------------------------------------------------------------