From d304d1d81aed679459c451a41e35031f899453d6 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Tue, 11 Dec 2018 18:30:29 +0100 Subject: [PATCH 01/16] Added configuration and make files for sphinx documentation generation --- docs/Makefile | 19 ++++++ docs/conf.py | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/index.rst | 22 ++++++ docs/make.bat | 35 ++++++++++ 4 files changed, 256 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..298ea9e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..24cd1b3 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'pyDTNsim' +copyright = '2018, Robert Wiewel' +author = 'Robert Wiewel' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '0.1.0' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'pyDTNsimdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pyDTNsim.tex', 'pyDTNsim Documentation', + 'Robert Wiewel', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'pydtnsim', 'pyDTNsim Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyDTNsim', 'pyDTNsim Documentation', + author, 'pyDTNsim', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + + +# -- Extension configuration ------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..6b464de --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,22 @@ +.. pyDTNsim documentation master file, created by + sphinx-quickstart on Tue Dec 11 18:24:57 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to pyDTNsim's documentation! +==================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + +Test diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..27f573b --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% + +:end +popd From 1e5625d2fc9ffcc98393cad84d5e19ffe90f38b6 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Sun, 30 Dec 2018 16:49:48 +0100 Subject: [PATCH 02/16] Added (abs) path configuration for sphinx source code evaluation --- docs/conf.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 24cd1b3..a91bb2b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) +import os +import sys +sys.path.insert(0, os.path.abspath('../..')) # -- Project information ----------------------------------------------------- From a92f6f21eccfc70b227a34b862aa22eb10d26764 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Sun, 30 Dec 2018 16:50:25 +0100 Subject: [PATCH 03/16] Added abstract (draft) structure for sphinx documentation --- docs/architecture.rst | 2 ++ docs/data_processing.rst | 2 ++ docs/development_guide.rst | 2 ++ docs/examples.rst | 2 ++ docs/getting_started.rst | 2 ++ docs/glossary.rst | 9 +++++++++ docs/index.rst | 22 ++++++++++++++++------ docs/install.rst | 2 ++ docs/monitoring.rst | 2 ++ docs/scenario_setup.rst | 2 ++ 10 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 docs/architecture.rst create mode 100644 docs/data_processing.rst create mode 100644 docs/development_guide.rst create mode 100644 docs/examples.rst create mode 100644 docs/getting_started.rst create mode 100644 docs/glossary.rst create mode 100644 docs/install.rst create mode 100644 docs/monitoring.rst create mode 100644 docs/scenario_setup.rst diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 0000000..edccb54 --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,2 @@ +pyDTNsim Architecture +===================== diff --git a/docs/data_processing.rst b/docs/data_processing.rst new file mode 100644 index 0000000..931f7ce --- /dev/null +++ b/docs/data_processing.rst @@ -0,0 +1,2 @@ +Simulation Data Processing +========================== diff --git a/docs/development_guide.rst b/docs/development_guide.rst new file mode 100644 index 0000000..a06f5ad --- /dev/null +++ b/docs/development_guide.rst @@ -0,0 +1,2 @@ +Development Guide +================= diff --git a/docs/examples.rst b/docs/examples.rst new file mode 100644 index 0000000..bac945d --- /dev/null +++ b/docs/examples.rst @@ -0,0 +1,2 @@ +Examples +======== diff --git a/docs/getting_started.rst b/docs/getting_started.rst new file mode 100644 index 0000000..437e57a --- /dev/null +++ b/docs/getting_started.rst @@ -0,0 +1,2 @@ +Getting started with pyDTNsim +============================= diff --git a/docs/glossary.rst b/docs/glossary.rst new file mode 100644 index 0000000..1159665 --- /dev/null +++ b/docs/glossary.rst @@ -0,0 +1,9 @@ +.. _glossary: + +Glossary +======== + +.. glossary:: + + Packet + In the context of this module, the term *Packet* is used synonymously with *Bundle*. That means that whenever *Packet* is used, it refers to the data unit used on the overlay network layer created by the `Bundle Protocol `_. It refers **NOT** to packets of all underlying layers like on the transport layer of the Convergence Layers. diff --git a/docs/index.rst b/docs/index.rst index 6b464de..afa0257 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,14 +3,25 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to pyDTNsim's documentation! -==================================== +pyDTNsim - a DTN simulation environment +======================================= + +*pyDTNsim* provides a simulation environment that allows the simulation of arbitrary Delay Tolerant Networking (DTN) scenarios on a packet level. *pyDTNsim* provides users with the ability to evaluate the performance of various routing approaches and to detect possibly occurring overload situations. Currently, the focus lies on deterministic Contact-Graph-based routing approaches, but there might be other approaches available in the future. The clear modularization allows users to easily implement routing approaches on their own. + +Contents +-------- .. toctree:: :maxdepth: 2 - :caption: Contents: - + install + getting_started + examples + scenario_setup + monitoring + data_processing + architecture + development_guide Indices and tables ================== @@ -18,5 +29,4 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - -Test +* :ref:`glossary` diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 0000000..11e4437 --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,2 @@ +Installation +============ diff --git a/docs/monitoring.rst b/docs/monitoring.rst new file mode 100644 index 0000000..f99db46 --- /dev/null +++ b/docs/monitoring.rst @@ -0,0 +1,2 @@ +Simulation Monitoring +===================== diff --git a/docs/scenario_setup.rst b/docs/scenario_setup.rst new file mode 100644 index 0000000..1e44675 --- /dev/null +++ b/docs/scenario_setup.rst @@ -0,0 +1,2 @@ +Simulation Scenario Setup +========================= From 1f8a1b903428e2212f69852acd82f36e158541f2 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Mon, 31 Dec 2018 16:57:24 +0100 Subject: [PATCH 04/16] Restructured toctree and added citation module --- docs/conf.py | 1 + docs/index.rst | 11 +++++++++-- docs/references.bib | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 docs/references.bib diff --git a/docs/conf.py b/docs/conf.py index a91bb2b..37a45e5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -43,6 +43,7 @@ 'sphinx.ext.doctest', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', + 'sphinxcontrib.bibtex', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/index.rst b/docs/index.rst index afa0257..1b20aec 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,15 +13,22 @@ Contents .. toctree:: :maxdepth: 2 + :caption: User Guide install getting_started examples scenario_setup + routing/index monitoring data_processing - architecture - development_guide + +.. toctree:: + :maxdepth: 2 + :caption: Development Guide + + architecture + development_guide Indices and tables ================== diff --git a/docs/references.bib b/docs/references.bib new file mode 100644 index 0000000..5c0d76f --- /dev/null +++ b/docs/references.bib @@ -0,0 +1,8 @@ +@article{Vahdat2000, +author = {Vahdat, Amin and Becker, David}, +journal = {Technical Report}, +number = {CS-200006}, +title = {{Epidemic routing for partially connected ad hoc networks}}, +url = {http://cseweb.ucsd.edu/~vahdat/papers/epidemic.pdf}, +year = {2000} +} From 2a6d2f925262c92f38c6d2d9ed15112ca61d02a5 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 00:35:42 +0100 Subject: [PATCH 05/16] Added routing/ in docs/ for routing algo documentation Also renamed architecture section --- docs/architecture.rst | 2 +- docs/routing/cgr.rst | 2 ++ docs/routing/index.rst | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 docs/routing/cgr.rst create mode 100644 docs/routing/index.rst diff --git a/docs/architecture.rst b/docs/architecture.rst index edccb54..b75c3ab 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -1,2 +1,2 @@ -pyDTNsim Architecture +Architecture Overview ===================== diff --git a/docs/routing/cgr.rst b/docs/routing/cgr.rst new file mode 100644 index 0000000..8fcede5 --- /dev/null +++ b/docs/routing/cgr.rst @@ -0,0 +1,2 @@ +Contact Graph Routing +===================== diff --git a/docs/routing/index.rst b/docs/routing/index.rst new file mode 100644 index 0000000..f2fe493 --- /dev/null +++ b/docs/routing/index.rst @@ -0,0 +1,11 @@ +.. _routing_mechanisms: + +Routing Mechanisms +================== + +With ``pyDTNsim``, the behavior of various routing mechanisms can be simulated. The currently implemented mechanisms are outlined in the next chapters: + +.. toctree:: + :maxdepth: 2 + + cgr From da44ef65a5e9f269f776b9ff8cc3e0ef263fc0c4 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 00:36:19 +0100 Subject: [PATCH 06/16] Added section about module installation in doc --- docs/getting_started.rst | 2 + docs/install.rst | 133 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 437e57a..352b49c 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -1,2 +1,4 @@ +.. _getting_started: + Getting started with pyDTNsim ============================= diff --git a/docs/install.rst b/docs/install.rst index 11e4437..e54c28e 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -1,2 +1,135 @@ Installation ============ +Depending on the intended use case, the installation procedure for the library differs. If the library modules should only be invoked by custom scripts, installing ``pyDTNsim`` via the Python package index PyPi_ is sufficient. If the simulation modules have to be altered, downloading the source code and installing ``pyDTNsim`` as editable python module is required. + +.. _PyPi: https://pypi.org/ + +Module Dependencies +------------------- +The following modules are used in various contexts of ``pyDTNsim``. However, some are only necessary for the development of the module and not for running simulations. + +.. _dependency_table: + ++-------------------+-----------+-----------------------------+-----------+ +| Python Module | License | Purpose | Dev? [1]_ | ++===================+===========+=============================+===========+ +| networkx | BSD | Library allows the export | | +| | | of networkx ``DiGraph`` | | +| | | objects for additional | | +| | | graph analyses. | | ++-------------------+-----------+-----------------------------+-----------+ +| tqdm | MIT | Used for displaying the | | +| | | simulation progress (i.e. | | +| | | elapsed simulated seconds). | | ++-------------------+-----------+-----------------------------+-----------+ +| jsonschema | MIT | Validation of JSON schemes | | +| | | in the loaded topology | | +| | | files. | | ++-------------------+-----------+-----------------------------+-----------+ +| pytest | MIT | Used for running the | x | +| | | modules unit tests. Only | | +| | | executed in CI, | | +| | | not integrated otherwise. | | ++-------------------+-----------+-----------------------------+-----------+ +| sphinx | BSD | Generation of this | x | +| | | documentation. Not | | +| | | invoked by the module. | | ++-------------------+-----------+-----------------------------+-----------+ +| sphinx_rtd_theme | MIT | Theme for ``sphinx``. | x | ++-------------------+-----------+-----------------------------+-----------+ +| pylint | GPL | Tool for detecting source | x | +| | | code issues. Only | | +| | | executed in CI, | | +| | | not integrated otherwise. | | ++-------------------+-----------+-----------------------------+-----------+ +| pydocstyle | MIT | Tool for validating | x | +| | | docstrings in source code. | | ++-------------------+-----------+-----------------------------+-----------+ +| termcolor | MIT | Provides colorful shell | x | +| | | output when testing | | +| | | the examples of the module. | | ++-------------------+-----------+-----------------------------+-----------+ + +.. [1] Modules with 'Dev?' checked are only relevant in the development context of this module. + +pyDTNsim uses new Python features, in particular + +- `Data Classes `_ (3.7), +- `Formatted String Literals `_ (3.6) and +- `Insertion-Order Preservation `_ of items added to a ``dict`` object. (3.7). + +Therefore, **Python 3.7+** is currently required for using this library. + +.. note:: + + It is planned to establish compatibility with older versions (especially 2.7) in the future. + + +PyPi Installation +----------------- +The latest version of *pyDTNsim* can be installed with ``pip3``: + +.. code-block:: sh + + $ pip3 install pydtnsim + +Thats it, ``pip3`` will download the module from PyPi_ and install it locally. Check if the module was installed correctly by invoking a Python shell and importing the module: + +.. code-block:: python + + > import pydtnsim + +If no error occurs, the installation was successful. Continue with the with the section :ref:`getting_started`. + +Source Code Installation +------------------------ +Alternatively, the module can be made available in the local Python instance by downloading it from `Github `_ and then installing it as editable package. + +This more advanced installation is necessary when the library module (or parts of it) have to be altered. For example, this is the case if contributing to the module is intended. + +Archive Download and Extraction +""""""""""""""""""""""""""""""" +The source can be downloaded as `.zip `_ or `.tar.gz `_ archive. + +In Linux, the download and extraction of the files can usually also be achieved using the utilities ``wget`` and ``tar``: + +.. code-block:: sh + + $ wget https://github.com/ducktec/pydtnsim/archive/master.tar.gz + $ tar -xzf master.tar.gz + $ cd pydtnsim-master/ + +Git Clone +""""""""" +If the version-control system ``git`` is installed, the project can also be cloned: + +.. code-block:: sh + + $ git clone https://github.com/ducktec/pydtnsim.git + $ cd pydtnsim/ + +Module Installation +""""""""""""""""""" +.. warning:: Please store the ``pydtnsim/`` source code folder in an appropriate (long-term) directory on your local device. As we are installing the module as editable, the Python environment will continuously reference the files directly instead of copying them to hidden internal folders. Moving the directory around after the installation will likely result in broken references and errors! + +As next step, the module can be made available in the Python environment: + +.. code-block:: sh + + $ pip install -e "." + +``pip3`` installs the module as editable (achieved with the parameter ``-e``) and tries to satisfy all core dependencies (see above :ref:`dependency table `). + +If all development dependencies [1]_ shall be installed, the ``[dev]`` specifier has to be added to the installation command: + +.. code-block:: sh + + $ pip install -e ".[dev]" + +Check if the module was installed correctly by invoking a Python shell and importing the module: + +.. code-block:: python + + > import pydtnsim + +If no error occurs, the installation was successful. Continue ith the section :ref:`getting_started`. From 83922521ea7d0fc35891e95a8fa7ea982d200cd4 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 16:41:48 +0100 Subject: [PATCH 07/16] Added napoleon ext to allow apidoc/automodule parsing of inline doc. --- docs/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/conf.py b/docs/conf.py index 37a45e5..2f9a7eb 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -44,6 +44,7 @@ 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', 'sphinxcontrib.bibtex', + 'sphinx.ext.napoleon', ] # Add any paths that contain templates here, relative to this directory. From 24a5ce770b982e5ba1eb5d98592a38ac5b827f50 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 16:43:28 +0100 Subject: [PATCH 08/16] Added generated rst files for module API, structure not final yet There is still a lot of room for improving the structure to access the autogenerated data --- docs/index.rst | 1 + docs/source/modules.rst | 7 +++ docs/source/pydtnsim.backend.rst | 22 ++++++++ docs/source/pydtnsim.monitors.rst | 30 ++++++++++ docs/source/pydtnsim.nodes.rst | 22 ++++++++ docs/source/pydtnsim.packet_generators.rst | 38 +++++++++++++ docs/source/pydtnsim.routing.rst | 54 ++++++++++++++++++ docs/source/pydtnsim.rst | 65 ++++++++++++++++++++++ 8 files changed, 239 insertions(+) create mode 100644 docs/source/modules.rst create mode 100644 docs/source/pydtnsim.backend.rst create mode 100644 docs/source/pydtnsim.monitors.rst create mode 100644 docs/source/pydtnsim.nodes.rst create mode 100644 docs/source/pydtnsim.packet_generators.rst create mode 100644 docs/source/pydtnsim.routing.rst create mode 100644 docs/source/pydtnsim.rst diff --git a/docs/index.rst b/docs/index.rst index 1b20aec..1f226aa 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,6 +22,7 @@ Contents routing/index monitoring data_processing + API pyDTNsim .. toctree:: :maxdepth: 2 diff --git a/docs/source/modules.rst b/docs/source/modules.rst new file mode 100644 index 0000000..0b0f9ed --- /dev/null +++ b/docs/source/modules.rst @@ -0,0 +1,7 @@ +pydtnsim +======== + +.. toctree:: + :maxdepth: 4 + + pydtnsim diff --git a/docs/source/pydtnsim.backend.rst b/docs/source/pydtnsim.backend.rst new file mode 100644 index 0000000..f0d7da8 --- /dev/null +++ b/docs/source/pydtnsim.backend.rst @@ -0,0 +1,22 @@ +pydtnsim.backend package +======================== + +Submodules +---------- + +pydtnsim.backend.qsim module +---------------------------- + +.. automodule:: pydtnsim.backend.qsim + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim.backend + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydtnsim.monitors.rst b/docs/source/pydtnsim.monitors.rst new file mode 100644 index 0000000..a0d8764 --- /dev/null +++ b/docs/source/pydtnsim.monitors.rst @@ -0,0 +1,30 @@ +pydtnsim.monitors package +========================= + +Submodules +---------- + +pydtnsim.monitors.base\_monitor module +-------------------------------------- + +.. automodule:: pydtnsim.monitors.base_monitor + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.monitors.monitor\_notifier module +------------------------------------------ + +.. automodule:: pydtnsim.monitors.monitor_notifier + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim.monitors + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydtnsim.nodes.rst b/docs/source/pydtnsim.nodes.rst new file mode 100644 index 0000000..477d35d --- /dev/null +++ b/docs/source/pydtnsim.nodes.rst @@ -0,0 +1,22 @@ +pydtnsim.nodes package +====================== + +Submodules +---------- + +pydtnsim.nodes.simple\_cgr\_node module +--------------------------------------- + +.. automodule:: pydtnsim.nodes.simple_cgr_node + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim.nodes + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydtnsim.packet_generators.rst b/docs/source/pydtnsim.packet_generators.rst new file mode 100644 index 0000000..a442564 --- /dev/null +++ b/docs/source/pydtnsim.packet_generators.rst @@ -0,0 +1,38 @@ +pydtnsim.packet\_generators package +=================================== + +Submodules +---------- + +pydtnsim.packet\_generators.base\_packet\_generator module +---------------------------------------------------------- + +.. automodule:: pydtnsim.packet_generators.base_packet_generator + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.packet\_generators.batch\_packet\_generator module +----------------------------------------------------------- + +.. automodule:: pydtnsim.packet_generators.batch_packet_generator + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.packet\_generators.continuous\_packet\_generator module +---------------------------------------------------------------- + +.. automodule:: pydtnsim.packet_generators.continuous_packet_generator + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim.packet_generators + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydtnsim.routing.rst b/docs/source/pydtnsim.routing.rst new file mode 100644 index 0000000..b61cd02 --- /dev/null +++ b/docs/source/pydtnsim.routing.rst @@ -0,0 +1,54 @@ +pydtnsim.routing package +======================== + +Submodules +---------- + +pydtnsim.routing.cgr\_anchor module +----------------------------------- + +.. automodule:: pydtnsim.routing.cgr_anchor + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.routing.cgr\_basic module +---------------------------------- + +.. automodule:: pydtnsim.routing.cgr_basic + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.routing.cgr\_utils module +---------------------------------- + +.. automodule:: pydtnsim.routing.cgr_utils + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.routing.dijkstra module +-------------------------------- + +.. automodule:: pydtnsim.routing.dijkstra + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.routing.scgr module +---------------------------- + +.. automodule:: pydtnsim.routing.scgr + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim.routing + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/pydtnsim.rst b/docs/source/pydtnsim.rst new file mode 100644 index 0000000..cf7ec11 --- /dev/null +++ b/docs/source/pydtnsim.rst @@ -0,0 +1,65 @@ +pydtnsim package +================ + +Subpackages +----------- + +.. toctree:: + + pydtnsim.backend + pydtnsim.monitors + pydtnsim.nodes + pydtnsim.packet_generators + pydtnsim.routing + +Submodules +---------- + +pydtnsim.contact module +----------------------- + +.. automodule:: pydtnsim.contact + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.contact\_graph module +------------------------------ + +.. automodule:: pydtnsim.contact_graph + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.contact\_plan module +----------------------------- + +.. automodule:: pydtnsim.contact_plan + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.packet module +---------------------- + +.. automodule:: pydtnsim.packet + :members: + :undoc-members: + :show-inheritance: + +pydtnsim.simulator module +------------------------- + +.. automodule:: pydtnsim.simulator + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: pydtnsim + :members: + :undoc-members: + :show-inheritance: From a821abbc39bc1d9ae165c80985b3141b4c0dbfd1 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 17:02:17 +0100 Subject: [PATCH 09/16] Fixed division by zero bug in Simulator if no components are simulated --- pydtnsim/simulator.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pydtnsim/simulator.py b/pydtnsim/simulator.py index 7b99c97..e4e4011 100644 --- a/pydtnsim/simulator.py +++ b/pydtnsim/simulator.py @@ -126,6 +126,7 @@ def run_simulation(self, # Signal to monitors that simulation ended self.notifier.simulation_ended() + print("Simulation completed!") self.__print_stats() def register_node(self, node): @@ -215,12 +216,15 @@ def __print_stats(self): local_rem_cap = self.contact_dict[contact].capacity remaining_capacity += local_rem_cap self.final_capacity_dict[contact] = local_rem_cap - - capacity_utilization = round( - (((self.overall_capacity - remaining_capacity) / - self.overall_capacity) * 100), 2) - print("- contact capacity utilization: {} %".format( - capacity_utilization)) + + # Only calculate the utilization if any capacity was available + # otherwise leads to division by zero error + if self.overall_capacity > 0: + capacity_utilization = round( + (((self.overall_capacity - remaining_capacity) / + self.overall_capacity) * 100), 2) + print("- contact capacity utilization: {} %".format( + capacity_utilization)) def get_utilization_list(self, ignore_inter_hotspot_contact=False, From cca84e92b1ce0234fdf65654161b1e929bf58424 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 9 Jan 2019 17:18:05 +0100 Subject: [PATCH 10/16] Started with getting started section of module documentation --- docs/getting_started.rst | 96 +++++++++++++++++++ .../getting_started/dtn_simulation.py | 20 ++++ docs/resources/getting_started/topology.svg | 2 + docs/resources/getting_started/topology.xml | 1 + 4 files changed, 119 insertions(+) create mode 100644 docs/resources/getting_started/dtn_simulation.py create mode 100644 docs/resources/getting_started/topology.svg create mode 100644 docs/resources/getting_started/topology.xml diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 352b49c..6c8726a 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -2,3 +2,99 @@ Getting started with pyDTNsim ============================= + +With *pyDTNsim* installed, we can start with running simulations using the library. In this section, a hands-on introduction into the features and the instrumentation procedure of the library module will be provided. + +The goal of this introduction is to simulate the simple intermittently connected network topology as depicted below and to generate key characteristics of this simulation run. + +Simulation Scenario +------------------- + +The following network topology shall be simulated for 1000 seconds: + +.. image:: resources/getting_started/topology.svg + :width: 100% + +The annotations at the arrows represent available contact between the two (physical) network nodes that an arrow is connecting in `mathematical interval notation `_ in seconds. All contacts are considered to allow for a transmission of data with 100 KBps. + +.. note:: The propagation delays are considered neglible in this scenario. This is in line with the current configuration of *pyDTNsim* which is not supporting (individual or global) delays at the moment. + +The nodes ``A`` and ``C`` are representing *"active"* endpoints which are both continuously inserting packets of 100 KB with a data generation rate of 10 KBps, addressed at node ``A`` and ``C`` respectively. The data generation will continue throughout the entire simulation period. + +Node ``B`` is functioning as intermediary node that is solely forwarding packets received from ``A`` and ``B``. It is neither the destination of any packets nor is it injecting any packets. + +*Contact Graph Routing (CGR)* will be used as routing mechanism. See :ref:`routing_mechanisms` for more details on provided mechanisms and their implementation. + +The characteristics that should be acquired with the simulation run are + +- the overall **average delivery time** of all delivered packets during the simulation run, +- the **number of packets** enqueued into the **limbo** (i.e., packets that could not be scheduled for transmission with CGR) and +- a **histogram** of the **average delivery time** of all delivered packets throughout the simulation run. + +Creating a simulation script +---------------------------- +As *pyDTNsim* is a library module, we have to create a simulation script ourselves to leverage the invoke the module's functionality. + +Just create a new python script file with your favorite editor or type + +.. code-block:: sh + + touch dtn_simulation.py + vim dtn_simulation.py + +With the script created, we can now start to import the libraries components. We start with creating a :class:`pydtnsim.simulator.Simulator` object. This object represents the event-oriented simulation environment that keeps track of the simulations components and is later invoked for the actual simulation run. Details about the abstract concept of the simulation environment can be found in :doc:`architecture`. + +The :class:`Simulator` can then be used to perform a simulation using it's member function :py:meth:`.Simulator.run_simulation`. For now, it is sufficient to provide this function with the simulation duration in milliseconds. It will then run a simulation from 0 ms to that provided parameter. + +The following code snippet shows the most basic simulation script using the :class:`.Simulator` class. Please add this snippet to your script file. + + + +.. code-block:: python + + from pydtnsim import Simulator + + def main(): + """Simulate basic scenario.""" + # Create simulation environment + simulator = Simulator() + + # Run the simulation for 1000 seconds (1000000 ms) + simulator.run_simulation(1000000) + + if __name__ == "__main__": + main() + +As no nodes or contacts were added to the :class:`.Simulator` object, nothing has to be simulated. When running the script, the output is as follows: + +.. code-block:: none + :linenos: + + > python3 dtn_simulation.py + Running simulation for 1000000 ms ... + Simulation completed! + Simulation Results: + - total number of packets generated: 0 + - total number of packets enqueued in limbos: 0 + - total number of packets enqueued in contacts: 0 + +Hooray, that was the first "successful" pyDTNsim simulation run! We didn't actually simulate any network but we can change that by adding simulation elements in the next step. + +But first, let's have a look at the output provided by the :class:`.Simulator` object: besides the message that the simulation was completed the output also provides some simple statistics about the performed simulation run in lines *(5-7)*. In our case, no packets were generated and subsequently, no packets remained in limbos or contacts at the end of the simulation run. + + + +Adding simulation elements +-------------------------- + +Injecting Data Packets +---------------------- + +Monitoring of the Simulation +---------------------------- + +Running a Simulation +-------------------- + +Post Processing and Evaluation +------------------------------ diff --git a/docs/resources/getting_started/dtn_simulation.py b/docs/resources/getting_started/dtn_simulation.py new file mode 100644 index 0000000..d265302 --- /dev/null +++ b/docs/resources/getting_started/dtn_simulation.py @@ -0,0 +1,20 @@ +"""Minimal Simulation Example.""" + +from pydtnsim import Simulator, ContactPlan, ContactGraph, Contact +from pydtnsim.nodes import SimpleCGRNode +from pydtnsim.packet_generators import BatchPacketGenerator + +from pydtnsim.routing import cgr_basic + + +def main(): + """Simulate basic scenario.""" + # Create simulation environment + simulator = Simulator() + + # Run the simulation for 1000 seconds (1000000 ms) + simulator.run_simulation(1000000) + + +if __name__ == "__main__": + main() diff --git a/docs/resources/getting_started/topology.svg b/docs/resources/getting_started/topology.svg new file mode 100644 index 0000000..9c042f0 --- /dev/null +++ b/docs/resources/getting_started/topology.svg @@ -0,0 +1,2 @@ + +
Node
A
[Not supported by viewer]
Node
B
[Not supported by viewer]
Node
C
[Not supported by viewer]
[0,100)
[500,750)
[Not supported by viewer]
[0,200)
[350,400)
[950,990)
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/resources/getting_started/topology.xml b/docs/resources/getting_started/topology.xml new file mode 100644 index 0000000..eb49a80 --- /dev/null +++ b/docs/resources/getting_started/topology.xml @@ -0,0 +1 @@ +5VfbjpswEP0aHvrQCuyQy2Ngk66222qlPHT3qfKCA24Npsa59es7DiaEW0qrtNpVFSnynLHHnjNzDFjYT/bvJcnijyKk3EJ2uLfwjYXQ1HHhXwOHAnAdXACRZGEBORWwYj+oAW2DblhI89pEJQRXLKuDgUhTGqgaRqQUu/q0teD1XTMS0RawCghvo59ZqGKTFppU+C1lUVzu7IxnhSch5WSTSR6TUOzOILywsC+FUMUo2fuUa+5KXop1yx7v6WCSpmrIgntyp5bf7z5sb/1x9uUZJTl7eGuibAnfmIQ/QQUtNOYQ03uWMIr0aN6GTFbqUFIF20FVwPB2MVN0lZFAe3bQF4DFKuFgOTAkeVaUas32FE7nrRnnvuBCHgPhJdK/0xZbKhXd92btnLiEHqQioUoeYEq5YGToN/03NuauKqZroPisjiVGTPtEp8AVwzAwJP8G4eM2bSE0nDGFVLGIREr4okI9KTZpqIm6setE0j1Tj2fjJz3lnautFA77aFYcjcqXKyLVXGsDoICTPGdBCS8ZL4N/pUodjCDJRgmAquPdC5GZeUVCOovLJYKkxUYG9AI5yAicyIiqC/Nwd8kl5USxbf0cV68gGigZ77VKBqOXJRk8kHD/tRLu2i+L8FGL8DaPadi+Qc7oG3jHXPHuKF8OfnV3oO5SDOR68BVjdngQDBLpfRo500YNizTNqvOHeTPQrBEINwIVPLQCHfvhlPaft8ik3SKuB0fwHdt+06FD1zs2uT9xO93N9gItqWZDSfGNlgJMRUobmjQQ4SxKdc9BA1HAPa1MBu9zc+NQ+sHVqf76Y/YKukYNXU/dlq4dp6vZ3L8k7Glf1VBf1bBufH/U554d3bPZf1RUPP1nRQWz+jwolFt9Y+HFTw== \ No newline at end of file From 81b0b11a86774393ee4119bfbca263c72da4ef49 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Mon, 14 Jan 2019 19:50:55 +0100 Subject: [PATCH 11/16] Continued "getting started" section of sphinx documentation --- docs/getting_started.rst | 146 ++++++- docs/resources/data_format_ion.xml | 1 + .../getting_started/injection_methods.svg | 413 ++++++++++++++++++ 3 files changed, 557 insertions(+), 3 deletions(-) create mode 100644 docs/resources/data_format_ion.xml create mode 100644 docs/resources/getting_started/injection_methods.svg diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 6c8726a..ec407fd 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -83,12 +83,152 @@ Hooray, that was the first "successful" pyDTNsim simulation run! We didn't actua But first, let's have a look at the output provided by the :class:`.Simulator` object: besides the message that the simulation was completed the output also provides some simple statistics about the performed simulation run in lines *(5-7)*. In our case, no packets were generated and subsequently, no packets remained in limbos or contacts at the end of the simulation run. - Adding simulation elements -------------------------- -Injecting Data Packets ----------------------- +In order to not just simulate empty scenarios, we now have to add (active and passive) simulation elements to the simulation environment. In particular, two elements have to be represented in the environment: physical network nodes (e.g., :class:`.SimpleCGRNode`) and contacts in between those nodes (:class:`.Contact`). + +.. note:: + + Both classes/objects referenced in the paragraph above are exemplary. Depending on the simulated routing mechanisms, the instantiated network node objects have to vary (and might even have to be implemented oneself for novel routing concepts). An opportunistic routing approach might have differing processing requirements both in terms of gathered knowledge at the physical nodes and the forwarding behavior during node contacts. + +.. warning:: + + With the development focus of this simulation environment having been CGR, the generalization in terms of applicable routing mechanisms has not been fully implemented in this area of the application. For now, only CGR implementations are provided and no abstract parent class exists for the easy adoption with other routing approaches. This improvement will likely be implemented in the near future. + +For the simulation elements including their helper classes, we need to add the following imports: + +.. code-block:: python + + from pydtnsim import ContactPlan, ContactGraph, Contact + from pydtnsim.nodes import SimpleCGRNode + from pydtnsim.routing import cgr_basic + +The imported objects will be explained in the following paragraphs. + +Network Topology +^^^^^^^^^^^^^^^^ + +As the network node need to be aware about the network topology since we are using :abbr:`CGR (Contact Graph Routing)` as routing mechanism, we have to provide such information during the instantiation. + +We provide the topology knowledge as a :class:`.ContactGraph` object. This object represents the topology as a time-invariant graph and can be easily generated from a :class:`.ContactPlan` object. This object holds the same information as the :class:`.ContactGraph`, but is easier to understand and modify for humans. More details on the reasoning behind the :class:`.ContactPlan` and the :class:`.ContactGraph` in the context of :abbr:`CGR (Contact Graph Routing)` is provided in :doc:`routing/cgr`. + +As outlined before, we first create the :class:`.ContactPlan` (line 2). The parameters provided during the instantiation are the default data rate in bits per millisecond (10 bits per millisecond, i.e. 10 KBps) and the default propagation delay in milliseconds (50 ms). + +.. warning:: + + The propagation delay is currently not factored in when simulating networks. The interface for providing such information is already implemented, but the simulation logic is not implemented yet. This is future work, so for now, the propagation delay is always neglected. + +.. code-block:: python + :linenos: + + # Generate empty contact plan + contact_plan = ContactPlan(10, 50) + + # Add the contacts + contact_plan.add_contact('node_a', 'node_b', 0, 100000) + contact_plan.add_contact('node_a', 'node_b', 500000, 750000) + contact_plan.add_contact('node_b', 'node_c', 0, 200000) + contact_plan.add_contact('node_b', 'node_c', 350000, 400000) + contact_plan.add_contact('node_b', 'node_c', 950000, 990000) + +In lines 5 to 9, the contacts based on our previously outlined scenario are added to the ``contact_plan`` object using :py:meth:`.ContactPlan.add_contact`. The parameters are + +- the source node, +- the destination node, +- the start time in milliseconds and +- the end time in milliseconds. + +As no additional optional parameters for the data rate and the delay were provided, the default values of the ``contact_plan`` object are used. + +Finally, we can simply convert the filled :class:`.ContactPlan` object into a :class:`.ContactGraph` object: + +.. code-block:: python + + # Convert contact plan to contact graph + contact_graph = ContactGraph(contact_plan) + +Contacts +^^^^^^^^ + +The contacts available in between network nodes throughout the simulation are simulated using the :class:`.Contact` object. These objects are an integral part of the simulation environment as they are one of two active **generator** elements that drive the simulation (and generate events, hence the name). Contacts are activated upon their contact start time and then perform handover operations from one node to another during their time active. At the end of a handover of a packet to another node, the routing mechanism on that other node is called to determine the future forwarding. + +With the information about the contacts already being available in the ``contact_plan`` object of the previous step, we can iterate over that information to generate our :class:`.Contact` objects: + +.. code-block:: python + :linenos: + + # Generate contact objects and register them + for planned_contact in contact_plan.get_contacts(): + # Create a Contact simulation object based on the ContactPlan + # information + contact = Contact(planned_contact.from_time, planned_contact.to_time, + planned_contact.datarate, planned_contact.from_node, + planned_contact.to_node, planned_contact.delay) + # Register the contact as a generator object in the simulation + # environment + simulator.register_contact(contact) + +In addition to the instantiation of the contacts in lines 5 to 7, in line 10, the respective contact also has to be registered with the simulation environment. This is to allow the simulation environment to call the contact upon its start time. + + +Network Nodes +^^^^^^^^^^^^^ + +With the topology information available in the correct format, we can add the network nodes. For all three nodes, we will use :class:`.SimpleCGRNode` as representation in the simulation environment. Again, we can use the `contact_plan` object that we instantiated and filled earlier to gather the relevant information for the instantiation: + +.. code-block:: python + :linenos: + + # Generate network node objects and register them + for planned_node in contact_plan.get_nodes(): + # Generate contact list of node + contact_list = contact_plan.get_outbound_contacts_of_node(planned_node) + # Create a dict that maps the contact identifiers to Contact simulation + # objects + contact_dict = simulator.get_contact_dict(contact_list) + # Create a node simulation object + SimpleCGRNode(planned_node, contact_dict, cgr_basic.cgr, contact_graph, + simulator, []) + +In line 2, we get a list of all network nodes in the topology using :py:meth:`.ContactPlan.get_nodes`. We then iterate over this list and create the individual nodes: + +1. We first have to get a list of all outbound nodes that the individual + network node has. This is done calling + :py:meth:`.ContactPlan.get_outbound_contacts_of_node`. +2. This list is then used to get a ``contact_dict`` from the + :class:`.Simulator` object. As this object is aware of all contacts and + their registered instantiations, it can map the textual list entries of the + outbound contacts from the previous step to actual :class:`.Contact` + objects. So by calling :py:meth:`.Simulator.get_contact_dict`, we get a + ``dict`` mapping a contacts identifier to the instantiation in the + simulation context. +3. With the ``contact_dict`` available, we can instantiate the actual network + node object as :class:`.SimpleCGRNode` with the following parameters: + + - the node identifier (e.g. ``node_a``), + - the ``contact_dict``, + - the routing mechanism's main function ``cgr_basic.cgr``, + - the topology information (in this case as :class:`.ContactGraph` object) + and + - the :class:`.Simulator` object. + +Packet Generators +^^^^^^^^^^^^^^^^^ + +Finally, we have to add packet generators that are injecting packets into the simulated network. Without them, regardless of the specified topology, no packets would be forwarded and thus, no non-trivial network behavior would be simulated. + +Currently, there two different packet generators provided in the simulation environment, the :class:`.BatchPacketGenerator` and the :class:`.ContinuousPacketGenerator`. Both are children of the parent :class:`.BasePacketGenerator`. + +The injection behavior of the two generators is depicted in the following figures: + +.. image:: resources/getting_started/injection_methods.svg + :width: 80% + :align: center + +The :class:`.BatchPacketGenerator` injects a specified number of packets at specified points in time whereas the :class:`.ContinuousPacketGenerator` injects packets continuously throughout the simulation period with a defined generation data rate. + +Depending on the scenario, one of them might be used for the simulation conducted. Alternatively, an own generator can be implemented based on the :class:`.BasePacketGenerator`. Monitoring of the Simulation ---------------------------- diff --git a/docs/resources/data_format_ion.xml b/docs/resources/data_format_ion.xml new file mode 100644 index 0000000..efdde21 --- /dev/null +++ b/docs/resources/data_format_ion.xml @@ -0,0 +1 @@ +7Zldb5swFIZ/DZeV+EhIuCxpu07atG6ZtN1NLj4FawZHxmnS/fodggkfTpu1XSlIyUWEX5tj+zwvjnEsb5FuP0iySj4LCtxybbq1vAvLdSezKX4XwkMpuEFQCrFktJScWliyP6BFW6trRiFvNVRCcMVWbTESWQaRamlESrFpN7sTvN3risRgCMuIcFP9wahKSnXuzmr9GlicVD07vp5fSqrGeiZ5QqjYNCTv0vIWUghVXqXbBfAid1VeyvuuHqndD0xCpv7lBh7GP7efzhL7S5h+vVIk+vUxPnPcMsw94Ws9Yz1a9VClIJZivbK8MBX35HYn2liSkLM/zbJQRDXK6ANoloGyZlHzaih6ICAVbA+h1U3rhDan7uwTikYEkYKSD9ikCuTMy1u0CZ2JDrGpkTpzPfOkgbPqimgXxfvQdaLxQuf6OXk30k6MvGMecBhholIMfeHgZa6k+A0LwYVEJRMZtgzvGOcdiXAWZ1iMMD+AelhklaGpz3VFyigtugk3CVOwXJGo6HODT/CO5DqjQDWWO5GpKrzlev7u845uaFJ/wtKmF5qs+0RtPmE4W6xTJ+BvC3zbht3gP7V75O8dWGFDZxzwbTsIbHvE8NG5Xfhun/Anh+B7vm2Pg39Bf9T8A8fgP+mT/9Tg79i7lI4CfzFS3K+PF78zMRf/Xvk7pgEM9JDR8+JNpWDISZ6zqG2Ex6DkYi0juAHJcKwgC7Asi7HRFCsVkTGoA5X+Pt9AjVefoxvqIz+ilSaBE8Xu2+EPJVf3cCMYdlxj8+z2fj3o8NFTL+9qvvN0A007gfxOIJ2mbqAd6/20X4HfP+F/Af75/8IfvDP+2Qn/8/HvV+jX4ne7y0jf+Ocn/C/A331oX4y/u4z0jN9c+5fYYzHA78jFcMJAd4ADegE8csjnTzu+0eX32vuZiz/yRy6W6/OC9K3Eq7i4ugZCQZr6ODwyqBOiYwfB7rA8Yv5CXGbUNEK5YIzTHoM6Q3jaHm61YRuKPQLDHheYJNMJ34garT8GdchwxB+z7tbkzfyBxfqvwXJHUv+/6l3+BQ== \ No newline at end of file diff --git a/docs/resources/getting_started/injection_methods.svg b/docs/resources/getting_started/injection_methods.svg new file mode 100644 index 0000000..7020591 --- /dev/null +++ b/docs/resources/getting_started/injection_methods.svg @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + + + Injected + + + Packets + + + + + + + + + + + + + + + + + + + + + + + + + + + + + t + + + + + + + + + + Injected + + + Packets + + + + + + + + + + + + + + + + + + Batch + Continuous + + + From 5f8db8c36f8fc0a248b7b757c3fc462de108274f Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 16 Jan 2019 16:33:26 +0100 Subject: [PATCH 12/16] Import Output Enum with Simulator class in root __init__.py This only fixes the symptoms of the insufficiently thought-out module structure, a proper solution will be provided in #12 --- pydtnsim/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydtnsim/__init__.py b/pydtnsim/__init__.py index f3e772a..6632a28 100644 --- a/pydtnsim/__init__.py +++ b/pydtnsim/__init__.py @@ -1,6 +1,6 @@ """Discrete event simulation library for DTN.""" -from .simulator import Simulator +from .simulator import Simulator, Output from .contact_graph import ContactGraph from .contact_plan import ContactPlan, ContactIdentifier from .contact import Contact From 44eead8af237508ac2feb0ad3f315c53e6923ba2 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 16 Jan 2019 16:36:56 +0100 Subject: [PATCH 13/16] Removed the half-baked contact utilization output from the sim summary. --- pydtnsim/simulator.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pydtnsim/simulator.py b/pydtnsim/simulator.py index e4e4011..3582782 100644 --- a/pydtnsim/simulator.py +++ b/pydtnsim/simulator.py @@ -216,15 +216,6 @@ def __print_stats(self): local_rem_cap = self.contact_dict[contact].capacity remaining_capacity += local_rem_cap self.final_capacity_dict[contact] = local_rem_cap - - # Only calculate the utilization if any capacity was available - # otherwise leads to division by zero error - if self.overall_capacity > 0: - capacity_utilization = round( - (((self.overall_capacity - remaining_capacity) / - self.overall_capacity) * 100), 2) - print("- contact capacity utilization: {} %".format( - capacity_utilization)) def get_utilization_list(self, ignore_inter_hotspot_contact=False, From 776b02950f13b64583450db8d68c6cfe88b18a56 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 16 Jan 2019 17:06:37 +0100 Subject: [PATCH 14/16] Completed subsection about simulation elements in getting started guide. Added downloadable simulation script for that section and various figures. --- docs/getting_started.rst | 91 ++++++++++++++++++- .../dtn_simulation_elements.py | 74 +++++++++++++++ .../packet_injection_scheme.svg | 2 + .../packet_injection_scheme.xml | 1 + 4 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 docs/resources/getting_started/dtn_simulation_elements.py create mode 100644 docs/resources/getting_started/packet_injection_scheme.svg create mode 100644 docs/resources/getting_started/packet_injection_scheme.xml diff --git a/docs/getting_started.rst b/docs/getting_started.rst index ec407fd..39cfc29 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -103,6 +103,7 @@ For the simulation elements including their helper classes, we need to add the f from pydtnsim import ContactPlan, ContactGraph, Contact from pydtnsim.nodes import SimpleCGRNode from pydtnsim.routing import cgr_basic + from pydtnsim.packet_generators import ContinuousPacketGenerator The imported objects will be explained in the following paragraphs. @@ -220,7 +221,7 @@ Finally, we have to add packet generators that are injecting packets into the si Currently, there two different packet generators provided in the simulation environment, the :class:`.BatchPacketGenerator` and the :class:`.ContinuousPacketGenerator`. Both are children of the parent :class:`.BasePacketGenerator`. -The injection behavior of the two generators is depicted in the following figures: +The injection behavior of the two generators is depicted in the following figure: .. image:: resources/getting_started/injection_methods.svg :width: 80% @@ -230,6 +231,94 @@ The :class:`.BatchPacketGenerator` injects a specified number of packets at spec Depending on the scenario, one of them might be used for the simulation conducted. Alternatively, an own generator can be implemented based on the :class:`.BasePacketGenerator`. +For our scenario, we will use the :class:`.ContinuousPacketGenerator` to inject packets for the routes ``node_a -> node_c`` and ``node_c -> node_a`` at a specified data generation rate of 10 KBps and with a packet size of 100 KB: + +.. code-block:: python + :linenos: + + # Generate packet generator 1 and register them + generator1 = ContinuousPacketGenerator( + 10, # Data Generation Rate: 10 Bytes per ms + 100000, # Packet Size: 100 KB + ['node_a'], # From 'node_a' + ['node_c'], # To 'node_c' + 0, # Start injection at simulation time 0s + 1000000) # End injection at simulation end (1000s) + + # Generate packet generator 2 and register them + generator2 = ContinuousPacketGenerator( + 10, # Data Generation Rate: 10 Bytes per ms + 100000, # Packet Size: 100 KB + ['node_c'], # From 'node_c' + ['node_a'], # To 'node_a' + 0, # Start injection at simulation time 0s + 1000000) # End injection at simulation end (1000s) + + # Register the generators as a generator objects in the simulation + # environment + simulator.register_generator(generator1) + simulator.register_generator(generator2) + +.. warning:: + + The implementation of the packet generator configuration is currently requiring the instantiation of two distinct generators to accomplish the bidirectional injection of packets between ``node_a <-> node_c``. This will be changed in a future release (likely ``v0.3.0``). + +.. warning:: + Also, the registration procedure for the generators is currently inconsistent with the other simulation elements. Therefore, a consistent registration procedure will be established in a future release as well. + +Two generators have to be instantiated, one for the injection of packets traveling from `node_a` to `node_c` and one for the reverse direction from `node_c` to `node_a`. + +The two instantiations in lines 2 to 8 and 11 to 17 are provided with several parameters: + +- the data generation rate, +- the packet size, +- a ``list`` of (``string``) node identifiers identifying all source nodes that the generator should inject packets with the given parameters and data rate, +- a ``list`` of (``string``) node identifiers identifying all destination nodes that the generator should address packets to with the given parameters and data rate, +- the injection start time (in ms absolute to the simulation start time) and +- the injection end time (in ms absolute to the simulation start time). + +With ``list``'s used for identifying source and destination nodes, the the generator injects for every element of the source node list packets with the given characteristics and rates to all elements of the destination node list. This injection scheme is also depicted in the following diagram: + +.. image:: resources/getting_started/packet_injection_scheme.svg + :width: 100% + :align: center + +With the two generators instantiated an configured, we have to register them with the simulation environment. This is done in lines 21 and 22. + +We now have all simulation elements in place and can run the simulation again. If you don't want to copy all code snippets from this documentation, you can also download the file created up to this point of the tutorial at :download:`this link `. + +If we run this extended script, we get the following output: + +.. code-block:: none + :linenos: + + > python3 dtn_simulation_elements.py + Running simulation for 1000000 ms ... + Simulation completed! + Simulation Results: + - total number of packets generated: 198 + - total number of packets enqueued in limbos: 165 + - total number of packets enqueued in contacts: 0 + +You can see that the generators properly generated packets and injected them into the network. The number of generated packets seems about right: with the configuration provided, the generators inject a packet to the (single) destination every 10 seconds. With 1000 seconds being simulated, this results in 99 injected packets per generator and 198 in total. As the simulation ends when 1000s is reached (excluding the termination value), the 100th packet of each generator that would be due at time 1000s is not added. + +Also, we can see in line 6, that only a fraction of the injected packets is actually forwarded and 165 of the 198 packets are enqueued in one of the nodes' limbos. A limbo is a queue that holds packets that cannot be forwarded to their destination nodes based on the available topology information. Every node has a limbo that is used for such packets. + +.. note:: + + The number of "discarded" packets can be directly attributed to the selected topology, the contact times and the nodes configuration (including the injection rates) and does not represent an (programming) error. + +As our contact plan has the same validity period as our simulation duration, no packets should remain scheduled in contacts after the simulation end. This is the case as can be seen in line 7. + +.. warning:: + + If the validity period of topology information exceeds the simulated period (e.g., a 1 hour simulation is conducted with a contact plan containing the computed contacts for 48 hours), packets can remain enqueued in *future* (i.e., beyond the simulation end time) contacts and will appear in the simulation results summary (in our example in line 7). + +In this section, we successfully simulated our specified simulation scenario. We even got some bits of information about what happened during the simulation (e.g., that a large number of packets was at some point enqueued into a node's limbo). + +However, usually when running a network simulation (especially in the academic context), more detailed analyses and key values are required. The next section will cope with the monitoring interface of pyDTNsim that allows for an extraction of arbitrary such values. + + Monitoring of the Simulation ---------------------------- diff --git a/docs/resources/getting_started/dtn_simulation_elements.py b/docs/resources/getting_started/dtn_simulation_elements.py new file mode 100644 index 0000000..3a400db --- /dev/null +++ b/docs/resources/getting_started/dtn_simulation_elements.py @@ -0,0 +1,74 @@ +from pydtnsim import Simulator +from pydtnsim import ContactPlan, ContactGraph, Contact +from pydtnsim.nodes import SimpleCGRNode +from pydtnsim.routing import cgr_basic +from pydtnsim.packet_generators import ContinuousPacketGenerator + +def main(): + """Simulate basic scenario.""" + # Create simulation environment + simulator = Simulator() + + # Generate empty contact plan + contact_plan = ContactPlan(10, 50) + + # Add the contacts + contact_plan.add_contact('node_a', 'node_b', 0, 100000) + contact_plan.add_contact('node_a', 'node_b', 500000, 750000) + contact_plan.add_contact('node_b', 'node_c', 0, 200000) + contact_plan.add_contact('node_b', 'node_c', 350000, 400000) + contact_plan.add_contact('node_b', 'node_c', 950000, 990000) + + # Convert contact plan to contact graph + contact_graph = ContactGraph(contact_plan) + + # Generate contact objects and register them + for planned_contact in contact_plan.get_contacts(): + # Create a Contact simulation object based on the ContactPlan + # information + contact = Contact(planned_contact.from_time, planned_contact.to_time, + planned_contact.datarate, planned_contact.from_node, + planned_contact.to_node, planned_contact.delay) + # Register the contact as a generator object in the simulation + # environment + simulator.register_contact(contact) + + # Generate network node objects and register them + for planned_node in contact_plan.get_nodes(): + # Generate contact list of node + contact_list = contact_plan.get_outbound_contacts_of_node(planned_node) + # Create a dict that maps the contact identifiers to Contact simulation + # objects + contact_dict = simulator.get_contact_dict(contact_list) + # Create a node simulation object + SimpleCGRNode(planned_node, contact_dict, cgr_basic.cgr, contact_graph, + simulator, []) + + # Generate packet generator 1 and register them + generator1 = ContinuousPacketGenerator( + 10, # Data Generation Rate: 10 Bytes per ms + 100000, # Packet Size: 100 KB + ['node_a'], # From 'node_a' + ['node_c'], # To 'node_c' + 0, # Start injection at simulation time 0s + 1000000) # End injection at simulation end (1000s) + + # Generate packet generator 2 and register them + generator2 = ContinuousPacketGenerator( + 10, # Data Generation Rate: 10 Bytes per ms + 100000, # Packet Size: 100 KB + ['node_c'], # From 'node_c' + ['node_a'], # To 'node_a' + 0, # Start injection at simulation time 0s + 1000000) # End injection at simulation end (1000s) + + # Register the generators as a generator objects in the simulation + # environment + simulator.register_generator(generator1) + simulator.register_generator(generator2) + + # Run the simulation for 1000 seconds (1000000 ms) + simulator.run_simulation(1000000) + +if __name__ == "__main__": + main() diff --git a/docs/resources/getting_started/packet_injection_scheme.svg b/docs/resources/getting_started/packet_injection_scheme.svg new file mode 100644 index 0000000..8387021 --- /dev/null +++ b/docs/resources/getting_started/packet_injection_scheme.svg @@ -0,0 +1,2 @@ + +
Dest D
Dest D
Dest E
Dest E
Dest F
Dest F
Source A
Source A
Source B
Source B
Source C
Source C
List of
Source Nodes
List of<br>Source Nodes<br>
List of
Destination Nodes
List of<br>Destination Nodes<br>
An arrow signals injection of packets for that node pair
An arrow signals injection of packets for that node pair
(
(
)
)
\ No newline at end of file diff --git a/docs/resources/getting_started/packet_injection_scheme.xml b/docs/resources/getting_started/packet_injection_scheme.xml new file mode 100644 index 0000000..b506494 --- /dev/null +++ b/docs/resources/getting_started/packet_injection_scheme.xml @@ -0,0 +1 @@ +7Vtdb6M4FP01kWYfdgU2X3lsknbmobMaKdKutG8OGHBLcOQ4TTK/fu1gCOCQZBQ+lE6KVOFrDL7nnGtfYzKC0+XuK0Or+DsNcDICRrAbwdkIAMcdi//SsM8MFnAzQ8RIkJnMo2FOfmJlNJR1QwK8rlzIKU04WVWNPk1T7POKDTFGt9XLQppUn7pCEdYMcx8luvVfEvA4s3q5F9L+DZMozp9sOsrhJcovVp6sYxTQbckEn0dwyijl2dlyN8WJxC7HJWv30lBbdIzhlF/T4Bty57MP/+31ffLf01fjn02wn/wJsrt8oGSjHFad5fscAXEXAbYoTLYx4Xi+Qr6s2Qq6hS3my0SUTHHKKEec0FQUx4YoL+kHWhzucqjFa/KzXJZXl8pCN7hcxgEpFxW/5QZoHeNAFUKSJFOaUHboM3wx5CHsyj3MON414mYWbAgVY7rEnO3FJaqBrSBRAjYBzMrboxxM18pscVkKOZZISTAqbn1kSZwoon6BNBM+WLvEGsxBKmizhqYNtBlsaL3KhruQ7CSedSztZ3m0hKVr/WVfRtM4AabRFZZ6CMzwmgvLTMNUOM6r4K05o+84RyulKa4BqEwoIZEMjASH8g4SRCKmhidlXpIgSJq4YnSTBgelt6Voz66zYI41FtwTLICuWDCdz6NoV8eyV0WbbpOin38jRbv6uNKvosefRtEADj1GG02Kfvl9FA3AwGM0cDSwq26XMH/DnO/VGgxtOBUmynhMI5qi5JXSlbqOIxZh/gMzIvqImUSVpJGohJI4umE+bqoUTbl6giPzxTQolWrxESDshb6mBVHj+B5ehAVnONAWcTXGhP+Hbp0BSmUUmW8X0zhdAgwnIpH+qHakfTo9fTwS3s9VUQVFI8N1/M+SVSXnLOnXKucuGM7SmhsYVk1/UJLy4+BgOrXJzqrFvCIja1XTSdGNG6Qzfkinc+mM+5EOhL1Kp80XDpeyojPETr3nyUs7M7VpO1VEh17RWhrE80yUwHjqIF1imUu35EshTXlH7HhWlZyhF7rQ0Ci446Ez9Hzsn4ywhWdbttHu0Gn3lVddOXS6/c660HxIp2vpdJawVecIYPQsnROz7EM6LUunn4Stb+nYPSZszcROqsS2m7AN/cJWf/ddJGyTu0jY2mSnnrAN/R43Xx99jqEzsLEXWKcizAML6DjtDp3joRM2szp0wp5nXeshna6l01HCBj3j/KyrEO5MOvZDOp1L59aE7aZ5pc/twXP4T8r4t5pXDb5taOrbhkViNb2LxKpNemqJ1eDbidDT2Hklh01dGo6Ak0gkF0ycRfKsIO5vKr/i1Oo7oNMXwGJ2G5/Vj9Sq5BqHv3bIHXsVcvM147b8oWmf3Oqj2xlu5V4+SbNvBx8EN3wPYBmXGDZBn+FrXfFiIBJYrRqdr37SOSq6+gszjlvL0ixPQ6XI3CqogK5Q0aecJynqwwfkEhwhMJSs5W3SN+F8JnkZFMJt/x1zWRUKAYn8JUYyYFIRDodawu4wBFxPHsquEsfxtRFxRneNkgA1RehR4vQaJaamhy/3QqOiC0Cd1pkpj054LFFl9cqUvm36x4OpKyKuCKj2mRPF469asqX18adB8Pl/ \ No newline at end of file From 534daee1a5764b3fd2cd167c94430f26b9c734c2 Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Wed, 16 Jan 2019 17:47:00 +0100 Subject: [PATCH 15/16] Removed reference to bibtex sphinx extension, not necessary so far Also updated year in config file --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 2f9a7eb..7854207 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,7 @@ # -- Project information ----------------------------------------------------- project = 'pyDTNsim' -copyright = '2018, Robert Wiewel' +copyright = '2019, Robert Wiewel' author = 'Robert Wiewel' # The short X.Y version @@ -43,8 +43,8 @@ 'sphinx.ext.doctest', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', - 'sphinxcontrib.bibtex', 'sphinx.ext.napoleon', +# 'sphinxcontrib.bibtex', ] # Add any paths that contain templates here, relative to this directory. From 8b54ab947300c7579948ff2593b0a8584d385b4f Mon Sep 17 00:00:00 2001 From: Robert Wiewel Date: Mon, 11 Feb 2019 20:39:07 +0100 Subject: [PATCH 16/16] Added tip box about pyenv and pipenv to sphinx doc. --- docs/install.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/install.rst b/docs/install.rst index e54c28e..58a36e2 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -133,3 +133,11 @@ Check if the module was installed correctly by invoking a Python shell and impor > import pydtnsim If no error occurs, the installation was successful. Continue ith the section :ref:`getting_started`. + +.. tip:: + + A recommendation in general, but a must in the context of upstream development is the use of the environment wrappers `pyenv `_ (for the version of the Python interpreter) and `pipenv `_ (for the Pip package environment). The configuration files for *pipenv* are provided (``Pipfile`` and ``Pipfile.lock``) and contain also the requirements for *pyenv*. + + In combination, the wrappers ensure a sound and deterministic development environment for all developers by installing clearly specified versions and encapsulating them from the other python (package) installations on the systems. An article outlining the benefits of the wrappers can be found at [#]_. + +.. [#] https://hackernoon.com/reaching-python-development-nirvana-bb5692adf30c?gi=26b62f02bc0b