From 36fdb0c6171270511f6a3fbd0994b9923ecded5e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 18 Dec 2017 09:28:41 -0800 Subject: [PATCH 001/152] updated assignment of copyright file name to add to dist file --- ...OF COPYRIGHT .pdf => ASSIGNMENT_OF_COPYRIGHT.pdf | Bin Makefile.am | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) rename ASSIGNMENT OF COPYRIGHT .pdf => ASSIGNMENT_OF_COPYRIGHT.pdf (100%) diff --git a/ASSIGNMENT OF COPYRIGHT .pdf b/ASSIGNMENT_OF_COPYRIGHT.pdf similarity index 100% rename from ASSIGNMENT OF COPYRIGHT .pdf rename to ASSIGNMENT_OF_COPYRIGHT.pdf diff --git a/Makefile.am b/Makefile.am index 9c49a312..98a3b129 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,7 +23,9 @@ SUBDIRS = ${GUI} ${DAEMON} ${DOCS} ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball -EXTRA_DIST = bootstrap.sh LICENSE README-Xen Changelog kernel \ +EXTRA_DIST = bootstrap.sh LICENSE \ + README.rst ASSIGNMENT_OF_COPYRIGHT.pdf \ + README-Xen Changelog kernel \ python-prefix.py revision.sh \ .version .version.date \ packaging/bsd \ From 7e217b4d6168bb3cc5f918c7f9181dc7c81356b8 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 18 Dec 2017 09:29:12 -0800 Subject: [PATCH 002/152] updated pngmath to imgmath in the sphinx conf file, pngmath was deprecated --- doc/conf.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py.in b/doc/conf.py.in index 6dab9d64..34655128 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -26,7 +26,7 @@ import sphinx_rtd_theme # 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.todo', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.imgmath', 'sphinx.ext.ifconfig'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] From d3210815ab54b9b994754686c016f32895d9d5d4 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 18 Dec 2017 15:50:28 -0800 Subject: [PATCH 003/152] updated email in python setup.py files, shifted test dependency together --- daemon/ns3/setup.py | 2 +- daemon/setup.py | 6 ++---- daemon/src/setup.py | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/daemon/ns3/setup.py b/daemon/ns3/setup.py index 811f5adb..a1d824a8 100644 --- a/daemon/ns3/setup.py +++ b/daemon/ns3/setup.py @@ -9,7 +9,7 @@ setup( description="Python ns-3 components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", author="Boeing Research & Technology", - author_email="core-dev@pf.itd.nrl.navy.mil", + author_email="core-dev@nrl.navy.mil", license="GPLv2", long_description="Python scripts and modules for building virtual simulated networks." ) diff --git a/daemon/setup.py b/daemon/setup.py index 7d8f1c32..c2c4cd18 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -23,17 +23,15 @@ setup(name="core-python", "enum34", "logzero" ], - setup_requires=[ - "pytest-runner" - ], tests_require=[ "pytest", + "pytest-runner" "pytest-cov", "mock" ], description="Python components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", author="Boeing Research & Technology", - author_email="core-dev@pf.itd.nrl.navy.mil", + author_email="core-dev@nrl.navy.mil", license="BSD", long_description="Python scripts and modules for building virtual emulated networks.") diff --git a/daemon/src/setup.py b/daemon/src/setup.py index b653f51b..79151cc2 100644 --- a/daemon/src/setup.py +++ b/daemon/src/setup.py @@ -36,7 +36,7 @@ setup( ], url="http://www.nrl.navy.mil/itd/ncs/products/core", author="Boeing Research & Technology", - author_email="core-dev@pf.itd.nrl.navy.mil", + author_email="core-dev@nrl.navy.mil", license="BSD", long_description="Extension modules and utilities to support virtual " "nodes using Linux network namespaces" From 58c6d03bc4f86187a768ca7a1e858f18ae119aea Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 19 Dec 2017 09:43:19 -0800 Subject: [PATCH 004/152] updates to target building separate packages with fpm --- Makefile.am | 52 ++++++++++++++++++++++++++++++++++++ daemon/ns3/setup.py | 2 +- daemon/setup.py | 64 +++++++++++++++++++++++---------------------- daemon/src/setup.py | 8 +++--- 4 files changed, 89 insertions(+), 37 deletions(-) diff --git a/Makefile.am b/Makefile.am index 98a3b129..4919ac0b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,6 +72,58 @@ deb: @echo "First create source archive with: dpkg-source -b core-@CORE_VERSION@" @echo "Then build with: pbuilder-dist precise i386 build core*.dsc" +.PHONE: fpm +fpm: + fpm -s python -t rpm \ + -m "CORE Developers " \ + --vendor "CORE Developers" \ + daemon/setup.py + fpm -s python -t rpm \ + -m "CORE Developers " \ + --vendor "CORE Developers" \ + daemon/src/setup.py + fpm -s python -t rpm \ + -m "CORE Developers " \ + --vendor "CORE Developers" \ + daemon/ns3/setup.py + +.PHONY: fpm-deb +fpm-deb: + fpm -s dir -t deb -n core -v $(CORE_VERSION) -C "$DESTDIR" \ + -p core_VERSION_ARCH.deb \ + --license "BSD 2-clause" \ + --vendor "CORE Developers" \ + --description "Emulate virtual networks in a box." \ + --url http://www.nrl.navy.mil/itd/ncs/products/core \ + -m "CORE Developers " \ + -d "procps" \ + -d "libc6 >= 2.14" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute2" \ + -d "libev4" \ + -d "python >= 2.7" \ + --deb-recommends quagga + + +.PHONY: fpm-rpm +fpm-rpm: + fpm -s dir -t rpm -n core -v $(CORE_VERSION) -C "$DESTDIR" \ + -p core_VERSION_ARCH.rpm \ + --license "BSD 2-clause" \ + --vendor "CORE Developers" \ + --description "Emulate virtual networks in a box." \ + --url http://www.nrl.navy.mil/itd/ncs/products/core \ + -m "CORE Developers " \ + -d "procps" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute" \ + -d "libev" \ + -d "python >= 2.7" + .PHONY: core-restart core-restart: /etc/init.d/core-daemon stop diff --git a/daemon/ns3/setup.py b/daemon/ns3/setup.py index a1d824a8..e3f248ac 100644 --- a/daemon/ns3/setup.py +++ b/daemon/ns3/setup.py @@ -1,7 +1,7 @@ from setuptools import setup setup( - name="corens3-python", + name="core-ns3", version="5.0", packages=[ "corens3", diff --git a/daemon/setup.py b/daemon/setup.py index c2c4cd18..7aa128cf 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -4,34 +4,36 @@ Defines how CORE will be built for installation. from setuptools import setup -setup(name="core-python", - version="5.0", - packages=[ - "core", - "core.addons", - "core.api", - "core.bsd", - "core.emane", - "core.misc", - "core.netns", - "core.phys", - "core.services", - "core.xen", - "core.xml", - ], - install_requires=[ - "enum34", - "logzero" - ], - tests_require=[ - "pytest", - "pytest-runner" - "pytest-cov", - "mock" - ], - description="Python components of CORE", - url="http://www.nrl.navy.mil/itd/ncs/products/core", - author="Boeing Research & Technology", - author_email="core-dev@nrl.navy.mil", - license="BSD", - long_description="Python scripts and modules for building virtual emulated networks.") +setup( + name="core", + version="5.0", + packages=[ + "core", + "core.addons", + "core.api", + "core.bsd", + "core.emane", + "core.misc", + "core.netns", + "core.phys", + "core.services", + "core.xen", + "core.xml", + ], + install_requires=[ + "enum34", + "logzero" + ], + tests_require=[ + "pytest", + "pytest-runner" + "pytest-cov", + "mock" + ], + description="Python components of CORE", + url="http://www.nrl.navy.mil/itd/ncs/products/core", + author="Boeing Research & Technology", + author_email="core-dev@nrl.navy.mil", + license="BSD", + long_description="Python scripts and modules for building virtual emulated networks." +) diff --git a/daemon/src/setup.py b/daemon/src/setup.py index 79151cc2..60819916 100644 --- a/daemon/src/setup.py +++ b/daemon/src/setup.py @@ -26,10 +26,9 @@ vcmd = Extension( ) setup( - name="core-python-netns", + name="core-netns", version="1.0", - description="Extension modules to support virtual nodes using " - "Linux network namespaces", + description="Extension modules to support virtual nodes using Linux network namespaces", ext_modules=[ netns, vcmd @@ -38,6 +37,5 @@ setup( author="Boeing Research & Technology", author_email="core-dev@nrl.navy.mil", license="BSD", - long_description="Extension modules and utilities to support virtual " - "nodes using Linux network namespaces" + long_description="Extension modules and utilities to support virtual nodes using Linux network namespaces" ) From 59e6b6630ab3bafa51806e3325fbdae92cc26d62 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 21 Dec 2017 16:19:12 -0800 Subject: [PATCH 005/152] added initial fpm commands for building packages and minor updates to support --- .gitignore | 7 +++ Makefile.am | 103 +++++++++++++++++++----------------- configure.ac | 4 ++ daemon/core/constants.py.in | 2 +- daemon/setup.py | 22 ++++++-- daemon/src/Makefile.am | 2 +- daemon/src/setup.py | 1 + gui/Makefile.am | 1 - 8 files changed, 87 insertions(+), 55 deletions(-) diff --git a/.gitignore b/.gitignore index 448f711a..3e9cd0b7 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,10 @@ stamp-h1 # ignore test coverage files coverage.xml + +# python files +*.egg-info + +# ignore package files +*.rpm +*.deb diff --git a/Makefile.am b/Makefile.am index 4919ac0b..ca3b2b23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -72,57 +72,62 @@ deb: @echo "First create source archive with: dpkg-source -b core-@CORE_VERSION@" @echo "Then build with: pbuilder-dist precise i386 build core*.dsc" -.PHONE: fpm + +define fpm-python = +fpm -s python -t $1 \ + -m "$(CORE_MAINTAINERS)" \ + --vendor "$(CORE_VENDOR)" \ + $2 +endef + +define fpm-gui = +fpm -s dir -t $1 -n core-gui \ + -m "$(CORE_MAINTAINERS)" \ + --license "BSD" \ + --description "Common Open Research Emulator GUI front-end" \ + --url http://www.nrl.navy.mil/itd/ncs/products/core \ + --vendor "$(CORE_VENDOR)" \ + -p core-gui_VERSION_ARCH.$1 \ + -v $(CORE_VERSION) \ + -d "bash" \ + -d "tcl" \ + -d "tk" \ + $2 \ + -C $(DESTDIR) +endef + +.PHONY: fpm fpm: + rm -f *.deb && rm -f *.rpm + $(call fpm-gui,rpm,-d "tkimg") + $(call fpm-gui,deb,-d "libtk-img") + $(call fpm-python,rpm,daemon/ns3/setup.py) + $(call fpm-python,deb,daemon/ns3/setup.py) fpm -s python -t rpm \ - -m "CORE Developers " \ - --vendor "CORE Developers" \ - daemon/setup.py - fpm -s python -t rpm \ - -m "CORE Developers " \ - --vendor "CORE Developers" \ - daemon/src/setup.py - fpm -s python -t rpm \ - -m "CORE Developers " \ - --vendor "CORE Developers" \ - daemon/ns3/setup.py - -.PHONY: fpm-deb -fpm-deb: - fpm -s dir -t deb -n core -v $(CORE_VERSION) -C "$DESTDIR" \ - -p core_VERSION_ARCH.deb \ - --license "BSD 2-clause" \ - --vendor "CORE Developers" \ - --description "Emulate virtual networks in a box." \ - --url http://www.nrl.navy.mil/itd/ncs/products/core \ - -m "CORE Developers " \ - -d "procps" \ - -d "libc6 >= 2.14" \ - -d "bash >= 3.0" \ - -d "bridge-utils" \ - -d "ebtables" \ - -d "iproute2" \ - -d "libev4" \ - -d "python >= 2.7" \ - --deb-recommends quagga - - -.PHONY: fpm-rpm -fpm-rpm: - fpm -s dir -t rpm -n core -v $(CORE_VERSION) -C "$DESTDIR" \ - -p core_VERSION_ARCH.rpm \ - --license "BSD 2-clause" \ - --vendor "CORE Developers" \ - --description "Emulate virtual networks in a box." \ - --url http://www.nrl.navy.mil/itd/ncs/products/core \ - -m "CORE Developers " \ - -d "procps" \ - -d "bash >= 3.0" \ - -d "bridge-utils" \ - -d "ebtables" \ - -d "iproute" \ - -d "libev" \ - -d "python >= 2.7" + -m "$(CORE_MAINTAINERS)" \ + --vendor "$(CORE_VENDOR)" \ + -d "procps-ng" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute" \ + -d "libev" \ + -d "net-tools" \ + -d "python >= 2.7, python < 3.0" \ + daemon/src/setup.py daemon/setup.py + fpm -s python -t deb \ + -m "$(CORE_MAINTAINERS)" \ + --vendor "$(CORE_VENDOR)" \ + -d "procps" \ + -d "libc6 >= 2.14" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute2" \ + -d "libev4" \ + -d "python (>= 2.7), python (<< 3.0)" \ + --deb-recommends quagga \ + daemon/src/setup.py daemon/setup.py .PHONY: core-restart core-restart: diff --git a/configure.ac b/configure.ac index a1f0ad6c..8227c1f5 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,8 @@ VERSION=$PACKAGE_VERSION CORE_VERSION=$PACKAGE_VERSION CORE_VERSION_DATE=m4_esyscmd_s([./revision.sh -d]) COREDPY_VERSION=$PACKAGE_VERSION +CORE_MAINTAINERS="CORE Developers " +CORE_VENDOR="CORE Developers" # # autoconf and automake initialization @@ -30,6 +32,8 @@ AM_INIT_AUTOMAKE([tar-ustar]) AC_SUBST(CORE_VERSION) AC_SUBST(CORE_VERSION_DATE) AC_SUBST(COREDPY_VERSION) +AC_SUBST(CORE_MAINTAINERS) +AC_SUBST(CORE_VENDOR) # # some of the following directory variables are not expanded at configure-time, diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index 674c0dc7..f5d05780 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -4,7 +4,7 @@ CORE_STATE_DIR = "@CORE_STATE_DIR@" CORE_CONF_DIR = "@CORE_CONF_DIR@" CORE_DATA_DIR = "@CORE_DATA_DIR@" CORE_LIB_DIR = "@CORE_LIB_DIR@" -CORE_SBIN_DIR = "@SBINDIR@" +CORE_SBIN_DIR = "@BINDIR@" BRCTL_BIN = "@brctl_path@/brctl" SYSCTL_BIN = "@sysctl_path@/sysctl" diff --git a/daemon/setup.py b/daemon/setup.py index 7aa128cf..78636c30 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -22,13 +22,29 @@ setup( ], install_requires=[ "enum34", - "logzero" + #"logzero", ], tests_require=[ "pytest", - "pytest-runner" + "pytest-runner", "pytest-cov", - "mock" + "mock", + ], + data_files=[ + ("/etc/core", [ + "data/core.conf", + "data/xen.conf", + ]), + ("/etc/init.d", [ + "../scripts/core-daemon", + ]), + ], + scripts=[ + "sbin/core-cleanup", + "sbin/core-daemon", + "sbin/core-manage", + "sbin/coresendmsg", + "sbin/core-xen-cleanup", ], description="Python components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", diff --git a/daemon/src/Makefile.am b/daemon/src/Makefile.am index 0cec0814..131d593f 100644 --- a/daemon/src/Makefile.am +++ b/daemon/src/Makefile.am @@ -34,7 +34,7 @@ netns_SOURCES = ${SRC_NETNS} noinst_LIBRARIES = libnetns.a libnetns_a_SOURCES = netnsmodule.c vcmdmodule.c libnetns.a: - SBINDIR=@SBINDIR@ LDFLAGS="$(LDFLAGS) @libev_LIBS@" CFLAGS="$(CFLAGS) @libev_CFLAGS@" $(PYTHON) setup.py build + SBINDIR=@SBINDIR@ LDFLAGS="$(LDFLAGS) @libev_LIBS@" CFLAGS="$(CFLAGS) @libev_CFLAGS@" $(PYTHON) setup.py build_ext # Python libraries install install-exec-local: diff --git a/daemon/src/setup.py b/daemon/src/setup.py index 60819916..1c111062 100644 --- a/daemon/src/setup.py +++ b/daemon/src/setup.py @@ -29,6 +29,7 @@ setup( name="core-netns", version="1.0", description="Extension modules to support virtual nodes using Linux network namespaces", + scripts=["vcmd", "vnoded", "netns"], ext_modules=[ netns, vcmd diff --git a/gui/Makefile.am b/gui/Makefile.am index 9846d935..25c494fd 100644 --- a/gui/Makefile.am +++ b/gui/Makefile.am @@ -59,7 +59,6 @@ dist_coreaddons_DATA = $(ADDONS_FILES) coreconfigsdir = $(datadir)/core/examples/configs dist_coreconfigs_DATA = $(CONFIG_FILES) - dist-hook: rm -rf $(distdir)/addons/.svn From 742ad0e3a22d6bab11bef2a49a22b64b50c5fa79 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 3 Jan 2018 10:53:34 -0800 Subject: [PATCH 006/152] removed the usage of logzero, added a formal logging configuration file using json --- daemon/core/__init__.py | 19 ++++++++++++------- daemon/data/logging.conf | 20 ++++++++++++++++++++ daemon/setup.py | 2 +- 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 daemon/data/logging.conf diff --git a/daemon/core/__init__.py b/daemon/core/__init__.py index 61f36a41..04688678 100644 --- a/daemon/core/__init__.py +++ b/daemon/core/__init__.py @@ -1,9 +1,14 @@ -import logzero +import json +import logging +import logging.config +import os -# configure custom format with function name -_format_template = "%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(funcName)s:" \ - "%(lineno)d]%(end_color)s %(message)s" -_formatter = logzero.LogFormatter(fmt=_format_template) -logzero.formatter(_formatter) +from core import constants -logger = logzero.logger +log_config_path = os.path.join(constants.CORE_CONF_DIR, "logging.conf") +with open(log_config_path, "r") as log_config_file: + log_config = json.load(log_config_file) + logging.config.dictConfig(log_config) + +#logging.basicConfig(format="%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s", level=logging.DEBUG) +logger = logging.getLogger() diff --git a/daemon/data/logging.conf b/daemon/data/logging.conf new file mode 100644 index 00000000..46de6e92 --- /dev/null +++ b/daemon/data/logging.conf @@ -0,0 +1,20 @@ +{ + "version": 1, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "formatter": "default", + "level": "DEBUG", + "stream": "ext://sys.stdout" + } + }, + "formatters": { + "default": { + "format": "%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s" + } + }, + "root": { + "level": "DEBUG", + "handlers": ["console"] + } +} diff --git a/daemon/setup.py b/daemon/setup.py index 78636c30..7e73f297 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -22,7 +22,6 @@ setup( ], install_requires=[ "enum34", - #"logzero", ], tests_require=[ "pytest", @@ -34,6 +33,7 @@ setup( ("/etc/core", [ "data/core.conf", "data/xen.conf", + "data/logging.conf", ]), ("/etc/init.d", [ "../scripts/core-daemon", From e4c3d9d13a7a92683c43adfd29bb6de1d1d4cd5e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 3 Jan 2018 13:45:19 -0800 Subject: [PATCH 007/152] updated daemon setup.py to leverage find_packages --- daemon/setup.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/daemon/setup.py b/daemon/setup.py index 7e73f297..dfe75c57 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -2,24 +2,12 @@ Defines how CORE will be built for installation. """ -from setuptools import setup +from setuptools import setup, find_packages setup( name="core", version="5.0", - packages=[ - "core", - "core.addons", - "core.api", - "core.bsd", - "core.emane", - "core.misc", - "core.netns", - "core.phys", - "core.services", - "core.xen", - "core.xml", - ], + packages=find_packages(), install_requires=[ "enum34", ], From afb6af5f87bf185d08088eebc9b8212c57ca4b26 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 3 Jan 2018 14:40:45 -0800 Subject: [PATCH 008/152] removed old olog format line --- daemon/core/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/daemon/core/__init__.py b/daemon/core/__init__.py index 04688678..e8899fc7 100644 --- a/daemon/core/__init__.py +++ b/daemon/core/__init__.py @@ -5,10 +5,12 @@ import os from core import constants + +# setup logging log_config_path = os.path.join(constants.CORE_CONF_DIR, "logging.conf") with open(log_config_path, "r") as log_config_file: log_config = json.load(log_config_file) logging.config.dictConfig(log_config) -#logging.basicConfig(format="%(asctime)s - %(levelname)s - %(module)s:%(funcName)s - %(message)s", level=logging.DEBUG) logger = logging.getLogger() + From 42bcb1c79d5dca2e21f3cd2cae2211fe02df68fd Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 4 Jan 2018 08:19:34 -0800 Subject: [PATCH 009/152] add default node map configuration, to avoid the need to set this up every time --- daemon/core/misc/nodeutils.py | 21 +++++++++++++++++-- daemon/core/session.py | 6 ++++++ daemon/examples/netns/basicrange.py | 7 +------ daemon/examples/netns/daemonnodes.py | 6 +----- daemon/examples/netns/distributed.py | 6 +----- daemon/examples/netns/emane80211.py | 6 +----- daemon/examples/netns/howmanynodes.py | 6 +----- .../examples/netns/iperf-performance-chain.py | 6 +----- daemon/examples/netns/ospfmanetmdrtest.py | 6 +----- daemon/examples/netns/switch.py | 6 +----- daemon/examples/netns/switchtest.py | 6 +----- daemon/examples/netns/wlanemanetests.py | 6 +----- daemon/examples/netns/wlantest.py | 6 +----- daemon/sbin/core-daemon | 7 ++----- 14 files changed, 38 insertions(+), 63 deletions(-) diff --git a/daemon/core/misc/nodeutils.py b/daemon/core/misc/nodeutils.py index eadd42c2..503daaa3 100644 --- a/daemon/core/misc/nodeutils.py +++ b/daemon/core/misc/nodeutils.py @@ -9,6 +9,12 @@ from core import logger _NODE_MAP = None +def _log_map(): + global _NODE_MAP + print_map = reduce(lambda x, y: _convert_map(x, y), _NODE_MAP.items(), {}) + logger.info("node class map: \n%s", pprint.pformat(print_map, indent=4)) + + def _convert_map(x, y): """ Convenience method to create a human readable version of the node map to log. @@ -21,6 +27,18 @@ def _convert_map(x, y): return x +def update_node_map(node_map): + """ + Update the current node map with the provided node map values. + + + :param dict node_map: node map to update with + """ + global _NODE_MAP + _NODE_MAP.update(node_map) + _log_map() + + def set_node_map(node_map): """ Set the global node map that proides a consistent way to retrieve differently configured nodes. @@ -29,9 +47,8 @@ def set_node_map(node_map): :return: nothing """ global _NODE_MAP - print_map = reduce(lambda x, y: _convert_map(x, y), node_map.items(), {}) - logger.info("setting node class map: \n%s", pprint.pformat(print_map, indent=4)) _NODE_MAP = node_map + _log_map() def get_node_class(node_type): diff --git a/daemon/core/session.py b/daemon/core/session.py index 175e00c3..aba53711 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -35,6 +35,7 @@ from core.enumerations import MessageFlags from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.location import CoreLocation +from core.misc import nodemaps from core.misc import nodeutils from core.misc import utils from core.misc.event import EventLoop @@ -49,6 +50,11 @@ from core.xen.xenconfig import XenConfigManager from core.xml.xmlsession import save_session_xml +# set default node map +node_map = nodemaps.NODES +nodeutils.set_node_map(node_map) + + class SessionManager(object): """ Manages currently known sessions. diff --git a/daemon/examples/netns/basicrange.py b/daemon/examples/netns/basicrange.py index ecf6db28..b1fdd2f8 100755 --- a/daemon/examples/netns/basicrange.py +++ b/daemon/examples/netns/basicrange.py @@ -13,8 +13,7 @@ import optparse import sys import time -from core.misc import ipaddress, nodeutils -from core.misc import nodemaps +from core.misc import ipaddress from core.mobility import BasicRangeModel from core.netns.nodes import WlanNode from core.netns.vnet import EbtablesQueue @@ -108,8 +107,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/daemonnodes.py b/daemon/examples/netns/daemonnodes.py index daad6c2d..2f8b7f81 100755 --- a/daemon/examples/netns/daemonnodes.py +++ b/daemon/examples/netns/daemonnodes.py @@ -25,7 +25,7 @@ from core.enumerations import LinkTlvs from core.enumerations import LinkTypes from core.enumerations import MessageFlags from core.enumerations import MessageTypes -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes # declare classes for use with Broker @@ -187,8 +187,4 @@ def main(): if __name__ == "__main__" or __name__ == "__builtin__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index b8e392f0..81cc7e3f 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -16,7 +16,7 @@ import sys from core import constants from core.api import coreapi, dataconversion from core.enumerations import CORE_API_PORT, EventTypes, EventTlvs, LinkTlvs, LinkTypes, MessageFlags -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes from core.session import Session @@ -124,8 +124,4 @@ def main(): if __name__ == "__main__" or __name__ == "__builtin__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/emane80211.py b/daemon/examples/netns/emane80211.py index 4dae69d0..e1874158 100755 --- a/daemon/examples/netns/emane80211.py +++ b/daemon/examples/netns/emane80211.py @@ -13,7 +13,7 @@ import sys from core import constants from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.nodes import EmaneNode -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes # node list (count from 1) @@ -100,8 +100,4 @@ def main(): if __name__ == "__main__" or __name__ == "__builtin__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/howmanynodes.py b/daemon/examples/netns/howmanynodes.py index 3387af6d..8803d872 100755 --- a/daemon/examples/netns/howmanynodes.py +++ b/daemon/examples/netns/howmanynodes.py @@ -20,7 +20,7 @@ import sys import time from core import constants -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes from core.session import Session @@ -206,8 +206,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/iperf-performance-chain.py b/daemon/examples/netns/iperf-performance-chain.py index cd9081a1..e946f727 100755 --- a/daemon/examples/netns/iperf-performance-chain.py +++ b/daemon/examples/netns/iperf-performance-chain.py @@ -19,7 +19,7 @@ import optparse import sys from core import constants -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes # node list (count from 1) @@ -100,8 +100,4 @@ def main(): if __name__ == "__main__" or __name__ == "__builtin__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/ospfmanetmdrtest.py b/daemon/examples/netns/ospfmanetmdrtest.py index 3a6c8b8b..f51d1e91 100755 --- a/daemon/examples/netns/ospfmanetmdrtest.py +++ b/daemon/examples/netns/ospfmanetmdrtest.py @@ -16,7 +16,7 @@ import time from string import Template from core.constants import QUAGGA_STATE_DIR -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.misc.utils import mutecall from core.netns import nodes @@ -602,8 +602,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - me = main() diff --git a/daemon/examples/netns/switch.py b/daemon/examples/netns/switch.py index 97d517e3..64137f36 100755 --- a/daemon/examples/netns/switch.py +++ b/daemon/examples/netns/switch.py @@ -10,7 +10,7 @@ import optparse import sys from core import constants -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.netns import nodes # node list (count from 1) @@ -73,8 +73,4 @@ def main(): if __name__ == "__main__" or __name__ == "__builtin__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/switchtest.py b/daemon/examples/netns/switchtest.py index c33ac09f..524ae2b0 100755 --- a/daemon/examples/netns/switchtest.py +++ b/daemon/examples/netns/switchtest.py @@ -12,7 +12,7 @@ import datetime import optparse import sys -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.misc.utils import mutecall from core.netns import nodes from core.session import Session @@ -101,8 +101,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/wlanemanetests.py b/daemon/examples/netns/wlanemanetests.py index 2f4b29d8..60ad31d2 100755 --- a/daemon/examples/netns/wlanemanetests.py +++ b/daemon/examples/netns/wlanemanetests.py @@ -41,7 +41,7 @@ from core import emane from core.emane.bypass import EmaneBypassModel from core.emane.nodes import EmaneNode from core.emane.rfpipe import EmaneRfPipeModel -from core.misc import ipaddress, nodemaps, nodeutils +from core.misc import ipaddress from core.netns import nodes from core.session import Session @@ -851,8 +851,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/examples/netns/wlantest.py b/daemon/examples/netns/wlantest.py index fc046fdb..70892d1b 100755 --- a/daemon/examples/netns/wlantest.py +++ b/daemon/examples/netns/wlantest.py @@ -12,7 +12,7 @@ import datetime import optparse import sys -from core.misc import ipaddress, nodeutils, nodemaps +from core.misc import ipaddress from core.misc.utils import mutecall from core.netns import nodes from core.session import Session @@ -99,8 +99,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - main() diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index 59fbb861..b47ec8f5 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -336,17 +336,14 @@ def main(): if __name__ == "__main__": # configure nodes to use - node_map = nodemaps.NODES if len(sys.argv) == 2 and sys.argv[1] == "ovs": from core.netns.openvswitch import OVS_NODES - node_map.update(OVS_NODES) + nodeutils.update_node_map(OVS_NODES) # update with BSD based nodes if os.uname()[0] == "FreeBSD": from core.bsd.nodes import BSD_NODES - node_map.update(BSD_NODES) - - nodeutils.set_node_map(node_map) + nodeutils.update_node_map(BSD_NODES) # load default services services.load() From e4a0069bc30dd4911250b6e1872a409e5cb554d4 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 4 Jan 2018 10:09:35 -0800 Subject: [PATCH 010/152] updated configuration to define the core bin dir within constants, updated code to use the core bin dir for vnoded and vcmd, based on using the fpm build system --- Makefile.am | 10 ++++++++-- daemon/core/constants.py.in | 3 ++- daemon/core/netns/vnode.py | 2 +- daemon/core/netns/vnodeclient.py | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index ca3b2b23..cd861141 100644 --- a/Makefile.am +++ b/Makefile.am @@ -97,8 +97,7 @@ fpm -s dir -t $1 -n core-gui \ endef .PHONY: fpm -fpm: - rm -f *.deb && rm -f *.rpm +fpm: clean-local-fpm $(call fpm-gui,rpm,-d "tkimg") $(call fpm-gui,deb,-d "libtk-img") $(call fpm-python,rpm,daemon/ns3/setup.py) @@ -129,6 +128,11 @@ fpm: --deb-recommends quagga \ daemon/src/setup.py daemon/setup.py +.PHONY: clean-local-fpm +clean-local-fpm: + -rm -rf *.deb + -rm -rf *.rpm + .PHONY: core-restart core-restart: /etc/init.d/core-daemon stop @@ -136,6 +140,8 @@ core-restart: rm -f /var/log/core-daemon.log /etc/init.d/core-daemon start +clean-local: clean-local-fpm + .version: Makefile echo $(CORE_VERSION) > $@ diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index f5d05780..1e5db2b6 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -4,7 +4,8 @@ CORE_STATE_DIR = "@CORE_STATE_DIR@" CORE_CONF_DIR = "@CORE_CONF_DIR@" CORE_DATA_DIR = "@CORE_DATA_DIR@" CORE_LIB_DIR = "@CORE_LIB_DIR@" -CORE_SBIN_DIR = "@BINDIR@" +CORE_SBIN_DIR = "@SBINDIR@" +CORE_BIN_DIR = "@BINDIR@" BRCTL_BIN = "@brctl_path@/brctl" SYSCTL_BIN = "@sysctl_path@/sysctl" diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 3f50d028..3879c5e1 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -73,7 +73,7 @@ class SimpleLxcNode(PyCoreNode): """ if self.up: raise Exception("already up") - vnoded = ["%s/vnoded" % constants.CORE_SBIN_DIR, "-v", "-c", self.ctrlchnlname, + vnoded = ["%s/vnoded" % constants.CORE_BIN_DIR, "-v", "-c", self.ctrlchnlname, "-l", self.ctrlchnlname + ".log", "-p", self.ctrlchnlname + ".pid"] if self.nodedir: diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index f20fd739..1d5fb05f 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -17,7 +17,7 @@ USE_VCMD_MODULE = True if USE_VCMD_MODULE: import vcmd -VCMD = os.path.join(constants.CORE_SBIN_DIR, "vcmd") +VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd") class VnodeClient(object): From d799390c4aee122dc6cf270bf5f16c5b29c4cdc6 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 4 Jan 2018 12:03:14 -0800 Subject: [PATCH 011/152] moved netns code from daemon/src to netns at the top level, updated files to account for location change --- Makefile.am | 9 ++++++--- configure.ac | 6 +++--- daemon/Makefile.am | 2 +- daemon/requirements.txt | 3 --- doc/devguide.rst | 2 +- doc/man/Makefile.am | 6 +++--- {daemon/src => netns}/.gitignore | 0 {daemon/src => netns}/MANIFEST.in | 0 {daemon/src => netns}/Makefile.am | 0 {daemon/src => netns}/myerr.h | 0 {daemon/src => netns}/netns.c | 0 {daemon/src => netns}/netns.h | 0 {daemon/src => netns}/netns_main.c | 0 {daemon/src => netns}/netnsmodule.c | 0 {daemon/src => netns}/setup.py | 0 {daemon/src => netns}/vcmd_main.c | 0 {daemon/src => netns}/vcmdmodule.c | 0 {daemon/src => netns}/version.h.in | 0 {daemon/src => netns}/vnode_chnl.c | 0 {daemon/src => netns}/vnode_chnl.h | 0 {daemon/src => netns}/vnode_client.c | 0 {daemon/src => netns}/vnode_client.h | 0 {daemon/src => netns}/vnode_cmd.c | 0 {daemon/src => netns}/vnode_cmd.h | 0 {daemon/src => netns}/vnode_io.c | 0 {daemon/src => netns}/vnode_io.h | 0 {daemon/src => netns}/vnode_msg.c | 0 {daemon/src => netns}/vnode_msg.h | 0 {daemon/src => netns}/vnode_server.c | 0 {daemon/src => netns}/vnode_server.h | 0 {daemon/src => netns}/vnode_tlv.h | 0 {daemon/src => netns}/vnoded_main.c | 0 32 files changed, 14 insertions(+), 14 deletions(-) rename {daemon/src => netns}/.gitignore (100%) rename {daemon/src => netns}/MANIFEST.in (100%) rename {daemon/src => netns}/Makefile.am (100%) rename {daemon/src => netns}/myerr.h (100%) rename {daemon/src => netns}/netns.c (100%) rename {daemon/src => netns}/netns.h (100%) rename {daemon/src => netns}/netns_main.c (100%) rename {daemon/src => netns}/netnsmodule.c (100%) rename {daemon/src => netns}/setup.py (100%) rename {daemon/src => netns}/vcmd_main.c (100%) rename {daemon/src => netns}/vcmdmodule.c (100%) rename {daemon/src => netns}/version.h.in (100%) rename {daemon/src => netns}/vnode_chnl.c (100%) rename {daemon/src => netns}/vnode_chnl.h (100%) rename {daemon/src => netns}/vnode_client.c (100%) rename {daemon/src => netns}/vnode_client.h (100%) rename {daemon/src => netns}/vnode_cmd.c (100%) rename {daemon/src => netns}/vnode_cmd.h (100%) rename {daemon/src => netns}/vnode_io.c (100%) rename {daemon/src => netns}/vnode_io.h (100%) rename {daemon/src => netns}/vnode_msg.c (100%) rename {daemon/src => netns}/vnode_msg.h (100%) rename {daemon/src => netns}/vnode_server.c (100%) rename {daemon/src => netns}/vnode_server.h (100%) rename {daemon/src => netns}/vnode_tlv.h (100%) rename {daemon/src => netns}/vnoded_main.c (100%) diff --git a/Makefile.am b/Makefile.am index cd861141..e1fe9021 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,9 +16,12 @@ endif if WANT_DAEMON DAEMON = scripts daemon endif +if WANT_NETNS + NETNS = netns +endif # keep docs last due to dependencies on binaries -SUBDIRS = ${GUI} ${DAEMON} ${DOCS} +SUBDIRS = ${GUI} ${DAEMON} ${DOCS} ${NETNS} ACLOCAL_AMFLAGS = -I config @@ -113,7 +116,7 @@ fpm: clean-local-fpm -d "libev" \ -d "net-tools" \ -d "python >= 2.7, python < 3.0" \ - daemon/src/setup.py daemon/setup.py + netns/setup.py daemon/setup.py fpm -s python -t deb \ -m "$(CORE_MAINTAINERS)" \ --vendor "$(CORE_VENDOR)" \ @@ -126,7 +129,7 @@ fpm: clean-local-fpm -d "libev4" \ -d "python (>= 2.7), python (<< 3.0)" \ --deb-recommends quagga \ - daemon/src/setup.py daemon/setup.py + netns/setup.py daemon/setup.py .PHONY: clean-local-fpm clean-local-fpm: diff --git a/configure.ac b/configure.ac index 8227c1f5..4bc5238f 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ CORE_VENDOR="CORE Developers" # # autoconf and automake initialization # -AC_CONFIG_SRCDIR([daemon/src/version.h.in]) +AC_CONFIG_SRCDIR([netns/version.h.in]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AC_CONFIG_HEADERS([config.h]) @@ -331,8 +331,8 @@ AC_CONFIG_FILES([Makefile doc/man/Makefile doc/figures/Makefile daemon/Makefile - daemon/src/Makefile - daemon/src/version.h + netns/Makefile + netns/version.h daemon/core/constants.py daemon/ns3/Makefile daemon/ns3/corens3/constants.py diff --git a/daemon/Makefile.am b/daemon/Makefile.am index cf903a44..4b1f589c 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -11,7 +11,7 @@ SETUPPY = setup.py SETUPPYFLAGS = -v if WANT_NETNS - SUBDIRS = src ns3 + SUBDIRS = ns3 endif SBIN_FILES = \ diff --git a/daemon/requirements.txt b/daemon/requirements.txt index 8d1241db..977eb416 100644 --- a/daemon/requirements.txt +++ b/daemon/requirements.txt @@ -1,7 +1,4 @@ enum34==1.1.6 -logzero==1.3.0 -grpcio==1.0.0 -grpcio-tools==1.0.0 mock==1.3.0 pycco==0.5.1 pytest==3.0.7 diff --git a/doc/devguide.rst b/doc/devguide.rst index e2f83e98..04fae329 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -34,7 +34,7 @@ These are being actively developed as of CORE |version|: project. * *daemon* - Python modules are found in the :file:`daemon/core` directory, the daemon under :file:`daemon/sbin/core-daemon`, and Python extension modules for - Linux Network Namespace support are in :file:`daemon/src`. + Linux Network Namespace support are in :file:`netns`. * *doc* - Documentation for the manual lives here in reStructuredText format. * *packaging* - Control files and script for building CORE packages are here. diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index d08c5445..5f688b2b 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -19,9 +19,9 @@ man_MANS = $(GUI_MANS) $(DAEMON_MANS) .PHONY: generate-mans generate-mans: $(HELP2MAN) --source CORE 'sh $(top_srcdir)/gui/core-gui' -o core-gui.1.new - $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vnoded -o vnoded.1.new - $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/vcmd -o vcmd.1.new - $(HELP2MAN) --no-info --source CORE $(top_srcdir)/daemon/src/netns -o netns.1.new + $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vnoded -o vnoded.1.new + $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vcmd -o vcmd.1.new + $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/netns -o netns.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new diff --git a/daemon/src/.gitignore b/netns/.gitignore similarity index 100% rename from daemon/src/.gitignore rename to netns/.gitignore diff --git a/daemon/src/MANIFEST.in b/netns/MANIFEST.in similarity index 100% rename from daemon/src/MANIFEST.in rename to netns/MANIFEST.in diff --git a/daemon/src/Makefile.am b/netns/Makefile.am similarity index 100% rename from daemon/src/Makefile.am rename to netns/Makefile.am diff --git a/daemon/src/myerr.h b/netns/myerr.h similarity index 100% rename from daemon/src/myerr.h rename to netns/myerr.h diff --git a/daemon/src/netns.c b/netns/netns.c similarity index 100% rename from daemon/src/netns.c rename to netns/netns.c diff --git a/daemon/src/netns.h b/netns/netns.h similarity index 100% rename from daemon/src/netns.h rename to netns/netns.h diff --git a/daemon/src/netns_main.c b/netns/netns_main.c similarity index 100% rename from daemon/src/netns_main.c rename to netns/netns_main.c diff --git a/daemon/src/netnsmodule.c b/netns/netnsmodule.c similarity index 100% rename from daemon/src/netnsmodule.c rename to netns/netnsmodule.c diff --git a/daemon/src/setup.py b/netns/setup.py similarity index 100% rename from daemon/src/setup.py rename to netns/setup.py diff --git a/daemon/src/vcmd_main.c b/netns/vcmd_main.c similarity index 100% rename from daemon/src/vcmd_main.c rename to netns/vcmd_main.c diff --git a/daemon/src/vcmdmodule.c b/netns/vcmdmodule.c similarity index 100% rename from daemon/src/vcmdmodule.c rename to netns/vcmdmodule.c diff --git a/daemon/src/version.h.in b/netns/version.h.in similarity index 100% rename from daemon/src/version.h.in rename to netns/version.h.in diff --git a/daemon/src/vnode_chnl.c b/netns/vnode_chnl.c similarity index 100% rename from daemon/src/vnode_chnl.c rename to netns/vnode_chnl.c diff --git a/daemon/src/vnode_chnl.h b/netns/vnode_chnl.h similarity index 100% rename from daemon/src/vnode_chnl.h rename to netns/vnode_chnl.h diff --git a/daemon/src/vnode_client.c b/netns/vnode_client.c similarity index 100% rename from daemon/src/vnode_client.c rename to netns/vnode_client.c diff --git a/daemon/src/vnode_client.h b/netns/vnode_client.h similarity index 100% rename from daemon/src/vnode_client.h rename to netns/vnode_client.h diff --git a/daemon/src/vnode_cmd.c b/netns/vnode_cmd.c similarity index 100% rename from daemon/src/vnode_cmd.c rename to netns/vnode_cmd.c diff --git a/daemon/src/vnode_cmd.h b/netns/vnode_cmd.h similarity index 100% rename from daemon/src/vnode_cmd.h rename to netns/vnode_cmd.h diff --git a/daemon/src/vnode_io.c b/netns/vnode_io.c similarity index 100% rename from daemon/src/vnode_io.c rename to netns/vnode_io.c diff --git a/daemon/src/vnode_io.h b/netns/vnode_io.h similarity index 100% rename from daemon/src/vnode_io.h rename to netns/vnode_io.h diff --git a/daemon/src/vnode_msg.c b/netns/vnode_msg.c similarity index 100% rename from daemon/src/vnode_msg.c rename to netns/vnode_msg.c diff --git a/daemon/src/vnode_msg.h b/netns/vnode_msg.h similarity index 100% rename from daemon/src/vnode_msg.h rename to netns/vnode_msg.h diff --git a/daemon/src/vnode_server.c b/netns/vnode_server.c similarity index 100% rename from daemon/src/vnode_server.c rename to netns/vnode_server.c diff --git a/daemon/src/vnode_server.h b/netns/vnode_server.h similarity index 100% rename from daemon/src/vnode_server.h rename to netns/vnode_server.h diff --git a/daemon/src/vnode_tlv.h b/netns/vnode_tlv.h similarity index 100% rename from daemon/src/vnode_tlv.h rename to netns/vnode_tlv.h diff --git a/daemon/src/vnoded_main.c b/netns/vnoded_main.c similarity index 100% rename from daemon/src/vnoded_main.c rename to netns/vnoded_main.c From 3da4c32825efe22b6ff1a64ddbc2d5593b7dde3b Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 4 Jan 2018 14:33:25 -0800 Subject: [PATCH 012/152] updated rpm/deb files to be built for both sysv and systemd --- Makefile.am | 64 ++++++++++++++++++++++++++++++------------------- daemon/setup.py | 35 +++++++++++++++++++++++---- netns/setup.py | 28 +++++++++++++++++++--- 3 files changed, 95 insertions(+), 32 deletions(-) diff --git a/Makefile.am b/Makefile.am index e1fe9021..cd250dea 100644 --- a/Makefile.am +++ b/Makefile.am @@ -99,37 +99,51 @@ fpm -s dir -t $1 -n core-gui \ -C $(DESTDIR) endef +define fpm-daemon-rpm = +fpm -s python -t rpm \ + -p NAME_$1_VERSION_ARCH.rpm \ + --python-setup-py-arguments --service=$1 \ + -m "$(CORE_MAINTAINERS)" \ + --vendor "$(CORE_VENDOR)" \ + -d "procps-ng" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute" \ + -d "libev" \ + -d "net-tools" \ + -d "python >= 2.7, python < 3.0" \ + netns/setup.py daemon/setup.py +endef + +define fpm-daemon-deb = +fpm -s python -t deb \ + -p NAME_$1_VERSION_ARCH.deb \ + --python-setup-py-arguments --service=$1 \ + -m "$(CORE_MAINTAINERS)" \ + --vendor "$(CORE_VENDOR)" \ + -d "procps" \ + -d "libc6 >= 2.14" \ + -d "bash >= 3.0" \ + -d "bridge-utils" \ + -d "ebtables" \ + -d "iproute2" \ + -d "libev4" \ + -d "python (>= 2.7), python (<< 3.0)" \ + --deb-recommends quagga \ + netns/setup.py daemon/setup.py +endef + .PHONY: fpm fpm: clean-local-fpm $(call fpm-gui,rpm,-d "tkimg") $(call fpm-gui,deb,-d "libtk-img") $(call fpm-python,rpm,daemon/ns3/setup.py) $(call fpm-python,deb,daemon/ns3/setup.py) - fpm -s python -t rpm \ - -m "$(CORE_MAINTAINERS)" \ - --vendor "$(CORE_VENDOR)" \ - -d "procps-ng" \ - -d "bash >= 3.0" \ - -d "bridge-utils" \ - -d "ebtables" \ - -d "iproute" \ - -d "libev" \ - -d "net-tools" \ - -d "python >= 2.7, python < 3.0" \ - netns/setup.py daemon/setup.py - fpm -s python -t deb \ - -m "$(CORE_MAINTAINERS)" \ - --vendor "$(CORE_VENDOR)" \ - -d "procps" \ - -d "libc6 >= 2.14" \ - -d "bash >= 3.0" \ - -d "bridge-utils" \ - -d "ebtables" \ - -d "iproute2" \ - -d "libev4" \ - -d "python (>= 2.7), python (<< 3.0)" \ - --deb-recommends quagga \ - netns/setup.py daemon/setup.py + $(call fpm-daemon-rpm,systemd) + $(call fpm-daemon-rpm,sysv) + $(call fpm-daemon-deb,systemd) + $(call fpm-daemon-deb,sysv) .PHONY: clean-local-fpm clean-local-fpm: diff --git a/daemon/setup.py b/daemon/setup.py index dfe75c57..ee759b52 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -3,6 +3,33 @@ Defines how CORE will be built for installation. """ from setuptools import setup, find_packages +from distutils.command.install import install + + +class CustomInstall(install): + user_options = install.user_options + [ + ("service=", None, "determine which service file to include") + ] + + def initialize_options(self): + install.initialize_options(self) + self.service = "sysv" + + def finalize_options(self): + install.finalize_options(self) + assert self.service in ("sysv", "systemd"), "must be sysv or systemd" + + def run(self): + if self.service == "sysv": + self.distribution.data_files.append(( + "/etc/init.d", ["../scripts/core-daemon"] + )) + else: + self.distribution.data_files.append(( + "/etc/systemd/system", ["../scripts/core-daemon.service"] + )) + install.run(self) + setup( name="core", @@ -23,9 +50,6 @@ setup( "data/xen.conf", "data/logging.conf", ]), - ("/etc/init.d", [ - "../scripts/core-daemon", - ]), ], scripts=[ "sbin/core-cleanup", @@ -39,5 +63,8 @@ setup( author="Boeing Research & Technology", author_email="core-dev@nrl.navy.mil", license="BSD", - long_description="Python scripts and modules for building virtual emulated networks." + long_description="Python scripts and modules for building virtual emulated networks.", + cmdclass={ + "install": CustomInstall + } ) diff --git a/netns/setup.py b/netns/setup.py index 1c111062..564dcef8 100644 --- a/netns/setup.py +++ b/netns/setup.py @@ -1,7 +1,26 @@ -# Copyright (c)2010-2012 the Boeing Company. -# See the LICENSE file included in this distribution. +""" +Defines how CORE netns will be build for installation. +""" from setuptools import setup, Extension +from distutils.command.install import install + + +class CustomInstall(install): + user_options = install.user_options + [ + ("service=", None, "determine which service file to include") + ] + + def initialize_options(self): + install.initialize_options(self) + self.service = "sysv" + + def finalize_options(self): + install.finalize_options(self) + assert self.service in ("sysv", "systemd"), "must be sysv or systemd" + + def run(self): + install.run(self) netns = Extension( "netns", @@ -38,5 +57,8 @@ setup( author="Boeing Research & Technology", author_email="core-dev@nrl.navy.mil", license="BSD", - long_description="Extension modules and utilities to support virtual nodes using Linux network namespaces" + long_description="Extension modules and utilities to support virtual nodes using Linux network namespaces", + cmdclass={ + "install": CustomInstall + } ) From 77be7f5c3076cc67475dfecc708276b8f7e446da Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 4 Jan 2018 16:34:22 -0800 Subject: [PATCH 013/152] moved ns3 from under daemon to the root of the project and updated references --- Makefile.am | 6 +++--- configure.ac | 8 ++++---- daemon/Makefile.am | 4 ---- doc/ns3.rst | 6 +++--- ns3/.gitignore | 1 + {daemon/ns3 => ns3}/LICENSE | 0 {daemon/ns3 => ns3}/Makefile.am | 0 {daemon/ns3 => ns3}/corens3/.gitignore | 0 {daemon/ns3 => ns3}/corens3/__init__.py | 0 {daemon/ns3 => ns3}/corens3/constants.py.in | 0 {daemon/ns3 => ns3}/corens3/obj.py | 0 {daemon/ns3 => ns3}/examples/ns3lte.py | 0 {daemon/ns3 => ns3}/examples/ns3wifi.py | 0 {daemon/ns3 => ns3}/examples/ns3wifirandomwalk.py | 0 {daemon/ns3 => ns3}/examples/ns3wimax.py | 0 {daemon/ns3 => ns3}/setup.py | 0 16 files changed, 11 insertions(+), 14 deletions(-) create mode 100644 ns3/.gitignore rename {daemon/ns3 => ns3}/LICENSE (100%) rename {daemon/ns3 => ns3}/Makefile.am (100%) rename {daemon/ns3 => ns3}/corens3/.gitignore (100%) rename {daemon/ns3 => ns3}/corens3/__init__.py (100%) rename {daemon/ns3 => ns3}/corens3/constants.py.in (100%) rename {daemon/ns3 => ns3}/corens3/obj.py (100%) rename {daemon/ns3 => ns3}/examples/ns3lte.py (100%) rename {daemon/ns3 => ns3}/examples/ns3wifi.py (100%) rename {daemon/ns3 => ns3}/examples/ns3wifirandomwalk.py (100%) rename {daemon/ns3 => ns3}/examples/ns3wimax.py (100%) rename {daemon/ns3 => ns3}/setup.py (100%) diff --git a/Makefile.am b/Makefile.am index cd250dea..5c8cbe3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ if WANT_DAEMON DAEMON = scripts daemon endif if WANT_NETNS - NETNS = netns + NETNS = netns ns3 endif # keep docs last due to dependencies on binaries @@ -138,8 +138,8 @@ endef fpm: clean-local-fpm $(call fpm-gui,rpm,-d "tkimg") $(call fpm-gui,deb,-d "libtk-img") - $(call fpm-python,rpm,daemon/ns3/setup.py) - $(call fpm-python,deb,daemon/ns3/setup.py) + $(call fpm-python,rpm,ns3/setup.py) + $(call fpm-python,deb,ns3/setup.py) $(call fpm-daemon-rpm,systemd) $(call fpm-daemon-rpm,sysv) $(call fpm-daemon-deb,systemd) diff --git a/configure.ac b/configure.ac index 4bc5238f..f9f40828 100644 --- a/configure.ac +++ b/configure.ac @@ -331,13 +331,13 @@ AC_CONFIG_FILES([Makefile doc/man/Makefile doc/figures/Makefile daemon/Makefile - netns/Makefile - netns/version.h daemon/core/constants.py - daemon/ns3/Makefile - daemon/ns3/corens3/constants.py daemon/doc/Makefile daemon/doc/conf.py + netns/Makefile + netns/version.h + ns3/Makefile + ns3/corens3/constants.py packaging/deb/core-daemon.install packaging/deb/core-daemon.prerm packaging/deb/core-gui.install diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 4b1f589c..bc0e5ca5 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -10,10 +10,6 @@ SETUPPY = setup.py SETUPPYFLAGS = -v -if WANT_NETNS - SUBDIRS = ns3 -endif - SBIN_FILES = \ sbin/core-cleanup \ sbin/core-daemon \ diff --git a/doc/ns3.rst b/doc/ns3.rst index 1f3c06c6..7221ba72 100644 --- a/doc/ns3.rst +++ b/doc/ns3.rst @@ -47,7 +47,7 @@ ns-3 Scripting Currently, ns-3 is supported by writing :ref:`Python scripts `, but not through drag-and-drop actions within the GUI. -If you have a copy of the CORE source, look under :file:`core/daemon/ns3/examples/` for example scripts; a CORE installation package puts these under +If you have a copy of the CORE source, look under :file:`ns3/examples/` for example scripts; a CORE installation package puts these under :file:`/usr/share/core/examples/corens3`. To run these scripts, install CORE so the CORE Python libraries are accessible, @@ -168,8 +168,8 @@ a constant-rate 802.11a-based ad hoc network, using a lot of ns-3 defaults. However, programs may be written with a blend of ns-3 API and CORE Python API calls. This section examines some of the fundamental objects in the CORE ns-3 support. Source code can be found in -:file:`daemon/ns3/corens3/obj.py` and example -code in :file:`daemon/ns3/corens3/examples/`. +:file:`ns3/corens3/obj.py` and example +code in :file:`ns3/corens3/examples/`. Ns3Session ---------- diff --git a/ns3/.gitignore b/ns3/.gitignore new file mode 100644 index 00000000..378eac25 --- /dev/null +++ b/ns3/.gitignore @@ -0,0 +1 @@ +build diff --git a/daemon/ns3/LICENSE b/ns3/LICENSE similarity index 100% rename from daemon/ns3/LICENSE rename to ns3/LICENSE diff --git a/daemon/ns3/Makefile.am b/ns3/Makefile.am similarity index 100% rename from daemon/ns3/Makefile.am rename to ns3/Makefile.am diff --git a/daemon/ns3/corens3/.gitignore b/ns3/corens3/.gitignore similarity index 100% rename from daemon/ns3/corens3/.gitignore rename to ns3/corens3/.gitignore diff --git a/daemon/ns3/corens3/__init__.py b/ns3/corens3/__init__.py similarity index 100% rename from daemon/ns3/corens3/__init__.py rename to ns3/corens3/__init__.py diff --git a/daemon/ns3/corens3/constants.py.in b/ns3/corens3/constants.py.in similarity index 100% rename from daemon/ns3/corens3/constants.py.in rename to ns3/corens3/constants.py.in diff --git a/daemon/ns3/corens3/obj.py b/ns3/corens3/obj.py similarity index 100% rename from daemon/ns3/corens3/obj.py rename to ns3/corens3/obj.py diff --git a/daemon/ns3/examples/ns3lte.py b/ns3/examples/ns3lte.py similarity index 100% rename from daemon/ns3/examples/ns3lte.py rename to ns3/examples/ns3lte.py diff --git a/daemon/ns3/examples/ns3wifi.py b/ns3/examples/ns3wifi.py similarity index 100% rename from daemon/ns3/examples/ns3wifi.py rename to ns3/examples/ns3wifi.py diff --git a/daemon/ns3/examples/ns3wifirandomwalk.py b/ns3/examples/ns3wifirandomwalk.py similarity index 100% rename from daemon/ns3/examples/ns3wifirandomwalk.py rename to ns3/examples/ns3wifirandomwalk.py diff --git a/daemon/ns3/examples/ns3wimax.py b/ns3/examples/ns3wimax.py similarity index 100% rename from daemon/ns3/examples/ns3wimax.py rename to ns3/examples/ns3wimax.py diff --git a/daemon/ns3/setup.py b/ns3/setup.py similarity index 100% rename from daemon/ns3/setup.py rename to ns3/setup.py From 3ce416b610431253a975c550b864e8181384adeb Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 9 Jan 2018 15:52:29 -0800 Subject: [PATCH 014/152] updated test cases to fix old broken code --- .gitignore | 3 +++ daemon/core/service.py | 29 +++++------------------------ daemon/sbin/core-daemon | 9 +++++++++ daemon/tests/conftest.py | 23 ++++++----------------- daemon/tests/test_core.py | 2 +- 5 files changed, 24 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 3e9cd0b7..8f0324f9 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ coverage.xml # ignore package files *.rpm *.deb + +# pytest cache files +.cache diff --git a/daemon/core/service.py b/daemon/core/service.py index f60059f0..7309baca 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -118,7 +118,11 @@ class ServiceManager(object): :return: list of core services :rtype: list """ - # validate path exists for importing + # validate path exists + logger.info("attempting to add services from path: %s", path) + if not os.path.isdir(path): + logger.warn("invalid custom service directory specified" ": %s" % path) + # check if path is in sys.path logger.info("getting custom services from: %s", path) parent_path = os.path.dirname(path) if parent_path not in sys.path: @@ -175,33 +179,10 @@ class CoreServices(ConfigurableManager): # dict of tuple of service objects, key is node number self.customservices = {} - paths = self.session.get_config_item('custom_services_dir') - if paths: - for path in paths.split(','): - path = path.strip() - self.importcustom(path) - # TODO: remove need for cyclic import from core.services import startup self.is_startup_service = startup.Startup.is_startup_service - def importcustom(self, path): - """ - Import services from a myservices directory. - - :param str path: path to import custom services from - :return: nothing - """ - - if not path or len(path) == 0: - return - - if not os.path.isdir(path): - logger.warn("invalid custom service directory specified" ": %s" % path) - return - - ServiceManager.add_services(path) - def reset(self): """ Called when config message with reset flag is received diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index b47ec8f5..85b9a8ac 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -39,6 +39,7 @@ from core.misc import nodemaps from core.misc import nodeutils from core.misc.utils import closeonexec from core.misc.utils import daemonize +from core.service import ServiceManager DEFAULT_MAXFD = 1024 @@ -313,6 +314,14 @@ def main(): for a in args: logger.error("ignoring command line argument: %s", a) + # attempt load custom services + service_paths = cfg.get("custom_services_dir") + logger.debug("custom service paths: %s", service_paths) + if service_paths: + for service_path in service_paths.split(','): + service_path = service_path.strip() + ServiceManager.add_services(service_path) + if cfg["daemonize"] == "True": daemonize(rootdir=None, umask=0, close_fds=False, stdin=os.devnull, diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index 878fb47a..96f740e8 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -8,12 +8,11 @@ import pytest from mock.mock import MagicMock +from core import services from core.coreserver import CoreServer from core.misc import nodemaps from core.misc import nodeutils from core.netns import nodes -from core.services import quagga -from core.services import utility from core.session import Session from core.api.coreapi import CoreConfMessage from core.api.coreapi import CoreEventMessage @@ -244,14 +243,6 @@ class Core(object): class CoreServerTest(object): def __init__(self): - # setup nodes - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) - - # load emane services - quagga.load_services() - utility.load_services() - address = ("localhost", CORE_API_PORT) self.server = CoreServer(address, CoreRequestHandler, { "numthreads": 1, @@ -320,19 +311,14 @@ class CoreServerTest(object): @pytest.fixture() def session(): - # configure default nodes - node_map = nodemaps.NODES - nodeutils.set_node_map(node_map) + # load default services + services.load() # create and return session session_fixture = Session(1, persistent=True) session_fixture.master = True assert os.path.exists(session_fixture.session_dir) - # load emane services - quagga.load_services() - utility.load_services() - # set location # session_fixture.master = True session_fixture.location.setrefgeo(47.57917, -122.13232, 2.00000) @@ -362,6 +348,9 @@ def core(session, ip_prefix): @pytest.fixture() def cored(): + # load default services + services.load() + # create and return server server = CoreServerTest() yield server diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 2e9094cc..f47827a0 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -36,7 +36,7 @@ class TestCore: :param conftest.Core core: core fixture to test with """ - core.session.services.importcustom(_SERVICES_PATH) + ServiceManager.add_services(_SERVICES_PATH) assert ServiceManager.get("MyService") assert ServiceManager.get("MyService2") From 7dff4f39877116f6ef805b027927db9056289bb6 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 10 Jan 2018 11:03:20 -0800 Subject: [PATCH 015/152] added examples and man pages to core packages --- daemon/setup.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/daemon/setup.py b/daemon/setup.py index ee759b52..7adbe671 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -2,10 +2,28 @@ Defines how CORE will be built for installation. """ +import glob +import os + from setuptools import setup, find_packages from distutils.command.install import install +def recursive_files(data_path, files_path): + data_files = [] + for path, directories, filenames in os.walk(files_path): + directory = os.path.join(data_path, path) + files = [] + for filename in filenames: + files.append(os.path.join(path, filename)) + data_files.append((directory, files)) + return data_files + + +def glob_files(glob_path): + return glob.glob(glob_path) + + class CustomInstall(install): user_options = install.user_options + [ ("service=", None, "determine which service file to include") @@ -50,7 +68,8 @@ setup( "data/xen.conf", "data/logging.conf", ]), - ], + ("/usr/local/share/man/man1", glob_files("../doc/man/**.1")), + ] + recursive_files("/usr/local/share/core", "examples"), scripts=[ "sbin/core-cleanup", "sbin/core-daemon", From 14312db02d74a03247177db879a9d9156760dbdd Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 10 Jan 2018 15:22:54 -0800 Subject: [PATCH 016/152] updated versions to 5.1 --- configure.ac | 2 +- daemon/setup.py | 2 +- netns/setup.py | 2 +- ns3/setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index f9f40828..eba5ab93 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ # # this defines the CORE version number, must be static for AC_INIT # -AC_INIT(core, m4_esyscmd_s([./revision.sh 5.0]), core-dev@nrl.navy.mil) +AC_INIT(core, m4_esyscmd_s([./revision.sh 5.1]), core-dev@nrl.navy.mil) VERSION=$PACKAGE_VERSION CORE_VERSION=$PACKAGE_VERSION CORE_VERSION_DATE=m4_esyscmd_s([./revision.sh -d]) diff --git a/daemon/setup.py b/daemon/setup.py index 7adbe671..1e438853 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -51,7 +51,7 @@ class CustomInstall(install): setup( name="core", - version="5.0", + version="5.1", packages=find_packages(), install_requires=[ "enum34", diff --git a/netns/setup.py b/netns/setup.py index 564dcef8..8ef5083f 100644 --- a/netns/setup.py +++ b/netns/setup.py @@ -46,7 +46,7 @@ vcmd = Extension( setup( name="core-netns", - version="1.0", + version="5.1", description="Extension modules to support virtual nodes using Linux network namespaces", scripts=["vcmd", "vnoded", "netns"], ext_modules=[ diff --git a/ns3/setup.py b/ns3/setup.py index e3f248ac..9154d76e 100644 --- a/ns3/setup.py +++ b/ns3/setup.py @@ -2,7 +2,7 @@ from setuptools import setup setup( name="core-ns3", - version="5.0", + version="5.1", packages=[ "corens3", ], From 3ba837128244aded0931cda6a8fe2491dd78946f Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 10 Jan 2018 15:59:46 -0800 Subject: [PATCH 017/152] updates to doc regarding changes --- doc/devguide.rst | 5 +++-- doc/install.rst | 46 ++++++++++++++++++++-------------------------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/doc/devguide.rst b/doc/devguide.rst index 04fae329..a449ffd0 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -33,8 +33,9 @@ These are being actively developed as of CORE |version|: * *gui* - Tcl/Tk GUI. This uses Tcl/Tk because of its roots with the IMUNES project. * *daemon* - Python modules are found in the :file:`daemon/core` directory, the - daemon under :file:`daemon/sbin/core-daemon`, and Python extension modules for - Linux Network Namespace support are in :file:`netns`. + daemon under :file:`daemon/sbin/core-daemon` +* *netns* - Python extension modules for Linux Network Namespace support are in :file:`netns`. +* *ns3* - Python ns3 script support for running CORE. * *doc* - Documentation for the manual lives here in reStructuredText format. * *packaging* - Control files and script for building CORE packages are here. diff --git a/doc/install.rst b/doc/install.rst index 0a046141..f4b28c39 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -25,30 +25,23 @@ The primary dependencies are Tcl/Tk (8.5 or newer) for the GUI, and Python 2.6 o .. index:: paths .. index:: install paths -CORE files are installed to the following directories. When installing from -source, the :file:`/usr/local` prefix is used in place of :file:`/usr` by -default. - -============================================= ================================= -Install Path Description -============================================= ================================= -:file:`/usr/bin/core-gui` GUI startup command -:file:`/usr/sbin/core-daemon` Daemon startup command -:file:`/usr/sbin/` Misc. helper commands/scripts -:file:`/usr/lib/core` GUI files -:file:`/usr/lib/python2.7/dist-packages/core` Python modules for daemon/scripts -:file:`/etc/core/` Daemon configuration files -:file:`~/.core/` User-specific GUI preferences and scenario files -:file:`/usr/share/core/` Example scripts and scenarios -:file:`/usr/share/man/man1/` Command man pages -:file:`/etc/init.d/core-daemon` System startup script for daemon -============================================= ================================= - - -Under Fedora, :file:`/site-packages/` is used instead of :file:`/dist-packages/` -for the Python modules, and :file:`/etc/systemd/system/core-daemon.service` -instead of :file:`/etc/init.d/core-daemon` for the system startup script. +CORE files are installed to the following directories. +======================================================= ================================= +Install Path Description +======================================================= ================================= +:file:`/usr/local/bin/core-gui` GUI startup command +:file:`/usr/local/bin/core-daemon` Daemon startup command +:file:`/usr/local/bin/` Misc. helper commands/scripts +:file:`/usr/local/lib/core` GUI files +:file:`/usr/local/lib/python2.7/dist-packages/core` Python modules for daemon/scripts +:file:`/etc/core/` Daemon configuration files +:file:`~/.core/` User-specific GUI preferences and scenario files +:file:`/usr/local/share/core/` Example scripts and scenarios +:file:`/usr/local/share/man/man1/` Command man pages +:file:`/etc/init.d/core-daemon` SysV startup script for daemon +:file:`/etc/systemd/system/core-daemon.service` Systemd startup script for daemon +======================================================= ================================= .. _Prerequisites: @@ -121,7 +114,8 @@ Installing from Packages The easiest way to install CORE is using the pre-built packages. The package managers on Ubuntu or Fedora will automatically install dependencies for you. -You can obtain the CORE packages from the `CORE downloads `_ page. +You can obtain the CORE packages from the `CORE downloads `_ page +or `CORE GitHub `_. .. _Installing_from_Packages_on_Ubuntu: @@ -285,14 +279,14 @@ Fedora release number. .. parsed-literal:: - yum localinstall core-daemon-|version|-|CORERPM| --nogpgcheck + yum localinstall python-core_|service|-|version|-|CORERPM| --nogpgcheck yum localinstall core-gui-|version|-|CORERPM2| --nogpgcheck or install from the command-line: .. parsed-literal:: - rpm -ivh core-daemon-|version|-|CORERPM| + rpm -ivh python-core_|service|-|version|-|CORERPM| rpm -ivh core-gui-|version|-|CORERPM2| From 26b1b0150525b4ad840c1ff0f8a0fc19b7880ac8 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 11 Jan 2018 11:21:56 -0800 Subject: [PATCH 018/152] updated to readme for building packages, update to makefile to install and build gui with one command --- .gitignore | 3 +++ Changelog | 11 +++++++++++ Makefile.am | 2 ++ README.rst | 25 +++++++++++++++++++++++-- daemon/setup.py | 31 +++++++++++++++++++++---------- 5 files changed, 60 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 8f0324f9..46a93660 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ core-*.tar.gz debian stamp-h1 +# python build directory +dist + # intellij *.iml .idea diff --git a/Changelog b/Changelog index 8d9f14c0..b9228986 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,14 @@ +2018-XX-XX CORE 5.1 + * DAEMON: + - default nodes are now set in the node map + - moved ns3 and netns directories to the top of the repo + - changes to make use of fpm as the tool for building packages + - removed usage of logzero to avoid dependency issues for built packages + * TEST: + - fixed some broken tests + * BUGFIXES: + - #142 - duplication of custom services + 2017-09-01 CORE 5.0 * DEVELOPMENT: - support for editorconfig to help standardize development across IDEs, from the defined configuration file diff --git a/Makefile.am b/Makefile.am index 5c8cbe3f..fd63834a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -101,6 +101,7 @@ endef define fpm-daemon-rpm = fpm -s python -t rpm \ + --verbose \ -p NAME_$1_VERSION_ARCH.rpm \ --python-setup-py-arguments --service=$1 \ -m "$(CORE_MAINTAINERS)" \ @@ -136,6 +137,7 @@ endef .PHONY: fpm fpm: clean-local-fpm + $(MAKE) -C gui install DESTDIR=$(DESTDIR) $(call fpm-gui,rpm,-d "tkimg") $(call fpm-gui,deb,-d "libtk-img") $(call fpm-python,rpm,ns3/setup.py) diff --git a/README.rst b/README.rst index 3dff84d8..1e85692f 100644 --- a/README.rst +++ b/README.rst @@ -44,8 +44,8 @@ Note: You may need to pass the proxy settings to sudo make install: Here is what is installed with 'make install': /usr/local/bin/core-gui - /usr/local/sbin/core-daemon - /usr/local/sbin/[vcmd, vnoded, coresendmsg, core-cleanup.sh] + /usr/local/bin/core-daemon + /usr/local/bin/[vcmd, vnoded, coresendmsg, core-cleanup.sh] /usr/local/lib/core/* /usr/local/share/core/* /usr/local/lib/python2.6/dist-packages/core/* @@ -66,6 +66,27 @@ Once that has been done you can run the following commands: ./configure make html +Building Packages +================= + +Install fpm + + http://fpm.readthedocs.io/en/latest/installing.html + +Build package commands, DESTDIR is used for gui packaging only + +* ./bootstrap.sh +* ./configure +* make +* mkdir /tmp/core-gui +* make fpm DESTDIR=/tmp/core-gui + +This will produce: + +* CORE GUI rpm/deb files +* CORE ns3 rpm/deb files +* CORE python rpm/deb files for SysV and systemd service types + Running CORE ============ diff --git a/daemon/setup.py b/daemon/setup.py index 1e438853..552a357c 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -9,6 +9,13 @@ from setuptools import setup, find_packages from distutils.command.install import install +_CORE_DIR = "/etc/core" +_MAN_DIR = "/usr/local/share/man/man1" +_SHARE_DIR = "/usr/local/share/core" +_SYSV = "/etc/init.d" +_SYSTEMD = "/etc/systemd/system" + + def recursive_files(data_path, files_path): data_files = [] for path, directories, filenames in os.walk(files_path): @@ -40,15 +47,26 @@ class CustomInstall(install): def run(self): if self.service == "sysv": self.distribution.data_files.append(( - "/etc/init.d", ["../scripts/core-daemon"] + _SYSV, ["../scripts/core-daemon"] )) else: self.distribution.data_files.append(( - "/etc/systemd/system", ["../scripts/core-daemon.service"] + _SYSTEMD, ["../scripts/core-daemon.service"] )) install.run(self) +data_files = [ + (_CORE_DIR, [ + "data/core.conf", + "data/xen.conf", + "data/logging.conf", + ]), + (_MAN_DIR, glob_files("../doc/man/**.1")), +] +data_files.extend(recursive_files(_SHARE_DIR, "examples")) + + setup( name="core", version="5.1", @@ -62,14 +80,7 @@ setup( "pytest-cov", "mock", ], - data_files=[ - ("/etc/core", [ - "data/core.conf", - "data/xen.conf", - "data/logging.conf", - ]), - ("/usr/local/share/man/man1", glob_files("../doc/man/**.1")), - ] + recursive_files("/usr/local/share/core", "examples"), + data_files=data_files, scripts=[ "sbin/core-cleanup", "sbin/core-daemon", From 5a246159f86a8a9418564947e68221cc7c2da370 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 11 Jan 2018 11:29:06 -0800 Subject: [PATCH 019/152] updates to readme to leverage code blocks markdown --- README.rst | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 1e85692f..75b6795a 100644 --- a/README.rst +++ b/README.rst @@ -33,10 +33,12 @@ Building CORE To build this software you should use: - ./bootstrap.sh - ./configure - make - sudo make install +```bash +./bootstrap.sh +./configure +make +sudo make install +``` Note: You may need to pass the proxy settings to sudo make install: sudo make install HTTP_PROXY= @@ -62,9 +64,11 @@ Being able to build documentation depends on help2man being installed. Once that has been done you can run the following commands: - ./bootstrap.sh - ./configure - make html +```bash +./bootstrap.sh +./configure +make html +``` Building Packages ================= @@ -75,11 +79,13 @@ Install fpm Build package commands, DESTDIR is used for gui packaging only -* ./bootstrap.sh -* ./configure -* make -* mkdir /tmp/core-gui -* make fpm DESTDIR=/tmp/core-gui +```bash +./bootstrap.sh +./configure +make +mkdir /tmp/core-gui +make fpm DESTDIR=/tmp/core-gui +``` This will produce: @@ -92,12 +98,16 @@ Running CORE First start the CORE services: - sudo /etc/init.d/core-daemon start +```bash +sudo /etc/init.d/core-daemon start +``` This automatically runs the core-daemon program. Assuming the GUI is in your PATH, run the CORE GUI by typing the following: - core-gui +```bash +core-gui +``` This launches the CORE GUI. You do not need to run the GUI as root. From 9187b5036139c7143be267cc973fcb32a5eb949e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 11 Jan 2018 12:03:55 -0800 Subject: [PATCH 020/152] made readme a markdown file --- Makefile.am | 3 +-- README.rst => README.md | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) rename README.rst => README.md (98%) diff --git a/Makefile.am b/Makefile.am index fd63834a..438db6f6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,7 @@ ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball EXTRA_DIST = bootstrap.sh LICENSE \ - README.rst ASSIGNMENT_OF_COPYRIGHT.pdf \ + README.md ASSIGNMENT_OF_COPYRIGHT.pdf \ README-Xen Changelog kernel \ python-prefix.py revision.sh \ .version .version.date \ @@ -101,7 +101,6 @@ endef define fpm-daemon-rpm = fpm -s python -t rpm \ - --verbose \ -p NAME_$1_VERSION_ARCH.rpm \ --python-setup-py-arguments --service=$1 \ -m "$(CORE_MAINTAINERS)" \ diff --git a/README.rst b/README.md similarity index 98% rename from README.rst rename to README.md index 75b6795a..e8abd335 100644 --- a/README.rst +++ b/README.md @@ -33,7 +33,7 @@ Building CORE To build this software you should use: -```bash +```shell ./bootstrap.sh ./configure make @@ -64,7 +64,7 @@ Being able to build documentation depends on help2man being installed. Once that has been done you can run the following commands: -```bash +```shell ./bootstrap.sh ./configure make html @@ -79,7 +79,7 @@ Install fpm Build package commands, DESTDIR is used for gui packaging only -```bash +```shell ./bootstrap.sh ./configure make @@ -98,14 +98,14 @@ Running CORE First start the CORE services: -```bash +```shell sudo /etc/init.d/core-daemon start ``` This automatically runs the core-daemon program. Assuming the GUI is in your PATH, run the CORE GUI by typing the following: -```bash +```shell core-gui ``` From 438204743e296526307532007004695ab3ae5ce7 Mon Sep 17 00:00:00 2001 From: Blake Harnden Date: Thu, 11 Jan 2018 13:19:57 -0700 Subject: [PATCH 021/152] Update README.md --- README.md | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index e8abd335..dedc1b35 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,9 @@ source repos, wiki, and bug tracker. There is a deprecated Google Code page (3) with the old wiki, blog, bug tracker, and quickstart guide. 1. http://www.nrl.navy.mil/itd/ncs/products/core - -2. https://github.com/coreemu/core - -3. http://code.google.com/p/coreemu/ - -4. `Official Documentation`_ - -.. _Official Documentation: https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/index.html - +1. https://github.com/coreemu/core +1. http://code.google.com/p/coreemu/ +1. [Official Documentation](https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/index.html) Building CORE ============= @@ -117,12 +111,5 @@ Support If you have questions, comments, or trouble, please use the CORE mailing lists: -- `core-users`_ for general comments and questions - -- `core-dev`_ for bugs, compile errors, and other development issues - - -.. _core-users: https://pf.itd.nrl.navy.mil/mailman/listinfo/core-users -.. _core-dev: https://pf.itd.nrl.navy.mil/mailman/listinfo/core-dev - - +- [core-users](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-users) for general comments and questions +- [core-dev](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-dev) for bugs, compile errors, and other development issues From 27192e180068e3b87e31e5ffab034d430f4490a7 Mon Sep 17 00:00:00 2001 From: Blake Harnden Date: Thu, 11 Jan 2018 13:21:08 -0700 Subject: [PATCH 022/152] Update README.md --- README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dedc1b35..1b295ecf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -==== CORE ==== @@ -9,7 +8,7 @@ Copyright (c)2005-2017 the Boeing Company. See the LICENSE file included in this distribution. About -===== +----- CORE is a tool for emulating networks using a GUI or Python scripts. The CORE project site (1) is a good source of introductory information, with a manual, @@ -23,7 +22,7 @@ Google Code page (3) with the old wiki, blog, bug tracker, and quickstart guide. 1. [Official Documentation](https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/index.html) Building CORE -============= +------------- To build this software you should use: @@ -52,7 +51,7 @@ Here is what is installed with 'make install': See the manual for the software required for building CORE. Building Documentation -====================== +---------------------- Being able to build documentation depends on help2man being installed. @@ -65,7 +64,7 @@ make html ``` Building Packages -================= +----------------- Install fpm @@ -88,7 +87,7 @@ This will produce: * CORE python rpm/deb files for SysV and systemd service types Running CORE -============ +------------ First start the CORE services: @@ -107,7 +106,7 @@ This launches the CORE GUI. You do not need to run the GUI as root. Support -======= +------- If you have questions, comments, or trouble, please use the CORE mailing lists: From 0ee07f89f0ee1cd16096eefe4610276dae491357 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 11 Jan 2018 16:54:12 -0800 Subject: [PATCH 023/152] removed unused import in core-daemon --- daemon/sbin/core-daemon | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index 85b9a8ac..ec5d7e3e 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -35,7 +35,6 @@ from core.api import coreapi from core.corehandlers import CoreDatagramRequestHandler from core.enumerations import MessageFlags from core.enumerations import RegisterTlvs -from core.misc import nodemaps from core.misc import nodeutils from core.misc.utils import closeonexec from core.misc.utils import daemonize @@ -347,11 +346,13 @@ if __name__ == "__main__": # configure nodes to use if len(sys.argv) == 2 and sys.argv[1] == "ovs": from core.netns.openvswitch import OVS_NODES + nodeutils.update_node_map(OVS_NODES) # update with BSD based nodes if os.uname()[0] == "FreeBSD": from core.bsd.nodes import BSD_NODES + nodeutils.update_node_map(BSD_NODES) # load default services From 4fdae0f4b3cc04c35213e25a29763354f727a017 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 12 Jan 2018 09:12:46 -0800 Subject: [PATCH 024/152] removed eric ide project file --- daemon/CORE.e4p | 223 --------------------------------------------- daemon/Makefile.am | 2 +- doc/scripting.rst | 12 --- 3 files changed, 1 insertion(+), 236 deletions(-) delete mode 100644 daemon/CORE.e4p diff --git a/daemon/CORE.e4p b/daemon/CORE.e4p deleted file mode 100644 index abf05a3c..00000000 --- a/daemon/CORE.e4p +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - - en - Python - Console - - 4.0 - - - - setup.py - examples/netns/switchtest.py - examples/netns/ospfmanetmdrtest.py - examples/netns/switch.py - examples/netns/wlantest.py - examples/stopsession.py - src/setup.py - core/emane/__init__.py - core/emane/emane.py - core/emane/ieee80211abg.py - core/emane/rfpipe.py - core/emane/nodes.py - core/netns/vif.py - core/netns/vnet.py - core/netns/__init__.py - core/netns/vnode.py - core/netns/vnodeclient.py - core/netns/nodes.py - core/service.py - core/__init__.py - core/addons/__init__.py - core/broker.py - core/services/__init__.py - core/services/quagga.py - core/misc/LatLongUTMconversion.py - core/misc/__init__.py - core/misc/ipaddr.py - core/misc/quagga.py - core/misc/utils.py - core/pycore.py - core/coreobj.py - core/location.py - core/session.py - core/api/__init__.py - core/api/data.py - core/api/coreapi.py - core/services/nrl.py - core/services/utility.py - core/bsd/netgraph.py - core/bsd/__init__.py - core/bsd/nodes.py - core/bsd/vnet.py - core/bsd/vnode.py - core/xen/xen.py - core/xen/xenconfig.py - core/xen/__init__.py - examples/myservices/sample.py - examples/myservices/__init__.py - core/services/security.py - core/emane/universal.py - examples/netns/wlanemanetests.py - core/services/xorp.py - core/misc/xmlutils.py - core/mobility.py - core/phys/pnodes.py - core/phys/__init__.py - ns3/setup.py - ns3/corens3/__init__.py - ns3/corens3/constants.py - ns3/corens3/obj.py - ns3/examples/ns3wifi.py - ns3/examples/ns3lte.py - ns3/examples/ns3wimax.py - core/emane/commeffect.py - core/services/ucarp.py - core/emane/bypass.py - core/conf.py - core/misc/event.py - core/sdt.py - core/services/bird.py - examples/netns/basicrange.py - examples/netns/howmanynodes.py - sbin/core-daemon - sbin/coresendmsg - sbin/core-cleanup - sbin/core-xen-cleanup - ns3/examples/ns3wifirandomwalk.py - core/misc/utm.py - - - - - - - - - - - - - Subversion - - - - add - - - - - - - - checkout - - - - - - - - commit - - - - - - - - diff - - - - - - - - export - - - - - - - - global - - - - - - - - history - - - - - - - - log - - - - - - - - remove - - - - - - - - status - - - - - - - - tag - - - - - - - - update - - - - - - - - - - - - standardLayout - - - True - - - - - - - - - - - diff --git a/daemon/Makefile.am b/daemon/Makefile.am index bc0e5ca5..30788906 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -125,4 +125,4 @@ DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST doc/Makefile.in doc/Makefile \ doc/conf.py core/addons/*.pyc # files to include with distribution tarball -EXTRA_DIST = $(SETUPPY) MANIFEST.in CORE.e4p core doc $(LOGROTATE_FILE) +EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) diff --git a/doc/scripting.rst b/doc/scripting.rst index f5620a1a..8db7b165 100644 --- a/doc/scripting.rst +++ b/doc/scripting.rst @@ -65,18 +65,6 @@ interactive Python shell, you can retrieve online help about the various classes and methods; for example *help(nodes.CoreNode)* or *help(Session)*. -An interactive development environment (IDE) is available for browsing -the CORE source, the -`Eric Python IDE `_. -CORE has a project file that can be opened by Eric, in the source under -:file:`core/daemon/CORE.e4p`. -This IDE -has a class browser for viewing a tree of classes and methods. It features -syntax highlighting, auto-completion, indenting, and more. One feature that -is helpful with learning the CORE Python modules is the ability to generate -class diagrams; right-click on a class, choose *Diagrams*, and -*Class Diagram*. - .. index:: daemon versus script .. index:: script versus daemon .. index:: script with GUI support From 17d5503fb234cd5a22372a851e40dfd827b6f356 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 12 Jan 2018 09:50:56 -0800 Subject: [PATCH 025/152] removed daemon addons directory and refereces --- Changelog | 1 + daemon/Makefile.am | 2 +- daemon/core/addons/__init__.py | 6 ---- daemon/core/corehandlers.py | 3 +- daemon/core/coreserver.py | 58 ---------------------------------- daemon/core/service.py | 2 +- daemon/data/core.conf | 2 -- daemon/sbin/core-daemon | 29 ----------------- packaging/rpm/core.spec.in | 2 -- 9 files changed, 4 insertions(+), 101 deletions(-) delete mode 100644 daemon/core/addons/__init__.py diff --git a/Changelog b/Changelog index b9228986..c057ae83 100644 --- a/Changelog +++ b/Changelog @@ -4,6 +4,7 @@ - moved ns3 and netns directories to the top of the repo - changes to make use of fpm as the tool for building packages - removed usage of logzero to avoid dependency issues for built packages + - removed daemon addons directory * TEST: - fixed some broken tests * BUGFIXES: diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 30788906..42f7dcc7 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -122,7 +122,7 @@ dist-hook: rm -rf `find $(distdir)/ -name .svn` `find $(distdir)/ -name '*.pyc'` DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST doc/Makefile.in doc/Makefile \ - doc/conf.py core/addons/*.pyc + doc/conf.py # files to include with distribution tarball EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) diff --git a/daemon/core/addons/__init__.py b/daemon/core/addons/__init__.py deleted file mode 100644 index c7cbb64e..00000000 --- a/daemon/core/addons/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -""" -Optional add ons can be put in this directory. Everything listed in __all__ is automatically -loaded by the main core module. -""" - -__all__ = [] diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 5b475fdf..dc6fe0af 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -1137,10 +1137,9 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if execute_server: try: logger.info("executing: %s", execute_server) + # TODO: remove this, unless we want to support udp/aux at any level if not isinstance(self.server, CoreServer): # CoreUdpServer): server = self.server.mainserver - # elif isinstance(self.server, CoreAuxServer): - # server = self.server.mainserver else: server = self.server if message.flags & MessageFlags.STRING.value: diff --git a/daemon/core/coreserver.py b/daemon/core/coreserver.py index 882f2239..058d4a0e 100644 --- a/daemon/core/coreserver.py +++ b/daemon/core/coreserver.py @@ -38,8 +38,6 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): self.sessions = {} self.udpserver = None self.udpthread = None - self.auxserver = None - self.auxthread = None self._sessions_lock = threading.Lock() CoreServer.add_server(self) SocketServer.TCPServer.__init__(self, server_address, handler_class) @@ -317,59 +315,3 @@ class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): :return: nothing """ self.serve_forever() - - -class CoreAuxServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): - """ - An auxiliary TCP server. - """ - daemon_threads = True - allow_reuse_address = True - - def __init__(self, server_address, handler_class, main_server): - """ - Create a CoreAuxServer instance. - - :param tuple[str, int] server_address: server address - :param class handler_class: class for handling requests - :param main_server: main server to associate with - """ - - self.mainserver = main_server - logger.info("auxiliary server started, listening on: %s", server_address) - SocketServer.TCPServer.__init__(self, server_address, handler_class) - - def start(self): - """ - Start the core auxiliary server. - - :return: nothing - """ - self.serve_forever() - - def set_session_master(self, handler): - """ - Set the session master handler. - - :param func handler: session master handler - :return: - """ - return self.mainserver.set_session_master(handler) - - def get_session(self, session_id=None): - """ - Retrieve a session. - - :param int session_id: id of session to retrieve - :return: core.session.Session - """ - return self.mainserver.get_session(session_id) - - def to_session_message(self, flags=0): - """ - Retrieve a session message. - - :param flags: message flags - :return: session message - """ - return self.mainserver.to_session_message(flags) diff --git a/daemon/core/service.py b/daemon/core/service.py index 7309baca..3b76eb0a 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -162,7 +162,7 @@ class CoreServices(ConfigurableManager): config_type = RegisterTlvs.UTILITY.value _invalid_custom_names = ( - 'core', 'addons', 'api', 'bsd', 'emane', 'misc', 'netns', 'phys', 'services', 'xen' + 'core', 'api', 'bsd', 'emane', 'misc', 'netns', 'phys', 'services', 'xen' ) def __init__(self, session): diff --git a/daemon/data/core.conf b/daemon/data/core.conf index 8ee2a532..032d4390 100644 --- a/daemon/data/core.conf +++ b/daemon/data/core.conf @@ -61,5 +61,3 @@ emane_models = RfPipe, Ieee80211abg, CommEffect, Bypass, Tdma # EMANE log level range [0,4] default: 2 #emane_log_level = 2 emane_realtime = True - -#aux_request_handler = core.addons.api2handler.CoreApi2RequestHandler:12222 diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index ec5d7e3e..d544eb89 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -59,28 +59,6 @@ def startudp(core_server, server_address): return core_server.udpserver -def startaux(core_server, aux_address, aux_handler): - """ - Start a thread running an auxiliary TCP server on the given address. - This server will communicate with client requests using a handler - using the aux_handler class. The aux_handler can provide an alternative - API to CORE. - - :param core.coreserver.CoreServer core_server: core server instance - :param tuple[str, int] aux_address: auxiliary server address - :param str aux_handler: auxiliary handler string to import - :return: auxiliary server - """ - handlermodname, dot, handlerclassname = aux_handler.rpartition(".") - handlermod = importlib.import_module(handlermodname) - handlerclass = getattr(handlermod, handlerclassname) - core_server.auxserver = coreserver.CoreAuxServer(aux_address, handlerclass, core_server) - core_server.auxthread = threading.Thread(target=core_server.auxserver.start) - core_server.auxthread.daemon = True - core_server.auxthread.start() - return core_server.auxserver - - def banner(): """ Output the program banner printed to the terminal or log file. @@ -113,12 +91,6 @@ def cored(cfg=None): udpserver = startudp(server, (host, port)) closeonexec(udpserver.fileno()) - auxreqhandler = cfg["aux_request_handler"] - if auxreqhandler: - handler, auxport = auxreqhandler.rsplit(":") - auxserver = startaux(server, (host, int(auxport)), handler) - closeonexec(auxserver.fileno()) - server.serve_forever() @@ -212,7 +184,6 @@ def get_merged_config(filename): "daemonize": "False", "debug": "False", "execfile": None, - "aux_request_handler": None, } usagestr = "usage: %prog [-h] [options] [args]\n\n" + \ diff --git a/packaging/rpm/core.spec.in b/packaging/rpm/core.spec.in index 1ccbbc86..a8abe483 100644 --- a/packaging/rpm/core.spec.in +++ b/packaging/rpm/core.spec.in @@ -321,8 +321,6 @@ fi %{python_sitelib}/core/sdt.py* %{python_sitelib}/core/service.py* %{python_sitelib}/core/coreserver.py* -%dir %{python_sitelib}/core/addons -%{python_sitelib}/core/addons/__init__.py* %dir %{python_sitelib}/core/api %{python_sitelib}/core/api/coreapi.py* %{python_sitelib}/core/api/data.py* From a166c162f7cfe4a776564a8982a1c2ac4af41973 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 15 Jan 2018 01:27:10 -0800 Subject: [PATCH 026/152] fixed #136, added check for sphinx-apidoc to configure.ac --- configure.ac | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configure.ac b/configure.ac index eba5ab93..351e7223 100644 --- a/configure.ac +++ b/configure.ac @@ -172,6 +172,12 @@ else want_docs=no fi +# check for sphinx required during make +AC_CHECK_PROG(sphinxapi_path, sphinx-apidoc, $as_dir, no, $SEARCHPATH) +if test "x$sphinxapi_path" = "xno" ; then + AC_MSG_ERROR(["Could not location sphinx-apidoc, from the python-sphinx package"]) +fi + #AC_PATH_PROGS(tcl_path, [tclsh tclsh8.5 tclsh8.4], no) #if test "x$tcl_path" = "xno" ; then # AC_MSG_ERROR([Could not locate tclsh. Please install Tcl/Tk.]) From f4f5c9f5d87ed97db942a9db7ab3f00a7988b3b6 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 15 Jan 2018 02:20:11 -0800 Subject: [PATCH 027/152] fix #137 --- Changelog | 2 ++ Makefile.am | 2 +- daemon/Makefile.am | 7 +++++-- daemon/doc/Makefile.am | 2 +- sonar-project.properties | 4 ++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Changelog b/Changelog index c057ae83..8ae480ae 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,8 @@ - fixed some broken tests * BUGFIXES: - #142 - duplication of custom services + - #136 - sphinx-apidoc command not found + - #137 - make command fails when using distclean 2017-09-01 CORE 5.0 * DEVELOPMENT: diff --git a/Makefile.am b/Makefile.am index 438db6f6..271a6c13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ # if WANT_DOCS - DOCS = doc daemon/doc + DOCS = doc endif if WANT_GUI GUI = gui diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 42f7dcc7..6c21e6d6 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -10,6 +10,10 @@ SETUPPY = setup.py SETUPPYFLAGS = -v +if WANT_DOCS + SUBDIRS = doc +endif + SBIN_FILES = \ sbin/core-cleanup \ sbin/core-daemon \ @@ -121,8 +125,7 @@ rpm: dist-hook: rm -rf `find $(distdir)/ -name .svn` `find $(distdir)/ -name '*.pyc'` -DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST doc/Makefile.in doc/Makefile \ - doc/conf.py +DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST # files to include with distribution tarball EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) diff --git a/daemon/doc/Makefile.am b/daemon/doc/Makefile.am index ca3b5664..dd2d0bb8 100644 --- a/daemon/doc/Makefile.am +++ b/daemon/doc/Makefile.am @@ -8,7 +8,7 @@ # # extra cruft to remove -DISTCLEANFILES = conf.py Makefile.in stamp-vti *.rst +DISTCLEANFILES = conf.py Makefile Makefile.in stamp-vti *.rst all: index.rst diff --git a/sonar-project.properties b/sonar-project.properties index d579815b..46f00a5e 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,10 +1,10 @@ # branch name for the sonar analysis -sonar.branch=origin/cleanup +sonar.branch=origin/master # required metadata sonar.projectKey=CORE sonar.projectName=CORE -sonar.projectVersion=1.0.0 +sonar.projectVersion=5.1 # define modules sonar.modules=PythonLibrary From 6f4ef0e1931793f6e5ec888e549f9cef529e79c6 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 15 Jan 2018 10:50:14 -0800 Subject: [PATCH 028/152] removed unused import and update sonar config to scan different components separately --- daemon/sbin/core-daemon | 1 - sonar-project.properties | 25 ++++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index d544eb89..9469d6e1 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -16,7 +16,6 @@ message handlers are defined and some support for sending messages. import ConfigParser import atexit -import importlib import optparse import os import signal diff --git a/sonar-project.properties b/sonar-project.properties index 46f00a5e..32fbdb4b 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -7,7 +7,7 @@ sonar.projectName=CORE sonar.projectVersion=5.1 # define modules -sonar.modules=PythonLibrary +sonar.modules=daemon,ns3,netns # Encoding of the source files sonar.sourceEncoding=UTF-8 @@ -15,9 +15,20 @@ sonar.sourceEncoding=UTF-8 # scm provider sonar.scm.provider=git -# python adapter library -PythonLibrary.sonar.projectBaseDir=daemon -PythonLibrary.sonar.language=py -PythonLibrary.sonar.sources=./core -PythonLibrary.sonar.tests=./tests -PythonLibrary.sonar.python.coverage.reportPath=coverage.xml +# daemon files +daemon.sonar.projectBaseDir=daemon +daemon.sonar.language=py +daemon.sonar.sources=./core +daemon.sonar.tests=./tests +daemon.sonar.python.coverage.reportPath=coverage.xml + +# ns3 files +ns3.sonar.projectBaseDir=ns3 +ns3.sonar.language=py +ns3.sonar.sources=./corens3 + +# netns files +netns.sonar.projectBaseDir=netns +netns.sonar.language=c +netns.sonar.sources=./ +netns.sonar.cfamily.build-wrapper-output.bypass=true From 45e82f05b24a2c83ef3c1869f5585645dd99e73c Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 5 Feb 2018 09:01:49 -0800 Subject: [PATCH 029/152] attempt to better support dynamic emane models --- daemon/core/emane/emanemanager.py | 19 ++++++- daemon/core/misc/utils.py | 88 +++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 69722796..f60b1084 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -29,6 +29,8 @@ from core.misc import utils from core.misc.ipaddress import MacAddress from core.xml import xmlutils +_PATH = os.path.abspath(os.path.dirname(__file__)) + # EMANE 0.7.4/0.8.1 try: import emaneeventservice @@ -91,7 +93,7 @@ class EmaneManager(ConfigurableManager): self._modelclsmap = { self.emane_config.name: self.emane_config } - self.loadmodels() + self.load_models(_PATH) def logversion(self): """ @@ -192,6 +194,21 @@ class EmaneManager(ConfigurableManager): self.session.add_config_object(emane_model.name, emane_model.config_type, emane_model.configure_emane) + def load_models(self, path): + """ + Loads EMANE models into the manager for usage within CORE. + + :param str path: path to retrieve model from + :return: nothing + """ + emane_models = utils.load_classes(path, EmaneModel) + for emane_model in emane_models: + logger.info("loading emane model: (%s) %s - %s", + emane_model, emane_model.name, RegisterTlvs(emane_model.config_type)) + self._modelclsmap[emane_model.name] = emane_model + self.session.add_config_object(emane_model.name, emane_model.config_type, + emane_model.configure_emane) + def addobj(self, obj): """ add a new EmaneNode object to this Emane controller object diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 62dccd0c..7eb9281c 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -2,8 +2,11 @@ Miscellaneous utility functions, wrappers around some subprocess procedures. """ +import importlib +import inspect import os import subprocess +import sys import fcntl import resource @@ -445,3 +448,88 @@ def checkforkernelmodule(name): if line.startswith(name + " "): return line.rstrip() return None + + +def _valid_module(path, file_name): + """ + Check if file is a valid python module. + + :param str path: path to file + :param str file_name: file name to check + :return: True if a valid python module file, False otherwise + :rtype: bool + """ + file_path = os.path.join(path, file_name) + if not os.path.isfile(file_path): + return False + + if file_name.startswith("_"): + return False + + if not file_name.endswith(".py"): + return False + + return True + + +def _is_class(module, member, clazz): + """ + Validates if a module member is a class and an instance of a CoreService. + + :param module: module to validate for service + :param member: member to validate for service + :param clazz: clazz type to check for validation + :return: True if a valid service, False otherwise + :rtype: bool + """ + if not inspect.isclass(member): + return False + + if not issubclass(member, clazz): + return False + + if member.__module__ != module.__name__: + return False + + return True + + +def load_classes(path, clazz): + """ + Dynamically load classes for use within CORE. + + :param path: path to load classes from + :param clazz: class type expected to be inherited from for loading + :return: list of classes loaded + """ + # validate path exists + logger.info("attempting to load modules from path: %s", path) + if not os.path.isdir(path): + logger.warn("invalid custom module directory specified" ": %s" % path) + # check if path is in sys.path + parent_path = os.path.dirname(path) + if parent_path not in sys.path: + logger.info("adding parent path to allow imports: %s", parent_path) + sys.path.append(parent_path) + + # retrieve potential service modules, and filter out invalid modules + base_module = os.path.basename(path) + module_names = os.listdir(path) + module_names = filter(lambda x: _valid_module(path, x), module_names) + module_names = map(lambda x: x[:-3], module_names) + + # import and add all service modules in the path + classes = [] + for module_name in module_names: + import_statement = "%s.%s" % (base_module, module_name) + logger.info("importing custom module: %s", import_statement) + try: + module = importlib.import_module(import_statement) + members = inspect.getmembers(module, lambda x: _is_class(module, x, clazz)) + for member in members: + clazz = member[1] + classes.append(clazz) + except: + logger.exception("unexpected error during import, skipping: %s", import_statement) + + return classes From c4a61b269b9453c1a2157802d79af3fb06615b42 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 5 Feb 2018 11:22:01 -0800 Subject: [PATCH 030/152] updates to support dynamic loading of emane models from a custom emane directory --- configure.ac | 4 +- daemon/core/emane/emanemanager.py | 28 +++++------ daemon/core/misc/utils.py | 4 +- daemon/core/service.py | 77 ++--------------------------- daemon/data/core.conf | 2 +- daemon/examples/myemane/__init__.py | 0 gui/core-gui.in | 6 +++ 7 files changed, 26 insertions(+), 95 deletions(-) create mode 100644 daemon/examples/myemane/__init__.py diff --git a/configure.ac b/configure.ac index 351e7223..b309eb30 100644 --- a/configure.ac +++ b/configure.ac @@ -12,10 +12,10 @@ # # this defines the CORE version number, must be static for AC_INIT # -AC_INIT(core, m4_esyscmd_s([./revision.sh 5.1]), core-dev@nrl.navy.mil) +AC_INIT(core, 5.1, core-dev@nrl.navy.mil) VERSION=$PACKAGE_VERSION CORE_VERSION=$PACKAGE_VERSION -CORE_VERSION_DATE=m4_esyscmd_s([./revision.sh -d]) +CORE_VERSION_DATE=m4_esyscmd_s([date +%Y%m%d]) COREDPY_VERSION=$PACKAGE_VERSION CORE_MAINTAINERS="CORE Developers " CORE_VENDOR="CORE Developers" diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index f60b1084..918f2c56 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -93,7 +93,16 @@ class EmaneManager(ConfigurableManager): self._modelclsmap = { self.emane_config.name: self.emane_config } - self.load_models(_PATH) + + # load provided models + self.load_models(EMANE_MODELS) + + # load custom models + custom_models_path = session.config.get("emane_models_dir") + if custom_models_path: + emane_models = utils.load_classes(custom_models_path, EmaneModel) + self.load_models(emane_models) + def logversion(self): """ @@ -183,25 +192,10 @@ class EmaneManager(ConfigurableManager): return rc - def loadmodels(self): + def load_models(self, emane_models): """ load EMANE models and make them available. """ - for emane_model in EMANE_MODELS: - logger.info("loading emane model: (%s) %s - %s", - emane_model, emane_model.name, RegisterTlvs(emane_model.config_type)) - self._modelclsmap[emane_model.name] = emane_model - self.session.add_config_object(emane_model.name, emane_model.config_type, - emane_model.configure_emane) - - def load_models(self, path): - """ - Loads EMANE models into the manager for usage within CORE. - - :param str path: path to retrieve model from - :return: nothing - """ - emane_models = utils.load_classes(path, EmaneModel) for emane_model in emane_models: logger.info("loading emane model: (%s) %s - %s", emane_model, emane_model.name, RegisterTlvs(emane_model.config_type)) diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 7eb9281c..f99847c7 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -527,8 +527,8 @@ def load_classes(path, clazz): module = importlib.import_module(import_statement) members = inspect.getmembers(module, lambda x: _is_class(module, x, clazz)) for member in members: - clazz = member[1] - classes.append(clazz) + valid_class = member[1] + classes.append(valid_class) except: logger.exception("unexpected error during import, skipping: %s", import_statement) diff --git a/daemon/core/service.py b/daemon/core/service.py index 3b76eb0a..16b7834d 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -29,49 +29,6 @@ from core.enumerations import RegisterTlvs from core.misc import utils -def _valid_module(path, file_name): - """ - Check if file is a valid python module. - - :param str path: path to file - :param str file_name: file name to check - :return: True if a valid python module file, False otherwise - :rtype: bool - """ - file_path = os.path.join(path, file_name) - if not os.path.isfile(file_path): - return False - - if file_name.startswith("_"): - return False - - if not file_name.endswith(".py"): - return False - - return True - - -def _is_service(module, member): - """ - Validates if a module member is a class and an instance of a CoreService. - - :param module: module to validate for service - :param member: member to validate for service - :return: True if a valid service, False otherwise - :rtype: bool - """ - if not inspect.isclass(member): - return False - - if not issubclass(member, CoreService): - return False - - if member.__module__ != module.__name__: - return False - - return True - - class ServiceManager(object): """ Manages services available for CORE nodes to use. @@ -118,36 +75,10 @@ class ServiceManager(object): :return: list of core services :rtype: list """ - # validate path exists - logger.info("attempting to add services from path: %s", path) - if not os.path.isdir(path): - logger.warn("invalid custom service directory specified" ": %s" % path) - # check if path is in sys.path - logger.info("getting custom services from: %s", path) - parent_path = os.path.dirname(path) - if parent_path not in sys.path: - logger.info("adding parent path to allow imports: %s", parent_path) - sys.path.append(parent_path) - - # retrieve potential service modules, and filter out invalid modules - base_module = os.path.basename(path) - module_names = os.listdir(path) - module_names = filter(lambda x: _valid_module(path, x), module_names) - module_names = map(lambda x: x[:-3], module_names) - - # import and add all service modules in the path - for module_name in module_names: - import_statement = "%s.%s" % (base_module, module_name) - logger.info("importing custom service module: %s", import_statement) - try: - module = importlib.import_module(import_statement) - members = inspect.getmembers(module, lambda x: _is_service(module, x)) - for member in members: - clazz = member[1] - clazz.on_load() - cls.add(clazz) - except: - logger.exception("unexpected error during import, skipping: %s", import_statement) + services = utils.load_classes(path, CoreService) + for service in services: + service.on_load() + cls.add(service) class CoreServices(ConfigurableManager): diff --git a/daemon/data/core.conf b/daemon/data/core.conf index 032d4390..97bb96bb 100644 --- a/daemon/data/core.conf +++ b/daemon/data/core.conf @@ -57,7 +57,7 @@ emane_platform_port = 8101 emane_transform_port = 8201 emane_event_generate = True emane_event_monitor = False -emane_models = RfPipe, Ieee80211abg, CommEffect, Bypass, Tdma +#emane_models_dir = /home/username/.core/emane # EMANE log level range [0,4] default: 2 #emane_log_level = 2 emane_realtime = True diff --git a/daemon/examples/myemane/__init__.py b/daemon/examples/myemane/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/gui/core-gui.in b/gui/core-gui.in index 2c42c186..a66d7f77 100755 --- a/gui/core-gui.in +++ b/gui/core-gui.in @@ -88,6 +88,12 @@ init_conf_dir() { else cp -a $CORE_DATA_DIR/examples/myservices/* $CONFDIR/myservices/ fi + mkdir -p $CONFDIR/myemane + if [ $? != 0 ]; then + echo "error making directory $CONFDIR/myemane!"; + else + cp -a $CORE_DATA_DIR/examples/myemane/* $CONFDIR/myemane/ + fi } cd $LIBDIR From 49a2f77f456ab20680e18552866f1474388529d9 Mon Sep 17 00:00:00 2001 From: Kevin Date: Mon, 26 Feb 2018 10:52:08 -0800 Subject: [PATCH 031/152] Added code to not query sdn information when node is offline --- daemon/core/netns/vnode.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 3879c5e1..400362b6 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -311,14 +311,16 @@ class SimpleLxcNode(PyCoreNode): veth.name = ifname - # retrieve interface information - result, output = self.cmdresult(["ip", "link", "show", veth.name]) - logger.info("interface command output: %s", output) - output = output.split("\n") - veth.flow_id = int(output[0].strip().split(":")[0]) + 1 - logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) - veth.hwaddr = output[1].strip().split()[1] - logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) + if self.up: + # TODO: potentially find better way to query interface ID + # retrieve interface information + result, output = self.cmdresult(["ip", "link", "show", veth.name]) + logger.info("interface command output: %s", output) + output = output.split("\n") + veth.flow_id = int(output[0].strip().split(":")[0]) + 1 + logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) + veth.hwaddr = output[1].strip().split()[1] + logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) try: self.addnetif(veth, ifindex) From 6b8ee13f5ded762c08816f58fbb81599038fb0dd Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Feb 2018 10:48:01 -0800 Subject: [PATCH 032/152] initial changes to try and cleanup shell commands used within core --- daemon/core/bsd/vnode.py | 1 - daemon/core/corehandlers.py | 8 +- daemon/core/coreobj.py | 2 +- daemon/core/emane/emanemanager.py | 11 +- daemon/core/netns/vif.py | 12 +- daemon/core/netns/vnode.py | 137 +++--------- daemon/core/netns/vnodeclient.py | 195 +++++++----------- daemon/core/service.py | 10 +- daemon/core/session.py | 3 +- daemon/examples/netns/basicrange.py | 2 +- daemon/examples/netns/distributed.py | 2 +- daemon/examples/netns/emane80211.py | 2 +- daemon/examples/netns/howmanynodes.py | 2 +- .../examples/netns/iperf-performance-chain.py | 8 +- daemon/examples/netns/ospfmanetmdrtest.py | 7 +- daemon/examples/netns/switch.py | 2 +- daemon/examples/netns/switchtest.py | 6 +- daemon/examples/netns/wlanemanetests.py | 18 +- daemon/examples/netns/wlantest.py | 6 +- daemon/tests/conftest.py | 12 +- daemon/tests/test_core.py | 28 ++- doc/scripting.rst | 2 +- 22 files changed, 185 insertions(+), 291 deletions(-) diff --git a/daemon/core/bsd/vnode.py b/daemon/core/bsd/vnode.py index 57967dbf..5e28eff8 100644 --- a/daemon/core/bsd/vnode.py +++ b/daemon/core/bsd/vnode.py @@ -282,7 +282,6 @@ class SimpleJailNode(PyCoreNode): def getaddr(self, ifname, rescan=False): return None - # return self.vnodeclient.getaddr(ifname = ifname, rescan = rescan) def addsymlink(self, path, file): """ diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index dc6fe0af..b770e38e 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -988,7 +988,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): upstream = True netif = net2.getlinknetif(net) if netif is None: - raise ValueError, "modify unknown link between nets" + raise ValueError("modify unknown link between nets") if upstream: netif.swapparams("_params_up") net.linkconfig(netif, bw=bw, delay=delay, @@ -1087,7 +1087,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # echo back exec message with cmd for spawning interactive terminal if command == "bash": command = "/bin/bash" - res = node.termcmdstring(command) + res = node.client.termcmdstring(command) tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data) return reply, @@ -1099,7 +1099,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if message.flags & MessageFlags.LOCAL.value: status, res = utils.cmdresult(shlex.split(command)) else: - status, res = node.cmdresult(shlex.split(command)) + status, res = node.client.cmdresult(shlex.split(command)) logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res)) if message.flags & MessageFlags.TEXT.value: tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) @@ -1112,7 +1112,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if message.flags & MessageFlags.LOCAL.value: utils.mutedetach(shlex.split(command)) else: - node.cmd(shlex.split(command), wait=False) + node.client.cmd(shlex.split(command), wait=False) except KeyError: logger.exception("error getting object: %s", node_num) # XXX wait and queue this message to try again later diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 76fb59e0..962c4a2a 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -556,7 +556,7 @@ class PyCoreNetIf(object): """ Creates a PyCoreNetIf instance. - :param node: node for interface + :param core.netns.vnode.SimpleLxcNode node: node for interface :param str name: interface name :param mtu: mtu value """ diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 918f2c56..49780661 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -912,17 +912,16 @@ class EmaneManager(ConfigurableManager): # multicast route is needed for OTA data cmd = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] - # rc = node.cmd(cmd, wait=True) - node.cmd(cmd, wait=True) + node.client.cmd(cmd, wait=True) # multicast route is also needed for event data if on control network if eventservicenetidx >= 0 and eventgroup != otagroup: cmd = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] - node.cmd(cmd, wait=True) + node.client.cmd(cmd, wait=True) try: cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] logger.info("Emane.startdaemons2() running %s" % str(cmd)) - status, output = node.cmdresult(cmd) + status, output = node.client.cmdresult(cmd) logger.info("Emane.startdaemons2() return code %d" % status) logger.info("Emane.startdaemons2() output: %s" % output) except subprocess.CalledProcessError: @@ -955,7 +954,7 @@ class EmaneManager(ConfigurableManager): stop_emane_on_host = True continue if node.up: - node.cmd(cmd, wait=False) + node.client.cmd(cmd, wait=False) # TODO: RJ45 node else: stop_emane_on_host = True @@ -1161,7 +1160,7 @@ class EmaneManager(ConfigurableManager): if emane.VERSION < emane.EMANE092: status = subprocess.call(cmd) else: - status = node.cmd(cmd, wait=True) + status = node.client.cmd(cmd, wait=True) except IOError: logger.exception("error checking if emane is running") diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index 7f254858..33d656ac 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -60,7 +60,7 @@ class VEth(PyCoreNetIf): if not self.up: return if self.node: - self.node.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) + self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) if self.localname: utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname]) self.up = False @@ -112,7 +112,7 @@ class TunTap(PyCoreNetIf): """ if not self.up: return - self.node.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) + self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) # if self.name: # mutedetach(["tunctl", "-d", self.localname]) self.up = False @@ -169,7 +169,7 @@ class TunTap(PyCoreNetIf): def nodedevexists(): cmd = (constants.IP_BIN, "link", "show", self.name) - return self.node.cmd(cmd) + return self.node.client.cmd(cmd) count = 0 while True: @@ -206,8 +206,8 @@ class TunTap(PyCoreNetIf): logger.exception(msg) return - self.node.cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) - self.node.cmd([constants.IP_BIN, "link", "set", self.name, "up"]) + self.node.client.cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) + self.node.client.cmd([constants.IP_BIN, "link", "set", self.name, "up"]) def setaddrs(self): """ @@ -217,7 +217,7 @@ class TunTap(PyCoreNetIf): """ self.waitfordevicenode() for addr in self.addrlist: - self.node.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) + self.node.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) class GreTap(PyCoreNetIf): diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 400362b6..7dd70e0a 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -27,6 +27,14 @@ utils.check_executables([constants.IP_BIN]) class SimpleLxcNode(PyCoreNode): """ Provides simple lxc functionality for core nodes. + + :type nodedir: str + :type ctrlchnlname: str + :type client: core.netns.vnodeclient.VnodeClient + :type pid: int + :type up: bool + :type lock: threading.RLock + :type _mounts: list[tuple[str, str]] """ valid_deladdrtype = ("inet", "inet6", "inet6link") @@ -43,7 +51,7 @@ class SimpleLxcNode(PyCoreNode): PyCoreNode.__init__(self, session, objid, name, start=start) self.nodedir = nodedir self.ctrlchnlname = os.path.abspath(os.path.join(self.session.session_dir, self.name)) - self.vnodeclient = None + self.client = None self.pid = None self.up = False self.lock = threading.RLock() @@ -100,11 +108,11 @@ class SimpleLxcNode(PyCoreNode): if tmp.wait(): raise Exception("command failed: %s" % vnoded) - self.vnodeclient = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) + self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) logger.info("bringing up loopback interface") - self.cmd([constants.IP_BIN, "link", "set", "lo", "up"]) + self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"]) logger.info("setting hostname: %s" % self.name) - self.cmd(["hostname", self.name]) + self.client.cmd(["hostname", self.name]) self.up = True def shutdown(self): @@ -142,88 +150,9 @@ class SimpleLxcNode(PyCoreNode): # clear interface data, close client, and mark self and not up self._netif.clear() - self.vnodeclient.close() + self.client.close() self.up = False - # TODO: potentially remove all these wrapper methods, just make use of object itself. - def cmd(self, args, wait=True): - """ - Wrapper around vnodeclient cmd. - - :param args: arguments for ocmmand - :param wait: wait or not - :return: - """ - return self.vnodeclient.cmd(args, wait) - - def cmdresult(self, args): - """ - Wrapper around vnodeclient cmdresult. - - :param args: arguments for ocmmand - :return: - """ - return self.vnodeclient.cmdresult(args) - - def popen(self, args): - """ - Wrapper around vnodeclient popen. - - :param args: arguments for ocmmand - :return: - """ - return self.vnodeclient.popen(args) - - def icmd(self, args): - """ - Wrapper around vnodeclient icmd. - - :param args: arguments for ocmmand - :return: - """ - return self.vnodeclient.icmd(args) - - def redircmd(self, infd, outfd, errfd, args, wait=True): - """ - Wrapper around vnodeclient redircmd. - - :param infd: input file descriptor - :param outfd: output file descriptor - :param errfd: err file descriptor - :param args: command arguments - :param wait: wait or not - :return: - """ - return self.vnodeclient.redircmd(infd, outfd, errfd, args, wait) - - def term(self, sh="/bin/sh"): - """ - Wrapper around vnodeclient term. - - :param sh: shell to create terminal for - :return: - """ - return self.vnodeclient.term(sh=sh) - - def termcmdstring(self, sh="/bin/sh"): - """ - Wrapper around vnodeclient termcmdstring. - - :param sh: shell to run command in - :return: - """ - return self.vnodeclient.termcmdstring(sh=sh) - - def shcmd(self, cmdstr, sh="/bin/sh"): - """ - Wrapper around vnodeclient shcmd. - - :param str cmdstr: command string - :param sh: shell to run command in - :return: - """ - return self.vnodeclient.shcmd(cmdstr, sh=sh) - def boot(self): """ Boot logic. @@ -243,9 +172,8 @@ class SimpleLxcNode(PyCoreNode): source = os.path.abspath(source) logger.info("mounting %s at %s" % (source, target)) try: - shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % ( - target, constants.MOUNT_BIN, source, target) - self.shcmd(shcmd) + shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) + self.client.shcmd(shcmd) self._mounts.append((source, target)) except IOError: logger.exception("mounting failed for %s at %s", source, target) @@ -259,7 +187,7 @@ class SimpleLxcNode(PyCoreNode): """ logger.info("unmounting: %s", target) try: - self.cmd([constants.UMOUNT_BIN, "-n", "-l", target]) + self.client.cmd([constants.UMOUNT_BIN, "-n", "-l", target]) except IOError: logger.exception("unmounting failed for %s" % target) @@ -307,14 +235,14 @@ class SimpleLxcNode(PyCoreNode): if self.up: subprocess.check_call([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) - self.cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) + self.client.cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) veth.name = ifname if self.up: # TODO: potentially find better way to query interface ID # retrieve interface information - result, output = self.cmdresult(["ip", "link", "show", veth.name]) + result, output = self.client.cmdresult(["ip", "link", "show", veth.name]) logger.info("interface command output: %s", output) output = output.split("\n") veth.flow_id = int(output[0].strip().split(":")[0]) + 1 @@ -375,8 +303,8 @@ class SimpleLxcNode(PyCoreNode): """ self._netif[ifindex].sethwaddr(addr) if self.up: - (status, result) = self.cmdresult([constants.IP_BIN, "link", "set", "dev", - self.ifname(ifindex), "address", str(addr)]) + (status, result) = self.client.cmdresult([constants.IP_BIN, "link", "set", "dev", + self.ifname(ifindex), "address", str(addr)]) if status: logger.error("error setting MAC address %s", str(addr)) @@ -390,11 +318,11 @@ class SimpleLxcNode(PyCoreNode): """ if self.up: if ":" in str(addr): # check if addr is ipv6 - self.cmd([constants.IP_BIN, "addr", "add", str(addr), - "dev", self.ifname(ifindex)]) + self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), + "dev", self.ifname(ifindex)]) else: - self.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", - "dev", self.ifname(ifindex)]) + self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", + "dev", self.ifname(ifindex)]) self._netif[ifindex].addaddr(addr) def deladdr(self, ifindex, addr): @@ -411,7 +339,7 @@ class SimpleLxcNode(PyCoreNode): logger.exception("trying to delete unknown address: %s" % addr) if self.up: - self.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) + self.client.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) def delalladdr(self, ifindex, addrtypes=valid_deladdrtype): """ @@ -438,7 +366,7 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - self.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) + self.client.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): """ @@ -503,13 +431,12 @@ class SimpleLxcNode(PyCoreNode): "type", "veth", "peer", "name", tmp2]) subprocess.call([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) - self.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) + self.client.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) self.addnetif(PyCoreNetIf(self, ifname), self.newifindex()) subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) - othernode.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) - othernode.addnetif(PyCoreNetIf(othernode, otherifname), - othernode.newifindex()) + othernode.client.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) + othernode.addnetif(PyCoreNetIf(othernode, otherifname), othernode.newifindex()) def addfile(self, srcname, filename): """ @@ -520,7 +447,7 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename) - self.shcmd(shcmd) + self.client.shcmd(shcmd) def getaddr(self, ifname, rescan=False): """ @@ -530,7 +457,7 @@ class SimpleLxcNode(PyCoreNode): :param bool rescan: rescan flag :return: """ - return self.vnodeclient.getaddr(ifname=ifname, rescan=rescan) + return self.client.getaddr(ifname=ifname, rescan=rescan) def netifstats(self, ifname=None): """ @@ -539,7 +466,7 @@ class SimpleLxcNode(PyCoreNode): :param str ifname: interface name to get state for :return: """ - return self.vnodeclient.netifstats(ifname=ifname) + return self.client.netifstats(ifname=ifname) class LxcNode(SimpleLxcNode): diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 1d5fb05f..f7b36f4b 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -6,17 +6,12 @@ by invoking the vcmd shell command. """ import os -import stat -import subprocess + +import vcmd from core import constants from core import logger -USE_VCMD_MODULE = True - -if USE_VCMD_MODULE: - import vcmd - VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd") @@ -34,12 +29,19 @@ class VnodeClient(object): """ self.name = name self.ctrlchnlname = ctrlchnlname - if USE_VCMD_MODULE: - self.cmdchnl = vcmd.VCmd(self.ctrlchnlname) - else: - self.cmdchnl = None + self.cmdchnl = vcmd.VCmd(self.ctrlchnlname) self._addr = {} + def _verify_connection(self): + """ + Checks that the vcmd client is properly connected. + + :return: nothing + :raises ValueError: when not connected + """ + if not self.connected(): + raise ValueError("vcmd not connected") + def connected(self): """ Check if node is connected or not. @@ -47,10 +49,7 @@ class VnodeClient(object): :return: True if connected, False otherwise :rtype: bool """ - if USE_VCMD_MODULE: - return self.cmdchnl.connected() - else: - return True + return self.cmdchnl.connected() def close(self): """ @@ -58,8 +57,7 @@ class VnodeClient(object): :return: nothing """ - if USE_VCMD_MODULE: - self.cmdchnl.close() + self.cmdchnl.close() def cmd(self, args, wait=True): """ @@ -70,24 +68,16 @@ class VnodeClient(object): :return: command status :rtype: int """ - if USE_VCMD_MODULE: - if not self.cmdchnl.connected(): - raise ValueError("self.cmdchnl not connected") - tmp = self.cmdchnl.qcmd(args) - if not wait: - return tmp - tmp = tmp.wait() - else: - if wait: - mode = os.P_WAIT - else: - mode = os.P_NOWAIT - tmp = os.spawnlp(mode, VCMD, VCMD, "-c", self.ctrlchnlname, "-q", "--", *args) - if not wait: - return tmp + self._verify_connection() + + # TODO: clean this up after checking return value for qcmd + tmp = self.cmdchnl.qcmd(args) + if not wait: + return tmp + tmp = tmp.wait() if tmp: - logger.warn("cmd exited with status %s: %s" % (tmp, str(args))) + logger.warn("cmd exited with status %s: %s", tmp, args) return tmp @@ -101,14 +91,16 @@ class VnodeClient(object): :return: command status and combined stdout and stderr output :rtype: tuple[int, str] """ - cmdid, cmdin, cmdout, cmderr = self.popen(args) - result = cmdout.read() - result += cmderr.read() - cmdin.close() - cmdout.close() - cmderr.close() - status = cmdid.wait() - return status, result + self._verify_connection() + + p, stdin, stdout, stderr = self.popen(args) + output = stdout.read() + stderr.read() + stdin.close() + stdout.close() + stderr.close() + status = p.wait() + + return status, output def popen(self, args): """ @@ -118,15 +110,8 @@ class VnodeClient(object): :return: popen object, stdin, stdout, and stderr :rtype: tuple """ - if USE_VCMD_MODULE: - if not self.cmdchnl.connected(): - raise ValueError("self.cmdchnl not connected") - return self.cmdchnl.popen(args) - else: - cmd = [VCMD, "-c", self.ctrlchnlname, "--"] - cmd.extend(args) - tmp = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - return tmp, tmp.stdin, tmp.stdout, tmp.stderr + self._verify_connection() + return self.cmdchnl.popen(args) def icmd(self, args): """ @@ -151,18 +136,20 @@ class VnodeClient(object): :return: command status :rtype: int """ - if not USE_VCMD_MODULE: - raise NotImplementedError - if not self.cmdchnl.connected(): - raise ValueError("self.cmdchnl not connected") + self._verify_connection() + + # TODO: clean this up after verifying redircmd return values tmp = self.cmdchnl.redircmd(infd, outfd, errfd, args) if not wait: return tmp + tmp = tmp.wait() if tmp: - logger.warn("cmd exited with status %s: %s" % (tmp, str(args))) + logger.warn("cmd exited with status %s: %s", tmp, args) + return tmp + # TODO: validate if this is ever used def term(self, sh="/bin/sh"): """ Open a terminal on a node. @@ -171,8 +158,7 @@ class VnodeClient(object): :return: terminal command result :rtype: int """ - cmd = ("xterm", "-ut", "-title", self.name, "-e", - VCMD, "-c", self.ctrlchnlname, "--", sh) + cmd = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh) if "SUDO_USER" in os.environ: cmd = ("su", "-s", "/bin/sh", "-c", "exec " + " ".join(map(lambda x: "'%s'" % x, cmd)), @@ -210,35 +196,36 @@ class VnodeClient(object): """ if ifname in self._addr and not rescan: return self._addr[ifname] - tmp = {"ether": [], "inet": [], "inet6": [], "inet6link": []} - cmd = [constants.IP_BIN, "addr", "show", "dev", ifname] - cmdid, cmdin, cmdout, cmderr = self.popen(cmd) - cmdin.close() - for line in cmdout: + interface = {"ether": [], "inet": [], "inet6": [], "inet6link": []} + cmd = [constants.IP_BIN, "addr", "show", "dev", ifname] + p, stdin, stdout, stderr = self.popen(cmd) + stdin.close() + + for line in stdout: line = line.strip().split() if line[0] == "link/ether": - tmp["ether"].append(line[1]) + interface["ether"].append(line[1]) elif line[0] == "inet": - tmp["inet"].append(line[1]) + interface["inet"].append(line[1]) elif line[0] == "inet6": if line[3] == "global": - tmp["inet6"].append(line[1]) + interface["inet6"].append(line[1]) elif line[3] == "link": - tmp["inet6link"].append(line[1]) + interface["inet6link"].append(line[1]) else: logger.warn("unknown scope: %s" % line[3]) - err = cmderr.read() - cmdout.close() - cmderr.close() - status = cmdid.wait() + err = stderr.read() + stdout.close() + stderr.close() + status = p.wait() if status: - logger.warn("nonzero exist status (%s) for cmd: %s" % (status, cmd)) + logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd) if err: - logger.warn("error output: %s" % err) - self._addr[ifname] = tmp - return tmp + logger.warn("error output: %s", err) + self._addr[ifname] = interface + return interface def netifstats(self, ifname=None): """ @@ -250,15 +237,15 @@ class VnodeClient(object): """ stats = {} cmd = ["cat", "/proc/net/dev"] - cmdid, cmdin, cmdout, cmderr = self.popen(cmd) - cmdin.close() + p, stdin, stdout, stderr = self.popen(cmd) + stdin.close() # ignore first line - cmdout.readline() + stdout.readline() # second line has count names - tmp = cmdout.readline().strip().split("|") + tmp = stdout.readline().strip().split("|") rxkeys = tmp[1].split() txkeys = tmp[2].split() - for line in cmdout: + for line in stdout: line = line.strip().split() devname, tmp = line[0].split(":") if tmp: @@ -271,53 +258,15 @@ class VnodeClient(object): for count in txkeys: stats[devname]["tx"][count] = int(line[field]) field += 1 - err = cmderr.read() - cmdout.close() - cmderr.close() - status = cmdid.wait() + err = stderr.read() + stdout.close() + stderr.close() + status = p.wait() if status: - logger.warn("nonzero exist status (%s) for cmd: %s" % (status, cmd)) + logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd) if err: - logger.warn("error output: %s" % err) + logger.warn("error output: %s", err) if ifname is not None: return stats[ifname] else: return stats - - -def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None): - """ - Create clients - - :param str sessiondir: session directory to create clients - :param class clientcls: class to create clients from - :param func cmdchnlfilterfunc: command channel filter function - :return: list of created clients - :rtype: list - """ - direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir)) - cmdchnls = filter(lambda x: stat.S_ISSOCK(os.stat(x).st_mode), direntries) - if cmdchnlfilterfunc: - cmdchnls = filter(cmdchnlfilterfunc, cmdchnls) - cmdchnls.sort() - return map(lambda x: clientcls(os.path.basename(x), x), cmdchnls) - - -def createremoteclients(sessiondir, clientcls=VnodeClient, filterfunc=None): - """ - Creates remote VnodeClients, for nodes emulated on other machines. The - session.Broker writes a n1.conf/server file having the server's info. - - :param str sessiondir: session directory to create clients - :param class clientcls: class to create clients from - :param func filterfunc: filter function - :return: list of remove clients - :rtype: list - """ - direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir)) - nodedirs = filter(lambda x: stat.S_ISDIR(os.stat(x).st_mode), direntries) - nodedirs = filter(lambda x: os.path.exists(os.path.join(x, "server")), nodedirs) - if filterfunc: - nodedirs = filter(filterfunc, nodedirs) - nodedirs.sort() - return map(lambda x: clientcls(x), nodedirs) diff --git a/daemon/core/service.py b/daemon/core/service.py index 16b7834d..b212d3e9 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -312,7 +312,7 @@ class CoreServices(ConfigurableManager): for cmd in service.getstartup(node, services): try: # NOTE: this wait=False can be problematic! - node.cmd(shlex.split(cmd), wait=False) + node.client.cmd(shlex.split(cmd), wait=False) except: logger.exception("error starting command %s", cmd) @@ -358,7 +358,7 @@ class CoreServices(ConfigurableManager): for cmd in service._startup: try: # NOTE: this wait=False can be problematic! - node.cmd(shlex.split(cmd), wait=False) + node.client.cmd(shlex.split(cmd), wait=False) except: logger.exception("error starting command %s", cmd) @@ -417,7 +417,7 @@ class CoreServices(ConfigurableManager): for cmd in validate_cmds: logger.info("validating service %s using: %s", service._name, cmd) try: - status, result = node.cmdresult(shlex.split(cmd)) + status, result = node.client.cmdresult(shlex.split(cmd)) if status != 0: raise ValueError("non-zero exit status") except: @@ -453,7 +453,7 @@ class CoreServices(ConfigurableManager): else: for cmd in service._shutdown: try: - tmp = node.cmd(shlex.split(cmd), wait=True) + tmp = node.client.cmd(shlex.split(cmd), wait=True) status += "%s" % tmp except: logger.exception("error running stop command %s", cmd) @@ -766,7 +766,7 @@ class CoreServices(ConfigurableManager): for cmd in cmds: try: # node.cmd(shlex.split(cmd), wait = False) - status = node.cmd(shlex.split(cmd), wait=True) + status = node.client.cmd(shlex.split(cmd), wait=True) if status != 0: fail += "Start %s(%s)," % (s._name, cmd) except: diff --git a/daemon/core/session.py b/daemon/core/session.py index aba53711..f4d7e01d 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -610,6 +610,7 @@ class Session(object): :param int object_id: object id to retrieve :return: object for the given id + :rtype: core.netns.vnode.SimpleLxcNode """ if object_id not in self.objects: raise KeyError("unknown object id %s" % object_id) @@ -1257,7 +1258,7 @@ class Session(object): utils.mutedetach(commands) else: node = self.get_object(node_id) - node.cmd(commands, wait=False) + node.client.cmd(commands, wait=False) def send_objects(self): """ diff --git a/daemon/examples/netns/basicrange.py b/daemon/examples/netns/basicrange.py index b1fdd2f8..a6a29348 100755 --- a/daemon/examples/netns/basicrange.py +++ b/daemon/examples/netns/basicrange.py @@ -59,7 +59,7 @@ def test(options): # launches terminal for the first node # n[0].term("bash") - n[0].icmd(["ping", "-c", "5", "127.0.0.1"]) + n[0].client.icmd(["ping", "-c", "5", "127.0.0.1"]) # wait for rate seconds to allow ebtables commands to commit time.sleep(EbtablesQueue.rate) diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index 81cc7e3f..1674b4df 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -82,7 +82,7 @@ def main(): for i in xrange(1, num_local + 1): node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + node.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) node.setposition(x=150 * i, y=150) n.append(node) diff --git a/daemon/examples/netns/emane80211.py b/daemon/examples/netns/emane80211.py index e1874158..3ca5ae45 100755 --- a/daemon/examples/netns/emane80211.py +++ b/daemon/examples/netns/emane80211.py @@ -84,7 +84,7 @@ def main(): tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.setposition(x=150 * i, y=150) session.services.addservicestonode(tmp, "", services_str) n.append(tmp) diff --git a/daemon/examples/netns/howmanynodes.py b/daemon/examples/netns/howmanynodes.py index 8803d872..bff69478 100755 --- a/daemon/examples/netns/howmanynodes.py +++ b/daemon/examples/netns/howmanynodes.py @@ -159,7 +159,7 @@ def main(): try: n = session.add_object(cls=nodes.LxcNode, name="n%d" % i) n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + n.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) if options.services is not None: session.services.addservicestonode(n, "", options.services) n.boot() diff --git a/daemon/examples/netns/iperf-performance-chain.py b/daemon/examples/netns/iperf-performance-chain.py index e946f727..ddc08568 100755 --- a/daemon/examples/netns/iperf-performance-chain.py +++ b/daemon/examples/netns/iperf-performance-chain.py @@ -19,7 +19,7 @@ import optparse import sys from core import constants -from core.misc import ipaddress +from core.misc import ipaddress from core.netns import nodes # node list (count from 1) @@ -72,9 +72,9 @@ def main(): prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i) right = session.add_object(cls=nodes.PtpNet) tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) + tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) + tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) tmp.setposition(x=100 * i, y=150) n.append(tmp) left = right diff --git a/daemon/examples/netns/ospfmanetmdrtest.py b/daemon/examples/netns/ospfmanetmdrtest.py index f51d1e91..63634c7f 100755 --- a/daemon/examples/netns/ospfmanetmdrtest.py +++ b/daemon/examples/netns/ospfmanetmdrtest.py @@ -16,6 +16,7 @@ import time from string import Template from core.constants import QUAGGA_STATE_DIR + from core.misc import ipaddress from core.misc.utils import mutecall from core.netns import nodes @@ -267,7 +268,7 @@ class ManetExperiment(object): self.nodes[i].boot() # run the boot.sh script on all nodes to start Quagga for i in xrange(numnodes): - self.nodes[i].cmd(["./%s" % self.nodes[i].bootsh]) + self.nodes[i].client.cmd(["./%s" % self.nodes[i].bootsh]) def compareroutes(self, node, kr, zr): """ Compare two lists of Route objects. @@ -386,7 +387,7 @@ class Cmd: def open(self): """ Exceute call to node.popen(). """ self.id, self.stdin, self.out, self.err = \ - self.node.popen(self.args) + self.node.client.popen(self.args) def parse(self): """ This method is overloaded by child classes and should return some @@ -409,7 +410,7 @@ class VtyshCmd(Cmd): def open(self): args = ("vtysh", "-c", self.args) - self.id, self.stdin, self.out, self.err = self.node.popen(args) + self.id, self.stdin, self.out, self.err = self.node.client.popen(args) class Ospf6NeighState(VtyshCmd): diff --git a/daemon/examples/netns/switch.py b/daemon/examples/netns/switch.py index 64137f36..66018da1 100755 --- a/daemon/examples/netns/switch.py +++ b/daemon/examples/netns/switch.py @@ -57,7 +57,7 @@ def main(): for i in xrange(1, options.numnodes + 1): tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.setposition(x=150 * i, y=150) n.append(tmp) diff --git a/daemon/examples/netns/switchtest.py b/daemon/examples/netns/switchtest.py index 524ae2b0..bb050c9d 100755 --- a/daemon/examples/netns/switchtest.py +++ b/daemon/examples/netns/switchtest.py @@ -36,9 +36,9 @@ def test(numnodes, testsec): tmp = session.add_object(cls=nodes.LxcNode, name="n%d" % i) tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.append(tmp) - n[0].cmd(["iperf", "-s", "-D"]) - n[-1].icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].cmd(["killall", "-9", "iperf"]) + n[0].client.cmd(["iperf", "-s", "-D"]) + n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) + n[0].client.cmd(["killall", "-9", "iperf"]) raw_input("press enter to exit") session.shutdown() diff --git a/daemon/examples/netns/wlanemanetests.py b/daemon/examples/netns/wlanemanetests.py index 60ad31d2..bfc06ad5 100755 --- a/daemon/examples/netns/wlanemanetests.py +++ b/daemon/examples/netns/wlanemanetests.py @@ -131,7 +131,7 @@ class Cmd(object): def open(self): """ Exceute call to node.popen(). """ - self.id, self.stdin, self.out, self.err = self.node.popen(self.args) + self.id, self.stdin, self.out, self.err = self.node.client.popen(self.args) def parse(self): """ This method is overloaded by child classes and should return some @@ -166,7 +166,7 @@ class ClientServerCmd(Cmd): self.client_open() # client status = self.client_id.wait() # stop the server - self.node.cmdresult(["killall", self.args[0]]) + self.node.client.cmdresult(["killall", self.args[0]]) r = self.parse() self.cleanup() return r @@ -174,7 +174,7 @@ class ClientServerCmd(Cmd): def client_open(self): """ Exceute call to client_node.popen(). """ self.client_id, self.client_stdin, self.client_out, self.client_err = \ - self.client_node.popen(self.client_args) + self.client_node.client.popen(self.client_args) def parse(self): """ This method is overloaded by child classes and should return some @@ -207,7 +207,7 @@ class PingCmd(Cmd): def run(self): if self.verbose: self.info("%s initial test ping (max 1 second)..." % self.node.name) - (status, result) = self.node.cmdresult(["ping", "-q", "-c", "1", "-w", "1", self.addr]) + (status, result) = self.node.client.cmdresult(["ping", "-q", "-c", "1", "-w", "1", self.addr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % (self.node.name, self.addr, result)) @@ -487,13 +487,13 @@ class Experiment(object): if i > 1: neigh_left = "%s" % prefix.addr(i - 1) cmd = routecmd + [neigh_left, "dev", node.netif(0).name] - (status, result) = node.cmdresult(cmd) + (status, result) = node.client.cmdresult(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) if i < numnodes: neigh_right = "%s" % prefix.addr(i + 1) cmd = routecmd + [neigh_right, "dev", node.netif(0).name] - (status, result) = node.cmdresult(cmd) + (status, result) = node.client.cmdresult(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) @@ -507,7 +507,7 @@ class Experiment(object): else: gw = neigh_right cmd = routecmd + [addr, "via", gw] - (status, result) = node.cmdresult(cmd) + (status, result) = node.client.cmdresult(cmd) if status != 0: self.warn("failed to add route: %s" % cmd) @@ -635,8 +635,8 @@ class Experiment(object): if self.verbose: self.info("%s initial test ping (max 1 second)..." % \ self.firstnode.name) - (status, result) = self.firstnode.cmdresult(["ping", "-q", "-c", "1", - "-w", "1", self.lastaddr]) + (status, result) = self.firstnode.client.cmdresult(["ping", "-q", "-c", "1", + "-w", "1", self.lastaddr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % \ (self.firstnode.name, self.lastaddr, result)) diff --git a/daemon/examples/netns/wlantest.py b/daemon/examples/netns/wlantest.py index 70892d1b..ce14377f 100755 --- a/daemon/examples/netns/wlantest.py +++ b/daemon/examples/netns/wlantest.py @@ -37,9 +37,9 @@ def test(numnodes, testsec): tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.append(tmp) net.link(n[0].netif(0), n[-1].netif(0)) - n[0].cmd(["iperf", "-s", "-D"]) - n[-1].icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].cmd(["killall", "-9", "iperf"]) + n[0].client.cmd(["iperf", "-s", "-D"]) + n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) + n[0].client.cmd(["killall", "-9", "iperf"]) session.shutdown() diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index 96f740e8..3890fe32 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -186,18 +186,18 @@ class Core(object): def ping(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - return from_node.cmd(["ping", "-c", "3", to_ip]) + return from_node.client.cmd(["ping", "-c", "3", to_ip]) def ping_output(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - vcmd, stdin, stdout, stderr = from_node.popen(["ping", "-i", "0.05", "-c", "3", to_ip]) + vcmd, stdin, stdout, stderr = from_node.client.popen(["ping", "-i", "0.05", "-c", "3", to_ip]) return stdout.read().strip() def iping(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - from_node.icmd(["ping", "-i", "0.01", "-c", "10", to_ip]) + from_node.client.icmd(["ping", "-i", "0.01", "-c", "10", to_ip]) def iperf(self, from_name, to_name): from_node = self.nodes[from_name] @@ -205,9 +205,9 @@ class Core(object): to_ip = str(self.get_ip(to_name)) # run iperf server, run client, kill iperf server - vcmd, stdin, stdout, stderr = to_node.popen(["iperf", "-s", "-u", "-y", "C"]) - from_node.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) - to_node.cmd(["killall", "-9", "iperf"]) + vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"]) + from_node.client.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) + to_node.client.cmd(["killall", "-9", "iperf"]) return stdout.read().strip() diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index f47827a0..8367c084 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -3,13 +3,12 @@ Unit tests for testing basic CORE networks. """ import os +import stat import threading import time - -import pytest - from xml.etree import ElementTree +import pytest from mock import MagicMock from conftest import EMANE_SERVICES @@ -18,6 +17,7 @@ from core.enumerations import MessageFlags from core.mobility import BasicRangeModel from core.netns import nodes from core.netns import vnodeclient +from core.netns.vnodeclient import VnodeClient from core.phys.pnodes import PhysicalNode from core.service import ServiceManager from core.xml import xmlsession @@ -29,6 +29,24 @@ _XML_VERSIONS = ["0.0", "1.0"] _NODE_CLASSES = [nodes.PtpNet, nodes.HubNode, nodes.SwitchNode] +def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None): + """ + Create clients + + :param str sessiondir: session directory to create clients + :param class clientcls: class to create clients from + :param func cmdchnlfilterfunc: command channel filter function + :return: list of created clients + :rtype: list + """ + direntries = map(lambda x: os.path.join(sessiondir, x), os.listdir(sessiondir)) + cmdchnls = filter(lambda x: stat.S_ISSOCK(os.stat(x).st_mode), direntries) + if cmdchnlfilterfunc: + cmdchnls = filter(cmdchnlfilterfunc, cmdchnls) + cmdchnls.sort() + return map(lambda x: clientcls(os.path.basename(x), x), cmdchnls) + + class TestCore: def test_import_service(self, core): """ @@ -145,7 +163,7 @@ class TestCore: # get node client for testing n1 = core.get_node("n1") - client = n1.vnodeclient + client = n1.client # instantiate session core.session.instantiate() @@ -178,7 +196,7 @@ class TestCore: assert not client.shcmd(command[0]) # check module methods - assert vnodeclient.createclients(core.session.session_dir) + assert createclients(core.session.session_dir) # check convenience methods for interface information assert client.getaddr("eth0") diff --git a/doc/scripting.rst b/doc/scripting.rst index 8db7b165..573522d0 100644 --- a/doc/scripting.rst +++ b/doc/scripting.rst @@ -47,7 +47,7 @@ Here are the basic elements of a CORE Python script: node1.newnetif(hub1, ["10.0.0.1/24"]) node2.newnetif(hub1, ["10.0.0.2/24"]) - node1.icmd(["ping", "-c", "5", "10.0.0.2"]) + node1.vnodeclient.icmd(["ping", "-c", "5", "10.0.0.2"]) session.shutdown() From ceb2e5467910af6fc5e5ce9c7623c2652f935a1b Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Feb 2018 10:55:57 -0800 Subject: [PATCH 033/152] small updates after verifying vcmd return values --- daemon/core/netns/vnodeclient.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index f7b36f4b..e5b450cf 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -70,16 +70,16 @@ class VnodeClient(object): """ self._verify_connection() - # TODO: clean this up after checking return value for qcmd - tmp = self.cmdchnl.qcmd(args) + # run command, return process when not waiting + p = self.cmdchnl.qcmd(args) if not wait: - return tmp - tmp = tmp.wait() + return p - if tmp: - logger.warn("cmd exited with status %s: %s", tmp, args) - - return tmp + # wait for and return exit status + status = p.wait() + if status: + logger.warn("cmd exited with status %s: %s", status, args) + return status def cmdresult(self, args): """ @@ -138,16 +138,16 @@ class VnodeClient(object): """ self._verify_connection() - # TODO: clean this up after verifying redircmd return values - tmp = self.cmdchnl.redircmd(infd, outfd, errfd, args) + # run command, return process when not waiting + p = self.cmdchnl.redircmd(infd, outfd, errfd, args) if not wait: - return tmp + return p - tmp = tmp.wait() - if tmp: - logger.warn("cmd exited with status %s: %s", tmp, args) - - return tmp + # wait for and return exit status + status = p.wait() + if status: + logger.warn("cmd exited with status %s: %s", status, args) + return status # TODO: validate if this is ever used def term(self, sh="/bin/sh"): From e35b4a0a4b359b7752880ef05275fd89c1e3674b Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Feb 2018 16:55:53 -0800 Subject: [PATCH 034/152] fixed bug with loading emane models in tests, after changing how emane models are loaded --- daemon/tests/conftest.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index 3890fe32..67ae188c 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -324,9 +324,6 @@ def session(): session_fixture.location.setrefgeo(47.57917, -122.13232, 2.00000) session_fixture.location.refscale = 150.0 - # load emane models - session_fixture.emane.loadmodels() - # return session fixture yield session_fixture From 127d0b066603ee9ea7f43622809797c5d9b29bc0 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Feb 2018 19:13:51 -0800 Subject: [PATCH 035/152] added a shell command with result, leveraged it usage to get output for failures during addfile and mounting within nodes --- daemon/core/netns/vnode.py | 18 ++++++++++++++---- daemon/core/netns/vnodeclient.py | 16 ++++++++++++++++ daemon/tests/test_core.py | 1 - 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 7dd70e0a..7c27804f 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -172,8 +172,10 @@ class SimpleLxcNode(PyCoreNode): source = os.path.abspath(source) logger.info("mounting %s at %s" % (source, target)) try: - shcmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) - self.client.shcmd(shcmd) + cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) + status, output = self.client.shcmd_result(cmd) + if status: + raise IOError("error during mount: %s" % output) self._mounts.append((source, target)) except IOError: logger.exception("mounting failed for %s at %s", source, target) @@ -446,8 +448,16 @@ class SimpleLxcNode(PyCoreNode): :param str filename: file name to add :return: nothing """ - shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename) - self.client.shcmd(shcmd) + logger.info("adding file from %s to %s", srcname, filename) + directory = os.path.dirname(filename) + + try: + cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename) + status, output = self.client.shcmd_result(cmd) + if status: + logger.error("error adding file: %s", output) + except IOError: + logger.exception("error during addfile") def getaddr(self, ifname, rescan=False): """ diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index ab45cf82..94271b04 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -6,6 +6,7 @@ by invoking the vcmd shell command. """ import os +import shlex import vcmd @@ -93,6 +94,10 @@ class VnodeClient(object): """ self._verify_connection() + # split shell string to shell array for convenience + if type(args) == str: + args = shlex.split(args) + p, stdin, stdout, stderr = self.popen(args) output = stdout.read() + stderr.read() stdin.close() @@ -184,6 +189,17 @@ class VnodeClient(object): """ return self.cmd([sh, "-c", cmdstr]) + def shcmd_result(self, cmd, sh="/bin/sh"): + """ + Execute a shell command and return the exist status and combined output. + + :param str cmd: shell command to run + :param str sh: shell to run command in + :return: exist status and combined output + :rtype: tuple[int, str] + """ + return self.cmdresult([sh, "-c", cmd]) + def getaddr(self, ifname, rescan=False): """ Get address for interface on node. diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 8367c084..dabc12ce 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -186,7 +186,6 @@ class TestCore: assert not client.shcmd(command[0]) # check various command using command line - vnodeclient.USE_VCMD_MODULE = False assert not client.cmd(command) status, output = client.cmdresult(command) assert not status From 78537d8e9560690baa795fefcaad6e6b2dcb6c3b Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Feb 2018 12:39:12 -0800 Subject: [PATCH 036/152] fixed some shell command usage in example files --- daemon/core/netns/vnodeclient.py | 1 - daemon/examples/netns/basicrange.py | 1 - daemon/examples/netns/distributed.py | 2 +- daemon/examples/netns/emane80211.py | 5 ++--- daemon/examples/netns/switch.py | 2 +- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index e5b450cf..ab45cf82 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -149,7 +149,6 @@ class VnodeClient(object): logger.warn("cmd exited with status %s: %s", status, args) return status - # TODO: validate if this is ever used def term(self, sh="/bin/sh"): """ Open a terminal on a node. diff --git a/daemon/examples/netns/basicrange.py b/daemon/examples/netns/basicrange.py index a6a29348..ca33bccb 100755 --- a/daemon/examples/netns/basicrange.py +++ b/daemon/examples/netns/basicrange.py @@ -58,7 +58,6 @@ def test(options): # session.sdt.updatenode(n[1].objid, 0, 10, 10, 2000000) # launches terminal for the first node - # n[0].term("bash") n[0].client.icmd(["ping", "-c", "5", "127.0.0.1"]) # wait for rate seconds to allow ebtables commands to commit diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index 1674b4df..8bbd1f49 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -116,7 +116,7 @@ def main(): session.broker.handlerawmsg(msg) # start a shell on node 1 - n[1].term("bash") + n[1].client.term("bash") print "elapsed time: %s" % (datetime.datetime.now() - start) print "To stop this session, use the 'core-cleanup' script on this server" diff --git a/daemon/examples/netns/emane80211.py b/daemon/examples/netns/emane80211.py index 3ca5ae45..1831ab1c 100755 --- a/daemon/examples/netns/emane80211.py +++ b/daemon/examples/netns/emane80211.py @@ -81,8 +81,7 @@ def main(): print "creating %d nodes with addresses from %s" % \ (options.numnodes, prefix) for i in xrange(1, options.numnodes + 1): - tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, - objid=i) + tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.setposition(x=150 * i, y=150) @@ -94,7 +93,7 @@ def main(): session.instantiate() # start a shell on node 1 - n[1].term("bash") + n[1].client.term("bash") print "elapsed time: %s" % (datetime.datetime.now() - start) diff --git a/daemon/examples/netns/switch.py b/daemon/examples/netns/switch.py index 66018da1..802eaa78 100755 --- a/daemon/examples/netns/switch.py +++ b/daemon/examples/netns/switch.py @@ -66,7 +66,7 @@ def main(): print "elapsed time: %s" % (datetime.datetime.now() - start) # start a shell on node 1 - n[1].term("bash") + n[1].client.term("bash") raw_input("press enter to exit") session.shutdown() From 59f22b12cfa104bc9ae309d4f3c96cccbb61ac27 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Feb 2018 14:56:13 -0800 Subject: [PATCH 037/152] minor refactoring to vnode.py --- daemon/core/netns/vnode.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 7dd70e0a..d4878074 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -161,6 +161,7 @@ class SimpleLxcNode(PyCoreNode): """ pass + # TODO: should change how this exception is just swallowed up def mount(self, source, target): """ Create and mount a directory. @@ -474,8 +475,7 @@ class LxcNode(SimpleLxcNode): Provides lcx node functionality for core nodes. """ - def __init__(self, session, objid=None, name=None, - nodedir=None, bootsh="boot.sh", start=True): + def __init__(self, session, objid=None, name=None, nodedir=None, bootsh="boot.sh", start=True): """ Create a LxcNode instance. @@ -486,8 +486,7 @@ class LxcNode(SimpleLxcNode): :param bootsh: boot shell :param bool start: start flag """ - super(LxcNode, self).__init__(session=session, objid=objid, - name=name, nodedir=nodedir, start=start) + super(LxcNode, self).__init__(session=session, objid=objid, name=name, nodedir=nodedir, start=start) self.bootsh = bootsh if start: self.startup() @@ -544,6 +543,7 @@ class LxcNode(SimpleLxcNode): self.rmnodedir() self.lock.release() + # TODO: should change how this exception is just swallowed up def privatedir(self, path): """ Create a private directory. From 719670c8959e8d4965c2763f468f91aaa5e71ad8 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Feb 2018 16:28:28 -0800 Subject: [PATCH 038/152] further cleanup to vnode.py and corrections to function docs --- daemon/core/coreobj.py | 2 +- daemon/core/misc/event.py | 2 +- daemon/core/netns/vif.py | 14 +-- daemon/core/netns/vnode.py | 220 +++++++++++++++------------------- daemon/core/service.py | 36 +++--- daemon/core/session.py | 7 +- daemon/core/xml/xmlparser0.py | 2 +- daemon/core/xml/xmlparser1.py | 2 +- ns3/corens3/obj.py | 10 +- 9 files changed, 133 insertions(+), 162 deletions(-) diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 962c4a2a..6993a09a 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -323,7 +323,7 @@ class PyCoreNode(PyCoreObj): if ifindex in self._netif: raise ValueError("ifindex %s already exists" % ifindex) self._netif[ifindex] = netif - # TODO: this hould have probably been set ahead, seems bad to me, check for failure and fix + # TODO: this should have probably been set ahead, seems bad to me, check for failure and fix netif.netindex = ifindex def delnetif(self, ifindex): diff --git a/daemon/core/misc/event.py b/daemon/core/misc/event.py index 76bc95f1..ec11ee1b 100644 --- a/daemon/core/misc/event.py +++ b/daemon/core/misc/event.py @@ -215,7 +215,7 @@ class EventLoop(object): """ Add an event to the event loop. - :param int delaysec: delay in seconds for event + :param float delaysec: delay in seconds for event :param func: event function :param args: event arguments :param kwds: event keyword arguments diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index 33d656ac..362c7d20 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -25,7 +25,7 @@ class VEth(PyCoreNetIf): """ Creates a VEth instance. - :param core.netns.nodes.CoreNode node: related core node + :param core.netns.vnode.SimpleLxcNode node: related core node :param str name: interface name :param str localname: interface local name :param mtu: interface mtu @@ -76,7 +76,7 @@ class TunTap(PyCoreNetIf): """ Create a TunTap instance. - :param core.netns.nodes.CoreNode node: related core node + :param core.netns.vnode.SimpleLxcNode node: related core node :param str name: interface name :param str localname: local interface name :param mtu: interface mtu @@ -136,7 +136,7 @@ class TunTap(PyCoreNetIf): msg += ", retrying..." logger.info(msg) time.sleep(delay) - delay = delay + delay + delay += delay if delay > maxretrydelay: delay = maxretrydelay else: @@ -168,7 +168,7 @@ class TunTap(PyCoreNetIf): """ def nodedevexists(): - cmd = (constants.IP_BIN, "link", "show", self.name) + cmd = [constants.IP_BIN, "link", "show", self.name] return self.node.client.cmd(cmd) count = 0 @@ -180,8 +180,8 @@ class TunTap(PyCoreNetIf): # check if this is an EMANE interface; if so, continue # waiting if EMANE is still running # TODO: remove emane code - if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and \ - self.node.session.emane.emanerunning(self.node): + if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and self.node.session.emane.emanerunning( + self.node): count += 1 else: raise e @@ -233,7 +233,7 @@ class GreTap(PyCoreNetIf): """ Creates a GreTap instance. - :param core.netns.nodes.CoreNode node: related core node + :param core.netns.vnode.SimpleLxcNode node: related core node :param str name: interface name :param core.session.Session session: core session instance :param mtu: interface mtu diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 33afbdce..1252e952 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -21,6 +21,8 @@ from core.netns import vnodeclient from core.netns.vif import TunTap from core.netns.vif import VEth +_DEFAULT_MTU = 1500 + utils.check_executables([constants.IP_BIN]) @@ -36,7 +38,7 @@ class SimpleLxcNode(PyCoreNode): :type lock: threading.RLock :type _mounts: list[tuple[str, str]] """ - valid_deladdrtype = ("inet", "inet6", "inet6link") + valid_address_types = {"inet", "inet6", "inet6link"} def __init__(self, session, objid=None, name=None, nodedir=None, start=True): """ @@ -80,10 +82,16 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - raise Exception("already up") - vnoded = ["%s/vnoded" % constants.CORE_BIN_DIR, "-v", "-c", self.ctrlchnlname, - "-l", self.ctrlchnlname + ".log", - "-p", self.ctrlchnlname + ".pid"] + raise ValueError("starting a node that is already up") + + # create a new namespace for this node using vnoded + vnoded = [ + "%s/vnoded" % constants.CORE_BIN_DIR, + "-v", + "-c", self.ctrlchnlname, + "-l", self.ctrlchnlname + ".log", + "-p", self.ctrlchnlname + ".pid" + ] if self.nodedir: vnoded += ["-C", self.nodedir] env = self.session.get_environment(state=False) @@ -91,28 +99,26 @@ class SimpleLxcNode(PyCoreNode): env["NODE_NAME"] = str(self.name) try: - tmp = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env) - except OSError: - msg = "error running vnoded command: %s" % vnoded - logger.exception("SimpleLxcNode.startup(): %s", msg) - raise Exception(msg) - - try: - self.pid = int(tmp.stdout.read()) - tmp.stdout.close() - except ValueError: - msg = "vnoded failed to create a namespace; " - msg += "check kernel support and user priveleges" - logger.exception("SimpleLxcNode.startup(): %s", msg) - - if tmp.wait(): - raise Exception("command failed: %s" % vnoded) + p = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env) + stdout, _ = p.communicate() + if p.returncode: + raise IOError("vnoded command failed: %s" % vnoded) + self.pid = int(stdout) + except (OSError, ValueError): + logger.exception("vnoded failed to create a namespace; check kernel support and user priveleges") + # create vnode client self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) + + # bring up the loopback interface logger.info("bringing up loopback interface") self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"]) + + # set hostname for node logger.info("setting hostname: %s" % self.name) self.client.cmd(["hostname", self.name]) + + # mark node as up self.up = True def shutdown(self): @@ -146,7 +152,7 @@ class SimpleLxcNode(PyCoreNode): if os.path.exists(self.ctrlchnlname): os.unlink(self.ctrlchnlname) except OSError: - logger.exception("error removing file") + logger.exception("error removing node directory") # clear interface data, close client, and mark self and not up self._netif.clear() @@ -190,9 +196,11 @@ class SimpleLxcNode(PyCoreNode): """ logger.info("unmounting: %s", target) try: - self.client.cmd([constants.UMOUNT_BIN, "-n", "-l", target]) + status, output = self.client.cmdresult([constants.UMOUNT_BIN, "-n", "-l", target]) + if status: + raise IOError("error unmounting %s: %s", target, output) except IOError: - logger.exception("unmounting failed for %s" % target) + logger.exception("error during unmount") def newifindex(self): """ @@ -213,8 +221,7 @@ class SimpleLxcNode(PyCoreNode): :param net: network to associate interface with :return: nothing """ - self.lock.acquire() - try: + with self.lock: if ifindex is None: ifindex = self.newifindex() @@ -234,7 +241,7 @@ class SimpleLxcNode(PyCoreNode): name = localname + "p" if len(name) >= 16: raise ValueError("interface name (%s) too long" % name) - veth = VEth(node=self, name=name, localname=localname, mtu=1500, net=net, start=self.up) + veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up) if self.up: subprocess.check_call([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) @@ -255,14 +262,12 @@ class SimpleLxcNode(PyCoreNode): try: self.addnetif(veth, ifindex) - except: + except ValueError as e: veth.shutdown() del veth - raise + raise e return ifindex - finally: - self.lock.release() def newtuntap(self, ifindex=None, ifname=None, net=None): """ @@ -274,8 +279,7 @@ class SimpleLxcNode(PyCoreNode): :return: interface index :rtype: int """ - self.lock.acquire() - try: + with self.lock: if ifindex is None: ifindex = self.newifindex() if ifname is None: @@ -283,18 +287,14 @@ class SimpleLxcNode(PyCoreNode): sessionid = self.session.short_session_id() localname = "tap%s.%s.%s" % (self.objid, ifindex, sessionid) name = ifname - ifclass = TunTap - tuntap = ifclass(node=self, name=name, localname=localname, - mtu=1500, net=net, start=self.up) + tuntap = TunTap(node=self, name=name, localname=localname, net=net, start=self.up) try: self.addnetif(tuntap, ifindex) - except Exception as e: + except ValueError as e: tuntap.shutdown() del tuntap raise e return ifindex - finally: - self.lock.release() def sethwaddr(self, ifindex, addr): """ @@ -306,10 +306,10 @@ class SimpleLxcNode(PyCoreNode): """ self._netif[ifindex].sethwaddr(addr) if self.up: - (status, result) = self.client.cmdresult([constants.IP_BIN, "link", "set", "dev", - self.ifname(ifindex), "address", str(addr)]) + cmd = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] + status, output = self.client.cmdresult(cmd) if status: - logger.error("error setting MAC address %s", str(addr)) + logger.error("error setting MAC address %s: %s", addr, output) def addaddr(self, ifindex, addr): """ @@ -320,12 +320,13 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - if ":" in str(addr): # check if addr is ipv6 - self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), - "dev", self.ifname(ifindex)]) + # check if addr is ipv6 + if ":" in str(addr): + cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] + self.client.cmd(cmd) else: - self.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", - "dev", self.ifname(ifindex)]) + cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] + self.client.cmd(cmd) self._netif[ifindex].addaddr(addr) def deladdr(self, ifindex, addr): @@ -344,22 +345,23 @@ class SimpleLxcNode(PyCoreNode): if self.up: self.client.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) - def delalladdr(self, ifindex, addrtypes=valid_deladdrtype): + def delalladdr(self, ifindex, address_types=valid_address_types): """ Delete all addresses from an interface. - :param int ifindex: index of interface to delete all addresses from - :param tuple addrtypes: address types to delete + :param int ifindex: index of interface to delete address types from + :param tuple[str] address_types: address types to delete :return: nothing """ - addr = self.getaddr(self.ifname(ifindex), rescan=True) - for t in addrtypes: - if t not in self.valid_deladdrtype: - raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype)) - for a in addr[t]: - self.deladdr(ifindex, a) + interface_name = self.ifname(ifindex) + addresses = self.client.getaddr(interface_name, rescan=True) + for address_type in address_types: + if address_type not in self.valid_address_types: + raise ValueError("addr type must be in: %s" % " ".join(self.valid_address_types)) + for address in addresses[address_type]: + self.deladdr(ifindex, address) # update cached information - self.getaddr(self.ifname(ifindex), rescan=True) + self.client.getaddr(interface_name, rescan=True) def ifup(self, ifindex): """ @@ -371,20 +373,22 @@ class SimpleLxcNode(PyCoreNode): if self.up: self.client.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) - def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): + def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None): """ Create a new network interface. :param net: network to associate with - :param list addrlist: addresses to add on the interface + :param list address_list: addresses to add on the interface :param core.misc.ipaddress.MacAddress hwaddr: hardware address to set for interface :param int ifindex: index of interface to create :param str ifname: name for interface :return: interface index :rtype: int """ - self.lock.acquire() - try: + if not address_list: + address_list = [] + + with self.lock: # TODO: see if you can move this to emane specific code if nodeutils.is_node(net, NodeTypes.EMANE): ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net) @@ -395,8 +399,8 @@ class SimpleLxcNode(PyCoreNode): self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for addr in utils.maketuple(addrlist): - netif.addaddr(addr) + for address in utils.maketuple(address_list): + netif.addaddr(address) return ifindex else: ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net) @@ -407,14 +411,11 @@ class SimpleLxcNode(PyCoreNode): if hwaddr: self.sethwaddr(ifindex, hwaddr) - if addrlist: - for addr in utils.maketuple(addrlist): - self.addaddr(ifindex, addr) + for address in utils.maketuple(address_list): + self.addaddr(ifindex, address) self.ifup(ifindex) return ifindex - finally: - self.lock.release() def connectnode(self, ifname, othernode, otherifname): """ @@ -426,20 +427,19 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ tmplen = 8 - tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) - for x in xrange(tmplen)]) - tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) - for x in xrange(tmplen)]) - subprocess.check_call([constants.IP_BIN, "link", "add", "name", tmp1, - "type", "veth", "peer", "name", tmp2]) + tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) + tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) + subprocess.check_call([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2]) subprocess.call([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) self.client.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) - self.addnetif(PyCoreNetIf(self, ifname), self.newifindex()) + interface = PyCoreNetIf(node=self, name=ifname, mtu=_DEFAULT_MTU) + self.addnetif(interface, self.newifindex()) subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) othernode.client.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) - othernode.addnetif(PyCoreNetIf(othernode, otherifname), othernode.newifindex()) + other_interface = PyCoreNetIf(node=othernode, name=otherifname, mtu=_DEFAULT_MTU) + othernode.addnetif(other_interface, othernode.newifindex()) def addfile(self, srcname, filename): """ @@ -456,29 +456,10 @@ class SimpleLxcNode(PyCoreNode): cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename) status, output = self.client.shcmd_result(cmd) if status: - logger.error("error adding file: %s", output) + raise IOError("error adding file: %s" % output) except IOError: logger.exception("error during addfile") - def getaddr(self, ifname, rescan=False): - """ - Wrapper around vnodeclient getaddr. - - :param str ifname: interface name to get address for - :param bool rescan: rescan flag - :return: - """ - return self.client.getaddr(ifname=ifname, rescan=rescan) - - def netifstats(self, ifname=None): - """ - Wrapper around vnodeclient netifstate. - - :param str ifname: interface name to get state for - :return: - """ - return self.client.netifstats(ifname=ifname) - class LxcNode(SimpleLxcNode): """ @@ -523,16 +504,14 @@ class LxcNode(SimpleLxcNode): :return: nothing """ - self.lock.acquire() - try: - self.makenodedir() - super(LxcNode, self).startup() - self.privatedir("/var/run") - self.privatedir("/var/log") - except OSError: - logger.exception("error during LxcNode.startup()") - finally: - self.lock.release() + with self.lock: + try: + self.makenodedir() + super(LxcNode, self).startup() + self.privatedir("/var/run") + self.privatedir("/var/log") + except OSError: + logger.exception("error during startup") def shutdown(self): """ @@ -542,16 +521,16 @@ class LxcNode(SimpleLxcNode): """ if not self.up: return - self.lock.acquire() - # services are instead stopped when session enters datacollect state - # self.session.services.stopnodeservices(self) - try: - super(LxcNode, self).shutdown() - except: - logger.exception("error during shutdown") - finally: - self.rmnodedir() - self.lock.release() + + with self.lock: + # services are instead stopped when session enters datacollect state + # self.session.services.stopnodeservices(self) + try: + super(LxcNode, self).shutdown() + except OSError: + logger.exception("error during shutdown") + finally: + self.rmnodedir() # TODO: should change how this exception is just swallowed up def privatedir(self, path): @@ -612,11 +591,10 @@ class LxcNode(SimpleLxcNode): :param int mode: mode for file :return: nothing """ - f = self.opennodefile(filename, "w") - f.write(contents) - os.chmod(f.name, mode) - f.close() - logger.info("created nodefile: %s; mode: 0%o", f.name, mode) + with self.opennodefile(filename, "w") as open_file: + open_file.write(contents) + os.chmod(open_file.name, mode) + logger.info("created nodefile: %s; mode: 0%o", open_file.name, mode) def nodefilecopy(self, filename, srcfilename, mode=None): """ diff --git a/daemon/core/service.py b/daemon/core/service.py index b212d3e9..a6169ef7 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -7,11 +7,7 @@ a list of available services to the GUI and for configuring individual services. """ -import importlib -import inspect -import os import shlex -import sys import time from itertools import repeat @@ -263,8 +259,8 @@ class CoreServices(ConfigurableManager): """ Start all services on a node. - :param core.netns.nodes.CoreNode node: node to start services on - :return: + :param core.netns.vnode.LxcNode node: node to start services on + :return: nothing """ services = sorted(node.services, key=lambda service: service._startindex) use_startup_service = any(map(self.is_startup_service, services)) @@ -285,7 +281,7 @@ class CoreServices(ConfigurableManager): Start a service on a node. Create private dirs, generate config files, and execute startup commands. - :param core.netns.nodes.CoreNode node: node to boot services on + :param core.netns.vnode.LxcNode node: node to boot services on :param CoreService service: service to start :param list services: service list :param bool use_startup_service: flag to use startup services or not @@ -295,7 +291,7 @@ class CoreServices(ConfigurableManager): self.bootnodecustomservice(node, service, services, use_startup_service) return - logger.info("starting service %s (%s)" % (service._name, service._startindex)) + logger.info("starting service %s (%s)", service._name, service._startindex) for directory in service._dirs: try: node.privatedir(directory) @@ -321,7 +317,7 @@ class CoreServices(ConfigurableManager): Start a custom service on a node. Create private dirs, use supplied config files, and execute supplied startup commands. - :param core.netns.nodes.CoreNode node: node to boot services on + :param core.netns.vnode.LxcNode node: node to boot services on :param CoreService service: service to start :param list services: service list :param bool use_startup_service: flag to use startup services or not @@ -368,7 +364,7 @@ class CoreServices(ConfigurableManager): config references an existing file that should be copied. Returns True for local files, False for generated. - :param core.netns.nodes.CoreNode node: node to copy service for + :param core.netns.vnode.LxcNode node: node to copy service for :param str filename: file name for a configured service :param str cfg: configuration string :return: True if successful, False otherwise @@ -387,7 +383,7 @@ class CoreServices(ConfigurableManager): """ Run validation commands for all services on a node. - :param core.netns.nodes.CoreNode node: node to validate services for + :param core.netns.vnode.LxcNode node: node to validate services for :return: nothing """ services = sorted(node.services, key=lambda service: service._startindex) @@ -398,7 +394,7 @@ class CoreServices(ConfigurableManager): """ Run the validation command(s) for a service. - :param core.netns.nodes.CoreNode node: node to validate service for + :param core.netns.vnode.LxcNode node: node to validate service for :param CoreService service: service to validate :param list services: services for node :return: service validation status @@ -441,7 +437,7 @@ class CoreServices(ConfigurableManager): """ Stop a service on a node. - :param core.netns.nodes.CoreNode node: node to stop a service on + :param core.netns.vnode.LxcNode node: node to stop a service on :param CoreService service: service to stop :return: status for stopping the services :rtype: str @@ -647,7 +643,7 @@ class CoreServices(ConfigurableManager): The file data is either auto-generated or comes from an existing config. :param list services: service list - :param core.netns.nodes.CoreNode node: node to get service file from + :param core.netns.vnode.LxcNode node: node to get service file from :param str filename: file name to retrieve :return: file message for node """ @@ -887,7 +883,7 @@ class CoreService(object): Return the configuration string to be written to a file or sent to the GUI for customization. - :param core.netns.nodes.CoreNode node: node to generate config for + :param core.netns.vnode.LxcNode node: node to generate config for :param str filename: file name to generate config for :param list services: services for node :return: nothing @@ -902,7 +898,7 @@ class CoreService(object): overridden to provide node-specific commands that may be based on other services. - :param core.netns.nodes.CoreNode node: node to get startup for + :param core.netns.vnode.LxcNode node: node to get startup for :param list services: services for node :return: startup commands :rtype: tuple @@ -917,7 +913,7 @@ class CoreService(object): overriden to provide node-specific commands that may be based on other services. - :param core.netns.nodes.CoreNode node: node to validate + :param core.netns.vnode.LxcNode node: node to validate :param list services: services for node :return: validation commands :rtype: tuple @@ -939,10 +935,8 @@ class CoreService(object): cls._shutdown, cls._validate, cls._meta, cls._starttime] if not cls._custom: # this is always reached due to classmethod - valmap[valmap.index(cls._configs)] = \ - cls.getconfigfilenames(node.objid, services) - valmap[valmap.index(cls._startup)] = \ - cls.getstartup(node, services) + valmap[valmap.index(cls._configs)] = cls.getconfigfilenames(node.objid, services) + valmap[valmap.index(cls._startup)] = cls.getstartup(node, services) vals = map(lambda a, b: "%s=%s" % (a, str(b)), cls.keys, valmap) return "|".join(vals) diff --git a/daemon/core/session.py b/daemon/core/session.py index f4d7e01d..5a75752a 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -49,7 +49,6 @@ from core.service import CoreServices from core.xen.xenconfig import XenConfigManager from core.xml.xmlsession import save_session_xml - # set default node map node_map = nodemaps.NODES nodeutils.set_node_map(node_map) @@ -523,7 +522,7 @@ class Session(object): if os.path.isfile(environment_config_file): utils.readfileintodict(environment_config_file, env) except IOError: - logger.exception("error reading environment configuration file: %s", environment_config_file) + logger.warn("environment configuration file does not exist: %s", environment_config_file) # attempt to read and add user environment file if self.user: @@ -610,7 +609,7 @@ class Session(object): :param int object_id: object id to retrieve :return: object for the given id - :rtype: core.netns.vnode.SimpleLxcNode + :rtype: core.netns.vnode.LxcNode """ if object_id not in self.objects: raise KeyError("unknown object id %s" % object_id) @@ -1167,7 +1166,7 @@ class Session(object): interface1 = node.newnetif(net=control_net, ifindex=control_net.CTRLIF_IDX_BASE + net_index, ifname="ctrl%d" % net_index, hwaddr=MacAddress.random(), - addrlist=addrlist) + address_list=addrlist) node.netif(interface1).control = True def update_control_interface_hosts(self, net_index=0, remove=False): diff --git a/daemon/core/xml/xmlparser0.py b/daemon/core/xml/xmlparser0.py index c0850d9c..7443070e 100644 --- a/daemon/core/xml/xmlparser0.py +++ b/daemon/core/xml/xmlparser0.py @@ -162,7 +162,7 @@ class CoreDocumentParser0(object): hwaddr = addrstr else: addrlist.append(addrstr) - i = n.newnetif(net, addrlist=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name) + i = n.newnetif(net, address_list=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name) for model in ifc.getElementsByTagName("model"): self.parsemodel(model, n, n.objid) key = (n.name, name) diff --git a/daemon/core/xml/xmlparser1.py b/daemon/core/xml/xmlparser1.py index b73bbb60..4b3b4be3 100644 --- a/daemon/core/xml/xmlparser1.py +++ b/daemon/core/xml/xmlparser1.py @@ -389,7 +389,7 @@ class CoreDocumentParser1(object): hwaddr = MacAddress.from_string(mac[0]) else: hwaddr = None - ifindex = node.newnetif(network, addrlist=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name) + ifindex = node.newnetif(network, address_list=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name) # TODO: 'hostname' addresses are unused msg = 'node \'%s\' interface \'%s\' connected ' \ 'to network \'%s\'' % (node.name, if_name, network.name) diff --git a/ns3/corens3/obj.py b/ns3/corens3/obj.py index 0d392a4b..6983f25b 100644 --- a/ns3/corens3/obj.py +++ b/ns3/corens3/obj.py @@ -51,21 +51,21 @@ class CoreNs3Node(CoreNode, ns.network.Node): kwds['objid'] = objid CoreNode.__init__(self, *args, **kwds) - def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): + def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None): """ Add a network interface. If we are attaching to a CoreNs3Net, this will be a TunTap. Otherwise dispatch to CoreNode.newnetif(). """ - if not addrlist: - addrlist = [] + if not address_list: + address_list = [] if not isinstance(net, CoreNs3Net): - return CoreNode.newnetif(self, net, addrlist, hwaddr, ifindex, ifname) + return CoreNode.newnetif(self, net, address_list, hwaddr, ifindex, ifname) ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net) self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for addr in maketuple(addrlist): + for addr in maketuple(address_list): netif.addaddr(addr) addrstr = netif.addrlist[0] From 908fb777deb9dd54daf419c0fd3e54d4016cd9bc Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 1 Mar 2018 09:17:58 -0800 Subject: [PATCH 039/152] updated to vnode on how commands are ran, updated all functions to capture output and raise exceptions when commands fail --- daemon/core/misc/utils.py | 13 ++++ daemon/core/netns/vnode.py | 111 +++++++++++++++++++------------ daemon/core/netns/vnodeclient.py | 31 ++++++--- 3 files changed, 104 insertions(+), 51 deletions(-) diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index f99847c7..c723e5aa 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -125,6 +125,19 @@ def mutecall(*args, **kwargs): return subprocess.call(*args, **kwargs) +def check_alloutput(cmd, **kwargs): + """ + Convenience wrapper to run subprocess.check_output and include stderr as well. + + :param list[str] cmd: command arguments to run + :param dict kwargs: option for running subprocess.check_output, beyond setting stderr to stdout + :return: combined stdout and stderr + :raises subprocess.CalledProcessError: when a non-zero exit status is encountered + """ + kwargs["stderr"] = subprocess.STDOUT + return subprocess.check_output(cmd, **kwargs) + + def mutecheck_call(*args, **kwargs): """ Run a muted check call command. diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 1252e952..12643472 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -99,24 +99,28 @@ class SimpleLxcNode(PyCoreNode): env["NODE_NAME"] = str(self.name) try: - p = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env) - stdout, _ = p.communicate() - if p.returncode: - raise IOError("vnoded command failed: %s" % vnoded) - self.pid = int(stdout) - except (OSError, ValueError): - logger.exception("vnoded failed to create a namespace; check kernel support and user priveleges") + output = utils.check_alloutput(vnoded, env=env) + # p = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env) + # stdout, _ = p.communicate() + # if p.returncode: + # raise IOError("vnoded command failed: %s" % vnoded) + self.pid = int(output) + except subprocess.CalledProcessError: + logger.exception("vnoded failed to create a namespace; check kernel support and user privileges") # create vnode client self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) - # bring up the loopback interface - logger.info("bringing up loopback interface") - self.client.cmd([constants.IP_BIN, "link", "set", "lo", "up"]) + try: + # bring up the loopback interface + logger.info("bringing up loopback interface") + self.client.check_alloutput([constants.IP_BIN, "link", "set", "lo", "up"]) - # set hostname for node - logger.info("setting hostname: %s" % self.name) - self.client.cmd(["hostname", self.name]) + # set hostname for node + logger.info("setting hostname: %s" % self.name) + self.client.check_alloutput(["hostname", self.name]) + except subprocess.CalledProcessError: + logger.exception("error setting up loopback and hostname: %s") # mark node as up self.up = True @@ -196,10 +200,8 @@ class SimpleLxcNode(PyCoreNode): """ logger.info("unmounting: %s", target) try: - status, output = self.client.cmdresult([constants.UMOUNT_BIN, "-n", "-l", target]) - if status: - raise IOError("error unmounting %s: %s", target, output) - except IOError: + self.client.check_alloutput([constants.UMOUNT_BIN, "-n", "-l", target]) + except subprocess.CalledProcessError: logger.exception("error during unmount") def newifindex(self): @@ -244,21 +246,27 @@ class SimpleLxcNode(PyCoreNode): veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up) if self.up: - subprocess.check_call([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) - self.client.cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) + try: + utils.check_alloutput([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) + self.client.check_alloutput([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) + except subprocess.CalledProcessError: + logger.exception("failure setting eth name") veth.name = ifname if self.up: # TODO: potentially find better way to query interface ID # retrieve interface information - result, output = self.client.cmdresult(["ip", "link", "show", veth.name]) - logger.info("interface command output: %s", output) - output = output.split("\n") - veth.flow_id = int(output[0].strip().split(":")[0]) + 1 - logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) - veth.hwaddr = output[1].strip().split()[1] - logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) + try: + output = self.client.check_alloutput(["ip", "link", "show", veth.name]) + logger.info("interface command output: %s", output) + output = output.split("\n") + veth.flow_id = int(output[0].strip().split(":")[0]) + 1 + logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) + veth.hwaddr = output[1].strip().split()[1] + logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) + except subprocess.CalledProcessError: + logger.exception("failure getting flow id and mac address") try: self.addnetif(veth, ifindex) @@ -282,18 +290,22 @@ class SimpleLxcNode(PyCoreNode): with self.lock: if ifindex is None: ifindex = self.newifindex() + if ifname is None: ifname = "eth%d" % ifindex + sessionid = self.session.short_session_id() localname = "tap%s.%s.%s" % (self.objid, ifindex, sessionid) name = ifname tuntap = TunTap(node=self, name=name, localname=localname, net=net, start=self.up) + try: self.addnetif(tuntap, ifindex) except ValueError as e: tuntap.shutdown() del tuntap raise e + return ifindex def sethwaddr(self, ifindex, addr): @@ -307,9 +319,10 @@ class SimpleLxcNode(PyCoreNode): self._netif[ifindex].sethwaddr(addr) if self.up: cmd = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] - status, output = self.client.cmdresult(cmd) - if status: - logger.error("error setting MAC address %s: %s", addr, output) + try: + self.client.check_alloutput(cmd) + except subprocess.CalledProcessError: + logger.exception("error setting MAC address %s: %s", addr) def addaddr(self, ifindex, addr): """ @@ -320,13 +333,17 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - # check if addr is ipv6 - if ":" in str(addr): - cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] - self.client.cmd(cmd) - else: - cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] - self.client.cmd(cmd) + try: + # check if addr is ipv6 + if ":" in str(addr): + cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] + self.client.check_alloutput(cmd) + else: + cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] + self.client.check_alloutput(cmd) + except subprocess.CalledProcessError: + logger.exception("failure adding interface address") + self._netif[ifindex].addaddr(addr) def deladdr(self, ifindex, addr): @@ -343,7 +360,10 @@ class SimpleLxcNode(PyCoreNode): logger.exception("trying to delete unknown address: %s" % addr) if self.up: - self.client.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) + try: + self.client.check_alloutput([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) + except subprocess.CalledProcessError: + logger.exception("failure deleting address") def delalladdr(self, ifindex, address_types=valid_address_types): """ @@ -355,11 +375,13 @@ class SimpleLxcNode(PyCoreNode): """ interface_name = self.ifname(ifindex) addresses = self.client.getaddr(interface_name, rescan=True) + for address_type in address_types: if address_type not in self.valid_address_types: raise ValueError("addr type must be in: %s" % " ".join(self.valid_address_types)) for address in addresses[address_type]: self.deladdr(ifindex, address) + # update cached information self.client.getaddr(interface_name, rescan=True) @@ -371,7 +393,10 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - self.client.cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) + try: + self.client.check_alloutput([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) + except subprocess.CalledProcessError: + logger.exception("failure bringing interface up") def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None): """ @@ -429,15 +454,15 @@ class SimpleLxcNode(PyCoreNode): tmplen = 8 tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) - subprocess.check_call([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2]) + utils.check_alloutput([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2]) - subprocess.call([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) - self.client.cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) + utils.check_alloutput([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) + self.client.check_alloutput([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) interface = PyCoreNetIf(node=self, name=ifname, mtu=_DEFAULT_MTU) self.addnetif(interface, self.newifindex()) - subprocess.check_call([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) - othernode.client.cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) + utils.check_alloutput([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) + othernode.client.check_alloutput([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) other_interface = PyCoreNetIf(node=othernode, name=otherifname, mtu=_DEFAULT_MTU) othernode.addnetif(other_interface, othernode.newifindex()) diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 94271b04..810e6a31 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -7,6 +7,7 @@ by invoking the vcmd shell command. import os import shlex +import subprocess import vcmd @@ -38,10 +39,10 @@ class VnodeClient(object): Checks that the vcmd client is properly connected. :return: nothing - :raises ValueError: when not connected + :raises IOError: when not connected """ if not self.connected(): - raise ValueError("vcmd not connected") + raise IOError("vcmd not connected") def connected(self): """ @@ -82,31 +83,45 @@ class VnodeClient(object): logger.warn("cmd exited with status %s: %s", status, args) return status - def cmdresult(self, args): + def cmdresult(self, cmd): """ Execute a command on a node and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list args: command arguments + :param list cmd: command arguments :return: command status and combined stdout and stderr output :rtype: tuple[int, str] """ self._verify_connection() # split shell string to shell array for convenience - if type(args) == str: - args = shlex.split(args) + if type(cmd) == str: + cmd = shlex.split(cmd) - p, stdin, stdout, stderr = self.popen(args) - output = stdout.read() + stderr.read() + p, stdin, stdout, stderr = self.popen(cmd) stdin.close() + output = stdout.read() + stderr.read() stdout.close() stderr.close() status = p.wait() return status, output + def check_alloutput(self, cmd): + """ + Run command and return output, raises exception when non-zero exit status is encountered. + + :param cmd: + :return: combined stdout and stderr combined + :rtype: str + :raises subprocess.CalledProcessError: when there is a non-zero exit status + """ + status, output = self.cmdresult(cmd) + if status: + raise subprocess.CalledProcessError(status, cmd, output) + return output + def popen(self, args): """ Execute a popen command against the node. From 0b8ee7760df0838117dc2f92bbb9feb8906d2297 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 1 Mar 2018 09:26:28 -0800 Subject: [PATCH 040/152] reverted refactoring method name until xen/bsd nodes are cleared out --- daemon/core/netns/vnode.py | 12 ++++++------ daemon/core/session.py | 2 +- daemon/core/xml/xmlparser0.py | 2 +- daemon/core/xml/xmlparser1.py | 2 +- ns3/corens3/obj.py | 10 +++++----- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 12643472..fe7a8f92 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -398,20 +398,20 @@ class SimpleLxcNode(PyCoreNode): except subprocess.CalledProcessError: logger.exception("failure bringing interface up") - def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None): + def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): """ Create a new network interface. :param net: network to associate with - :param list address_list: addresses to add on the interface + :param list addrlist: addresses to add on the interface :param core.misc.ipaddress.MacAddress hwaddr: hardware address to set for interface :param int ifindex: index of interface to create :param str ifname: name for interface :return: interface index :rtype: int """ - if not address_list: - address_list = [] + if not addrlist: + addrlist = [] with self.lock: # TODO: see if you can move this to emane specific code @@ -424,7 +424,7 @@ class SimpleLxcNode(PyCoreNode): self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for address in utils.maketuple(address_list): + for address in utils.maketuple(addrlist): netif.addaddr(address) return ifindex else: @@ -436,7 +436,7 @@ class SimpleLxcNode(PyCoreNode): if hwaddr: self.sethwaddr(ifindex, hwaddr) - for address in utils.maketuple(address_list): + for address in utils.maketuple(addrlist): self.addaddr(ifindex, address) self.ifup(ifindex) diff --git a/daemon/core/session.py b/daemon/core/session.py index 5a75752a..f7567162 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -1166,7 +1166,7 @@ class Session(object): interface1 = node.newnetif(net=control_net, ifindex=control_net.CTRLIF_IDX_BASE + net_index, ifname="ctrl%d" % net_index, hwaddr=MacAddress.random(), - address_list=addrlist) + addrlist=addrlist) node.netif(interface1).control = True def update_control_interface_hosts(self, net_index=0, remove=False): diff --git a/daemon/core/xml/xmlparser0.py b/daemon/core/xml/xmlparser0.py index 7443070e..c0850d9c 100644 --- a/daemon/core/xml/xmlparser0.py +++ b/daemon/core/xml/xmlparser0.py @@ -162,7 +162,7 @@ class CoreDocumentParser0(object): hwaddr = addrstr else: addrlist.append(addrstr) - i = n.newnetif(net, address_list=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name) + i = n.newnetif(net, addrlist=addrlist, hwaddr=hwaddr, ifindex=None, ifname=name) for model in ifc.getElementsByTagName("model"): self.parsemodel(model, n, n.objid) key = (n.name, name) diff --git a/daemon/core/xml/xmlparser1.py b/daemon/core/xml/xmlparser1.py index 4b3b4be3..b73bbb60 100644 --- a/daemon/core/xml/xmlparser1.py +++ b/daemon/core/xml/xmlparser1.py @@ -389,7 +389,7 @@ class CoreDocumentParser1(object): hwaddr = MacAddress.from_string(mac[0]) else: hwaddr = None - ifindex = node.newnetif(network, address_list=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name) + ifindex = node.newnetif(network, addrlist=ipv4 + ipv6, hwaddr=hwaddr, ifindex=None, ifname=if_name) # TODO: 'hostname' addresses are unused msg = 'node \'%s\' interface \'%s\' connected ' \ 'to network \'%s\'' % (node.name, if_name, network.name) diff --git a/ns3/corens3/obj.py b/ns3/corens3/obj.py index 6983f25b..0d392a4b 100644 --- a/ns3/corens3/obj.py +++ b/ns3/corens3/obj.py @@ -51,21 +51,21 @@ class CoreNs3Node(CoreNode, ns.network.Node): kwds['objid'] = objid CoreNode.__init__(self, *args, **kwds) - def newnetif(self, net=None, address_list=None, hwaddr=None, ifindex=None, ifname=None): + def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): """ Add a network interface. If we are attaching to a CoreNs3Net, this will be a TunTap. Otherwise dispatch to CoreNode.newnetif(). """ - if not address_list: - address_list = [] + if not addrlist: + addrlist = [] if not isinstance(net, CoreNs3Net): - return CoreNode.newnetif(self, net, address_list, hwaddr, ifindex, ifname) + return CoreNode.newnetif(self, net, addrlist, hwaddr, ifindex, ifname) ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net) self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for addr in maketuple(address_list): + for addr in maketuple(addrlist): netif.addaddr(addr) addrstr = netif.addrlist[0] From d3bd61ddcfaf321814e0c0702a2cf26442dca02a Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 1 Mar 2018 13:21:25 -0800 Subject: [PATCH 041/152] updates to consolidate commands that need to be defined by a new node type --- daemon/core/corehandlers.py | 9 ++- daemon/core/coreobj.py | 41 +++++++++++ daemon/core/emane/__init__.py | 2 +- daemon/core/emane/emanemanager.py | 26 ++++--- daemon/core/misc/utils.py | 55 ++++++++++++-- daemon/core/netns/nodes.py | 2 +- daemon/core/netns/openvswitch.py | 2 +- daemon/core/netns/vif.py | 44 ++++++----- daemon/core/netns/vnode.py | 73 +++++++++++++++---- daemon/core/netns/vnodeclient.py | 70 +++++++++--------- daemon/core/phys/pnodes.py | 43 +++++++---- daemon/core/service.py | 37 ++++------ daemon/core/services/utility.py | 2 +- daemon/core/session.py | 12 +-- daemon/examples/netns/distributed.py | 2 +- daemon/examples/netns/emane80211.py | 2 +- daemon/examples/netns/howmanynodes.py | 2 +- .../examples/netns/iperf-performance-chain.py | 6 +- daemon/examples/netns/ospfmanetmdrtest.py | 5 +- daemon/examples/netns/switch.py | 2 +- daemon/examples/netns/switchtest.py | 4 +- daemon/examples/netns/wlanemanetests.py | 14 ++-- daemon/examples/netns/wlantest.py | 4 +- daemon/tests/conftest.py | 26 +++---- daemon/tests/test_core.py | 4 +- 25 files changed, 314 insertions(+), 175 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index b770e38e..b0e4a11f 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -1087,7 +1087,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # echo back exec message with cmd for spawning interactive terminal if command == "bash": command = "/bin/bash" - res = node.client.termcmdstring(command) + res = node.termcmdstring(command) tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data) return reply, @@ -1097,9 +1097,9 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if message.flags & MessageFlags.STRING.value or message.flags & MessageFlags.TEXT.value: # shlex.split() handles quotes within the string if message.flags & MessageFlags.LOCAL.value: - status, res = utils.cmdresult(shlex.split(command)) + status, res = utils.cmd_output(command) else: - status, res = node.client.cmdresult(shlex.split(command)) + status, res = node.cmd_output(command) logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res)) if message.flags & MessageFlags.TEXT.value: tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) @@ -1110,9 +1110,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # execute the command with no response else: if message.flags & MessageFlags.LOCAL.value: + # TODO: get this consolidated into utils utils.mutedetach(shlex.split(command)) else: - node.client.cmd(shlex.split(command), wait=False) + node.cmd(command, wait=False) except KeyError: logger.exception("error getting object: %s", node_num) # XXX wait and queue this message to try again later diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 6993a09a..a47bf12d 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -412,6 +412,47 @@ class PyCoreNode(PyCoreObj): return common + def check_cmd(self, cmd): + """ + Runs shell command on node. + + :param list[str]/str cmd: command to run + :return: exist status and combined stdout and stderr + :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when a non-zero exit status occurs + """ + raise NotImplementedError + + def cmd(self, cmd, wait=True): + """ + Runs shell command on node, with option to not wait for a result. + + :param list[str]/str cmd: command to run + :param bool wait: wait for command to exit, defaults to True + :return: exit status for command + :rtype: int + """ + raise NotImplementedError + + def cmd_output(self, cmd): + """ + Runs shell command on node and get exit status and output. + + :param list[str]/str cmd: command to run + :return: exit status and combined stdout and stderr + :rtype: tuple[int, str] + """ + raise NotImplementedError + + def termcmdstring(self, sh): + """ + Create a terminal command string. + + :param str sh: shell to execute command in + :return: str + """ + raise NotImplementedError + class PyCoreNet(PyCoreObj): """ diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 892feb6e..9aa9dcbc 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -24,7 +24,7 @@ def emane_version(): cmd = ("emane", "--version") try: - status, result = utils.cmdresult(cmd) + status, result = utils.cmd_output(cmd) except (OSError, subprocess.CalledProcessError): logger.exception("error checking emane version") status = -1 diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 49780661..62e48711 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -103,7 +103,6 @@ class EmaneManager(ConfigurableManager): emane_models = utils.load_classes(custom_models_path, EmaneModel) self.load_models(emane_models) - def logversion(self): """ Log the installed EMANE version. @@ -912,16 +911,23 @@ class EmaneManager(ConfigurableManager): # multicast route is needed for OTA data cmd = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] - node.client.cmd(cmd, wait=True) + try: + node.check_cmd(cmd) + except subprocess.CalledProcessError: + logger.exception("error adding route for OTA data") + # multicast route is also needed for event data if on control network if eventservicenetidx >= 0 and eventgroup != otagroup: cmd = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] - node.client.cmd(cmd, wait=True) + try: + node.check_cmd(cmd) + except subprocess.CalledProcessError: + logger.exception("error adding route for event data") try: cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] logger.info("Emane.startdaemons2() running %s" % str(cmd)) - status, output = node.client.cmdresult(cmd) + status, output = node.check_cmd(cmd) logger.info("Emane.startdaemons2() return code %d" % status) logger.info("Emane.startdaemons2() output: %s" % output) except subprocess.CalledProcessError: @@ -934,8 +940,8 @@ class EmaneManager(ConfigurableManager): try: emanecmd += ["-f", os.path.join(path, "emane.log")] cmd = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons2() running %s" % str(cmd)) - subprocess.check_call(cmd, cwd=path) + logger.info("Emane.startdaemons2() running %s" % cmd) + utils.check_cmd(cmd, cwd=path) except subprocess.CalledProcessError: logger.exception("error starting emane") @@ -954,7 +960,7 @@ class EmaneManager(ConfigurableManager): stop_emane_on_host = True continue if node.up: - node.client.cmd(cmd, wait=False) + node.cmd(cmd, wait=False) # TODO: RJ45 node else: stop_emane_on_host = True @@ -1158,10 +1164,10 @@ class EmaneManager(ConfigurableManager): try: if emane.VERSION < emane.EMANE092: - status = subprocess.call(cmd) + status = subprocess.check_call(cmd) else: - status = node.client.cmd(cmd, wait=True) - except IOError: + status, _ = node.check_cmd(cmd) + except subprocess.CalledProcessError: logger.exception("error checking if emane is running") return status == 0 diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index c723e5aa..a7981090 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -5,6 +5,7 @@ Miscellaneous utility functions, wrappers around some subprocess procedures. import importlib import inspect import os +import shlex import subprocess import sys @@ -111,6 +112,20 @@ def maketuplefromstr(s, value_type): return tuple(value_type(i) for i in values) +def split_cmd(cmd): + """ + Convenience method for splitting potential string commands into a shell-like syntax list. + + :param list/str cmd: command list or string + :return: shell-like syntax list + :rtype: list + """ + # split shell string to shell array for convenience + if type(cmd) == str: + cmd = shlex.split(cmd) + return cmd + + def mutecall(*args, **kwargs): """ Run a muted call command. @@ -129,11 +144,12 @@ def check_alloutput(cmd, **kwargs): """ Convenience wrapper to run subprocess.check_output and include stderr as well. - :param list[str] cmd: command arguments to run + :param list[str]/str cmd: command arguments to run :param dict kwargs: option for running subprocess.check_output, beyond setting stderr to stdout :return: combined stdout and stderr :raises subprocess.CalledProcessError: when a non-zero exit status is encountered """ + cmd = split_cmd(cmd) kwargs["stderr"] = subprocess.STDOUT return subprocess.check_output(cmd, **kwargs) @@ -218,20 +234,43 @@ def mutedetach(*args, **kwargs): return subprocess.Popen(*args, **kwargs).pid -def cmdresult(args): +def cmd_output(cmd): """ Execute a command on the host and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list args: command arguments + :param list[str]/str cmd: command arguments :return: command status and stdout :rtype: tuple[int, str] """ - cmdid = subprocess.Popen(args, stdin=open(os.devnull, "r"), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - # err will always be None - result, err = cmdid.communicate() - status = cmdid.wait() - return status, result + # split shell string to shell array for convenience + cmd = split_cmd(cmd) + p = subprocess.Popen(cmd, stdin=open(os.devnull, "r"), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout, _ = p.communicate() + status = p.wait() + return status, stdout + + +def check_cmd(cmd, **kwargs): + """ + Execute a command on the host and return a tuple containing the exit status and result string. stderr output + is folded into the stdout result string. + + :param list[str]/str cmd: command arguments + :param dict kwargs: keyword arguments to pass to subprocess.Popen + :return: command status and stdout + :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when there is a non-zero exit status + """ + kwargs["stdout"] = subprocess.PIPE + kwargs["stderr"] = subprocess.STDOUT + cmd = split_cmd(cmd) + p = subprocess.Popen(cmd, **kwargs) + stdout, _ = p.communicate() + status = p.wait() + if status: + raise subprocess.CalledProcessError(status, cmd, stdout) + return status, stdout def hexdump(s, bytes_per_word=2, words_per_line=8): diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index d678c930..88178613 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -103,7 +103,7 @@ class CtrlNet(LxBrNet): :return: True if an old bridge was detected, False otherwise :rtype: bool """ - retstat, retstr = utils.cmdresult([constants.BRCTL_BIN, "show"]) + retstat, retstr = utils.cmd_output([constants.BRCTL_BIN, "show"]) if retstat != 0: logger.error("Unable to retrieve list of installed bridges") lines = retstr.split("\n") diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index 31efb5bb..f09716f3 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -406,7 +406,7 @@ class OvsCtrlNet(OvsNet): Check if there are old control net bridges and delete them """ - status, output = utils.cmdresult([constants.OVS_BIN, "list-br"]) + status, output = utils.cmd_output([constants.OVS_BIN, "list-br"]) output = output.strip() if output: for line in output.split("\n"): diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index 362c7d20..00717fcc 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -59,10 +59,16 @@ class VEth(PyCoreNetIf): """ if not self.up: return + if self.node: - self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) + try: + self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) + except subprocess.CalledProcessError: + logger.exception("error shutting down interface") + if self.localname: utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname]) + self.up = False @@ -98,10 +104,10 @@ class TunTap(PyCoreNetIf): """ # TODO: more sophisticated TAP creation here # Debian does not support -p (tap) option, RedHat does. - # For now, this is disabled to allow the TAP to be created by another - # system (e.g. EMANE"s emanetransportd) - # check_call(["tunctl", "-t", self.name]) - # self.install() + # For now, this is disabled to allow the TAP to be created by another + # system (e.g. EMANE"s emanetransportd) + # check_call(["tunctl", "-t", self.name]) + # self.install() self.up = True def shutdown(self): @@ -112,9 +118,12 @@ class TunTap(PyCoreNetIf): """ if not self.up: return - self.node.client.cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) - # if self.name: - # mutedetach(["tunctl", "-d", self.localname]) + + try: + self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) + except subprocess.CalledProcessError: + logger.exception("error shutting down tunnel tap") + self.up = False def waitfor(self, func, attempts=10, maxretrydelay=0.25): @@ -169,7 +178,7 @@ class TunTap(PyCoreNetIf): def nodedevexists(): cmd = [constants.IP_BIN, "link", "show", self.name] - return self.node.client.cmd(cmd) + return self.node.cmd(cmd) count = 0 while True: @@ -199,15 +208,11 @@ class TunTap(PyCoreNetIf): netns = str(self.node.pid) try: - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "netns", netns]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "netns", netns]) + self.node.check_cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) + self.node.check_cmd([constants.IP_BIN, "link", "set", self.name, "up"]) except subprocess.CalledProcessError: - msg = "error installing TAP interface %s, command:" % self.localname - msg += "ip link set %s netns %s" % (self.localname, netns) - logger.exception(msg) - return - - self.node.client.cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) - self.node.client.cmd([constants.IP_BIN, "link", "set", self.name, "up"]) + logger.exception("error installing TAP interface") def setaddrs(self): """ @@ -217,7 +222,10 @@ class TunTap(PyCoreNetIf): """ self.waitfordevicenode() for addr in self.addrlist: - self.node.client.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) + try: + self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) + except subprocess.CalledProcessError: + logger.exception("failure setting interface address") class GreTap(PyCoreNetIf): diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index fe7a8f92..5cbc8467 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -114,11 +114,11 @@ class SimpleLxcNode(PyCoreNode): try: # bring up the loopback interface logger.info("bringing up loopback interface") - self.client.check_alloutput([constants.IP_BIN, "link", "set", "lo", "up"]) + self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"]) # set hostname for node logger.info("setting hostname: %s" % self.name) - self.client.check_alloutput(["hostname", self.name]) + self.check_cmd(["hostname", self.name]) except subprocess.CalledProcessError: logger.exception("error setting up loopback and hostname: %s") @@ -171,6 +171,47 @@ class SimpleLxcNode(PyCoreNode): """ pass + def cmd(self, cmd, wait=True): + """ + Runs shell command on node, with option to not wait for a result. + + :param list[str]/str cmd: command to run + :param bool wait: wait for command to exit, defaults to True + :return: exit status for command + :rtype: int + """ + return self.client.cmd(cmd, wait) + + def cmd_output(self, cmd): + """ + Runs shell command on node and get exit status and output. + + :param list[str]/str cmd: command to run + :return: exit status and combined stdout and stderr + :rtype: tuple[int, str] + """ + return self.client.cmd_output(cmd) + + def check_cmd(self, cmd): + """ + Runs shell command on node. + + :param list[str]/str cmd: command to run + :return: exist status and combined stdout and stderr + :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when a non-zero exit status occurs + """ + return self.client.check_cmd(cmd) + + def termcmdstring(self, sh="/bin/sh"): + """ + Create a terminal command string. + + :param str sh: shell to execute command in + :return: str + """ + return self.client.termcmdstring(sh) + # TODO: should change how this exception is just swallowed up def mount(self, source, target): """ @@ -200,7 +241,7 @@ class SimpleLxcNode(PyCoreNode): """ logger.info("unmounting: %s", target) try: - self.client.check_alloutput([constants.UMOUNT_BIN, "-n", "-l", target]) + self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target]) except subprocess.CalledProcessError: logger.exception("error during unmount") @@ -247,8 +288,8 @@ class SimpleLxcNode(PyCoreNode): if self.up: try: - utils.check_alloutput([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) - self.client.check_alloutput([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) + utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) + self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) except subprocess.CalledProcessError: logger.exception("failure setting eth name") @@ -258,7 +299,7 @@ class SimpleLxcNode(PyCoreNode): # TODO: potentially find better way to query interface ID # retrieve interface information try: - output = self.client.check_alloutput(["ip", "link", "show", veth.name]) + _, output = self.check_cmd(["ip", "link", "show", veth.name]) logger.info("interface command output: %s", output) output = output.split("\n") veth.flow_id = int(output[0].strip().split(":")[0]) + 1 @@ -320,7 +361,7 @@ class SimpleLxcNode(PyCoreNode): if self.up: cmd = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] try: - self.client.check_alloutput(cmd) + self.check_cmd(cmd) except subprocess.CalledProcessError: logger.exception("error setting MAC address %s: %s", addr) @@ -337,10 +378,10 @@ class SimpleLxcNode(PyCoreNode): # check if addr is ipv6 if ":" in str(addr): cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] - self.client.check_alloutput(cmd) + self.check_cmd(cmd) else: cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] - self.client.check_alloutput(cmd) + self.check_cmd(cmd) except subprocess.CalledProcessError: logger.exception("failure adding interface address") @@ -361,7 +402,7 @@ class SimpleLxcNode(PyCoreNode): if self.up: try: - self.client.check_alloutput([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) + self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) except subprocess.CalledProcessError: logger.exception("failure deleting address") @@ -394,7 +435,7 @@ class SimpleLxcNode(PyCoreNode): """ if self.up: try: - self.client.check_alloutput([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) + self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) except subprocess.CalledProcessError: logger.exception("failure bringing interface up") @@ -454,15 +495,15 @@ class SimpleLxcNode(PyCoreNode): tmplen = 8 tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) for _ in xrange(tmplen)]) - utils.check_alloutput([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2]) + utils.check_cmd([constants.IP_BIN, "link", "add", "name", tmp1, "type", "veth", "peer", "name", tmp2]) - utils.check_alloutput([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) - self.client.check_alloutput([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) + utils.check_cmd([constants.IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) + self.check_cmd([constants.IP_BIN, "link", "set", tmp1, "name", ifname]) interface = PyCoreNetIf(node=self, name=ifname, mtu=_DEFAULT_MTU) self.addnetif(interface, self.newifindex()) - utils.check_alloutput([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) - othernode.client.check_alloutput([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) + utils.check_cmd([constants.IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) + othernode.check_cmd([constants.IP_BIN, "link", "set", tmp2, "name", otherifname]) other_interface = PyCoreNetIf(node=othernode, name=otherifname, mtu=_DEFAULT_MTU) othernode.addnetif(other_interface, othernode.newifindex()) diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 810e6a31..53fe165b 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -6,13 +6,13 @@ by invoking the vcmd shell command. """ import os -import shlex import subprocess import vcmd from core import constants from core import logger +from core.misc import utils VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd") @@ -61,89 +61,86 @@ class VnodeClient(object): """ self.cmdchnl.close() - def cmd(self, args, wait=True): + def cmd(self, cmd, wait=True): """ Execute a command on a node and return the status (return code). - :param list args: command arguments + :param list[str]/str cmd: command arguments :param bool wait: wait for command to end or not :return: command status :rtype: int """ self._verify_connection() + cmd = utils.split_cmd(cmd) # run command, return process when not waiting - p = self.cmdchnl.qcmd(args) + p = self.cmdchnl.qcmd(cmd) if not wait: - return p + return 0 # wait for and return exit status status = p.wait() if status: - logger.warn("cmd exited with status %s: %s", status, args) + logger.warn("cmd exited with status %s: %s", status, cmd) + return status - def cmdresult(self, cmd): + def cmd_output(self, cmd): """ Execute a command on a node and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list cmd: command arguments + :param list[str]/str cmd: command to run :return: command status and combined stdout and stderr output :rtype: tuple[int, str] """ - self._verify_connection() - - # split shell string to shell array for convenience - if type(cmd) == str: - cmd = shlex.split(cmd) - p, stdin, stdout, stderr = self.popen(cmd) stdin.close() output = stdout.read() + stderr.read() stdout.close() stderr.close() status = p.wait() - return status, output - def check_alloutput(self, cmd): + def check_cmd(self, cmd): """ - Run command and return output, raises exception when non-zero exit status is encountered. + Run command and return exit status and combined stdout and stderr. - :param cmd: - :return: combined stdout and stderr combined - :rtype: str + :param list[str]/str cmd: command to run + :return: exit status and combined stdout and stderr + :rtype: tuple[int, str] :raises subprocess.CalledProcessError: when there is a non-zero exit status """ - status, output = self.cmdresult(cmd) + status, output = self.cmd_output(cmd) if status: raise subprocess.CalledProcessError(status, cmd, output) - return output + return status, output - def popen(self, args): + def popen(self, cmd): """ Execute a popen command against the node. - :param list args: command arguments + :param list[str]/str cmd: command arguments :return: popen object, stdin, stdout, and stderr :rtype: tuple """ self._verify_connection() - return self.cmdchnl.popen(args) + cmd = utils.split_cmd(cmd) + return self.cmdchnl.popen(cmd) - def icmd(self, args): + def icmd(self, cmd): """ Execute an icmd against a node. - :param list args: command arguments + :param list[str]/str cmd: command arguments :return: command result :rtype: int """ - return os.spawnlp(os.P_WAIT, VCMD, VCMD, "-c", self.ctrlchnlname, "--", *args) + cmd = utils.split_cmd(cmd) + return os.spawnlp(os.P_WAIT, VCMD, VCMD, "-c", self.ctrlchnlname, "--", *cmd) - def redircmd(self, infd, outfd, errfd, args, wait=True): + def redircmd(self, infd, outfd, errfd, cmd, wait=True): """ Execute a command on a node with standard input, output, and error redirected according to the given file descriptors. @@ -151,7 +148,7 @@ class VnodeClient(object): :param infd: stdin file descriptor :param outfd: stdout file descriptor :param errfd: stderr file descriptor - :param list args: command arguments + :param list[str]/str cmd: command arguments :param bool wait: wait flag :return: command status :rtype: int @@ -159,14 +156,15 @@ class VnodeClient(object): self._verify_connection() # run command, return process when not waiting - p = self.cmdchnl.redircmd(infd, outfd, errfd, args) + cmd = utils.split_cmd(cmd) + p = self.cmdchnl.redircmd(infd, outfd, errfd, cmd) if not wait: return p # wait for and return exit status status = p.wait() if status: - logger.warn("cmd exited with status %s: %s", status, args) + logger.warn("cmd exited with status %s: %s", status, cmd) return status def term(self, sh="/bin/sh"): @@ -193,16 +191,16 @@ class VnodeClient(object): """ return "%s -c %s -- %s" % (VCMD, self.ctrlchnlname, sh) - def shcmd(self, cmdstr, sh="/bin/sh"): + def shcmd(self, cmd, sh="/bin/sh"): """ Execute a shell command. - :param str cmdstr: command string + :param str cmd: command string :param str sh: shell to run command in :return: command result :rtype: int """ - return self.cmd([sh, "-c", cmdstr]) + return self.cmd([sh, "-c", cmd]) def shcmd_result(self, cmd, sh="/bin/sh"): """ @@ -213,7 +211,7 @@ class VnodeClient(object): :return: exist status and combined output :rtype: tuple[int, str] """ - return self.cmdresult([sh, "-c", cmd]) + return self.cmd_output([sh, "-c", cmd]) def getaddr(self, ifname, rescan=False): """ diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 2788fc0a..3f85c635 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -65,29 +65,46 @@ class PhysicalNode(PyCoreNode): run a command on the physical node """ os.chdir(self.nodedir) + status = -1 + try: if wait: # os.spawnlp(os.P_WAIT, args) - subprocess.call(args) + status = subprocess.call(args) else: # os.spawnlp(os.P_NOWAIT, args) subprocess.Popen(args) + status = 0 except subprocess.CalledProcessError: - logger.exception("cmd exited with status: %s", str(args)) + logger.exception("cmd exited with status: %s", args) - def cmdresult(self, args): + return status + + def cmd_output(self, args): """ run a command on the physical node and get the result """ os.chdir(self.nodedir) # in Python 2.7 we can use subprocess.check_output() here - tmp = subprocess.Popen(args, stdin=open(os.devnull, 'r'), - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) # err will always be None - result, err = tmp.communicate() - status = tmp.wait() - return status, result + stdout, err = p.communicate() + status = p.wait() + return status, stdout + + def check_cmd(self, cmd): + """ + Runs shell command on node. + + :param list[str]/str cmd: command to run + :return: exist status and combined stdout and stderr + :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when a non-zero exit status occurs + """ + status, output = self.cmd_output(cmd) + if status: + raise subprocess.CalledProcessError(status, cmd, output) + return status, output def shcmd(self, cmdstr, sh="/bin/sh"): return self.cmd([sh, "-c", cmdstr]) @@ -99,10 +116,10 @@ class PhysicalNode(PyCoreNode): self._netif[ifindex].sethwaddr(addr) ifname = self.ifname(ifindex) if self.up: - (status, result) = self.cmdresult( - [constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)]) - if status: - logger.error("error setting MAC address %s", str(addr)) + try: + self.check_cmd([constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)]) + except subprocess.CalledProcessError: + logger.exception("error setting MAC address %s", addr) def addaddr(self, ifindex, addr): """ diff --git a/daemon/core/service.py b/daemon/core/service.py index a6169ef7..fe37e95f 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -6,8 +6,7 @@ The CoreServices class handles configuration messages for sending a list of available services to the GUI and for configuring individual services. """ - -import shlex +import subprocess import time from itertools import repeat @@ -307,8 +306,8 @@ class CoreServices(ConfigurableManager): for cmd in service.getstartup(node, services): try: - # NOTE: this wait=False can be problematic! - node.client.cmd(shlex.split(cmd), wait=False) + # TODO: this wait=False can be problematic! + node.cmd(cmd, wait=False) except: logger.exception("error starting command %s", cmd) @@ -353,8 +352,8 @@ class CoreServices(ConfigurableManager): for cmd in service._startup: try: - # NOTE: this wait=False can be problematic! - node.client.cmd(shlex.split(cmd), wait=False) + # TODO: this wait=False can be problematic! + node.cmd(cmd, wait=False) except: logger.exception("error starting command %s", cmd) @@ -413,11 +412,9 @@ class CoreServices(ConfigurableManager): for cmd in validate_cmds: logger.info("validating service %s using: %s", service._name, cmd) try: - status, result = node.client.cmdresult(shlex.split(cmd)) - if status != 0: - raise ValueError("non-zero exit status") - except: - logger.exception("validate command failed: %s", cmd) + status, _ = node.check_cmd(cmd) + except subprocess.CalledProcessError: + logger.exception("validate command failed") status = -1 return status @@ -449,11 +446,12 @@ class CoreServices(ConfigurableManager): else: for cmd in service._shutdown: try: - tmp = node.client.cmd(shlex.split(cmd), wait=True) - status += "%s" % tmp - except: + status, _ = node.check_cmd(cmd) + status = str(status) + except subprocess.CalledProcessError: logger.exception("error running stop command %s", cmd) - status += "-1" + # TODO: determine if its ok to just return the bad exit status + status = "-1" return status def configure_request(self, config_data): @@ -761,13 +759,10 @@ class CoreServices(ConfigurableManager): if len(cmds) > 0: for cmd in cmds: try: - # node.cmd(shlex.split(cmd), wait = False) - status = node.client.cmd(shlex.split(cmd), wait=True) - if status != 0: - fail += "Start %s(%s)," % (s._name, cmd) - except: + node.check_cmd(cmd) + except subprocess.CalledProcessError: logger.exception("error starting command %s", cmd) - fail += "Start %s," % s._name + fail += "Start %s(%s)," % (s._name, cmd) if event_type == EventTypes.PAUSE.value: status = self.validatenodeservice(node, s, services) if status != 0: diff --git a/daemon/core/services/utility.py b/daemon/core/services/utility.py index 912a9c1f..534fc752 100644 --- a/daemon/core/services/utility.py +++ b/daemon/core/services/utility.py @@ -418,7 +418,7 @@ class HttpService(UtilService): Detect the apache2 version using the 'a2query' command. """ try: - status, result = utils.cmdresult(['a2query', '-v']) + status, result = utils.cmd_output(['a2query', '-v']) except subprocess.CalledProcessError: status = -1 diff --git a/daemon/core/session.py b/daemon/core/session.py index f7567162..cf57b07e 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -530,7 +530,7 @@ class Session(object): try: utils.readfileintodict(environment_user_file, env) except IOError: - logger.exception("error reading user core environment settings file: %s", environment_user_file) + logger.warn("error reading user core environment settings file: %s", environment_user_file) return env @@ -609,7 +609,7 @@ class Session(object): :param int object_id: object id to retrieve :return: object for the given id - :rtype: core.netns.vnode.LxcNode + :rtype: core.coreobj.PyCoreNode """ if object_id not in self.objects: raise KeyError("unknown object id %s" % object_id) @@ -1238,13 +1238,14 @@ class Session(object): name = "" logger.info("scheduled event %s at time %s data=%s", name, event_time + current_time, data) + # TODO: if data is None, this blows up, but this ties into how event functions are ran, need to clean that up def run_event(self, node_id=None, name=None, data=None): """ Run a scheduled event, executing commands in the data string. :param int node_id: node id to run event :param str name: event name - :param data: event data + :param str data: event data :return: nothing """ now = self.runtime() @@ -1252,12 +1253,13 @@ class Session(object): name = "" logger.info("running event %s at time %s cmd=%s" % (name, now, data)) - commands = shlex.split(data) if not node_id: + # TODO: look to consolidate shlex to utils + commands = shlex.split(data) utils.mutedetach(commands) else: node = self.get_object(node_id) - node.client.cmd(commands, wait=False) + node.cmd(data, wait=False) def send_objects(self): """ diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index 8bbd1f49..a76388b1 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -82,7 +82,7 @@ def main(): for i in xrange(1, num_local + 1): node = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - node.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + node.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) node.setposition(x=150 * i, y=150) n.append(node) diff --git a/daemon/examples/netns/emane80211.py b/daemon/examples/netns/emane80211.py index 1831ab1c..e9f30ef6 100755 --- a/daemon/examples/netns/emane80211.py +++ b/daemon/examples/netns/emane80211.py @@ -83,7 +83,7 @@ def main(): for i in xrange(1, options.numnodes + 1): tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.setposition(x=150 * i, y=150) session.services.addservicestonode(tmp, "", services_str) n.append(tmp) diff --git a/daemon/examples/netns/howmanynodes.py b/daemon/examples/netns/howmanynodes.py index bff69478..8803d872 100755 --- a/daemon/examples/netns/howmanynodes.py +++ b/daemon/examples/netns/howmanynodes.py @@ -159,7 +159,7 @@ def main(): try: n = session.add_object(cls=nodes.LxcNode, name="n%d" % i) n.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - n.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + n.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) if options.services is not None: session.services.addservicestonode(n, "", options.services) n.boot() diff --git a/daemon/examples/netns/iperf-performance-chain.py b/daemon/examples/netns/iperf-performance-chain.py index ddc08568..412dd9a6 100755 --- a/daemon/examples/netns/iperf-performance-chain.py +++ b/daemon/examples/netns/iperf-performance-chain.py @@ -72,9 +72,9 @@ def main(): prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i) right = session.add_object(cls=nodes.PtpNet) tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)]) - tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) - tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) - tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) + tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) + tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) tmp.setposition(x=100 * i, y=150) n.append(tmp) left = right diff --git a/daemon/examples/netns/ospfmanetmdrtest.py b/daemon/examples/netns/ospfmanetmdrtest.py index 63634c7f..727f9436 100755 --- a/daemon/examples/netns/ospfmanetmdrtest.py +++ b/daemon/examples/netns/ospfmanetmdrtest.py @@ -268,7 +268,7 @@ class ManetExperiment(object): self.nodes[i].boot() # run the boot.sh script on all nodes to start Quagga for i in xrange(numnodes): - self.nodes[i].client.cmd(["./%s" % self.nodes[i].bootsh]) + self.nodes[i].cmd(["./%s" % self.nodes[i].bootsh]) def compareroutes(self, node, kr, zr): """ Compare two lists of Route objects. @@ -386,8 +386,7 @@ class Cmd: def open(self): """ Exceute call to node.popen(). """ - self.id, self.stdin, self.out, self.err = \ - self.node.client.popen(self.args) + self.id, self.stdin, self.out, self.err = self.node.client.popen(self.args) def parse(self): """ This method is overloaded by child classes and should return some diff --git a/daemon/examples/netns/switch.py b/daemon/examples/netns/switch.py index 802eaa78..bf43562f 100755 --- a/daemon/examples/netns/switch.py +++ b/daemon/examples/netns/switch.py @@ -57,7 +57,7 @@ def main(): for i in xrange(1, options.numnodes + 1): tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) tmp.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.client.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) + tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) tmp.setposition(x=150 * i, y=150) n.append(tmp) diff --git a/daemon/examples/netns/switchtest.py b/daemon/examples/netns/switchtest.py index bb050c9d..6b1e953d 100755 --- a/daemon/examples/netns/switchtest.py +++ b/daemon/examples/netns/switchtest.py @@ -36,9 +36,9 @@ def test(numnodes, testsec): tmp = session.add_object(cls=nodes.LxcNode, name="n%d" % i) tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.append(tmp) - n[0].client.cmd(["iperf", "-s", "-D"]) + n[0].cmd(["iperf", "-s", "-D"]) n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].client.cmd(["killall", "-9", "iperf"]) + n[0].cmd(["killall", "-9", "iperf"]) raw_input("press enter to exit") session.shutdown() diff --git a/daemon/examples/netns/wlanemanetests.py b/daemon/examples/netns/wlanemanetests.py index bfc06ad5..6c9617a3 100755 --- a/daemon/examples/netns/wlanemanetests.py +++ b/daemon/examples/netns/wlanemanetests.py @@ -166,7 +166,7 @@ class ClientServerCmd(Cmd): self.client_open() # client status = self.client_id.wait() # stop the server - self.node.client.cmdresult(["killall", self.args[0]]) + self.node.cmd_output(["killall", self.args[0]]) r = self.parse() self.cleanup() return r @@ -207,7 +207,7 @@ class PingCmd(Cmd): def run(self): if self.verbose: self.info("%s initial test ping (max 1 second)..." % self.node.name) - (status, result) = self.node.client.cmdresult(["ping", "-q", "-c", "1", "-w", "1", self.addr]) + (status, result) = self.node.cmd_output(["ping", "-q", "-c", "1", "-w", "1", self.addr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % (self.node.name, self.addr, result)) @@ -226,7 +226,7 @@ class PingCmd(Cmd): stats = stats_str.split("/") avg_latency = float(stats[1]) mdev = float(stats[3].split(" ")[0]) - except Exception, e: + except: self.warn("ping parsing exception: %s" % e) return avg_latency, mdev @@ -487,13 +487,13 @@ class Experiment(object): if i > 1: neigh_left = "%s" % prefix.addr(i - 1) cmd = routecmd + [neigh_left, "dev", node.netif(0).name] - (status, result) = node.client.cmdresult(cmd) + (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) if i < numnodes: neigh_right = "%s" % prefix.addr(i + 1) cmd = routecmd + [neigh_right, "dev", node.netif(0).name] - (status, result) = node.client.cmdresult(cmd) + (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) @@ -507,7 +507,7 @@ class Experiment(object): else: gw = neigh_right cmd = routecmd + [addr, "via", gw] - (status, result) = node.client.cmdresult(cmd) + (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add route: %s" % cmd) @@ -635,7 +635,7 @@ class Experiment(object): if self.verbose: self.info("%s initial test ping (max 1 second)..." % \ self.firstnode.name) - (status, result) = self.firstnode.client.cmdresult(["ping", "-q", "-c", "1", + (status, result) = self.firstnode.cmd_output(["ping", "-q", "-c", "1", "-w", "1", self.lastaddr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % \ diff --git a/daemon/examples/netns/wlantest.py b/daemon/examples/netns/wlantest.py index ce14377f..da2a813d 100755 --- a/daemon/examples/netns/wlantest.py +++ b/daemon/examples/netns/wlantest.py @@ -37,9 +37,9 @@ def test(numnodes, testsec): tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) n.append(tmp) net.link(n[0].netif(0), n[-1].netif(0)) - n[0].client.cmd(["iperf", "-s", "-D"]) + n[0].cmd(["iperf", "-s", "-D"]) n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].client.cmd(["killall", "-9", "iperf"]) + n[0].cmd(["killall", "-9", "iperf"]) session.shutdown() diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index 67ae188c..ffb6d6ac 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -5,23 +5,18 @@ Unit test fixture module. import os import pytest - from mock.mock import MagicMock from core import services -from core.coreserver import CoreServer -from core.misc import nodemaps -from core.misc import nodeutils -from core.netns import nodes -from core.session import Session from core.api.coreapi import CoreConfMessage from core.api.coreapi import CoreEventMessage from core.api.coreapi import CoreExecMessage from core.api.coreapi import CoreLinkMessage from core.api.coreapi import CoreNodeMessage from core.corehandlers import CoreRequestHandler -from core.enumerations import ConfigTlvs +from core.coreserver import CoreServer from core.enumerations import CORE_API_PORT +from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs from core.enumerations import EventTypes from core.enumerations import ExecuteTlvs @@ -32,6 +27,8 @@ from core.enumerations import NodeTlvs from core.enumerations import NodeTypes from core.misc import ipaddress from core.misc.ipaddress import MacAddress +from core.netns import nodes +from core.session import Session EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward" @@ -186,18 +183,13 @@ class Core(object): def ping(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - return from_node.client.cmd(["ping", "-c", "3", to_ip]) + return from_node.cmd(["ping", "-c", "3", to_ip]) def ping_output(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - vcmd, stdin, stdout, stderr = from_node.client.popen(["ping", "-i", "0.05", "-c", "3", to_ip]) - return stdout.read().strip() - - def iping(self, from_name, to_name): - from_node = self.nodes[from_name] - to_ip = str(self.get_ip(to_name)) - from_node.client.icmd(["ping", "-i", "0.01", "-c", "10", to_ip]) + _, output = from_node.check_cmd(["ping", "-i", "0.05", "-c", "3", to_ip]) + return output def iperf(self, from_name, to_name): from_node = self.nodes[from_name] @@ -206,8 +198,8 @@ class Core(object): # run iperf server, run client, kill iperf server vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"]) - from_node.client.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) - to_node.client.cmd(["killall", "-9", "iperf"]) + from_node.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) + to_node.cmd(["killall", "-9", "iperf"]) return stdout.read().strip() diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index dabc12ce..2340f2fb 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -177,7 +177,7 @@ class TestCore: # check various command using vcmd module command = ["ls"] assert not client.cmd(command) - status, output = client.cmdresult(command) + status, output = client.cmd_output(command) assert not status p, stdin, stdout, stderr = client.popen(command) assert not p.status() @@ -187,7 +187,7 @@ class TestCore: # check various command using command line assert not client.cmd(command) - status, output = client.cmdresult(command) + status, output = client.cmd_output(command) assert not status p, stdin, stdout, stderr = client.popen(command) assert not p.wait() From 870d87804be1eb48f31baf674a25c3539ba95683 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 1 Mar 2018 13:46:09 -0800 Subject: [PATCH 042/152] updated commands that return output to strip it before returning --- daemon/core/netns/vnodeclient.py | 4 ++-- daemon/core/phys/pnodes.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 53fe165b..e78f802c 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -101,7 +101,7 @@ class VnodeClient(object): stdout.close() stderr.close() status = p.wait() - return status, output + return status, output.strip() def check_cmd(self, cmd): """ @@ -115,7 +115,7 @@ class VnodeClient(object): status, output = self.cmd_output(cmd) if status: raise subprocess.CalledProcessError(status, cmd, output) - return status, output + return status, output.strip() def popen(self, cmd): """ diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 3f85c635..f9be028d 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -90,7 +90,7 @@ class PhysicalNode(PyCoreNode): # err will always be None stdout, err = p.communicate() status = p.wait() - return status, stdout + return status, stdout.strip() def check_cmd(self, cmd): """ @@ -104,7 +104,7 @@ class PhysicalNode(PyCoreNode): status, output = self.cmd_output(cmd) if status: raise subprocess.CalledProcessError(status, cmd, output) - return status, output + return status, output.strip() def shcmd(self, cmdstr, sh="/bin/sh"): return self.cmd([sh, "-c", cmdstr]) From 6211b0958511676d691d311a1879724647c6c49d Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 1 Mar 2018 16:23:58 -0800 Subject: [PATCH 043/152] further cleanup in regards the commands that are being used within core --- daemon/core/coreobj.py | 12 +-- daemon/core/emane/__init__.py | 6 +- daemon/core/emane/emanemanager.py | 56 +++++++------ daemon/core/misc/utils.py | 95 ++++++++++++---------- daemon/core/mobility.py | 8 +- daemon/core/netns/nodes.py | 129 +++++++++++++++--------------- daemon/core/netns/openvswitch.py | 40 ++++----- daemon/core/netns/vif.py | 36 ++++----- daemon/core/netns/vnet.py | 52 ++++++------ daemon/core/netns/vnode.py | 36 ++++----- daemon/core/netns/vnodeclient.py | 74 ++++++++--------- daemon/core/phys/pnodes.py | 41 +++++----- daemon/core/service.py | 32 ++++---- daemon/core/session.py | 10 +-- daemon/core/xml/xmldeployment.py | 11 ++- 15 files changed, 322 insertions(+), 316 deletions(-) diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index a47bf12d..6af238b8 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -412,33 +412,33 @@ class PyCoreNode(PyCoreObj): return common - def check_cmd(self, cmd): + def check_cmd(self, args): """ Runs shell command on node. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exist status and combined stdout and stderr :rtype: tuple[int, str] :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ raise NotImplementedError - def cmd(self, cmd, wait=True): + def cmd(self, args, wait=True): """ Runs shell command on node, with option to not wait for a result. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :param bool wait: wait for command to exit, defaults to True :return: exit status for command :rtype: int """ raise NotImplementedError - def cmd_output(self, cmd): + def cmd_output(self, args): """ Runs shell command on node and get exit status and output. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exit status and combined stdout and stderr :rtype: tuple[int, str] """ diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 9aa9dcbc..fff93664 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -21,11 +21,11 @@ def emane_version(): """ global VERSION global VERSIONSTR - cmd = ("emane", "--version") + args = ("emane", "--version") try: - status, result = utils.cmd_output(cmd) - except (OSError, subprocess.CalledProcessError): + status, result = utils.check_cmd(args) + except subprocess.CalledProcessError: logger.exception("error checking emane version") status = -1 result = "" diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 62e48711..6ce75328 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -788,7 +788,7 @@ class EmaneManager(ConfigurableManager): the transportdaemon*.xml. """ try: - subprocess.check_call(["emanegentransportxml", "platform.xml"], cwd=self.session.session_dir) + utils.check_cmd(["emanegentransportxml", "platform.xml"], cwd=self.session.session_dir) except subprocess.CalledProcessError: logger.exception("error running emanegentransportxml") @@ -845,23 +845,23 @@ class EmaneManager(ConfigurableManager): if realtime: emanecmd += "-r", try: - cmd = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons() running %s" % str(cmd)) - subprocess.check_call(cmd, cwd=path) + args = emanecmd + [os.path.join(path, "platform.xml")] + logger.info("Emane.startdaemons() running %s" % str(args)) + utils.check_cmd(args, cwd=path) except subprocess.CalledProcessError: logger.exception("error starting emane") # start one transport daemon per transportdaemon*.xml file - transcmd = ["emanetransportd", "-d", "--logl", loglevel, "-f", os.path.join(path, "emanetransportd.log")] + args = ["emanetransportd", "-d", "--logl", loglevel, "-f", os.path.join(path, "emanetransportd.log")] if realtime: - transcmd += "-r", + args += "-r", files = os.listdir(path) for file in files: if file[-3:] == "xml" and file[:15] == "transportdaemon": - cmd = transcmd + [os.path.join(path, file)] + args = args + [os.path.join(path, file)] try: - logger.info("Emane.startdaemons() running %s" % str(cmd)) - subprocess.check_call(cmd, cwd=path) + logger.info("Emane.startdaemons() running %s" % str(args)) + utils.check_cmd(args, cwd=path) except subprocess.CalledProcessError: logger.exception("error starting emanetransportd") @@ -910,24 +910,24 @@ class EmaneManager(ConfigurableManager): self.session.add_remove_control_interface(node, eventservicenetidx, remove=False, conf_required=False) # multicast route is needed for OTA data - cmd = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] + args = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] try: - node.check_cmd(cmd) + node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("error adding route for OTA data") # multicast route is also needed for event data if on control network if eventservicenetidx >= 0 and eventgroup != otagroup: - cmd = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] + args = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] try: - node.check_cmd(cmd) + node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("error adding route for event data") try: - cmd = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] - logger.info("Emane.startdaemons2() running %s" % str(cmd)) - status, output = node.check_cmd(cmd) + args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] + logger.info("Emane.startdaemons2() running %s" % str(args)) + status, output = node.check_cmd(args) logger.info("Emane.startdaemons2() return code %d" % status) logger.info("Emane.startdaemons2() output: %s" % output) except subprocess.CalledProcessError: @@ -939,9 +939,9 @@ class EmaneManager(ConfigurableManager): path = self.session.session_dir try: emanecmd += ["-f", os.path.join(path, "emane.log")] - cmd = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons2() running %s" % cmd) - utils.check_cmd(cmd, cwd=path) + args = emanecmd + [os.path.join(path, "platform.xml")] + logger.info("Emane.startdaemons2() running %s" % args) + utils.check_cmd(args, cwd=path) except subprocess.CalledProcessError: logger.exception("error starting emane") @@ -951,7 +951,7 @@ class EmaneManager(ConfigurableManager): """ # TODO: we may want to improve this if we had the PIDs from the # specific EMANE daemons that we"ve started - cmd = ["killall", "-q", "emane"] + args = ["killall", "-q", "emane"] stop_emane_on_host = False if emane.VERSION > emane.EMANE091: for node in self.getnodes(): @@ -960,13 +960,17 @@ class EmaneManager(ConfigurableManager): stop_emane_on_host = True continue if node.up: - node.cmd(cmd, wait=False) + node.cmd(args, wait=False) # TODO: RJ45 node else: stop_emane_on_host = True + if stop_emane_on_host: - subprocess.call(cmd) - subprocess.call(["killall", "-q", "emanetransportd"]) + try: + utils.check_cmd(args) + utils.check_cmd(["killall", "-q", "emanetransportd"]) + except subprocess.CalledProcessError: + logger.exception("error shutting down emane daemons") def installnetifs(self, do_netns=True): """ @@ -1160,13 +1164,13 @@ class EmaneManager(ConfigurableManager): is running, False otherwise. """ status = -1 - cmd = ["pkill", "-0", "-x", "emane"] + args = ["pkill", "-0", "-x", "emane"] try: if emane.VERSION < emane.EMANE092: - status = subprocess.check_call(cmd) + status = utils.check_cmd(args) else: - status, _ = node.check_cmd(cmd) + status, _ = node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("error checking if emane is running") diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index a7981090..c80b4771 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -14,6 +14,8 @@ import resource from core import logger +DEVNULL = open(os.devnull, "wb") + def closeonexec(fd): """ @@ -112,18 +114,18 @@ def maketuplefromstr(s, value_type): return tuple(value_type(i) for i in values) -def split_cmd(cmd): +def split_args(args): """ Convenience method for splitting potential string commands into a shell-like syntax list. - :param list/str cmd: command list or string + :param list/str args: command list or string :return: shell-like syntax list :rtype: list """ # split shell string to shell array for convenience - if type(cmd) == str: - cmd = shlex.split(cmd) - return cmd + if type(args) == str: + args = shlex.split(args) + return args def mutecall(*args, **kwargs): @@ -135,25 +137,11 @@ def mutecall(*args, **kwargs): :return: command result :rtype: int """ - kwargs["stdout"] = open(os.devnull, "w") + kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT return subprocess.call(*args, **kwargs) -def check_alloutput(cmd, **kwargs): - """ - Convenience wrapper to run subprocess.check_output and include stderr as well. - - :param list[str]/str cmd: command arguments to run - :param dict kwargs: option for running subprocess.check_output, beyond setting stderr to stdout - :return: combined stdout and stderr - :raises subprocess.CalledProcessError: when a non-zero exit status is encountered - """ - cmd = split_cmd(cmd) - kwargs["stderr"] = subprocess.STDOUT - return subprocess.check_output(cmd, **kwargs) - - def mutecheck_call(*args, **kwargs): """ Run a muted check call command. @@ -163,7 +151,7 @@ def mutecheck_call(*args, **kwargs): :return: command result :rtype: int """ - kwargs["stdout"] = open(os.devnull, "w") + kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT return subprocess.check_call(*args, **kwargs) @@ -189,7 +177,7 @@ def mutespawn(*args, **kwargs): :return: process id of the command :rtype: int """ - kwargs["stdout"] = open(os.devnull, "w") + kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT return subprocess.Popen(*args, **kwargs).pid @@ -229,48 +217,73 @@ def mutedetach(*args, **kwargs): :rtype: int """ kwargs["preexec_fn"] = detachinit - kwargs["stdout"] = open(os.devnull, "w") + kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT return subprocess.Popen(*args, **kwargs).pid -def cmd_output(cmd): +def cmd(args, wait=True): + """ + Runs a command on and returns the exit status. + + :param list[str]|str args: command arguments + :param bool wait: wait for command to end or not + :return: command status + :rtype: int + """ + args = split_args(args) + try: + p = subprocess.Popen(args) + if not wait: + return 0 + return p.wait() + except OSError: + raise subprocess.CalledProcessError(-1, args) + + +def cmd_output(args): """ Execute a command on the host and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :return: command status and stdout :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when the file to execute is not found """ - # split shell string to shell array for convenience - cmd = split_cmd(cmd) - p = subprocess.Popen(cmd, stdin=open(os.devnull, "r"), stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - stdout, _ = p.communicate() - status = p.wait() - return status, stdout + args = split_args(args) + try: + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout, _ = p.communicate() + status = p.wait() + return status, stdout + except OSError: + raise subprocess.CalledProcessError(-1, args) -def check_cmd(cmd, **kwargs): +def check_cmd(args, **kwargs): """ Execute a command on the host and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :param dict kwargs: keyword arguments to pass to subprocess.Popen :return: command status and stdout :rtype: tuple[int, str] - :raises subprocess.CalledProcessError: when there is a non-zero exit status + :raises subprocess.CalledProcessError: when there is a non-zero exit status or the file to execute is not found """ kwargs["stdout"] = subprocess.PIPE kwargs["stderr"] = subprocess.STDOUT - cmd = split_cmd(cmd) - p = subprocess.Popen(cmd, **kwargs) - stdout, _ = p.communicate() - status = p.wait() - if status: - raise subprocess.CalledProcessError(status, cmd, stdout) - return status, stdout + args = split_args(args) + try: + p = subprocess.Popen(args, **kwargs) + stdout, _ = p.communicate() + status = p.wait() + if status: + raise subprocess.CalledProcessError(status, args, stdout) + return status, stdout + except OSError: + raise subprocess.CalledProcessError(-1, args) def hexdump(s, bytes_per_word=2, words_per_line=8): diff --git a/daemon/core/mobility.py b/daemon/core/mobility.py index c32b68b0..7bc131ba 100644 --- a/daemon/core/mobility.py +++ b/daemon/core/mobility.py @@ -21,6 +21,7 @@ from core.enumerations import MessageFlags from core.enumerations import MessageTypes from core.enumerations import NodeTlvs from core.enumerations import RegisterTlvs +from core.misc import utils from core.misc.ipaddress import IpAddress @@ -1238,10 +1239,7 @@ class Ns2ScriptedMobility(WayPointMobility): return filename = self.findfile(filename) try: - subprocess.check_call( - ["/bin/sh", filename, typestr], - cwd=self.session.sessiondir, - env=self.session.get_environment() - ) + args = ["/bin/sh", filename, typestr] + utils.check_cmd(args, cwd=self.session.sessiondir, env=self.session.get_environment()) except subprocess.CalledProcessError: logger.exception("Error running script '%s' for WLAN state %s", filename, typestr) diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index 88178613..804a3376 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -73,26 +73,31 @@ class CtrlNet(LxBrNet): return LxBrNet.startup(self) + if self.hostid: addr = self.prefix.addr(self.hostid) else: addr = self.prefix.max_addr() + msg = "Added control network bridge: %s %s" % (self.brname, self.prefix) addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)] + if self.assign_address: self.addrconfig(addrlist=addrlist) msg += " address %s" % addr logger.info(msg) + if self.updown_script is not None: logger.info("interface %s updown script (%s startup) called", self.brname, self.updown_script) - subprocess.check_call([self.updown_script, self.brname, "startup"]) + utils.check_cmd([self.updown_script, self.brname, "startup"]) + if self.serverintf is not None: try: - subprocess.check_call([constants.BRCTL_BIN, "addif", self.brname, self.serverintf]) - subprocess.check_call([constants.IP_BIN, "link", "set", self.serverintf, "up"]) + utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) except subprocess.CalledProcessError: - logger.exception("Error joining server interface %s to controlnet bridge %s", + logger.exception("error joining server interface %s to controlnet bridge %s", self.serverintf, self.brname) def detectoldbridge(self): @@ -103,32 +108,24 @@ class CtrlNet(LxBrNet): :return: True if an old bridge was detected, False otherwise :rtype: bool """ - retstat, retstr = utils.cmd_output([constants.BRCTL_BIN, "show"]) - if retstat != 0: + status, output = utils.cmd_output([constants.BRCTL_BIN, "show"]) + if status != 0: logger.error("Unable to retrieve list of installed bridges") - lines = retstr.split("\n") - for line in lines[1:]: - cols = line.split("\t") - oldbr = cols[0] - flds = cols[0].split(".") - if len(flds) == 3: - if flds[0] == "b" and flds[1] == self.objid: - logger.error( - "Error: An active control net bridge (%s) found. " \ - "An older session might still be running. " \ - "Stop all sessions and, if needed, delete %s to continue." % \ - (oldbr, oldbr) - ) - return True - """ - # Do this if we want to delete the old bridge - logger.warn("Warning: Old %s bridge found: %s" % (self.objid, oldbr)) - try: - check_call([BRCTL_BIN, "delbr", oldbr]) - except subprocess.CalledProcessError as e: - logger.exception("Error deleting old bridge %s", oldbr, e) - logger.info("Deleted %s", oldbr) - """ + else: + lines = output.split("\n") + for line in lines[1:]: + cols = line.split("\t") + oldbr = cols[0] + flds = cols[0].split(".") + if len(flds) == 3: + if flds[0] == "b" and flds[1] == self.objid: + logger.error( + "Error: An active control net bridge (%s) found. " + "An older session might still be running. " + "Stop all sessions and, if needed, delete %s to continue." % + (oldbr, oldbr) + ) + return True return False def shutdown(self): @@ -139,14 +136,14 @@ class CtrlNet(LxBrNet): """ if self.serverintf is not None: try: - subprocess.check_call([constants.BRCTL_BIN, "delif", self.brname, self.serverintf]) + utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf]) except subprocess.CalledProcessError: - logger.exception("Error deleting server interface %s to controlnet bridge %s", + logger.exception("error deleting server interface %s to controlnet bridge %s", self.serverintf, self.brname) if self.updown_script is not None: logger.info("interface %s updown script (%s shutdown) called" % (self.brname, self.updown_script)) - subprocess.check_call([self.updown_script, self.brname, "shutdown"]) + utils.check_cmd([self.updown_script, self.brname, "shutdown"]) LxBrNet.shutdown(self) def all_link_data(self, flags): @@ -324,7 +321,7 @@ class HubNode(LxBrNet): """ LxBrNet.__init__(self, session, objid, name, start) if start: - subprocess.check_call([constants.BRCTL_BIN, "setageing", self.brname, "0"]) + utils.check_cmd([constants.BRCTL_BIN, "setageing", self.brname, "0"]) class WlanNode(LxBrNet): @@ -457,6 +454,8 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): # the following are PyCoreNetIf attributes self.transport_type = "raw" self.localname = name + self.old_up = False + self.old_addrs = [] if start: self.startup() @@ -470,7 +469,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): self.savestate() try: - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "up"]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"]) self.up = True except subprocess.CalledProcessError: logger.exception("failed to run command: %s link set %s up", constants.IP_BIN, self.localname) @@ -484,9 +483,14 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): """ if not self.up: return - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "down"]) - subprocess.check_call([constants.IP_BIN, "addr", "flush", "dev", self.localname]) - utils.mutecall([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"]) + + try: + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"]) + utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname]) + utils.mutecall([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"]) + except subprocess.CalledProcessError as e: + logger.exception("error shutting down: %s", e.output) + self.up = False self.restorestate() @@ -604,7 +608,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :return: nothing """ if self.up: - subprocess.check_call([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) + utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) PyCoreNetIf.addaddr(self, addr) def deladdr(self, addr): @@ -615,7 +619,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :return: nothing """ if self.up: - subprocess.check_call([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name]) + utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name]) PyCoreNetIf.deladdr(self, addr) def savestate(self): @@ -627,30 +631,26 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): """ self.old_up = False self.old_addrs = [] - cmd = [constants.IP_BIN, "addr", "show", "dev", self.localname] + args = [constants.IP_BIN, "addr", "show", "dev", self.localname] try: - tmp = subprocess.Popen(cmd, stdout=subprocess.PIPE) - except OSError: - logger.exception("Failed to run %s command: %s", constants.IP_BIN, cmd) - if tmp.wait(): - logger.warn("Command failed: %s", cmd) - return - lines = tmp.stdout.read() - tmp.stdout.close() - for l in lines.split("\n"): - items = l.split() - if len(items) < 2: - continue - if items[1] == "%s:" % self.localname: - flags = items[2][1:-1].split(",") - if "UP" in flags: - self.old_up = True - elif items[0] == "inet": - self.old_addrs.append((items[1], items[3])) - elif items[0] == "inet6": - if items[1][:4] == "fe80": + _, output = utils.check_cmd(args) + for line in output.split("\n"): + items = line.split() + if len(items) < 2: continue - self.old_addrs.append((items[1], None)) + + if items[1] == "%s:" % self.localname: + flags = items[2][1:-1].split(",") + if "UP" in flags: + self.old_up = True + elif items[0] == "inet": + self.old_addrs.append((items[1], items[3])) + elif items[0] == "inet6": + if items[1][:4] == "fe80": + continue + self.old_addrs.append((items[1], None)) + except subprocess.CalledProcessError: + logger.exception("error during save state") def restorestate(self): """ @@ -660,11 +660,12 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): """ for addr in self.old_addrs: if addr[1] is None: - subprocess.check_call([constants.IP_BIN, "addr", "add", addr[0], "dev", self.localname]) + utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "dev", self.localname]) else: - subprocess.check_call([constants.IP_BIN, "addr", "add", addr[0], "brd", addr[1], "dev", self.localname]) + utils.check_cmd([constants.IP_BIN, "addr", "add", addr[0], "brd", addr[1], "dev", self.localname]) + if self.old_up: - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "up"]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"]) def setposition(self, x=None, y=None, z=None): """ diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index f09716f3..3698f296 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -82,18 +82,18 @@ class OvsNet(PyCoreNet): def startup(self): try: - subprocess.check_call([constants.OVS_BIN, "add-br", self.bridge_name]) + utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name]) except subprocess.CalledProcessError: logger.exception("error adding bridge") try: # turn off spanning tree protocol and forwarding delay # TODO: appears stp and rstp are off by default, make sure this always holds true - # TODO: apears ovs only supports rstp forward delay and again it"s off by default - subprocess.check_call([constants.IP_BIN, "link", "set", self.bridge_name, "up"]) + # TODO: apears ovs only supports rstp forward delay and again it's off by default + utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "up"]) # create a new ebtables chain for this bridge - ebtables_commands(subprocess.check_call, [ + ebtables_commands(utils.check_cmd, [ [constants.EBTABLES_BIN, "-N", self.bridge_name, "-P", self.policy], [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name] ]) @@ -129,8 +129,8 @@ class OvsNet(PyCoreNet): def attach(self, interface): if self.up: try: - subprocess.check_call([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname]) - subprocess.check_call([constants.IP_BIN, "link", "set", interface.localname, "up"]) + utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname]) + utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"]) except subprocess.CalledProcessError: logger.exception("error joining interface %s to bridge %s", interface.localname, self.bridge_name) return @@ -140,7 +140,7 @@ class OvsNet(PyCoreNet): def detach(self, interface): if self.up: try: - subprocess.check_call([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname]) + utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname]) except subprocess.CalledProcessError: logger.exception("error removing interface %s from bridge %s", interface.localname, self.bridge_name) return @@ -217,14 +217,14 @@ class OvsNet(PyCoreNet): limit = 0xffff # max IP payload tbf = ["tbf", "rate", str(bw), "burst", str(burst), "limit", str(limit)] logger.info("linkconfig: %s" % [tc + parent + ["handle", "1:"] + tbf]) - subprocess.check_call(tc + parent + ["handle", "1:"] + tbf) + utils.check_cmd(tc + parent + ["handle", "1:"] + tbf) interface.setparam("has_tbf", True) elif interface.getparam("has_tbf") and bw <= 0: tcd = [] + tc tcd[2] = "delete" if self.up: - subprocess.check_call(tcd + parent) + utils.check_cmd(tcd + parent) interface.setparam("has_tbf", False) # removing the parent removes the child @@ -273,12 +273,12 @@ class OvsNet(PyCoreNet): if self.up: logger.info("linkconfig: %s" % ([tc + parent + ["handle", "10:"]],)) - subprocess.check_call(tc + parent + ["handle", "10:"]) + utils.check_cmd(tc + parent + ["handle", "10:"]) interface.setparam("has_netem", False) elif len(netem) > 1: if self.up: logger.info("linkconfig: %s" % ([tc + parent + ["handle", "10:"] + netem],)) - subprocess.check_call(tc + parent + ["handle", "10:"] + netem) + utils.check_cmd(tc + parent + ["handle", "10:"] + netem) interface.setparam("has_netem", True) def linknet(self, network): @@ -312,8 +312,8 @@ class OvsNet(PyCoreNet): if network.up: # this is similar to net.attach() but uses netif.name instead # of localname - subprocess.check_call([constants.OVS_BIN, "add-port", network.bridge_name, interface.name]) - subprocess.check_call([constants.IP_BIN, "link", "set", interface.name, "up"]) + utils.check_cmd([constants.OVS_BIN, "add-port", network.bridge_name, interface.name]) + utils.check_cmd([constants.IP_BIN, "link", "set", interface.name, "up"]) # TODO: is there a native method for this? see if this causes issues # i = network.newifindex() @@ -347,7 +347,7 @@ class OvsNet(PyCoreNet): for address in addresses: try: - subprocess.check_call([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name]) + utils.check_cmd([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name]) except subprocess.CalledProcessError: logger.exception("error adding IP address") @@ -390,12 +390,12 @@ class OvsCtrlNet(OvsNet): if self.updown_script: logger.info("interface %s updown script %s startup called" % (self.bridge_name, self.updown_script)) - subprocess.check_call([self.updown_script, self.bridge_name, "startup"]) + utils.check_cmd([self.updown_script, self.bridge_name, "startup"]) if self.serverintf: try: - subprocess.check_call([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf]) - subprocess.check_call([constants.IP_BIN, "link", "set", self.serverintf, "up"]) + utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) except subprocess.CalledProcessError: logger.exception("error joining server interface %s to controlnet bridge %s", self.serverintf, self.bridge_name) @@ -420,14 +420,14 @@ class OvsCtrlNet(OvsNet): def shutdown(self): if self.serverintf: try: - subprocess.check_call([constants.OVS_BIN, "del-port", self.bridge_name, self.serverintf]) + utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, self.serverintf]) except subprocess.CalledProcessError: logger.exception("Error deleting server interface %s to controlnet bridge %s", self.serverintf, self.bridge_name) if self.updown_script: logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script) - subprocess.check_call([self.updown_script, self.bridge_name, "shutdown"]) + utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"]) OvsNet.shutdown(self) @@ -576,7 +576,7 @@ class OvsHubNode(OvsNet): if start: # TODO: verify that the below flow accomplishes what is desired for a "HUB" # TODO: replace "brctl setageing 0" - subprocess.check_call([constants.OVS_FLOW_BIN, "add-flow", self.bridge_name, "action=flood"]) + utils.check_cmd([constants.OVS_FLOW_BIN, "add-flow", self.bridge_name, "action=flood"]) class OvsWlanNode(OvsNet): diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index 00717fcc..0729d246 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -46,9 +46,9 @@ class VEth(PyCoreNetIf): :return: nothing """ - subprocess.check_call([constants.IP_BIN, "link", "add", "name", self.localname, - "type", "veth", "peer", "name", self.name]) - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "up"]) + utils.check_cmd([constants.IP_BIN, "link", "add", "name", self.localname, + "type", "veth", "peer", "name", self.name]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"]) self.up = True def shutdown(self): @@ -164,8 +164,8 @@ class TunTap(PyCoreNetIf): """ def localdevexists(): - cmd = (constants.IP_BIN, "link", "show", self.localname) - return utils.mutecall(cmd) + args = (constants.IP_BIN, "link", "show", self.localname) + return utils.mutecall(args) self.waitfor(localdevexists) @@ -177,8 +177,8 @@ class TunTap(PyCoreNetIf): """ def nodedevexists(): - cmd = [constants.IP_BIN, "link", "show", self.name] - return self.node.cmd(cmd) + args = [constants.IP_BIN, "link", "show", self.name] + return self.node.cmd(args) count = 0 while True: @@ -268,17 +268,17 @@ class GreTap(PyCoreNetIf): if remoteip is None: raise ValueError, "missing remote IP required for GRE TAP device" - cmd = ("ip", "link", "add", self.localname, "type", "gretap", + args = ("ip", "link", "add", self.localname, "type", "gretap", "remote", str(remoteip)) if localip: - cmd += ("local", str(localip)) + args += ("local", str(localip)) if ttl: - cmd += ("ttl", str(ttl)) + args += ("ttl", str(ttl)) if key: - cmd += ("key", str(key)) - subprocess.check_call(cmd) - cmd = ("ip", "link", "set", self.localname, "up") - subprocess.check_call(cmd) + args += ("key", str(key)) + utils.check_cmd(args) + args = ("ip", "link", "set", self.localname, "up") + utils.check_cmd(args) self.up = True def shutdown(self): @@ -288,10 +288,10 @@ class GreTap(PyCoreNetIf): :return: nothing """ if self.localname: - cmd = ("ip", "link", "set", self.localname, "down") - subprocess.check_call(cmd) - cmd = ("ip", "link", "del", self.localname) - subprocess.check_call(cmd) + args = ("ip", "link", "set", self.localname, "down") + utils.check_cmd(args) + args = ("ip", "link", "del", self.localname) + utils.check_cmd(args) self.localname = None def data(self, message_type): diff --git a/daemon/core/netns/vnet.py b/daemon/core/netns/vnet.py index d31df94c..bf2689d5 100644 --- a/daemon/core/netns/vnet.py +++ b/daemon/core/netns/vnet.py @@ -165,30 +165,30 @@ class EbtablesQueue(object): :return: nothing """ # save kernel ebtables snapshot to a file - cmd = self.ebatomiccmd(["--atomic-save", ]) + args = self.ebatomiccmd(["--atomic-save", ]) try: - subprocess.check_call(cmd) + utils.check_cmd(args) except subprocess.CalledProcessError: - logger.exception("atomic-save (%s)", cmd) + logger.exception("atomic-save (%s)", args) # no atomic file, exit return # modify the table file using queued ebtables commands for c in self.cmds: - cmd = self.ebatomiccmd(c) + args = self.ebatomiccmd(c) try: - subprocess.check_call(cmd) + utils.check_cmd(args) except subprocess.CalledProcessError: - logger.exception("cmd=%s", cmd) + logger.exception("cmd=%s", args) self.cmds = [] # commit the table file to the kernel - cmd = self.ebatomiccmd(["--atomic-commit", ]) + args = self.ebatomiccmd(["--atomic-commit", ]) try: - subprocess.check_call(cmd) + utils.check_cmd(args) os.unlink(self.atomic_file) except OSError: - logger.exception("atomic-commit (%s)", cmd) + logger.exception("atomic-commit (%s)", args) def ebchange(self, wlan): """ @@ -241,8 +241,8 @@ def ebtablescmds(call, cmds): :return: nothing """ with ebtables_lock: - for cmd in cmds: - call(cmd) + for args in cmds: + call(args) class LxBrNet(PyCoreNet): @@ -281,17 +281,17 @@ class LxBrNet(PyCoreNet): :return: nothing """ try: - subprocess.check_call([constants.BRCTL_BIN, "addbr", self.brname]) + utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname]) except subprocess.CalledProcessError: logger.exception("Error adding bridge") try: # turn off spanning tree protocol and forwarding delay - subprocess.check_call([constants.BRCTL_BIN, "stp", self.brname, "off"]) - subprocess.check_call([constants.BRCTL_BIN, "setfd", self.brname, "0"]) - subprocess.check_call([constants.IP_BIN, "link", "set", self.brname, "up"]) + utils.check_cmd([constants.BRCTL_BIN, "stp", self.brname, "off"]) + utils.check_cmd([constants.BRCTL_BIN, "setfd", self.brname, "0"]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "up"]) # create a new ebtables chain for this bridge - ebtablescmds(subprocess.check_call, [ + ebtablescmds(utils.check_cmd, [ [constants.EBTABLES_BIN, "-N", self.brname, "-P", self.policy], [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.brname, "-j", self.brname] ]) @@ -336,8 +336,8 @@ class LxBrNet(PyCoreNet): """ if self.up: try: - subprocess.check_call([constants.BRCTL_BIN, "addif", self.brname, netif.localname]) - subprocess.check_call([constants.IP_BIN, "link", "set", netif.localname, "up"]) + utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname]) + utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"]) except subprocess.CalledProcessError: logger.exception("Error joining interface %s to bridge %s", netif.localname, self.brname) return @@ -352,7 +352,7 @@ class LxBrNet(PyCoreNet): """ if self.up: try: - subprocess.check_call([constants.BRCTL_BIN, "delif", self.brname, netif.localname]) + utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname]) except subprocess.CalledProcessError: logger.exception("Error removing interface %s from bridge %s", netif.localname, self.brname) return @@ -452,14 +452,14 @@ class LxBrNet(PyCoreNet): if bw > 0: if self.up: logger.info("linkconfig: %s" % ([tc + parent + ["handle", "1:"] + tbf],)) - subprocess.check_call(tc + parent + ["handle", "1:"] + tbf) + utils.check_cmd(tc + parent + ["handle", "1:"] + tbf) netif.setparam("has_tbf", True) changed = True elif netif.getparam("has_tbf") and bw <= 0: tcd = [] + tc tcd[2] = "delete" if self.up: - subprocess.check_call(tcd + parent) + utils.check_cmd(tcd + parent) netif.setparam("has_tbf", False) # removing the parent removes the child netif.setparam("has_netem", False) @@ -497,12 +497,12 @@ class LxBrNet(PyCoreNet): tc[2] = "delete" if self.up: logger.info("linkconfig: %s" % ([tc + parent + ["handle", "10:"]],)) - subprocess.check_call(tc + parent + ["handle", "10:"]) + utils.check_cmd(tc + parent + ["handle", "10:"]) netif.setparam("has_netem", False) elif len(netem) > 1: if self.up: logger.info("linkconfig: %s" % ([tc + parent + ["handle", "10:"] + netem],)) - subprocess.check_call(tc + parent + ["handle", "10:"] + netem) + utils.check_cmd(tc + parent + ["handle", "10:"] + netem) netif.setparam("has_netem", True) def linknet(self, net): @@ -535,8 +535,8 @@ class LxBrNet(PyCoreNet): if net.up: # this is similar to net.attach() but uses netif.name instead # of localname - subprocess.check_call([constants.BRCTL_BIN, "addif", net.brname, netif.name]) - subprocess.check_call([constants.IP_BIN, "link", "set", netif.name, "up"]) + utils.check_cmd([constants.BRCTL_BIN, "addif", net.brname, netif.name]) + utils.check_cmd([constants.IP_BIN, "link", "set", netif.name, "up"]) i = net.newifindex() net._netif[i] = netif with net._linked_lock: @@ -570,7 +570,7 @@ class LxBrNet(PyCoreNet): return for addr in addrlist: try: - subprocess.check_call([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname]) + utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname]) except subprocess.CalledProcessError: logger.exception("Error adding IP address") diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 5cbc8467..74631c41 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -99,11 +99,7 @@ class SimpleLxcNode(PyCoreNode): env["NODE_NAME"] = str(self.name) try: - output = utils.check_alloutput(vnoded, env=env) - # p = subprocess.Popen(vnoded, stdout=subprocess.PIPE, env=env) - # stdout, _ = p.communicate() - # if p.returncode: - # raise IOError("vnoded command failed: %s" % vnoded) + _, output = utils.check_cmd(vnoded, env=env) self.pid = int(output) except subprocess.CalledProcessError: logger.exception("vnoded failed to create a namespace; check kernel support and user privileges") @@ -171,37 +167,37 @@ class SimpleLxcNode(PyCoreNode): """ pass - def cmd(self, cmd, wait=True): + def cmd(self, args, wait=True): """ Runs shell command on node, with option to not wait for a result. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :param bool wait: wait for command to exit, defaults to True :return: exit status for command :rtype: int """ - return self.client.cmd(cmd, wait) + return self.client.cmd(args, wait) - def cmd_output(self, cmd): + def cmd_output(self, args): """ Runs shell command on node and get exit status and output. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exit status and combined stdout and stderr :rtype: tuple[int, str] """ - return self.client.cmd_output(cmd) + return self.client.cmd_output(args) - def check_cmd(self, cmd): + def check_cmd(self, args): """ Runs shell command on node. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exist status and combined stdout and stderr :rtype: tuple[int, str] :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ - return self.client.check_cmd(cmd) + return self.client.check_cmd(args) def termcmdstring(self, sh="/bin/sh"): """ @@ -359,9 +355,9 @@ class SimpleLxcNode(PyCoreNode): """ self._netif[ifindex].sethwaddr(addr) if self.up: - cmd = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] + args = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] try: - self.check_cmd(cmd) + self.check_cmd(args) except subprocess.CalledProcessError: logger.exception("error setting MAC address %s: %s", addr) @@ -377,11 +373,11 @@ class SimpleLxcNode(PyCoreNode): try: # check if addr is ipv6 if ":" in str(addr): - cmd = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] - self.check_cmd(cmd) + args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] + self.check_cmd(args) else: - cmd = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] - self.check_cmd(cmd) + args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] + self.check_cmd(args) except subprocess.CalledProcessError: logger.exception("failure adding interface address") diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index e78f802c..42e124ff 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -61,41 +61,37 @@ class VnodeClient(object): """ self.cmdchnl.close() - def cmd(self, cmd, wait=True): + def cmd(self, args, wait=True): """ Execute a command on a node and return the status (return code). - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :param bool wait: wait for command to end or not :return: command status :rtype: int """ self._verify_connection() - cmd = utils.split_cmd(cmd) + args = utils.split_args(args) # run command, return process when not waiting - p = self.cmdchnl.qcmd(cmd) + p = self.cmdchnl.qcmd(args) if not wait: return 0 # wait for and return exit status - status = p.wait() - if status: - logger.warn("cmd exited with status %s: %s", status, cmd) + return p.wait() - return status - - def cmd_output(self, cmd): + def cmd_output(self, args): """ Execute a command on a node and return a tuple containing the exit status and result string. stderr output is folded into the stdout result string. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: command status and combined stdout and stderr output :rtype: tuple[int, str] """ - p, stdin, stdout, stderr = self.popen(cmd) + p, stdin, stdout, stderr = self.popen(args) stdin.close() output = stdout.read() + stderr.read() stdout.close() @@ -103,44 +99,44 @@ class VnodeClient(object): status = p.wait() return status, output.strip() - def check_cmd(self, cmd): + def check_cmd(self, args): """ Run command and return exit status and combined stdout and stderr. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exit status and combined stdout and stderr :rtype: tuple[int, str] :raises subprocess.CalledProcessError: when there is a non-zero exit status """ - status, output = self.cmd_output(cmd) + status, output = self.cmd_output(args) if status: - raise subprocess.CalledProcessError(status, cmd, output) + raise subprocess.CalledProcessError(status, args, output) return status, output.strip() - def popen(self, cmd): + def popen(self, args): """ Execute a popen command against the node. - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :return: popen object, stdin, stdout, and stderr :rtype: tuple """ self._verify_connection() - cmd = utils.split_cmd(cmd) - return self.cmdchnl.popen(cmd) + args = utils.split_args(args) + return self.cmdchnl.popen(args) - def icmd(self, cmd): + def icmd(self, args): """ Execute an icmd against a node. - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :return: command result :rtype: int """ - cmd = utils.split_cmd(cmd) - return os.spawnlp(os.P_WAIT, VCMD, VCMD, "-c", self.ctrlchnlname, "--", *cmd) + args = utils.split_args(args) + return os.spawnlp(os.P_WAIT, VCMD, VCMD, "-c", self.ctrlchnlname, "--", *args) - def redircmd(self, infd, outfd, errfd, cmd, wait=True): + def redircmd(self, infd, outfd, errfd, args, wait=True): """ Execute a command on a node with standard input, output, and error redirected according to the given file descriptors. @@ -148,7 +144,7 @@ class VnodeClient(object): :param infd: stdin file descriptor :param outfd: stdout file descriptor :param errfd: stderr file descriptor - :param list[str]/str cmd: command arguments + :param list[str]|str args: command arguments :param bool wait: wait flag :return: command status :rtype: int @@ -156,15 +152,15 @@ class VnodeClient(object): self._verify_connection() # run command, return process when not waiting - cmd = utils.split_cmd(cmd) - p = self.cmdchnl.redircmd(infd, outfd, errfd, cmd) + args = utils.split_args(args) + p = self.cmdchnl.redircmd(infd, outfd, errfd, args) if not wait: return p # wait for and return exit status status = p.wait() if status: - logger.warn("cmd exited with status %s: %s", status, cmd) + logger.warn("cmd exited with status %s: %s", status, args) return status def term(self, sh="/bin/sh"): @@ -175,12 +171,12 @@ class VnodeClient(object): :return: terminal command result :rtype: int """ - cmd = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh) + args = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh) if "SUDO_USER" in os.environ: - cmd = ("su", "-s", "/bin/sh", "-c", - "exec " + " ".join(map(lambda x: "'%s'" % x, cmd)), + args = ("su", "-s", "/bin/sh", "-c", + "exec " + " ".join(map(lambda x: "'%s'" % x, args)), os.environ["SUDO_USER"]) - return os.spawnvp(os.P_NOWAIT, cmd[0], cmd) + return os.spawnvp(os.P_NOWAIT, args[0], args) def termcmdstring(self, sh="/bin/sh"): """ @@ -226,8 +222,8 @@ class VnodeClient(object): return self._addr[ifname] interface = {"ether": [], "inet": [], "inet6": [], "inet6link": []} - cmd = [constants.IP_BIN, "addr", "show", "dev", ifname] - p, stdin, stdout, stderr = self.popen(cmd) + args = [constants.IP_BIN, "addr", "show", "dev", ifname] + p, stdin, stdout, stderr = self.popen(args) stdin.close() for line in stdout: @@ -249,7 +245,7 @@ class VnodeClient(object): stderr.close() status = p.wait() if status: - logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd) + logger.warn("nonzero exist status (%s) for cmd: %s", status, args) if err: logger.warn("error output: %s", err) self._addr[ifname] = interface @@ -264,8 +260,8 @@ class VnodeClient(object): :rtype: dict """ stats = {} - cmd = ["cat", "/proc/net/dev"] - p, stdin, stdout, stderr = self.popen(cmd) + args = ["cat", "/proc/net/dev"] + p, stdin, stdout, stderr = self.popen(args) stdin.close() # ignore first line stdout.readline() @@ -291,7 +287,7 @@ class VnodeClient(object): stderr.close() status = p.wait() if status: - logger.warn("nonzero exist status (%s) for cmd: %s", status, cmd) + logger.warn("nonzero exist status (%s) for cmd: %s", status, args) if err: logger.warn("error output: %s", err) if ifname is not None: diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index f9be028d..4287c100 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -55,34 +55,33 @@ class PhysicalNode(PyCoreNode): def termcmdstring(self, sh="/bin/sh"): """ - The broker will add the appropriate SSH command to open a terminal - on this physical node. + Create a terminal command string. + + :param str sh: shell to execute command in + :return: str """ return sh def cmd(self, args, wait=True): """ - run a command on the physical node + Runs shell command on node, with option to not wait for a result. + + :param list[str]|str args: command to run + :param bool wait: wait for command to exit, defaults to True + :return: exit status for command + :rtype: int """ os.chdir(self.nodedir) - status = -1 - - try: - if wait: - # os.spawnlp(os.P_WAIT, args) - status = subprocess.call(args) - else: - # os.spawnlp(os.P_NOWAIT, args) - subprocess.Popen(args) - status = 0 - except subprocess.CalledProcessError: - logger.exception("cmd exited with status: %s", args) - + status = utils.cmd(args, wait) return status def cmd_output(self, args): """ - run a command on the physical node and get the result + Runs shell command on node and get exit status and output. + + :param list[str]|str args: command to run + :return: exit status and combined stdout and stderr + :rtype: tuple[int, str] """ os.chdir(self.nodedir) # in Python 2.7 we can use subprocess.check_output() here @@ -92,18 +91,18 @@ class PhysicalNode(PyCoreNode): status = p.wait() return status, stdout.strip() - def check_cmd(self, cmd): + def check_cmd(self, args): """ Runs shell command on node. - :param list[str]/str cmd: command to run + :param list[str]|str args: command to run :return: exist status and combined stdout and stderr :rtype: tuple[int, str] :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ - status, output = self.cmd_output(cmd) + status, output = self.cmd_output(args) if status: - raise subprocess.CalledProcessError(status, cmd, output) + raise subprocess.CalledProcessError(status, args, output) return status, output.strip() def shcmd(self, cmdstr, sh="/bin/sh"): diff --git a/daemon/core/service.py b/daemon/core/service.py index fe37e95f..ca962e22 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -304,12 +304,12 @@ class CoreServices(ConfigurableManager): if use_startup_service and not self.is_startup_service(service): return - for cmd in service.getstartup(node, services): + for args in service.getstartup(node, services): try: # TODO: this wait=False can be problematic! - node.cmd(cmd, wait=False) + node.cmd(args, wait=False) except: - logger.exception("error starting command %s", cmd) + logger.exception("error starting command %s", args) def bootnodecustomservice(self, node, service, services, use_startup_service): """ @@ -350,12 +350,12 @@ class CoreServices(ConfigurableManager): if use_startup_service and not self.is_startup_service(service): return - for cmd in service._startup: + for args in service._startup: try: # TODO: this wait=False can be problematic! - node.cmd(cmd, wait=False) + node.cmd(args, wait=False) except: - logger.exception("error starting command %s", cmd) + logger.exception("error starting command %s", args) def copyservicefile(self, node, filename, cfg): """ @@ -409,10 +409,10 @@ class CoreServices(ConfigurableManager): status = 0 # has validate commands if len(validate_cmds) > 0: - for cmd in validate_cmds: - logger.info("validating service %s using: %s", service._name, cmd) + for args in validate_cmds: + logger.info("validating service %s using: %s", service._name, args) try: - status, _ = node.check_cmd(cmd) + status, _ = node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("validate command failed") status = -1 @@ -444,12 +444,12 @@ class CoreServices(ConfigurableManager): # doesn't have a shutdown command status += "0" else: - for cmd in service._shutdown: + for args in service._shutdown: try: - status, _ = node.check_cmd(cmd) + status, _ = node.check_cmd(args) status = str(status) except subprocess.CalledProcessError: - logger.exception("error running stop command %s", cmd) + logger.exception("error running stop command %s", args) # TODO: determine if its ok to just return the bad exit status status = "-1" return status @@ -757,12 +757,12 @@ class CoreServices(ConfigurableManager): else: cmds = s.getstartup(node, services) if len(cmds) > 0: - for cmd in cmds: + for args in cmds: try: - node.check_cmd(cmd) + node.check_cmd(args) except subprocess.CalledProcessError: - logger.exception("error starting command %s", cmd) - fail += "Start %s(%s)," % (s._name, cmd) + logger.exception("error starting command %s", args) + fail += "Start %s(%s)," % (s._name, args) if event_type == EventTypes.PAUSE.value: status = self.validatenodeservice(node, s, services) if status != 0: diff --git a/daemon/core/session.py b/daemon/core/session.py index cf57b07e..442464c9 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -429,11 +429,11 @@ class Session(object): # execute hook file try: - subprocess.check_call(["/bin/sh", file_name], stdin=open(os.devnull, 'r'), - stdout=stdout, stderr=stderr, close_fds=True, - cwd=self.session_dir, env=self.get_environment()) - except subprocess.CalledProcessError: - logger.exception("error running hook '%s'", file_name) + args = ["/bin/sh", file_name] + subprocess.check_call(args, stdout=stdout, stderr=stderr, + close_fds=True, cwd=self.session_dir, env=self.get_environment()) + except (OSError, subprocess.CalledProcessError): + logger.exception("error running hook: %s", file_name) def run_state_hooks(self, state): """ diff --git a/daemon/core/xml/xmldeployment.py b/daemon/core/xml/xmldeployment.py index a1b387ad..1c9fd4cf 100644 --- a/daemon/core/xml/xmldeployment.py +++ b/daemon/core/xml/xmldeployment.py @@ -1,12 +1,11 @@ import os import socket -import subprocess from core import constants from core import emane from core import logger from core.enumerations import NodeTypes -from core.misc import ipaddress +from core.misc import ipaddress, utils from core.misc import nodeutils from core.netns import nodes from core.xml import xmlutils @@ -26,8 +25,8 @@ class CoreDeploymentWriter(object): def get_ipv4_addresses(hostname): if hostname == 'localhost': addr_list = [] - cmd = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') - output = subprocess.check_output(cmd) + args = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') + _, output = utils.check_cmd(args) for line in output.split(os.linesep): split = line.split() if not split: @@ -48,8 +47,8 @@ class CoreDeploymentWriter(object): """ if hostname == 'localhost': iface_list = [] - cmd = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') - output = subprocess.check_output(cmd) + args = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') + _, output = utils.check_cmd(args) for line in output.split(os.linesep): split = line.split() if not split: From 00b3c974488569f6dc4c6d4984f853b1dc2c8a43 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 09:15:52 -0800 Subject: [PATCH 044/152] further removal and refactoring of methods used within misc/utils.py --- daemon/core/bsd/netgraph.py | 2 +- daemon/core/bsd/vnode.py | 2 +- daemon/core/corehandlers.py | 9 +- daemon/core/emane/emanemanager.py | 2 +- daemon/core/emane/emanemodel.py | 2 +- daemon/core/misc/quagga.py | 6 +- daemon/core/misc/utils.py | 326 +++++++--------------- daemon/core/netns/nodes.py | 4 +- daemon/core/netns/openvswitch.py | 23 +- daemon/core/netns/vif.py | 8 +- daemon/core/netns/vnet.py | 20 +- daemon/core/netns/vnode.py | 4 +- daemon/core/phys/pnodes.py | 2 +- daemon/core/service.py | 4 +- daemon/core/services/nrl.py | 2 +- daemon/core/services/utility.py | 2 +- daemon/core/session.py | 13 +- daemon/core/xen/xen.py | 20 +- daemon/examples/netns/ospfmanetmdrtest.py | 5 +- daemon/examples/netns/switchtest.py | 4 +- daemon/examples/netns/wlantest.py | 4 +- daemon/sbin/core-daemon | 6 +- ns3/corens3/obj.py | 4 +- 23 files changed, 181 insertions(+), 293 deletions(-) diff --git a/daemon/core/bsd/netgraph.py b/daemon/core/bsd/netgraph.py index c74a326b..59e47238 100644 --- a/daemon/core/bsd/netgraph.py +++ b/daemon/core/bsd/netgraph.py @@ -86,4 +86,4 @@ def ngloadkernelmodule(name): :param str name: module name :return: nothing """ - utils.mutecall(["kldload", name]) + utils.check_cmd(["kldload", name]) diff --git a/daemon/core/bsd/vnode.py b/daemon/core/bsd/vnode.py index 5e28eff8..f4846d1c 100644 --- a/daemon/core/bsd/vnode.py +++ b/daemon/core/bsd/vnode.py @@ -263,7 +263,7 @@ class SimpleJailNode(PyCoreNode): self.attachnet(ifindex, net) if hwaddr: self.sethwaddr(ifindex, hwaddr) - for addr in utils.maketuple(addrlist): + for addr in utils.make_tuple(addrlist): self.addaddr(ifindex, addr) self.ifup(ifindex) return ifindex diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index b0e4a11f..aa9b1775 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -93,7 +93,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): self.master = False self.session = None - utils.closeonexec(request.fileno()) + utils.close_onexec(request.fileno()) SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) def setup(self): @@ -371,7 +371,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): try: header = self.request.recv(coreapi.CoreMessage.header_len) if len(header) > 0: - logger.debug("received message header: %s", utils.hexdump(header)) + logger.debug("received message header: %s", utils.hex_dump(header)) except IOError as e: raise IOError("error receiving header (%s)" % e) @@ -388,7 +388,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): data = "" while len(data) < message_len: data += self.request.recv(message_len - len(data)) - logger.debug("received message data: %s" % utils.hexdump(data)) + logger.debug("received message data: %s" % utils.hex_dump(data)) if len(data) > message_len: error_message = "received message length does not match received data (%s != %s)" % ( len(data), message_len) @@ -1110,8 +1110,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # execute the command with no response else: if message.flags & MessageFlags.LOCAL.value: - # TODO: get this consolidated into utils - utils.mutedetach(shlex.split(command)) + utils.mute_detach(command) else: node.cmd(command, wait=False) except KeyError: diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 6ce75328..c5d6f7c5 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -182,7 +182,7 @@ class EmaneManager(ConfigurableManager): if self.service: for f in self.service._readFd, self.service._writeFd, self.service._socket, self.service._socketOTA: if f: - utils.closeonexec(f) + utils.close_onexec(f) if filename is not None: os.environ.pop(EmaneManager.EVENTCFGVAR) diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 642dd4f9..9efd54fb 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -190,7 +190,7 @@ class EmaneModel(WirelessModel): multiple values. """ try: - values = utils.maketuplefromstr(value, str) + values = utils.make_tuple_fromstr(value, str) except SyntaxError: logger.exception("error in value string to param list") return None diff --git a/daemon/core/misc/quagga.py b/daemon/core/misc/quagga.py index 99058312..9887277d 100644 --- a/daemon/core/misc/quagga.py +++ b/daemon/core/misc/quagga.py @@ -136,7 +136,7 @@ router ospf6 :param routerid: router id :param str redistribute: redistribute value """ - ospf6ifs = utils.maketuple(ospf6ifs) + ospf6ifs = utils.make_tuple(ospf6ifs) interfaces = "\n!\n".join(map(str, ospf6ifs)) ospfifs = "\n ".join(map(lambda x: "interface %s area %s" % (x.name(), area), ospf6ifs)) Conf.__init__(self, interfaces=interfaces, routerid=routerid, ospfifs=ospfifs, redistribute=redistribute) @@ -163,9 +163,9 @@ $forwarding :param str logfile: log file name :param debugs: debug options """ - routers = "\n!\n".join(map(str, utils.maketuple(routers))) + routers = "\n!\n".join(map(str, utils.make_tuple(routers))) if debugs: - debugs = "\n".join(utils.maketuple(debugs)) + debugs = "\n".join(utils.make_tuple(debugs)) else: debugs = "! no debugs" forwarding = "ip forwarding\nipv6 forwarding" diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index c80b4771..29e87f4c 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -17,7 +17,74 @@ from core import logger DEVNULL = open(os.devnull, "wb") -def closeonexec(fd): +def _detach_init(): + """ + Fork a child process and exit. + + :return: nothing + """ + if os.fork(): + # parent exits + os._exit(0) + os.setsid() + + +def _valid_module(path, file_name): + """ + Check if file is a valid python module. + + :param str path: path to file + :param str file_name: file name to check + :return: True if a valid python module file, False otherwise + :rtype: bool + """ + file_path = os.path.join(path, file_name) + if not os.path.isfile(file_path): + return False + + if file_name.startswith("_"): + return False + + if not file_name.endswith(".py"): + return False + + return True + + +def _is_class(module, member, clazz): + """ + Validates if a module member is a class and an instance of a CoreService. + + :param module: module to validate for service + :param member: member to validate for service + :param clazz: clazz type to check for validation + :return: True if a valid service, False otherwise + :rtype: bool + """ + if not inspect.isclass(member): + return False + + if not issubclass(member, clazz): + return False + + if member.__module__ != module.__name__: + return False + + return True + + +def _is_exe(file_path): + """ + Check if a given file path exists and is an executable file. + + :param str file_path: file path to check + :return: True if the file is considered and executable file, False otherwise + :rtype: bool + """ + return os.path.isfile(file_path) and os.access(file_path, os.X_OK) + + +def close_onexec(fd): """ Close on execution of a shell process. @@ -37,56 +104,11 @@ def check_executables(executables): :raises EnvironmentError: when an executable doesn't exist or is not executable """ for executable in executables: - if not is_exe(executable): + if not _is_exe(executable): raise EnvironmentError("executable not found: %s" % executable) -def is_exe(file_path): - """ - Check if a given file path exists and is an executable file. - - :param str file_path: file path to check - :return: True if the file is considered and executable file, False otherwise - :rtype: bool - """ - return os.path.isfile(file_path) and os.access(file_path, os.X_OK) - - -def which(program): - """ - From: http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python - - :param str program: program to check for - :return: path if it exists, none otherwise - """ - fpath, fname = os.path.split(program) - if fpath: - if is_exe(program): - return program - else: - for path in os.environ["PATH"].split(os.pathsep): - path = path.strip("\"") - exe_file = os.path.join(path, program) - if is_exe(exe_file): - return exe_file - - return None - - -def ensurepath(pathlist): - """ - Checks a list of paths are contained within the environment path, if not add it to the path. - - :param list[str] pathlist: list of paths to check - :return: nothing - """ - searchpath = os.environ["PATH"].split(":") - for p in set(pathlist): - if p not in searchpath: - os.environ["PATH"] += ":" + p - - -def maketuple(obj): +def make_tuple(obj): """ Create a tuple from an object, or return the object itself. @@ -100,7 +122,7 @@ def maketuple(obj): return obj, -def maketuplefromstr(s, value_type): +def make_tuple_fromstr(s, value_type): """ Create a tuple from a string. @@ -122,101 +144,22 @@ def split_args(args): :return: shell-like syntax list :rtype: list """ - # split shell string to shell array for convenience if type(args) == str: args = shlex.split(args) return args -def mutecall(*args, **kwargs): - """ - Run a muted call command. - - :param list args: arguments for the command - :param dict kwargs: keyword arguments for the command - :return: command result - :rtype: int - """ - kwargs["stdout"] = DEVNULL - kwargs["stderr"] = subprocess.STDOUT - return subprocess.call(*args, **kwargs) - - -def mutecheck_call(*args, **kwargs): - """ - Run a muted check call command. - - :param list args: arguments for the command - :param dict kwargs: keyword arguments for the command - :return: command result - :rtype: int - """ - kwargs["stdout"] = DEVNULL - kwargs["stderr"] = subprocess.STDOUT - return subprocess.check_call(*args, **kwargs) - - -def spawn(*args, **kwargs): - """ - Wrapper for running a spawn command and returning the process id. - - :param list args: arguments for the command - :param dict kwargs: keyword arguments for the command - :return: process id of the command - :rtype: int - """ - return subprocess.Popen(*args, **kwargs).pid - - -def mutespawn(*args, **kwargs): - """ - Wrapper for running a muted spawned command. - - :param list args: arguments for the command - :param dict kwargs: keyword arguments for the command - :return: process id of the command - :rtype: int - """ - kwargs["stdout"] = DEVNULL - kwargs["stderr"] = subprocess.STDOUT - return subprocess.Popen(*args, **kwargs).pid - - -def detachinit(): - """ - Fork a child process and exit. - - :return: nothing - """ - if os.fork(): - # parent exits - os._exit(0) - os.setsid() - - -def detach(*args, **kwargs): - """ - Run a detached process by forking it. - - :param list args: arguments for the command - :param dict kwargs: keyword arguments for the command - :return: process id of the command - :rtype: int - """ - kwargs["preexec_fn"] = detachinit - return subprocess.Popen(*args, **kwargs).pid - - -def mutedetach(*args, **kwargs): +def mute_detach(args, **kwargs): """ Run a muted detached process by forking it. - :param list args: arguments for the command + :param list[str]|str args: arguments for the command :param dict kwargs: keyword arguments for the command :return: process id of the command :rtype: int """ - kwargs["preexec_fn"] = detachinit + args = split_args(args) + kwargs["preexec_fn"] = _detach_init kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT return subprocess.Popen(*args, **kwargs).pid @@ -286,7 +229,7 @@ def check_cmd(args, **kwargs): raise subprocess.CalledProcessError(-1, args) -def hexdump(s, bytes_per_word=2, words_per_line=8): +def hex_dump(s, bytes_per_word=2, words_per_line=8): """ Hex dump of a string. @@ -297,10 +240,11 @@ def hexdump(s, bytes_per_word=2, words_per_line=8): """ dump = "" count = 0 - bytes = bytes_per_word * words_per_line + total_bytes = bytes_per_word * words_per_line + while s: - line = s[:bytes] - s = s[bytes:] + line = s[:total_bytes] + s = s[total_bytes:] tmp = map(lambda x: ("%02x" * bytes_per_word) % x, zip(*[iter(map(ord, line))] * bytes_per_word)) if len(line) % 2: @@ -310,7 +254,7 @@ def hexdump(s, bytes_per_word=2, words_per_line=8): return dump[:-1] -def filemunge(pathname, header, text): +def file_munge(pathname, header, text): """ Insert text at the end of a file, surrounded by header comments. @@ -320,15 +264,15 @@ def filemunge(pathname, header, text): :return: nothing """ # prevent duplicates - filedemunge(pathname, header) - f = open(pathname, "a") - f.write("# BEGIN %s\n" % header) - f.write(text) - f.write("# END %s\n" % header) - f.close() + file_demunge(pathname, header) + + with open(pathname, "a") as append_file: + append_file.write("# BEGIN %s\n" % header) + append_file.write(text) + append_file.write("# END %s\n" % header) -def filedemunge(pathname, header): +def file_demunge(pathname, header): """ Remove text that was inserted in a file surrounded by header comments. @@ -336,25 +280,27 @@ def filedemunge(pathname, header): :param str header: header text to target for removal :return: nothing """ - f = open(pathname, "r") - lines = f.readlines() - f.close() + with open(pathname, "r") as read_file: + lines = read_file.readlines() + start = None end = None + for i in range(len(lines)): if lines[i] == "# BEGIN %s\n" % header: start = i elif lines[i] == "# END %s\n" % header: end = i + 1 + if start is None or end is None: return - f = open(pathname, "w") - lines = lines[:start] + lines[end:] - f.write("".join(lines)) - f.close() + + with open(pathname, "w") as write_file: + lines = lines[:start] + lines[end:] + write_file.write("".join(lines)) -def expandcorepath(pathname, session=None, node=None): +def expand_corepath(pathname, session=None, node=None): """ Expand a file path given session information. @@ -369,13 +315,15 @@ def expandcorepath(pathname, session=None, node=None): pathname = pathname.replace("%SESSION%", str(session.session_id)) pathname = pathname.replace("%SESSION_DIR%", session.session_dir) pathname = pathname.replace("%SESSION_USER%", session.user) + if node is not None: pathname = pathname.replace("%NODE%", str(node.objid)) pathname = pathname.replace("%NODENAME%", node.name) + return pathname -def sysctldevname(devname): +def sysctl_devname(devname): """ Translate a device name to the name used with sysctl. @@ -477,7 +425,7 @@ def daemonize(rootdir="/", umask=0, close_fds=False, dontclose=(), logger.exception("error closing file descriptor") -def readfileintodict(filename, d): +def load_config(filename, d): """ Read key=value pairs from a file, into a dict. Skip comments; strip newline characters and spacing. @@ -487,78 +435,18 @@ def readfileintodict(filename, d): """ with open(filename, "r") as f: lines = f.readlines() - for l in lines: - if l[:1] == "#": + + for line in lines: + if line[:1] == "#": continue + try: - key, value = l.split("=", 1) + key, value = line.split("=", 1) d[key] = value.strip() except ValueError: logger.exception("error reading file to dict: %s", filename) -def checkforkernelmodule(name): - """ - Return a string if a Linux kernel module is loaded, None otherwise. - The string is the line from /proc/modules containing the module name, - memory size (bytes), number of loaded instances, dependencies, state, - and kernel memory offset. - - :param str name: name of kernel module to check for - :return: kernel module line, None otherwise - :rtype: str - """ - with open("/proc/modules", "r") as f: - for line in f: - if line.startswith(name + " "): - return line.rstrip() - return None - - -def _valid_module(path, file_name): - """ - Check if file is a valid python module. - - :param str path: path to file - :param str file_name: file name to check - :return: True if a valid python module file, False otherwise - :rtype: bool - """ - file_path = os.path.join(path, file_name) - if not os.path.isfile(file_path): - return False - - if file_name.startswith("_"): - return False - - if not file_name.endswith(".py"): - return False - - return True - - -def _is_class(module, member, clazz): - """ - Validates if a module member is a class and an instance of a CoreService. - - :param module: module to validate for service - :param member: member to validate for service - :param clazz: clazz type to check for validation - :return: True if a valid service, False otherwise - :rtype: bool - """ - if not inspect.isclass(member): - return False - - if not issubclass(member, clazz): - return False - - if member.__module__ != module.__name__: - return False - - return True - - def load_classes(path, clazz): """ Dynamically load classes for use within CORE. diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index 804a3376..d638577b 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -487,7 +487,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): try: utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"]) utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname]) - utils.mutecall([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"]) + utils.check_cmd([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"]) except subprocess.CalledProcessError as e: logger.exception("error shutting down: %s", e.output) @@ -541,7 +541,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): self.attachnet(net) if addrlist: - for addr in utils.maketuple(addrlist): + for addr in utils.make_tuple(addrlist): self.addaddr(addr) return ifindex diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index 3698f296..dcf9e73e 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -36,12 +36,9 @@ utils.check_executables([ def ebtables_commands(call, commands): - ebtables_lock.acquire() - try: + with ebtables_lock: for command in commands: call(command) - finally: - ebtables_lock.release() class OvsNet(PyCoreNet): @@ -109,16 +106,18 @@ class OvsNet(PyCoreNet): ebtables_queue.stopupdateloop(self) - utils.mutecall([constants.IP_BIN, "link", "set", self.bridge_name, "down"]) - utils.mutecall([constants.OVS_BIN, "del-br", self.bridge_name]) - - ebtables_commands(utils.mutecall, [ - [constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name], - [constants.EBTABLES_BIN, "-X", self.bridge_name] - ]) + try: + utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "down"]) + utils.check_cmd([constants.OVS_BIN, "del-br", self.bridge_name]) + ebtables_commands(utils.check_cmd, [ + [constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name], + [constants.EBTABLES_BIN, "-X", self.bridge_name] + ]) + except subprocess.CalledProcessError as e: + logger.exception("error bringing bridge down and removing it: %s", e.output) + # removes veth pairs used for bridge-to-bridge connections for interface in self.netifs(): - # removes veth pairs used for bridge-to-bridge connections interface.shutdown() self._netif.clear() diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index 0729d246..d6d97e97 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -67,7 +67,7 @@ class VEth(PyCoreNetIf): logger.exception("error shutting down interface") if self.localname: - utils.mutedetach([constants.IP_BIN, "link", "delete", self.localname]) + utils.mute_detach([constants.IP_BIN, "link", "delete", self.localname]) self.up = False @@ -164,8 +164,8 @@ class TunTap(PyCoreNetIf): """ def localdevexists(): - args = (constants.IP_BIN, "link", "show", self.localname) - return utils.mutecall(args) + args = [constants.IP_BIN, "link", "show", self.localname] + return utils.cmd(args) self.waitfor(localdevexists) @@ -269,7 +269,7 @@ class GreTap(PyCoreNetIf): if remoteip is None: raise ValueError, "missing remote IP required for GRE TAP device" args = ("ip", "link", "add", self.localname, "type", "gretap", - "remote", str(remoteip)) + "remote", str(remoteip)) if localip: args += ("local", str(localip)) if ttl: diff --git a/daemon/core/netns/vnet.py b/daemon/core/netns/vnet.py index bf2689d5..62f8fd2b 100644 --- a/daemon/core/netns/vnet.py +++ b/daemon/core/netns/vnet.py @@ -313,15 +313,21 @@ class LxBrNet(PyCoreNet): if not self.up: return ebq.stopupdateloop(self) - utils.mutecall([constants.IP_BIN, "link", "set", self.brname, "down"]) - utils.mutecall([constants.BRCTL_BIN, "delbr", self.brname]) - ebtablescmds(utils.mutecall, [ - [constants.EBTABLES_BIN, "-D", "FORWARD", - "--logical-in", self.brname, "-j", self.brname], - [constants.EBTABLES_BIN, "-X", self.brname]]) + + try: + utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "down"]) + utils.check_cmd([constants.BRCTL_BIN, "delbr", self.brname]) + ebtablescmds(utils.check_cmd, [ + [constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.brname, "-j", self.brname], + [constants.EBTABLES_BIN, "-X", self.brname] + ]) + except subprocess.CalledProcessError as e: + logger.exception("error during shutdown: %s", e.output) + + # removes veth pairs used for bridge-to-bridge connections for netif in self.netifs(): - # removes veth pairs used for bridge-to-bridge connections netif.shutdown() + self._netif.clear() self._linked.clear() del self.session diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 74631c41..5b0ccf21 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -461,7 +461,7 @@ class SimpleLxcNode(PyCoreNode): self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for address in utils.maketuple(addrlist): + for address in utils.make_tuple(addrlist): netif.addaddr(address) return ifindex else: @@ -473,7 +473,7 @@ class SimpleLxcNode(PyCoreNode): if hwaddr: self.sethwaddr(ifindex, hwaddr) - for address in utils.maketuple(addrlist): + for address in utils.make_tuple(addrlist): self.addaddr(ifindex, address) self.ifup(ifindex) diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 4287c100..548cb670 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -158,7 +158,7 @@ class PhysicalNode(PyCoreNode): netif.localname = netif.name if hwaddr: self.sethwaddr(ifindex, hwaddr) - for addr in utils.maketuple(addrlist): + for addr in utils.make_tuple(addrlist): self.addaddr(ifindex, addr) if self.up: self.cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"]) diff --git a/daemon/core/service.py b/daemon/core/service.py index ca962e22..71aa8997 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -372,7 +372,7 @@ class CoreServices(ConfigurableManager): if cfg[:7] == 'file://': src = cfg[7:] src = src.split('\n')[0] - src = utils.expandcorepath(src, node.session, node) + src = utils.expand_corepath(src, node.session, node) # TODO: glob here node.nodefilecopy(filename, src, mode=0644) return True @@ -968,7 +968,7 @@ class CoreService(object): elif key == "meta": value = str(value) else: - value = utils.maketuplefromstr(value, str) + value = utils.make_tuple_fromstr(value, str) if key == "dirs": self._dirs = value diff --git a/daemon/core/services/nrl.py b/daemon/core/services/nrl.py index a6a416ea..a506f2d0 100644 --- a/daemon/core/services/nrl.py +++ b/daemon/core/services/nrl.py @@ -57,7 +57,7 @@ class MgenSinkService(NrlService): def generateconfig(cls, node, filename, services): cfg = "0.0 LISTEN UDP 5000\n" for ifc in node.netifs(): - name = utils.sysctldevname(ifc.name) + name = utils.sysctl_devname(ifc.name) cfg += "0.0 Join 224.225.1.2 INTERFACE %s\n" % name return cfg diff --git a/daemon/core/services/utility.py b/daemon/core/services/utility.py index 534fc752..87289639 100644 --- a/daemon/core/services/utility.py +++ b/daemon/core/services/utility.py @@ -60,7 +60,7 @@ class IPForwardService(UtilService): %(sysctl)s -w net.ipv4.conf.default.rp_filter=0 """ % {'sysctl': constants.SYSCTL_BIN} for ifc in node.netifs(): - name = utils.sysctldevname(ifc.name) + name = utils.sysctl_devname(ifc.name) cfg += "%s -w net.ipv4.conf.%s.forwarding=1\n" % (constants.SYSCTL_BIN, name) cfg += "%s -w net.ipv4.conf.%s.send_redirects=0\n" % \ (constants.SYSCTL_BIN, name) diff --git a/daemon/core/session.py b/daemon/core/session.py index 442464c9..1c156599 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -7,7 +7,6 @@ import atexit import os import pprint import random -import shlex import shutil import subprocess import tempfile @@ -520,7 +519,7 @@ class Session(object): environment_config_file = os.path.join(constants.CORE_CONF_DIR, "environment") try: if os.path.isfile(environment_config_file): - utils.readfileintodict(environment_config_file, env) + utils.load_config(environment_config_file, env) except IOError: logger.warn("environment configuration file does not exist: %s", environment_config_file) @@ -528,7 +527,7 @@ class Session(object): if self.user: environment_user_file = os.path.join("/home", self.user, ".core", "environment") try: - utils.readfileintodict(environment_user_file, env) + utils.load_config(environment_user_file, env) except IOError: logger.warn("error reading user core environment settings file: %s", environment_user_file) @@ -1189,7 +1188,7 @@ class Session(object): header = "CORE session %s host entries" % self.session_id if remove: logger.info("Removing /etc/hosts file entries.") - utils.filedemunge("/etc/hosts", header) + utils.file_demunge("/etc/hosts", header) return entries = [] @@ -1200,7 +1199,7 @@ class Session(object): logger.info("Adding %d /etc/hosts file entries." % len(entries)) - utils.filemunge("/etc/hosts", header, "\n".join(entries) + "\n") + utils.file_munge("/etc/hosts", header, "\n".join(entries) + "\n") def runtime(self): """ @@ -1254,9 +1253,7 @@ class Session(object): logger.info("running event %s at time %s cmd=%s" % (name, now, data)) if not node_id: - # TODO: look to consolidate shlex to utils - commands = shlex.split(data) - utils.mutedetach(commands) + utils.mute_detach(data) else: node = self.get_object(node_id) node.cmd(data, wait=False) diff --git a/daemon/core/xen/xen.py b/daemon/core/xen/xen.py index 74909f51..1cdbf6f0 100644 --- a/daemon/core/xen/xen.py +++ b/daemon/core/xen/xen.py @@ -237,7 +237,7 @@ class XenNode(PyCoreNode): # unpause VM logger.warn("XEN PVM boot() unpause domU %s", self.vmname) - utils.mutecheck_call([XM_PATH, "unpause", self.vmname]) + utils.check_cmd([XM_PATH, "unpause", self.vmname]) self.booted = True finally: @@ -261,7 +261,7 @@ class XenNode(PyCoreNode): try: # RJE XXX what to do here if self.booted: - utils.mutecheck_call([XM_PATH, "destroy", self.vmname]) + utils.check_cmd([XM_PATH, "destroy", self.vmname]) self.booted = False except (OSError, subprocess.CalledProcessError): # ignore this error too, the VM may have exited already @@ -272,9 +272,9 @@ class XenNode(PyCoreNode): while os.path.exists(self.lvpath): try: subprocess.check_call([UDEVADM_PATH, "settle"]) - utils.mutecall([LVCHANGE_PATH, "-an", self.lvpath]) + utils.check_cmd([LVCHANGE_PATH, "-an", self.lvpath]) lvm_remove_count += 1 - utils.mutecall([LVREMOVE_PATH, "-f", self.lvpath]) + utils.check_cmd([LVREMOVE_PATH, "-f", self.lvpath]) except OSError: logger.exception("error during shutdown") @@ -296,8 +296,8 @@ class XenNode(PyCoreNode): """ if os.path.exists(self.lvpath): raise Exception, "LVM volume already exists" - utils.mutecheck_call([LVCREATE_PATH, "--size", self.disksize, - "--name", self.lvname, self.vgname]) + utils.check_cmd([LVCREATE_PATH, "--size", self.disksize, + "--name", self.lvname, self.vgname]) def createpartitions(self): """ @@ -337,8 +337,8 @@ class XenNode(PyCoreNode): persistdev = "/dev/mapper/" + lines[0].strip().split(" ")[0].strip() swapdev = "/dev/mapper/" + lines[1].strip().split(" ")[0].strip() subprocess.check_call([KPARTX_PATH, "-a", self.lvpath]) - utils.mutecheck_call([MKFSEXT4_PATH, "-L", "persist", persistdev]) - utils.mutecheck_call([MKSWAP_PATH, "-f", "-L", "swap", swapdev]) + utils.check_cmd([MKFSEXT4_PATH, "-L", "persist", persistdev]) + utils.check_cmd([MKSWAP_PATH, "-f", "-L", "swap", swapdev]) return persistdev def untarpersistent(self, tarname, iso): @@ -431,7 +431,7 @@ class XenNode(PyCoreNode): for action in ("poweroff", "reboot", "suspend", "crash", "halt"): args.append("on_%s=destroy" % action) args.append("extra=" + self.getconfigitem("xm_create_extra")) - utils.mutecheck_call(args) + utils.check_cmd(args) # from class LxcNode def privatedir(self, path): @@ -710,7 +710,7 @@ class XenNode(PyCoreNode): if hwaddr: self.sethwaddr(ifindex, hwaddr) - for addr in utils.maketuple(addrlist): + for addr in utils.make_tuple(addrlist): self.addaddr(ifindex, addr) # self.ifup(ifindex) return ifindex diff --git a/daemon/examples/netns/ospfmanetmdrtest.py b/daemon/examples/netns/ospfmanetmdrtest.py index 727f9436..7c55fe81 100755 --- a/daemon/examples/netns/ospfmanetmdrtest.py +++ b/daemon/examples/netns/ospfmanetmdrtest.py @@ -18,7 +18,7 @@ from string import Template from core.constants import QUAGGA_STATE_DIR from core.misc import ipaddress -from core.misc.utils import mutecall +from core.misc.utils import check_cmd from core.netns import nodes # this is the /etc/core/core.conf default @@ -33,8 +33,7 @@ try: if os.path.exists(os.path.join(p, "zebra")): quagga_path = p break - mutecall([os.path.join(quagga_path, "zebra"), - "-u", "root", "-g", "root", "-v"]) + check_cmd([os.path.join(quagga_path, "zebra"), "-u", "root", "-g", "root", "-v"]) except OSError: sys.stderr.write("ERROR: running zebra failed\n") sys.exit(1) diff --git a/daemon/examples/netns/switchtest.py b/daemon/examples/netns/switchtest.py index 6b1e953d..f31a1fc6 100755 --- a/daemon/examples/netns/switchtest.py +++ b/daemon/examples/netns/switchtest.py @@ -13,12 +13,12 @@ import optparse import sys from core.misc import ipaddress -from core.misc.utils import mutecall +from core.misc.utils import check_cmd from core.netns import nodes from core.session import Session try: - mutecall(["iperf", "-v"]) + check_cmd(["iperf", "-v"]) except OSError: sys.stderr.write("ERROR: running iperf failed\n") sys.exit(1) diff --git a/daemon/examples/netns/wlantest.py b/daemon/examples/netns/wlantest.py index da2a813d..1679c81c 100755 --- a/daemon/examples/netns/wlantest.py +++ b/daemon/examples/netns/wlantest.py @@ -13,12 +13,12 @@ import optparse import sys from core.misc import ipaddress -from core.misc.utils import mutecall +from core.misc.utils import check_cmd from core.netns import nodes from core.session import Session try: - mutecall(["iperf", "-v"]) + check_cmd(["iperf", "-v"]) except OSError: sys.stderr.write("ERROR: running iperf failed\n") sys.exit(1) diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index 9469d6e1..d8e0a6e0 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -35,7 +35,7 @@ from core.corehandlers import CoreDatagramRequestHandler from core.enumerations import MessageFlags from core.enumerations import RegisterTlvs from core.misc import nodeutils -from core.misc.utils import closeonexec +from core.misc.utils import close_onexec from core.misc.utils import daemonize from core.service import ServiceManager @@ -84,11 +84,11 @@ def cored(cfg=None): logger.exception("error starting main server on: %s:%s", host, port) sys.exit(1) - closeonexec(server.fileno()) + close_onexec(server.fileno()) logger.info("main server started, listening on: %s:%s\n" % (host, port)) udpserver = startudp(server, (host, port)) - closeonexec(udpserver.fileno()) + close_onexec(udpserver.fileno()) server.serve_forever() diff --git a/ns3/corens3/obj.py b/ns3/corens3/obj.py index 0d392a4b..e076e8f4 100644 --- a/ns3/corens3/obj.py +++ b/ns3/corens3/obj.py @@ -21,7 +21,7 @@ from core.coreobj import PyCoreNet from core.enumerations import EventTypes from core.enumerations import LinkTypes from core.enumerations import NodeTypes -from core.misc.utils import maketuple +from core.misc.utils import make_tuple from core.mobility import WayPointMobility from core.netns.nodes import CoreNode from core.session import Session @@ -65,7 +65,7 @@ class CoreNs3Node(CoreNode, ns.network.Node): self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) - for addr in maketuple(addrlist): + for addr in make_tuple(addrlist): netif.addaddr(addr) addrstr = netif.addrlist[0] From 513bb7e2637c6a081108f8f11ef95de3675b5599 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 09:20:50 -0800 Subject: [PATCH 045/152] fixed issue with refactored mute_detach --- daemon/core/misc/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 29e87f4c..41a92add 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -162,7 +162,7 @@ def mute_detach(args, **kwargs): kwargs["preexec_fn"] = _detach_init kwargs["stdout"] = DEVNULL kwargs["stderr"] = subprocess.STDOUT - return subprocess.Popen(*args, **kwargs).pid + return subprocess.Popen(args, **kwargs).pid def cmd(args, wait=True): From cd77875e643ef9c66c5a027162fcbaa166162399 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 09:36:29 -0800 Subject: [PATCH 046/152] switched pnodes to check commands ran for configuration --- daemon/core/phys/pnodes.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 548cb670..2c781f7a 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -125,7 +125,7 @@ class PhysicalNode(PyCoreNode): same as SimpleLxcNode.addaddr() """ if self.up: - self.cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]) + self.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)]) self._netif[ifindex].addaddr(addr) @@ -139,7 +139,7 @@ class PhysicalNode(PyCoreNode): logger.exception("trying to delete unknown address: %s", addr) if self.up: - self.cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) + self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) def adoptnetif(self, netif, ifindex, hwaddr, addrlist): """ @@ -151,17 +151,22 @@ class PhysicalNode(PyCoreNode): netif.name = "gt%d" % ifindex netif.node = self self.addnetif(netif, ifindex) + # use a more reasonable name, e.g. "gt0" instead of "gt.56286.150" if self.up: - self.cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "down"]) - self.cmd([constants.IP_BIN, "link", "set", netif.localname, "name", netif.name]) + self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "down"]) + self.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "name", netif.name]) + netif.localname = netif.name + if hwaddr: self.sethwaddr(ifindex, hwaddr) + for addr in utils.make_tuple(addrlist): self.addaddr(ifindex, addr) + if self.up: - self.cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"]) + self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"]) def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): @@ -230,19 +235,19 @@ class PhysicalNode(PyCoreNode): try: os.makedirs(target) - self.cmd([constants.MOUNT_BIN, "--bind", source, target]) + self.check_cmd([constants.MOUNT_BIN, "--bind", source, target]) self._mounts.append((source, target)) except OSError: logger.exception("error making directories") - except: - logger.exception("mounting failed for %s at %s", source, target) + except subprocess.CalledProcessError as e: + logger.exception("mounting failed for %s at %s: %s", source, target, e.output) def umount(self, target): logger.info("unmounting '%s'" % target) try: - self.cmd([constants.UMOUNT_BIN, "-l", target]) - except: - logger.exception("unmounting failed for %s", target) + self.check_cmd([constants.UMOUNT_BIN, "-l", target]) + except subprocess.CalledProcessError as e: + logger.exception("unmounting failed for %s: %s", target, e.output) def opennodefile(self, filename, mode="w"): dirname, basename = os.path.split(filename) From a3356127d2e48ce0e603576b21fe5a83a27ae4f9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 09:47:28 -0800 Subject: [PATCH 047/152] removed deprecated sonarqube setting to try and leverage new branch settings --- sonar-project.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonar-project.properties b/sonar-project.properties index 32fbdb4b..13f1d64e 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,5 +1,6 @@ # branch name for the sonar analysis -sonar.branch=origin/master +sonar.branch.name=5.1_shell_cleanup +sonar.branch.target=master # required metadata sonar.projectKey=CORE From 43554cbb62b80c1c8e7ad1dad35bbebabc838d67 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 13:39:44 -0800 Subject: [PATCH 048/152] initial effort to remove swallowing exceptions within internal code --- daemon/core/coreobj.py | 30 ++++- daemon/core/emane/__init__.py | 43 +++--- daemon/core/emane/emanemanager.py | 10 +- daemon/core/misc/utils.py | 6 +- daemon/core/netns/nodes.py | 197 +++++++++++++++++---------- daemon/core/netns/openvswitch.py | 85 +++++------- daemon/core/netns/vif.py | 90 +++++++------ daemon/core/netns/vnet.py | 215 ++++++++++++++---------------- daemon/core/netns/vnode.py | 140 ++++++++----------- daemon/core/netns/vnodeclient.py | 6 +- 10 files changed, 423 insertions(+), 399 deletions(-) diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 6af238b8..76ebc1c8 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -37,9 +37,9 @@ class Position(object): """ Returns True if the position has actually changed. - :param x: x position - :param y: y position - :param z: z position + :param float x: x position + :param float y: y position + :param float z: z position :return: True if position changed, False otherwise :rtype: bool """ @@ -113,9 +113,9 @@ class PyCoreObj(object): """ Set the (x,y,z) position of the object. - :param x: x position - :param y: y position - :param z: z position + :param float x: x position + :param float y: y position + :param float z: z position :return: True if position changed, False otherwise :rtype: bool """ @@ -460,6 +460,22 @@ class PyCoreNet(PyCoreObj): """ linktype = LinkTypes.WIRED.value + def startup(self): + """ + Each object implements its own startup method. + + :return: nothing + """ + raise NotImplementedError + + def shutdown(self): + """ + Each object implements its own shutdown method. + + :return: nothing + """ + raise NotImplementedError + def __init__(self, session, objid, name, start=True): """ Create a PyCoreNet instance. @@ -597,7 +613,7 @@ class PyCoreNetIf(object): """ Creates a PyCoreNetIf instance. - :param core.netns.vnode.SimpleLxcNode node: node for interface + :param core.coreobj.PyCoreNode node: node for interface :param str name: interface name :param mtu: mtu value """ diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index fff93664..8fa9557a 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -21,31 +21,30 @@ def emane_version(): """ global VERSION global VERSIONSTR - args = ("emane", "--version") - - try: - status, result = utils.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("error checking emane version") - status = -1 - result = "" + args = ["emane", "--version"] VERSION = EMANEUNK - if status == 0: - if result.startswith("0.7.4"): - VERSION = EMANE074 - elif result.startswith("0.8.1"): - VERSION = EMANE081 - elif result.startswith("0.9.1"): - VERSION = EMANE091 - elif result.startswith("0.9.2"): - VERSION = EMANE092 - elif result.startswith("0.9.3"): - VERSION = EMANE093 - elif result.startswith("1.0.1"): - VERSION = EMANE101 - VERSIONSTR = result.strip() + try: + status, output = utils.check_cmd(args) + if status == 0: + if output.startswith("0.7.4"): + VERSION = EMANE074 + elif output.startswith("0.8.1"): + VERSION = EMANE081 + elif output.startswith("0.9.1"): + VERSION = EMANE091 + elif output.startswith("0.9.2"): + VERSION = EMANE092 + elif output.startswith("0.9.3"): + VERSION = EMANE093 + elif output.startswith("1.0.1"): + VERSION = EMANE101 + except subprocess.CalledProcessError: + logger.exception("error checking emane version") + output = "" + + VERSIONSTR = output.strip() # set version variables for the Emane class diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index c5d6f7c5..424b19ab 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -925,7 +925,8 @@ class EmaneManager(ConfigurableManager): logger.exception("error adding route for event data") try: - args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] + args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), + os.path.join(path, "platform%d.xml" % n)] logger.info("Emane.startdaemons2() running %s" % str(args)) status, output = node.check_cmd(args) logger.info("Emane.startdaemons2() return code %d" % status) @@ -1163,14 +1164,15 @@ class EmaneManager(ConfigurableManager): Return True if an EMANE process associated with the given node is running, False otherwise. """ - status = -1 args = ["pkill", "-0", "-x", "emane"] + status = -1 try: if emane.VERSION < emane.EMANE092: - status = utils.check_cmd(args) + utils.check_cmd(args) else: - status, _ = node.check_cmd(args) + node.check_cmd(args) + status = 0 except subprocess.CalledProcessError: logger.exception("error checking if emane is running") diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 41a92add..ad907391 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -199,7 +199,7 @@ def cmd_output(args): p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate() status = p.wait() - return status, stdout + return status, stdout.strip() except OSError: raise subprocess.CalledProcessError(-1, args) @@ -222,9 +222,9 @@ def check_cmd(args, **kwargs): p = subprocess.Popen(args, **kwargs) stdout, _ = p.communicate() status = p.wait() - if status: + if status != 0: raise subprocess.CalledProcessError(status, args, stdout) - return status, stdout + return status, stdout.strip() except OSError: raise subprocess.CalledProcessError(-1, args) diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index d638577b..1757bc1c 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -68,6 +68,7 @@ class CtrlNet(LxBrNet): Startup functionality for the control network. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ if self.detectoldbridge(): return @@ -79,26 +80,23 @@ class CtrlNet(LxBrNet): else: addr = self.prefix.max_addr() - msg = "Added control network bridge: %s %s" % (self.brname, self.prefix) - addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)] + logger.info("added control network bridge: %s %s", self.brname, self.prefix) if self.assign_address: + addrlist = ["%s/%s" % (addr, self.prefix.prefixlen)] self.addrconfig(addrlist=addrlist) - msg += " address %s" % addr - logger.info(msg) + logger.info("address %s", addr) - if self.updown_script is not None: - logger.info("interface %s updown script (%s startup) called", - self.brname, self.updown_script) + if self.updown_script: + logger.info("interface %s updown script (%s startup) called", self.brname, self.updown_script) utils.check_cmd([self.updown_script, self.brname, "startup"]) - if self.serverintf is not None: - try: - utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf]) - utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) - except subprocess.CalledProcessError: - logger.exception("error joining server interface %s to controlnet bridge %s", - self.serverintf, self.brname) + if self.serverintf: + # sets the interface as a port of the bridge + utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, self.serverintf]) + + # bring interface up + utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) def detectoldbridge(self): """ @@ -120,10 +118,9 @@ class CtrlNet(LxBrNet): if len(flds) == 3: if flds[0] == "b" and flds[1] == self.objid: logger.error( - "Error: An active control net bridge (%s) found. " + "error: An active control net bridge (%s) found. " "An older session might still be running. " - "Stop all sessions and, if needed, delete %s to continue." % - (oldbr, oldbr) + "Stop all sessions and, if needed, delete %s to continue.", oldbr, oldbr ) return True return False @@ -137,20 +134,26 @@ class CtrlNet(LxBrNet): if self.serverintf is not None: try: utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf]) - except subprocess.CalledProcessError: - logger.exception("error deleting server interface %s to controlnet bridge %s", - self.serverintf, self.brname) + except subprocess.CalledProcessError as e: + logger.exception("error deleting server interface %s from bridge %s: %s", + self.serverintf, self.brname, e.output) if self.updown_script is not None: - logger.info("interface %s updown script (%s shutdown) called" % (self.brname, self.updown_script)) - utils.check_cmd([self.updown_script, self.brname, "shutdown"]) + try: + logger.info("interface %s updown script (%s shutdown) called", self.brname, self.updown_script) + utils.check_cmd([self.updown_script, self.brname, "shutdown"]) + except subprocess.CalledProcessError as e: + logger.exception("error issuing shutdown script shutdown: %s", e.output) + LxBrNet.shutdown(self) def all_link_data(self, flags): """ Do not include CtrlNet in link messages describing this session. - :return: nothing + :param flags: message flags + :return: list of link data + :rtype: list[core.data.LinkData] """ return [] @@ -172,29 +175,36 @@ class PtpNet(LxBrNet): """ Attach a network interface, but limit attachment to two interfaces. - :param core.coreobj.PyCoreNetIf netif: network interface + :param core.netns.vif.VEth netif: network interface :return: nothing """ if len(self._netif) >= 2: raise ValueError("Point-to-point links support at most 2 network interfaces") + LxBrNet.attach(self, netif) - def data(self, message_type): + def data(self, message_type, lat=None, lon=None, alt=None): """ Do not generate a Node Message for point-to-point links. They are built using a link message instead. - :return: nothing + :param message_type: purpose for the data object we are creating + :param float lat: latitude + :param float lon: longitude + :param float alt: altitude + :return: node data object + :rtype: core.data.NodeData """ - pass + return None def all_link_data(self, flags): """ Build CORE API TLVs for a point-to-point link. One Link message describes this network. - :return: all link data - :rtype: list[LinkData] + :param flags: message flags + :return: list of link data + :rtype: list[core.data.LinkData] """ all_links = [] @@ -318,8 +328,11 @@ class HubNode(LxBrNet): :param int objid: node id :param str name: node namee :param bool start: start flag + :raises subprocess.CalledProcessError: when there is a command exception """ LxBrNet.__init__(self, session, objid, name, start) + + # TODO: move to startup method if start: utils.check_cmd([constants.BRCTL_BIN, "setageing", self.brname, "0"]) @@ -353,7 +366,7 @@ class WlanNode(LxBrNet): """ Attach a network interface. - :param core.coreobj.PyCoreNetIf netif: network interface + :param core.netns.vif.VEth netif: network interface :return: nothing """ LxBrNet.attach(self, netif) @@ -364,7 +377,6 @@ class WlanNode(LxBrNet): x, y, z = netif.node.position.get() # invokes any netif.poshook netif.setposition(x, y, z) - # self.model.setlinkparams() def setmodel(self, model, config): """ @@ -398,25 +410,28 @@ class WlanNode(LxBrNet): logger.info("updating model %s" % model_name) if self.model is None or self.model.name != model_name: return + model = self.model if model.config_type == RegisterTlvs.WIRELESS.value: if not model.updateconfig(values): return + if self.model.position_callback: for netif in self.netifs(): netif.poshook = self.model.position_callback if netif.node is not None: (x, y, z) = netif.node.position.get() netif.poshook(netif, x, y, z) + self.model.setlinkparams() def all_link_data(self, flags): """ Retrieve all link data. - :param flags: link flags - :return: all link data - :rtype: list[LinkData] + :param flags: message flags + :return: list of link data + :rtype: list[core.data.LinkData] """ all_links = LxBrNet.all_link_data(self, flags) @@ -446,7 +461,6 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :return: """ PyCoreNode.__init__(self, session, objid, name, start=start) - # this initializes net, params, poshook PyCoreNetIf.__init__(self, node=self, name=name, mtu=mtu) self.up = False self.lock = threading.RLock() @@ -456,6 +470,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): self.localname = name self.old_up = False self.old_addrs = [] + if start: self.startup() @@ -464,15 +479,12 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): Set the interface in the up state. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ # interface will also be marked up during net.attach() self.savestate() - - try: - utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"]) - self.up = True - except subprocess.CalledProcessError: - logger.exception("failed to run command: %s link set %s up", constants.IP_BIN, self.localname) + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "up"]) + self.up = True def shutdown(self): """ @@ -504,6 +516,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): """ PyCoreNetIf.attachnet(self, net) + # TODO: issue in that both classes inherited from provide the same method with different signatures def detachnet(self): """ Detach a network. @@ -523,7 +536,9 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param str hwaddr: hardware address :param int ifindex: interface index :param str ifname: interface name - :return: + :return: interface index + :rtype: int + :raises ValueError: when an interface has already been created, one max """ with self.lock: if ifindex is None: @@ -556,14 +571,12 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): if ifindex is None: ifindex = 0 - if ifindex not in self._netif: - raise ValueError, "ifindex %s does not exist" % ifindex - self._netif.pop(ifindex) + if ifindex == self.ifindex: self.shutdown() else: - raise ValueError, "ifindex %s does not exist" % ifindex + raise ValueError("ifindex %s does not exist" % ifindex) def netif(self, ifindex, net=None): """ @@ -606,9 +619,11 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param str addr: address to add :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ if self.up: utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) + PyCoreNetIf.addaddr(self, addr) def deladdr(self, addr): @@ -617,9 +632,11 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param str addr: address to delete :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ if self.up: utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name]) + PyCoreNetIf.deladdr(self, addr) def savestate(self): @@ -628,35 +645,34 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): interface for emulation purposes. TODO: save/restore the PROMISC flag :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ self.old_up = False self.old_addrs = [] args = [constants.IP_BIN, "addr", "show", "dev", self.localname] - try: - _, output = utils.check_cmd(args) - for line in output.split("\n"): - items = line.split() - if len(items) < 2: - continue + _, output = utils.check_cmd(args) + for line in output.split("\n"): + items = line.split() + if len(items) < 2: + continue - if items[1] == "%s:" % self.localname: - flags = items[2][1:-1].split(",") - if "UP" in flags: - self.old_up = True - elif items[0] == "inet": - self.old_addrs.append((items[1], items[3])) - elif items[0] == "inet6": - if items[1][:4] == "fe80": - continue - self.old_addrs.append((items[1], None)) - except subprocess.CalledProcessError: - logger.exception("error during save state") + if items[1] == "%s:" % self.localname: + flags = items[2][1:-1].split(",") + if "UP" in flags: + self.old_up = True + elif items[0] == "inet": + self.old_addrs.append((items[1], items[3])) + elif items[0] == "inet6": + if items[1][:4] == "fe80": + continue + self.old_addrs.append((items[1], None)) def restorestate(self): """ Restore the addresses and other interface state after using it. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ for addr in self.old_addrs: if addr[1] is None: @@ -669,13 +685,58 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): def setposition(self, x=None, y=None, z=None): """ - Use setposition() from both parent classes. + Uses setposition from both parent classes. - :return: nothing + :param float x: x position + :param float y: y position + :param float z: z position + :return: True if position changed, False otherwise + :rtype: bool """ - PyCoreObj.setposition(self, x, y, z) - # invoke any poshook + result = PyCoreObj.setposition(self, x, y, z) PyCoreNetIf.setposition(self, x, y, z) + return result + + def check_cmd(self, args): + """ + Runs shell command on node. + + :param list[str]|str args: command to run + :return: exist status and combined stdout and stderr + :rtype: tuple[int, str] + :raises subprocess.CalledProcessError: when a non-zero exit status occurs + """ + raise NotImplementedError + + def cmd(self, args, wait=True): + """ + Runs shell command on node, with option to not wait for a result. + + :param list[str]|str args: command to run + :param bool wait: wait for command to exit, defaults to True + :return: exit status for command + :rtype: int + """ + raise NotImplementedError + + def cmd_output(self, args): + """ + Runs shell command on node and get exit status and output. + + :param list[str]|str args: command to run + :return: exit status and combined stdout and stderr + :rtype: tuple[int, str] + """ + raise NotImplementedError + + def termcmdstring(self, sh): + """ + Create a terminal command string. + + :param str sh: shell to execute command in + :return: str + """ + raise NotImplementedError class TunnelNode(GreTapBridge): diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index dcf9e73e..a8dd3b32 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -78,24 +78,23 @@ class OvsNet(PyCoreNet): ebtables_queue.startupdateloop(self) def startup(self): - try: - utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name]) - except subprocess.CalledProcessError: - logger.exception("error adding bridge") + """ - try: - # turn off spanning tree protocol and forwarding delay - # TODO: appears stp and rstp are off by default, make sure this always holds true - # TODO: apears ovs only supports rstp forward delay and again it's off by default - utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "up"]) + :return: + :raises subprocess.CalledProcessError: when there is a command exception + """ + utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name]) - # create a new ebtables chain for this bridge - ebtables_commands(utils.check_cmd, [ - [constants.EBTABLES_BIN, "-N", self.bridge_name, "-P", self.policy], - [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name] - ]) - except subprocess.CalledProcessError: - logger.exception("Error setting bridge parameters") + # turn off spanning tree protocol and forwarding delay + # TODO: appears stp and rstp are off by default, make sure this always holds true + # TODO: apears ovs only supports rstp forward delay and again it's off by default + utils.check_cmd([constants.IP_BIN, "link", "set", self.bridge_name, "up"]) + + # create a new ebtables chain for this bridge + ebtables_commands(utils.check_cmd, [ + [constants.EBTABLES_BIN, "-N", self.bridge_name, "-P", self.policy], + [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name] + ]) self.up = True @@ -127,22 +126,14 @@ class OvsNet(PyCoreNet): def attach(self, interface): if self.up: - try: - utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname]) - utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"]) - except subprocess.CalledProcessError: - logger.exception("error joining interface %s to bridge %s", interface.localname, self.bridge_name) - return + utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, interface.localname]) + utils.check_cmd([constants.IP_BIN, "link", "set", interface.localname, "up"]) PyCoreNet.attach(self, interface) def detach(self, interface): if self.up: - try: - utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname]) - except subprocess.CalledProcessError: - logger.exception("error removing interface %s from bridge %s", interface.localname, self.bridge_name) - return + utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, interface.localname]) PyCoreNet.detach(self, interface) @@ -345,10 +336,7 @@ class OvsNet(PyCoreNet): return for address in addresses: - try: - utils.check_cmd([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name]) - except subprocess.CalledProcessError: - logger.exception("error adding IP address") + utils.check_cmd([constants.IP_BIN, "addr", "add", str(address), "dev", self.bridge_name]) class OvsCtrlNet(OvsNet): @@ -392,20 +380,16 @@ class OvsCtrlNet(OvsNet): utils.check_cmd([self.updown_script, self.bridge_name, "startup"]) if self.serverintf: - try: - utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf]) - utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) - except subprocess.CalledProcessError: - logger.exception("error joining server interface %s to controlnet bridge %s", - self.serverintf, self.bridge_name) + utils.check_cmd([constants.OVS_BIN, "add-port", self.bridge_name, self.serverintf]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.serverintf, "up"]) def detectoldbridge(self): """ - Occassionally, control net bridges from previously closed sessions are not cleaned up. + Occasionally, control net bridges from previously closed sessions are not cleaned up. Check if there are old control net bridges and delete them """ - status, output = utils.cmd_output([constants.OVS_BIN, "list-br"]) + _, output = utils.check_cmd([constants.OVS_BIN, "list-br"]) output = output.strip() if output: for line in output.split("\n"): @@ -420,13 +404,16 @@ class OvsCtrlNet(OvsNet): if self.serverintf: try: utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, self.serverintf]) - except subprocess.CalledProcessError: - logger.exception("Error deleting server interface %s to controlnet bridge %s", - self.serverintf, self.bridge_name) + except subprocess.CalledProcessError as e: + logger.exception("error deleting server interface %s to controlnet bridge %s: %s", + self.serverintf, self.bridge_name, e.output) if self.updown_script: - logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script) - utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"]) + try: + logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script) + utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"]) + except subprocess.CalledProcessError as e: + logger.exception("error during updown script shutdown: %s", e.output) OvsNet.shutdown(self) @@ -445,12 +432,12 @@ class OvsPtpNet(OvsNet): raise ValueError("point-to-point links support at most 2 network interfaces") OvsNet.attach(self, interface) - def data(self, message_type): + def data(self, message_type, lat=None, lon=None, alt=None): """ Do not generate a Node Message for point-to-point links. They are built using a link message instead. """ - pass + return None def all_link_data(self, flags): """ @@ -685,8 +672,8 @@ class OvsGreTapBridge(OvsNet): if remoteip is None: self.gretap = None else: - self.gretap = GreTap(node=self, name=None, session=session, remoteip=remoteip, - objid=None, localip=localip, ttl=ttl, key=self.grekey) + self.gretap = GreTap(node=self, session=session, remoteip=remoteip, + localip=localip, ttl=ttl, key=self.grekey) if start: self.startup() @@ -726,7 +713,7 @@ class OvsGreTapBridge(OvsNet): if len(addresses) > 1: localip = addresses[1].split("/")[0] - self.gretap = GreTap(session=self.session, remoteip=remoteip, objid=None, name=None, + self.gretap = GreTap(session=self.session, remoteip=remoteip, localip=localip, ttl=self.ttl, key=self.grekey) self.attach(self.gretap) diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index d6d97e97..eee8801b 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -31,7 +31,7 @@ class VEth(PyCoreNetIf): :param mtu: interface mtu :param net: network :param bool start: start flag - :return: + :raises subprocess.CalledProcessError: when there is a command exception """ # note that net arg is ignored PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) @@ -45,6 +45,7 @@ class VEth(PyCoreNetIf): Interface startup logic. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ utils.check_cmd([constants.IP_BIN, "link", "add", "name", self.localname, "type", "veth", "peer", "name", self.name]) @@ -63,11 +64,14 @@ class VEth(PyCoreNetIf): if self.node: try: self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) - except subprocess.CalledProcessError: - logger.exception("error shutting down interface") + except subprocess.CalledProcessError as e: + logger.exception("error shutting down interface: %s", e.output) if self.localname: - utils.mute_detach([constants.IP_BIN, "link", "delete", self.localname]) + try: + utils.check_cmd([constants.IP_BIN, "link", "delete", self.localname]) + except subprocess.CalledProcessError as e: + logger.exception("error deleting link: %s", e.output) self.up = False @@ -121,8 +125,8 @@ class TunTap(PyCoreNetIf): try: self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) - except subprocess.CalledProcessError: - logger.exception("error shutting down tunnel tap") + except subprocess.CalledProcessError as e: + logger.exception("error shutting down tunnel tap: %s", e.output) self.up = False @@ -133,13 +137,16 @@ class TunTap(PyCoreNetIf): :param func: function to wait for a result of zero :param int attempts: number of attempts to wait for a zero result :param float maxretrydelay: maximum retry delay - :return: nothing + :return: True if wait succeeded, False otherwise + :rtype: bool """ delay = 0.01 + result = False for i in xrange(1, attempts + 1): r = func() if r == 0: - return + result = True + break msg = "attempt %s failed with nonzero exit status %s" % (i, r) if i < attempts + 1: msg += ", retrying..." @@ -152,7 +159,7 @@ class TunTap(PyCoreNetIf): msg += ", giving up" logger.info(msg) - raise RuntimeError("command failed after %s attempts" % attempts) + return result def waitfordevicelocal(self): """ @@ -182,18 +189,20 @@ class TunTap(PyCoreNetIf): count = 0 while True: - try: - self.waitfor(nodedevexists) + result = self.waitfor(nodedevexists) + if result: break - except RuntimeError as e: - # check if this is an EMANE interface; if so, continue - # waiting if EMANE is still running - # TODO: remove emane code - if count < 5 and nodeutils.is_node(self.net, NodeTypes.EMANE) and self.node.session.emane.emanerunning( - self.node): - count += 1 - else: - raise e + + # check if this is an EMANE interface; if so, continue + # waiting if EMANE is still running + # TODO: remove emane code + should_retry = count < 5 + is_emane_node = nodeutils.is_node(self.net, NodeTypes.EMANE) + is_emane_running = self.node.session.emane.emanerunning(self.node) + if all([should_retry, is_emane_node, is_emane_running]): + count += 1 + else: + raise RuntimeError("node device failed to exist") def install(self): """ @@ -203,16 +212,13 @@ class TunTap(PyCoreNetIf): end of the TAP. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ self.waitfordevicelocal() netns = str(self.node.pid) - - try: - utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "netns", netns]) - self.node.check_cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) - self.node.check_cmd([constants.IP_BIN, "link", "set", self.name, "up"]) - except subprocess.CalledProcessError: - logger.exception("error installing TAP interface") + utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "netns", netns]) + self.node.check_cmd([constants.IP_BIN, "link", "set", self.localname, "name", self.name]) + self.node.check_cmd([constants.IP_BIN, "link", "set", self.name, "up"]) def setaddrs(self): """ @@ -222,10 +228,7 @@ class TunTap(PyCoreNetIf): """ self.waitfordevicenode() for addr in self.addrlist: - try: - self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) - except subprocess.CalledProcessError: - logger.exception("failure setting interface address") + self.node.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) class GreTap(PyCoreNetIf): @@ -251,6 +254,7 @@ class GreTap(PyCoreNetIf): :param ttl: ttl value :param key: gre tap key :param bool start: start flag + :raises subprocess.CalledProcessError: when there is a command exception """ PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) self.session = session @@ -268,16 +272,16 @@ class GreTap(PyCoreNetIf): if remoteip is None: raise ValueError, "missing remote IP required for GRE TAP device" - args = ("ip", "link", "add", self.localname, "type", "gretap", - "remote", str(remoteip)) + args = ["ip", "link", "add", self.localname, "type", "gretap", + "remote", str(remoteip)] if localip: - args += ("local", str(localip)) + args += ["local", str(localip)] if ttl: - args += ("ttl", str(ttl)) + args += ["ttl", str(ttl)] if key: - args += ("key", str(key)) + args += ["key", str(key)] utils.check_cmd(args) - args = ("ip", "link", "set", self.localname, "up") + args = ["ip", "link", "set", self.localname, "up"] utils.check_cmd(args) self.up = True @@ -288,10 +292,14 @@ class GreTap(PyCoreNetIf): :return: nothing """ if self.localname: - args = ("ip", "link", "set", self.localname, "down") - utils.check_cmd(args) - args = ("ip", "link", "del", self.localname) - utils.check_cmd(args) + try: + args = ["ip", "link", "set", self.localname, "down"] + utils.check_cmd(args) + args = ["ip", "link", "del", self.localname] + utils.check_cmd(args) + except subprocess.CalledProcessError as e: + logger.exception("error during shutdown: %s", e.output) + self.localname = None def data(self, message_type): diff --git a/daemon/core/netns/vnet.py b/daemon/core/netns/vnet.py index 62f8fd2b..8467a87d 100644 --- a/daemon/core/netns/vnet.py +++ b/daemon/core/netns/vnet.py @@ -59,11 +59,12 @@ class EbtablesQueue(object): :return: nothing """ - self.updatelock.acquire() - self.last_update_time[wlan] = time.time() - self.updatelock.release() + with self.updatelock: + self.last_update_time[wlan] = time.time() + if self.doupdateloop: return + self.doupdateloop = True self.updatethread = threading.Thread(target=self.updateloop) self.updatethread.daemon = True @@ -75,15 +76,15 @@ class EbtablesQueue(object): :return: nothing """ - self.updatelock.acquire() - try: - del self.last_update_time[wlan] - except KeyError: - logger.exception("error deleting last update time for wlan, ignored before: %s", wlan) + with self.updatelock: + try: + del self.last_update_time[wlan] + except KeyError: + logger.exception("error deleting last update time for wlan, ignored before: %s", wlan) - self.updatelock.release() if len(self.last_update_time) > 0: return + self.doupdateloop = False if self.updatethread: self.updatethread.join() @@ -137,25 +138,26 @@ class EbtablesQueue(object): :return: nothing """ while self.doupdateloop: - self.updatelock.acquire() - for wlan in self.updates: - """ - Check if wlan is from a previously closed session. Because of the - rate limiting scheme employed here, this may happen if a new session - is started soon after closing a previous session. - """ - try: - wlan.session - except: - # Just mark as updated to remove from self.updates. - self.updated(wlan) - continue - if self.lastupdate(wlan) > self.rate: - self.buildcmds(wlan) - # print "ebtables commit %d rules" % len(self.cmds) - self.ebcommit(wlan) - self.updated(wlan) - self.updatelock.release() + with self.updatelock: + for wlan in self.updates: + """ + Check if wlan is from a previously closed session. Because of the + rate limiting scheme employed here, this may happen if a new session + is started soon after closing a previous session. + """ + # TODO: if these are WlanNodes, this will never throw an exception + try: + wlan.session + except: + # Just mark as updated to remove from self.updates. + self.updated(wlan) + continue + + if self.lastupdate(wlan) > self.rate: + self.buildcmds(wlan) + self.ebcommit(wlan) + self.updated(wlan) + time.sleep(self.rate) def ebcommit(self, wlan): @@ -166,29 +168,22 @@ class EbtablesQueue(object): """ # save kernel ebtables snapshot to a file args = self.ebatomiccmd(["--atomic-save", ]) - try: - utils.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("atomic-save (%s)", args) - # no atomic file, exit - return + utils.check_cmd(args) + # modify the table file using queued ebtables commands for c in self.cmds: args = self.ebatomiccmd(c) - try: - utils.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("cmd=%s", args) - + utils.check_cmd(args) self.cmds = [] + # commit the table file to the kernel args = self.ebatomiccmd(["--atomic-commit", ]) + utils.check_cmd(args) try: - utils.check_cmd(args) os.unlink(self.atomic_file) except OSError: - logger.exception("atomic-commit (%s)", args) + logger.exception("error removing atomic file: %s", self.atomic_file) def ebchange(self, wlan): """ @@ -197,10 +192,9 @@ class EbtablesQueue(object): :return: nothing """ - self.updatelock.acquire() - if wlan not in self.updates: - self.updates.append(wlan) - self.updatelock.release() + with self.updatelock: + if wlan not in self.updates: + self.updates.append(wlan) def buildcmds(self, wlan): """ @@ -208,23 +202,22 @@ class EbtablesQueue(object): :return: nothing """ - wlan._linked_lock.acquire() - # flush the chain - self.cmds.extend([["-F", wlan.brname], ]) - # rebuild the chain - for netif1, v in wlan._linked.items(): - for netif2, linked in v.items(): - if wlan.policy == "DROP" and linked: - self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname, - "-o", netif2.localname, "-j", "ACCEPT"], - ["-A", wlan.brname, "-o", netif1.localname, - "-i", netif2.localname, "-j", "ACCEPT"]]) - elif wlan.policy == "ACCEPT" and not linked: - self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname, - "-o", netif2.localname, "-j", "DROP"], - ["-A", wlan.brname, "-o", netif1.localname, - "-i", netif2.localname, "-j", "DROP"]]) - wlan._linked_lock.release() + with wlan._linked_lock: + # flush the chain + self.cmds.extend([["-F", wlan.brname], ]) + # rebuild the chain + for netif1, v in wlan._linked.items(): + for netif2, linked in v.items(): + if wlan.policy == "DROP" and linked: + self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname, + "-o", netif2.localname, "-j", "ACCEPT"], + ["-A", wlan.brname, "-o", netif1.localname, + "-i", netif2.localname, "-j", "ACCEPT"]]) + elif wlan.policy == "ACCEPT" and not linked: + self.cmds.extend([["-A", wlan.brname, "-i", netif1.localname, + "-o", netif2.localname, "-j", "DROP"], + ["-A", wlan.brname, "-o", netif1.localname, + "-i", netif2.localname, "-j", "DROP"]]) # a global object because all WLANs share the same queue @@ -279,28 +272,24 @@ class LxBrNet(PyCoreNet): Linux bridge starup logic. :return: nothing + :raises subprocess.CalledProcessError: when there is a command exception """ - try: - utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname]) - except subprocess.CalledProcessError: - logger.exception("Error adding bridge") + utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname]) - try: - # turn off spanning tree protocol and forwarding delay - utils.check_cmd([constants.BRCTL_BIN, "stp", self.brname, "off"]) - utils.check_cmd([constants.BRCTL_BIN, "setfd", self.brname, "0"]) - utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "up"]) - # create a new ebtables chain for this bridge - ebtablescmds(utils.check_cmd, [ - [constants.EBTABLES_BIN, "-N", self.brname, "-P", self.policy], - [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.brname, "-j", self.brname] - ]) - # turn off multicast snooping so mcast forwarding occurs w/o IGMP joins - snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname - if os.path.exists(snoop): - open(snoop, "w").write("0") - except subprocess.CalledProcessError: - logger.exception("Error setting bridge parameters") + # turn off spanning tree protocol and forwarding delay + utils.check_cmd([constants.BRCTL_BIN, "stp", self.brname, "off"]) + utils.check_cmd([constants.BRCTL_BIN, "setfd", self.brname, "0"]) + utils.check_cmd([constants.IP_BIN, "link", "set", self.brname, "up"]) + # create a new ebtables chain for this bridge + ebtablescmds(utils.check_cmd, [ + [constants.EBTABLES_BIN, "-N", self.brname, "-P", self.policy], + [constants.EBTABLES_BIN, "-A", "FORWARD", "--logical-in", self.brname, "-j", self.brname] + ]) + # turn off multicast snooping so mcast forwarding occurs w/o IGMP joins + snoop = "/sys/devices/virtual/net/%s/bridge/multicast_snooping" % self.brname + if os.path.exists(snoop): + with open(snoop, "w") as snoop_file: + snoop_file.write("0") self.up = True @@ -312,6 +301,7 @@ class LxBrNet(PyCoreNet): """ if not self.up: return + ebq.stopupdateloop(self) try: @@ -333,20 +323,18 @@ class LxBrNet(PyCoreNet): del self.session self.up = False + # TODO: this depends on a subtype with localname defined, seems like the wrong place for this to live def attach(self, netif): """ Attach a network interface. - :param core.netns.vif.VEth netif: network interface to attach + :param core.netns.vnode.VEth netif: network interface to attach :return: nothing """ if self.up: - try: - utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname]) - utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"]) - except subprocess.CalledProcessError: - logger.exception("Error joining interface %s to bridge %s", netif.localname, self.brname) - return + utils.check_cmd([constants.BRCTL_BIN, "addif", self.brname, netif.localname]) + utils.check_cmd([constants.IP_BIN, "link", "set", netif.localname, "up"]) + PyCoreNet.attach(self, netif) def detach(self, netif): @@ -357,11 +345,8 @@ class LxBrNet(PyCoreNet): :return: nothing """ if self.up: - try: - utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname]) - except subprocess.CalledProcessError: - logger.exception("Error removing interface %s from bridge %s", netif.localname, self.brname) - return + utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, netif.localname]) + PyCoreNet.detach(self, netif) def linked(self, netif1, netif2): @@ -402,12 +387,11 @@ class LxBrNet(PyCoreNet): :param core.netns.vif.Veth netif2: interface two :return: nothing """ - self._linked_lock.acquire() - if not self.linked(netif1, netif2): - self._linked_lock.release() - return - self._linked[netif1][netif2] = False - self._linked_lock.release() + with self._linked_lock: + if not self.linked(netif1, netif2): + return + self._linked[netif1][netif2] = False + ebq.ebchange(self) def link(self, netif1, netif2): @@ -419,12 +403,11 @@ class LxBrNet(PyCoreNet): :param core.netns.vif.Veth netif2: interface two :return: nothing """ - self._linked_lock.acquire() - if self.linked(netif1, netif2): - self._linked_lock.release() - return - self._linked[netif1][netif2] = True - self._linked_lock.release() + with self._linked_lock: + if self.linked(netif1, netif2): + return + self._linked[netif1][netif2] = True + ebq.ebchange(self) def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, @@ -525,18 +508,21 @@ class LxBrNet(PyCoreNet): self_objid = "%x" % self.objid except TypeError: self_objid = "%s" % self.objid + try: net_objid = "%x" % net.objid except TypeError: net_objid = "%s" % net.objid + localname = "veth%s.%s.%s" % (self_objid, net_objid, sessionid) if len(localname) >= 16: raise ValueError("interface local name %s too long" % localname) + name = "veth%s.%s.%s" % (net_objid, self_objid, sessionid) if len(name) >= 16: raise ValueError("interface name %s too long" % name) - netif = VEth(node=None, name=name, localname=localname, - mtu=1500, net=self, start=self.up) + + netif = VEth(node=None, name=name, localname=localname, mtu=1500, net=self, start=self.up) self.attach(netif) if net.up: # this is similar to net.attach() but uses netif.name instead @@ -563,6 +549,7 @@ class LxBrNet(PyCoreNet): for netif in self.netifs(): if hasattr(netif, "othernet") and netif.othernet == net: return netif + return None def addrconfig(self, addrlist): @@ -574,11 +561,9 @@ class LxBrNet(PyCoreNet): """ if not self.up: return + for addr in addrlist: - try: - utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname]) - except subprocess.CalledProcessError: - logger.exception("Error adding IP address") + utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.brname]) class GreTapBridge(LxBrNet): @@ -615,8 +600,8 @@ class GreTapBridge(LxBrNet): if remoteip is None: self.gretap = None else: - self.gretap = GreTap(node=self, name=None, session=session, remoteip=remoteip, - objid=None, localip=localip, ttl=ttl, key=self.grekey) + self.gretap = GreTap(node=self, session=session, remoteip=remoteip, + localip=localip, ttl=ttl, key=self.grekey) if start: self.startup() @@ -658,7 +643,7 @@ class GreTapBridge(LxBrNet): localip = None if len(addrlist) > 1: localip = addrlist[1].split("/")[0] - self.gretap = GreTap(session=self.session, remoteip=remoteip, objid=None, name=None, + self.gretap = GreTap(session=self.session, remoteip=remoteip, localip=localip, ttl=self.ttl, key=self.grekey) self.attach(self.gretap) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 5b0ccf21..d92fac1e 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -98,25 +98,19 @@ class SimpleLxcNode(PyCoreNode): env["NODE_NUMBER"] = str(self.objid) env["NODE_NAME"] = str(self.name) - try: - _, output = utils.check_cmd(vnoded, env=env) - self.pid = int(output) - except subprocess.CalledProcessError: - logger.exception("vnoded failed to create a namespace; check kernel support and user privileges") + _, output = utils.check_cmd(vnoded, env=env) + self.pid = int(output) # create vnode client self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) - try: - # bring up the loopback interface - logger.info("bringing up loopback interface") - self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"]) + # bring up the loopback interface + logger.info("bringing up loopback interface") + self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"]) - # set hostname for node - logger.info("setting hostname: %s" % self.name) - self.check_cmd(["hostname", self.name]) - except subprocess.CalledProcessError: - logger.exception("error setting up loopback and hostname: %s") + # set hostname for node + logger.info("setting hostname: %s" % self.name) + self.check_cmd(["hostname", self.name]) # mark node as up self.up = True @@ -165,7 +159,7 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ - pass + return None def cmd(self, args, wait=True): """ @@ -208,7 +202,6 @@ class SimpleLxcNode(PyCoreNode): """ return self.client.termcmdstring(sh) - # TODO: should change how this exception is just swallowed up def mount(self, source, target): """ Create and mount a directory. @@ -216,17 +209,15 @@ class SimpleLxcNode(PyCoreNode): :param str source: source directory to mount :param str target: target directory to create :return: nothing + :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ source = os.path.abspath(source) logger.info("mounting %s at %s" % (source, target)) - try: - cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) - status, output = self.client.shcmd_result(cmd) - if status: - raise IOError("error during mount: %s" % output) - self._mounts.append((source, target)) - except IOError: - logger.exception("mounting failed for %s at %s", source, target) + cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) + status, output = self.client.shcmd_result(cmd) + if status: + raise subprocess.CalledProcessError(status, cmd, output) + self._mounts.append((source, target)) def umount(self, target): """ @@ -238,8 +229,8 @@ class SimpleLxcNode(PyCoreNode): logger.info("unmounting: %s", target) try: self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target]) - except subprocess.CalledProcessError: - logger.exception("error during unmount") + except subprocess.CalledProcessError as e: + logger.exception("error during unmount: %s", e.output) def newifindex(self): """ @@ -277,33 +268,29 @@ class SimpleLxcNode(PyCoreNode): localname = "veth" + suffix if len(localname) >= 16: raise ValueError("interface local name (%s) too long" % localname) + name = localname + "p" if len(name) >= 16: raise ValueError("interface name (%s) too long" % name) + veth = VEth(node=self, name=name, localname=localname, net=net, start=self.up) if self.up: - try: - utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) - self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) - except subprocess.CalledProcessError: - logger.exception("failure setting eth name") + utils.check_cmd([constants.IP_BIN, "link", "set", veth.name, "netns", str(self.pid)]) + self.check_cmd([constants.IP_BIN, "link", "set", veth.name, "name", ifname]) veth.name = ifname if self.up: # TODO: potentially find better way to query interface ID # retrieve interface information - try: - _, output = self.check_cmd(["ip", "link", "show", veth.name]) - logger.info("interface command output: %s", output) - output = output.split("\n") - veth.flow_id = int(output[0].strip().split(":")[0]) + 1 - logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) - veth.hwaddr = output[1].strip().split()[1] - logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) - except subprocess.CalledProcessError: - logger.exception("failure getting flow id and mac address") + _, output = self.check_cmd(["ip", "link", "show", veth.name]) + logger.info("interface command output: %s", output) + output = output.split("\n") + veth.flow_id = int(output[0].strip().split(":")[0]) + 1 + logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) + veth.hwaddr = output[1].strip().split()[1] + logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) try: self.addnetif(veth, ifindex) @@ -351,15 +338,13 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to set hardware address for :param core.misc.ipaddress.MacAddress addr: hardware address to set - :return: mothing + :return: nothing + :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ self._netif[ifindex].sethwaddr(addr) if self.up: args = [constants.IP_BIN, "link", "set", "dev", self.ifname(ifindex), "address", str(addr)] - try: - self.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("error setting MAC address %s: %s", addr) + self.check_cmd(args) def addaddr(self, ifindex, addr): """ @@ -370,16 +355,13 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - try: - # check if addr is ipv6 - if ":" in str(addr): - args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] - self.check_cmd(args) - else: - args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] - self.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("failure adding interface address") + # check if addr is ipv6 + if ":" in str(addr): + args = [constants.IP_BIN, "addr", "add", str(addr), "dev", self.ifname(ifindex)] + self.check_cmd(args) + else: + args = [constants.IP_BIN, "addr", "add", str(addr), "broadcast", "+", "dev", self.ifname(ifindex)] + self.check_cmd(args) self._netif[ifindex].addaddr(addr) @@ -390,6 +372,7 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to delete address from :param str addr: address to delete from interface :return: nothing + :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ try: self._netif[ifindex].deladdr(addr) @@ -397,10 +380,7 @@ class SimpleLxcNode(PyCoreNode): logger.exception("trying to delete unknown address: %s" % addr) if self.up: - try: - self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) - except subprocess.CalledProcessError: - logger.exception("failure deleting address") + self.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.ifname(ifindex)]) def delalladdr(self, ifindex, address_types=valid_address_types): """ @@ -409,6 +389,7 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to delete address types from :param tuple[str] address_types: address types to delete :return: nothing + :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ interface_name = self.ifname(ifindex) addresses = self.client.getaddr(interface_name, rescan=True) @@ -430,10 +411,7 @@ class SimpleLxcNode(PyCoreNode): :return: nothing """ if self.up: - try: - self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) - except subprocess.CalledProcessError: - logger.exception("failure bringing interface up") + self.check_cmd([constants.IP_BIN, "link", "set", self.ifname(ifindex), "up"]) def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): """ @@ -510,17 +488,15 @@ class SimpleLxcNode(PyCoreNode): :param str srcname: source file name :param str filename: file name to add :return: nothing + :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ logger.info("adding file from %s to %s", srcname, filename) directory = os.path.dirname(filename) - try: - cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename) - status, output = self.client.shcmd_result(cmd) - if status: - raise IOError("error adding file: %s" % output) - except IOError: - logger.exception("error during addfile") + cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename) + status, output = self.client.shcmd_result(cmd) + if status: + raise subprocess.CalledProcessError(status, cmd, output) class LxcNode(SimpleLxcNode): @@ -567,13 +543,10 @@ class LxcNode(SimpleLxcNode): :return: nothing """ with self.lock: - try: - self.makenodedir() - super(LxcNode, self).startup() - self.privatedir("/var/run") - self.privatedir("/var/log") - except OSError: - logger.exception("error during startup") + self.makenodedir() + super(LxcNode, self).startup() + self.privatedir("/var/run") + self.privatedir("/var/log") def shutdown(self): """ @@ -585,8 +558,6 @@ class LxcNode(SimpleLxcNode): return with self.lock: - # services are instead stopped when session enters datacollect state - # self.session.services.stopnodeservices(self) try: super(LxcNode, self).shutdown() except OSError: @@ -605,12 +576,7 @@ class LxcNode(SimpleLxcNode): if path[0] != "/": raise ValueError("path not fully qualified: %s" % path) hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip("/").replace("/", ".")) - - try: - os.mkdir(hostpath) - except OSError: - logger.exception("error creating directory: %s", hostpath) - + os.mkdir(hostpath) self.mount(hostpath, path) def hostfilename(self, filename): @@ -622,7 +588,7 @@ class LxcNode(SimpleLxcNode): """ dirname, basename = os.path.split(filename) if not basename: - raise ValueError("no basename for filename: " + filename) + raise ValueError("no basename for filename: %s" % filename) if dirname and dirname[0] == "/": dirname = dirname[1:] dirname = dirname.replace("/", ".") diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 42e124ff..f501dc98 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -109,7 +109,7 @@ class VnodeClient(object): :raises subprocess.CalledProcessError: when there is a non-zero exit status """ status, output = self.cmd_output(args) - if status: + if status != 0: raise subprocess.CalledProcessError(status, args, output) return status, output.strip() @@ -174,8 +174,8 @@ class VnodeClient(object): args = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh) if "SUDO_USER" in os.environ: args = ("su", "-s", "/bin/sh", "-c", - "exec " + " ".join(map(lambda x: "'%s'" % x, args)), - os.environ["SUDO_USER"]) + "exec " + " ".join(map(lambda x: "'%s'" % x, args)), + os.environ["SUDO_USER"]) return os.spawnvp(os.P_NOWAIT, args[0], args) def termcmdstring(self, sh="/bin/sh"): From a8ee7f35d69e5338f697dbe37f8c20f9e3193d8e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 13:57:50 -0800 Subject: [PATCH 049/152] updates to check_cmd to just return output, as status is pointless --- daemon/core/coreobj.py | 4 ++-- daemon/core/emane/__init__.py | 27 +++++++++++++-------------- daemon/core/emane/emanemanager.py | 7 +++---- daemon/core/misc/utils.py | 6 +++--- daemon/core/netns/nodes.py | 2 +- daemon/core/netns/openvswitch.py | 2 +- daemon/core/netns/vnode.py | 8 ++++---- daemon/core/netns/vnodeclient.py | 6 +++--- daemon/core/phys/pnodes.py | 6 +++--- daemon/core/service.py | 14 +++++--------- daemon/core/xml/xmldeployment.py | 12 ++++++------ daemon/tests/conftest.py | 2 +- 12 files changed, 45 insertions(+), 51 deletions(-) diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 76ebc1c8..10bf83ea 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -417,8 +417,8 @@ class PyCoreNode(PyCoreObj): Runs shell command on node. :param list[str]|str args: command to run - :return: exist status and combined stdout and stderr - :rtype: tuple[int, str] + :return: combined stdout and stderr + :rtype: str :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ raise NotImplementedError diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 8fa9557a..18f01a83 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -26,20 +26,19 @@ def emane_version(): VERSION = EMANEUNK try: - status, output = utils.check_cmd(args) - if status == 0: - if output.startswith("0.7.4"): - VERSION = EMANE074 - elif output.startswith("0.8.1"): - VERSION = EMANE081 - elif output.startswith("0.9.1"): - VERSION = EMANE091 - elif output.startswith("0.9.2"): - VERSION = EMANE092 - elif output.startswith("0.9.3"): - VERSION = EMANE093 - elif output.startswith("1.0.1"): - VERSION = EMANE101 + output = utils.check_cmd(args) + if output.startswith("0.7.4"): + VERSION = EMANE074 + elif output.startswith("0.8.1"): + VERSION = EMANE081 + elif output.startswith("0.9.1"): + VERSION = EMANE091 + elif output.startswith("0.9.2"): + VERSION = EMANE092 + elif output.startswith("0.9.3"): + VERSION = EMANE093 + elif output.startswith("1.0.1"): + VERSION = EMANE101 except subprocess.CalledProcessError: logger.exception("error checking emane version") output = "" diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 424b19ab..dc3042e4 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -927,10 +927,9 @@ class EmaneManager(ConfigurableManager): try: args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] - logger.info("Emane.startdaemons2() running %s" % str(args)) - status, output = node.check_cmd(args) - logger.info("Emane.startdaemons2() return code %d" % status) - logger.info("Emane.startdaemons2() output: %s" % output) + logger.info("Emane.startdaemons2() running %s", args) + output = node.check_cmd(args) + logger.info("Emane.startdaemons2() output: %s", output) except subprocess.CalledProcessError: logger.exception("error starting emane") diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index ad907391..d8b31fd3 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -211,8 +211,8 @@ def check_cmd(args, **kwargs): :param list[str]|str args: command arguments :param dict kwargs: keyword arguments to pass to subprocess.Popen - :return: command status and stdout - :rtype: tuple[int, str] + :return: combined stdout and stderr + :rtype: str :raises subprocess.CalledProcessError: when there is a non-zero exit status or the file to execute is not found """ kwargs["stdout"] = subprocess.PIPE @@ -224,7 +224,7 @@ def check_cmd(args, **kwargs): status = p.wait() if status != 0: raise subprocess.CalledProcessError(status, args, stdout) - return status, stdout.strip() + return stdout.strip() except OSError: raise subprocess.CalledProcessError(-1, args) diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index 1757bc1c..0fe6c3d7 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -650,7 +650,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): self.old_up = False self.old_addrs = [] args = [constants.IP_BIN, "addr", "show", "dev", self.localname] - _, output = utils.check_cmd(args) + output = utils.check_cmd(args) for line in output.split("\n"): items = line.split() if len(items) < 2: diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index a8dd3b32..bb515d67 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -389,7 +389,7 @@ class OvsCtrlNet(OvsNet): Check if there are old control net bridges and delete them """ - _, output = utils.check_cmd([constants.OVS_BIN, "list-br"]) + output = utils.check_cmd([constants.OVS_BIN, "list-br"]) output = output.strip() if output: for line in output.split("\n"): diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index d92fac1e..12784d18 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -98,7 +98,7 @@ class SimpleLxcNode(PyCoreNode): env["NODE_NUMBER"] = str(self.objid) env["NODE_NAME"] = str(self.name) - _, output = utils.check_cmd(vnoded, env=env) + output = utils.check_cmd(vnoded, env=env) self.pid = int(output) # create vnode client @@ -187,8 +187,8 @@ class SimpleLxcNode(PyCoreNode): Runs shell command on node. :param list[str]|str args: command to run - :return: exist status and combined stdout and stderr - :rtype: tuple[int, str] + :return: combined stdout and stderr + :rtype: str :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ return self.client.check_cmd(args) @@ -284,7 +284,7 @@ class SimpleLxcNode(PyCoreNode): if self.up: # TODO: potentially find better way to query interface ID # retrieve interface information - _, output = self.check_cmd(["ip", "link", "show", veth.name]) + output = self.check_cmd(["ip", "link", "show", veth.name]) logger.info("interface command output: %s", output) output = output.split("\n") veth.flow_id = int(output[0].strip().split(":")[0]) + 1 diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index f501dc98..5b61decb 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -104,14 +104,14 @@ class VnodeClient(object): Run command and return exit status and combined stdout and stderr. :param list[str]|str args: command to run - :return: exit status and combined stdout and stderr - :rtype: tuple[int, str] + :return: combined stdout and stderr + :rtype: str :raises subprocess.CalledProcessError: when there is a non-zero exit status """ status, output = self.cmd_output(args) if status != 0: raise subprocess.CalledProcessError(status, args, output) - return status, output.strip() + return output.strip() def popen(self, args): """ diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 2c781f7a..adba0a95 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -96,14 +96,14 @@ class PhysicalNode(PyCoreNode): Runs shell command on node. :param list[str]|str args: command to run - :return: exist status and combined stdout and stderr - :rtype: tuple[int, str] + :return: combined stdout and stderr + :rtype: str :raises subprocess.CalledProcessError: when a non-zero exit status occurs """ status, output = self.cmd_output(args) if status: raise subprocess.CalledProcessError(status, args, output) - return status, output.strip() + return output.strip() def shcmd(self, cmdstr, sh="/bin/sh"): return self.cmd([sh, "-c", cmdstr]) diff --git a/daemon/core/service.py b/daemon/core/service.py index 71aa8997..385ca524 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -408,11 +408,11 @@ class CoreServices(ConfigurableManager): status = 0 # has validate commands - if len(validate_cmds) > 0: + if validate_cmds: for args in validate_cmds: logger.info("validating service %s using: %s", service._name, args) try: - status, _ = node.check_cmd(args) + node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("validate command failed") status = -1 @@ -439,15 +439,11 @@ class CoreServices(ConfigurableManager): :return: status for stopping the services :rtype: str """ - status = "" - if len(service._shutdown) == 0: - # doesn't have a shutdown command - status += "0" - else: + status = "0" + if service._shutdown: for args in service._shutdown: try: - status, _ = node.check_cmd(args) - status = str(status) + node.check_cmd(args) except subprocess.CalledProcessError: logger.exception("error running stop command %s", args) # TODO: determine if its ok to just return the bad exit status diff --git a/daemon/core/xml/xmldeployment.py b/daemon/core/xml/xmldeployment.py index 1c9fd4cf..180a56f5 100644 --- a/daemon/core/xml/xmldeployment.py +++ b/daemon/core/xml/xmldeployment.py @@ -25,8 +25,8 @@ class CoreDeploymentWriter(object): def get_ipv4_addresses(hostname): if hostname == 'localhost': addr_list = [] - args = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') - _, output = utils.check_cmd(args) + args = [constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show'] + output = utils.check_cmd(args) for line in output.split(os.linesep): split = line.split() if not split: @@ -43,12 +43,12 @@ class CoreDeploymentWriter(object): def get_interface_names(hostname): """ Uses same methodology of get_ipv4_addresses() to get - parallel list of interface names to go with ... - """ + parallel list of interface names to go with ... + """ if hostname == 'localhost': iface_list = [] - args = (constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show') - _, output = utils.check_cmd(args) + args = [constants.IP_BIN, '-o', '-f', 'inet', 'addr', 'show'] + output = utils.check_cmd(args) for line in output.split(os.linesep): split = line.split() if not split: diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index ffb6d6ac..50b088d7 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -188,7 +188,7 @@ class Core(object): def ping_output(self, from_name, to_name): from_node = self.nodes[from_name] to_ip = str(self.get_ip(to_name)) - _, output = from_node.check_cmd(["ping", "-i", "0.05", "-c", "3", to_ip]) + output = from_node.check_cmd(["ping", "-i", "0.05", "-c", "3", to_ip]) return output def iperf(self, from_name, to_name): From fbc749849c403f33d229c9fabaeddc5bbc767d82 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 14:12:57 -0800 Subject: [PATCH 050/152] updates to expose exceptions from physical nodes as well --- daemon/core/phys/pnodes.py | 76 ++++++++++++++------------------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index adba0a95..4e47c71f 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -31,27 +31,22 @@ class PhysicalNode(PyCoreNode): self.session.services.validatenodeservices(self) def startup(self): - self.lock.acquire() - try: + with self.lock: self.makenodedir() - # self.privatedir("/var/run") - # self.privatedir("/var/log") - except OSError: - logger.exception("startup error") - finally: - self.lock.release() def shutdown(self): if not self.up: return - self.lock.acquire() - while self._mounts: - source, target = self._mounts.pop(-1) - self.umount(target) - for netif in self.netifs(): - netif.shutdown() - self.rmnodedir() - self.lock.release() + + with self.lock: + while self._mounts: + source, target = self._mounts.pop(-1) + self.umount(target) + + for netif in self.netifs(): + netif.shutdown() + + self.rmnodedir() def termcmdstring(self, sh="/bin/sh"): """ @@ -84,10 +79,8 @@ class PhysicalNode(PyCoreNode): :rtype: tuple[int, str] """ os.chdir(self.nodedir) - # in Python 2.7 we can use subprocess.check_output() here p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - # err will always be None - stdout, err = p.communicate() + stdout, _ = p.communicate() status = p.wait() return status, stdout.strip() @@ -115,10 +108,7 @@ class PhysicalNode(PyCoreNode): self._netif[ifindex].sethwaddr(addr) ifname = self.ifname(ifindex) if self.up: - try: - self.check_cmd([constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)]) - except subprocess.CalledProcessError: - logger.exception("error setting MAC address %s", addr) + self.check_cmd([constants.IP_BIN, "link", "set", "dev", ifname, "address", str(addr)]) def addaddr(self, ifindex, addr): """ @@ -168,16 +158,14 @@ class PhysicalNode(PyCoreNode): if self.up: self.check_cmd([constants.IP_BIN, "link", "set", "dev", netif.localname, "up"]) - def linkconfig(self, netif, bw=None, delay=None, - loss=None, duplicate=None, jitter=None, netif2=None): + def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): """ Apply tc queing disciplines using LxBrNet.linkconfig() """ # borrow the tc qdisc commands from LxBrNet.linkconfig() linux_bridge = LxBrNet(session=self.session, start=False) linux_bridge.up = True - linux_bridge.linkconfig(netif, bw=bw, delay=delay, loss=loss, duplicate=duplicate, - jitter=jitter, netif2=netif2) + linux_bridge.linkconfig(netif, bw=bw, delay=delay, loss=loss, duplicate=duplicate, jitter=jitter, netif2=netif2) del linux_bridge def newifindex(self): @@ -220,27 +208,17 @@ class PhysicalNode(PyCoreNode): def privatedir(self, path): if path[0] != "/": - raise ValueError, "path not fully qualified: " + path + raise ValueError("path not fully qualified: %s" % path) hostpath = os.path.join(self.nodedir, os.path.normpath(path).strip('/').replace('/', '.')) - try: - os.mkdir(hostpath) - except OSError: - logger.exception("error creating directory: %s", hostpath) - + os.mkdir(hostpath) self.mount(hostpath, path) def mount(self, source, target): source = os.path.abspath(source) - logger.info("mounting %s at %s" % (source, target)) - - try: - os.makedirs(target) - self.check_cmd([constants.MOUNT_BIN, "--bind", source, target]) - self._mounts.append((source, target)) - except OSError: - logger.exception("error making directories") - except subprocess.CalledProcessError as e: - logger.exception("mounting failed for %s at %s: %s", source, target, e.output) + logger.info("mounting %s at %s", source, target) + os.makedirs(target) + self.check_cmd([constants.MOUNT_BIN, "--bind", source, target]) + self._mounts.append((source, target)) def umount(self, target): logger.info("unmounting '%s'" % target) @@ -253,18 +231,20 @@ class PhysicalNode(PyCoreNode): dirname, basename = os.path.split(filename) if not basename: raise ValueError("no basename for filename: " + filename) + if dirname and dirname[0] == "/": dirname = dirname[1:] + dirname = dirname.replace("/", ".") dirname = os.path.join(self.nodedir, dirname) if not os.path.isdir(dirname): os.makedirs(dirname, mode=0755) + hostfilename = os.path.join(dirname, basename) return open(hostfilename, mode) def nodefile(self, filename, contents, mode=0644): - f = self.opennodefile(filename, "w") - f.write(contents) - os.chmod(f.name, mode) - f.close() - logger.info("created nodefile: '%s'; mode: 0%o" % (f.name, mode)) + with self.opennodefile(filename, "w") as node_file: + node_file.write(contents) + os.chmod(node_file.name, mode) + logger.info("created nodefile: '%s'; mode: 0%o", node_file.name, mode) From 29a3496eda5a29a58bbe97720aa9181114142ea3 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 15:54:27 -0800 Subject: [PATCH 051/152] expose command exceptions within emane and mobility --- daemon/core/emane/emanemanager.py | 81 +++++++++++-------------------- daemon/core/mobility.py | 8 +-- daemon/core/session.py | 2 +- 3 files changed, 30 insertions(+), 61 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index dc3042e4..5724590c 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -784,13 +784,9 @@ class EmaneManager(ConfigurableManager): def buildtransportxml(self): """ - Calls emanegentransportxml using a platform.xml file to build - the transportdaemon*.xml. + Calls emanegentransportxml using a platform.xml file to build the transportdaemon*.xml. """ - try: - utils.check_cmd(["emanegentransportxml", "platform.xml"], cwd=self.session.session_dir) - except subprocess.CalledProcessError: - logger.exception("error running emanegentransportxml") + utils.check_cmd(["emanegentransportxml", "platform.xml"], cwd=self.session.session_dir) def buildeventservicexml(self): """ @@ -844,26 +840,21 @@ class EmaneManager(ConfigurableManager): emanecmd = ["emane", "-d", "--logl", loglevel, "-f", os.path.join(path, "emane.log")] if realtime: emanecmd += "-r", - try: - args = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons() running %s" % str(args)) - utils.check_cmd(args, cwd=path) - except subprocess.CalledProcessError: - logger.exception("error starting emane") + + args = emanecmd + [os.path.join(path, "platform.xml")] + logger.info("Emane.startdaemons() running %s" % str(args)) + utils.check_cmd(args, cwd=path) # start one transport daemon per transportdaemon*.xml file args = ["emanetransportd", "-d", "--logl", loglevel, "-f", os.path.join(path, "emanetransportd.log")] if realtime: args += "-r", files = os.listdir(path) - for file in files: - if file[-3:] == "xml" and file[:15] == "transportdaemon": - args = args + [os.path.join(path, file)] - try: - logger.info("Emane.startdaemons() running %s" % str(args)) - utils.check_cmd(args, cwd=path) - except subprocess.CalledProcessError: - logger.exception("error starting emanetransportd") + for current_file in files: + if current_file[-3:] == "xml" and current_file[:15] == "transportdaemon": + args = args + [os.path.join(path, current_file)] + logger.info("Emane.startdaemons() running %s" % str(args)) + utils.check_cmd(args, cwd=path) def startdaemons2(self): """ @@ -911,39 +902,28 @@ class EmaneManager(ConfigurableManager): # multicast route is needed for OTA data args = [constants.IP_BIN, "route", "add", otagroup, "dev", otadev] - try: - node.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("error adding route for OTA data") + node.check_cmd(args) # multicast route is also needed for event data if on control network if eventservicenetidx >= 0 and eventgroup != otagroup: args = [constants.IP_BIN, "route", "add", eventgroup, "dev", eventdev] - try: - node.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("error adding route for event data") + node.check_cmd(args) - try: - args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), - os.path.join(path, "platform%d.xml" % n)] - logger.info("Emane.startdaemons2() running %s", args) - output = node.check_cmd(args) - logger.info("Emane.startdaemons2() output: %s", output) - except subprocess.CalledProcessError: - logger.exception("error starting emane") + # start emane + args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), + os.path.join(path, "platform%d.xml" % n)] + logger.info("Emane.startdaemons2() running %s", args) + output = node.check_cmd(args) + logger.info("Emane.startdaemons2() output: %s", output) if not run_emane_on_host: return path = self.session.session_dir - try: - emanecmd += ["-f", os.path.join(path, "emane.log")] - args = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons2() running %s" % args) - utils.check_cmd(args, cwd=path) - except subprocess.CalledProcessError: - logger.exception("error starting emane") + emanecmd += ["-f", os.path.join(path, "emane.log")] + args = emanecmd + [os.path.join(path, "platform.xml")] + logger.info("Emane.startdaemons2() running %s" % args) + utils.check_cmd(args, cwd=path) def stopdaemons(self): """ @@ -1164,17 +1144,10 @@ class EmaneManager(ConfigurableManager): is running, False otherwise. """ args = ["pkill", "-0", "-x", "emane"] - - status = -1 - try: - if emane.VERSION < emane.EMANE092: - utils.check_cmd(args) - else: - node.check_cmd(args) - status = 0 - except subprocess.CalledProcessError: - logger.exception("error checking if emane is running") - + if emane.VERSION < emane.EMANE092: + status = utils.cmd(args) + else: + status = node.cmd(args) return status == 0 diff --git a/daemon/core/mobility.py b/daemon/core/mobility.py index 7bc131ba..58c1b162 100644 --- a/daemon/core/mobility.py +++ b/daemon/core/mobility.py @@ -5,7 +5,6 @@ mobility.py: mobility helpers for moving nodes and calculating wireless range. import heapq import math import os -import subprocess import threading import time @@ -1238,8 +1237,5 @@ class Ns2ScriptedMobility(WayPointMobility): if filename is None or filename == '': return filename = self.findfile(filename) - try: - args = ["/bin/sh", filename, typestr] - utils.check_cmd(args, cwd=self.session.sessiondir, env=self.session.get_environment()) - except subprocess.CalledProcessError: - logger.exception("Error running script '%s' for WLAN state %s", filename, typestr) + args = ["/bin/sh", filename, typestr] + utils.check_cmd(args, cwd=self.session.sessiondir, env=self.session.get_environment()) diff --git a/daemon/core/session.py b/daemon/core/session.py index 1c156599..342adc66 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -529,7 +529,7 @@ class Session(object): try: utils.load_config(environment_user_file, env) except IOError: - logger.warn("error reading user core environment settings file: %s", environment_user_file) + logger.info("error reading user core environment settings file: %s", environment_user_file) return env From 974559843ab425c04f53a8923fd10e04112e2e6b Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 2 Mar 2018 16:22:20 -0800 Subject: [PATCH 052/152] defined custom core command error that defaults to printing command output as well --- daemon/core/__init__.py | 10 +++++++++- daemon/core/coreobj.py | 2 +- daemon/core/emane/__init__.py | 5 ++--- daemon/core/emane/emanemanager.py | 4 ++-- daemon/core/misc/utils.py | 13 +++++++------ daemon/core/netns/nodes.py | 31 +++++++++++++++---------------- daemon/core/netns/openvswitch.py | 18 +++++++++--------- daemon/core/netns/vif.py | 26 +++++++++++++------------- daemon/core/netns/vnet.py | 8 ++++---- daemon/core/netns/vnode.py | 22 +++++++++++----------- daemon/core/netns/vnodeclient.py | 6 +++--- daemon/core/phys/pnodes.py | 9 +++++---- daemon/core/service.py | 10 +++++----- daemon/core/services/utility.py | 4 ++-- daemon/core/xen/xen.py | 3 ++- 15 files changed, 90 insertions(+), 81 deletions(-) diff --git a/daemon/core/__init__.py b/daemon/core/__init__.py index e8899fc7..3a0d31a6 100644 --- a/daemon/core/__init__.py +++ b/daemon/core/__init__.py @@ -2,10 +2,10 @@ import json import logging import logging.config import os +import subprocess from core import constants - # setup logging log_config_path = os.path.join(constants.CORE_CONF_DIR, "logging.conf") with open(log_config_path, "r") as log_config_file: @@ -14,3 +14,11 @@ with open(log_config_path, "r") as log_config_file: logger = logging.getLogger() + +class CoreCommandError(subprocess.CalledProcessError): + """ + Used when encountering internal CORE command errors. + """ + + def __str__(self): + return "Command(%s), Status(%s):\n%s" % (self.cmd, self.returncode, self.output) diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index 10bf83ea..e9fe024e 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -419,7 +419,7 @@ class PyCoreNode(PyCoreObj): :param list[str]|str args: command to run :return: combined stdout and stderr :rtype: str - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ raise NotImplementedError diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 18f01a83..5446bf88 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -1,5 +1,4 @@ -import subprocess - +from core import CoreCommandError from core import logger from core.misc import utils @@ -39,7 +38,7 @@ def emane_version(): VERSION = EMANE093 elif output.startswith("1.0.1"): VERSION = EMANE101 - except subprocess.CalledProcessError: + except CoreCommandError: logger.exception("error checking emane version") output = "" diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 5724590c..4777e050 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -3,10 +3,10 @@ emane.py: definition of an Emane class for implementing configuration control of """ import os -import subprocess import threading from xml.dom.minidom import parseString +from core import CoreCommandError from core import constants from core import emane from core import logger @@ -949,7 +949,7 @@ class EmaneManager(ConfigurableManager): try: utils.check_cmd(args) utils.check_cmd(["killall", "-q", "emanetransportd"]) - except subprocess.CalledProcessError: + except CoreCommandError: logger.exception("error shutting down emane daemons") def installnetifs(self, do_netns=True): diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index d8b31fd3..f13f0152 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -12,6 +12,7 @@ import sys import fcntl import resource +from core import CoreCommandError from core import logger DEVNULL = open(os.devnull, "wb") @@ -181,7 +182,7 @@ def cmd(args, wait=True): return 0 return p.wait() except OSError: - raise subprocess.CalledProcessError(-1, args) + raise CoreCommandError(-1, args) def cmd_output(args): @@ -192,7 +193,7 @@ def cmd_output(args): :param list[str]|str args: command arguments :return: command status and stdout :rtype: tuple[int, str] - :raises subprocess.CalledProcessError: when the file to execute is not found + :raises CoreCommandError: when the file to execute is not found """ args = split_args(args) try: @@ -201,7 +202,7 @@ def cmd_output(args): status = p.wait() return status, stdout.strip() except OSError: - raise subprocess.CalledProcessError(-1, args) + raise CoreCommandError(-1, args) def check_cmd(args, **kwargs): @@ -213,7 +214,7 @@ def check_cmd(args, **kwargs): :param dict kwargs: keyword arguments to pass to subprocess.Popen :return: combined stdout and stderr :rtype: str - :raises subprocess.CalledProcessError: when there is a non-zero exit status or the file to execute is not found + :raises CoreCommandError: when there is a non-zero exit status or the file to execute is not found """ kwargs["stdout"] = subprocess.PIPE kwargs["stderr"] = subprocess.STDOUT @@ -223,10 +224,10 @@ def check_cmd(args, **kwargs): stdout, _ = p.communicate() status = p.wait() if status != 0: - raise subprocess.CalledProcessError(status, args, stdout) + raise CoreCommandError(status, args, stdout) return stdout.strip() except OSError: - raise subprocess.CalledProcessError(-1, args) + raise CoreCommandError(-1, args) def hex_dump(s, bytes_per_word=2, words_per_line=8): diff --git a/daemon/core/netns/nodes.py b/daemon/core/netns/nodes.py index 0fe6c3d7..a225eb6f 100644 --- a/daemon/core/netns/nodes.py +++ b/daemon/core/netns/nodes.py @@ -4,11 +4,11 @@ implementing specific node types. """ import socket -import subprocess import threading from socket import AF_INET from socket import AF_INET6 +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNetIf @@ -68,7 +68,7 @@ class CtrlNet(LxBrNet): Startup functionality for the control network. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ if self.detectoldbridge(): return @@ -134,16 +134,15 @@ class CtrlNet(LxBrNet): if self.serverintf is not None: try: utils.check_cmd([constants.BRCTL_BIN, "delif", self.brname, self.serverintf]) - except subprocess.CalledProcessError as e: - logger.exception("error deleting server interface %s from bridge %s: %s", - self.serverintf, self.brname, e.output) + except CoreCommandError: + logger.exception("error deleting server interface %s from bridge %s", self.serverintf, self.brname) if self.updown_script is not None: try: logger.info("interface %s updown script (%s shutdown) called", self.brname, self.updown_script) utils.check_cmd([self.updown_script, self.brname, "shutdown"]) - except subprocess.CalledProcessError as e: - logger.exception("error issuing shutdown script shutdown: %s", e.output) + except CoreCommandError: + logger.exception("error issuing shutdown script shutdown") LxBrNet.shutdown(self) @@ -328,7 +327,7 @@ class HubNode(LxBrNet): :param int objid: node id :param str name: node namee :param bool start: start flag - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ LxBrNet.__init__(self, session, objid, name, start) @@ -479,7 +478,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): Set the interface in the up state. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ # interface will also be marked up during net.attach() self.savestate() @@ -500,8 +499,8 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): utils.check_cmd([constants.IP_BIN, "link", "set", self.localname, "down"]) utils.check_cmd([constants.IP_BIN, "addr", "flush", "dev", self.localname]) utils.check_cmd([constants.TC_BIN, "qdisc", "del", "dev", self.localname, "root"]) - except subprocess.CalledProcessError as e: - logger.exception("error shutting down: %s", e.output) + except CoreCommandError: + logger.exception("error shutting down") self.up = False self.restorestate() @@ -619,7 +618,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param str addr: address to add :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ if self.up: utils.check_cmd([constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) @@ -632,7 +631,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param str addr: address to delete :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ if self.up: utils.check_cmd([constants.IP_BIN, "addr", "del", str(addr), "dev", self.name]) @@ -645,7 +644,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): interface for emulation purposes. TODO: save/restore the PROMISC flag :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ self.old_up = False self.old_addrs = [] @@ -672,7 +671,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): Restore the addresses and other interface state after using it. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ for addr in self.old_addrs: if addr[1] is None: @@ -704,7 +703,7 @@ class RJ45Node(PyCoreNode, PyCoreNetIf): :param list[str]|str args: command to run :return: exist status and combined stdout and stderr :rtype: tuple[int, str] - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ raise NotImplementedError diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index bb515d67..341ab92a 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -3,11 +3,11 @@ TODO: probably goes away, or implement the usage of "unshare", or docker formal. """ import socket -import subprocess import threading from socket import AF_INET from socket import AF_INET6 +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNet @@ -81,7 +81,7 @@ class OvsNet(PyCoreNet): """ :return: - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ utils.check_cmd([constants.OVS_BIN, "add-br", self.bridge_name]) @@ -112,8 +112,8 @@ class OvsNet(PyCoreNet): [constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.bridge_name, "-j", self.bridge_name], [constants.EBTABLES_BIN, "-X", self.bridge_name] ]) - except subprocess.CalledProcessError as e: - logger.exception("error bringing bridge down and removing it: %s", e.output) + except CoreCommandError: + logger.exception("error bringing bridge down and removing it") # removes veth pairs used for bridge-to-bridge connections for interface in self.netifs(): @@ -404,16 +404,16 @@ class OvsCtrlNet(OvsNet): if self.serverintf: try: utils.check_cmd([constants.OVS_BIN, "del-port", self.bridge_name, self.serverintf]) - except subprocess.CalledProcessError as e: - logger.exception("error deleting server interface %s to controlnet bridge %s: %s", - self.serverintf, self.bridge_name, e.output) + except CoreCommandError: + logger.exception("error deleting server interface %s to controlnet bridge %s", + self.serverintf, self.bridge_name) if self.updown_script: try: logger.info("interface %s updown script (%s shutdown) called", self.bridge_name, self.updown_script) utils.check_cmd([self.updown_script, self.bridge_name, "shutdown"]) - except subprocess.CalledProcessError as e: - logger.exception("error during updown script shutdown: %s", e.output) + except CoreCommandError: + logger.exception("error during updown script shutdown") OvsNet.shutdown(self) diff --git a/daemon/core/netns/vif.py b/daemon/core/netns/vif.py index eee8801b..b7d77d23 100644 --- a/daemon/core/netns/vif.py +++ b/daemon/core/netns/vif.py @@ -2,9 +2,9 @@ virtual ethernet classes that implement the interfaces available under Linux. """ -import subprocess import time +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNetIf @@ -31,7 +31,7 @@ class VEth(PyCoreNetIf): :param mtu: interface mtu :param net: network :param bool start: start flag - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ # note that net arg is ignored PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) @@ -45,7 +45,7 @@ class VEth(PyCoreNetIf): Interface startup logic. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ utils.check_cmd([constants.IP_BIN, "link", "add", "name", self.localname, "type", "veth", "peer", "name", self.name]) @@ -64,14 +64,14 @@ class VEth(PyCoreNetIf): if self.node: try: self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) - except subprocess.CalledProcessError as e: - logger.exception("error shutting down interface: %s", e.output) + except CoreCommandError: + logger.exception("error shutting down interface") if self.localname: try: utils.check_cmd([constants.IP_BIN, "link", "delete", self.localname]) - except subprocess.CalledProcessError as e: - logger.exception("error deleting link: %s", e.output) + except CoreCommandError: + logger.exception("error deleting link") self.up = False @@ -125,8 +125,8 @@ class TunTap(PyCoreNetIf): try: self.node.check_cmd([constants.IP_BIN, "-6", "addr", "flush", "dev", self.name]) - except subprocess.CalledProcessError as e: - logger.exception("error shutting down tunnel tap: %s", e.output) + except CoreCommandError: + logger.exception("error shutting down tunnel tap") self.up = False @@ -212,7 +212,7 @@ class TunTap(PyCoreNetIf): end of the TAP. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ self.waitfordevicelocal() netns = str(self.node.pid) @@ -254,7 +254,7 @@ class GreTap(PyCoreNetIf): :param ttl: ttl value :param key: gre tap key :param bool start: start flag - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) self.session = session @@ -297,8 +297,8 @@ class GreTap(PyCoreNetIf): utils.check_cmd(args) args = ["ip", "link", "del", self.localname] utils.check_cmd(args) - except subprocess.CalledProcessError as e: - logger.exception("error during shutdown: %s", e.output) + except CoreCommandError: + logger.exception("error during shutdown") self.localname = None diff --git a/daemon/core/netns/vnet.py b/daemon/core/netns/vnet.py index 8467a87d..545ca648 100644 --- a/daemon/core/netns/vnet.py +++ b/daemon/core/netns/vnet.py @@ -4,10 +4,10 @@ Linux Ethernet bridging and ebtables rules. """ import os -import subprocess import threading import time +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNet @@ -272,7 +272,7 @@ class LxBrNet(PyCoreNet): Linux bridge starup logic. :return: nothing - :raises subprocess.CalledProcessError: when there is a command exception + :raises CoreCommandError: when there is a command exception """ utils.check_cmd([constants.BRCTL_BIN, "addbr", self.brname]) @@ -311,8 +311,8 @@ class LxBrNet(PyCoreNet): [constants.EBTABLES_BIN, "-D", "FORWARD", "--logical-in", self.brname, "-j", self.brname], [constants.EBTABLES_BIN, "-X", self.brname] ]) - except subprocess.CalledProcessError as e: - logger.exception("error during shutdown: %s", e.output) + except CoreCommandError: + logger.exception("error during shutdown") # removes veth pairs used for bridge-to-bridge connections for netif in self.netifs(): diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 12784d18..987fdac5 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -7,9 +7,9 @@ import random import shutil import signal import string -import subprocess import threading +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNetIf @@ -189,7 +189,7 @@ class SimpleLxcNode(PyCoreNode): :param list[str]|str args: command to run :return: combined stdout and stderr :rtype: str - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ return self.client.check_cmd(args) @@ -209,14 +209,14 @@ class SimpleLxcNode(PyCoreNode): :param str source: source directory to mount :param str target: target directory to create :return: nothing - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ source = os.path.abspath(source) logger.info("mounting %s at %s" % (source, target)) cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) status, output = self.client.shcmd_result(cmd) if status: - raise subprocess.CalledProcessError(status, cmd, output) + raise CoreCommandError(status, cmd, output) self._mounts.append((source, target)) def umount(self, target): @@ -229,8 +229,8 @@ class SimpleLxcNode(PyCoreNode): logger.info("unmounting: %s", target) try: self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target]) - except subprocess.CalledProcessError as e: - logger.exception("error during unmount: %s", e.output) + except CoreCommandError: + logger.exception("error during unmount") def newifindex(self): """ @@ -339,7 +339,7 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to set hardware address for :param core.misc.ipaddress.MacAddress addr: hardware address to set :return: nothing - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ self._netif[ifindex].sethwaddr(addr) if self.up: @@ -372,7 +372,7 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to delete address from :param str addr: address to delete from interface :return: nothing - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ try: self._netif[ifindex].deladdr(addr) @@ -389,7 +389,7 @@ class SimpleLxcNode(PyCoreNode): :param int ifindex: index of interface to delete address types from :param tuple[str] address_types: address types to delete :return: nothing - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ interface_name = self.ifname(ifindex) addresses = self.client.getaddr(interface_name, rescan=True) @@ -488,7 +488,7 @@ class SimpleLxcNode(PyCoreNode): :param str srcname: source file name :param str filename: file name to add :return: nothing - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ logger.info("adding file from %s to %s", srcname, filename) directory = os.path.dirname(filename) @@ -496,7 +496,7 @@ class SimpleLxcNode(PyCoreNode): cmd = 'mkdir -p "%s" && mv "%s" "%s" && sync' % (directory, srcname, filename) status, output = self.client.shcmd_result(cmd) if status: - raise subprocess.CalledProcessError(status, cmd, output) + raise CoreCommandError(status, cmd, output) class LxcNode(SimpleLxcNode): diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 5b61decb..5d5ebea0 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -6,10 +6,10 @@ by invoking the vcmd shell command. """ import os -import subprocess import vcmd +from core import CoreCommandError from core import constants from core import logger from core.misc import utils @@ -106,11 +106,11 @@ class VnodeClient(object): :param list[str]|str args: command to run :return: combined stdout and stderr :rtype: str - :raises subprocess.CalledProcessError: when there is a non-zero exit status + :raises core.CoreCommandError: when there is a non-zero exit status """ status, output = self.cmd_output(args) if status != 0: - raise subprocess.CalledProcessError(status, args, output) + raise CoreCommandError(status, args, output) return output.strip() def popen(self, args): diff --git a/daemon/core/phys/pnodes.py b/daemon/core/phys/pnodes.py index 4e47c71f..eb3d9bbb 100644 --- a/daemon/core/phys/pnodes.py +++ b/daemon/core/phys/pnodes.py @@ -6,6 +6,7 @@ import os import subprocess import threading +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNode @@ -91,11 +92,11 @@ class PhysicalNode(PyCoreNode): :param list[str]|str args: command to run :return: combined stdout and stderr :rtype: str - :raises subprocess.CalledProcessError: when a non-zero exit status occurs + :raises CoreCommandError: when a non-zero exit status occurs """ status, output = self.cmd_output(args) if status: - raise subprocess.CalledProcessError(status, args, output) + raise CoreCommandError(status, args, output) return output.strip() def shcmd(self, cmdstr, sh="/bin/sh"): @@ -224,8 +225,8 @@ class PhysicalNode(PyCoreNode): logger.info("unmounting '%s'" % target) try: self.check_cmd([constants.UMOUNT_BIN, "-l", target]) - except subprocess.CalledProcessError as e: - logger.exception("unmounting failed for %s: %s", target, e.output) + except CoreCommandError: + logger.exception("unmounting failed for %s", target) def opennodefile(self, filename, mode="w"): dirname, basename = os.path.split(filename) diff --git a/daemon/core/service.py b/daemon/core/service.py index 385ca524..c54d8c4a 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -6,10 +6,10 @@ The CoreServices class handles configuration messages for sending a list of available services to the GUI and for configuring individual services. """ -import subprocess import time from itertools import repeat +from core import CoreCommandError from core import logger from core.conf import Configurable from core.conf import ConfigurableManager @@ -413,7 +413,7 @@ class CoreServices(ConfigurableManager): logger.info("validating service %s using: %s", service._name, args) try: node.check_cmd(args) - except subprocess.CalledProcessError: + except CoreCommandError: logger.exception("validate command failed") status = -1 @@ -444,7 +444,7 @@ class CoreServices(ConfigurableManager): for args in service._shutdown: try: node.check_cmd(args) - except subprocess.CalledProcessError: + except CoreCommandError: logger.exception("error running stop command %s", args) # TODO: determine if its ok to just return the bad exit status status = "-1" @@ -756,8 +756,8 @@ class CoreServices(ConfigurableManager): for args in cmds: try: node.check_cmd(args) - except subprocess.CalledProcessError: - logger.exception("error starting command %s", args) + except CoreCommandError: + logger.exception("error starting command") fail += "Start %s(%s)," % (s._name, args) if event_type == EventTypes.PAUSE.value: status = self.validatenodeservice(node, s, services) diff --git a/daemon/core/services/utility.py b/daemon/core/services/utility.py index 87289639..6049c9a5 100644 --- a/daemon/core/services/utility.py +++ b/daemon/core/services/utility.py @@ -3,8 +3,8 @@ utility.py: defines miscellaneous utility services. """ import os -import subprocess +from core import CoreCommandError from core import constants from core.misc import utils from core.misc.ipaddress import Ipv4Prefix @@ -419,7 +419,7 @@ class HttpService(UtilService): """ try: status, result = utils.cmd_output(['a2query', '-v']) - except subprocess.CalledProcessError: + except CoreCommandError: status = -1 if status == 0 and result[:3] == '2.4': diff --git a/daemon/core/xen/xen.py b/daemon/core/xen/xen.py index 1cdbf6f0..95ae72fe 100644 --- a/daemon/core/xen/xen.py +++ b/daemon/core/xen/xen.py @@ -13,6 +13,7 @@ import threading import crypt +from core import CoreCommandError from core import constants from core import logger from core.coreobj import PyCoreNetIf @@ -263,7 +264,7 @@ class XenNode(PyCoreNode): if self.booted: utils.check_cmd([XM_PATH, "destroy", self.vmname]) self.booted = False - except (OSError, subprocess.CalledProcessError): + except CoreCommandError: # ignore this error too, the VM may have exited already logger.exception("error during shutdown") From ec79c7dba383cbc031542fbb8294482e8f03c6fa Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 5 Mar 2018 09:20:49 -0800 Subject: [PATCH 053/152] removed some exceptions that were logged but ignore within services --- daemon/core/service.py | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/daemon/core/service.py b/daemon/core/service.py index c54d8c4a..c45cadf3 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -292,10 +292,7 @@ class CoreServices(ConfigurableManager): logger.info("starting service %s (%s)", service._name, service._startindex) for directory in service._dirs: - try: - node.privatedir(directory) - except: - logger.exception("Error making node %s dir %s", node.name, directory) + node.privatedir(directory) for filename in service.getconfigfilenames(node.objid, services): cfg = service.generateconfig(node, filename, services) @@ -305,11 +302,8 @@ class CoreServices(ConfigurableManager): return for args in service.getstartup(node, services): - try: - # TODO: this wait=False can be problematic! - node.cmd(args, wait=False) - except: - logger.exception("error starting command %s", args) + # TODO: this wait=False can be problematic! + node.cmd(args, wait=False) def bootnodecustomservice(self, node, service, services, use_startup_service): """ @@ -322,13 +316,9 @@ class CoreServices(ConfigurableManager): :param bool use_startup_service: flag to use startup services or not :return: nothing """ - logger.info("starting service(%s) %s (%s)(custom)", - service, service._name, service._startindex) + logger.info("starting service(%s) %s (%s)(custom)", service, service._name, service._startindex) for directory in service._dirs: - try: - node.privatedir(directory) - except: - logger.exception("error making node %s dir %s", node.name, directory) + node.privatedir(directory) logger.info("service configurations: %s", service._configs) for i, filename in enumerate(service._configs): @@ -351,11 +341,8 @@ class CoreServices(ConfigurableManager): return for args in service._startup: - try: - # TODO: this wait=False can be problematic! - node.cmd(args, wait=False) - except: - logger.exception("error starting command %s", args) + # TODO: this wait=False can be problematic! + node.cmd(args, wait=False) def copyservicefile(self, node, filename, cfg): """ @@ -776,11 +763,8 @@ class CoreServices(ConfigurableManager): cfg = self.getservicefiledata(s, filename) if cfg is None: cfg = s.generateconfig(node, filename, services) - try: - node.nodefile(filename, cfg) - except: - logger.exception("error in configure file: %s", filename) - fail += "%s," % s._name + + node.nodefile(filename, cfg) fail_data = "" if len(fail) > 0: From 4518136cd77ec946a7b61158e1b9979afd6437d9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 5 Mar 2018 11:54:23 -0800 Subject: [PATCH 054/152] fixed bad ignore for Makefiles under the kernel directory --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 46a93660..2a2aeb33 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .version .version.date Makefile +!kernel/**/Makefile Makefile.in aclocal.m4 autom4te.cache @@ -13,7 +14,6 @@ config.h.in config.log config.status configure -core-*.tar.gz debian stamp-h1 @@ -36,6 +36,7 @@ coverage.xml # ignore package files *.rpm *.deb +*.tar.gz # pytest cache files .cache From bc1e3e70c942675712ef779860a5b7c62a586aae Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Mar 2018 12:54:19 -0800 Subject: [PATCH 055/152] initial pass at removing bsd and code related to using bsd nodes --- Makefile.am | 2 - bootstrap.sh | 22 +- configure.ac | 34 +- daemon/core/bsd/__init__.py | 0 daemon/core/bsd/netgraph.py | 89 - daemon/core/bsd/nodes.py | 212 - daemon/core/bsd/vnet.py | 206 - daemon/core/bsd/vnode.py | 386 - daemon/core/service.py | 6 +- daemon/core/services/nrl.py | 5 +- daemon/core/services/utility.py | 46 +- daemon/core/session.py | 2 +- daemon/sbin/core-daemon | 6 - doc/constants.txt | 6 +- doc/devguide.rst | 165 +- doc/install.rst | 282 +- doc/intro.rst | 82 +- doc/performance.rst | 14 +- doc/usage.rst | 173 +- gui/Makefile.am | 6 +- gui/api.tcl | 96 +- gui/cfgparse.tcl | 90 +- gui/configs/sample5-mgen.imn | 6 +- gui/editor.tcl | 276 +- gui/exec.tcl | 115 +- gui/filemgmt.tcl | 54 +- gui/linkcfg.tcl | 60 +- gui/mobility.tcl | 28 +- gui/util.tcl | 51 +- gui/widget.tcl | 373 +- kernel/freebsd/4.11-R-CORE.diff | 7150 ------------------ kernel/freebsd/README.txt | 24 - kernel/freebsd/freebsd7-config-CORE | 20 - kernel/freebsd/freebsd7-config-COREDEBUG | 22 - kernel/freebsd/freebsd8-config-CORE | 11 - kernel/freebsd/imunes-8.0-RELEASE.diff | 372 - kernel/freebsd/ng_pipe/Makefile | 27 - kernel/freebsd/ng_pipe/README | 21 - kernel/freebsd/ng_pipe/ng_pipe.c | 1170 --- kernel/freebsd/ng_pipe/ng_pipe.h | 171 - kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c | 1277 ---- kernel/freebsd/ng_wlan/Makefile | 27 - kernel/freebsd/ng_wlan/README | 50 - kernel/freebsd/ng_wlan/ng_wlan.c | 1315 ---- kernel/freebsd/ng_wlan/ng_wlan.h | 109 - kernel/freebsd/ng_wlan/ng_wlan_tag.h | 60 - kernel/freebsd/symlinks-8.1-RELEASE.diff | 78 - kernel/freebsd/vimage/Makefile | 14 - kernel/freebsd/vimage/vimage.8 | 195 - kernel/freebsd/vimage/vimage.c | 390 - kernel/freebsd/vimage_7-CORE.diff | 3077 -------- packaging/bsd/core-kernel-deinstall-4.11.sh | 7 - packaging/bsd/core-kernel-deinstall-8.x.sh | 21 - packaging/bsd/core-kernel-pkgcreate.sh | 96 - packaging/bsd/core-kernel-preinstall-4.11.sh | 18 - packaging/bsd/core-kernel-preinstall-8.x.sh | 27 - packaging/bsd/core-kernel.pkgdesc | 1 - packaging/bsd/core-kernel.pkgdesclong | 1 - packaging/bsd/core-pkgcreate.sh | 68 - packaging/bsd/core.pkgdesc | 1 - packaging/bsd/core.pkgdesclong | 3 - scripts/Makefile.am | 12 +- 62 files changed, 720 insertions(+), 18008 deletions(-) delete mode 100644 daemon/core/bsd/__init__.py delete mode 100644 daemon/core/bsd/netgraph.py delete mode 100644 daemon/core/bsd/nodes.py delete mode 100644 daemon/core/bsd/vnet.py delete mode 100644 daemon/core/bsd/vnode.py delete mode 100644 kernel/freebsd/4.11-R-CORE.diff delete mode 100644 kernel/freebsd/README.txt delete mode 100644 kernel/freebsd/freebsd7-config-CORE delete mode 100644 kernel/freebsd/freebsd7-config-COREDEBUG delete mode 100644 kernel/freebsd/freebsd8-config-CORE delete mode 100644 kernel/freebsd/imunes-8.0-RELEASE.diff delete mode 100644 kernel/freebsd/ng_pipe/Makefile delete mode 100644 kernel/freebsd/ng_pipe/README delete mode 100644 kernel/freebsd/ng_pipe/ng_pipe.c delete mode 100644 kernel/freebsd/ng_pipe/ng_pipe.h delete mode 100644 kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c delete mode 100644 kernel/freebsd/ng_wlan/Makefile delete mode 100644 kernel/freebsd/ng_wlan/README delete mode 100644 kernel/freebsd/ng_wlan/ng_wlan.c delete mode 100644 kernel/freebsd/ng_wlan/ng_wlan.h delete mode 100644 kernel/freebsd/ng_wlan/ng_wlan_tag.h delete mode 100644 kernel/freebsd/symlinks-8.1-RELEASE.diff delete mode 100644 kernel/freebsd/vimage/Makefile delete mode 100644 kernel/freebsd/vimage/vimage.8 delete mode 100644 kernel/freebsd/vimage/vimage.c delete mode 100644 kernel/freebsd/vimage_7-CORE.diff delete mode 100755 packaging/bsd/core-kernel-deinstall-4.11.sh delete mode 100755 packaging/bsd/core-kernel-deinstall-8.x.sh delete mode 100755 packaging/bsd/core-kernel-pkgcreate.sh delete mode 100755 packaging/bsd/core-kernel-preinstall-4.11.sh delete mode 100755 packaging/bsd/core-kernel-preinstall-8.x.sh delete mode 100644 packaging/bsd/core-kernel.pkgdesc delete mode 100644 packaging/bsd/core-kernel.pkgdesclong delete mode 100755 packaging/bsd/core-pkgcreate.sh delete mode 100644 packaging/bsd/core.pkgdesc delete mode 100644 packaging/bsd/core.pkgdesclong diff --git a/Makefile.am b/Makefile.am index 271a6c13..26fda233 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,7 +31,6 @@ EXTRA_DIST = bootstrap.sh LICENSE \ README-Xen Changelog kernel \ python-prefix.py revision.sh \ .version .version.date \ - packaging/bsd \ packaging/deb/compat \ packaging/deb/copyright \ packaging/deb/changelog \ @@ -55,7 +54,6 @@ MAINTAINERCLEANFILES = \ # don't include svn dirs in source tarball dist-hook: rm -rf `find $(distdir)/kernel -name .svn` - rm -rf $(distdir)/packaging/bsd/.svn # build a source RPM .PHONY: rpm diff --git a/bootstrap.sh b/bootstrap.sh index d1c2f227..ab3d741c 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -7,16 +7,17 @@ # Bootstrap the autoconf system. # -if [ x$1 = x ]; then # PASS +# PASS +if [ x$1 = x ]; then echo "Bootstrapping the autoconf system..." -# echo " These autotools programs should be installed for this script to work:" -# echo " aclocal, libtoolize, autoheader, automake, autoconf" echo "(Messages below about copying and installing files are normal.)" -elif [ x$1 = xclean ]; then # clean - take out the trash +# clean - take out the trash +elif [ x$1 = xclean ]; then echo "Cleaning up the autoconf mess..." - rm -rf autom4te.cache config BSDmakefile + rm -rf autom4te.cache config exit 0; -else # help text +# help text +else echo "usage: $0 [clean]" echo -n " Use this script to bootstrap the autoconf build system prior to " echo "running the " @@ -29,15 +30,6 @@ if ! [ -d "config" ]; then mkdir config fi -# on FreeBSD, discourage use of make -UNAME=`uname` -if [ x${UNAME} = xFreeBSD ]; then - echo "all:" > BSDmakefile - echo ' @echo "Please use GNU make instead by typing:"' >> BSDmakefile - echo ' @echo " gmake"' >> BSDmakefile - echo ' @echo ""' >> BSDmakefile -fi - # bootstrapping echo "(1/4) Running aclocal..." && aclocal -I config \ && echo "(2/4) Running autoheader..." && autoheader \ diff --git a/configure.ac b/configure.ac index b309eb30..9bd21586 100644 --- a/configure.ac +++ b/configure.ac @@ -104,7 +104,6 @@ AC_ARG_ENABLE([daemon], AC_SUBST(enable_daemon) if test "x$enable_daemon" = "xno"; then want_python=no - want_bsd=no want_linux_netns=no fi @@ -211,18 +210,9 @@ if test "x$enable_daemon" = "xyes" ; then fi # Host-specific detection -want_linux_netns=no -want_bsd=no -if test `uname -s` = "FreeBSD"; then - want_bsd=yes - AC_CHECK_PROGS(gmake) - # FreeBSD fix for linking libev port below - CFLAGS="$CFLAGS -L/usr/local/lib" -else - want_linux_netns=yes -fi +want_linux_netns=yes + if test "x$want_python" = "xno"; then - want_bsd=no want_linux_netns=no fi @@ -283,17 +273,6 @@ if test "x$want_linux_netns" = "xyes"; then AC_MSG_ERROR([Could not locate tc (from iproute package).]) fi fi -if test "x$want_bsd" = "xyes"; then - if test "x$ifconfig_path" = "xno" ; then - AC_MSG_ERROR([Could not locate the 'ifconfig' utility.]) - fi - if test "x$ngctl_path" = "xno" ; then - AC_MSG_ERROR([Could not locate the 'ngctl' utility.]) - fi - if test "x$vimage_path" = "xno" ; then - AC_MSG_ERROR([Could not locate the 'vimage' utility.]) - fi -fi AC_ARG_WITH([startup], [AS_HELP_STRING([--with-startup=option], @@ -306,7 +285,6 @@ AC_MSG_RESULT([using startup option $with_startup]) # Variable substitutions AM_CONDITIONAL(WANT_GUI, test x$enable_gui = xyes) AM_CONDITIONAL(WANT_DAEMON, test x$enable_daemon = xyes) -AM_CONDITIONAL(WANT_BSD, test x$want_bsd = xyes) AM_CONDITIONAL(WANT_DOCS, test x$want_docs = xyes) AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes) AM_CONDITIONAL(WANT_NETNS, test x$want_linux_netns = xyes) @@ -370,19 +348,15 @@ ${PACKAGE_STRING} Configuration: Features to build: Python bindings: ${want_python} Linux Namespaces emulation: ${want_linux_netns} - FreeBSD Jails emulation: ${want_bsd} Documentation: ${want_docs} ------------------------------------------------------------------------" -if test "x${want_bsd}" = "xyes" ; then - # TODO: more sophisticated checks of gmake vs make - echo ">>> NOTE: on FreeBSD you should use 'gmake' instead of 'make' -------------------------------------------------------------------------" -fi + if test "x${want_linux_netns}" = "xyes" ; then echo "On this platform you should run core-gui as a normal user. ------------------------------------------------------------------------" fi + if test "x${progs_missing}" != "x" ; then echo ">>> NOTE: the following programs could not be found:" echo " $progs_missing diff --git a/daemon/core/bsd/__init__.py b/daemon/core/bsd/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/daemon/core/bsd/netgraph.py b/daemon/core/bsd/netgraph.py deleted file mode 100644 index 59e47238..00000000 --- a/daemon/core/bsd/netgraph.py +++ /dev/null @@ -1,89 +0,0 @@ -""" -netgraph.py: Netgraph helper functions; for now these are wrappers around -ngctl commands. -""" - -import subprocess - -from core import constants -from core.misc import utils - -utils.check_executables([constants.NGCTL_BIN]) - - -def createngnode(node_type, hookstr, name=None): - """ - Create a new Netgraph node of type and optionally assign name. The - hook string hookstr should contain two names. This is a string so - other commands may be inserted after the two names. - Return the name and netgraph ID of the new node. - - :param node_type: node type to create - :param hookstr: hook string - :param name: name - :return: name and id - :rtype: tuple - """ - hook1 = hookstr.split()[0] - ngcmd = "mkpeer %s %s \n show .%s" % (node_type, hookstr, hook1) - cmd = [constants.NGCTL_BIN, "-f", "-"] - cmdid = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - # err will always be None - result, err = cmdid.communicate(input=ngcmd) - status = cmdid.wait() - if status > 0: - raise Exception("error creating Netgraph node %s (%s): %s" % (node_type, ngcmd, result)) - results = result.split() - ngname = results[1] - ngid = results[5] - if name: - subprocess.check_call([constants.NGCTL_BIN, "name", "[0x%s]:" % ngid, name]) - return ngname, ngid - - -def destroyngnode(name): - """ - Shutdown a Netgraph node having the given name. - - :param str name: node name - :return: nothing - """ - subprocess.check_call([constants.NGCTL_BIN, "shutdown", "%s:" % name]) - - -def connectngnodes(name1, name2, hook1, hook2): - """ - Connect two hooks of two Netgraph nodes given by their names. - - :param str name1: name one - :param str name2: name two - :param str hook1: hook one - :param str hook2: hook two - :return: nothing - """ - node1 = "%s:" % name1 - node2 = "%s:" % name2 - subprocess.check_call([constants.NGCTL_BIN, "connect", node1, node2, hook1, hook2]) - - -def ngmessage(name, msg): - """ - Send a Netgraph message to the node named name. - - :param str name: node name - :param list msg: message - :return: nothing - """ - cmd = [constants.NGCTL_BIN, "msg", "%s:" % name] + msg - subprocess.check_call(cmd) - - -def ngloadkernelmodule(name): - """ - Load a kernel module by invoking kldstat. This is needed for the - ng_ether module which automatically creates Netgraph nodes when loaded. - - :param str name: module name - :return: nothing - """ - utils.check_cmd(["kldload", name]) diff --git a/daemon/core/bsd/nodes.py b/daemon/core/bsd/nodes.py deleted file mode 100644 index fc265ee6..00000000 --- a/daemon/core/bsd/nodes.py +++ /dev/null @@ -1,212 +0,0 @@ -""" -nodes.py: definition of CoreNode classes and other node classes that inherit -from the CoreNode, implementing specific node types. -""" - -import socket -import subprocess - -from core import constants -from core import logger -from core.api import coreapi -from core.bsd.netgraph import connectngnodes -from core.bsd.netgraph import ngloadkernelmodule -from core.bsd.vnet import NetgraphNet -from core.bsd.vnet import NetgraphPipeNet -from core.bsd.vnode import JailNode -from core.enumerations import LinkTlvs -from core.enumerations import LinkTypes -from core.enumerations import NodeTypes -from core.enumerations import RegisterTlvs -from core.misc import ipaddress -from core.misc import utils - -utils.check_executables([constants.IFCONFIG_BIN]) - - -class CoreNode(JailNode): - apitype = NodeTypes.DEFAULT.value - - -class PtpNet(NetgraphPipeNet): - def tonodemsg(self, flags): - """ - Do not generate a Node Message for point-to-point links. They are - built using a link message instead. - """ - pass - - def tolinkmsgs(self, flags): - """ - Build CORE API TLVs for a point-to-point link. One Link message - describes this network. - """ - tlvdata = "" - if len(self._netif) != 2: - return tlvdata - (if1, if2) = self._netif.items() - if1 = if1[1] - if2 = if2[1] - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, if1.node.objid) - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, if2.node.objid) - delay = if1.getparam("delay") - bw = if1.getparam("bw") - loss = if1.getparam("loss") - duplicate = if1.getparam("duplicate") - jitter = if1.getparam("jitter") - if delay is not None: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DELAY.value, delay) - if bw is not None: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.BANDWIDTH.value, bw) - if loss is not None: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.PER.value, str(loss)) - if duplicate is not None: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.DUP.value, str(duplicate)) - if jitter is not None: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.JITTER.value, jitter) - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, self.linktype) - - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_NUMBER.value, if1.node.getifindex(if1)) - if if1.hwaddr: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE1_MAC.value, if1.hwaddr) - for addr in if1.addrlist: - ip, sep, mask = addr.partition("/") - mask = int(mask) - if ipaddress.is_ipv4_address(ip): - family = socket.AF_INET - tlvtypeip = LinkTlvs.INTERFACE1_IP4.value - tlvtypemask = LinkTlvs.INTERFACE1_IP4_MASK - else: - family = socket.AF_INET6 - tlvtypeip = LinkTlvs.INTERFACE1_IP6.value - tlvtypemask = LinkTlvs.INTERFACE1_IP6_MASK.value - ipl = socket.inet_pton(family, ip) - tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl)) - tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask) - - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, if2.node.getifindex(if2)) - if if2.hwaddr: - tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_MAC.value, if2.hwaddr) - for addr in if2.addrlist: - ip, sep, mask = addr.partition("/") - mask = int(mask) - if ipaddress.is_ipv4_address(ip): - family = socket.AF_INET - tlvtypeip = LinkTlvs.INTERFACE2_IP4.value - tlvtypemask = LinkTlvs.INTERFACE2_IP4_MASK - else: - family = socket.AF_INET6 - tlvtypeip = LinkTlvs.INTERFACE2_IP6.value - tlvtypemask = LinkTlvs.INTERFACE2_IP6_MASK.value - ipl = socket.inet_pton(family, ip) - tlvdata += coreapi.CoreLinkTlv.pack(tlvtypeip, ipaddress.IpAddress(af=family, address=ipl)) - tlvdata += coreapi.CoreLinkTlv.pack(tlvtypemask, mask) - - msg = coreapi.CoreLinkMessage.pack(flags, tlvdata) - return [msg, ] - - -class SwitchNode(NetgraphNet): - ngtype = "bridge" - nghooks = "link0 link0\nmsg .link0 setpersistent" - apitype = NodeTypes.SWITCH.value - policy = "ACCEPT" - - -class HubNode(NetgraphNet): - ngtype = "hub" - nghooks = "link0 link0\nmsg .link0 setpersistent" - apitype = NodeTypes.HUB.value - policy = "ACCEPT" - - -class WlanNode(NetgraphNet): - ngtype = "wlan" - nghooks = "anchor anchor" - apitype = NodeTypes.WIRELESS_LAN.value - linktype = LinkTypes.WIRELESS.value - policy = "DROP" - - def __init__(self, session, objid=None, name=None, start=True, policy=None): - NetgraphNet.__init__(self, session, objid, name, start, policy) - # wireless model such as basic range - self.model = None - # mobility model such as scripted - self.mobility = None - - def attach(self, netif): - NetgraphNet.attach(self, netif) - if self.model: - netif.poshook = self.model.position_callback - if netif.node is None: - return - x, y, z = netif.node.position.get() - netif.poshook(netif, x, y, z) - - def setmodel(self, model, config): - """ - Mobility and wireless model. - - :param core.mobility.WirelessModel.cls model: model to set - :param dict config: configuration for model - :return: - """ - logger.info("adding model %s" % model.name) - if model.config_type == RegisterTlvs.WIRELESS.value: - self.model = model(session=self.session, objid=self.objid, values=config) - if self.model.position_callback: - for netif in self.netifs(): - netif.poshook = self.model.position_callback - if netif.node is not None: - x, y, z = netif.node.position.get() - netif.poshook(netif, x, y, z) - self.model.setlinkparams() - elif model.config_type == RegisterTlvs.MOBILITY.value: - self.mobility = model(session=self.session, objid=self.objid, values=config) - - -class RJ45Node(NetgraphPipeNet): - apitype = NodeTypes.RJ45.value - policy = "ACCEPT" - - def __init__(self, session, objid, name, start=True): - if start: - ngloadkernelmodule("ng_ether") - NetgraphPipeNet.__init__(self, session, objid, name, start) - if start: - self.setpromisc(True) - - def shutdown(self): - self.setpromisc(False) - NetgraphPipeNet.shutdown(self) - - def setpromisc(self, promisc): - p = "promisc" - if not promisc: - p = "-" + p - subprocess.check_call([constants.IFCONFIG_BIN, self.name, "up", p]) - - def attach(self, netif): - if len(self._netif) > 0: - raise ValueError("RJ45 networks support at most 1 network interface") - NetgraphPipeNet.attach(self, netif) - connectngnodes(self.ngname, self.name, self.gethook(), "lower") - - -class TunnelNode(NetgraphNet): - ngtype = "pipe" - nghooks = "upper lower" - apitype = NodeTypes.TUNNEL.value - policy = "ACCEPT" - - -BSD_NODES = { - NodeTypes.DEFAULT: CoreNode, - NodeTypes.SWITCH: SwitchNode, - NodeTypes.HUB: HubNode, - NodeTypes.WIRELESS_LAN: WlanNode, - NodeTypes.RJ45: RJ45Node, - NodeTypes.TUNNEL: TunnelNode, - NodeTypes.PEER_TO_PEER: PtpNet, - NodeTypes.CONTROL_NET: None -} diff --git a/daemon/core/bsd/vnet.py b/daemon/core/bsd/vnet.py deleted file mode 100644 index 5142cd7c..00000000 --- a/daemon/core/bsd/vnet.py +++ /dev/null @@ -1,206 +0,0 @@ -""" -vnet.py: NetgraphNet and NetgraphPipeNet classes that implement virtual networks -using the FreeBSD Netgraph subsystem. -""" - -from core import logger -from core.bsd.netgraph import connectngnodes -from core.bsd.netgraph import createngnode -from core.bsd.netgraph import destroyngnode -from core.bsd.netgraph import ngmessage -from core.coreobj import PyCoreNet - - -class NetgraphNet(PyCoreNet): - ngtype = None - nghooks = () - - def __init__(self, session, objid=None, name=None, start=True, policy=None): - PyCoreNet.__init__(self, session, objid, name) - if name is None: - name = str(self.objid) - if policy is not None: - self.policy = policy - self.name = name - self.ngname = "n_%s_%s" % (str(self.objid), self.session.session_id) - self.ngid = None - self._netif = {} - self._linked = {} - self.up = False - if start: - self.startup() - - def startup(self): - tmp, self.ngid = createngnode(node_type=self.ngtype, hookstr=self.nghooks, name=self.ngname) - self.up = True - - def shutdown(self): - if not self.up: - return - self.up = False - while self._netif: - k, netif = self._netif.popitem() - if netif.pipe: - pipe = netif.pipe - netif.pipe = None - pipe.shutdown() - else: - netif.shutdown() - self._netif.clear() - self._linked.clear() - del self.session - destroyngnode(self.ngname) - - def attach(self, netif): - """ - Attach an interface to this netgraph node. Create a pipe between - the interface and the hub/switch/wlan node. - (Note that the PtpNet subclass overrides this method.) - """ - if self.up: - pipe = self.session.addobj(cls=NetgraphPipeNet, start=True) - pipe.attach(netif) - hook = "link%d" % len(self._netif) - pipe.attachnet(self, hook) - PyCoreNet.attach(self, netif) - - def detach(self, netif): - PyCoreNet.detach(self, netif) - - def linked(self, netif1, netif2): - # check if the network interfaces are attached to this network - if self._netif[netif1] != netif1: - raise ValueError("inconsistency for netif %s" % netif1.name) - if self._netif[netif2] != netif2: - raise ValueError("inconsistency for netif %s" % netif2.name) - - try: - linked = self._linked[netif1][netif2] - except KeyError: - linked = False - self._linked[netif1][netif2] = linked - - return linked - - def unlink(self, netif1, netif2): - if not self.linked(netif1, netif2): - return - msg = ["unlink", "{", "node1=0x%s" % netif1.pipe.ngid] - msg += ["node2=0x%s" % netif2.pipe.ngid, "}"] - ngmessage(self.ngname, msg) - self._linked[netif1][netif2] = False - - def link(self, netif1, netif2): - if self.linked(netif1, netif2): - return - msg = ["link", "{", "node1=0x%s" % netif1.pipe.ngid] - msg += ["node2=0x%s" % netif2.pipe.ngid, "}"] - ngmessage(self.ngname, msg) - self._linked[netif1][netif2] = True - - def linknet(self, net): - """ - Link this bridge with another by creating a veth pair and installing - each device into each bridge. - """ - raise NotImplementedError - - def linkconfig(self, netif, bw=None, delay=None, - loss=None, duplicate=None, jitter=None, netif2=None): - """ - Set link effects by modifying the pipe connected to an interface. - """ - if not netif.pipe: - logger.warn("linkconfig for %s but interface %s has no pipe", self.name, netif.name) - return - return netif.pipe.linkconfig(netif, bw, delay, loss, duplicate, jitter, netif2) - - -class NetgraphPipeNet(NetgraphNet): - ngtype = "pipe" - nghooks = "upper lower" - - def __init__(self, session, objid=None, name=None, start=True, policy=None): - NetgraphNet.__init__(self, session, objid, name, start, policy) - if start: - # account for Ethernet header - ngmessage(self.ngname, ["setcfg", "{", "header_offset=14", "}"]) - - def attach(self, netif): - """ - Attach an interface to this pipe node. - The first interface is connected to the "upper" hook, the second - connected to the "lower" hook. - """ - if len(self._netif) > 1: - raise ValueError("Netgraph pipes support at most 2 network interfaces") - if self.up: - hook = self.gethook() - connectngnodes(self.ngname, netif.localname, hook, netif.hook) - if netif.pipe: - raise ValueError("Interface %s already attached to pipe %s" % (netif.name, netif.pipe.name)) - netif.pipe = self - self._netif[netif] = netif - self._linked[netif] = {} - - def attachnet(self, net, hook): - """ - Attach another NetgraphNet to this pipe node. - """ - localhook = self.gethook() - connectngnodes(self.ngname, net.ngname, localhook, hook) - - def gethook(self): - """ - Returns the first hook (e.g. "upper") then the second hook - (e.g. "lower") based on the number of connections. - """ - hooks = self.nghooks.split() - if len(self._netif) == 0: - return hooks[0] - else: - return hooks[1] - - def linkconfig(self, netif, bw=None, delay=None, - loss=None, duplicate=None, jitter=None, netif2=None): - """ - Set link effects by sending a Netgraph setcfg message to the pipe. - """ - netif.setparam("bw", bw) - netif.setparam("delay", delay) - netif.setparam("loss", loss) - netif.setparam("duplicate", duplicate) - netif.setparam("jitter", jitter) - if not self.up: - return - params = [] - upstream = [] - downstream = [] - if bw is not None: - if str(bw) == "0": - bw = "-1" - params += ["bandwidth=%s" % bw, ] - if delay is not None: - if str(delay) == "0": - delay = "-1" - params += ["delay=%s" % delay, ] - if loss is not None: - if str(loss) == "0": - loss = "-1" - upstream += ["BER=%s" % loss, ] - downstream += ["BER=%s" % loss, ] - if duplicate is not None: - if str(duplicate) == "0": - duplicate = "-1" - upstream += ["duplicate=%s" % duplicate, ] - downstream += ["duplicate=%s" % duplicate, ] - if jitter: - logger.warn("jitter parameter ignored for link %s", self.name) - if len(params) > 0 or len(upstream) > 0 or len(downstream) > 0: - setcfg = ["setcfg", "{", ] + params - if len(upstream) > 0: - setcfg += ["upstream={", ] + upstream + ["}", ] - if len(downstream) > 0: - setcfg += ["downstream={", ] + downstream + ["}", ] - setcfg += ["}", ] - ngmessage(self.ngname, setcfg) diff --git a/daemon/core/bsd/vnode.py b/daemon/core/bsd/vnode.py deleted file mode 100644 index f4846d1c..00000000 --- a/daemon/core/bsd/vnode.py +++ /dev/null @@ -1,386 +0,0 @@ -""" -vnode.py: SimpleJailNode and JailNode classes that implement the FreeBSD -jail-based virtual node. -""" - -import os -import subprocess -import threading - -from core import constants -from core import logger -from core.bsd.netgraph import createngnode -from core.bsd.netgraph import destroyngnode -from core.coreobj import PyCoreNetIf -from core.coreobj import PyCoreNode -from core.misc import utils - -utils.check_executables([constants.IFCONFIG_BIN, constants.VIMAGE_BIN]) - - -class VEth(PyCoreNetIf): - def __init__(self, node, name, localname, mtu=1500, net=None, - start=True): - PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) - # name is the device name (e.g. ngeth0, ngeth1, etc.) before it is - # installed in a node; the Netgraph name is renamed to localname - # e.g. before install: name = ngeth0 localname = n0_0_123 - # after install: name = eth0 localname = n0_0_123 - self.localname = localname - self.ngid = None - self.net = None - self.pipe = None - self.addrlist = [] - self.hwaddr = None - self.up = False - self.hook = "ether" - if start: - self.startup() - - def startup(self): - hookstr = "%s %s" % (self.hook, self.hook) - ngname, ngid = createngnode(node_type="eiface", hookstr=hookstr, name=self.localname) - self.name = ngname - self.ngid = ngid - subprocess.check_call([constants.IFCONFIG_BIN, ngname, "up"]) - self.up = True - - def shutdown(self): - if not self.up: - return - destroyngnode(self.localname) - self.up = False - - def attachnet(self, net): - if self.net: - self.detachnet() - self.net = None - net.attach(self) - self.net = net - - def detachnet(self): - if self.net is not None: - self.net.detach(self) - - def addaddr(self, addr): - self.addrlist.append(addr) - - def deladdr(self, addr): - self.addrlist.remove(addr) - - def sethwaddr(self, addr): - self.hwaddr = addr - - -class TunTap(PyCoreNetIf): - """ - TUN/TAP virtual device in TAP mode - """ - - def __init__(self, node, name, localname, mtu=None, net=None, start=True): - raise NotImplementedError - - -class SimpleJailNode(PyCoreNode): - def __init__(self, session, objid=None, name=None, nodedir=None): - PyCoreNode.__init__(self, session, objid, name) - self.nodedir = nodedir - self.pid = None - self.up = False - self.lock = threading.RLock() - self._mounts = [] - - def startup(self): - if self.up: - raise Exception("already up") - vimg = [constants.VIMAGE_BIN, "-c", self.name] - try: - os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg) - except OSError: - raise Exception("vimage command not found while running: %s" % vimg) - logger.info("bringing up loopback interface") - self.cmd([constants.IFCONFIG_BIN, "lo0", "127.0.0.1"]) - logger.info("setting hostname: %s", self.name) - self.cmd(["hostname", self.name]) - self.cmd([constants.SYSCTL_BIN, "vfs.morphing_symlinks=1"]) - self.up = True - - def shutdown(self): - if not self.up: - return - for netif in self.netifs(): - netif.shutdown() - self._netif.clear() - del self.session - vimg = [constants.VIMAGE_BIN, "-d", self.name] - try: - os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, *vimg) - except OSError: - raise Exception("vimage command not found while running: %s" % vimg) - self.up = False - - def cmd(self, args, wait=True): - if wait: - mode = os.P_WAIT - else: - mode = os.P_NOWAIT - tmp = subprocess.call([constants.VIMAGE_BIN, self.name] + args, cwd=self.nodedir) - if not wait: - tmp = None - if tmp: - logger.warn("cmd exited with status %s: %s", tmp, str(args)) - return tmp - - def cmdresult(self, args, wait=True): - cmdid, cmdin, cmdout, cmderr = self.popen(args) - result = cmdout.read() - result += cmderr.read() - cmdin.close() - cmdout.close() - cmderr.close() - if wait: - status = cmdid.wait() - else: - status = 0 - return status, result - - def popen(self, args): - cmd = [constants.VIMAGE_BIN, self.name] - cmd.extend(args) - tmp = subprocess.Popen(cmd, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, cwd=self.nodedir) - return tmp, tmp.stdin, tmp.stdout, tmp.stderr - - def icmd(self, args): - return os.spawnlp(os.P_WAIT, constants.VIMAGE_BIN, constants.VIMAGE_BIN, self.name, *args) - - def term(self, sh="/bin/sh"): - return os.spawnlp(os.P_WAIT, "xterm", "xterm", "-ut", - "-title", self.name, "-e", constants.VIMAGE_BIN, self.name, sh) - - def termcmdstring(self, sh="/bin/sh"): - """ - We add "sudo" to the command string because the GUI runs as a - normal user. - """ - return "cd %s && sudo %s %s %s" % (self.nodedir, constants.VIMAGE_BIN, self.name, sh) - - def shcmd(self, cmdstr, sh="/bin/sh"): - return self.cmd([sh, "-c", cmdstr]) - - def boot(self): - pass - - def mount(self, source, target): - source = os.path.abspath(source) - logger.info("mounting %s at %s", source, target) - self.addsymlink(path=target, file=None) - - def umount(self, target): - logger.info("unmounting %s", target) - - def newveth(self, ifindex=None, ifname=None, net=None): - self.lock.acquire() - try: - if ifindex is None: - ifindex = self.newifindex() - if ifname is None: - ifname = "eth%d" % ifindex - sessionid = self.session.short_session_id() - name = "n%s_%s_%s" % (self.objid, ifindex, sessionid) - localname = name - ifclass = VEth - veth = ifclass(node=self, name=name, localname=localname, - mtu=1500, net=net, start=self.up) - if self.up: - # install into jail - subprocess.check_call([constants.IFCONFIG_BIN, veth.name, "vnet", self.name]) - - # rename from "ngeth0" to "eth0" - self.cmd([constants.IFCONFIG_BIN, veth.name, "name", ifname]) - - veth.name = ifname - try: - self.addnetif(veth, ifindex) - except: - veth.shutdown() - del veth - raise - return ifindex - finally: - self.lock.release() - - def sethwaddr(self, ifindex, addr): - self._netif[ifindex].sethwaddr(addr) - if self.up: - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "link", str(addr)]) - - def addaddr(self, ifindex, addr): - if self.up: - if ":" in addr: - family = "inet6" - else: - family = "inet" - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "alias", str(addr)]) - self._netif[ifindex].addaddr(addr) - - def deladdr(self, ifindex, addr): - try: - self._netif[ifindex].deladdr(addr) - except ValueError: - logger.warn("trying to delete unknown address: %s", addr) - if self.up: - if ":" in addr: - family = "inet6" - else: - family = "inet" - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), family, "-alias", - str(addr)]) - - valid_deladdrtype = ("inet", "inet6", "inet6link") - - def delalladdr(self, ifindex, addrtypes=valid_deladdrtype): - addr = self.getaddr(self.ifname(ifindex), rescan=True) - for t in addrtypes: - if t not in self.valid_deladdrtype: - raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype)) - for a in addr[t]: - self.deladdr(ifindex, a) - # update cached information - self.getaddr(self.ifname(ifindex), rescan=True) - - def ifup(self, ifindex): - if self.up: - self.cmd([constants.IFCONFIG_BIN, self.ifname(ifindex), "up"]) - - def newnetif(self, net=None, addrlist=[], hwaddr=None, - ifindex=None, ifname=None): - self.lock.acquire() - try: - ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net) - if net is not None: - self.attachnet(ifindex, net) - if hwaddr: - self.sethwaddr(ifindex, hwaddr) - for addr in utils.make_tuple(addrlist): - self.addaddr(ifindex, addr) - self.ifup(ifindex) - return ifindex - finally: - self.lock.release() - - def attachnet(self, ifindex, net): - self._netif[ifindex].attachnet(net) - - def detachnet(self, ifindex): - self._netif[ifindex].detachnet() - - def addfile(self, srcname, filename): - shcmd = 'mkdir -p $(dirname "%s") && mv "%s" "%s" && sync' % (filename, srcname, filename) - self.shcmd(shcmd) - - def getaddr(self, ifname, rescan=False): - return None - - def addsymlink(self, path, file): - """ - Create a symbolic link from /path/name/file -> - /tmp/pycore.nnnnn/@.conf/path.name/file - """ - dirname = path - if dirname and dirname[0] == "/": - dirname = dirname[1:] - dirname = dirname.replace("/", ".") - if file: - pathname = os.path.join(path, file) - sym = os.path.join(self.session.session_dir, "@.conf", dirname, file) - else: - pathname = path - sym = os.path.join(self.session.session_dir, "@.conf", dirname) - - if os.path.islink(pathname): - if os.readlink(pathname) == sym: - # this link already exists - silently return - return - os.unlink(pathname) - else: - if os.path.exists(pathname): - logger.warn("did not create symlink for %s since path exists on host", pathname) - return - logger.info("creating symlink %s -> %s", pathname, sym) - os.symlink(sym, pathname) - - -class JailNode(SimpleJailNode): - def __init__(self, session, objid=None, name=None, nodedir=None, bootsh="boot.sh", start=True): - super(JailNode, self).__init__(session=session, objid=objid, name=name, nodedir=nodedir) - self.bootsh = bootsh - if not start: - return - # below here is considered node startup/instantiation code - self.makenodedir() - self.startup() - - def boot(self): - self.session.services.bootnodeservices(self) - - def validate(self): - self.session.services.validatenodeservices(self) - - def startup(self): - self.lock.acquire() - try: - super(JailNode, self).startup() - # self.privatedir("/var/run") - # self.privatedir("/var/log") - finally: - self.lock.release() - - def shutdown(self): - if not self.up: - return - self.lock.acquire() - # services are instead stopped when session enters datacollect state - # self.session.services.stopnodeservices(self) - try: - super(JailNode, self).shutdown() - finally: - self.rmnodedir() - self.lock.release() - - def privatedir(self, path): - if path[0] != "/": - raise ValueError, "path not fully qualified: " + path - hostpath = os.path.join( - self.nodedir, - os.path.normpath(path).strip("/").replace("/", ".") - ) - try: - os.mkdir(hostpath) - except OSError: - pass - except Exception, e: - raise Exception, e - self.mount(hostpath, path) - - def opennodefile(self, filename, mode="w"): - dirname, basename = os.path.split(filename) - # self.addsymlink(path=dirname, file=basename) - if not basename: - raise ValueError("no basename for filename: %s" % filename) - if dirname and dirname[0] == "/": - dirname = dirname[1:] - dirname = dirname.replace("/", ".") - dirname = os.path.join(self.nodedir, dirname) - if not os.path.isdir(dirname): - os.makedirs(dirname, mode=0755) - hostfilename = os.path.join(dirname, basename) - return open(hostfilename, mode) - - def nodefile(self, filename, contents, mode=0644): - f = self.opennodefile(filename, "w") - f.write(contents) - os.chmod(f.name, mode) - f.close() - logger.info("created nodefile: %s; mode: 0%o", f.name, mode) diff --git a/daemon/core/service.py b/daemon/core/service.py index c45cadf3..7956a573 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -87,9 +87,7 @@ class CoreServices(ConfigurableManager): name = "services" config_type = RegisterTlvs.UTILITY.value - _invalid_custom_names = ( - 'core', 'api', 'bsd', 'emane', 'misc', 'netns', 'phys', 'services', 'xen' - ) + _invalid_custom_names = ('core', 'api', 'emane', 'misc', 'netns', 'phys', 'services', 'xen') def __init__(self, session): """ @@ -763,7 +761,7 @@ class CoreServices(ConfigurableManager): cfg = self.getservicefiledata(s, filename) if cfg is None: cfg = s.generateconfig(node, filename, services) - + node.nodefile(filename, cfg) fail_data = "" diff --git a/daemon/core/services/nrl.py b/daemon/core/services/nrl.py index a506f2d0..a2afbfba 100644 --- a/daemon/core/services/nrl.py +++ b/daemon/core/services/nrl.py @@ -298,8 +298,7 @@ class OlsrOrg(NrlService): ####################################### ### Linux specific OLSRd extensions ### ####################################### -# these parameters are only working on linux at the moment, but might become -# useful on BSD in the future +# these parameters are only working on linux at the moment # SrcIpRoutes tells OLSRd to set the Src flag of host routes to the originator-ip # of the node. In addition to this an additional localhost device is created @@ -516,7 +515,7 @@ LinkQualityFishEye 0 # - /lib, followed by /usr/lib # # the examples in this list are for linux, so check if the plugin is -# available if you use windows/BSD. +# available if you use windows. # each plugin should have a README file in it's lib subfolder # LoadPlugin "olsrd_txtinfo.dll" diff --git a/daemon/core/services/utility.py b/daemon/core/services/utility.py index 6049c9a5..c0d3a931 100644 --- a/daemon/core/services/utility.py +++ b/daemon/core/services/utility.py @@ -40,10 +40,8 @@ class IPForwardService(UtilService): def generateconfig(cls, node, filename, services): if os.uname()[0] == "Linux": return cls.generateconfiglinux(node, filename, services) - elif os.uname()[0] == "FreeBSD": - return cls.generateconfigbsd(node, filename, services) else: - raise Exception, "unknown platform" + raise Exception("unknown platform") @classmethod def generateconfiglinux(cls, node, filename, services): @@ -67,17 +65,6 @@ class IPForwardService(UtilService): cfg += "%s -w net.ipv4.conf.%s.rp_filter=0\n" % (constants.SYSCTL_BIN, name) return cfg - @classmethod - def generateconfigbsd(cls, node, filename, services): - return """\ -#!/bin/sh -# auto-generated by IPForward service (utility.py) -%s -w net.inet.ip.forwarding=1 -%s -w net.inet6.ip6.forwarding=1 -%s -w net.inet.icmp.bmcastecho=1 -%s -w net.inet.icmp.icmplim=0 -""" % (constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN, constants.SYSCTL_BIN) - class DefaultRouteService(UtilService): _name = "DefaultRoute" @@ -108,10 +95,8 @@ class DefaultRouteService(UtilService): else: if os.uname()[0] == "Linux": rtcmd = "ip route add default via" - elif os.uname()[0] == "FreeBSD": - rtcmd = "route add -%s" % fam else: - raise Exception, "unknown platform" + raise Exception("unknown platform") return "%s %s" % (rtcmd, net.min_addr()) @@ -132,10 +117,8 @@ class DefaultMulticastRouteService(UtilService): continue if os.uname()[0] == "Linux": rtcmd = "ip route add 224.0.0.0/4 dev" - elif os.uname()[0] == "FreeBSD": - rtcmd = "route add 224.0.0.0/4 -iface" else: - raise Exception, "unknown platform" + raise Exception("unknown platform") cfg += "%s %s\n" % (rtcmd, ifc.name) cfg += "\n" break @@ -176,21 +159,15 @@ class StaticRouteService(UtilService): else: if os.uname()[0] == "Linux": rtcmd = "#/sbin/ip route add %s via" % dst - elif os.uname()[0] == "FreeBSD": - rtcmd = "#/sbin/route add -%s %s" % (fam, dst) else: - raise Exception, "unknown platform" + raise Exception("unknown platform") return "%s %s" % (rtcmd, net.min_addr()) class SshService(UtilService): _name = "SSH" - if os.uname()[0] == "FreeBSD": - _configs = ("startsshd.sh", "sshd_config",) - _dirs = () - else: - _configs = ("startsshd.sh", "/etc/ssh/sshd_config",) - _dirs = ("/etc/ssh", "/var/run/sshd",) + _configs = ("startsshd.sh", "/etc/ssh/sshd_config",) + _dirs = ("/etc/ssh", "/var/run/sshd",) _startup = ("sh startsshd.sh",) _shutdown = ("killall sshd",) _validate = () @@ -201,14 +178,9 @@ class SshService(UtilService): Use a startup script for launching sshd in order to wait for host key generation. """ - if os.uname()[0] == "FreeBSD": - sshcfgdir = node.nodedir - sshstatedir = node.nodedir - sshlibdir = "/usr/libexec" - else: - sshcfgdir = cls._dirs[0] - sshstatedir = cls._dirs[1] - sshlibdir = "/usr/lib/openssh" + sshcfgdir = cls._dirs[0] + sshstatedir = cls._dirs[1] + sshlibdir = "/usr/lib/openssh" if filename == "startsshd.sh": return """\ #!/bin/sh diff --git a/daemon/core/session.py b/daemon/core/session.py index 342adc66..080db896 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -933,7 +933,7 @@ class Session(object): """ with self._objects_lock: for obj in self.objects.itervalues(): - # TODO: PyCoreNode is not the type to check, but there are two types, due to bsd and netns + # TODO: PyCoreNode is not the type to check if isinstance(obj, nodes.PyCoreNode) and not nodeutils.is_node(obj, NodeTypes.RJ45): # add a control interface if configured logger.info("booting node: %s - %s", obj.objid, obj.name) diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index d8e0a6e0..edee959b 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -319,12 +319,6 @@ if __name__ == "__main__": nodeutils.update_node_map(OVS_NODES) - # update with BSD based nodes - if os.uname()[0] == "FreeBSD": - from core.bsd.nodes import BSD_NODES - - nodeutils.update_node_map(BSD_NODES) - # load default services services.load() diff --git a/doc/constants.txt b/doc/constants.txt index eaf63e5a..fea150c4 100644 --- a/doc/constants.txt +++ b/doc/constants.txt @@ -4,15 +4,13 @@ .. |CENTOSVERSION| replace:: 6.x or 7.x -.. |BSDVERSION| replace:: 9.0 - .. |CORERPM| replace:: 1.fc20.x86_64.rpm .. |CORERPM2| replace:: 1.fc20.noarch.rpm .. |COREDEB| replace:: 0ubuntu1_precise_amd64.deb .. |COREDEB2| replace:: 0ubuntu1_precise_all.deb .. |QVER| replace:: quagga-0.99.21mr2.2 -.. |QVERDEB| replace:: quagga-mr_0.99.21mr2.2_amd64.deb +.. |QVERDEB| replace:: quagga-mr_0.99.21mr2.2_amd64.deb .. |QVERRPM| replace:: quagga-0.99.21mr2.2-1.fc16.x86_64.rpm .. |APTDEPS| replace:: bash bridge-utils ebtables iproute libev-dev python @@ -20,6 +18,6 @@ .. |APTDEPS3| replace:: autoconf automake gcc libev-dev make python-dev libreadline-dev pkg-config imagemagick help2man .. |YUMDEPS| replace:: bash bridge-utils ebtables iproute libev python procps-ng net-tools -.. |YUMDEPS2| replace:: tcl tk tkimg +.. |YUMDEPS2| replace:: tcl tk tkimg .. |YUMDEPS3| replace:: autoconf automake make libev-devel python-devel ImageMagick help2man diff --git a/doc/devguide.rst b/doc/devguide.rst index a449ffd0..9b703cca 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -39,10 +39,6 @@ These are being actively developed as of CORE |version|: * *doc* - Documentation for the manual lives here in reStructuredText format. * *packaging* - Control files and script for building CORE packages are here. -These directories are not so actively developed: - -* *kernel* - patches and modules mostly related to FreeBSD. - .. _The_CORE_API: The CORE API @@ -59,8 +55,7 @@ The GUI communicates with the CORE daemon using the API. One emulation server communicates with another using the API. The API also allows other systems to interact with the CORE emulation. The API allows another system to add, remove, or modify nodes and links, and enables executing commands on the emulated -systems. On FreeBSD, the API is used for enhancing the wireless LAN -calculations. Wireless link parameters are updated on-the-fly based on node +systems. Wireless link parameters are updated on-the-fly based on node positions. CORE listens on a local TCP port for API messages. The other system could be @@ -88,7 +83,7 @@ The *vnoded* daemon is the program used to create a new namespace, and listen on a control channel for commands that may instantiate other processes. This daemon runs as PID 1 in the container. It is launched automatically by the CORE daemon. The control channel is a UNIX domain socket usually named -:file:`/tmp/pycore.23098/n3`, for node 3 running on CORE +:file:`/tmp/pycore.23098/n3`, for node 3 running on CORE session 23098, for example. Root privileges are required for creating a new namespace. @@ -107,13 +102,13 @@ using a command such as: :: gnome-terminal -e vcmd -c /tmp/pycore.50160/n1 -- bash - + Similarly, the IPv4 routes Observer Widget will run a command to display the routing table using a command such as: :: vcmd -c /tmp/pycore.50160/n1 -- /sbin/ip -4 ro - + .. index:: core-cleanup @@ -139,7 +134,7 @@ network namespace emulation. tc qdisc show # view the rules that make the wireless LAN work ebtables -L - + Below is a transcript of creating two emulated nodes and connecting them together with a wired link: @@ -179,156 +174,8 @@ Below is a transcript of creating two emulated nodes and connecting them togethe # display connectivity and ping from node 1 to node 2 brctl show vcmd -c /tmp/n1.ctl -- ping 10.0.0.2 - + The above example script can be found as :file:`twonodes.sh` in the :file:`examples/netns` directory. Use *core-cleanup* to clean up after the script. - -.. _FreeBSD_Commands: - -FreeBSD Commands -================ - - -.. index:: vimage -.. index:: ngctl -.. index:: Netgraph -.. _FreeBSD_Kernel_Commands: - -FreeBSD Kernel Commands ------------------------ - -The FreeBSD kernel emulation controlled by CORE is realized through several -userspace commands. The CORE GUI itself could be thought of as a glorified -script that dispatches these commands to build and manage the kernel emulation. - - -* **vimage** - the vimage command, short for "virtual image", is used to - create lightweight virtual machines and execute commands within the virtual - image context. On a FreeBSD CORE machine, see the *vimage(8)* man page for - complete details. The vimage command comes from the VirtNet project which - virtualizes the FreeBSD network stack. - - -* **ngctl** - the ngctl command, short for "netgraph control", creates - Netgraph nodes and hooks, connects them together, and allows for various - interactions with the Netgraph nodes. See the *ngctl(8)* man page for - complete details. The ngctl command is built-in to FreeBSD because the - Netgraph system is part of the kernel. - -Both commands must be run as root. -Some example usage of the *vimage* command follows below. -:: - - vimage # displays the current virtual image - vimage -l # lists running virtual images - vimage e0_n0 ps aux # list the processes running on node 0 - for i in 1 2 3 4 5 - do # execute a command on all nodes - vimage e0_n$i sysctl -w net.inet.ip.redirect=0 - done - - -The *ngctl* command is more complex, due to the variety of Netgraph nodes -available and each of their options. -:: - - ngctl l # list active Netgraph nodes - ngctl show e0_n8: # display node hook information - ngctl msg e0_n0-n1: getstats # get pkt count statistics from a pipe node - ngctl shutdown \\[0x0da3\\]: # shut down unnamed node using hex node ID - - -There are many other combinations of commands not shown here. See the online -manual (man) pages for complete details. - -Below is a transcript of creating two emulated nodes, `router0` and `router1`, -and connecting them together with a link: - -.. index:: create nodes from command-line - -.. index:: command-line - -:: - - # create node 0 - vimage -c e0_n0 - vimage e0_n0 hostname router0 - ngctl mkpeer eiface ether ether - vimage -i e0_n0 ngeth0 eth0 - vimage e0_n0 ifconfig eth0 link 40:00:aa:aa:00:00 - vimage e0_n0 ifconfig lo0 inet localhost - vimage e0_n0 sysctl net.inet.ip.forwarding=1 - vimage e0_n0 sysctl net.inet6.ip6.forwarding=1 - vimage e0_n0 ifconfig eth0 mtu 1500 - - # create node 1 - vimage -c e0_n1 - vimage e0_n1 hostname router1 - ngctl mkpeer eiface ether ether - vimage -i e0_n1 ngeth1 eth0 - vimage e0_n1 ifconfig eth0 link 40:00:aa:aa:0:1 - vimage e0_n1 ifconfig lo0 inet localhost - vimage e0_n1 sysctl net.inet.ip.forwarding=1 - vimage e0_n1 sysctl net.inet6.ip6.forwarding=1 - vimage e0_n1 ifconfig eth0 mtu 1500 - - # create a link between n0 and n1 - ngctl mkpeer eth0@e0_n0: pipe ether upper - ngctl name eth0@e0_n0:ether e0_n0-n1 - ngctl connect e0_n0-n1: eth0@e0_n1: lower ether - ngctl msg e0_n0-n1: setcfg \\ - {{ bandwidth=100000000 delay=0 upstream={ BER=0 dupl - icate=0 } downstream={ BER=0 duplicate=0 } }} - ngctl msg e0_n0-n1: setcfg {{ downstream={ fifo=1 } }} - ngctl msg e0_n0-n1: setcfg {{ downstream={ droptail=1 } }} - ngctl msg e0_n0-n1: setcfg {{ downstream={ queuelen=50 } }} - ngctl msg e0_n0-n1: setcfg {{ upstream={ fifo=1 } }} - ngctl msg e0_n0-n1: setcfg {{ upstream={ droptail=1 } }} - ngctl msg e0_n0-n1: setcfg {{ upstream={ queuelen=50 } }} - - -Other FreeBSD commands that may be of interest: -.. index:: FreeBSD commands - -* **kldstat**, **kldload**, **kldunload** - list, load, and unload - FreeBSD kernel modules -* **sysctl** - display and modify various pieces of kernel state -* **pkg_info**, **pkg_add**, **pkg_delete** - list, add, or remove - FreeBSD software packages. -* **vtysh** - start a Quagga CLI for router configuration - -Netgraph Nodes --------------- - -.. index:: Netgraph - -.. index:: Netgraph nodes - -Each Netgraph node implements a protocol or processes data in some well-defined -manner (see the `netgraph(4)` man page). The netgraph source code is located -in `/usr/src/sys/netgraph`. There you might discover additional nodes that -implement some desired functionality, that have not yet been included in CORE. -Using certain kernel commands, you can likely include these types of nodes into -your CORE emulation. - -The following Netgraph nodes are used by CORE: - -* **ng_bridge** - switch node performs Ethernet bridging - -* **ng_cisco** - Cisco HDLC serial links - -* **ng_eiface** - virtual Ethernet interface that is assigned to each virtual machine - -* **ng_ether** - physical Ethernet devices, used by the RJ45 tool - -* **ng_hub** - hub node - -* **ng_pipe** - used for wired Ethernet links, imposes packet delay, bandwidth restrictions, and other link characteristics - -* **ng_socket** - socket used by *ngctl* utility - -* **ng_wlan** - wireless LAN node - - diff --git a/doc/install.rst b/doc/install.rst index f4b28c39..3a9346c1 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -9,14 +9,14 @@ Installation ************ -This chapter describes how to set up a CORE machine. Note that the easiest +This chapter describes how to set up a CORE machine. Note that the easiest way to install CORE is using a binary package on Ubuntu or Fedora (deb or rpm) using the distribution's package manager to automatically install dependencies, see :ref:`Installing_from_Packages`. Ubuntu and Fedora Linux are the recommended distributions for running CORE. Ubuntu |UBUNTUVERSION| and Fedora |FEDORAVERSION| ship with kernels with support for namespaces built-in. They support the latest hardware. However, -these distributions are not strictly required. CORE will likely work on other +these distributions are not strictly required. CORE will likely work on other flavors of Linux, see :ref:`Installing_from_Source`. The primary dependencies are Tcl/Tk (8.5 or newer) for the GUI, and Python 2.6 or 2.7 for the CORE daemon. @@ -50,7 +50,7 @@ Prerequisites .. index:: Prerequisites -The Linux or FreeBSD operating system is required. The GUI uses the Tcl/Tk scripting toolkit, and the CORE daemon require Python. Details of the individual software packages required can be found in the installation steps. +A Linux operating system is required. The GUI uses the Tcl/Tk scripting toolkit, and the CORE daemon requires Python. Details of the individual software packages required can be found in the installation steps. .. _Required_Hardware: @@ -61,7 +61,7 @@ Required Hardware .. index:: System requirements -Any computer capable of running Linux or FreeBSD should be able to run CORE. Since the physical machine will be hosting numerous virtual machines, as a general rule you should select a machine having as much RAM and CPU resources as possible. +Any computer capable of running Linux should be able to run CORE. Since the physical machine will be hosting numerous virtual machines, as a general rule you should select a machine having as much RAM and CPU resources as possible. A *general recommendation* would be: @@ -70,9 +70,9 @@ A *general recommendation* would be: * about 3 MB of free disk space (plus more for dependency packages such as Tcl/Tk) * X11 for the GUI, or remote X11 over SSH -The computer can be a laptop, desktop, or rack-mount server. A keyboard, mouse, +The computer can be a laptop, desktop, or rack-mount server. A keyboard, mouse, and monitor are not required if a network connection is available -for remotely accessing the machine. A 3D accelerated graphics card +for remotely accessing the machine. A 3D accelerated graphics card is not required. .. _Required_Software: @@ -80,18 +80,13 @@ is not required. Required Software ----------------- -CORE requires the Linux or FreeBSD operating systems because it uses virtualization provided by the kernel. It does not run on the Windows or Mac OS X operating systems (unless it is running within a virtual machine guest.) There are two -different virtualization technologies that CORE can currently use: -Linux network namespaces and FreeBSD jails, +CORE requires a Linux operating systems because it uses virtualization provided by the kernel. It does not run on the Windows or Mac OS X operating systems (unless it is running within a virtual machine guest.) +The virtualization technology that CORE currently uses: +Linux network namespaces, see :ref:`How_Does_it_Work?` for virtualization details. **Linux network namespaces is the recommended platform.** Development is focused here and it supports the latest features. It is the easiest to install because there is no need to patch, install, and run a special Linux kernel. -FreeBSD |BSDVERSION|-RELEASE may offer the best scalability. If your -applications run under FreeBSD and you are comfortable with that platform, -this may be a good choice. Device and application support by BSD -may not be as extensive as Linux. - The CORE GUI requires the X.Org X Window system (X11), or can run over a remote X11 session. For specific Tcl/Tk, Python, and other libraries required to run CORE, refer to the :ref:`Installation` section. @@ -113,7 +108,7 @@ Installing from Packages The easiest way to install CORE is using the pre-built packages. The package managers on Ubuntu or Fedora will -automatically install dependencies for you. +automatically install dependencies for you. You can obtain the CORE packages from the `CORE downloads `_ page or `CORE GitHub `_. @@ -143,7 +138,7 @@ First install the Ubuntu |UBUNTUVERSION| operating system. to select which Quagga package to use. -* **Optional:** install the prerequisite packages (otherwise skip this +* **Optional:** install the prerequisite packages (otherwise skip this step and have the package manager install them for you.) .. parsed-literal:: @@ -152,13 +147,13 @@ First install the Ubuntu |UBUNTUVERSION| operating system. # update-manager instead of apt-get update/dist-upgrade sudo apt-get update sudo apt-get dist-upgrade - sudo apt-get install |APTDEPS| |APTDEPS2| - + sudo apt-get install |APTDEPS| |APTDEPS2| + * Install Quagga for routing. If you plan on working with wireless - networks, we recommend + networks, we recommend installing `OSPF MDR `__ - (replace `amd64` below with `i386` if needed + (replace `amd64` below with `i386` if needed to match your architecture): .. parsed-literal:: @@ -172,7 +167,7 @@ First install the Ubuntu |UBUNTUVERSION| operating system. :: sudo apt-get install quagga - + * Install the CORE deb packages for Ubuntu, using a GUI that automatically resolves dependencies (note that the absolute path to the deb file must be used with ``software-center``): @@ -181,24 +176,24 @@ First install the Ubuntu |UBUNTUVERSION| operating system. software-center /home/user/Downloads/core-daemon\_\ |version|-|COREDEB| software-center /home/user/Downloads/core-gui\_\ |version|-|COREDEB2| - + or install from command-line: - + .. parsed-literal:: sudo dpkg -i core-daemon\_\ |version|-|COREDEB| sudo dpkg -i core-gui\_\ |version|-|COREDEB2| - + * Start the CORE daemon as root. :: sudo /etc/init.d/core-daemon start - + * Run the CORE GUI as a normal user: :: core-gui - + After running the ``core-gui`` command, a GUI should appear with a canvas for drawing topologies. Messages will print out on the console about @@ -217,7 +212,7 @@ examples below, replace with `i686` is using a 32-bit architecture. Also, Fedora release number. * **CentOS only:** in order to install the `libev` and `tkimg` prerequisite - packages, you + packages, you first need to install the `EPEL `_ repo (Extra Packages for Enterprise Linux): @@ -229,7 +224,7 @@ Fedora release number. * **CentOS 7.x only:** as of this writing, the `tkimg` prerequisite package is missing from EPEL 7.x, but the EPEL 6.x package can be manually installed - from + from `here `_ :: @@ -249,7 +244,7 @@ Fedora release number. yum install |YUMDEPS| |YUMDEPS2| -* **Optional (Fedora 17+):** Fedora 17 and newer have an additional +* **Optional (Fedora 17+):** Fedora 17 and newer have an additional prerequisite providing the required netem kernel modules (otherwise skip this step and have the package manager install it for you.) @@ -272,7 +267,7 @@ Fedora release number. :: yum install quagga - + * Install the CORE RPM packages for Fedora and automatically resolve dependencies: @@ -281,14 +276,14 @@ Fedora release number. yum localinstall python-core_|service|-|version|-|CORERPM| --nogpgcheck yum localinstall core-gui-|version|-|CORERPM2| --nogpgcheck - + or install from the command-line: .. parsed-literal:: rpm -ivh python-core_|service|-|version|-|CORERPM| rpm -ivh core-gui-|version|-|CORERPM2| - + * Turn off SELINUX by setting ``SELINUX=disabled`` in the :file:`/etc/sysconfig/selinux` file, and adding ``selinux=0`` to the kernel line in your :file:`/etc/grub.conf` file; on Fedora 15 and newer, disable sandboxd using ``chkconfig sandbox off``; @@ -304,12 +299,12 @@ Fedora release number. systemctl start core-daemon.service # or for CentOS: /etc/init.d/core-daemon start - + * Run the CORE GUI as a normal user: :: core-gui - + After running the ``core-gui`` command, a GUI should appear with a canvas for drawing topologies. Messages will print out on the console about @@ -335,11 +330,11 @@ These packages are not required for normal binary package installs. sudo apt-get install |APTDEPS| \\ |APTDEPS2| \\ |APTDEPS3| - + You can obtain the CORE source from the `CORE source `_ page. Choose either a stable release version or -the development snapshot available in the `nightly_snapshots` directory. -The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up +the development snapshot available in the `nightly_snapshots` directory. +The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up builds on multi-core systems. .. parsed-literal:: @@ -350,9 +345,9 @@ builds on multi-core systems. ./configure make -j8 sudo make install - -The CORE Manual documentation is built separately from the :file:`doc/` + +The CORE Manual documentation is built separately from the :file:`doc/` sub-directory in the source. It requires Sphinx: .. parsed-literal:: @@ -376,16 +371,16 @@ These packages are not required for normal binary package installs. yum install |YUMDEPS| \\ |YUMDEPS2| \\ |YUMDEPS3| - + .. NOTE:: For a minimal X11 installation, also try these packages:: - + yum install xauth xterm urw-fonts You can obtain the CORE source from the `CORE source `_ page. Choose either a stable release version or the development snapshot available in the :file:`nightly_snapshots` directory. -The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up +The ``-j8`` argument to ``make`` will run eight simultaneous jobs, to speed up builds on multi-core systems. Notice the ``configure`` flag to tell the build system that a systemd service file should be installed under Fedora. @@ -397,18 +392,12 @@ system that a systemd service file should be installed under Fedora. ./configure --with-startup=systemd make -j8 sudo make install - - -Note that the Linux RPM and Debian packages do not use the ``/usr/local`` -prefix, and files are instead installed to ``/usr/sbin``, and -``/usr/lib``. This difference is a result of aligning with the directory -structure of Linux packaging systems and FreeBSD ports packaging. Another note is that the Python distutils in Fedora Linux will install the CORE Python modules to :file:`/usr/lib/python2.7/site-packages/core`, instead of using the :file:`dist-packages` directory. -The CORE Manual documentation is built separately from the :file:`doc/` +The CORE Manual documentation is built separately from the :file:`doc/` sub-directory in the source. It requires Sphinx: .. parsed-literal:: @@ -438,7 +427,7 @@ CentOS/EL6 does not use the systemd service file, so the `configure` option `--with-startup=systemd` should be omitted: :: - + ./configure @@ -448,12 +437,12 @@ CentOS/EL6 does not use the systemd service file, so the `configure` option Installing from Source on SUSE ------------------------------ -To build CORE from source on SUSE or OpenSUSE, +To build CORE from source on SUSE or OpenSUSE, use the similar instructions shown in :ref:`Installing_from_Source_on_Fedora`, except that the following `configure` option should be used: :: - + ./configure --with-startup=suse This causes a separate init script to be installed that is tailored towards SUSE systems. @@ -463,153 +452,6 @@ The `zypper` command is used instead of `yum`. For OpenSUSE/Xen based installations, refer to the `README-Xen` file included in the CORE source. - -.. _Installing_from_Source_on_FreeBSD: - -Installing from Source on FreeBSD ---------------------------------- - -.. index:: kernel patch - -**Rebuilding the FreeBSD Kernel** - - -The FreeBSD kernel requires a small patch to allow per-node directories in the -filesystem. Also, the `VIMAGE` build option needs to be turned on to enable -jail-based network stack virtualization. The source code for the FreeBSD -kernel is located in :file:`/usr/src/sys`. - -Instructions below will use the :file:`/usr/src/sys/amd64` architecture -directory, but the directory :file:`/usr/src/sys/i386` should be substituted -if you are using a 32-bit architecture. - -The kernel patch is available from the CORE source tarball under core-|version|/kernel/symlinks-8.1-RELEASE.diff. This patch applies to the -FreeBSD 8.x or 9.x kernels. - -.. parsed-literal:: - - cd /usr/src/sys - # first you can check if the patch applies cleanly using the '-C' option - patch -p1 -C < ~/core-|version|/kernel/symlinks-8.1-RELEASE.diff - # without '-C' applies the patch - patch -p1 < ~/core-|version|/kernel/symlinks-8.1-RELEASE.diff - - -A kernel configuration file named :file:`CORE` can be found within the source tarball: core-|version|/kernel/freebsd8-config-CORE. The config is valid for -FreeBSD 8.x or 9.x kernels. - -The contents of this configuration file are shown below; you can edit it to suit your needs. - -:: - - # this is the FreeBSD 9.x kernel configuration file for CORE - include GENERIC - ident CORE - - options VIMAGE - nooptions SCTP - options IPSEC - device crypto - - options IPFIREWALL - options IPFIREWALL_DEFAULT_TO_ACCEPT - - -The kernel configuration file can be linked or copied to the kernel source directory. Use it to configure and build the kernel: - -.. parsed-literal:: - - cd /usr/src/sys/amd64/conf - cp ~/core-|version|/kernel/freebsd8-config-CORE CORE - config CORE - cd ../compile/CORE - make cleandepend && make depend - make -j8 && make install - - -Change the number 8 above to match the number of CPU cores you have times two. -Note that the ``make install`` step will move your existing kernel to -``/boot/kernel.old`` and removes that directory if it already exists. Reboot to -enable this new patched kernel. - -**Building CORE from Source on FreeBSD** - -Here are the prerequisite packages from the FreeBSD ports system: - -:: - - pkg_add -r tk85 - pkg_add -r libimg - pkg_add -r bash - pkg_add -r libev - pkg_add -r sudo - pkg_add -r python - pkg_add -r autotools - pkg_add -r gmake - - -Note that if you are installing to a bare FreeBSD system and want to SSH with X11 forwarding to that system, these packages will help: - -:: - - pkg_add -r xauth - pkg_add -r xorg-fonts - - -The ``sudo`` package needs to be configured so a normal user can run the CORE -GUI using the command ``core-gui`` (opening a shell window on a node uses a -command such as ``sudo vimage n1``.) - -On FreeBSD, the CORE source is built using autotools and gmake: - -.. parsed-literal:: - - tar xzf core-|version|.tar.gz - cd core-|version| - ./bootstrap.sh - ./configure - gmake -j8 - sudo gmake install - - -Build and install the ``vimage`` utility for controlling virtual images. The source can be obtained from `FreeBSD SVN `_, or it is included with the CORE source for convenience: - -.. parsed-literal:: - - cd core-|version|/kernel/vimage - make - make install - - -.. index:: FreeBSD; kernel modules - -.. index:: kernel modules - -.. index:: ng_wlan and ng_pipe - -On FreeBSD you should also install the CORE kernel modules for wireless emulation. Perform this step after you have recompiled and installed FreeBSD kernel. - -.. parsed-literal:: - - cd core-|version|/kernel/ng_pipe - make - sudo make install - cd ../ng_wlan - make - sudo make install - - -The :file:`ng_wlan` kernel module allows for the creation of WLAN nodes. This -is a modified :file:`ng_hub` Netgraph module. Instead of packets being copied -to every connected node, the WLAN maintains a hash table of connected node -pairs. Furthermore, link parameters can be specified for node pairs, in -addition to the on/off connectivity. The parameters are tagged to each packet -and sent to the connected :file:`ng_pipe` module. The :file:`ng_pipe` has been -modified to read any tagged parameters and apply them instead of its default -link effects. - -The :file:`ng_wlan` also supports linking together multiple WLANs across different machines using the :file:`ng_ksocket` Netgraph node, for distributed emulation. - The Quagga routing suite is recommended for routing, :ref:`Quagga_Routing_Software` for installation. @@ -624,12 +466,12 @@ Virtual networks generally require some form of routing in order to work (e.g. to automatically populate routing tables for routing packets from one subnet to another.) CORE builds OSPF routing protocol configurations by default when the blue router -node type is used. The OSPF protocol is available -from the `Quagga open source routing suite `_. +node type is used. The OSPF protocol is available +from the `Quagga open source routing suite `_. Other routing protocols are available using different node services, :ref:`Default_Services_and_Node_Types`. -Quagga is not specified as a dependency for the CORE packages because +Quagga is not specified as a dependency for the CORE packages because there are two different Quagga packages that you may use: * `Quagga `_ - the standard version of Quagga, suitable for static wired networks, and usually available via your distribution's package manager. @@ -639,7 +481,7 @@ there are two different Quagga packages that you may use: .. index:: MANET Designated Routers (MDR) -* +* `OSPF MANET Designated Routers `_ (MDR) - the Quagga routing suite with a modified version of OSPFv3, optimized for use with mobile wireless networks. The *mdr* node type (and the MDR service) requires this variant of Quagga. @@ -651,26 +493,19 @@ otherwise install the standard version of Quagga using your package manager or f Installing Quagga from Packages ------------------------------- -To install the standard version of Quagga from packages, use your package -manager (Linux) or the ports system (FreeBSD). +To install the standard version of Quagga from packages, use your package manager (Linux). Ubuntu users: :: sudo apt-get install quagga - + Fedora users: :: yum install quagga - -FreeBSD users: -:: - pkg_add -r quagga - - -To install the Quagga variant having OSPFv3 MDR, first download the +To install the Quagga variant having OSPFv3 MDR, first download the appropriate package, and install using the package manager. Ubuntu users: @@ -709,7 +544,7 @@ To compile Quagga to work with CORE on Linux: --localstatedir=/var/run/quagga make sudo make install - + Note that the configuration directory :file:`/usr/local/etc/quagga` shown for Quagga above could be :file:`/etc/quagga`, if you create a symbolic link from @@ -723,26 +558,9 @@ If you try to run quagga after installing from source and get an error such as: error while loading shared libraries libzebra.so.0 -this is usually a sign that you have to run `sudo ldconfig` to refresh the +this is usually a sign that you have to run `sudo ldconfig` to refresh the cache file. -To compile Quagga to work with CORE on FreeBSD: - -.. parsed-literal:: - - tar xzf |QVER|.tar.gz - cd |QVER| - ./configure --enable-user=root --enable-group=wheel \\ - --sysconfdir=/usr/local/etc/quagga --enable-vtysh \\ - --localstatedir=/var/run/quagga - gmake - gmake install - - -On FreeBSD |BSDVERSION| you can use ``make`` or ``gmake``. -You probably want to compile Quagga from the ports system in -:file:`/usr/ports/net/quagga`. - VCORE ===== diff --git a/doc/intro.rst b/doc/intro.rst index d0ddc0c2..95c11f86 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -12,8 +12,8 @@ networks. As an emulator, CORE builds a representation of a real computer network that runs in real time, as opposed to simulation, where abstract models are used. The live-running emulation can be connected to physical networks and routers. It provides an environment for running real applications and -protocols, taking advantage of virtualization provided by the Linux or FreeBSD -operating systems. +protocols, taking advantage of virtualization provided by the Linux operating +system. Some of its key features are: @@ -94,8 +94,7 @@ further control. How Does it Work? ================= -A CORE node is a lightweight virtual machine. The CORE framework runs on Linux -and FreeBSD systems. The primary platform used for development is Linux. +A CORE node is a lightweight virtual machine. The CORE framework runs on Linux. .. index:: single: Linux; virtualization @@ -104,8 +103,6 @@ and FreeBSD systems. The primary platform used for development is Linux. single: network namespaces * :ref:`Linux` CORE uses Linux network namespace virtualization to build virtual nodes, and ties them together with virtual networks using Linux Ethernet bridging. -* :ref:`FreeBSD` CORE uses jails with a network stack virtualization kernel option to build virtual nodes, and ties them together with virtual networks using BSD's Netgraph system. - .. _Linux: @@ -117,9 +114,9 @@ technique used by CORE. LXC has been part of the mainline Linux kernel since 2.6.24. Recent Linux distributions such as Fedora and Ubuntu have namespaces-enabled kernels out of the box, so the kernel does not need to be patched or recompiled. -A namespace is created using the ``clone()`` system call. Similar -to the BSD jails, each namespace has its own process environment and private -network stack. Network namespaces share the same filesystem in CORE. +A namespace is created using the ``clone()`` system call. Each namespace has +its own process environment and private network stack. Network namespaces +share the same filesystem in CORE. .. index:: single: Linux; bridging @@ -132,56 +129,6 @@ disciplines. Ebtables is Ethernet frame filtering on Linux bridges. Wireless networks are emulated by controlling which interfaces can send and receive with ebtables rules. - -.. _FreeBSD: - -FreeBSD -------- - -.. index:: - single: FreeBSD; Network stack virtualization - single: FreeBSD; jails - single: FreeBSD; vimages - -FreeBSD jails provide an isolated process space, a virtual environment for -running programs. Starting with FreeBSD 8.0, a new `vimage` kernel option -extends BSD jails so that each jail can have its own virtual network stack -- -its own networking variables such as addresses, interfaces, routes, counters, -protocol state, socket information, etc. The existing networking algorithms and -code paths are intact but operate on this virtualized state. - -Each jail plus network stack forms a lightweight virtual machine. These are -named jails or *virtual images* (or *vimages*) and are created using a the -``jail`` or ``vimage`` command. Unlike traditional virtual -machines, vimages do not feature entire operating systems running on emulated -hardware. All of the vimages will share the same processor, memory, clock, and -other system resources. Because the actual hardware is not emulated and network -packets can be passed by reference through the in-kernel Netgraph system, -vimages are quite lightweight and a single system can accommodate numerous -instances. - -Virtual network stacks in FreeBSD were historically available as a patch to the -FreeBSD 4.11 and 7.0 kernels, and the VirtNet project [#f1]_ [#f2]_ -added this functionality to the -mainline 8.0-RELEASE and newer kernels. - -.. index:: - single: FreeBSD; Netgraph - -The FreeBSD Operating System kernel features a graph-based -networking subsystem named Netgraph. The netgraph(4) manual page quoted below -best defines this system: - - The netgraph system provides a uniform and modular system for the - implementation of kernel objects which perform various networking functions. - The objects, known as nodes, can be arranged into arbitrarily complicated - graphs. Nodes have hooks which are used to connect two nodes together, - forming the edges in the graph. Nodes communicate along the edges to - process data, implement protocols, etc. - - The aim of netgraph is to supplement rather than replace the existing - kernel networking infrastructure. - .. index:: single: IMUNES single: VirtNet @@ -201,7 +148,7 @@ The Tcl/Tk CORE GUI was originally derived from the open source project from the University of Zagreb as a custom project within Boeing Research and Technology's Network Technology research group in 2004. Since then they have developed the CORE -framework to use not only FreeBSD but Linux virtualization, have developed a +framework to use Linux virtualization, have developed a Python framework, and made numerous user- and kernel-space developments, such as support for wireless networks, IPsec, the ability to distribute emulations, simulation integration, and more. The IMUNES project also consists of userspace @@ -226,20 +173,16 @@ CORE has been released by Boeing to the open source community under the BSD license. If you find CORE useful for your work, please contribute back to the project. Contributions can be as simple as reporting a bug, dropping a line of encouragement or technical suggestions to the mailing lists, or can also -include submitting patches or maintaining aspects of the tool. For details on -contributing to CORE, please visit the -`wiki `_. +include submitting patches or maintaining aspects of the tool. For contributing to +CORE, please visit the +`CORE GitHub `_. Besides this manual, there are other additional resources available online: * `CORE website `_ - main project page containing demos, downloads, and mailing list information. -* `CORE supplemental website `_ - supplemental Google Code page with a quickstart guide, wiki, bug tracker, and screenshots. .. index:: - single: wiki - single: CORE; wiki - -The `CORE wiki `_ is a good place to check for the latest documentation and tips. + single: CORE Goals ----- @@ -255,10 +198,9 @@ Non-Goals --------- This is a list of Non-Goals, specific things that people may be interested in but are not areas that we will pursue. - #. Reinventing the wheel - Where possible, CORE reuses existing open source components such as virtualization, Netgraph, netem, bridging, Quagga, etc. #. 1,000,000 nodes - While the goal of CORE is to provide efficient, scalable network emulation, there is no set goal of N number of nodes. There are realistic limits on what a machine can handle as its resources are divided amongst virtual nodes. We will continue to make things more efficient and let the user determine the right number of nodes based on available hardware and the activities each node is performing. -#. Solves every problem - CORE is about emulating networking layers 3-7 using virtual network stacks in the Linux or FreeBSD operating systems. +#. Solves every problem - CORE is about emulating networking layers 3-7 using virtual network stacks in Linux operating systems. #. Hardware-specific - CORE itself is not an instantiation of hardware, a testbed, or a specific laboratory setup; it should run on commodity laptop and desktop PCs, in addition to high-end server hardware. diff --git a/doc/performance.rst b/doc/performance.rst index fe51c685..24d483e1 100644 --- a/doc/performance.rst +++ b/doc/performance.rst @@ -19,7 +19,7 @@ The top question about the performance of CORE is often * Hardware - the number and speed of processors in the computer, the available processor cache, RAM memory, and front-side bus speed may greatly affect overall performance. -* Operating system version - Linux or FreeBSD, and the specific kernel versions +* Operating system version - distribution of Linux and the specific kernel versions used will affect overall performance. * Active processes - all nodes share the same CPU resources, so if one or more nodes is performing a CPU-intensive task, overall performance will suffer. @@ -28,8 +28,8 @@ The top question about the performance of CORE is often * GUI usage - widgets that run periodically, mobility scenarios, and other GUI interactions generally consume CPU cycles that may be needed for emulation. -On a typical single-CPU Xeon 3.0GHz server machine with 2GB RAM running FreeBSD -|BSDVERSION|, we have found it reasonable to run 30-75 nodes running +On a typical single-CPU Xeon 3.0GHz server machine with 2GB RAM running Linux, +we have found it reasonable to run 30-75 nodes running OSPFv2 and OSPFv3 routing. On this hardware CORE can instantiate 100 or more nodes, but at that point it becomes critical as to what each of the nodes is doing. @@ -38,7 +38,7 @@ doing. Because this software is primarily a network emulator, the more appropriate question is *how much network traffic can it handle?* On the same 3.0GHz server -described above, running FreeBSD 4.11, about 300,000 packets-per-second can be +described above, running Linux, about 300,000 packets-per-second can be pushed through the system. The number of hops and the size of the packets is less important. The limiting factor is the number of times that the operating system needs to handle a packet. The 300,000 pps figure represents the number @@ -52,9 +52,9 @@ throughput seen on the full length of the network path. For a more detailed study of performance in CORE, refer to the following publications: -* J\. Ahrenholz, T. Goff, and B. Adamson, Integration of the CORE and EMANE Network Emulators, Proceedings of the IEEE Military Communications Conference 2011, November 2011. +* J\. Ahrenholz, T. Goff, and B. Adamson, Integration of the CORE and EMANE Network Emulators, Proceedings of the IEEE Military Communications Conference 2011, November 2011. -* Ahrenholz, J., Comparison of CORE Network Emulation Platforms, Proceedings of the IEEE Military Communications Conference 2010, pp. 864-869, November 2010. +* Ahrenholz, J., Comparison of CORE Network Emulation Platforms, Proceedings of the IEEE Military Communications Conference 2010, pp. 864-869, November 2010. -* J\. Ahrenholz, C. Danilov, T. Henderson, and J.H. Kim, CORE: A real-time network emulator, Proceedings of IEEE MILCOM Conference, 2008. +* J\. Ahrenholz, C. Danilov, T. Henderson, and J.H. Kim, CORE: A real-time network emulator, Proceedings of IEEE MILCOM Conference, 2008. diff --git a/doc/usage.rst b/doc/usage.rst index ec6e6028..0312312f 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -11,9 +11,9 @@ Using the CORE GUI .. index:: how to use CORE -CORE can be used via the GUI or :ref:`Python_Scripting`. -A typical emulation workflow is outlined in :ref:`emulation-workflow`. -Often the GUI is used to draw nodes and network devices on the canvas. +CORE can be used via the GUI or :ref:`Python_Scripting`. +A typical emulation workflow is outlined in :ref:`emulation-workflow`. +Often the GUI is used to draw nodes and network devices on the canvas. A Python script could also be written, that imports the CORE Python module, to configure and instantiate nodes and networks. This chapter primarily covers usage of the CORE GUI. .. _emulation-workflow: @@ -24,7 +24,7 @@ A Python script could also be written, that imports the CORE Python module, to c Emulation Workflow -CORE can be customized to perform any action at each phase depicted in :ref:`emulation-workflow`. See the *Hooks...* entry on the +CORE can be customized to perform any action at each phase depicted in :ref:`emulation-workflow`. See the *Hooks...* entry on the :ref:`Session_Menu` for details about when these session states are reached. @@ -43,13 +43,13 @@ mode. Nodes are drawn on a blank canvas using the toolbar on the left and configured from right-click menus or by double-clicking them. The GUI does not need to be run as root. -Once editing is complete, pressing the green `Start` button (or choosing `Execute` from the `Session` menu) instantiates the topology within the FreeBSD kernel and enters Execute mode. In execute mode, the user can interact with the running emulated machines by double-clicking or right-clicking on them. The editing toolbar disappears and is replaced by an execute toolbar, which provides tools while running the emulation. Pressing the red `Stop` button (or choosing `Terminate` from the `Session` menu) will destroy the running emulation and return CORE to Edit mode. +Once editing is complete, pressing the green `Start` button (or choosing `Execute` from the `Session` menu) instantiates the topology within the Linux kernel and enters Execute mode. In execute mode, the user can interact with the running emulated machines by double-clicking or right-clicking on them. The editing toolbar disappears and is replaced by an execute toolbar, which provides tools while running the emulation. Pressing the red `Stop` button (or choosing `Terminate` from the `Session` menu) will destroy the running emulation and return CORE to Edit mode. CORE can be started directly in Execute mode by specifying ``--start`` and a topology file on the command line: :: core-gui --start ~/.core/configs/myfile.imn - + Once the emulation is running, the GUI can be closed, and a prompt will appear asking if the emulation should be terminated. The emulation may be left running and the GUI can reconnect to an existing session at a later time. @@ -62,8 +62,8 @@ There is also a **Batch** mode where CORE runs without the GUI and will instanti :: core-gui --batch ~/.core/configs/myfile.imn - -A session running in batch mode can be accessed using the ``vcmd`` command (or ``vimage`` on FreeBSD), or the GUI can connect to the session. + +A session running in batch mode can be accessed using the ``vcmd`` command, or the GUI can connect to the session. .. index:: closebatch @@ -76,12 +76,12 @@ The session number is printed in the terminal when batch mode is started. This s If you forget the session number, you can always start the CORE GUI and use :ref:`Session_Menu` CORE sessions dialog box. .. NOTE:: - It is quite easy to have overlapping sessions when running in batch mode. This may become a problem when control networks are employed in these sessions as there could be addressing conflicts. See :ref:`Control_Network` for remedies. - + It is quite easy to have overlapping sessions when running in batch mode. This may become a problem when control networks are employed in these sessions as there could be addressing conflicts. See :ref:`Control_Network` for remedies. + .. NOTE:: If you like to use batch mode, consider writing a - CORE :ref:`Python script ` directly. + CORE :ref:`Python script ` directly. This enables access to the full power of the Python API. The :ref:`File_Menu` has a basic `Export Python Script` option for getting started with a GUI-designed topology. @@ -92,8 +92,7 @@ The session number is printed in the terminal when batch mode is started. This s .. index:: root privileges -The GUI can be run as a normal user on Linux. For FreeBSD, the GUI should be run -as root in order to start an emulation. +The GUI can be run as a normal user on Linux. .. index:: port number @@ -204,7 +203,7 @@ sub-menus, which appear when you click on their group icon. wireless nodes based on the distance between them * |rj45| *RJ45* - with the RJ45 Physical Interface Tool, emulated nodes can - be linked to real physical interfaces on the Linux or FreeBSD machine; + be linked to real physical interfaces; using this tool, real networks and devices can be physically connected to the live-running emulation (:ref:`RJ45_Tool`) @@ -330,7 +329,7 @@ File Menu The File menu contains options for manipulating the :file:`.imn` :ref:`Configuration_Files`. Generally, these menu items should not be used in -Execute mode (:ref:`Modes_of_Operation`.) +Execute mode (:ref:`Modes_of_Operation`.) .. index:: New @@ -340,7 +339,7 @@ Execute mode (:ref:`Modes_of_Operation`.) * *Open* - invokes the File Open dialog box for selecting a new :file:`.imn` or XML file to open. You can change the default path used for this dialog - in the :ref:`Preferences` Dialog. + in the :ref:`Preferences` Dialog. .. index:: Save @@ -349,16 +348,16 @@ Execute mode (:ref:`Modes_of_Operation`.) .. index:: Save As XML -* *Save As XML* - invokes the Save As dialog box for selecting a new +* *Save As XML* - invokes the Save As dialog box for selecting a new :file:`.xml` file for saving the current configuration in the XML file. - See :ref:`Configuration_Files`. + See :ref:`Configuration_Files`. .. index:: Save As imn * *Save As imn* - invokes the Save As dialog box for selecting a new :file:`.imn` topology file for saving the current configuration. Files are saved in the - *IMUNES network configuration* file format described in + *IMUNES network configuration* file format described in :ref:`Configuration_Files`. .. index:: Export Python script @@ -376,7 +375,7 @@ Execute mode (:ref:`Modes_of_Operation`.) .. index:: Execute Python script with options * *Execute Python script with options* - invokes a File Open dialog box for selecting a - Python script to run and automatically connect to. After a selection is made, + Python script to run and automatically connect to. After a selection is made, a Python Script Options dialog box is invoked to allow for command-line options to be added. The Python script must create a new CORE Session and add this session to the daemon's list of sessions in order for this to work; see :ref:`Python_Scripting`. @@ -386,7 +385,7 @@ Execute mode (:ref:`Modes_of_Operation`.) * *Open current file in editor* - this opens the current topology file in the ``vim`` text editor. First you need to save the file. Once the file has been edited with a text editor, you will need to reload the file to see your - changes. The text editor can be changed from the :ref:`Preferences` Dialog. + changes. The text editor can be changed from the :ref:`Preferences` Dialog. .. index:: Print .. index:: printing @@ -434,7 +433,7 @@ Edit Menu * *Cut*, *Copy*, *Paste* - used to cut, copy, and paste a selection. When nodes are pasted, their node numbers are automatically incremented, and existing links are preserved with new IP addresses assigned. Services and their - customizations are copied to the new node, but care should be taken as + customizations are copied to the new node, but care should be taken as node IP addresses have changed with possibly old addresses remaining in any custom service configurations. Annotations may also be copied and pasted. @@ -503,7 +502,7 @@ The canvas menu provides commands for adding, removing, changing, and switching altitude reference point used to convert between geographic and Cartesian coordinate systems. By clicking the *Save as default* option, all new canvases will be created with these properties. The default canvas size can - also be changed in the :ref:`Preferences` dialog box. + also be changed in the :ref:`Preferences` dialog box. * *Wallpaper...* - used for setting the canvas background image, :ref:`Customizing_your_Topology's_Look`. @@ -538,12 +537,12 @@ canvas. .. index:: hide nodes * *Show hidden nodes* - reveal nodes that have been hidden. Nodes are hidden by - selecting one or more nodes, right-clicking one and choosing *hide*. + selecting one or more nodes, right-clicking one and choosing *hide*. .. index:: locked view * *Locked* - toggles locked view; when the view is locked, nodes cannot be - moved around on the canvas with the mouse. This could be useful when + moved around on the canvas with the mouse. This could be useful when sharing the topology with someone and you do not expect them to change things. @@ -585,7 +584,7 @@ The tools menu lists different utility functions. .. index:: autorearrange selected * *Autorearrange selected* - automatically arranges the selected nodes on the - canvas. + canvas. .. index:: align to grid @@ -710,7 +709,7 @@ Here are some standard widgets: routing protocols. A line is drawn from each router halfway to the router ID of an adjacent router. The color of the line is based on the OSPF adjacency state such as Two-way or Full. To learn about the different colors, see the - *Configure Adjacency...* menu item. The :file:`vtysh` command is used to + *Configure Adjacency...* menu item. The :file:`vtysh` command is used to dump OSPF neighbor information. Only half of the line is drawn because each router may be in a different adjacency state with respect to the other. @@ -724,11 +723,7 @@ Here are some standard widgets: link. If the throughput exceeds a certain threshold, the link will become highlighted. For wireless nodes which broadcast data to all nodes in range, the throughput rate is displayed next to the node and the node will become - circled if the threshold is exceeded. *Note: under FreeBSD, the - Throughput Widget will - display "0.0 kbps" on all links that have no configured link effects, because - of the way link statistics are counted; to fix this, add a small delay or a - bandwidth limit to each link.* + circled if the threshold is exceeded. .. _Observer_Widgets: @@ -810,7 +805,7 @@ and options. of configured hooks, and buttons on the bottom left allow adding, editing, and removing hook scripts. The new or edit button will open a hook script editing window. A hook script is a shell script invoked on the host (not - within a virtual node). + within a virtual node). The script is started at the session state specified in the drop down: @@ -818,14 +813,14 @@ and options. * *configuration* - when the user presses the *Start* button, node, link, and other configuration data is sent to the backend. This state is also - reached when the user customizes a service. + reached when the user customizes a service. * *instantiation* - after - configuration data has been sent, just before the nodes are created. + configuration data has been sent, just before the nodes are created. * *runtime* - all nodes and networks have been - built and are running. (This is the same state at which - the previously-named *global experiment script* was run.) + built and are running. (This is the same state at which + the previously-named *global experiment script* was run.) * *datacollect* - the user has pressed the *Stop* button, but before services have been stopped and nodes have been @@ -837,18 +832,18 @@ and options. * *Reset node positions* - if you have moved nodes around using the mouse or by using a mobility module, choosing this item will reset all nodes to their original position on the canvas. The node locations are - remembered when you first press the Start button. + remembered when you first press the Start button. * *Emulation servers...* - invokes the CORE emulation servers dialog for configuring :ref:`Distributed_Emulation`. -* *Change Sessions...* - invokes the Sessions dialog for switching between +* *Change Sessions...* - invokes the Sessions dialog for switching between different running sessions. This dialog is presented during startup when one or more sessions are already running. * *Options...* - presents per-session options, such as the IPv4 prefix to be - used, if any, for a control network + used, if any, for a control network (see :ref:`Communicating_with_the_Host_Machine`); the ability to preserve the session directory; and an on/off switch for SDT3D support. @@ -871,7 +866,7 @@ Connecting with Physical Networks CORE's emulated networks run in real time, so they can be connected to live physical networks. The RJ45 tool and the Tunnel tool help with connecting to -the real world. These tools are available from the *Link-layer nodes* menu. +the real world. These tools are available from the *Link-layer nodes* menu. When connecting two or more CORE emulations together, MAC address collisions should be avoided. CORE automatically assigns MAC addresses to interfaces when @@ -893,7 +888,7 @@ with the CORE nodes in real time. The main drawback is that one physical interface is required for each connection. When the physical interface is assigned to CORE, it may not be used for anything else. Another consideration is that the computer or network that -you are connecting to must be co-located with the CORE machine. +you are connecting to must be co-located with the CORE machine. To place an RJ45 connection, click on the *Link-layer nodes* toolbar and select the *RJ45 Tool* from the submenu. Click on the canvas near the node you want to @@ -904,8 +899,8 @@ physical interface. A list of available interfaces will be shown, and one may be selected by double-clicking its name in the list, or an interface name may be entered into the text box. -.. NOTE:: - When you press the Start button to instantiate your topology, the +.. NOTE:: + When you press the Start button to instantiate your topology, the interface assigned to the RJ45 will be connected to the CORE topology. The interface can no longer be used by the system. For example, if there was an IP address assigned to the physical interface before execution, the address @@ -925,7 +920,7 @@ physical ports are available, but the (e.g. switching) hardware connected to the physical port must support the VLAN tagging, and the available bandwidth will be shared. -You need to create separate VLAN virtual devices on the Linux or FreeBSD host, +You need to create separate VLAN virtual devices on the Linux host, and then assign these devices to RJ45 nodes inside of CORE. The VLANning is actually performed outside of CORE, so when the CORE emulated node receives a packet, the VLAN tag will already be removed. @@ -953,15 +948,15 @@ Tunneling can be helpful when the number of physical interfaces is limited or when the peer is located on a different network. Also a physical interface does not need to be dedicated to CORE as with the RJ45 tool. -The peer GRE tunnel endpoint may be another CORE machine or a (Linux, FreeBSD, -etc.) host that supports GRE tunneling. When placing a Tunnel node, initially +The peer GRE tunnel endpoint may be another CORE machine or another +host that supports GRE tunneling. When placing a Tunnel node, initially the node will display "UNASSIGNED". This text should be replaced with the IP address of the tunnel peer. This is the IP address of the other CORE machine or physical machine, not an IP address of another virtual node. .. NOTE:: Be aware of possible MTU issues with GRE devices. The *gretap* device - has an interface MTU of 1,458 bytes; when joined to a Linux bridge, the + has an interface MTU of 1,458 bytes; when joined to a Linux bridge, the bridge's MTU becomes 1,458 bytes. The Linux bridge will not perform fragmentation for large packets if other bridge ports have a higher MTU such as 1,500 bytes. @@ -977,7 +972,7 @@ used. .. index:: ip link command Here are example commands for building the other end of a tunnel on a Linux -machine. In this example, a router in CORE has the virtual address +machine. In this example, a router in CORE has the virtual address ``10.0.0.1/24`` and the CORE host machine has the (real) address ``198.51.100.34/24``. The Linux box that will connect with the CORE machine is reachable over the (real) network @@ -989,7 +984,7 @@ an address from the subnet of the virtual router node, ``10.0.0.2/24``. :: - + # these commands are run on the tunnel peer sudo ip link add gt0 type gretap remote 198.51.100.34 local 198.51.100.76 key 1 sudo ip addr add 10.0.0.2/24 dev gt0 @@ -1053,7 +1048,7 @@ the node, and SSH with X11 forwarding can be used from the host to the node: ssh -X 172.16.0.5 xclock Note that the :file:`coresendmsg` utility can be used for a node to send -messages to the CORE daemon running on the host (if the ``listenaddr = 0.0.0.0`` +messages to the CORE daemon running on the host (if the ``listenaddr = 0.0.0.0`` is set in the :file:`/etc/core/core.conf` file) to interact with the running emulation. For example, a node may move itself or other nodes, or change its icon based on some node state. @@ -1108,7 +1103,7 @@ Wired Networks Wired networks are created using the *Link Tool* to draw a link between two nodes. This automatically draws a red line representing an Ethernet link and -creates new interfaces on network-layer nodes. +creates new interfaces on network-layer nodes. .. index:: link configuration @@ -1124,12 +1119,11 @@ link, affecting its display. .. index:: lanswitch Link-layer nodes are provided for modeling wired networks. These do not create -a separate network stack when instantiated, but are implemented using bridging -(Linux) or Netgraph nodes (FreeBSD). These are the hub, switch, and wireless -LAN nodes. The hub copies each packet from the incoming link to every connected -link, while the switch behaves more like an Ethernet switch and keeps track of -the Ethernet address of the connected peer, forwarding unicast traffic only to -the appropriate ports. +a separate network stack when instantiated, but are implemented using Linux bridging. +These are the hub, switch, and wireless LAN nodes. The hub copies each packet from +the incoming link to every connected link, while the switch behaves more like an +Ethernet switch and keeps track of the Ethernet address of the connected peer, +forwarding unicast traffic only to the appropriate ports. The wireless LAN (WLAN) is covered in the next section. @@ -1158,13 +1152,13 @@ on platform. See the table below for a brief overview of wireless model types. ============= ===================== ======== ================================================================== Model Type Supported Platform(s) Fidelity Description ============= ===================== ======== ================================================================== -Basic on/off Linux, FreeBSD Low Linux Ethernet bridging with ebtables (Linux) or ng_wlan (FreeBSD) +Basic on/off Linux Low Linux Ethernet bridging with ebtables EMANE Plug-in Linux High TAP device connected to EMANE emulator with pluggable MAC and PHY radio types ============= ===================== ======== ================================================================== To quickly build a wireless network, you can first place several router nodes -onto the canvas. If you have the +onto the canvas. If you have the :ref:`Quagga MDR software ` installed, it is recommended that you use the *mdr* node type for reduced routing overhead. Next choose the *wireless LAN* from the *Link-layer nodes* submenu. First set the @@ -1198,8 +1192,6 @@ dragging them, and wireless links will be dynamically made or broken. The *EMANE* tab lists available EMANE models to use for wireless networking. See the :ref:`EMANE` chapter for details on using EMANE. -On FreeBSD, the WLAN node is realized using the *ng_wlan* Netgraph node. - .. _Mobility_Scripting: Mobility Scripting @@ -1213,7 +1205,7 @@ Mobility Scripting .. index:: mobility scripting -CORE has a few ways to script mobility. +CORE has a few ways to script mobility. * ns-2 script - the script specifies either absolute positions or waypoints with a velocity. Locations are given with Cartesian coordinates. @@ -1226,7 +1218,7 @@ CORE has a few ways to script mobility. For the first method, you can create a mobility script using a text editor, or using a tool such as `BonnMotion `_, and associate the script with one of the wireless -using the WLAN configuration dialog box. Click the *ns-2 mobility script...* +using the WLAN configuration dialog box. Click the *ns-2 mobility script...* button, and set the *mobility script file* field in the resulting *ns2script* configuration dialog. @@ -1254,11 +1246,11 @@ The format of an ns-2 mobility script looks like: $node_(2) set Y_ 240.0 $node_(2) set Z_ 0.00 $ns_ at 1.00 "$node_(2) setdest 130.0 280.0 15.0" - + The first three lines set an initial position for node 2. The last line in the above example causes node 2 to move towards the destination `(130, 280)` at -speed `15`. All units are screen coordinates, with speed in units per second. +speed `15`. All units are screen coordinates, with speed in units per second. The total script time is learned after all nodes have reached their waypoints. Initially, the time slider in the mobility script dialog will not be @@ -1305,13 +1297,12 @@ Distributed Emulation A large emulation scenario can be deployed on multiple emulation servers and controlled by a single GUI. The GUI, representing the entire topology, can be run on one of the emulation servers or on a separate machine. Emulations can be -distributed on Linux, while tunneling support has not been added yet for -FreeBSD. +distributed on Linux. Each machine that will act as an emulation server needs to have CORE installed. It is not important to have the GUI component but the CORE Python daemon :file:`core-daemon` needs to be installed. Set the ``listenaddr`` line in the -:file:`/etc/core/core.conf` configuration file so that the CORE Python +:file:`/etc/core/core.conf` configuration file so that the CORE Python daemon will respond to commands from other servers: :: @@ -1320,7 +1311,7 @@ daemon will respond to commands from other servers: pidfile = /var/run/core-daemon.pid logfile = /var/log/core-daemon.log listenaddr = 0.0.0.0 - + The ``listenaddr`` should be set to the address of the interface that should receive CORE API control commands from the other servers; setting ``listenaddr @@ -1356,19 +1347,19 @@ Servers are configured by choosing *Emulation servers...* from the *Session* menu. Servers parameters are configured in the list below and stored in a *servers.conf* file for use in different scenarios. The IP address and port of the server must be specified. The name of each server will be saved in the -topology file as each node's location. +topology file as each node's location. .. NOTE:: The server that the GUI connects with - is referred to as the master server. + is referred to as the master server. The user needs to assign nodes to emulation servers in the scenario. Making no -assignment means the node will be emulated on the master server -In the configuration window of every node, a drop-down box located between -the *Node name* and the *Image* button will select the name of the emulation -server. By default, this menu shows *(none)*, indicating that the node will -be emulated locally on the master. When entering Execute mode, the CORE GUI +assignment means the node will be emulated on the master server +In the configuration window of every node, a drop-down box located between +the *Node name* and the *Image* button will select the name of the emulation +server. By default, this menu shows *(none)*, indicating that the node will +be emulated locally on the master. When entering Execute mode, the CORE GUI will deploy the node on its assigned emulation server. Another way to assign emulation servers is to select one or more nodes using @@ -1395,7 +1386,7 @@ If there is a link between two nodes residing on different servers, the GUI will draw the link with a dashed line, and automatically create necessary tunnels between the nodes when executed. Care should be taken to arrange the topology such that the number of tunnels is minimized. The tunnels carry data -between servers to connect nodes as specified in the topology. +between servers to connect nodes as specified in the topology. These tunnels are created using GRE tunneling, similar to the :ref:`Tunnel_Tool`. @@ -1561,7 +1552,7 @@ service. Generally they send a kill signal to the running process using the *kill* or *killall* commands. If the service does not terminate the running processes using a shutdown command, the processes will be killed when the *vnoded* daemon is terminated (with *kill -9*) and -the namespace destroyed. It is a good practice to +the namespace destroyed. It is a good practice to specify shutdown commands, which will allow for proper process termination, and for run-time control of stopping and restarting services. @@ -1606,7 +1597,7 @@ in the :file:`/etc/core/core.conf` configuration file. A sample is provided in the :file:`myservices/` directory. .. NOTE:: - The directory name used in `custom_services_dir` should be unique and + The directory name used in `custom_services_dir` should be unique and should not correspond to any existing Python module name. For example, don't use the name `subprocess` or `services`. @@ -1641,7 +1632,7 @@ create a bridge or namespace, or the failure to launch EMANE processes for an EMANE-based network. Clicking on an exception displays details for that -exception. If a node number is specified, that node is highlighted on the +exception. If a node number is specified, that node is highlighted on the canvas when the exception is selected. The exception source is a text string to help trace where the exception occurred; "service:UserDefined" for example, would appear for a failed validation command with the UserDefined service. @@ -1654,7 +1645,7 @@ list and for viewing the CORE daemon and node log files. .. index:: CEL batch mode .. NOTE:: - In batch mode, exceptions received from the CORE daemon are displayed on + In batch mode, exceptions received from the CORE daemon are displayed on the console. .. _Configuration_Files: @@ -1668,16 +1659,16 @@ Configuration Files Configurations are saved to :file:`xml` or :file:`.imn` topology files using the *File* menu. You -can easily edit these files with a text editor. +can easily edit these files with a text editor. Any time you edit the topology file, you will need to stop the emulation if it were running and reload the file. -The :file:`.xml` `file schema is specified by NRL `_ and there are two versions to date: -version 0.0 and version 1.0, -with 1.0 as the current default. CORE can open either XML version. However, the -xmlfilever line in :file:`/etc/core/core.conf` controls the version of the XML file -that CORE will create. +The :file:`.xml` `file schema is specified by NRL `_ and there are two versions to date: +version 0.0 and version 1.0, +with 1.0 as the current default. CORE can open either XML version. However, the +xmlfilever line in :file:`/etc/core/core.conf` controls the version of the XML file +that CORE will create. .. index:: Scenario Plan XML @@ -1685,7 +1676,7 @@ In version 1.0, the XML file is also referred to as the Scenario Plan. The Scena made up of the following: -* `Network Plan` - describes nodes, hosts, interfaces, and the networks to +* `Network Plan` - describes nodes, hosts, interfaces, and the networks to which they belong. * `Motion Plan` - describes position and motion patterns for nodes in an emulation. @@ -1694,7 +1685,7 @@ made up of the following: * `Visualization Plan` - meta-data that is not part of the NRL XML schema but used only by CORE. For example, GUI options, canvas and annotation info, etc. are contained here. -* `Test Bed Mappings` - describes mappings of nodes, interfaces and EMANE modules in the scenario to +* `Test Bed Mappings` - describes mappings of nodes, interfaces and EMANE modules in the scenario to test bed hardware. CORE includes Test Bed Mappings in XML files that are saved while the scenario is running. @@ -1710,7 +1701,7 @@ indentation is one tab character. .. tip:: There are several topology examples included with CORE in the :file:`configs/` directory. - This directory can be found in :file:`~/.core/configs`, or + This directory can be found in :file:`~/.core/configs`, or installed to the filesystem under :file:`/usr[/local]/share/examples/configs`. diff --git a/gui/Makefile.am b/gui/Makefile.am index 25c494fd..65cf085b 100644 --- a/gui/Makefile.am +++ b/gui/Makefile.am @@ -33,8 +33,6 @@ CONFIG_FILES = configs/sample1.imn configs/sample1.scen \ configs/sample9-vpn.imn \ configs/sample10-kitchen-sink.imn -OTHER_FILES = core-bsd-cleanup.sh - # # CORE GUI script (/usr/local/bin/core-gui) # @@ -44,7 +42,7 @@ dist_bin_SCRIPTS = core-gui # Tcl/Tk scripts (/usr/local/lib/core) # coredir = $(CORE_LIB_DIR) -dist_core_DATA = $(TCL_FILES) +dist_core_DATA = $(TCL_FILES) dist_core_SCRIPTS = $(OTHER_FILES) # @@ -57,7 +55,7 @@ dist_coreaddons_DATA = $(ADDONS_FILES) # Sample configs (/usr/local/share/core/examples/configs) # coreconfigsdir = $(datadir)/core/examples/configs -dist_coreconfigs_DATA = $(CONFIG_FILES) +dist_coreconfigs_DATA = $(CONFIG_FILES) dist-hook: rm -rf $(distdir)/addons/.svn diff --git a/gui/api.tcl b/gui/api.tcl index df6e611e..89b02605 100644 --- a/gui/api.tcl +++ b/gui/api.tcl @@ -135,7 +135,7 @@ proc receiveMessage { channel } { # # Open an API socket to the specified server:port, prompt user for retry -# if specified; set the readable file event and parameters; +# if specified; set the readable file event and parameters; # returns the channel name or -1 on error. # proc openAPIChannel { server port retry } { @@ -186,7 +186,7 @@ proc openAPIChannel { server port retry } { # now we have a valid socket, set up encoding and receive event fconfigure $s -blocking 0 -encoding binary -translation { binary binary } \ - -buffering full -buffersize 4096 + -buffering full -buffersize 4096 fileevent $s readable [list receiveMessage $s] return $s } @@ -299,7 +299,7 @@ proc parseNodeMessage { data len flags } { # verbose debugging #puts "tlv type=$type length=$length pad=$pad current=$current" incr current 2 - + if {![info exists typenames($type)] } { ;# unknown TLV type if { $prmsg } { puts -nonewline "unknown=$type," } incr current $length @@ -352,11 +352,11 @@ proc parseNodeMessage { data len flags } { } else { set exists true } - + if { $vals(name) == "" } {; # make sure there is a node name set name $node if { $exists } { set name [getNodeName $node] } - array set vals [list name $name] + array set vals [list name $name] } if { $exists } { if { $flags == 1 } { @@ -384,9 +384,7 @@ proc parseNodeMessage { data len flags } { set wlans_needing_update { } if { $vals(emuid) != -1 } { - # For Linux (FreeBSD populates ngnodeidmap in l3node.instantiate/ - # buildInterface when the netgraph ID is known) - # populate ngnodeidmap for later use with wireless; it is treated as + # For Linux populate ngnodeidmap for later use with wireless; it is treated as # a hex value string (without the leading "0x") global ngnodeidmap foreach wlan [findWlanNodes $node] { @@ -484,7 +482,7 @@ proc apiNodeCreate { node vals_ref } { return } set canv "c$canv" - if { [lsearch $canvas_list $canv] < 0 && $canv == "c0" } { + if { [lsearch $canvas_list $canv] < 0 && $canv == "c0" } { # special case -- support old imn files with Canvas0 global $canv lappend canvas_list $canv @@ -787,12 +785,12 @@ proc apiLinkAddModify { node1 node2 vals_ref add } { updateLinkGuiAttr $wired_link $vals(guiattr) return # if add flag is set and a wired link already exists, assume wlan linkage - # special case: rj45 model=1 means link via wireless + # special case: rj45 model=1 means link via wireless } elseif {[nodeType $node1] == "rj45" || [nodeType $node2] == "rj45"} { if { [nodeType $node1] == "rj45" } { set rj45node $node1; set othernode $node2; } else { set rj45node $node2; set othernode $node1; } - if { [netconfFetchSection $rj45node model] == 1 } { + if { [netconfFetchSection $rj45node model] == 1 } { set wlan [findWlanNodes $othernode] if {$wlan != ""} {newGUILink $wlan $rj45node};# link rj4node to wlan } @@ -1034,7 +1032,7 @@ proc parseRegMessage { data len flags channel } { # TLV header if { [binary scan $data @${current}cc type length] != 2 } { puts "TLV header error" - break + break } set length [expr {$length & 0xFF}]; # convert signed to unsigned if { $length == 0 } { @@ -1078,9 +1076,9 @@ proc parseRegMessage { data len flags channel } { if { $session != "" } { # The channel passed to here is soon after discarded for # sessions that are started from XML or Python scripts. This causes - # an exception in the GUI when responding back to daemon if the - # response is sent after the channel has been destroyed. Setting - # the channel to -1 basically disables the GUI response to the daemon, + # an exception in the GUI when responding back to daemon if the + # response is sent after the channel has been destroyed. Setting + # the channel to -1 basically disables the GUI response to the daemon, # but it turns out the daemon does not need the response anyway. set channel -1 # assume session string only contains one session number @@ -1432,7 +1430,7 @@ proc parseEventMessage { data len flags channel } { 2 { incr current $pad binary scan $data @${current}I eventtype - if { $prmsg == 1} { + if { $prmsg == 1} { set typestr "" foreach t [array names eventtypes] { if { $eventtypes($t) == $eventtype } { @@ -1493,7 +1491,7 @@ proc parseEventMessage { data len flags channel } { set name [lindex [getEmulPlugin "*"] 0] if { [getAssignedRemoteServers] == "" } { # start a new session if not distributed - # otherwise we need to allow time for node delete messages + # otherwise we need to allow time for node delete messages # from other servers pluginConnect $name disconnect 1 pluginConnect $name connect 1 @@ -1529,7 +1527,7 @@ proc parseSessionMessage { data len flags channel } { set typelength [parseTLVHeader $data current] set type [lindex $typelength 0] set length [lindex $typelength 1] - if { $length == 0 || $length == "" } { + if { $length == 0 || $length == "" } { puts "warning: zero-length TLV, discarding remainder of message!" break } @@ -1737,7 +1735,7 @@ proc sendNodePosMessage { channel node nodeid x y wlanid force } { if {$wlanid > -1} { incr len 8 } if {$force == 1 } { set crit 0x4 } else { set crit 0x0 } #puts "sending [expr $len+4] bytes: $nodeid $x $y $wlanid" - if { $prmsg == 1 } { + if { $prmsg == 1 } { puts -nonewline ">NODE(flags=$crit,$node,x=$x,y=$y" } set msg [binary format ccSc2sIc2Sc2S \ 1 $crit $len \ @@ -1805,8 +1803,8 @@ proc sendNodeAddMessage { channel node } { } else { set canv "" } - - # services + + # services set svc [getNodeServices $node false] set svc [join $svc "|"] set svc_len [string length $svc] @@ -1854,7 +1852,7 @@ proc sendNodeAddMessage { channel node } { set mac [join [split $macstr ":"] ""] puts -nonewline $channel [binary format c2x2W {0x5 8} 0x$mac] } - + # IPv6 address if { $ipv6 != 0 } { if { $prmsg == 1 } { puts -nonewline "$ipv6str," } @@ -1943,7 +1941,7 @@ proc sendNodeDelMessage { channel node } { proc sendLinkMessage { channel link type {sendboth true} } { global showAPI set prmsg $showAPI - + set node1 [lindex [linkPeers $link] 0] set node2 [lindex [linkPeers $link] 1] set if1 [ifcByPeer $node1 $node2]; set if2 [ifcByPeer $node2 $node1] @@ -2207,7 +2205,7 @@ proc getIfcAddrs { node ifc ipv4p ipv6p macp ipv4maskp ipv6maskp lenp } { # IPv4 address set ipv4str [getIfcIPv4addr $node $ifc] - if {$ipv4str != ""} { + if {$ipv4str != ""} { set ipv4 [lindex [split $ipv4str /] 0] if { [info exists ipv4mask ] } { set ipv4mask [lindex [split $ipv4str / ] 1] @@ -2222,7 +2220,7 @@ proc getIfcAddrs { node ifc ipv4p ipv6p macp ipv4maskp ipv6maskp lenp } { # IPv6 address set ipv6str [getIfcIPv6addr $node $ifc] - if {$ipv6str != ""} { + if {$ipv6str != ""} { set ipv6 [lindex [split $ipv6str /] 0] if { [info exists ipv6mask ] } { set ipv6mask [lindex [split $ipv6str / ] 1] @@ -2248,7 +2246,7 @@ proc getIfcAddrs { node ifc ipv4p ipv6p macp ipv4maskp ipv6maskp lenp } { # # Register Message: (registration types) -# This is a simple Register Message, types is an array of +# This is a simple Register Message, types is an array of # tuples. proc sendRegMessage { channel flags types_list } { global showAPI regtypes @@ -2361,7 +2359,7 @@ proc sendConfRequestMessage { channel node model flags netid opaque } { set msg4 [binary format c2sI {0x23 4} 0 0x$netid ] } - #catch {puts -nonewline $channel $msg1$model$model_pad$msg2$msg3$msg4$msg5} + #catch {puts -nonewline $channel $msg1$model$model_pad$msg2$msg3$msg4$msg5} puts -nonewline $channel $msg1$msg1b$msg1c$model$model_pad$msg2$msg3$msg4 if { $opaque_len > 0 } { puts -nonewline $channel $msgop } @@ -2436,7 +2434,7 @@ proc sendConfReplyMessage { channel node model types values opaque } { # session number set msg3 "" if { $session != "" } { - incr len [expr {2 + $session_len + $session_pad_len }] + incr len [expr {2 + $session_len + $session_pad_len }] set msg3 [binary format cc 0x0A $session_len] set msg3 $msg3$session$session_pad } @@ -2472,7 +2470,7 @@ proc sendEventMessage { channel type nodenum name data flags } { set data_pad_len [pad_32bit $data_len] if { $data_len > 0 } { incr len [expr {2 + $data_len + $data_pad_len}] } - if { $prmsg == 1 } { + if { $prmsg == 1 } { puts -nonewline ">EVENT(flags=$flags," } set msg [binary format ccS 8 $flags $len ] ;# message header @@ -2481,7 +2479,7 @@ proc sendEventMessage { channel type nodenum name data flags } { if { $prmsg == 1 } { puts -nonewline "node=$nodenum," } set msg2 [binary format c2sI {0x01 4} 0 $nodenum] } - if { $prmsg == 1} { + if { $prmsg == 1} { set typestr "" foreach t [array names eventtypes] { if { $eventtypes($t) == $type } { set typestr "-$t"; break } @@ -2513,7 +2511,7 @@ proc sendEventMessage { channel type nodenum name data flags } { # deploy working configuration using CORE API -# Deploys a current working configuration. It creates all the +# Deploys a current working configuration. It creates all the # nodes and link as defined in configuration file. proc deployCfgAPI { sock } { global eid @@ -2546,13 +2544,13 @@ proc deployCfgAPI { sock } { sendSessionProperties $sock - # this tells the CORE services that we are starting to send + # this tells the CORE services that we are starting to send # configuration data # clear any existing config sendEventMessage $sock $eventtypes(definition_state) -1 "" "" 0 # inform CORE services about emulation servers, hook scripts, canvas info, # and services - sendEventMessage $sock $eventtypes(configuration_state) -1 "" "" 0 + sendEventMessage $sock $eventtypes(configuration_state) -1 "" "" 0 sendEmulationServerInfo $sock 0 sendSessionOptions $sock sendHooks $sock @@ -2567,7 +2565,7 @@ proc deployCfgAPI { sock } { set type [nodeType $node] set name [getNodeName $node] if { $type == "pseudo" } { continue } - + statgraph inc 1 statline "Creating node $name" if { [[typemodel $node].layer] == "NETWORK" } { @@ -2611,7 +2609,7 @@ proc deployCfgAPI { sock } { # status bar graph statgraph off 0 statline "Network topology instantiated in [expr [clock seconds] - $t_start] seconds ([llength $node_list] nodes and [llength $link_list] links)." - + # TODO: turn on tcpdump if enabled; customPostConfigCommands; # addons 4 deployCfgHook @@ -2628,8 +2626,8 @@ proc deployCfgAPI { sock } { sendTrafficScripts $sock # tell the CORE services that we are ready to instantiate - sendEventMessage $sock $eventtypes(instantiation_state) -1 "" "" 0 - + sendEventMessage $sock $eventtypes(instantiation_state) -1 "" "" 0 + set deployCfgAPI_lock 0 ;# unlock statline "Network topology instantiated in [expr [clock seconds] - $t_start] seconds ([llength $node_list] nodes and [llength $link_list] links)." @@ -2651,7 +2649,7 @@ proc shutdownSession {} { set plugin [lindex [getEmulPlugin "*"] 0] set sock [pluginConnect $plugin connect true] - sendEventMessage $sock $eventtypes(datacollect_state) -1 "" "" 0 + sendEventMessage $sock $eventtypes(datacollect_state) -1 "" "" 0 # shut down all links foreach link $link_list { @@ -2712,7 +2710,7 @@ proc sendNodeTypeInfo { sock reset } { sendConfRequestMessage $sock -1 "all" 0x3 -1 "" return } - # build a list of node types in use + # build a list of node types in use set typesinuse "" foreach node $node_list { set type [nodeType $node] @@ -2974,7 +2972,7 @@ proc sendFileMessage { channel node type f sf data data_len } { set prmsg $showAPI set node_num [string range $node 1 end] - + set f_len [string length $f] set f_pad_len [pad_32bit $f_len] set f_pad [binary format x$f_pad_len] @@ -3013,7 +3011,7 @@ proc sendFileMessage { channel node type f sf data data_len } { if { $prmsg == 1 } { puts -nonewline ">FILE(flags=$flags,$node,f=$f," if { $type != "" } { puts -nonewline "type=$type," } - if { $sf != "" } { puts "src=$sf)" + if { $sf != "" } { puts "src=$sf)" } else { puts "data=($data_len))" } } @@ -3077,7 +3075,7 @@ proc sendSessionMessage { channel flags num name sfile nodecount tf user } { set user_pad_len [pad_32bit $user_len] if { $user_len > 0 } { incr len [expr { 2 + $user_len + $user_pad_len }] } - if { $prmsg == 1 } { + if { $prmsg == 1 } { puts -nonewline ">SESSION(flags=$flags" } set msgh [binary format ccS 0x09 $flags $len ] ;# message header @@ -3089,7 +3087,7 @@ proc sendSessionMessage { channel flags num name sfile nodecount tf user } { set msg2 "" if { $name_len > 0 } { if { $prmsg == 1 } { puts -nonewline ",name=$name" } - # TODO: name_len > 255 + # TODO: name_len > 255 set name_hdr [binary format cc 0x02 $name_len] set name_pad [binary format x$name_pad_len] set msg2 "$name_hdr$name$name_pad" @@ -3097,7 +3095,7 @@ proc sendSessionMessage { channel flags num name sfile nodecount tf user } { set msg3 "" if { $sfile_len > 0 } { if { $prmsg == 1 } { puts -nonewline ",file=$sfile" } - # TODO: sfile_len > 255 + # TODO: sfile_len > 255 set sfile_hdr [binary format cc 0x03 $sfile_len] set sfile_pad [binary format x$sfile_pad_len] set msg3 "$sfile_hdr$sfile$sfile_pad" @@ -3150,11 +3148,11 @@ proc xmlFileLoadSave { cmd name } { # inform daemon about nodes and links when saving in edit mode if { $cmd == "save" && $oper_mode != "exec" } { sendSessionProperties $sock - # this tells the CORE services that we are starting to send + # this tells the CORE services that we are starting to send # configuration data # clear any existing config sendEventMessage $sock $eventtypes(definition_state) -1 "" "" 0 - sendEventMessage $sock $eventtypes(configuration_state) -1 "" "" 0 + sendEventMessage $sock $eventtypes(configuration_state) -1 "" "" 0 sendEmulationServerInfo $sock 0 sendSessionOptions $sock sendHooks $sock @@ -3246,7 +3244,7 @@ proc buildStringTLV { type data len_ref } { } if { $data_len > 255 } { - set hdr [binary format ccS $type 0 $data_len] + set hdr [binary format ccS $type 0 $data_len] set hdr_len 4 } else { set hdr [binary format cc $type $data_len] @@ -3274,7 +3272,7 @@ proc pad_32bit { len } { proc macToString { mac_num } { set mac_bytes "" - # convert 64-bit integer into 12-digit hex string + # convert 64-bit integer into 12-digit hex string set mac_num 0x[format "%.12lx" $mac_num] while { $mac_num > 0 } { # append 8-bit hex number to list @@ -3295,7 +3293,7 @@ proc macToString { mac_num } { set r {} set i [llength $mac_bytes] while { $i > 0 } { lappend r [lindex $mac_bytes [incr i -1]] } - + return [join $r :] } diff --git a/gui/cfgparse.tcl b/gui/cfgparse.tcl index ce84e81e..6e730886 100644 --- a/gui/cfgparse.tcl +++ b/gui/cfgparse.tcl @@ -35,24 +35,24 @@ # NAME # cfgparse.tcl -- file used for parsing the configuration # FUNCTION -# This module is used for parsing the configuration, i.e. reading the -# configuration from a file or a string and writing the configuration -# to a file or a string. This module also contains a function for returning +# This module is used for parsing the configuration, i.e. reading the +# configuration from a file or a string and writing the configuration +# to a file or a string. This module also contains a function for returning # a new ID for nodes, links and canvases. #**** #****f* nodecfg.tcl/dumpputs # NAME -# dumpputs -- puts a string to a file or a string configuration +# dumpputs -- puts a string to a file or a string configuration # SYNOPSIS # dumpputs $method $destination $string # FUNCTION -# Puts a sting to the file or appends the string configuration (used for +# Puts a sting to the file or appends the string configuration (used for # undo functions), the choice depends on the value of method parameter. # INPUTS -# * method -- method used. Possiable values are file (if saving the string +# * method -- method used. Possiable values are file (if saving the string # to the file) and string (if appending the string configuration) -# * dest -- destination used. File_id for files, and string name for string +# * dest -- destination used. File_id for files, and string name for string # configuration # * string -- the string that is inserted to a file or appended to the string # configuartion @@ -73,7 +73,7 @@ proc dumpputs {method dest string} { #****f* nodecfg.tcl/dumpCfg # NAME -# dumpCfg -- puts the current configuraton to a file or a string +# dumpCfg -- puts the current configuraton to a file or a string # SYNOPSIS # dumpCfg $method $destination # FUNCTION @@ -81,7 +81,7 @@ proc dumpputs {method dest string} { # INPUTS # * method -- used method. Possiable values are file (saving current congif # to the file) and string (saving current config in a string) -# * dest -- destination used. File_id for files, and string name for string +# * dest -- destination used. File_id for files, and string name for string # configurations #**** @@ -95,7 +95,7 @@ proc dumpCfg {method dest} { dumpputs $method $dest "\}" dumpputs $method $dest "" } - + foreach node $node_list { global $node upvar 0 $node lnode @@ -129,7 +129,7 @@ proc dumpCfg {method dest} { } } dumpputs $method $dest " \}" - } elseif { "[lindex $element 0]" == "ipsec-config" } { + } elseif { "[lindex $element 0]" == "ipsec-config" } { dumpputs $method $dest " ipsec-config \{" foreach line [lindex $element 1] { if { $line != {} } { @@ -228,24 +228,24 @@ proc dumpGlobalOptions { method dest } { global mac_addr_start dumpputs $method $dest "option global \{" - if {$showIfNames == 0} { - dumpputs $method $dest " interface_names no" + if {$showIfNames == 0} { + dumpputs $method $dest " interface_names no" } else { dumpputs $method $dest " interface_names yes" } - if {$showIfIPaddrs == 0} { - dumpputs $method $dest " ip_addresses no" + if {$showIfIPaddrs == 0} { + dumpputs $method $dest " ip_addresses no" } else { dumpputs $method $dest " ip_addresses yes" } - if {$showIfIPv6addrs == 0} { - dumpputs $method $dest " ipv6_addresses no" + if {$showIfIPv6addrs == 0} { + dumpputs $method $dest " ipv6_addresses no" } else { dumpputs $method $dest " ipv6_addresses yes" } - if {$showNodeLabels == 0} { - dumpputs $method $dest " node_labels no" + if {$showNodeLabels == 0} { + dumpputs $method $dest " node_labels no" } else { dumpputs $method $dest " node_labels yes" } - if {$showLinkLabels == 0} { - dumpputs $method $dest " link_labels no" + if {$showLinkLabels == 0} { + dumpputs $method $dest " link_labels no" } else { dumpputs $method $dest " link_labels yes" } if {$showAPI == 0} { @@ -290,7 +290,7 @@ proc setGlobalOption { field value } { global showIfIPaddrs showIfIPv6addrs global showBkgImage showGrid showAnnotations global showAPI - global mac_addr_start + global mac_addr_start global g_traffic_start_opt global g_view_locked @@ -400,8 +400,8 @@ proc cleanupGUIState {} { # SYNOPSIS # loadCfg $cfg # FUNCTION -# Loads the configuration written in the cfg string to a current -# configuration. +# Loads the configuration written in the cfg string to a current +# configuration. # INPUTS # * cfg -- string containing the new working configuration. #**** @@ -489,7 +489,7 @@ proc loadCfg { cfg } { # consume first two list elements from line set value [lindex $line 1] set line [lreplace $line 0 1] - + if {"$class" == "node"} { switch -exact -- $field { type { @@ -561,7 +561,7 @@ proc loadCfg { cfg } { } ipsec-config { set cfg "" - + foreach zline [split $value { }] { if { [string index "$zline" 0] == " " } { @@ -600,7 +600,8 @@ proc loadCfg { cfg } { custom-pre-config-commands { # Boeing - custom pre config commands set cfg "" - foreach zline [split $value { }] { + foreach zline [split $value { +}] { if { [string index "$zline" 0] == " " } { set zline [string replace "$zline" 0 0] } @@ -612,7 +613,8 @@ proc loadCfg { cfg } { custom-post-config-commands { # Boeing - custom post config commands set cfg "" - foreach zline [split $value { }] { + foreach zline [split $value { +}] { if { [string index "$zline" 0] == " " } { set zline [string replace "$zline" 0 0] } @@ -628,7 +630,8 @@ proc loadCfg { cfg } { ine-config { # Boeing - INE set cfg "" - foreach zline [split $value { }] { + foreach zline [split $value { +}] { if { [string index "$zline" 0] == " " } { set zline [string replace "$zline" 0 0] } @@ -682,7 +685,7 @@ proc loadCfg { cfg } { switch -exact -- $field { name { lappend $object "name $value" - } + } height { lappend $object "height $value" } @@ -695,10 +698,10 @@ proc loadCfg { cfg } { y { lappend $object "y $value" } - color { + color { lappend $object "color $value" - } - } + } + } } elseif {"$class" == "link"} { switch -exact -- $field { nodes { @@ -863,20 +866,20 @@ proc loadCfg { cfg } { #****f* nodecfg.tcl/newObjectId # NAME -# newObjectId -- new object Id +# newObjectId -- new object Id # SYNOPSIS # set obj_id [newObjectId $type] # FUNCTION # Returns the Id for a new object of the defined type. Supported types -# are node, link and canvas. The Id is in the form $mark$number. $mark is the +# are node, link and canvas. The Id is in the form $mark$number. $mark is the # first letter of the given type and $number is the first available number to -# that can be used for id. +# that can be used for id. # INPUTS # * type -- the type of the new object. Can be node, link or canvas. # RESULT -# * obj_id -- object Id in the form $mark$number. $mark is the +# * obj_id -- object Id in the form $mark$number. $mark is the # first letter of the given type and $number is the first available number to -# that can be used for id. +# that can be used for id. #**** proc newObjectId { type } { @@ -950,7 +953,7 @@ proc loadServersConf { } { global CONFDIR exec_servers DEFAULT_API_PORT set confname "$CONFDIR/servers.conf" if { [catch { set f [open "$confname" r] } ] } { - puts "Creating a default $confname" + puts "Creating a default $confname" if { [catch { set f [open "$confname" w+] } ] } { puts "***Warning: could not create a default $confname file." return @@ -1035,7 +1038,7 @@ proc popupPrefs {} { -command "addFileToMrulist \"\"" pack $wi.dirs.mru.label $wi.dirs.mru.num $wi.dirs.mru.clear -side left pack $wi.dirs.mru -side top -anchor w -padx 4 -pady 4 - + pack $wi.dirs -side top -fill x # @@ -1049,7 +1052,7 @@ proc popupPrefs {} { -variable g_prefs(gui_save_size) pack $wi.win.win.savepos $wi.win.win.savesiz -side left -anchor w -padx 4 pack $wi.win.win -side top -anchor w -padx 4 -pady 4 - + frame $wi.win.a checkbutton $wi.win.a.snaptogrid -text "snap to grid" \ -variable g_prefs(gui_snap_grid) @@ -1123,9 +1126,8 @@ proc initDefaultPrefs {} { # variable expansions must be done here array set g_prefs [list default_conf_path "$CONFDIR/configs"] array set g_prefs [list gui_canvas_refpt "$DEFAULT_REFPT"] - if { $tcl_platform(os) == "FreeBSD" } { set shell "/usr/local/bin/bash" - } else { set shell "bash" } - array set g_prefs [list shell $shell] + set shell "bash" + array set g_prefs [list shell $shell] array set g_prefs [list gui_text_editor [get_text_editor true]] array set g_prefs [list gui_term_prog [get_term_prog true]] setDefaultAddrs ipv4 diff --git a/gui/configs/sample5-mgen.imn b/gui/configs/sample5-mgen.imn index e27b55a7..d80a58a6 100644 --- a/gui/configs/sample5-mgen.imn +++ b/gui/configs/sample5-mgen.imn @@ -86,11 +86,7 @@ node n2 { HN=`hostname` SCRIPTDIR=$SESSION_DIR LOGDIR=/var/log - - if [ `uname` = "FreeBSD" ]; then - SCRIPTDIR=/tmp/e0_$HN - LOGDIR=$SCRIPTDIR - fi + cd $SCRIPTDIR ( cat << 'EOF' diff --git a/gui/editor.tcl b/gui/editor.tcl index e558cda5..1195ee18 100644 --- a/gui/editor.tcl +++ b/gui/editor.tcl @@ -34,7 +34,7 @@ #****h* imunes/editor.tcl # NAME # editor.tcl -- file used for defining functions that can be used in -# edit mode as well as all the functions which change the appearance +# edit mode as well as all the functions which change the appearance # of the imunes GUI. # FUNCTION # This module is used for defining all possible actions in imunes @@ -71,8 +71,8 @@ proc animateCursor {} { # split links and links connecting nodes on different canvases. # INPUTS # * link_id -- the link id -# * atomic -- defines if the remove was atomic action or a part -# of a composed, non-atomic action (relevant for updating log +# * atomic -- defines if the remove was atomic action or a part +# of a composed, non-atomic action (relevant for updating log # for undo). #**** @@ -137,7 +137,7 @@ proc removeGUINode { node } { # SYNOPSIS # updateUndoLog # FUNCTION -# Updates the undo log. Writes the current configuration to the +# Updates the undo log. Writes the current configuration to the # undolog array and updates the undolevel variable. #**** @@ -161,7 +161,7 @@ proc updateUndoLog {} { # NAME # undo -- undo function # SYNOPSIS -# undo +# undo # FUNCTION # Undo the change. Reads the undolog and updates the current # configuration. Reduces the value of undolevel. @@ -185,10 +185,10 @@ proc undo {} { # SYNOPSIS # redo # FUNCTION -# Redo the change if possible (redolevel is greater than +# Redo the change if possible (redolevel is greater than # undolevel). Reads the configuration from undolog and -# updates the current configuration. Increases the value -# of undolevel. +# updates the current configuration. Increases the value +# of undolevel. #**** proc redo {} { @@ -244,7 +244,7 @@ proc redrawAll {} { "-$border -$border [expr {$e_sizex + $border}] \ [expr {$e_sizey + $border}]" - + saveRestoreWlanLinks .c save .c delete all set background [.c create rectangle 0 0 $e_sizex $e_sizey \ @@ -264,7 +264,7 @@ proc redrawAll {} { if { [getNodeCanvas $obj] == $curcanvas } { drawAnnotation $obj } - } + } } # Grid @@ -303,7 +303,7 @@ proc redrawAll {} { } } - redrawAllThruplots + redrawAllThruplots foreach link $link_list { set nodes [linkPeers $link] if { [getNodeCanvas [lindex $nodes 0]] != $curcanvas || @@ -330,7 +330,7 @@ proc redrawAll {} { # Draws the specified node. Draws node's image (router pc # host lanswitch rj45 hub pseudo) and label. # The visibility of the label depends on the showNodeLabels -# variable for all types of nodes and on invisible variable +# variable for all types of nodes and on invisible variable # for pseudo nodes. # INPUTS # * node_id -- node id @@ -342,7 +342,7 @@ proc drawNode { c node } { global curcanvas zoom global wlan if { $c == "" } { set c .c } ;# default canvas - + set type [nodeType $node] set coords [getNodeCoords $node] set x [expr {[lindex $coords 0] * $zoom}] @@ -361,7 +361,7 @@ proc drawNode { c node } { if { $tmp != "" } { set cimg $tmp } if { $cimg != "" } { # name of global variable storing the image is the filename without path - set img [file tail $cimg] + set img [file tail $cimg] # create the variable if the image hasn't been loaded before global [set img] if { ![info exists $img] } { @@ -433,9 +433,9 @@ proc drawNode { c node } { # SYNOPSIS # drawLink link_id # FUNCTION -# Draws the specified link. An arrow is displayed for links +# Draws the specified link. An arrow is displayed for links # connected to pseudo nodes. If the variable invisible -# is specified link connecting a pseudo node stays hidden. +# is specified link connecting a pseudo node stays hidden. # INPUTS # * link_id -- link id #**** @@ -486,7 +486,7 @@ proc drawLink { link } { } foreach n [list $lnode1 $lnode2] { if { [getNodeHidden $n] } { - hideNode $n + hideNode $n statline "Hidden node(s) exist." } } @@ -535,7 +535,7 @@ proc drawWlanLink { node1 node2 wlan } { # set ifcName [chooseIfName $lnode1 $lnode2] # FUNCTION # Choose intreface name. The name can be: -# * eth -- for interface connecting pc, host and router +# * eth -- for interface connecting pc, host and router # * e -- for interface connecting hub and lanswitch # INPUTS # * link_id -- link id @@ -564,7 +564,7 @@ proc chooseIfName { lnode1 lnode2 } { return eth } rj45 { - return + return } tunnel { return e @@ -589,8 +589,8 @@ proc chooseIfName { lnode1 lnode2 } { # SYNOPSIS # set l2peers [listLANNodes $l2node $l2peers] # FUNCTION -# Recursive function for finding all link layer nodes that are -# connected to node l2node. Returns the list of all link layer +# Recursive function for finding all link layer nodes that are +# connected to node l2node. Returns the list of all link layer # nodes that are on the same LAN as l2node. # INPUTS # * l2node -- node id of a link layer node @@ -622,7 +622,7 @@ proc listLANnodes { l2node l2peers } { # FUNCTION # Calculates dx and dy variables of the calling function. # INPUTS -# * lnode -- node id of a node whose dx and dy coordinates are +# * lnode -- node id of a node whose dx and dy coordinates are # calculated #**** @@ -680,8 +680,8 @@ proc calcDxDy { lnode } { # address and IPv6 address. # INPUTS # * lnode1 -- node id of a node where the interface resides -# * lnode2 -- node id of the node that is connected by this -# interface. +# * lnode2 -- node id of the node that is connected by this +# interface. #**** proc updateIfcLabel { lnode1 lnode2 } { global showIfNames showIfIPaddrs showIfIPv6addrs @@ -715,7 +715,7 @@ proc updateIfcLabel { lnode1 lnode2 } { .c itemconfigure "interface && $lnode1 && $link" \ -text "$labelstr" # Boeing: hide ifc label on wlans - if { [nodeType $lnode1] == "wlan" } { + if { [nodeType $lnode1] == "wlan" } { .c itemconfigure "interface && $lnode1 && $link" -state hidden } } @@ -876,11 +876,11 @@ proc redrawWlanLink { link } { #****f* editor.tcl/splitGUILink # NAME -# splitGUILink -- splits a links +# splitGUILink -- splits a links # SYNOPSIS # splitGUILink $link # FUNCTION -# Splits the link and draws new links and new pseudo nodes +# Splits the link and draws new links and new pseudo nodes # on the canvas. # INPUTS # * link -- link id @@ -925,7 +925,7 @@ proc splitGUILink { link } { #****f* editor.tcl/selectNode # NAME -# selectNode -- select node +# selectNode -- select node # SYNOPSIS # selectNode $c $obj # FUNCTION @@ -1019,11 +1019,11 @@ proc selectAdjacent {} { #****f* editor.tcl/button3link # NAME -# button3link +# button3link # SYNOPSIS # button3link $c $x $y # FUNCTION -# This procedure is called when a right mouse button is +# This procedure is called when a right mouse button is # clicked on the canvas. If there is a link on the place of # mouse click this procedure creates and configures a popup # menu. The options in the menu are: @@ -1099,7 +1099,7 @@ proc button3link { c x y } { #****f* editor.tcl/movetoCanvas # NAME -# movetoCanvas -- move to canvas +# movetoCanvas -- move to canvas # SYNOPSIS # movetoCanvas $canvas # FUNCTION @@ -1176,7 +1176,7 @@ proc mergeGUINode { node } { # SYNOPSIS # button3node $c $x $y # FUNCTION -# This procedure is called when a right mouse button is +# This procedure is called when a right mouse button is # clicked on the canvas. Also called when double-clicking # on a node during runtime. # If there is a node on the place of @@ -1190,18 +1190,18 @@ proc mergeGUINode { node } { # that have mirror nodes on the same canvas (Pseudo nodes # created by splitting a link). # * Delete -- delete the node -# * Shell window -- specifies the shell window to open in -# exec mode. This option is available only to nodes on a +# * Shell window -- specifies the shell window to open in +# exec mode. This option is available only to nodes on a # network layer -# * Ethereal -- opens a Ethereal program for the specified -# node and the specified interface. This option is available +# * Ethereal -- opens a Ethereal program for the specified +# node and the specified interface. This option is available # only for network layer nodes in exec mode. # INPUTS # * c -- tk canvas # * x -- x coordinate for popup menu # * y -- y coordinate for popup menu #**** -#old proc button3node { c x y } +#old proc button3node { c x y } #Boeing proc button3node { c x y button } { global oper_mode env eid canvas_list node_list curcanvas systype g_prefs @@ -1242,7 +1242,7 @@ proc button3node { c x y button } { if { $button == "shift" } { ;# normal bash shell spawnShell $node $shell } else { ;# right-click vtysh shell - set cmd [[typemodel $node].shellcmd $node] + set cmd [[typemodel $node].shellcmd $node] if { $cmd != "/bin/sh" && $cmd != "" } { spawnShell $node $cmd } } return ;# open shell, don't post a menu @@ -1437,7 +1437,7 @@ proc button3node { c x y button } { addInterfaceCommand $node .button3menu "Wireshark" "wireshark -k -i" \ $execstate 0 # wireshark on host veth pair -- need veth pair name - #wireshark -k -i + #wireshark -k -i if { [lindex $systype 0] == "Linux" } { set name [getNodeName $node] .button3menu add command -label "View log..." -state $execstate \ @@ -1464,7 +1464,7 @@ proc button3node { c x y button } { # This procedure spawns a new shell for a specified node. # The shell is specified in cmd parameter. # INPUTS -# * node -- node id of the node for which the shell +# * node -- node id of the node for which the shell # is spawned. # * cmd -- the path to the shell. #**** @@ -1527,9 +1527,9 @@ proc raiseAll {c} { # SYNOPSIS # button1 $c $x $y $button # FUNCTION -# This procedure is called when a left mouse button is +# This procedure is called when a left mouse button is # clicked on the canvas. This procedure selects a new -# node or creates a new node, depending on the selected +# node or creates a new node, depending on the selected # tool. # INPUTS # * c -- tk canvas @@ -1563,7 +1563,7 @@ proc button1 { c x y button } { set curobj [$c find withtag current] set curtype [lindex [$c gettags current] 0] - + if { $curtype == "node" || \ $curtype == "oval" || $curtype == "rectangle" || $curtype == "text" \ || ( $curtype == "nodelabel" && \ @@ -1613,7 +1613,7 @@ proc button1 { c x y button } { if { $g_view_locked == 1 } { return } if { $activetoolp == "routers" } { if {$activetool != "OVS"} { - set node [newNode router] + set node [newNode router] } else { set node [newNode OVS]} setNodeModel $node $activetool @@ -1666,7 +1666,7 @@ proc button1 { c x y button } { set newlink [$c create line $lastX $lastY $x $y \ -fill $defLinkColor -width $defLinkWidth \ -tags "link"] - # twonode tool support + # twonode tool support } elseif {$g_twoNodeSelect != "" && $curtype == "node"} { set curnode [lindex [$c gettags $curobj] 1] selectTwoNode $curnode @@ -1683,14 +1683,14 @@ proc setResizeMode { c x y } { set isThruplot false set type1 notset - if {$c == ".c"} { + if {$c == ".c"} { set t1 [$c gettags current] set o1 [lindex $t1 1] set type1 [nodeType $o1] } else { set o1 $c set c .c - set isThruplot true + set isThruplot true } #DYL #puts "RESIZE NODETYPE = $type1" @@ -1743,11 +1743,11 @@ proc setResizeMode { c x y } { # NAME # button1-motion # SYNOPSIS -# button1-motion $c $x $y +# button1-motion $c $x $y # FUNCTION -# This procedure is called when a left mouse button is -# pressed and the mouse is moved around the canvas. -# This procedure creates new select box, moves the +# This procedure is called when a left mouse button is +# pressed and the mouse is moved around the canvas. +# This procedure creates new select box, moves the # selected nodes or draws a new link. # INPUTS # * c -- tk canvas @@ -1767,8 +1767,8 @@ proc button1-motion { c x y } { if {$thruPlotDragStart == "dragging"} { #puts "active tool is $activetool" - thruPlotDrag $c $thruPlotCur $x $y null true - return + thruPlotDrag $c $thruPlotCur $x $y null true + return } # fix occasional error @@ -1800,7 +1800,7 @@ proc button1-motion { c x y } { set dx [expr {$x-$lastX} ] set dy [expr {$y-$lastY} ] # this provides smoother drawing - if { $dx > $markersize || $dy > $markersize } { + if { $dx > $markersize || $dy > $markersize } { set mark [$c create line $lastX $lastY $x $y \ -width $markersize -fill $markercolor -tags "marker"] $c raise $mark \ @@ -1886,7 +1886,7 @@ proc button1-motion { c x y } { } # resizing an annotation } elseif { $curtype == "selectmark" } { - foreach o [$c find withtag "selected"] { + foreach o [$c find withtag "selected"] { set node [lindex [$c gettags $o] 1] set tagovi [$c gettags $o] set koord [getNodeCoords $node] @@ -1992,12 +1992,12 @@ proc button1-motion { c x y } { #****f* editor.tcl/pseudo.layer # NAME -# pseudo.layer +# pseudo.layer # SYNOPSIS # set layer [pseudo.layer] # FUNCTION # Returns the layer on which the pseudo node operates -# i.e. returns no layer. +# i.e. returns no layer. # RESULT # * layer -- returns an empty string #**** @@ -2011,8 +2011,8 @@ proc pseudo.layer {} { # SYNOPSIS # newGUILink $lnode1 $lnode2 # FUNCTION -# This procedure is called to create a new link between -# nodes lnode1 and lnode2. Nodes can be on the same canvas +# This procedure is called to create a new link between +# nodes lnode1 and lnode2. Nodes can be on the same canvas # or on different canvases. The result of this function # is directly visible in GUI. # INPUTS @@ -2052,10 +2052,10 @@ proc newGUILink { lnode1 lnode2 } { # NAME # button1-release # SYNOPSIS -# button1-release $c $x $y +# button1-release $c $x $y # FUNCTION -# This procedure is called when a left mouse button is -# released. +# This procedure is called when a left mouse button is +# released. # The result of this function depends on the actions # during the button1-motion procedure. # INPUTS @@ -2202,7 +2202,7 @@ proc button1-release { c x y } { nodeEnter $c # $changed!=1 - } elseif {$activetool == "select" } { + } elseif {$activetool == "select" } { if {$selectbox == ""} { set x1 $x set y1 $y @@ -2243,10 +2243,10 @@ proc button1-release { c x y } { } else { # select tool resizing an object by dragging its handles # DYL bugfix. if x,y does not change, do not resize! - # fixes a bug where the object dissappears - if { $x != $x1 || $y != $y1 } { + # fixes a bug where the object dissappears + if { $x != $x1 || $y != $y1 } { setNodeCoords $resizeobj "$x $y $x1 $y1" - } + } set redrawNeeded 1 set resizemode false } @@ -2269,11 +2269,11 @@ proc button1-release { c x y } { # SYNOPSIS # nodeEnter $c # FUNCTION -# This procedure prints the node id, node name and +# This procedure prints the node id, node name and # node model (if exists), as well as all the interfaces -# of the node in the status line. +# of the node in the status line. # Information is presented for the node above which is -# the mouse pointer. +# the mouse pointer. # INPUTS # * c -- tk canvas #**** @@ -2314,7 +2314,7 @@ proc nodeEnter { c } { # This procedure prints the link id, link bandwidth # and link delay in the status line. # Information is presented for the link above which is -# the mouse pointer. +# the mouse pointer. # INPUTS # * c -- tk canvas #**** @@ -2351,13 +2351,13 @@ proc anyLeave {c} { } -#****f* editor.tcl/checkIntRange +#****f* editor.tcl/checkIntRange # NAME # checkIntRange -- check integer range # SYNOPSIS # set check [checkIntRange $str $low $high] # FUNCTION -# This procedure checks the input string to see if it is +# This procedure checks the input string to see if it is # an integer between the low and high value. # INPUTS # str -- string to check @@ -2407,14 +2407,14 @@ proc checkHostname { str } { } -#****f* editor.tcl/focusAndFlash +#****f* editor.tcl/focusAndFlash # NAME # focusAndFlash -- focus and flash # SYNOPSIS # focusAndFlash $W $count # FUNCTION # This procedure sets the focus on the bad entry field -# and on this filed it provides an effect of flashing +# and on this filed it provides an effect of flashing # for approximately 1 second. # INPUTS # * W -- textbox field that caused the bed entry @@ -2454,7 +2454,7 @@ proc focusAndFlash {W {count 9}} { # SYNOPSIS # popupConfigDialog $c # FUNCTION -# Dynamically creates a popup dialog box for configuring +# Dynamically creates a popup dialog box for configuring # links or nodes in IMUNES. # INPUTS # * c -- canvas id @@ -2540,10 +2540,10 @@ proc popupConfigDialog { c } { $wi.ftop.name insert 0 [getNodeName $target] set img [getNodeImage $target] ttk::button $wi.ftop.img -image $img -command "popupCustomImage $target" - + if { $type == "rj45" } { rj45ifclist $wi $target 0 - } + } # execution server global exec_servers node_location set node_location [getNodeLocation $target] @@ -2556,7 +2556,7 @@ proc popupConfigDialog { c } { # end Boeing pack $wi.ftop -side top if { $type == "router" || $type == "OVS"} { - + ttk::frame $wi.model -borderwidth 4 ttk::label $wi.model.label -text "Type:" set runstate "disabled" @@ -2618,7 +2618,7 @@ proc popupConfigDialog { c } { global conntype set conntype [netconfFetchSection $target "tunnel-type"] if { $conntype == "" } { set conntype "UDP" } - + # TODO: clean this up ttk::frame $wi.linfo @@ -2804,7 +2804,7 @@ proc popupConfigDialog { c } { ttk::frame $wi.unilabel -borderwidth 4 ttk::label $wi.unilabel.updown -text "Symmetric link effects:" pack $wi.unilabel.updown -side left -anchor w - pack $wi.unilabel -side top -anchor w + pack $wi.unilabel -side top -anchor w ttk::frame $wi.bandwidth -borderwidth 4 ttk::label $wi.bandwidth.label -anchor e -text "Bandwidth (bps):" @@ -2932,11 +2932,11 @@ proc popupConfigDialog { c } { "popupConfigApply $wi $object_type $target 0" focus $wi.butt.apply # Boeing: remove range circles upon cancel - if {$type == "wlan"} { + if {$type == "wlan"} { set cancelcmd "set badentry -1 ; destroy $wi;" - set cancelcmd "$cancelcmd updateRangeCircles $target 0" + set cancelcmd "$cancelcmd updateRangeCircles $target 0" } else { - set cancelcmd "set badentry -1 ; destroy $wi" + set cancelcmd "set badentry -1 ; destroy $wi" } ttk::button $wi.butt.cancel -text "Cancel" -command $cancelcmd #end Boeing @@ -3072,18 +3072,18 @@ proc macEntryHelper { wi ifc } { # SYNOPSIS # popupConfigApply $w $object_type $target $phase # FUNCTION -# This procedure is called when the button apply is pressed in +# This procedure is called when the button apply is pressed in # popup configuration dialog box. It reads different # configuration parameters depending on the object_type. # INPUTS # * w -- widget -# * object_type -- describes the object type that is currently +# * object_type -- describes the object type that is currently # configured. It can be either link or node. # * target -- node id of the configured node or link id of the # configured link -# * phase -- This procedure is invoked in two diffenet phases -# to enable validation of the entry that was the last made. -# When calling this function always use the phase parameter +# * phase -- This procedure is invoked in two diffenet phases +# to enable validation of the entry that was the last made. +# When calling this function always use the phase parameter # set to 0. #**** proc popupConfigApply { wi object_type target phase } { @@ -3131,12 +3131,12 @@ proc popupConfigApply { wi object_type target phase } { # Boeing - added wlan, remote, tunnel, ktunnel items if { $type == "wlan" } { - wlanConfigDialogHelper $wi $target 1 + wlanConfigDialogHelper $wi $target 1 } elseif { $type == "tunnel" } { # # apply tunnel items # - set ipaddr "$name/24" ;# tunnel name == IP address of peer + set ipaddr "$name/24" ;# tunnel name == IP address of peer set oldipaddr [getIfcIPv4addr $target e0] if { $ipaddr != $oldipaddr } { setIfcIPv4addr $target e0 $ipaddr @@ -3176,7 +3176,7 @@ proc popupConfigApply { wi object_type target phase } { if { $oldlocal != $local } { netconfInsertSection $target [list "local-hook" $local] } -# Boeing changing to interface name for RJ45 +# Boeing changing to interface name for RJ45 # } elseif { $type == "rj45" } { # # # # apply rj45 items @@ -3240,7 +3240,7 @@ proc popupConfigApply { wi object_type target phase } { link { global g_link_config_uni_state set mirror [getLinkMirror $target] - + if { [setIfChanged $target $mirror $wi "bandwidth" "LinkBandwidth"] } { set changed 1 } @@ -3314,7 +3314,7 @@ proc setIfChanged { target mirror wi ctl procname } { # printCanvas $w # FUNCTION # This procedure is called when the print button in -# print dialog box is pressed. +# print dialog box is pressed. # INPUTS # * w -- print dialog widget #**** @@ -3335,12 +3335,12 @@ proc printCanvas { w } { # SYNOPSIS # deleteSelection # FUNCTION -# By calling this procedure all the selected nodes in imunes will +# By calling this procedure all the selected nodes in imunes will # be deleted. #**** proc deleteSelection { } { global changed - global background + global background global viewid catch {unset viewid} .c config -cursor watch; update @@ -3412,7 +3412,7 @@ proc align2grid {} { # FUNCTION # This procedure rearranges the position of nodes in imunes. # It can be used to rearrange all the nodes or only the selected -# nodes. +# nodes. # INPUTS # * mode -- when set to "selected" only the selected nodes will be # rearranged. @@ -3594,16 +3594,16 @@ proc rearrange_off { } { } -#****f* editor.tcl/switchCanvas +#****f* editor.tcl/switchCanvas # NAME # switchCanvas -- switch canvas # SYNOPSIS # switchCanvas $direction # FUNCTION -# This procedure switches the canvas in one of the defined +# This procedure switches the canvas in one of the defined # directions (previous, next, first and last). # INPUTS -# * direction -- the direction of switching canvas. Can be: prev -- +# * direction -- the direction of switching canvas. Can be: prev -- # previus, next -- next, first -- first, last -- last. #**** proc switchCanvas { direction } { @@ -3706,7 +3706,7 @@ proc resizeCanvasPopup {} { labelframe $w.size -text "Size" frame $w.size.pixels - pack $w.size $w.size.pixels -side top -padx 4 -pady 4 -fill x + pack $w.size $w.size.pixels -side top -padx 4 -pady 4 -fill x spinbox $w.size.pixels.x -bg white -width 5 $w.size.pixels.x insert 0 $x $w.size.pixels.x configure -from 300 -to 5000 -increment 2 @@ -3717,10 +3717,10 @@ proc resizeCanvasPopup {} { label $w.size.pixels.label2 -text "H pixels" pack $w.size.pixels.x $w.size.pixels.label $w.size.pixels.y \ $w.size.pixels.label2 -side left -pady 2 -padx 2 -fill x - + frame $w.size.meters - pack $w.size.meters -side top -padx 4 -pady 4 -fill x - spinbox $w.size.meters.x -bg white -width 7 + pack $w.size.meters -side top -padx 4 -pady 4 -fill x + spinbox $w.size.meters.x -bg white -width 7 $w.size.meters.x configure -from 300 -to 10000 -increment 100 label $w.size.meters.label -text "x" spinbox $w.size.meters.y -bg white -width 7 @@ -3789,7 +3789,7 @@ proc resizeCanvasPopup {} { checkbutton $w.default.save -text "Save as default" \ -variable resize_canvas_save_default pack $w.default.save -side left -pady 2 -padx 2 -fill x - pack $w.default -side bottom -fill x + pack $w.default -side bottom -fill x # update the size in meters based on pixels syncSizeScale $w xp @@ -3884,7 +3884,7 @@ proc resizeCanvasApply { w } { # SYNOPSIS # animate # FUNCTION -# This function animates the selectbox. The animation looks +# This function animates the selectbox. The animation looks # different for edit and exec mode. #**** proc animate {} { @@ -3929,7 +3929,7 @@ proc zoom { dir } { set newzoom $z } } - set zoom $newzoom + set zoom $newzoom } redrawAll } @@ -3945,7 +3945,7 @@ proc zoom { dir } { break } } - set zoom $newzoom + set zoom $newzoom } redrawAll } @@ -3965,7 +3965,7 @@ proc zoom { dir } { # SYNOPSIS # double1onGrid $c %x %y # FUNCTION -# As grid is layered above annotations this procedure is used to find +# As grid is layered above annotations this procedure is used to find # annotation object closest to cursor #**** @@ -3977,7 +3977,7 @@ proc double1onGrid { c x y } { return } # Is this really necessary? - set coords [getNodeCoords $node] + set coords [getNodeCoords $node] set x1 [lindex $coords 0] set y1 [lindex $coords 1] set x2 [lindex $coords 2] @@ -4065,7 +4065,7 @@ proc configRemoteServers {} { frame $wi.s -borderwidth 4 listbox $wi.s.servers -selectmode single -width 60 \ -yscrollcommand "$wi.s.servers_scroll set" -exportselection 0 - scrollbar $wi.s.servers_scroll -command "$wi.s.servers yview" + scrollbar $wi.s.servers_scroll -command "$wi.s.servers yview" pack $wi.s.servers $wi.s.servers_scroll -fill both -side left pack $wi.s -fill both -side top # add scrollbar @@ -4095,9 +4095,9 @@ proc configRemoteServers {} { button $wi.c.c.add -image $plugin_img_add \ -command "configRemoteServersHelper $wi 1" button $wi.c.c.mod -image $plugin_img_save \ - -command "configRemoteServersHelper $wi 2" + -command "configRemoteServersHelper $wi 2" button $wi.c.c.del -image $plugin_img_del \ - -command "configRemoteServersHelper $wi 3" + -command "configRemoteServersHelper $wi 3" pack $wi.c.c.add $wi.c.c.mod $wi.c.c.del -side left pack $wi.c -fill x -side top # assignment buttons @@ -4134,7 +4134,7 @@ proc configRemoteServers {} { # apply/cancel buttons frame $wi.b -borderwidth 4 button $wi.b.apply -text "Apply" -command \ - "writeServersConf; redrawAll; destroy $wi" + "writeServersConf; redrawAll; destroy $wi" button $wi.b.cancel -text "Cancel" -command "loadServersConf; destroy $wi" pack $wi.b.cancel $wi.b.apply -side right pack $wi.b -side bottom @@ -4169,7 +4169,7 @@ proc configRemoteServersHelper { wi action } { set newserver [$wi.c.c.name get] $wi.s.servers insert $index $newserver # update the array - set conf [list [$wi.c.c.ip get] [$wi.c.c.port get]] + set conf [list [$wi.c.c.ip get] [$wi.c.c.port get]] array set exec_servers [list $newserver $conf] $wi.s.servers selection set $index set last_server_selected $index @@ -4183,7 +4183,7 @@ proc selectRemoteServer { wi } { # clear entries $wi.c.c.name delete 0 end; $wi.c.c.ip delete 0 end; - $wi.c.c.port delete 0 end + $wi.c.c.port delete 0 end set server [$wi.s.servers get $selected] if { ![info exists exec_servers($server)] } { return } @@ -4215,7 +4215,7 @@ proc popupCustomImage { node } { set wi .customimagedialog catch {destroy $wi} toplevel $wi -takefocus 1 - wm transient $wi .popup + wm transient $wi .popup wm resizable $wi 0 0 wm title $wi "[getNodeName $node] ($node) image" grab $wi @@ -4228,11 +4228,11 @@ proc popupCustomImage { node } { global configwin set configwin $wi - button $wi.ftop.filebtn -text "..." -command { + button $wi.ftop.filebtn -text "..." -command { global configwin g_imageFileTypes set f [tk_getOpenFile -filetypes $g_imageFileTypes \ -initialdir "$CORE_DATA_DIR/icons/normal"] - if { $f != "" } { + if { $f != "" } { set node [string trim [lindex [wm title $configwin] 1] "()"] $configwin.ftop.filename delete 0 end $configwin.ftop.filename insert 0 $f @@ -4271,7 +4271,7 @@ proc popupCustomImagePreview { wi node } { setNodeCoords $node "150 50" setNodeLabelCoords $node "150 78" - if { $img_save != $img_new } { setCustomImage $node $img_new } + if { $img_save != $img_new } { setCustomImage $node $img_new } $wi.fmid.c delete all drawNode $wi.fmid.c $node @@ -4363,9 +4363,9 @@ proc markerOptions { show } { # Boeing: draw the marker sizes tool on a small canvas proc drawMarkerSizes { c sel } { # determine the coordinates of the selection box based on value of sel - if { $sel == 1 } { set coords {0 0 16 16} - } elseif { $sel == 2 } { set coords {16 0 32 16} - } elseif { $sel == 3 } { set coords {0 16 16 32} + if { $sel == 1 } { set coords {0 0 16 16} + } elseif { $sel == 2 } { set coords {16 0 32 16} + } elseif { $sel == 3 } { set coords {0 16 16 32} } else { set coords {16 16 32 32} } # draw the selection box $c create rectangle $coords -fill gray -tag square -width 0 @@ -4393,18 +4393,18 @@ proc markerSize { x y } { drawMarkerSizes .left.markeropt.sizes $sel } -# Boeing: set canvas wallpaper +# Boeing: set canvas wallpaper proc wallpaperPopup {} { global curcanvas set w .wallpaperDlg catch {destroy $w} toplevel $w - + wm transient $w . wm title $w "Set Canvas Wallpaper" grab $w - + # preview canvas $w.preview -background white -relief sunken -width 200 -height 100 \ -borderwidth 1 @@ -4421,7 +4421,7 @@ proc wallpaperPopup {} { # file browse button global configwin set configwin $w - button $w.f.filebtn -text "..." -command { + button $w.f.filebtn -text "..." -command { global configwin showGrid adjustCanvas fileDialogBox_initial global g_imageFileTypes # use default conf file path upon first run @@ -4443,7 +4443,7 @@ proc wallpaperPopup {} { } # clear wallpaper button - button $w.f.clear -text "clear" -command { + button $w.f.clear -text "clear" -command { global configwin wallpaperStyle $configwin.f.file delete 0 end $configwin.preview delete "wallpaper" @@ -4493,11 +4493,11 @@ proc wallpaperPopup {} { # buttons frame $w.btns - button $w.btns.apply -text "Apply" -command { + button $w.btns.apply -text "Apply" -command { global configwin wallpaperStyle curcanvas adjustCanvas set f [$configwin.f.file get] - if {$adjustCanvas} { - wallpaperAdjustCanvas $curcanvas $f $wallpaperStyle + if {$adjustCanvas} { + wallpaperAdjustCanvas $curcanvas $f $wallpaperStyle } setCanvasWallpaper $curcanvas $f $wallpaperStyle redrawAll @@ -4536,7 +4536,7 @@ proc wallpaperAdjustCanvas { c f style } { #puts -nonewline "wallpaperAdjustCanvas img($imgx, $imgy) $cx, $cy -> " - # For scaled and tiled styles, expand canvas x and y to a multiple of + # For scaled and tiled styles, expand canvas x and y to a multiple of # imgx, imgy for better stretching. If the image is larger than the canvas, # just increase the canvas size to accomodate it. if {$style == "scaled" || $style == "tiled"} { @@ -4605,13 +4605,13 @@ proc drawWallpaper { c f style } { # grow image if { $cx >= $imgx || $cy > $imgy } { set x [expr 1+($cx / $imgx)] - set y [expr 1+($cy / $imgy)] + set y [expr 1+($cy / $imgy)] $img2 copy $img -zoom $x $y # shrink image } else { $img2 copy $img -subsample \ [expr { int($imgx / $cx) }] \ - [expr { int($imgy / $cy) }] + [expr { int($imgy / $cy) }] } $c create image [expr 1+$cx/2] [expr 1+$cy/2] -image $img2 \ -tags "background wallpaper" @@ -4635,7 +4635,7 @@ proc drawWallpaper { c f style } { } raiseAll $c - + } # helper for close/cancel buttons @@ -4665,11 +4665,11 @@ proc rj45ifclist { wi node wasclicked } { listbox $wi.ftop.ifc.ifc_list -height 4 -width 30 \ -selectmode browse -yscrollcommand "$wi.ftop.ifc.ifc_scroll set" scrollbar $wi.ftop.ifc.ifc_scroll \ - -command "$wi.ftop.ifc.ifc_list yview" + -command "$wi.ftop.ifc.ifc_list yview" set ifname "" set ifip "" - # this handles differences between Linux and FreeBSD ifconfig + # this handles differences between ifconfig foreach line [split [nexec localnode ifconfig -a] "\n"] { set char [string index $line 0] if { $char != " " && $char != " " } { @@ -4924,7 +4924,7 @@ proc popupHookScript { name } { "genericOpenSaveButtonPress $c $wi.mid.script $wi.n.name" } ttk::combobox $wi.n.state -width 15 -state readonly -exportselection 0 \ - -values $CORE_STATES + -values $CORE_STATES pack $wi.n.lab $wi.n.name -padx 4 -pady 4 -side left pack $wi.n.open $wi.n.save -pady 4 -side left pack $wi.n.state -padx 4 -pady 4 -side left @@ -5081,7 +5081,7 @@ proc popupFileView { pathname } { ttk::label $wi.top.fnl -text "File:" ttk::entry $wi.top.fn #ttk::entry $wi.top.fn -state readonly - pack $wi.top.fnl -padx 4 -side left + pack $wi.top.fnl -padx 4 -side left pack $wi.top.fn -padx 4 -side left -fill both -expand true pack $wi.top -padx 4 -pady 4 -side top -fill both -expand true $wi.top.fn insert 0 $pathname diff --git a/gui/exec.tcl b/gui/exec.tcl index 1e5eec76..2105ac35 100644 --- a/gui/exec.tcl +++ b/gui/exec.tcl @@ -38,10 +38,10 @@ # SYNOPSIS # set result [nexec $args] # FUNCTION -# Executes the sting given in args variable. The sting is not executed +# Executes the sting given in args variable. The sting is not executed # if IMUNES is running in editor only mode. Execution of a string can # be local or remote. If socket can not be opened in try of a remote -# execution, mode is switched to editor only mode. +# execution, mode is switched to editor only mode. # INPUTS # * args -- the string that should be executed localy or remotely. # RESULT @@ -80,7 +80,7 @@ proc acquireOperModeLock { mode } { if { $mode == "exec" } { set choice [tk_messageBox -type yesno -default no -icon warning \ -message "You have selected to start the session while the previous one is still shutting down. Are you sure you want to interrupt the shutdown? (not recommended)"] - if { $choice == "no" } { + if { $choice == "no" } { set activetool select return; # return and allow previous setOperMode to finish... } @@ -88,7 +88,7 @@ proc acquireOperModeLock { mode } { } elseif { $setOperMode_lock } { ;# mode == "edit" set choice [tk_messageBox -type yesno -default no -icon warning \ -message "You are trying to stop the session while it is still starting. Are you sure you want to interrupt the startup? (not recommeded)"] - if { $choice == "no" } { + if { $choice == "no" } { set activetool select return; # return and allow previous setOperMode to finish... } @@ -155,7 +155,7 @@ proc drawToolbar { mode } { # add buttons when in edit mode set imgf "$CORE_DATA_DIR/icons/tiny/$b.gif" set image [image create photo -file $imgf] - catch { + catch { radiobutton .left.$b -indicatoron 0 \ -variable activetool -value $b -selectcolor $defSelectionColor \ -width 32 -height 32 -image $image \ @@ -163,7 +163,7 @@ proc drawToolbar { mode } { leftToolTip $b .left pack .left.$b -side top } - } + } } # popup toolbar buttons have submenus set buttons {routers hubs bgobjs} @@ -192,7 +192,7 @@ proc drawToolbar { mode } { -borderwidth 1 -tearoff 0] # create the child menutbuttons drawToolbarSubmenu $b $menubuttons - # tooltips for parent and submenu items + # tooltips for parent and submenu items leftToolTip $b .left bind $buttonmenu <> {leftToolTipSubMenu %W} bind $buttonmenu { @@ -206,7 +206,7 @@ proc drawToolbar { mode } { } } - # + # # Exec mode button bar # if { "$mode" == "edit" } { @@ -267,7 +267,7 @@ proc drawToolbarSubmenu { b menubuttons } { $buttonmenu add command -image $img -columnbreak 1 \ -command "popupMenuChoose $b $menubutton $imgf" } - # add an edit button to the end of the row + # add an edit button to the end of the row if { $b == "routers" } { set imgf "$CORE_DATA_DIR/icons/normal/document-properties.gif" set img [createImageButton $imgf 0] @@ -279,7 +279,7 @@ proc drawToolbarSubmenu { b menubuttons } { proc setSessionStartStopMenu { mode } { if { $mode == "exec" } { catch {.menubar.session entryconfigure "Start" \ - -label "Stop" -command "startStopButton edit"} + -label "Stop" -command "startStopButton edit"} } else { catch {.menubar.session entryconfigure "Stop" \ -label "Start" -command "startStopButton exec"} @@ -339,8 +339,8 @@ proc startStopButton { mode } { # Sets imunes operating mode to the value of the parameter mode. # The mode can be set only to edit or exec. # When changing the mode to exec all the emulation interfaces are -# checked (if they are nonexistent the message is displayed, and -# mode is not changed), all the required buttons are disabled +# checked (if they are nonexistent the message is displayed, and +# mode is not changed), all the required buttons are disabled # (except the simulation/Terminate button, that is enabled) and # procedure deployCfg is called. # When changing the mode to edit, all required buttons are enabled @@ -387,7 +387,7 @@ proc setOperMode { mode { type "" } } { # # Start/stop the emulation - # + # ### start button is pressed if { "$mode" == "exec" } { rearrange_off @@ -395,11 +395,11 @@ proc setOperMode { mode { type "" } } { resetAllNodeCoords save clearExceptions "" "" throwCEL true - - # Bind left mouse click to displaying the CPU usage in + + # Bind left mouse click to displaying the CPU usage in # a graph format bind .bottom.cpu_load <1> {manageCPUwindow %X %Y 1} - + monitor_loop set plugin [lindex [getEmulPlugin "*"] 0] set emul_sock [pluginConnect $plugin connect false] @@ -422,7 +422,7 @@ proc setOperMode { mode { type "" } } { clearWlanLinks "" widgets_stop set oper_mode edit - + # Bind left mouse click to clearing the CPU graph bind .bottom.cpu_load <1> {manageCPUwindow %X %Y 0} manageCPUwindow %X %Y 0 @@ -438,7 +438,7 @@ proc setOperMode { mode { type "" } } { # SYNOPSIS # statline $line # FUNCTION -# Sets the string of the status line. If the execution mode is +# Sets the string of the status line. If the execution mode is # set to batch the line is just printed on the standard output. # INPUTS # * line -- line to be displayed @@ -475,15 +475,15 @@ proc getNextMac {} { # monitor_loop # FUNCTION # Calculates the usage of cpu, mbuffers and mbuf clusters. -# The results are displayed in status line and updated +# The results are displayed in status line and updated # every two seconds. #**** proc monitor_loop {} { global oper_mode systype global server_cpuusage - global exec_servers + global exec_servers + - if {$oper_mode != "exec"} { .bottom.cpu_load config -text "" .bottom.mbuf config -text "" @@ -492,7 +492,7 @@ proc monitor_loop {} { if { [lindex $systype 0] == "Linux" } { set cpuusage [getCPUUsage] - + #TODO: get the cpu usage on all the assigned server # store usage history for each server stored in an array list set assigned_servers [getAssignedRemoteServers] @@ -509,22 +509,22 @@ proc monitor_loop {} { # TODO: receive CPU usage from other servers set cpuusageforserver 0 } - + # append the latest cpu value to the end of list and # only keep and display the last 20 values for each server - set server_cpuusage($ip) [lappend server_cpuusage($ip) $cpuusageforserver] + set server_cpuusage($ip) [lappend server_cpuusage($ip) $cpuusageforserver] if { [llength $server_cpuusage($ip)] > 20 } { set server_cpuusage($ip) [lreplace $server_cpuusage($ip) 0 0] - } + } } - - + + #plot the usage data if cpu windows already opened # for all servers if { [winfo exists .cpu]} { plotCPUusage } - + set cputxt "CPU [lindex $cpuusage 0]% (" set cpuusage [lreplace $cpuusage 0 0] for { set n 0 } { $n < [llength $cpuusage] } { incr n } { @@ -544,13 +544,8 @@ proc monitor_loop {} { return } - if { $systype == "FreeBSD 4.11-RELEASE" } { - set defaultname "default" - set cpun 3 - } else { - set defaultname "." + set defaultname "." set cpun 4 - } # CPU usage from `vimage -l` set vimagetext [nexec localnode vimage -l $defaultname | xargs] @@ -578,7 +573,7 @@ proc monitor_loop {} { # SYNOPSIS # execSetLinkParams $eid $link # FUNCTION -# Sets the link parameters during execution. +# Sets the link parameters during execution. # All the parameters are set at the same time. # INPUTS # eid -- experiment id @@ -649,7 +644,7 @@ proc createImageButton { imgf style } { } } return $img - + } # Boeing: status bar graph @@ -689,7 +684,7 @@ proc statgraph { cmd n } { } } } - + proc popupConnectMessage { dst } { global CORE_DATA_DIR execMode @@ -751,21 +746,21 @@ proc manageCPUwindow {xpos ypos start} { global exec_servers global server_cpuusage - + if {$start == 1} { - if { ![winfo exists .cpu]} { + if { ![winfo exists .cpu]} { toplevel .cpu wm geometry .cpu 200x210+$xpos+$ypos wm resizable .cpu 0 0 - wm title .cpu "CPU Usage" - canvas .cpu.graph -width 200 -height 210 + wm title .cpu "CPU Usage" + canvas .cpu.graph -width 200 -height 210 pack .cpu.graph - } + } } else { if { [winfo exists .cpu]} { destroy .cpu set assigned_servers [getAssignedRemoteServers] - + for {set i 0} {$i <= [llength $assigned_servers]} {incr i} { if {$i == [llength $assigned_servers]} { set ip [getMyIP] @@ -774,7 +769,7 @@ proc manageCPUwindow {xpos ypos start} { set srv [array get exec_servers $server] if { $srv == "" } { continue } set ip [lindex $srv 0] - } + } set server_cpuusage($ip) [lreplace $server_cpuusage($ip) 0 end] } } @@ -789,7 +784,7 @@ proc getMyIP { } { set myIP [lindex [fconfigure $theServer -sockname] 0] close $theServer return $myIP - + } # display all values stored in cpu usage history for each server @@ -797,24 +792,24 @@ proc plotCPUusage { } { global cpu_palettes global exec_servers global server_cpuusage - - .cpu.graph delete "all" + + .cpu.graph delete "all" .cpu.graph create line 0 100 200 100 -width 2 .cpu.graph create line 0 80 200 80 -width 1 .cpu.graph create line 0 60 200 60 -width 1 .cpu.graph create line 0 40 200 40 -width 1 .cpu.graph create line 0 20 200 20 -width 1 .cpu.graph create line 0 0 200 0 -width 1 - + .cpu.graph create line 40 0 40 100 -width 1 .cpu.graph create line 80 0 80 100 -width 1 .cpu.graph create line 120 0 120 100 -width 1 .cpu.graph create line 160 0 160 100 -width 1 .cpu.graph create line 200 0 200 100 -width 1 - # for each server create a plot of cpu usage - set assigned_servers [getAssignedRemoteServers] - for {set i 0} {$i <= [llength $assigned_servers]} {incr i} { + # for each server create a plot of cpu usage + set assigned_servers [getAssignedRemoteServers] + for {set i 0} {$i <= [llength $assigned_servers]} {incr i} { if {$i == [llength $assigned_servers]} { set ip [getMyIP] } else { @@ -823,9 +818,9 @@ proc plotCPUusage { } { if { $srv == "" } { continue } set ip [lindex $srv 0] } - + #need to add multiple cpuusgaehistory (array) - for { set n 1 } { $n < [llength $server_cpuusage($ip)] } { incr n } { + for { set n 1 } { $n < [llength $server_cpuusage($ip)] } { incr n } { set prevn [expr {$n - 1}] set x1 [expr {$prevn * 10}] set y1 [expr {100 - [lindex $server_cpuusage($ip) $prevn]}] @@ -837,15 +832,15 @@ proc plotCPUusage { } { .cpu.graph create line $x1 $y1 $x2 $y2 -fill [lindex $cpu_palettes end] } - #debug - #puts " cpu $x1 $y1 $x2 $y2" + #debug + #puts " cpu $x1 $y1 $x2 $y2" } - + #for each server create a legend (limited to 8) set legendtext $ip append legendtext " " [lindex $server_cpuusage($ip) end] "%" - - set legendy [expr {($i * 10) + 120}] + + set legendy [expr {($i * 10) + 120}] set legendx 10 if {$i < [llength $cpu_palettes]} { .cpu.graph create rectangle $legendx $legendy \ @@ -861,9 +856,9 @@ proc plotCPUusage { } { .cpu.graph create text [expr {$legendx + 15}] [expr {$legendy + 4}]\ -text $legendtext -fill [lindex $cpu_palettes end] \ -anchor w -justify left - + } - + } } diff --git a/gui/filemgmt.tcl b/gui/filemgmt.tcl index d6ba580e..e76874a7 100644 --- a/gui/filemgmt.tcl +++ b/gui/filemgmt.tcl @@ -36,41 +36,41 @@ # NAME # filemgmt.tcl -- file used for manipulation with files # FUNCTION -# This module is used for all file manipulations. In this file +# This module is used for all file manipulations. In this file # a file is read, a new file opened or existing file saved. # NOTES # variables: -# +# # currentFile # relative or absolute path to the current configuration file -# +# # fileTypes -# types that will be displayed when opening new file +# types that will be displayed when opening new file # # procedures used for loading and storing the configuration file: # -# newFile +# newFile # - creates an empty project # # openFile {filename} # - loads configuration from filename # -# saveFile {selectedFile} -# - saves current configuration to a file named selectedFile +# saveFile {selectedFile} +# - saves current configuration to a file named selectedFile # unless the file name is an empty string # # fileOpenStartUp # - opens the file named as command line argument -# +# # fileNewDialogBox -# - opens message box to optionally save the changes +# - opens message box to optionally save the changes # # fileOpenDialogBox # - opens dialog box for selecting a file to open # # fileSaveDialogBox # - opens dialog box for saving a file under new name if there is no -# current file +# current file #**** set currentFile "" @@ -103,11 +103,6 @@ proc newFile {} { set g_view_locked 0 # flush daemon configuration - if { [llength [findWlanNodes ""]] > 0 } { - if { [lindex $systype 0] == "FreeBSD" } { - catch { exec ngctl config wlan_ctl: flush=all } - } - } loadCfg "" resetGlobalVars newfile set curcanvas [lindex $canvas_list 0] @@ -143,7 +138,7 @@ proc newFile {} { # Loads the configuration from the file named $filename. #**** proc openFile { filename } { - global currentFile + global currentFile global undolog activetool global canvas_list curcanvas systype global changed @@ -190,11 +185,6 @@ proc openFile { filename } { } # flush daemon configuration - if { [llength [findWlanNodes ""]] > 0 } { - if { [lindex $systype 0] == "FreeBSD" } { - catch { exec ngctl config wlan_ctl: flush=all } - } - } set cfg "" if { [catch { set fileId [open $currentFile r] } err] } { puts "error opening file $currentFile: $err" @@ -209,7 +199,7 @@ proc openFile { filename } { loadCfg $cfg switchCanvas none - set undolog(0) $cfg + set undolog(0) $cfg set activetool select # remember opened files @@ -236,11 +226,11 @@ proc resetGlobalVars { reason } { # FUNCTION # Loads the current configuration into the selectedFile file. # INPUTS -# * selectedFile -- the name of the file where current +# * selectedFile -- the name of the file where current # configuration is saved. #**** proc saveFile { selectedFile } { - global currentFile + global currentFile global changed if { $selectedFile == ""} { @@ -275,7 +265,7 @@ proc saveFile { selectedFile } { # SYNOPSIS # fileOpenStartUp # FUNCTION -# Loads configuration from batch input file to the current +# Loads configuration from batch input file to the current # configuration. #**** proc fileOpenStartUp {} { @@ -310,7 +300,7 @@ proc fileNewDialogBox {} { if {$changed != 0 } { set choice [promptForSave] } - + if { $choice != "cancel"} { newFile } @@ -370,7 +360,7 @@ proc fileSaveDialogBox { prompt } { set ft [lreplace $ft 0 0] set ft [linsert $ft 1 $imn] } - + set dir "" # use default conf file path upon first run if { $fileDialogBox_initial == 0} { @@ -450,7 +440,7 @@ proc loadDotFile {} { set isfile 0 if {[catch {set dotfile [open "$CONFDIR/prefs.conf" r]} ]} return close $dotfile - + if {[catch { source "$CONFDIR/prefs.conf" }]} { puts "The $CONFDIR/prefs.conf preferences file is invalid, ignoring it." #file delete "~/.core" @@ -468,7 +458,7 @@ proc savePrefsFile { } { # header puts $dotfile "# CORE ${CORE_VERSION} GUI preference file" - + # save the most-recently-used file list puts $dotfile "set g_mrulist \"$g_mrulist\"" @@ -550,10 +540,6 @@ proc exit {} { if { [popupStopSessionPrompt]=="cancel" } { return } - # Flush daemon configuration - if { [lindex $systype 0] == "FreeBSD" } { - catch { exec ngctl config wlan_ctl: flush=all } - } # Prompt for save if file was changed if { $changed != 0 && [promptForSave] == "cancel" } { return @@ -579,7 +565,7 @@ proc exit {} { # save user preferences savePrefsFile - + exit.real } diff --git a/gui/linkcfg.tcl b/gui/linkcfg.tcl index 3febc25e..adaa75bc 100644 --- a/gui/linkcfg.tcl +++ b/gui/linkcfg.tcl @@ -35,11 +35,11 @@ # NAME # linkcfg.tcl -- file used for manipultaion with links in IMUNES # FUNCTION -# This module is used to define all the actions used for configuring -# links in IMUNES. +# This module is used to define all the actions used for configuring +# links in IMUNES. # # NOTES -# +# # linkPeers { link_id } # Returns node_ids of link endpoints # @@ -53,7 +53,7 @@ # ... in bits per second # # getLinkBandwidthString { link_id } -# ... as string +# ... as string # # getLinkDelay { link_id } # ... in microseconds @@ -83,7 +83,7 @@ # INPUTS # * link_id -- link id # RESULT -# * link_peers -- returns nodes_ids of a link endpoints +# * link_peers -- returns nodes_ids of a link endpoints # in a list {node1_id node2_id} #**** @@ -100,14 +100,14 @@ proc linkPeers { link } { # SYNOPSIS # set link_id [linkByPeers $node1_id $node2_id] # FUNCTION -# Returns link_id whose peers are node1 and node2. +# Returns link_id whose peers are node1 and node2. # The order of input nodes is irrelevant. # INPUTS # * node1_id -- node id of the first node # * node2_id -- node id of the second node # RESULT -# * link_id -- returns id of a link connecting endpoints -# node1_id node2_id. +# * link_id -- returns id of a link connecting endpoints +# node1_id node2_id. #**** proc linkByPeers { node1 node2 } { @@ -144,7 +144,7 @@ proc linkByPeersMirror { node1 node2 } { # removeLink $link_id # FUNCTION # Removes the link and related entries in peering node's configs. -# Updates the default route for peer nodes. +# Updates the default route for peer nodes. # INPUTS # * link_id -- link id #**** @@ -199,7 +199,7 @@ proc getLinkBandwidth { link {dir "down"} } { # INPUTS # * link_id -- link id # RESULT -# * bandwidth_str -- The value of link bandwidth formated in a sting +# * bandwidth_str -- The value of link bandwidth formated in a sting # containing a measure unit. #**** @@ -332,7 +332,7 @@ proc getLinkDelay { link {dir "down"} } { # INPUTS # * link_id -- link id # RESULT -# * delay -- The value of link delay formated in a string +# * delay -- The value of link delay formated in a string # containing a measure unit. #**** @@ -437,7 +437,7 @@ proc getLinkBERString { link } { if { $ber != "" } { set berstr "$berstr$ber%" } - if { $berup != "" } { + if { $berup != "" } { set berstr "$berstr / $berup%" } return $berstr @@ -472,7 +472,7 @@ proc setLinkBER { link value } { #****f* linkcfg.tcl/getLinkDup # NAME -# getLinkDup -- get link packet duplicate value +# getLinkDup -- get link packet duplicate value # SYNOPSIS # set duplicate [getLinkDup $link_id] # FUNCTION @@ -508,7 +508,7 @@ proc getLinkDupString { link } { #****f* linkcfg.tcl/setLinkDup # NAME -# setLinkDup -- set link packet duplicate value +# setLinkDup -- set link packet duplicate value # SYNOPSIS # setLinkDup $link_id $value # FUNCTION @@ -547,7 +547,7 @@ proc isLinkUni { link } { #****f* linkcfg.tcl/getLinkMirror # NAME -# getLinkMirror -- get link's mirror link +# getLinkMirror -- get link's mirror link # SYNOPSIS # set mirror_link_id [getLinkMirror $link_id] # FUNCTION @@ -569,7 +569,7 @@ proc getLinkMirror { link } { #****f* linkcfg.tcl/setLinkMirror # NAME -# setLinkMirror -- set link's mirror link +# setLinkMirror -- set link's mirror link # SYNOPSIS # setLinkMirror $link_id $mirror_link_id # FUNCTION @@ -599,7 +599,7 @@ proc setLinkMirror { link value } { # SYNOPSIS # set nodes [splitLink $link_id $nodetype] # FUNCTION -# Splits the link in two parts. Each part of the split link is one +# Splits the link in two parts. Each part of the split link is one # pseudo link. # INPUTS # * link_id -- link id @@ -674,7 +674,7 @@ proc splitLink { link nodetype } { # SYNOPSIS # set new_link_id [mergeLink $link_id] # FUNCTION -# Rebuilts a link from two pseudo link. +# Rebuilts a link from two pseudo link. # INPUTS # * link_id -- pseudo link id # RESULT @@ -754,11 +754,11 @@ proc newLink { lnode1 lnode2 } { global systype if { ([nodeType $lnode1] == "lanswitch" ||[nodeType $lnode1] == "OVS") && \ [nodeType $lnode2] != "router" && \ - ([nodeType $lnode2] != "lanswitch" || [nodeType $lnode2] != "OVS") } { + ([nodeType $lnode2] != "lanswitch" || [nodeType $lnode2] != "OVS") } { set regular no } if { ([nodeType $lnode2] == "lanswitch" || [nodeType $lnode2] == "OVS") && \ [nodeType $lnode1] != "router" && \ - ([nodeType $lnode1] != "lanswitch" || [nodeType $lnode1] != "OVS" )} { + ([nodeType $lnode1] != "lanswitch" || [nodeType $lnode1] != "OVS" )} { #Khaled: puts "connecting '$lnode1' (type: '[nodeType $lnode1]') to '$lnode2' (type: '[nodeType $lnode2]') " set regular no } if { [nodeType $lnode1] == "hub" && \ @@ -839,15 +839,11 @@ proc newLink { lnode1 lnode2 } { if { [string range $model 0 6] == "coreapi" } { set delay 0; # delay controlled by wireless module } elseif {$delay != ""} { - if { [lindex $systype 0] == "FreeBSD" } { - lappend $link "delay [expr $delay/2]" - } else { lappend $link "delay $delay" - } - } + } # Exclude OVS from network layer nodes IP address asignments if { ([[typemodel $lnode2].layer] == "NETWORK") && ([nodeType $lnode2] != "OVS") } { - + #Khaled: puts "Assigning '$lnode2' (type: '[nodeType $lnode2]') an automatic IP address" if { $ipv4_addr2 == "" } { autoIPv4addr $lnode2 $ifname2 } @@ -872,7 +868,7 @@ proc newLink { lnode1 lnode2 } { if { [nodeType $lnode2] != "pseudo" && [nodeType $lnode1] != "wlan" && ([[typemodel $lnode1].layer] == "NETWORK" && [nodeType $lnode1] != "OVS") } { - + if { $ipv4_addr1 == "" && $do_auto_addressing } { autoIPv4addr $lnode1 $ifname1 } @@ -884,16 +880,16 @@ proc newLink { lnode1 lnode2 } { if { [nodeType $lnode1] != "pseudo" && [nodeType $lnode1] != "wlan" && ([[typemodel $lnode2].layer] == "NETWORK" && [nodeType $lnode2] != "OVS") } { - + if { $ipv4_addr2 == "" && $do_auto_addressing } { - autoIPv4addr $lnode2 $ifname2 + autoIPv4addr $lnode2 $ifname2 } if { $ipv6_addr2 == "" && $do_auto_addressing } { autoIPv6addr $lnode2 $ifname2 } } - # tunnel address based on its name + # tunnel address based on its name if { [nodeType $lnode1] == "tunnel" } { set ipaddr "[getNodeName $lnode1]/24" setIfcIPv4addr $lnode1 e0 $ipaddr @@ -914,7 +910,7 @@ proc newLink { lnode1 lnode2 } { # FUNCTION # Returns the link id of the link connecting the node's interface # INPUTS -# * node_id -- node id +# * node_id -- node id # * ifc -- interface # RESULT # * link_id -- link id. @@ -1021,7 +1017,7 @@ proc updateLinkGuiAttr { link attr } { } color { setLinkColor $link $value - .c itemconfigure "link && $link" -fill [getLinkColor $link] + .c itemconfigure "link && $link" -fill [getLinkColor $link] } dash { .c itemconfigure "link && $link" -dash $value diff --git a/gui/mobility.tcl b/gui/mobility.tcl index 61e79508..67a0006c 100644 --- a/gui/mobility.tcl +++ b/gui/mobility.tcl @@ -6,7 +6,7 @@ # shows the Two-node Tool proc popupTwoNodeDialog { } { global twonodePID lastTwoNodeHop g_twoNodeSelect g_twoNodeSelectCallback - + markerOptions off set wi .twonodetool catch {destroy $wi} @@ -61,7 +61,7 @@ proc popupTwoNodeDialog { } { # buttons on the bottom frame $wi.butt -borderwidth 6 - button $wi.butt.run -text "Run" -command "runTwoNodeCommand $wi" + button $wi.butt.run -text "Run" -command "runTwoNodeCommand $wi" button $wi.butt.cancel -text "Clear" -command "clearTwoNodeDialog $wi 0" button $wi.butt.close -text "Close" -command "clearTwoNodeDialog $wi 1" pack $wi.butt.run $wi.butt.cancel $wi.butt.close -side left @@ -83,11 +83,7 @@ proc clearTwoNodeDialog { wi done} { set emul [getEmulPlugin $node] set emulation_type [lindex $emul 1] catch { - if { $os == "FreeBSD" } { - exec sudo kill -9 $twonodePID 2> /dev/null - } else { - exec kill -9 $twonodePID 2> /dev/null - } + exec kill -9 $twonodePID 2> /dev/null } set twonodePID 0 } @@ -318,11 +314,11 @@ proc drawTwoNodeLine { node line type } { # search for hops matching this nexthop address set hops [findNextHops $lastTwoNodeHop $nexthop ""] if {[llength $hops] == 0} { - puts "Couldn't highlight next hop: $nexthop"; + puts "Couldn't highlight next hop: $nexthop"; return } - # highlight the path + # highlight the path set a $lastTwoNodeHop foreach b $hops { highlightLink $a $b @@ -372,7 +368,7 @@ proc nodeHasAddr { node addr } { if { $nodeaddr == $addr } { return 1 } - } + } return 0 } @@ -429,7 +425,7 @@ proc clearLinkHighlights { } { # Boeing: shows the Two-node Tool proc popupRunDialog { } { global node_list activetool systype - + set activetool select markerOptions off set wi .runtool @@ -489,7 +485,7 @@ proc popupRunDialog { } { # buttons on the bottom frame $wi.butt -borderwidth 6 - button $wi.butt.run -text "Run" -command "runToolCommand $wi \"\"" + button $wi.butt.run -text "Run" -command "runToolCommand $wi \"\"" button $wi.butt.close -text "Close" -command "destroy $wi" pack $wi.butt.run $wi.butt.close -side left pack $wi.butt -side bottom @@ -504,7 +500,7 @@ proc runToolCommand { wi node } { if { ![winfo exists $wi] } { return }; # user has closed window # start running commands - if { $node == "" } { + if { $node == "" } { $wi.results.text delete 1.0 end set selected [$wi.n.nodes.nodes curselection] if { [llength $selected] == 0 } { @@ -518,8 +514,8 @@ proc runToolCommand { wi node } { set next "" set getnext 0 - foreach i [$wi.n.nodes.nodes curselection] { ;# find the next node - set n [lindex $node_list $i] + foreach i [$wi.n.nodes.nodes curselection] { ;# find the next node + set n [lindex $node_list $i] if {$n == $node } { set getnext 1 } elseif { $getnext == 1 } { @@ -553,7 +549,7 @@ proc runToolCommand { wi node } { # callback after receiving exec message response proc exec_runtool_callback { node execnum cmd result status } { set wi .runtool - + if { ![winfo exists $wi] } { return }; # user has closed window $wi.results.text insert end "> $node > $cmd:\n" diff --git a/gui/util.tcl b/gui/util.tcl index 204694b0..3052f73b 100644 --- a/gui/util.tcl +++ b/gui/util.tcl @@ -9,14 +9,13 @@ set g_imageFileTypes {{"images" {.gif}} {"images" {.jpg}} {"images" {.png}} {"images" {.xbm}} {"All files" {*} }} global execMode -if { $execMode == "interactive"} { +if { $execMode == "interactive"} { if { [catch { package require Img }] } { puts "warning: Tcl/Tk Img package not found" puts " Thumbnails and other image types (JPG, PNG, etc.) will not be supported." puts " Please install it with:" puts " yum install tkimg (RedHat/Fedora)" - puts " sudo apt-get install libtk-img (Debian/Ubuntu)" - puts " pkg_add -r libimg (FreeBSD)\n" + puts " sudo apt-get install libtk-img (Debian/Ubuntu)\n" set g_imageFileTypes {{"images" {.gif}} {"All files" {*} }} } } @@ -51,7 +50,7 @@ proc checkOS {} { set machine [exec uname -m] set kernel [exec uname -v] - set x11 0 + set x11 0 catch { set x11 [winfo server .c] } set os_ident "$os_name $os_ver" @@ -203,7 +202,7 @@ proc upgradeNetworkConfigToServices { } { puts "updating Quagga services on node $node" } ;# end quagga services # - # convert static model to router + # convert static model to router # if { [getNodeModel $node] == "static" } { setNodeModel $node "router" @@ -223,7 +222,7 @@ proc upgradeNetworkConfigToServices { } { setCustomConfig $node "service:UserDefined" "UserDefined" \ $statvals 0 setCustomConfig $node "service:UserDefined:$cfgname" $cfgname $cfg 0 - set services [getNodeServices $node true] + set services [getNodeServices $node true] lappend services "UserDefined" setNodeServices $node $services puts "adding user-defined static routing service on node $node" @@ -240,7 +239,7 @@ proc getCPUUsage { } { } array set cpu {} - + while { [ gets $f line ] >= 0 } { set cpun [lindex $line 0] set user [lindex $line 1]; set nice [lindex $line 2] @@ -264,14 +263,14 @@ proc getCPUUsage { } { set usage_time [expr {($u-$lu) + ($n-$ln) + ($s-$ls)}] set total_time [expr {$usage_time + ($i-$li)}] - if { $total_time <= 0 } { + if { $total_time <= 0 } { set cpuusage "" ;# avoid div by zero } else { set cpuusage [expr { 100 * $usage_time / $total_time }] } lappend cpuusages $cpuusage } - return $cpuusages + return $cpuusages } # Node selection dialog display given message 'msg' with initial node selection @@ -294,7 +293,7 @@ proc popupSelectNodes { msg initsel callback } { listbox $wi.nodes.fr.nodelist -width 40 \ -listvariable node_list -yscrollcommand "$wi.nodes.fr.scroll set" \ -activestyle dotbox -selectmode extended - scrollbar $wi.nodes.fr.scroll -command "$wi.nodes.fr.nodelist yview" + scrollbar $wi.nodes.fr.scroll -command "$wi.nodes.fr.nodelist yview" pack $wi.nodes.fr.nodelist -fill both -expand true -side left pack $wi.nodes.fr.scroll -fill y -expand true -side left pack $wi.nodes.label $wi.nodes.fr -side top -padx 4 -pady 4 \ @@ -352,7 +351,7 @@ proc popupRenumberNodes { } { listbox $wi.nodes.left.fr.from -selectmode single -width 20 \ -listvariable node_list -yscrollcommand "$wi.nodes.left.fr.scroll set" \ -activestyle dotbox - scrollbar $wi.nodes.left.fr.scroll -command "$wi.nodes.left.fr.from yview" + scrollbar $wi.nodes.left.fr.scroll -command "$wi.nodes.left.fr.from yview" pack $wi.nodes.left.fr.from $wi.nodes.left.fr.scroll -fill y -side left pack $wi.nodes.left.label $wi.nodes.left.fr -side top -padx 4 -pady 4 \ -anchor w @@ -487,24 +486,16 @@ proc addStaticRoutesToConfig { node cfg_ref } { upvar 1 $cfg_ref cfg foreach statrte [getStatIPv4routes $node] { - if {[lindex $systype 0] == "Linux" } { ;# Linux set net [lindex [split $statrte] 0] set gw [lindex [split $statrte] 1] lappend cfg "/sbin/ip -4 route add $net via $gw" - } else { ;# FreeBSD - lappend cfg "route -q add -inet $statrte" - } } foreach statrte [getStatIPv6routes $node] { - if { [lindex $systype 0] == "Linux" } { ;# Linux set net [lindex [split $statrte] 0] set gw [lindex [split $statrte] 1] if { $net == "::/0" } { set net "default" } lappend cfg "/sbin/ip -6 route add $net via $gw" - } else { ;# FreeBSD - lappend cfg "route -q add -inet6 $statrte" - } } } @@ -514,11 +505,7 @@ proc getServiceStartString { } { setSystype - if { [lindex $systype 0] == "Linux" } { ;# Linux return "/etc/init.d/core-daemon start" - } else { ;# FreeBSD - return "/usr/local/etc/rc.d/core onestart" - } } proc popupBuildHostsFile { } { @@ -540,7 +527,7 @@ proc popupBuildHostsFile { } { pack $wi.top.help -side top -fill both -expand true pack $wi.top -padx 4 -pady 4 -side top - # text box + # text box frame $wi.mid text $wi.mid.hosts -relief sunken -bd 2 \ -yscrollcommand "$wi.mid.scroll set" -setgrid 1 -height 30 -undo 1 \ @@ -585,7 +572,7 @@ proc popupBuildHostsFile { } { set wi .buildhostsdialog set hosts [string trim [$wi.mid.hosts get 0.0 end]] set filename [$wi.fil.filename get] - set fileId [open $filename a] + set fileId [open $filename a] puts $fileId $hosts close $fileId destroy $wi @@ -707,7 +694,7 @@ proc addressConfigHelper { wi fam cmd } { } } -# set the default addresses for automatic allocation in the g_prefs array +# set the default addresses for automatic allocation in the g_prefs array # for the given address family proc setDefaultAddrs { fam } { global g_prefs @@ -737,8 +724,8 @@ proc popupMacAddressConfig { } { frame $wi.top set helptext "MAC addresses are automatically assigned starting with\n" set helptext "$helptext 00:00:00:aa:00:nn, where nn starts with the below" - set helptext "$helptext value.\n You should change this value when tunneling" - set helptext "$helptext between \nemulations to prevent MAC address conflicts." + set helptext "$helptext value.\n You should change this value when tunneling" + set helptext "$helptext between \nemulations to prevent MAC address conflicts." label $wi.top.help -text $helptext pack $wi.top.help -side top -fill both -expand true @@ -863,7 +850,7 @@ proc _launchBrowser url { # helper for registering a callback with a tk_optionMenu variable, when a user # clicks on the menu and changes the value; if the global variable var is -# cleared, this callback is cancelled +# cleared, this callback is cancelled # NOTE: when closing the window that calls this, ensure that var is cleared proc tkOptionMenuCallback { ctl var cb args } { if { ![winfo exists $ctl] } { return } @@ -1094,7 +1081,7 @@ proc get_text_editor { want_default } { if { $want_default } { return "EDITOR" } else { - return $ed + return $ed } } # return the first installed editor from EDITORS global @@ -1203,7 +1190,7 @@ proc delAddrsFromNodes { fam nodes } { # fix for Tcl/Tk 8.5.8 and lower which doesn't have ttk::spinbox # set spinbox [getspinbox] # $spinbox $var -justify right -width 10 ... -# +# proc getspinbox {} { if { [info command ttk::spinbox] == "" } { return spinbox @@ -1308,7 +1295,7 @@ proc findButton { w } { if { $first == "" } { $tree insert {} end -id none -values [list "" "" "" "no results found"] } else { - $tree selection set $first + $tree selection set $first } . config -cursor left_ptr diff --git a/gui/widget.tcl b/gui/widget.tcl index 12c40499..ec1d48e7 100644 --- a/gui/widget.tcl +++ b/gui/widget.tcl @@ -22,19 +22,19 @@ if {$vtysh == ""} { # widget array: name, {config, init, periodic, move} # array set widgets { - "Throughput" - { widget_thru_config widget_thru_init widget_thru_periodic widget_thru_move } + "Throughput" + { widget_thru_config widget_thru_init widget_thru_periodic widget_thru_move } "Adjacency" { widget_adjacency_config widget_adjacency_init widget_adjacency_periodic widget_adjacency_move } } -# TODO: fix CPU Widget; it is disabled because Linux network namespaces and -# FreeBSD jails do not have a CPU usage reporting mechanism right now -# "CPU" +# TODO: fix CPU Widget; it is disabled because Linux network namespaces +# do not have a CPU usage reporting mechanism right now +# "CPU" # { widget_cpu_config widget_cpu_init widget_cpu_periodic widget_cpu_move } # Common Observer Widget definitions set widgets_obs_quagga [subst { - 5 + 5 {{OSPFv2 neighbors} {$vtysh -c {show ip ospf neighbor}}} 6 @@ -47,31 +47,6 @@ set widgets_obs_quagga [subst { {{PIM neighbors} {$vtysh -c {show ip pim neighbor}}} }] -# Observer Widget definitions for FreeBSD -array set widgets_obs_bsd $widgets_obs_quagga -array set widgets_obs_bsd { - 1 - { "processes" "ps ax" } - 2 - { "ifconfig" "ifconfig" } - 3 - { "IPv4 routes" "netstat -f inet -rn" } - 4 - { "IPv6 routes" "netstat -f inet6 -rn" } - 7 - { "IPv4 listening sockets" "sockstat -4l" } - 8 - { "IPv6 listening sockets" "sockstat -6l" } - 9 - { "IPv4 MFC entries" "ifmcstat -f inet" } - 10 - { "IPv6 MFC entries" "ifmcstat -f inet6" } - 11 - { "firewall rules" "ipfw -a list" } - 12 - { "IPsec policies" "setkey -DP" } -} - # Observer Widget definitions for Linux array set widgets_obs_linux $widgets_obs_quagga array set widgets_obs_linux { @@ -104,17 +79,13 @@ set widget_loop_ID -1 # proc init_default_widgets_obs {} { global systype widgets widgets_obs widget_obs last_widgetObserveNode - global widgets_obs_bsd widgets_obs_linux + global widgets_obs_linux setSystype array unset widgets_obs - if { [lindex $systype 0] == "Linux" } { set arrayname widgets_obs_linux # this works, but we will instead reset all indices: #array set widgets_obs [array get widgets_obs_linux] - } else { - set arrayname widgets_obs_bsd - } # this resets the array indices to be 1, 2, 3, etc. set i 1 @@ -142,7 +113,7 @@ proc init_widget_menu {} { foreach w [array names widgets] { global enable_$w set enable_$w 0 - # note that a more modular way to break out submenus would be nice here + # note that a more modular way to break out submenus would be nice here if { $w == "Adjacency" } { widget_adjacency_init_submenu .menubar.widgets continue @@ -374,9 +345,9 @@ proc configObsWidgets {} { button $wi.c.c3.add -text "new" \ -command "configObsWidgetsHelper $wi 1" button $wi.c.c3.mod -text "modify" \ - -command "configObsWidgetsHelper $wi 2" + -command "configObsWidgetsHelper $wi 2" button $wi.c.c3.del -text "delete" \ - -command "configObsWidgetsHelper $wi 3" + -command "configObsWidgetsHelper $wi 3" pack $wi.c.c3.del $wi.c.c3.mod $wi.c.c3.add -side right pack $wi.c.c3 -fill x -side top @@ -386,7 +357,7 @@ proc configObsWidgets {} { frame $wi.s -borderwidth 4 listbox $wi.s.servers -selectmode single -width 50 \ -yscrollcommand "$wi.s.servers_scroll set" -exportselection 0 - scrollbar $wi.s.servers_scroll -command "$wi.s.servers yview" + scrollbar $wi.s.servers_scroll -command "$wi.s.servers yview" pack $wi.s.servers $wi.s.servers_scroll -fill y -side left pack $wi.s -fill x -side top bind $wi.s.servers <> "selectObsWidgetConf $wi" @@ -531,7 +502,7 @@ proc selectObsWidgetConf { wi } { set selected [$wi.s.servers curselection] # clear entries - $wi.c.c.name delete 0 end + $wi.c.c.name delete 0 end $wi.c.c2.cmd delete 0 end set w [$wi.s.servers get $selected] @@ -602,23 +573,18 @@ proc widget_thru_config {} { checkbutton $wi.tlab.up \ -text "Include receptions" -variable thruConfig(up) pack $wi.tlab.show_thru $wi.tlab.avg $wi.tlab.down \ - $wi.tlab.up -side top -anchor w -padx 4 + $wi.tlab.up -side top -anchor w -padx 4 pack $wi.tlab -side top frame $wi.msg -borderwidth 4 global systype - if { [lindex $systype 0] == "FreeBSD" } { - set lab1txt "Note: links with no impairments (bw, delay,\netc) " - set lab1txt "${lab1txt}will display 0.0 throughput" - } else { set lab1txt "" - } label $wi.msg.lab1 -text $lab1txt pack $wi.msg.lab1 -side top -padx 4 -pady 4 pack $wi.msg -side top labelframe $wi.hi -padx 4 -pady 4 -text "Link highlighting" - + # Threshold (set to zero to disable) label $wi.hi.lab1 -text \ "Highlight link if throuhgput exceeds this " @@ -632,7 +598,7 @@ proc widget_thru_config {} { scale $wi.hi.threshscale -from 0.0 -to 1000.0 -orient horizontal \ -showvalue false -sliderrelief raised -variable thruConfig(thresh) pack $wi.hi.threshscale -side top -fill x - + frame $wi.hi.w label $wi.hi.w.lab3 -text "Highlight link width:" spinbox $wi.hi.w.width -bg white -width 8 -textvariable thruConfig(width) \ @@ -649,7 +615,7 @@ proc widget_thru_config {} { pack $wi.hi.co.colbtn $wi.hi.co.color $wi.hi.co.lab1 \ -side right -padx 4 -pady 4 pack $wi.hi.co -side top - + pack $wi.hi -side top # OK button at bottom @@ -748,7 +714,7 @@ proc ngctl_output_to_ifname { line } { # Throughput widget periodic procedure # proc widget_thru_periodic { now } { - global systype eid link_list + global systype eid link_list global link_thru_stats link_thru_avg_stats link_thru_last_time thruConfig global throughput_cache @@ -759,7 +725,7 @@ proc widget_thru_periodic { now } { set dt [expr { ($now - $link_thru_last_time)/1000.0 }] set link_thru_last_time $now if { $dt <= 0.0 } { return } - + # keep wireless stats in an array array set wireless_stats {} @@ -820,7 +786,7 @@ proc widget_thru_periodic { now } { set kbps [expr {$kbps + $kbps_down}] } #set kbps [expr {$kbps_down + $kbps_up}] - + if { $thruConfig(avg) } { if { ![info exists link_thru_avg_stats($key)] } { set link_thru_avg_stats($key) $kbps @@ -831,7 +797,7 @@ proc widget_thru_periodic { now } { set kbps $s } } - set kbps_str [format "%.3f" $kbps] + set kbps_str [format "%.3f" $kbps] # wireless link - keep total of wireless throughput for this node # (supports membership to multiple wlans) @@ -855,14 +821,14 @@ proc widget_thru_periodic { now } { } .c itemconfigure "link && $link" -width $width -fill $color } - thruPlotUpdate .c $link $kbps + thruPlotUpdate .c $link $kbps }; # end foreach link # after summing all wireless link bandwidths, go back and perform # highlighting and label updating foreach node [array names wireless_stats] { set kbps_str [format "%.3f" $wireless_stats($node)] - + # erase any existing circles (otherwise we get duplicates) .c delete -withtag "$node && rangecircles" # wireless circle if exceeding threshold @@ -897,13 +863,13 @@ proc widget_thru_periodic { now } { # helper to convert ng_pipe stats into upstream/downstream bytes proc getstats_bytes_netgraph { raw_input } { # Rec'd response "getstats" (1) from "e0_n0-n1:": - # Args: { downstream={ FwdOctets=416 FwdFrames=6 } + # Args: { downstream={ FwdOctets=416 FwdFrames=6 } # upstream={ FwdOctets=416 FwdFrames=6 } } set tmp [split $raw_input ":"] if { [llength $tmp] != 4 } { return [list 0 0] } - + set statline [lindex [lindex $tmp 3] 0] set down [lindex $statline 1] set up [lindex $statline 5] @@ -952,8 +918,8 @@ proc getstats_bytes_proc { raw_input ifname } { break } # match the ifname exactly - } elseif { [string range $statline 0 $ifname_len] == "$ifname:" } { - break + } elseif { [string range $statline 0 $ifname_len] == "$ifname:" } { + break } set statline "" } @@ -964,8 +930,8 @@ proc getstats_bytes_proc { raw_input ifname } { set stats [lindex $statline 1] set down_bytes [lindex $stats 0] - set up_bytes [lindex $stats 8] - + set up_bytes [lindex $stats 8] + if { $down_bytes == "" } { set down_bytes 0 } if { $up_bytes == "" } { set up_bytes 0 } @@ -979,43 +945,43 @@ proc widget_thru_move { c node done } { # Create a new throughput plot. proc thruPlot { c link x y height width isresize} { - global widgets enable_Throughput thruPlotColor curPlotBgColor + global widgets enable_Throughput thruPlotColor curPlotBgColor global plot_list - - # if thruplot is called from resize, $link will hold full name + + # if thruplot is called from resize, $link will hold full name if { $isresize == true } { set g $link # extract linkname from full path regexp {l(.*)thruplot} $g match sub1 set link "l$sub1" - } else { - # if new thruplot is created create full name + } else { + # if new thruplot is created create full name set g "$c.${link}thruplot" } # update plot_list - # Plot info to be stored : + # Plot info to be stored : # - canvas coords - # - size (height, width) - # - color scheme - # - linkname - + # - size (height, width) + # - color scheme + # - linkname + # global plot variable that stores all plot info global ${link}thruplot - - # reset global variable - if {[info exists ${link}thruplot]} { unset ${link}thruplot} + + # reset global variable + if {[info exists ${link}thruplot]} { unset ${link}thruplot} set ${link}thruplot {} - lappend ${link}thruplot "name $g" - lappend ${link}thruplot "height $height" - lappend ${link}thruplot "width $width" - lappend ${link}thruplot "x $x" - lappend ${link}thruplot "y $y" - + lappend ${link}thruplot "name $g" + lappend ${link}thruplot "height $height" + lappend ${link}thruplot "width $width" + lappend ${link}thruplot "x $x" + lappend ${link}thruplot "y $y" - # if not in color dict, add and set to default (blue) + + # if not in color dict, add and set to default (blue) if {[dict exists $thruPlotColor $g] == 0} { dict set thruPlotColor $g blue set curPlotBgColor "#EEEEFF" @@ -1025,11 +991,11 @@ proc thruPlot { c link x y height width isresize} { thruPlotSetScheme $scheme lappend ${link}thruplot "color $scheme" } - - # add plot to global plot_list - if {[lsearch $plot_list ${link}thruplot] eq -1} { + + # add plot to global plot_list + if {[lsearch $plot_list ${link}thruplot] eq -1} { lappend plot_list ${link}thruplot - } + } # set global global $g @@ -1040,7 +1006,7 @@ proc thruPlot { c link x y height width isresize} { destroy $g # TODO: support multiple plots for the same link } - canvas $g -height $height -width $width -bg $curPlotBgColor + canvas $g -height $height -width $width -bg $curPlotBgColor $c create window $x $y -window $g -tags "thruplot $g" # set link interface title @@ -1049,21 +1015,21 @@ proc thruPlot { c link x y height width isresize} { set if1 [ifcByPeer $lnode1 $lnode2] set if2 [ifcByPeer $lnode2 $lnode1] - - # if too narrow, bring title down + + # if too narrow, bring title down if {$width < 220} { $g create text $width 20 -anchor ne -text "$if1@$lnode1 - $if2@$lnode2" } else { $g create text $width 0 -anchor ne -text "$if1@$lnode1 - $if2@$lnode2" - } + } # bind items bind $g <1> "thruPlotClick $c $g %x %y none" bind $g "thruPlotHandleB1Motion $c $g %x %y start" - bind $g <3> "thruPlotPopup $g %x %y" + bind $g <3> "thruPlotPopup $g %x %y" - #DYL trying to update cursor look - bind $g "selectmarkEnter $g %x %y" + #DYL trying to update cursor look + bind $g "selectmarkEnter $g %x %y" bind $g "selectmarkLeave $c %x %y" bind $g "thruPlotHandleRelease $c $g %x %y done" #TODO when we are inside the thruplot, the graph hides the cursor @@ -1085,27 +1051,27 @@ proc thruPlotPopup {g xclick yclick } { .button3menu delete 0 end - .button3menu.color delete 0 end + .button3menu.color delete 0 end .button3menu add cascade -label "Set Color" -menu .button3menu.color - - # color red - .button3menu.color add command -label "Red" -command "setThruPlotColor $g red" - - # color blue - .button3menu.color add command -label "Green" -command "setThruPlotColor $g green" - # color green + # color red + .button3menu.color add command -label "Red" -command "setThruPlotColor $g red" + + # color blue + .button3menu.color add command -label "Green" -command "setThruPlotColor $g green" + + # color green .button3menu.color add command -label "Blue" -command "setThruPlotColor $g blue" # delete .button3menu add command -label "Delete" -command "deletePlot $g" - + set x [winfo pointerx .] - set y [winfo pointery .] + set y [winfo pointery .] tk_popup .button3menu $x $y } -# remove thruplot +# remove thruplot proc deletePlot { g } { global plot_list regexp {.c.(.*thruplot)} $g match plotname @@ -1119,15 +1085,15 @@ proc deletePlot { g } { # Mouse click on a throughput plot. # check to see if resize proc thruPlotClick { c g x y modifier } { - global thruplotResize cursorToResizemode resizemode resizeobj thruPlotDragStart thruPlotCur - - set cursorMode [$c cget -cursor] - + global thruplotResize cursorToResizemode resizemode resizeobj thruPlotDragStart thruPlotCur + + set cursorMode [$c cget -cursor] + # check if resizeMode if {$cursorMode != "left_ptr" && $cursorMode != "crosshair"} { - global oldX1 oldY1 oldX2 oldY2 + global oldX1 oldY1 oldX2 oldY2 - # save old top left and bottom right points + # save old top left and bottom right points set bbox [$c bbox $g] set oldX1 [lindex $bbox 0] set oldY1 [lindex $bbox 1] @@ -1135,28 +1101,28 @@ proc thruPlotClick { c g x y modifier } { set oldY2 [lindex $bbox 3] # set resizeobj and resize mode - set resizeobj $g + set resizeobj $g set resizemode [dict get $cursorToResizemode $cursorMode] set thruplotResize true } else { # update cursor to drag (crosshair) - $c configure -cursor crosshair - set thruPlotDragStart true - set thruPlotCur $g + $c configure -cursor crosshair + set thruPlotDragStart true + set thruPlotCur $g } - + } -# Must handle either a resize or a drag +# Must handle either a resize or a drag # The plot canvas gets the B1-Motion event, not the parent canvas proc thruPlotHandleB1Motion {c g x y what} { - global thruplotResize resizemode resizeobj + global thruplotResize resizemode resizeobj set cursorMode [$c cget -cursor] - # check if drag (center is clicked) + # check if drag (center is clicked) if {($cursorMode == "left_ptr" || $cursorMode == "crosshair") && $thruplotResize == false} { thruPlotDrag $c $g $x $y $what false } else { - # resize was clicked + # resize was clicked } } @@ -1168,30 +1134,30 @@ proc thruPlotHandleRelease { c g x y what} { thruPlotDrag $c $g $x $y $what false } else { thruPlotRescale $c $g $x $y - } + } } # redraw thruplot # x y show coords relative to top left corner of thruplot proc thruPlotRescale { c g x y } { - global thruplotResize resizemode oldX1 oldY1 oldX2 oldY2 + global thruplotResize resizemode oldX1 oldY1 oldX2 oldY2 # resize based on resize mode switch $resizemode { ld { - # if the left bot corner is clicked just look at new x set new height + # if the left bot corner is clicked just look at new x set new height lassign [calcDimensions [expr {$oldX1 + $x}] $oldY1 $oldX2 [expr {$oldY1 + $y}]] cx cy h w - thruPlot $c $g $cx $cy $h $w true + thruPlot $c $g $cx $cy $h $w true } ru { # if the right top corner is clicked just look at new x set new heigth lassign [calcDimensions $oldX1 [expr {$oldY1 + $y}] [expr {$oldX1 + $x}] $oldY2] cx cy h w - thruPlot $c $g $cx $cy $h $w true + thruPlot $c $g $cx $cy $h $w true } rd { - # if the right bottom corner clicked + # if the right bottom corner clicked lassign [calcDimensions $oldX1 $oldY1 [expr {$oldX1 + $x}] [expr {$oldY1 + $y}]] cx cy h w - thruPlot $c $g $cx $cy $h $w true + thruPlot $c $g $cx $cy $h $w true } lu { # if the left bottom corner clicked @@ -1205,44 +1171,44 @@ proc thruPlotRescale { c g x y } { } l { # if the left side is clicked just look at new x - lassign [calcDimensions [expr {$oldX1 + $x}] $oldY1 $oldX2 $oldY2] cx cy h w - thruPlot $c $g $cx $cy $h $w true + lassign [calcDimensions [expr {$oldX1 + $x}] $oldY1 $oldX2 $oldY2] cx cy h w + thruPlot $c $g $cx $cy $h $w true } u { - # if the top side is click just look at new y + # if the top side is click just look at new y lassign [calcDimensions $oldX1 [expr {$oldY1 + $y}] $oldX2 $oldY2] cx cy h w - thruPlot $c $g $cx $cy $h $w true + thruPlot $c $g $cx $cy $h $w true } d { # if the top side is click just look at new y lassign [calcDimensions $oldX1 $oldY1 $oldX2 [expr {$oldY1 + $y}]] cx cy h w - thruPlot $c $g $cx $cy $h $w true + thruPlot $c $g $cx $cy $h $w true } default { - puts "ERROR: should not come here. resize mode is invalid." - } + puts "ERROR: should not come here. resize mode is invalid." + } } # rescale is done reset rescale global variables set cursor left_ptr set thruplotResize false - set resizemode false + set resizemode false } # Calculate center, height, width based on top left and bot right corners proc calcDimensions { x1 y1 x2 y2 } { - set h [expr {$y2 - $y1}] + set h [expr {$y2 - $y1}] set w [expr {$x2 - $x1}] # enforce min size if {$h < 100} { - set h 100 + set h 100 } if {$w < 100} { set w 100 } - list [expr {$x1 + ($w/2)}] [expr {$y1 + ($h/2)}] $h $w + list [expr {$x1 + ($w/2)}] [expr {$y1 + ($h/2)}] $h $w } # Mouse drag a throughput plot. @@ -1250,67 +1216,67 @@ proc thruPlotDrag { c g x y what fromCanvas} { global thruPlotDragStart thruPlotCur global plot_list set pad 60 - set maxjump 500 + set maxjump 500 # this fixes a bug when thruplot is off screen if {$fromCanvas == true} { #puts "handling from canvas" - $c coords $thruPlotCur [expr {$x - $pad}] [expr {$y- $pad}] - return + $c coords $thruPlotCur [expr {$x - $pad}] [expr {$y- $pad}] + return } if {$thruPlotDragStart == false} { if { [expr abs($x)] > $maxjump || [expr abs($y)] > $maxjump} { puts "ERROR can not drag too far at one time" - return - } - } else { + return + } + } else { set curx [lindex [$c coords $g] 0] set cury [lindex [$c coords $g] 1] - # perform the actual drag + # perform the actual drag set newx [expr {$x - $pad + $curx}] - set newy [expr {$y- $pad + $cury}] - $c coords $thruPlotCur $newx $newy + set newy [expr {$y- $pad + $cury}] + $c coords $thruPlotCur $newx $newy # save new coords DYL - regexp {.c.(l.*thruplot)} $g match name - # global ${name} + regexp {.c.(l.*thruplot)} $g match name + # global ${name} # find and replace x coord - updatePlotAttr ${name} "x" $newx - updatePlotAttr ${name} "y" $newy + updatePlotAttr ${name} "x" $newx + updatePlotAttr ${name} "y" $newy set thruPlotDragStart dragging - } + } } proc redrawAllThruplots {} { global plot_list foreach tp $plot_list { - # extract the following properties from the thruplot : + # extract the following properties from the thruplot : # full path # height, width # x,y coords, # color scheme set fp [getPlotAttr $tp name] set height [getPlotAttr $tp height] - set width [getPlotAttr $tp width] + set width [getPlotAttr $tp width] set x [getPlotAttr $tp x] set y [getPlotAttr $tp y] set color [getPlotAttr $tp color] - thruPlot .c $fp $x $y $height $width true - setThruPlotColor $fp $color - } + thruPlot .c $fp $x $y $height $width true + setThruPlotColor $fp $color + } } -# this will update an attribute of the global thruplot variable +# this will update an attribute of the global thruplot variable proc updatePlotAttr { plot attr val } { # puts "updating $attr of ${plot} to $val" global ${plot} - # find and replace attribute + # find and replace attribute set i [lsearch [set ${plot}] "$attr *"] # puts " found at $i" if { $i >= 0 } { @@ -1320,7 +1286,7 @@ proc updatePlotAttr { plot attr val } { } } -# this will return an attribute from the plotlist +# this will return an attribute from the plotlist proc getPlotAttr {plot attr} { global ${plot} @@ -1345,7 +1311,7 @@ proc setThruPlotColor { g color} { # set global variables that determine color scheme thruPlotSetScheme $color - # update old data + # update old data $g itemconfigure "filler" -fill $curPlotFillColor $g itemconfigure "line" -fill $curPlotLineColor $g configure -bg $curPlotBgColor @@ -1372,15 +1338,15 @@ proc thruPlotSetScheme { color } { set curPlotBgColor "#eeffee" } default { - puts "ERROR: invalid plot color '$color'" + puts "ERROR: invalid plot color '$color'" } - } + } } # update a throughput plot with a new data point proc thruPlotUpdate { c link kbps } { set g "$c.${link}thruplot" - global $g curPlotLineColor curPlotFillColor curPlotBgColor thruPlotColor thruPlotMaxKBPS + global $g curPlotLineColor curPlotFillColor curPlotBgColor thruPlotColor thruPlotMaxKBPS # Check if window exists if { ![winfo exists $g] } { @@ -1389,10 +1355,10 @@ proc thruPlotUpdate { c link kbps } { # lookup scheme for thruplot and set scheme set scheme [dict get $thruPlotColor $g] - thruPlotSetScheme $scheme - # set bg to scheme - $g configure -bg $curPlotBgColor - + thruPlotSetScheme $scheme + # set bg to scheme + $g configure -bg $curPlotBgColor + set maxx [$g cget -width] set maxy [$g cget -height] set yscale [thruPlotAutoScale $g $kbps] @@ -1400,7 +1366,7 @@ proc thruPlotUpdate { c link kbps } { # shift graph to the left by dt pixels set dt 5.0 $g move "data" -$dt 0.0 - + thruPlotDeleteOldData $g $dt set last [$g find withtag "data && last"] @@ -1416,8 +1382,8 @@ proc thruPlotUpdate { c link kbps } { $g create polygon $x1 $y1 $x2 $y2 $x2 $maxy $x1 $maxy \ -tags "data filler" -fill $curPlotFillColor -width 2 - - $g create line $x1 $y1 $x2 $y2 -tags "data last line" -fill $curPlotLineColor + + $g create line $x1 $y1 $x2 $y2 -tags "data last line" -fill $curPlotLineColor } # return the existing y-value scale; if the given value is off the scale, @@ -1426,21 +1392,21 @@ proc thruPlotAutoScale { g val } { set yscale [lindex [$g itemcget "ticks && scalemax" -text] 0] global thruPlotMaxKBPS - # update global max + # update global max if { $val > $thruPlotMaxKBPS} { set thruPlotMaxKBPS $val - } else { + } else { set val $thruPlotMaxKBPS } - # default + # default if { $yscale == "" || $yscale < 1.0 } { set yscale 10.0 - } + } if { $val < $yscale } { return $yscale ;# value within bounds of existing scale - } + } set maxy [$g cget -height] set newyscale [expr {ceil($val) + 5.0}] @@ -1519,7 +1485,7 @@ proc thruPlotDrawScale { g max } { proc thruPlotDeleteOldData { g dt } { foreach i [$g find withtag "data"] { if { [lindex [$g coords $i] 0] < [expr { -2.0 * $dt }] } { - $g delete $i + $g delete $i } } } @@ -1571,7 +1537,7 @@ proc widget_cpu_config {} { labelframe $wi.hi -padx 4 -pady 4 -text "Node highlighting" - + # Threshold (set to zero to disable) label $wi.hi.lab1 -text "Highlight node if CPU usage exceeds this " pack $wi.hi.lab1 -side top -anchor w @@ -1581,7 +1547,7 @@ proc widget_cpu_config {} { label $wi.hi.t.lab2 -text "% CPU" pack $wi.hi.t.lab2 $wi.hi.t.thresh $wi.hi.t.lab1 -side right -padx 4 -pady 4 pack $wi.hi.lab1 $wi.hi.t -side top - + # Highlight color/width frame $wi.hi.w label $wi.hi.w.lab3 -text "radius:" @@ -1597,7 +1563,7 @@ proc widget_cpu_config {} { pack $wi.hi.w.colbtn $wi.hi.w.color $wi.hi.w.lab1 \ -side right -padx 4 -pady 4 pack $wi.hi.w -side top - + pack $wi.hi -side top -fill x # OK button at bottom @@ -1642,13 +1608,8 @@ proc widget_cpu_init {command} { # proc widget_cpu_periodic { now } { global systype - - if { [lindex $systype 0] == "FreeBSD" } { - widget_cpu_periodic_vimage $now - } else { puts "warning: the CPU widget is not functional for this platform yet" return - } } proc widget_cpu_periodic_vimage { now } { @@ -1664,10 +1625,10 @@ proc widget_cpu_periodic_vimage { now } { set newtext [format "%.2f %%" $cpustats($eid\_$node)] set coords [getCPUcoords $node] - set x [lindex $coords 0] - set y [lindex $coords 1] - set basex [lindex $coords 2] - set basey [lindex $coords 3] + set x [lindex $coords 0] + set y [lindex $coords 1] + set basex [lindex $coords 2] + set basey [lindex $coords 3] set existing [.c find withtag "cpulabel && $node"] if { [llength $existing] == 0 } { ;# create new label @@ -1678,7 +1639,7 @@ proc widget_cpu_periodic_vimage { now } { .c itemconfigure $cpulabel -text $newtext } .c raise $cpulabel - # perform highlighting + # perform highlighting set existing [.c find withtag "cpuhi && $node"] if { $cpustats($eid\_$node) >= $cpuConfig(thresh) } { if { [llength $existing] == 0 } { @@ -1692,7 +1653,7 @@ proc widget_cpu_periodic_vimage { now } { #.c raise "link && $node" .c raise "node && $node" } - + } elseif { [llength $existing] > 0 } { .c delete $existing } @@ -1726,7 +1687,7 @@ proc getstats_cpu_vimage { raw_input} { if { $numlines <= 4 } { return [list 0 0] } - + # add node_name/cpu to a list set ret {} set i 0 @@ -1756,7 +1717,7 @@ proc getstats_cpu_vestat { } { global cpu_vestat_history; # remember previous jiffies set Hertz 100.0; # from , varies per architecture - # read /proc/vz/vestat + # read /proc/vz/vestat if { [catch {set f [open "/proc/vz/vestat" r]} e] } { puts "error opening /proc/vz/vestat: $e" return @@ -1784,8 +1745,8 @@ proc getstats_cpu_vestat { } { array set cpu_vestat_history [list uptime $uptime_now] set elapsed [expr {$uptime_now - $uptime_old}] if { $elapsed == 0.0 } { set elapsed 1.0 }; # don't divide by zero - - + + # add node_name/cpu to a list set ret {} for { set i 0 } { $i < [llength $lines] } { incr i } { @@ -1943,7 +1904,7 @@ proc get_router_id {node} { } } if {[lsearch [getNodeServices $node true] "OLSR"] != -1 } { - + set sock [lindex [getEmulPlugin $node] 2] set exec_num [newExecCallbackRequest adjacencyrouterid] set name [getNodeName $node] @@ -2008,7 +1969,7 @@ proc widget_adjacency_init {command} { set enable_Adjacency_OSPFv3 0 set enable_Adjacency_OLSR 0 set adjacency_config(proto) "OLSRv2_proto" - } + } } # Initialize @@ -2017,7 +1978,7 @@ proc widget_adjacency_init {command} { foreach node $node_list { ;# save router-id node pairs for later lookup if { [nodeType $node] != "router" } { continue } if {[lsearch [getNodeServices $node true] "zebra"] < 0 && - [lsearch [getNodeServices $node true] "OLSR"] < 0 && + [lsearch [getNodeServices $node true] "OLSR"] < 0 && [lsearch [getNodeServices $node true] "OLSRv2"] < 0} { continue } @@ -2107,16 +2068,16 @@ proc exec_adjacency_callback { node execnum cmd result status } { global g_api_exec_num set changed 0 set c .c - + set proto $adjacency_config(proto) array set colors $adjacency_config(colors) if { $adjacency_config(offset) } { set o 5 } else { set o 0 } - $c addtag adjdelete withtag "adjline && $node" ;# flag del all adjlines + $c addtag adjdelete withtag "adjline && $node" ;# flag del all adjlines set adjs [getadj_from_neighbors $result $proto] - + foreach adj $adjs { - + set peer [lindex $adj 0] set line [$c find withtag "adjline && $node && $peer"] @@ -2193,7 +2154,7 @@ proc getadj_from_neighbors { raw_input proto } { "LOST" { set state "Down" } "MPR" { set state "Full" } "PENDING" { set state "Init" } - "INVALID" { set state "Down" } + "INVALID" { set state "Down" } } lappend ret [list $rtrid $state] } @@ -2205,7 +2166,7 @@ proc getadj_from_neighbors { raw_input proto } { #10.0.0.2 1 00:00:06 Init/PointToPoint 00:00:00 eth0[PointToP #10.0.0.2 1 00:00:06 Twoway/PointToPoint 00:00:00 eth0[PointToP #10.0.0.2 1 00:00:06 Full/PointToPoint 00:00:38 eth0[PointToP -#10.0.7.2 1 Full/Backup 37.240s 10.0.0.2 eth0:10.0.0.1 +#10.0.7.2 1 Full/Backup 37.240s 10.0.0.2 eth0:10.0.0.1 foreach line [split $raw_input "\n"] { set rtrid [string trim [string range $line 0 14]] if { $rtrid == "Neighbor ID" } { continue } @@ -2284,17 +2245,17 @@ proc widget_adjacency_init_submenu { m } { set enable_Adjacency_OSPFv2 0 $m.adj add checkbutton -label "OSPFv2" -variable enable_Adjacency_OSPFv2 \ -command "[lindex $widgets(Adjacency) 1] menu2" - + global enable_Adjacency_OSPFv3 set enable_Adjacency_OSPFv3 0 $m.adj add checkbutton -label "OSPFv3" -variable enable_Adjacency_OSPFv3 \ -command "[lindex $widgets(Adjacency) 1] menu3" - + global enable_Adjacency_OLSR set enable_Adjacency_OLSR 0 $m.adj add checkbutton -label "OLSR" -variable enable_Adjacency_OLSR \ -command "[lindex $widgets(Adjacency) 1] menu4" - + global enable_Adjacency_OLSRv2 set enable_Adjacency_OLSRv2 0 $m.adj add checkbutton -label "OLSRv2" -variable enable_Adjacency_OLSRv2 \ diff --git a/kernel/freebsd/4.11-R-CORE.diff b/kernel/freebsd/4.11-R-CORE.diff deleted file mode 100644 index ab7329c6..00000000 --- a/kernel/freebsd/4.11-R-CORE.diff +++ /dev/null @@ -1,7150 +0,0 @@ -diff -urN sys/i386/conf/CORE sys.CORE/i386/conf/CORE ---- sys/i386/conf/CORE Wed Dec 31 16:00:00 1969 -+++ sys.CORE/i386/conf/CORE Wed Jan 31 16:02:43 2007 -@@ -0,0 +1,182 @@ -+machine i386 -+cpu I586_CPU -+cpu I686_CPU -+ident CORE -+maxusers 0 -+ -+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols -+options DDB -+ -+options INET #InterNETworking -+options INET6 #IPv6 communications protocols -+options IPSEC -+options IPSEC_ESP -+#options IPSEC_DEBUG -+options FFS #Berkeley Fast Filesystem -+options FFS_ROOT #FFS usable as root device [keep this!] -+options SOFTUPDATES #Enable FFS soft updates support -+options UFS_DIRHASH #Improve performance on big directories -+options MFS #Memory Filesystem -+options MD_ROOT #MD is a potential root device -+options MSDOSFS #MSDOS Filesystem -+options CD9660 #ISO 9660 Filesystem -+options CD9660_ROOT #CD-ROM usable as root, CD9660 required -+options PROCFS #Process filesystem -+options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] -+options UCONSOLE #Allow users to grab the console -+options USERCONFIG #boot -c editor -+options VISUAL_USERCONFIG #visual boot -c editor -+options KTRACE #ktrace(1) support -+options SYSVSHM #SYSV-style shared memory -+options SYSVMSG #SYSV-style message queues -+options SYSVSEM #SYSV-style semaphores -+options P1003_1B #Posix P1003_1B real-time extensions -+options _KPOSIX_PRIORITY_SCHEDULING -+options ICMP_BANDLIM #Rate limit bad replies -+options KBD_INSTALL_CDEV # install a CDEV entry in /dev -+ -+device isa -+device pci -+ -+# Floppy drives -+device fdc0 at isa? port IO_FD1 irq 6 drq 2 -+device fd0 at fdc0 drive 0 -+ -+# ATA and ATAPI devices -+device ata0 at isa? port IO_WD1 irq 14 -+device ata1 at isa? port IO_WD2 irq 15 -+device ata -+device atadisk # ATA disk drives -+device atapicd # ATAPI CDROM drives -+device atapifd # ATAPI floppy drives -+device atapist # ATAPI tape drives -+options ATA_STATIC_ID #Static device numbering -+ -+# SCSI peripherals -+device scbus # SCSI bus (required) -+device da # Direct Access (disks) -+device sa # Sequential Access (tape etc) -+device cd # CD -+device pass # Passthrough device (direct SCSI access) -+ -+# atkbdc0 controls both the keyboard and the PS/2 mouse -+device atkbdc0 at isa? port IO_KBD -+device atkbd0 at atkbdc? irq 1 flags 0x1 -+device psm0 at atkbdc? irq 12 -+ -+device vga0 at isa? -+ -+# syscons is the default console driver, resembling an SCO console -+device sc0 at isa? flags 0x100 -+ -+device agp # support several AGP chipsets -+ -+# Floating point support - do not disable. -+device npx0 at nexus? port IO_NPX irq 13 -+ -+# Power management support (see LINT for more options) -+#device apm0 at nexus? #flags 0x20 # Advanced Power Management -+ -+# PCCARD (PCMCIA) support -+device card -+device pcic0 at isa? irq 0 port 0x3e0 iomem 0xd0000 -+device pcic1 at isa? irq 0 port 0x3e2 iomem 0xd4000 disable -+ -+# Serial (COM) ports -+# jeffa: added debug flag -+device sio0 at isa? port IO_COM1 flags 0x80 irq 4 -+#device sio0 at isa? port IO_COM1 flags 0x10 irq 4 -+device sio1 at isa? port IO_COM2 irq 3 -+ -+# PCI Ethernet NICs. -+device de # DEC/Intel DC21x4x (``Tulip'') -+device em # Intel PRO/1000 adapter Gigabit Ethernet Card (``Wiseman'') -+device txp # 3Com 3cR990 (``Typhoon'') -+device vx # 3Com 3c590, 3c595 (``Vortex'') -+ -+# PCI Ethernet NICs that use the common MII bus controller code. -+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs! -+device miibus # MII bus support -+device dc # DEC/Intel 21143 and various workalikes -+device fxp # Intel EtherExpress PRO/100B (82557, 82558) -+device pcn # AMD Am79C97x PCI 10/100 NICs -+device rl # RealTek 8129/8139 -+device sf # Adaptec AIC-6915 (``Starfire'') -+device sis # Silicon Integrated Systems SiS 900/SiS 7016 -+device ste # Sundance ST201 (D-Link DFE-550TX) -+device tl # Texas Instruments ThunderLAN -+device tx # SMC EtherPower II (83c170 ``EPIC'') -+device vr # VIA Rhine, Rhine II -+device wb # Winbond W89C840F -+device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'') -+device bge # Broadcom BCM570x (``Tigon III'') -+ -+# ISA Ethernet NICs. -+# 'device ed' requires 'device miibus' -+device ed0 at isa? disable port 0x280 irq 10 iomem 0xd8000 -+device ex -+device ep -+device fe0 at isa? disable port 0x300 -+# Xircom Ethernet -+device xe -+ -+# Wireless -+#device awi -+device wi -+device an -+ -+# The probe order of these is presently determined by i386/isa/isa_compat.c. -+device ie0 at isa? disable port 0x300 irq 10 iomem 0xd0000 -+#device le0 at isa? disable port 0x300 irq 5 iomem 0xd0000 -+device lnc0 at isa? disable port 0x280 irq 10 drq 0 -+device cs0 at isa? disable port 0x300 -+device sn0 at isa? disable port 0x300 irq 10 -+ -+# Pseudo devices - the number indicates how many units to allocate. -+pseudo-device loop # Network loopback -+pseudo-device ether # Ethernet support -+pseudo-device tun # Packet tunnel. -+pseudo-device pty # Pseudo-ttys (telnet etc) -+pseudo-device md # Memory "disks" -+pseudo-device gif -+pseudo-device gre -+ -+# The `bpf' pseudo-device enables the Berkeley Packet Filter. -+# Be aware of the administrative consequences of enabling this! -+pseudo-device bpf #Berkeley packet filter -+ -+# USB support -+device uhci # UHCI PCI->USB interface -+device ohci # OHCI PCI->USB interface -+device usb # USB Bus (required) -+device ugen # Generic -+device uhid # "Human Interface Devices" -+device ukbd # Keyboard -+device ulpt # Printer -+device umass # Disks/Mass storage - Requires scbus and da -+device ums # Mouse -+# USB Ethernet, requires mii -+device aue # ADMtek USB ethernet -+device cue # CATC USB ethernet -+device kue # Kawasaki LSI USB ethernet -+# USB com devices -+device ucom -+device uftdi -+ -+# LIMUNES specific options -+options ROOTDEVNAME=\"cd9660:acd0\" -+options UNION # Is this really needed? -+options EXT2FS # And this? -+pseudo-device vn 15 # Vnode driver (turns a file into a device) -+ -+options MROUTING # Multicast routing -+options PIM # Protocol Independent Multicast -+#options IPFIREWALL # firewall -+#options IPFIREWALL_DEFAULT_TO_ACCEPT # allow everything by default -+#options IPDIVERT # divert sockets -+ -+options HZ=1000 -+#options AUTO_EOI_1 -+options CPU_ENABLE_SSE -+options CPU_FASTER_5X86_FPU -+makeoptions CONF_CFLAGS=-mpentiumpro -diff -urN sys/kern/kern_vimage.c sys.CORE/kern/kern_vimage.c ---- sys/kern/kern_vimage.c Wed Jan 31 15:57:04 2007 -+++ sys.CORE/kern/kern_vimage.c Wed Jan 31 16:02:43 2007 -@@ -52,9 +52,13 @@ - #include - #include - #include -+#include - #include - - #include -+#ifdef IPSEC -+#include -+#endif - - /* Arbitrary values */ - #define TCP_SYNCACHE_HASHSIZE 512 -@@ -107,6 +111,12 @@ - { "mrt6stat", V_NET, v_mrt6stat, sizeof (x_vnet->mrt6stat) }, - { "mf6ctable", V_NET, v_mf6ctable, sizeof (x_vnet->mf6ctable) }, - { "mif6table", V_NET, v_mif6table, sizeof (x_vnet->mif6table) }, -+#ifdef IPSEC -+ { "ipsecstat", V_NET, v_ipsecstat, sizeof (x_vnet->ipsecstat) }, -+#ifdef INET6 -+ { "ipsec6stat", V_NET, v_ipsec6stat, sizeof (x_vnet->ipsec6stat) }, -+#endif /* INET6 */ -+#endif /* IPSEC */ - { NULL, 0, 0 , 0 } - }; - -@@ -742,7 +752,17 @@ - } - - rtable_init((void **)vnet->rt_tables, vnet); -+#ifdef IPSEC -+ if (vnet != vnet0) -+ key_init(vnet); -+#endif - vi_loopattach(vnet); -+ if (vnet != vnet0) -+ gif_init(vnet); -+ -+ /*Boeing IDC*/ -+ if (vnet != vnet0) -+ gre_init(vnet); - - if (IPFW_LOADED) - ip_fw_init_ptr(vnet); -@@ -796,6 +816,15 @@ - - free((caddr_t)vnet->ifnet_addrs, M_IFADDR); - free((caddr_t)vnet->ifindex2ifnet, M_IFADDR); -+ -+ while (!LIST_EMPTY(&vnet->gif_softc_list)) -+ gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if); -+ rman_fini(vnet->gifunits); -+ -+ /*Boeing IDC*/ -+ while (!LIST_EMPTY(&vnet->gre_softc_list)) -+ gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if); -+ rman_fini(vnet->greunits); - - /* hopefully, we are finally clear to free the vnet container itself! */ - LIST_REMOVE(vnet, vnet_le); -diff -urN sys/net/if.c sys.CORE/net/if.c ---- sys/net/if.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/if.c Wed Jan 31 16:19:58 2007 -@@ -276,6 +276,11 @@ - sdl->sdl_data[--namelen] = 0xff; - TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); - } -+#ifdef MROUTING -+#ifdef PIM -+ vnet->reg_vif_num = -1; /* XXX means VIFI_INVALID */ -+#endif -+#endif - - /* Announce the interface. */ - rt_ifannouncemsg(ifp, IFAN_ARRIVAL); -diff -urN sys/net/if_gif.c sys.CORE/net/if_gif.c ---- sys/net/if_gif.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/if_gif.c Wed Jan 31 16:02:43 2007 -@@ -90,7 +90,9 @@ - #define GIF_MAXUNIT 0x7fff /* ifp->if_unit is only 15 bits */ - - static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); -+#ifdef MOVED_TO_VNET - static struct rman gifunits[1]; -+#endif /* MOVED_TO_VNET */ - - int gif_clone_create __P((struct if_clone *, int *, struct vnet *)); - void gif_clone_destroy __P((struct ifnet *)); -@@ -114,22 +116,26 @@ - */ - #define MAX_GIF_NEST 1 - #endif -+#ifdef MOVED_TO_VNET - static int max_gif_nesting = MAX_GIF_NEST; --SYSCTL_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, -- &max_gif_nesting, 0, "Max nested tunnels"); -+#endif /* MOVED_TO_VNET */ -+SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, -+ v_max_gif_nesting, 0, "Max nested tunnels"); - - /* - * By default, we disallow creation of multiple tunnels between the same - * pair of addresses. Some applications require this functionality so - * we allow control over this check here. - */ -+#ifdef MOVED_TO_VNET - #ifdef XBONEHACK - static int parallel_tunnels = 1; - #else - static int parallel_tunnels = 0; - #endif --SYSCTL_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, -- ¶llel_tunnels, 0, "Allow parallel tunnels?"); -+#endif /* MOVED_TO_VNET */ -+SYSCTL_V_INT(V_NET, _net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, -+ v_parallel_tunnels, 0, "Allow parallel tunnels?"); - - int - gif_clone_create(ifc, unit, vnet) -@@ -140,17 +146,19 @@ - struct resource *r; - struct gif_softc *sc; - -+ if (vnet == NULL) -+ panic("gif_clone_create: NULL vnet was passed."); - if (*unit > GIF_MAXUNIT) - return (ENXIO); - - if (*unit < 0) { -- r = rman_reserve_resource(gifunits, 0, GIF_MAXUNIT, 1, -+ r = rman_reserve_resource(vnet->gifunits, 0, GIF_MAXUNIT, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - if (r == NULL) - return (ENOSPC); - *unit = rman_get_start(r); - } else { -- r = rman_reserve_resource(gifunits, *unit, *unit, 1, -+ r = rman_reserve_resource(vnet->gifunits, *unit, *unit, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - if (r == NULL) - return (EEXIST); -@@ -202,6 +210,8 @@ - struct gif_softc *sc = ifp->if_softc; - struct vnet *vnet = ifp->if_vnet; - -+ if (vnet == NULL) -+ panic("gif_clone_destroy: NULL vnet from ifp."); - gif_delete_tunnel(&sc->gif_if); - LIST_REMOVE(sc, gif_list); - #ifdef INET6 -@@ -226,31 +236,61 @@ - free(sc, M_GIF); - } - -+/* Initialize gif vars for a single vnet */ -+int -+gif_init(vnet) -+ struct vnet *vnet; -+{ -+ int err=0; -+ -+ vnet->max_gif_nesting = MAX_GIF_NEST; -+ vnet->parallel_tunnels = 0; -+ vnet->gifunits->rm_type = RMAN_ARRAY; -+ vnet->gifunits->rm_descr = "configurable if_gif units"; -+ err = rman_init(vnet->gifunits); -+ if (err != 0) -+ return (err); -+ err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT); -+ if (err != 0) { -+ printf("%s: gifunits: rman_manage_region: Failed %d\n", -+ GIFNAME, err); -+ rman_fini(vnet->gifunits); -+ return (err); -+ } -+ LIST_INIT(&vnet->gif_softc_list); -+ -+ return 0; -+} -+ - static int - gifmodevent(mod, type, data) - module_t mod; - int type; - void *data; - { -- int err; -+ int err=0; - struct vnet *vnet; - - switch (type) { - case MOD_LOAD: -- gifunits->rm_type = RMAN_ARRAY; -- gifunits->rm_descr = "configurable if_gif units"; -- err = rman_init(gifunits); -+ LIST_FOREACH(vnet, &vnet_head, vnet_le) -+ { -+ vnet->max_gif_nesting = MAX_GIF_NEST; -+ vnet->parallel_tunnels = 0; -+ vnet->gifunits->rm_type = RMAN_ARRAY; -+ vnet->gifunits->rm_descr = "configurable if_gif units"; -+ err = rman_init(vnet->gifunits); - if (err != 0) - return (err); -- err = rman_manage_region(gifunits, 0, GIF_MAXUNIT); -+ err = rman_manage_region(vnet->gifunits, 0, GIF_MAXUNIT); - if (err != 0) { - printf("%s: gifunits: rman_manage_region: Failed %d\n", - GIFNAME, err); -- rman_fini(gifunits); -+ rman_fini(vnet->gifunits); - return (err); - } -- LIST_FOREACH(vnet, &vnet_head, vnet_le) -- LIST_INIT(&vnet->gif_softc_list); -+ LIST_INIT(&vnet->gif_softc_list); -+ } - if_clone_attach(&gif_cloner); - - #ifdef INET6 -@@ -261,11 +301,12 @@ - case MOD_UNLOAD: - if_clone_detach(&gif_cloner); - -- LIST_FOREACH(vnet, &vnet_head, vnet_le) -+ LIST_FOREACH(vnet, &vnet_head, vnet_le) { - while (!LIST_EMPTY(&vnet->gif_softc_list)) - gif_clone_destroy(&LIST_FIRST(&vnet->gif_softc_list)->gif_if); -+ err = rman_fini(vnet->gifunits); -+ } - -- err = rman_fini(gifunits); - if (err != 0) - return (err); - #ifdef INET6 -@@ -295,6 +336,8 @@ - struct ip ip; - struct gif_softc *sc; - -+ if (vnet == NULL) -+ panic("gif_encapcheck: NULL vnet was passed."); - sc = (struct gif_softc *)arg; - if (sc == NULL) - return 0; -@@ -358,6 +401,11 @@ - struct gif_softc *sc = (struct gif_softc*)ifp; - int error = 0; - static int called = 0; /* XXX: MUTEX */ -+ struct vnet *vnet; -+ -+ vnet = ifp->if_vnet; -+ /*if (vnet == NULL) -+ panic("gif_output: cannot find vnet.");*/ - - /* - * gif may cause infinite recursion calls when misconfigured. -@@ -366,7 +414,7 @@ - * mutual exclusion of the variable CALLED, especially if we - * use kernel thread. - */ -- if (++called > max_gif_nesting) { -+ if (++called > vnet->max_gif_nesting) { - log(LOG_NOTICE, - "gif_output: recursively called too many times(%d)\n", - called); -@@ -441,13 +489,16 @@ - int s, isr; - struct p_ifqueue *p_ifq = NULL; - struct ifqueue *ifq; -- struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; -+ struct vnet *vnet; - - if (ifp == NULL) { - /* just in case */ - m_freem(m); - return; - } -+ vnet = ifp->if_vnet; -+ if (vnet == NULL) -+ panic("gif_input: NULL vnet was passed."); - - m->m_pkthdr.rcvif = ifp; - -@@ -779,6 +830,8 @@ - int error = 0; - struct vnet *vnet = sc->gif_vnet; - -+ if (vnet == NULL) -+ panic("gif_set_tunnel: NULL vnet from sc->gif_vnet"); - s = splnet(); - - LIST_FOREACH(sc2, &vnet->gif_softc_list, gif_list) { -@@ -796,7 +849,7 @@ - * Disallow parallel tunnels unless instructed - * otherwise. - */ -- if (!parallel_tunnels && -+ if (!vnet->parallel_tunnels && - bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 && - bcmp(sc2->gif_psrc, src, src->sa_len) == 0) { - error = EADDRNOTAVAIL; -diff -urN sys/net/if_gif.h sys.CORE/net/if_gif.h ---- sys/net/if_gif.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/if_gif.h Wed Jan 31 16:02:43 2007 -@@ -75,6 +75,7 @@ - #define GIF_MTU_MAX (8192) /* Maximum MTU */ - - /* Prototypes */ -+int gif_init(struct vnet *); - void gifattach0 __P((struct gif_softc *)); - void gif_input __P((struct mbuf *, int, struct ifnet *)); - int gif_output __P((struct ifnet *, struct mbuf *, -diff -urN sys/net/if_gre.c sys.CORE/net/if_gre.c ---- sys/net/if_gre.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/if_gre.c Wed Jan 31 16:02:43 2007 -@@ -97,10 +97,14 @@ - #define GRE_MAXUNIT 0x7fff - - static MALLOC_DEFINE(M_GRE, GRENAME, "Generic Routing Encapsulation"); -+#ifdef MOVED_TO_VNET - static struct rman greunits[1]; -+#endif /* MOVED_TO_VNET */ - --static int gre_clone_create(struct if_clone *, int *, struct vnet *); --static void gre_clone_destroy(struct ifnet *); -+/*Boeing IDC static int gre_clone_create(struct if_clone *, int *, struct vnet *);*/ -+/*Boeing IDC static void gre_clone_destroy(struct ifnet *);*/ -+int gre_clone_create __P((struct if_clone *, int *, struct vnet *)); -+void gre_clone_destroy __P((struct ifnet *)); - static int gre_ioctl(struct ifnet *, u_long, caddr_t); - static int gre_output(struct ifnet *, struct mbuf *, struct sockaddr *, - struct rtentry *rt); -@@ -144,9 +148,11 @@ - */ - #define MAX_GRE_NEST 1 - #endif -+#ifdef MOVED_TO_VNET - static int max_gre_nesting = MAX_GRE_NEST; --SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW, -- &max_gre_nesting, 0, "Max nested tunnels"); -+#endif /* MOVED_TO_VNET */ -+SYSCTL_V_INT(V_NET, _net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW, -+ v_max_gre_nesting, 0, "Max nested tunnels"); - - /* ARGSUSED */ - static void -@@ -167,17 +173,20 @@ - struct resource *r; - struct gre_softc *sc; - -+ if (vnet == NULL) -+ panic("gre_clone_create: NULL vnet was passed."); -+ - if (*unit > GRE_MAXUNIT) - return (ENXIO); - - if (*unit < 0) { -- r = rman_reserve_resource(greunits, 0, GRE_MAXUNIT, 1, -+ r = rman_reserve_resource(vnet->greunits, 0, GRE_MAXUNIT, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - if (r == NULL) - return (ENOSPC); - *unit = rman_get_start(r); - } else { -- r = rman_reserve_resource(greunits, *unit, *unit, 1, -+ r = rman_reserve_resource(vnet->greunits, *unit, *unit, 1, - RF_ALLOCATED | RF_ACTIVE, NULL); - if (r == NULL) - return (EEXIST); -@@ -211,12 +220,16 @@ - return (0); - } - --static void -+/*static*/ -+void - gre_clone_destroy(ifp) - struct ifnet *ifp; - { - int err; - struct gre_softc *sc = ifp->if_softc; -+ /*Boeing IDC copied from if_gif.c*/ -+ if (sc->g_vnet == NULL) -+ panic("gre_clone_destroy: NULL vnet from ifp."); - - #ifdef INET - if (sc->encap != NULL) -@@ -232,6 +245,37 @@ - free(sc, M_GRE); - } - -+ -+/*Boeing IDC*/ -+ -+/* Initialize gif vars for a single vnet */ -+int -+gre_init(vnet) -+ struct vnet *vnet; -+{ -+ int err=0; -+ -+ vnet->max_gre_nesting = MAX_GRE_NEST; -+ vnet->parallel_tunnels = 0; -+ vnet->greunits->rm_type = RMAN_ARRAY; -+ vnet->gifunits->rm_descr = "configurable if_gre units"; -+ err = rman_init(vnet->greunits); -+ if (err != 0) -+ return (err); -+ err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT); -+ if (err != 0) { -+ printf("%s: greunits: rman_manage_region: Failed %d\n", -+ GRENAME, err); -+ rman_fini(vnet->greunits); -+ return (err); -+ } -+ LIST_INIT(&vnet->gre_softc_list); -+ return 0; -+} -+ -+ -+ -+ - /* - * The output routine. Takes a packet and encapsulates it in the protocol - * given by sc->g_proto. See also RFC 1701 and RFC 2004 -@@ -247,12 +291,14 @@ - u_char osrc; - u_short etype = 0; - struct mobile_h mob_h; -+ struct vnet *vnet; - -+ vnet = ifp->if_vnet; - /* - * gre may cause infinite recursion calls when misconfigured. - * We'll prevent this by introducing upper limit. - */ -- if (++(sc->called) > max_gre_nesting) { -+ if (++(sc->called) > vnet->max_gre_nesting) { - printf("%s: gre_output: recursively called too many " - "times(%d)\n", if_name(&sc->sc_if), sc->called); - m_freem(m); -@@ -780,31 +826,33 @@ - - switch (type) { - case MOD_LOAD: -- greunits->rm_type = RMAN_ARRAY; -- greunits->rm_descr = "configurable if_gre units"; -- err = rman_init(greunits); -+ LIST_FOREACH(vnet, &vnet_head, vnet_le) -+ { -+ vnet->max_gre_nesting = MAX_GRE_NEST; -+ vnet->greunits->rm_type = RMAN_ARRAY; -+ vnet->greunits->rm_descr = "configurable if_gre units"; -+ err = rman_init(vnet->greunits); - if (err != 0) - return (err); -- err = rman_manage_region(greunits, 0, GRE_MAXUNIT); -+ err = rman_manage_region(vnet->greunits, 0, GRE_MAXUNIT); - if (err != 0) { -- printf("%s: greunits: rman_manage_region: Failed %d\n", -- GRENAME, err); -- rman_fini(greunits); -- return (err); -+ printf("%s: greunits: rman_manage_region: Failed %d\n", -+ GRENAME, err); -+ rman_fini(vnet->greunits); -+ return (err); -+ } -+ greattach(vnet); - } -- -- LIST_FOREACH(vnet, &vnet_head, vnet_le) -- greattach(vnet); -- - break; - case MOD_UNLOAD: - if_clone_detach(&gre_cloner); - -- LIST_FOREACH(vnet, &vnet_head, vnet_le) -+ err = 0; -+ LIST_FOREACH(vnet, &vnet_head, vnet_le) { - while (!LIST_EMPTY(&vnet->gre_softc_list)) - gre_clone_destroy(&LIST_FIRST(&vnet->gre_softc_list)->sc_if); -- -- err = rman_fini(greunits); -+ err += rman_fini(vnet->greunits); -+ } - if (err != 0) - return (err); - -diff -urN sys/net/if_gre.h sys.CORE/net/if_gre.h ---- sys/net/if_gre.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/if_gre.h Wed Jan 31 16:02:43 2007 -@@ -172,4 +172,7 @@ - u_short gre_in_cksum(u_short *p, u_int len); - #endif /* _KERNEL */ - -+/* Prototypes */ -+int gre_init(struct vnet *); -+ - #endif -diff -urN sys/net/vnet.h sys.CORE/net/vnet.h ---- sys/net/vnet.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/net/vnet.h Wed Jan 31 16:02:43 2007 -@@ -83,6 +83,15 @@ - #include - #include - -+/* IPsec support */ -+#include -+#include -+#include -+#include -+/* gif support */ -+#include -+#include -+ - #ifdef _KERNEL - - int vi_if_move(struct vi_req *, struct ifnet *, struct vimage *); -@@ -131,6 +140,7 @@ - - TAILQ_HEAD(dadq_head, dadq); - -+/**/ - - struct vnet { - LIST_ENTRY(vnet) vnet_le; /* linked list of all vnets */ -@@ -172,7 +182,8 @@ - struct ifnet loif; /* from net/if_loop.c */ - struct ifnet vipa; /* from net/if_loop.c */ - -- struct gre_softc_head gre_softc_list; -+ /*Boeing IDC struct gre_softc_head gre_softc_list;*/ -+ LIST_HEAD(, gre_softc) gre_softc_list; - LIST_HEAD(, gif_softc) gif_softc_list; - - /* NETINET */ -@@ -370,6 +381,8 @@ - struct udpstat udpstat; /* from udp_usrreq.c */ - struct icmpstat icmpstat; /* from ip_icmp.c */ - struct igmpstat igmpstat; /* from igmp.c */ -+ struct pfkeystat pfkeystat; /* from keysock.c */ -+ struct _keystat { u_long getspi_count; } keystat; - - u_int rsvpdebug; /* from ip_mroute.c */ - u_int mrtdebug; -@@ -571,6 +584,67 @@ - - struct ip_fib_heap_entry ip_fib_heap[33]; - int ip_fib_heap_index; -+ -+/* gif tunneling interface stuff */ -+ /* -+ * from net/if_gif.c -+ */ -+ struct rman gifunits[1]; -+ int max_gif_nesting; -+ int parallel_tunnels; -+ /* -+ * from net/if_gre.c -+ */ -+ struct rman greunits[1]; -+ int max_gre_nesting; -+/* IPsec stuff */ -+/* Do not use #ifdef IPSEC here, or problems will occur! */ -+ /* -+ * from netkey/key.c -+ */ -+ u_int key_spi_trycnt; -+ u_int32_t key_spi_minval; -+ u_int32_t key_spi_maxval; -+ u_int32_t policy_id; -+ u_int key_int_random; /*interval to initialize randseed,1(m)*/ -+ u_int key_larval_lifetime; /* interval to expire acquiring, 30(s)*/ -+ int key_blockacq_count; /* counter for blocking SADB_ACQUIRE.*/ -+ int key_blockacq_lifetime; /* lifetime for blocking SADB_ACQUIRE.*/ -+ int key_preferred_oldsa; /* preferred old sa rather than new sa.*/ -+ u_int32_t acq_seq; -+ int key_tick_init_random; -+ LIST_HEAD(_sptree, secpolicy) sptree[IPSEC_DIR_MAX]; /* SPD */ -+ LIST_HEAD(_sahtree, secashead) sahtree; /* SAD */ -+ LIST_HEAD(_regtree, secreg) regtree[SADB_SATYPE_MAX + 1]; /* regd list*/ -+ LIST_HEAD(_acqtree, secacq) acqtree; /* acquiring list */ -+ LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ -+ struct key_cb key_cb; -+ -+ /* -+ * from netinet6/ipsec.c -+ */ -+ /* int ipsec_debug; stays in ipsec.c to avoid unnecessary passing -+ of vnet in simple functions that are printing */ -+ struct ipsecstat ipsecstat; -+ int ip4_ah_cleartos; -+ int ip4_ah_offsetmask; /* maybe IP_DF? */ -+ int ip4_ipsec_dfbit; /* DF bit on encap. 0: clear 1: set 2: copy */ -+ int ip4_esp_trans_deflev; -+ int ip4_esp_net_deflev; -+ int ip4_ah_trans_deflev; -+ int ip4_ah_net_deflev; -+ struct secpolicy ip4_def_policy; -+ int ip4_ipsec_ecn; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -+ int ip4_esp_randpad; -+ struct ipsecstat ipsec6stat; -+ int ip6_esp_trans_deflev; -+ int ip6_esp_net_deflev; -+ int ip6_ah_trans_deflev; -+ int ip6_ah_net_deflev; -+ struct secpolicy ip6_def_policy; -+ int ip6_ipsec_ecn; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -+ int ip6_esp_randpad; -+ - }; - - /* -@@ -827,7 +901,41 @@ - #define v_rtq_reallyold6 offsetof(struct vnet, rtq_reallyold6) - #define v_rtq_minreallyold6 offsetof(struct vnet, rtq_minreallyold6) - #define v_rtq_toomany6 offsetof(struct vnet, rtq_toomany6) -- -+#define v_max_gif_nesting offsetof(struct vnet, max_gif_nesting) -+#define v_parallel_tunnels offsetof(struct vnet, parallel_tunnels) -+#define v_max_gre_nesting offsetof(struct vnet, max_gre_nesting) -+#define v_key_debug_level offsetof(struct vnet, key_debug_level) -+#define v_key_spi_trycnt offsetof(struct vnet, key_spi_trycnt) -+#define v_key_spi_minval offsetof(struct vnet, key_spi_minval) -+#define v_key_spi_maxval offsetof(struct vnet, key_spi_maxval) -+#define v_policy_id offsetof(struct vnet, policy_id) -+#define v_key_int_random offsetof(struct vnet, key_int_random) -+#define v_key_larval_lifetime offsetof(struct vnet, key_larval_lifetime) -+#define v_key_blockacq_count offsetof(struct vnet, key_blockacq_count) -+#define v_key_blockacq_lifetime offsetof(struct vnet, key_blockacq_lifetime) -+#define v_key_preferred_oldsa offsetof(struct vnet, key_preferred_oldsa) -+#define v_acq_seq offsetof(struct vnet, acq_seq) -+#define v_key_tick_init_random offsetof(struct vnet, key_tick_init_random) -+#define v_key_cb offsetof(struct vnet, key_cb) -+#define v_ipsecstat offsetof(struct vnet, ipsecstat) -+#define v_ip4_ah_cleartos offsetof(struct vnet, ip4_ah_cleartos) -+#define v_ip4_ah_offsetmask offsetof(struct vnet, ip4_ah_offsetmask) -+#define v_ip4_ipsec_dfbit offsetof(struct vnet, ip4_ipsec_dfbit) -+#define v_ip4_esp_trans_deflev offsetof(struct vnet, ip4_esp_trans_deflev) -+#define v_ip4_esp_net_deflev offsetof(struct vnet, ip4_esp_net_deflev) -+#define v_ip4_ah_trans_deflev offsetof(struct vnet, ip4_ah_trans_deflev) -+#define v_ip4_ah_net_deflev offsetof(struct vnet, ip4_ah_net_deflev) -+#define v_ip4_def_policy offsetof(struct vnet, ip4_def_policy) -+#define v_ip4_ipsec_ecn offsetof(struct vnet, ip4_ipsec_ecn) -+#define v_ip4_esp_randpad offsetof(struct vnet, ip4_esp_randpad) -+#define v_ipsec6stat offsetof(struct vnet, ipsec6stat) -+#define v_ip6_esp_trans_deflev offsetof(struct vnet, ip6_esp_trans_deflev) -+#define v_ip6_esp_net_deflev offsetof(struct vnet, ip6_esp_net_deflev) -+#define v_ip6_ah_trans_deflev offsetof(struct vnet, ip6_ah_trans_deflev) -+#define v_ip6_ah_net_deflev offsetof(struct vnet, ip6_ah_net_deflev) -+#define v_ip6_def_policy offsetof(struct vnet, ip6_def_policy) -+#define v_ip6_ipsec_ecn offsetof(struct vnet, ip6_ipsec_ecn) -+#define v_ip6_esp_randpad offsetof(struct vnet, ip6_esp_randpad) - - #endif _KERNEL - -diff -urN sys/netinet/ip_encap.c sys.CORE/netinet/ip_encap.c ---- sys/netinet/ip_encap.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/ip_encap.c Wed Jan 31 16:02:43 2007 -@@ -151,6 +151,7 @@ - - match = NULL; - matchprio = 0; -+ - for (ep = LIST_FIRST(&vnet->encaptab); ep; ep = LIST_NEXT(ep, chain)) { - if (ep->af != AF_INET) - continue; -@@ -228,7 +229,7 @@ - const struct ip6protosw *psw; - struct encaptab *ep, *match; - int prio, matchprio; -- struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; -+ struct vnet *vnet = m->m_pkthdr.rcvif->if_vnet; - - ip6 = mtod(m, struct ip6_hdr *); - -@@ -378,7 +379,7 @@ - encap_attach_func(af, proto, func, psw, arg, vnet) - int af; - int proto; -- int (*func) __P((const struct mbuf *, int, int, void *)); -+ int (*func) __P((const struct mbuf *, int, int, void *, struct vnet *)); - const struct protosw *psw; - void *arg; - struct vnet *vnet; -@@ -450,6 +451,8 @@ - u_int8_t *r; - int matchlen; - -+ char *inetadd; -+ - if (sp->sa_len > sizeof(s) || dp->sa_len > sizeof(d)) - return 0; - if (sp->sa_family != ep->af || dp->sa_family != ep->af) -@@ -483,11 +486,24 @@ - d.ss_len = dp->sa_len; - d.ss_family = dp->sa_family; - -- if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && -+ if (bcmp(&s, &ep->src, ep->src.ss_len) == 0 && - bcmp(&d, &ep->dst, ep->dst.ss_len) == 0) { - return matchlen; -- } else -- return 0; -+ /*Boeing IDC MTUN IPv4 case*/ -+ } else if ((ep->src.ss_family == AF_INET) && -+ (IN_MULTICAST(ntohl(((struct sockaddr_in*)&ep->dst)->sin_addr.s_addr ))) && -+ (IN_MULTICAST(ntohl(((struct sockaddr_in*)sp)->sin_addr.s_addr ))) && -+ (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) { -+ return matchlen+1; -+ /*Boeing IDC MTUN IPv6 case*/ -+ } else if ((ep->src.ss_family == AF_INET6) && -+ (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)&ep->dst)->sin6_addr))) && -+ (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6*)sp)->sin6_addr))) && -+ (bcmp(&s, &ep->dst, ep->src.ss_len) == 0)) { -+ return matchlen+1; -+ } else { -+ return 0; -+ } - } - - static void -diff -urN sys/netinet/ip_encap.h sys.CORE/netinet/ip_encap.h ---- sys/netinet/ip_encap.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/ip_encap.h Wed Jan 31 16:02:43 2007 -@@ -57,7 +57,7 @@ - const struct sockaddr *, const struct protosw *, void *, - struct vnet *); - const struct encaptab *encap_attach_func(int, int, -- int (*)(const struct mbuf *, int, int, void *), -+ int (*)(const struct mbuf *, int, int, void *, struct vnet *), - const struct protosw *, void *, struct vnet *); - int encap_detach(const struct encaptab *, struct vnet *); - void *encap_getarg(struct mbuf *); -diff -urN sys/netinet/ip_icmp.c sys.CORE/netinet/ip_icmp.c ---- sys/netinet/ip_icmp.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/ip_icmp.c Wed Jan 31 16:02:43 2007 -@@ -600,7 +600,7 @@ - (struct sockaddr *)&icmpgw, (struct rtentry **)0, vnet); - pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc, vnet); - #ifdef IPSEC -- key_sa_routechange((struct sockaddr *)&icmpsrc); -+ key_sa_routechange((struct sockaddr *)&icmpsrc, vnet); - #endif - break; - -diff -urN sys/netinet/ip_input.c sys.CORE/netinet/ip_input.c ---- sys/netinet/ip_input.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/ip_input.c Wed Jan 31 16:02:43 2007 -@@ -694,8 +694,8 @@ - /* - * Enforce inbound IPsec SPD. - */ -- if (ipsec4_in_reject(m, NULL)) { -- ipsecstat.in_polvio++; -+ if (ipsec4_in_reject(m, NULL, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto bad; - } - #endif /* IPSEC */ -@@ -903,8 +903,8 @@ - * code - like udp/tcp/raw ip. - */ - if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 && -- ipsec4_in_reject(m, NULL)) { -- ipsecstat.in_polvio++; -+ ipsec4_in_reject(m, NULL, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto bad; - } - #endif -@@ -1970,7 +1970,7 @@ - sp = ipsec4_getpolicybyaddr(mcopy, - IPSEC_DIR_OUTBOUND, - IP_FORWARDING, -- &ipsecerror); -+ &ipsecerror, vnet); - - if (sp == NULL) - destifp = vnet->ipforward_rt.ro_rt->rt_ifp; -@@ -1978,7 +1978,7 @@ - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, -- NULL); -+ NULL, vnet); - - /* - * find the correct route for outer IPv4 -@@ -2029,7 +2029,7 @@ - /* count IPsec header size */ - ipsechdr = ipsec4_hdrsiz(mcopy, - IPSEC_DIR_OUTBOUND, -- NULL); -+ NULL, vnet); - - /* - * find the correct route for outer IPv4 -diff -urN sys/netinet/ip_output.c sys.CORE/netinet/ip_output.c ---- sys/netinet/ip_output.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/ip_output.c Wed Jan 31 16:02:43 2007 -@@ -320,14 +320,22 @@ - * See if the caller provided any multicast options - */ - if (imo != NULL) { -- ip->ip_ttl = imo->imo_multicast_ttl; -+ /* Boeing IDC to handle divert re-injection -+ * If you don't want the TTL to be modified then -+ * set the multicast_ttl socket option to zero. -+ */ -+ if (imo->imo_multicast_ttl != 0){ -+ ip->ip_ttl = imo->imo_multicast_ttl; -+ } - if (imo->imo_multicast_vif != -1) - ip->ip_src.s_addr = - ip_mcast_src ? - ip_mcast_src(imo->imo_multicast_vif, vnet) : - INADDR_ANY; -- } else -- ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; -+ } else { -+ ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL; -+ } -+ - /* - * Confirm that the outgoing interface supports multicast. - */ -@@ -459,12 +467,12 @@ - #ifdef IPSEC - /* get SP for this packet */ - if (so == NULL) -- sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error); -+ sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error, vnet); - else - sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); - - if (sp == NULL) { -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - goto bad; - } - -@@ -476,7 +484,7 @@ - /* - * This packet is just discarded. - */ -- ipsecstat.out_polvio++; -+ vnet->ipsecstat.out_polvio++; - goto bad; - - case IPSEC_POLICY_BYPASS: -diff -urN sys/netinet/raw_ip.c sys.CORE/netinet/raw_ip.c ---- sys/netinet/raw_ip.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/raw_ip.c Wed Jan 31 16:02:43 2007 -@@ -184,9 +184,9 @@ - - #ifdef IPSEC - /* check AH/ESP integrity. */ -- if (n && ipsec4_in_reject_so(n, last->inp_socket)) { -+ if (n && ipsec4_in_reject_so(n, last->inp_socket, vnet)) { - m_freem(n); -- ipsecstat.in_polvio++; -+ vnet->ipsecstat.in_polvio++; - /* do not inject data to pcb */ - } else - #endif /*IPSEC*/ -@@ -217,9 +217,9 @@ - } - #ifdef IPSEC - /* check AH/ESP integrity. */ -- if (last && ipsec4_in_reject_so(m, last->inp_socket)) { -+ if (last && ipsec4_in_reject_so(m, last->inp_socket, vnet)) { - m_freem(m); -- ipsecstat.in_polvio++; -+ vnet->ipsecstat.in_polvio++; - vnet->ipstat.ips_delivered--; - /* do not inject data to pcb */ - } else -diff -urN sys/netinet/tcp_input.c sys.CORE/netinet/tcp_input.c ---- sys/netinet/tcp_input.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/tcp_input.c Wed Jan 31 16:02:43 2007 -@@ -580,13 +580,15 @@ - - #ifdef IPSEC - if (isipv6) { -- if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket)) { -- ipsec6stat.in_polvio++; -+#ifdef INET6 -+ if (inp != NULL && ipsec6_in_reject_so(m, inp->inp_socket, vnet)) { -+ vnet->ipsec6stat.in_polvio++; - goto drop; - } -+#endif - } else { -- if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket)) { -- ipsecstat.in_polvio++; -+ if (inp != NULL && ipsec4_in_reject_so(m, inp->inp_socket, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto drop; - } - } -diff -urN sys/netinet/tcp_subr.c sys.CORE/netinet/tcp_subr.c ---- sys/netinet/tcp_subr.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/tcp_subr.c Wed Jan 31 16:02:43 2007 -@@ -1468,9 +1468,13 @@ - struct ip6_hdr *ip6; - #endif /* INET6 */ - struct tcphdr *th; -+ struct vnet *vnet; - - if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL)) - return 0; -+ vnet = tp->t_vnet; -+ if (vnet == NULL) -+ panic("ipsec_hdrsiz_tcp: NULL vnet was passed."); - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (!m) - return 0; -@@ -1482,7 +1486,7 @@ - m->m_pkthdr.len = m->m_len = - sizeof(struct ip6_hdr) + sizeof(struct tcphdr); - tcp_fillheaders(tp, ip6, th); -- hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); -+ hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet); - } else - #endif /* INET6 */ - { -@@ -1490,7 +1494,7 @@ - th = (struct tcphdr *)(ip + 1); - m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr); - tcp_fillheaders(tp, ip, th); -- hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp); -+ hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp, vnet); - } - - m_free(m); -diff -urN sys/netinet/udp_usrreq.c sys.CORE/netinet/udp_usrreq.c ---- sys/netinet/udp_usrreq.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet/udp_usrreq.c Wed Jan 31 16:02:43 2007 -@@ -325,8 +325,8 @@ - - #ifdef IPSEC - /* check AH/ESP integrity. */ -- if (ipsec4_in_reject_so(m, last->inp_socket)) -- ipsecstat.in_polvio++; -+ if (ipsec4_in_reject_so(m, last->inp_socket, vnet)) -+ vnet->ipsecstat.in_polvio++; - /* do not inject data to pcb */ - else - #endif /*IPSEC*/ -@@ -365,8 +365,8 @@ - } - #ifdef IPSEC - /* check AH/ESP integrity. */ -- if (ipsec4_in_reject_so(m, last->inp_socket)) { -- ipsecstat.in_polvio++; -+ if (ipsec4_in_reject_so(m, last->inp_socket, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto bad; - } - #endif /*IPSEC*/ -@@ -410,8 +410,8 @@ - return; - } - #ifdef IPSEC -- if (ipsec4_in_reject_so(m, inp->inp_socket)) { -- ipsecstat.in_polvio++; -+ if (ipsec4_in_reject_so(m, inp->inp_socket, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto bad; - } - #endif /*IPSEC*/ -diff -urN sys/netinet6/ah.h sys.CORE/netinet6/ah.h ---- sys/netinet6/ah.h Sat Apr 27 22:40:26 2002 -+++ sys.CORE/netinet6/ah.h Wed Jan 31 16:02:43 2007 -@@ -86,9 +86,9 @@ - - extern size_t ah_hdrsiz __P((struct ipsecrequest *)); - extern void ah4_input __P((struct mbuf *, ...)); --extern int ah4_output __P((struct mbuf *, struct ipsecrequest *)); -+extern int ah4_output __P((struct mbuf *, struct ipsecrequest *, struct vnet*)); - extern int ah4_calccksum __P((struct mbuf *, caddr_t, size_t, -- const struct ah_algorithm *, struct secasvar *)); -+ const struct ah_algorithm *, struct secasvar *, struct vnet *)); - #endif /* _KERNEL */ - - #endif /* _NETINET6_AH_H_ */ -diff -urN sys/netinet6/ah_core.c sys.CORE/netinet6/ah_core.c ---- sys/netinet6/ah_core.c Sat Apr 27 22:40:26 2002 -+++ sys.CORE/netinet6/ah_core.c Wed Jan 31 16:02:43 2007 -@@ -52,6 +52,7 @@ - #include - #include - -+#include - #include - #include - -@@ -1181,12 +1182,13 @@ - * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. - */ - int --ah4_calccksum(m, ahdat, len, algo, sav) -+ah4_calccksum(m, ahdat, len, algo, sav, vnet) - struct mbuf *m; - caddr_t ahdat; - size_t len; - const struct ah_algorithm *algo; - struct secasvar *sav; -+ struct vnet *vnet; - { - int off; - int hdrtype; -@@ -1200,6 +1202,9 @@ - if ((m->m_flags & M_PKTHDR) == 0) - return EINVAL; - -+ if (vnet == NULL) -+ panic("ah4_calccksum: NULL vnet was passed."); -+ - ahseen = 0; - hdrtype = -1; /* dummy, it is called IPPROTO_IP */ - -@@ -1231,9 +1236,9 @@ - #endif - iphdr.ip_ttl = 0; - iphdr.ip_sum = htons(0); -- if (ip4_ah_cleartos) -+ if (vnet->ip4_ah_cleartos) - iphdr.ip_tos = 0; -- iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask); -+ iphdr.ip_off = htons(ntohs(iphdr.ip_off) & vnet->ip4_ah_offsetmask); - (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip)); - - if (hlen != sizeof(struct ip)) { -diff -urN sys/netinet6/ah_input.c sys.CORE/netinet6/ah_input.c ---- sys/netinet6/ah_input.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ah_input.c Wed Jan 31 16:02:43 2007 -@@ -87,6 +87,8 @@ - #define KEYDEBUG(lev,arg) - #endif - -+#include -+ - #include - - #include -@@ -120,19 +122,25 @@ - int off, proto; - va_list ap; - size_t stripsiz = 0; -+ struct vnet *vnet; - - va_start(ap, m); - off = va_arg(ap, int); - proto = va_arg(ap, int); - va_end(ap); - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ah4_input: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; -+ if (vnet == NULL) -+ panic("ah4_input: NULL vnet passed."); - #ifndef PULLDOWN_TEST - if (m->m_len < off + sizeof(struct newah)) { - m = m_pullup(m, off + sizeof(struct newah)); - if (!m) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" - "dropping the packet for simplicity\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - } -@@ -145,7 +153,7 @@ - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup;" - "dropping the packet for simplicity\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - #endif -@@ -161,11 +169,11 @@ - - if ((sav = key_allocsa(AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, -- IPPROTO_AH, spi)) == 0) { -+ IPPROTO_AH, spi, vnet)) == 0) { - ipseclog((LOG_WARNING, - "IPv4 AH input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_nosa++; -+ vnet->ipsecstat.in_nosa++; - goto fail; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, -@@ -175,7 +183,7 @@ - ipseclog((LOG_DEBUG, - "IPv4 AH input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_badspi++; -+ vnet->ipsecstat.in_badspi++; - goto fail; - } - -@@ -184,7 +192,7 @@ - ipseclog((LOG_DEBUG, "IPv4 AH input: " - "unsupported authentication algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_badspi++; -+ vnet->ipsecstat.in_badspi++; - goto fail; - } - -@@ -225,7 +233,7 @@ - "(%lu, should be at least %lu): %s\n", - (u_long)siz1, (u_long)siz, - ipsec4_logpacketstr(ip, spi))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - if ((ah->ah_len << 2) - sizoff != siz1) { -@@ -233,7 +241,7 @@ - "(%d should be %lu): %s\n", - (ah->ah_len << 2) - sizoff, (u_long)siz1, - ipsec4_logpacketstr(ip, spi))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - -@@ -242,7 +250,7 @@ - m = m_pullup(m, off + sizeof(struct ah) + sizoff + siz1); - if (!m) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - -@@ -254,7 +262,7 @@ - sizeof(struct ah) + sizoff + siz1); - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv4 AH input: can't pullup\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - #endif -@@ -267,7 +275,7 @@ - if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) - ; /* okey */ - else { -- ipsecstat.in_ahreplay++; -+ vnet->ipsecstat.in_ahreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -@@ -283,7 +291,7 @@ - if (!cksum) { - ipseclog((LOG_DEBUG, "IPv4 AH input: " - "couldn't alloc temporary region for cksum\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - -@@ -293,12 +301,12 @@ - */ - ip->ip_len = htons(ip->ip_len + hlen); - ip->ip_off = htons(ip->ip_off); -- if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { -+ if (ah4_calccksum(m, (caddr_t)cksum, siz1, algo, sav, vnet)) { - free(cksum, M_TEMP); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } -- ipsecstat.in_ahhist[sav->alg_auth]++; -+ vnet->ipsecstat.in_ahhist[sav->alg_auth]++; - /* - * flip them back. - */ -@@ -321,7 +329,7 @@ - "checksum mismatch in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); - free(cksum, M_TEMP); -- ipsecstat.in_ahauthfail++; -+ vnet->ipsecstat.in_ahauthfail++; - goto fail; - } - } -@@ -374,12 +382,12 @@ - ipseclog((LOG_DEBUG, - "IPv4 AH input: authentication succeess\n")); - #endif -- ipsecstat.in_ahauthsucc++; -+ vnet->ipsecstat.in_ahauthsucc++; - } else { - ipseclog((LOG_WARNING, - "authentication failed in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_ahauthfail++; -+ vnet->ipsecstat.in_ahauthfail++; - goto fail; - } - -@@ -388,7 +396,7 @@ - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { -- ipsecstat.in_ahreplay++; -+ vnet->ipsecstat.in_ahreplay++; - goto fail; - } - } -@@ -416,19 +424,19 @@ - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (!m) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - } - ip = mtod(m, struct ip *); - /* ECN consideration. */ -- ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); -+ ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos); - if (!key_checktunnelsanity(sav, AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { - ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " - "in IPv4 AH input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - -@@ -459,13 +467,13 @@ - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - goto fail; - } - - s = splimp(); - if (IF_QFULL(&g_ipintrq)) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - splx(s); - goto fail; - } -@@ -521,7 +529,7 @@ - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (m == NULL) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - } -@@ -536,14 +544,14 @@ - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - goto fail; - } - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && -- ipsec4_in_reject(m, NULL)) { -- ipsecstat.in_polvio++; -+ ipsec4_in_reject(m, NULL, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto fail; - } - (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); -@@ -557,7 +565,7 @@ - printf("DP ah4_input call free SA:%p\n", sav)); - key_freesav(sav); - } -- ipsecstat.in_success++; -+ vnet->ipsecstat.in_success++; - return; - - fail: -@@ -591,7 +599,12 @@ - u_int16_t nxt; - int s; - size_t stripsiz = 0; -+ struct vnet *vnet; - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ah6_input: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; -+ if (vnet == NULL) - #ifndef PULLDOWN_TEST - IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), IPPROTO_DONE); - ah = (struct ah *)(mtod(m, caddr_t) + off); -@@ -599,7 +612,7 @@ - IP6_EXTHDR_GET(ah, struct ah *, m, off, sizeof(struct newah)); - if (ah == NULL) { - ipseclog((LOG_DEBUG, "IPv6 AH input: can't pullup\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - return IPPROTO_DONE; - } - #endif -@@ -612,17 +625,17 @@ - if (ntohs(ip6->ip6_plen) == 0) { - ipseclog((LOG_ERR, "IPv6 AH input: " - "AH with IPv6 jumbogram is not supported.\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - - if ((sav = key_allocsa(AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, -- IPPROTO_AH, spi)) == 0) { -+ IPPROTO_AH, spi, vnet)) == 0) { - ipseclog((LOG_WARNING, - "IPv6 AH input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_nosa++; -+ vnet->ipsec6stat.in_nosa++; - goto fail; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, -@@ -632,7 +645,7 @@ - ipseclog((LOG_DEBUG, - "IPv6 AH input: non-mature/dying SA found for spi %u; ", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_badspi++; -+ vnet->ipsec6stat.in_badspi++; - goto fail; - } - -@@ -641,7 +654,7 @@ - ipseclog((LOG_DEBUG, "IPv6 AH input: " - "unsupported authentication algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_badspi++; -+ vnet->ipsec6stat.in_badspi++; - goto fail; - } - -@@ -665,7 +678,7 @@ - "(%lu, should be at least %lu): %s\n", - (u_long)siz1, (u_long)siz, - ipsec6_logpacketstr(ip6, spi))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - if ((ah->ah_len << 2) - sizoff != siz1) { -@@ -673,7 +686,7 @@ - "(%d should be %lu): %s\n", - (ah->ah_len << 2) - sizoff, (u_long)siz1, - ipsec6_logpacketstr(ip6, spi))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - #ifndef PULLDOWN_TEST -@@ -683,7 +696,7 @@ - sizeof(struct ah) + sizoff + siz1); - if (ah == NULL) { - ipseclog((LOG_NOTICE, "couldn't pullup gather IPv6 AH checksum part")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - m = NULL; - goto fail; - } -@@ -697,7 +710,7 @@ - if (ipsec_chkreplay(ntohl(((struct newah *)ah)->ah_seq), sav)) - ; /* okey */ - else { -- ipsec6stat.in_ahreplay++; -+ vnet->ipsec6stat.in_ahreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), -@@ -714,16 +727,16 @@ - if (!cksum) { - ipseclog((LOG_DEBUG, "IPv6 AH input: " - "couldn't alloc temporary region for cksum\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - - if (ah6_calccksum(m, (caddr_t)cksum, siz1, algo, sav)) { - free(cksum, M_TEMP); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } -- ipsec6stat.in_ahhist[sav->alg_auth]++; -+ vnet->ipsec6stat.in_ahhist[sav->alg_auth]++; - - { - caddr_t sumpos = NULL; -@@ -741,7 +754,7 @@ - "checksum mismatch in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); - free(cksum, M_TEMP); -- ipsec6stat.in_ahauthfail++; -+ vnet->ipsec6stat.in_ahauthfail++; - goto fail; - } - } -@@ -786,12 +799,12 @@ - ipseclog((LOG_DEBUG, - "IPv6 AH input: authentication succeess\n")); - #endif -- ipsec6stat.in_ahauthsucc++; -+ vnet->ipsec6stat.in_ahauthsucc++; - } else { - ipseclog((LOG_WARNING, - "authentication failed in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -- ipsec6stat.in_ahauthfail++; -+ vnet->ipsec6stat.in_ahauthfail++; - goto fail; - } - -@@ -800,7 +813,7 @@ - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newah *)ah)->ah_seq), sav)) { -- ipsec6stat.in_ahreplay++; -+ vnet->ipsec6stat.in_ahreplay++; - goto fail; - } - } -@@ -832,20 +845,20 @@ - */ - m = m_pullup(m, sizeof(*ip6)); - if (!m) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - } - ip6 = mtod(m, struct ip6_hdr *); - /* ECN consideration. */ -- ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); -+ ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); - if (!key_checktunnelsanity(sav, AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { - ipseclog((LOG_NOTICE, "ipsec tunnel address mismatch " - "in IPv6 AH input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), - ipsec_logsastr(sav))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - -@@ -861,17 +874,17 @@ - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - goto fail; - } - - s = splimp(); -- if (IF_QFULL(&ip6intrq)) { -- ipsec6stat.in_inval++; -+ if (IF_QFULL(&g_ip6intrq)) { -+ vnet->ipsec6stat.in_inval++; - splx(s); - goto fail; - } -- IF_ENQUEUE(&ip6intrq, m); -+ IF_ENQUEUE(&g_ip6intrq, m); - m = NULL; - schednetisr(NETISR_IPV6); /* can be skipped but to make sure */ - splx(s); -@@ -934,7 +947,7 @@ - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_AH, spi) != 0) { -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - goto fail; - } - } -@@ -947,7 +960,7 @@ - printf("DP ah6_input call free SA:%p\n", sav)); - key_freesav(sav); - } -- ipsec6stat.in_success++; -+ vnet->ipsec6stat.in_success++; - return nxt; - - fail: -@@ -972,6 +985,7 @@ - struct secasvar *sav; - struct ip6_hdr *ip6; - struct mbuf *m; -+ struct vnet *vnet = NULL; - struct ip6ctlparam *ip6cp = NULL; - int off; - struct sockaddr_in6 *sa6_src, *sa6_dst; -@@ -986,11 +1000,15 @@ - if (d != NULL) { - ip6cp = (struct ip6ctlparam *)d; - m = ip6cp->ip6c_m; -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ah6_ctlinput: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; - } else { - m = NULL; - ip6 = NULL; -+ off = 0; - } - - if (ip6) { -@@ -1025,7 +1043,7 @@ - sav = key_allocsa(AF_INET6, - (caddr_t)&sa6_src->sin6_addr, - (caddr_t)&sa6_dst->sin6_addr, -- IPPROTO_AH, ahp->ah_spi); -+ IPPROTO_AH, ahp->ah_spi, vnet); - if (sav) { - if (sav->state == SADB_SASTATE_MATURE || - sav->state == SADB_SASTATE_DYING) -@@ -1042,7 +1060,7 @@ - * corresponding routing entry, or - * - ignore the MTU change notification. - */ -- icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); -+ icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet); - } - - /* we normally notify single pcb here */ -diff -urN sys/netinet6/ah_output.c sys.CORE/netinet6/ah_output.c ---- sys/netinet6/ah_output.c Mon May 5 23:46:58 2003 -+++ sys.CORE/netinet6/ah_output.c Wed Jan 31 16:02:43 2007 -@@ -75,6 +75,7 @@ - #include - - #include -+#include - - #ifdef INET - static struct in_addr *ah4_finaldst __P((struct mbuf *)); -@@ -142,9 +143,10 @@ - * the function does not modify m. - */ - int --ah4_output(m, isr) -+ah4_output(m, isr, vnet) - struct mbuf *m; - struct ipsecrequest *isr; -+ struct vnet *vnet; - { - struct secasvar *sav = isr->sav; - const struct ah_algorithm *algo; -@@ -159,6 +161,8 @@ - struct in_addr *finaldst; - int error; - -+ if (vnet == NULL) -+ panic("ah4_output: NULL vnet was passed."); - /* sanity checks */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && !sav->replay) { - struct ip *ip; -@@ -169,7 +173,7 @@ - (u_int32_t)ntohl(ip->ip_src.s_addr), - (u_int32_t)ntohl(ip->ip_dst.s_addr), - (u_int32_t)ntohl(sav->spi))); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -178,7 +182,7 @@ - if (!algo) { - ipseclog((LOG_ERR, "ah4_output: unsupported algorithm: " - "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -260,7 +264,7 @@ - ipseclog((LOG_WARNING, - "replay counter overflowed. %s\n", - ipsec_logsastr(sav))); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -282,7 +286,7 @@ - ip->ip_len = htons(ntohs(ip->ip_len) + ahlen); - else { - ipseclog((LOG_ERR, "IPv4 AH output: size exceeds limit\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - return EMSGSIZE; - } -@@ -304,13 +308,13 @@ - * calcurate the checksum, based on security association - * and the algorithm specified. - */ -- error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); -+ error = ah4_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav, vnet); - if (error) { - ipseclog((LOG_ERR, - "error after ah4_calccksum, called from ah4_output")); - m_freem(m); - m = NULL; -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - return error; - } - -@@ -318,8 +322,8 @@ - ip = mtod(m, struct ip *); /* just to make sure */ - ip->ip_dst.s_addr = dst.s_addr; - } -- ipsecstat.out_success++; -- ipsecstat.out_ahhist[sav->alg_auth]++; -+ vnet->ipsecstat.out_success++; -+ vnet->ipsecstat.out_ahhist[sav->alg_auth]++; - key_sa_recordxfer(sav, m); - - return 0; -@@ -371,6 +375,11 @@ - int error = 0; - int ahlen; - struct ip6_hdr *ip6; -+ struct vnet *vnet; -+ -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ah6_output: unable to find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "ah6_output: first mbuf too short\n")); -@@ -422,7 +431,7 @@ - ipseclog((LOG_DEBUG, "ah6_output: internal error: " - "sav->replay is null: SPI=%u\n", - (u_int32_t)ntohl(sav->spi))); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -431,7 +440,7 @@ - if (!algo) { - ipseclog((LOG_ERR, "ah6_output: unsupported algorithm: " - "SPI=%u\n", (u_int32_t)ntohl(sav->spi))); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -467,7 +476,7 @@ - ipseclog((LOG_WARNING, - "replay counter overflowed. %s\n", - ipsec_logsastr(sav))); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - m_freem(m); - return EINVAL; - } -@@ -487,13 +496,13 @@ - */ - error = ah6_calccksum(m, (caddr_t)ahsumpos, plen, algo, sav); - if (error) { -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - m_freem(m); - } else { -- ipsec6stat.out_success++; -+ vnet->ipsec6stat.out_success++; - key_sa_recordxfer(sav, m); - } -- ipsec6stat.out_ahhist[sav->alg_auth]++; -+ vnet->ipsec6stat.out_ahhist[sav->alg_auth]++; - - return(error); - } -diff -urN sys/netinet6/esp.h sys.CORE/netinet6/esp.h ---- sys/netinet6/esp.h Sat Apr 27 22:40:26 2002 -+++ sys.CORE/netinet6/esp.h Wed Jan 31 16:02:43 2007 -@@ -97,7 +97,8 @@ - extern int esp_max_ivlen __P((void)); - - /* crypt routines */ --extern int esp4_output __P((struct mbuf *, struct ipsecrequest *)); -+extern int esp4_output __P((struct mbuf *, struct ipsecrequest *, -+ struct vnet *vnet)); - extern void esp4_input __P((struct mbuf *, ...)); - extern size_t esp_hdrsiz __P((struct ipsecrequest *)); - -diff -urN sys/netinet6/esp6.h sys.CORE/netinet6/esp6.h ---- sys/netinet6/esp6.h Tue Jul 3 04:01:49 2001 -+++ sys.CORE/netinet6/esp6.h Wed Jan 31 16:02:43 2007 -@@ -39,10 +39,10 @@ - - #ifdef _KERNEL - extern int esp6_output __P((struct mbuf *, u_char *, struct mbuf *, -- struct ipsecrequest *)); -+ struct ipsecrequest *, struct vnet *)); - extern int esp6_input __P((struct mbuf **, int *, int)); - --extern void esp6_ctlinput __P((int, struct sockaddr *, void *)); -+extern void esp6_ctlinput __P((int, struct sockaddr *, void *, struct vnet *)); - #endif /*_KERNEL*/ - - #endif /*_NETINET6_ESP6_H_*/ -diff -urN sys/netinet6/esp_input.c sys.CORE/netinet6/esp_input.c ---- sys/netinet6/esp_input.c Fri Nov 28 06:52:52 2003 -+++ sys.CORE/netinet6/esp_input.c Wed Jan 31 16:02:43 2007 -@@ -89,6 +89,7 @@ - #include - - #include -+#include - - #define IPLEN_FLIPPED - -@@ -123,17 +124,21 @@ - int s; - va_list ap; - int off, proto; -+ struct vnet *vnet; - - va_start(ap, m); - off = va_arg(ap, int); - proto = va_arg(ap, int); - va_end(ap); - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("esp4_input: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - /* sanity check for alignment. */ - if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { - ipseclog((LOG_ERR, "IPv4 ESP input: packet alignment problem " - "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -142,7 +147,7 @@ - if (!m) { - ipseclog((LOG_DEBUG, - "IPv4 ESP input: can't pullup in esp4_input\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - } -@@ -160,11 +165,11 @@ - - if ((sav = key_allocsa(AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst, -- IPPROTO_ESP, spi)) == 0) { -+ IPPROTO_ESP, spi, vnet)) == 0) { - ipseclog((LOG_WARNING, - "IPv4 ESP input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_nosa++; -+ vnet->ipsecstat.in_nosa++; - goto bad; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, -@@ -174,7 +179,7 @@ - ipseclog((LOG_DEBUG, - "IPv4 ESP input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_badspi++; -+ vnet->ipsecstat.in_badspi++; - goto bad; - } - algo = esp_algorithm_lookup(sav->alg_enc); -@@ -182,7 +187,7 @@ - ipseclog((LOG_DEBUG, "IPv4 ESP input: " - "unsupported encryption algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsecstat.in_badspi++; -+ vnet->ipsecstat.in_badspi++; - goto bad; - } - -@@ -191,7 +196,7 @@ - if (ivlen < 0) { - ipseclog((LOG_ERR, "inproper ivlen in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -209,7 +214,7 @@ - if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) - ; /* okey */ - else { -- ipsecstat.in_espreplay++; -+ vnet->ipsecstat.in_espreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -@@ -228,14 +233,14 @@ - goto noreplaycheck; - siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); - if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - if (AH_MAXSUMSIZE < siz) { - ipseclog((LOG_DEBUG, - "internal error: AH_MAXSUMSIZE must be larger than %lu\n", - (u_long)siz)); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -244,14 +249,14 @@ - if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { - ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_espauthfail++; -+ vnet->ipsecstat.in_espauthfail++; - goto bad; - } - - if (bcmp(sum0, sum, siz) != 0) { - ipseclog((LOG_WARNING, "auth fail in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_espauthfail++; -+ vnet->ipsecstat.in_espauthfail++; - goto bad; - } - -@@ -264,7 +269,7 @@ - ip->ip_len = htons(ntohs(ip->ip_len) - siz); - #endif - m->m_flags |= M_AUTHIPDGM; -- ipsecstat.in_espauthsucc++; -+ vnet->ipsecstat.in_espauthsucc++; - } - - /* -@@ -272,7 +277,7 @@ - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { -- ipsecstat.in_espreplay++; -+ vnet->ipsecstat.in_espreplay++; - goto bad; - } - } -@@ -294,7 +299,7 @@ - if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { - ipseclog((LOG_WARNING, - "IPv4 ESP input: packet too short\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -303,7 +308,7 @@ - if (!m) { - ipseclog((LOG_DEBUG, - "IPv4 ESP input: can't pullup in esp4_input\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - } -@@ -312,7 +317,7 @@ - * pre-compute and cache intermediate key - */ - if (esp_schedule(algo, sav) != 0) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -326,10 +331,10 @@ - m = NULL; - ipseclog((LOG_ERR, "decrypt fail in IPv4 ESP input: %s\n", - ipsec_logsastr(sav))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } -- ipsecstat.in_esphist[sav->alg_enc]++; -+ vnet->ipsecstat.in_esphist[sav->alg_enc]++; - - m->m_flags |= M_DECRYPTED; - -@@ -346,7 +351,7 @@ - ipseclog((LOG_WARNING, - "bad pad length in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - -@@ -375,36 +380,36 @@ - if (m->m_len < sizeof(*ip)) { - m = m_pullup(m, sizeof(*ip)); - if (!m) { -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - } - ip = mtod(m, struct ip *); - /* ECN consideration. */ -- ip_ecn_egress(ip4_ipsec_ecn, &tos, &ip->ip_tos); -+ ip_ecn_egress(vnet->ip4_ipsec_ecn, &tos, &ip->ip_tos); - if (!key_checktunnelsanity(sav, AF_INET, - (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst)) { - ipseclog((LOG_ERR, "ipsec tunnel address mismatch " - "in IPv4 ESP input: %s %s\n", - ipsec4_logpacketstr(ip, spi), ipsec_logsastr(sav))); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto bad; - } - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV4, 0) != 0) { -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - goto bad; - } - - s = splimp(); -- if (IF_QFULL(&ipintrq)) { -- ipsecstat.in_inval++; -+ if (IF_QFULL(&g_ipintrq)) { -+ vnet->ipsecstat.in_inval++; - splx(s); - goto bad; - } -- IF_ENQUEUE(&ipintrq, m); -+ IF_ENQUEUE(&g_ipintrq, m); - m = NULL; - schednetisr(NETISR_IP); /* can be skipped but to make sure */ - splx(s); -@@ -435,14 +440,14 @@ - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - goto bad; - } - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && -- ipsec4_in_reject(m, NULL)) { -- ipsecstat.in_polvio++; -+ ipsec4_in_reject(m, NULL, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto bad; - } - (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); -@@ -456,7 +461,7 @@ - printf("DP esp4_input call free SA:%p\n", sav)); - key_freesav(sav); - } -- ipsecstat.in_success++; -+ vnet->ipsecstat.in_success++; - return; - - bad: -@@ -478,6 +483,7 @@ - int *offp, proto; - { - struct mbuf *m = *mp; -+ struct vnet *vnet; - int off = *offp; - struct ip6_hdr *ip6; - struct esp *esp; -@@ -491,11 +497,14 @@ - size_t esplen; - int s; - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("esp6_input: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - /* sanity check for alignment. */ - if (off % 4 != 0 || m->m_pkthdr.len % 4 != 0) { - ipseclog((LOG_ERR, "IPv6 ESP input: packet alignment problem " - "(off=%d, pktlen=%d)\n", off, m->m_pkthdr.len)); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -505,7 +514,7 @@ - #else - IP6_EXTHDR_GET(esp, struct esp *, m, off, ESPMAXLEN); - if (esp == NULL) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - return IPPROTO_DONE; - } - #endif -@@ -514,7 +523,7 @@ - if (ntohs(ip6->ip6_plen) == 0) { - ipseclog((LOG_ERR, "IPv6 ESP input: " - "ESP with IPv6 jumbogram is not supported.\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -523,11 +532,11 @@ - - if ((sav = key_allocsa(AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst, -- IPPROTO_ESP, spi)) == 0) { -+ IPPROTO_ESP, spi, vnet)) == 0) { - ipseclog((LOG_WARNING, - "IPv6 ESP input: no key association found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_nosa++; -+ vnet->ipsec6stat.in_nosa++; - goto bad; - } - KEYDEBUG(KEYDEBUG_IPSEC_STAMP, -@@ -537,7 +546,7 @@ - ipseclog((LOG_DEBUG, - "IPv6 ESP input: non-mature/dying SA found for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_badspi++; -+ vnet->ipsec6stat.in_badspi++; - goto bad; - } - algo = esp_algorithm_lookup(sav->alg_enc); -@@ -545,7 +554,7 @@ - ipseclog((LOG_DEBUG, "IPv6 ESP input: " - "unsupported encryption algorithm for spi %u\n", - (u_int32_t)ntohl(spi))); -- ipsec6stat.in_badspi++; -+ vnet->ipsec6stat.in_badspi++; - goto bad; - } - -@@ -554,7 +563,7 @@ - if (ivlen < 0) { - ipseclog((LOG_ERR, "inproper ivlen in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -- ipsec6stat.in_badspi++; -+ vnet->ipsec6stat.in_badspi++; - goto bad; - } - -@@ -572,7 +581,7 @@ - if (ipsec_chkreplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) - ; /* okey */ - else { -- ipsec6stat.in_espreplay++; -+ vnet->ipsec6stat.in_espreplay++; - ipseclog((LOG_WARNING, - "replay packet in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -@@ -591,14 +600,14 @@ - goto noreplaycheck; - siz = (((*sumalgo->sumsiz)(sav) + 3) & ~(4 - 1)); - if (m->m_pkthdr.len < off + ESPMAXLEN + siz) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - if (AH_MAXSUMSIZE < siz) { - ipseclog((LOG_DEBUG, - "internal error: AH_MAXSUMSIZE must be larger than %lu\n", - (u_long)siz)); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -607,14 +616,14 @@ - if (esp_auth(m, off, m->m_pkthdr.len - off - siz, sav, sum)) { - ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -- ipsec6stat.in_espauthfail++; -+ vnet->ipsec6stat.in_espauthfail++; - goto bad; - } - - if (bcmp(sum0, sum, siz) != 0) { - ipseclog((LOG_WARNING, "auth fail in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -- ipsec6stat.in_espauthfail++; -+ vnet->ipsec6stat.in_espauthfail++; - goto bad; - } - -@@ -624,7 +633,7 @@ - ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - siz); - - m->m_flags |= M_AUTHIPDGM; -- ipsec6stat.in_espauthsucc++; -+ vnet->ipsec6stat.in_espauthsucc++; - } - - /* -@@ -632,7 +641,7 @@ - */ - if ((sav->flags & SADB_X_EXT_OLD) == 0 && sav->replay) { - if (ipsec_updatereplay(ntohl(((struct newesp *)esp)->esp_seq), sav)) { -- ipsec6stat.in_espreplay++; -+ vnet->ipsec6stat.in_espreplay++; - goto bad; - } - } -@@ -654,7 +663,7 @@ - if (m->m_pkthdr.len < off + esplen + ivlen + sizeof(esptail)) { - ipseclog((LOG_WARNING, - "IPv6 ESP input: packet too short\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -663,7 +672,7 @@ - #else - IP6_EXTHDR_GET(esp, struct esp *, m, off, esplen + ivlen); - if (esp == NULL) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - m = NULL; - goto bad; - } -@@ -674,7 +683,7 @@ - * pre-compute and cache intermediate key - */ - if (esp_schedule(algo, sav) != 0) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -688,10 +697,10 @@ - m = NULL; - ipseclog((LOG_ERR, "decrypt fail in IPv6 ESP input: %s\n", - ipsec_logsastr(sav))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } -- ipsec6stat.in_esphist[sav->alg_enc]++; -+ vnet->ipsec6stat.in_esphist[sav->alg_enc]++; - - m->m_flags |= M_DECRYPTED; - -@@ -708,7 +717,7 @@ - ipseclog((LOG_WARNING, - "bad pad length in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), ipsec_logsastr(sav))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - -@@ -740,37 +749,37 @@ - #endif - m = m_pullup(m, sizeof(*ip6)); - if (!m) { -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - } - ip6 = mtod(m, struct ip6_hdr *); - /* ECN consideration. */ -- ip6_ecn_egress(ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); -+ ip6_ecn_egress(vnet->ip6_ipsec_ecn, &flowinfo, &ip6->ip6_flow); - if (!key_checktunnelsanity(sav, AF_INET6, - (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst)) { - ipseclog((LOG_ERR, "ipsec tunnel address mismatch " - "in IPv6 ESP input: %s %s\n", - ipsec6_logpacketstr(ip6, spi), - ipsec_logsastr(sav))); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto bad; - } - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0 || - ipsec_addhist(m, IPPROTO_IPV6, 0) != 0) { -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - goto bad; - } - - s = splimp(); -- if (IF_QFULL(&ip6intrq)) { -- ipsec6stat.in_inval++; -+ if (IF_QFULL(&g_ip6intrq)) { -+ vnet->ipsec6stat.in_inval++; - splx(s); - goto bad; - } -- IF_ENQUEUE(&ip6intrq, m); -+ IF_ENQUEUE(&g_ip6intrq, m); - m = NULL; - schednetisr(NETISR_IPV6); /* can be skipped but to make sure */ - splx(s); -@@ -864,7 +873,7 @@ - - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_ESP, spi) != 0) { -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - goto bad; - } - } -@@ -877,7 +886,7 @@ - printf("DP esp6_input call free SA:%p\n", sav)); - key_freesav(sav); - } -- ipsec6stat.in_success++; -+ vnet->ipsec6stat.in_success++; - return nxt; - - bad: -@@ -892,10 +901,11 @@ - } - - void --esp6_ctlinput(cmd, sa, d) -+esp6_ctlinput(cmd, sa, d, vnet) - int cmd; - struct sockaddr *sa; - void *d; -+ struct vnet *vnet; - { - const struct newesp *espp; - struct newesp esp; -@@ -906,6 +916,8 @@ - int off; - struct sockaddr_in6 *sa6_src, *sa6_dst; - -+ if (vnet == NULL) -+ panic("esp6_ctlinput: NULL vnet was passed."); - if (sa->sa_family != AF_INET6 || - sa->sa_len != sizeof(struct sockaddr_in6)) - return; -@@ -921,6 +933,7 @@ - } else { - m = NULL; - ip6 = NULL; -+ off = 0; - } - - if (ip6) { -@@ -939,7 +952,7 @@ - */ - bzero(&ip6cp1, sizeof(ip6cp1)); - ip6cp1.ip6c_src = ip6cp->ip6c_src; -- pfctlinput2(cmd, sa, (void *)&ip6cp1); -+ pfctlinput2(cmd, sa, (void *)&ip6cp1, vnet); - - /* - * Then go to special cases that need ESP header information. -@@ -973,7 +986,7 @@ - sav = key_allocsa(AF_INET6, - (caddr_t)&sa6_src->sin6_addr, - (caddr_t)&sa6_dst->sin6_addr, -- IPPROTO_ESP, espp->esp_spi); -+ IPPROTO_ESP, espp->esp_spi, vnet); - if (sav) { - if (sav->state == SADB_SASTATE_MATURE || - sav->state == SADB_SASTATE_DYING) -@@ -990,7 +1003,7 @@ - * corresponding routing entry, or - * - ignore the MTU change notification. - */ -- icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); -+ icmp6_mtudisc_update((struct ip6ctlparam *)d, valid, vnet); - } - } else { - /* we normally notify any pcb here */ -diff -urN sys/netinet6/esp_output.c sys.CORE/netinet6/esp_output.c ---- sys/netinet6/esp_output.c Fri Nov 28 06:54:26 2003 -+++ sys.CORE/netinet6/esp_output.c Wed Jan 31 16:02:43 2007 -@@ -78,9 +78,10 @@ - #include - - #include -+#include - - static int esp_output __P((struct mbuf *, u_char *, struct mbuf *, -- struct ipsecrequest *, int)); -+ struct ipsecrequest *, int, struct vnet *)); - - /* - * compute ESP header size. -@@ -174,12 +175,13 @@ - * <-----------------> espoff - */ - static int --esp_output(m, nexthdrp, md, isr, af) -+esp_output(m, nexthdrp, md, isr, af, vnet) - struct mbuf *m; - u_char *nexthdrp; - struct mbuf *md; - struct ipsecrequest *isr; - int af; -+ struct vnet *vnet; - { - struct mbuf *n; - struct mbuf *mprev; -@@ -197,17 +199,19 @@ - int error = 0; - struct ipsecstat *stat; - -+ if (vnet == NULL) -+ panic("esp6_output: NULL vnet was passed."); - switch (af) { - #ifdef INET - case AF_INET: - afnumber = 4; -- stat = &ipsecstat; -+ stat = &vnet->ipsecstat; - break; - #endif - #ifdef INET6 - case AF_INET6: - afnumber = 6; -- stat = &ipsec6stat; -+ stat = &vnet->ipsec6stat; - break; - #endif - default: -@@ -229,7 +233,7 @@ - (u_int32_t)ntohl(ip->ip_src.s_addr), - (u_int32_t)ntohl(ip->ip_dst.s_addr), - (u_int32_t)ntohl(sav->spi))); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - break; - } - #endif /* INET */ -@@ -238,7 +242,7 @@ - ipseclog((LOG_DEBUG, "esp6_output: internal error: " - "sav->replay is null: SPI=%u\n", - (u_int32_t)ntohl(sav->spi))); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - break; - #endif /* INET6 */ - default: -@@ -368,7 +372,7 @@ - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; -@@ -435,12 +439,12 @@ - switch (af) { - #ifdef INET - case AF_INET: -- randpadmax = ip4_esp_randpad; -+ randpadmax = vnet->ip4_esp_randpad; - break; - #endif - #ifdef INET6 - case AF_INET6: -- randpadmax = ip6_esp_randpad; -+ randpadmax = vnet->ip6_esp_randpad; - break; - #endif - default: -@@ -539,7 +543,7 @@ - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; -@@ -651,7 +655,7 @@ - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; -@@ -686,9 +690,10 @@ - - #ifdef INET - int --esp4_output(m, isr) -+esp4_output(m, isr, vnet) - struct mbuf *m; - struct ipsecrequest *isr; -+ struct vnet *vnet; - { - struct ip *ip; - if (m->m_len < sizeof(struct ip)) { -@@ -698,23 +703,24 @@ - } - ip = mtod(m, struct ip *); - /* XXX assumes that m->m_next points to payload */ -- return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET); -+ return esp_output(m, &ip->ip_p, m->m_next, isr, AF_INET, vnet); - } - #endif /* INET */ - - #ifdef INET6 - int --esp6_output(m, nexthdrp, md, isr) -+esp6_output(m, nexthdrp, md, isr, vnet) - struct mbuf *m; - u_char *nexthdrp; - struct mbuf *md; - struct ipsecrequest *isr; -+ struct vnet *vnet; - { - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "esp6_output: first mbuf too short\n")); - m_freem(m); - return 0; - } -- return esp_output(m, nexthdrp, md, isr, AF_INET6); -+ return esp_output(m, nexthdrp, md, isr, AF_INET6, vnet); - } - #endif /* INET6 */ -diff -urN sys/netinet6/icmp6.c sys.CORE/netinet6/icmp6.c ---- sys/netinet6/icmp6.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/icmp6.c Wed Jan 31 16:02:43 2007 -@@ -2416,7 +2416,7 @@ - bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr)); - pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst, vnet); - #ifdef IPSEC -- key_sa_routechange((struct sockaddr *)&sdst); -+ key_sa_routechange((struct sockaddr *)&sdst, vnet); - #endif - } - -diff -urN sys/netinet6/in6_ifattach.c sys.CORE/netinet6/in6_ifattach.c ---- sys/netinet6/in6_ifattach.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/in6_ifattach.c Wed Jan 31 16:02:43 2007 -@@ -1032,6 +1032,8 @@ - - bzero(nullbuf, sizeof(nullbuf)); - for (i = 1; i < vnet->if_index + 1; i++) { -+ if (vnet->nd_ifinfo == NULL) /* nd6 not initialized yet! */ -+ continue; - ndi = &vnet->nd_ifinfo[i]; - if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) { - /* -diff -urN sys/netinet6/in6_proto.c sys.CORE/netinet6/in6_proto.c ---- sys/netinet6/in6_proto.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/in6_proto.c Wed Jan 31 16:02:43 2007 -@@ -209,7 +209,7 @@ - #ifdef IPSEC - { SOCK_RAW, &inet6domain, IPPROTO_AH, PR_ATOMIC|PR_ADDR, - ah6_input, 0, 0, 0, -- 0, -+ 0, 0, - 0, 0, 0, 0, - &nousrreqs, - }, -@@ -218,14 +218,14 @@ - esp6_input, 0, - esp6_ctlinput, - 0, -- 0, -+ 0, 0, - 0, 0, 0, 0, - &nousrreqs, - }, - #endif - { SOCK_RAW, &inet6domain, IPPROTO_IPCOMP, PR_ATOMIC|PR_ADDR, - ipcomp6_input, 0, 0, 0, -- 0, -+ 0, 0, - 0, 0, 0, 0, - &nousrreqs, - }, -diff -urN sys/netinet6/ip6_forward.c sys.CORE/netinet6/ip6_forward.c ---- sys/netinet6/ip6_forward.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ip6_forward.c Wed Jan 31 16:02:43 2007 -@@ -122,9 +122,9 @@ - * Don't increment ip6s_cantforward because this is the check - * before forwarding packet actually. - */ -- if (ipsec6_in_reject(m, NULL)) { -+ if (ipsec6_in_reject(m, NULL, vnet)) { - #if !defined(FAST_IPSEC) -- ipsec6stat.in_polvio++; -+ vnet->ipsec6stat.in_polvio++; - #endif - m_freem(m); - return; -@@ -178,9 +178,9 @@ - #ifdef IPSEC - /* get a security policy for this packet */ - sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING, -- &error); -+ &error, vnet); - if (sp == NULL) { -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - vnet->ip6stat.ip6s_cantforward++; - if (mcopy) { - #if 0 -@@ -201,7 +201,7 @@ - /* - * This packet is just discarded. - */ -- ipsec6stat.out_polvio++; -+ vnet->ipsec6stat.out_polvio++; - vnet->ip6stat.ip6s_cantforward++; - key_freesp(sp); - if (mcopy) { -@@ -263,7 +263,7 @@ - state.ro = NULL; /* update at ipsec6_output_tunnel() */ - state.dst = NULL; /* update at ipsec6_output_tunnel() */ - -- error = ipsec6_output_tunnel(&state, sp, 0); -+ error = ipsec6_output_tunnel(&state, sp, 0, vnet); - - m = state.m; - key_freesp(sp); -@@ -401,10 +401,10 @@ - * encapsulated packet as "rt->rt_ifp". - */ - sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND, -- IP_FORWARDING, &ipsecerror); -+ IP_FORWARDING, &ipsecerror, vnet); - if (sp) { - ipsechdrsiz = ipsec6_hdrsiz(mcopy, -- IPSEC_DIR_OUTBOUND, NULL); -+ IPSEC_DIR_OUTBOUND, NULL, vnet); - if (ipsechdrsiz < mtu) - mtu -= ipsechdrsiz; - } -diff -urN sys/netinet6/ip6_input.c sys.CORE/netinet6/ip6_input.c ---- sys/netinet6/ip6_input.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ip6_input.c Wed Jan 31 16:02:43 2007 -@@ -928,8 +928,8 @@ - * code - like udp/tcp/raw ip. - */ - if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && -- ipsec6_in_reject(m, NULL)) { -- ipsec6stat.in_polvio++; -+ ipsec6_in_reject(m, NULL, vnet)) { -+ vnet->ipsec6stat.in_polvio++; - goto bad; - } - #endif -diff -urN sys/netinet6/ip6_output.c sys.CORE/netinet6/ip6_output.c ---- sys/netinet6/ip6_output.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ip6_output.c Wed Jan 31 16:02:43 2007 -@@ -193,6 +193,8 @@ - ip6 = mtod(m, struct ip6_hdr *); - #endif /* FAST_IPSEC */ - -+ if (vnet == NULL) -+ panic("ip6_output: NULL vnet was passed."); - #define MAKE_EXTHDR(hp, mp) \ - do { \ - if (hp) { \ -@@ -221,12 +223,12 @@ - #ifdef IPSEC - /* get a security policy for this packet */ - if (so == NULL) -- sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error); -+ sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error, vnet); - else - sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error); - - if (sp == NULL) { -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - goto freehdrs; - } - -@@ -238,7 +240,7 @@ - /* - * This packet is just discarded. - */ -- ipsec6stat.out_polvio++; -+ vnet->ipsec6stat.out_polvio++; - goto freehdrs; - - case IPSEC_POLICY_BYPASS: -@@ -250,7 +252,7 @@ - case IPSEC_POLICY_IPSEC: - if (sp->req == NULL) { - /* acquire a policy */ -- error = key_spdacquire(sp); -+ error = key_spdacquire(sp, vnet); - goto freehdrs; - } - needipsec = 1; -@@ -436,7 +438,7 @@ - bzero(&state, sizeof(state)); - state.m = m; - error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags, -- &needipsectun); -+ &needipsectun, vnet); - m = state.m; - if (error) { - /* mbuf is already reclaimed in ipsec6_output_trans. */ -@@ -562,7 +564,7 @@ - state.ro = (struct route *)ro; - state.dst = (struct sockaddr *)dst; - -- error = ipsec6_output_tunnel(&state, sp, flags); -+ error = ipsec6_output_tunnel(&state, sp, flags, vnet); - - m = state.m; - ro = (struct route_in6 *)state.ro; -@@ -1337,6 +1339,8 @@ - int alwaysfrag = 0; - int error = 0; - -+ if (vnet == NULL) -+ panic("ip6_getpmtu: NULL vnet was passed."); - if (ro_pmtu != ro) { - /* The first hop and the final destination may differ. */ - struct sockaddr_in6 *sa6_dst = -@@ -1416,6 +1420,8 @@ - int optlen; - struct proc *p; - -+ if (vnet == NULL) -+ panic("ip6_ctloutput: NULL vnet from socket."); - if (sopt) { - level = sopt->sopt_level; - op = sopt->sopt_dir; -@@ -1853,6 +1859,8 @@ - struct proc *p = sopt->sopt_p; - int priv = 0; - -+ if (vnet == NULL) -+ panic("ip6_pcbopts: NULL vnet from socket."); - /* turn off any old options. */ - if (opt) { - #ifdef DIAGNOSTIC -@@ -2042,6 +2050,8 @@ - struct in6_multi_mship *imm; - struct proc *p = curproc; /* XXX */ - -+ if (vnet == NULL) -+ panic("ip6_setmoptions: NULL vnet passed."); - if (im6o == NULL) { - /* - * No multicast option buffer attached to the pcb; -@@ -2326,6 +2336,8 @@ - - *mp = m_get(M_WAIT, MT_HEADER); /* XXX */ - -+ if (vnet == NULL) -+ panic("ip6_getmoptions: NULL vnet was passed."); - switch (optname) { - - case IPV6_MULTICAST_IF: -diff -urN sys/netinet6/ipcomp_input.c sys.CORE/netinet6/ipcomp_input.c ---- sys/netinet6/ipcomp_input.c Sat Apr 27 22:40:27 2002 -+++ sys.CORE/netinet6/ipcomp_input.c Wed Jan 31 16:02:43 2007 -@@ -47,6 +47,7 @@ - #include - #include - -+/*#include */ - #include - #include - #include -@@ -79,6 +80,7 @@ - #include - - #include -+#include - - #define IPLEN_FLIPPED - -@@ -106,6 +108,7 @@ - size_t newlen, olen; - struct secasvar *sav = NULL; - int off, proto; -+ struct vnet *vnet; - va_list ap; - - va_start(ap, m); -@@ -113,10 +116,14 @@ - proto = va_arg(ap, int); - va_end(ap); - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipcomp_input: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; -+ - if (m->m_pkthdr.len < off + sizeof(struct ipcomp)) { - ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " - "(packet too short)\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - -@@ -125,7 +132,7 @@ - m = NULL; /* already freed */ - ipseclog((LOG_DEBUG, "IPv4 IPComp input: assumption failed " - "(pulldown failure)\n")); -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - ipcomp = mtod(md, struct ipcomp *); -@@ -141,7 +148,7 @@ - - if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { - sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, -- (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi)); -+ (caddr_t)&ip->ip_dst, IPPROTO_IPCOMP, htonl(cpi), vnet); - if (sav != NULL - && (sav->state == SADB_SASTATE_MATURE - || sav->state == SADB_SASTATE_DYING)) { -@@ -153,7 +160,7 @@ - if (!algo) { - ipseclog((LOG_WARNING, "IPv4 IPComp input: unknown cpi %u\n", - cpi)); -- ipsecstat.in_nosa++; -+ vnet->ipsecstat.in_nosa++; - goto fail; - } - -@@ -173,13 +180,13 @@ - error = (*algo->decompress)(m, m->m_next, &newlen); - if (error != 0) { - if (error == EINVAL) -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - else if (error == ENOBUFS) -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - m = NULL; - goto fail; - } -- ipsecstat.in_comphist[cpi]++; -+ vnet->ipsecstat.in_comphist[cpi]++; - - /* - * returning decompressed packet onto icmp is meaningless. -@@ -204,7 +211,7 @@ - len -= olen; - if (len & ~0xffff) { - /* packet too big after decompress */ -- ipsecstat.in_inval++; -+ vnet->ipsecstat.in_inval++; - goto fail; - } - #ifdef IPLEN_FLIPPED -@@ -218,7 +225,7 @@ - if (sav) { - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { -- ipsecstat.in_nomem++; -+ vnet->ipsecstat.in_nomem++; - goto fail; - } - key_freesav(sav); -@@ -227,8 +234,8 @@ - - if (nxt != IPPROTO_DONE) { - if ((inetsw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && -- ipsec4_in_reject(m, NULL)) { -- ipsecstat.in_polvio++; -+ ipsec4_in_reject(m, NULL, vnet)) { -+ vnet->ipsecstat.in_polvio++; - goto fail; - } - (*inetsw[ip_protox[nxt]].pr_input)(m, off, nxt); -@@ -236,7 +243,7 @@ - m_freem(m); - m = NULL; - -- ipsecstat.in_success++; -+ vnet->ipsecstat.in_success++; - return; - - fail: -@@ -265,16 +272,20 @@ - size_t newlen; - struct secasvar *sav = NULL; - char *prvnxtp; -+ struct vnet *vnet = NULL; - - m = *mp; - off = *offp; - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipcomp6_input: unable to find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - md = m_pulldown(m, off, sizeof(*ipcomp), NULL); - if (!m) { - m = NULL; /* already freed */ - ipseclog((LOG_DEBUG, "IPv6 IPComp input: assumption failed " - "(pulldown failure)\n")); -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - goto fail; - } - ipcomp = mtod(md, struct ipcomp *); -@@ -285,7 +296,8 @@ - - if (cpi >= IPCOMP_CPI_NEGOTIATE_MIN) { - sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, -- (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi)); -+ (caddr_t)&ip6->ip6_dst, IPPROTO_IPCOMP, htonl(cpi), -+ vnet); - if (sav != NULL - && (sav->state == SADB_SASTATE_MATURE - || sav->state == SADB_SASTATE_DYING)) { -@@ -297,7 +309,7 @@ - if (!algo) { - ipseclog((LOG_WARNING, "IPv6 IPComp input: unknown cpi %u; " - "dropping the packet for simplicity\n", cpi)); -- ipsec6stat.in_nosa++; -+ vnet->ipsec6stat.in_nosa++; - goto fail; - } - -@@ -311,13 +323,13 @@ - error = (*algo->decompress)(m, md, &newlen); - if (error != 0) { - if (error == EINVAL) -- ipsec6stat.in_inval++; -+ vnet->ipsec6stat.in_inval++; - else if (error == ENOBUFS) -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - m = NULL; - goto fail; - } -- ipsec6stat.in_comphist[cpi]++; -+ vnet->ipsec6stat.in_comphist[cpi]++; - m->m_pkthdr.len = off + newlen; - - /* -@@ -338,7 +350,7 @@ - if (sav) { - key_sa_recordxfer(sav, m); - if (ipsec_addhist(m, IPPROTO_IPCOMP, (u_int32_t)cpi) != 0) { -- ipsec6stat.in_nomem++; -+ vnet->ipsec6stat.in_nomem++; - goto fail; - } - key_freesav(sav); -@@ -346,7 +358,7 @@ - } - *offp = off; - *mp = m; -- ipsec6stat.in_success++; -+ vnet->ipsec6stat.in_success++; - return nxt; - - fail: -diff -urN sys/netinet6/ipcomp_output.c sys.CORE/netinet6/ipcomp_output.c ---- sys/netinet6/ipcomp_output.c Tue Apr 29 01:33:50 2003 -+++ sys.CORE/netinet6/ipcomp_output.c Wed Jan 31 16:02:43 2007 -@@ -80,6 +80,7 @@ - #include - - #include -+#include - - static int ipcomp_output __P((struct mbuf *, u_char *, struct mbuf *, - struct ipsecrequest *, int)); -@@ -123,18 +124,23 @@ - int afnumber; - int error = 0; - struct ipsecstat *stat; -+ struct vnet *vnet; -+ -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipcomp_output: unable to get vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - - switch (af) { - #ifdef INET - case AF_INET: - afnumber = 4; -- stat = &ipsecstat; -+ stat = &vnet->ipsecstat; - break; - #endif - #ifdef INET6 - case AF_INET6: - afnumber = 6; -- stat = &ipsec6stat; -+ stat = &vnet->ipsec6stat; - break; - #endif - default: -@@ -309,7 +315,7 @@ - else { - ipseclog((LOG_ERR, - "IPv4 ESP output: size exceeds limit\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - error = EMSGSIZE; - goto fail; -@@ -353,9 +359,14 @@ - struct ipsecrequest *isr; - { - struct ip *ip; -+ struct vnet *vnet; -+ -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipcomp4_output: unable to get vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - if (m->m_len < sizeof(struct ip)) { - ipseclog((LOG_DEBUG, "ipcomp4_output: first mbuf too short\n")); -- ipsecstat.out_inval++; -+ vnet->ipsecstat.out_inval++; - m_freem(m); - return 0; - } -@@ -373,9 +384,13 @@ - struct mbuf *md; - struct ipsecrequest *isr; - { -+ struct vnet *vnet; -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipcomp6_output: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - if (m->m_len < sizeof(struct ip6_hdr)) { - ipseclog((LOG_DEBUG, "ipcomp6_output: first mbuf too short\n")); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - m_freem(m); - return 0; - } -diff -urN sys/netinet6/ipsec.c sys.CORE/netinet6/ipsec.c ---- sys/netinet6/ipsec.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ipsec.c Wed Jan 31 16:02:43 2007 -@@ -112,6 +112,7 @@ - int ipsec_debug = 0; - #endif - -+#ifdef MOVED_TO_VNET - struct ipsecstat ipsecstat; - int ip4_ah_cleartos = 1; - int ip4_ah_offsetmask = 0; /* maybe IP_DF? */ -@@ -123,6 +124,7 @@ - struct secpolicy ip4_def_policy; - int ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ - int ip4_esp_randpad = -1; -+#endif - - #ifdef SYSCTL_DECL - SYSCTL_DECL(_net_inet_ipsec); -@@ -132,32 +134,33 @@ - #endif - - /* net.inet.ipsec */ --SYSCTL_STRUCT(_net_inet_ipsec, IPSECCTL_STATS, -- stats, CTLFLAG_RD, &ipsecstat, ipsecstat, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, -- def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, -- CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -- CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, -- CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -- CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, -- ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, -- ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, -- dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, -- ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); -+SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, IPSECCTL_STATS, -+ stats, CTLFLAG_RD, v_ipsecstat, ipsecstat, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY, -+ def_policy, CTLFLAG_RW, &((struct secpolicy*)v_ip4_def_policy)->policy, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, -+ esp_trans_deflev, CTLFLAG_RW, v_ip4_esp_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -+ CTLFLAG_RW, v_ip4_esp_net_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, -+ CTLFLAG_RW, v_ip4_ah_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -+ CTLFLAG_RW, v_ip4_ah_net_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS, -+ ah_cleartos, CTLFLAG_RW, v_ip4_ah_cleartos, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, -+ ah_offsetmask, CTLFLAG_RW, v_ip4_ah_offsetmask, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT, -+ dfbit, CTLFLAG_RW, v_ip4_ipsec_dfbit, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN, -+ ecn, CTLFLAG_RW, v_ip4_ipsec_ecn, 0, ""); - SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, -- esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD, -+ esp_randpad, CTLFLAG_RW, v_ip4_esp_randpad, 0, ""); - - #ifdef INET6 -+#ifdef MOVED_TO_VNET - struct ipsecstat ipsec6stat; - int ip6_esp_trans_deflev = IPSEC_LEVEL_USE; - int ip6_esp_net_deflev = IPSEC_LEVEL_USE; -@@ -166,26 +169,27 @@ - struct secpolicy ip6_def_policy; - int ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ - int ip6_esp_randpad = -1; -+#endif /* MOVED_TO_VNET */ - - /* net.inet6.ipsec6 */ --SYSCTL_STRUCT(_net_inet6_ipsec6, IPSECCTL_STATS, -- stats, CTLFLAG_RD, &ipsec6stat, ipsecstat, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, -- def_policy, CTLFLAG_RW, &ip6_def_policy.policy, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, -- CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -- CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, -- CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -- CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, -- ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); -+SYSCTL_V_STRUCT(V_NET, _net_inet6_ipsec6, IPSECCTL_STATS, -+ stats, CTLFLAG_RD, v_ipsec6stat, ipsecstat, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY, -+ def_policy, CTLFLAG_RW, &((struct secpolicy *)v_ip6_def_policy)->policy, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, -+ esp_trans_deflev, CTLFLAG_RW, v_ip6_esp_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -+ CTLFLAG_RW, v_ip6_esp_net_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, -+ ah_trans_deflev, CTLFLAG_RW, v_ip6_ah_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -+ CTLFLAG_RW, v_ip6_ah_net_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN, -+ ecn, CTLFLAG_RW, v_ip6_ipsec_ecn, 0, ""); - SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, -- esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, -+ esp_randpad, CTLFLAG_RW, v_ip6_esp_randpad, 0, ""); - #endif /* INET6 */ - - static int ipsec_setspidx_mbuf -@@ -217,10 +221,10 @@ - static struct mbuf *ipsec6_splithdr __P((struct mbuf *)); - #endif - #ifdef INET --static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *)); -+static int ipsec4_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *)); - #endif - #ifdef INET6 --static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *)); -+static int ipsec6_encapsulate __P((struct mbuf *, struct secasvar *, struct vnet *)); - #endif - - /* -@@ -245,11 +249,15 @@ - struct inpcbpolicy *pcbsp = NULL; - struct secpolicy *currsp = NULL; /* policy on socket */ - struct secpolicy *kernsp = NULL; /* policy on kernel */ -+ struct vnet *vnet; - - /* sanity check */ - if (m == NULL || so == NULL || error == NULL) - panic("ipsec4_getpolicybysock: NULL pointer was passed."); -- -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("ipsec4_getpolicybysock: NULL vnet pointer."); -+ - switch (so->so_proto->pr_domain->dom_family) { - case AF_INET: - /* set spidx in pcb */ -@@ -306,7 +314,7 @@ - - case IPSEC_POLICY_ENTRUST: - /* look for a policy in SPD */ -- kernsp = key_allocsp(&currsp->spidx, dir); -+ kernsp = key_allocsp(&currsp->spidx, dir, vnet); - - /* SP found */ - if (kernsp != NULL) { -@@ -318,16 +326,16 @@ - } - - /* no SP found */ -- if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip4_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", -- ip4_def_policy.policy, IPSEC_POLICY_NONE)); -- ip4_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE)); -+ vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip4_def_policy.refcnt++; -+ vnet->ip4_def_policy.refcnt++; - *error = 0; -- return &ip4_def_policy; -+ return &vnet->ip4_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; -@@ -345,7 +353,7 @@ - - /* when non-privilieged socket */ - /* look for a policy in SPD */ -- kernsp = key_allocsp(&currsp->spidx, dir); -+ kernsp = key_allocsp(&currsp->spidx, dir, vnet); - - /* SP found */ - if (kernsp != NULL) { -@@ -366,16 +374,16 @@ - return NULL; - - case IPSEC_POLICY_ENTRUST: -- if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip4_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", -- ip4_def_policy.policy, IPSEC_POLICY_NONE)); -- ip4_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip4_def_policy.policy, IPSEC_POLICY_NONE)); -+ vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip4_def_policy.refcnt++; -+ vnet->ip4_def_policy.refcnt++; - *error = 0; -- return &ip4_def_policy; -+ return &vnet->ip4_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; -@@ -402,17 +410,20 @@ - * others : error occured. - */ - struct secpolicy * --ipsec4_getpolicybyaddr(m, dir, flag, error) -+ipsec4_getpolicybyaddr(m, dir, flag, error, vnet) - struct mbuf *m; - u_int dir; - int flag; - int *error; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - - /* sanity check */ - if (m == NULL || error == NULL) - panic("ipsec4_getpolicybyaddr: NULL pointer was passed."); -+ if (vnet == NULL) -+ panic("ipsec4_getpolicybyaddr: NULL vnet pointer was passed."); - - { - struct secpolicyindex spidx; -@@ -426,7 +437,7 @@ - if (*error != 0) - return NULL; - -- sp = key_allocsp(&spidx, dir); -+ sp = key_allocsp(&spidx, dir, vnet); - } - - /* SP found */ -@@ -439,16 +450,16 @@ - } - - /* no SP found */ -- if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip4_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip4_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip4_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n", -- ip4_def_policy.policy, -+ vnet->ip4_def_policy.policy, - IPSEC_POLICY_NONE)); -- ip4_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip4_def_policy.refcnt++; -+ vnet->ip4_def_policy.refcnt++; - *error = 0; -- return &ip4_def_policy; -+ return &vnet->ip4_def_policy; - } - - #ifdef INET6 -@@ -472,10 +483,15 @@ - struct inpcbpolicy *pcbsp = NULL; - struct secpolicy *currsp = NULL; /* policy on socket */ - struct secpolicy *kernsp = NULL; /* policy on kernel */ -+ struct vnet *vnet; - - /* sanity check */ - if (m == NULL || so == NULL || error == NULL) - panic("ipsec6_getpolicybysock: NULL pointer was passed."); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("ipsec6_getpolicybysock: NULL vnet pointer was passed."); -+ - - #ifdef DIAGNOSTIC - if (so->so_proto->pr_domain->dom_family != AF_INET6) -@@ -516,7 +532,7 @@ - - case IPSEC_POLICY_ENTRUST: - /* look for a policy in SPD */ -- kernsp = key_allocsp(&currsp->spidx, dir); -+ kernsp = key_allocsp(&currsp->spidx, dir, vnet); - - /* SP found */ - if (kernsp != NULL) { -@@ -528,16 +544,16 @@ - } - - /* no SP found */ -- if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip6_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", -- ip6_def_policy.policy, IPSEC_POLICY_NONE)); -- ip6_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); -+ vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip6_def_policy.refcnt++; -+ vnet->ip6_def_policy.refcnt++; - *error = 0; -- return &ip6_def_policy; -+ return &vnet->ip6_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; -@@ -555,7 +571,7 @@ - - /* when non-privilieged socket */ - /* look for a policy in SPD */ -- kernsp = key_allocsp(&currsp->spidx, dir); -+ kernsp = key_allocsp(&currsp->spidx, dir, vnet); - - /* SP found */ - if (kernsp != NULL) { -@@ -576,16 +592,16 @@ - return NULL; - - case IPSEC_POLICY_ENTRUST: -- if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip6_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, - "fixed system default policy: %d->%d\n", -- ip6_def_policy.policy, IPSEC_POLICY_NONE)); -- ip6_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); -+ vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip6_def_policy.refcnt++; -+ vnet->ip6_def_policy.refcnt++; - *error = 0; -- return &ip6_def_policy; -+ return &vnet->ip6_def_policy; - - case IPSEC_POLICY_IPSEC: - currsp->refcnt++; -@@ -619,17 +635,20 @@ - #endif - - struct secpolicy * --ipsec6_getpolicybyaddr(m, dir, flag, error) -+ipsec6_getpolicybyaddr(m, dir, flag, error, vnet) - struct mbuf *m; - u_int dir; - int flag; - int *error; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - - /* sanity check */ - if (m == NULL || error == NULL) - panic("ipsec6_getpolicybyaddr: NULL pointer was passed."); -+ if (vnet == NULL) -+ panic("ipsec6_getpolicybyaddr: NULL vnet pointer was passed."); - - { - struct secpolicyindex spidx; -@@ -643,7 +662,7 @@ - if (*error != 0) - return NULL; - -- sp = key_allocsp(&spidx, dir); -+ sp = key_allocsp(&spidx, dir, vnet); - } - - /* SP found */ -@@ -656,15 +675,15 @@ - } - - /* no SP found */ -- if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD -- && ip6_def_policy.policy != IPSEC_POLICY_NONE) { -+ if (vnet->ip6_def_policy.policy != IPSEC_POLICY_DISCARD -+ && vnet->ip6_def_policy.policy != IPSEC_POLICY_NONE) { - ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", -- ip6_def_policy.policy, IPSEC_POLICY_NONE)); -- ip6_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip6_def_policy.policy, IPSEC_POLICY_NONE)); -+ vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; - } -- ip6_def_policy.refcnt++; -+ vnet->ip6_def_policy.refcnt++; - *error = 0; -- return &ip6_def_policy; -+ return &vnet->ip6_def_policy; - } - #endif /* INET6 */ - -@@ -1505,8 +1524,9 @@ - * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned. - */ - u_int --ipsec_get_reqlevel(isr) -+ipsec_get_reqlevel(isr, vnet) - struct ipsecrequest *isr; -+ struct vnet *vnet; - { - u_int level = 0; - u_int esp_trans_deflev, esp_net_deflev, ah_trans_deflev, ah_net_deflev; -@@ -1514,6 +1534,8 @@ - /* sanity check */ - if (isr == NULL || isr->sp == NULL) - panic("ipsec_get_reqlevel: NULL pointer is passed."); -+ if (vnet == NULL) -+ panic("ipsec_get_reqlevel: NULL vnet is passed."); - if (((struct sockaddr *)&isr->sp->spidx.src)->sa_family - != ((struct sockaddr *)&isr->sp->spidx.dst)->sa_family) - panic("ipsec_get_reqlevel: family mismatched."); -@@ -1534,18 +1556,18 @@ - switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) { - #ifdef INET - case AF_INET: -- esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev); -- esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev); -- ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev); -- ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev); -+ esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_trans_deflev); -+ esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_esp_net_deflev); -+ ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_trans_deflev); -+ ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip4_ah_net_deflev); - break; - #endif - #ifdef INET6 - case AF_INET6: -- esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev); -- esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev); -- ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev); -- ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev); -+ esp_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_trans_deflev); -+ esp_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_esp_net_deflev); -+ ah_trans_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_trans_deflev); -+ ah_net_deflev = IPSEC_CHECK_DEFAULT(vnet->ip6_ah_net_deflev); - break; - #endif /* INET6 */ - default: -@@ -1614,10 +1636,16 @@ - struct ipsecrequest *isr; - u_int level; - int need_auth, need_conf, need_icv; -+ struct vnet *vnet; - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("ipsec_in_reject: using SP\n"); - kdebug_secpolicy(sp)); -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipsec_in_reject(): unable to get vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; -+ if (vnet == NULL) -+ panic("ipsec_in_reject(): NULL vnet was passed."); - - /* check policy */ - switch (sp->policy) { -@@ -1644,7 +1672,7 @@ - for (isr = sp->req; isr != NULL; isr = isr->next) { - - /* get current level */ -- level = ipsec_get_reqlevel(isr); -+ level = ipsec_get_reqlevel(isr, vnet); - - switch (isr->saidx.proto) { - case IPPROTO_ESP: -@@ -1691,9 +1719,10 @@ - * and {ah,esp}4_input for tunnel mode - */ - int --ipsec4_in_reject_so(m, so) -+ipsec4_in_reject_so(m, so, vnet) - struct mbuf *m; - struct socket *so; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - int error; -@@ -1708,7 +1737,7 @@ - * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (so == NULL) -- sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); -+ sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet); - else - sp = ipsec4_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); - -@@ -1725,14 +1754,15 @@ - } - - int --ipsec4_in_reject(m, inp) -+ipsec4_in_reject(m, inp, vnet) - struct mbuf *m; - struct inpcb *inp; -+ struct vnet *vnet; - { - if (inp == NULL) -- return ipsec4_in_reject_so(m, NULL); -+ return ipsec4_in_reject_so(m, NULL, vnet); - if (inp->inp_socket) -- return ipsec4_in_reject_so(m, inp->inp_socket); -+ return ipsec4_in_reject_so(m, inp->inp_socket, vnet); - else - panic("ipsec4_in_reject: invalid inpcb/socket"); - } -@@ -1744,9 +1774,10 @@ - * and {ah,esp}6_input for tunnel mode - */ - int --ipsec6_in_reject_so(m, so) -+ipsec6_in_reject_so(m, so, vnet) - struct mbuf *m; - struct socket *so; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - int error; -@@ -1761,7 +1792,7 @@ - * ipsec6_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (so == NULL) -- sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error); -+ sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error, vnet); - else - sp = ipsec6_getpolicybysock(m, IPSEC_DIR_INBOUND, so, &error); - -@@ -1777,14 +1808,15 @@ - } - - int --ipsec6_in_reject(m, in6p) -+ipsec6_in_reject(m, in6p, vnet) - struct mbuf *m; - struct in6pcb *in6p; -+ struct vnet *vnet; - { - if (in6p == NULL) -- return ipsec6_in_reject_so(m, NULL); -+ return ipsec6_in_reject_so(m, NULL, vnet); - if (in6p->in6p_socket) -- return ipsec6_in_reject_so(m, in6p->in6p_socket); -+ return ipsec6_in_reject_so(m, in6p->in6p_socket, vnet); - else - panic("ipsec6_in_reject: invalid in6p/socket"); - } -@@ -1868,10 +1900,11 @@ - - /* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */ - size_t --ipsec4_hdrsiz(m, dir, inp) -+ipsec4_hdrsiz(m, dir, inp, vnet) - struct mbuf *m; - u_int dir; - struct inpcb *inp; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - int error; -@@ -1888,7 +1921,7 @@ - * ipsec4_getpolicybyaddr() with IP_FORWARDING flag. - */ - if (inp == NULL) -- sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error); -+ sp = ipsec4_getpolicybyaddr(m, dir, IP_FORWARDING, &error,vnet); - else - sp = ipsec4_getpolicybysock(m, dir, inp->inp_socket, &error); - -@@ -1910,10 +1943,11 @@ - * and maybe from ip6_forward.() - */ - size_t --ipsec6_hdrsiz(m, dir, in6p) -+ipsec6_hdrsiz(m, dir, in6p, vnet) - struct mbuf *m; - u_int dir; - struct in6pcb *in6p; -+ struct vnet *vnet; - { - struct secpolicy *sp = NULL; - int error; -@@ -1928,7 +1962,7 @@ - /* get SP for this packet */ - /* XXX Is it right to call with IP_FORWARDING. */ - if (in6p == NULL) -- sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error); -+ sp = ipsec6_getpolicybyaddr(m, dir, IP_FORWARDING, &error, vnet); - else - sp = ipsec6_getpolicybysock(m, dir, in6p->in6p_socket, &error); - -@@ -1951,9 +1985,10 @@ - * ip->ip_src must be fixed later on. - */ - static int --ipsec4_encapsulate(m, sav) -+ipsec4_encapsulate(m, sav, vnet) - struct mbuf *m; - struct secasvar *sav; -+ struct vnet *vnet; - { - struct ip *oip; - struct ip *ip; -@@ -1967,6 +2002,8 @@ - m_freem(m); - return EINVAL; - } -+ if (vnet == NULL) -+ panic("ipsec4_encapsulate(): vnet is NULL."); - #if 0 - /* XXX if the dst is myself, perform nothing. */ - if (key_ismyaddr((struct sockaddr *)&sav->sah->saidx.dst)) { -@@ -2030,7 +2067,7 @@ - - /* construct new IPv4 header. see RFC 2401 5.1.2.1 */ - /* ECN consideration. */ -- ip_ecn_ingress(ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos); -+ ip_ecn_ingress(vnet->ip4_ipsec_ecn, &ip->ip_tos, &oip->ip_tos); - #ifdef _IP_VHL - ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); - #else -@@ -2038,7 +2075,7 @@ - #endif - ip->ip_off &= htons(~IP_OFFMASK); - ip->ip_off &= htons(~IP_MF); -- switch (ip4_ipsec_dfbit) { -+ switch (vnet->ip4_ipsec_dfbit) { - case 0: /* clear DF bit */ - ip->ip_off &= htons(~IP_DF); - break; -@@ -2058,7 +2095,7 @@ - #ifdef RANDOM_IP_ID - ip->ip_id = ip_randomid(); - #else -- ip->ip_id = htons(ip_id++); -+ ip->ip_id = htons(vnet->ip_id++); - #endif - bcopy(&((struct sockaddr_in *)&sav->sah->saidx.src)->sin_addr, - &ip->ip_src, sizeof(ip->ip_src)); -@@ -2074,14 +2111,18 @@ - - #ifdef INET6 - static int --ipsec6_encapsulate(m, sav) -+ipsec6_encapsulate(m, sav, vnet) - struct mbuf *m; - struct secasvar *sav; -+ struct vnet *vnet; - { - struct ip6_hdr *oip6; - struct ip6_hdr *ip6; - size_t plen; - -+ if (vnet == NULL) -+ panic("ipsec6_encapsulate(): vnet is NULL."); -+ - /* can't tunnel between different AFs */ - if (((struct sockaddr *)&sav->sah->saidx.src)->sa_family - != ((struct sockaddr *)&sav->sah->saidx.dst)->sa_family -@@ -2133,7 +2174,7 @@ - - /* construct new IPv6 header. see RFC 2401 5.1.2.2 */ - /* ECN consideration. */ -- ip6_ecn_ingress(ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); -+ ip6_ecn_ingress(vnet->ip6_ipsec_ecn, &ip6->ip6_flow, &oip6->ip6_flow); - if (plen < IPV6_MAXPACKET - sizeof(struct ip6_hdr)) - ip6->ip6_plen = htons(plen); - else { -@@ -2493,6 +2534,8 @@ - panic("state->ro == NULL in ipsec4_output"); - if (!state->dst) - panic("state->dst == NULL in ipsec4_output"); -+ if (vnet == NULL) -+ panic("ipsec4_output: vnet is NULL."); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("ipsec4_output: applyed SP\n"); -@@ -2541,13 +2584,13 @@ - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ -- ipsecstat.out_nosa++; -+ vnet->ipsecstat.out_nosa++; - goto bad; - } - - /* validity check */ - if (isr->sav == NULL) { -- switch (ipsec_get_reqlevel(isr)) { -+ switch (ipsec_get_reqlevel(isr, vnet)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: -@@ -2565,7 +2608,7 @@ - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { -- ipsecstat.out_nosa++; -+ vnet->ipsecstat.out_nosa++; - error = EINVAL; - goto bad; - } -@@ -2596,7 +2639,7 @@ - error = ENOMEM; - goto bad; - } -- error = ipsec4_encapsulate(state->m, isr->sav); -+ error = ipsec4_encapsulate(state->m, isr->sav, vnet); - splx(s); - if (error) { - state->m = NULL; -@@ -2641,7 +2684,7 @@ - switch (isr->saidx.proto) { - case IPPROTO_ESP: - #ifdef IPSEC_ESP -- if ((error = esp4_output(state->m, isr)) != 0) { -+ if ((error = esp4_output(state->m, isr, vnet)) != 0) { - state->m = NULL; - goto bad; - } -@@ -2653,7 +2696,7 @@ - goto bad; - #endif - case IPPROTO_AH: -- if ((error = ah4_output(state->m, isr)) != 0) { -+ if ((error = ah4_output(state->m, isr, vnet)) != 0) { - state->m = NULL; - goto bad; - } -@@ -2695,13 +2738,14 @@ - * IPsec output logic for IPv6, transport mode. - */ - int --ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun) -+ipsec6_output_trans(state, nexthdrp, mprev, sp, flags, tun, vnet) - struct ipsec_output_state *state; - u_char *nexthdrp; - struct mbuf *mprev; - struct secpolicy *sp; - int flags; - int *tun; -+ struct vnet *vnet; - { - struct ip6_hdr *ip6; - struct ipsecrequest *isr = NULL; -@@ -2722,6 +2766,8 @@ - panic("sp == NULL in ipsec6_output_trans"); - if (!tun) - panic("tun == NULL in ipsec6_output_trans"); -+ if (!vnet) -+ panic("vnet == NULL in ipsec6_output_trans"); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("ipsec6_output_trans: applyed SP\n"); -@@ -2766,7 +2812,7 @@ - } - } - -- if (key_checkrequest(isr, &saidx) == ENOENT) { -+ if (key_checkrequest(isr, &saidx, vnet) == ENOENT) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called -@@ -2774,7 +2820,7 @@ - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ -- ipsec6stat.out_nosa++; -+ vnet->ipsec6stat.out_nosa++; - error = ENOENT; - - /* -@@ -2793,7 +2839,7 @@ - - /* validity check */ - if (isr->sav == NULL) { -- switch (ipsec_get_reqlevel(isr)) { -+ switch (ipsec_get_reqlevel(isr, vnet)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: -@@ -2808,7 +2854,7 @@ - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { -- ipsec6stat.out_nosa++; -+ vnet->ipsec6stat.out_nosa++; - error = EINVAL; - goto bad; - } -@@ -2816,7 +2862,7 @@ - switch (isr->saidx.proto) { - case IPPROTO_ESP: - #ifdef IPSEC_ESP -- error = esp6_output(state->m, nexthdrp, mprev->m_next, isr); -+ error = esp6_output(state->m, nexthdrp, mprev->m_next, isr, vnet); - #else - m_freem(state->m); - error = EINVAL; -@@ -2832,7 +2878,7 @@ - ipseclog((LOG_ERR, "ipsec6_output_trans: " - "unknown ipsec protocol %d\n", isr->saidx.proto)); - m_freem(state->m); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - error = EINVAL; - break; - } -@@ -2844,7 +2890,7 @@ - if (plen > IPV6_MAXPACKET) { - ipseclog((LOG_ERR, "ipsec6_output_trans: " - "IPsec with IPv6 jumbogram is not supported\n")); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - error = EINVAL; /* XXX */ - goto bad; - } -@@ -2868,10 +2914,11 @@ - * IPsec output logic for IPv6, tunnel mode. - */ - int --ipsec6_output_tunnel(state, sp, flags) -+ipsec6_output_tunnel(state, sp, flags, vnet) - struct ipsec_output_state *state; - struct secpolicy *sp; - int flags; -+ struct vnet *vnet; - { - struct ip6_hdr *ip6; - struct ipsecrequest *isr = NULL; -@@ -2887,6 +2934,8 @@ - panic("state->m == NULL in ipsec6_output_tunnel"); - if (!sp) - panic("sp == NULL in ipsec6_output_tunnel"); -+ if (!vnet) -+ panic("vnet == NULL in ipsec6_output_tunnel"); - - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("ipsec6_output_tunnel: applyed SP\n"); -@@ -2943,7 +2992,7 @@ - } - } - -- if (key_checkrequest(isr, &saidx) == ENOENT) { -+ if (key_checkrequest(isr, &saidx, vnet) == ENOENT) { - /* - * IPsec processing is required, but no SA found. - * I assume that key_acquire() had been called -@@ -2951,14 +3000,14 @@ - * this packet because it is responsibility for - * upper layer to retransmit the packet. - */ -- ipsec6stat.out_nosa++; -+ vnet->ipsec6stat.out_nosa++; - error = ENOENT; - goto bad; - } - - /* validity check */ - if (isr->sav == NULL) { -- switch (ipsec_get_reqlevel(isr)) { -+ switch (ipsec_get_reqlevel(isr, vnet)) { - case IPSEC_LEVEL_USE: - continue; - case IPSEC_LEVEL_REQUIRE: -@@ -2973,7 +3022,7 @@ - */ - if (isr->sav->state != SADB_SASTATE_MATURE - && isr->sav->state != SADB_SASTATE_DYING) { -- ipsec6stat.out_nosa++; -+ vnet->ipsec6stat.out_nosa++; - error = EINVAL; - goto bad; - } -@@ -2994,7 +3043,7 @@ - "family mismatched between inner and outer, spi=%u\n", - (u_int32_t)ntohl(isr->sav->spi))); - splx(s); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - error = EAFNOSUPPORT; - goto bad; - } -@@ -3002,11 +3051,11 @@ - state->m = ipsec6_splithdr(state->m); - if (!state->m) { - splx(s); -- ipsec6stat.out_nomem++; -+ vnet->ipsec6stat.out_nomem++; - error = ENOMEM; - goto bad; - } -- error = ipsec6_encapsulate(state->m, isr->sav); -+ error = ipsec6_encapsulate(state->m, isr->sav, vnet); - splx(s); - if (error) { - state->m = 0; -@@ -3028,11 +3077,11 @@ - dst6->sin6_family = AF_INET6; - dst6->sin6_len = sizeof(*dst6); - dst6->sin6_addr = ip6->ip6_dst; -- rtalloc(state->ro); -+ rtalloc(state->ro, vnet); - } - if (state->ro->ro_rt == 0) { -- ip6stat.ip6s_noroute++; -- ipsec6stat.out_noroute++; -+ vnet->ip6stat.ip6s_noroute++; -+ vnet->ipsec6stat.out_noroute++; - error = EHOSTUNREACH; - goto bad; - } -@@ -3047,7 +3096,7 @@ - - state->m = ipsec6_splithdr(state->m); - if (!state->m) { -- ipsec6stat.out_nomem++; -+ vnet->ipsec6stat.out_nomem++; - error = ENOMEM; - goto bad; - } -@@ -3055,7 +3104,7 @@ - switch (isr->saidx.proto) { - case IPPROTO_ESP: - #ifdef IPSEC_ESP -- error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr); -+ error = esp6_output(state->m, &ip6->ip6_nxt, state->m->m_next, isr, vnet); - #else - m_freem(state->m); - error = EINVAL; -@@ -3071,7 +3120,7 @@ - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "unknown ipsec protocol %d\n", isr->saidx.proto)); - m_freem(state->m); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - error = EINVAL; - break; - } -@@ -3083,7 +3132,7 @@ - if (plen > IPV6_MAXPACKET) { - ipseclog((LOG_ERR, "ipsec6_output_tunnel: " - "IPsec with IPv6 jumbogram is not supported\n")); -- ipsec6stat.out_inval++; -+ vnet->ipsec6stat.out_inval++; - error = EINVAL; /* XXX */ - goto bad; - } -@@ -3193,7 +3242,11 @@ - int hlen; - struct secpolicy *sp; - struct ip *oip; -+ struct vnet *vnet; - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipsec4_tunnel_validate: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; - #ifdef DIAGNOSTIC - if (m->m_len < sizeof(struct ip)) - panic("too short mbuf on ipsec4_tunnel_validate"); -@@ -3260,7 +3313,7 @@ - */ - - sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, -- (struct sockaddr *)&isrc, (struct sockaddr *)&idst); -+ (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet); - if (!sp) - return 0; - key_freesp(sp); -@@ -3282,7 +3335,12 @@ - struct sockaddr_in6 osrc, odst, isrc, idst; - struct secpolicy *sp; - struct ip6_hdr *oip6; -+ struct vnet *vnet; - -+ if (m == NULL || m->m_pkthdr.rcvif == NULL) -+ panic("ipsec6_tunnel_validate: cannot find vnet."); -+ vnet = m->m_pkthdr.rcvif->if_vnet; -+ - #ifdef DIAGNOSTIC - if (m->m_len < sizeof(struct ip6_hdr)) - panic("too short mbuf on ipsec6_tunnel_validate"); -@@ -3325,7 +3383,7 @@ - */ - - sp = key_gettunnel((struct sockaddr *)&osrc, (struct sockaddr *)&odst, -- (struct sockaddr *)&isrc, (struct sockaddr *)&idst); -+ (struct sockaddr *)&isrc, (struct sockaddr *)&idst, vnet); - /* - * when there is no suitable inbound policy for the packet of the ipsec - * tunnel mode, the kernel never decapsulate the tunneled packet -diff -urN sys/netinet6/ipsec.h sys.CORE/netinet6/ipsec.h ---- sys/netinet6/ipsec.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/ipsec.h Wed Jan 31 16:02:43 2007 -@@ -285,6 +285,7 @@ - - extern int ipsec_debug; - -+#ifdef MOVED_TO_VNET - extern struct ipsecstat ipsecstat; - extern struct secpolicy ip4_def_policy; - extern int ip4_esp_trans_deflev; -@@ -296,34 +297,36 @@ - extern int ip4_ipsec_dfbit; - extern int ip4_ipsec_ecn; - extern int ip4_esp_randpad; -+#endif - - #define ipseclog(x) do { if (ipsec_debug) log x; } while (0) - - extern struct secpolicy *ipsec4_getpolicybysock - __P((struct mbuf *, u_int, struct socket *, int *)); - extern struct secpolicy *ipsec4_getpolicybyaddr -- __P((struct mbuf *, u_int, int, int *)); -+ __P((struct mbuf *, u_int, int, int *, struct vnet *)); - - struct inpcb; - extern int ipsec_init_policy __P((struct socket *so, struct inpcbpolicy **)); - extern int ipsec_copy_policy - __P((struct inpcbpolicy *, struct inpcbpolicy *)); --extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *)); -+extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *, struct vnet *)); - - extern int ipsec4_set_policy __P((struct inpcb *inp, int optname, - caddr_t request, size_t len, int priv)); - extern int ipsec4_get_policy __P((struct inpcb *inpcb, caddr_t request, - size_t len, struct mbuf **mp)); - extern int ipsec4_delete_pcbpolicy __P((struct inpcb *)); --extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *)); --extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *)); -+extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *)); -+extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *)); - - struct secas; - struct tcpcb; - extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *)); - extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *)); - --extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *)); -+extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *, -+ struct vnet *)); - extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *)); - - struct ip; -diff -urN sys/netinet6/ipsec6.h sys.CORE/netinet6/ipsec6.h ---- sys/netinet6/ipsec6.h Tue Jul 3 04:01:54 2001 -+++ sys.CORE/netinet6/ipsec6.h Wed Jan 31 16:02:43 2007 -@@ -53,29 +53,29 @@ - extern struct secpolicy *ipsec6_getpolicybysock - __P((struct mbuf *, u_int, struct socket *, int *)); - extern struct secpolicy *ipsec6_getpolicybyaddr -- __P((struct mbuf *, u_int, int, int *)); -+ __P((struct mbuf *, u_int, int, int *, struct vnet *)); - - struct inpcb; - --extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *)); -+extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *, struct vnet *)); - extern int ipsec6_delete_pcbpolicy __P((struct inpcb *)); - extern int ipsec6_set_policy __P((struct inpcb *inp, int optname, - caddr_t request, size_t len, int priv)); - extern int ipsec6_get_policy - __P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp)); --extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *)); -+extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *, struct vnet *)); - - struct tcp6cb; - --extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *)); -+extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *, struct vnet *vnet)); - - struct ip6_hdr; - extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t)); - - extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *, -- struct mbuf *, struct secpolicy *, int, int *)); -+ struct mbuf *, struct secpolicy *, int, int *, struct vnet *)); - extern int ipsec6_output_tunnel __P((struct ipsec_output_state *, -- struct secpolicy *, int)); -+ struct secpolicy *, int, struct vnet *)); - extern int ipsec6_tunnel_validate __P((struct mbuf *, int, u_int, - struct secasvar *)); - #endif /*_KERNEL*/ -diff -urN sys/netinet6/raw_ip6.c sys.CORE/netinet6/raw_ip6.c ---- sys/netinet6/raw_ip6.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/raw_ip6.c Wed Jan 31 16:02:43 2007 -@@ -168,9 +168,9 @@ - /* - * Check AH/ESP integrity. - */ -- if (n && ipsec6_in_reject_so(n, last->inp_socket)) { -+ if (n && ipsec6_in_reject_so(n, last->inp_socket, vnet)) { - m_freem(n); -- ipsec6stat.in_polvio++; -+ vnet->ipsec6stat.in_polvio++; - /* do not inject data into pcb */ - } else - #endif /*IPSEC*/ -@@ -207,10 +207,10 @@ - /* - * Check AH/ESP integrity. - */ -- if (last && ipsec6_in_reject_so(m, last->inp_socket)) { -+ if (last && ipsec6_in_reject_so(m, last->inp_socket, vnet)) { - m_freem(m); -- ipsec6stat.in_polvio++; -- ip6stat.ip6s_delivered--; -+ vnet->ipsec6stat.in_polvio++; -+ vnet->ip6stat.ip6s_delivered--; - /* do not inject data into pcb */ - } else - #endif /*IPSEC*/ -@@ -220,7 +220,7 @@ - */ - if (last && ipsec6_in_reject(m, last)) { - m_freem(m); -- ip6stat.ip6s_delivered--; -+ vnet->ip6stat.ip6s_delivered--; - /* do not inject data into pcb */ - } else - #endif /*FAST_IPSEC*/ -diff -urN sys/netinet6/udp6_usrreq.c sys.CORE/netinet6/udp6_usrreq.c ---- sys/netinet6/udp6_usrreq.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netinet6/udp6_usrreq.c Wed Jan 31 16:02:43 2007 -@@ -260,8 +260,8 @@ - /* - * Check AH/ESP integrity. - */ -- if (ipsec6_in_reject_so(m, last->inp_socket)) -- ipsec6stat.in_polvio++; -+ if (ipsec6_in_reject_so(m, last->inp_socket, vnet)) -+ vnet->ipsec6stat.in_polvio++; - /* do not inject data into pcb */ - else - #endif /* IPSEC */ -@@ -327,8 +327,8 @@ - /* - * Check AH/ESP integrity. - */ -- if (ipsec6_in_reject_so(m, last->inp_socket)) { -- ipsec6stat.in_polvio++; -+ if (ipsec6_in_reject_so(m, last->inp_socket, vnet)) { -+ vnet->ipsec6stat.in_polvio++; - goto bad; - } - #endif /* IPSEC */ -@@ -383,8 +383,8 @@ - /* - * Check AH/ESP integrity. - */ -- if (ipsec6_in_reject_so(m, in6p->in6p_socket)) { -- ipsec6stat.in_polvio++; -+ if (ipsec6_in_reject_so(m, in6p->in6p_socket, vnet)) { -+ vnet->ipsec6stat.in_polvio++; - goto bad; - } - #endif /* IPSEC */ -diff -urN sys/netipsec/ipsec.c sys.CORE/netipsec/ipsec.c ---- sys/netipsec/ipsec.c Mon Jun 30 18:38:13 2003 -+++ sys.CORE/netipsec/ipsec.c Wed Jan 31 16:02:43 2007 -@@ -53,6 +53,7 @@ - #include - #include - -+#include - #include - #include - -@@ -123,31 +124,31 @@ - SYSCTL_DECL(_net_inet_ipsec); - - /* net.inet.ipsec */ --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV,esp_trans_deflev, - CTLFLAG_RW, &ip4_esp_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip4_esp_net_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, - CTLFLAG_RW, &ip4_ah_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip4_ah_net_deflev, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_CLEARTOS, - ah_cleartos, CTLFLAG_RW, &ah_cleartos, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_AH_OFFSETMASK, - ah_offsetmask, CTLFLAG_RW, &ip4_ah_offsetmask, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DFBIT, - dfbit, CTLFLAG_RW, &ip4_ipsec_dfbit, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip4_ipsec_ecn, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); --SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip4_esp_randpad, 0, ""); --SYSCTL_INT(_net_inet_ipsec, OID_AUTO, -+SYSCTL_V_INT(V_NET, _net_inet_ipsec, OID_AUTO, - crypto_support, CTLFLAG_RW, &crypto_support,0, ""); --SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO, -+SYSCTL_V_STRUCT(V_NET, _net_inet_ipsec, OID_AUTO, - ipsecstats, CTLFLAG_RD, &newipsecstat, newipsecstat, ""); - - #ifdef INET6 -@@ -165,21 +166,21 @@ - SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD, - 0,0, compat_ipsecstats_sysctl, "S", ""); - #endif /* COMPAT_KAME */ --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_POLICY, - def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev, -- CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, -+ esp_trans_deflev, CTLFLAG_RW, &ip6_esp_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev, - CTLFLAG_RW, &ip6_esp_net_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev, -- CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, -+ ah_trans_deflev, CTLFLAG_RW, &ip6_ah_trans_deflev, 0, ""); -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev, - CTLFLAG_RW, &ip6_ah_net_deflev, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ECN, - ecn, CTLFLAG_RW, &ip6_ipsec_ecn, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_DEBUG, - debug, CTLFLAG_RW, &ipsec_debug, 0, ""); --SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, -+SYSCTL_V_INT(V_NET, _net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD, - esp_randpad, CTLFLAG_RW, &ip6_esp_randpad, 0, ""); - #endif /* INET6 */ - -diff -urN sys/netipsec/key.c sys.CORE/netipsec/key.c ---- sys/netipsec/key.c Sat Feb 14 14:23:23 2004 -+++ sys.CORE/netipsec/key.c Wed Jan 31 16:02:43 2007 -@@ -54,6 +54,7 @@ - #include - #include - -+#include - #include - #include - #include -@@ -203,51 +204,51 @@ - SYSCTL_DECL(_net_key); - #endif - --SYSCTL_INT(_net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_DEBUG_LEVEL, debug, CTLFLAG_RW, \ - &key_debug_level, 0, ""); - - /* max count of trial for the decision of spi value */ --SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ - &key_spi_trycnt, 0, ""); - - /* minimum spi value to allocate automatically. */ --SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ - &key_spi_minval, 0, ""); - - /* maximun spi value to allocate automatically. */ --SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ - &key_spi_maxval, 0, ""); - - /* interval to initialize randseed */ --SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ - &key_int_random, 0, ""); - - /* lifetime for larval SA */ --SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ - &key_larval_lifetime, 0, ""); - - /* counter for blocking to send SADB_ACQUIRE to IKEd */ --SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT,blockacq_count,CTLFLAG_RW, \ - &key_blockacq_count, 0, ""); - - /* lifetime for blocking to send SADB_ACQUIRE to IKEd */ --SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ - &key_blockacq_lifetime, 0, ""); - - /* ESP auth */ --SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ - &ipsec_esp_auth, 0, ""); - - /* minimum ESP key length */ --SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ - &ipsec_esp_keymin, 0, ""); - - /* minimum AH key length */ --SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ - &ipsec_ah_keymin, 0, ""); - - /* perfered old SA rather than new SA */ --SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA,prefered_oldsa, CTLFLAG_RW,\ - &key_prefered_oldsa, 0, ""); - - #ifndef LIST_FOREACH -@@ -349,12 +350,13 @@ - int extlen[SADB_EXT_MAX + 1]; - }; - --static struct secasvar *key_allocsa_policy __P((const struct secasindex *)); -+static struct secasvar *key_allocsa_policy __P((const struct secasindex *, -+ struct vnet *)); - static void key_freesp_so __P((struct secpolicy **)); - static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int)); - static void key_delsp __P((struct secpolicy *)); --static struct secpolicy *key_getsp __P((struct secpolicyindex *)); --static struct secpolicy *key_getspbyid __P((u_int32_t)); -+static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*)); -+static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet *)); - static u_int32_t key_newreqid __P((void)); - static struct mbuf *key_gather_mbuf __P((struct mbuf *, - const struct sadb_msghdr *, int, int, ...)); -@@ -523,7 +525,7 @@ - * others: found and return the pointer. - */ - struct secpolicy * --key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag) -+key_allocsp(struct secpolicyindex *spidx, u_int dir, const char* where, int tag, struct vnet *vnet) - { - struct secpolicy *sp; - int s; -@@ -541,7 +543,7 @@ - printf("*** objects\n"); - kdebug_secpolicyindex(spidx)); - -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); -@@ -580,7 +582,7 @@ - union sockaddr_union *dst, - u_int8_t proto, - u_int dir, -- const char* where, int tag) -+ const char* where, int tag, struct vnet *vnet) - { - struct secpolicy *sp; - int s; -@@ -599,7 +601,7 @@ - printf("spi %u proto %u dir %u\n", spi, proto, dir); - kdebug_sockaddr(&dst->sa)); - -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); -@@ -642,7 +644,7 @@ - const struct sockaddr *odst, - const struct sockaddr *isrc, - const struct sockaddr *idst, -- const char* where, int tag) -+ const char* where, int tag, struct vnet *vnet) - { - struct secpolicy *sp; - const int dir = IPSEC_DIR_INBOUND; -@@ -661,7 +663,7 @@ - } - - s = splnet(); /*called from softclock()*/ -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - -@@ -817,7 +819,7 @@ - struct secasvar *sav; - u_int stateidx, state; - -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) -@@ -991,7 +993,7 @@ - union sockaddr_union *dst, - u_int proto, - u_int32_t spi, -- const char* where, int tag) -+ const char* where, int tag, struct vnet *vnet) - { - struct secashead *sah; - struct secasvar *sav; -@@ -1010,7 +1012,7 @@ - * encrypted so we can't check internal IP header. - */ - s = splnet(); /*called from softclock()*/ -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - /* search valid state */ - for (stateidx = 0; - stateidx < _ARRAYLEN(saorder_state_valid); -@@ -1213,13 +1215,13 @@ - * others : found, pointer to a SP. - */ - static struct secpolicy * --key_getsp(struct secpolicyindex *spidx) -+key_getsp(struct secpolicyindex *spidx, struct vnet *vnet) - { - struct secpolicy *sp; - - KASSERT(spidx != NULL, ("key_getsp: null spidx")); - -- LIST_FOREACH(sp, &sptree[spidx->dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_exactly(spidx, &sp->spidx)) { -@@ -1237,11 +1239,11 @@ - * others : found, pointer to a SP. - */ - static struct secpolicy * --key_getspbyid(u_int32_t id) -+key_getspbyid(u_int32_t id, struct vnet *vnet) - { - struct secpolicy *sp; - -- LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { -@@ -1250,7 +1252,7 @@ - } - } - -- LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { -@@ -7060,37 +7062,59 @@ - } - - void --key_init() -+key_init(vnet) -+ struct vnet *vnet; - { - int i; - - for (i = 0; i < IPSEC_DIR_MAX; i++) { -- LIST_INIT(&sptree[i]); -+ LIST_INIT(&vnet->sptree[i]); - } - -- LIST_INIT(&sahtree); -+ LIST_INIT(&vnet->sahtree); - - for (i = 0; i <= SADB_SATYPE_MAX; i++) { -- LIST_INIT(®tree[i]); -+ LIST_INIT(&vnet->regtree[i]); - } - - #ifndef IPSEC_NONBLOCK_ACQUIRE -- LIST_INIT(&acqtree); -+ LIST_INIT(&vnet->acqtree); - #endif -- LIST_INIT(&spacqtree); -+ LIST_INIT(&vnet->spacqtree); - - /* system default */ -- ip4_def_policy.policy = IPSEC_POLICY_NONE; -- ip4_def_policy.refcnt++; /*never reclaim this*/ -+ vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip4_def_policy.refcnt++; /*never reclaim this*/ - - #ifndef IPSEC_DEBUG2 - timeout((void *)key_timehandler, (void *)0, hz); - #endif /*IPSEC_DEBUG2*/ - - /* initialize key statistics */ -- keystat.getspi_count = 1; -+ vnet->keystat.getspi_count = 1; -+ -+ /* initialize vars in struct vnet */ -+ vnet->acq_seq = 0; -+ vnet->ip4_ah_offsetmask = 0; -+ vnet->ip4_ipsec_dfbit = 0; -+ vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ipsec_ecn = 0; -+ vnet->ip4_esp_randpad = -1; -+ vnet->crypto_support = 0; -+#ifdef INET6 -+ vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ipsec_ecn = 0; -+ vnet->ip6_esp_randpad = -1; -+#endif - -- printf("IPsec: Initialized Security Association Processing.\n"); -+ if (vnet == vnet0) -+ printf("IPsec: Initialized Security Association Processing.\n"); - - return; - } -diff -urN sys/netipsec/keysock.c sys.CORE/netipsec/keysock.c ---- sys/netipsec/keysock.c Thu Jan 23 21:11:36 2003 -+++ sys.CORE/netipsec/keysock.c Wed Jan 31 16:02:43 2007 -@@ -592,10 +592,11 @@ - }; - - static void --key_init0(void) -+key_init0(vnet) -+ struct vnet *vnet; - { -- bzero((caddr_t)&key_cb, sizeof(key_cb)); -- key_init(); -+ bzero((caddr_t)&vnet->key_cb, sizeof(key_cb)); -+ key_init(vnet); - } - - struct domain keydomain = -diff -urN sys/netkey/key.c sys.CORE/netkey/key.c ---- sys/netkey/key.c Thu Jan 13 14:47:18 2005 -+++ sys.CORE/netkey/key.c Wed Jan 31 16:02:43 2007 -@@ -107,6 +107,8 @@ - #include - - #include -+#include -+#include - - #ifndef satosin - #define satosin(s) ((struct sockaddr_in *)s) -@@ -126,6 +128,7 @@ - */ - - u_int32_t key_debug_level = 0; -+#ifdef MOVED_TO_VNET - static u_int key_spi_trycnt = 1000; - static u_int32_t key_spi_minval = 0x100; - static u_int32_t key_spi_maxval = 0x0fffffff; /* XXX */ -@@ -149,6 +152,7 @@ - static LIST_HEAD(_spacqtree, secspacq) spacqtree; /* SP acquiring list */ - - struct key_cb key_cb; -+#endif /* MOVED_TO_VNET */ - - /* search order for SAs */ - static const u_int saorder_state_valid_prefer_old[] = { -@@ -223,32 +227,32 @@ - &key_debug_level, 0, ""); - - /* max count of trial for the decision of spi value */ --SYSCTL_INT(_net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ -- &key_spi_trycnt, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_TRY, spi_trycnt, CTLFLAG_RW, \ -+ v_key_spi_trycnt, 0, ""); - - /* minimum spi value to allocate automatically. */ --SYSCTL_INT(_net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ -- &key_spi_minval, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MIN_VALUE, spi_minval, CTLFLAG_RW, \ -+ v_key_spi_minval, 0, ""); - - /* maximun spi value to allocate automatically. */ --SYSCTL_INT(_net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ -- &key_spi_maxval, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_SPI_MAX_VALUE, spi_maxval, CTLFLAG_RW, \ -+ v_key_spi_maxval, 0, ""); - - /* interval to initialize randseed */ --SYSCTL_INT(_net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ -- &key_int_random, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_RANDOM_INT, int_random, CTLFLAG_RW, \ -+ v_key_int_random, 0, ""); - - /* lifetime for larval SA */ --SYSCTL_INT(_net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ -- &key_larval_lifetime, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_LARVAL_LIFETIME, larval_lifetime, CTLFLAG_RW, \ -+ v_key_larval_lifetime, 0, ""); - - /* counter for blocking to send SADB_ACQUIRE to IKEd */ --SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ -- &key_blockacq_count, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_COUNT, blockacq_count, CTLFLAG_RW, \ -+ v_key_blockacq_count, 0, ""); - - /* lifetime for blocking to send SADB_ACQUIRE to IKEd */ --SYSCTL_INT(_net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ -- &key_blockacq_lifetime, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_BLOCKACQ_LIFETIME, blockacq_lifetime, CTLFLAG_RW, \ -+ v_key_blockacq_lifetime, 0, ""); - - /* ESP auth */ - SYSCTL_INT(_net_key, KEYCTL_ESP_AUTH, esp_auth, CTLFLAG_RW, \ -@@ -263,8 +267,8 @@ - &ipsec_ah_keymin, 0, ""); - - /* perfered old SA rather than new SA */ --SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ -- &key_preferred_oldsa, 0, ""); -+SYSCTL_V_INT(V_NET, _net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ -+ v_key_preferred_oldsa, 0, ""); - - #ifndef LIST_FOREACH - #define LIST_FOREACH(elm, head, field) \ -@@ -352,9 +356,11 @@ - } while (0) - - /* key statistics */ -+#ifdef MOVED_TO_VNET - struct _keystat { - u_long getspi_count; /* the avarage of count to try to get new SPI */ - } keystat; -+#endif - - struct sadb_msghdr { - struct sadb_msg *msg; -@@ -363,18 +369,20 @@ - int extlen[SADB_EXT_MAX + 1]; - }; - --static struct secasvar *key_allocsa_policy __P((struct secasindex *)); -+static struct secasvar *key_allocsa_policy __P((struct secasindex *, -+ struct vnet *)); - static void key_freesp_so __P((struct secpolicy **)); --static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int)); -+static struct secasvar *key_do_allocsa_policy __P((struct secashead *, u_int, -+ struct vnet *)); - static void key_delsp __P((struct secpolicy *)); --static struct secpolicy *key_getsp __P((struct secpolicyindex *)); --static struct secpolicy *key_getspbyid __P((u_int32_t)); -+static struct secpolicy *key_getsp __P((struct secpolicyindex *, struct vnet*)); -+static struct secpolicy *key_getspbyid __P((u_int32_t, struct vnet*)); - static u_int32_t key_newreqid __P((void)); - static struct mbuf *key_gather_mbuf __P((struct mbuf *, - const struct sadb_msghdr *, int, int, ...)); - static int key_spdadd __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); --static u_int32_t key_getnewspid __P((void)); -+static u_int32_t key_getnewspid __P((struct vnet *)); - static int key_spddelete __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); - static int key_spddelete2 __P((struct socket *, struct mbuf *, -@@ -388,14 +396,15 @@ - static struct mbuf *key_setdumpsp __P((struct secpolicy *, - u_int8_t, u_int32_t, u_int32_t)); - static u_int key_getspreqmsglen __P((struct secpolicy *)); --static int key_spdexpire __P((struct secpolicy *)); --static struct secashead *key_newsah __P((struct secasindex *)); -+static int key_spdexpire __P((struct secpolicy *, struct vnet *)); -+static struct secashead *key_newsah __P((struct secasindex *, struct vnet *)); - static void key_delsah __P((struct secashead *)); - static struct secasvar *key_newsav __P((struct mbuf *, - const struct sadb_msghdr *, struct secashead *, int *)); - static void key_delsav __P((struct secasvar *)); --static struct secashead *key_getsah __P((struct secasindex *)); --static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t)); -+static struct secashead *key_getsah __P((struct secasindex *, struct vnet *)); -+static struct secasvar *key_checkspidup __P((struct secasindex *, u_int32_t, -+ struct vnet *)); - static struct secasvar *key_getsavbyspi __P((struct secashead *, u_int32_t)); - static int key_setsaval __P((struct secasvar *, struct mbuf *, - const struct sadb_msghdr *)); -@@ -416,7 +425,7 @@ - u_int32_t)); - static void *key_newbuf __P((const void *, u_int)); - #ifdef INET6 --static int key_ismyaddr6 __P((struct sockaddr_in6 *)); -+static int key_ismyaddr6 __P((struct sockaddr_in6 *, struct vnet *)); - #endif - - /* flags for key_cmpsaidx() */ -@@ -440,7 +449,8 @@ - static int key_getspi __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); - static u_int32_t key_do_getnewspi __P((struct sadb_spirange *, -- struct secasindex *)); -+ struct secasindex *, -+ struct vnet *)); - static int key_update __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); - #ifdef IPSEC_DOSEQCHECK -@@ -465,19 +475,20 @@ - static struct mbuf *key_getcomb_ipcomp __P((void)); - static struct mbuf *key_getprop __P((const struct secasindex *)); - --static int key_acquire __P((struct secasindex *, struct secpolicy *)); -+static int key_acquire __P((struct secasindex *, struct secpolicy *, -+ struct vnet *)); - #ifndef IPSEC_NONBLOCK_ACQUIRE --static struct secacq *key_newacq __P((struct secasindex *)); --static struct secacq *key_getacq __P((struct secasindex *)); --static struct secacq *key_getacqbyseq __P((u_int32_t)); -+static struct secacq *key_newacq __P((struct secasindex *, struct vnet *)); -+static struct secacq *key_getacq __P((struct secasindex *, struct vnet *)); -+static struct secacq *key_getacqbyseq __P((u_int32_t, struct vnet *)); - #endif - static struct secspacq *key_newspacq __P((struct secpolicyindex *)); --static struct secspacq *key_getspacq __P((struct secpolicyindex *)); -+static struct secspacq *key_getspacq __P((struct secpolicyindex *, struct vnet *)); - static int key_acquire2 __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); - static int key_register __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); --static int key_expire __P((struct secasvar *)); -+static int key_expire __P((struct secasvar *, struct vnet *vnet)); - static int key_flush __P((struct socket *, struct mbuf *, - const struct sadb_msghdr *)); - static int key_dump __P((struct socket *, struct mbuf *, -@@ -486,7 +497,7 @@ - const struct sadb_msghdr *)); - static int key_senderror __P((struct socket *, struct mbuf *, int)); - static int key_validate_ext __P((const struct sadb_ext *, int)); --static int key_align __P((struct mbuf *, struct sadb_msghdr *)); -+static int key_align __P((struct mbuf *, struct sadb_msghdr *, struct vnet *)); - #if 0 - static const char *key_getfqdn __P((void)); - static const char *key_getuserfqdn __P((void)); -@@ -502,9 +513,10 @@ - * others: found and return the pointer. - */ - struct secpolicy * --key_allocsp(spidx, dir) -+key_allocsp(spidx, dir, vnet) - struct secpolicyindex *spidx; - u_int dir; -+ struct vnet *vnet; - { - struct secpolicy *sp; - struct timeval tv; -@@ -513,6 +525,8 @@ - /* sanity check */ - if (spidx == NULL) - panic("key_allocsp: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_allocsp: NULL vnet is passed.\n"); - - /* check direction */ - switch (dir) { -@@ -529,7 +543,7 @@ - printf("*** objects\n"); - kdebug_secpolicyindex(spidx)); - -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - KEYDEBUG(KEYDEBUG_IPSEC_DATA, - printf("*** in SPD\n"); - kdebug_secpolicyindex(&sp->spidx)); -@@ -564,8 +578,9 @@ - * XXX slow - */ - struct secpolicy * --key_gettunnel(osrc, odst, isrc, idst) -+key_gettunnel(osrc, odst, isrc, idst, vnet) - struct sockaddr *osrc, *odst, *isrc, *idst; -+ struct vnet *vnet; - { - struct secpolicy *sp; - const int dir = IPSEC_DIR_INBOUND; -@@ -580,9 +595,11 @@ - isrc->sa_family, idst->sa_family)); - return NULL; - } -+ if (vnet == NULL) -+ panic("key_gettunnel: NULL vnet is passed.\n"); - - s = splnet(); /*called from softclock()*/ -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - -@@ -639,9 +656,10 @@ - * ENOENT: policy may be valid, but SA with REQUIRE is on acquiring. - */ - int --key_checkrequest(isr, saidx) -+key_checkrequest(isr, saidx, vnet) - struct ipsecrequest *isr; - struct secasindex *saidx; -+ struct vnet *vnet; - { - u_int level; - int error; -@@ -649,6 +667,8 @@ - /* sanity check */ - if (isr == NULL || saidx == NULL) - panic("key_checkrequest: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_checkrequest: NULL vnet is passed.\n"); - - /* check mode */ - switch (saidx->mode) { -@@ -661,7 +681,7 @@ - } - - /* get current level */ -- level = ipsec_get_reqlevel(isr); -+ level = ipsec_get_reqlevel(isr, vnet); - - #if 0 - /* -@@ -704,14 +724,14 @@ - * See key_do_allocsa_policy(), and draft-jenkins-ipsec-rekeying-03.txt. - */ - if (isr->sav == NULL) -- isr->sav = key_allocsa_policy(saidx); -+ isr->sav = key_allocsa_policy(saidx, vnet); - - /* When there is SA. */ - if (isr->sav != NULL) - return 0; - - /* there is no SA */ -- if ((error = key_acquire(saidx, isr->sp)) != 0) { -+ if ((error = key_acquire(saidx, isr->sp, vnet)) != 0) { - /* XXX What should I do ? */ - ipseclog((LOG_DEBUG, "key_checkrequest: error %d returned " - "from key_acquire.\n", error)); -@@ -728,8 +748,9 @@ - * others: found and return the pointer. - */ - static struct secasvar * --key_allocsa_policy(saidx) -+key_allocsa_policy(saidx, vnet) - struct secasindex *saidx; -+ struct vnet *vnet; - { - struct secashead *sah; - struct secasvar *sav; -@@ -737,7 +758,9 @@ - const u_int *saorder_state_valid; - int arraysize; - -- LIST_FOREACH(sah, &sahtree, chain) { -+ if (vnet == NULL) -+ panic("key_allocsa_policy: NULL vnet is passed.\n"); -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) -@@ -752,7 +775,7 @@ - * search a valid state list for outbound packet. - * This search order is important. - */ -- if (key_preferred_oldsa) { -+ if (vnet->key_preferred_oldsa) { - saorder_state_valid = saorder_state_valid_prefer_old; - arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); - } else { -@@ -764,7 +787,7 @@ - - state = saorder_state_valid[stateidx]; - -- sav = key_do_allocsa_policy(sah, state); -+ sav = key_do_allocsa_policy(sah, state, vnet); - if (sav != NULL) - return sav; - } -@@ -780,12 +803,15 @@ - * others : found, pointer to a SA. - */ - static struct secasvar * --key_do_allocsa_policy(sah, state) -+key_do_allocsa_policy(sah, state, vnet) - struct secashead *sah; - u_int state; -+ struct vnet *vnet; - { - struct secasvar *sav, *nextsav, *candidate, *d; - -+ if (vnet == NULL) -+ panic("key_do_allocsa_policy: NULL vnet is passed.\n"); - /* initilize */ - candidate = NULL; - -@@ -812,7 +838,7 @@ - "lifetime_current is NULL.\n"); - - /* What the best method is to compare ? */ -- if (key_preferred_oldsa) { -+ if (vnet->key_preferred_oldsa) { - if (candidate->lft_c->sadb_lifetime_addtime > - sav->lft_c->sadb_lifetime_addtime) { - candidate = sav; -@@ -883,7 +909,7 @@ - PFKEY_UNIT64(result->m_pkthdr.len); - - if (key_sendup_mbuf(NULL, result, -- KEY_SENDUP_REGISTERED)) -+ KEY_SENDUP_REGISTERED, vnet)) - goto msgfail; - msgfail: - key_freesav(d); -@@ -916,10 +942,11 @@ - * keep source address in IPsec SA. We see a tricky situation here. - */ - struct secasvar * --key_allocsa(family, src, dst, proto, spi) -+key_allocsa(family, src, dst, proto, spi, vnet) - u_int family, proto; - caddr_t src, dst; - u_int32_t spi; -+ struct vnet *vnet; - { - struct secashead *sah; - struct secasvar *sav; -@@ -933,12 +960,14 @@ - /* sanity check */ - if (src == NULL || dst == NULL) - panic("key_allocsa: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_allocsa: NULL vnet is passed.\n"); - - /* - * when both systems employ similar strategy to use a SA. - * the search order is important even in the inbound case. - */ -- if (key_preferred_oldsa) { -+ if (vnet->key_preferred_oldsa) { - saorder_state_valid = saorder_state_valid_prefer_old; - arraysize = _ARRAYLEN(saorder_state_valid_prefer_old); - } else { -@@ -953,7 +982,7 @@ - * encrypted so we can't check internal IP header. - */ - s = splnet(); /*called from softclock()*/ -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - /* - * search a valid state list for inbound packet. - * the search order is not important. -@@ -1248,16 +1277,19 @@ - * others : found, pointer to a SP. - */ - static struct secpolicy * --key_getsp(spidx) -+key_getsp(spidx, vnet) - struct secpolicyindex *spidx; -+ struct vnet *vnet; - { - struct secpolicy *sp; - - /* sanity check */ - if (spidx == NULL) - panic("key_getsp: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_getsp: NULL vnet is passed.\n"); - -- LIST_FOREACH(sp, &sptree[spidx->dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[spidx->dir], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (key_cmpspidx_exactly(spidx, &sp->spidx)) { -@@ -1275,12 +1307,15 @@ - * others : found, pointer to a SP. - */ - static struct secpolicy * --key_getspbyid(id) -+key_getspbyid(id, vnet) - u_int32_t id; -+ struct vnet *vnet; - { - struct secpolicy *sp; - -- LIST_FOREACH(sp, &sptree[IPSEC_DIR_INBOUND], chain) { -+ if (vnet == NULL) -+ panic("key_getspbyid: NULL vnet is passed.\n"); -+ LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_INBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { -@@ -1289,7 +1324,7 @@ - } - } - -- LIST_FOREACH(sp, &sptree[IPSEC_DIR_OUTBOUND], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[IPSEC_DIR_OUTBOUND], chain) { - if (sp->state == IPSEC_SPSTATE_DEAD) - continue; - if (sp->id == id) { -@@ -1735,10 +1770,14 @@ - struct secpolicy *newsp; - struct timeval tv; - int error; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdadd: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spdadd: NULL vnet pointer.\n"); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || -@@ -1808,7 +1847,7 @@ - * If the type is either SPDADD or SPDSETIDX AND a SP is found, - * then error. - */ -- newsp = key_getsp(&spidx); -+ newsp = key_getsp(&spidx, vnet); - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - if (newsp) { - newsp->state = IPSEC_SPSTATE_DEAD; -@@ -1827,7 +1866,7 @@ - return key_senderror(so, m, error); - } - -- if ((newsp->id = key_getnewspid()) == 0) { -+ if ((newsp->id = key_getnewspid(vnet)) == 0) { - keydb_delsecpolicy(newsp); - return key_senderror(so, m, ENOBUFS); - } -@@ -1879,12 +1918,13 @@ - - newsp->refcnt = 1; /* do not reclaim until I say I do */ - newsp->state = IPSEC_SPSTATE_ALIVE; -- LIST_INSERT_TAIL(&sptree[newsp->spidx.dir], newsp, secpolicy, chain); -+ LIST_INSERT_TAIL(&vnet->sptree[newsp->spidx.dir], newsp, -+ secpolicy, chain); - - /* delete the entry in spacqtree */ - if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) { - struct secspacq *spacq; -- if ((spacq = key_getspacq(&spidx)) != NULL) { -+ if ((spacq = key_getspacq(&spidx, vnet)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - microtime(&tv); - spacq->created = tv.tv_sec; -@@ -1934,7 +1974,7 @@ - xpl->sadb_x_policy_id = newsp->id; - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -1945,17 +1985,22 @@ - * others: success. - */ - static u_int32_t --key_getnewspid() -+key_getnewspid(vnet) -+ struct vnet *vnet; - { - u_int32_t newid = 0; -- int count = key_spi_trycnt; /* XXX */ -+ int count; - struct secpolicy *sp; - -+ if (vnet == NULL) -+ panic("key_getnewspid: NULL vnet was passed."); -+ count = vnet->key_spi_trycnt; /* XXX */ - /* when requesting to allocate spi ranged */ - while (count--) { -- newid = (policy_id = (policy_id == ~0 ? 1 : policy_id + 1)); -+ newid = (vnet->policy_id = (vnet->policy_id == ~0 ? -+ 1 : vnet->policy_id+1)); - -- if ((sp = key_getspbyid(newid)) == NULL) -+ if ((sp = key_getspbyid(newid, vnet)) == NULL) - break; - - key_freesp(sp); -@@ -1991,10 +2036,14 @@ - struct sadb_x_policy *xpl0; - struct secpolicyindex spidx; - struct secpolicy *sp; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spddelete: NULL vnet pointer.\n"); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL || -@@ -2034,7 +2083,7 @@ - } - - /* Is there SP in SPD ? */ -- if ((sp = key_getsp(&spidx)) == NULL) { -+ if ((sp = key_getsp(&spidx, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete: no SP found.\n")); - return key_senderror(so, m, EINVAL); - } -@@ -2060,7 +2109,7 @@ - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -2084,10 +2133,14 @@ - { - u_int32_t id; - struct secpolicy *sp; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddelete2: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spddelete2: NULL vnet pointer.\n"); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { -@@ -2099,7 +2152,7 @@ - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ -- if ((sp = key_getspbyid(id)) == NULL) { -+ if ((sp = key_getspbyid(id, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_spddelete2: no SP found id:%u.\n", id)); - key_senderror(so, m, EINVAL); - } -@@ -2156,7 +2209,7 @@ - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -2181,10 +2234,14 @@ - u_int32_t id; - struct secpolicy *sp; - struct mbuf *n; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdget: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spdget: NULL vnet pointer.\n"); - - if (mhp->ext[SADB_X_EXT_POLICY] == NULL || - mhp->extlen[SADB_X_EXT_POLICY] < sizeof(struct sadb_x_policy)) { -@@ -2195,7 +2252,7 @@ - id = ((struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY])->sadb_x_policy_id; - - /* Is there SP in SPD ? */ -- if ((sp = key_getspbyid(id)) == NULL) { -+ if ((sp = key_getspbyid(id, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_spdget: no SP found id:%u.\n", id)); - return key_senderror(so, m, ENOENT); - } -@@ -2203,7 +2260,7 @@ - n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid); - if (n != NULL) { - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); - } else - return key_senderror(so, m, ENOBUFS); - } -@@ -2224,8 +2281,9 @@ - * others: error number - */ - int --key_spdacquire(sp) -+key_spdacquire(sp, vnet) - struct secpolicy *sp; -+ struct vnet *vnet; - { - struct mbuf *result = NULL, *m; - struct secspacq *newspacq; -@@ -2238,10 +2296,12 @@ - panic("key_spdacquire: called but there is request.\n"); - if (sp->policy != IPSEC_POLICY_IPSEC) - panic("key_spdacquire: policy mismathed. IPsec is expected.\n"); -+ if (vnet == NULL) -+ panic("key_spdacquire: NULL vnet is passed.\n"); - - /* get a entry to check whether sent message or not. */ -- if ((newspacq = key_getspacq(&sp->spidx)) != NULL) { -- if (key_blockacq_count < newspacq->count) { -+ if ((newspacq = key_getspacq(&sp->spidx, vnet)) != NULL) { -+ if (vnet->key_blockacq_count < newspacq->count) { - /* reset counter and do send message. */ - newspacq->count = 0; - } else { -@@ -2255,7 +2315,7 @@ - return ENOBUFS; - - /* add to acqtree */ -- LIST_INSERT_HEAD(&spacqtree, newspacq, chain); -+ LIST_INSERT_HEAD(&vnet->spacqtree, newspacq, chain); - } - - /* create new sadb_msg to reply. */ -@@ -2273,7 +2333,7 @@ - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - -- return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(NULL, m, KEY_SENDUP_REGISTERED, vnet); - - fail: - if (result) -@@ -2302,16 +2362,20 @@ - struct sadb_msg *newmsg; - struct secpolicy *sp; - u_int dir; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spdflush: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spdflush: NULL vnet pointer.\n"); - - if (m->m_len != PFKEY_ALIGN8(sizeof(struct sadb_msg))) - return key_senderror(so, m, EINVAL); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - sp->state = IPSEC_SPSTATE_DEAD; - } - } -@@ -2329,7 +2393,7 @@ - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - -- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); - } - - /* -@@ -2353,15 +2417,19 @@ - int cnt; - u_int dir; - struct mbuf *n; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_spddump: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_spddump: NULL vnet pointer.\n"); - - /* search SPD entry and get buffer size. */ - cnt = 0; - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - cnt++; - } - } -@@ -2370,13 +2438,13 @@ - return key_senderror(so, m, ENOENT); - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { -- LIST_FOREACH(sp, &sptree[dir], chain) { -+ LIST_FOREACH(sp, &vnet->sptree[dir], chain) { - --cnt; - n = key_setdumpsp(sp, SADB_X_SPDDUMP, cnt, - mhp->msg->sadb_msg_pid); - - if (n) -- key_sendup_mbuf(so, n, KEY_SENDUP_ONE); -+ key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); - } - } - -@@ -2481,8 +2549,9 @@ - * others : error number - */ - static int --key_spdexpire(sp) -+key_spdexpire(sp, vnet) - struct secpolicy *sp; -+ struct vnet *vnet; - { - int s; - struct mbuf *result = NULL, *m; -@@ -2496,6 +2565,8 @@ - /* sanity check */ - if (sp == NULL) - panic("key_spdexpire: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_spdexpire: NULL vnet is passed.\n"); - - /* set msg header */ - m = key_setsadbmsg(SADB_X_SPDEXPIRE, 0, 0, 0, 0, 0); -@@ -2580,7 +2651,7 @@ - PFKEY_UNIT64(result->m_pkthdr.len); - - splx(s); -- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); - - fail: - if (result) -@@ -2596,14 +2667,17 @@ - * others : pointer to new SA head. - */ - static struct secashead * --key_newsah(saidx) -+key_newsah(saidx, vnet) - struct secasindex *saidx; -+ struct vnet *vnet; - { - struct secashead *newsah; - - /* sanity check */ - if (saidx == NULL) - panic("key_newsaidx: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_newsaidx: NULL vnet is passed.\n"); - - newsah = keydb_newsecashead(); - if (newsah == NULL) -@@ -2613,7 +2687,7 @@ - - /* add to saidxtree */ - newsah->state = SADB_SASTATE_MATURE; -- LIST_INSERT_HEAD(&sahtree, newsah, chain); -+ LIST_INSERT_HEAD(&vnet->sahtree, newsah, chain); - - return(newsah); - } -@@ -2846,12 +2920,15 @@ - * others : found, pointer to a SA. - */ - static struct secashead * --key_getsah(saidx) -+key_getsah(saidx, vnet) - struct secasindex *saidx; -+ struct vnet *vnet; - { - struct secashead *sah; - -- LIST_FOREACH(sah, &sahtree, chain) { -+ if (vnet == NULL) -+ panic("key_getsah: NULL vnet was passed."); -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, saidx, CMP_REQID)) -@@ -2869,13 +2946,16 @@ - * others : found, pointer to a SA. - */ - static struct secasvar * --key_checkspidup(saidx, spi) -+key_checkspidup(saidx, spi, vnet) - struct secasindex *saidx; - u_int32_t spi; -+ struct vnet *vnet; - { - struct secashead *sah; - struct secasvar *sav; - -+ if (vnet == NULL) -+ panic("key_checkspidup: NULL vnet was passed."); - /* check address family */ - if (saidx->src.ss_family != saidx->dst.ss_family) { - ipseclog((LOG_DEBUG, "key_checkspidup: address family mismatched.\n")); -@@ -2883,8 +2963,8 @@ - } - - /* check all SAD */ -- LIST_FOREACH(sah, &sahtree, chain) { -- if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst)) -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { -+ if (!key_ismyaddr((struct sockaddr *)&sah->saidx.dst, vnet)) - continue; - sav = key_getsavbyspi(sah, spi); - if (sav != NULL) -@@ -3794,8 +3874,9 @@ - * 0: false - */ - int --key_ismyaddr(sa) -+key_ismyaddr(sa, vnet) - struct sockaddr *sa; -+ struct vnet *vnet; - { - #ifdef INET - struct sockaddr_in *sin; -@@ -3805,12 +3886,14 @@ - /* sanity check */ - if (sa == NULL) - panic("key_ismyaddr: NULL pointer is passed.\n"); -+ if (vnet == NULL) -+ panic("key_ismyaddr: NULL vnet was passed."); - - switch (sa->sa_family) { - #ifdef INET - case AF_INET: - sin = (struct sockaddr_in *)sa; -- for (ia = in_ifaddrhead.tqh_first; ia; -+ for (ia = vnet->in_ifaddrhead.tqh_first; ia; - ia = ia->ia_link.tqe_next) - { - if (sin->sin_family == ia->ia_addr.sin_family && -@@ -3824,7 +3907,7 @@ - #endif - #ifdef INET6 - case AF_INET6: -- return key_ismyaddr6((struct sockaddr_in6 *)sa); -+ return key_ismyaddr6((struct sockaddr_in6 *)sa, vnet); - #endif - } - -@@ -3841,13 +3924,16 @@ - #include - - static int --key_ismyaddr6(sin6) -+key_ismyaddr6(sin6, vnet) - struct sockaddr_in6 *sin6; -+ struct vnet *vnet; - { - struct in6_ifaddr *ia; - struct in6_multi *in6m; - -- for (ia = in6_ifaddr; ia; ia = ia->ia_next) { -+ if (vnet == NULL) -+ panic("key_ismyaddr6: NULL vnet was passed."); -+ for (ia = vnet->in6_ifaddr; ia; ia = ia->ia_next) { - if (key_sockaddrcmp((struct sockaddr *)&sin6, - (struct sockaddr *)&ia->ia_addr, 0) == 0) - return 1; -@@ -4178,17 +4264,22 @@ - u_int dir; - int s; - struct timeval tv; -+ struct vnet *vnet; - - microtime(&tv); - - s = splnet(); /*called from softclock()*/ - -+ /* This timer function is called once to step through every vnet. */ -+ LIST_FOREACH(vnet, &vnet_head, vnet_le) -+ { -+ - /* SPD */ - { - struct secpolicy *sp, *nextsp; - - for (dir = 0; dir < IPSEC_DIR_MAX; dir++) { -- for (sp = LIST_FIRST(&sptree[dir]); -+ for (sp = LIST_FIRST(&vnet->sptree[dir]); - sp != NULL; - sp = nextsp) { - -@@ -4208,7 +4299,7 @@ - || (sp->validtime - && tv.tv_sec - sp->lastused > sp->validtime)) { - sp->state = IPSEC_SPSTATE_DEAD; -- key_spdexpire(sp); -+ key_spdexpire(sp, vnet); - continue; - } - } -@@ -4220,7 +4311,7 @@ - struct secashead *sah, *nextsah; - struct secasvar *sav, *nextsav; - -- for (sah = LIST_FIRST(&sahtree); -+ for (sah = LIST_FIRST(&vnet->sahtree); - sah != NULL; - sah = nextsah) { - -@@ -4239,7 +4330,7 @@ - - nextsav = LIST_NEXT(sav, chain); - -- if (tv.tv_sec - sav->created > key_larval_lifetime) { -+ if (tv.tv_sec - sav->created > vnet->key_larval_lifetime) { - key_freesav(sav); - } - } -@@ -4284,7 +4375,7 @@ - * message in the status of - * DYING. Do remove below code. - */ -- key_expire(sav); -+ key_expire(sav, vnet); - } - } - -@@ -4303,7 +4394,7 @@ - * message in the status of - * DYING. Do remove below code. - */ -- key_expire(sav); -+ key_expire(sav, vnet); - } - } - -@@ -4387,13 +4478,13 @@ - { - struct secacq *acq, *nextacq; - -- for (acq = LIST_FIRST(&acqtree); -+ for (acq = LIST_FIRST(&vnet->acqtree); - acq != NULL; - acq = nextacq) { - - nextacq = LIST_NEXT(acq, chain); - -- if (tv.tv_sec - acq->created > key_blockacq_lifetime -+ if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime - && __LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - KFREE(acq); -@@ -4406,13 +4497,13 @@ - { - struct secspacq *acq, *nextacq; - -- for (acq = LIST_FIRST(&spacqtree); -+ for (acq = LIST_FIRST(&vnet->spacqtree); - acq != NULL; - acq = nextacq) { - - nextacq = LIST_NEXT(acq, chain); - -- if (tv.tv_sec - acq->created > key_blockacq_lifetime -+ if (tv.tv_sec - acq->created > vnet->key_blockacq_lifetime - && __LIST_CHAINED(acq)) { - LIST_REMOVE(acq, chain); - KFREE(acq); -@@ -4421,11 +4512,13 @@ - } - - /* initialize random seed */ -- if (key_tick_init_random++ > key_int_random) { -- key_tick_init_random = 0; -+ if (vnet->key_tick_init_random++ > vnet->key_int_random) { -+ vnet->key_tick_init_random = 0; - key_srandom(); - } - -+ /* end LIST_FOREACH(vnet, ...) */ -+ } - #ifndef IPSEC_DEBUG2 - /* do exchange to tick time !! */ - (void)timeout((void *)key_timehandler, (void *)0, hz); -@@ -4562,10 +4655,14 @@ - u_int8_t mode; - u_int32_t reqid; - int error; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_getspi: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_getspi: cannot find vnet.\n"); - - if (mhp->ext[SADB_EXT_ADDRESS_SRC] == NULL || - mhp->ext[SADB_EXT_ADDRESS_DST] == NULL) { -@@ -4633,14 +4730,14 @@ - - /* SPI allocation */ - spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE], -- &saidx); -+ &saidx, vnet); - if (spi == 0) - return key_senderror(so, m, EINVAL); - - /* get a SA index */ -- if ((newsah = key_getsah(&saidx)) == NULL) { -+ if ((newsah = key_getsah(&saidx, vnet)) == NULL) { - /* create a new SA index */ -- if ((newsah = key_newsah(&saidx)) == NULL) { -+ if ((newsah = key_newsah(&saidx, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_getspi: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } -@@ -4661,7 +4758,7 @@ - /* delete the entry in acqtree */ - if (mhp->msg->sadb_msg_seq != 0) { - struct secacq *acq; -- if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) != NULL) { -+ if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) != NULL) { - /* reset counter in order to deletion by timehandler. */ - struct timeval tv; - microtime(&tv); -@@ -4722,7 +4819,7 @@ - if (n->m_len < sizeof(struct sadb_msg)) { - n = m_pullup(n, sizeof(struct sadb_msg)); - if (n == NULL) -- return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet); - } - - n->m_pkthdr.len = 0; -@@ -4735,7 +4832,7 @@ - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); - } - } - -@@ -4747,21 +4844,26 @@ - * others: success. - */ - static u_int32_t --key_do_getnewspi(spirange, saidx) -+key_do_getnewspi(spirange, saidx, vnet) - struct sadb_spirange *spirange; - struct secasindex *saidx; -+ struct vnet *vnet; - { - u_int32_t newspi; - u_int32_t min, max; -- int count = key_spi_trycnt; -+ int count; -+ -+ if (vnet == NULL) -+ panic("key_do_getnewspi: NULL vnet was passed."); -+ count = vnet->key_spi_trycnt; - - /* set spi range to allocate */ - if (spirange != NULL) { - min = spirange->sadb_spirange_min; - max = spirange->sadb_spirange_max; - } else { -- min = key_spi_minval; -- max = key_spi_maxval; -+ min = vnet->key_spi_minval; -+ max = vnet->key_spi_maxval; - } - /* IPCOMP needs 2-byte SPI */ - if (saidx->proto == IPPROTO_IPCOMP) { -@@ -4776,7 +4878,7 @@ - } - - if (min == max) { -- if (key_checkspidup(saidx, min) != NULL) { -+ if (key_checkspidup(saidx, min, vnet) != NULL) { - ipseclog((LOG_DEBUG, "key_do_getnewspi: SPI %u exists already.\n", min)); - return 0; - } -@@ -4794,7 +4896,7 @@ - /* generate pseudo-random SPI value ranged. */ - newspi = min + (key_random() % (max - min + 1)); - -- if (key_checkspidup(saidx, newspi) == NULL) -+ if (key_checkspidup(saidx, newspi, vnet) == NULL) - break; - } - -@@ -4805,8 +4907,8 @@ - } - - /* statistics */ -- keystat.getspi_count = -- (keystat.getspi_count + key_spi_trycnt - count) / 2; -+ vnet->keystat.getspi_count = -+ (vnet->keystat.getspi_count + vnet->key_spi_trycnt - count)/2; - - return newspi; - } -@@ -4839,10 +4941,14 @@ - u_int8_t mode; - u_int32_t reqid; - int error; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_update: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_update: cannot find vnet.\n"); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -4887,7 +4993,7 @@ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ -- if ((sah = key_getsah(&saidx)) == NULL) { -+ if ((sah = key_getsah(&saidx, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_update: no SA index found.\n")); - return key_senderror(so, m, ENOENT); - } -@@ -4963,7 +5069,7 @@ - } - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -5034,10 +5140,14 @@ - u_int8_t mode; - u_int32_t reqid; - int error; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_add: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_add: NULL vnet pointer is passed.\n"); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -5082,9 +5192,9 @@ - KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ -- if ((newsah = key_getsah(&saidx)) == NULL) { -+ if ((newsah = key_getsah(&saidx, vnet)) == NULL) { - /* create a new SA header */ -- if ((newsah = key_newsah(&saidx)) == NULL) { -+ if ((newsah = key_newsah(&saidx, vnet)) == NULL) { - ipseclog((LOG_DEBUG, "key_add: No more memory.\n")); - return key_senderror(so, m, ENOBUFS); - } -@@ -5130,7 +5240,7 @@ - } - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -5265,10 +5375,14 @@ - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_delete: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_delete: NULL vnet pointer is passed.\n"); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -5309,7 +5423,7 @@ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) -@@ -5349,7 +5463,7 @@ - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -5368,6 +5482,11 @@ - struct secashead *sah; - struct secasvar *sav, *nextsav; - u_int stateidx, state; -+ struct vnet *vnet; -+ -+ if (so == NULL || so->so_vnet == NULL) -+ panic("key_delete_all: cannot find vnet.\n"); -+ vnet = so->so_vnet; - - src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]); -@@ -5375,7 +5494,7 @@ - /* XXX boundary check against sa_len */ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) -@@ -5425,7 +5544,7 @@ - newmsg->sadb_msg_len = PFKEY_UNIT64(n->m_pkthdr.len); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ALL, vnet); - } - } - -@@ -5453,10 +5572,14 @@ - struct secashead *sah; - struct secasvar *sav = NULL; - u_int16_t proto; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_get: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_get: NULL vnet pointer is passed.\n"); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -5485,7 +5608,7 @@ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA header */ -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_HEAD) == 0) -@@ -5518,7 +5641,7 @@ - return key_senderror(so, m, ENOBUFS); - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_ONE); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); - } - } - -@@ -5795,9 +5918,10 @@ - * others: error number - */ - static int --key_acquire(saidx, sp) -+key_acquire(saidx, sp, vnet) - struct secasindex *saidx; - struct secpolicy *sp; -+ struct vnet *vnet; - { - struct mbuf *result = NULL, *m; - #ifndef IPSEC_NONBLOCK_ACQUIRE -@@ -5812,6 +5936,8 @@ - panic("key_acquire: NULL pointer is passed.\n"); - if ((satype = key_proto2satype(saidx->proto)) == 0) - panic("key_acquire: invalid proto is passed.\n"); -+ if (vnet == NULL) -+ panic("key_acquire: NULL vnet is passed.\n"); - - #ifndef IPSEC_NONBLOCK_ACQUIRE - /* -@@ -5821,8 +5947,8 @@ - * managed with ACQUIRING list. - */ - /* get a entry to check whether sending message or not. */ -- if ((newacq = key_getacq(saidx)) != NULL) { -- if (key_blockacq_count < newacq->count) { -+ if ((newacq = key_getacq(saidx, vnet)) != NULL) { -+ if (vnet->key_blockacq_count < newacq->count) { - /* reset counter and do send message. */ - newacq->count = 0; - } else { -@@ -5832,11 +5958,11 @@ - } - } else { - /* make new entry for blocking to send SADB_ACQUIRE. */ -- if ((newacq = key_newacq(saidx)) == NULL) -+ if ((newacq = key_newacq(saidx, vnet)) == NULL) - return ENOBUFS; - - /* add to acqtree */ -- LIST_INSERT_HEAD(&acqtree, newacq, chain); -+ LIST_INSERT_HEAD(&vnet->acqtree, newacq, chain); - } - #endif - -@@ -5966,7 +6092,7 @@ - mtod(result, struct sadb_msg *)->sadb_msg_len = - PFKEY_UNIT64(result->m_pkthdr.len); - -- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); - - fail: - if (result) -@@ -5976,12 +6102,15 @@ - - #ifndef IPSEC_NONBLOCK_ACQUIRE - static struct secacq * --key_newacq(saidx) -+key_newacq(saidx, vnet) - struct secasindex *saidx; -+ struct vnet *vnet; - { - struct secacq *newacq; - struct timeval tv; - -+ if (vnet == NULL) -+ panic("key_newacq: NULL vnet was passed."); - /* get new entry */ - KMALLOC(newacq, struct secacq *, sizeof(struct secacq)); - if (newacq == NULL) { -@@ -5992,7 +6121,7 @@ - - /* copy secindex */ - bcopy(saidx, &newacq->saidx, sizeof(newacq->saidx)); -- newacq->seq = (acq_seq == ~0 ? 1 : ++acq_seq); -+ newacq->seq = (vnet->acq_seq == ~0 ? 1 : ++vnet->acq_seq); - microtime(&tv); - newacq->created = tv.tv_sec; - newacq->count = 0; -@@ -6001,12 +6130,15 @@ - } - - static struct secacq * --key_getacq(saidx) -+key_getacq(saidx, vnet) - struct secasindex *saidx; -+ struct vnet *vnet; - { - struct secacq *acq; - -- LIST_FOREACH(acq, &acqtree, chain) { -+ if (vnet == NULL) -+ panic("key_getacq: NULL vnet was passed."); -+ LIST_FOREACH(acq, &vnet->acqtree, chain) { - if (key_cmpsaidx(saidx, &acq->saidx, CMP_EXACTLY)) - return acq; - } -@@ -6015,12 +6147,15 @@ - } - - static struct secacq * --key_getacqbyseq(seq) -+key_getacqbyseq(seq, vnet) - u_int32_t seq; -+ struct vnet *vnet; - { - struct secacq *acq; - -- LIST_FOREACH(acq, &acqtree, chain) { -+ if (vnet == NULL) -+ panic("key_getacqbyseq: NULL vnet was passed."); -+ LIST_FOREACH(acq, &vnet->acqtree, chain) { - if (acq->seq == seq) - return acq; - } -@@ -6054,12 +6189,15 @@ - } - - static struct secspacq * --key_getspacq(spidx) -+key_getspacq(spidx, vnet) - struct secpolicyindex *spidx; -+ struct vnet *vnet; - { - struct secspacq *acq; - -- LIST_FOREACH(acq, &spacqtree, chain) { -+ if (vnet == NULL) -+ panic("key_getspacq: NULL vnet was passed."); -+ LIST_FOREACH(acq, &vnet->spacqtree, chain) { - if (key_cmpspidx_exactly(spidx, &acq->spidx)) - return acq; - } -@@ -6092,10 +6230,14 @@ - struct secashead *sah; - u_int16_t proto; - int error; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_acquire2: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_acquire2: NULL vnet pointer is passed.\n"); - - /* - * Error message from KMd. -@@ -6115,7 +6257,7 @@ - return 0; - } - -- if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq)) == NULL) { -+ if ((acq = key_getacqbyseq(mhp->msg->sadb_msg_seq, vnet)) == NULL) { - /* - * the specified larval SA is already gone, or we got - * a bogus sequence number. we can silently ignore it. -@@ -6165,7 +6307,7 @@ - KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx); - - /* get a SA index */ -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (sah->state == SADB_SASTATE_DEAD) - continue; - if (key_cmpsaidx(&sah->saidx, &saidx, CMP_MODE_REQID)) -@@ -6176,14 +6318,14 @@ - return key_senderror(so, m, EEXIST); - } - -- error = key_acquire(&saidx, NULL); -+ error = key_acquire(&saidx, NULL, vnet); - if (error != 0) { - ipseclog((LOG_DEBUG, "key_acquire2: error %d returned " - "from key_acquire.\n", mhp->msg->sadb_msg_errno)); - return key_senderror(so, m, error); - } - -- return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_REGISTERED, vnet); - } - - /* -@@ -6206,13 +6348,17 @@ - const struct sadb_msghdr *mhp; - { - struct secreg *reg, *newreg = 0; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_register: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_register: NULL vnet is passed.\n"); - - /* check for invalid register message */ -- if (mhp->msg->sadb_msg_satype >= sizeof(regtree)/sizeof(regtree[0])) -+ if (mhp->msg->sadb_msg_satype >= sizeof(vnet->regtree)/sizeof(vnet->regtree[0])) - return key_senderror(so, m, EINVAL); - - /* When SATYPE_UNSPEC is specified, only return sabd_supported. */ -@@ -6220,7 +6366,7 @@ - goto setmsg; - - /* check whether existing or not */ -- LIST_FOREACH(reg, ®tree[mhp->msg->sadb_msg_satype], chain) { -+ LIST_FOREACH(reg, &vnet->regtree[mhp->msg->sadb_msg_satype], chain) { - if (reg->so == so) { - ipseclog((LOG_DEBUG, "key_register: socket exists already.\n")); - return key_senderror(so, m, EEXIST); -@@ -6239,7 +6385,8 @@ - ((struct keycb *)sotorawcb(so))->kp_registered++; - - /* add regnode to regtree. */ -- LIST_INSERT_HEAD(®tree[mhp->msg->sadb_msg_satype], newreg, chain); -+ LIST_INSERT_HEAD(&vnet->regtree[mhp->msg->sadb_msg_satype], -+ newreg, chain); - - setmsg: - { -@@ -6355,7 +6502,7 @@ - #endif - - m_freem(m); -- return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(so, n, KEY_SENDUP_REGISTERED, vnet); - } - } - -@@ -6369,10 +6516,14 @@ - { - struct secreg *reg; - int i; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL) - panic("key_freereg: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_freereg: NULL vnet pointer is passed.\n"); - - /* - * check whether existing or not. -@@ -6380,7 +6531,7 @@ - * one socket is registered to multiple type of SA. - */ - for (i = 0; i <= SADB_SATYPE_MAX; i++) { -- LIST_FOREACH(reg, ®tree[i], chain) { -+ LIST_FOREACH(reg, &vnet->regtree[i], chain) { - if (reg->so == so - && __LIST_CHAINED(reg)) { - LIST_REMOVE(reg, chain); -@@ -6404,8 +6555,9 @@ - * others : error number - */ - static int --key_expire(sav) -+key_expire(sav, vnet) - struct secasvar *sav; -+ struct vnet *vnet; - { - int s; - int satype; -@@ -6414,6 +6566,8 @@ - int error = -1; - struct sadb_lifetime *lt; - -+ if (vnet == NULL) -+ panic("key_expire: NULL vnet was passed."); - /* XXX: Why do we lock ? */ - s = splnet(); /*called from softclock()*/ - -@@ -6513,7 +6667,7 @@ - PFKEY_UNIT64(result->m_pkthdr.len); - - splx(s); -- return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED); -+ return key_sendup_mbuf(NULL, result, KEY_SENDUP_REGISTERED, vnet); - - fail: - if (result) -@@ -6546,10 +6700,14 @@ - u_int16_t proto; - u_int8_t state; - u_int stateidx; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_flush: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_flush: NULL vnet pointer is passed.\n"); - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -6558,7 +6716,7 @@ - } - - /* no SATYPE specified, i.e. flushing all SA. */ -- for (sah = LIST_FIRST(&sahtree); -+ for (sah = LIST_FIRST(&vnet->sahtree); - sah != NULL; - sah = nextsah) { - nextsah = LIST_NEXT(sah, chain); -@@ -6599,7 +6757,7 @@ - newmsg->sadb_msg_errno = 0; - newmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - -- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); - } - - /* -@@ -6629,10 +6787,12 @@ - int cnt; - struct sadb_msg *newmsg; - struct mbuf *n; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_dump: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; - - /* map satype to proto */ - if ((proto = key_satype2proto(mhp->msg->sadb_msg_satype)) == 0) { -@@ -6642,7 +6802,7 @@ - - /* count sav entries to be sent to the userland. */ - cnt = 0; -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; -@@ -6662,7 +6822,7 @@ - - /* send this to the userland, one at a time. */ - newmsg = NULL; -- LIST_FOREACH(sah, &sahtree, chain) { -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - if (mhp->msg->sadb_msg_satype != SADB_SATYPE_UNSPEC - && proto != sah->saidx.proto) - continue; -@@ -6683,7 +6843,7 @@ - if (!n) - return key_senderror(so, m, ENOBUFS); - -- key_sendup_mbuf(so, n, KEY_SENDUP_ONE); -+ key_sendup_mbuf(so, n, KEY_SENDUP_ONE, vnet); - } - } - } -@@ -6704,10 +6864,14 @@ - const struct sadb_msghdr *mhp; - { - int olen; -+ struct vnet *vnet; - - /* sanity check */ - if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL) - panic("key_promisc: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL); -+ panic("key_promisc: NULL vnet pointer is passed.\n"); - - olen = PFKEY_UNUNIT64(mhp->msg->sadb_msg_len); - -@@ -6736,14 +6900,14 @@ - - /* send the original message back to everyone */ - mhp->msg->sadb_msg_errno = 0; -- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); - } else { - /* send packet as is */ - - m_adj(m, PFKEY_ALIGN8(sizeof(struct sadb_msg))); - - /* TODO: if sadb_msg_seq is specified, send to specific pid */ -- return key_sendup_mbuf(so, m, KEY_SENDUP_ALL); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ALL, vnet); - } - } - -@@ -6790,6 +6954,7 @@ - struct mbuf *m; - struct socket *so; - { -+ struct vnet *vnet; - struct sadb_msg *msg; - struct sadb_msghdr mh; - u_int orglen; -@@ -6799,6 +6964,9 @@ - /* sanity check */ - if (m == NULL || so == NULL) - panic("key_parse: NULL pointer is passed.\n"); -+ vnet = so->so_vnet; -+ if (vnet == NULL) -+ panic("key_parse: NULL vnet is passed.\n"); - - #if 0 /*kdebug_sadb assumes msg in linear buffer*/ - KEYDEBUG(KEYDEBUG_KEY_DUMP, -@@ -6818,7 +6986,7 @@ - if ((m->m_flags & M_PKTHDR) == 0 || - m->m_pkthdr.len != m->m_pkthdr.len) { - ipseclog((LOG_DEBUG, "key_parse: invalid message length.\n")); -- pfkeystat.out_invlen++; -+ vnet->pfkeystat.out_invlen++; - error = EINVAL; - goto senderror; - } -@@ -6827,7 +6995,7 @@ - ipseclog((LOG_DEBUG, - "key_parse: PF_KEY version %u is mismatched.\n", - msg->sadb_msg_version)); -- pfkeystat.out_invver++; -+ vnet->pfkeystat.out_invver++; - error = EINVAL; - goto senderror; - } -@@ -6835,7 +7003,7 @@ - if (msg->sadb_msg_type > SADB_MAX) { - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_type)); -- pfkeystat.out_invmsgtype++; -+ vnet->pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } -@@ -6868,7 +7036,7 @@ - } - - /* align the mbuf chain so that extensions are in contiguous region. */ -- error = key_align(m, &mh); -+ error = key_align(m, &mh, vnet); - if (error) - return error; - -@@ -6892,7 +7060,7 @@ - case SADB_EXPIRE: - ipseclog((LOG_DEBUG, "key_parse: must specify satype " - "when msg type=%u.\n", msg->sadb_msg_type)); -- pfkeystat.out_invsatype++; -+ vnet->pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } -@@ -6911,7 +7079,7 @@ - case SADB_X_SPDDELETE2: - ipseclog((LOG_DEBUG, "key_parse: illegal satype=%u\n", - msg->sadb_msg_type)); -- pfkeystat.out_invsatype++; -+ vnet->pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } -@@ -6922,7 +7090,7 @@ - case SADB_SATYPE_MIP: - ipseclog((LOG_DEBUG, "key_parse: type %u isn't supported.\n", - msg->sadb_msg_satype)); -- pfkeystat.out_invsatype++; -+ vnet->pfkeystat.out_invsatype++; - error = EOPNOTSUPP; - goto senderror; - case 1: /* XXX: What does it do? */ -@@ -6932,7 +7100,7 @@ - default: - ipseclog((LOG_DEBUG, "key_parse: invalid type %u is passed.\n", - msg->sadb_msg_satype)); -- pfkeystat.out_invsatype++; -+ vnet->pfkeystat.out_invsatype++; - error = EINVAL; - goto senderror; - } -@@ -6949,7 +7117,7 @@ - /* check upper layer protocol */ - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - ipseclog((LOG_DEBUG, "key_parse: upper layer protocol mismatched.\n")); -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -6958,7 +7126,7 @@ - if (PFKEY_ADDR_SADDR(src0)->sa_family != - PFKEY_ADDR_SADDR(dst0)->sa_family) { - ipseclog((LOG_DEBUG, "key_parse: address family mismatched.\n")); -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -6966,7 +7134,7 @@ - PFKEY_ADDR_SADDR(dst0)->sa_len) { - ipseclog((LOG_DEBUG, - "key_parse: address struct size mismatched.\n")); -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -6975,7 +7143,7 @@ - case AF_INET: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in)) { -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -6983,7 +7151,7 @@ - case AF_INET6: - if (PFKEY_ADDR_SADDR(src0)->sa_len != - sizeof(struct sockaddr_in6)) { -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -6991,7 +7159,7 @@ - default: - ipseclog((LOG_DEBUG, - "key_parse: unsupported address family.\n")); -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EAFNOSUPPORT; - goto senderror; - } -@@ -7013,7 +7181,7 @@ - dst0->sadb_address_prefixlen > plen) { - ipseclog((LOG_DEBUG, - "key_parse: illegal prefixlen.\n")); -- pfkeystat.out_invaddr++; -+ vnet->pfkeystat.out_invaddr++; - error = EINVAL; - goto senderror; - } -@@ -7026,7 +7194,7 @@ - - if (msg->sadb_msg_type >= sizeof(key_typesw)/sizeof(key_typesw[0]) || - key_typesw[msg->sadb_msg_type] == NULL) { -- pfkeystat.out_invmsgtype++; -+ vnet->pfkeystat.out_invmsgtype++; - error = EINVAL; - goto senderror; - } -@@ -7035,7 +7203,7 @@ - - senderror: - msg->sadb_msg_errno = error; -- return key_sendup_mbuf(so, m, target); -+ return key_sendup_mbuf(so, m, target, vnet); - } - - static int -@@ -7044,14 +7212,18 @@ - struct mbuf *m; - int code; - { -+ struct vnet *vnet; - struct sadb_msg *msg; - -+ if (so == NULL || so->so_vnet == NULL) -+ panic("key_senderror: cannot find vnet"); -+ vnet = so->so_vnet; - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_senderror"); - - msg = mtod(m, struct sadb_msg *); - msg->sadb_msg_errno = code; -- return key_sendup_mbuf(so, m, KEY_SENDUP_ONE); -+ return key_sendup_mbuf(so, m, KEY_SENDUP_ONE, vnet); - } - - /* -@@ -7060,9 +7232,10 @@ - * XXX larger-than-MCLBYTES extension? - */ - static int --key_align(m, mhp) -+key_align(m, mhp, vnet) - struct mbuf *m; - struct sadb_msghdr *mhp; -+ struct vnet *vnet; - { - struct mbuf *n; - struct sadb_ext *ext; -@@ -7075,6 +7248,8 @@ - panic("key_align: NULL pointer is passed.\n"); - if (m->m_len < sizeof(struct sadb_msg)) - panic("invalid mbuf passed to key_align"); -+ if (vnet == NULL) -+ panic("key_align: NULL vnet is passed.\n"); - - /* initialize */ - bzero(mhp, sizeof(*mhp)); -@@ -7122,7 +7297,7 @@ - "key_align: duplicate ext_type %u " - "is passed.\n", ext->sadb_ext_type)); - m_freem(m); -- pfkeystat.out_dupext++; -+ vnet->pfkeystat.out_dupext++; - return EINVAL; - } - break; -@@ -7131,7 +7306,7 @@ - "key_align: invalid ext_type %u is passed.\n", - ext->sadb_ext_type)); - m_freem(m); -- pfkeystat.out_invexttype++; -+ vnet->pfkeystat.out_invexttype++; - return EINVAL; - } - -@@ -7139,7 +7314,7 @@ - - if (key_validate_ext(ext, extlen)) { - m_freem(m); -- pfkeystat.out_invlen++; -+ vnet->pfkeystat.out_invlen++; - return EINVAL; - } - -@@ -7157,7 +7332,7 @@ - - if (off != end) { - m_freem(m); -- pfkeystat.out_invlen++; -+ vnet->pfkeystat.out_invlen++; - return EINVAL; - } - -@@ -7224,49 +7399,97 @@ - } - - void --key_init() -+key_init(vnet) -+ struct vnet *vnet; - { - int i; - -- bzero((caddr_t)&key_cb, sizeof(key_cb)); -+ if (vnet == NULL) -+ panic("key_init: NULL vnet was passed."); -+ bzero((caddr_t)&vnet->key_cb, sizeof(vnet->key_cb)); - - for (i = 0; i < IPSEC_DIR_MAX; i++) { -- LIST_INIT(&sptree[i]); -+ LIST_INIT(&vnet->sptree[i]); - } - -- LIST_INIT(&sahtree); -+ LIST_INIT(&vnet->sahtree); - - for (i = 0; i <= SADB_SATYPE_MAX; i++) { -- LIST_INIT(®tree[i]); -+ LIST_INIT(&vnet->regtree[i]); - } - - #ifndef IPSEC_NONBLOCK_ACQUIRE -- LIST_INIT(&acqtree); -+ LIST_INIT(&vnet->acqtree); - #endif -- LIST_INIT(&spacqtree); -+ LIST_INIT(&vnet->spacqtree); - - /* system default */ - #ifdef INET -- ip4_def_policy.policy = IPSEC_POLICY_NONE; -- ip4_def_policy.refcnt++; /*never reclaim this*/ -+ vnet->ip4_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip4_def_policy.refcnt++; /*never reclaim this*/ - #endif - #ifdef INET6 -- ip6_def_policy.policy = IPSEC_POLICY_NONE; -- ip6_def_policy.refcnt++; /*never reclaim this*/ -+ vnet->ip6_def_policy.policy = IPSEC_POLICY_NONE; -+ vnet->ip6_def_policy.refcnt++; /*never reclaim this*/ - #endif - --#ifndef IPSEC_DEBUG2 -- timeout((void *)key_timehandler, (void *)0, hz); --#endif /*IPSEC_DEBUG2*/ -- - /* initialize key statistics */ -- keystat.getspi_count = 1; -+ vnet->keystat.getspi_count = 1; - -- printf("IPsec: Initialized Security Association Processing.\n"); -+ /* initalize vnet variables (normally static) */ -+ /* from netkey/key.c */ -+ vnet->key_spi_trycnt = 1000; -+ vnet->key_spi_minval = 0x100; -+ vnet->key_spi_maxval = 0x0fffffff; /* XXX */ -+ vnet->policy_id = 0; -+ vnet->key_int_random = 60; /*interval to initialize randseed,1(m)*/ -+ vnet->key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ -+ vnet->key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ -+ vnet->key_blockacq_lifetime = 20;/* lifetime f/ blocking SADB_ACQUIRE.*/ -+ vnet->key_preferred_oldsa = 1; /* preferred old sa rather than new sa.*/ -+ vnet->acq_seq = 0; -+ vnet->key_tick_init_random = 0; -+ -+ /* from netinet6/ipsec.c */ -+ vnet->ip4_ah_cleartos = 1; -+ vnet->ip4_ah_offsetmask = 0; /* maybe IP_DF? */ -+ vnet->ip4_ipsec_dfbit = 0;/* DF bit on encap. 0: clear 1: set 2: copy */ -+ vnet->ip4_esp_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_esp_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ah_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ah_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip4_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -+ vnet->ip4_esp_randpad = -1; -+#ifdef INET6 -+ /* what about ipsec6stat? */ -+ vnet->ip6_esp_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_esp_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ah_trans_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ah_net_deflev = IPSEC_LEVEL_USE; -+ vnet->ip6_ipsec_ecn = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */ -+ vnet->ip6_esp_randpad = -1; -+#endif -+ -+/* net.inet6.ipsec6 */ -+ -+#ifndef IPSEC_DEBUG2 -+ if (vnet == vnet0) /* one timehandler iterates for all vnets */ -+ timeout((void *)key_timehandler, (void *)0, hz); -+#endif /*IPSEC_DEBUG2*/ -+ -+ if (vnet == vnet0) -+ printf("IPsec: Initialized Security Association Processing.\n"); - - return; - } - -+void -+key_destroy(vnet) -+struct vnet *vnet; -+{ -+ /* XXX do nothing */ -+} -+ - /* - * XXX: maybe This function is called after INBOUND IPsec processing. - * -@@ -7406,13 +7629,16 @@ - - /* dumb version */ - void --key_sa_routechange(dst) -+key_sa_routechange(dst, vnet) - struct sockaddr *dst; -+ struct vnet *vnet; - { - struct secashead *sah; - struct route *ro; - -- LIST_FOREACH(sah, &sahtree, chain) { -+ if (vnet == NULL) -+ panic("key_sa_routechange: NULL vnet was passed."); -+ LIST_FOREACH(sah, &vnet->sahtree, chain) { - ro = &sah->sa_route; - if (ro->ro_rt && dst->sa_len == ro->ro_dst.sa_len - && bcmp(dst, &ro->ro_dst, dst->sa_len) == 0) { -diff -urN sys/netkey/key.h sys.CORE/netkey/key.h ---- sys/netkey/key.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netkey/key.h Wed Jan 31 16:02:43 2007 -@@ -35,7 +35,7 @@ - - #ifdef _KERNEL - --extern struct key_cb key_cb; -+/*extern struct key_cb key_cb;*/ - - struct secpolicy; - struct secpolicyindex; -@@ -46,14 +46,15 @@ - struct sadb_msg; - struct sadb_x_policy; - --extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int)); -+extern struct secpolicy *key_allocsp __P((struct secpolicyindex *, u_int, -+ struct vnet*)); - extern struct secpolicy *key_gettunnel __P((struct sockaddr *, -- struct sockaddr *, struct sockaddr *, struct sockaddr *)); -+ struct sockaddr *, struct sockaddr *, struct sockaddr *, struct vnet*)); - extern int key_checkrequest - __P((struct ipsecrequest *isr, struct secasindex *, - struct vnet *)); - extern struct secasvar *key_allocsa __P((u_int, caddr_t, caddr_t, -- u_int, u_int32_t)); -+ u_int, u_int32_t, struct vnet *)); - extern void key_freesp __P((struct secpolicy *)); - extern void key_freeso __P((struct socket *)); - extern void key_freesav __P((struct secasvar *)); -@@ -68,11 +69,12 @@ - extern void key_randomfill __P((void *, size_t)); - extern void key_freereg __P((struct socket *)); - extern int key_parse __P((struct mbuf *, struct socket *)); --extern void key_init __P((void)); -+extern void key_init __P((struct vnet *)); -+extern void key_destroy __P((struct vnet *)); - extern int key_checktunnelsanity __P((struct secasvar *, u_int, - caddr_t, caddr_t)); - extern void key_sa_recordxfer __P((struct secasvar *, struct mbuf *)); --extern void key_sa_routechange __P((struct sockaddr *)); -+extern void key_sa_routechange __P((struct sockaddr *, struct vnet *)); - extern void key_sa_stir_iv __P((struct secasvar *)); - - #ifdef MALLOC_DECLARE -diff -urN sys/netkey/keysock.c sys.CORE/netkey/keysock.c ---- sys/netkey/keysock.c Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netkey/keysock.c Wed Jan 31 16:02:43 2007 -@@ -65,9 +65,7 @@ - struct sockaddr key_dst = { 2, PF_KEY, }; - struct sockaddr key_src = { 2, PF_KEY, }; - --static int key_sendup0 __P((struct rawcb *, struct mbuf *, int)); -- --struct pfkeystat pfkeystat; -+static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, struct vnet*)); - - /* - * key_output() -@@ -86,27 +84,31 @@ - int s; - struct socket *so; - va_list ap; -+ struct vnet *vnet; - - va_start(ap, m); - so = va_arg(ap, struct socket *); -+ vnet = va_arg(ap, struct vnet *); - va_end(ap); - - if (m == 0) - panic("key_output: NULL pointer was passed.\n"); -+ if (vnet == NULL) -+ panic("key_output: NULL vnet was passed.\n"); - -- pfkeystat.out_total++; -- pfkeystat.out_bytes += m->m_pkthdr.len; -+ vnet->pfkeystat.out_total++; -+ vnet->pfkeystat.out_bytes += m->m_pkthdr.len; - - len = m->m_pkthdr.len; - if (len < sizeof(struct sadb_msg)) { -- pfkeystat.out_tooshort++; -+ vnet->pfkeystat.out_tooshort++; - error = EINVAL; - goto end; - } - - if (m->m_len < sizeof(struct sadb_msg)) { - if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { -- pfkeystat.out_nomem++; -+ vnet->pfkeystat.out_nomem++; - error = ENOBUFS; - goto end; - } -@@ -118,9 +120,9 @@ - KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); - - msg = mtod(m, struct sadb_msg *); -- pfkeystat.out_msgtype[msg->sadb_msg_type]++; -+ vnet->pfkeystat.out_msgtype[msg->sadb_msg_type]++; - if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { -- pfkeystat.out_invlen++; -+ vnet->pfkeystat.out_invlen++; - error = EINVAL; - goto end; - } -@@ -140,13 +142,17 @@ - * send message to the socket. - */ - static int --key_sendup0(rp, m, promisc) -+key_sendup0(rp, m, promisc, vnet) - struct rawcb *rp; - struct mbuf *m; - int promisc; -+ struct vnet *vnet; - { - int error; - -+ if (vnet == NULL) -+ panic("key_sendup0: NULL vnet was passed.\n"); -+ - if (promisc) { - struct sadb_msg *pmsg; - -@@ -154,7 +160,7 @@ - if (m && m->m_len < sizeof(struct sadb_msg)) - m = m_pullup(m, sizeof(struct sadb_msg)); - if (!m) { -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - m_freem(m); - return ENOBUFS; - } -@@ -167,12 +173,12 @@ - pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); - /* pid and seq? */ - -- pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; -+ vnet->pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; - } - - if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, - m, NULL)) { -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - m_freem(m); - error = ENOBUFS; - } else -@@ -196,6 +202,8 @@ - /* sanity check */ - if (so == 0 || msg == 0) - panic("key_sendup: NULL pointer was passed.\n"); -+ if (vnet == NULL) -+ panic("key_sendup: NULL vnet was passed.\n"); - - KEYDEBUG(KEYDEBUG_KEY_DUMP, - printf("key_sendup: \n"); -@@ -205,9 +213,9 @@ - * we increment statistics here, just in case we have ENOBUFS - * in this function. - */ -- pfkeystat.in_total++; -- pfkeystat.in_bytes += len; -- pfkeystat.in_msgtype[msg->sadb_msg_type]++; -+ vnet->pfkeystat.in_total++; -+ vnet->pfkeystat.in_bytes += len; -+ vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++; - - /* - * Get mbuf chain whenever possible (not clusters), -@@ -229,7 +237,7 @@ - n->m_len = MLEN; - } - if (!n) { -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - return ENOBUFS; - } - if (tlen >= MCLBYTES) { /*XXX better threshold? */ -@@ -237,7 +245,7 @@ - if ((n->m_flags & M_EXT) == 0) { - m_free(n); - m_freem(m); -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - return ENOBUFS; - } - n->m_len = MCLBYTES; -@@ -260,9 +268,9 @@ - m_copyback(m, 0, len, (caddr_t)msg); - - /* avoid duplicated statistics */ -- pfkeystat.in_total--; -- pfkeystat.in_bytes -= len; -- pfkeystat.in_msgtype[msg->sadb_msg_type]--; -+ vnet->pfkeystat.in_total--; -+ vnet->pfkeystat.in_bytes -= len; -+ vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]--; - - return key_sendup_mbuf(so, m, target, vnet); - } -@@ -285,14 +293,16 @@ - panic("key_sendup_mbuf: NULL pointer was passed.\n"); - if (so == NULL && target == KEY_SENDUP_ONE) - panic("key_sendup_mbuf: NULL pointer was passed.\n"); -+ if (vnet == NULL) -+ panic("key_sendup_mbuf: NULL vnet pointer was passed.\n"); - -- pfkeystat.in_total++; -- pfkeystat.in_bytes += m->m_pkthdr.len; -+ vnet->pfkeystat.in_total++; -+ vnet->pfkeystat.in_bytes += m->m_pkthdr.len; - if (m->m_len < sizeof(struct sadb_msg)) { - #if 1 - m = m_pullup(m, sizeof(struct sadb_msg)); - if (m == NULL) { -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - return ENOBUFS; - } - #else -@@ -302,7 +312,7 @@ - if (m->m_len >= sizeof(struct sadb_msg)) { - struct sadb_msg *msg; - msg = mtod(m, struct sadb_msg *); -- pfkeystat.in_msgtype[msg->sadb_msg_type]++; -+ vnet->pfkeystat.in_msgtype[msg->sadb_msg_type]++; - } - - LIST_FOREACH(rp, &vnet->rawcb_list, list) -@@ -323,7 +333,7 @@ - */ - if (((struct keycb *)rp)->kp_promisc) { - if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { -- (void)key_sendup0(rp, n, 1); -+ (void)key_sendup0(rp, n, 1, vnet); - n = NULL; - } - } -@@ -347,18 +357,18 @@ - sendup++; - break; - } -- pfkeystat.in_msgtarget[target]++; -+ vnet->pfkeystat.in_msgtarget[target]++; - - if (!sendup) - continue; - - if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { - m_freem(m); -- pfkeystat.in_nomem++; -+ vnet->pfkeystat.in_nomem++; - return ENOBUFS; - } - -- if ((error = key_sendup0(rp, n, 0)) != 0) { -+ if ((error = key_sendup0(rp, n, 0, vnet)) != 0) { - m_freem(m); - return error; - } -@@ -367,7 +377,7 @@ - } - - if (so) { -- error = key_sendup0(sotorawcb(so), m, 0); -+ error = key_sendup0(sotorawcb(so), m, 0, vnet); - m = NULL; - } else { - error = 0; -@@ -397,9 +407,12 @@ - static int - key_attach(struct socket *so, int proto, struct proc *p) - { -+ struct vnet *vnet = so->so_vnet; - struct keycb *kp; - int s, error; - -+ if (vnet == NULL) -+ panic("key_attach: NULL vnet was passed.\n"); - if (sotorawcb(so) != 0) - return EISCONN; /* XXX panic? */ - kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */ -@@ -428,8 +441,8 @@ - kp->kp_promisc = kp->kp_registered = 0; - - if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ -- key_cb.key_count++; -- key_cb.any_count++; -+ vnet->key_cb.key_count++; -+ vnet->key_cb.any_count++; - kp->kp_raw.rcb_laddr = &key_src; - kp->kp_raw.rcb_faddr = &key_dst; - soisconnected(so); -@@ -474,15 +487,18 @@ - static int - key_detach(struct socket *so) - { -+ struct vnet *vnet = so->so_vnet; - struct keycb *kp = (struct keycb *)sotorawcb(so); - int s, error; - -+ if (vnet == NULL) -+ panic("key_detach: NULL vnet from sock."); - s = splnet(); - if (kp != 0) { - if (kp->kp_raw.rcb_proto.sp_protocol - == PF_KEY) /* XXX: AF_KEY */ -- key_cb.key_count--; -- key_cb.any_count--; -+ vnet->key_cb.key_count--; -+ vnet->key_cb.any_count--; - - key_freereg(so); - } -@@ -585,13 +601,13 @@ - { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, - 0, key_output, raw_ctlinput, 0, - 0, -- raw_init, 0, 0, 0, -+ raw_init, raw_destroy, 0, 0, 0, - &key_usrreqs - } - }; - - struct domain keydomain = -- { PF_KEY, "key", key_init, 0, 0, -+ { PF_KEY, "key", key_init, key_destroy, 0, 0, - keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] }; - - DOMAIN_SET(key); -diff -urN sys/netkey/keysock.h sys.CORE/netkey/keysock.h ---- sys/netkey/keysock.h Wed Jan 31 15:57:05 2007 -+++ sys.CORE/netkey/keysock.h Wed Jan 31 16:02:43 2007 -@@ -69,8 +69,6 @@ - int kp_registered; /* registered socket */ - }; - --extern struct pfkeystat pfkeystat; -- - extern int key_output __P((struct mbuf *, ...)); - extern int key_usrreq __P((struct socket *, - int, struct mbuf *, struct mbuf *, struct mbuf *)); diff --git a/kernel/freebsd/README.txt b/kernel/freebsd/README.txt deleted file mode 100644 index f58d7f7b..00000000 --- a/kernel/freebsd/README.txt +++ /dev/null @@ -1,24 +0,0 @@ -CORE kernel patches - -For information on the kernel modules ng_pipe and ng_wlan, see the README files in their respective directories. You should run the make && make install from -the module directories for CORE to work properly. - -FreeBSD 8.x requires the small patches to allow per-node directories. - -The FreeBSD 7.x version of CORE does not require the patch included here. -Instead you should download the latest vimage_7 kernel from: - http://imunes.net/virtnet/ - -The FreeBSD 4.11 version of CORE requires the included patch to work. See the -CORE manual for patching details. - -ng_pipe module you should install with FreeBSD 4.11 or 7.x -ng_wlan module you should install with FreeBSD 4.11 or 7.x -4.11-R-CORE.diff patch you should use with FreeBSD 4.11 -freebsd7-config-CORE config that you may use with vimage_7 kernels -freebsd7-config-COREDEBUG debugging config for use with vimage_7 kernels -vimage_7-CORE.diff patch to add multicast routing to vimage_7_20081015 -imunes-8.0-RELEASE.diff per-node directories, persistent hub/switch, and - traffic snopping for wireshark for FreeBSD 8.0 -symlinks-8.1-RELEASE.diff per-node directories for FreeBSD 8.1 - diff --git a/kernel/freebsd/freebsd7-config-CORE b/kernel/freebsd/freebsd7-config-CORE deleted file mode 100644 index 6601c866..00000000 --- a/kernel/freebsd/freebsd7-config-CORE +++ /dev/null @@ -1,20 +0,0 @@ -# -# VIMAGE - sample kernel configuration file with a virtualized network stack -# configure. -# -# $FreeBSD$ -# -include GENERIC -ident CORE - -options IPSEC -device crypto -options VIMAGE -options IPFIREWALL -options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default - -# -# Some kernel subsystems and functions don't yet compile with VIMAGE. Remove -# from the configuration for now. -# -nooptions SCTP diff --git a/kernel/freebsd/freebsd7-config-COREDEBUG b/kernel/freebsd/freebsd7-config-COREDEBUG deleted file mode 100644 index b5314659..00000000 --- a/kernel/freebsd/freebsd7-config-COREDEBUG +++ /dev/null @@ -1,22 +0,0 @@ -# -# VIMAGE - sample kernel configuration file with a virtualized network stack -# configure. -# -# $FreeBSD$ -# -include GENERIC -ident COREDEBUG - -device crypto -options IPSEC -options VIMAGE -options DDB -options GDB -options KDB -options KDB_TRACE - -# -# Some kernel subsystems and functions don't yet compile with VIMAGE. Remove -# from the configuration for now. -# -nooptions SCTP diff --git a/kernel/freebsd/freebsd8-config-CORE b/kernel/freebsd/freebsd8-config-CORE deleted file mode 100644 index 06d4d606..00000000 --- a/kernel/freebsd/freebsd8-config-CORE +++ /dev/null @@ -1,11 +0,0 @@ -# this is the FreeBSD 8.x kernel configuration file for CORE -include GENERIC -ident CORE - -options VIMAGE -nooptions SCTP -options IPSEC -device crypto - -options IPFIREWALL -options IPFIREWALL_DEFAULT_TO_ACCEPT diff --git a/kernel/freebsd/imunes-8.0-RELEASE.diff b/kernel/freebsd/imunes-8.0-RELEASE.diff deleted file mode 100644 index 0492751b..00000000 --- a/kernel/freebsd/imunes-8.0-RELEASE.diff +++ /dev/null @@ -1,372 +0,0 @@ -# This patch is from http://imunes.net/imunes-8.0-RC3.diff -# -# This patch enables per-node directories, persistent hub/switch nodes, traffic -# snooping for wireshark, and disallows vlan interfaces within a jail. -diff -drup src-org/sys/kern/vfs_lookup.c src/sys/kern/vfs_lookup.c ---- src-org/sys/kern/vfs_lookup.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/kern/vfs_lookup.c 2009-11-11 12:46:02.000000000 +0000 -@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_loo - #include - #endif - -+#include -+ - #include - #include - -@@ -72,6 +74,19 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, en - "unsigned long"); - SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); - -+#ifdef VIMAGE -+#define IMUNES_SYMLINK_HACK -+#endif -+ -+#ifdef IMUNES_SYMLINK_HACK -+static VNET_DEFINE(int, morphing_symlinks); -+#define V_morphing_symlinks VNET(morphing_symlinks) -+ -+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW, -+ &VNET_NAME(morphing_symlinks), 0, -+ "Resolve @ to vimage name in symlinks"); -+#endif -+ - /* - * Allocation zone for namei - */ -@@ -333,6 +348,44 @@ namei(struct nameidata *ndp) - error = ENOENT; - break; - } -+#ifdef IMUNES_SYMLINK_HACK -+ /* -+ * If the symbolic link includes a special character '@', -+ * and V_morphing_symlinks is set, substitute the first -+ * occurence of '@' with full path to jail / vimage name. -+ * If the full path includes subhierarchies, s/./\// when -+ * expanding '@' to jail / vimage name. -+ * -+ * XXX revisit buffer length checking. -+ */ -+ CURVNET_SET_QUIET(TD_TO_VNET(curthread)); -+ if (V_morphing_symlinks) { -+ char *sp = strchr(cp, '@'); -+ -+ if (sp) { -+ char *vname = td->td_ucred->cr_prison->pr_name; -+ int vnamelen = strlen(vname); -+ int i; -+ -+ if (vnamelen >= auio.uio_resid) { -+ if (ndp->ni_pathlen > 1) -+ uma_zfree(namei_zone, cp); -+ error = ENAMETOOLONG; -+ CURVNET_RESTORE(); -+ break; -+ } -+ bcopy(sp + 1, sp + vnamelen, -+ linklen - (sp - cp)); -+ bcopy(td->td_ucred->cr_prison->pr_name, -+ sp, vnamelen); -+ linklen += (vnamelen - 1); -+ for (i = 0; i < vnamelen; i++) -+ if (sp[i] == '.') -+ sp[i] = '/'; -+ } -+ } -+ CURVNET_RESTORE(); -+#endif - if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { - if (ndp->ni_pathlen > 1) - uma_zfree(namei_zone, cp); -diff -drup src-org/sys/net/bpf.c src/sys/net/bpf.c ---- src-org/sys/net/bpf.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/net/bpf.c 2009-11-11 12:46:02.000000000 +0000 -@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/net/bpf.c,v - #include - #include - #include -+#include - #include - #include - #include -@@ -1435,9 +1436,34 @@ bpf_setif(struct bpf_d *d, struct ifreq - struct bpf_if *bp; - struct ifnet *theywant; - -+#define XVNET_BPF_SNOOPING -+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) -+ struct vnet *target_vnet = curvnet; -+ char *c; -+ -+ /* Attempt to attach to an ifnet in a foreign vnet, specified as @ */ -+ c = rindex(ifr->ifr_name, '@'); -+ if ( c != NULL ) { -+ struct prison *target_pr; -+ -+ *c++ = 0; -+ if (!isascii(*c) && !isdigit(*c)) -+ return ENXIO; -+ target_pr = prison_find_name(curthread->td_ucred->cr_prison, c); -+ if (target_pr == NULL) -+ return ENXIO; -+ target_vnet = target_pr->pr_vnet; -+ } -+ CURVNET_SET_QUIET(target_vnet); -+#endif -+ - theywant = ifunit(ifr->ifr_name); -- if (theywant == NULL || theywant->if_bpf == NULL) -+ if (theywant == NULL || theywant->if_bpf == NULL) { -+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) -+ CURVNET_RESTORE(); -+#endif - return (ENXIO); -+ } - - bp = theywant->if_bpf; - -@@ -1477,6 +1503,9 @@ bpf_setif(struct bpf_d *d, struct ifreq - BPFD_LOCK(d); - reset_d(d); - BPFD_UNLOCK(d); -+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING) -+ CURVNET_RESTORE(); -+#endif - return (0); - } - -diff -drup src-org/sys/net/if.c src/sys/net/if.c ---- src-org/sys/net/if.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/net/if.c 2009-11-11 12:46:02.000000000 +0000 -@@ -813,6 +813,14 @@ if_detach_internal(struct ifnet *ifp, in - struct ifnet *iter; - int found = 0; - -+ /* -+ * Detach from any vlan, bridge or lagg ifnets linked to us. -+ * A small though unlikely window for a race from here to ifp -+ * unlinking from ifnet list is possible, hence we repeat the -+ * procedure once again further bellow. XXX. -+ */ -+ EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); -+ - IFNET_WLOCK(); - TAILQ_FOREACH(iter, &V_ifnet, if_link) - if (iter == ifp) { -diff -drup src-org/sys/net/if_llatbl.c src/sys/net/if_llatbl.c ---- src-org/sys/net/if_llatbl.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/net/if_llatbl.c 2009-11-11 12:53:49.000000000 +0000 -@@ -57,11 +57,14 @@ __FBSDID("$FreeBSD: src/sys/net/if_llatb - - MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables"); - --static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables); -+static VNET_DEFINE(SLIST_HEAD(, lltable), lltables); -+#define V_lltables VNET(lltables) - - extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *, - u_char *); - -+static void vnet_lltable_init(void); -+ - struct rwlock lltable_rwlock; - RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock"); - -@@ -75,7 +78,7 @@ lltable_sysctl_dumparp(int af, struct sy - int error = 0; - - LLTABLE_RLOCK(); -- SLIST_FOREACH(llt, &lltables, llt_link) { -+ SLIST_FOREACH(llt, &V_lltables, llt_link) { - if (llt->llt_af == af) { - error = llt->llt_dump(llt, wr); - if (error != 0) -@@ -157,7 +160,7 @@ lltable_free(struct lltable *llt) - KASSERT(llt != NULL, ("%s: llt is NULL", __func__)); - - LLTABLE_WLOCK(); -- SLIST_REMOVE(&lltables, llt, lltable, llt_link); -+ SLIST_REMOVE(&V_lltables, llt, lltable, llt_link); - LLTABLE_WUNLOCK(); - - for (i=0; i < LLTBL_HASHTBL_SIZE; i++) { -@@ -180,7 +183,7 @@ lltable_drain(int af) - register int i; - - LLTABLE_RLOCK(); -- SLIST_FOREACH(llt, &lltables, llt_link) { -+ SLIST_FOREACH(llt, &V_lltables, llt_link) { - if (llt->llt_af != af) - continue; - -@@ -202,7 +205,7 @@ lltable_prefix_free(int af, struct socka - struct lltable *llt; - - LLTABLE_RLOCK(); -- SLIST_FOREACH(llt, &lltables, llt_link) { -+ SLIST_FOREACH(llt, &V_lltables, llt_link) { - if (llt->llt_af != af) - continue; - -@@ -232,7 +235,7 @@ lltable_init(struct ifnet *ifp, int af) - LIST_INIT(&llt->lle_head[i]); - - LLTABLE_WLOCK(); -- SLIST_INSERT_HEAD(&lltables, llt, llt_link); -+ SLIST_INSERT_HEAD(&V_lltables, llt, llt_link); - LLTABLE_WUNLOCK(); - - return (llt); -@@ -302,7 +305,7 @@ lla_rt_output(struct rt_msghdr *rtm, str - - /* XXX linked list may be too expensive */ - LLTABLE_RLOCK(); -- SLIST_FOREACH(llt, &lltables, llt_link) { -+ SLIST_FOREACH(llt, &V_lltables, llt_link) { - if (llt->llt_af == dst->sa_family && - llt->llt_ifp == ifp) - break; -@@ -367,3 +370,12 @@ lla_rt_output(struct rt_msghdr *rtm, str - - return (error); - } -+ -+static void -+vnet_lltable_init() -+{ -+ -+ SLIST_INIT(&V_lltables); -+} -+VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, vnet_lltable_init, NULL); -+ -diff -drup src-org/sys/net/if_vlan.c src/sys/net/if_vlan.c ---- src-org/sys/net/if_vlan.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/net/if_vlan.c 2009-11-11 12:46:02.000000000 +0000 -@@ -1359,6 +1359,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd - error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); - if (error) - break; -+#ifdef VIMAGE -+ if (ifp->if_home_vnet != ifp->if_vnet) { -+ error = EPERM; -+ break; -+ } -+#endif - if (vlr.vlr_parent[0] == '\0') { - vlan_unconfig(ifp); - break; -@@ -1386,6 +1392,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd - - case SIOCGETVLAN: - bzero(&vlr, sizeof(vlr)); -+#ifdef VIMAGE -+ if (ifp->if_home_vnet != ifp->if_vnet) { -+ error = EPERM; -+ break; -+ } -+#endif - VLAN_LOCK(); - if (TRUNK(ifv) != NULL) { - strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname, -diff -drup src-org/sys/netgraph/ng_bridge.c src/sys/netgraph/ng_bridge.c ---- src-org/sys/netgraph/ng_bridge.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/netgraph/ng_bridge.c 2009-11-11 12:46:02.000000000 +0000 -@@ -105,6 +105,7 @@ struct ng_bridge_private { - u_int numBuckets; /* num buckets in table */ - u_int hashMask; /* numBuckets - 1 */ - int numLinks; /* num connected links */ -+ int persistent; /* can exist w/o any hooks */ - struct callout timer; /* one second periodic timer */ - }; - typedef struct ng_bridge_private *priv_p; -@@ -345,13 +346,13 @@ static int - ng_bridge_newhook(node_p node, hook_p hook, const char *name) - { - const priv_p priv = NG_NODE_PRIVATE(node); -+ int linkNum = -1; - - /* Check for a link hook */ - if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX, - strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) { - const char *cp; - char *eptr; -- u_long linkNum; - - cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX); - if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0')) -@@ -359,6 +360,12 @@ ng_bridge_newhook(node_p node, hook_p ho - linkNum = strtoul(cp, &eptr, 10); - if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS) - return (EINVAL); -+ } else if (strcmp(name, "anchor") == 0) { -+ linkNum = 0; -+ priv->persistent = 1; -+ } -+ -+ if (linkNum >= 0 ) { - if (priv->links[linkNum] != NULL) - return (EISCONN); - priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]), -@@ -366,7 +373,7 @@ ng_bridge_newhook(node_p node, hook_p ho - if (priv->links[linkNum] == NULL) - return (ENOMEM); - priv->links[linkNum]->hook = hook; -- NG_HOOK_SET_PRIVATE(hook, (void *)linkNum); -+ NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)linkNum); - priv->numLinks++; - return (0); - } -@@ -799,7 +806,8 @@ ng_bridge_disconnect(hook_p hook) - - /* If no more hooks, go away */ - if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) -- && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) { -+ && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) -+ && !priv->persistent) { - ng_rmnode_self(NG_HOOK_NODE(hook)); - } - return (0); -diff -drup src-org/sys/netgraph/ng_hub.c src/sys/netgraph/ng_hub.c ---- src-org/sys/netgraph/ng_hub.c 2009-10-25 01:10:29.000000000 +0000 -+++ src/sys/netgraph/ng_hub.c 2009-11-11 12:46:02.000000000 +0000 -@@ -37,6 +37,7 @@ - #include - - static ng_constructor_t ng_hub_constructor; -+static ng_newhook_t ng_hub_newhook; - static ng_rcvdata_t ng_hub_rcvdata; - static ng_disconnect_t ng_hub_disconnect; - -@@ -44,6 +45,7 @@ static struct ng_type ng_hub_typestruct - .version = NG_ABI_VERSION, - .name = NG_HUB_NODE_TYPE, - .constructor = ng_hub_constructor, -+ .newhook = ng_hub_newhook, - .rcvdata = ng_hub_rcvdata, - .disconnect = ng_hub_disconnect, - }; -@@ -57,6 +59,14 @@ ng_hub_constructor(node_p node) - return (0); - } - -+static int -+ng_hub_newhook(node_p node, hook_p hook, const char *name) -+{ -+ if (strcmp(name, "anchor") == 0) -+ node->nd_private = (void *) 1; -+ return (0); -+} -+ - static int - ng_hub_rcvdata(hook_p hook, item_p item) - { -@@ -94,7 +104,7 @@ ng_hub_disconnect(hook_p hook) - { - - if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && -- NG_NODE_IS_VALID(NG_HOOK_NODE(hook))) -+ NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !hook->hk_node->nd_private) - ng_rmnode_self(NG_HOOK_NODE(hook)); - return (0); - } diff --git a/kernel/freebsd/ng_pipe/Makefile b/kernel/freebsd/ng_pipe/Makefile deleted file mode 100644 index 561097c3..00000000 --- a/kernel/freebsd/ng_pipe/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -# (c)2008 the Boeing Company -# -# modified ng_pipe node -# -.if !defined(PLATFORM) -#PLATFORM=i386 -PLATFORM=amd64 -.endif - -CFLAGS=-DBOEING_WLAN -I/usr/src/sys/${PLATFORM}/compile/CORE - -KMOD= ng_pipe - -SRCS= ng_pipe.c - -#MAN= ng_pipe.4 - -# FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0" -#.if defined(OSTYPE) -#.if (${OSTYPE} == "FreeBSD") -#CFLAGS+=-DFREEBSD411 -#SRCS= ng_pipe_freebsd4.c -#.endif -#.endif - -.include diff --git a/kernel/freebsd/ng_pipe/README b/kernel/freebsd/ng_pipe/README deleted file mode 100644 index 43e090de..00000000 --- a/kernel/freebsd/ng_pipe/README +++ /dev/null @@ -1,21 +0,0 @@ - -ng_pipe FreeBSD kernel module - -See the copyright statement at the top of the source file. -Copyright (c) 2004, 2005, 2007 University of Zagreb -Copyright (c) 2007 FreeBSD Foundation -(c) 2008 the Boeing Company -modifications: Jeff Ahrenholz - -More complete documentation is available in the ng_pipe(4) man page. - -This version of ng_pipe has been modified as follows: -- added burst rate (or burstiness) which is the probability that the next packet - will be dropped given an error with the current packet, 0 to 100 -- added jitter effect, which randomizes the delay an additional amount from - 0 to jitter microseconds -- ng_wlan support added, to remove and read mbuf tags containing wlan link - effect information -- bugfix: random number generation improved from defective modulo algorithm -- bugfix: fixed mbuf dangling pointer reference when ng_pipe has both duplicates - and errors configured diff --git a/kernel/freebsd/ng_pipe/ng_pipe.c b/kernel/freebsd/ng_pipe/ng_pipe.c deleted file mode 100644 index 3adeaff7..00000000 --- a/kernel/freebsd/ng_pipe/ng_pipe.c +++ /dev/null @@ -1,1170 +0,0 @@ -/* - * Copyright (c) 2004-2008 University of Zagreb - * Copyright (c) 2007-2008 FreeBSD Foundation - * - * This software was developed by the University of Zagreb and the - * FreeBSD Foundation under sponsorship by the Stichting NLnet and the - * FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * This node permits simple traffic shaping by emulating bandwidth - * and delay, as well as random packet losses. - * The node has two hooks, upper and lower. Traffic flowing from upper to - * lower hook is referenced as downstream, and vice versa. Parameters for - * both directions can be set separately, except for delay. - */ - - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include -#include -#include - -#ifdef BOEING_WLAN -#include "ng_pipe.h" -#include "../ng_wlan/ng_wlan.h" -#include "../ng_wlan/ng_wlan_tag.h" -#else -#include -#endif /* BOEING_WLAN */ - -static MALLOC_DEFINE(M_NG_PIPE, "ng_pipe", "ng_pipe"); - -struct mtx ng_pipe_giant; - -/* Packet header struct */ -struct ngp_hdr { - TAILQ_ENTRY(ngp_hdr) ngp_link; /* next pkt in queue */ - struct timeval when; /* this packet's due time */ - struct mbuf *m; /* ptr to the packet data */ -}; -TAILQ_HEAD(p_head, ngp_hdr); - -/* FIFO queue struct */ -struct ngp_fifo { - TAILQ_ENTRY(ngp_fifo) fifo_le; /* list of active queues only */ - struct p_head packet_head; /* FIFO queue head */ - u_int32_t hash; /* flow signature */ - struct timeval vtime; /* virtual time, for WFQ */ - u_int32_t rr_deficit; /* for DRR */ - u_int32_t packets; /* # of packets in this queue */ -}; - -/* Per hook info */ -struct hookinfo { - hook_p hook; - int noqueue; /* bypass any processing */ - TAILQ_HEAD(, ngp_fifo) fifo_head; /* FIFO queues */ - TAILQ_HEAD(, ngp_hdr) qout_head; /* delay queue head */ - LIST_ENTRY(hookinfo) active_le; /* active hooks */ - struct timeval qin_utime; - struct ng_pipe_hookcfg cfg; - struct ng_pipe_hookrun run; - struct ng_pipe_hookstat stats; - uint64_t *ber_p; /* loss_p(BER,psize) map */ -}; - -/* Per node info */ -struct node_priv { - u_int64_t delay; - u_int32_t overhead; - u_int32_t header_offset; - struct hookinfo lower; - struct hookinfo upper; -}; -typedef struct node_priv *priv_p; - -/* Macro for calculating the virtual time for packet dequeueing in WFQ */ -#define FIFO_VTIME_SORT(plen) \ - if (hinfo->cfg.wfq && hinfo->cfg.bandwidth) { \ - ngp_f->vtime.tv_usec = now->tv_usec + ((uint64_t) (plen) \ - + priv->overhead ) * hinfo->run.fifo_queues * \ - 8000000 / hinfo->cfg.bandwidth; \ - ngp_f->vtime.tv_sec = now->tv_sec + \ - ngp_f->vtime.tv_usec / 1000000; \ - ngp_f->vtime.tv_usec = ngp_f->vtime.tv_usec % 1000000; \ - TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) \ - if (ngp_f1->vtime.tv_sec > ngp_f->vtime.tv_sec || \ - (ngp_f1->vtime.tv_sec == ngp_f->vtime.tv_sec && \ - ngp_f1->vtime.tv_usec > ngp_f->vtime.tv_usec)) \ - break; \ - if (ngp_f1 == NULL) \ - TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ - else \ - TAILQ_INSERT_BEFORE(ngp_f1, ngp_f, fifo_le); \ - } else \ - TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ - - -static void parse_cfg(struct ng_pipe_hookcfg *, struct ng_pipe_hookcfg *, - struct hookinfo *, priv_p); -static void pipe_dequeue(struct hookinfo *, struct timeval *); -static void pipe_scheduler(void *); -static void pipe_poll(void); -static int ngp_modevent(module_t, int, void *); - -/* linked list of active "pipe" hooks */ -static LIST_HEAD(, hookinfo) active_head; -static int active_gen_id = 0; - -/* timeout handle for pipe_scheduler */ -static struct callout polling_timer; - -/* zone for storing ngp_hdr-s */ -static uma_zone_t ngp_zone; - -/* Netgraph methods */ -static ng_constructor_t ngp_constructor; -static ng_rcvmsg_t ngp_rcvmsg; -static ng_shutdown_t ngp_shutdown; -static ng_newhook_t ngp_newhook; -static ng_rcvdata_t ngp_rcvdata; -static ng_disconnect_t ngp_disconnect; - -/* Parse type for struct ng_pipe_hookstat */ -static const struct ng_parse_struct_field - ng_pipe_hookstat_type_fields[] = NG_PIPE_HOOKSTAT_INFO; -static const struct ng_parse_type ng_pipe_hookstat_type = { - &ng_parse_struct_type, - &ng_pipe_hookstat_type_fields -}; - -/* Parse type for struct ng_pipe_stats */ -static const struct ng_parse_struct_field ng_pipe_stats_type_fields[] = - NG_PIPE_STATS_INFO(&ng_pipe_hookstat_type); -static const struct ng_parse_type ng_pipe_stats_type = { - &ng_parse_struct_type, - &ng_pipe_stats_type_fields -}; - -/* Parse type for struct ng_pipe_hookrun */ -static const struct ng_parse_struct_field - ng_pipe_hookrun_type_fields[] = NG_PIPE_HOOKRUN_INFO; -static const struct ng_parse_type ng_pipe_hookrun_type = { - &ng_parse_struct_type, - &ng_pipe_hookrun_type_fields -}; - -/* Parse type for struct ng_pipe_run */ -static const struct ng_parse_struct_field - ng_pipe_run_type_fields[] = NG_PIPE_RUN_INFO(&ng_pipe_hookrun_type); -static const struct ng_parse_type ng_pipe_run_type = { - &ng_parse_struct_type, - &ng_pipe_run_type_fields -}; - -/* Parse type for struct ng_pipe_hookcfg */ -static const struct ng_parse_struct_field - ng_pipe_hookcfg_type_fields[] = NG_PIPE_HOOKCFG_INFO; -static const struct ng_parse_type ng_pipe_hookcfg_type = { - &ng_parse_struct_type, - &ng_pipe_hookcfg_type_fields -}; - -/* Parse type for struct ng_pipe_cfg */ -static const struct ng_parse_struct_field - ng_pipe_cfg_type_fields[] = NG_PIPE_CFG_INFO(&ng_pipe_hookcfg_type); -static const struct ng_parse_type ng_pipe_cfg_type = { - &ng_parse_struct_type, - &ng_pipe_cfg_type_fields -}; - -/* List of commands and how to convert arguments to/from ASCII */ -static const struct ng_cmdlist ngp_cmds[] = { - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_GET_STATS, - .name = "getstats", - .respType = &ng_pipe_stats_type - }, - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_CLR_STATS, - .name = "clrstats" - }, - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_GETCLR_STATS, - .name = "getclrstats", - .respType = &ng_pipe_stats_type - }, - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_GET_RUN, - .name = "getrun", - .respType = &ng_pipe_run_type - }, - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_GET_CFG, - .name = "getcfg", - .respType = &ng_pipe_cfg_type - }, - { - .cookie = NGM_PIPE_COOKIE, - .cmd = NGM_PIPE_SET_CFG, - .name = "setcfg", - .mesgType = &ng_pipe_cfg_type, - }, - { 0 } -}; - -/* Netgraph type descriptor */ -static struct ng_type ng_pipe_typestruct = { - .version = NG_ABI_VERSION, - .name = NG_PIPE_NODE_TYPE, - .mod_event = ngp_modevent, - .constructor = ngp_constructor, - .shutdown = ngp_shutdown, - .rcvmsg = ngp_rcvmsg, - .newhook = ngp_newhook, - .rcvdata = ngp_rcvdata, - .disconnect = ngp_disconnect, - .cmdlist = ngp_cmds -}; -NETGRAPH_INIT(pipe, &ng_pipe_typestruct); - -/* Node constructor */ -static int -ngp_constructor(node_p node) -{ - priv_p priv; - - MALLOC(priv, priv_p, sizeof(*priv), M_NG_PIPE, M_ZERO | M_NOWAIT); - if (priv == NULL) - return (ENOMEM); - NG_NODE_SET_PRIVATE(node, priv); - - return (0); -} - -/* Add a hook */ -static int -ngp_newhook(node_p node, hook_p hook, const char *name) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct hookinfo *hinfo; - - if (strcmp(name, NG_PIPE_HOOK_UPPER) == 0) { - bzero(&priv->upper, sizeof(priv->upper)); - priv->upper.hook = hook; - NG_HOOK_SET_PRIVATE(hook, &priv->upper); - } else if (strcmp(name, NG_PIPE_HOOK_LOWER) == 0) { - bzero(&priv->lower, sizeof(priv->lower)); - priv->lower.hook = hook; - NG_HOOK_SET_PRIVATE(hook, &priv->lower); - } else - return (EINVAL); - - /* Load non-zero initial cfg values */ - hinfo = NG_HOOK_PRIVATE(hook); - hinfo->cfg.qin_size_limit = 50; - hinfo->cfg.fifo = 1; - hinfo->cfg.droptail = 1; - TAILQ_INIT(&hinfo->fifo_head); - TAILQ_INIT(&hinfo->qout_head); - return (0); -} - -/* Receive a control message */ -static int -ngp_rcvmsg(node_p node, item_p item, hook_p lasthook) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_mesg *resp = NULL; - struct ng_mesg *msg; - struct ng_pipe_stats *stats; - struct ng_pipe_run *run; - struct ng_pipe_cfg *cfg; - int error = 0; - - mtx_lock(&ng_pipe_giant); - - NGI_GET_MSG(item, msg); - switch (msg->header.typecookie) { - case NGM_PIPE_COOKIE: - switch (msg->header.cmd) { - case NGM_PIPE_GET_STATS: - case NGM_PIPE_CLR_STATS: - case NGM_PIPE_GETCLR_STATS: - if (msg->header.cmd != NGM_PIPE_CLR_STATS) { - NG_MKRESPONSE(resp, msg, - sizeof(*stats), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - break; - } - stats = (struct ng_pipe_stats *)resp->data; - bcopy(&priv->upper.stats, &stats->downstream, - sizeof(stats->downstream)); - bcopy(&priv->lower.stats, &stats->upstream, - sizeof(stats->upstream)); - } - if (msg->header.cmd != NGM_PIPE_GET_STATS) { - bzero(&priv->upper.stats, - sizeof(priv->upper.stats)); - bzero(&priv->lower.stats, - sizeof(priv->lower.stats)); - } - break; - case NGM_PIPE_GET_RUN: - NG_MKRESPONSE(resp, msg, sizeof(*run), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - break; - } - run = (struct ng_pipe_run *)resp->data; - bcopy(&priv->upper.run, &run->downstream, - sizeof(run->downstream)); - bcopy(&priv->lower.run, &run->upstream, - sizeof(run->upstream)); - break; - case NGM_PIPE_GET_CFG: - NG_MKRESPONSE(resp, msg, sizeof(*cfg), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - break; - } - cfg = (struct ng_pipe_cfg *)resp->data; - bcopy(&priv->upper.cfg, &cfg->downstream, - sizeof(cfg->downstream)); - bcopy(&priv->lower.cfg, &cfg->upstream, - sizeof(cfg->upstream)); - cfg->delay = priv->delay; - cfg->overhead = priv->overhead; - cfg->header_offset = priv->header_offset; - if (cfg->upstream.bandwidth == - cfg->downstream.bandwidth) { - cfg->bandwidth = cfg->upstream.bandwidth; - cfg->upstream.bandwidth = 0; - cfg->downstream.bandwidth = 0; - } else - cfg->bandwidth = 0; - break; - case NGM_PIPE_SET_CFG: - cfg = (struct ng_pipe_cfg *)msg->data; - if (msg->header.arglen != sizeof(*cfg)) { - error = EINVAL; - break; - } - - if (cfg->delay == -1) - priv->delay = 0; - else if (cfg->delay > 0 && cfg->delay < 10000000) - priv->delay = cfg->delay; - - if (cfg->bandwidth == -1) { - priv->upper.cfg.bandwidth = 0; - priv->lower.cfg.bandwidth = 0; - priv->overhead = 0; - } else if (cfg->bandwidth >= 100 && - cfg->bandwidth <= 1000000000) { - priv->upper.cfg.bandwidth = cfg->bandwidth; - priv->lower.cfg.bandwidth = cfg->bandwidth; - if (cfg->bandwidth >= 10000000) - priv->overhead = 8+4+12; /* Ethernet */ - else - priv->overhead = 10; /* HDLC */ - } - - if (cfg->overhead == -1) - priv->overhead = 0; - else if (cfg->overhead > 0 && cfg->overhead < 256) - priv->overhead = cfg->overhead; - - if (cfg->header_offset == -1) - priv->header_offset = 0; - else if (cfg->header_offset > 0 && - cfg->header_offset < 64) - priv->header_offset = cfg->header_offset; - - parse_cfg(&priv->upper.cfg, &cfg->downstream, - &priv->upper, priv); - parse_cfg(&priv->lower.cfg, &cfg->upstream, - &priv->lower, priv); - break; - default: - error = EINVAL; - break; - } - break; - default: - error = EINVAL; - break; - } - NG_RESPOND_MSG(error, node, item, resp); - NG_FREE_MSG(msg); - - mtx_unlock(&ng_pipe_giant); - - return (error); -} - -static void -parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, - struct hookinfo *hinfo, priv_p priv) -{ - - if (new->ber == -1) { - current->ber = 0; - if (hinfo->ber_p) { - FREE(hinfo->ber_p, M_NG_PIPE); - hinfo->ber_p = NULL; - } - } else if (new->ber >= 1 && new->ber <= 1000000000000) { - static const uint64_t one = 0x1000000000000; /* = 2^48 */ - uint64_t p0, p; - uint32_t fsize, i; - - if (hinfo->ber_p == NULL) - MALLOC(hinfo->ber_p, uint64_t *, \ - (MAX_FSIZE + MAX_OHSIZE)*sizeof(uint64_t), \ - M_NG_PIPE, M_NOWAIT); - current->ber = new->ber; - - /* - * For given BER and each frame size N (in bytes) calculate - * the probability P_OK that the frame is clean: - * - * P_OK(BER,N) = (1 - 1/BER)^(N*8) - * - * We use a 64-bit fixed-point format with decimal point - * positioned between bits 47 and 48. - */ - p0 = one - one / new->ber; - p = one; - for (fsize = 0; fsize < MAX_FSIZE + MAX_OHSIZE; fsize++) { - hinfo->ber_p[fsize] = p; - for (i=0; i<8; i++) - p = (p*(p0&0xffff)>>48) + \ - (p*((p0>>16)&0xffff)>>32) + \ - (p*(p0>>32)>>16); - } - } - - if (new->qin_size_limit == -1) - current->qin_size_limit = 0; - else if (new->qin_size_limit >= 5) - current->qin_size_limit = new->qin_size_limit; - - if (new->qout_size_limit == -1) - current->qout_size_limit = 0; - else if (new->qout_size_limit >= 5) - current->qout_size_limit = new->qout_size_limit; - - if (new->duplicate == -1) - current->duplicate = 0; - else if (new->duplicate > 0 && new->duplicate <= 50) - current->duplicate = new->duplicate; - - if (new->fifo) { - current->fifo = 1; - current->wfq = 0; - current->drr = 0; - } - - if (new->wfq) { - current->fifo = 0; - current->wfq = 1; - current->drr = 0; - } - - if (new->drr) { - current->fifo = 0; - current->wfq = 0; - /* DRR quantum */ - if (new->drr >= 32) - current->drr = new->drr; - else - current->drr = 2048; /* default quantum */ - } - - if (new->droptail) { - current->droptail = 1; - current->drophead = 0; - } - - if (new->drophead) { - current->droptail = 0; - current->drophead = 1; - } - - if (new->bandwidth == -1) { - current->bandwidth = 0; - current->fifo = 1; - current->wfq = 0; - current->drr = 0; - } else if (new->bandwidth >= 100 && new->bandwidth <= 1000000000) - current->bandwidth = new->bandwidth; - - if (current->bandwidth | priv->delay | - current->duplicate | current->ber) - hinfo->noqueue = 0; - else - hinfo->noqueue = 1; -} - -/* - * Compute a hash signature for a packet. This function suffers from the - * NIH sindrome, so probably it would be wise to look around what other - * folks have found out to be a good and efficient IP hash function... - */ -static int ip_hash(struct mbuf *m, int offset) -{ - u_int64_t i; - struct ip *ip = (struct ip *)(mtod(m, u_char *) + offset); - - if (m->m_len < sizeof(struct ip) + offset || - ip->ip_v != 4 || ip->ip_hl << 2 != sizeof(struct ip)) - return 0; - - i = ((u_int64_t) ip->ip_src.s_addr ^ - ((u_int64_t) ip->ip_src.s_addr << 13) ^ - ((u_int64_t) ip->ip_dst.s_addr << 7) ^ - ((u_int64_t) ip->ip_dst.s_addr << 19)); - return (i ^ (i >> 32)); -} - -/* - * Receive data on a hook - both in upstream and downstream direction. - * We put the frame on the inbound queue, and try to initiate dequeuing - * sequence immediately. If inbound queue is full, discard one frame - * depending on dropping policy (from the head or from the tail of the - * queue). - */ -static int -ngp_rcvdata(hook_p hook, item_p item) -{ - struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook); - const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); - struct timeval uuptime; - struct timeval *now = &uuptime; - struct ngp_fifo *ngp_f = NULL, *ngp_f1; - struct ngp_hdr *ngp_h = NULL; - struct mbuf *m; - int hash; - int error = 0; - - if (hinfo->noqueue) { - struct hookinfo *dest; - if (hinfo == &priv->lower) - dest = &priv->upper; - else - dest = &priv->lower; - NG_FWD_ITEM_HOOK(error, item, dest->hook); - return error; - } - - mtx_lock(&ng_pipe_giant); - microuptime(now); - - /* - * Attach us to the list of active ng_pipes if this was an empty - * one before, and also update the queue service deadline time. - */ - if (hinfo->run.qin_frames == 0) { - struct timeval *when = &hinfo->qin_utime; - if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec - && when->tv_usec < now->tv_usec)) { - when->tv_sec = now->tv_sec; - when->tv_usec = now->tv_usec; - } - if (hinfo->run.qout_frames == 0) - LIST_INSERT_HEAD(&active_head, hinfo, active_le); - } - - /* Populate the packet header */ - ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); - KASSERT((ngp_h != NULL), ("ngp_h zalloc failed (1)")); - NGI_GET_M(item, m); - KASSERT(m != NULL, ("NGI_GET_M failed")); - ngp_h->m = m; - NG_FREE_ITEM(item); - - if (hinfo->cfg.fifo) - hash = 0; /* all packets go into a single FIFO queue */ - else - hash = ip_hash(m, priv->header_offset); - - /* Find the appropriate FIFO queue for the packet and enqueue it*/ - TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le) - if (hash == ngp_f->hash) - break; - if (ngp_f == NULL) { - ngp_f = uma_zalloc(ngp_zone, M_NOWAIT); - KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (2)")); - TAILQ_INIT(&ngp_f->packet_head); - ngp_f->hash = hash; - ngp_f->packets = 1; - ngp_f->rr_deficit = hinfo->cfg.drr; /* DRR quantum */ - hinfo->run.fifo_queues++; - TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); - FIFO_VTIME_SORT(m->m_pkthdr.len); - } else { - TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); - ngp_f->packets++; - } - hinfo->run.qin_frames++; - hinfo->run.qin_octets += m->m_pkthdr.len; - - /* Discard a frame if inbound queue limit has been reached */ - if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { - struct mbuf *m1; - int longest = 0; - - /* Find the longest queue */ - TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) - if (ngp_f1->packets > longest) { - longest = ngp_f1->packets; - ngp_f = ngp_f1; - } - - /* Drop a frame from the queue head/tail, depending on cfg */ - if (hinfo->cfg.drophead) - ngp_h = TAILQ_FIRST(&ngp_f->packet_head); - else - ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - m1 = ngp_h->m; - uma_zfree(ngp_zone, ngp_h); - hinfo->run.qin_octets -= m1->m_pkthdr.len; - hinfo->stats.in_disc_octets += m1->m_pkthdr.len; - m_freem(m1); - if (--(ngp_f->packets) == 0) { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - uma_zfree(ngp_zone, ngp_f); - hinfo->run.fifo_queues--; - } - hinfo->run.qin_frames--; - hinfo->stats.in_disc_frames++; - } else if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { - struct mbuf *m1; - int longest = 0; - - /* Find the longest queue */ - TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) - if (ngp_f1->packets > longest) { - longest = ngp_f1->packets; - ngp_f = ngp_f1; - } - - /* Drop a frame from the queue head/tail, depending on cfg */ - if (hinfo->cfg.drophead) - ngp_h = TAILQ_FIRST(&ngp_f->packet_head); - else - ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - m1 = ngp_h->m; - uma_zfree(ngp_zone, ngp_h); - hinfo->run.qin_octets -= m1->m_pkthdr.len; - hinfo->stats.in_disc_octets += m1->m_pkthdr.len; - m_freem(m1); - if (--(ngp_f->packets) == 0) { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - uma_zfree(ngp_zone, ngp_f); - hinfo->run.fifo_queues--; - } - hinfo->run.qin_frames--; - hinfo->stats.in_disc_frames++; - } - - /* - * Try to start the dequeuing process immediately. We must - * hold the ng_pipe_giant lock here and pipe_dequeue() will - * release it - */ - pipe_dequeue(hinfo, now); - - return (0); -} - -#ifdef BOEING_WLAN -/* generate a random integer between 1 and max */ -#define pipe_good_random(max) (1 + (random() % max)) -#if 0 -/* generate a good random integer between 1 and max */ -#define pipe_good_random(max) \ - (1 + (int) (max * (random() / (__ULONG_MAX + 1.0)))) -#endif -#endif - -/* - * Dequeueing sequence - we basically do the following: - * 1) Try to extract the frame from the inbound (bandwidth) queue; - * 2) In accordance to BER specified, discard the frame randomly; - * 3) If the frame survives BER, prepend it with delay info and move it - * to outbound (delay) queue; - * 4) Loop to 2) until bandwidth quota for this timeslice is reached, or - * inbound queue is flushed completely; - * 5) Extract the first frame from the outbound queue, if it's time has - * come. Queue the frame for transmission on the outbound hook; - * 6) Loop to 5) until outbound queue is flushed completely, or the next - * frame in the queue is not scheduled to be dequeued yet; - * 7) Transimit all frames queued in 5) - * - * Note: the caller must hold the ng_pipe_giant lock; this function - * returns with the lock released. - */ -static void -pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { - static uint64_t rand, oldrand; - const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hinfo->hook)); - struct hookinfo *dest; - struct ngp_fifo *ngp_f, *ngp_f1; - struct ngp_hdr *ngp_h; - struct timeval *when; - struct mbuf *q_head = NULL; - struct mbuf *q_tail = NULL; - struct mbuf *m; - int error = 0; -#ifdef BOEING_WLAN - struct ngp_hdr *ngp_h1 = NULL; - struct m_tag *tag = NULL; - struct ng_wlan_tag wtag; - static int was_lost = 0; -#endif /* BOEING_WLAN */ - - /* Which one is the destination hook? */ - if (hinfo == &priv->lower) - dest = &priv->upper; - else - dest = &priv->lower; - - /* Bandwidth queue processing */ - while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { - when = &hinfo->qin_utime; - if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec - && when->tv_usec > now->tv_usec)) - break; - - ngp_h = TAILQ_FIRST(&ngp_f->packet_head); - m = ngp_h->m; - -#ifdef BOEING_WLAN - /* Check the first mbuf tag for WLAN data, and remove it */ - tag = m_tag_first(m); - if (tag && (tag->m_tag_cookie == NGM_WLAN_COOKIE) && - (tag->m_tag_id == NG_TAG_WLAN)) { - WLAN_TAG_COPY( (&wtag), tag) - /* enforce maximum parameters */ - if (wtag.delay > NG_WLAN_MAX_DELAY) - wtag.delay = NG_WLAN_MAX_DELAY; - if (wtag.duplicate > NG_WLAN_MAX_DUP) - wtag.duplicate = NG_WLAN_MAX_DUP; - if (wtag.jitter > NG_WLAN_MAX_JITTER) - wtag.jitter = NG_WLAN_MAX_JITTER; - m_tag_delete(m, tag); - } else { - WLAN_TAG_ZERO( (&wtag) ); - } -#endif /* BOEING_WLAN */ - /* Deficit Round Robin (DRR) processing */ - if (hinfo->cfg.drr) { - if (ngp_f->rr_deficit >= m->m_pkthdr.len) { - ngp_f->rr_deficit -= m->m_pkthdr.len; - } else { - ngp_f->rr_deficit += hinfo->cfg.drr; - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - TAILQ_INSERT_TAIL(&hinfo->fifo_head, - ngp_f, fifo_le); - continue; - } - } - - /* - * Either create a duplicate and pass it on, or dequeue - * the original packet... - */ -#ifdef BOEING_WLAN - if (wtag.duplicate && - pipe_good_random(100) <= wtag.duplicate) { - ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); - KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); - ngp_h->m = m_dup(m, M_NOWAIT); - KASSERT(ngp_h->m != NULL, ("m_dup failed")); - m = ngp_h->m; /* Boeing: we are now working with copied - mbuf, leaving original in the queue */ - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.duplicate && - pipe_good_random(100) <= hinfo->cfg.duplicate) {/*Boeing*/ - /* random() % 100 <= hinfo->cfg.duplicate) { */ - ngp_h = uma_zalloc(ngp_zone, M_NOWAIT); - KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); - ngp_h->m = m_dup(m, M_NOWAIT); - KASSERT(ngp_h->m != NULL, ("m_dup failed")); - m = ngp_h->m; /* Boeing: we are now working with copied - mbuf, leaving original in the queue */ - } else { - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - hinfo->run.qin_frames--; - hinfo->run.qin_octets -= m->m_pkthdr.len; - ngp_f->packets--; - } - /* Boeing: now we have valid ngp_h and m pointers */ - - /* Calculate the serialization delay */ -#ifdef BOEING_WLAN - if (wtag.bandwidth) { - hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len - + priv->overhead ) * - 8000000 / wtag.bandwidth; - hinfo->qin_utime.tv_sec += - hinfo->qin_utime.tv_usec / 1000000; - hinfo->qin_utime.tv_usec = - hinfo->qin_utime.tv_usec % 1000000; - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.bandwidth) { - hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len - + priv->overhead ) * - 8000000 / hinfo->cfg.bandwidth; - hinfo->qin_utime.tv_sec += - hinfo->qin_utime.tv_usec / 1000000; - hinfo->qin_utime.tv_usec = - hinfo->qin_utime.tv_usec % 1000000; - } - when = &ngp_h->when; - when->tv_sec = hinfo->qin_utime.tv_sec; - when->tv_usec = hinfo->qin_utime.tv_usec; - - /* Sort / rearrange inbound queues */ - if (ngp_f->packets) { - if (hinfo->cfg.wfq) { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - FIFO_VTIME_SORT(TAILQ_FIRST( - &ngp_f->packet_head)->m->m_pkthdr.len) - } - } else { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - uma_zfree(ngp_zone, ngp_f); - hinfo->run.fifo_queues--; - } - - /* Randomly discard the frame, according to BER setting */ -#ifdef BOEING_WLAN - /* use specified Packet Error Rate setting for random discard */ - if (wtag.per) { - u_int16_t burst, test; - burst = wtag.burst; - if (burst < wtag.per) burst = wtag.per; - if (was_lost) { - test = burst; - } else if ((wtag.per >= 100) || (burst >= 100)) { - test = 100; - } else { - test = wtag.per*(100-burst)/(100-wtag.per); - } - if (pipe_good_random(100) <= test) { - was_lost = 1; - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - uma_zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } - was_lost = 0; - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.ber && - ((oldrand = rand) ^ (rand = random())<<17) >= - hinfo->ber_p[priv->overhead + m->m_pkthdr.len] ) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - uma_zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } - - /* Discard frame if outbound queue size limit exceeded */ - if (hinfo->cfg.qout_size_limit && - hinfo->run.qout_frames>=hinfo->cfg.qout_size_limit) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - uma_zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } - -#ifdef BOEING_WLAN - /* Calculate the propagation delay including jitter */ - if (wtag.jitter) { - when->tv_usec += pipe_good_random(wtag.jitter); - /* overflow handled below... */ - } - when->tv_usec += wtag.delay ? wtag.delay : priv->delay; -#else - /* Calculate the propagation delay */ - when->tv_usec += priv->delay; -#endif /* BOEING_WLAN */ - when->tv_sec += when->tv_usec / 1000000; - when->tv_usec = when->tv_usec % 1000000; - - /* Put the frame into the delay queue */ -#ifdef BOEING_WLAN - /* Because WLAN packets may have varying dequeue times, we need to - * perform sorted queueing; the dequeuing process expects packets in - * the queue that are sorted by time. - */ - TAILQ_FOREACH(ngp_h1, &hinfo->qout_head, ngp_link) { - if (ngp_h1->when.tv_sec > ngp_h->when.tv_sec || - (ngp_h1->when.tv_sec == ngp_h->when.tv_sec && - ngp_h1->when.tv_usec > ngp_h->when.tv_usec)) - break; - } - if (ngp_h1 == NULL) - TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); - else - TAILQ_INSERT_BEFORE(ngp_h1, ngp_h, ngp_link); - /* The original code below just inserts the packet at the - * tail of the queue because the delay time is constant. */ -#else /* BOEING_WLAN */ - TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); -#endif /* BOEING_WLAN */ - hinfo->run.qout_frames++; - hinfo->run.qout_octets += m->m_pkthdr.len; - } - - /* Delay queue processing */ - while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { - struct mbuf *m = ngp_h->m; - -/* BOEING_WLAN: this is why we have sorted the queue input */ - when = &ngp_h->when; - if (when->tv_sec > now->tv_sec || - (when->tv_sec == now->tv_sec && - when->tv_usec > now->tv_usec)) - break; - - /* Update outbound queue stats */ - hinfo->stats.fwd_frames++; - hinfo->stats.fwd_octets += m->m_pkthdr.len; - hinfo->run.qout_frames--; - hinfo->run.qout_octets -= m->m_pkthdr.len; - - /* Dequeue the packet from qout */ - TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); - uma_zfree(ngp_zone, ngp_h); - - /* Enqueue locally for sending downstream */ - if (q_head == NULL) - q_head = m; - if (q_tail) - q_tail->m_nextpkt = m; - q_tail = m; - m->m_nextpkt = NULL; - } - - /* If both queues are empty detach us from the list of active queues */ - if (hinfo->run.qin_frames + hinfo->run.qout_frames == 0) { - LIST_REMOVE(hinfo, active_le); - active_gen_id++; - } - - mtx_unlock(&ng_pipe_giant); - - while ((m = q_head) != NULL) { - q_head = m->m_nextpkt; - m->m_nextpkt = NULL; - NG_SEND_DATA(error, dest->hook, m, meta); - } -} - - -/* - * This routine is called on every clock tick. We poll all nodes/hooks - * for queued frames by calling pipe_dequeue(). - */ -static void -pipe_scheduler(void *arg) -{ - pipe_poll(); - - /* Reschedule */ - callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); -} - - -/* - * Traverse the list of all active hooks and attempt to dequeue - * some packets. Hooks with empty queues are not traversed since - * they are not linked into this list. - */ -static void -pipe_poll(void) -{ - struct hookinfo *hinfo; - struct timeval now; - int old_gen_id = active_gen_id; - - mtx_lock(&ng_pipe_giant); - microuptime(&now); - LIST_FOREACH(hinfo, &active_head, active_le) { - CURVNET_SET(NG_HOOK_NODE(hinfo->hook)->nd_vnet); - pipe_dequeue(hinfo, &now); - CURVNET_RESTORE(); - mtx_lock(&ng_pipe_giant); - if (old_gen_id != active_gen_id) { - /* the list was updated; restart traversing */ - hinfo = LIST_FIRST(&active_head); - if (hinfo == NULL) - break; - old_gen_id = active_gen_id; - continue; - } - } - mtx_unlock(&ng_pipe_giant); -} - - -/* - * Shutdown processing - * - * This is tricky. If we have both a lower and upper hook, then we - * probably want to extricate ourselves and leave the two peers - * still linked to each other. Otherwise we should just shut down as - * a normal node would. - */ -static int -ngp_shutdown(node_p node) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - - if (priv->lower.hook && priv->upper.hook) - ng_bypass(priv->lower.hook, priv->upper.hook); - else { - if (priv->upper.hook != NULL) - ng_rmhook_self(priv->upper.hook); - if (priv->lower.hook != NULL) - ng_rmhook_self(priv->lower.hook); - } - NG_NODE_UNREF(node); - FREE(priv, M_NG_PIPE); - return (0); -} - - -/* - * Hook disconnection - */ -static int -ngp_disconnect(hook_p hook) -{ - struct hookinfo *const hinfo = NG_HOOK_PRIVATE(hook); - struct ngp_fifo *ngp_f; - struct ngp_hdr *ngp_h; - int removed = 0; - - mtx_lock(&ng_pipe_giant); - - KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__)); - hinfo->hook = NULL; - - /* Flush all fifo queues associated with the hook */ - while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { - while ((ngp_h = TAILQ_FIRST(&ngp_f->packet_head))) { - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - m_freem(ngp_h->m); - uma_zfree(ngp_zone, ngp_h); - removed++; - } - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - uma_zfree(ngp_zone, ngp_f); - } - - /* Flush the delay queue */ - while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { - TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); - m_freem(ngp_h->m); - uma_zfree(ngp_zone, ngp_h); - removed++; - } - - /* - * Both queues should be empty by now, so detach us from - * the list of active queues - */ - if (removed) { - LIST_REMOVE(hinfo, active_le); - active_gen_id++; - } - if (hinfo->run.qin_frames + hinfo->run.qout_frames != removed) - printf("Mismatch: queued=%d but removed=%d !?!", - hinfo->run.qin_frames + hinfo->run.qout_frames, removed); - - /* Release the packet loss probability table (BER) */ - if (hinfo->ber_p) - FREE(hinfo->ber_p, M_NG_PIPE); - - mtx_unlock(&ng_pipe_giant); - - return (0); -} - -static int -ngp_modevent(module_t mod, int type, void *unused) -{ - int error = 0; - - switch (type) { - case MOD_LOAD: - ngp_zone = uma_zcreate("ng_pipe", max(sizeof(struct ngp_hdr), - sizeof (struct ngp_fifo)), NULL, NULL, NULL, NULL, - UMA_ALIGN_PTR, 0); - if (ngp_zone == NULL) - panic("ng_pipe: couldn't allocate descriptor zone"); - - mtx_init(&ng_pipe_giant, "ng_pipe_giant", NULL, MTX_DEF); - LIST_INIT(&active_head); - callout_init(&polling_timer, CALLOUT_MPSAFE); - callout_reset(&polling_timer, 1, &pipe_scheduler, NULL); - break; - case MOD_UNLOAD: - callout_drain(&polling_timer); - uma_zdestroy(ngp_zone); - mtx_destroy(&ng_pipe_giant); - break; - default: - error = EOPNOTSUPP; - break; - } - - return (error); -} diff --git a/kernel/freebsd/ng_pipe/ng_pipe.h b/kernel/freebsd/ng_pipe/ng_pipe.h deleted file mode 100644 index fd5f1acf..00000000 --- a/kernel/freebsd/ng_pipe/ng_pipe.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2004, 2007 University of Zagreb - * Copyright (c) 2007 FreeBSD Foundation - * - * This software was developed by the University of Zagreb and the - * FreeBSD Foundation under sponsorship by the Stichting NLnet and the - * FreeBSD Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _NETGRAPH_PIPE_H_ -#define _NETGRAPH_PIPE_H_ - -/* Node type name and magic cookie */ -#define NG_PIPE_NODE_TYPE "pipe" -#define NGM_PIPE_COOKIE 200708191 - -/* Hook names */ -#define NG_PIPE_HOOK_UPPER "upper" -#define NG_PIPE_HOOK_LOWER "lower" - -#define MAX_FSIZE 16384 /* Largest supported frame size, in bytes, for BER */ -#define MAX_OHSIZE 256 /* Largest supported dummy-framing size, in bytes */ - -/* Statistics structure for one hook */ -struct ng_pipe_hookstat { - u_int64_t fwd_octets; - u_int64_t fwd_frames; - u_int64_t in_disc_octets; - u_int64_t in_disc_frames; - u_int64_t out_disc_octets; - u_int64_t out_disc_frames; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_HOOKSTAT_INFO { \ - { "FwdOctets", &ng_parse_uint64_type }, \ - { "FwdFrames", &ng_parse_uint64_type }, \ - { "queueDropOctets", &ng_parse_uint64_type }, \ - { "queueDropFrames", &ng_parse_uint64_type }, \ - { "delayDropOctets", &ng_parse_uint64_type }, \ - { "delayDropFrames", &ng_parse_uint64_type }, \ - { NULL }, \ -} - -/* Statistics structure returned by NGM_PIPE_GET_STATS */ -struct ng_pipe_stats { - struct ng_pipe_hookstat downstream; - struct ng_pipe_hookstat upstream; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_STATS_INFO(hstype) { \ - { "downstream", (hstype) }, \ - { "upstream", (hstype) }, \ - { NULL }, \ -} - -/* Runtime structure for one hook */ -struct ng_pipe_hookrun { - u_int32_t fifo_queues; - u_int32_t qin_octets; - u_int32_t qin_frames; - u_int32_t qout_octets; - u_int32_t qout_frames; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_HOOKRUN_INFO { \ - { "queues", &ng_parse_uint32_type }, \ - { "queuedOctets", &ng_parse_uint32_type }, \ - { "queuedFrames", &ng_parse_uint32_type }, \ - { "delayedOctets", &ng_parse_uint32_type }, \ - { "delayedFrames", &ng_parse_uint32_type }, \ - { NULL }, \ -} - -/* Runtime structure returned by NGM_PIPE_GET_RUN */ -struct ng_pipe_run { - struct ng_pipe_hookrun downstream; - struct ng_pipe_hookrun upstream; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_RUN_INFO(hstype) { \ - { "downstream", (hstype) }, \ - { "upstream", (hstype) }, \ - { NULL }, \ -} - -/* Config structure for one hook */ -struct ng_pipe_hookcfg { - u_int64_t bandwidth; - u_int64_t ber; - u_int32_t qin_size_limit; - u_int32_t qout_size_limit; - u_int32_t duplicate; - u_int32_t fifo; - u_int32_t drr; - u_int32_t wfq; - u_int32_t droptail; - u_int32_t drophead; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_HOOKCFG_INFO { \ - { "bandwidth", &ng_parse_uint64_type }, \ - { "BER", &ng_parse_uint64_type }, \ - { "queuelen", &ng_parse_uint32_type }, \ - { "delaylen", &ng_parse_uint32_type }, \ - { "duplicate", &ng_parse_uint32_type }, \ - { "fifo", &ng_parse_uint32_type }, \ - { "drr", &ng_parse_uint32_type }, \ - { "wfq", &ng_parse_uint32_type }, \ - { "droptail", &ng_parse_uint32_type }, \ - { "drophead", &ng_parse_uint32_type }, \ - { NULL }, \ -} - -/* Config structure returned by NGM_PIPE_GET_CFG */ -struct ng_pipe_cfg { - u_int64_t bandwidth; - u_int64_t delay; - u_int32_t header_offset; - u_int32_t overhead; - struct ng_pipe_hookcfg downstream; - struct ng_pipe_hookcfg upstream; -}; - -/* Keep this in sync with the above structure definition */ -#define NG_PIPE_CFG_INFO(hstype) { \ - { "bandwidth", &ng_parse_uint64_type }, \ - { "delay", &ng_parse_uint64_type }, \ - { "header_offset", &ng_parse_uint32_type }, \ - { "overhead", &ng_parse_uint32_type }, \ - { "downstream", (hstype) }, \ - { "upstream", (hstype) }, \ - { NULL }, \ -} - -/* Netgraph commands */ -enum { - NGM_PIPE_GET_STATS=1, /* get stats */ - NGM_PIPE_CLR_STATS, /* clear stats */ - NGM_PIPE_GETCLR_STATS, /* atomically get and clear stats */ - NGM_PIPE_GET_RUN, /* get current runtime status */ - NGM_PIPE_GET_CFG, /* get configurable parameters */ - NGM_PIPE_SET_CFG, /* set configurable parameters */ -}; - -#endif /* _NETGRAPH_PIPE_H_ */ diff --git a/kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c b/kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c deleted file mode 100644 index 6a3a2716..00000000 --- a/kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * ng_pipe.c - * - * Copyright (c) 2004 University of Zagreb, Croatia - * Copyright (c) 1996-1999 Whistle Communications, Inc. - * All rights reserved. - * - * Subject to the following obligations and disclaimer of warranty, use and - * redistribution of this software, in source or object code forms, with or - * without modifications are expressly permitted by Whistle Communications - * and author; provided, however, that: - * 1. Any and all reproductions of the source or object code must include the - * copyright notice above and the following disclaimer of warranties; and - * 2. No rights are granted, in any manner or form, to use Whistle - * Communications, Inc. trademarks, including the mark "WHISTLE - * COMMUNICATIONS" on advertising, endorsements, or otherwise except as - * such appears in the above copyright notice or in the software. - * - * THIS SOFTWARE IS BEING PROVIDED BY BOTH AUTHOR AND WHISTLE COMMUNICATIONS - * "AS IS", AND TO THE MAXIMUM EXTENT PERMITTED BY LAW, THEY MAKE NO - * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, - * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. - * AUTHOR AND WHISTLE COMMUNICATIONS DO NOT WARRANT, GUARANTEE, OR MAKE - * ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS - * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. - * IN NO EVENT WILL AUTHOR OR WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES - * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING - * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF AUTHOR OR WHISTLE COMMUNICATIONS IS ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* v 1.15 2004/10/25 */ - -/* - * This node permits simple traffic shaping by emulating bandwidth - * and delay, as well as random packet losses. - * The node has two hooks, upper and lower. Traffic flowing from upper to - * lower hook is referenced as downstream, and vice versa. Parameters for - * both directions can be set separately, except for delay. - */ - -/* - * TODO: - * - * - some splimp()s and extra checks are possibly pure paranoia, - * if they prove to be redundant they should be removed. - * - * - update the manpage. - */ - - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "ng_pipe.h" - -#ifdef XCP -#include "xcp_var.h" -#endif - -#ifdef BOEING_WLAN -#include "../ng_wlan/ng_wlan.h" -#include "../ng_wlan/ng_wlan_tag.h" -#endif /* BOEING_WLAN */ - -typedef void idle_polling_t (void); -extern idle_polling_t *idle_polling_h; -extern int cpu_idle_hlt; - -/* Packet header struct */ -struct ngp_hdr { - TAILQ_ENTRY(ngp_hdr) ngp_link; /* next pkt in queue */ - struct timeval when; /* when to dequeue this packet? */ - struct mbuf *m; /* ptr to the actual packet data */ -#ifdef BOEING_WLAN - meta_p meta; /* optional metadata containing link effects from ng_wlan*/ -#endif -}; - -TAILQ_HEAD(p_head ,ngp_hdr); - -/* FIFO queue struct */ -struct ngp_fifo { - TAILQ_ENTRY(ngp_fifo) fifo_le; /* list of active queues only */ - struct p_head packet_head; /* FIFO queue head */ - u_int32_t hash; /* flow signature */ - struct timeval vtime; /* virtual time, for WFQ */ - u_int32_t rr_deficit; /* for DRR */ - u_int32_t packets; /* # of packets in this queue */ -}; - -/* Per hook info */ -struct hookinfo { - hook_p hook; - LIST_ENTRY(hookinfo) hook_le; /* all active ng_pipe instances */ - TAILQ_HEAD(, ngp_fifo) fifo_head; /* this hooks's FIFO queues */ - TAILQ_HEAD(, ngp_hdr) qout_head; /* delay queue head */ - struct timeval qin_utime; - struct ng_pipe_hookcfg cfg; - struct ng_pipe_hookrun run; - struct ng_pipe_hookstat stats; -#ifdef XCP - struct xcp_router_state xcps; -#endif - uint64_t *ber_p; -}; - -/* Per node info */ -struct privdata { - node_p node; - LIST_ENTRY(privdata) node_le; - u_int64_t delay; - u_int32_t overhead; - u_int32_t header_offset; - struct hookinfo lower; - struct hookinfo upper; -}; -typedef struct privdata *sc_p; - -/* Macro for calculating the virtual time for packet dequeueing in WFQ */ -#define FIFO_VTIME_SORT(plen) \ - if (hinfo->cfg.wfq && hinfo->cfg.bandwidth) { \ - ngp_f->vtime.tv_usec = now->tv_usec + ((uint64_t) (plen) \ - + sc->overhead ) * hinfo->run.fifo_queues * \ - 8000000 / hinfo->cfg.bandwidth; \ - ngp_f->vtime.tv_sec = now->tv_sec + \ - ngp_f->vtime.tv_usec / 1000000; \ - ngp_f->vtime.tv_usec = ngp_f->vtime.tv_usec % 1000000; \ - TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) \ - if (ngp_f1->vtime.tv_sec > ngp_f->vtime.tv_sec || \ - (ngp_f1->vtime.tv_sec == ngp_f->vtime.tv_sec && \ - ngp_f1->vtime.tv_usec > ngp_f->vtime.tv_usec)) \ - break; \ - if (ngp_f1 == NULL) \ - TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ - else \ - TAILQ_INSERT_BEFORE(ngp_f1, ngp_f, fifo_le); \ - } else \ - TAILQ_INSERT_TAIL(&hinfo->fifo_head, ngp_f, fifo_le); \ - - -static void parse_cfg(struct ng_pipe_hookcfg *, struct ng_pipe_hookcfg *, - struct hookinfo *); -static void pipe_dequeue(struct hookinfo *, struct timeval *); -static void pipe_scheduler(void); -static void pipe_poll(void); -static int ngp_modevent(module_t, int, void *); - -/* linked list of all "pipe" nodes */ -LIST_HEAD(pipe_node_head, privdata) node_head; - -/* linked list of active "pipe" hooks */ -LIST_HEAD(pipe_hook_head, hookinfo) hook_head; - -/* timeout handle for pipe_scheduler */ -struct callout_handle ds_handle = { 0 }; - -/* saved value of cpu_idle_hlt */ -static int old_cpu_idle_hlt = 0; - -/* VM zone for storing ngp_hdr-s */ -struct vm_zone *ngp_zone; - -/* Netgraph methods */ -static ng_constructor_t ngp_constructor; -static ng_rcvmsg_t ngp_rcvmsg; -static ng_shutdown_t ngp_rmnode; -static ng_newhook_t ngp_newhook; -static ng_rcvdata_t ngp_rcvdata; -static ng_disconnect_t ngp_disconnect; - -/* Parse type for struct ng_pipe_hookstat */ -static const struct ng_parse_struct_field - ng_pipe_hookstat_type_fields[] = NG_PIPE_HOOKSTAT_INFO; -static const struct ng_parse_type ng_pipe_hookstat_type = { - &ng_parse_struct_type, - &ng_pipe_hookstat_type_fields -}; - -/* Parse type for struct ng_pipe_stats */ -static const struct ng_parse_struct_field ng_pipe_stats_type_fields[] = - NG_PIPE_STATS_INFO(&ng_pipe_hookstat_type); -static const struct ng_parse_type ng_pipe_stats_type = { - &ng_parse_struct_type, - &ng_pipe_stats_type_fields -}; - -/* Parse type for struct ng_pipe_hookrun */ -static const struct ng_parse_struct_field - ng_pipe_hookrun_type_fields[] = NG_PIPE_HOOKRUN_INFO; -static const struct ng_parse_type ng_pipe_hookrun_type = { - &ng_parse_struct_type, - &ng_pipe_hookrun_type_fields -}; - -/* Parse type for struct ng_pipe_run */ -static const struct ng_parse_struct_field - ng_pipe_run_type_fields[] = NG_PIPE_RUN_INFO(&ng_pipe_hookrun_type); -static const struct ng_parse_type ng_pipe_run_type = { - &ng_parse_struct_type, - &ng_pipe_run_type_fields -}; - -/* Parse type for struct ng_pipe_hookcfg */ -static const struct ng_parse_struct_field - ng_pipe_hookcfg_type_fields[] = NG_PIPE_HOOKCFG_INFO; -static const struct ng_parse_type ng_pipe_hookcfg_type = { - &ng_parse_struct_type, - &ng_pipe_hookcfg_type_fields -}; - -/* Parse type for struct ng_pipe_cfg */ -static const struct ng_parse_struct_field - ng_pipe_cfg_type_fields[] = NG_PIPE_CFG_INFO(&ng_pipe_hookcfg_type); -static const struct ng_parse_type ng_pipe_cfg_type = { - &ng_parse_struct_type, - &ng_pipe_cfg_type_fields -}; - -/* List of commands and how to convert arguments to/from ASCII */ -static const struct ng_cmdlist ng_pipe_cmds[] = { - { - NGM_PIPE_COOKIE, - NGM_PIPE_GET_STATS, - "getstats", - NULL, - &ng_pipe_stats_type - }, - { - NGM_PIPE_COOKIE, - NGM_PIPE_CLR_STATS, - "clrstats", - NULL, - NULL - }, - { - NGM_PIPE_COOKIE, - NGM_PIPE_GETCLR_STATS, - "getclrstats", - NULL, - &ng_pipe_stats_type - }, - { - NGM_PIPE_COOKIE, - NGM_PIPE_GET_RUN, - "getrun", - NULL, - &ng_pipe_run_type - }, - { - NGM_PIPE_COOKIE, - NGM_PIPE_GET_CFG, - "getcfg", - NULL, - &ng_pipe_cfg_type - }, - { - NGM_PIPE_COOKIE, - NGM_PIPE_SET_CFG, - "setcfg", - &ng_pipe_cfg_type, - NULL - }, - { 0 } -}; - -/* Netgraph type descriptor */ -static struct ng_type ng_pipe_typestruct = { - NG_VERSION, - NG_PIPE_NODE_TYPE, - ngp_modevent, - ngp_constructor, - ngp_rcvmsg, - ngp_rmnode, - ngp_newhook, - NULL, - NULL, - ngp_rcvdata, - ngp_rcvdata, - ngp_disconnect, - ng_pipe_cmds -}; -NETGRAPH_INIT(pipe, &ng_pipe_typestruct); - -#ifdef BOEING_WLAN -/* generate a random integer between 1 and max */ -#define pipe_good_random(max) (1 + (random() % max)) -#endif - -/* - * Node constructor - */ -static int -ngp_constructor(node_p *nodep) -{ - sc_p privdata; - node_p node; - int error = 0; - int s; - - MALLOC(privdata, sc_p, sizeof(*privdata), M_NETGRAPH, M_NOWAIT); - if (privdata == NULL) - return (ENOMEM); - bzero(privdata, sizeof(*privdata)); - - if ((error = ng_make_node_common(&ng_pipe_typestruct, nodep))) { - FREE(privdata, M_NETGRAPH); - return (error); - } - - node=*nodep; - node->private = privdata; - privdata->node = node; - - /* Add new node to the "all nodes" list */ - s=splimp(); - LIST_INSERT_HEAD(&node_head, privdata, node_le); - splx(s); - - return (0); -} - - -/* - * Add a hook - */ -static int -ngp_newhook(node_p node, hook_p hook, const char *name) -{ - const sc_p sc = node->private; - struct hookinfo *hinfo; - - if (strcmp(name, NG_PIPE_HOOK_UPPER) == 0) { - bzero(&sc->upper, sizeof(sc->upper)); - sc->upper.hook = hook; - hook->private = &sc->upper; - } else if (strcmp(name, NG_PIPE_HOOK_LOWER) == 0) { - bzero(&sc->lower, sizeof(sc->lower)); - sc->lower.hook = hook; - hook->private = &sc->lower; - } else - return (EINVAL); - - /* Load non-zero initial cfg values */ - hinfo = (struct hookinfo *) hook->private; - hinfo->cfg.qin_size_limit = 50; - hinfo->cfg.fifo = 1; - hinfo->cfg.droptail = 1; - TAILQ_INIT(&hinfo->fifo_head); - TAILQ_INIT(&hinfo->qout_head); - return (0); -} - - -/* - * Receive a control message - */ -static int -ngp_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr, - struct ng_mesg **rptr) -{ - const sc_p sc = node->private; - struct ng_mesg *resp = NULL; - int error = 0; - - switch (msg->header.typecookie) { - case NGM_PIPE_COOKIE: - switch (msg->header.cmd) { - case NGM_PIPE_GET_STATS: - case NGM_PIPE_CLR_STATS: - case NGM_PIPE_GETCLR_STATS: - { - struct ng_pipe_stats *stats; - - if (msg->header.cmd != NGM_PIPE_CLR_STATS) { - NG_MKRESPONSE(resp, msg, - sizeof(*stats), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - goto done; - } - stats=(struct ng_pipe_stats *)resp->data; - bcopy(&sc->upper.stats, &stats->downstream, - sizeof(stats->downstream)); - bcopy(&sc->lower.stats, &stats->upstream, - sizeof(stats->upstream)); - } - if (msg->header.cmd != NGM_PIPE_GET_STATS) { - bzero(&sc->upper.stats, - sizeof(sc->upper.stats)); - bzero(&sc->lower.stats, - sizeof(sc->lower.stats)); - } - break; - } - case NGM_PIPE_GET_RUN: - { - struct ng_pipe_run *run; - - NG_MKRESPONSE(resp, msg, sizeof(*run), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - goto done; - } - run = (struct ng_pipe_run *)resp->data; - bcopy(&sc->upper.run, &run->downstream, - sizeof(run->downstream)); - bcopy(&sc->lower.run, &run->upstream, - sizeof(run->upstream)); - break; - } - case NGM_PIPE_GET_CFG: - { - struct ng_pipe_cfg *cfg; - - NG_MKRESPONSE(resp, msg, sizeof(*cfg), M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - goto done; - } - cfg = (struct ng_pipe_cfg *)resp->data; - bcopy(&sc->upper.cfg, &cfg->downstream, - sizeof(cfg->downstream)); - bcopy(&sc->lower.cfg, &cfg->upstream, - sizeof(cfg->upstream)); - cfg->delay = sc->delay; - cfg->overhead = sc->overhead; - cfg->header_offset = sc->header_offset; - if (cfg->upstream.bandwidth == - cfg->downstream.bandwidth) { - cfg->bandwidth = cfg->upstream.bandwidth; - cfg->upstream.bandwidth = 0; - cfg->downstream.bandwidth = 0; - } else - cfg->bandwidth = 0; - break; - } - case NGM_PIPE_SET_CFG: - { - struct ng_pipe_cfg *cfg; - - cfg = (struct ng_pipe_cfg *)msg->data; - if (msg->header.arglen != sizeof(*cfg)) { - error = EINVAL; - break; - } - - if (cfg->delay == -1) - sc->delay = 0; - else if (cfg->delay > 0 && cfg->delay < 10000000) - sc->delay = cfg->delay; - - if (cfg->bandwidth == -1) { - sc->upper.cfg.bandwidth = 0; - sc->lower.cfg.bandwidth = 0; - sc->overhead = 0; - } else if (cfg->bandwidth >= 100 && - cfg->bandwidth <= 1000000000) { - sc->upper.cfg.bandwidth = cfg->bandwidth; - sc->lower.cfg.bandwidth = cfg->bandwidth; - if (cfg->bandwidth >= 10000000) - sc->overhead = 8+4+12; /* Ethernet */ - else - sc->overhead = 10; /* HDLC */ - } - - if (cfg->overhead == -1) - sc->overhead = 0; - else if (cfg->overhead > 0 && cfg->overhead < 256) - sc->overhead = cfg->overhead; - - if (cfg->header_offset == -1) - sc->header_offset = 0; - else if (cfg->header_offset > 0 && - cfg->header_offset < 64) - sc->header_offset = cfg->header_offset; - - parse_cfg(&sc->upper.cfg, &cfg->downstream, &sc->upper); - parse_cfg(&sc->lower.cfg, &cfg->upstream, &sc->lower); - break; - } - - default: - error = EINVAL; - break; - } - break; - default: - error = EINVAL; - break; - } - if (rptr) - *rptr = resp; - else if (resp) - FREE(resp, M_NETGRAPH); - -done: - FREE(msg, M_NETGRAPH); - return (error); -} - - -static void -parse_cfg(struct ng_pipe_hookcfg *current, struct ng_pipe_hookcfg *new, - struct hookinfo *hinfo) -{ - - if (new->ber == -1) { - current->ber = 0; - if (hinfo->ber_p) { - FREE(hinfo->ber_p, M_NETGRAPH); - hinfo->ber_p = NULL; - } - } - else if (new->ber >= 1 && new->ber <= 1000000000000) { - static const uint64_t one = 0x1000000000000; /* = 2^48 */ - uint64_t p0, p; - uint32_t fsize, i; - - if (hinfo->ber_p == NULL) - MALLOC(hinfo->ber_p, uint64_t *, \ - (MAX_FSIZE + MAX_OHSIZE)*sizeof(uint64_t), \ - M_NETGRAPH, M_NOWAIT); - current->ber = new->ber; - - /* - * For given BER and each frame size N (in bytes) calculate - * the probability P_OK that the frame is clean: - * - * P_OK(BER,N) = (1 - 1/BER)^(N*8) - * - * We use a 64-bit fixed-point format with decimal point - * positioned between bits 47 and 48. - */ - p0 = one - one / new->ber; - p = one; - for (fsize = 0; fsize < MAX_FSIZE + MAX_OHSIZE; fsize++) { - hinfo->ber_p[fsize] = p; - for (i=0; i<8; i++) - p = (p*(p0&0xffff)>>48) + \ - (p*((p0>>16)&0xffff)>>32) + \ - (p*(p0>>32)>>16); - } - } - - if (new->qin_size_limit == 0xffff) - current->qin_size_limit = 0; - else if (new->qin_size_limit >= 5) - current->qin_size_limit = new->qin_size_limit; - - if (new->qout_size_limit == 0xffff) - current->qout_size_limit = 0; - else if (new->qout_size_limit >= 5) - current->qout_size_limit = new->qout_size_limit; - - if (new->duplicate == -1) - current->duplicate = 0; - else if (new->duplicate > 0 && new->duplicate <= 50) - current->duplicate = new->duplicate; - - if (new->fifo) { - current->fifo = 1; - current->wfq = 0; - current->drr = 0; - } - - if (new->wfq) { - current->fifo = 0; - current->wfq = 1; - current->drr = 0; - } - - if (new->drr) { - current->fifo = 0; - current->wfq = 0; - /* DRR quantum */ - if (new->drr >= 32) - current->drr = new->drr; - else - current->drr = 2048; /* default quantum */ - } - - if (new->droptail) { - current->droptail = 1; - current->drophead = 0; - } - - if (new->drophead) { - current->droptail = 0; - current->drophead = 1; - } - - if (new->bandwidth == -1) { - current->bandwidth = 0; - current->fifo = 1; - current->wfq = 0; - current->drr = 0; - } else if (new->bandwidth >= 100 && new->bandwidth <= 1000000000) - current->bandwidth = new->bandwidth; - -#ifdef XCP - init_xcp_state(&hinfo->xcps, 0, current->bandwidth / 1024); -#endif -} - - -/* - * Compute a hash signature for a packet. This function suffers from the - * NIH sindrome, so probably it would be wise to look around what other - * folks have found out to be a good and efficient IP hash function... - */ -__inline static int ip_hash(struct mbuf *m, int offset) -{ - u_int64_t i; - struct ip *ip = (struct ip *)(mtod(m, u_char *) + offset); - struct udphdr *udp = 0; - - if (m->m_len < sizeof(struct ip) + offset || - ip->ip_v != 4 || ip->ip_hl << 2 != sizeof(struct ip)) - return 0; - - if ((m->m_len >= sizeof(struct ip) + sizeof(struct udphdr) + offset) && - (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) && - !(ntohs(ip->ip_off) & IP_OFFMASK)) - udp = (struct udphdr *)((u_char *) ip + sizeof(struct ip)); - -#if 0 /* an overkill IP hash, but could be too slow */ - i = 0; - for ( j = (ip->ip_p & 0x1f) + 1; j ; j = j >> 2) { - i ^= ((u_int64_t) ip->ip_src.s_addr - + ((u_int64_t) ip->ip_dst.s_addr << 7) - - ((u_int64_t) ip->ip_src.s_addr << 13) - - ((u_int64_t) ip->ip_dst.s_addr << 19) - + ((u_int64_t) ip->ip_p << 9)) << j; - if (udp) - i ^= (((u_int64_t) udp->uh_sport << (ip->ip_p + 5)) - - ((u_int64_t) udp->uh_dport << ip->ip_p)) << j; - } -#else /* a slightly faster yet less reliable version */ - i = ((u_int64_t) ip->ip_src.s_addr - ^ ((u_int64_t) ip->ip_dst.s_addr << 7) - ^ ((u_int64_t) ip->ip_src.s_addr << 13) - ^ ((u_int64_t) ip->ip_dst.s_addr << 19) - ^ ((u_int64_t) ip->ip_p << 9)); - if (udp) - i ^= (((u_int64_t) udp->uh_sport << (ip->ip_p + 5)) - ^ ((u_int64_t) udp->uh_dport << ip->ip_p)); -#endif - return (i ^ (i >> 32)); -} - - -/* - * Receive data on a hook - both in upstream and downstream direction. - * We put the frame on the inbound queue, and try to initiate dequeuing - * sequence immediately. If inbound queue is full, discard one frame - * depending on dropping policy (from the head or from the tail of the - * queue). - */ -static int -ngp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) -{ - struct hookinfo *const hinfo = (struct hookinfo *) hook->private; - const sc_p sc = hook->node->private; - struct timeval uuptime; - struct timeval *now = &uuptime; - struct ngp_fifo *ngp_f = NULL, *ngp_f1; - struct ngp_hdr *ngp_h = NULL; - int hash; - int s; - - microuptime(now); - s = splimp(); - -#ifdef BOEING_WLAN - if (meta != NULL) { - if ((meta->used_len != WLAN_META_SIZE) || - (meta->options[0].cookie != NGM_WLAN_COOKIE)) { - /* metadata from elsewhere, not queued */ - NG_FREE_META(meta); /* sets meta = NULL */ - }/* else metadata from ng_wlan, contains tag */ - } -#else - NG_FREE_META(meta); -#endif - - /* - * Attach us to the list of active ng_pipes if this one was an empty - * one before, and also update the queue service deadline time. - */ - if (hinfo->run.qin_frames == 0) { - struct timeval *when = &hinfo->qin_utime; - if (when->tv_sec < now->tv_sec || (when->tv_sec == now->tv_sec - && when->tv_usec < now->tv_usec)) { - when->tv_sec = now->tv_sec; - when->tv_usec = now->tv_usec; - } - if (hinfo->run.qout_frames == 0) { - LIST_INSERT_HEAD(&hook_head, hinfo, hook_le); - if (cpu_idle_hlt) { - old_cpu_idle_hlt = cpu_idle_hlt; - cpu_idle_hlt = 0; - } - } - } - - /* Populate the packet header */ - ngp_h = zalloc(ngp_zone); - ngp_h->m = m; -#ifdef BOEING_WLAN - ngp_h->meta = meta; - meta = NULL; /* don't free elsewhere */ -#endif - - if (hinfo->cfg.fifo) - hash = 0; /* all packets go into a single FIFO queue */ - else - hash = ip_hash(m, sc->header_offset); - -#ifdef XCP - if (do_xcp) - xcp_forward(m, sc->header_offset, &hinfo->xcps); -#endif - - /* Find the appropriate FIFO queue for the packet and enqueue it*/ - TAILQ_FOREACH(ngp_f, &hinfo->fifo_head, fifo_le) - if (hash == ngp_f->hash) - break; - if (ngp_f == NULL) { - ngp_f = zalloc(ngp_zone); - TAILQ_INIT(&ngp_f->packet_head); - ngp_f->hash = hash; - ngp_f->packets = 1; - ngp_f->rr_deficit = hinfo->cfg.drr; /* DRR quantum */ - hinfo->run.fifo_queues++; - TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); - FIFO_VTIME_SORT(m->m_pkthdr.len); - } else { - TAILQ_INSERT_TAIL(&ngp_f->packet_head, ngp_h, ngp_link); - ngp_f->packets++; - } - hinfo->run.qin_frames++; - hinfo->run.qin_octets += m->m_pkthdr.len; - - /* Discard a frame if inbound queue limit has been reached */ - if (hinfo->run.qin_frames > hinfo->cfg.qin_size_limit) { - struct mbuf *m1; - int longest = 0; - - /* Find the longest queue */ - TAILQ_FOREACH(ngp_f1, &hinfo->fifo_head, fifo_le) - if (ngp_f1->packets > longest) { - longest = ngp_f1->packets; - ngp_f = ngp_f1; - } - - /* Drop a frame from the queue head/tail, depending on cfg */ - if (hinfo->cfg.drophead) - ngp_h = TAILQ_FIRST(&ngp_f->packet_head); - else - ngp_h = TAILQ_LAST(&ngp_f->packet_head, p_head); - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - m1 = ngp_h->m; -#ifdef BOEING_WLAN - NG_FREE_META(ngp_h->meta); -#endif /* BOEING_WLAN */ - zfree(ngp_zone, ngp_h); - hinfo->run.qin_octets -= m1->m_pkthdr.len; - hinfo->stats.in_disc_octets += m1->m_pkthdr.len; - m_freem(m1); - if (--(ngp_f->packets) == 0) { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - zfree(ngp_zone, ngp_f); - hinfo->run.fifo_queues--; - } - hinfo->run.qin_frames--; - hinfo->stats.in_disc_frames++; - } - - /* Try to start the dequeuing process immediately */ - pipe_dequeue(hinfo, now); - - splx(s); - return (0); -} - - -/* - * Dequeueing sequence - we basically do the following: - * 1) Try to extract the frame from the inbound (bandwidth) queue; - * 2) In accordance to BER specified, discard the frame randomly; - * 3) If the frame survives BER, prepend it with delay info and move it - * to outbound (delay) queue, or send directly to the outbound hook; - * 4) Loop to 2) until bandwidth limit is reached, or inbound queue is - * flushed completely; - * 5) Extract the first frame from the outbound queue, if it's time has come. - * Send this frame to the outbound hook; - * 6) Loop to 6) until outbound queue is flushed completely, or the next - * frame in the queue is not scheduled to be dequeued yet - * - * This routine must be called at splimp()! - */ -static void -pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { - static uint64_t rand, oldrand; - const sc_p sc = hinfo->hook->node->private; - struct hookinfo *dest; - struct ngp_fifo *ngp_f, *ngp_f1; - struct ngp_hdr *ngp_h; - struct timeval *when; - meta_p meta = NULL; - int error = 0; - struct mbuf *m; -#ifdef BOEING_WLAN - struct ngp_hdr *ngp_h1 = NULL; - struct ng_wlan_tag *tag, wtag; - int need_free_meta; -#endif /* BOEING_WLAN */ - - /* Which one is the destination hook? */ - if (hinfo == &sc->lower) - dest = &sc->upper; - else - dest = &sc->lower; - - /* Bandwidth queue processing */ - while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { - when = &hinfo->qin_utime; - if (when->tv_sec > now->tv_sec || (when->tv_sec == now->tv_sec - && when->tv_usec > now->tv_usec)) - break; - - ngp_h = TAILQ_FIRST(&ngp_f->packet_head); - m = ngp_h->m; -#ifdef BOEING_WLAN - meta = ngp_h->meta; - ngp_h->meta = NULL; /* keep ptr in meta*/ - need_free_meta = 0; - if (meta != NULL) { - need_free_meta = 1; - tag = (struct ng_wlan_tag*)meta->options; - WLAN_TAG_COPY( (&wtag), tag) - /* enforce maximum parameters */ - if (wtag.delay > NG_WLAN_MAX_DELAY) - wtag.delay = NG_WLAN_MAX_DELAY; - if (wtag.duplicate > NG_WLAN_MAX_DUP) - wtag.duplicate = NG_WLAN_MAX_DUP; - if (wtag.jitter > NG_WLAN_MAX_JITTER) - wtag.jitter = NG_WLAN_MAX_JITTER; - } else { - WLAN_TAG_ZERO( (&wtag) ); - } -#endif /* BOEING_WLAN */ - - /* Deficit Round Robin (DRR) processing */ - if (hinfo->cfg.drr) { - if (ngp_f->rr_deficit >= m->m_pkthdr.len) { - ngp_f->rr_deficit -= m->m_pkthdr.len; - } else { - ngp_f->rr_deficit += hinfo->cfg.drr; - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - TAILQ_INSERT_TAIL(&hinfo->fifo_head, \ - ngp_f, fifo_le); - /* BOEING_WLAN: need to free meta here? */ - continue; - } - } - - /* - * Either create a duplicate and pass it on, or dequeue - * the original packet... - */ -#ifdef BOEING_WLAN - if (wtag.duplicate && - pipe_good_random(100) <= wtag.duplicate) { - ngp_h = zalloc(ngp_zone); - KASSERT(ngp_h != NULL, ("ngp_h zalloc failed (3)")); - ngp_h->m = m_dup(m, M_NOWAIT); - ngp_h->meta = meta; /* reuse the old metadata instead of - * allocating another */ - need_free_meta = 0; - meta = NULL; - KASSERT(ngp_h->m != NULL, ("m_dup failed")); - m = ngp_h->m; /* Boeing: we are now working with copied - mbuf, leaving original in the queue */ - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.duplicate && - random() % 100 <= hinfo->cfg.duplicate) { - if ((m = m_dup(m, M_NOWAIT))) - if ((ngp_h = zalloc(ngp_zone))) - ngp_h->m = m; - if ( m == NULL || ngp_h == NULL ) - panic("ng_pipe: m_dup or zalloc failed!"); - } else { - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - hinfo->run.qin_frames--; - hinfo->run.qin_octets -= m->m_pkthdr.len; - ngp_f->packets--; - } -#ifdef BOEING_WLAN - /* free the metadata if it was not re-used for the duplicate */ - if (need_free_meta) - NG_FREE_META(meta); -#endif /* BOEING_WLAN */ - - /* Calculate the serialization delay */ -#ifdef BOEING_WLAN - if (wtag.bandwidth) { - hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len - + sc->overhead ) * - 8000000 / wtag.bandwidth; - hinfo->qin_utime.tv_sec += - hinfo->qin_utime.tv_usec / 1000000; - hinfo->qin_utime.tv_usec = - hinfo->qin_utime.tv_usec % 1000000; - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.bandwidth) { - hinfo->qin_utime.tv_usec += ((uint64_t) m->m_pkthdr.len - + sc->overhead ) * - 8000000 / hinfo->cfg.bandwidth; - hinfo->qin_utime.tv_sec += - hinfo->qin_utime.tv_usec / 1000000; - hinfo->qin_utime.tv_usec = - hinfo->qin_utime.tv_usec % 1000000; - } - when = &ngp_h->when; - when->tv_sec = hinfo->qin_utime.tv_sec; - when->tv_usec = hinfo->qin_utime.tv_usec; - - /* Sort / rearrange inbound queues */ - if (ngp_f->packets) { - if (hinfo->cfg.wfq) { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - FIFO_VTIME_SORT(TAILQ_FIRST(&ngp_f->packet_head)->m->m_pkthdr.len) - } - } else { - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - zfree(ngp_zone, ngp_f); - hinfo->run.fifo_queues--; - } - - /* Randomly discard the frame, according to BER setting */ -#ifdef BOEING_WLAN - /* use specified Packet Error Rate setting for random discard */ - if (wtag.per && - pipe_good_random(100) <= wtag.per) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } else -#endif /* BOEING_WLAN */ - if (hinfo->cfg.ber && - ( (oldrand = rand) ^ (rand = random())<<17) >= - hinfo->ber_p[sc->overhead + m->m_pkthdr.len] ) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } - - /* Discard frame if outbound queue size limit exceeded */ - if (hinfo->cfg.qout_size_limit && - hinfo->run.qout_frames>=hinfo->cfg.qout_size_limit) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - zfree(ngp_zone, ngp_h); - m_freem(m); - continue; - } - -#ifdef BOEING_WLAN - /* Calculate the propagation delay including jitter */ - if (wtag.jitter) { - when->tv_usec += pipe_good_random(wtag.jitter); - /* overflow handled below... */ - } - when->tv_usec += wtag.delay ? wtag.delay : sc->delay; -#else - /* Calculate the propagation delay */ - when->tv_usec += sc->delay; -#endif /* BOEING_WLAN */ - when->tv_sec += when->tv_usec / 1000000; - when->tv_usec = when->tv_usec % 1000000; - - /* Put the frame into the delay queue */ -#ifdef BOEING_WLAN - /* Because WLAN packets may have varying dequeue times, we need to - * perform sorted queueing; the dequeuing process expects packets in - * the queue that are sorted by time. - */ - TAILQ_FOREACH(ngp_h1, &hinfo->qout_head, ngp_link) { - if (ngp_h1->when.tv_sec > ngp_h->when.tv_sec || - (ngp_h1->when.tv_sec == ngp_h->when.tv_sec && - ngp_h1->when.tv_usec > ngp_h->when.tv_usec)) - break; - } - if (ngp_h1 == NULL) - TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); - else - TAILQ_INSERT_BEFORE(ngp_h1, ngp_h, ngp_link); - /* The original code below just inserts the packet at the - * tail of the queue because the delay time is constant. */ -#else /* BOEING_WLAN */ - TAILQ_INSERT_TAIL(&hinfo->qout_head, ngp_h, ngp_link); -#endif /* BOEING_WLAN */ - hinfo->run.qout_frames++; - hinfo->run.qout_octets += m->m_pkthdr.len; - } - - /* Delay queue processing */ - while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { - struct mbuf *m = ngp_h->m; - -/* BOEING_WLAN: this is why we have sorted the queue input */ - when = &ngp_h->when; - if (when->tv_sec > now->tv_sec || - (when->tv_sec == now->tv_sec && - when->tv_usec > now->tv_usec)) - break; - - /* Update outbound queue stats */ - hinfo->stats.fwd_frames++; - hinfo->stats.fwd_octets += m->m_pkthdr.len; - hinfo->run.qout_frames--; - hinfo->run.qout_octets -= m->m_pkthdr.len; - - /* Dequeue/send the packet */ - TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); - zfree(ngp_zone, ngp_h); -#ifdef BOEING_WLAN - NG_SEND_DATA_ONLY(error, dest->hook, m); -#else - NG_SEND_DATA(error, dest->hook, m, meta); -#endif /* BOEING_WLAN */ - } - - /* If both queues are empty detach us from the list of active queues */ - if (hinfo->run.qin_frames + hinfo->run.qout_frames == 0) - LIST_REMOVE(hinfo, hook_le); -} - - -/* - * This routine is called on every clock tick. We poll all nodes/hooks - * for queued frames by calling pipe_dequeue(). - */ -static void -pipe_scheduler(void) -{ - static struct timeval old; - struct timeval new; - - microuptime(&new); - if (old.tv_sec > new.tv_sec) - printf ("ng_pipe: dsec=%ld\n", old.tv_sec - new.tv_sec); - else if (old.tv_sec == new.tv_sec && old.tv_usec > new.tv_usec) - printf ("ng_pipe: dusec=%ld\n", old.tv_usec - new.tv_usec); - old.tv_sec = new.tv_sec; - old.tv_usec = new.tv_usec; - - pipe_poll(); - -#ifdef XCP - if ( do_xcp ) { - sc_p priv; - - /* Set off any XCP timers hooked to ng_pipe queues */ - - LIST_FOREACH(priv, &node_head, node_le) { - if ( --priv->upper.xcps.ticks_until_Te == 0 ) - xcp_Te_timeout(&priv->upper.xcps); - if ( --priv->upper.xcps.ticks_until_Tq == 0 ) - xcp_Tq_timeout(&priv->upper.xcps); - if ( --priv->lower.xcps.ticks_until_Te == 0 ) - xcp_Te_timeout(&priv->lower.xcps); - if ( --priv->lower.xcps.ticks_until_Tq == 0 ) - xcp_Tq_timeout(&priv->lower.xcps); - } - } -#endif - - /* Reschedule */ - ds_handle = timeout((timeout_t *) &pipe_scheduler, NULL, 1); -} - - -static void -pipe_poll(void) -{ - struct hookinfo *hinfo; - int s; - struct timeval now; - - s=splimp(); - - microuptime(&now); - LIST_FOREACH(hinfo, &hook_head, hook_le) - pipe_dequeue(hinfo, &now); - if (LIST_EMPTY(&hook_head) && cpu_idle_hlt == 0) - cpu_idle_hlt = old_cpu_idle_hlt; - - splx(s); -} - - -/* - * Shutdown processing - * - * This is tricky. If we have both a lower and upper hook, then we - * probably want to extricate ourselves and leave the two peers - * still linked to each other. Otherwise we should just shut down as - * a normal node would. We run at splimp() in order to avoid race - * condition with pipe_scheduler(). - */ -static int -ngp_rmnode(node_p node) -{ - const sc_p privdata = node->private; - int s; - - s=splimp(); - - node->flags |= NG_INVALID; - if (privdata->lower.hook && privdata->upper.hook) - ng_bypass(privdata->lower.hook, privdata->upper.hook); - ng_cutlinks(node); - ng_unname(node); - - /* unlink the node from the list */ - LIST_REMOVE(privdata, node_le); - - node->private = NULL; - ng_unref(privdata->node); - FREE(privdata, M_NETGRAPH); - - splx(s); - return (0); -} - - -/* - * Hook disconnection - */ -static int -ngp_disconnect(hook_p hook) -{ - struct hookinfo *const hinfo = (struct hookinfo *) hook->private; - struct ngp_fifo *ngp_f; - struct ngp_hdr *ngp_h; - int s, removed = 0; - - s=splimp(); - - KASSERT(hinfo != NULL, ("%s: null info", __FUNCTION__)); - hinfo->hook = NULL; - - /* Flush all fifo queues associated with the hook */ - while ((ngp_f = TAILQ_FIRST(&hinfo->fifo_head))) { - while ((ngp_h = TAILQ_FIRST(&ngp_f->packet_head))) { - TAILQ_REMOVE(&ngp_f->packet_head, ngp_h, ngp_link); - m_freem(ngp_h->m); -#ifdef BOEING_WLAN - NG_FREE_META(ngp_h->meta); -#endif /* BOEING_WLAN */ - zfree(ngp_zone, ngp_h); - removed++; - } - TAILQ_REMOVE(&hinfo->fifo_head, ngp_f, fifo_le); - zfree(ngp_zone, ngp_f); - } - - /* Flush the delay queue */ - while ((ngp_h = TAILQ_FIRST(&hinfo->qout_head))) { - TAILQ_REMOVE(&hinfo->qout_head, ngp_h, ngp_link); - m_freem(ngp_h->m); -#ifdef BOEING_WLAN - NG_FREE_META(ngp_h->meta); -#endif /* BOEING_WLAN */ - zfree(ngp_zone, ngp_h); - removed++; - } - - /* - * Both queues should be empty by now, so detach us from - * the list of active queues - */ - if (removed) - LIST_REMOVE(hinfo, hook_le); - if (hinfo->run.qin_frames + hinfo->run.qout_frames != removed) - printf("Mismatch: queued=%d but removed=%d !?!", - hinfo->run.qin_frames + hinfo->run.qout_frames, - removed); - - /* Release the packet loss probability table (BER) */ - if (hinfo->ber_p) - FREE(hinfo->ber_p, M_NETGRAPH); - - if (hook->node->numhooks == 0) - ng_rmnode(hook->node); - - splx(s); - return (0); -} - -static int -ngp_modevent(module_t mod, int type, void *unused) -{ - sc_p priv; - int error = 0; - int s; - - switch (type) { - case MOD_LOAD: - if (ngp_zone) - error = EEXIST; - else { - ngp_zone = zinit("ng_pipe", - max(sizeof(struct ngp_hdr), sizeof (struct ngp_fifo)), - nmbufs, ZONE_INTERRUPT, 0); - if (ngp_zone == NULL) { - error = ENOMEM; - break; - } - LIST_INIT(&node_head); - LIST_INIT(&hook_head); - ds_handle = timeout((timeout_t *) &pipe_scheduler, - NULL, 1); - idle_polling_h = pipe_poll; - } - break; - case MOD_UNLOAD: - LIST_FOREACH(priv, &node_head, node_le) - error = EBUSY; - - if (error == 0) { - s = splimp(); - idle_polling_h = NULL; - untimeout((timeout_t *) &pipe_scheduler, NULL, - ds_handle); - ds_handle.callout = NULL; - zdestroy(ngp_zone); - splx (s); - } - break; - default: - break; - } - - return (error); -} diff --git a/kernel/freebsd/ng_wlan/Makefile b/kernel/freebsd/ng_wlan/Makefile deleted file mode 100644 index 9d3136c7..00000000 --- a/kernel/freebsd/ng_wlan/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -# (c)2006-2011 the Boeing Company -# -# ng_wlan -# -.if !defined(PLATFORM) -#PLATFORM=i386 -PLATFORM=amd64 -.endif - -CFLAGS+=-I/usr/src/sys/${PLATFORM}/compile/CORE -DMULTICAST_LOOKUPS -# FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0" - -#.if defined(OSTYPE) -#.if (${OSTYPE} == "FreeBSD") -#CFLAGS+=-DFREEBSD411 -#.endif -#.endif - -KMOD= ng_wlan - -SRCS= ng_wlan.c - -#MAN= ng_wlan.4 - -.include - diff --git a/kernel/freebsd/ng_wlan/README b/kernel/freebsd/ng_wlan/README deleted file mode 100644 index 97c1cbe4..00000000 --- a/kernel/freebsd/ng_wlan/README +++ /dev/null @@ -1,50 +0,0 @@ - -ng_wlan FreeBSD kernel module - -(c) 2006-2011 the Boeing Company -author: Jeff Ahrenholz - - - The ng_wlan modules implements a netgraph node that models wireless -LAN connectivity. ng_wlan extends the ng_hub node, only instead of sending -packets to each connected peer, maintains a hash table of node connectivity, -and sends packets between two nodes only when they are linked. By default all -nodes are unlinked. Nodes can be linked and unlinked using "link" and -"unlink" messages: - ngctl msg e0_n2: link { node1=0x23 node2=0x0c } - -The node IDs of the two nodes are the parameters, as depicted above. - - Link effects between can also be specified for each node pair. If two nodes -are linked and parameters are specified, an mbuf tag will be added to each data -packet mbuf that specifies the effects. For FreeBSD 4.11, the metadata parameter -is used instead of mbuf tags. Delay (microseconds), bandwidth -(bits per second), PER (% packet errors), duplicates (%), jitter -(microseconds), and burst (% burst errors) are supported. This tag is then -removed by the ng_pipe node and the appropriate effects are applied. Link -effects are specified with "set" and "unset" messages: - ngctl msg e0_n2: set { node1=0x23 node2=0x0c delay=50000 bandwidth=54000000 per=0 duplicate=0 jitter=5000 burst=30 } - ngctl msg e0_n2: unset { node1=0x23 node2=0x0c } - -Note that a special ng_pipe module is needed (the default one does not support -the mbuf tags and some effects.) - -A separate error rate and burst rate affecting all multicast packets may be -defined. Use the "mer" message: - ngctl msg e0_n2: mer { mer=20 mburst=35 } -The above example sets the multicast error rate to drop 20% of all multicast -packets, with 35% burst errors. - -When MULTICAST_LOOKUPS is defined, a second lookup table is defined for each -WLAN where multicast group, source, and node pair tuples can be linked or -unlinked. This causes different forwarding behavior for multicast packets, -where non-local groups are only forwarded if the node pair has been linked -together for that group (and the normal node pair has been linked). -Usage: - ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0x0a000002 } - ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0} - ngctl msg e0_n2: mcastunset { node1=0x23 node2=0x0c group=0xEF020364 source=0 } -Once the first mcastset/mcastunset message is received, that ng_wlan will drop -all non-local multicast packets that do not have a matching source, group, -node pair entry. The source address of zero matches any IP source. - diff --git a/kernel/freebsd/ng_wlan/ng_wlan.c b/kernel/freebsd/ng_wlan/ng_wlan.c deleted file mode 100644 index f6d6b810..00000000 --- a/kernel/freebsd/ng_wlan/ng_wlan.c +++ /dev/null @@ -1,1315 +0,0 @@ -/* - * Copyright (c) 2006-2011 the Boeing Company - * ng_wlan is based on ng_hub, which is: - * Copyright (c) 2004 Ruslan Ermilov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -#include -#include -#include -#include -#include -#ifdef MULTICAST_LOOKUPS -#include /* in.h */ -#include /* IN_MULTICAST(), etc */ -#include /* struct ip */ -#include /* struct ether_header */ -#endif /* MULTICAST_LOOKUPS */ - -#include -#include -#include -/* #include */ -#include "ng_wlan.h" -#include "ng_wlan_tag.h" - -#ifdef NG_SEPARATE_MALLOC -MALLOC_DEFINE(M_NETGRAPH_WLAN, "netgraph_wlan", "netgraph WLAN node "); -#else -#define M_NETGRAPH_WLAN M_NETGRAPH -#endif - -#ifdef WLAN_GIANT_LOCK -struct mtx ng_wlan_giant; -#endif - -#ifdef MULTICAST_LOOKUPS -#define mtod_off(m,off,t) ((t)(mtod((m),caddr_t)+(off))) -#define IP_MCAST_HDR_OFFSET ETHER_HDR_LEN -#define IP_MCAST_MIN_LEN (IP_MCAST_HDR_OFFSET + sizeof(struct ip)) -#endif /* MULTICAST_LOOKUPS */ - -/* - * WLAN node data types - */ -/* Hash table entry for wlan connectivity */ -struct ng_wlan_hent { - ng_ID_t l_id; - ng_ID_t g_id; - int linked; - u_int64_t delay; - u_int64_t bandwidth; - u_int16_t per; - u_int16_t duplicate; - u_int32_t jitter; - u_int16_t burst; - SLIST_ENTRY(ng_wlan_hent) next; -}; - -/* Hash table bucket declaration */ -/* struct ng_wlan_bucket { - struct ng_wlan_hent *slh_first; -};*/ -SLIST_HEAD(ng_wlan_bucket, ng_wlan_hent); - -#define MIN_BUCKETS 256 -#define HASH(a, b) ( ((a << 16) + b) % MIN_BUCKETS ) - -#define IS_PEER_KSOCKET(h) \ - (NG_PEER_NODE(h) != NULL && \ - NG_PEER_NODE(h)->nd_type->name[0] == 'k' && \ - NG_PEER_NODE(h)->nd_type->name[1] == 's') - -/* WLAN node private data */ -struct ng_wlan_private { - struct ng_wlan_bucket *tab; -#ifndef FREEBSD411 - struct mtx ng_wlan_tab_lock; -#ifdef MULTICAST_LOOKUPS - struct ng_wlan_mcast_bucket *mcast_tab; - struct mtx ng_wlan_mcast_tab_lock; - int multicast_enabled; -#endif -#endif /* !FREEBSD411 */ - int persistent; - u_int16_t mer; /* multicast error rate */ - u_int16_t mburst; /* multicast burst rate */ -}; -typedef struct ng_wlan_private *priv_p; - -/* - * Local function declarations - */ -static int ng_wlan_lookup(node_p node, hook_p hook1, hook_p hook2, - struct ng_wlan_tag *tag); -static int ng_wlan_unlink(node_p node, ng_ID_t node1, ng_ID_t node2); -static int ng_wlan_link(node_p node, ng_ID_t node1, ng_ID_t node2, - struct ng_wlan_set_data *data); - -#ifdef MULTICAST_LOOKUPS -static int ng_wlan_mcast_lookup(node_p node, hook_p hook1, hook_p hook2, - u_int32_t group, u_int32_t source); -static int ng_wlan_mcast_link(node_p node, ng_ID_t node1, ng_ID_t node2, - u_int32_t group, u_int32_t source, int unlink); - -/* Hash table entry for multicast connectivity */ -struct ng_wlan_mcast_hent { - ng_ID_t l_id; - ng_ID_t g_id; - u_int32_t group; - u_int32_t source; - int linked; - SLIST_ENTRY(ng_wlan_mcast_hent) next; -}; - -SLIST_HEAD(ng_wlan_mcast_bucket, ng_wlan_mcast_hent); -#define MCAST_HASH(a, b, g) ( (((a << 16) + b) & g) % MIN_BUCKETS ) -#endif /* MULTICAST_LOOKUPS */ - -/* - * Netgraph node methods - */ -#ifndef FREEBSD411 -static int ng_wlan_modevent(module_t mod, int type, void *unused); -#endif -static ng_constructor_t ng_wlan_constructor; -static ng_rcvmsg_t ng_wlan_rcvmsg; -static ng_shutdown_t ng_wlan_rmnode; -static ng_newhook_t ng_wlan_newhook; -static ng_rcvdata_t ng_wlan_rcvdata; -#ifndef FREEBSD411 -static ng_rcvdata_t ng_wlan_rcvdata_ks; -#endif -static ng_disconnect_t ng_wlan_disconnect; - -/* Parse types */ -static const struct ng_parse_struct_field ng_wlan_link_type_fields[] - = NG_WLAN_CONFIG_TYPE_INFO; -static const struct ng_parse_type ng_wlan_link_type = { - &ng_parse_struct_type, - &ng_wlan_link_type_fields -}; -static const struct ng_parse_struct_field ng_wlan_set_type_fields[] - = NG_WLAN_SET_DATA_TYPE_INFO; -static const struct ng_parse_type ng_wlan_set_type = { - &ng_parse_struct_type, - &ng_wlan_set_type_fields -}; -static const struct ng_parse_struct_field ng_wlan_mer_type_fields[] - = NG_WLAN_MER_TYPE_INFO; -static const struct ng_parse_type ng_wlan_mer_type = { - &ng_parse_struct_type, - &ng_wlan_mer_type_fields -}; -#ifdef MULTICAST_LOOKUPS -static const struct ng_parse_struct_field ng_wlan_multicast_set_type_fields[] - = NG_WLAN_MULTICAST_SET_DATA_TYPE_INFO; -static const struct ng_parse_type ng_wlan_multicast_set_type = { - &ng_parse_struct_type, - &ng_wlan_multicast_set_type_fields -}; -#endif /* MULTICAST_LOOKUPS */ - -/* List of commands and how to convert arguments to/from ASCII */ -static const struct ng_cmdlist ng_wlan_cmdlist[] = { - { - NGM_WLAN_COOKIE, - NGM_WLAN_LINK_NODES, - "link", - &ng_wlan_link_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_UNLINK_NODES, - "unlink", - &ng_wlan_link_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_NODES_SET, - "set", - &ng_wlan_set_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_NODES_UNSET, - "unset", - &ng_wlan_link_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_NODES_GET, - "get", - &ng_wlan_link_type, - &ng_wlan_set_type - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_MER, - "mer", - &ng_wlan_mer_type, - NULL - }, -#ifdef MULTICAST_LOOKUPS - { - NGM_WLAN_COOKIE, - NGM_WLAN_MULTICAST_SET, - "mcastset", - &ng_wlan_multicast_set_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_MULTICAST_UNSET, - "mcastunset", - &ng_wlan_multicast_set_type, - NULL - }, - { - NGM_WLAN_COOKIE, - NGM_WLAN_MULTICAST_GET, - "mcastget", - &ng_wlan_multicast_set_type, - &ng_wlan_multicast_set_type - }, -#endif /* MULTICAST_LOOKUPS */ - { 0 } -}; - -/* - * Netgraph node type descriptor - */ -static struct ng_type ng_wlan_typestruct = { - .version = NG_ABI_VERSION, - .name = NG_WLAN_NODE_TYPE, -#ifndef FREEBSD411 - .mod_event = ng_wlan_modevent, -#endif - .constructor = ng_wlan_constructor, - .rcvmsg = ng_wlan_rcvmsg, - .shutdown = ng_wlan_rmnode, - .newhook = ng_wlan_newhook, - .rcvdata = ng_wlan_rcvdata, - .disconnect = ng_wlan_disconnect, - .cmdlist = ng_wlan_cmdlist, -}; -NETGRAPH_INIT(wlan, &ng_wlan_typestruct); - -#ifndef FREEBSD411 -/* - * Function implementations - */ -static int -ng_wlan_modevent(module_t mod, int type, void *unused) -{ - int error = 0; - - switch (type) { - case MOD_LOAD: -#ifdef WLAN_GIANT_LOCK - mtx_init(&ng_wlan_giant, "ng_wlan_giant", NULL, MTX_DEF); -#endif - break; - case MOD_UNLOAD: -#ifdef WLAN_GIANT_LOCK - mtx_destroy(&ng_wlan_giant); -#endif - break; - default: - error = EOPNOTSUPP; - break; - } - - return (error); -} -#endif /* !FREEBSD411 */ - -#ifdef FREEBSD411 -static int -ng_wlan_constructor(node_p *nodep) -#else -static int -ng_wlan_constructor(node_p node) -#endif -{ - priv_p priv; -#ifdef FREEBSD411 - int error=0; -#endif - - /* initialize the hash table */ - MALLOC( priv, priv_p, - sizeof(struct ng_wlan_private), - M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); - if (priv == NULL) - return (ENOMEM); - - MALLOC( priv->tab, struct ng_wlan_bucket *, - MIN_BUCKETS * sizeof(struct ng_wlan_bucket), - M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); - if (priv->tab == NULL) { - FREE(priv, M_NETGRAPH_WLAN); - return (ENOMEM); - } -#ifdef FREEBSD411 - /* Call the generic node constructor. */ - if ((error=ng_make_node_common(&ng_wlan_typestruct, nodep))) { - FREE(priv->tab, M_NETGRAPH_WLAN); - FREE(priv, M_NETGRAPH_WLAN); - return(error); - } - NG_NODE_SET_PRIVATE(*nodep, priv); -#else /* FREEBSD411 */ -#ifdef MULTICAST_LOOKUPS - priv->multicast_enabled = 0; /* turned off, until ng_wlan_mcast_link()*/ - /* initialize multicast hash table */ - MALLOC( priv->mcast_tab, struct ng_wlan_mcast_bucket *, - MIN_BUCKETS * sizeof(struct ng_wlan_mcast_bucket), - M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); - if (priv->mcast_tab == NULL) { - FREE(priv->tab, M_NETGRAPH_WLAN); - FREE(priv, M_NETGRAPH_WLAN); - return (ENOMEM); - } - mtx_init(&priv->ng_wlan_mcast_tab_lock, "ng_wlan_mcast_tab_lock", NULL, - MTX_DEF); -#endif /* MULTICAST_LOOKUPS */ - mtx_init(&priv->ng_wlan_tab_lock, "ng_wlan_tab_lock", NULL, MTX_DEF); - NG_NODE_SET_PRIVATE(node, priv); -#endif /* FREEBSD411 */ - - return (0); -} - -static int -ng_wlan_newhook(node_p node, hook_p hook, const char *name) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - - /* ksocket hooks "ks0", "ks1", etc. get special receive function */ - if (name[0] == 'k' && name[1] == 's') { -#ifndef FREEBSD411 - NG_HOOK_SET_RCVDATA(hook, ng_wlan_rcvdata_ks); -#endif - return 0; - } - - if (strcmp(name, "anchor") == 0) { - if (priv->persistent) - return(EISCONN); - priv->persistent = 1; - } - return 0; -} - -/* - * Receive a control message. - */ -#ifdef FREEBSD411 -static int -ng_wlan_rcvmsg(node_p node, struct ng_mesg *msg, - const char *retaddr, struct ng_mesg **rptr) -#else -static int -ng_wlan_rcvmsg(node_p node, item_p item, hook_p lasthook) -#endif -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_mesg *resp = NULL; - int error = 0; - struct ng_wlan_config *nodes; - struct ng_wlan_set_data *set_data; - struct ng_wlan_tag tag; - u_int32_t node1, node2; - struct ng_hook h1, h2; - struct ng_node n1, n2; -#ifndef FREEBSD411 - struct ng_mesg *msg; -#ifdef MULTICAST_LOOKUPS - struct ng_wlan_multicast_set_data *mcsd; - u_int32_t group, src; - int unlink; -#endif /* MULTICAST_LOOKUPS */ -#endif - -#ifndef FREEBSD411 -#ifdef WLAN_GIANT_LOCK - mtx_lock(&ng_wlan_giant); -#else - mtx_lock(&priv->ng_wlan_tab_lock); -#ifdef MULTICAST_LOOKUPS - mtx_lock(&priv->ng_wlan_mcast_tab_lock); -#endif /* MULTICAST_LOOKUPS */ -#endif - NGI_GET_MSG(item, msg); -#endif /* !FREEBSD411 */ - - switch (msg->header.typecookie) { - case NGM_WLAN_COOKIE: - switch (msg->header.cmd) { - /* all of these messages take (node1=a,node2=b) param */ - case NGM_WLAN_LINK_NODES: - case NGM_WLAN_UNLINK_NODES: - case NGM_WLAN_NODES_UNSET: - case NGM_WLAN_NODES_GET: - if (msg->header.arglen - != sizeof(struct ng_wlan_config)) { - error = EINVAL; - break; - } - nodes = (struct ng_wlan_config *)msg->data; - node1 = nodes->node1; - node2 = nodes->node2; - if (msg->header.cmd == NGM_WLAN_NODES_GET) { - NG_MKRESPONSE(resp, msg, sizeof(*set_data), - M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - break; - } - set_data = (struct ng_wlan_set_data*)resp->data; - bzero(set_data, sizeof(*set_data)); - /* make fake peer/node structures for lookup */ -#ifdef FREEBSD411 - h1.peer = &h2; h2.peer = &h1; - h1.node = &n1; h2.node = &n2; - n1.ID = node1; n2.ID = node2; -#else - h1.hk_peer = &h2; h2.hk_peer = &h1; - h1.hk_node = &n1; h2.hk_node = &n2; - n1.nd_ID = node1; n2.nd_ID = node2; -#endif - if (ng_wlan_lookup(node, &h1, &h2, &tag)) { - set_data->node1 = node1; - set_data->node2 = node2; - WLAN_TAG_COPY(set_data, (&tag)); - } /* if not found, node1/node2 will be zero */ - break; - } - if (msg->header.cmd == NGM_WLAN_LINK_NODES) - error = ng_wlan_link(node, node1, node2, NULL); - else - error = ng_wlan_unlink(node, node1, node2); - break; - case NGM_WLAN_NODES_SET: - if (msg->header.arglen - != sizeof(struct ng_wlan_set_data)) { - error = EINVAL; - break; - } - set_data = (struct ng_wlan_set_data *)msg->data; - node1 = set_data->node1; - node2 = set_data->node2; - if (set_data->delay > NG_WLAN_MAX_DELAY || - set_data->bandwidth > NG_WLAN_MAX_BW || - set_data->per > NG_WLAN_MAX_PER || - set_data->duplicate > NG_WLAN_MAX_DUP || - set_data->jitter > NG_WLAN_MAX_JITTER || - set_data->burst > NG_WLAN_MAX_BURST) { - error = EINVAL; - break; - } - error = ng_wlan_link(node, node1, node2, set_data); - break; - case NGM_WLAN_MER: - if (msg->header.arglen != sizeof(struct ng_wlan_mer)) { - error = EINVAL; - break; - } - priv->mer = *((u_int16_t *)msg->data); - priv->mburst = *((u_int16_t *)&msg->data[2]); - break; - case NGM_WLAN_MULTICAST_SET: - case NGM_WLAN_MULTICAST_UNSET: - case NGM_WLAN_MULTICAST_GET: -#ifndef MULTICAST_LOOKUPS - error = ENOTSUP; - break; -#else - if (msg->header.arglen - != sizeof(struct ng_wlan_multicast_set_data)) { - error = EINVAL; - break; - } - unlink = (msg->header.cmd == NGM_WLAN_MULTICAST_UNSET); - mcsd = (struct ng_wlan_multicast_set_data *)msg->data; - node1 = mcsd->node1; - node2 = mcsd->node2; - group = mcsd->group; - src = mcsd->source; - if (msg->header.cmd == NGM_WLAN_MULTICAST_GET) { - NG_MKRESPONSE(resp, msg, sizeof(*mcsd), - M_NOWAIT); - if (resp == NULL) { - error = ENOMEM; - break; - } - mcsd = (struct ng_wlan_multicast_set_data*) - resp->data; - bzero(mcsd, sizeof(*mcsd)); - /* make fake peer/node structures for lookup */ -#ifdef FREEBSD411 - h1.peer = &h2; h2.peer = &h1; - h1.node = &n1; h2.node = &n2; - n1.ID = node1; n2.ID = node2; -#else - h1.hk_peer = &h2; h2.hk_peer = &h1; - h1.hk_node = &n1; h2.hk_node = &n2; - n1.nd_ID = node1; n2.nd_ID = node2; -#endif - if (ng_wlan_mcast_lookup(node, &h1, &h2, group, - src)){ - mcsd->node1 = node1; - mcsd->node2 = node2; - mcsd->group = group; - } /* if not found, node1/node2 will be zero */ - break; - } - error = ng_wlan_mcast_link(node, node1, node2, group, - src, unlink); - break; -#endif /* MULTICAST_LOOKUPS */ - default: - error = EINVAL; - break; - } - break; - default: - error = EINVAL; - break; - } - -#ifndef FREEBSD411 - NG_RESPOND_MSG(error, node, item, resp); -#endif - NG_FREE_MSG(msg); - -#ifndef FREEBSD411 -#ifdef WLAN_GIANT_LOCK - mtx_unlock(&ng_wlan_giant); -#else - mtx_unlock(&priv->ng_wlan_tab_lock); -#ifdef MULTICAST_LOOKUPS - mtx_unlock(&priv->ng_wlan_mcast_tab_lock); -#endif /* MULTICAST_LOOKUPS */ -#endif -#endif - return(error); -} - - -#ifdef FREEBSD411 -/* - * Handle incoming data from connected netgraph hooks. - * FreeBSD 4.11 version uses netgraph metadata. - * Does not support ksocket backchannel, multicast lookups. - */ -static int -ng_wlan_rcvdata(hook_p hook, struct mbuf *m, meta_p meta) -{ - const node_p node = NG_HOOK_NODE(hook); - const priv_p priv = NG_NODE_PRIVATE(node); - int error = 0; - hook_p hook2; - struct mbuf *m2; - int nhooks; - struct ng_wlan_tag *tag = NULL; - - /* Checking for NG_INVALID flag fixes race upon shutdown */ - if ((NG_NODE_NOT_VALID(node)) || - ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { - NG_FREE_DATA(m, meta); - return (0); - } - - /* Meta information is not preserved by this node but replaced with - * its own data. This sets meta = NULL */ - NG_FREE_META(meta); - - /* Count number of linked nodes, not just number of hooks */ - nhooks = 0; - LIST_FOREACH(hook2, &node->hooks, hooks) - { - /* TODO: maintain a count of the number of linked nodes */ - if (hook2 == hook) - continue; - if (!ng_wlan_lookup(node, hook, hook2, NULL)) - continue; - nhooks++; - } - if (nhooks==0) /* Nobody to receive the data */ - goto rcvdata_free_item_error; - LIST_FOREACH(hook2, &node->hooks, hooks) - { - if (hook2 == hook) - continue; - /* Allocate a meta+tag for sending with the data, which may or - may not be used. If used, the ptr is set to NULL for the - next loop iteration; unused (non-NULL ptr) will be freed - after loop. - */ - if (!meta) { - MALLOC(meta, meta_p, WLAN_META_SIZE, - M_NETGRAPH, M_NOWAIT | M_ZERO); - if (!meta) goto rcvdata_free_item_error_nobufs; - meta->used_len = (u_short) WLAN_META_SIZE; - meta->allocated_len = (u_short) WLAN_META_SIZE; - meta->flags = 0; - meta->priority = WLAN_META_PRIORITY; - meta->discardability = -1; - tag = (struct ng_wlan_tag*)meta->options; - tag->meta_hdr.cookie = NGM_WLAN_COOKIE; - tag->meta_hdr.type = NG_TAG_WLAN; - tag->meta_hdr.len = sizeof(struct ng_wlan_tag); - } - WLAN_TAG_ZERO(tag); - - if ( !ng_wlan_lookup(node, hook, hook2, tag)) { - /* determine if peers are connected, fill in tag data */ - continue; - } - if ((m->m_flags & M_MCAST) && (priv->mer > 0) && tag) { - tag->per = priv->mer; /* use configured mcast error */ - tag->burst = priv->mburst; /* use conf mcast burst */ - } - - if (--nhooks == 0) { /* nhooks is really number of links */ - if (tag && TAG_HAS_DATA(tag)) { - /* send metadata and set meta = NULL */ - NG_SEND_DATA(error, hook2, m, meta); - tag = NULL; /* tag used */ - } else { - /* Don't send any metadata */ - NG_SEND_DATA_ONLY(error, hook2, m); - } - break; /* no need to loop and malloc */ - } else { - if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) - goto rcvdata_free_item_error_nobufs; - if (tag && TAG_HAS_DATA(tag)) { - /* send metadata and set meta = NULL */ - NG_SEND_DATA(error, hook2, m2, meta); - tag = NULL; /* tag used */ - } else { - /* Don't send any metadata */ - NG_SEND_DATA_ONLY(error, hook2, m2); - if (error) /* XXX free mbuf? */ - continue; /* don't give up */ - } - } /* end if nhooks==0 */ - } /* end FOREACH hook */ - - if (meta) /* cleanup unused meta+tag */ - NG_FREE_META(meta); - - goto rcvdata_out; - -rcvdata_free_item_error_nobufs: - error = ENOBUFS; -rcvdata_free_item_error: - NG_FREE_DATA(m, meta); - -rcvdata_out: - return (error); -} - -#else /* FREEBSD411 */ -/* - * Handle incoming data from connected netgraph hooks. - * FreeBSD 7.0 version uses mbuf tags; has additional features: - * - ksocket backchannel for connecting two ng_wlans together - * - multicast lookups for different forwarding behavior for multicast packets - */ -static int -ng_wlan_rcvdata(hook_p hook, item_p item) -{ - const node_p node = NG_HOOK_NODE(hook); - int error = 0; - hook_p hook2; - struct mbuf *m2; - int nhooks; - struct ng_wlan_tag *tag = NULL; - struct mbuf *m; - const priv_p priv = NG_NODE_PRIVATE(node); - ng_ID_t srcid; - node_p peer; -#ifdef MULTICAST_LOOKUPS - u_int32_t group, src; - struct ip *ip; - struct ether_header *eh; -#endif /* MULTICAST_LOOKUPS */ - - /* Checking for NG_INVALID flag fixes race upon shutdown */ - if ((NG_NODE_NOT_VALID(node)) || - ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { - NG_FREE_ITEM(item); - return (0); - } - -#ifdef WLAN_GIANT_LOCK - mtx_lock(&ng_wlan_giant); -#else - mtx_lock(&priv->ng_wlan_tab_lock); -#endif - m = NGI_M(item); /* 'item' still owns it... we are peeking */ - -#ifdef MULTICAST_LOOKUPS - mtx_lock(&priv->ng_wlan_mcast_tab_lock); - src = group = 0; - if (priv->multicast_enabled && - (m->m_flags & M_MCAST) && (m->m_flags & M_PKTHDR)) { - /* disassociate mbuf from item (now we must free it) */ - NGI_GET_M(item, m); - /* Get group of packets sent to non-local multicast addresses */ - if ((m->m_pkthdr.len >= IP_MCAST_MIN_LEN) && - (m = m_pullup(m, IP_MCAST_MIN_LEN)) != NULL) { - eh = mtod_off(m, 0, struct ether_header *); - if (ETHER_IS_MULTICAST(eh->ether_dhost) && - ntohs(eh->ether_type) == ETHERTYPE_IP) { - ip = mtod_off(m, IP_MCAST_HDR_OFFSET, - struct ip *); - if ((ip->ip_v == IPVERSION) && - IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) && - !(IN_LOCAL_GROUP(ntohl(ip->ip_dst.s_addr)))) { - group = ntohl(ip->ip_dst.s_addr); - src = NG_NODE_ID(NG_PEER_NODE(hook)); - } - } - } else if (!m) { /* m_pullup failed, free item and leave */ - error = EINVAL; - goto rcvdata_free_item_error; - } - NGI_M(item) = m; /* give mbuf back to item */ - } -#endif /* MULTICAST_LOOKUPS */ - - /* Count number of linked nodes, not just number of hooks */ - nhooks = 0; - LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) - { - /* TODO: maintain a count of the number of linked nodes */ - if (hook2 == hook) - continue; - if (IS_PEER_KSOCKET(hook2)) { /* count all ksockets */ - nhooks++; - continue; - } -#ifdef MULTICAST_LOOKUPS - /* count hook using multicast lookup if packet is multicast */ - if ( group > 0 ) { - if (!ng_wlan_mcast_lookup(node, hook, hook2, group, src) || - !ng_wlan_lookup(node, hook, hook2, NULL)) - continue; - /* use normal unicast lookup */ - } else -#endif /* MULTICAST_LOOKUPS */ - if (!ng_wlan_lookup(node, hook, hook2, NULL)) - continue; - nhooks++; - } - if (nhooks==0) /* Nobody to receive the data */ - goto rcvdata_free_item_error; - - LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) - { - if (hook2 == hook) - continue; - /* Allocate a tag for prepending to the mbuf, which may or - may not be used. If used, the ptr is set to NULL for the - next loop iteration; unused (non-NULL ptr) will be freed - after loop. - */ - if (!tag) - tag = (struct ng_wlan_tag *)m_tag_alloc(NGM_WLAN_COOKIE, - NG_TAG_WLAN, TAGSIZE, M_NOWAIT | M_ZERO); - if (!tag) goto rcvdata_free_item_error_nobufs; - WLAN_TAG_ZERO(tag); - - /* check for ksocket backchannel to another ng_wlan */ - srcid = 0; - if (IS_PEER_KSOCKET(hook2)) { - /* this hook is connected to a ksocket - * set srcid for prepending the mbuf */ - peer = NG_PEER_NODE(hook2); - srcid = (NG_NODE_ID(peer) << 8) + - NG_NODE_ID(NG_PEER_NODE(hook)); - } else -#ifdef MULTICAST_LOOKUPS - if ( group > 0 ) { - if (!ng_wlan_mcast_lookup(node, hook, hook2, group, src) || - !ng_wlan_lookup(node, hook, hook2, tag)) - continue; /* multicast lookup failed */ - /* multicast lookup success - tag data filled in */ - } else -#endif /* MULTICAST_LOOKUPS */ - if ( !ng_wlan_lookup(node, hook, hook2, tag)) { - /* determine if peers are connected, fill in tag data */ - continue; - } - if ((m->m_flags & M_MCAST) && (priv->mer > 0) && tag) { - tag->per = priv->mer; /* use configured mcast error */ - tag->burst = priv->mburst; /* use conf mcast burst */ - } - - if (--nhooks == 0) { /* nhooks is really number of links */ - if (srcid > 0) { /* add srcid for ksockets */ - NGI_GET_M(item, m); - M_PREPEND(m, sizeof(ng_ID_t), M_DONTWAIT); - if (!m) goto rcvdata_free_item_error_nobufs; - mtod(m, ng_ID_t*)[0] = htonl(srcid); - NGI_M(item) = m; - } else if (tag && TAG_HAS_DATA(tag)) { - m_tag_prepend(m, &tag->tag); - tag = NULL; /* tag used */ - } - NG_FWD_ITEM_HOOK(error, item, hook2); - break; /* no need to loop and malloc */ - } else { - if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) - goto rcvdata_free_item_error_nobufs; - if (srcid > 0) { /* add srcid for ksockets */ - M_PREPEND(m2, sizeof(ng_ID_t), M_DONTWAIT); - if (!m2) goto rcvdata_free_item_error_nobufs; - mtod(m2, ng_ID_t*)[0] = htonl(srcid); - } else if (tag && TAG_HAS_DATA(tag)) { - m_tag_prepend(m2, &tag->tag); - tag = NULL; /* tag used */ - } - NG_SEND_DATA_ONLY(error, hook2, m2); - if (error) /* XXX free mbuf? */ - continue; /* don't give up */ - } /* end if nhooks==0 */ - } /* end FOREACH hook */ - - if (tag) /* cleanup unused tag */ - m_tag_free(&tag->tag); - - /* assume item has been freed by fwd above (nhooks==0) */ - goto rcvdata_out; - -rcvdata_free_item_error_nobufs: - error = ENOBUFS; -rcvdata_free_item_error: - NG_FREE_ITEM(item); - -rcvdata_out: -#ifdef WLAN_GIANT_LOCK - mtx_unlock(&ng_wlan_giant); -#else - mtx_unlock(&priv->ng_wlan_tab_lock); -#ifdef MULTICAST_LOOKUPS - mtx_unlock(&priv->ng_wlan_mcast_tab_lock); -#endif /* MULTICAST_LOOKUPS */ -#endif - return (error); -} -#endif /* FREEBSD411 */ - -#ifndef FREEBSD411 -/* - * Handle incoming data from hooks connected to kernel sockets - */ -static int -ng_wlan_rcvdata_ks(hook_p hook, item_p item) -{ - const node_p node = NG_HOOK_NODE(hook); - const priv_p priv = NG_NODE_PRIVATE(node); - int error = 0; - hook_p hook2; - struct mbuf *m, *m2; - int nhooks; - struct ng_wlan_tag *tag = NULL; - ng_ID_t srcid; - struct ng_hook hooklookup, hooklookup2; - struct ng_node nodelookup; - - /* Checking for NG_INVALID flag fixes race upon shutdown */ - if ((NG_NODE_NOT_VALID(node)) || - ((nhooks = NG_NODE_NUMHOOKS(node)) == 1)) { - NG_FREE_ITEM(item); - return (0); - } - -#ifndef FREEBSD411 -#ifdef WLAN_GIANT_LOCK - mtx_lock(&ng_wlan_giant); -#else - mtx_lock(&priv->ng_wlan_tab_lock); -#endif -#endif - /* this packet came from another system, so we read the - * netgraph ID from the mbuf for use in lookups */ - NGI_GET_M(item, m); - if (m->m_pkthdr.len < sizeof(ng_ID_t)) { /* too short */ - error = EINVAL; - goto rcvdata_ks_free_item_error; - } - if (m->m_len < sizeof(ng_ID_t) && - (m = m_pullup(m, sizeof(ng_ID_t))) == NULL) { - goto rcvdata_ks_free_item_error_nobufs; - } - srcid = ntohl(*mtod(m, ng_ID_t*)); - m_adj(m, sizeof(ng_ID_t)); - NGI_M(item) = (m); - /* build fake hooks/node for performing lookup */ - hooklookup2.hk_node = &nodelookup; - hooklookup.hk_peer = &hooklookup2; - nodelookup.nd_ID = srcid; - - /* Count number of linked nodes, not just number of hooks */ - nhooks = 0; - LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { - /* TODO: maintain a count of the number of linked nodes */ - if (hook2 == hook) - continue; - /* ksockets not counted here -- they'll be skipped */ - if (!ng_wlan_lookup(node, &hooklookup, hook2, NULL)) - continue; - nhooks++; - } - if (nhooks==0) /* Nobody to receive the data */ - goto rcvdata_ks_free_item_error; - - - LIST_FOREACH(hook2, &node->nd_hooks, hk_hooks) { - if (hook2 == hook) - continue; - /* Allocate a tag for prepending to the mbuf, which may or - may not be used. If used, the ptr is set to NULL for the - next loop iteration; unused (non-NULL ptr) will be freed - after loop. - */ - if (!tag) - tag = (struct ng_wlan_tag *)m_tag_alloc(NGM_WLAN_COOKIE, - NG_TAG_WLAN, TAGSIZE, M_NOWAIT | M_ZERO); - if (!tag) goto rcvdata_ks_free_item_error_nobufs; - WLAN_TAG_ZERO(tag); - - /* don't send data to other ksockets */ - if (IS_PEER_KSOCKET(hook2)) { - continue; - /* determine if peers are connected */ - } else if ( !ng_wlan_lookup(node, &hooklookup, hook2, tag)) { - continue; - } - - if (--nhooks == 0) { /* nhooks is really number of links */ - if (tag && TAG_HAS_DATA(tag)) { - m_tag_prepend(m, &tag->tag); - tag = NULL; /* tag used */ - } - NG_FWD_ITEM_HOOK(error, item, hook2); - } else { - if ((m2 = m_dup(m, M_DONTWAIT)) == NULL) - goto rcvdata_ks_free_item_error_nobufs; - if (tag && TAG_HAS_DATA(tag)) { - m_tag_prepend(m2, &tag->tag); - tag = NULL; /* tag used */ - } - NG_SEND_DATA_ONLY(error, hook2, m2); - if (error) /* XXX free mbuf? */ - continue; /* don't give up */ - } - } - if (tag) /* cleanup unused tag */ - m_tag_free(&tag->tag); - - goto rcvdata_ks_out; - -rcvdata_ks_free_item_error_nobufs: - error = ENOBUFS; -rcvdata_ks_free_item_error: - NG_FREE_ITEM(item); - -rcvdata_ks_out: -#ifndef FREEBSD411 -#ifdef WLAN_GIANT_LOCK - mtx_unlock(&ng_wlan_giant); -#else - mtx_unlock(&priv->ng_wlan_tab_lock); -#endif -#endif - return (error); -} -#endif /* !FREEBSD411 */ - - -static int -ng_wlan_disconnect(hook_p hook) -{ -#ifdef FREEBSD411 - const priv_p priv = hook->node->private; -#else - const priv_p priv = hook->hk_node->nd_private; -#endif - - if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 && - NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !priv->persistent) -#ifdef FREEBSD411 - ng_rmnode(NG_HOOK_NODE(hook)); -#else - ng_rmnode_self(NG_HOOK_NODE(hook)); -#endif - return (0); -} - -static int -ng_wlan_rmnode(node_p node) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - int b, s; - struct ng_wlan_hent *tmp; -#ifdef MULTICAST_LOOKUPS - struct ng_wlan_mcast_hent *mtmp; -#endif /* MULTICAST_LOOKUPS */ - s=splimp(); - -#ifdef FREEBSD411 - node->flags |= NG_INVALID; - ng_cutlinks(node); - ng_unname(node); -#else - node->nd_flags |= NGF_INVALID; -#endif - NG_NODE_SET_PRIVATE(node, NULL); - NG_NODE_UNREF(node); - /* empty any link lists */ - for (b = 0; b < MIN_BUCKETS; b++) { - tmp = SLIST_FIRST(&priv->tab[b]); - while (tmp) { - SLIST_REMOVE_HEAD(&priv->tab[b], next); - FREE(tmp, M_NETGRAPH_WLAN); - tmp = SLIST_FIRST(&priv->tab[b]); - } - } - FREE(priv->tab, M_NETGRAPH_WLAN); -#ifndef FREEBSD411 - mtx_destroy(&priv->ng_wlan_tab_lock); -#endif - priv->tab = NULL; -#ifdef MULTICAST_LOOKUPS - /* empty any multicast entry link lists */ - for (b = 0; b < MIN_BUCKETS; b++) { - mtmp = SLIST_FIRST(&priv->mcast_tab[b]); - while (mtmp) { - SLIST_REMOVE_HEAD(&priv->mcast_tab[b], next); - FREE(mtmp, M_NETGRAPH_WLAN); - mtmp = SLIST_FIRST(&priv->mcast_tab[b]); - } - } - FREE(priv->mcast_tab, M_NETGRAPH_WLAN); - mtx_destroy(&priv->ng_wlan_mcast_tab_lock); -#endif /* MULTICAST_LOOKUPS */ - FREE(priv, M_NETGRAPH_WLAN); - - splx(s); - return 0; -} - -/********************************************************************* -* WLAN FUNCTIONS * -**********************************************************************/ - -#define NODE_SORT(a, b, l, g) do { \ - if (a > b) { \ - g = a; \ - l = b; \ - } else { \ - g = b; \ - l = a; \ - } \ -} while (0); - -/* - * Returns 1 if peers are linked, 0 if unlinked (default). - */ -static int -ng_wlan_lookup(node_p node, hook_p hook1, hook_p hook2, - struct ng_wlan_tag *tag) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_wlan_hent *hent; - node_p node1, node2; - ng_ID_t l_id, g_id; - int bucket; - - if (!hook1 || !hook2) - return 0; - node1 = NG_PEER_NODE(hook1); - node2 = NG_PEER_NODE(hook2); - if (!node1 || !node2) - return 0; - - NODE_SORT(NG_NODE_ID(node1), NG_NODE_ID(node2), l_id, g_id); - bucket = HASH(l_id, g_id); - -/* mtx_lock(&priv->ng_wlan_tab_lock); */ - SLIST_FOREACH(hent, &priv->tab[bucket], next) { - if ((hent->l_id == l_id) && (hent->g_id == g_id)) { - /* optionally fill in tag with link data*/ - if (tag && hent->linked) { - tag->delay = hent->delay; - tag->bandwidth = hent->bandwidth; - tag->per = hent->per; - tag->duplicate = hent->duplicate; - tag->jitter = hent->jitter; - tag->burst = hent->burst; - } -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return (hent->linked); /* linked or not linked flag */ - } - } -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return 0; /* not linked (not found) */ -} - -#ifdef MULTICAST_LOOKUPS -/* - * Returns 1 if peers are linked for this multicast group, - * 0 if unlinked (default). - */ -static int -ng_wlan_mcast_lookup(node_p node, hook_p hook1, hook_p hook2, - u_int32_t group, u_int32_t source) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - struct ng_wlan_mcast_hent *hent; - node_p node1, node2; - ng_ID_t l_id, g_id; - int bucket; - - if (!hook1 || !hook2) - return 0; - - node1 = NG_PEER_NODE(hook1); - node2 = NG_PEER_NODE(hook2); - if (!node1 || !node2) - return 0; - - NODE_SORT(NG_NODE_ID(node1), NG_NODE_ID(node2), l_id, g_id); - bucket = MCAST_HASH(l_id, g_id, group); - - SLIST_FOREACH(hent, &priv->mcast_tab[bucket], next) { - if ((hent->l_id == l_id) && (hent->g_id == g_id) && - (hent->group == group) && (hent->source == source)) { - return (hent->linked); - } - } - return 0; /* not linked (not found) */ -} - -/* - * Link/unlink to peers for a given multicast group. - */ -static int -ng_wlan_mcast_link(node_p node, ng_ID_t node1, ng_ID_t node2, - u_int32_t group, u_int32_t source, int unlink) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - ng_ID_t l_id, g_id; - int bucket; - struct ng_wlan_mcast_hent *hent; - - NODE_SORT(node1, node2, l_id, g_id); - bucket = MCAST_HASH(l_id, g_id, group); - priv->multicast_enabled = 1; /* turn on multicast lookups, - this is never turned off */ - - /* Look for existing entry */ - SLIST_FOREACH(hent, &priv->mcast_tab[bucket], next) { - if ((hent->l_id == l_id) && (hent->g_id == g_id) && - (hent->group == group) && (hent->source == source)) - break; - } - - /* Unlink called but no entry exists */ - if (!hent && unlink) { - return 0; - } - - /* Allocate and initialize a new hash table entry */ - if (!hent) { - MALLOC( hent, struct ng_wlan_mcast_hent *, - sizeof(*hent), M_NETGRAPH_WLAN, M_NOWAIT); - if (hent == NULL) { - return(ENOBUFS); - } - hent->l_id = l_id; - hent->g_id = g_id; - hent->group = group; - hent->source = source; - /* Add the new element to the hash bucket */ - SLIST_INSERT_HEAD(&priv->mcast_tab[bucket], hent, next); - } - - if (unlink) - hent->linked = 0; - else - hent->linked = 1; - return 0; -} -#endif /* MULTICAST_LOOKUPS */ - -/* - * Link two peers together. - * Once two peers have been linked together, the link can be flagged as - * linked/unlinked in their hash table entry. Set link data if supplied. - */ -static int -ng_wlan_link(node_p node, ng_ID_t node1, ng_ID_t node2, - struct ng_wlan_set_data *data) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - ng_ID_t l_id, g_id; - int bucket; - struct ng_wlan_hent *hent; - - NODE_SORT(node1, node2, l_id, g_id); - bucket = HASH(l_id, g_id); -/* mtx_lock(&priv->ng_wlan_tab_lock); */ - - /* Look for existing entry */ - SLIST_FOREACH(hent, &priv->tab[bucket], next) { - if ((hent->l_id == l_id) && (hent->g_id == g_id)) - break; - } - /* Allocate and initialize a new hash table entry */ - if (!hent) { - MALLOC( hent, struct ng_wlan_hent *, - sizeof(*hent), M_NETGRAPH_WLAN, M_NOWAIT | M_ZERO); - if (hent == NULL) { -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return(ENOBUFS); - } - hent->l_id = l_id; - hent->g_id = g_id; - /* Add the new element to the hash bucket */ - SLIST_INSERT_HEAD(&priv->tab[bucket], hent, next); - } - - hent->linked = 1; - if (data) { - hent->delay = data->delay; - hent->bandwidth = data->bandwidth; - hent->per = data->per; - hent->duplicate = data->duplicate; - hent->jitter = data->jitter; - hent->burst = data->burst; - } else { - WLAN_TAG_ZERO(hent); - } -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return 0; -} - - -/* - * Unlink two previously-linked peers. - * because singly-linked list is not optimized for removals, we just - * unset the "linked" flag. Link data is zeroed. - */ -static int -ng_wlan_unlink(node_p node, ng_ID_t node1, ng_ID_t node2) -{ - const priv_p priv = NG_NODE_PRIVATE(node); - ng_ID_t l_id, g_id; - int bucket; - struct ng_wlan_hent *hent; - - NODE_SORT(node1, node2, l_id, g_id); - bucket = HASH(l_id, g_id); - - /* Look for existing entry */ -/* mtx_lock(&priv->ng_wlan_tab_lock); */ - SLIST_FOREACH(hent, &priv->tab[bucket], next) { - /* entry exists in hash table, unset linked flag */ - if ((hent->l_id == l_id) && (hent->g_id == g_id)) { - hent->linked = 0; - WLAN_TAG_ZERO(hent); -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return(0); - } - } - /* Entry does not exist in the hash table, do nothing. */ -/* mtx_unlock(&priv->ng_wlan_tab_lock); */ - return 0; -} - diff --git a/kernel/freebsd/ng_wlan/ng_wlan.h b/kernel/freebsd/ng_wlan/ng_wlan.h deleted file mode 100644 index 567a57a6..00000000 --- a/kernel/freebsd/ng_wlan/ng_wlan.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2006-2011 the Boeing Company - * ng_wlan is based on ng_hub, which is: - * Copyright (c) 2004 Ruslan Ermilov - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#ifndef _NETGRAPH_NG_WLAN_H_ -#define _NETGRAPH_NG_WLAN_H_ - -/* Node type name and magic cookie. */ -#define NG_WLAN_NODE_TYPE "wlan" -#define NGM_WLAN_COOKIE 1146673193 - -/* Control message parse info */ -struct ng_wlan_config { - u_int32_t node1; - u_int32_t node2; -}; -#define NG_WLAN_CONFIG_TYPE_INFO { \ - { "node1", &ng_parse_uint32_type }, \ - { "node2", &ng_parse_uint32_type }, \ - { NULL } \ -} - -struct ng_wlan_set_data { - u_int32_t node1; - u_int32_t node2; - u_int64_t delay; /* keep these aligned with struct ng_wlan_tag */ - u_int64_t bandwidth; - u_int16_t per; - u_int16_t duplicate; - u_int32_t jitter; - u_int16_t burst; -}; -#define NG_WLAN_SET_DATA_TYPE_INFO { \ - { "node1", &ng_parse_uint32_type }, \ - { "node2", &ng_parse_uint32_type }, \ - { "delay", &ng_parse_uint64_type }, \ - { "bandwidth", &ng_parse_uint64_type }, \ - { "per", &ng_parse_uint16_type }, \ - { "duplicate", &ng_parse_uint16_type }, \ - { "jitter", &ng_parse_uint32_type }, \ - { "burst", &ng_parse_uint16_type }, \ - { NULL } \ -} - -struct ng_wlan_mer { - uint16_t mer; - uint16_t mburst; -}; -#define NG_WLAN_MER_TYPE_INFO { \ - { "mer", &ng_parse_uint16_type }, \ - { "mburst", &ng_parse_uint16_type }, \ - { NULL } \ -} - -#ifdef MULTICAST_LOOKUPS -struct ng_wlan_multicast_set_data { - u_int32_t node1; - u_int32_t node2; - u_int32_t group; - u_int32_t source; -}; -#define NG_WLAN_MULTICAST_SET_DATA_TYPE_INFO { \ - { "node1", &ng_parse_uint32_type }, \ - { "node2", &ng_parse_uint32_type }, \ - { "group", &ng_parse_uint32_type }, \ - { "source", &ng_parse_uint32_type }, \ - { NULL } \ -} -#endif /* MULTICAST_LOOKUPS */ - -/* List of supported Netgraph control messages */ -enum { - NGM_WLAN_LINK_NODES = 1, - NGM_WLAN_UNLINK_NODES, - NGM_WLAN_NODES_SET, - NGM_WLAN_NODES_UNSET, - NGM_WLAN_NODES_GET, - NGM_WLAN_MER, /* MULTICAST_ERR */ - NGM_WLAN_MULTICAST_SET, /* MULTICAST_LOOKUPS */ - NGM_WLAN_MULTICAST_UNSET, /* MULTICAST_LOOKUPS */ - NGM_WLAN_MULTICAST_GET, /* MULTICAST_LOOKUPS */ -}; - -#endif /* _NETGRAPH_NG_WLAN_H_ */ diff --git a/kernel/freebsd/ng_wlan/ng_wlan_tag.h b/kernel/freebsd/ng_wlan/ng_wlan_tag.h deleted file mode 100644 index cf52802d..00000000 --- a/kernel/freebsd/ng_wlan/ng_wlan_tag.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2006-2011 the Boeing Company - * All rights reserved. - * - * author: Jeff Ahrenholz - */ - - -#define NG_TAG_WLAN 0x01 -#ifdef FREEBSD411 -#define WLAN_META_SIZE (sizeof(struct ng_meta))+(sizeof(struct ng_wlan_tag)) -#define WLAN_META_PRIORITY 0x01 -#define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct meta_field_header)) -#else -#define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct m_tag)) -#endif - -#define NG_WLAN_MAX_DELAY 2000000 /* 2,000,000us = 2s */ -#define NG_WLAN_MAX_BW 1000000000 /* 1,000,000,000bps = 1000M */ -#define NG_WLAN_MAX_PER 100 /* 100% */ -#define NG_WLAN_MAX_DUP 50 /* 50% */ -#define NG_WLAN_MAX_JITTER NG_WLAN_MAX_DELAY -#define NG_WLAN_MAX_BURST NG_WLAN_MAX_PER - -/* Tag data that is prepended to packets passing through the WLAN node. - */ -struct ng_wlan_tag { -#ifdef FREEBSD411 - struct meta_field_header meta_hdr; -#else - struct m_tag tag; -#endif - u_int64_t delay; - u_int64_t bandwidth; - u_int16_t per; - u_int16_t duplicate; - u_int32_t jitter; - u_int16_t burst; -}; - -#define TAG_HAS_DATA(t) (t->delay || t->bandwidth || t->per || t->duplicate \ - || t->jitter || t->burst ) - -#define WLAN_TAG_ZERO(t) do { \ - t->delay = 0; \ - t->bandwidth = 0; \ - t->per = 0; \ - t->duplicate = 0; \ - t->jitter = 0; \ - t->burst = 0; \ -} while(0); - -#define WLAN_TAG_COPY(a, b) do { \ - a->delay = ((struct ng_wlan_tag*)b)->delay; \ - a->bandwidth = ((struct ng_wlan_tag*)b)->bandwidth; \ - a->per = ((struct ng_wlan_tag*)b)->per; \ - a->duplicate = ((struct ng_wlan_tag*)b)->duplicate; \ - a->jitter = ((struct ng_wlan_tag*)b)->jitter; \ - a->burst = ((struct ng_wlan_tag*)b)->burst; \ -} while(0); diff --git a/kernel/freebsd/symlinks-8.1-RELEASE.diff b/kernel/freebsd/symlinks-8.1-RELEASE.diff deleted file mode 100644 index e713e76c..00000000 --- a/kernel/freebsd/symlinks-8.1-RELEASE.diff +++ /dev/null @@ -1,78 +0,0 @@ -Index: sys/kern/vfs_lookup.c -=========================================================================== ---- sys/kern/vfs_lookup.c 2010/06/17 19:18:00 #3 -+++ sys/kern/vfs_lookup.c 2010/06/17 19:18:00 -@@ -59,6 +59,8 @@ - #include - #endif - -+#include -+ - #include - #include - -@@ -72,6 +74,19 @@ - "unsigned long"); - SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *"); - -+#ifdef VIMAGE -+#define IMUNES_SYMLINK_HACK -+#endif -+ -+#ifdef IMUNES_SYMLINK_HACK -+static VNET_DEFINE(int, morphing_symlinks); -+#define V_morphing_symlinks VNET(morphing_symlinks) -+ -+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW, -+ &VNET_NAME(morphing_symlinks), 0, -+ "Resolve @ to vimage name in symlinks"); -+#endif -+ - /* - * Allocation zone for namei - */ -@@ -333,6 +348,44 @@ - error = ENOENT; - break; - } -+#ifdef IMUNES_SYMLINK_HACK -+ /* -+ * If the symbolic link includes a special character '@', -+ * and V_morphing_symlinks is set, substitute the first -+ * occurence of '@' with full path to jail / vimage name. -+ * If the full path includes subhierarchies, s/./\// when -+ * expanding '@' to jail / vimage name. -+ * -+ * XXX revisit buffer length checking. -+ */ -+ CURVNET_SET_QUIET(TD_TO_VNET(curthread)); -+ if (V_morphing_symlinks) { -+ char *sp = strchr(cp, '@'); -+ -+ if (sp) { -+ char *vname = td->td_ucred->cr_prison->pr_name; -+ int vnamelen = strlen(vname); -+ int i; -+ -+ if (vnamelen >= auio.uio_resid) { -+ if (ndp->ni_pathlen > 1) -+ uma_zfree(namei_zone, cp); -+ error = ENAMETOOLONG; -+ CURVNET_RESTORE(); -+ break; -+ } -+ bcopy(sp + 1, sp + vnamelen, -+ linklen - (sp - cp)); -+ bcopy(td->td_ucred->cr_prison->pr_name, -+ sp, vnamelen); -+ linklen += (vnamelen - 1); -+ for (i = 0; i < vnamelen; i++) -+ if (sp[i] == '.') -+ sp[i] = '/'; -+ } -+ } -+ CURVNET_RESTORE(); -+#endif - if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { - if (ndp->ni_pathlen > 1) - uma_zfree(namei_zone, cp); diff --git a/kernel/freebsd/vimage/Makefile b/kernel/freebsd/vimage/Makefile deleted file mode 100644 index 76c76179..00000000 --- a/kernel/freebsd/vimage/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# $FreeBSD$ - -PROG= vimage -LDADD= -ljail -DPADD= ${LIBJAIL} - -WARNS?= 2 -CFLAGS+= -I../../../sys - -MAN= vimage.8 - -BINDIR?= /usr/sbin - -.include diff --git a/kernel/freebsd/vimage/vimage.8 b/kernel/freebsd/vimage/vimage.8 deleted file mode 100644 index d55bcba4..00000000 --- a/kernel/freebsd/vimage/vimage.8 +++ /dev/null @@ -1,195 +0,0 @@ -.\" Copyright (c) 2002, 2003 Marko Zec -.\" Copyright (c) 2009 University of Zagreb -.\" Copyright (c) 2009 FreeBSD Foundation -.\" -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd August 25, 2009 -.Dt VIMAGE 8 -.Os -.Sh NAME -.Nm vimage -.Nd manage virtual network stacks -.Sh SYNOPSIS -.Nm -.Op Fl c | m -.Ar vname -.Op Ar param=value ... -.Nm -.Fl d -.Ar vname -.Nm -.Fl l -.Op Fl rvj -.Op Ar vname -.Nm -.Fl i -.Ar vname ifname -.Op Ar newifname -.Nm -.Ar vi_name -.Op command ... -.Sh DESCRIPTION -The -.Nm -utility is an alternative user interface for controlling virtual network -stacks in FreeBSD, aimed primarily at supporting legacy applications -which are not yet converted to using -.Xr jail 8 , -.Xr jexec 8 , -and -.Xr jls 8 . -. -.Ss Overview -A virtual image or vimage is a jail with its own independent network -stack instance. Every process, socket and network interface present -in the system is always attached to one, and only one, virtual network -stack instance (vnet). -During system bootup sequence a default vnet -is created to which all the configured interfaces and user processes -are initially attached. -Assuming that enough system resources are -are available, a user with sufficient privileges can create and manage -a hierarchy of subordinated virtual images. -The -.Nm -command allows for creation, deletion and monitoring of virtual images, -as well as for execution of arbitrary processes in a targeted virtual -image. -.Ss Invocation -If invoked with no modifiers, the -.Nm -command spawns a new interactive shell in virtual image -.Ar vname . -If optional additional arguments following -.Ar vname -are provided, the first of those will be executed in place of the -interactive shell, and the rest of the arguments will be passed as -arguments to the executed command. -.Pp -The following modifiers are available: -.Bl -tag -width indent -.It Fl c -Create a new virtual image named -.Ar vname . -Additional arguments, if provided, may be used to specify operating -parameters different from defaults, in format -.Ar param=value . -See -.Xr jail 8 -for an extensive list of available parameters. -.It Fl m -Modify the parameters of a virtual image named -.Ar vname , -using the same syntax as with the -c form of the command. -.It Fl d -Delete the virtual image -.Ar vname . -No processes and/or sockets should exist in the target virtual image -in order for the delete request to succeed. Non-loopback interfaces -residing in the target virtual image will be reassigned to the virtual -image's parent. -.It Fl l -List the properties and statistics for virtual images one level -below the current one in the hierarchy. If an optional argument -.Ar vname -is provided, only the information regarding the target virtual image -.Ar vname -is displayed. -With the optional -.Op Ar -r -switch enabled the list will include all virtual images below the -current level in the vimage hierarchy. -Enabling the optional -.Op Ar -v -or -.Op Ar -j -switches results in a more detailed output. -.It Fl i -Move interface -.Ar ifname -to the target virtual image -.Ar vname . -Interfaces will be automatically renamed to -.So -ethXX -.Sc , -unless an optional argument specifying the desired interface name -.Op Ar newifname -is provided. -.El -.Sh EXAMPLES -Create a new virtual image named -.So v1 -.Sc , -which is allowed to create and manage an own subhierarchy of vimages: -.Pp -.Dl vimage -c v1 children.max=100 -.Pp -Execute the -.So ifconfig -.Sc command in the virtual image -.So v1 -.Sc : -.Pp -.Dl vimage v1 ifconfig -.Pp -Move the interface -.So vlan0 -.Sc to the virtual image -.So v1 -.Sc while renaming the interface as -.So -ve0 -.Sc : -.Pp -.Dl vimage -i v1 vlan0 ve0 -.Pp -Show the status information for virtual image -.So v1 -.Sc : -.Pp -.Dl vimage -lv v1 -.Sh DIAGNOSTICS -The -.Nm -command exits 0 on success, and >0 if an error occurs. -.Sh SEE ALSO -.Xr jail 8 -.Xr jexec 8 -.Xr jls 8 -.Sh HISTORY -Network stack virtualization framework first appeared as a patchset -against the FreeBSD 4.7 kernel in 2002, and was maintained outside -of the main FreeBSD tree. -As a result of a project sponsored by the FreeBSD Foundation and -Stiching NLNet, integrated virtualized network stack first appeared -in FreeBSD 8.0. -.Sh BUGS -Deletion of vimages / vnets is known to leak kernel memory and fail at -stopping various timers, hence may lead to system crashes. -.Sh AUTHOR -.An "Marko Zec" Aq zec@fer.hr diff --git a/kernel/freebsd/vimage/vimage.c b/kernel/freebsd/vimage/vimage.c deleted file mode 100644 index e6655999..00000000 --- a/kernel/freebsd/vimage/vimage.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2002-2004 Marko Zec - * Copyright (c) 2009 University of Zagreb - * Copyright (c) 2009 FreeBSD Foundation - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -typedef enum { - VI_SWITCHTO, - VI_CREATE, - VI_MODIFY, - VI_DESTROY, - VI_IFMOVE, - VI_GET -} vi_cmd_t; - -typedef struct vimage_status { - char name[MAXPATHLEN]; /* Must be first field for strcmp(). */ - char path[MAXPATHLEN]; - char hostname[MAXPATHLEN]; - char domainname[MAXPATHLEN]; - int jid; - int parentjid; - int vnet; - int childcnt; - int childmax; - int cpuset; - int rawsock; - int socket_af; - int mount; -} vstat_t; - -#define VST_SIZE_STEP 1024 -#define MAXPARAMS 32 - -static int getjail(vstat_t *, int, int); - -static char *invocname; - -static void -usage(void) -{ - - fprintf(stderr, - "usage: %s [-c | -m] vname [param=value ...]\n" - " %s -d vname\n" - " %s -l[rvj] [vname]\n" - " %s -i vname ifname [newifname]\n" - " %s vname [command ...]\n", - invocname, invocname, invocname, invocname, invocname); - exit(1); -} - -int -main(int argc, char **argv) -{ - struct jailparam params[MAXPARAMS]; - char ifname[IFNAMSIZ]; - struct ifreq ifreq; - vi_cmd_t newcmd, cmd; - int recurse = 0; - int verbose = 0; - int jid, i, s, namelen; - int vst_size, vst_last; - vstat_t *vst; - char *str; - char ch; - - invocname = argv[0]; - - newcmd = cmd = VI_SWITCHTO; /* Default if no modifiers specified. */ - while ((ch = getopt(argc, argv, "cdijlmrv")) != -1) { - switch (ch) { - case 'c': - newcmd = VI_CREATE; - break; - case 'm': - newcmd = VI_MODIFY; - break; - case 'd': - newcmd = VI_DESTROY; - break; - case 'l': - newcmd = VI_GET; - break; - case 'i': - newcmd = VI_IFMOVE; - break; - case 'r': - recurse = 1; - break; - case 'v': - verbose++; - break; - case 'j': - verbose = 2; - break; - default: - usage(); - } - if (cmd == VI_SWITCHTO || cmd == newcmd) - cmd = newcmd; - else - usage(); - } - argc -= optind; - argv += optind; - - if ((cmd != VI_GET && (argc == 0 || recurse != 0 || verbose != 0)) || - (cmd == VI_IFMOVE && (argc < 2 || argc > 3)) || - (cmd == VI_MODIFY && argc < 2) || argc >= MAXPARAMS) - usage(); - - switch (cmd) { - case VI_GET: - vst_last = 0; - vst_size = VST_SIZE_STEP; - if ((vst = malloc(vst_size * sizeof(*vst))) == NULL) - break; - if (argc == 1) - namelen = strlen(argv[0]); - else - namelen = 0; - jid = 0; - while ((jid = getjail(&vst[vst_last], jid, verbose)) > 0) { - /* Skip jails which do not own vnets. */ - if (vst[vst_last].vnet != 1) - continue; - /* Skip non-matching vnames / hierarchies. */ - if (namelen && - ((strlen(vst[vst_last].name) < namelen || - strncmp(vst[vst_last].name, argv[0], namelen) != 0) - || (strlen(vst[vst_last].name) > namelen && - vst[vst_last].name[namelen] != '.'))) - continue; - /* Skip any sub-trees if -r not requested. */ - if (!recurse && - (strlen(vst[vst_last].name) < namelen || - strchr(&vst[vst_last].name[namelen], '.') != NULL)) - continue; - /* Grow vst table if necessary. */ - if (++vst_last == vst_size) { - vst_size += VST_SIZE_STEP; - vst = realloc(vst, vst_size * sizeof(*vst)); - if (vst == NULL) - break; - } - } - if (vst == NULL) - break; - /* Sort: the key is the 1st field in *vst, i.e. vimage name. */ - qsort(vst, vst_last, sizeof(*vst), (void *) strcmp); - for (i = 0; i < vst_last; i++) { - if (!verbose) { - printf("%s\n", vst[i].name); - continue; - } - - printf("%s:\n", vst[i].name); - printf(" Path: %s\n", vst[i].path); - printf(" Hostname: %s\n", vst[i].hostname); - printf(" Domainname: %s\n", vst[i].domainname); - printf(" Children: %d\n", vst[i].childcnt); - - if (verbose < 2) - continue; - - printf(" Children limit: %d\n", vst[i].childmax); - printf(" CPUsetID: %d\n", vst[i].cpuset); - printf(" JID: %d\n", vst[i].jid); - printf(" PJID: %d\n", vst[i].parentjid); - printf(" Raw sockets allowed: %d\n", vst[i].rawsock); - printf(" All AF allowed: %d\n", vst[i].socket_af); - printf(" Mount allowed: %d\n", vst[i].mount); - } - free(vst); - exit(0); - - case VI_IFMOVE: - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - break; - if ((jid = jail_getid(argv[0])) < 0) - break; - ifreq.ifr_jid = jid; - strncpy(ifreq.ifr_name, argv[1], sizeof(ifreq.ifr_name)); - if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0) - break; - close(s); - if (argc == 3) - snprintf(ifname, sizeof(ifname), "%s", argv[2]); - else - snprintf(ifname, sizeof(ifname), "eth0"); - ifreq.ifr_data = ifname; - /* Do we need to rename the ifnet? */ - if (strcmp(ifreq.ifr_name, ifname) != 0) { - /* Switch to the context of the target vimage. */ - if (jail_attach(jid) < 0) - break; - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - break; - for (namelen = 0; isalpha(ifname[namelen]); namelen++); - i = 0; - /* Search for a free ifunit in target vnet. Unsafe. */ - while (ioctl(s, SIOCSIFNAME, (caddr_t)&ifreq) < 0) { - snprintf(&ifname[namelen], - sizeof(ifname) - namelen, "%d", i); - /* Emergency brake. */ - if (i++ == IF_MAXUNIT) - break; - } - } - if (i < IF_MAXUNIT) - printf("%s@%s\n", ifname, argv[0]); - else - printf("%s@%s\n", ifreq.ifr_name, argv[0]); - exit(0); - - case VI_CREATE: - if (jail_setv(JAIL_CREATE, - "name", argv[0], - "vnet", NULL, - "host", NULL, - "persist", NULL, - "allow.raw_sockets", "true", - "allow.socket_af", "true", - "allow.mount", "true", - NULL) < 0) - break; - if (argc == 1) - exit(0); - /* Not done yet, proceed to apply non-default parameters. */ - - case VI_MODIFY: - jailparam_init(¶ms[0], "name"); - jailparam_import(¶ms[0], argv[0]); - for (i = 1; i < argc; i++) { - for (str = argv[i]; *str != '=' && *str != 0; str++) { - /* Do nothing - search for '=' delimeter. */ - } - if (*str == 0) - break; - *str++ = 0; - if (*str == 0) - break; - jailparam_init(¶ms[i], argv[i]); - jailparam_import(¶ms[i], str); - } - if (i != argc) - break; - if (jailparam_set(params, i, JAIL_UPDATE) < 0) - break; - exit(0); - - case VI_DESTROY: - if ((jid = jail_getid(argv[0])) < 0) - break; - if (jail_remove(jid) < 0) - break; - exit(0); - - case VI_SWITCHTO: - if ((jid = jail_getid(argv[0])) < 0) - break; - if (jail_attach(jid) < 0) - break; - if (argc == 1) { - printf("Switched to vimage %s\n", argv[0]); - if ((str = getenv("SHELL")) == NULL) - execlp("/bin/sh", invocname, NULL); - else - execlp(str, invocname, NULL); - } else - execvp(argv[1], &argv[1]); - break; - - default: - /* Should be unreachable. */ - break; - } - - if (jail_errmsg[0]) - fprintf(stderr, "Error: %s\n", jail_errmsg); - else - perror("Error"); - exit(1); -} - -static int -getjail(vstat_t *vs, int lastjid, int verbose) -{ - struct jailparam params[32]; /* Must be > max(psize). */ - int psize = 0; - - bzero(params, sizeof(params)); - bzero(vs, sizeof(*vs)); - - jailparam_init(¶ms[psize], "lastjid"); - jailparam_import_raw(¶ms[psize++], &lastjid, sizeof lastjid); - - jailparam_init(¶ms[psize], "vnet"); - jailparam_import_raw(¶ms[psize++], &vs->vnet, sizeof(vs->vnet)); - - jailparam_init(¶ms[psize], "name"); - jailparam_import_raw(¶ms[psize++], &vs->name, sizeof(vs->name)); - - if (verbose == 0) - goto done; - - jailparam_init(¶ms[psize], "path"); - jailparam_import_raw(¶ms[psize++], &vs->path, sizeof(vs->path)); - - jailparam_init(¶ms[psize], "host.hostname"); - jailparam_import_raw(¶ms[psize++], &vs->hostname, - sizeof(vs->hostname)); - - jailparam_init(¶ms[psize], "host.domainname"); - jailparam_import_raw(¶ms[psize++], &vs->domainname, - sizeof(vs->domainname)); - - jailparam_init(¶ms[psize], "children.cur"); - jailparam_import_raw(¶ms[psize++], &vs->childcnt, - sizeof(vs->childcnt)); - - if (verbose == 1) - goto done; - - jailparam_init(¶ms[psize], "children.max"); - jailparam_import_raw(¶ms[psize++], &vs->childmax, - sizeof(vs->childmax)); - - jailparam_init(¶ms[psize], "cpuset.id"); - jailparam_import_raw(¶ms[psize++], &vs->cpuset, - sizeof(vs->cpuset)); - - jailparam_init(¶ms[psize], "parent"); - jailparam_import_raw(¶ms[psize++], &vs->parentjid, - sizeof(vs->parentjid)); - - jailparam_init(¶ms[psize], "allow.raw_sockets"); - jailparam_import_raw(¶ms[psize++], &vs->rawsock, - sizeof(vs->rawsock)); - - jailparam_init(¶ms[psize], "allow.socket_af"); - jailparam_import_raw(¶ms[psize++], &vs->socket_af, - sizeof(vs->socket_af)); - - jailparam_init(¶ms[psize], "allow.mount"); - jailparam_import_raw(¶ms[psize++], &vs->mount, sizeof(vs->mount)); - -done: - vs->jid = jailparam_get(params, psize, 0); - jailparam_free(params, psize); - return (vs->jid); -} diff --git a/kernel/freebsd/vimage_7-CORE.diff b/kernel/freebsd/vimage_7-CORE.diff deleted file mode 100644 index c28bd1be..00000000 --- a/kernel/freebsd/vimage_7-CORE.diff +++ /dev/null @@ -1,3077 +0,0 @@ -diff -ur sys.20081015/netinet/ip_mroute.c sys/netinet/ip_mroute.c ---- sys.20081015/netinet/ip_mroute.c 2008-08-16 16:29:19.000000000 -0700 -+++ sys/netinet/ip_mroute.c 2008-11-05 16:30:04.000000000 -0800 -@@ -99,6 +99,7 @@ - #include - #include - #ifdef INET6 -+#include - #include - #include - #include -@@ -112,21 +113,30 @@ - * Control debugging code for rsvp and multicast routing code. - * Can only set them with the debugger. - */ -+#ifndef VIMAGE - static u_int rsvpdebug; /* non-zero enables debugging */ - - static u_int mrtdebug; /* any set of the flags below */ -+#endif /* !VIMAGE */ - #define DEBUG_MFC 0x02 - #define DEBUG_FORWARD 0x04 - #define DEBUG_EXPIRE 0x08 - #define DEBUG_XMIT 0x10 - #define DEBUG_PIM 0x20 - -+#ifndef VIMAGE - #define VIFI_INVALID ((vifi_t) -1) -+#endif /* !VIMAGE */ - - #define M_HASCL(m) ((m)->m_flags & M_EXT) - - static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables"); - -+static int vnet_mroute_iattach(const void *); -+static int vnet_mroute_idetach(const void *); -+ -+VNET_MOD_DECLARE(MROUTE, mroute, vnet_mroute_iattach, vnet_mroute_idetach, INET, NULL) -+ - /* - * Locking. We use two locks: one for the virtual interface table and - * one for the forwarding table. These locks may be nested in which case -@@ -140,48 +150,59 @@ - * - */ - -+#ifndef VIMAGE - static struct mrtstat mrtstat; --SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW, -- &mrtstat, mrtstat, -+#endif /* !VIMAGE */ -+SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_ip, OID_AUTO, mrtstat, -+ CTLFLAG_RW, mrtstat, mrtstat, - "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)"); -- -+#ifndef VIMAGE - static struct mfc *mfctable[MFCTBLSIZ]; --SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, mfctable, CTLFLAG_RD, -- &mfctable, sizeof(mfctable), "S,*mfc[MFCTBLSIZ]", -+SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO, -+ mfctable, CTLFLAG_RD, mfctable, sizeof(mfctable), sysctl_handle_opaque, -+ "S,*mfc[MFCTBLSIZ]", - "Multicast Forwarding Table (struct *mfc[MFCTBLSIZ], netinet/ip_mroute.h)"); - - static struct mtx mrouter_mtx; --#define MROUTER_LOCK() mtx_lock(&mrouter_mtx) --#define MROUTER_UNLOCK() mtx_unlock(&mrouter_mtx) --#define MROUTER_LOCK_ASSERT() mtx_assert(&mrouter_mtx, MA_OWNED) -+#endif /* !VIMAGE */ -+#define MROUTER_LOCK() mtx_lock(&V_mrouter_mtx) -+#define MROUTER_UNLOCK() mtx_unlock(&V_mrouter_mtx) -+#define MROUTER_LOCK_ASSERT() mtx_assert(&V_mrouter_mtx, MA_OWNED) - #define MROUTER_LOCK_INIT() \ -- mtx_init(&mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF) --#define MROUTER_LOCK_DESTROY() mtx_destroy(&mrouter_mtx) -+ mtx_init(&V_mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF) -+#define MROUTER_LOCK_DESTROY() mtx_destroy(&V_mrouter_mtx) - -+#ifndef VIMAGE - static struct mtx mfc_mtx; --#define MFC_LOCK() mtx_lock(&mfc_mtx) --#define MFC_UNLOCK() mtx_unlock(&mfc_mtx) --#define MFC_LOCK_ASSERT() mtx_assert(&mfc_mtx, MA_OWNED) --#define MFC_LOCK_INIT() mtx_init(&mfc_mtx, "mroute mfc table", NULL, MTX_DEF) --#define MFC_LOCK_DESTROY() mtx_destroy(&mfc_mtx) -+#endif /* !VIMAGE */ -+#define MFC_LOCK() mtx_lock(&V_mfc_mtx) -+#define MFC_UNLOCK() mtx_unlock(&V_mfc_mtx) -+#define MFC_LOCK_ASSERT() mtx_assert(&V_mfc_mtx, MA_OWNED) -+#define MFC_LOCK_INIT() mtx_init(&V_mfc_mtx, "mroute mfc table", NULL, MTX_DEF) -+#define MFC_LOCK_DESTROY() mtx_destroy(&V_mfc_mtx) - -+#ifndef VIMAGE - static struct vif viftable[MAXVIFS]; --SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD, -- &viftable, sizeof(viftable), "S,vif[MAXVIFS]", -+SYSCTL_V_OID(V_NET, vnet_mroute, _net_inet_ip, CTLTYPE_OPAQUE|OID_AUTO, viftable, -+ CTLFLAG_RD, viftable, sizeof(viftable), sysctl_handle_opaque, -+ "S,vif[MAXVIFS]", - "Multicast Virtual Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)"); - - static struct mtx vif_mtx; --#define VIF_LOCK() mtx_lock(&vif_mtx) --#define VIF_UNLOCK() mtx_unlock(&vif_mtx) --#define VIF_LOCK_ASSERT() mtx_assert(&vif_mtx, MA_OWNED) --#define VIF_LOCK_INIT() mtx_init(&vif_mtx, "mroute vif table", NULL, MTX_DEF) --#define VIF_LOCK_DESTROY() mtx_destroy(&vif_mtx) -+#endif /* !VIMAGE */ -+#define VIF_LOCK() mtx_lock(&V_vif_mtx) -+#define VIF_UNLOCK() mtx_unlock(&V_vif_mtx) -+#define VIF_LOCK_ASSERT() mtx_assert(&V_vif_mtx, MA_OWNED) -+#define VIF_LOCK_INIT() mtx_init(&V_vif_mtx, "mroute vif table", NULL, MTX_DEF) -+#define VIF_LOCK_DESTROY() mtx_destroy(&V_vif_mtx) - -+#ifndef VIMAGE - static u_char nexpire[MFCTBLSIZ]; - - static eventhandler_tag if_detach_event_tag = NULL; - - static struct callout expire_upcalls_ch; -+#endif /* !VIMAGE */ - - #define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */ - #define UPCALL_EXPIRE 6 /* number of timeouts */ -@@ -196,25 +217,31 @@ - * Pending timeouts are stored in a hash table, the key being the - * expiration time. Periodically, the entries are analysed and processed. - */ -+#ifndef VIMAGE - #define BW_METER_BUCKETS 1024 - static struct bw_meter *bw_meter_timers[BW_METER_BUCKETS]; --static struct callout bw_meter_ch; -+static struct callout V_bw_meter_ch; -+#endif /* !VIMAGE */ - #define BW_METER_PERIOD (hz) /* periodical handling of bw meters */ - - /* - * Pending upcalls are stored in a vector which is flushed when - * full, or periodically - */ -+#ifndef VIMAGE - static struct bw_upcall bw_upcalls[BW_UPCALLS_MAX]; - static u_int bw_upcalls_n; /* # of pending upcalls */ - static struct callout bw_upcalls_ch; -+#endif /* !VIMAGE */ - #define BW_UPCALLS_PERIOD (hz) /* periodical flush of bw upcalls */ - -+#ifndef VIMAGE - static struct pimstat pimstat; -+#endif /* !VIMAGE */ - - SYSCTL_NODE(_net_inet, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); --SYSCTL_STRUCT(_net_inet_pim, PIMCTL_STATS, stats, CTLFLAG_RD, -- &pimstat, pimstat, -+SYSCTL_V_STRUCT(V_NET, vnet_mroute, _net_inet_pim, PIMCTL_STATS, stats, -+ CTLFLAG_RD, pimstat, pimstat, - "PIM Statistics (struct pimstat, netinet/pim_var.h)"); - - static u_long pim_squelch_wholepkt = 0; -@@ -222,6 +249,7 @@ - &pim_squelch_wholepkt, 0, - "Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified"); - -+ - extern struct domain inetdomain; - struct protosw in_pim_protosw = { - .pr_type = SOCK_RAW, -@@ -291,13 +319,17 @@ - 0 /* flags */ - }; - -+#ifndef VIMAGE - static struct ifnet multicast_register_if; - static vifi_t reg_vif_num = VIFI_INVALID; -+#endif /* !VIMAGE */ - - /* - * Private variables. - */ -+#ifndef VIMAGE - static vifi_t numvifs; -+#endif /* !VIMAGE */ - - static u_long X_ip_mcast_src(int vifi); - static int X_ip_mforward(struct ip *ip, struct ifnet *ifp, -@@ -337,7 +369,7 @@ - static void bw_upcalls_send(void); - static void schedule_bw_meter(struct bw_meter *x, struct timeval *nowp); - static void unschedule_bw_meter(struct bw_meter *x); --static void bw_meter_process(void); -+static void bw_meter_process(struct vnet *vnet); - static void expire_bw_upcalls_send(void *); - static void expire_bw_meter_process(void *); - -@@ -352,7 +384,9 @@ - /* - * whether or not special PIM assert processing is enabled. - */ -+#ifndef VIMAGE - static int pim_assert; -+#endif /* !VIMAGE */ - /* - * Rate limit for assert notification messages, in usec - */ -@@ -367,7 +401,9 @@ - MRT_MFC_FLAGS_BORDER_VIF | - MRT_MFC_RP | - MRT_MFC_BW_UPCALL); -+#ifndef VIMAGE - static uint32_t mrt_api_config = 0; -+#endif /* !VIMAGE */ - - /* - * Hash function for a source, group entry -@@ -383,11 +419,12 @@ - static struct mfc * - mfc_find(in_addr_t o, in_addr_t g) - { -+ INIT_VNET_MROUTE(curvnet); - struct mfc *rt; - - MFC_LOCK_ASSERT(); - -- for (rt = mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next) -+ for (rt = V_mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next) - if ((rt->mfc_origin.s_addr == o) && - (rt->mfc_mcastgrp.s_addr == g) && (rt->mfc_stall == NULL)) - break; -@@ -424,7 +461,8 @@ - static int - X_ip_mrouter_set(struct socket *so, struct sockopt *sopt) - { -- INIT_VNET_INET(curvnet); -+ INIT_VNET_INET(so->so_vnet); -+ INIT_VNET_MROUTE(so->so_vnet); - int error, optval; - vifi_t vifi; - struct vifctl vifc; -@@ -468,7 +506,7 @@ - * select data size depending on API version. - */ - if (sopt->sopt_name == MRT_ADD_MFC && -- mrt_api_config & MRT_API_FLAGS_ALL) { -+ V_mrt_api_config & MRT_API_FLAGS_ALL) { - error = sooptcopyin(sopt, &mfc, sizeof(struct mfcctl2), - sizeof(struct mfcctl2)); - } else { -@@ -525,6 +563,7 @@ - static int - X_ip_mrouter_get(struct socket *so, struct sockopt *sopt) - { -+ INIT_VNET_MROUTE(so->so_vnet); - int error; - static int version = 0x0305; /* !!! why is this here? XXX */ - -@@ -534,7 +573,7 @@ - break; - - case MRT_ASSERT: -- error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert); -+ error = sooptcopyout(sopt, &V_pim_assert, sizeof V_pim_assert); - break; - - case MRT_API_SUPPORT: -@@ -542,7 +581,7 @@ - break; - - case MRT_API_CONFIG: -- error = sooptcopyout(sopt, &mrt_api_config, sizeof mrt_api_config); -+ error = sooptcopyout(sopt, &V_mrt_api_config, sizeof V_mrt_api_config); - break; - - default: -@@ -590,6 +629,7 @@ - static int - get_sg_cnt(struct sioc_sg_req *req) - { -+ INIT_VNET_MROUTE(curvnet); - struct mfc *rt; - - MFC_LOCK(); -@@ -612,18 +652,19 @@ - static int - get_vif_cnt(struct sioc_vif_req *req) - { -+ INIT_VNET_MROUTE(curvnet); - vifi_t vifi = req->vifi; - - VIF_LOCK(); -- if (vifi >= numvifs) { -+ if (vifi >= V_numvifs) { - VIF_UNLOCK(); - return EINVAL; - } - -- req->icount = viftable[vifi].v_pkt_in; -- req->ocount = viftable[vifi].v_pkt_out; -- req->ibytes = viftable[vifi].v_bytes_in; -- req->obytes = viftable[vifi].v_bytes_out; -+ req->icount = V_viftable[vifi].v_pkt_in; -+ req->ocount = V_viftable[vifi].v_pkt_out; -+ req->ibytes = V_viftable[vifi].v_bytes_in; -+ req->obytes = V_viftable[vifi].v_bytes_out; - VIF_UNLOCK(); - - return 0; -@@ -632,24 +673,30 @@ - static void - ip_mrouter_reset(void) - { -- bzero((caddr_t)mfctable, sizeof(mfctable)); -- bzero((caddr_t)nexpire, sizeof(nexpire)); -- -- pim_assert = 0; -- mrt_api_config = 0; -- -- callout_init(&expire_upcalls_ch, CALLOUT_MPSAFE); -- -- bw_upcalls_n = 0; -- bzero((caddr_t)bw_meter_timers, sizeof(bw_meter_timers)); -- callout_init(&bw_upcalls_ch, CALLOUT_MPSAFE); -- callout_init(&bw_meter_ch, CALLOUT_MPSAFE); -+ INIT_VNET_MROUTE(curvnet); -+ bzero((caddr_t)V_mfctable, sizeof(V_mfctable)); -+ bzero((caddr_t)V_nexpire, sizeof(V_nexpire)); -+ if (V_reg_vif_num != VIFI_INVALID) -+ IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); -+ bzero(&V_multicast_register_if, sizeof(V_multicast_register_if)); -+ -+ V_reg_vif_num = VIFI_INVALID; -+ V_pim_assert = 0; -+ V_mrt_api_config = 0; -+ -+ callout_init(&V_expire_upcalls_ch, CALLOUT_MPSAFE); -+ -+ V_bw_upcalls_n = 0; -+ bzero((caddr_t)V_bw_meter_timers, sizeof(V_bw_meter_timers)); -+ callout_init(&V_bw_upcalls_ch, CALLOUT_MPSAFE); -+ callout_init(&V_bw_meter_ch, CALLOUT_MPSAFE); - } - - static void - if_detached_event(void *arg __unused, struct ifnet *ifp) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - vifi_t vifi; - int i; - struct mfc *mfc; -@@ -676,12 +723,12 @@ - */ - VIF_LOCK(); - MFC_LOCK(); -- for (vifi = 0; vifi < numvifs; vifi++) { -- if (viftable[vifi].v_ifp != ifp) -+ for (vifi = 0; vifi < V_numvifs; vifi++) { -+ if (V_viftable[vifi].v_ifp != ifp) - continue; - for (i = 0; i < MFCTBLSIZ; i++) { -- ppmfc = &mfctable[i]; -- for (mfc = mfctable[i]; mfc != NULL; ) { -+ ppmfc = &V_mfctable[i]; -+ for (mfc = V_mfctable[i]; mfc != NULL; ) { - nmfc = mfc->mfc_next; - if (mfc->mfc_parent == vifi) { - for (pq = mfc->mfc_stall; pq != NULL; ) { -@@ -713,9 +760,10 @@ - static int - ip_mrouter_init(struct socket *so, int version) - { -- INIT_VNET_INET(curvnet); -+ INIT_VNET_INET(so->so_vnet); -+ INIT_VNET_MROUTE(so->so_vnet); - -- if (mrtdebug) -+ if (V_mrtdebug) - log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n", - so->so_type, so->so_proto->pr_protocol); - -@@ -732,24 +780,25 @@ - return EADDRINUSE; - } - -- if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, -+ V_if_detach_event_tag = EVENTHANDLER_REGISTER(ifnet_departure_event, - if_detached_event, NULL, EVENTHANDLER_PRI_ANY); -- if (if_detach_event_tag == NULL) { -+ if (V_if_detach_event_tag == NULL) { - MROUTER_UNLOCK(); - return (ENOMEM); - } - -- callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL); -- -- callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD, -- expire_bw_upcalls_send, NULL); -- callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL); -+ callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, -+ expire_upcalls, (void *)so->so_vnet); -+ callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, -+ expire_bw_upcalls_send, (void *)so->so_vnet); -+ callout_reset(&V_bw_meter_ch, BW_METER_PERIOD, -+ expire_bw_meter_process, (void *)so->so_vnet); - - V_ip_mrouter = so; - - MROUTER_UNLOCK(); - -- if (mrtdebug) -+ if (V_mrtdebug) - log(LOG_DEBUG, "ip_mrouter_init\n"); - - return 0; -@@ -762,6 +811,7 @@ - X_ip_mrouter_done(void) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - vifi_t vifi; - int i; - struct ifnet *ifp; -@@ -780,41 +830,41 @@ - * Detach/disable hooks to the reset of the system. - */ - V_ip_mrouter = NULL; -- mrt_api_config = 0; -+ V_mrt_api_config = 0; - - VIF_LOCK(); - /* - * For each phyint in use, disable promiscuous reception of all IP - * multicasts. - */ -- for (vifi = 0; vifi < numvifs; vifi++) { -- if (viftable[vifi].v_lcl_addr.s_addr != 0 && -- !(viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { -+ for (vifi = 0; vifi < V_numvifs; vifi++) { -+ if (V_viftable[vifi].v_lcl_addr.s_addr != 0 && -+ !(V_viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) { - struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr); - - so->sin_len = sizeof(struct sockaddr_in); - so->sin_family = AF_INET; - so->sin_addr.s_addr = INADDR_ANY; -- ifp = viftable[vifi].v_ifp; -+ ifp = V_viftable[vifi].v_ifp; - if_allmulti(ifp, 0); - } - } -- bzero((caddr_t)viftable, sizeof(viftable)); -- numvifs = 0; -- pim_assert = 0; -+ bzero((caddr_t)V_viftable, sizeof(V_viftable)); -+ V_numvifs = 0; -+ V_pim_assert = 0; - VIF_UNLOCK(); -- EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag); -+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_if_detach_event_tag); - - /* - * Free all multicast forwarding cache entries. - */ -- callout_stop(&expire_upcalls_ch); -- callout_stop(&bw_upcalls_ch); -- callout_stop(&bw_meter_ch); -+ callout_stop(&V_expire_upcalls_ch); -+ callout_stop(&V_bw_upcalls_ch); -+ callout_stop(&V_bw_meter_ch); - - MFC_LOCK(); - for (i = 0; i < MFCTBLSIZ; i++) { -- for (rt = mfctable[i]; rt != NULL; ) { -+ for (rt = V_mfctable[i]; rt != NULL; ) { - struct mfc *nr = rt->mfc_next; - - for (rte = rt->mfc_stall; rte != NULL; ) { -@@ -829,17 +879,19 @@ - rt = nr; - } - } -- bzero((caddr_t)mfctable, sizeof(mfctable)); -- bzero((caddr_t)nexpire, sizeof(nexpire)); -- bw_upcalls_n = 0; -- bzero(bw_meter_timers, sizeof(bw_meter_timers)); -+ bzero((caddr_t)V_mfctable, sizeof(V_mfctable)); -+ bzero((caddr_t)V_nexpire, sizeof(V_nexpire)); -+ V_bw_upcalls_n = 0; -+ bzero(V_bw_meter_timers, sizeof(V_bw_meter_timers)); - MFC_UNLOCK(); - -- reg_vif_num = VIFI_INVALID; -+ if (V_reg_vif_num != VIFI_INVALID) -+ IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); -+ V_reg_vif_num = VIFI_INVALID; - - MROUTER_UNLOCK(); - -- if (mrtdebug) -+ if (V_mrtdebug) - log(LOG_DEBUG, "ip_mrouter_done\n"); - - return 0; -@@ -851,10 +903,11 @@ - static int - set_assert(int i) - { -+ INIT_VNET_MROUTE(curvnet); - if ((i != 1) && (i != 0)) - return EINVAL; - -- pim_assert = i; -+ V_pim_assert = i; - - return 0; - } -@@ -865,6 +918,7 @@ - int - set_api_config(uint32_t *apival) - { -+ INIT_VNET_MROUTE(curvnet); - int i; - - /* -@@ -874,23 +928,23 @@ - * - pim_assert is not enabled - * - the MFC table is empty - */ -- if (numvifs > 0) { -+ if (V_numvifs > 0) { - *apival = 0; - return EPERM; - } -- if (pim_assert) { -+ if (V_pim_assert) { - *apival = 0; - return EPERM; - } - for (i = 0; i < MFCTBLSIZ; i++) { -- if (mfctable[i] != NULL) { -+ if (V_mfctable[i] != NULL) { - *apival = 0; - return EPERM; - } - } - -- mrt_api_config = *apival & mrt_api_support; -- *apival = mrt_api_config; -+ V_mrt_api_config = *apival & mrt_api_support; -+ *apival = V_mrt_api_config; - - return 0; - } -@@ -901,7 +955,8 @@ - static int - add_vif(struct vifctl *vifcp) - { -- struct vif *vifp = viftable + vifcp->vifc_vifi; -+ INIT_VNET_MROUTE(curvnet); -+ struct vif *vifp = V_viftable + vifcp->vifc_vifi; - struct sockaddr_in sin = {sizeof sin, AF_INET}; - struct ifaddr *ifa; - struct ifnet *ifp; -@@ -950,14 +1005,19 @@ - VIF_UNLOCK(); - return EOPNOTSUPP; - } else if (vifcp->vifc_flags & VIFF_REGISTER) { -- ifp = &multicast_register_if; -- if (mrtdebug) -+ ifp = &V_multicast_register_if; -+ if (V_mrtdebug) - log(LOG_DEBUG, "Adding a register vif, ifp: %p\n", -- (void *)&multicast_register_if); -- if (reg_vif_num == VIFI_INVALID) { -- if_initname(&multicast_register_if, "register_vif", 0); -- multicast_register_if.if_flags = IFF_LOOPBACK; -- reg_vif_num = vifcp->vifc_vifi; -+ (void *)&V_multicast_register_if); -+ if (V_reg_vif_num == VIFI_INVALID) { -+ if_initname(&V_multicast_register_if, "register_vif", 0); -+ V_multicast_register_if.if_flags = IFF_LOOPBACK; -+ V_reg_vif_num = vifcp->vifc_vifi; -+ IF_ADDR_LOCK_INIT(&V_multicast_register_if); -+#ifdef VIMAGE -+ V_multicast_register_if.if_vnet = curvnet; -+ V_multicast_register_if.if_home_vnet = curvnet; -+#endif /* VIMAGE */ - } - } else { /* Make sure the interface supports multicast */ - if ((ifp->if_flags & IFF_MULTICAST) == 0) { -@@ -988,11 +1048,11 @@ - bzero(&vifp->v_route, sizeof(vifp->v_route)); - - /* Adjust numvifs up if the vifi is higher than numvifs */ -- if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1; -+ if (V_numvifs <= vifcp->vifc_vifi) V_numvifs = vifcp->vifc_vifi + 1; - - VIF_UNLOCK(); - -- if (mrtdebug) -+ if (V_mrtdebug) - log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x\n", - vifcp->vifc_vifi, - (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr), -@@ -1009,14 +1069,15 @@ - static int - del_vif_locked(vifi_t vifi) - { -+ INIT_VNET_MROUTE(curvnet); - struct vif *vifp; - - VIF_LOCK_ASSERT(); - -- if (vifi >= numvifs) { -+ if (vifi >= V_numvifs) { - return EINVAL; - } -- vifp = &viftable[vifi]; -+ vifp = &V_viftable[vifi]; - if (vifp->v_lcl_addr.s_addr == INADDR_ANY) { - return EADDRNOTAVAIL; - } -@@ -1024,19 +1085,22 @@ - if (!(vifp->v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) - if_allmulti(vifp->v_ifp, 0); - -- if (vifp->v_flags & VIFF_REGISTER) -- reg_vif_num = VIFI_INVALID; -+ if (vifp->v_flags & VIFF_REGISTER) { -+ if (V_reg_vif_num != VIFI_INVALID) -+ IF_ADDR_LOCK_DESTROY(&V_multicast_register_if); -+ V_reg_vif_num = VIFI_INVALID; -+ } - - bzero((caddr_t)vifp, sizeof (*vifp)); - -- if (mrtdebug) -- log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs); -+ if (V_mrtdebug) -+ log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, V_numvifs); - - /* Adjust numvifs down */ -- for (vifi = numvifs; vifi > 0; vifi--) -- if (viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY) -+ for (vifi = V_numvifs; vifi > 0; vifi--) -+ if (V_viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY) - break; -- numvifs = vifi; -+ V_numvifs = vifi; - - return 0; - } -@@ -1044,6 +1108,7 @@ - static int - del_vif(vifi_t vifi) - { -+ INIT_VNET_MROUTE(curvnet); - int cc; - - VIF_LOCK(); -@@ -1059,16 +1124,17 @@ - static void - update_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp) - { -+ INIT_VNET_MROUTE(curvnet); - int i; - - rt->mfc_parent = mfccp->mfcc_parent; -- for (i = 0; i < numvifs; i++) { -+ for (i = 0; i < V_numvifs; i++) { - rt->mfc_ttls[i] = mfccp->mfcc_ttls[i]; -- rt->mfc_flags[i] = mfccp->mfcc_flags[i] & mrt_api_config & -+ rt->mfc_flags[i] = mfccp->mfcc_flags[i] & V_mrt_api_config & - MRT_MFC_FLAGS_ALL; - } - /* set the RP address */ -- if (mrt_api_config & MRT_MFC_RP) -+ if (V_mrt_api_config & MRT_MFC_RP) - rt->mfc_rp = mfccp->mfcc_rp; - else - rt->mfc_rp.s_addr = INADDR_ANY; -@@ -1099,6 +1165,7 @@ - static int - add_mfc(struct mfcctl2 *mfccp) - { -+ INIT_VNET_MROUTE(curvnet); - struct mfc *rt; - u_long hash; - struct rtdetq *rte; -@@ -1111,7 +1178,7 @@ - - /* If an entry already exists, just update the fields */ - if (rt) { -- if (mrtdebug & DEBUG_MFC) -+ if (V_mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n", - (u_long)ntohl(mfccp->mfcc_origin.s_addr), - (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), -@@ -1127,7 +1194,7 @@ - * Find the entry for which the upcall was made and update - */ - hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr); -- for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { -+ for (rt = V_mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) { - - if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && - (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) && -@@ -1140,7 +1207,7 @@ - (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent, (void *)rt->mfc_stall); - -- if (mrtdebug & DEBUG_MFC) -+ if (V_mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n", - (u_long)ntohl(mfccp->mfcc_origin.s_addr), - (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), -@@ -1149,7 +1216,7 @@ - init_mfc_params(rt, mfccp); - - rt->mfc_expire = 0; /* Don't clean this guy up */ -- nexpire[hash]--; -+ V_nexpire[hash]--; - - /* free packets Qed at the end of this entry */ - for (rte = rt->mfc_stall; rte != NULL; ) { -@@ -1168,18 +1235,18 @@ - * It is possible that an entry is being inserted without an upcall - */ - if (nstl == 0) { -- if (mrtdebug & DEBUG_MFC) -+ if (V_mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n", - hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr), - (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr), - mfccp->mfcc_parent); - -- for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) { -+ for (rt = V_mfctable[hash]; rt != NULL; rt = rt->mfc_next) { - if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) && - (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) { - init_mfc_params(rt, mfccp); - if (rt->mfc_expire) -- nexpire[hash]--; -+ V_nexpire[hash]--; - rt->mfc_expire = 0; - break; /* XXX */ - } -@@ -1198,8 +1265,8 @@ - - rt->mfc_bw_meter = NULL; - /* insert new entry at head of hash chain */ -- rt->mfc_next = mfctable[hash]; -- mfctable[hash] = rt; -+ rt->mfc_next = V_mfctable[hash]; -+ V_mfctable[hash] = rt; - } - } - MFC_UNLOCK(); -@@ -1213,6 +1280,7 @@ - static int - del_mfc(struct mfcctl2 *mfccp) - { -+ INIT_VNET_MROUTE(curvnet); - struct in_addr origin; - struct in_addr mcastgrp; - struct mfc *rt; -@@ -1223,14 +1291,14 @@ - origin = mfccp->mfcc_origin; - mcastgrp = mfccp->mfcc_mcastgrp; - -- if (mrtdebug & DEBUG_MFC) -+ if (V_mrtdebug & DEBUG_MFC) - log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n", - (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr)); - - MFC_LOCK(); - - hash = MFCHASH(origin.s_addr, mcastgrp.s_addr); -- for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next) -+ for (nptr = &V_mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next) - if (origin.s_addr == rt->mfc_origin.s_addr && - mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr && - rt->mfc_stall == NULL) -@@ -1294,11 +1362,12 @@ - struct ip_moptions *imo) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - struct mfc *rt; - int error; - vifi_t vifi; - -- if (mrtdebug & DEBUG_FORWARD) -+ if (V_mrtdebug & DEBUG_FORWARD) - log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n", - (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr), - (void *)ifp); -@@ -1326,11 +1395,11 @@ - - VIF_LOCK(); - MFC_LOCK(); -- if (imo && ((vifi = imo->imo_multicast_vif) < numvifs)) { -+ if (imo && ((vifi = imo->imo_multicast_vif) < V_numvifs)) { - if (ip->ip_ttl < MAXTTL) - ip->ip_ttl++; /* compensate for -1 in *_send routines */ -- if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { -- struct vif *vifp = viftable + vifi; -+ if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) { -+ struct vif *vifp = V_viftable + vifi; - - printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s)\n", - (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr), -@@ -1343,7 +1412,7 @@ - VIF_UNLOCK(); - return error; - } -- if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) { -+ if (V_rsvpdebug && ip->ip_p == IPPROTO_RSVP) { - printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n", - (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr)); - if (!imo) -@@ -1363,7 +1432,7 @@ - /* - * Determine forwarding vifs from the forwarding cache table - */ -- ++mrtstat.mrts_mfc_lookups; -+ ++V_mrtstat.mrts_mfc_lookups; - rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr); - - /* Entry exists, so forward if necessary */ -@@ -1383,10 +1452,10 @@ - u_long hash; - int hlen = ip->ip_hl << 2; - -- ++mrtstat.mrts_mfc_misses; -+ ++V_mrtstat.mrts_mfc_misses; - -- mrtstat.mrts_no_route++; -- if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) -+ V_mrtstat.mrts_no_route++; -+ if (V_mrtdebug & (DEBUG_FORWARD | DEBUG_MFC)) - log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n", - (u_long)ntohl(ip->ip_src.s_addr), - (u_long)ntohl(ip->ip_dst.s_addr)); -@@ -1414,7 +1483,7 @@ - - /* is there an upcall waiting for this flow ? */ - hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr); -- for (rt = mfctable[hash]; rt; rt = rt->mfc_next) { -+ for (rt = V_mfctable[hash]; rt; rt = rt->mfc_next) { - if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) && - (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) && - (rt->mfc_stall != NULL)) -@@ -1431,9 +1500,9 @@ - * Locate the vifi for the incoming interface for this packet. - * If none found, drop packet. - */ -- for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++) -+ for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; vifi++) - ; -- if (vifi >= numvifs) /* vif not found, drop packet */ -+ if (vifi >= V_numvifs) /* vif not found, drop packet */ - goto non_fatal; - - /* no upcall, so make a new entry */ -@@ -1455,12 +1524,12 @@ - im->im_mbz = 0; - im->im_vif = vifi; - -- mrtstat.mrts_upcalls++; -+ V_mrtstat.mrts_upcalls++; - - k_igmpsrc.sin_addr = ip->ip_src; - if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { - log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n"); -- ++mrtstat.mrts_upq_sockfull; -+ ++V_mrtstat.mrts_upq_sockfull; - fail1: - free(rt, M_MRTABLE); - fail: -@@ -1475,8 +1544,8 @@ - rt->mfc_origin.s_addr = ip->ip_src.s_addr; - rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr; - rt->mfc_expire = UPCALL_EXPIRE; -- nexpire[hash]++; -- for (i = 0; i < numvifs; i++) { -+ V_nexpire[hash]++; -+ for (i = 0; i < V_numvifs; i++) { - rt->mfc_ttls[i] = 0; - rt->mfc_flags[i] = 0; - } -@@ -1487,8 +1556,8 @@ - rt->mfc_bw_meter = NULL; - - /* link into table */ -- rt->mfc_next = mfctable[hash]; -- mfctable[hash] = rt; -+ rt->mfc_next = V_mfctable[hash]; -+ V_mfctable[hash] = rt; - rt->mfc_stall = rte; - - } else { -@@ -1505,7 +1574,7 @@ - npkts++; - - if (npkts > MAX_UPQ) { -- mrtstat.mrts_upq_ovflw++; -+ V_mrtstat.mrts_upq_ovflw++; - non_fatal: - free(rte, M_MRTABLE); - m_freem(mb0); -@@ -1535,15 +1604,16 @@ - static void - expire_upcalls(void *unused) - { -+ INIT_VNET_MROUTE( ((struct vnet *)unused) ); - struct rtdetq *rte; - struct mfc *mfc, **nptr; - int i; - - MFC_LOCK(); - for (i = 0; i < MFCTBLSIZ; i++) { -- if (nexpire[i] == 0) -+ if (V_nexpire[i] == 0) - continue; -- nptr = &mfctable[i]; -+ nptr = &V_mfctable[i]; - for (mfc = *nptr; mfc != NULL; mfc = *nptr) { - /* - * Skip real cache entries -@@ -1552,7 +1622,7 @@ - */ - if (mfc->mfc_stall != NULL && mfc->mfc_expire != 0 && - --mfc->mfc_expire == 0) { -- if (mrtdebug & DEBUG_EXPIRE) -+ if (V_mrtdebug & DEBUG_EXPIRE) - log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n", - (u_long)ntohl(mfc->mfc_origin.s_addr), - (u_long)ntohl(mfc->mfc_mcastgrp.s_addr)); -@@ -1567,8 +1637,8 @@ - free(rte, M_MRTABLE); - rte = n; - } -- ++mrtstat.mrts_cache_cleanups; -- nexpire[i]--; -+ ++V_mrtstat.mrts_cache_cleanups; -+ V_nexpire[i]--; - - /* - * free the bw_meter entries -@@ -1587,9 +1657,8 @@ - } - } - } -+ callout_reset(&V_expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, unused); - MFC_UNLOCK(); -- -- callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL); - } - - /* -@@ -1599,6 +1668,7 @@ - ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - struct ip *ip = mtod(m, struct ip *); - vifi_t vifi; - int plen = ip->ip_len; -@@ -1610,11 +1680,11 @@ - * - * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.) - */ -- if (xmt_vif < numvifs) { -- if (viftable[xmt_vif].v_flags & VIFF_REGISTER) -- pim_register_send(ip, viftable + xmt_vif, m, rt); -+ if (xmt_vif < V_numvifs) { -+ if (V_viftable[xmt_vif].v_flags & VIFF_REGISTER) -+ pim_register_send(ip, V_viftable + xmt_vif, m, rt); - else -- phyint_send(ip, viftable + xmt_vif, m); -+ phyint_send(ip, V_viftable + xmt_vif, m); - return 1; - } - -@@ -1622,12 +1692,12 @@ - * Don't forward if it didn't arrive from the parent vif for its origin. - */ - vifi = rt->mfc_parent; -- if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) { -+ if ((vifi >= V_numvifs) || (V_viftable[vifi].v_ifp != ifp)) { - /* came in the wrong interface */ -- if (mrtdebug & DEBUG_FORWARD) -+ if (V_mrtdebug & DEBUG_FORWARD) - log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n", -- (void *)ifp, vifi, (void *)viftable[vifi].v_ifp); -- ++mrtstat.mrts_wrong_if; -+ (void *)ifp, vifi, (void *)V_viftable[vifi].v_ifp); -+ ++V_mrtstat.mrts_wrong_if; - ++rt->mfc_wrong_if; - /* - * If we are doing PIM assert processing, send a message -@@ -1637,17 +1707,18 @@ - * can complete the SPT switch, regardless of the type - * of the iif (broadcast media, GRE tunnel, etc). - */ -- if (pim_assert && (vifi < numvifs) && viftable[vifi].v_ifp) { -+ if (V_pim_assert && (vifi < V_numvifs) && V_viftable[vifi].v_ifp) { - struct timeval now; - u_long delta; - -- if (ifp == &multicast_register_if) -- pimstat.pims_rcv_registers_wrongiif++; -+ if (ifp == &V_multicast_register_if) -+ V_pimstat.pims_rcv_registers_wrongiif++; - - /* Get vifi for the incoming packet */ -- for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++) -+ for (vifi=0; vifi < V_numvifs && V_viftable[vifi].v_ifp != ifp; -+ vifi++) - ; -- if (vifi >= numvifs) -+ if (vifi >= V_numvifs) - return 0; /* The iif is not found: ignore the packet. */ - - if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_DISABLE_WRONGVIF) -@@ -1675,13 +1746,13 @@ - im->im_mbz = 0; - im->im_vif = vifi; - -- mrtstat.mrts_upcalls++; -+ V_mrtstat.mrts_upcalls++; - - k_igmpsrc.sin_addr = im->im_src; - if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) { - log(LOG_WARNING, - "ip_mforward: ip_mrouter socket queue full\n"); -- ++mrtstat.mrts_upq_sockfull; -+ ++V_mrtstat.mrts_upq_sockfull; - return ENOBUFS; - } - } -@@ -1690,12 +1761,12 @@ - } - - /* If I sourced this packet, it counts as output, else it was input. */ -- if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) { -- viftable[vifi].v_pkt_out++; -- viftable[vifi].v_bytes_out += plen; -+ if (ip->ip_src.s_addr == V_viftable[vifi].v_lcl_addr.s_addr) { -+ V_viftable[vifi].v_pkt_out++; -+ V_viftable[vifi].v_bytes_out += plen; - } else { -- viftable[vifi].v_pkt_in++; -- viftable[vifi].v_bytes_in += plen; -+ V_viftable[vifi].v_pkt_in++; -+ V_viftable[vifi].v_bytes_in += plen; - } - rt->mfc_pkt_cnt++; - rt->mfc_byte_cnt += plen; -@@ -1706,14 +1777,14 @@ - * - the ttl exceeds the vif's threshold - * - there are group members downstream on interface - */ -- for (vifi = 0; vifi < numvifs; vifi++) -+ for (vifi = 0; vifi < V_numvifs; vifi++) - if ((rt->mfc_ttls[vifi] > 0) && (ip->ip_ttl > rt->mfc_ttls[vifi])) { -- viftable[vifi].v_pkt_out++; -- viftable[vifi].v_bytes_out += plen; -- if (viftable[vifi].v_flags & VIFF_REGISTER) -- pim_register_send(ip, viftable + vifi, m, rt); -+ V_viftable[vifi].v_pkt_out++; -+ V_viftable[vifi].v_bytes_out += plen; -+ if (V_viftable[vifi].v_flags & VIFF_REGISTER) -+ pim_register_send(ip, V_viftable + vifi, m, rt); - else -- phyint_send(ip, viftable + vifi, m); -+ phyint_send(ip, V_viftable + vifi, m); - } - - /* -@@ -1738,8 +1809,9 @@ - static int - X_legal_vif_num(int vif) - { -+ INIT_VNET_MROUTE(curvnet); - /* XXX unlocked, matter? */ -- return (vif >= 0 && vif < numvifs); -+ return (vif >= 0 && vif < V_numvifs); - } - - /* -@@ -1748,9 +1820,10 @@ - static u_long - X_ip_mcast_src(int vifi) - { -+ INIT_VNET_MROUTE(curvnet); - /* XXX unlocked, matter? */ -- if (vifi >= 0 && vifi < numvifs) -- return viftable[vifi].v_lcl_addr.s_addr; -+ if (vifi >= 0 && vifi < V_numvifs) -+ return V_viftable[vifi].v_lcl_addr.s_addr; - else - return INADDR_ANY; - } -@@ -1780,6 +1853,7 @@ - static void - send_packet(struct vif *vifp, struct mbuf *m) - { -+ INIT_VNET_MROUTE(curvnet); - struct ip_moptions imo; - struct in_multi *imm[2]; - int error; -@@ -1801,16 +1875,17 @@ - * the loopback interface, thus preventing looping. - */ - error = ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, &imo, NULL); -- if (mrtdebug & DEBUG_XMIT) { -+ if (V_mrtdebug & DEBUG_XMIT) { - log(LOG_DEBUG, "phyint_send on vif %td err %d\n", -- vifp - viftable, error); -+ vifp - V_viftable, error); - } - } - - static int - X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt) - { -- INIT_VNET_INET(curvnet); -+ INIT_VNET_INET(so->so_vnet); -+ INIT_VNET_MROUTE(so->so_vnet); - int error, vifi; - - if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) -@@ -1822,39 +1897,39 @@ - - VIF_LOCK(); - -- if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */ -+ if (vifi < 0 || vifi >= V_numvifs) { /* Error if vif is invalid */ - VIF_UNLOCK(); - return EADDRNOTAVAIL; - } - - if (sopt->sopt_name == IP_RSVP_VIF_ON) { - /* Check if socket is available. */ -- if (viftable[vifi].v_rsvpd != NULL) { -+ if (V_viftable[vifi].v_rsvpd != NULL) { - VIF_UNLOCK(); - return EADDRINUSE; - } - -- viftable[vifi].v_rsvpd = so; -+ V_viftable[vifi].v_rsvpd = so; - /* This may seem silly, but we need to be sure we don't over-increment - * the RSVP counter, in case something slips up. - */ -- if (!viftable[vifi].v_rsvp_on) { -- viftable[vifi].v_rsvp_on = 1; -+ if (!V_viftable[vifi].v_rsvp_on) { -+ V_viftable[vifi].v_rsvp_on = 1; - V_rsvp_on++; - } - } else { /* must be VIF_OFF */ - /* - * XXX as an additional consistency check, one could make sure -- * that viftable[vifi].v_rsvpd == so, otherwise passing so as -+ * that V_viftable[vifi].v_rsvpd == so, otherwise passing so as - * first parameter is pretty useless. - */ -- viftable[vifi].v_rsvpd = NULL; -+ V_viftable[vifi].v_rsvpd = NULL; - /* - * This may seem silly, but we need to be sure we don't over-decrement - * the RSVP counter, in case something slips up. - */ -- if (viftable[vifi].v_rsvp_on) { -- viftable[vifi].v_rsvp_on = 0; -+ if (V_viftable[vifi].v_rsvp_on) { -+ V_viftable[vifi].v_rsvp_on = 0; - V_rsvp_on--; - } - } -@@ -1865,7 +1940,8 @@ - static void - X_ip_rsvp_force_done(struct socket *so) - { -- INIT_VNET_INET(curvnet); -+ INIT_VNET_INET(so->so_vnet); -+ INIT_VNET_MROUTE(so->so_vnet); - int vifi; - - /* Don't bother if it is not the right type of socket. */ -@@ -1877,14 +1953,14 @@ - /* The socket may be attached to more than one vif...this - * is perfectly legal. - */ -- for (vifi = 0; vifi < numvifs; vifi++) { -- if (viftable[vifi].v_rsvpd == so) { -- viftable[vifi].v_rsvpd = NULL; -+ for (vifi = 0; vifi < V_numvifs; vifi++) { -+ if (V_viftable[vifi].v_rsvpd == so) { -+ V_viftable[vifi].v_rsvpd = NULL; - /* This may seem silly, but we need to be sure we don't - * over-decrement the RSVP counter, in case something slips up. - */ -- if (viftable[vifi].v_rsvp_on) { -- viftable[vifi].v_rsvp_on = 0; -+ if (V_viftable[vifi].v_rsvp_on) { -+ V_viftable[vifi].v_rsvp_on = 0; - V_rsvp_on--; - } - } -@@ -1897,12 +1973,13 @@ - X_rsvp_input(struct mbuf *m, int off) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - int vifi; - struct ip *ip = mtod(m, struct ip *); - struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET }; - struct ifnet *ifp; - -- if (rsvpdebug) -+ if (V_rsvpdebug) - printf("rsvp_input: rsvp_on %d\n", V_rsvp_on); - - /* Can still get packets with rsvp_on = 0 if there is a local member -@@ -1914,7 +1991,7 @@ - return; - } - -- if (rsvpdebug) -+ if (V_rsvpdebug) - printf("rsvp_input: check vifs\n"); - - #ifdef DIAGNOSTIC -@@ -1925,14 +2002,14 @@ - - VIF_LOCK(); - /* Find which vif the packet arrived on. */ -- for (vifi = 0; vifi < numvifs; vifi++) -- if (viftable[vifi].v_ifp == ifp) -+ for (vifi = 0; vifi < V_numvifs; vifi++) -+ if (V_viftable[vifi].v_ifp == ifp) - break; - -- if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) { -+ if (vifi == V_numvifs || V_viftable[vifi].v_rsvpd == NULL) { - /* - * Drop the lock here to avoid holding it across rip_input. -- * This could make rsvpdebug printfs wrong. If you care, -+ * This could make V_rsvpdebug printfs wrong. If you care, - * record the state of stuff before dropping the lock. - */ - VIF_UNLOCK(); -@@ -1942,13 +2019,13 @@ - * is no specific socket for this vif. - */ - if (V_ip_rsvpd != NULL) { -- if (rsvpdebug) -+ if (V_rsvpdebug) - printf("rsvp_input: Sending packet up old-style socket\n"); - rip_input(m, off); /* xxx */ - } else { -- if (rsvpdebug && vifi == numvifs) -+ if (V_rsvpdebug && vifi == V_numvifs) - printf("rsvp_input: Can't find vif for packet.\n"); -- else if (rsvpdebug && viftable[vifi].v_rsvpd == NULL) -+ else if (V_rsvpdebug && V_viftable[vifi].v_rsvpd == NULL) - printf("rsvp_input: No socket defined for vif %d\n",vifi); - m_freem(m); - } -@@ -1956,15 +2033,15 @@ - } - rsvp_src.sin_addr = ip->ip_src; - -- if (rsvpdebug && m) -+ if (V_rsvpdebug && m) - printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n", -- m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv))); -+ m->m_len,sbspace(&(V_viftable[vifi].v_rsvpd->so_rcv))); - -- if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { -- if (rsvpdebug) -+ if (socket_send(V_viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) { -+ if (V_rsvpdebug) - printf("rsvp_input: Failed to append to socket\n"); - } else { -- if (rsvpdebug) -+ if (V_rsvpdebug) - printf("rsvp_input: send packet up\n"); - } - VIF_UNLOCK(); -@@ -2004,6 +2081,7 @@ - static int - add_bw_upcall(struct bw_upcall *req) - { -+ INIT_VNET_MROUTE(curvnet); - struct mfc *mfc; - struct timeval delta = { BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC, - BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC }; -@@ -2011,7 +2089,7 @@ - struct bw_meter *x; - uint32_t flags; - -- if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) -+ if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL)) - return EOPNOTSUPP; - - /* Test if the flags are valid */ -@@ -2096,10 +2174,11 @@ - static int - del_bw_upcall(struct bw_upcall *req) - { -+ INIT_VNET_MROUTE(curvnet); - struct mfc *mfc; - struct bw_meter *x; - -- if (!(mrt_api_config & MRT_MFC_BW_UPCALL)) -+ if (!(V_mrt_api_config & MRT_MFC_BW_UPCALL)) - return EOPNOTSUPP; - - MFC_LOCK(); -@@ -2252,6 +2331,7 @@ - static void - bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp) - { -+ INIT_VNET_MROUTE(curvnet); - struct timeval delta; - struct bw_upcall *u; - -@@ -2266,13 +2346,13 @@ - /* - * If there are too many pending upcalls, deliver them now - */ -- if (bw_upcalls_n >= BW_UPCALLS_MAX) -+ if (V_bw_upcalls_n >= BW_UPCALLS_MAX) - bw_upcalls_send(); - - /* - * Set the bw_upcall entry - */ -- u = &bw_upcalls[bw_upcalls_n++]; -+ u = &V_bw_upcalls[V_bw_upcalls_n++]; - u->bu_src = x->bm_mfc->mfc_origin; - u->bu_dst = x->bm_mfc->mfc_mcastgrp; - u->bu_threshold.b_time = x->bm_threshold.b_time; -@@ -2299,8 +2379,9 @@ - bw_upcalls_send(void) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - struct mbuf *m; -- int len = bw_upcalls_n * sizeof(bw_upcalls[0]); -+ int len = V_bw_upcalls_n * sizeof(V_bw_upcalls[0]); - struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET }; - static struct igmpmsg igmpmsg = { 0, /* unused1 */ - 0, /* unused2 */ -@@ -2313,10 +2394,10 @@ - - MFC_LOCK_ASSERT(); - -- if (bw_upcalls_n == 0) -+ if (V_bw_upcalls_n == 0) - return; /* No pending upcalls */ - -- bw_upcalls_n = 0; -+ V_bw_upcalls_n = 0; - - /* - * Allocate a new mbuf, initialize it with the header and -@@ -2330,16 +2411,16 @@ - - m->m_len = m->m_pkthdr.len = 0; - m_copyback(m, 0, sizeof(struct igmpmsg), (caddr_t)&igmpmsg); -- m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&bw_upcalls[0]); -+ m_copyback(m, sizeof(struct igmpmsg), len, (caddr_t)&V_bw_upcalls[0]); - - /* - * Send the upcalls - * XXX do we need to set the address in k_igmpsrc ? - */ -- mrtstat.mrts_upcalls++; -+ V_mrtstat.mrts_upcalls++; - if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) { - log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n"); -- ++mrtstat.mrts_upq_sockfull; -+ ++V_mrtstat.mrts_upq_sockfull; - } - } - -@@ -2364,6 +2445,7 @@ - static void - schedule_bw_meter(struct bw_meter *x, struct timeval *nowp) - { -+ INIT_VNET_MROUTE(curvnet); - int time_hash; - - MFC_LOCK_ASSERT(); -@@ -2383,8 +2465,8 @@ - * Compute the timeout hash value and insert the entry - */ - BW_METER_TIMEHASH(x, time_hash); -- x->bm_time_next = bw_meter_timers[time_hash]; -- bw_meter_timers[time_hash] = x; -+ x->bm_time_next = V_bw_meter_timers[time_hash]; -+ V_bw_meter_timers[time_hash] = x; - x->bm_time_hash = time_hash; - } - -@@ -2395,6 +2477,7 @@ - static void - unschedule_bw_meter(struct bw_meter *x) - { -+ INIT_VNET_MROUTE(curvnet); - int time_hash; - struct bw_meter *prev, *tmp; - -@@ -2410,7 +2493,7 @@ - if (time_hash >= BW_METER_BUCKETS) - return; /* Entry was not scheduled */ - -- for (prev = NULL, tmp = bw_meter_timers[time_hash]; -+ for (prev = NULL, tmp = V_bw_meter_timers[time_hash]; - tmp != NULL; prev = tmp, tmp = tmp->bm_time_next) - if (tmp == x) - break; -@@ -2421,7 +2504,7 @@ - if (prev != NULL) - prev->bm_time_next = x->bm_time_next; - else -- bw_meter_timers[time_hash] = x->bm_time_next; -+ V_bw_meter_timers[time_hash] = x->bm_time_next; - - x->bm_time_next = NULL; - x->bm_time_hash = BW_METER_BUCKETS; -@@ -2438,8 +2521,9 @@ - * looking at. - */ - static void --bw_meter_process() -+bw_meter_process(struct vnet *vnet) - { -+ INIT_VNET_MROUTE(vnet); - static uint32_t last_tv_sec; /* last time we processed this */ - - uint32_t loops; -@@ -2456,6 +2540,7 @@ - loops = BW_METER_BUCKETS; - - MFC_LOCK(); -+ CURVNET_SET(vnet); - /* - * Process all bins of bw_meter entries from the one after the last - * processed to the current one. On entry, i points to the last bucket -@@ -2468,8 +2553,8 @@ - i = 0; - - /* Disconnect the list of bw_meter entries from the bin */ -- tmp_list = bw_meter_timers[i]; -- bw_meter_timers[i] = NULL; -+ tmp_list = V_bw_meter_timers[i]; -+ V_bw_meter_timers[i] = NULL; - - /* Process the list of bw_meter entries */ - while (tmp_list != NULL) { -@@ -2492,8 +2577,8 @@ - if (++time_hash >= BW_METER_BUCKETS) - time_hash = 0; - } -- x->bm_time_next = bw_meter_timers[time_hash]; -- bw_meter_timers[time_hash] = x; -+ x->bm_time_next = V_bw_meter_timers[time_hash]; -+ V_bw_meter_timers[time_hash] = x; - x->bm_time_hash = time_hash; - - continue; -@@ -2520,6 +2605,7 @@ - /* Send all upcalls that are pending delivery */ - bw_upcalls_send(); - -+ CURVNET_RESTORE(); - MFC_UNLOCK(); - } - -@@ -2529,12 +2615,14 @@ - static void - expire_bw_upcalls_send(void *unused) - { -+ INIT_VNET_MROUTE( (struct vnet *)unused ); - MFC_LOCK(); -+ CURVNET_SET( (struct vnet*)unused ); - bw_upcalls_send(); -+ callout_reset(&V_bw_upcalls_ch, BW_UPCALLS_PERIOD, -+ expire_bw_upcalls_send, unused); -+ CURVNET_RESTORE(); - MFC_UNLOCK(); -- -- callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD, -- expire_bw_upcalls_send, NULL); - } - - /* -@@ -2544,10 +2632,12 @@ - static void - expire_bw_meter_process(void *unused) - { -- if (mrt_api_config & MRT_MFC_BW_UPCALL) -- bw_meter_process(); -+ INIT_VNET_MROUTE( (struct vnet *)unused ); -+ if (V_mrt_api_config & MRT_MFC_BW_UPCALL) -+ bw_meter_process( (struct vnet *)unused ); - -- callout_reset(&bw_meter_ch, BW_METER_PERIOD, expire_bw_meter_process, NULL); -+ callout_reset(&V_bw_meter_ch, BW_METER_PERIOD, -+ expire_bw_meter_process, unused); - } - - /* -@@ -2562,16 +2652,17 @@ - pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m, - struct mfc *rt) - { -+ INIT_VNET_MROUTE(curvnet); - struct mbuf *mb_copy, *mm; - -- if (mrtdebug & DEBUG_PIM) -+ if (V_mrtdebug & DEBUG_PIM) - log(LOG_DEBUG, "pim_register_send: "); - - /* - * Do not send IGMP_WHOLEPKT notifications to userland, if the - * rendezvous point was unspecified, and we were told not to. - */ -- if (pim_squelch_wholepkt != 0 && (mrt_api_config & MRT_MFC_RP) && -+ if (pim_squelch_wholepkt != 0 && (V_mrt_api_config & MRT_MFC_RP) && - (rt->mfc_rp.s_addr == INADDR_ANY)) - return 0; - -@@ -2589,7 +2680,7 @@ - mm = m_pullup(mm, sizeof(struct ip)); - if (mm != NULL) { - ip = mtod(mm, struct ip *); -- if ((mrt_api_config & MRT_MFC_RP) && -+ if ((V_mrt_api_config & MRT_MFC_RP) && - (rt->mfc_rp.s_addr != INADDR_ANY)) { - pim_register_send_rp(ip, vifp, mm, rt); - } else { -@@ -2660,6 +2751,7 @@ - struct mbuf *mb_copy, struct mfc *rt) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - struct mbuf *mb_first; - int len = ntohs(ip->ip_len); - struct igmpmsg *im; -@@ -2684,25 +2776,25 @@ - im = mtod(mb_first, struct igmpmsg *); - im->im_msgtype = IGMPMSG_WHOLEPKT; - im->im_mbz = 0; -- im->im_vif = vifp - viftable; -+ im->im_vif = vifp - V_viftable; - im->im_src = ip->ip_src; - im->im_dst = ip->ip_dst; - - k_igmpsrc.sin_addr = ip->ip_src; - -- mrtstat.mrts_upcalls++; -+ V_mrtstat.mrts_upcalls++; - - if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) { -- if (mrtdebug & DEBUG_PIM) -+ if (V_mrtdebug & DEBUG_PIM) - log(LOG_WARNING, - "mcast: pim_register_send_upcall: ip_mrouter socket queue full"); -- ++mrtstat.mrts_upq_sockfull; -+ ++V_mrtstat.mrts_upq_sockfull; - return ENOBUFS; - } - - /* Keep statistics */ -- pimstat.pims_snd_registers_msgs++; -- pimstat.pims_snd_registers_bytes += len; -+ V_pimstat.pims_snd_registers_msgs++; -+ V_pimstat.pims_snd_registers_bytes += len; - - return 0; - } -@@ -2715,6 +2807,7 @@ - struct mfc *rt) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_MROUTE(curvnet); - struct mbuf *mb_first; - struct ip *ip_outer; - struct pim_encap_pimhdr *pimhdr; -@@ -2723,7 +2816,7 @@ - - VIF_LOCK_ASSERT(); - -- if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) { -+ if ((vifi >= V_numvifs) || (V_viftable[vifi].v_lcl_addr.s_addr == 0)) { - m_freem(mb_copy); - return EADDRNOTAVAIL; /* The iif vif is invalid */ - } -@@ -2749,7 +2842,7 @@ - *ip_outer = pim_encap_iphdr; - ip_outer->ip_id = ip_newid(); - ip_outer->ip_len = len + sizeof(pim_encap_iphdr) + sizeof(pim_encap_pimhdr); -- ip_outer->ip_src = viftable[vifi].v_lcl_addr; -+ ip_outer->ip_src = V_viftable[vifi].v_lcl_addr; - ip_outer->ip_dst = rt->mfc_rp; - /* - * Copy the inner header TOS to the outer header, and take care of the -@@ -2762,7 +2855,7 @@ - + sizeof(pim_encap_iphdr)); - *pimhdr = pim_encap_pimhdr; - /* If the iif crosses a border, set the Border-bit */ -- if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & mrt_api_config) -+ if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_BORDER_VIF & V_mrt_api_config) - pimhdr->flags |= htonl(PIM_BORDER_REGISTER); - - mb_first->m_data += sizeof(pim_encap_iphdr); -@@ -2772,8 +2865,8 @@ - send_packet(vifp, mb_first); - - /* Keep statistics */ -- pimstat.pims_snd_registers_msgs++; -- pimstat.pims_snd_registers_bytes += len; -+ V_pimstat.pims_snd_registers_msgs++; -+ V_pimstat.pims_snd_registers_bytes += len; - - return 0; - } -@@ -2807,6 +2900,7 @@ - void - pim_input(struct mbuf *m, int off) - { -+ INIT_VNET_MROUTE(curvnet); - struct ip *ip = mtod(m, struct ip *); - struct pim *pim; - int minlen; -@@ -2815,14 +2909,14 @@ - int iphlen = off; - - /* Keep statistics */ -- pimstat.pims_rcv_total_msgs++; -- pimstat.pims_rcv_total_bytes += datalen; -+ V_pimstat.pims_rcv_total_msgs++; -+ V_pimstat.pims_rcv_total_bytes += datalen; - - /* - * Validate lengths - */ - if (datalen < PIM_MINLEN) { -- pimstat.pims_rcv_tooshort++; -+ V_pimstat.pims_rcv_tooshort++; - log(LOG_ERR, "pim_input: packet size too small %d from %lx\n", - datalen, (u_long)ip->ip_src.s_addr); - m_freem(m); -@@ -2866,8 +2960,8 @@ - if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) { - /* do nothing, checksum okay */ - } else if (in_cksum(m, datalen)) { -- pimstat.pims_rcv_badsum++; -- if (mrtdebug & DEBUG_PIM) -+ V_pimstat.pims_rcv_badsum++; -+ if (V_mrtdebug & DEBUG_PIM) - log(LOG_DEBUG, "pim_input: invalid checksum"); - m_freem(m); - return; -@@ -2875,7 +2969,7 @@ - - /* PIM version check */ - if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) { -- pimstat.pims_rcv_badversion++; -+ V_pimstat.pims_rcv_badversion++; - log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n", - PIM_VT_V(pim->pim_vt), PIM_VERSION); - m_freem(m); -@@ -2899,24 +2993,24 @@ - struct ifnet *vifp; - - VIF_LOCK(); -- if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) { -+ if ((V_reg_vif_num >= V_numvifs) || (V_reg_vif_num == VIFI_INVALID)) { - VIF_UNLOCK(); -- if (mrtdebug & DEBUG_PIM) -+ if (V_mrtdebug & DEBUG_PIM) - log(LOG_DEBUG, -- "pim_input: register vif not set: %d\n", reg_vif_num); -+ "pim_input: register vif not set: %d\n", V_reg_vif_num); - m_freem(m); - return; - } - /* XXX need refcnt? */ -- vifp = viftable[reg_vif_num].v_ifp; -+ vifp = V_viftable[V_reg_vif_num].v_ifp; - VIF_UNLOCK(); - - /* - * Validate length - */ - if (datalen < PIM_REG_MINLEN) { -- pimstat.pims_rcv_tooshort++; -- pimstat.pims_rcv_badregisters++; -+ V_pimstat.pims_rcv_tooshort++; -+ V_pimstat.pims_rcv_badregisters++; - log(LOG_ERR, - "pim_input: register packet size too small %d from %lx\n", - datalen, (u_long)ip->ip_src.s_addr); -@@ -2927,7 +3021,7 @@ - reghdr = (u_int32_t *)(pim + 1); - encap_ip = (struct ip *)(reghdr + 1); - -- if (mrtdebug & DEBUG_PIM) { -+ if (V_mrtdebug & DEBUG_PIM) { - log(LOG_DEBUG, - "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n", - (u_long)ntohl(encap_ip->ip_src.s_addr), -@@ -2937,8 +3031,8 @@ - - /* verify the version number of the inner packet */ - if (encap_ip->ip_v != IPVERSION) { -- pimstat.pims_rcv_badregisters++; -- if (mrtdebug & DEBUG_PIM) { -+ V_pimstat.pims_rcv_badregisters++; -+ if (V_mrtdebug & DEBUG_PIM) { - log(LOG_DEBUG, "pim_input: invalid IP version (%d) " - "of the inner packet\n", encap_ip->ip_v); - } -@@ -2948,8 +3042,8 @@ - - /* verify the inner packet is destined to a mcast group */ - if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) { -- pimstat.pims_rcv_badregisters++; -- if (mrtdebug & DEBUG_PIM) -+ V_pimstat.pims_rcv_badregisters++; -+ if (V_mrtdebug & DEBUG_PIM) - log(LOG_DEBUG, - "pim_input: inner packet of register is not " - "multicast %lx\n", -@@ -3000,21 +3094,21 @@ - - /* Keep statistics */ - /* XXX: registers_bytes include only the encap. mcast pkt */ -- pimstat.pims_rcv_registers_msgs++; -- pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len); -+ V_pimstat.pims_rcv_registers_msgs++; -+ V_pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len); - - /* - * forward the inner ip packet; point m_data at the inner ip. - */ - m_adj(m, iphlen + PIM_MINLEN); - -- if (mrtdebug & DEBUG_PIM) { -+ if (V_mrtdebug & DEBUG_PIM) { - log(LOG_DEBUG, - "pim_input: forwarding decapsulated register: " - "src %lx, dst %lx, vif %d\n", - (u_long)ntohl(encap_ip->ip_src.s_addr), - (u_long)ntohl(encap_ip->ip_dst.s_addr), -- reg_vif_num); -+ V_reg_vif_num); - } - /* NB: vifp was collected above; can it change on us? */ - if_simloop(vifp, m, dst.sin_family, 0); -@@ -3037,6 +3131,41 @@ - return; - } - -+#ifdef VIMAGE -+/* initialization for multicast routing state */ -+static int -+vnet_mroute_iattach(unused) -+ const void *unused; -+{ -+ INIT_VNET_MROUTE(curvnet); -+ -+ V_reg_vif_num = VIFI_INVALID; -+ MROUTER_LOCK_INIT(); -+ MFC_LOCK_INIT(); -+ VIF_LOCK_INIT(); -+ ip_mrouter_reset(); -+ return 0; -+} -+ -+/* de-initialization for multicast routing state */ -+static int -+vnet_mroute_idetach(unused) -+ const void *unused; -+{ -+ INIT_VNET_MROUTE(curvnet); -+ -+ X_ip_mrouter_done(); -+#ifdef INET6 -+ X_ip6_mrouter_done(); -+#endif -+ -+ VIF_LOCK_DESTROY(); -+ MFC_LOCK_DESTROY(); -+ MROUTER_LOCK_DESTROY(); -+ return 0; -+} -+#endif /* VIMAGE */ -+ - /* - * XXX: This is common code for dealing with initialization for both - * the IPv4 and IPv6 multicast forwarding paths. It could do with cleanup. -@@ -3045,12 +3174,15 @@ - ip_mroute_modevent(module_t mod, int type, void *unused) - { - INIT_VNET_INET(curvnet); -+ INIT_VNET_INET6(curvnet); -+ INIT_VNET_MROUTE(curvnet); - switch (type) { - case MOD_LOAD: -- MROUTER_LOCK_INIT(); -- MFC_LOCK_INIT(); -- VIF_LOCK_INIT(); -- ip_mrouter_reset(); -+#ifdef VIMAGE -+ vnet_mod_register(&vnet_mroute_modinfo); -+#else -+ vnet_mroute_iattach(NULL); -+#endif - TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt", - &pim_squelch_wholepkt); - -@@ -3113,17 +3245,21 @@ - */ - if (V_ip_mrouter - #ifdef INET6 -- || ip6_mrouter -+ || V_ip6_mrouter - #endif - ) - return EINVAL; - -+#ifdef VIMAGE -+ vnet_mod_deregister(&vnet_mroute_modinfo); -+#else -+ vnet_mroute_idetach(NULL) -+#endif - #ifdef INET6 - if (pim6_encap_cookie) { - encap_detach(pim6_encap_cookie); - pim6_encap_cookie = NULL; - } -- X_ip6_mrouter_done(); - ip6_mforward = NULL; - ip6_mrouter_done = NULL; - ip6_mrouter_get = NULL; -@@ -3135,7 +3271,6 @@ - encap_detach(pim_encap_cookie); - pim_encap_cookie = NULL; - } -- X_ip_mrouter_done(); - ip_mcast_src = NULL; - ip_mforward = NULL; - ip_mrouter_done = NULL; -@@ -3148,10 +3283,6 @@ - legal_vif_num = NULL; - mrt_ioctl = NULL; - rsvp_input_p = NULL; -- -- VIF_LOCK_DESTROY(); -- MFC_LOCK_DESTROY(); -- MROUTER_LOCK_DESTROY(); - break; - - default: -diff -ur sys.20081015/netinet/ip_mroute.h sys/netinet/ip_mroute.h ---- sys.20081015/netinet/ip_mroute.h 2008-08-16 16:29:19.000000000 -0700 -+++ sys/netinet/ip_mroute.h 2008-11-05 13:21:08.000000000 -0800 -@@ -52,6 +52,10 @@ - * bandwidth metering and signaling. - */ - -+#ifdef VIMAGE -+#include /* struct pimstat */ -+#endif -+ - - /* - * Multicast Routing set/getsockopt commands. -@@ -80,6 +84,9 @@ - typedef u_long vifbitmap_t; - typedef u_short vifi_t; /* type of a vif index */ - #define ALL_VIFS (vifi_t)-1 -+#ifdef VIMAGE -+#define VIFI_INVALID ((vifi_t) -1) -+#endif /* VIMAGE */ - - #define VIFM_SET(n, m) ((m) |= (1 << (n))) - #define VIFM_CLR(n, m) ((m) &= ~(1 << (n))) -@@ -205,6 +212,10 @@ - #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_SEC 3 - #define BW_UPCALL_THRESHOLD_INTERVAL_MIN_USEC 0 - -+#ifdef VIMAGE -+#define BW_METER_BUCKETS 1024 -+#endif /* VIMAGE */ -+ - /* - * The kernel's multicast routing statistics. - */ -@@ -361,6 +372,62 @@ - extern int (*ip_mrouter_done)(void); - extern int (*mrt_ioctl)(int, caddr_t, int); - -+#ifdef VIMAGE -+struct vnet_mroute { -+ /* from ip_mroute.c */ -+ u_int _rsvpdebug; -+ u_int _mrtdebug; -+ struct mrtstat _mrtstat; -+ struct mfc *_mfctable[MFCTBLSIZ]; -+ struct mtx _mrouter_mtx; -+ struct mtx _mfc_mtx; -+ struct vif _viftable[MAXVIFS]; -+ struct mtx _vif_mtx; -+ u_char _nexpire[MFCTBLSIZ]; -+ eventhandler_tag _if_detach_event_tag; -+ struct callout _expire_upcalls_ch; -+ struct bw_meter *_bw_meter_timers[BW_METER_BUCKETS]; -+ struct callout _bw_meter_ch; -+ struct bw_upcall _bw_upcalls[BW_UPCALLS_MAX]; -+ u_int _bw_upcalls_n; -+ struct callout _bw_upcalls_ch; -+ struct pimstat _pimstat; -+ struct ifnet _multicast_register_if; -+ vifi_t _reg_vif_num; -+ vifi_t _numvifs; -+ int _pim_assert; -+ uint32_t _mrt_api_config; -+}; -+#endif /* VIMAGE */ -+ -+#define INIT_VNET_MROUTE(vnet) \ -+ INIT_FROM_VNET(vnet, VNET_MOD_MROUTE, struct vnet_mroute, vnet_mroute) -+ -+#define VNET_MROUTE(sym) VSYM(vnet_mroute, sym) -+ -+#define V_rsvpdebug VNET_MROUTE(rsvpdebug) -+#define V_mrtdebug VNET_MROUTE(mrtdebug) -+#define V_mrtstat VNET_MROUTE(mrtstat) -+#define V_mfctable VNET_MROUTE(mfctable) -+#define V_mrouter_mtx VNET_MROUTE(mrouter_mtx) -+#define V_mfc_mtx VNET_MROUTE(mfc_mtx) -+#define V_viftable VNET_MROUTE(viftable) -+#define V_vif_mtx VNET_MROUTE(vif_mtx) -+#define V_nexpire VNET_MROUTE(nexpire) -+#define V_if_detach_event_tag VNET_MROUTE(if_detach_event_tag) -+#define V_expire_upcalls_ch VNET_MROUTE(expire_upcalls_ch) -+#define V_bw_meter_timers VNET_MROUTE(bw_meter_timers) -+#define V_bw_meter_ch VNET_MROUTE(bw_meter_ch) -+#define V_bw_upcalls VNET_MROUTE(bw_upcalls) -+#define V_bw_upcalls_n VNET_MROUTE(bw_upcalls_n) -+#define V_bw_upcalls_ch VNET_MROUTE(bw_upcalls_ch) -+#define V_pimstat VNET_MROUTE(pimstat) -+#define V_multicast_register_if VNET_MROUTE(multicast_register_if) -+#define V_reg_vif_num VNET_MROUTE(reg_vif_num) -+#define V_numvifs VNET_MROUTE(numvifs) -+#define V_pim_assert VNET_MROUTE(pim_assert) -+#define V_mrt_api_config VNET_MROUTE(mrt_api_config) -+ - #endif /* _KERNEL */ - - #endif /* _NETINET_IP_MROUTE_H_ */ -diff -ur sys.20081015/netinet/pim_var.h sys/netinet/pim_var.h ---- sys.20081015/netinet/pim_var.h 2007-11-19 06:49:11.000000000 -0800 -+++ sys/netinet/pim_var.h 2008-10-28 20:01:22.000000000 -0700 -@@ -73,7 +73,9 @@ - #ifdef _KERNEL - - void pim_input(struct mbuf *, int); -+#ifdef SYSCTL_DECL - SYSCTL_DECL(_net_inet_pim); - #endif -+#endif - - #endif /* _NETINET_PIM_VAR_H_ */ -diff -ur sys.20081015/netinet/vinet.h sys/netinet/vinet.h ---- sys.20081015/netinet/vinet.h 2007-11-19 09:09:38.000000000 -0800 -+++ sys/netinet/vinet.h 2008-11-03 16:04:36.000000000 -0800 -@@ -53,6 +53,9 @@ - #include - #include - #include -+#include -+#include -+#include - - struct vnet_inet { - struct in_ifaddrhashhead *_in_ifaddrhashtbl; -diff -ur sys.20081015/netinet6/ip6_input.c sys/netinet6/ip6_input.c ---- sys.20081015/netinet6/ip6_input.c 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/ip6_input.c 2008-10-28 20:01:22.000000000 -0700 -@@ -192,6 +192,20 @@ - nd6_init(); - frag6_init(); - -+ V_ip6_mrouter_ver = 0; -+ V_ip6_mrouter = NULL; -+ bzero(&V_mrt6stat, sizeof(V_mrt6stat)); -+ bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); -+ bzero((caddr_t)V_n6expire, sizeof(V_n6expire)); -+ bzero((caddr_t)V_mif6table, sizeof(V_mif6table)); -+ V_mrt6debug = 0; -+ V_multicast_register_if6 = NULL; -+ V_nummifs = 0; -+ V_reg_mif_num = (mifi_t)-1; -+ bzero(&V_pim6stat, sizeof(V_pim6stat)); -+ V_pim6 = 0; -+ bzero((caddr_t)V_upcall_data, sizeof(V_upcall_data)); -+ - #ifdef VIMAGE - /* Skip global initialization stuff for non-default instances. */ - if (!IS_DEFAULT_VNET(curvnet)) -@@ -507,7 +521,7 @@ - IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); - if (in6m) - ours = 1; -- else if (!ip6_mrouter) { -+ else if (!V_ip6_mrouter) { - V_ip6stat.ip6s_notmember++; - V_ip6stat.ip6s_cantforward++; - in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); -@@ -768,7 +782,7 @@ - * ip6_mforward() returns a non-zero value, the packet - * must be discarded, else it may be accepted below. - */ -- if (ip6_mrouter && ip6_mforward && -+ if (V_ip6_mrouter && ip6_mforward && - ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { - V_ip6stat.ip6s_cantforward++; - m_freem(m); -diff -ur sys.20081015/netinet6/ip6_mroute.c sys/netinet6/ip6_mroute.c ---- sys.20081015/netinet6/ip6_mroute.c 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/ip6_mroute.c 2008-11-05 14:34:10.000000000 -0800 -@@ -160,14 +160,17 @@ - SYSCTL_DECL(_net_inet6_ip6); - SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); - -+#ifndef VIMAGE - static struct mrt6stat mrt6stat; --SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW, -- &mrt6stat, mrt6stat, -+#endif /* !VIMAGE */ -+SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_ip6, OID_AUTO, mrt6stat, -+ CTLFLAG_RW, mrt6stat, mrt6stat, - "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)"); - - #define NO_RTE_FOUND 0x1 - #define RTE_FOUND 0x2 - -+#ifndef VIMAGE - static struct mf6c *mf6ctable[MF6CTBLSIZ]; - SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD, - &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]", -@@ -180,6 +183,7 @@ - SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD, - &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]", - "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)"); -+#endif /* !VIMAGE */ - - #ifdef MRT6DEBUG - #ifndef VIMAGE -@@ -199,7 +203,9 @@ - - #ifdef INET - #ifdef MROUTING -+#ifndef VIMAGE - extern struct socket *ip_mrouter; -+#endif /* !VIMAGE */ - #endif - #endif - -@@ -214,19 +220,23 @@ - * only exist as a placeholder for multicast source - * verification. - */ -+#ifndef VIMAGE - static struct ifnet *multicast_register_if6; -+#endif /* !VIMAGE */ - - #define ENCAP_HOPS 64 - - /* - * Private variables. - */ -+#ifndef VIMAGE - static mifi_t nummifs = 0; - static mifi_t reg_mif_num = (mifi_t)-1; - - static struct pim6stat pim6stat; --SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD, -- &pim6stat, pim6stat, -+#endif /* !VIMAGE */ -+SYSCTL_V_STRUCT(V_NET, vnet_inet6, _net_inet6_pim, PIM6CTL_STATS, stats, -+ CTLFLAG_RD, pim6stat, pim6stat, - "PIM Statistics (struct pim6stat, netinet6/pim_var.h)"); - - #ifndef VIMAGE -@@ -245,9 +255,9 @@ - * Find a route for a given origin IPv6 address and Multicast group address. - */ - #define MF6CFIND(o, g, rt) do { \ -- struct mf6c *_rt = mf6ctable[MF6CHASH(o,g)]; \ -+ struct mf6c *_rt = V_mf6ctable[MF6CHASH(o,g)]; \ - rt = NULL; \ -- mrt6stat.mrt6s_mfc_lookups++; \ -+ V_mrt6stat.mrt6s_mfc_lookups++; \ - while (_rt) { \ - if (IN6_ARE_ADDR_EQUAL(&_rt->mf6c_origin.sin6_addr, &(o)) && \ - IN6_ARE_ADDR_EQUAL(&_rt->mf6c_mcastgrp.sin6_addr, &(g)) && \ -@@ -258,7 +268,7 @@ - _rt = _rt->mf6c_next; \ - } \ - if (rt == NULL) { \ -- mrt6stat.mrt6s_mfc_misses++; \ -+ V_mrt6stat.mrt6s_mfc_misses++; \ - } \ - } while (/*CONSTCOND*/ 0) - -@@ -291,7 +301,9 @@ - - #ifdef UPCALL_TIMING - #define UPCALL_MAX 50 -+#ifndef VIMAGE - static u_long upcall_data[UPCALL_MAX + 1]; -+#endif /* !VIMAGE */ - static void collate(); - #endif /* UPCALL_TIMING */ - -@@ -303,7 +315,9 @@ - static int add_m6fc(struct mf6cctl *); - static int del_m6fc(struct mf6cctl *); - --static struct callout expire_upcalls_ch; -+#ifndef VIMAGE -+static struct callout expire_upcalls_ch6; -+#endif /* !VIMAGE */ - - int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m); - int X_ip6_mrouter_done(void); -@@ -311,19 +325,21 @@ - int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt); - int X_mrt6_ioctl(int cmd, caddr_t data); - -+ - /* - * Handle MRT setsockopt commands to modify the multicast routing tables. - */ - int - X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) - { -+ INIT_VNET_INET6(so->so_vnet); - int error = 0; - int optval; - struct mif6ctl mifc; - struct mf6cctl mfcc; - mifi_t mifi; - -- if (so != ip6_mrouter && sopt->sopt_name != MRT6_INIT) -+ if (so != V_ip6_mrouter && sopt->sopt_name != MRT6_INIT) - return (EACCES); - - switch (sopt->sopt_name) { -@@ -385,10 +401,10 @@ - int - X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) - { -- INIT_VNET_INET6(curvnet); -+ INIT_VNET_INET6(so->so_vnet); - int error = 0; - -- if (so != ip6_mrouter) -+ if (so != V_ip6_mrouter) - return (EACCES); - - switch (sopt->sopt_name) { -@@ -421,6 +437,7 @@ - static int - get_sg_cnt(struct sioc_sg_req6 *req) - { -+ INIT_VNET_INET6(curvnet); - struct mf6c *rt; - int s; - -@@ -446,15 +463,16 @@ - static int - get_mif6_cnt(struct sioc_mif_req6 *req) - { -+ INIT_VNET_INET6(curvnet); - mifi_t mifi = req->mifi; - -- if (mifi >= nummifs) -+ if (mifi >= V_nummifs) - return (EINVAL); - -- req->icount = mif6table[mifi].m6_pkt_in; -- req->ocount = mif6table[mifi].m6_pkt_out; -- req->ibytes = mif6table[mifi].m6_bytes_in; -- req->obytes = mif6table[mifi].m6_bytes_out; -+ req->icount = V_mif6table[mifi].m6_pkt_in; -+ req->ocount = V_mif6table[mifi].m6_pkt_out; -+ req->ibytes = V_mif6table[mifi].m6_bytes_in; -+ req->obytes = V_mif6table[mifi].m6_bytes_out; - - return (0); - } -@@ -477,9 +495,11 @@ - static int - ip6_mrouter_init(struct socket *so, int v, int cmd) - { -- INIT_VNET_INET6(curvnet); -+ INIT_VNET_INET6(so->so_vnet); - - V_ip6_mrouter_ver = 0; -+ V_nummifs = 0; -+ V_reg_mif_num = (mifi_t)-1; - - #ifdef MRT6DEBUG - V_mrt6debug = 0; -@@ -497,20 +517,20 @@ - if (v != 1) - return (ENOPROTOOPT); - -- if (ip6_mrouter != NULL) -+ if (V_ip6_mrouter != NULL) - return (EADDRINUSE); - -- ip6_mrouter = so; -+ V_ip6_mrouter = so; - V_ip6_mrouter_ver = cmd; - -- bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); -- bzero((caddr_t)n6expire, sizeof(n6expire)); -+ bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); -+ bzero((caddr_t)V_n6expire, sizeof(V_n6expire)); - - V_pim6 = 0;/* used for stubbing out/in pim stuff */ - -- callout_init(&expire_upcalls_ch, 0); -- callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, -- expire_upcalls, NULL); -+ callout_init(&V_expire_upcalls_ch6, 0); -+ callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT, -+ expire_upcalls, (void *)so->so_vnet); - - #ifdef MRT6DEBUG - if (V_mrt6debug) -@@ -547,29 +567,29 @@ - * XXX: there may be an interface in which the IPv4 multicast - * daemon is not interested... - */ -- if (!ip_mrouter) -+ if (!V_ip_mrouter) - #endif - #endif - { -- for (mifi = 0; mifi < nummifs; mifi++) { -- if (mif6table[mifi].m6_ifp && -- !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { -- if_allmulti(mif6table[mifi].m6_ifp, 0); -+ for (mifi = 0; mifi < V_nummifs; mifi++) { -+ if (V_mif6table[mifi].m6_ifp && -+ !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) { -+ if_allmulti(V_mif6table[mifi].m6_ifp, 0); - } - } - } -- bzero((caddr_t)mif6table, sizeof(mif6table)); -- nummifs = 0; -+ bzero((caddr_t)V_mif6table, sizeof(V_mif6table)); -+ V_nummifs = 0; - - V_pim6 = 0; /* used to stub out/in pim specific code */ - -- callout_stop(&expire_upcalls_ch); -+ callout_stop(&V_expire_upcalls_ch6); - - /* - * Free all multicast forwarding cache entries. - */ - for (i = 0; i < MF6CTBLSIZ; i++) { -- rt = mf6ctable[i]; -+ rt = V_mf6ctable[i]; - while (rt) { - struct mf6c *frt; - -@@ -586,19 +606,19 @@ - } - } - -- bzero((caddr_t)mf6ctable, sizeof(mf6ctable)); -+ bzero((caddr_t)V_mf6ctable, sizeof(V_mf6ctable)); - - /* - * Reset register interface - */ -- if (reg_mif_num != (mifi_t)-1 && multicast_register_if6 != NULL) { -- if_detach(multicast_register_if6); -- if_free(multicast_register_if6); -- reg_mif_num = (mifi_t)-1; -- multicast_register_if6 = NULL; -+ if (V_reg_mif_num != (mifi_t)-1 && V_multicast_register_if6 != NULL) { -+ if_detach(V_multicast_register_if6); -+ if_free(V_multicast_register_if6); -+ V_reg_mif_num = (mifi_t)-1; -+ V_multicast_register_if6 = NULL; - } - -- ip6_mrouter = NULL; -+ V_ip6_mrouter = NULL; - V_ip6_mrouter_ver = 0; - - splx(s); -@@ -620,13 +640,14 @@ - add_m6if(struct mif6ctl *mifcp) - { - INIT_VNET_NET(curvnet); -+ INIT_VNET_INET6(curvnet); - struct mif6 *mifp; - struct ifnet *ifp; - int error, s; - - if (mifcp->mif6c_mifi >= MAXMIFS) - return (EINVAL); -- mifp = mif6table + mifcp->mif6c_mifi; -+ mifp = V_mif6table + mifcp->mif6c_mifi; - if (mifp->m6_ifp) - return (EADDRINUSE); /* XXX: is it appropriate? */ - if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) -@@ -634,14 +655,14 @@ - ifp = ifnet_byindex(mifcp->mif6c_pifi); - - if (mifcp->mif6c_flags & MIFF_REGISTER) { -- if (reg_mif_num == (mifi_t)-1) { -+ if (V_reg_mif_num == (mifi_t)-1) { - ifp = if_alloc(IFT_OTHER); - - if_initname(ifp, "register_mif", 0); - ifp->if_flags |= IFF_LOOPBACK; - if_attach(ifp); -- multicast_register_if6 = ifp; -- reg_mif_num = mifcp->mif6c_mifi; -+ V_multicast_register_if6 = ifp; -+ V_reg_mif_num = mifcp->mif6c_mifi; - /* - * it is impossible to guess the ifindex of the - * register interface. So mif6c_pifi is automatically -@@ -649,7 +670,7 @@ - */ - mifcp->mif6c_pifi = ifp->if_index; - } else { -- ifp = multicast_register_if6; -+ ifp = V_multicast_register_if6; - } - - } /* if REGISTER */ -@@ -676,9 +697,9 @@ - mifp->m6_bytes_out = 0; - splx(s); - -- /* Adjust nummifs up if the mifi is higher than nummifs */ -- if (nummifs <= mifcp->mif6c_mifi) -- nummifs = mifcp->mif6c_mifi + 1; -+ /* Adjust V_nummifs up if the mifi is higher than V_nummifs */ -+ if (V_nummifs <= mifcp->mif6c_mifi) -+ V_nummifs = mifcp->mif6c_mifi + 1; - - #ifdef MRT6DEBUG - if (V_mrt6debug) -@@ -697,12 +718,13 @@ - static int - del_m6if(mifi_t *mifip) - { -- struct mif6 *mifp = mif6table + *mifip; -+ INIT_VNET_INET6(curvnet); -+ struct mif6 *mifp = V_mif6table + *mifip; - mifi_t mifi; - struct ifnet *ifp; - int s; - -- if (*mifip >= nummifs) -+ if (*mifip >= V_nummifs) - return (EINVAL); - if (mifp->m6_ifp == NULL) - return (EINVAL); -@@ -718,28 +740,28 @@ - - if_allmulti(ifp, 0); - } else { -- if (reg_mif_num != (mifi_t)-1 && -- multicast_register_if6 != NULL) { -- if_detach(multicast_register_if6); -- if_free(multicast_register_if6); -- reg_mif_num = (mifi_t)-1; -- multicast_register_if6 = NULL; -+ if (V_reg_mif_num != (mifi_t)-1 && -+ V_multicast_register_if6 != NULL) { -+ if_detach(V_multicast_register_if6); -+ if_free(V_multicast_register_if6); -+ V_reg_mif_num = (mifi_t)-1; -+ V_multicast_register_if6 = NULL; - } - } - - bzero((caddr_t)mifp, sizeof(*mifp)); - -- /* Adjust nummifs down */ -- for (mifi = nummifs; mifi > 0; mifi--) -- if (mif6table[mifi - 1].m6_ifp) -+ /* Adjust V_nummifs down */ -+ for (mifi = V_nummifs; mifi > 0; mifi--) -+ if (V_mif6table[mifi - 1].m6_ifp) - break; -- nummifs = mifi; -+ V_nummifs = mifi; - - splx(s); - - #ifdef MRT6DEBUG - if (V_mrt6debug) -- log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs); -+ log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, V_nummifs); - #endif - - return (0); -@@ -787,7 +809,7 @@ - s = splnet(); - hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr, - mfccp->mf6cc_mcastgrp.sin6_addr); -- for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { -+ for (rt = V_mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) { - if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, - &mfccp->mf6cc_origin.sin6_addr) && - IN6_ARE_ADDR_EQUAL(&rt->mf6c_mcastgrp.sin6_addr, -@@ -825,7 +847,7 @@ - rt->mf6c_wrong_if = 0; - - rt->mf6c_expire = 0; /* Don't clean this guy up */ -- n6expire[hash]--; -+ V_n6expire[hash]--; - - /* free packets Qed at the end of this entry */ - for (rte = rt->mf6c_stall; rte != NULL; ) { -@@ -856,7 +878,7 @@ - mfccp->mf6cc_parent); - #endif - -- for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { -+ for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) { - - if (IN6_ARE_ADDR_EQUAL(&rt->mf6c_origin.sin6_addr, - &mfccp->mf6cc_origin.sin6_addr)&& -@@ -873,7 +895,7 @@ - rt->mf6c_wrong_if = 0; - - if (rt->mf6c_expire) -- n6expire[hash]--; -+ V_n6expire[hash]--; - rt->mf6c_expire = 0; - } - } -@@ -899,8 +921,8 @@ - rt->mf6c_stall = NULL; - - /* link into table */ -- rt->mf6c_next = mf6ctable[hash]; -- mf6ctable[hash] = rt; -+ rt->mf6c_next = V_mf6ctable[hash]; -+ V_mf6ctable[hash] = rt; - } - } - splx(s); -@@ -914,6 +936,7 @@ - static void - collate(struct timeval *t) - { -+ INIT_VNET_INET6(curvnet); - u_long d; - struct timeval tp; - u_long delta; -@@ -928,7 +951,7 @@ - if (d > UPCALL_MAX) - d = UPCALL_MAX; - -- ++upcall_data[d]; -+ ++V_upcall_data[d]; - } - } - #endif /* UPCALL_TIMING */ -@@ -962,7 +985,7 @@ - - s = splnet(); - -- nptr = &mf6ctable[hash]; -+ nptr = &V_mf6ctable[hash]; - while ((rt = *nptr) != NULL) { - if (IN6_ARE_ADDR_EQUAL(&origin.sin6_addr, - &rt->mf6c_origin.sin6_addr) && -@@ -1097,7 +1120,7 @@ - GET_TIME(tp); - #endif /* UPCALL_TIMING */ - -- mrt6stat.mrt6s_no_route++; -+ V_mrt6stat.mrt6s_no_route++; - #ifdef MRT6DEBUG - if (V_mrt6debug & (DEBUG_FORWARD | DEBUG_MFC)) - log(LOG_DEBUG, "ip6_mforward: no rte s %s g %s\n", -@@ -1131,7 +1154,7 @@ - - /* is there an upcall waiting for this packet? */ - hash = MF6CHASH(ip6->ip6_src, ip6->ip6_dst); -- for (rt = mf6ctable[hash]; rt; rt = rt->mf6c_next) { -+ for (rt = V_mf6ctable[hash]; rt; rt = rt->mf6c_next) { - if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, - &rt->mf6c_origin.sin6_addr) && - IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, -@@ -1205,8 +1228,8 @@ - "getting the iif info in the kernel\n"); - #endif - -- for (mifp = mif6table, mifi = 0; -- mifi < nummifs && mifp->m6_ifp != ifp; -+ for (mifp = V_mif6table, mifi = 0; -+ mifi < V_nummifs && mifp->m6_ifp != ifp; - mifp++, mifi++) - ; - -@@ -1221,10 +1244,10 @@ - break; - } - -- if (socket_send(ip6_mrouter, mm, &sin6) < 0) { -+ if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { - log(LOG_WARNING, "ip6_mforward: ip6_mrouter " - "socket queue full\n"); -- mrt6stat.mrt6s_upq_sockfull++; -+ V_mrt6stat.mrt6s_upq_sockfull++; - free(rte, M_MRTABLE6); - m_freem(mb0); - free(rt, M_MRTABLE6); -@@ -1232,7 +1255,7 @@ - return (ENOBUFS); - } - -- mrt6stat.mrt6s_upcalls++; -+ V_mrt6stat.mrt6s_upcalls++; - - /* insert new entry at head of hash chain */ - bzero(rt, sizeof(*rt)); -@@ -1243,12 +1266,12 @@ - rt->mf6c_mcastgrp.sin6_len = sizeof(struct sockaddr_in6); - rt->mf6c_mcastgrp.sin6_addr = ip6->ip6_dst; - rt->mf6c_expire = UPCALL_EXPIRE; -- n6expire[hash]++; -+ V_n6expire[hash]++; - rt->mf6c_parent = MF6C_INCOMPLETE_PARENT; - - /* link into table */ -- rt->mf6c_next = mf6ctable[hash]; -- mf6ctable[hash] = rt; -+ rt->mf6c_next = V_mf6ctable[hash]; -+ V_mf6ctable[hash] = rt; - /* Add this entry to the end of the queue */ - rt->mf6c_stall = rte; - } else { -@@ -1258,7 +1281,7 @@ - - for (p = &rt->mf6c_stall; *p != NULL; p = &(*p)->next) - if (++npkts > MAX_UPQ6) { -- mrt6stat.mrt6s_upq_ovflw++; -+ V_mrt6stat.mrt6s_upq_ovflw++; - free(rte, M_MRTABLE6); - m_freem(mb0); - splx(s); -@@ -1289,7 +1312,7 @@ - static void - expire_upcalls(void *unused) - { -- INIT_VNET_INET6(curvnet); -+ INIT_VNET_INET6( (struct vnet*)unused ); - struct rtdetq *rte; - struct mf6c *mfc, **nptr; - int i; -@@ -1297,9 +1320,9 @@ - - s = splnet(); - for (i = 0; i < MF6CTBLSIZ; i++) { -- if (n6expire[i] == 0) -+ if (V_n6expire[i] == 0) - continue; -- nptr = &mf6ctable[i]; -+ nptr = &V_mf6ctable[i]; - while ((mfc = *nptr) != NULL) { - rte = mfc->mf6c_stall; - /* -@@ -1329,8 +1352,8 @@ - free(rte, M_MRTABLE6); - rte = n; - } while (rte != NULL); -- mrt6stat.mrt6s_cache_cleanups++; -- n6expire[i]--; -+ V_mrt6stat.mrt6s_cache_cleanups++; -+ V_n6expire[i]--; - - *nptr = mfc->mf6c_next; - free(mfc, M_MRTABLE6); -@@ -1339,9 +1362,9 @@ - } - } - } -+ callout_reset(&V_expire_upcalls_ch6, EXPIRE_TIMEOUT, -+ expire_upcalls, unused); - splx(s); -- callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, -- expire_upcalls, NULL); - } - - /* -@@ -1377,16 +1400,16 @@ - * for its origin. - */ - mifi = rt->mf6c_parent; -- if ((mifi >= nummifs) || (mif6table[mifi].m6_ifp != ifp)) { -+ if ((mifi >= V_nummifs) || (V_mif6table[mifi].m6_ifp != ifp)) { - /* came in the wrong interface */ - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_FORWARD) - log(LOG_DEBUG, - "wrong if: ifid %d mifi %d mififid %x\n", - ifp->if_index, mifi, -- mif6table[mifi].m6_ifp->if_index); -+ V_mif6table[mifi].m6_ifp->if_index); - #endif -- mrt6stat.mrt6s_wrong_if++; -+ V_mrt6stat.mrt6s_wrong_if++; - rt->mf6c_wrong_if++; - /* - * If we are doing PIM processing, and we are forwarding -@@ -1394,7 +1417,7 @@ - * routing daemon. - */ - /* have to make sure this is a valid mif */ -- if (mifi < nummifs && mif6table[mifi].m6_ifp) -+ if (mifi < V_nummifs && V_mif6table[mifi].m6_ifp) - if (V_pim6 && (m->m_flags & M_LOOP) == 0) { - /* - * Check the M_LOOP flag to avoid an -@@ -1440,8 +1463,8 @@ - return (EINVAL); - } - -- for (mifp = mif6table, iif = 0; -- iif < nummifs && mifp && -+ for (mifp = V_mif6table, iif = 0; -+ iif < V_nummifs && mifp && - mifp->m6_ifp != ifp; - mifp++, iif++) - ; -@@ -1459,14 +1482,14 @@ - break; - } - -- mrt6stat.mrt6s_upcalls++; -+ V_mrt6stat.mrt6s_upcalls++; - -- if (socket_send(ip6_mrouter, mm, &sin6) < 0) { -+ if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { - #ifdef MRT6DEBUG - if (V_mrt6debug) - log(LOG_WARNING, "mdq, ip6_mrouter socket queue full\n"); - #endif -- ++mrt6stat.mrt6s_upq_sockfull; -+ ++V_mrt6stat.mrt6s_upq_sockfull; - return (ENOBUFS); - } /* if socket Q full */ - } /* if PIM */ -@@ -1476,11 +1499,11 @@ - /* If I sourced this packet, it counts as output, else it was input. */ - if (m->m_pkthdr.rcvif == NULL) { - /* XXX: is rcvif really NULL when output?? */ -- mif6table[mifi].m6_pkt_out++; -- mif6table[mifi].m6_bytes_out += plen; -+ V_mif6table[mifi].m6_pkt_out++; -+ V_mif6table[mifi].m6_bytes_out += plen; - } else { -- mif6table[mifi].m6_pkt_in++; -- mif6table[mifi].m6_bytes_in += plen; -+ V_mif6table[mifi].m6_pkt_in++; -+ V_mif6table[mifi].m6_bytes_in += plen; - } - rt->mf6c_pkt_cnt++; - rt->mf6c_byte_cnt += plen; -@@ -1496,7 +1519,7 @@ - V_ip6stat.ip6s_badscope++; - return (error); - } -- for (mifp = mif6table, mifi = 0; mifi < nummifs; mifp++, mifi++) { -+ for (mifp = V_mif6table, mifi = 0; mifi < V_nummifs; mifp++, mifi++) { - if (IF_ISSET(mifi, &rt->mf6c_ifset)) { - /* - * check if the outgoing packet is going to break -@@ -1504,12 +1527,12 @@ - * XXX For packets through PIM register tunnel - * interface, we believe a routing daemon. - */ -- if (!(mif6table[rt->mf6c_parent].m6_flags & -+ if (!(V_mif6table[rt->mf6c_parent].m6_flags & - MIFF_REGISTER) && -- !(mif6table[mifi].m6_flags & MIFF_REGISTER)) { -- if (in6_setscope(&src0, mif6table[mifi].m6_ifp, -+ !(V_mif6table[mifi].m6_flags & MIFF_REGISTER)) { -+ if (in6_setscope(&src0, V_mif6table[mifi].m6_ifp, - &oszone) || -- in6_setscope(&dst0, mif6table[mifi].m6_ifp, -+ in6_setscope(&dst0, V_mif6table[mifi].m6_ifp, - &odzone) || - iszone != oszone || - idzone != odzone) { -@@ -1575,7 +1598,7 @@ - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_XMIT) - log(LOG_DEBUG, "phyint_send on mif %d err %d\n", -- mifp - mif6table, error); -+ mifp - V_mif6table, error); - #endif - splx(s); - return; -@@ -1611,7 +1634,7 @@ - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_XMIT) - log(LOG_DEBUG, "phyint_send on mif %d err %d\n", -- mifp - mif6table, error); -+ mifp - V_mif6table, error); - #endif - } else { - /* -@@ -1659,7 +1682,7 @@ - ip6_sprintf(ip6bufd, &ip6->ip6_dst)); - } - #endif -- ++pim6stat.pim6s_snd_registers; -+ ++V_pim6stat.pim6s_snd_registers; - - /* Make a copy of the packet to send to the user level process */ - MGETHDR(mm, M_DONTWAIT, MT_HEADER); -@@ -1691,18 +1714,18 @@ - im6->im6_msgtype = MRT6MSG_WHOLEPKT; - im6->im6_mbz = 0; - -- im6->im6_mif = mif - mif6table; -+ im6->im6_mif = mif - V_mif6table; - - /* iif info is not given for reg. encap.n */ -- mrt6stat.mrt6s_upcalls++; -+ V_mrt6stat.mrt6s_upcalls++; - -- if (socket_send(ip6_mrouter, mm, &sin6) < 0) { -+ if (socket_send(V_ip6_mrouter, mm, &sin6) < 0) { - #ifdef MRT6DEBUG - if (V_mrt6debug) - log(LOG_WARNING, - "register_send: ip6_mrouter socket queue full\n"); - #endif -- ++mrt6stat.mrt6s_upq_sockfull; -+ ++V_mrt6stat.mrt6s_upq_sockfull; - return (ENOBUFS); - } - return (0); -@@ -1726,7 +1749,7 @@ - int minlen; - int off = *offp; - -- ++pim6stat.pim6s_rcv_total; -+ ++V_pim6stat.pim6s_rcv_total; - - ip6 = mtod(m, struct ip6_hdr *); - pimlen = m->m_pkthdr.len - *offp; -@@ -1735,7 +1758,7 @@ - * Validate lengths - */ - if (pimlen < PIM_MINLEN) { -- ++pim6stat.pim6s_rcv_tooshort; -+ ++V_pim6stat.pim6s_rcv_tooshort; - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_PIM) - log(LOG_DEBUG,"pim6_input: PIM packet too short\n"); -@@ -1768,7 +1791,7 @@ - #else - IP6_EXTHDR_GET(pim, struct pim *, m, off, minlen); - if (pim == NULL) { -- pim6stat.pim6s_rcv_tooshort++; -+ V_pim6stat.pim6s_rcv_tooshort++; - return (IPPROTO_DONE); - } - #endif -@@ -1788,7 +1811,7 @@ - cksumlen = pimlen; - - if (in6_cksum(m, IPPROTO_PIM, off, cksumlen)) { -- ++pim6stat.pim6s_rcv_badsum; -+ ++V_pim6stat.pim6s_rcv_badsum; - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_PIM) - log(LOG_DEBUG, -@@ -1802,7 +1825,7 @@ - - /* PIM version check */ - if (pim->pim_ver != PIM_VERSION) { -- ++pim6stat.pim6s_rcv_badversion; -+ ++V_pim6stat.pim6s_rcv_badversion; - #ifdef MRT6DEBUG - log(LOG_ERR, - "pim6_input: incorrect version %d, expecting %d\n", -@@ -1828,14 +1851,14 @@ - char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; - #endif - -- ++pim6stat.pim6s_rcv_registers; -+ ++V_pim6stat.pim6s_rcv_registers; - -- if ((reg_mif_num >= nummifs) || (reg_mif_num == (mifi_t) -1)) { -+ if ((V_reg_mif_num >= V_nummifs) || (V_reg_mif_num == (mifi_t) -1)) { - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_PIM) - log(LOG_DEBUG, - "pim6_input: register mif not set: %d\n", -- reg_mif_num); -+ V_reg_mif_num); - #endif - m_freem(m); - return (IPPROTO_DONE); -@@ -1850,8 +1873,8 @@ - * Validate length - */ - if (pimlen < PIM6_REG_MINLEN) { -- ++pim6stat.pim6s_rcv_tooshort; -- ++pim6stat.pim6s_rcv_badregisters; -+ ++V_pim6stat.pim6s_rcv_tooshort; -+ ++V_pim6stat.pim6s_rcv_badregisters; - #ifdef MRT6DEBUG - log(LOG_ERR, - "pim6_input: register packet size too " -@@ -1875,7 +1898,7 @@ - - /* verify the version number of the inner packet */ - if ((eip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { -- ++pim6stat.pim6s_rcv_badregisters; -+ ++V_pim6stat.pim6s_rcv_badregisters; - #ifdef MRT6DEBUG - log(LOG_DEBUG, "pim6_input: invalid IP version (%d) " - "of the inner packet\n", -@@ -1887,7 +1910,7 @@ - - /* verify the inner packet is destined to a mcast group */ - if (!IN6_IS_ADDR_MULTICAST(&eip6->ip6_dst)) { -- ++pim6stat.pim6s_rcv_badregisters; -+ ++V_pim6stat.pim6s_rcv_badregisters; - #ifdef MRT6DEBUG - if (V_mrt6debug & DEBUG_PIM) - log(LOG_DEBUG, -@@ -1924,11 +1947,11 @@ - "src %s, dst %s, mif %d\n", - ip6_sprintf(ip6bufs, &eip6->ip6_src), - ip6_sprintf(ip6bufd, &eip6->ip6_dst), -- reg_mif_num); -+ V_reg_mif_num); - } - #endif - -- rc = if_simloop(mif6table[reg_mif_num].m6_ifp, m, -+ rc = if_simloop(V_mif6table[V_reg_mif_num].m6_ifp, m, - dst.sin6_family, 0); - - /* prepare the register head to send to the mrouting daemon */ -diff -ur sys.20081015/netinet6/ip6_mroute.h sys/netinet6/ip6_mroute.h ---- sys.20081015/netinet6/ip6_mroute.h 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/ip6_mroute.h 2008-11-05 13:21:56.000000000 -0800 -@@ -266,6 +266,7 @@ - extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt); - extern int (*ip6_mrouter_done)(void); - extern int (*mrt6_ioctl)(int, caddr_t); -+ - #endif /* _KERNEL */ - - #endif /* !_NETINET6_IP6_MROUTE_H_ */ -diff -ur sys.20081015/netinet6/ip6_output.c sys/netinet6/ip6_output.c ---- sys.20081015/netinet6/ip6_output.c 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/ip6_output.c 2008-10-28 20:01:22.000000000 -0700 -@@ -744,7 +744,7 @@ - * above, will be forwarded by the ip6_input() routine, - * if necessary. - */ -- if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { -+ if (V_ip6_mrouter && (flags & IPV6_FORWARDING) == 0) { - /* - * XXX: ip6_mforward expects that rcvif is NULL - * when it is called from the originating path. -diff -ur sys.20081015/netinet6/ip6_var.h sys/netinet6/ip6_var.h ---- sys.20081015/netinet6/ip6_var.h 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/ip6_var.h 2008-10-28 20:01:22.000000000 -0700 -@@ -292,8 +292,8 @@ - extern int ip6_v6only; - #endif - --extern struct socket *ip6_mrouter; /* multicast routing daemon */ - #ifndef VIMAGE -+extern struct socket *ip6_mrouter; /* multicast routing daemon */ - extern int ip6_sendredirects; /* send IP redirects when forwarding? */ - extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */ - extern int ip6_maxfrags; /* Maximum fragments in reassembly queue */ -diff -ur sys.20081015/netinet6/mld6.c sys/netinet6/mld6.c ---- sys.20081015/netinet6/mld6.c 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/mld6.c 2008-10-28 20:01:22.000000000 -0700 -@@ -518,7 +518,7 @@ - * Request loopback of the report if we are acting as a multicast - * router, so that the process-level routing daemon can hear it. - */ -- im6o.im6o_multicast_loop = (ip6_mrouter != NULL); -+ im6o.im6o_multicast_loop = (V_ip6_mrouter != NULL); - - /* increment output statictics */ - V_icmp6stat.icp6s_outhist[type]++; -diff -ur sys.20081015/netinet6/raw_ip6.c sys/netinet6/raw_ip6.c ---- sys.20081015/netinet6/raw_ip6.c 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/raw_ip6.c 2008-10-28 20:01:22.000000000 -0700 -@@ -129,7 +129,9 @@ - /* - * Hooks for multicast forwarding. - */ -+#ifndef VIMAGE - struct socket *ip6_mrouter = NULL; -+#endif - int (*ip6_mrouter_set)(struct socket *, struct sockopt *); - int (*ip6_mrouter_get)(struct socket *, struct sockopt *); - int (*ip6_mrouter_done)(void); -@@ -599,12 +601,13 @@ - rip6_detach(struct socket *so) - { - INIT_VNET_INET(so->so_vnet); -+ INIT_VNET_INET6(so->so_vnet); - struct inpcb *inp; - - inp = sotoinpcb(so); - KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); - -- if (so == ip6_mrouter && ip6_mrouter_done) -+ if (so == V_ip6_mrouter && ip6_mrouter_done) - ip6_mrouter_done(); - /* xxx: RSVP */ - INP_INFO_WLOCK(&V_ripcbinfo); -diff -ur sys.20081015/netinet6/vinet6.h sys/netinet6/vinet6.h ---- sys.20081015/netinet6/vinet6.h 2008-10-15 08:25:28.000000000 -0700 -+++ sys/netinet6/vinet6.h 2008-10-29 12:58:52.000000000 -0700 -@@ -43,6 +43,8 @@ - #include - #include - #include -+#include -+#include /* struct pim6stat */ - - #define INIT_VNET_INET6(vnet) \ - INIT_FROM_VNET(vnet, VNET_MOD_INET6, \ -@@ -95,6 +97,7 @@ - //int _icmp6_nodeinfo; - - int _ip6_forwarding; -+ struct socket * _ip6_mrouter; - int _ip6_sendredirects; - int _ip6_defhlim; - int _ip6_defmcasthlim; -@@ -149,14 +152,25 @@ - u_int32_t _ip6_temp_preferred_lifetime; - u_int32_t _ip6_temp_valid_lifetime; - -- int _ip6_mrouter_ver; -- int _pim6; -- u_int _mrt6debug; -- - int _ip6_temp_regen_advance; - int _ip6_use_defzone; - - struct ip6_pktopts _ip6_opts; -+ -+ /* from ip6_mroute.c */ -+ int _ip6_mrouter_ver; /* = 0; */ -+ struct mrt6stat _mrt6stat; -+ struct mf6c * _mf6ctable[MF6CTBLSIZ]; -+ u_char _n6expire[MF6CTBLSIZ]; -+ struct mif6 _mif6table[MAXMIFS]; -+ u_int _mrt6debug; -+ struct ifnet * _multicast_register_if6; -+ mifi_t _nummifs; /* = 0; */ -+ mifi_t _reg_mif_num; /* = (mifi_t)-1; */ -+ struct pim6stat _pim6stat; -+ int _pim6; -+ u_long _upcall_data[51]; -+ struct callout _expire_upcalls_ch6; - }; - #endif - -@@ -206,6 +220,7 @@ - //#define V_icmp6_nodeinfo VNET_INET6(icmp6_nodeinfo) - - #define V_ip6_forwarding VNET_INET6(ip6_forwarding) -+#define V_ip6_mrouter VNET_INET6(ip6_mrouter) - #define V_ip6_sendredirects VNET_INET6(ip6_sendredirects) - #define V_ip6_defhlim VNET_INET6(ip6_defhlim) - #define V_ip6_defmcasthlim VNET_INET6(ip6_defmcasthlim) -@@ -260,13 +275,24 @@ - #define V_ip6_temp_preferred_lifetime VNET_INET6(ip6_temp_preferred_lifetime) - #define V_ip6_temp_valid_lifetime VNET_INET6(ip6_temp_valid_lifetime) - --#define V_ip6_mrouter_ver VNET_INET6(ip6_mrouter_ver) --#define V_pim6 VNET_INET6(pim6) --#define V_mrt6debug VNET_INET6(mrt6debug) - #define V_ip6_temp_regen_advance VNET_INET6(ip6_temp_regen_advance) - - #define V_ip6_use_defzone VNET_INET6(ip6_use_defzone) - - #define V_ip6_opts VNET_INET6(ip6_opts) - -+#define V_ip6_mrouter_ver VNET_INET6(ip6_mrouter_ver) -+#define V_mrt6stat VNET_INET6(mrt6stat) -+#define V_mf6ctable VNET_INET6(mf6ctable) -+#define V_n6expire VNET_INET6(n6expire) -+#define V_mif6table VNET_INET6(mif6table) -+#define V_mrt6debug VNET_INET6(mrt6debug) -+#define V_multicast_register_if6 VNET_INET6(multicast_register_if6) -+#define V_nummifs VNET_INET6(nummifs) -+#define V_reg_mif_num VNET_INET6(reg_mif_num) -+#define V_pim6stat VNET_INET6(pim6stat) -+#define V_pim6 VNET_INET6(pim6) -+#define V_upcall_data VNET_INET6(upcall_data) -+#define V_expire_upcalls_ch6 VNET_INET6(expire_upcalls_ch6) -+ - #endif /* !_NETINET6_VINET6_H_ */ -diff -ur sys.20081015/netipsec/keysock.c sys/netipsec/keysock.c ---- sys.20081015/netipsec/keysock.c 2008-10-15 08:25:29.000000000 -0700 -+++ sys/netipsec/keysock.c 2008-10-29 07:57:18.000000000 -0700 -@@ -429,8 +429,8 @@ - kp->kp_promisc = kp->kp_registered = 0; - - if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ -- key_cb.key_count++; -- key_cb.any_count++; -+ V_key_cb.key_count++; -+ V_key_cb.any_count++; - soisconnected(so); - so->so_options |= SO_USELOOPBACK; - -diff -ur sys.20081015/sys/vimage.h sys/sys/vimage.h ---- sys.20081015/sys/vimage.h 2008-10-15 08:25:30.000000000 -0700 -+++ sys/sys/vimage.h 2008-11-04 13:56:18.000000000 -0800 -@@ -77,6 +77,7 @@ - #define VNET_MOD_IPX 9 - #define VNET_MOD_ATALK 10 - #define VNET_MOD_DIVERT 11 -+#define VNET_MOD_MROUTE 12 - /* stateless modules */ - #define VNET_MOD_NG_WORMHOLE 19 - #define VNET_MOD_NG_ETHER 20 -@@ -103,6 +104,7 @@ - #define V_MOD_vnet_pf VNET_MOD_PF - #define V_MOD_vnet_gif VNET_MOD_GIF - #define V_MOD_vnet_ipsec VNET_MOD_IPSEC -+#define V_MOD_vnet_mroute VNET_MOD_MROUTE - - #define V_MOD_vprocg 0 - #define V_MOD_vcpu 0 diff --git a/packaging/bsd/core-kernel-deinstall-4.11.sh b/packaging/bsd/core-kernel-deinstall-4.11.sh deleted file mode 100755 index b52c96e2..00000000 --- a/packaging/bsd/core-kernel-deinstall-4.11.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -echo Restoring /kernel.old ... -install -m 555 -o root -g wheel -fschg /kernel.old /kernel -rm -rf /modules -mv /modules.old /modules - diff --git a/packaging/bsd/core-kernel-deinstall-8.x.sh b/packaging/bsd/core-kernel-deinstall-8.x.sh deleted file mode 100755 index 5b64141b..00000000 --- a/packaging/bsd/core-kernel-deinstall-8.x.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -PREV="" - -if [ ! -e "/boot/kernel.old" ] ; then - if [ ! -e "/boot/GENERIC" ] ; then - echo Previous kernel does not exist in /boot/kernel.old or /boot/GENERIC ! - exit 1; - else - PREV="/boot/GENERIC" - fi; -else - PREV="/boot/kernel.old" -fi; - -echo Removing current kernel... -chflags -R noschg /boot/kernel -rm -rf /boot/kernel -echo Restoring previous kernel from $PREV... -mv $PREV /boot/kernel - -exit 0; diff --git a/packaging/bsd/core-kernel-pkgcreate.sh b/packaging/bsd/core-kernel-pkgcreate.sh deleted file mode 100755 index 00f2bbac..00000000 --- a/packaging/bsd/core-kernel-pkgcreate.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/sh -VER=0.0 - -# determine FreeBSD 4.11 or 8.x -REL=`uname -r` -case "$REL" in - 9.*) - echo "Using FreeBSD 9.x..." - KERN=9.x - SCRIPTVER=8.x - ;; - 8.*) - echo "Using FreeBSD 8.x..." - KERN=8.x - SCRIPTVER=8.x - ;; - 4.11-RELEASE) - echo "Using FreeBSD 4.11..." - KERN=4.11 - SCRIPTVER=4.11 - ;; - *) - echo "What version of FreeBSD are you running (4.11/8.x) ?" - exit 1 -esac - -if [ "a$1" = "a" ] -then - echo "usage: ./core-kernel-release.sh 20080228 [clean]" - echo a version number is required - exit 1; -else -VER=$1 -fi; - -if [ "a$2" = "aclean" ] -then - echo Cleaning up... - rm -f core-kernel.pkglist.tmp - rm -f core-kernel.pkglist - rm -f core-kernel-${KERN}-${VER}.tbz - exit -fi; - - -# check for /kernel.new on 4.11 -if [ ${KERN} = "4.11" ] -then - -if [ -e "/kernel.new" ] -then - echo Note: proceeding using this kernel... - ls -al /kernel.new -else - echo "error: first copy the desired kernel to /kernel.new" - exit -fi; - -fi; - - - -# -# build the packing list -# -echo @comment ORIGIN:net/core-kernel > core-kernel.pkglist -if [ ${KERN} = "4.11" ] -# FreeBSD 4.11 -then -echo @cwd / >> core-kernel.pkglist -echo kernel.new >> core-kernel.pkglist -find /modules \! -type d > core-kernel.pkglist.tmp -find /sbin/vimage >> core-kernel.pkglist.tmp -find /usr/share/man/man8/vimage.8.gz >> core-kernel.pkglist.tmp -find /sbin/ngctl >> core-kernel.pkglist.tmp -find /usr/share/man/man8/ngctl.8.gz >> core-kernel.pkglist.tmp -# FreeBSD 8.x -else -echo @cwd /boot >> core-kernel.pkglist -PWDOLD=${PWD} -cd /boot -find kernel \! -type d > ${PWDOLD}/core-kernel.pkglist.tmp -cd ${PWDOLD} -echo @cwd / >> core-kernel.pkglist.tmp -find /usr/sbin/vimage >> core-kernel.pkglist.tmp -find /usr/share/man/man8/vimage.8.gz >> core-kernel.pkglist.tmp -fi; - -# remove leading '/' from lines -sed -e "s,^/,," core-kernel.pkglist.tmp >> core-kernel.pkglist - -# -# build the package -# -pkg_create -c core-kernel.pkgdesc -d core-kernel.pkgdesclong -f core-kernel.pkglist -i core-kernel-preinstall-${SCRIPTVER}.sh -K core-kernel-deinstall-${SCRIPTVER}.sh -v core-kernel-${KERN}-${VER}.tbz - diff --git a/packaging/bsd/core-kernel-preinstall-4.11.sh b/packaging/bsd/core-kernel-preinstall-4.11.sh deleted file mode 100755 index b53ffee2..00000000 --- a/packaging/bsd/core-kernel-preinstall-4.11.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -if [ "x$2" = "xPOST-INSTALL" ] -then - install -m 555 -o root -g wheel -fschg /kernel.new /kernel - rm -f /kernel.new - echo Please reboot this machine to enable the new CORE kernel. - exit 0; -fi; - -install -m 555 -o root -g wheel -fschg /kernel /kernel.old -if [ -e /modules.old ] -then - rm -rf /modules.old -fi; - -mv /modules /modules.old -exit 0; diff --git a/packaging/bsd/core-kernel-preinstall-8.x.sh b/packaging/bsd/core-kernel-preinstall-8.x.sh deleted file mode 100755 index 1a5dc2f3..00000000 --- a/packaging/bsd/core-kernel-preinstall-8.x.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -if [ "x$2" = "xPOST-INSTALL" ] -then - echo Please reboot this machine to enable the new CORE kernel. - exit 0; -fi; - -# PRE-INSTALL -# save the GENERIC kernel -OLDNAME=`strings /boot/kernel/kernel | tail -n 1` -if [ "x$OLDNAME" = "xGENERIC" ] -then - chflags -R noschg /boot/kernel - mv /boot/kernel /boot/GENERIC - exit 0; -fi; -# get rid of /boot/kernel.old if it is in the way -if [ -e "/boot/kernel.old" ] ; then - chflags -R noschg /boot/kernel.old - rm -rf /boot/kernel.old -fi; - -chflags -R noschg /boot/kernel -mv /boot/kernel /boot/kernel.old - -exit 0; diff --git a/packaging/bsd/core-kernel.pkgdesc b/packaging/bsd/core-kernel.pkgdesc deleted file mode 100644 index 9c9bcf63..00000000 --- a/packaging/bsd/core-kernel.pkgdesc +++ /dev/null @@ -1 +0,0 @@ -CORE FreeBSD kernel enables lightweight virtual machines diff --git a/packaging/bsd/core-kernel.pkgdesclong b/packaging/bsd/core-kernel.pkgdesclong deleted file mode 100644 index 83beefc9..00000000 --- a/packaging/bsd/core-kernel.pkgdesclong +++ /dev/null @@ -1 +0,0 @@ -This package contains the CORE FreeBSD kernel with kernel modules. Custom modules include ng_pipe and ng_wlan. Also contains the userspace utility program vimage. This package can be used along with the CORE GUI to build emulated networks. This kernel is based on the GENERIC kernel with the VIMAGE option turned on (per-jail network stack virtualization), and with a small patch to allow per-node filesystem access. diff --git a/packaging/bsd/core-pkgcreate.sh b/packaging/bsd/core-pkgcreate.sh deleted file mode 100755 index fd8233f0..00000000 --- a/packaging/bsd/core-pkgcreate.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh - -VER=`grep -m 1 "set CORE_VERSION" ../../gui/version.tcl | awk '{ print $3 }'` -ARCH=`uname -m` -# determine FreeBSD 4.11 or 7.x -REL=`uname -r` -case "$REL" in - 9.*) - echo "Using FreeBSD 9.x..." - KERN=9.x - ;; - 8.*) - echo "Using FreeBSD 8.x..." - KERN=8.x - ;; - 4.11-RELEASE) - echo "Using FreeBSD 4.11..." - KERN=4.11 - ;; - *) - echo "What version of FreeBSD are you running (4.11/8.x) ?" - exit 1 -esac - -if [ "a$1" = "aclean" ] -then - echo Cleaning up... - rm -f core.pkglist.tmp - rm -f core.pkglist - rm -f core-${KERN}-${VER}.tbz - rm -rf /tmp/staging - exit -fi; - - -# -# build the packing list -# -echo @comment ORIGIN:net/core > core.pkglist -echo @cwd /usr/local >> core.pkglist -PKG_BASH=`pkg_info -E -x ^bash` -# for 4.11 change this back to 8.4 -PKG_TCL=`pkg_info -E -x ^tcl-8.5` -PKG_TK=`pkg_info -E -x ^tk-8.5` -echo @pkgdep ${PKG_BASH} >> core.pkglist -echo @comment DEPORIGIN:shells/bash >> core.pkglist -echo @pkgdep ${PKG_TCL} >> core.pkglist -echo @comment DEPORIGIN:lang/tcl85 >> core.pkglist -echo @pkgdep ${PKG_TK} >> core.pkglist -echo @comment DEPORIGIN:x11-toolkits/tk85 >> core.pkglist - -SAVEDIR=`pwd` -cd ../.. -rm -rf /tmp/staging -gmake DESTDIR=/tmp/staging install -cd $SAVEDIR -find /tmp/staging/usr/local \! -type d >> core.pkglist -echo @cwd /etc >> core.pkglist -find /tmp/staging/etc \! -type d >> core.pkglist -sed -e "s,^/tmp/staging/usr/local/,," core.pkglist > core.pkglist.new1 -sed -e "s,^/tmp/staging/etc/,," core.pkglist.new1 > core.pkglist -rm -f core.pkglist.new1 - -# -# build the package -# -pkg_create -c core.pkgdesc -d core.pkgdesclong -f core.pkglist -v core-${KERN}-${ARCH}-${VER}.tbz - diff --git a/packaging/bsd/core.pkgdesc b/packaging/bsd/core.pkgdesc deleted file mode 100644 index c836d5cd..00000000 --- a/packaging/bsd/core.pkgdesc +++ /dev/null @@ -1 +0,0 @@ -Common Open Research Emulator userspace components diff --git a/packaging/bsd/core.pkgdesclong b/packaging/bsd/core.pkgdesclong deleted file mode 100644 index e8158147..00000000 --- a/packaging/bsd/core.pkgdesclong +++ /dev/null @@ -1,3 +0,0 @@ -The Common Open Research Emulator (CORE) is a tool that allows you to emulate entire networks on a FreeBSD or Linux machine. You can connect these emulated networks to live networks (or to additional emulated networks) via the machine's physical interfaces. This package contains CORE userspace components for easily drawing topologies that drive lightweight virutalized network stacks. - -WWW: http://www.nrl.navy.mil/itd/ncs/products/core diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 95622585..3f6a4f44 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -24,15 +24,7 @@ dist-hook: rm -rf $(distdir)/xen/.svn # install startup scripts based on --with-startup=option configure option -# FreeBSD, init.d (default), systemd, SUSE -if WANT_BSD -startupdir = /usr/local/etc/rc.d -startup_SCRIPTS = core-daemon - -core-daemon: core-daemon-rc.d - cp $< $@ -else - +# init.d (default), systemd, SUSE if WANT_INITD startupdir = /etc/init.d startup_SCRIPTS = core-daemon @@ -51,8 +43,6 @@ startup_SCRIPTS = core-daemon core-daemon: core-daemon-init.d-SUSE cp $< $@ endif -# endif FreeBSD -endif # remove extra scripts and their directories if they are empty uninstall-hook: From 940e10ef5ef5eca938107f496fa7121764188764 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Mar 2018 14:42:41 -0800 Subject: [PATCH 056/152] small change to documentation referencing other virtualizations --- doc/intro.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/intro.rst b/doc/intro.rst index 95c11f86..4274f2f6 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -63,7 +63,6 @@ command-line tools. The system is modular to allow mixing different components. The virtual networks component, for example, can be realized with other network simulators and emulators, such as ns-3 and EMANE. -Different types of kernel virtualization are supported. Another example is how a session can be designed and started using the GUI, and continue to run in "headless" operation with the GUI closed. The CORE API is sockets based, From a5370ee28c4a4001b67a75e3fee108f361dbf2a2 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Mar 2018 15:47:14 -0800 Subject: [PATCH 057/152] initial commit removing all related xen code, docs, files --- Makefile.am | 2 +- README-Xen | 87 --- configure.ac | 1 - daemon/Makefile.am | 4 +- daemon/core/corehandlers.py | 5 +- daemon/core/enumerations.py | 1 - daemon/core/misc/nodemaps.py | 2 - daemon/core/sdt.py | 17 +- daemon/core/service.py | 2 +- daemon/core/session.py | 5 - daemon/core/xen/__init__.py | 0 daemon/core/xen/xen.py | 789 -------------------------- daemon/core/xen/xenconfig.py | 301 ---------- daemon/core/xml/xmlparser0.py | 2 - daemon/core/xml/xmlparser1.py | 4 - daemon/data/xen.conf | 35 -- daemon/sbin/core-xen-cleanup | 73 --- daemon/setup.py | 8 +- doc/install.rst | 3 - doc/machine.rst | 28 +- doc/man/Makefile.am | 3 +- doc/man/core-cleanup.1 | 1 - doc/man/core-xen-cleanup.1 | 28 - doc/usage.rst | 5 - gui/api.tcl | 7 +- gui/configs/sample10-kitchen-sink.imn | 2 +- gui/core-bsd-cleanup.sh | 60 -- gui/icons/Makefile.am | 7 +- gui/icons/normal/xen.gif | Bin 1684 -> 0 bytes gui/icons/svg/xen.svg | 181 ------ gui/icons/tiny/xen.gif | Bin 905 -> 0 bytes gui/nodes.tcl | 46 +- gui/plugins.tcl | 55 +- packaging/deb/core-daemon.install.in | 1 - packaging/rpm/core.spec.in | 10 - scripts/Makefile.am | 9 +- scripts/core-daemon-init.d-SUSE | 4 +- scripts/xen/Makefile.am | 15 - scripts/xen/vif-core | 48 -- 39 files changed, 80 insertions(+), 1771 deletions(-) delete mode 100644 README-Xen delete mode 100644 daemon/core/xen/__init__.py delete mode 100644 daemon/core/xen/xen.py delete mode 100644 daemon/core/xen/xenconfig.py delete mode 100644 daemon/data/xen.conf delete mode 100755 daemon/sbin/core-xen-cleanup delete mode 100644 doc/man/core-xen-cleanup.1 delete mode 100755 gui/core-bsd-cleanup.sh delete mode 100644 gui/icons/normal/xen.gif delete mode 100644 gui/icons/svg/xen.svg delete mode 100644 gui/icons/tiny/xen.gif delete mode 100644 scripts/xen/Makefile.am delete mode 100755 scripts/xen/vif-core diff --git a/Makefile.am b/Makefile.am index 26fda233..23ec7183 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,7 @@ ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball EXTRA_DIST = bootstrap.sh LICENSE \ README.md ASSIGNMENT_OF_COPYRIGHT.pdf \ - README-Xen Changelog kernel \ + Changelog kernel \ python-prefix.py revision.sh \ .version .version.date \ packaging/deb/compat \ diff --git a/README-Xen b/README-Xen deleted file mode 100644 index 80b742ba..00000000 --- a/README-Xen +++ /dev/null @@ -1,87 +0,0 @@ -CORE Xen README - -This file describes the xen branch of the CORE development tree which enables -machines based on Xen domUs. When you edit node types, you are given the option -of changing the machine type (netns, physical, or xen) and the profile for -each node type. - -CORE will create each domU machine on the fly, having a bootable ISO image that -contains the root filesystem, and a special persitent area (/rtr/persistent) -using a LVM volume where configuration is stored. See the /etc/core/xen.conf -file for related settings here. - -INSTALLATION - -1. Tested under OpenSUSE 11.3 which allows installing a Xen dom0 during the - install process. - -2. Create an LVM volume group having enough free space available for CORE to - build logical volumes for domU nodes. The name of this group is set with the - 'vg_name=' option in /etc/core/xen.conf. (With 256M per persistent area, - 10GB would allow for 40 nodes.) - -3. To get libev-devel in OpenSUSE, use: - zypper ar http://download.opensuse.org/repositories/X11:/windowmanagers/openSUSE_11.3 WindowManagers - zypper install libev-devel - -4. In addition to the normal CORE dependencies - (see http://code.google.com/p/coreemu/wiki/Quickstart), pyparted-3.2 is used - when creating LVM partitions and decorator-3.3.0 is a dependency for - pyparted. The 'python setup.py install' and 'make install' need to be - performed on these source tarballs as no packages are available. - - tar xzf decorator-3.3.0.tar.gz - cd decorator-3.3.0 - python setup.py build - python setup.py install - - tar xzf pyparted-3.2.tar.gz - cd pyparted-3.2 - ./configure - make - make install - -5. These Xen parameters were used for dom0, by editing /boot/grub/menu.lst: - a) Add options to "kernel /xen.gz" line: - gnttab_max_nr_frames=128 dom0_mem=1G dom0_max_vcpus=2 dom0_vcpus_pin - b) Make Xen default boot by editing the "default" line with the - index for the Xen boot option. e.g. change "default 0" to "default 2" - Reboot to enable the Xen kernel. - -5. Run CORE's ./configure script as root to properly discover sbin binaries. - - tar xzf core-xen.tgz - cd core-xen - ./bootstrap.sh - ./configure - make - make install - -6. Put your ISO images in /opt/core-xen/iso-files and set the "iso_file=" - xen.conf option appropriately. - -7. Uncomment the controlnet entry in /etc/core/core.conf: - # establish a control backchannel for accessing nodes - controlnet = 172.16.0.0/24 - - This setting governs what IP addresses will be used for a control channel. - Given this default setting the host dom0 will have the address 172.16.0.254 - assigned to a bridge device; domU VMs will get interfaces joined to this - bridge, having addresses such as 172.16.0.1 for node n1, 172.16.0.2 for n2, - etc. - - When 'controlnet =' is unspecified in the core.conf file, double-clicking on - a node results in the 'xm console' method. A key mapping is set up so you - can press 'F1' then 'F2' to login as root. The key ctrl+']' detaches from the - console. Only one console is available per domU VM. - -8. When 'controlnet =' is specified, double-clicking on a node results in an - attempt to ssh to that node's control IP address. - Put a host RSA key for use on the domUs in /opt/core-xen/ssh: - - mkdir -p /opt/core-xen/ssh - ssh-keygen -t rsa -f /opt/core-xen/ssh/ssh_host_rsa_key - cp ~/.ssh/id_rsa.pub /opt/core-xen/ssh/authorized_keys - chmod 600 /opt/core-xen/ssh/authorized_keys - - diff --git a/configure.ac b/configure.ac index 9bd21586..e643110d 100644 --- a/configure.ac +++ b/configure.ac @@ -309,7 +309,6 @@ AC_CONFIG_FILES([Makefile scripts/Makefile scripts/core-daemon.service scripts/perf/Makefile - scripts/xen/Makefile doc/Makefile doc/conf.py doc/man/Makefile diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 6c21e6d6..20ba8b36 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -18,14 +18,12 @@ SBIN_FILES = \ sbin/core-cleanup \ sbin/core-daemon \ sbin/core-manage \ - sbin/core-xen-cleanup \ sbin/coresendmsg dist_sbin_SCRIPTS = $(SBIN_FILES) CONF_FILES = \ - data/core.conf \ - data/xen.conf + data/core.conf coreconfdir = $(CORE_CONF_DIR) dist_coreconf_DATA = $(CONF_FILES) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index aa9b1775..73c308e5 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -618,9 +618,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): model = message.get_tlv(NodeTlvs.MODEL.value) class_args = {"start": start} - if node_type == NodeTypes.XEN.value: - class_args["model"] = model - if node_type == NodeTypes.RJ45.value and hasattr( self.session.options, "enablerj45") and self.session.options.enablerj45 == "0": class_args["start"] = False @@ -639,7 +636,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # add services to a node, either from its services TLV or # through the configured defaults for this node type - if node_type in [NodeTypes.DEFAULT.value, NodeTypes.PHYSICAL.value, NodeTypes.XEN.value]: + if node_type in [NodeTypes.DEFAULT.value, NodeTypes.PHYSICAL.value]: if model is None: # TODO: default model from conf file? model = "router" diff --git a/daemon/core/enumerations.py b/daemon/core/enumerations.py index b81ca09f..ac287272 100644 --- a/daemon/core/enumerations.py +++ b/daemon/core/enumerations.py @@ -69,7 +69,6 @@ class NodeTypes(Enum): """ DEFAULT = 0 PHYSICAL = 1 - XEN = 2 TBD = 3 SWITCH = 4 HUB = 5 diff --git a/daemon/core/misc/nodemaps.py b/daemon/core/misc/nodemaps.py index dfb9ad91..8c3d0c37 100644 --- a/daemon/core/misc/nodemaps.py +++ b/daemon/core/misc/nodemaps.py @@ -8,13 +8,11 @@ from core.enumerations import NodeTypes from core.netns import nodes from core.netns.vnet import GreTapBridge from core.phys import pnodes -from core.xen import xen # legacy core nodes, that leverage linux bridges NODES = { NodeTypes.DEFAULT: nodes.CoreNode, NodeTypes.PHYSICAL: pnodes.PhysicalNode, - NodeTypes.XEN: xen.XenNode, NodeTypes.TBD: None, NodeTypes.SWITCH: nodes.SwitchNode, NodeTypes.HUB: nodes.HubNode, diff --git a/daemon/core/sdt.py b/daemon/core/sdt.py index d035d50e..054b7a58 100644 --- a/daemon/core/sdt.py +++ b/daemon/core/sdt.py @@ -46,11 +46,15 @@ class Sdt(object): DEFAULT_ALT = 2500 # TODO: read in user"s nodes.conf here; below are default node types from the GUI DEFAULT_SPRITES = [ - ("router", "router.gif"), ("host", "host.gif"), - ("PC", "pc.gif"), ("mdr", "mdr.gif"), - ("prouter", "router_green.gif"), ("xen", "xen.gif"), - ("hub", "hub.gif"), ("lanswitch", "lanswitch.gif"), - ("wlan", "wlan.gif"), ("rj45", "rj45.gif"), + ("router", "router.gif"), + ("host", "host.gif"), + ("PC", "pc.gif"), + ("mdr", "mdr.gif"), + ("prouter", "router_green.gif"), + ("hub", "hub.gif"), + ("lanswitch", "lanswitch.gif"), + ("wlan", "wlan.gif"), + ("rj45", "rj45.gif"), ("tunnel", "tunnel.gif"), ] @@ -404,8 +408,7 @@ class Sdt(object): net = False if nodetype == NodeTypes.DEFAULT.value or \ - nodetype == NodeTypes.PHYSICAL.value or \ - nodetype == NodeTypes.XEN.value: + nodetype == NodeTypes.PHYSICAL.value: if model is None: model = "router" type = model diff --git a/daemon/core/service.py b/daemon/core/service.py index 7956a573..34863afa 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -87,7 +87,7 @@ class CoreServices(ConfigurableManager): name = "services" config_type = RegisterTlvs.UTILITY.value - _invalid_custom_names = ('core', 'api', 'emane', 'misc', 'netns', 'phys', 'services', 'xen') + _invalid_custom_names = ('core', 'api', 'emane', 'misc', 'netns', 'phys', 'services') def __init__(self, session): """ diff --git a/daemon/core/session.py b/daemon/core/session.py index 080db896..192e558c 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -45,7 +45,6 @@ from core.mobility import Ns2ScriptedMobility from core.netns import nodes from core.sdt import Sdt from core.service import CoreServices -from core.xen.xenconfig import XenConfigManager from core.xml.xmlsession import save_session_xml # set default node map @@ -190,10 +189,6 @@ class Session(object): self.emane = EmaneManager(session=self) self.add_config_object(EmaneManager.name, EmaneManager.config_type, self.emane.configure) - # setup xen - self.xen = XenConfigManager(session=self) - self.add_config_object(XenConfigManager.name, XenConfigManager.config_type, self.xen.configure) - # setup sdt self.sdt = Sdt(session=self) diff --git a/daemon/core/xen/__init__.py b/daemon/core/xen/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/daemon/core/xen/xen.py b/daemon/core/xen/xen.py deleted file mode 100644 index 95ae72fe..00000000 --- a/daemon/core/xen/xen.py +++ /dev/null @@ -1,789 +0,0 @@ -""" -xen.py: implementation of the XenNode and XenVEth classes that support -generating Xen domUs based on an ISO image and persistent configuration area -""" - -import base64 -import os -import shutil -import string -import subprocess -import sys -import threading - -import crypt - -from core import CoreCommandError -from core import constants -from core import logger -from core.coreobj import PyCoreNetIf -from core.coreobj import PyCoreNode -from core.enumerations import NodeTypes -from core.misc import nodeutils -from core.misc import utils -from core.netns.vnode import LxcNode - -try: - import parted -except ImportError: - logger.error("failed to import parted for xen nodes") - -try: - import fsimage -except ImportError: - # fix for fsimage under Ubuntu - sys.path.append("/usr/lib/xen-default/lib/python") - try: - import fsimage - except ImportError: - logger.error("failed to import fsimage for xen nodes") - -# XXX move these out to config file -AWK_PATH = "/bin/awk" -KPARTX_PATH = "/sbin/kpartx" -LVCREATE_PATH = "/sbin/lvcreate" -LVREMOVE_PATH = "/sbin/lvremove" -LVCHANGE_PATH = "/sbin/lvchange" -MKFSEXT4_PATH = "/sbin/mkfs.ext4" -MKSWAP_PATH = "/sbin/mkswap" -TAR_PATH = "/bin/tar" -SED_PATH = "/bin/sed" -XM_PATH = "/usr/sbin/xm" -UDEVADM_PATH = "/sbin/udevadm" - - -class XenVEth(PyCoreNetIf): - def __init__(self, node, name, localname, mtu=1500, net=None, start=True, hwaddr=None): - # note that net arg is ignored - PyCoreNetIf.__init__(self, node=node, name=name, mtu=mtu) - self.localname = localname - self.up = False - self.hwaddr = hwaddr - if start: - self.startup() - - def startup(self): - cmd = [XM_PATH, "network-attach", self.node.vmname, "vifname=%s" % self.localname, "script=vif-core"] - if self.hwaddr is not None: - cmd.append("mac=%s" % self.hwaddr) - subprocess.check_call(cmd) - subprocess.check_call([constants.IP_BIN, "link", "set", self.localname, "up"]) - self.up = True - - def shutdown(self): - if not self.up: - return - if self.localname: - if self.hwaddr is not None: - pass - # this should be doable, but some argument isn"t a string - # check_call([XM_PATH, "network-detach", self.node.vmname, - # self.hwaddr]) - self.up = False - - -class XenNode(PyCoreNode): - apitype = NodeTypes.XEN.value - - files_to_ignore = frozenset([ - # "ipforward.sh", - "quaggaboot.sh", - ]) - - files_redirection = { - "ipforward.sh": "/core-tmp/ipforward.sh", - } - - cmds_to_ignore = frozenset([ - # "sh ipforward.sh", - # "sh quaggaboot.sh zebra", - # "sh quaggaboot.sh ospfd", - # "sh quaggaboot.sh ospf6d", - "killall zebra", - "killall ospfd", - "killall ospf6d", - "pidof zebra", "pidof ospfd", "pidof ospf6d", - ]) - - def redir_cmd_ipforward(self): - sysctl_file = open(os.path.join(self.mountdir, self.etcdir, "sysctl.conf"), "a") - p1 = subprocess.Popen([AWK_PATH, "/^\/sbin\/sysctl -w/ {print $NF}", - os.path.join(self.nodedir, "core-tmp/ipforward.sh")], stdout=sysctl_file) - p1.wait() - sysctl_file.close() - - def redir_cmd_zebra(self): - subprocess.check_call([SED_PATH, "-i", "-e", "s/^zebra=no/zebra=yes/", - os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - - def redir_cmd_ospfd(self): - subprocess.check_call([SED_PATH, "-i", "-e", "s/^ospfd=no/ospfd=yes/", - os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - - def redir_cmd_ospf6d(self): - subprocess.check_call([SED_PATH, "-i", "-e", "s/^ospf6d=no/ospf6d=yes/", - os.path.join(self.mountdir, self.etcdir, "quagga/daemons")]) - - cmds_redirection = { - "sh ipforward.sh": redir_cmd_ipforward, - "sh quaggaboot.sh zebra": redir_cmd_zebra, - "sh quaggaboot.sh ospfd": redir_cmd_ospfd, - "sh quaggaboot.sh ospf6d": redir_cmd_ospf6d, - } - - # CoreNode: no __init__, take from LxcNode & SimpleLxcNode - def __init__(self, session, objid=None, name=None, - nodedir=None, bootsh="boot.sh", start=True, model=None, - vgname=None, ramsize=None, disksize=None, - isofile=None): - # SimpleLxcNode initialization - PyCoreNode.__init__(self, session=session, objid=objid, name=name) - self.nodedir = nodedir - self.model = model - # indicates startup() has been invoked and disk has been initialized - self.up = False - # indicates boot() has been invoked and domU is running - self.booted = False - self.ifindex = 0 - self.lock = threading.RLock() - self._netif = {} - # domU name - self.vmname = "c" + str(session.session_id) + "-" + name - # LVM volume group name - self.vgname = self.getconfigitem("vg_name", vgname) - # LVM logical volume name - self.lvname = self.vmname + "-" - # LVM logical volume device path name - self.lvpath = os.path.join("/dev", self.vgname, self.lvname) - self.disksize = self.getconfigitem("disk_size", disksize) - self.ramsize = int(self.getconfigitem("ram_size", ramsize)) - self.isofile = self.getconfigitem("iso_file", isofile) - # temporary mount point for paused VM persistent filesystem - self.mountdir = None - self.etcdir = self.getconfigitem("etc_path") - - # TODO: remove this temporary hack - self.files_redirection["/usr/local/etc/quagga/Quagga.conf"] = os.path.join( - self.getconfigitem("mount_path"), self.etcdir, "quagga/Quagga.conf") - - # LxcNode initialization - # self.makenodedir() - if self.nodedir is None: - self.nodedir = os.path.join(session.session_dir, self.name + ".conf") - self.mountdir = self.nodedir + self.getconfigitem("mount_path") - if not os.path.isdir(self.mountdir): - os.makedirs(self.mountdir) - self.tmpnodedir = True - else: - raise Exception("Xen PVM node requires a temporary nodedir") - self.bootsh = bootsh - if start: - self.startup() - - def getconfigitem(self, name, default=None): - """ - Configuration items come from the xen.conf file and/or input from - the GUI, and are stored in the session using the XenConfigManager - object. self.model is used to identify particular profiles - associated with a node type in the GUI. - """ - return self.session.xen.getconfigitem(name=name, model=self.model, node=self, value=default) - - # from class LxcNode (also SimpleLxcNode) - def startup(self): - logger.warn("XEN PVM startup() called: preparing disk for %s", self.name) - self.lock.acquire() - try: - if self.up: - raise Exception("already up") - self.createlogicalvolume() - self.createpartitions() - persistdev = self.createfilesystems() - subprocess.check_call([constants.MOUNT_BIN, "-t", "ext4", persistdev, self.mountdir]) - self.untarpersistent(tarname=self.getconfigitem("persist_tar_iso"), - iso=True) - self.setrootpassword(pw=self.getconfigitem("root_password")) - self.sethostname(old="UBASE", new=self.name) - self.setupssh(keypath=self.getconfigitem("ssh_key_path")) - self.createvm() - self.up = True - finally: - self.lock.release() - - # from class LxcNode (also SimpleLxcNode) - def boot(self): - logger.warn("XEN PVM boot() called") - - self.lock.acquire() - if not self.up: - raise Exception("Can't boot VM without initialized disk") - - if self.booted: - self.lock.release() - return - - self.session.services.bootnodeservices(self) - tarname = self.getconfigitem("persist_tar") - if tarname: - self.untarpersistent(tarname=tarname, iso=False) - - try: - subprocess.check_call([constants.UMOUNT_BIN, self.mountdir]) - self.unmount_all(self.mountdir) - subprocess.check_call([UDEVADM_PATH, "settle"]) - subprocess.check_call([KPARTX_PATH, "-d", self.lvpath]) - - # time.sleep(5) - # time.sleep(1) - - # unpause VM - logger.warn("XEN PVM boot() unpause domU %s", self.vmname) - utils.check_cmd([XM_PATH, "unpause", self.vmname]) - - self.booted = True - finally: - self.lock.release() - - def validate(self): - self.session.services.validatenodeservices(self) - - # from class LxcNode (also SimpleLxcNode) - def shutdown(self): - logger.warn("XEN PVM shutdown() called") - if not self.up: - return - self.lock.acquire() - try: - if self.up: - # sketch from SimpleLxcNode - for netif in self.netifs(): - netif.shutdown() - - try: - # RJE XXX what to do here - if self.booted: - utils.check_cmd([XM_PATH, "destroy", self.vmname]) - self.booted = False - except CoreCommandError: - # ignore this error too, the VM may have exited already - logger.exception("error during shutdown") - - # discard LVM volume - lvm_remove_count = 0 - while os.path.exists(self.lvpath): - try: - subprocess.check_call([UDEVADM_PATH, "settle"]) - utils.check_cmd([LVCHANGE_PATH, "-an", self.lvpath]) - lvm_remove_count += 1 - utils.check_cmd([LVREMOVE_PATH, "-f", self.lvpath]) - except OSError: - logger.exception("error during shutdown") - - if lvm_remove_count > 1: - logger.warn("XEN PVM shutdown() required %d lvremove executions.", lvm_remove_count) - - self._netif.clear() - del self.session - - self.up = False - - finally: - self.rmnodedir() - self.lock.release() - - def createlogicalvolume(self): - """ - Create a logical volume for this Xen domU. Called from startup(). - """ - if os.path.exists(self.lvpath): - raise Exception, "LVM volume already exists" - utils.check_cmd([LVCREATE_PATH, "--size", self.disksize, - "--name", self.lvname, self.vgname]) - - def createpartitions(self): - """ - Partition the LVM volume into persistent and swap partitions - using the parted module. - """ - dev = parted.Device(path=self.lvpath) - dev.removeFromCache() - disk = parted.freshDisk(dev, "msdos") - constraint = parted.Constraint(device=dev) - persist_size = int(0.75 * constraint.maxSize) - self.createpartition(device=dev, disk=disk, start=1, - end=persist_size - 1, type="ext4") - self.createpartition(device=dev, disk=disk, start=persist_size, - end=constraint.maxSize - 1, type="linux-swap(v1)") - disk.commit() - - def createpartition(self, device, disk, start, end, type): - """ - Create a single partition of the specified type and size and add - it to the disk object, using the parted module. - """ - geo = parted.Geometry(device=device, start=start, end=end) - fs = parted.FileSystem(type=type, geometry=geo) - part = parted.Partition(disk=disk, fs=fs, type=parted.PARTITION_NORMAL, geometry=geo) - constraint = parted.Constraint(exactGeom=geo) - disk.addPartition(partition=part, constraint=constraint) - - def createfilesystems(self): - """ - Make an ext4 filesystem and swap space. Return the device name for - the persistent partition so we can mount it. - """ - output = subprocess.Popen([KPARTX_PATH, "-l", self.lvpath], - stdout=subprocess.PIPE).communicate()[0] - lines = output.splitlines() - persistdev = "/dev/mapper/" + lines[0].strip().split(" ")[0].strip() - swapdev = "/dev/mapper/" + lines[1].strip().split(" ")[0].strip() - subprocess.check_call([KPARTX_PATH, "-a", self.lvpath]) - utils.check_cmd([MKFSEXT4_PATH, "-L", "persist", persistdev]) - utils.check_cmd([MKSWAP_PATH, "-f", "-L", "swap", swapdev]) - return persistdev - - def untarpersistent(self, tarname, iso): - """ - Unpack a persistent template tar file to the mounted mount dir. - Uses fsimage library to read from an ISO file. - """ - # filename may use hostname - tarname = tarname.replace("%h", self.name) - if iso: - try: - fs = fsimage.open(self.isofile, 0) - except IOError: - logger.exception("Failed to open ISO file: %s", self.isofile) - return - try: - tardata = fs.open_file(tarname).read() - except IOError: - logger.exception("Failed to open tar file: %s", tarname) - return - finally: - del fs - else: - try: - f = open(tarname) - tardata = f.read() - f.close() - except IOError: - logger.exception("Failed to open tar file: %s", tarname) - return - p = subprocess.Popen([TAR_PATH, "-C", self.mountdir, "--numeric-owner", - "-xf", "-"], stdin=subprocess.PIPE) - p.communicate(input=tardata) - p.wait() - - def setrootpassword(self, pw): - """ - Set the root password by updating the shadow password file that - is on the filesystem mounted in the temporary area. - """ - saltedpw = crypt.crypt(pw, "$6$" + base64.b64encode(os.urandom(12))) - subprocess.check_call([SED_PATH, "-i", "-e", - "/^root:/s_^root:\([^:]*\):_root:" + saltedpw + ":_", - os.path.join(self.mountdir, self.etcdir, "shadow")]) - - def sethostname(self, old, new): - """ - Set the hostname by updating the hostname and hosts files that - reside on the filesystem mounted in the temporary area. - """ - subprocess.check_call([SED_PATH, "-i", "-e", "s/%s/%s/" % (old, new), - os.path.join(self.mountdir, self.etcdir, "hostname")]) - subprocess.check_call([SED_PATH, "-i", "-e", "s/%s/%s/" % (old, new), - os.path.join(self.mountdir, self.etcdir, "hosts")]) - - def setupssh(self, keypath): - """ - Configure SSH access by installing host keys and a system-wide - authorized_keys file. - """ - sshdcfg = os.path.join(self.mountdir, self.etcdir, "ssh/sshd_config") - subprocess.check_call([SED_PATH, "-i", "-e", "s/PermitRootLogin no/PermitRootLogin yes/", sshdcfg]) - sshdir = os.path.join(self.getconfigitem("mount_path"), self.etcdir, "ssh") - # backslash slashes for use in sed - sshdir = sshdir.replace("/", "\\/") - subprocess.check_call([SED_PATH, "-i", "-e", - "s/#AuthorizedKeysFile %h\/.ssh\/authorized_keys/" + \ - "AuthorizedKeysFile " + sshdir + "\/authorized_keys/", - sshdcfg]) - for f in "ssh_host_rsa_key", "ssh_host_rsa_key.pub", "authorized_keys": - src = os.path.join(keypath, f) - dst = os.path.join(self.mountdir, self.etcdir, "ssh", f) - shutil.copy(src, dst) - if f[-3:] != "pub": - os.chmod(dst, 0600) - - def createvm(self): - """ - Instantiate a *paused* domU VM - Instantiate it now, so we can add network interfaces, - pause it so we can have the filesystem open for configuration. - """ - args = [XM_PATH, "create", os.devnull, "--paused"] - args.extend(["name=" + self.vmname, "memory=" + str(self.ramsize)]) - args.append("disk=tap:aio:" + self.isofile + ",hda,r") - args.append("disk=phy:" + self.lvpath + ",hdb,w") - args.append("bootloader=pygrub") - bootargs = "--kernel=/isolinux/vmlinuz --ramdisk=/isolinux/initrd" - args.append("bootargs=" + bootargs) - for action in ("poweroff", "reboot", "suspend", "crash", "halt"): - args.append("on_%s=destroy" % action) - args.append("extra=" + self.getconfigitem("xm_create_extra")) - utils.check_cmd(args) - - # from class LxcNode - def privatedir(self, path): - # self.warn("XEN PVM privatedir() called") - # Do nothing, Xen PVM nodes are fully private - pass - - # from class LxcNode - def opennodefile(self, filename, mode="w"): - logger.warn("XEN PVM opennodefile() called") - raise Exception("Can't open VM file with opennodefile()") - - # from class LxcNode - # open a file on a paused Xen node - def openpausednodefile(self, filename, mode="w"): - dirname, basename = os.path.split(filename) - if not basename: - raise ValueError("no basename for filename: %s" % filename) - if dirname and dirname[0] == "/": - dirname = dirname[1:] - # dirname = dirname.replace("/", ".") - dirname = os.path.join(self.nodedir, dirname) - if not os.path.isdir(dirname): - os.makedirs(dirname, mode=0755) - hostfilename = os.path.join(dirname, basename) - return open(hostfilename, mode) - - # from class LxcNode - def nodefile(self, filename, contents, mode=0644): - if filename in self.files_to_ignore: - # self.warn("XEN PVM nodefile(filename=%s) ignored" % [filename]) - return - - if filename in self.files_redirection: - redirection_filename = self.files_redirection[filename] - logger.warn("XEN PVM nodefile(filename=%s) redirected to %s", filename, redirection_filename) - filename = redirection_filename - - logger.warn("XEN PVM nodefile(filename=%s) called", filename) - self.lock.acquire() - if not self.up: - self.lock.release() - raise Exception("Can't access VM file as VM disk isn't ready") - - if self.booted: - self.lock.release() - raise Exception("Can't access VM file as VM is already running") - - try: - f = self.openpausednodefile(filename, "w") - f.write(contents) - os.chmod(f.name, mode) - f.close() - logger.info("created nodefile: %s; mode: 0%o", f.name, mode) - finally: - self.lock.release() - - # from class SimpleLxcNode - def alive(self): - # is VM running? - return False # XXX - - def cmd(self, args, wait=True): - cmd_string = string.join(args, " ") - if cmd_string in self.cmds_to_ignore: - # self.warn("XEN PVM cmd(args=[%s]) called and ignored" % cmdAsString) - return 0 - if cmd_string in self.cmds_redirection: - self.cmds_redirection[cmd_string](self) - return 0 - - logger("XEN PVM cmd(args=[%s]) called, but not yet implemented", cmd_string) - return 0 - - def cmdresult(self, args): - cmd_string = string.join(args, " ") - if cmd_string in self.cmds_to_ignore: - # self.warn("XEN PVM cmd(args=[%s]) called and ignored" % cmdAsString) - return 0, "" - logger.warn("XEN PVM cmdresult(args=[%s]) called, but not yet implemented", cmd_string) - return 0, "" - - def popen(self, args): - cmd_string = string.join(args, " ") - logger.warn("XEN PVM popen(args=[%s]) called, but not yet implemented", cmd_string) - return - - def icmd(self, args): - cmd_string = string.join(args, " ") - logger.warn("XEN PVM icmd(args=[%s]) called, but not yet implemented", cmd_string) - return - - def term(self, sh="/bin/sh"): - logger.warn("XEN PVM term() called, but not yet implemented") - return - - def termcmdstring(self, sh="/bin/sh"): - """ - We may add "sudo" to the command string because the GUI runs as a - normal user. Use SSH if control interface is available, otherwise - use Xen console with a keymapping for easy login. - """ - controlifc = None - for ifc in self.netifs(): - if hasattr(ifc, "control") and ifc.control is True: - controlifc = ifc - break - cmd = "xterm " - # use SSH if control interface is available - if controlifc: - controlip = controlifc.addrlist[0].split("/")[0] - cmd += "-e ssh root@%s" % controlip - return cmd - # otherwise use "xm console" - # pw = self.getconfigitem("root_password") - # cmd += "-xrm "XTerm*VT100.translations: #override F1: " - # cmd += "string(\"root\\n\") \\n F2: string(\"%s\\n\")" " % pw - cmd += "-e sudo %s console %s" % (XM_PATH, self.vmname) - return cmd - - def shcmd(self, cmdstr, sh="/bin/sh"): - logger("XEN PVM shcmd(args=[%s]) called, but not yet implemented", cmdstr) - return - - def mount(self, source, target): - logger.warn("XEN PVM Nodes can't bind-mount filesystems") - - def umount(self, target): - logger.warn("XEN PVM Nodes can't bind-mount filesystems") - - def newifindex(self): - self.lock.acquire() - try: - while self.ifindex in self._netif: - self.ifindex += 1 - ifindex = self.ifindex - self.ifindex += 1 - return ifindex - finally: - self.lock.release() - - def getifindex(self, netif): - for ifindex in self._netif: - if self._netif[ifindex] is netif: - return ifindex - return -1 - - def addnetif(self, netif, ifindex): - logger.warn("XEN PVM addnetif() called") - PyCoreNode.addnetif(self, netif, ifindex) - - def delnetif(self, ifindex): - logger.warn("XEN PVM delnetif() called") - PyCoreNode.delnetif(self, ifindex) - - def newveth(self, ifindex=None, ifname=None, net=None, hwaddr=None): - logger.warn("XEN PVM newveth(ifindex=%s, ifname=%s) called", ifindex, ifname) - - self.lock.acquire() - try: - if ifindex is None: - ifindex = self.newifindex() - if ifname is None: - ifname = "eth%d" % ifindex - sessionid = self.session.short_session_id() - name = "n%s.%s.%s" % (self.objid, ifindex, sessionid) - localname = "n%s.%s.%s" % (self.objid, ifname, sessionid) - ifclass = XenVEth - veth = ifclass(node=self, name=name, localname=localname, - mtu=1500, net=net, hwaddr=hwaddr) - - veth.name = ifname - try: - self.addnetif(veth, ifindex) - except: - veth.shutdown() - del veth - raise - return ifindex - finally: - self.lock.release() - - def newtuntap(self, ifindex=None, ifname=None, net=None): - logger.warn("XEN PVM newtuntap() called but not implemented") - - def sethwaddr(self, ifindex, addr): - self._netif[ifindex].sethwaddr(addr) - if self.up: - pass - # self.cmd([IP_BIN, "link", "set", "dev", self.ifname(ifindex), - # "address", str(addr)]) - - def addaddr(self, ifindex, addr): - if self.up: - pass - # self.cmd([IP_BIN, "addr", "add", str(addr), - # "dev", self.ifname(ifindex)]) - self._netif[ifindex].addaddr(addr) - - def deladdr(self, ifindex, addr): - try: - self._netif[ifindex].deladdr(addr) - except ValueError: - logger.exception("trying to delete unknown address: %s", addr) - - if self.up: - pass - # self.cmd([IP_BIN, "addr", "del", str(addr), - # "dev", self.ifname(ifindex)]) - - valid_deladdrtype = ("inet", "inet6", "inet6link") - - def delalladdr(self, ifindex, addrtypes=valid_deladdrtype): - addr = self.getaddr(self.ifname(ifindex), rescan=True) - for t in addrtypes: - if t not in self.valid_deladdrtype: - raise ValueError("addr type must be in: " + " ".join(self.valid_deladdrtype)) - for a in addr[t]: - self.deladdr(ifindex, a) - # update cached information - self.getaddr(self.ifname(ifindex), rescan=True) - - # Xen PVM relies on boot process to bring up links - # def ifup(self, ifindex): - # if self.up: - # self.cmd([IP_BIN, "link", "set", self.ifname(ifindex), "up"]) - - def newnetif(self, net=None, addrlist=[], hwaddr=None, ifindex=None, ifname=None): - logger.warn("XEN PVM newnetif(ifindex=%s, ifname=%s) called", ifindex, ifname) - - self.lock.acquire() - - if not self.up: - self.lock.release() - raise Exception("Can't access add veth as VM disk isn't ready") - - if self.booted: - self.lock.release() - raise Exception("Can't access add veth as VM is already running") - - try: - if nodeutils.is_node(net, NodeTypes.EMANE): - raise Exception("Xen PVM doesn't yet support Emane nets") - - # ifindex = self.newtuntap(ifindex = ifindex, ifname = ifname, - # net = net) - # # TUN/TAP is not ready for addressing yet; the device may - # # take some time to appear, and installing it into a - # # namespace after it has been bound removes addressing; - # # save addresses with the interface now - # self.attachnet(ifindex, net) - # netif = self.netif(ifindex) - # netif.sethwaddr(hwaddr) - # for addr in maketuple(addrlist): - # netif.addaddr(addr) - # return ifindex - else: - ifindex = self.newveth(ifindex=ifindex, ifname=ifname, - net=net, hwaddr=hwaddr) - if net is not None: - self.attachnet(ifindex, net) - - rulefile = os.path.join(self.getconfigitem("mount_path"), - self.etcdir, - "udev/rules.d/70-persistent-net.rules") - f = self.openpausednodefile(rulefile, "a") - f.write( - "\n# Xen PVM virtual interface #%s %s with MAC address %s\n" % (ifindex, self.ifname(ifindex), hwaddr)) - # Using MAC address as we"re now loading PVM net driver "early" - # OLD: Would like to use MAC address, but udev isn"t working with paravirtualized NICs. Perhaps the "set hw address" isn"t triggering a rescan. - f.write( - 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", KERNEL=="eth*", NAME="%s"\n' % ( - hwaddr, self.ifname(ifindex))) - # f.write("SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", DEVPATH=="/devices/vif-%s/?*", KERNEL=="eth*", NAME="%s"\n" % (ifindex, self.ifname(ifindex))) - f.close() - - if hwaddr: - self.sethwaddr(ifindex, hwaddr) - for addr in utils.make_tuple(addrlist): - self.addaddr(ifindex, addr) - # self.ifup(ifindex) - return ifindex - finally: - self.lock.release() - - def connectnode(self, ifname, othernode, otherifname): - logger.warn("XEN PVM connectnode() called") - - # tmplen = 8 - # tmp1 = "tmp." + "".join([random.choice(string.ascii_lowercase) - # for x in xrange(tmplen)]) - # tmp2 = "tmp." + "".join([random.choice(string.ascii_lowercase) - # for x in xrange(tmplen)]) - # check_call([IP_BIN, "link", "add", "name", tmp1, - # "type", "veth", "peer", "name", tmp2]) - # - # check_call([IP_BIN, "link", "set", tmp1, "netns", str(self.pid)]) - # self.cmd([IP_BIN, "link", "set", tmp1, "name", ifname]) - # self.addnetif(PyCoreNetIf(self, ifname), self.newifindex()) - # - # check_call([IP_BIN, "link", "set", tmp2, "netns", str(othernode.pid)]) - # othernode.cmd([IP_BIN, "link", "set", tmp2, "name", otherifname]) - # othernode.addnetif(PyCoreNetIf(othernode, otherifname), - # othernode.newifindex()) - - def addfile(self, srcname, filename, mode=0644): - self.lock.acquire() - if not self.up: - self.lock.release() - raise Exception("Can't access VM file as VM disk isn't ready") - - if self.booted: - self.lock.release() - raise Exception("Can't access VM file as VM is already running") - - if filename in self.files_to_ignore: - # self.warn("XEN PVM addfile(filename=%s) ignored" % [filename]) - return - - if filename in self.files_redirection: - redirection_filename = self.files_redirection[filename] - logger.warn("XEN PVM addfile(filename=%s) redirected to %s", filename, redirection_filename) - filename = redirection_filename - - try: - fin = open(srcname, "r") - contents = fin.read() - fin.close() - - fout = self.openpausednodefile(filename, "w") - fout.write(contents) - os.chmod(fout.name, mode) - fout.close() - logger.info("created nodefile: %s; mode: 0%o", fout.name, mode) - finally: - self.lock.release() - - logger.warn("XEN PVM addfile(filename=%s) called", filename) - - # shcmd = "mkdir -p $(dirname "%s") && mv "%s" "%s" && sync" % \ - # (filename, srcname, filename) - # self.shcmd(shcmd) - - def unmount_all(self, path): - """ - Namespaces inherit the host mounts, so we need to ensure that all - namespaces have unmounted our temporary mount area so that the - kpartx command will succeed. - """ - # Session.bootnodes() already has self.session._objslock - for o in self.session.objects.itervalues(): - if not isinstance(o, LxcNode): - continue - o.umount(path) diff --git a/daemon/core/xen/xenconfig.py b/daemon/core/xen/xenconfig.py deleted file mode 100644 index 42e6e842..00000000 --- a/daemon/core/xen/xenconfig.py +++ /dev/null @@ -1,301 +0,0 @@ -""" -xenconfig.py: Implementation of the XenConfigManager class for managing -configurable items for XenNodes. - -Configuration for a XenNode is available at these three levels: -Global config: XenConfigManager.configs[0] = (type="xen", values) - Nodes of this machine type have this config. These are the default values. - XenConfigManager.default_config comes from defaults + xen.conf -Node type config: XenConfigManager.configs[0] = (type="mytype", values) - All nodes of this type have this config. -Node-specific config: XenConfigManager.configs[nodenumber] = (type, values) - The node having this specific number has this config. -""" - -import ConfigParser -import os -import string - -from core import constants -from core import logger -from core.api import coreapi -from core.conf import Configurable -from core.conf import ConfigurableManager -from core.enumerations import ConfigDataTypes -from core.enumerations import ConfigFlags -from core.enumerations import ConfigTlvs -from core.enumerations import RegisterTlvs - - -class XenConfigManager(ConfigurableManager): - """ - Xen controller object. Lives in a Session instance and is used for - building Xen profiles. - """ - name = "xen" - config_type = RegisterTlvs.EMULATION_SERVER.value - - def __init__(self, session): - """ - Creates a XenConfigManager instance. - - :param core.session.Session session: session this manager is tied to - :return: nothing - """ - ConfigurableManager.__init__(self) - self.default_config = XenDefaultConfig(session, object_id=None) - self.loadconfigfile() - - def setconfig(self, nodenum, conftype, values): - """ - Add configuration values for a node to a dictionary; values are - usually received from a Configuration Message, and may refer to a - node for which no object exists yet - - :param int nodenum: node id to configure - :param str conftype: configuration type - :param tuple values: values to configure - :return: None - """ - # used for storing the global default config - if nodenum is None: - nodenum = 0 - return ConfigurableManager.setconfig(self, nodenum, conftype, values) - - def getconfig(self, nodenum, conftype, defaultvalues): - """ - Get configuration values for a node; if the values don"t exist in - our dictionary then return the default values supplied; if conftype - is None then we return a match on any conftype. - - :param int nodenum: node id to configure - :param str conftype: configuration type - :param tuple defaultvalues: default values to return - :return: configuration for node and config type - :rtype: tuple - """ - # used for storing the global default config - if nodenum is None: - nodenum = 0 - return ConfigurableManager.getconfig(self, nodenum, conftype, defaultvalues) - - def clearconfig(self, nodenum): - """ - Remove configuration values for a node - - :param int nodenum: node id to clear config - :return: nothing - """ - ConfigurableManager.clearconfig(self, nodenum) - if 0 in self.configs: - self.configs.pop(0) - - def configure(self, session, config_data): - """ - Handle configuration messages for global Xen config. - - :param core.conf.ConfigData config_data: configuration data for carrying out a configuration - """ - return self.default_config.configure(self, config_data) - - def loadconfigfile(self, filename=None): - """ - Load defaults from the /etc/core/xen.conf file into dict object. - - :param str filename: file name of configuration to load - :return: nothing - """ - if filename is None: - filename = os.path.join(constants.CORE_CONF_DIR, "xen.conf") - cfg = ConfigParser.SafeConfigParser() - if filename not in cfg.read(filename): - logger.warn("unable to read Xen config file: %s", filename) - return - section = "xen" - if not cfg.has_section(section): - logger.warn("%s is missing a xen section!", filename) - return - self.configfile = dict(cfg.items(section)) - # populate default config items from config file entries - vals = list(self.default_config.getdefaultvalues()) - names = self.default_config.getnames() - for i in range(len(names)): - if names[i] in self.configfile: - vals[i] = self.configfile[names[i]] - # this sets XenConfigManager.configs[0] = (type="xen", vals) - self.setconfig(None, self.default_config.name, vals) - - def getconfigitem(self, name, model=None, node=None, value=None): - """ - Get a config item of the given name, first looking for node-specific - configuration, then model specific, and finally global defaults. - If a value is supplied, it will override any stored config. - - :param str name: name of config item to get - :param model: model config to get - :param node: node config to get - :param value: value to override stored config, if provided - :return: nothing - """ - if value is not None: - return value - n = None - if node: - n = node.objid - (t, v) = self.getconfig(nodenum=n, conftype=model, defaultvalues=None) - if n is not None and v is None: - # get item from default config for the node type - (t, v) = self.getconfig(nodenum=None, conftype=model, defaultvalues=None) - if v is None: - # get item from default config for the machine type - (t, v) = self.getconfig(nodenum=None, conftype=self.default_config.name, defaultvalues=None) - - confignames = self.default_config.getnames() - if v and name in confignames: - i = confignames.index(name) - return v[i] - else: - # name may only exist in config file - if name in self.configfile: - return self.configfile[name] - else: - # logger.warn("missing config item "%s"" % name) - return None - - -class XenConfig(Configurable): - """ - Manage Xen configuration profiles. - """ - - @classmethod - def configure(cls, xen, config_data): - """ - Handle configuration messages for setting up a model. - Similar to Configurable.configure(), but considers opaque data - for indicating node types. - - :param xen: xen instance to configure - :param core.conf.ConfigData config_data: configuration data for carrying out a configuration - """ - reply = None - node_id = config_data.node - object_name = config_data.object - config_type = config_data.type - opaque = config_data.opaque - values_str = config_data.data_values - - nodetype = object_name - if opaque is not None: - opaque_items = opaque.split(":") - if len(opaque_items) != 2: - logger.warn("xen config: invalid opaque data in conf message") - return None - nodetype = opaque_items[1] - - logger.info("received configure message for %s", nodetype) - if config_type == ConfigFlags.REQUEST.value: - logger.info("replying to configure request for %s " % nodetype) - # when object name is "all", the reply to this request may be None - # if this node has not been configured for this model; otherwise we - # reply with the defaults for this model - if object_name == "all": - typeflags = ConfigFlags.UPDATE.value - else: - typeflags = ConfigFlags.NONE.value - values = xen.getconfig(node_id, nodetype, defaultvalues=None)[1] - if values is None: - # get defaults from default "xen" config which includes - # settings from both cls._confdefaultvalues and xen.conf - defaults = cls.getdefaultvalues() - values = xen.getconfig(node_id, cls.name, defaults)[1] - if values is None: - return None - # reply with config options - if node_id is None: - node_id = 0 - reply = cls.config_data(0, node_id, typeflags, nodetype, values) - elif config_type == ConfigFlags.RESET.value: - if object_name == "all": - xen.clearconfig(node_id) - # elif conftype == coreapi.CONF_TYPE_FLAGS_UPDATE: - else: - # store the configuration values for later use, when the XenNode - # object has been created - if object_name is None: - logger.info("no configuration object for node %s" % node_id) - return None - if values_str is None: - # use default or preconfigured values - defaults = cls.getdefaultvalues() - values = xen.getconfig(node_id, cls.name, defaults)[1] - else: - # use new values supplied from the conf message - values = values_str.split("|") - xen.setconfig(node_id, nodetype, values) - - return reply - - @classmethod - def config_data(cls, flags, node_id, type_flags, nodetype, values): - """ - Convert this class to a Config API message. Some TLVs are defined - by the class, but node number, conf type flags, and values must - be passed in. - - :param int flags: configuration flags - :param int node_id: node id - :param int type_flags: type flags - :param int nodetype: node type - :param tuple values: values - :return: configuration message - """ - values_str = string.join(values, "|") - tlvdata = "" - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.NODE.value, node_id) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.OBJECT.value, cls.name) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.TYPE.value, type_flags) - datatypes = tuple(map(lambda x: x[1], cls.config_matrix)) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.DATA_TYPES.value, datatypes) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.VALUES.value, values_str) - captions = reduce(lambda a, b: a + "|" + b, map(lambda x: x[4], cls.config_matrix)) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.CAPTIONS, captions) - possiblevals = reduce(lambda a, b: a + "|" + b, map(lambda x: x[3], cls.config_matrix)) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.POSSIBLE_VALUES.value, possiblevals) - if cls.bitmap is not None: - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.BITMAP.value, cls.bitmap) - if cls.config_groups is not None: - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.GROUPS.value, cls.config_groups) - opaque = "%s:%s" % (cls.name, nodetype) - tlvdata += coreapi.CoreConfigTlv.pack(ConfigTlvs.OPAQUE.value, opaque) - msg = coreapi.CoreConfMessage.pack(flags, tlvdata) - return msg - - -class XenDefaultConfig(XenConfig): - """ - Global default Xen configuration options. - """ - name = "xen" - # Configuration items: - # ("name", "type", "default", "possible-value-list", "caption") - config_matrix = [ - ("ram_size", ConfigDataTypes.STRING.value, "256", "", - "ram size (MB)"), - ("disk_size", ConfigDataTypes.STRING.value, "256M", "", - "disk size (use K/M/G suffix)"), - ("iso_file", ConfigDataTypes.STRING.value, "", "", - "iso file"), - ("mount_path", ConfigDataTypes.STRING.value, "", "", - "mount path"), - ("etc_path", ConfigDataTypes.STRING.value, "", "", - "etc path"), - ("persist_tar_iso", ConfigDataTypes.STRING.value, "", "", - "iso persist tar file"), - ("persist_tar", ConfigDataTypes.STRING.value, "", "", - "persist tar file"), - ("root_password", ConfigDataTypes.STRING.value, "password", "", - "root password"), - ] - - config_groups = "domU properties:1-%d" % len(config_matrix) diff --git a/daemon/core/xml/xmlparser0.py b/daemon/core/xml/xmlparser0.py index c0850d9c..936c7b6f 100644 --- a/daemon/core/xml/xmlparser0.py +++ b/daemon/core/xml/xmlparser0.py @@ -202,8 +202,6 @@ class CoreDocumentParser0(object): mgr = None self.parsenetem(model, obj, kvs) - elif name[:3] == "xen": - mgr = self.session.xen # TODO: assign other config managers here if mgr: mgr.setconfig_keyvalues(nodenum, name, kvs) diff --git a/daemon/core/xml/xmlparser1.py b/daemon/core/xml/xmlparser1.py index b73bbb60..0ee96cd6 100644 --- a/daemon/core/xml/xmlparser1.py +++ b/daemon/core/xml/xmlparser1.py @@ -204,8 +204,6 @@ class CoreDocumentParser1(object): mgr = self.session.mobility elif model_name.startswith('emane'): mgr = self.session.emane - elif model_name.startswith('xen'): - mgr = self.session.xen else: # TODO: any other config managers? raise NotImplementedError @@ -685,8 +683,6 @@ class CoreDocumentParser1(object): 'host': 'host.gif', 'PC': 'pc.gif', 'mdr': 'mdr.gif', - # 'prouter': 'router_green.gif', - # 'xen': 'xen.gif' } icon_set = False for child in xmlutils.iter_children_with_name(element, 'CORE:presentation'): diff --git a/daemon/data/xen.conf b/daemon/data/xen.conf deleted file mode 100644 index 5077ccc9..00000000 --- a/daemon/data/xen.conf +++ /dev/null @@ -1,35 +0,0 @@ -# Configuration file for CORE Xen support -### Xen configuration options ### -[xen] - -### The following three configuration options *must* be specified in this -### system-wide configuration file. -# LVM volume group name for creating new volumes -vg_name = domU -# directory containing an RSA SSH host key and authorized_keys file to use -# within the VM -ssh_key_path = /opt/core-xen/ssh -# extra arguments to pass via 'extra=' option to 'xm create' -xm_create_extra = console=hvc0 rtr_boot=/dev/xvda rtr_boot_fstype=iso9660 rtr_root=/boot/root.img rtr_persist=LABEL=persist rtr_swap=LABEL=swap rtr_overlay_limit=500 - -### The remaining configuration options *may* be specified here. -### If not specified here, they *must* be specified in the user (or scenario's) -### nodes.conf file as profile-specific configuration options. -# domU RAM memory size in MB -ram_size = 256 -# domU disk size in MB -disk_size = 256M -# ISO filesystem to mount as read-only -iso_file = /opt/core-xen/iso-files/rtr.iso -# directory used temporarily as moint point for persistent area, under -# /tmp/pycore.nnnnn/nX.conf/ -mount_path = /rtr/persist -# mount_path + this directory where configuration files are located on the VM -etc_path = config/etc -# name of tar file within the iso_file to unpack to mount_path -persist_tar_iso = persist-template.tar -# name of tar file in dom0 that will be unpacked to mount_path prior to boot -# the string '%h' will be replaced with the hostname (e.g. 'n3' for node 3) -persist_tar = /opt/core-xen/rtr-configs/custom-%%h.tar -# root password to set -root_password = password diff --git a/daemon/sbin/core-xen-cleanup b/daemon/sbin/core-xen-cleanup deleted file mode 100755 index 871de8a8..00000000 --- a/daemon/sbin/core-xen-cleanup +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -if [ "z$1" = "z-h" -o "z$1" = "z--help" ]; then - echo "usage: $0 [-d]" - echo -n " Clean up all CORE Xen domUs, bridges, interfaces, " - echo "and session\n directories. Options:" - echo " -h show this help message and exit" - echo " -d also kill the Python daemon" - exit 0 -fi - -if [ `id -u` != 0 ]; then - echo "Permission denied. Re-run this script as root." - exit 1 -fi - -PATH="/sbin:/bin:/usr/sbin:/usr/bin" -export PATH - -if [ "z$1" = "z-d" ]; then - pypids=`pidof python python2` - for p in $pypids; do - grep -q core-daemon /proc/$p/cmdline - if [ $? = 0 ]; then - echo "cleaning up core-daemon process: $p" - kill -9 $p - fi - done -fi - -mount | awk ' - /\/tmp\/pycore\./ { print "umount " $3; system("umount " $3); } -' - -domus=`xm list | awk ' - /^c.*-n.*/ { print $1; }'` -for domu in $domus -do - echo "destroy $domu" - xm destroy $domu -done - -vgs=`vgs | awk '{ print $1; }'` -for vg in $vgs -do - if [ ! -x /dev/$vg ]; then - continue - fi - echo "searching volume group: $vg" - lvs=`ls /dev/$vg/c*-n*- 2> /dev/null` - for lv in $lvs - do - echo "removing volume $lv" - kpartx -d $lv - lvchange -an $lv - lvremove $lv - done -done - -/sbin/ip link show | awk ' - /b\.ctrlnet\.[0-9]+/ {print "removing interface " $2; system("ip link set " $2 " down; brctl delbr " $2); } -' - -ls /sys/class/net | awk ' - /^b\.[0-9]+\.[0-9]+$/ {print "removing interface " $1; system("ip link set " $1 " down; brctl delbr " $1); } -' - - -ebtables -L FORWARD | awk ' - /^-.*b\./ {print "removing ebtables " $0; system("ebtables -D FORWARD " $0); print "removing ebtables chain " $4; system("ebtables -X " $4);} -' - -rm -rf /tmp/pycore* diff --git a/daemon/setup.py b/daemon/setup.py index 552a357c..35769399 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -4,10 +4,9 @@ Defines how CORE will be built for installation. import glob import os - -from setuptools import setup, find_packages from distutils.command.install import install +from setuptools import setup, find_packages _CORE_DIR = "/etc/core" _MAN_DIR = "/usr/local/share/man/man1" @@ -58,15 +57,13 @@ class CustomInstall(install): data_files = [ (_CORE_DIR, [ - "data/core.conf", - "data/xen.conf", + "data/core.conf", "data/logging.conf", ]), (_MAN_DIR, glob_files("../doc/man/**.1")), ] data_files.extend(recursive_files(_SHARE_DIR, "examples")) - setup( name="core", version="5.1", @@ -86,7 +83,6 @@ setup( "sbin/core-daemon", "sbin/core-manage", "sbin/coresendmsg", - "sbin/core-xen-cleanup", ], description="Python components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", diff --git a/doc/install.rst b/doc/install.rst index 3a9346c1..4390e162 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -449,9 +449,6 @@ This causes a separate init script to be installed that is tailored towards SUSE The `zypper` command is used instead of `yum`. -For OpenSUSE/Xen based installations, refer to the `README-Xen` file included -in the CORE source. - The Quagga routing suite is recommended for routing, :ref:`Quagga_Routing_Software` for installation. diff --git a/doc/machine.rst b/doc/machine.rst index 588a383b..61a2e1c4 100644 --- a/doc/machine.rst +++ b/doc/machine.rst @@ -22,9 +22,9 @@ netns The *netns* machine type is the default. This is for nodes that will be backed by Linux network namespaces. See :ref:`Linux` for a brief explanation of -netns. This default machine type is very lightweight, providing a minimum +netns. This default machine type is very lightweight, providing a minimum amount of -virtualization in order to emulate a network. +virtualization in order to emulate a network. Another reason this is designated as the default machine type is because this virtualization technology typically requires no changes to the kernel; it is available out-of-the-box @@ -54,7 +54,7 @@ isolated or virtualized environment, but directly on the operating system. Physical nodes must be assigned to servers, the same way nodes are assigned to emulation servers with :ref:`Distributed_Emulation`. The list of available physical nodes currently shares the same dialog box -and list as the emulation servers, accessed using the *Emulation Servers...* +and list as the emulation servers, accessed using the *Emulation Servers...* entry from the *Session* menu. .. index:: GRE tunnels with physical nodes @@ -65,27 +65,7 @@ is drawn to indicate network tunneling. A GRE tunneling interface will be created on the physical node and used to tunnel traffic to and from the emulated world. -Double-clicking on a physical node during runtime +Double-clicking on a physical node during runtime opens a terminal with an SSH shell to that node. Users should configure public-key SSH login as done with emulation servers. - -.. _xen: - -xen -=== - -.. index:: xen machine type - -The *xen* machine type is an experimental new type in CORE for managing -Xen domUs from within CORE. After further development, -it may be documented here. - -Current limitations include only supporting ISO-based filesystems, and lack -of integration with node services, EMANE, and possibly other features of CORE. - -There is a :file:`README-Xen` file available in the CORE source that contains -further instructions for setting up Xen-based nodes. - - - diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 5f688b2b..f76eee84 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -12,7 +12,7 @@ if WANT_GUI endif if WANT_DAEMON DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 coresendmsg.1 \ - core-cleanup.1 core-xen-cleanup.1 core-manage.1 + core-cleanup.1 core-manage.1 endif man_MANS = $(GUI_MANS) $(DAEMON_MANS) @@ -25,7 +25,6 @@ generate-mans: $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new - $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-xen-cleanup -o core-xen-cleanup.1.new $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-manage -o core-manage.1.new .PHONY: diff diff --git a/doc/man/core-cleanup.1 b/doc/man/core-cleanup.1 index a14928ef..e4fe4eb5 100644 --- a/doc/man/core-cleanup.1 +++ b/doc/man/core-cleanup.1 @@ -20,7 +20,6 @@ remove the core-daemon.log file .BR core-gui(1), .BR core-daemon(1), .BR coresendmsg(1), -.BR core-xen-cleanup(1), .BR vcmd(1), .BR vnoded(1) .SH BUGS diff --git a/doc/man/core-xen-cleanup.1 b/doc/man/core-xen-cleanup.1 deleted file mode 100644 index 98d74cc0..00000000 --- a/doc/man/core-xen-cleanup.1 +++ /dev/null @@ -1,28 +0,0 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.40.4. -.TH CORE-XEN-CLEANUP "1" "2014-08-06" "CORE-XEN-CLEANUP" "User Commands" -.SH NAME -core-xen-cleanup \- clean-up script for CORE Xen domUs -.SH DESCRIPTION -usage: core\-xen\-cleanup [\-d] -.IP -Clean up all CORE Xen domUs, bridges, interfaces, and session -directories. Options: -.TP -\fB\-h\fR -show this help message and exit -.TP -\fB\-d\fR -also kill the Python daemon -.SH "SEE ALSO" -.BR core-gui(1), -.BR core-daemon(1), -.BR coresendmsg(1), -.BR core-cleanup(1), -.BR vcmd(1), -.BR vnoded(1) -.SH BUGS -Warning! This script will remove logical volumes that match the name "/dev/vg*/c*-n*-" on all volume groups. Use with care. -Report bugs to -.BI core-dev@pf.itd.nrl.navy.mil. - - diff --git a/doc/usage.rst b/doc/usage.rst index 0312312f..fb16e747 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -1436,7 +1436,6 @@ Default Services and Node Types Here are the default node types and their services: -.. index:: Xen .. index:: physical nodes * *router* - zebra, OSFPv2, OSPFv3, and IPForward services for IGP @@ -1450,10 +1449,6 @@ Here are the default node types and their services: * *prouter* - a physical router, having the same default services as the *router* node type; for incorporating Linux testbed machines into an emulation, the :ref:`Machine_Types` is set to :ref:`physical`. -* *xen* - a Xen-based router, having the same default services as the - *router* node type; for incorporating Xen domUs into an emulation, the - :ref:`Machine_Types` is set to :ref:`xen`, and different *profiles* are - available. Configuration files can be automatically generated by each service. For example, CORE automatically generates routing protocol configuration for the diff --git a/gui/api.tcl b/gui/api.tcl index 89b02605..34658431 100644 --- a/gui/api.tcl +++ b/gui/api.tcl @@ -30,7 +30,7 @@ array set g_execRequests { shell "" observer "" } # for a simulator, uncomment this line or cut/paste into debugger: # set XSCALE 4.0; set YSCALE 4.0; set XOFFSET 1800; set YOFFSET 300 -array set nodetypes { 0 def 1 phys 2 xen 3 tbd 4 lanswitch 5 hub \ +array set nodetypes { 0 def 1 phys 2 tbd 3 tbd 4 lanswitch 5 hub \ 6 wlan 7 rj45 8 tunnel 9 ktunnel 10 emane } array set regtypes { wl 1 mob 2 util 3 exec 4 gui 5 emul 6 } @@ -470,7 +470,7 @@ proc apiNodeCreate { node vals_ref } { set nodetype $nodetypes($vals(type)) set nodename $vals(name) if { $nodetype == "emane" } { set nodetype "wlan" } ;# special case - EMANE - if { $nodetype == "def" || $nodetype == "xen" } { set nodetype "router" } + if { $nodetype == "def" } { set nodetype "router" } newNode [list $nodetype $node] ;# use node number supplied from API message setNodeName $node $nodename if { $vals(canv) == "" } { @@ -509,7 +509,7 @@ proc apiNodeCreate { node vals_ref } { set model $vals(model) if { $model != "" && $vals(type) < 4} { - # set model only for (0 def 1 phys 2 xen 3 tbd) 4 lanswitch + # set model only for (0 def 1 phys 2 tbd 3 tbd) 4 lanswitch setNodeModel $node $model if { [lsearch -exact [getNodeTypeNames] $model] == -1 } { puts "warning: unknown node type '$model' in Node message!" @@ -2920,7 +2920,6 @@ proc getNodeTypeAPI { node } { jail { return 0x0 } OVS { return 0x0 } physical { return 0x1 } - xen { return 0x2 } tbd { return 0x3 } lanswitch { return 0x4 } hub { return 0x5 } diff --git a/gui/configs/sample10-kitchen-sink.imn b/gui/configs/sample10-kitchen-sink.imn index d5463952..dacee547 100644 --- a/gui/configs/sample10-kitchen-sink.imn +++ b/gui/configs/sample10-kitchen-sink.imn @@ -2,7 +2,7 @@ comments { Kitchen Sink ============ -Contains every type of node available in CORE, except for the Xen and physical (prouter) +Contains every type of node available in CORE, except for physical (prouter) machine types, and nodes distributed on other emulation servers. To get the RJ45 node to work, a test0 interface should first be created like this: diff --git a/gui/core-bsd-cleanup.sh b/gui/core-bsd-cleanup.sh deleted file mode 100755 index a73c6daa..00000000 --- a/gui/core-bsd-cleanup.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -# -# cleanup.sh -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# Removes leftover netgraph nodes and vimages from an emulation that -# did not exit properly. -# - -ngnodes="pipe eiface hub switch wlan" -vimages=`vimage -l | fgrep -v " " | cut -d: -f 1 | sed s/\"//g` - -# shutdown netgraph nodes -for ngn in $ngnodes -do - nodes=`ngctl list | grep $ngn | awk '{print $2}'` - for n in $nodes - do - echo ngctl shutdown $n: - ngctl shutdown $n: - done -done - -# kills processes and remove vimages -for vimage in $vimages -do - procs=`vimage $vimage ps x | awk '{print $1}'` - for proc in $procs - do - if [ $proc != "PID" ] - then - echo vimage $vimage kill $proc - vimage $vimage kill $proc - fi - done - loopback=`vimage $vimage ifconfig -a | head -n 1 | awk '{split($1,a,":"); print a[1]}'` - if [ "$loopback" != "" ] - then - addrs=`ifconfig $loopback | grep inet | awk '{print $2}'` - for addr in $addrs - do - echo vimage $vimage ifconfig $loopback $addr -alias - vimage $vimage ifconfig $loopback $addr -alias - if [ $? != 0 ] - then - vimage $vimage ifconfig $loopback inet6 $addr -alias - fi - done - echo vimage $vimage ifconfig $loopback down - vimage $vimage ifconfig $loopback down - fi - vimage $vimage kill -9 -1 2> /dev/null - echo vimage -d $vimage - vimage -d $vimage -done - -# clean up temporary area -rm -rf /tmp/pycore.* diff --git a/gui/icons/Makefile.am b/gui/icons/Makefile.am index f4ceea8e..dc2b2e93 100644 --- a/gui/icons/Makefile.am +++ b/gui/icons/Makefile.am @@ -35,7 +35,6 @@ TINY_ICONS = tiny/button.play.gif \ tiny/folder.gif \ tiny/cel.gif \ tiny/fileopen.gif \ - tiny/xen.gif \ tiny/plot.gif NORM_ICONS = normal/gps-diagram.xbm \ @@ -53,8 +52,7 @@ NORM_ICONS = normal/gps-diagram.xbm \ normal/document-properties.gif \ normal/thumb-unknown.gif \ normal/router_purple.gif normal/router_yellow.gif \ - normal/ap.gif normal/mdr.gif \ - normal/xen.gif + normal/ap.gif normal/mdr.gif SVG_ICONS = svg/ap.svg \ svg/cel.svg \ @@ -71,8 +69,7 @@ SVG_ICONS = svg/ap.svg \ svg/router_yellow.svg \ svg/start.svg \ svg/tunnel.svg \ - svg/vlan.svg \ - svg/xen.svg + svg/vlan.svg # # Icon files (/usr/local/share/core/icons/[tiny,normal,svg]) diff --git a/gui/icons/normal/xen.gif b/gui/icons/normal/xen.gif deleted file mode 100644 index 0b8e8e3892a4c0089f16e3e6f931a4206e2ab5bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1684 zcmeH{`#aNn0LMQT?Gl>%N@heZaWbldZZkGtx0-Z9F3%=vB-fE!HM6mn%jRw_Ll~oj zE~J#rT;@^-$8k;_C2>^9Lzk!IJkF_q;{0^p|G@is-p}jxc6B4$JJ4(Z4txecNl6Kg zK%!LD)X^GRI(k~V7>vFFcDJdqnZ=&HKkPf`h<7+_f6T>!NHXwBJ>VOS^S=6{UkuUH z8#?I=`S`g7(7l5~&YZtUrp0@NUkSbt7ZwpgkBkh7iVI_;gfo)Dldc+{Vww7L%mTUQ z!Mwe+9P2Q_K6(K@qG*3~*}=GShr}w!B$4B#YR9DNi)n19%XPh&ecy>-wR^H`n zx#u|f(HsFIlh5E4r{)wT<_It6mZs)cl9&w;OYF>U_TV&;d96OYn`GWCx18H&^4dHF zonD0xPL%cp32u3p^`sTogcRM4thmppedJTo`&0G6=~{(<{YXILlfdS&lm^+ACV6@$ zm&LutDyqsXyTPjxUl%nB>Ra>0?IkUprLFhM+q*Mv4rH|{vTqNI?nnilj|;ngDS0p^ zd^l0t)!*=FsIg~6B%74GMe|K~qnz-V1r2>>>*`riEA34quHNaQZ4 zt(u^R2*8D=x6!s`pm&oap>|^uM>hzXhRn~BGu50@CKYQ`5@vT0l>y}Cv7@{~X171D($>AIut^cm9cxIgqG&hqslC}Y!a^D^ zAwrHjTP|_)F*79==#dWIA$C~o&^tOzJ!04Q%Kf@Q&*{P?*g&2US!lmLYpl?+4`a2M zEVFElhFNx&-p=PeXK=n%_TeF+5V|x9S&vvRF&^C$BYf7*nm|p}oF?X)XcNtP4U?xw z!`)q%hVh*rq{*6W+66r~gaby#>OY=6r4ih9x^+rRwvxiX+2Xiy7H@xsNC8`0H`uQ_U7tsRp)8<#1p(N8LZ1eOph431@q?anR7P#r$pEW>WBQ*w*B}wO&=PwN;{iO^W3rRt!s(NUlt_ z)$$WwG`&WehsL;KRlzC|dl>Ku*p$$vrB*5Gx@G$S_R!nP5?hbG*l1O>RBur@{&wd+ zx|Ac1>y~mbSSC$kIHNm)y_Gm1sqgao1f()7wOIvh!2za9YMRowH&zBr-Hor~aGZae zc$NAe^>;wQ4YXX42<~AH$4^a4PhAf8F^T8oq|ESx^HYB+W(A(fx7p=#f zKDE{MtzcW)hAS@P&8U85Vs1 - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - Xen - - diff --git a/gui/icons/tiny/xen.gif b/gui/icons/tiny/xen.gif deleted file mode 100644 index ccba644ec26b47a1ce0b325368219db8f8f7cd0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 905 zcmV;419tpJNk%w1VIcq(0QLX?0RaIF4Gs?x5*HgBA0#FuDJv;2F)T7RE;TqaIz2Z( zLpwu9Jw{3$PJ13veIQbQL{3vlR9Q}0UQ%6SRA6OWXl`F^bZK~hB2|JVS%oKEh$vo) zD`Sp6Yl<#sk}qhJF>94FZJ0H2n>co!Ie4Ercc40Wpg(`8Lui6-euP4Pq(6YCWrLS$ zhnr}MnR<(qb&sBYlAT6@rbvRPLWHbJgQ!!Atyqn(MvAgpkFZOTw@sA0U6HbWmZM{q zwP%^PY@E7vqrOv|!&RWhSEI>Urp#NZ&U&W7eW=5OnWc)Jr-YrUiJqy3qOOdgtDdE& zl%uJJq_Bvjv67~+ma4OyuC|%3xtp=Op{uN=uCaow#f-Ddl)2BByU>}u(WJb`sK3ms z!_T9{)~&|TugKJ@%G$BY*0avsx6s|V(cZSw;Jnr2zS-u)+Ty|8>cryi&F1gMkGeJmOTwF3dVryJBmEEYA z&x=1@M>RD_KtDV-r<9U)A>k%AKR{)|S~Dg`wrgmnxiUEzL4uhgFKgPY5mSRw5FkkI zY2$HeN1X-^JRB-$Vg?s2KzKBCSE8hiBR?jc5MtzFg9jNxY9c4I4L*-?({0`AwWSQ~+bZ zpkXjo5G~d$FtFyp0>_XePp*8qicbe0w~9kQ@qY*!GuAt0TbXr05C5AOrT)F`V}Pr+-#@QT@X|a zggt~-fFMnR1ZNDuzyuMv2Ok`B&_UlLvVp+D8A^oV1{qGI(FPSvumVLJZD66Gf>>xG f2nZ;|ki?00F~NirPCx<06Hj0fBaBbf5eNV~$l!rL diff --git a/gui/nodes.tcl b/gui/nodes.tcl index 20d8853d..3d54adf0 100644 --- a/gui/nodes.tcl +++ b/gui/nodes.tcl @@ -26,14 +26,12 @@ array set g_node_types_default { 5 {prouter router_green.gif router_green.gif \ {zebra OSPFv2 OSPFv3 IPForward} \ physical {built-in type for physical nodes}} - 6 {xen xen.gif xen.gif {zebra OSPFv2 OSPFv3 IPForward} \ - xen {built-in type for Xen PVM domU router}} 7 {OVS lanswitch.gif lanswitch.gif {DefaultRoute SSH OvsService} OVS {} } } # possible machine types for nodes -set MACHINE_TYPES "netns physical xen OVS" +set MACHINE_TYPES "netns physical OVS" # array populated from nodes.conf file array set g_node_types { } @@ -65,7 +63,7 @@ proc loadNodesConf { } { set line [list $idx $data] } } - + # load into array of nodes if { [catch {array set g_node_types $line} e] } { puts "Error reading $confname line '$node': $e" @@ -86,13 +84,13 @@ proc checkNodeTypes { fatal } { puts "error: missing built-in node type '$name'!" puts "move your ~/.core/nodes.conf file to re-create the defaults" if { $fatal } { - exit + exit } else { return $name } } - + } return "" } @@ -187,7 +185,7 @@ proc getNodeTypeServices { type } { return "" } -# return the machine type (e.g. netns, physical, xen) of the currently selected +# return the machine type (e.g. netns, physical) of the currently selected # node type from the toolbar proc getNodeTypeMachineType { type } { global MACHINE_TYPES g_node_types @@ -211,7 +209,7 @@ proc getNodeTypeProfile { type } { return "" } -# return the machine type (e.g. netns, physical, xen) of the currently selected +# return the machine type (e.g. netns, physical) of the currently selected # node type from the toolbar proc getNodeTypeMachineType { type } { global MACHINE_TYPES g_node_types @@ -269,7 +267,7 @@ proc popupNodeProfileConfig { channel node model types values captions bitmap po global g_node_types set opaque_items [split $opaque :] - if { [llength $opaque_items] != 2 } { + if { [llength $opaque_items] != 2 } { puts "warning: received unexpected opaque data in conf message!" return } @@ -334,7 +332,7 @@ proc popupNodesConfig {} { labelframe $wi.s -borderwidth 0 -text "Node Types" listbox $wi.s.nodes -selectmode single -height 5 -width 15 \ -yscrollcommand "$wi.s.nodes_scroll set" -exportselection 0 - scrollbar $wi.s.nodes_scroll -command "$wi.s.nodes yview" + scrollbar $wi.s.nodes_scroll -command "$wi.s.nodes yview" pack $wi.s.nodes $wi.s.nodes_scroll -fill y -side left pack $wi.s -padx 4 -pady 4 -fill both -side top -expand true @@ -365,9 +363,9 @@ proc popupNodesConfig {} { frame $wi.s.edit -borderwidth 4 frame $wi.s.edit.0 label $wi.s.edit.0.namelab -text "Name" - entry $wi.s.edit.0.name -bg white -width 20 + entry $wi.s.edit.0.name -bg white -width 20 pack $wi.s.edit.0.namelab $wi.s.edit.0.name -side left - + frame $wi.s.edit.1 label $wi.s.edit.1.iconlab -text "Icon" entry $wi.s.edit.1.icon -bg white -width 25 @@ -422,7 +420,7 @@ proc popupNodesConfig {} { nodesConfigSelect $wi "" - # close button + # close button frame $wi.b -borderwidth 0 button $wi.b.close -text "Close" -command "nodesConfigClose $wi" pack $wi.b.close -side right @@ -461,7 +459,7 @@ proc nodesConfigSelect { wi cmd } { set selected_idx [$wi.s.nodes curselection] if { $selected_idx == "" } { return } - + set idx [expr {$selected_idx + 1}] if { ![info exists g_node_types($idx)] } { return } @@ -522,7 +520,7 @@ proc nodesConfigImgDialog { wi ctl size } { if { [string first $dir $f] == 0 } { # chop off default path of $dir set f [string range $f [string length $dir] end] - } + } if { $f != "" } { $ctl delete 0 end $ctl insert 0 $f @@ -581,7 +579,7 @@ proc nodesConfigHelper { wi cmd } { set newdata [lreplace $newdata 0 0 $newname] set newdata [lreplace $newdata 5 5 ""] ;# zero the meta-data array set g_node_types [list $arridx $newdata] - set newsel [expr {$arridx - 1}] + set newsel [expr {$arridx - 1}] } save { nodesConfigSelect $wi save @@ -591,26 +589,26 @@ proc nodesConfigHelper { wi cmd } { } up - down { - if {$cmd == "up" } { + if {$cmd == "up" } { if { $arridx < 2 } { return } - set newidx [expr {$arridx - 1}] - set newsel [expr {$idx - 1}] + set newidx [expr {$arridx - 1}] + set newsel [expr {$idx - 1}] } else { if { $idx >= [expr {[$ctl size] - 1}]} { return } set newidx [expr {$arridx + 1}] - set newsel [expr {$idx + 1}] + set newsel [expr {$idx + 1}] } set newentry [lindex [array get g_node_types $arridx] 1] set oldentry [lindex [array get g_node_types $newidx] 1] if {$oldentry != ""} { - array set g_node_types [list $arridx $oldentry] + array set g_node_types [list $arridx $oldentry] } array set g_node_types [list $newidx $newentry] } } nodesConfigRefreshList $wi - if { $newsel != "" } { + if { $newsel != "" } { $ctl selection clear 0 end $ctl selection set $newsel } @@ -628,12 +626,12 @@ proc nodesConfigServices { wi services_or_profile } { set sock [lindex [getEmulPlugin "*"] 2] # node number 0 is sent, but these services are not associated with a node if { $services_or_profile == "profile" } { - set services_or_profile $g_machine_type ;# address the e.g. "xen" model + set services_or_profile $g_machine_type ;# address the model set opaque "$g_machine_type:$g_node_type_services_hint" } else { set opaque "" } - sendConfRequestMessage $sock -1 $services_or_profile 0x1 -1 $opaque + sendConfRequestMessage $sock -1 $services_or_profile 0x1 -1 $opaque } # helper for when close button is pressed diff --git a/gui/plugins.tcl b/gui/plugins.tcl index 11754100..04376c73 100644 --- a/gui/plugins.tcl +++ b/gui/plugins.tcl @@ -49,7 +49,7 @@ set plugin_img_folder [image create photo -file "$iconpath/folder.gif"] array set g_plugin_button_tooltips { add "add a new plugin" - edit "edit the selected plugin" + edit "edit the selected plugin" del "remove the selected plugin" conn "connect to this plugin" disc "disconnect from this plugin" @@ -78,7 +78,7 @@ proc popupPluginsConfig {} { labelframe $wi.s -borderwidth 0 -text "Plugins" listbox $wi.s.plugins -selectmode single -height 5 -width 50 \ -yscrollcommand "$wi.s.plugins_scroll set" -exportselection 0 - scrollbar $wi.s.plugins_scroll -command "$wi.s.plugins yview" + scrollbar $wi.s.plugins_scroll -command "$wi.s.plugins yview" pack $wi.s.plugins $wi.s.plugins_scroll -fill y -side left pack $wi.s -padx 4 -pady 4 -fill both -side top -expand true @@ -118,7 +118,7 @@ proc popupPluginsConfig {} { bind $wi.s.plugins <> "pluginsConfigSelect $wi" pluginsConfigSelect $wi - # close button + # close button frame $wi.b -borderwidth 0 button $wi.b.save -text "Save" -command "writePluginsConf; destroy $wi" button $wi.b.cancel -text "Cancel" -command "destroy $wi" @@ -216,8 +216,8 @@ proc popupPluginsConfigEdit { parent action } { # proc popupPluginConfigEditApply { wi selected_idx selected_name } { global g_plugins g_plugin_types plugin_config_type plugin_config_autoconn - - # get values from the dialog + + # get values from the dialog set name "\"[string trim [$wi.c.a.name get]]\"" set ip [string trim [$wi.c.b.ip get]] set port [string trim [$wi.c.b.port get]] @@ -243,8 +243,8 @@ proc popupPluginConfigEditApply { wi selected_idx selected_name } { array unset g_plugins "\"$selected_name\"" } } - - # manipulate the g_plugins array + + # manipulate the g_plugins array set plugin_data [list $ip $port $typenum $ac $status $cap $sock] array set g_plugins [list $name $plugin_data] } @@ -335,7 +335,7 @@ proc pluginsConfigSelect { wi } { set buttons_state normal set name "\"[$wi.s.plugins get $selected_idx]\"" } - + # enable or disable the editing/control buttons if { $name == "\"GUI\"" } { # this program is the GUI, you cannot change this connection @@ -420,7 +420,7 @@ proc popupPluginsCapConfig { wlan parent } { set wi .pluginCapConfig catch {destroy $wi} toplevel $wi - wm transient $parent . + wm transient $parent . wm title $wi "Available Plugins" # update dialog @@ -435,7 +435,7 @@ proc popupPluginsCapConfig { wlan parent } { listbox $wi.active.plugins -selectmode single -width 55 -height 5 \ -yscrollcommand "$wi.active.scroll set" -exportselection 0 scrollbar $wi.active.scroll -command "$wi.active.plugins yview" - pack $wi.active.plugins -fill both -side left + pack $wi.active.plugins -fill both -side left pack $wi.active.scroll -fill y -side left pack $wi.active -side top -fill both -expand true -padx 4 -pady 4 @@ -462,7 +462,7 @@ proc popupPluginsCapConfig { wlan parent } { listbox $wi.avail.plugins -selectmode single -width 55 -height 5 \ -yscrollcommand "$wi.avail.scroll set" -exportselection 0 scrollbar $wi.avail.scroll -command "$wi.avail.plugins yview" - pack $wi.avail.plugins -fill both -side left + pack $wi.avail.plugins -fill both -side left pack $wi.avail.scroll -fill y -side left pack $wi.avail -side top -fill both -expand true -padx 4 -pady 4 @@ -472,7 +472,7 @@ proc popupPluginsCapConfig { wlan parent } { "popupPluginsCapConfigHelper $wi up $wlan" # this reads from the existing wlan config - if { $g_cap_in_use == "" } { + if { $g_cap_in_use == "" } { set g_cap_in_use [getCapabilities $wlan "mobmodel"] } @@ -525,25 +525,25 @@ proc popupPluginsCapConfigHelper { wi cmd wlan} { set channel [pluginConnect $plugin connect 1] if { $cap == "location" } { # hack to map location capabilities with canvas size/scale dialog - resizeCanvasPopup + resizeCanvasPopup return } if { $channel != -1 && $channel != "" } { - sendConfRequestMessage $channel $wlan $cap $flags $netid $opaque + sendConfRequestMessage $channel $wlan $cap $flags $netid $opaque } return } else { ;# up/down enable/disable button preseed set capstr [$l get $selected_idx] $l delete $selected_idx $selected_idx $l2 insert end $capstr - $l2 selection set end + $l2 selection set end # put the capabilities from the active list into the g_cap_in_use list # this list will be read in wlanConfigDialogHelper when Apply pressed set g_cap_in_use {} set g_cap_in_use_set 1 foreach capstr [$wi.active.plugins get 0 end] { set cap [string trim [lindex [split $capstr -] 1]] - lappend g_cap_in_use $cap + lappend g_cap_in_use $cap } } } @@ -560,7 +560,7 @@ proc configCap { node models } { set opaque "" ;# unused set channel [pluginConnect $plugin connect 1] if { $channel != -1 && $channel != "" } { - sendConfRequestMessage $channel $node $models $flags $netid $opaque + sendConfRequestMessage $channel $node $models $flags $netid $opaque } } @@ -612,7 +612,6 @@ proc capTitle { cap } { # Session options # EMANE options # EMANE model options, per-WLAN/per-interface -# node profile (Xen machine type) # proc popupCapabilityConfig { channel wlan model types values captions bmp possible_values groups } { global node_list g_node_type_services_hint g_popupcap_keys g_prefs @@ -620,7 +619,7 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib catch {destroy $wi} toplevel $wi set modelname [capTitle $model] - wm transient $wi . + wm transient $wi . wm title $wi "$modelname configuration" array unset g_popupcap_keys ;# hint for supporting key=value w/apply button @@ -656,7 +655,7 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib if { $customcfg != "" } { set cfg [lindex [lindex $customcfg 2] 1] - } else { + } else { set cfg "" } # session options stored in array, not custom-config @@ -676,7 +675,7 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib set value [lindex $kv 1] if { $cfg != "" } { ;# possibly use existing config value - if { $key == "" } { ;# support old "value" format + if { $key == "" } { ;# support old "value" format set value [lindex $cfg $n] } else { set value [getKeyValue $key $cfg $value] @@ -694,7 +693,7 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib set gn [lindex $groupinfo 0] set groupcaption [lindex $groupinfo 1] if { $lastgn != $gn } { - ttk::frame $wi.vals.$gn + ttk::frame $wi.vals.$gn $wi.vals add $wi.vals.$gn -text $groupcaption -underline 0 set lastgn $gn } @@ -889,7 +888,7 @@ proc popupSessionConfig { channel sessionids sessionnames sessionfiles nodecount set wi .popupSessionConfig catch {destroy $wi} toplevel $wi - wm transient $wi . + wm transient $wi . wm title $wi "CORE Sessions" ttk::frame $wi.top @@ -965,7 +964,7 @@ proc popupSessionConfig { channel sessionids sessionnames sessionfiles nodecount grid $wi.btn.new $wi.btn.conn $wi.btn.shut $wi.btn.cancel -padx 4 -pady 4 grid columnconfigure $wi 0 -weight 1 pack $wi.btn -side bottom -fill x - + bind $wi $conn_cmd bind $wi $close_cmd bind $wi.tree <> "sessionConfigSelect $wi {$thumbs}" @@ -1114,7 +1113,7 @@ proc setPluginCapList { plugin caps } { return -1 ;# unknown plugin } set plugin_data $g_plugins($plugin) - set plugin_data [lreplace $plugin_data 5 5 $caps] + set plugin_data [lreplace $plugin_data 5 5 $caps] array set g_plugins [list $plugin $plugin_data] return 0 } @@ -1200,7 +1199,7 @@ proc autoConnectPlugins { } { proc pluginConnect { name cmd retry } { global g_plugins if { $name == "" } { set name \"core-daemon\" } - if { ![info exists g_plugins($name)] } { + if { ![info exists g_plugins($name)] } { puts "pluginConnect error: $name does not exist!" return -1 } @@ -1223,7 +1222,7 @@ proc pluginConnect { name cmd retry } { 1 { ;# CORE API if { $cmd == "toggle" } { if { $snum == 0 } { - set cmd connect + set cmd connect } elseif { $snum == 1 } { set cmd disconnect } @@ -1303,7 +1302,7 @@ proc pluginRefresh { plugin } { # proc pluginChannelClosed { sock } { global g_plugins - set plugin [pluginByChannel $sock] + set plugin [pluginByChannel $sock] if { $plugin == "" } { return } ;# channel not found set plugin_data $g_plugins($plugin) set plugin_data [lreplace $plugin_data 6 6 -1]; # sock = -1 diff --git a/packaging/deb/core-daemon.install.in b/packaging/deb/core-daemon.install.in index 4656c188..8dda2c9c 100644 --- a/packaging/deb/core-daemon.install.in +++ b/packaging/deb/core-daemon.install.in @@ -14,7 +14,6 @@ @datarootdir@/man/man1/core-daemon.1 @datarootdir@/man/man1/coresendmsg.1 @datarootdir@/man/man1/core-cleanup.1 -@datarootdir@/man/man1/core-xen-cleanup.1 @pyprefix@/lib/python2.7/dist-packages /etc/init.d /etc/logrotate.d diff --git a/packaging/rpm/core.spec.in b/packaging/rpm/core.spec.in index a8abe483..90266115 100644 --- a/packaging/rpm/core.spec.in +++ b/packaging/rpm/core.spec.in @@ -147,7 +147,6 @@ fi %{_datadir}/%{name}/icons/normal/thumb-unknown.gif %{_datadir}/%{name}/icons/normal/tunnel.gif %{_datadir}/%{name}/icons/normal/wlan.gif -%{_datadir}/%{name}/icons/normal/xen.gif %dir %{_datadir}/%{name}/icons/svg %{_datadir}/%{name}/icons/svg/ap.svg %{_datadir}/%{name}/icons/svg/cel.svg @@ -165,7 +164,6 @@ fi %{_datadir}/%{name}/icons/svg/start.svg %{_datadir}/%{name}/icons/svg/tunnel.svg %{_datadir}/%{name}/icons/svg/vlan.svg -%{_datadir}/%{name}/icons/svg/xen.svg %dir %{_datadir}/%{name}/icons/tiny %{_datadir}/%{name}/icons/tiny/ap.gif %{_datadir}/%{name}/icons/tiny/arrow.down.gif @@ -219,7 +217,6 @@ fi %{_datadir}/%{name}/icons/tiny/twonode.gif %{_datadir}/%{name}/icons/tiny/view-refresh.gif %{_datadir}/%{name}/icons/tiny/wlan.gif -%{_datadir}/%{name}/icons/tiny/xen.gif @CORE_LIB_DIR@/initgui.tcl @CORE_LIB_DIR@/ipv4.tcl @CORE_LIB_DIR@/ipv6.tcl @@ -259,7 +256,6 @@ fi %files daemon %config @CORE_CONF_DIR@/core.conf %config @CORE_CONF_DIR@/perflogserver.conf -%config @CORE_CONF_DIR@/xen.conf %dir %{_datadir}/%{name} %dir %{_datadir}/%{name}/examples %{_datadir}/%{name}/examples/controlnet_updown @@ -308,7 +304,6 @@ fi %doc %{_mandir}/man1/core-daemon.1.gz %doc %{_mandir}/man1/core-manage.1.gz %doc %{_mandir}/man1/coresendmsg.1.gz -%doc %{_mandir}/man1/core-xen-cleanup.1.gz %doc %{_mandir}/man1/netns.1.gz %doc %{_mandir}/man1/vcmd.1.gz %doc %{_mandir}/man1/vnoded.1.gz @@ -393,15 +388,10 @@ fi %{python_sitelib}/core/services/utility.py* %{python_sitelib}/core/services/xorp.py* %{python_sitelib}/core/session.py* -%dir %{python_sitelib}/core/xen -%{python_sitelib}/core/xen/__init__.py* -%{python_sitelib}/core/xen/xenconfig.py* -%{python_sitelib}/core/xen/xen.py* %{_sbindir}/core-cleanup %{_sbindir}/core-daemon %{_sbindir}/core-manage %{_sbindir}/coresendmsg -%{_sbindir}/core-xen-cleanup %{_sbindir}/netns %{_sbindir}/vcmd %{_sbindir}/vnoded diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 3f6a4f44..4a1cc6ad 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -9,20 +9,15 @@ CLEANFILES = core-daemon -DISTCLEANFILES = Makefile.in xen/Makefile xen/Makefile.in +DISTCLEANFILES = Makefile.in EXTRA_DIST = core-daemon-init.d \ core-daemon.service.in \ core-daemon-rc.d \ - core-daemon-init.d-SUSE \ - xen + core-daemon-init.d-SUSE SUBDIRS = perf -# clean up dirs included by EXTRA_DIST -dist-hook: - rm -rf $(distdir)/xen/.svn - # install startup scripts based on --with-startup=option configure option # init.d (default), systemd, SUSE if WANT_INITD diff --git a/scripts/core-daemon-init.d-SUSE b/scripts/core-daemon-init.d-SUSE index e7a703d9..9b6a4aea 100755 --- a/scripts/core-daemon-init.d-SUSE +++ b/scripts/core-daemon-init.d-SUSE @@ -35,8 +35,8 @@ # ### BEGIN INIT INFO # Provides: core-daemon -# Required-Start: $network $remote_fs xend -# Required-Stop: $network $remote_fs xend +# Required-Start: $network $remote_fs +# Required-Stop: $network $remote_fs # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: core-daemon diff --git a/scripts/xen/Makefile.am b/scripts/xen/Makefile.am deleted file mode 100644 index 7c9ca338..00000000 --- a/scripts/xen/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -# CORE -# (c)2012 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# -# Makefile for installing Xen scripts. -# - -install-exec-hook: - test -d "$(DESTDIR)/etc/init.d" || \ - mkdir -p $(DESTDIR)/etc/init.d - test -d "$(DESTDIR)/etc/xen/scripts" && \ - cp -f linux/scripts/vif-core $(DESTDIR)/etc/xen/scripts - diff --git a/scripts/xen/vif-core b/scripts/xen/vif-core deleted file mode 100755 index 71a8a495..00000000 --- a/scripts/xen/vif-core +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -#============================================================================ -# ${XEN_SCRIPT_DIR}/vif-bridge -# -# Script for configuring a vif in bridged mode. -# The hotplugging system will call this script if it is specified either in -# the device configuration given to Xend, or the default Xend configuration -# in ${XEN_CONFIG_DIR}/xend-config.sxp. If the script is specified in -# neither of those places, then this script is the default. -# -# Usage: -# vif-bridge (add|remove|online|offline) -# -# Environment vars: -# vif vif interface name (required). -# XENBUS_PATH path to this device's details in the XenStore (required). -# -# Read from the store: -# bridge bridge to add the vif to (optional). Defaults to searching for the -# bridge itself. -# ip list of IP networks for the vif, space-separated (optional). -# -# up: -# Enslaves the vif interface to the bridge and adds iptables rules -# for its ip addresses (if any). -# -# down: -# Removes the vif interface from the bridge and removes the iptables -# rules for its ip addresses (if any). -#============================================================================ - -dir=$(dirname "$0") -. "$dir/vif-common.sh" - -case "$command" in - online) - do_without_error ifconfig "$vif" up - ;; - offline) - do_without_error ifconfig "$vif" down - ;; -esac - -log debug "Successful vif-core $command for $vif, bridge $bridge." -if [ "$command" == "online" ] -then - success -fi From 3bfcdac63030d2d9519e5f465b23260615c4626f Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 7 Mar 2018 16:19:01 -0800 Subject: [PATCH 058/152] updated index in gui defined nodes to be in order --- gui/nodes.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/nodes.tcl b/gui/nodes.tcl index 3d54adf0..1ddcbd6d 100644 --- a/gui/nodes.tcl +++ b/gui/nodes.tcl @@ -26,7 +26,7 @@ array set g_node_types_default { 5 {prouter router_green.gif router_green.gif \ {zebra OSPFv2 OSPFv3 IPForward} \ physical {built-in type for physical nodes}} - 7 {OVS lanswitch.gif lanswitch.gif {DefaultRoute SSH OvsService} OVS {} } + 6 {OVS lanswitch.gif lanswitch.gif {DefaultRoute SSH OvsService} OVS {} } } From bffed34a472b51139209a32e64c866f7a713a4b8 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 8 Mar 2018 11:20:26 -0800 Subject: [PATCH 059/152] removed kernel patches and some minor cleanup to documentation in relation --- Makefile.am | 6 +- doc/install.rst | 30 - doc/intro.rst | 3 +- kernel/core-kernel-2.6.38/Makefile | 62 - kernel/core-kernel-2.6.38/README.txt | 9 - kernel/core-kernel-2.6.38/config.core | 1 - .../patches/00-linux-2.6.38.flow-cache.patch | 31 - .../patches/00-linux-2.6.38.ifindex.patch | 52 - .../patches/00-linux-2.6.38.nfnetlink.patch | 1662 ----------------- kernel/core-kernel-3.0/Makefile | 62 - kernel/core-kernel-3.0/README.txt | 9 - kernel/core-kernel-3.0/config.core | 1 - .../patches/00-linux-3.0.flow-cache.patch | 49 - .../patches/00-linux-3.0.ifindex.patch | 51 - .../00-linux-3.0.nfnetlink_queue.patch | 351 ---- .../01-linux-3.0.nfnetlink_queue.patch | 516 ----- kernel/core-kernel-3.2/Makefile | 62 - kernel/core-kernel-3.2/README.txt | 8 - kernel/core-kernel-3.2/config.core | 1 - .../patches/00-linux-3.2.ifindex.patch | 60 - .../00-linux-3.2.nfnetlink_queue.patch | 351 ---- .../01-linux-3.2.nfnetlink_queue.patch | 544 ------ kernel/core-kernel-3.5/Makefile | 70 - kernel/core-kernel-3.5/config.core | 1 - .../core-kernel-3.5/patches/00-ifindex.patch | 60 - .../patches/00-nfnetlink_queue.patch | 351 ---- .../patches/01-nfnetlink_queue.patch | 494 ----- kernel/core-kernel-3.8/Makefile | 70 - kernel/core-kernel-3.8/config.core | 1 - .../core-kernel-3.8/patches/00-ifindex.patch | 29 - .../patches/00-nfnetlink_queue.patch | 307 --- .../patches/01-nfnetlink_queue.patch | 475 ----- 32 files changed, 2 insertions(+), 5777 deletions(-) delete mode 100644 kernel/core-kernel-2.6.38/Makefile delete mode 100644 kernel/core-kernel-2.6.38/README.txt delete mode 100644 kernel/core-kernel-2.6.38/config.core delete mode 100644 kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.flow-cache.patch delete mode 100644 kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.ifindex.patch delete mode 100644 kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch delete mode 100644 kernel/core-kernel-3.0/Makefile delete mode 100644 kernel/core-kernel-3.0/README.txt delete mode 100644 kernel/core-kernel-3.0/config.core delete mode 100644 kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch delete mode 100644 kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch delete mode 100644 kernel/core-kernel-3.0/patches/00-linux-3.0.nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.0/patches/01-linux-3.0.nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.2/Makefile delete mode 100644 kernel/core-kernel-3.2/README.txt delete mode 100644 kernel/core-kernel-3.2/config.core delete mode 100644 kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch delete mode 100644 kernel/core-kernel-3.2/patches/00-linux-3.2.nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.2/patches/01-linux-3.2.nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.5/Makefile delete mode 100644 kernel/core-kernel-3.5/config.core delete mode 100644 kernel/core-kernel-3.5/patches/00-ifindex.patch delete mode 100644 kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.8/Makefile delete mode 100644 kernel/core-kernel-3.8/config.core delete mode 100644 kernel/core-kernel-3.8/patches/00-ifindex.patch delete mode 100644 kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch delete mode 100644 kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch diff --git a/Makefile.am b/Makefile.am index 23ec7183..4fa80ead 100644 --- a/Makefile.am +++ b/Makefile.am @@ -28,7 +28,7 @@ ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball EXTRA_DIST = bootstrap.sh LICENSE \ README.md ASSIGNMENT_OF_COPYRIGHT.pdf \ - Changelog kernel \ + Changelog \ python-prefix.py revision.sh \ .version .version.date \ packaging/deb/compat \ @@ -51,10 +51,6 @@ MAINTAINERCLEANFILES = \ .version \ .version.date -# don't include svn dirs in source tarball -dist-hook: - rm -rf `find $(distdir)/kernel -name .svn` - # build a source RPM .PHONY: rpm rpm: dist diff --git a/doc/install.rst b/doc/install.rst index 4390e162..51f9d9ee 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -119,36 +119,6 @@ Installing from Packages on Ubuntu First install the Ubuntu |UBUNTUVERSION| operating system. -.. tip:: - With Debian or Ubuntu 14.04 (trusty) and newer, you can simply install - CORE using the following command:: - - sudo apt-get install core-network - - Proceed to the "Install Quagga for routing." line below to install Quagga. - The other commands shown in this section apply to binary packages - downloaded from the CORE website instead of using the Debian/Ubuntu - repositories. - - -.. NOTE:: - Linux package managers (e.g. `software-center`, `yum`) will take care - of installing the dependencies for you when you use the CORE packages. - You do not need to manually use these installation lines. You do need - to select which Quagga package to use. - - -* **Optional:** install the prerequisite packages (otherwise skip this - step and have the package manager install them for you.) - - .. parsed-literal:: - - # make sure the system is up to date; you can also use synaptic or - # update-manager instead of apt-get update/dist-upgrade - sudo apt-get update - sudo apt-get dist-upgrade - sudo apt-get install |APTDEPS| |APTDEPS2| - * Install Quagga for routing. If you plan on working with wireless networks, we recommend installing diff --git a/doc/intro.rst b/doc/intro.rst index 4274f2f6..f9888b65 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -111,8 +111,7 @@ Linux network namespaces (also known as netns, LXC, or `Linux containers `_) is the primary virtualization technique used by CORE. LXC has been part of the mainline Linux kernel since 2.6.24. Recent Linux distributions such as Fedora and Ubuntu have -namespaces-enabled kernels out of the box, so the kernel does not need to be -patched or recompiled. +namespaces-enabled kernels out of the box. A namespace is created using the ``clone()`` system call. Each namespace has its own process environment and private network stack. Network namespaces share the same filesystem in CORE. diff --git a/kernel/core-kernel-2.6.38/Makefile b/kernel/core-kernel-2.6.38/Makefile deleted file mode 100644 index 393c83b5..00000000 --- a/kernel/core-kernel-2.6.38/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -VERSION := 2.6.38 -TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 - -SUBVERSION := -core -REVISION := 1.0 - -PATCHDIR := patches -PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) - -CONFIG := config.core - -DEPDEBS := linux-source kernel-package po-debconf gettext - -CONCURRENCY_LEVEL := 2 - -MAINTAINER ?= Tom Goff -EMAIL ?= thomas.goff@boeing.com - -MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ - --append-to-version $(SUBVERSION) --revision $(REVISION) - -.PHONY: build -build: debcheck defaultconfig patch - export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ - KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && \ - if [ -f ../$(CONFIG) ]; then \ - cat ../$(CONFIG) >> .config; \ - fi && \ - fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch - -.PHONY: debcheck -debcheck: - for d in $(DEPDEBS); do \ - if ! dpkg-query -s $$d > /dev/null 2>&1; then \ - echo ERROR: build dependency not installed: $$d >&2; \ - exit 1; \ - fi; \ - done - -.PHONY: defaultconfig -defaultconfig: linux-source-$(VERSION) - export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure - -.PHONY: patch -patch: linux-source-$(VERSION) patch-stamp -patch-stamp: $(PATCHES) - for p in $^; do \ - if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ - echo ERROR: applying patch failed: $$p >&2; \ - exit 1; \ - fi; \ - done - touch patch-stamp - -linux-source-$(VERSION): $(TARBALL) - tar -xjf $^ - -.PHONY: clean -clean: - rm -rf linux-source-$(VERSION) patch-stamp diff --git a/kernel/core-kernel-2.6.38/README.txt b/kernel/core-kernel-2.6.38/README.txt deleted file mode 100644 index 5e473f58..00000000 --- a/kernel/core-kernel-2.6.38/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -Author: Tom Goff - -The Makefile is basically a wrapper around the make-kpkg command that -simplifies building kernel packages. Running make will do some basic -dependency checks then build architecture appropriate kernel packages that -include changes from the patches directory. The nfnetlink patch is what -virtualizes the netfilter queue mechanism; the flow-cache patch allows using -IPsec between network namespaces; the ifindex patch virtualizes network -interface index numbers. diff --git a/kernel/core-kernel-2.6.38/config.core b/kernel/core-kernel-2.6.38/config.core deleted file mode 100644 index 27c7ef7a..00000000 --- a/kernel/core-kernel-2.6.38/config.core +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XFRM_STATISTICS=y diff --git a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.flow-cache.patch b/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.flow-cache.patch deleted file mode 100644 index 4bb5d6f6..00000000 --- a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.flow-cache.patch +++ /dev/null @@ -1,31 +0,0 @@ -Only use the flow cache for the initial network namespace. - -The flow cache is not per netns and its entries do not include what -namespace they are valid for. This causes problems when transformed -traffic is sent between namespaces. ---- - net/core/flow.c | 4 ++++ - 1 files changed, 4 insertions(+), 0 deletions(-) - -diff --git a/net/core/flow.c b/net/core/flow.c -index 127c8a7..890510f 100644 ---- a/net/core/flow.c -+++ b/net/core/flow.c -@@ -24,6 +24,7 @@ - #include - #include - #include -+#include - - struct flow_cache_entry { - union { -@@ -227,6 +228,9 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir, - if (!fcp->hash_table) - goto nocache; - -+ if (!net_eq(net, &init_net)) -+ goto nocache; -+ - if (fcp->hash_rnd_recalc) - flow_new_hash_rnd(fc, fcp); - diff --git a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.ifindex.patch b/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.ifindex.patch deleted file mode 100644 index 85fbb14a..00000000 --- a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.ifindex.patch +++ /dev/null @@ -1,52 +0,0 @@ -Make network device ifindex sequential per network namespace. - ---- - include/net/net_namespace.h | 2 ++ - net/core/dev.c | 13 ++++++------- - 2 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 1bf812b..6ee0db4 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -57,6 +57,8 @@ struct net { - struct sock *rtnl; /* rtnetlink socket */ - struct sock *genl_sock; - -+ int ifindex; -+ - struct list_head dev_base_head; - struct hlist_head *dev_name_head; - struct hlist_head *dev_index_head; -diff --git a/net/core/dev.c b/net/core/dev.c -index 6561021..764a190 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -4975,12 +4975,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) - */ - static int dev_new_index(struct net *net) - { -- static int ifindex; - for (;;) { -- if (++ifindex <= 0) -- ifindex = 1; -- if (!__dev_get_by_index(net, ifindex)) -- return ifindex; -+ if (++net->ifindex <= 0) -+ net->ifindex = 1; -+ if (!__dev_get_by_index(net, net->ifindex)) -+ return net->ifindex; - } - } - -@@ -5918,8 +5917,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char - /* Actually switch the network namespace */ - dev_net_set(dev, net); - -- /* If there is an ifindex conflict assign a new one */ -- if (__dev_get_by_index(net, dev->ifindex)) { -+ /* Assign a new ifindex */ -+ { - int iflink = (dev->iflink == dev->ifindex); - dev->ifindex = dev_new_index(net); - if (iflink) diff --git a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch b/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch deleted file mode 100644 index 8cb8bdec..00000000 --- a/kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch +++ /dev/null @@ -1,1662 +0,0 @@ -netfilter: make nfnetlink network namespace aware - -Move static variables to structures allocated per netns and accessed -with generic net pointers. - -Make nfnetlink subsystem registration per netns. - -Make proc filesystem entries per netns. ---- - include/linux/netfilter.h | 2 +- - include/linux/netfilter/nfnetlink.h | 10 +- - include/net/netfilter/nf_queue.h | 3 +- - net/ipv4/netfilter/ip_queue.c | 6 +- - net/ipv6/netfilter/ip6_queue.c | 6 +- - net/netfilter/core.c | 55 +++++++-- - net/netfilter/nf_conntrack_netlink.c | 55 ++++++--- - net/netfilter/nf_log.c | 34 ++++-- - net/netfilter/nf_queue.c | 47 ++++++- - net/netfilter/nfnetlink.c | 89 ++++++++++---- - net/netfilter/nfnetlink_log.c | 218 ++++++++++++++++++++++------------ - net/netfilter/nfnetlink_queue.c | 191 ++++++++++++++++++++---------- - net/netfilter/xt_osf.c | 42 +++++-- - 13 files changed, 537 insertions(+), 221 deletions(-) - -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index 1893837..f52e719 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -329,7 +329,7 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) - - #ifdef CONFIG_PROC_FS - #include --extern struct proc_dir_entry *proc_net_netfilter; -+extern struct proc_dir_entry *proc_net_netfilter(struct net *net); - #endif - - #else /* !CONFIG_NETFILTER */ -diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h -index 361d6b5..8acaa17 100644 ---- a/include/linux/netfilter/nfnetlink.h -+++ b/include/linux/netfilter/nfnetlink.h -@@ -70,8 +70,10 @@ struct nfnetlink_subsystem { - const struct nfnl_callback *cb; /* callback for individual types */ - }; - --extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); --extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); -+extern int nfnetlink_subsys_register(struct net *net, -+ const struct nfnetlink_subsystem *n); -+extern int nfnetlink_subsys_unregister(struct net *net, -+ const struct nfnetlink_subsystem *n); - - extern int nfnetlink_has_listeners(struct net *net, unsigned int group); - extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, -@@ -79,8 +81,8 @@ extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigne - extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); - extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); - --extern void nfnl_lock(void); --extern void nfnl_unlock(void); -+extern void nfnl_lock(struct net *net); -+extern void nfnl_unlock(struct net *net); - - #define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ - MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) -diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h -index 252fd10..3e5bde8 100644 ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -19,7 +19,8 @@ struct nf_queue_entry { - - /* Packet queuing */ - struct nf_queue_handler { -- int (*outfn)(struct nf_queue_entry *entry, -+ int (*outfn)(struct net *net, -+ struct nf_queue_entry *entry, - unsigned int queuenum); - char *name; - }; -diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c -index d2c1311..bccef48 100644 ---- a/net/ipv4/netfilter/ip_queue.c -+++ b/net/ipv4/netfilter/ip_queue.c -@@ -223,7 +223,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -237,6 +238,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c -index 413ab07..b227789 100644 ---- a/net/ipv6/netfilter/ip6_queue.c -+++ b/net/ipv6/netfilter/ip6_queue.c -@@ -223,7 +223,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -237,6 +238,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/netfilter/core.c b/net/netfilter/core.c -index 4aa614b..157785f 100644 ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - - #include "nf_internals.h" -@@ -249,24 +250,62 @@ EXPORT_SYMBOL(nf_conntrack_destroy); - #endif /* CONFIG_NF_CONNTRACK */ - - #ifdef CONFIG_PROC_FS --struct proc_dir_entry *proc_net_netfilter; -+static int netfilter_net_id __read_mostly; -+struct netns_netfilter { -+ struct proc_dir_entry *proc_net_netfilter; -+}; -+ -+struct proc_dir_entry *proc_net_netfilter(struct net *net) -+{ -+ struct netns_netfilter *net_netfilter; -+ -+ net_netfilter = net_generic(net, netfilter_net_id); -+ return net_netfilter->proc_net_netfilter; -+} - EXPORT_SYMBOL(proc_net_netfilter); --#endif -+ -+static int __net_init netfilter_net_init(struct net *net) -+{ -+ struct netns_netfilter *net_netfilter = -+ net_generic(net, netfilter_net_id); -+ -+ net_netfilter->proc_net_netfilter = -+ proc_net_mkdir(net, "netfilter", net->proc_net); -+ if (!net_netfilter->proc_net_netfilter) { -+ pr_err("cannot create netfilter proc entry\n"); -+ return -ENOMEM; -+ } -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_net_exit(struct net *net) -+{ -+ proc_net_remove(net, "netfilter"); -+} -+ -+static struct pernet_operations netfilter_net_ops = { -+ .init = netfilter_net_init, -+ .exit = netfilter_net_exit, -+ .id = &netfilter_net_id, -+ .size = sizeof(struct netns_netfilter), -+}; -+#endif /* CONFIG_PROC_FS */ - - void __init netfilter_init(void) - { - int i, h; -+ -+#ifdef CONFIG_PROC_FS -+ if (register_pernet_subsys(&netfilter_net_ops)) -+ panic("netfilter_init: cannot initialize per netns operations"); -+#endif -+ - for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - INIT_LIST_HEAD(&nf_hooks[i][h]); - } - --#ifdef CONFIG_PROC_FS -- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); -- if (!proc_net_netfilter) -- panic("cannot create netfilter proc entry"); --#endif -- - if (netfilter_queue_init() < 0) - panic("cannot initialize nf_queue"); - if (netfilter_log_init() < 0) -diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c -index eead9db..6c22c74 100644 ---- a/net/netfilter/nf_conntrack_netlink.c -+++ b/net/netfilter/nf_conntrack_netlink.c -@@ -984,20 +984,21 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, - const struct nlattr *attr) - { - typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup; -+ struct net *net = nf_ct_net(ct); - - parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook); - if (!parse_nat_setup) { - #ifdef CONFIG_MODULES - rcu_read_unlock(); - spin_unlock_bh(&nf_conntrack_lock); -- nfnl_unlock(); -+ nfnl_unlock(net); - if (request_module("nf-nat-ipv4") < 0) { -- nfnl_lock(); -+ nfnl_lock(net); - spin_lock_bh(&nf_conntrack_lock); - rcu_read_lock(); - return -EOPNOTSUPP; - } -- nfnl_lock(); -+ nfnl_lock(net); - spin_lock_bh(&nf_conntrack_lock); - rcu_read_lock(); - if (nfnetlink_parse_nat_setup_hook) -@@ -2114,28 +2115,59 @@ MODULE_ALIAS("ip_conntrack_netlink"); - MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); - MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP); - --static int __init ctnetlink_init(void) -+static int __net_init ctnetlink_net_init(struct net *net) - { - int ret; - - pr_info("ctnetlink v%s: registering with nfnetlink.\n", version); -- ret = nfnetlink_subsys_register(&ctnl_subsys); -+ ret = nfnetlink_subsys_register(net, &ctnl_subsys); - if (ret < 0) { - pr_err("ctnetlink_init: cannot register with nfnetlink.\n"); - goto err_out; - } - -- ret = nfnetlink_subsys_register(&ctnl_exp_subsys); -+ ret = nfnetlink_subsys_register(net, &ctnl_exp_subsys); - if (ret < 0) { - pr_err("ctnetlink_init: cannot register exp with nfnetlink.\n"); - goto err_unreg_subsys; - } - -+ return 0; -+ -+err_unreg_subsys: -+ nfnetlink_subsys_unregister(net, &ctnl_subsys); -+err_out: -+ return ret; -+} -+ -+static void __net_exit ctnetlink_net_exit(struct net *net) -+{ -+ pr_info("ctnetlink: unregistering from nfnetlink.\n"); -+ -+ nfnetlink_subsys_unregister(net, &ctnl_exp_subsys); -+ nfnetlink_subsys_unregister(net, &ctnl_subsys); -+} -+ -+static struct pernet_operations ctnetlink_net_ops = { -+ .init = ctnetlink_net_init, -+ .exit = ctnetlink_net_exit, -+}; -+ -+static int __init ctnetlink_init(void) -+{ -+ int ret; -+ -+ ret = register_pernet_subsys(&ctnetlink_net_ops); -+ if (ret) { -+ pr_err("ctnetlink_init: cannot initialize ctnetlink.\n"); -+ goto err_out; -+ } -+ - #ifdef CONFIG_NF_CONNTRACK_EVENTS - ret = nf_conntrack_register_notifier(&ctnl_notifier); - if (ret < 0) { - pr_err("ctnetlink_init: cannot register notifier.\n"); -- goto err_unreg_exp_subsys; -+ goto err_out; - } - - ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp); -@@ -2150,27 +2182,20 @@ static int __init ctnetlink_init(void) - #ifdef CONFIG_NF_CONNTRACK_EVENTS - err_unreg_notifier: - nf_conntrack_unregister_notifier(&ctnl_notifier); --err_unreg_exp_subsys: -- nfnetlink_subsys_unregister(&ctnl_exp_subsys); - #endif --err_unreg_subsys: -- nfnetlink_subsys_unregister(&ctnl_subsys); - err_out: - return ret; - } - - static void __exit ctnetlink_exit(void) - { -- pr_info("ctnetlink: unregistering from nfnetlink.\n"); -- - nf_ct_remove_userspace_expectations(); - #ifdef CONFIG_NF_CONNTRACK_EVENTS - nf_ct_expect_unregister_notifier(&ctnl_notifier_exp); - nf_conntrack_unregister_notifier(&ctnl_notifier); - #endif - -- nfnetlink_subsys_unregister(&ctnl_exp_subsys); -- nfnetlink_subsys_unregister(&ctnl_subsys); -+ unregister_pernet_subsys(&ctnetlink_net_ops); - } - - module_init(ctnetlink_init); -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index 9181699..6c193b1 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -209,7 +209,24 @@ static const struct file_operations nflog_file_ops = { - .release = seq_release, - }; - -+static int __net_init netfilter_log_net_init(struct net *net) -+{ -+ if (!proc_create("nf_log", S_IRUGO, -+ proc_net_netfilter(net), &nflog_file_ops)) -+ return -ENOMEM; -+ -+ return 0; -+} - -+static void __net_exit netfilter_log_net_exit(struct net *net) -+{ -+ remove_proc_entry("nf_log", proc_net_netfilter(net)); -+} -+ -+static struct pernet_operations netfilter_log_net_ops = { -+ .init = netfilter_log_net_init, -+ .exit = netfilter_log_net_exit, -+}; - #endif /* PROC_FS */ - - #ifdef CONFIG_SYSCTL -@@ -288,26 +305,27 @@ static __init int netfilter_log_sysctl_init(void) - - return 0; - } --#else --static __init int netfilter_log_sysctl_init(void) --{ -- return 0; --} - #endif /* CONFIG_SYSCTL */ - - int __init netfilter_log_init(void) - { - int i, r; -+ - #ifdef CONFIG_PROC_FS -- if (!proc_create("nf_log", S_IRUGO, -- proc_net_netfilter, &nflog_file_ops)) -- return -1; -+ r = register_pernet_subsys(&netfilter_log_net_ops); -+ if (r) { -+ pr_err("netfilter_log_init: " -+ "cannot initialize per netns operations\n"); -+ return r; -+ } - #endif - -+#ifdef CONFIG_SYSCTL - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); - if (r < 0) - return r; -+#endif - - for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) - INIT_LIST_HEAD(&(nf_loggers_l[i])); -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index 74aebed..c9fc05f 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -123,6 +123,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+ struct net *net = NULL; - - /* QUEUE == DROP if noone is waiting, to be safe. */ - rcu_read_lock(); -@@ -156,6 +157,17 @@ static int __nf_queue(struct sk_buff *skb, - return 0; - } - -+ if (indev) -+ net = dev_net(indev); -+ else if (outdev) -+ net = dev_net(outdev); -+ else if (skb->sk) -+ net = sock_net(skb->sk); -+ else { -+ pr_warn("%s: no net for skb: %p\n", __func__, skb); -+ goto err_unlock; -+ } -+ - /* Bump dev refs so they don't vanish while packet is out */ - if (indev) - dev_hold(indev); -@@ -173,7 +185,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - skb_dst_force(skb); - afinfo->saveroute(skb, entry); -- status = qh->outfn(entry, queuenum); -+ status = qh->outfn(net, entry, queuenum); - - rcu_read_unlock(); - -@@ -344,16 +356,37 @@ static const struct file_operations nfqueue_file_ops = { - .llseek = seq_lseek, - .release = seq_release, - }; --#endif /* PROC_FS */ -- - --int __init netfilter_queue_init(void) -+static int __net_init netfilter_queue_net_init(struct net *net) - { --#ifdef CONFIG_PROC_FS - if (!proc_create("nf_queue", S_IRUGO, -- proc_net_netfilter, &nfqueue_file_ops)) -+ proc_net_netfilter(net), &nfqueue_file_ops)) - return -1; --#endif -+ - return 0; - } - -+static void __net_exit netfilter_queue_net_exit(struct net *net) -+{ -+ remove_proc_entry("nf_queue", proc_net_netfilter(net)); -+} -+ -+static struct pernet_operations netfilter_queue_net_ops = { -+ .init = netfilter_queue_net_init, -+ .exit = netfilter_queue_net_exit, -+}; -+#endif /* PROC_FS */ -+ -+int __init netfilter_queue_init(void) -+{ -+ int err = 0; -+ -+#ifdef CONFIG_PROC_FS -+ err = register_pernet_subsys(&netfilter_queue_net_ops); -+ if (err) -+ pr_err("netfilter_queue_init: " -+ "cannot initialize per netns operations\n"); -+#endif -+ -+ return err; -+} -diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c -index b4a4532..235da38 100644 ---- a/net/netfilter/nfnetlink.c -+++ b/net/netfilter/nfnetlink.c -@@ -24,6 +24,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -35,55 +37,79 @@ MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Harald Welte "); - MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER); - -+static int nfnl_net_id __read_mostly; -+struct netns_nfnl { -+ const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; -+ struct mutex nfnl_mutex; -+}; -+ - static char __initdata nfversion[] = "0.30"; - --static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; --static DEFINE_MUTEX(nfnl_mutex); -+static void __nfnl_lock(struct netns_nfnl *net_nfnl) -+{ -+ mutex_lock(&net_nfnl->nfnl_mutex); -+} - --void nfnl_lock(void) -+void nfnl_lock(struct net *net) - { -- mutex_lock(&nfnl_mutex); -+ struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); -+ -+ __nfnl_lock(net_nfnl); - } - EXPORT_SYMBOL_GPL(nfnl_lock); - --void nfnl_unlock(void) -+static void __nfnl_unlock(struct netns_nfnl *net_nfnl) -+{ -+ mutex_unlock(&net_nfnl->nfnl_mutex); -+} -+ -+void nfnl_unlock(struct net *net) - { -- mutex_unlock(&nfnl_mutex); -+ struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); -+ -+ __nfnl_unlock(net_nfnl); - } - EXPORT_SYMBOL_GPL(nfnl_unlock); - --int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) -+int nfnetlink_subsys_register(struct net *net, -+ const struct nfnetlink_subsystem *n) - { -- nfnl_lock(); -- if (subsys_table[n->subsys_id]) { -- nfnl_unlock(); -+ struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); -+ -+ __nfnl_lock(net_nfnl); -+ if (net_nfnl->subsys_table[n->subsys_id]) { -+ __nfnl_unlock(net_nfnl); - return -EBUSY; - } -- subsys_table[n->subsys_id] = n; -- nfnl_unlock(); -+ net_nfnl->subsys_table[n->subsys_id] = n; -+ __nfnl_unlock(net_nfnl); - - return 0; - } - EXPORT_SYMBOL_GPL(nfnetlink_subsys_register); - --int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n) -+int nfnetlink_subsys_unregister(struct net *net, -+ const struct nfnetlink_subsystem *n) - { -- nfnl_lock(); -- subsys_table[n->subsys_id] = NULL; -- nfnl_unlock(); -+ struct netns_nfnl *net_nfnl = net_generic(net, nfnl_net_id); -+ -+ __nfnl_lock(net_nfnl); -+ net_nfnl->subsys_table[n->subsys_id] = NULL; -+ __nfnl_unlock(net_nfnl); - - return 0; - } - EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister); - --static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t type) -+static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(struct netns_nfnl *net_nfnl, -+ u_int16_t type) - { - u_int8_t subsys_id = NFNL_SUBSYS_ID(type); - - if (subsys_id >= NFNL_SUBSYS_COUNT) - return NULL; - -- return subsys_table[subsys_id]; -+ return net_nfnl->subsys_table[subsys_id]; - } - - static inline const struct nfnl_callback * -@@ -129,6 +155,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) - const struct nfnl_callback *nc; - const struct nfnetlink_subsystem *ss; - int type, err; -+ struct netns_nfnl *net_nfnl; - - if (security_netlink_recv(skb, CAP_NET_ADMIN)) - return -EPERM; -@@ -137,15 +164,17 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) - if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) - return 0; - -+ net_nfnl = net_generic(net, nfnl_net_id); -+ - type = nlh->nlmsg_type; - replay: -- ss = nfnetlink_get_subsys(type); -+ ss = nfnetlink_get_subsys(net_nfnl, type); - if (!ss) { - #ifdef CONFIG_MODULES -- nfnl_unlock(); -+ nfnl_unlock(net); - request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); -- nfnl_lock(); -- ss = nfnetlink_get_subsys(type); -+ nfnl_lock(net); -+ ss = nfnetlink_get_subsys(net_nfnl, type); - if (!ss) - #endif - return -EINVAL; -@@ -176,14 +205,18 @@ replay: - - static void nfnetlink_rcv(struct sk_buff *skb) - { -- nfnl_lock(); -+ struct net *net = sock_net(skb->sk); -+ -+ nfnl_lock(net); - netlink_rcv_skb(skb, &nfnetlink_rcv_msg); -- nfnl_unlock(); -+ nfnl_unlock(net); - } - - static int __net_init nfnetlink_net_init(struct net *net) - { - struct sock *nfnl; -+ int i; -+ struct netns_nfnl *net_nfnl; - - nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX, - nfnetlink_rcv, NULL, THIS_MODULE); -@@ -191,6 +224,12 @@ static int __net_init nfnetlink_net_init(struct net *net) - return -ENOMEM; - net->nfnl_stash = nfnl; - rcu_assign_pointer(net->nfnl, nfnl); -+ -+ net_nfnl = net_generic(net, nfnl_net_id); -+ for (i = 0; i < NFNL_SUBSYS_COUNT; i++) -+ net_nfnl->subsys_table[i] = NULL; -+ mutex_init(&net_nfnl->nfnl_mutex); -+ - return 0; - } - -@@ -208,6 +247,8 @@ static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list) - static struct pernet_operations nfnetlink_net_ops = { - .init = nfnetlink_net_init, - .exit_batch = nfnetlink_net_exit_batch, -+ .id = &nfnl_net_id, -+ .size = sizeof(struct netns_nfnl), - }; - - static int __init nfnetlink_init(void) -diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index 6a1572b..44508bb 100644 ---- a/net/netfilter/nfnetlink_log.c -+++ b/net/netfilter/nfnetlink_log.c -@@ -32,6 +32,8 @@ - #include - #include - #include -+#include -+#include - - #include - -@@ -67,14 +69,17 @@ struct nfulnl_instance { - u_int16_t flags; - u_int8_t copy_mode; - struct rcu_head rcu; --}; - --static DEFINE_SPINLOCK(instances_lock); --static atomic_t global_seq; -+ struct net *net; -+}; - - #define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS]; --static unsigned int hash_init; -+static int nfulnl_net_id __read_mostly; -+struct netns_nfulnl { -+ spinlock_t instances_lock; -+ atomic_t global_seq; -+ struct hlist_head instance_table[INSTANCE_BUCKETS]; -+}; - - static inline u_int8_t instance_hashfn(u_int16_t group_num) - { -@@ -82,13 +87,13 @@ static inline u_int8_t instance_hashfn(u_int16_t group_num) - } - - static struct nfulnl_instance * --__instance_lookup(u_int16_t group_num) -+__instance_lookup(struct netns_nfulnl *net_nfulnl, u_int16_t group_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfulnl_instance *inst; - -- head = &instance_table[instance_hashfn(group_num)]; -+ head = &net_nfulnl->instance_table[instance_hashfn(group_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->group_num == group_num) - return inst; -@@ -103,12 +108,12 @@ instance_get(struct nfulnl_instance *inst) - } - - static struct nfulnl_instance * --instance_lookup_get(u_int16_t group_num) -+instance_lookup_get(struct netns_nfulnl *net_nfulnl, u_int16_t group_num) - { - struct nfulnl_instance *inst; - - rcu_read_lock_bh(); -- inst = __instance_lookup(group_num); -+ inst = __instance_lookup(net_nfulnl, group_num); - if (inst && !atomic_inc_not_zero(&inst->use)) - inst = NULL; - rcu_read_unlock_bh(); -@@ -118,7 +123,10 @@ instance_lookup_get(u_int16_t group_num) - - static void nfulnl_instance_free_rcu(struct rcu_head *head) - { -- kfree(container_of(head, struct nfulnl_instance, rcu)); -+ struct nfulnl_instance *inst = -+ container_of(head, struct nfulnl_instance, rcu); -+ put_net(inst->net); -+ kfree(inst); - module_put(THIS_MODULE); - } - -@@ -132,13 +140,14 @@ instance_put(struct nfulnl_instance *inst) - static void nfulnl_timer(unsigned long data); - - static struct nfulnl_instance * --instance_create(u_int16_t group_num, int pid) -+instance_create(struct net *net, struct netns_nfulnl *net_nfulnl, -+ u_int16_t group_num, int pid) - { - struct nfulnl_instance *inst; - int err; - -- spin_lock_bh(&instances_lock); -- if (__instance_lookup(group_num)) { -+ spin_lock_bh(&net_nfulnl->instances_lock); -+ if (__instance_lookup(net_nfulnl, group_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -171,15 +180,17 @@ instance_create(u_int16_t group_num, int pid) - inst->copy_mode = NFULNL_COPY_PACKET; - inst->copy_range = NFULNL_COPY_RANGE_MAX; - -+ inst->net = get_net(net); -+ - hlist_add_head_rcu(&inst->hlist, -- &instance_table[instance_hashfn(group_num)]); -+ &net_nfulnl->instance_table[instance_hashfn(group_num)]); - -- spin_unlock_bh(&instances_lock); -+ spin_unlock_bh(&net_nfulnl->instances_lock); - - return inst; - - out_unlock: -- spin_unlock_bh(&instances_lock); -+ spin_unlock_bh(&net_nfulnl->instances_lock); - return ERR_PTR(err); - } - -@@ -208,11 +219,11 @@ __instance_destroy(struct nfulnl_instance *inst) - } - - static inline void --instance_destroy(struct nfulnl_instance *inst) -+instance_destroy(struct netns_nfulnl *net_nfulnl, struct nfulnl_instance *inst) - { -- spin_lock_bh(&instances_lock); -+ spin_lock_bh(&net_nfulnl->instances_lock); - __instance_destroy(inst); -- spin_unlock_bh(&instances_lock); -+ spin_unlock_bh(&net_nfulnl->instances_lock); - } - - static int -@@ -334,7 +345,7 @@ __nfulnl_send(struct nfulnl_instance *inst) - NLMSG_DONE, - sizeof(struct nfgenmsg)); - -- status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_pid, -+ status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_pid, - MSG_DONTWAIT); - - inst->qlen = 0; -@@ -369,7 +380,8 @@ nfulnl_timer(unsigned long data) - /* This is an inline function, we don't really care about a long - * list of arguments */ - static inline int --__build_packet_message(struct nfulnl_instance *inst, -+__build_packet_message(struct netns_nfulnl *net_nfulnl, -+ struct nfulnl_instance *inst, - const struct sk_buff *skb, - unsigned int data_len, - u_int8_t pf, -@@ -507,7 +519,7 @@ __build_packet_message(struct nfulnl_instance *inst, - /* global sequence number */ - if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) - NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL, -- htonl(atomic_inc_return(&global_seq))); -+ htonl(atomic_inc_return(&net_nfulnl->global_seq))); - - if (data_len) { - struct nlattr *nla; -@@ -563,13 +575,16 @@ nfulnl_log_packet(u_int8_t pf, - const struct nf_loginfo *li; - unsigned int qthreshold; - unsigned int plen; -+ struct netns_nfulnl *net_nfulnl; -+ -+ net_nfulnl = net_generic(dev_net(in), nfulnl_net_id); - - if (li_user && li_user->type == NF_LOG_TYPE_ULOG) - li = li_user; - else - li = &default_loginfo; - -- inst = instance_lookup_get(li->u.ulog.group); -+ inst = instance_lookup_get(net_nfulnl, li->u.ulog.group); - if (!inst) - return; - -@@ -651,7 +666,7 @@ nfulnl_log_packet(u_int8_t pf, - - inst->qlen++; - -- __build_packet_message(inst, skb, data_len, pf, -+ __build_packet_message(net_nfulnl, inst, skb, data_len, pf, - hooknum, in, out, li, prefix, plen); - - if (inst->qlen >= qthreshold) -@@ -680,24 +695,26 @@ nfulnl_rcv_nl_event(struct notifier_block *this, - unsigned long event, void *ptr) - { - struct netlink_notify *n = ptr; -+ struct netns_nfulnl *net_nfulnl; - -+ net_nfulnl = net_generic(n->net, nfulnl_net_id); - if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { - int i; - - /* destroy all instances for this pid */ -- spin_lock_bh(&instances_lock); -+ spin_lock_bh(&net_nfulnl->instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfulnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &net_nfulnl->instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((net_eq(n->net, &init_net)) && -- (n->pid == inst->peer_pid)) -+ if (n->pid == inst->peer_pid) - __instance_destroy(inst); - } - } -- spin_unlock_bh(&instances_lock); -+ spin_unlock_bh(&net_nfulnl->instances_lock); - } - return NOTIFY_DONE; - } -@@ -739,6 +756,10 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfulnl_instance *inst; - struct nfulnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); -+ struct netns_nfulnl *net_nfulnl; -+ -+ net_nfulnl = net_generic(net, nfulnl_net_id); - - if (nfula[NFULA_CFG_CMD]) { - u_int8_t pf = nfmsg->nfgen_family; -@@ -754,7 +775,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - } - -- inst = instance_lookup_get(group_num); -+ inst = instance_lookup_get(net_nfulnl, group_num); - if (inst && inst->peer_pid != NETLINK_CB(skb).pid) { - ret = -EPERM; - goto out_put; -@@ -768,7 +789,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - goto out_put; - } - -- inst = instance_create(group_num, -+ inst = instance_create(net, net_nfulnl, group_num, - NETLINK_CB(skb).pid); - if (IS_ERR(inst)) { - ret = PTR_ERR(inst); -@@ -781,7 +802,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - goto out; - } - -- instance_destroy(inst); -+ instance_destroy(net_nfulnl, inst); - goto out_put; - default: - ret = -ENOTSUPP; -@@ -867,37 +888,45 @@ struct iter_state { - unsigned int bucket; - }; - --static struct hlist_node *get_first(struct iter_state *st) -+static struct hlist_node *get_first(struct seq_file *seq) - { -+ struct iter_state *st = seq->private; -+ struct netns_nfulnl *net_nfulnl; -+ - if (!st) - return NULL; - -+ net_nfulnl = net_generic(seq_file_net(seq), nfulnl_net_id); - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return rcu_dereference_bh(instance_table[st->bucket].first); -+ if (!hlist_empty(&net_nfulnl->instance_table[st->bucket])) -+ return rcu_dereference_bh(net_nfulnl->instance_table[st->bucket].first); - } - return NULL; - } - --static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) -+static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) - { -+ struct iter_state *st = seq->private; -+ struct netns_nfulnl *net_nfulnl; -+ -+ net_nfulnl = net_generic(seq_file_net(seq), nfulnl_net_id); - h = rcu_dereference_bh(h->next); - while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) - return NULL; - -- h = rcu_dereference_bh(instance_table[st->bucket].first); -+ h = rcu_dereference_bh(net_nfulnl->instance_table[st->bucket].first); - } - return h; - } - --static struct hlist_node *get_idx(struct iter_state *st, loff_t pos) -+static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) - { - struct hlist_node *head; -- head = get_first(st); -+ head = get_first(seq); - - if (head) -- while (pos && (head = get_next(st, head))) -+ while (pos && (head = get_next(seq, head))) - pos--; - return pos ? NULL : head; - } -@@ -906,13 +935,13 @@ static void *seq_start(struct seq_file *seq, loff_t *pos) - __acquires(rcu_bh) - { - rcu_read_lock_bh(); -- return get_idx(seq->private, *pos); -+ return get_idx(seq, *pos); - } - - static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - { - (*pos)++; -- return get_next(s->private, v); -+ return get_next(s, v); - } - - static void seq_stop(struct seq_file *s, void *v) -@@ -941,8 +970,8 @@ static const struct seq_operations nful_seq_ops = { - - static int nful_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nful_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nful_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nful_file_ops = { -@@ -950,62 +979,103 @@ static const struct file_operations nful_file_ops = { - .open = nful_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - --static int __init nfnetlink_log_init(void) -+static int __net_init nfnetlink_log_net_init(struct net *net) - { -- int i, status = -ENOMEM; -+ int err, i; -+ struct netns_nfulnl *net_nfulnl = net_generic(net, nfulnl_net_id); - -+ spin_lock_init(&net_nfulnl->instances_lock); -+ atomic_set(&net_nfulnl->global_seq, 0); - for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -+ INIT_HLIST_HEAD(&net_nfulnl->instance_table[i]); - -- /* it's not really all that important to have a random value, so -- * we can do this from the init function, even if there hasn't -- * been that much entropy yet */ -- get_random_bytes(&hash_init, sizeof(hash_init)); -+#ifdef CONFIG_PROC_FS -+ if (proc_net_fops_create(net, "nfnetlink_log", 0440, -+ &nful_file_ops)) -+ return -ENOMEM; -+#endif - -- netlink_register_notifier(&nfulnl_rtnl_notifier); -- status = nfnetlink_subsys_register(&nfulnl_subsys); -- if (status < 0) { -+ err = nfnetlink_subsys_register(net, &nfulnl_subsys); -+ if (err < 0) { - printk(KERN_ERR "log: failed to create netlink socket\n"); -- goto cleanup_netlink_notifier; -+ goto cleanup_proc; - } - -- status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); -- if (status < 0) { -- printk(KERN_ERR "log: failed to register logger\n"); -- goto cleanup_subsys; -- } -+ return 0; - -+cleanup_proc: - #ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_log", 0440, -- proc_net_netfilter, &nful_file_ops)) -- goto cleanup_logger; -+ proc_net_remove(net, "nfnetlink_log"); - #endif -- return status; -+ return err; -+} -+ -+static void __net_exit nfnetlink_log_net_exit(struct net *net) -+{ -+ int i; -+ struct netns_nfulnl *net_nfulnl; - -+ nfnetlink_subsys_unregister(net, &nfulnl_subsys); - #ifdef CONFIG_PROC_FS --cleanup_logger: -- nf_log_unregister(&nfulnl_logger); -+ proc_net_remove(net, "nfnetlink_log"); - #endif --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfulnl_subsys); -+ -+ net_nfulnl = net_generic(net, nfulnl_net_id); -+ spin_lock_bh(&net_nfulnl->instances_lock); -+ for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ struct hlist_node *tmp, *t2; -+ struct nfulnl_instance *inst; -+ struct hlist_head *head = &net_nfulnl->instance_table[i]; -+ -+ hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) -+ __instance_destroy(inst); -+ } -+ spin_unlock_bh(&net_nfulnl->instances_lock); -+} -+ -+static struct pernet_operations nfnetlink_log_net_ops = { -+ .init = nfnetlink_log_net_init, -+ .exit = nfnetlink_log_net_exit, -+ .id = &nfulnl_net_id, -+ .size = sizeof(struct netns_nfulnl), -+}; -+ -+static int __init nfnetlink_log_init(void) -+{ -+ int err; -+ -+ err = register_pernet_subsys(&nfnetlink_log_net_ops); -+ if (err) { -+ pr_err("nfnetlink_log_init: " -+ "cannot initialize per netns operations\n"); -+ return err; -+ } -+ -+ netlink_register_notifier(&nfulnl_rtnl_notifier); -+ -+ err = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); -+ if (err < 0) { -+ pr_err("log: failed to register logger\n"); -+ goto cleanup_netlink_notifier; -+ } -+ -+ return err; -+ - cleanup_netlink_notifier: - netlink_unregister_notifier(&nfulnl_rtnl_notifier); -- return status; -+ return err; - } - - static void __exit nfnetlink_log_fini(void) - { - nf_log_unregister(&nfulnl_logger); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_log", proc_net_netfilter); --#endif -- nfnetlink_subsys_unregister(&nfulnl_subsys); - netlink_unregister_notifier(&nfulnl_rtnl_notifier); -+ unregister_pernet_subsys(&nfnetlink_log_net_ops); - } - - MODULE_DESCRIPTION("netfilter userspace logging"); -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index 68e67d1..3fa78a7 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -30,6 +30,8 @@ - #include - #include - #include -+#include -+#include - - #include - -@@ -62,12 +64,14 @@ struct nfqnl_instance { - struct list_head queue_list; /* packets in queue */ - }; - --typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); -- --static DEFINE_SPINLOCK(instances_lock); -- - #define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; -+static int nfqnl_net_id __read_mostly; -+struct netns_nfqnl { -+ spinlock_t instances_lock; -+ struct hlist_head instance_table[INSTANCE_BUCKETS]; -+}; -+ -+typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - - static inline u_int8_t instance_hashfn(u_int16_t queue_num) - { -@@ -75,13 +79,14 @@ static inline u_int8_t instance_hashfn(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_lookup(u_int16_t queue_num) -+instance_lookup(struct net *net, u_int16_t queue_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfqnl_instance *inst; -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - -- head = &instance_table[instance_hashfn(queue_num)]; -+ head = &net_nfqnl->instance_table[instance_hashfn(queue_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->queue_num == queue_num) - return inst; -@@ -90,14 +95,15 @@ instance_lookup(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_create(u_int16_t queue_num, int pid) -+instance_create(struct net *net, u_int16_t queue_num, int pid) - { -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - struct nfqnl_instance *inst; - unsigned int h; - int err; - -- spin_lock(&instances_lock); -- if (instance_lookup(queue_num)) { -+ spin_lock(&net_nfqnl->instances_lock); -+ if (instance_lookup(net, queue_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -122,16 +128,16 @@ instance_create(u_int16_t queue_num, int pid) - } - - h = instance_hashfn(queue_num); -- hlist_add_head_rcu(&inst->hlist, &instance_table[h]); -+ hlist_add_head_rcu(&inst->hlist, &net_nfqnl->instance_table[h]); - -- spin_unlock(&instances_lock); -+ spin_unlock(&net_nfqnl->instances_lock); - - return inst; - - out_free: - kfree(inst); - out_unlock: -- spin_unlock(&instances_lock); -+ spin_unlock(&net_nfqnl->instances_lock); - return ERR_PTR(err); - } - -@@ -157,11 +163,13 @@ __instance_destroy(struct nfqnl_instance *inst) - } - - static void --instance_destroy(struct nfqnl_instance *inst) -+instance_destroy(struct net *net, struct nfqnl_instance *inst) - { -- spin_lock(&instances_lock); -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); -+ -+ spin_lock(&net_nfqnl->instances_lock); - __instance_destroy(inst); -- spin_unlock(&instances_lock); -+ spin_unlock(&net_nfqnl->instances_lock); - } - - static inline void -@@ -383,14 +391,15 @@ nla_put_failure: - } - - static int --nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - struct sk_buff *nskb; - struct nfqnl_instance *queue; - int err; - - /* rcu_read_lock()ed by nf_hook_slow() */ -- queue = instance_lookup(queuenum); -+ queue = instance_lookup(net, queuenum); - if (!queue) - goto err_out; - -@@ -416,7 +425,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - } - - /* nfnetlink_unicast will either free the nskb or add it to a socket */ -- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); -+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); - if (err < 0) { - queue->queue_user_dropped++; - goto err_out_unlock; -@@ -525,16 +534,17 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) - /* drop all packets with either indev or outdev == ifindex from all queue - * instances */ - static void --nfqnl_dev_drop(int ifindex) -+nfqnl_dev_drop(struct net *net, int ifindex) - { - int i; -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - - rcu_read_lock(); - - for (i = 0; i < INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = &net_nfqnl->instance_table[i]; - - hlist_for_each_entry_rcu(inst, tmp, head, hlist) - nfqnl_flush(inst, dev_cmp, ifindex); -@@ -551,12 +561,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, - { - struct net_device *dev = ptr; - -- if (!net_eq(dev_net(dev), &init_net)) -- return NOTIFY_DONE; -- - /* Drop any packets associated with the downed device */ - if (event == NETDEV_DOWN) -- nfqnl_dev_drop(dev->ifindex); -+ nfqnl_dev_drop(dev_net(dev), dev->ifindex); - return NOTIFY_DONE; - } - -@@ -569,24 +576,25 @@ nfqnl_rcv_nl_event(struct notifier_block *this, - unsigned long event, void *ptr) - { - struct netlink_notify *n = ptr; -+ struct netns_nfqnl *net_nfqnl = net_generic(n->net, nfqnl_net_id); - - if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { - int i; - - /* destroy all instances for this pid */ -- spin_lock(&instances_lock); -+ spin_lock(&net_nfqnl->instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &net_nfqnl->instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((n->net == &init_net) && -- (n->pid == inst->peer_pid)) -+ if (n->pid == inst->peer_pid) - __instance_destroy(inst); - } - } -- spin_unlock(&instances_lock); -+ spin_unlock(&net_nfqnl->instances_lock); - } - return NOTIFY_DONE; - } -@@ -614,9 +622,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, - unsigned int verdict; - struct nf_queue_entry *entry; - int err; -+ struct net *net = sock_net(ctnl); - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) { - err = -ENODEV; - goto err_out_unlock; -@@ -692,6 +701,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - struct nfqnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); - - if (nfqa[NFQA_CFG_CMD]) { - cmd = nla_data(nfqa[NFQA_CFG_CMD]); -@@ -708,7 +718,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { - ret = -EPERM; - goto err_out_unlock; -@@ -721,7 +731,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -EBUSY; - goto err_out_unlock; - } -- queue = instance_create(queue_num, NETLINK_CB(skb).pid); -+ queue = instance_create(net, queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) { - ret = PTR_ERR(queue); - goto err_out_unlock; -@@ -732,7 +743,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -ENODEV; - goto err_out_unlock; - } -- instance_destroy(queue); -+ instance_destroy(net, queue); - break; - case NFQNL_CFG_CMD_PF_BIND: - case NFQNL_CFG_CMD_PF_UNBIND: -@@ -799,13 +810,15 @@ struct iter_state { - static struct hlist_node *get_first(struct seq_file *seq) - { - struct iter_state *st = seq->private; -+ struct net *net = seq_file_net(seq); -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - - if (!st) - return NULL; - - for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return instance_table[st->bucket].first; -+ if (!hlist_empty(&net_nfqnl->instance_table[st->bucket])) -+ return net_nfqnl->instance_table[st->bucket].first; - } - return NULL; - } -@@ -813,13 +826,15 @@ static struct hlist_node *get_first(struct seq_file *seq) - static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) - { - struct iter_state *st = seq->private; -+ struct net *net = seq_file_net(seq); -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - - h = h->next; - while (!h) { - if (++st->bucket >= INSTANCE_BUCKETS) - return NULL; - -- h = instance_table[st->bucket].first; -+ h = net_nfqnl->instance_table[st->bucket].first; - } - return h; - } -@@ -836,9 +851,11 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) - } - - static void *seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(instances_lock) - { -- spin_lock(&instances_lock); -+ struct netns_nfqnl *net_nfqnl = -+ net_generic(seq_file_net(seq), nfqnl_net_id); -+ -+ spin_lock(&net_nfqnl->instances_lock); - return get_idx(seq, *pos); - } - -@@ -849,9 +866,11 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - } - - static void seq_stop(struct seq_file *s, void *v) -- __releases(instances_lock) - { -- spin_unlock(&instances_lock); -+ struct netns_nfqnl *net_nfqnl = -+ net_generic(seq_file_net(s), nfqnl_net_id); -+ -+ spin_unlock(&net_nfqnl->instances_lock); - } - - static int seq_show(struct seq_file *s, void *v) -@@ -875,8 +894,8 @@ static const struct seq_operations nfqnl_seq_ops = { - - static int nfqnl_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nfqnl_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nfqnl_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nfqnl_file_ops = { -@@ -884,54 +903,96 @@ static const struct file_operations nfqnl_file_ops = { - .open = nfqnl_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - --static int __init nfnetlink_queue_init(void) -+static int __net_init nfnetlink_queue_net_init(struct net *net) - { -- int i, status = -ENOMEM; -+ int err, i; -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - -+ spin_lock_init(&net_nfqnl->instances_lock); - for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -+ INIT_HLIST_HEAD(&net_nfqnl->instance_table[i]); - -- netlink_register_notifier(&nfqnl_rtnl_notifier); -- status = nfnetlink_subsys_register(&nfqnl_subsys); -- if (status < 0) { -+#ifdef CONFIG_PROC_FS -+ if (proc_net_fops_create(net, "nfnetlink_queue", 0440, -+ &nfqnl_file_ops) == NULL) -+ return -ENOMEM; -+#endif -+ -+ err = nfnetlink_subsys_register(net, &nfqnl_subsys); -+ if (err < 0) { - printk(KERN_ERR "nf_queue: failed to create netlink socket\n"); -- goto cleanup_netlink_notifier; -+ goto cleanup_proc; - } - -+ return 0; -+ -+cleanup_proc: - #ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_queue", 0440, -- proc_net_netfilter, &nfqnl_file_ops)) -- goto cleanup_subsys; -+ proc_net_remove(net, "nfnetlink_queue"); - #endif -+ return err; -+} - -- register_netdevice_notifier(&nfqnl_dev_notifier); -- return status; -+static void __net_exit nfnetlink_queue_net_exit(struct net *net) -+{ -+ int i; -+ struct netns_nfqnl *net_nfqnl = net_generic(net, nfqnl_net_id); - -+ nfnetlink_subsys_unregister(net, &nfqnl_subsys); - #ifdef CONFIG_PROC_FS --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfqnl_subsys); -+ proc_net_remove(net, "nfnetlink_queue"); - #endif --cleanup_netlink_notifier: -- netlink_unregister_notifier(&nfqnl_rtnl_notifier); -- return status; -+ -+ spin_lock(&net_nfqnl->instances_lock); -+ for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ struct hlist_node *tmp, *t2; -+ struct nfqnl_instance *inst; -+ struct hlist_head *head = &net_nfqnl->instance_table[i]; -+ -+ hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) -+ __instance_destroy(inst); -+ } -+ spin_unlock(&net_nfqnl->instances_lock); -+} -+ -+static struct pernet_operations nfnetlink_queue_net_ops = { -+ .init = nfnetlink_queue_net_init, -+ .exit = nfnetlink_queue_net_exit, -+ .id = &nfqnl_net_id, -+ .size = sizeof(struct netns_nfqnl), -+}; -+ -+static int __init nfnetlink_queue_init(void) -+{ -+ int err; -+ -+ err = register_pernet_subsys(&nfnetlink_queue_net_ops); -+ if (err) { -+ pr_err("nfnetlink_queue_init: " -+ "cannot initialize per netns operations\n"); -+ return err; -+ } -+ -+ netlink_register_notifier(&nfqnl_rtnl_notifier); -+ register_netdevice_notifier(&nfqnl_dev_notifier); -+ -+ return err; - } - - static void __exit nfnetlink_queue_fini(void) - { - nf_unregister_queue_handlers(&nfqh); - unregister_netdevice_notifier(&nfqnl_dev_notifier); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_queue", proc_net_netfilter); --#endif -- nfnetlink_subsys_unregister(&nfqnl_subsys); - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - - rcu_barrier(); /* Wait for completion of call_rcu()'s */ -+ -+ unregister_pernet_subsys(&nfnetlink_queue_net_ops); - } - - MODULE_DESCRIPTION("netfilter packet queue handler"); -diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c -index 4327e10..62fdeb1 100644 ---- a/net/netfilter/xt_osf.c -+++ b/net/netfilter/xt_osf.c -@@ -31,6 +31,7 @@ - - #include - #include -+#include - - #include - #include -@@ -359,6 +360,27 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) - return fmatch == FMATCH_OK; - } - -+static int __net_init xt_osf_net_init(struct net *net) -+{ -+ int err; -+ -+ err = nfnetlink_subsys_register(net, &xt_osf_nfnetlink); -+ if (err < 0) -+ pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err); -+ -+ return err; -+} -+ -+static void __net_exit xt_osf_net_exit(struct net *net) -+{ -+ nfnetlink_subsys_unregister(net, &xt_osf_nfnetlink); -+} -+ -+static struct pernet_operations xt_osf_net_ops = { -+ .init = xt_osf_net_init, -+ .exit = xt_osf_net_exit, -+}; -+ - static struct xt_match xt_osf_match = { - .name = "osf", - .revision = 0, -@@ -374,29 +396,26 @@ static struct xt_match xt_osf_match = { - - static int __init xt_osf_init(void) - { -- int err = -EINVAL; -+ int err; - int i; - - for (i=0; i> .config; \ - fi && \ - fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch - -.PHONY: debcheck -debcheck: - for d in $(DEPDEBS); do \ - if ! dpkg-query -s $$d > /dev/null 2>&1; then \ - echo ERROR: build dependency not installed: $$d >&2; \ - exit 1; \ - fi; \ - done - -.PHONY: defaultconfig -defaultconfig: linux-source-$(VERSION) - export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure - -.PHONY: patch -patch: linux-source-$(VERSION) patch-stamp -patch-stamp: $(PATCHES) - for p in $^; do \ - if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ - echo ERROR: applying patch failed: $$p >&2; \ - exit 1; \ - fi; \ - done - touch patch-stamp - -linux-source-$(VERSION): $(TARBALL) - tar -xjf $^ - -.PHONY: clean -clean: - rm -rf linux-source-$(VERSION) patch-stamp diff --git a/kernel/core-kernel-3.0/README.txt b/kernel/core-kernel-3.0/README.txt deleted file mode 100644 index 5e473f58..00000000 --- a/kernel/core-kernel-3.0/README.txt +++ /dev/null @@ -1,9 +0,0 @@ -Author: Tom Goff - -The Makefile is basically a wrapper around the make-kpkg command that -simplifies building kernel packages. Running make will do some basic -dependency checks then build architecture appropriate kernel packages that -include changes from the patches directory. The nfnetlink patch is what -virtualizes the netfilter queue mechanism; the flow-cache patch allows using -IPsec between network namespaces; the ifindex patch virtualizes network -interface index numbers. diff --git a/kernel/core-kernel-3.0/config.core b/kernel/core-kernel-3.0/config.core deleted file mode 100644 index 27c7ef7a..00000000 --- a/kernel/core-kernel-3.0/config.core +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XFRM_STATISTICS=y diff --git a/kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch b/kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch deleted file mode 100644 index 73ebc8db..00000000 --- a/kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch +++ /dev/null @@ -1,49 +0,0 @@ -commit 0542b69e2c57fc9668ce6a03155bea6e1f557901 -Author: dpward -Date: Wed Aug 31 06:05:27 2011 +0000 - - net: Make flow cache namespace-aware - - flow_cache_lookup will return a cached object (or null pointer) that the - resolver (i.e. xfrm_policy_lookup) previously found for another namespace - using the same key/family/dir. Instead, make the namespace part of what - identifies entries in the cache. - - As before, flow_entry_valid will return 0 for entries where the namespace - has been deleted, and they will be removed from the cache the next time - flow_cache_gc_task is run. - - Reported-by: Andrew Dickinson - Signed-off-by: David Ward - Signed-off-by: David S. Miller - -diff --git a/net/core/flow.c b/net/core/flow.c -index bf32c33..47b6d26 100644 ---- a/net/core/flow.c -+++ b/net/core/flow.c -@@ -30,6 +30,7 @@ struct flow_cache_entry { - struct hlist_node hlist; - struct list_head gc_list; - } u; -+ struct net *net; - u16 family; - u8 dir; - u32 genid; -@@ -232,7 +233,8 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, - - hash = flow_hash_code(fc, fcp, key); - hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) { -- if (tfle->family == family && -+ if (tfle->net == net && -+ tfle->family == family && - tfle->dir == dir && - flow_key_compare(key, &tfle->key) == 0) { - fle = tfle; -@@ -246,6 +248,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, - - fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); - if (fle) { -+ fle->net = net; - fle->family = family; - fle->dir = dir; - memcpy(&fle->key, key, sizeof(*key)); diff --git a/kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch b/kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch deleted file mode 100644 index 0f387b69..00000000 --- a/kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch +++ /dev/null @@ -1,51 +0,0 @@ -commit 7da7dfcb787d77929c15d5b7127c816ee16f1ede -Author: Tom Goff -Date: Fri Dec 16 17:39:00 2011 -0800 - - Make network device ifindex sequential per network namespace. - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 3bb6fa0..2fd53da 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -62,6 +62,8 @@ struct net { - struct sock *rtnl; /* rtnetlink socket */ - struct sock *genl_sock; - -+ int ifindex; -+ - struct list_head dev_base_head; - struct hlist_head *dev_name_head; - struct hlist_head *dev_index_head; -diff --git a/net/core/dev.c b/net/core/dev.c -index 6ba50a1..ba95aa5 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -5260,12 +5260,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) - */ - static int dev_new_index(struct net *net) - { -- static int ifindex; - for (;;) { -- if (++ifindex <= 0) -- ifindex = 1; -- if (!__dev_get_by_index(net, ifindex)) -- return ifindex; -+ if (++net->ifindex <= 0) -+ net->ifindex = 1; -+ if (!__dev_get_by_index(net, net->ifindex)) -+ return net->ifindex; - } - } - -@@ -6277,8 +6276,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char - /* Actually switch the network namespace */ - dev_net_set(dev, net); - -- /* If there is an ifindex conflict assign a new one */ -- if (__dev_get_by_index(net, dev->ifindex)) { -+ /* Assign a new ifindex */ -+ { - int iflink = (dev->iflink == dev->ifindex); - dev->ifindex = dev_new_index(net); - if (iflink) diff --git a/kernel/core-kernel-3.0/patches/00-linux-3.0.nfnetlink_queue.patch b/kernel/core-kernel-3.0/patches/00-linux-3.0.nfnetlink_queue.patch deleted file mode 100644 index 80716881..00000000 --- a/kernel/core-kernel-3.0/patches/00-linux-3.0.nfnetlink_queue.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 4b819adab7892f61a96bab1e36e5d9a74018432b Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Tue, 3 Jan 2012 14:39:04 -0800 -Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per - netns. - -This allows subsystems to create per-netns entries. - -Signed-off-by: Tom Goff ---- - include/linux/netfilter.h | 5 ---- - include/net/net_namespace.h | 3 ++ - net/netfilter/core.c | 35 +++++++++++++++++++++++------- - net/netfilter/nf_log.c | 33 +++++++++++++++++++++++++--- - net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++--- - net/netfilter/nfnetlink_log.c | 44 ++++++++++++++++++++++++++----------- - net/netfilter/nfnetlink_queue.c | 45 ++++++++++++++++++++++++++------------ - 7 files changed, 148 insertions(+), 48 deletions(-) - -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index 857f502..b4e02fb 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) - #endif - } - --#ifdef CONFIG_PROC_FS --#include --extern struct proc_dir_entry *proc_net_netfilter; --#endif -- - #else /* !CONFIG_NETFILTER */ - #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) - #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 3bb6fa0..cf126ef 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -84,6 +84,9 @@ struct net { - struct netns_dccp dccp; - #endif - #ifdef CONFIG_NETFILTER -+#ifdef CONFIG_PROC_FS -+ struct proc_dir_entry *proc_net_netfilter; -+#endif - struct netns_xt xt; - #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - struct netns_ct ct; -diff --git a/net/netfilter/core.c b/net/netfilter/core.c -index afca6c7..9d9b103 100644 ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) - EXPORT_SYMBOL(nf_conntrack_destroy); - #endif /* CONFIG_NF_CONNTRACK */ - -+static int __net_init netfilter_net_init(struct net *net) -+{ - #ifdef CONFIG_PROC_FS --struct proc_dir_entry *proc_net_netfilter; --EXPORT_SYMBOL(proc_net_netfilter); -+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", -+ net->proc_net); -+ if (!net->proc_net_netfilter) { -+ pr_err("%s: cannot create netfilter proc entry\n", __func__); -+ return -ENOMEM; -+ } - #endif - -+ return 0; -+} -+ -+static void __net_exit netfilter_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ proc_net_remove(net, "netfilter"); -+#endif -+} -+ -+static struct pernet_operations netfilter_net_ops = { -+ .init = netfilter_net_init, -+ .exit = netfilter_net_exit, -+}; -+ - void __init netfilter_init(void) - { - int i, h; -+ -+ if (register_pernet_subsys(&netfilter_net_ops)) -+ panic("%s: failed to register per netns operations", __func__); -+ - for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - INIT_LIST_HEAD(&nf_hooks[i][h]); - } - --#ifdef CONFIG_PROC_FS -- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); -- if (!proc_net_netfilter) -- panic("cannot create netfilter proc entry"); --#endif -- - if (netfilter_queue_init() < 0) - panic("cannot initialize nf_queue"); - if (netfilter_log_init() < 0) -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index ce0c406..ccc15d6 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void) - } - #endif /* CONFIG_SYSCTL */ - --int __init netfilter_log_init(void) -+static int __net_init netfilter_log_net_init(struct net *net) - { -- int i, r; - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_log", S_IRUGO, -- proc_net_netfilter, &nflog_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nflog_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_log", net->proc_net_netfilter); - #endif -+} -+ -+static struct pernet_operations netfilter_log_net_ops = { -+ .init = netfilter_log_net_init, -+ .exit = netfilter_log_net_exit, -+}; -+ -+int __init netfilter_log_init(void) -+{ -+ int i, r; -+ -+ r = register_pernet_subsys(&netfilter_log_net_ops); -+ if (r) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return r; -+ } - - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index 99ffd28..ecb84a3 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = { - }; - #endif /* PROC_FS */ - -- --int __init netfilter_queue_init(void) -+static int __net_init netfilter_queue_net_init(struct net *net) - { - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_queue", S_IRUGO, -- proc_net_netfilter, &nfqueue_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nfqueue_file_ops)) -+ return -ENOMEM; - #endif -+ - return 0; - } - -+static void __net_exit netfilter_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations netfilter_queue_net_ops = { -+ .init = netfilter_queue_net_init, -+ .exit = netfilter_queue_net_exit, -+}; -+ -+int __init netfilter_queue_init(void) -+{ -+ int err; -+ -+ err = register_pernet_subsys(&netfilter_queue_net_ops); -+ if (err) -+ pr_err("%s: cannot initialize per netns operations\n", -+ __func__); -+ -+ return err; -+} -diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index 66b2c54..e4c3c1e 100644 ---- a/net/netfilter/nfnetlink_log.c -+++ b/net/netfilter/nfnetlink_log.c -@@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_log_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_log", 0440, -+ net->proc_net_netfilter, &nful_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_log_net_ops = { -+ .init = nfnetlink_log_net_init, -+ .exit = nfnetlink_log_net_exit, -+}; -+ - static int __init nfnetlink_log_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_log_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void) - goto cleanup_subsys; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_log", 0440, -- proc_net_netfilter, &nful_file_ops)) -- goto cleanup_logger; --#endif - return status; - --#ifdef CONFIG_PROC_FS --cleanup_logger: -- nf_log_unregister(&nfulnl_logger); --#endif - cleanup_subsys: - nfnetlink_subsys_unregister(&nfulnl_subsys); - cleanup_netlink_notifier: -@@ -996,9 +1017,6 @@ cleanup_netlink_notifier: - static void __exit nfnetlink_log_fini(void) - { - nf_log_unregister(&nfulnl_logger); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_log", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfulnl_subsys); - netlink_unregister_notifier(&nfulnl_rtnl_notifier); - } -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index a80b0cb..b615da5 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_queue_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_queue", 0440, -+ net->proc_net_netfilter, &nfqnl_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_queue_net_ops = { -+ .init = nfnetlink_queue_net_init, -+ .exit = nfnetlink_queue_net_exit, -+}; -+ - static int __init nfnetlink_queue_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_queue_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void) - goto cleanup_netlink_notifier; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_queue", 0440, -- proc_net_netfilter, &nfqnl_file_ops)) -- goto cleanup_subsys; --#endif -- - register_netdevice_notifier(&nfqnl_dev_notifier); - return status; - --#ifdef CONFIG_PROC_FS --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfqnl_subsys); --#endif - cleanup_netlink_notifier: - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - return status; -@@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void) - { - nf_unregister_queue_handlers(&nfqh); - unregister_netdevice_notifier(&nfqnl_dev_notifier); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_queue", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfqnl_subsys); - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - --- -1.7.5.4 - diff --git a/kernel/core-kernel-3.0/patches/01-linux-3.0.nfnetlink_queue.patch b/kernel/core-kernel-3.0/patches/01-linux-3.0.nfnetlink_queue.patch deleted file mode 100644 index 26c08c05..00000000 --- a/kernel/core-kernel-3.0/patches/01-linux-3.0.nfnetlink_queue.patch +++ /dev/null @@ -1,516 +0,0 @@ -From dd504f32d24e9f239d429204c43a5c500c9853c6 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Tue, 3 Jan 2012 15:52:32 -0800 -Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. - -Make nfnetlink_queue network namespace aware including a per-netns -/proc/net/netfilter/nfnetlink_queue file. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 6 ++ - include/net/netfilter/nf_queue.h | 3 +- - include/net/netns/nfqnl.h | 14 ++++ - net/ipv4/netfilter/ip_queue.c | 6 ++- - net/ipv6/netfilter/ip6_queue.c | 6 ++- - net/netfilter/nf_queue.c | 12 +++- - net/netfilter/nfnetlink_queue.c | 138 +++++++++++++++++++------------------- - 7 files changed, 112 insertions(+), 73 deletions(-) - create mode 100644 include/net/netns/nfqnl.h - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index cf126ef..4b6f04a 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -21,6 +21,9 @@ - #include - #endif - #include -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+#include -+#endif - - struct proc_dir_entry; - struct net_device; -@@ -93,6 +96,9 @@ struct net { - #endif - struct sock *nfnl; - struct sock *nfnl_stash; -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+ struct netns_nfqnl nfqnl; -+#endif - #endif - #ifdef CONFIG_WEXT_CORE - struct sk_buff_head wext_nlevents; -diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h -index 252fd10..3e5bde8 100644 ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -19,7 +19,8 @@ struct nf_queue_entry { - - /* Packet queuing */ - struct nf_queue_handler { -- int (*outfn)(struct nf_queue_entry *entry, -+ int (*outfn)(struct net *net, -+ struct nf_queue_entry *entry, - unsigned int queuenum); - char *name; - }; -diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h -new file mode 100644 -index 0000000..0fe7fbe ---- /dev/null -+++ b/include/net/netns/nfqnl.h -@@ -0,0 +1,14 @@ -+#ifndef __NETNS_NFQNL_H -+#define __NETNS_NFQNL_H -+ -+#include -+#include -+ -+#define NFQNL_INSTANCE_BUCKETS 16 -+ -+struct netns_nfqnl { -+ spinlock_t instances_lock; -+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; -+}; -+ -+#endif /* __NETNS_NFQNL_H */ -diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c -index e59aabd..f3c43e5 100644 ---- a/net/ipv4/netfilter/ip_queue.c -+++ b/net/ipv4/netfilter/ip_queue.c -@@ -225,7 +225,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c -index e63c397..322c511 100644 ---- a/net/ipv6/netfilter/ip6_queue.c -+++ b/net/ipv6/netfilter/ip6_queue.c -@@ -225,7 +225,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index ecb84a3..9490bd5 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+ struct net *net; -+ -+ if (indev) -+ net = dev_net(indev); -+ else if (skb->sk) -+ net = sock_net(skb->sk); -+ else if (outdev) -+ net = dev_net(outdev); -+ else -+ return status; - - /* QUEUE == DROP if no one is waiting, to be safe. */ - rcu_read_lock(); -@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - skb_dst_force(skb); - afinfo->saveroute(skb, entry); -- status = qh->outfn(entry, queuenum); -+ status = qh->outfn(net, entry, queuenum); - - rcu_read_unlock(); - -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index b615da5..48ea6f4 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -64,24 +64,19 @@ struct nfqnl_instance { - - typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - --static DEFINE_SPINLOCK(instances_lock); -- --#define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; -- - static inline u_int8_t instance_hashfn(u_int16_t queue_num) - { -- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; -+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; - } - - static struct nfqnl_instance * --instance_lookup(u_int16_t queue_num) -+instance_lookup(struct net *net, u_int16_t queue_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfqnl_instance *inst; - -- head = &instance_table[instance_hashfn(queue_num)]; -+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->queue_num == queue_num) - return inst; -@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_create(u_int16_t queue_num, int pid) -+instance_create(struct net *net, u_int16_t queue_num, int pid) - { - struct nfqnl_instance *inst; - unsigned int h; - int err; - -- spin_lock(&instances_lock); -- if (instance_lookup(queue_num)) { -+ spin_lock(&net->nfqnl.instances_lock); -+ if (instance_lookup(net, queue_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) - } - - h = instance_hashfn(queue_num); -- hlist_add_head_rcu(&inst->hlist, &instance_table[h]); -+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - - return inst; - - out_free: - kfree(inst); - out_unlock: -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - return ERR_PTR(err); - } - -@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) - } - - static void --instance_destroy(struct nfqnl_instance *inst) -+instance_destroy(struct net *net, struct nfqnl_instance *inst) - { -- spin_lock(&instances_lock); -+ spin_lock(&net->nfqnl.instances_lock); - __instance_destroy(inst); -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static inline void -@@ -390,7 +385,8 @@ nla_put_failure: - } - - static int --nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - struct sk_buff *nskb; - struct nfqnl_instance *queue; -@@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - __be32 *packet_id_ptr; - - /* rcu_read_lock()ed by nf_hook_slow() */ -- queue = instance_lookup(queuenum); -+ queue = instance_lookup(net, queuenum); - if (!queue) { - err = -ESRCH; - goto err_out; -@@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - *packet_id_ptr = htonl(entry->id); - - /* nfnetlink_unicast will either free the nskb or add it to a socket */ -- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); -+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); - if (err < 0) { - queue->queue_user_dropped++; - goto err_out_unlock; -@@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) - /* drop all packets with either indev or outdev == ifindex from all queue - * instances */ - static void --nfqnl_dev_drop(int ifindex) -+nfqnl_dev_drop(struct net *net, int ifindex) - { - int i; - - rcu_read_lock(); - -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = &net->nfqnl.instance_table[i]; - - hlist_for_each_entry_rcu(inst, tmp, head, hlist) - nfqnl_flush(inst, dev_cmp, ifindex); -@@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, - { - struct net_device *dev = ptr; - -- if (!net_eq(dev_net(dev), &init_net)) -- return NOTIFY_DONE; -- - /* Drop any packets associated with the downed device */ - if (event == NETDEV_DOWN) -- nfqnl_dev_drop(dev->ifindex); -+ nfqnl_dev_drop(dev_net(dev), dev->ifindex); - return NOTIFY_DONE; - } - -@@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, - int i; - - /* destroy all instances for this pid */ -- spin_lock(&instances_lock); -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ spin_lock(&n->net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &n->net->nfqnl.instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((n->net == &init_net) && -- (n->pid == inst->peer_pid)) -+ if (n->pid == inst->peer_pid) - __instance_destroy(inst); - } - } -- spin_unlock(&instances_lock); -+ spin_unlock(&n->net->nfqnl.instances_lock); - } - return NOTIFY_DONE; - } -@@ -715,9 +710,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, - unsigned int verdict; - struct nf_queue_entry *entry; - int err; -+ struct net *net = sock_net(ctnl); - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) { - err = -ENODEV; - goto err_out_unlock; -@@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - struct nfqnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); - - if (nfqa[NFQA_CFG_CMD]) { - cmd = nla_data(nfqa[NFQA_CFG_CMD]); -@@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { - ret = -EPERM; - goto err_out_unlock; -@@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -EBUSY; - goto err_out_unlock; - } -- queue = instance_create(queue_num, NETLINK_CB(skb).pid); -+ queue = instance_create(net, queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) { - ret = PTR_ERR(queue); - goto err_out_unlock; -@@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -ENODEV; - goto err_out_unlock; - } -- instance_destroy(queue); -+ instance_destroy(net, queue); - break; - case NFQNL_CFG_CMD_PF_BIND: - case NFQNL_CFG_CMD_PF_UNBIND: -@@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { - - #ifdef CONFIG_PROC_FS - struct iter_state { -+ struct seq_net_private p; - unsigned int bucket; - }; - --static struct hlist_node *get_first(struct seq_file *seq) -+static struct hlist_node *get_first(struct net *net, struct iter_state *st) - { -- struct iter_state *st = seq->private; -- - if (!st) - return NULL; - -- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return instance_table[st->bucket].first; -+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { -+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) -+ return net->nfqnl.instance_table[st->bucket].first; - } - return NULL; - } - --static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) -+static struct hlist_node *get_next(struct net *net, struct iter_state *st, -+ struct hlist_node *h) - { -- struct iter_state *st = seq->private; -- - h = h->next; - while (!h) { -- if (++st->bucket >= INSTANCE_BUCKETS) -+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) - return NULL; - -- h = instance_table[st->bucket].first; -+ h = net->nfqnl.instance_table[st->bucket].first; - } - return h; - } - --static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) -+static struct hlist_node *get_idx(struct net *net, struct iter_state *st, -+ loff_t pos) - { - struct hlist_node *head; -- head = get_first(seq); -+ head = get_first(net, st); - - if (head) -- while (pos && (head = get_next(seq, head))) -+ while (pos && (head = get_next(net, st, head))) - pos--; - return pos ? NULL : head; - } - - static void *seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(instances_lock) - { -- spin_lock(&instances_lock); -- return get_idx(seq, *pos); -+ struct net *net = seq_file_net(seq); -+ spin_lock(&net->nfqnl.instances_lock); -+ return get_idx(net, seq->private, *pos); - } - - static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - { - (*pos)++; -- return get_next(s, v); -+ return get_next(seq_file_net(s), s->private, v); - } - - static void seq_stop(struct seq_file *s, void *v) -- __releases(instances_lock) - { -- spin_unlock(&instances_lock); -+ struct net *net = seq_file_net(s); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static int seq_show(struct seq_file *s, void *v) -@@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = { - - static int nfqnl_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nfqnl_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nfqnl_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nfqnl_file_ops = { -@@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = { - .open = nfqnl_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - - static int __net_init nfnetlink_queue_net_init(struct net *net) - { -+ int i; -+ -+ spin_lock_init(&net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) -+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); -+ - #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - net->proc_net_netfilter, &nfqnl_file_ops)) -@@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { - - static int __init nfnetlink_queue_init(void) - { -- int i, status; -+ int status; - - status = register_pernet_subsys(&nfnetlink_queue_net_ops); - if (status) { -@@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void) - return status; - } - -- for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -- - netlink_register_notifier(&nfqnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfqnl_subsys); - if (status < 0) { --- -1.7.5.4 - diff --git a/kernel/core-kernel-3.2/Makefile b/kernel/core-kernel-3.2/Makefile deleted file mode 100644 index a0bf6541..00000000 --- a/kernel/core-kernel-3.2/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -VERSION := 3.2.0 -TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 - -SUBVERSION := -core -REVISION := 1.0 - -PATCHDIR := patches -PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) - -CONFIG := config.core - -DEPDEBS := linux-source kernel-package po-debconf gettext - -CONCURRENCY_LEVEL := 8 - -MAINTAINER ?= Tom Goff -EMAIL ?= thomas.goff@boeing.com - -MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ - --append-to-version $(SUBVERSION) --revision $(REVISION) - -.PHONY: build -build: debcheck defaultconfig patch - export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ - KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && \ - if [ -f ../$(CONFIG) ]; then \ - cat ../$(CONFIG) >> .config; \ - fi && \ - fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch - -.PHONY: debcheck -debcheck: - for d in $(DEPDEBS); do \ - if ! dpkg-query -s $$d > /dev/null 2>&1; then \ - echo ERROR: build dependency not installed: $$d >&2; \ - exit 1; \ - fi; \ - done - -.PHONY: defaultconfig -defaultconfig: linux-source-$(VERSION) - export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure - -.PHONY: patch -patch: linux-source-$(VERSION) patch-stamp -patch-stamp: $(PATCHES) - for p in $^; do \ - if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ - echo ERROR: applying patch failed: $$p >&2; \ - exit 1; \ - fi; \ - done - touch patch-stamp - -linux-source-$(VERSION): $(TARBALL) - tar -xjf $^ - -.PHONY: clean -clean: - rm -rf linux-source-$(VERSION) patch-stamp diff --git a/kernel/core-kernel-3.2/README.txt b/kernel/core-kernel-3.2/README.txt deleted file mode 100644 index abfd9212..00000000 --- a/kernel/core-kernel-3.2/README.txt +++ /dev/null @@ -1,8 +0,0 @@ -Author: Tom Goff - -The Makefile is basically a wrapper around the make-kpkg command that -simplifies building kernel packages. Running make will do some basic -dependency checks then build architecture appropriate kernel packages that -include changes from the patches directory. The nfnetlink patch is what -virtualizes the netfilter queue mechanism; -the ifindex patch virtualizes network interface index numbers. diff --git a/kernel/core-kernel-3.2/config.core b/kernel/core-kernel-3.2/config.core deleted file mode 100644 index 27c7ef7a..00000000 --- a/kernel/core-kernel-3.2/config.core +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XFRM_STATISTICS=y diff --git a/kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch b/kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch deleted file mode 100644 index fa556298..00000000 --- a/kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 918e253ebaa3d28c54ff64b596a0afc8779d106a Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Fri, 27 Jul 2012 00:02:50 -0700 -Subject: [PATCH] Make network device ifindex sequential per network - namespace. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 2 ++ - net/core/dev.c | 13 ++++++------- - 2 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 4b6f04a..266e747 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -65,6 +65,8 @@ struct net { - struct sock *rtnl; /* rtnetlink socket */ - struct sock *genl_sock; - -+ int ifindex; -+ - struct list_head dev_base_head; - struct hlist_head *dev_name_head; - struct hlist_head *dev_index_head; -diff --git a/net/core/dev.c b/net/core/dev.c -index 1cbddc9..d7f5711 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -5236,12 +5236,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) - */ - static int dev_new_index(struct net *net) - { -- static int ifindex; - for (;;) { -- if (++ifindex <= 0) -- ifindex = 1; -- if (!__dev_get_by_index(net, ifindex)) -- return ifindex; -+ if (++net->ifindex <= 0) -+ net->ifindex = 1; -+ if (!__dev_get_by_index(net, net->ifindex)) -+ return net->ifindex; - } - } - -@@ -6253,8 +6252,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char - /* Actually switch the network namespace */ - dev_net_set(dev, net); - -- /* If there is an ifindex conflict assign a new one */ -- if (__dev_get_by_index(net, dev->ifindex)) { -+ /* Assign a new ifindex */ -+ { - int iflink = (dev->iflink == dev->ifindex); - dev->ifindex = dev_new_index(net); - if (iflink) --- -1.7.9.5 - diff --git a/kernel/core-kernel-3.2/patches/00-linux-3.2.nfnetlink_queue.patch b/kernel/core-kernel-3.2/patches/00-linux-3.2.nfnetlink_queue.patch deleted file mode 100644 index 2c268435..00000000 --- a/kernel/core-kernel-3.2/patches/00-linux-3.2.nfnetlink_queue.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 67765faf27ec646bcc008bd34d12e48a7466dcdd Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Thu, 26 Jul 2012 23:57:06 -0700 -Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per - netns. - -This allows subsystems to create per-netns entries. - -Signed-off-by: Tom Goff ---- - include/linux/netfilter.h | 5 ----- - include/net/net_namespace.h | 3 +++ - net/netfilter/core.c | 35 +++++++++++++++++++++++------- - net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++---- - net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++---- - net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++----------- - net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------ - 7 files changed, 148 insertions(+), 48 deletions(-) - -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index 857f502..b4e02fb 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) - #endif - } - --#ifdef CONFIG_PROC_FS --#include --extern struct proc_dir_entry *proc_net_netfilter; --#endif -- - #else /* !CONFIG_NETFILTER */ - #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) - #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 3bb6fa0..cf126ef 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -84,6 +84,9 @@ struct net { - struct netns_dccp dccp; - #endif - #ifdef CONFIG_NETFILTER -+#ifdef CONFIG_PROC_FS -+ struct proc_dir_entry *proc_net_netfilter; -+#endif - struct netns_xt xt; - #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - struct netns_ct ct; -diff --git a/net/netfilter/core.c b/net/netfilter/core.c -index afca6c7..9d9b103 100644 ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) - EXPORT_SYMBOL(nf_conntrack_destroy); - #endif /* CONFIG_NF_CONNTRACK */ - -+static int __net_init netfilter_net_init(struct net *net) -+{ - #ifdef CONFIG_PROC_FS --struct proc_dir_entry *proc_net_netfilter; --EXPORT_SYMBOL(proc_net_netfilter); -+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", -+ net->proc_net); -+ if (!net->proc_net_netfilter) { -+ pr_err("%s: cannot create netfilter proc entry\n", __func__); -+ return -ENOMEM; -+ } - #endif - -+ return 0; -+} -+ -+static void __net_exit netfilter_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ proc_net_remove(net, "netfilter"); -+#endif -+} -+ -+static struct pernet_operations netfilter_net_ops = { -+ .init = netfilter_net_init, -+ .exit = netfilter_net_exit, -+}; -+ - void __init netfilter_init(void) - { - int i, h; -+ -+ if (register_pernet_subsys(&netfilter_net_ops)) -+ panic("%s: failed to register per netns operations", __func__); -+ - for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - INIT_LIST_HEAD(&nf_hooks[i][h]); - } - --#ifdef CONFIG_PROC_FS -- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); -- if (!proc_net_netfilter) -- panic("cannot create netfilter proc entry"); --#endif -- - if (netfilter_queue_init() < 0) - panic("cannot initialize nf_queue"); - if (netfilter_log_init() < 0) -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index 957374a..c546ad7 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void) - } - #endif /* CONFIG_SYSCTL */ - --int __init netfilter_log_init(void) -+static int __net_init netfilter_log_net_init(struct net *net) - { -- int i, r; - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_log", S_IRUGO, -- proc_net_netfilter, &nflog_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nflog_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_log", net->proc_net_netfilter); - #endif -+} -+ -+static struct pernet_operations netfilter_log_net_ops = { -+ .init = netfilter_log_net_init, -+ .exit = netfilter_log_net_exit, -+}; -+ -+int __init netfilter_log_init(void) -+{ -+ int i, r; -+ -+ r = register_pernet_subsys(&netfilter_log_net_ops); -+ if (r) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return r; -+ } - - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index b3a7db6..470ec3a 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = { - }; - #endif /* PROC_FS */ - -- --int __init netfilter_queue_init(void) -+static int __net_init netfilter_queue_net_init(struct net *net) - { - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_queue", S_IRUGO, -- proc_net_netfilter, &nfqueue_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nfqueue_file_ops)) -+ return -ENOMEM; - #endif -+ - return 0; - } - -+static void __net_exit netfilter_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations netfilter_queue_net_ops = { -+ .init = netfilter_queue_net_init, -+ .exit = netfilter_queue_net_exit, -+}; -+ -+int __init netfilter_queue_init(void) -+{ -+ int err; -+ -+ err = register_pernet_subsys(&netfilter_queue_net_ops); -+ if (err) -+ pr_err("%s: cannot initialize per netns operations\n", -+ __func__); -+ -+ return err; -+} -diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index 66b2c54..e4c3c1e 100644 ---- a/net/netfilter/nfnetlink_log.c -+++ b/net/netfilter/nfnetlink_log.c -@@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_log_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_log", 0440, -+ net->proc_net_netfilter, &nful_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_log_net_ops = { -+ .init = nfnetlink_log_net_init, -+ .exit = nfnetlink_log_net_exit, -+}; -+ - static int __init nfnetlink_log_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_log_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void) - goto cleanup_subsys; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_log", 0440, -- proc_net_netfilter, &nful_file_ops)) -- goto cleanup_logger; --#endif - return status; - --#ifdef CONFIG_PROC_FS --cleanup_logger: -- nf_log_unregister(&nfulnl_logger); --#endif - cleanup_subsys: - nfnetlink_subsys_unregister(&nfulnl_subsys); - cleanup_netlink_notifier: -@@ -996,9 +1017,6 @@ cleanup_netlink_notifier: - static void __exit nfnetlink_log_fini(void) - { - nf_log_unregister(&nfulnl_logger); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_log", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfulnl_subsys); - netlink_unregister_notifier(&nfulnl_rtnl_notifier); - } -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index a80b0cb..b615da5 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_queue_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_queue", 0440, -+ net->proc_net_netfilter, &nfqnl_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_queue_net_ops = { -+ .init = nfnetlink_queue_net_init, -+ .exit = nfnetlink_queue_net_exit, -+}; -+ - static int __init nfnetlink_queue_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_queue_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void) - goto cleanup_netlink_notifier; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_queue", 0440, -- proc_net_netfilter, &nfqnl_file_ops)) -- goto cleanup_subsys; --#endif -- - register_netdevice_notifier(&nfqnl_dev_notifier); - return status; - --#ifdef CONFIG_PROC_FS --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfqnl_subsys); --#endif - cleanup_netlink_notifier: - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - return status; -@@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void) - { - nf_unregister_queue_handlers(&nfqh); - unregister_netdevice_notifier(&nfqnl_dev_notifier); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_queue", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfqnl_subsys); - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - --- -1.7.9.5 - diff --git a/kernel/core-kernel-3.2/patches/01-linux-3.2.nfnetlink_queue.patch b/kernel/core-kernel-3.2/patches/01-linux-3.2.nfnetlink_queue.patch deleted file mode 100644 index b931f365..00000000 --- a/kernel/core-kernel-3.2/patches/01-linux-3.2.nfnetlink_queue.patch +++ /dev/null @@ -1,544 +0,0 @@ -From f8179877a37f37631d831de6381f22fd643b4ea0 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Thu, 26 Jul 2012 23:58:38 -0700 -Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. - -Make nfnetlink_queue network namespace aware including a per-netns -/proc/net/netfilter/nfnetlink_queue file. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 6 ++ - include/net/netfilter/nf_queue.h | 3 +- - include/net/netns/nfqnl.h | 14 ++++ - net/ipv4/netfilter/ip_queue.c | 6 +- - net/ipv6/netfilter/ip6_queue.c | 6 +- - net/netfilter/nf_queue.c | 12 +++- - net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++------------------- - 7 files changed, 111 insertions(+), 72 deletions(-) - create mode 100644 include/net/netns/nfqnl.h - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index cf126ef..4b6f04a 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -21,6 +21,9 @@ - #include - #endif - #include -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+#include -+#endif - - struct proc_dir_entry; - struct net_device; -@@ -93,6 +96,9 @@ struct net { - #endif - struct sock *nfnl; - struct sock *nfnl_stash; -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+ struct netns_nfqnl nfqnl; -+#endif - #endif - #ifdef CONFIG_WEXT_CORE - struct sk_buff_head wext_nlevents; -diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h -index 252fd10..3e5bde8 100644 ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -19,7 +19,8 @@ struct nf_queue_entry { - - /* Packet queuing */ - struct nf_queue_handler { -- int (*outfn)(struct nf_queue_entry *entry, -+ int (*outfn)(struct net *net, -+ struct nf_queue_entry *entry, - unsigned int queuenum); - char *name; - }; -diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h -new file mode 100644 -index 0000000..0fe7fbe ---- /dev/null -+++ b/include/net/netns/nfqnl.h -@@ -0,0 +1,14 @@ -+#ifndef __NETNS_NFQNL_H -+#define __NETNS_NFQNL_H -+ -+#include -+#include -+ -+#define NFQNL_INSTANCE_BUCKETS 16 -+ -+struct netns_nfqnl { -+ spinlock_t instances_lock; -+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; -+}; -+ -+#endif /* __NETNS_NFQNL_H */ -diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c -index e59aabd..f3c43e5 100644 ---- a/net/ipv4/netfilter/ip_queue.c -+++ b/net/ipv4/netfilter/ip_queue.c -@@ -225,7 +225,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c -index e63c397..322c511 100644 ---- a/net/ipv6/netfilter/ip6_queue.c -+++ b/net/ipv6/netfilter/ip6_queue.c -@@ -225,7 +225,8 @@ nlmsg_failure: - } - - static int --ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - int status = -EINVAL; - struct sk_buff *nskb; -@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - - spin_lock_bh(&queue_lock); - -+ if (!net_eq(net, &init_net)) -+ goto err_out_free_nskb; -+ - if (!peer_pid) - goto err_out_free_nskb; - -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index 470ec3a..6894ecc 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+ struct net *net; -+ -+ if (indev) -+ net = dev_net(indev); -+ else if (skb->sk) -+ net = sock_net(skb->sk); -+ else if (outdev) -+ net = dev_net(outdev); -+ else -+ return status; - - /* QUEUE == DROP if no one is waiting, to be safe. */ - rcu_read_lock(); -@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - skb_dst_force(skb); - afinfo->saveroute(skb, entry); -- status = qh->outfn(entry, queuenum); -+ status = qh->outfn(net, entry, queuenum); - - rcu_read_unlock(); - -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index b615da5..11725a0 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -64,24 +64,19 @@ struct nfqnl_instance { - - typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - --static DEFINE_SPINLOCK(instances_lock); -- --#define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; -- - static inline u_int8_t instance_hashfn(u_int16_t queue_num) - { -- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; -+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; - } - - static struct nfqnl_instance * --instance_lookup(u_int16_t queue_num) -+instance_lookup(struct net *net, u_int16_t queue_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfqnl_instance *inst; - -- head = &instance_table[instance_hashfn(queue_num)]; -+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->queue_num == queue_num) - return inst; -@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_create(u_int16_t queue_num, int pid) -+instance_create(struct net *net, u_int16_t queue_num, int pid) - { - struct nfqnl_instance *inst; - unsigned int h; - int err; - -- spin_lock(&instances_lock); -- if (instance_lookup(queue_num)) { -+ spin_lock(&net->nfqnl.instances_lock); -+ if (instance_lookup(net, queue_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) - } - - h = instance_hashfn(queue_num); -- hlist_add_head_rcu(&inst->hlist, &instance_table[h]); -+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - - return inst; - - out_free: - kfree(inst); - out_unlock: -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - return ERR_PTR(err); - } - -@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) - } - - static void --instance_destroy(struct nfqnl_instance *inst) -+instance_destroy(struct net *net, struct nfqnl_instance *inst) - { -- spin_lock(&instances_lock); -+ spin_lock(&net->nfqnl.instances_lock); - __instance_destroy(inst); -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static inline void -@@ -390,7 +385,8 @@ nla_put_failure: - } - - static int --nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - struct sk_buff *nskb; - struct nfqnl_instance *queue; -@@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - __be32 *packet_id_ptr; - - /* rcu_read_lock()ed by nf_hook_slow() */ -- queue = instance_lookup(queuenum); -+ queue = instance_lookup(net, queuenum); - if (!queue) { - err = -ESRCH; - goto err_out; -@@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - *packet_id_ptr = htonl(entry->id); - - /* nfnetlink_unicast will either free the nskb or add it to a socket */ -- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); -+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); - if (err < 0) { - queue->queue_user_dropped++; - goto err_out_unlock; -@@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) - /* drop all packets with either indev or outdev == ifindex from all queue - * instances */ - static void --nfqnl_dev_drop(int ifindex) -+nfqnl_dev_drop(struct net *net, int ifindex) - { - int i; - - rcu_read_lock(); - -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = &net->nfqnl.instance_table[i]; - - hlist_for_each_entry_rcu(inst, tmp, head, hlist) - nfqnl_flush(inst, dev_cmp, ifindex); -@@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, - { - struct net_device *dev = ptr; - -- if (!net_eq(dev_net(dev), &init_net)) -- return NOTIFY_DONE; -- - /* Drop any packets associated with the downed device */ - if (event == NETDEV_DOWN) -- nfqnl_dev_drop(dev->ifindex); -+ nfqnl_dev_drop(dev_net(dev), dev->ifindex); - return NOTIFY_DONE; - } - -@@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, - int i; - - /* destroy all instances for this pid */ -- spin_lock(&instances_lock); -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ spin_lock(&n->net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &n->net->nfqnl.instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((n->net == &init_net) && -- (n->pid == inst->peer_pid)) -+ if (n->pid == inst->peer_pid) - __instance_destroy(inst); - } - } -- spin_unlock(&instances_lock); -+ spin_unlock(&n->net->nfqnl.instances_lock); - } - return NOTIFY_DONE; - } -@@ -622,11 +615,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { - [NFQA_MARK] = { .type = NLA_U32 }, - }; - --static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) -+static struct nfqnl_instance *verdict_instance_lookup(struct net *net, -+ u16 queue_num, int nlpid) - { - struct nfqnl_instance *queue; - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - return ERR_PTR(-ENODEV); - -@@ -670,7 +664,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, - LIST_HEAD(batch_list); - u16 queue_num = ntohs(nfmsg->res_id); - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); -+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -715,11 +710,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - unsigned int verdict; - struct nf_queue_entry *entry; -+ struct net *net = sock_net(ctnl); - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); -+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - struct nfqnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); - - if (nfqa[NFQA_CFG_CMD]) { - cmd = nla_data(nfqa[NFQA_CFG_CMD]); -@@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { - ret = -EPERM; - goto err_out_unlock; -@@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -EBUSY; - goto err_out_unlock; - } -- queue = instance_create(queue_num, NETLINK_CB(skb).pid); -+ queue = instance_create(net, queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) { - ret = PTR_ERR(queue); - goto err_out_unlock; -@@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -ENODEV; - goto err_out_unlock; - } -- instance_destroy(queue); -+ instance_destroy(net, queue); - break; - case NFQNL_CFG_CMD_PF_BIND: - case NFQNL_CFG_CMD_PF_UNBIND: -@@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { - - #ifdef CONFIG_PROC_FS - struct iter_state { -+ struct seq_net_private p; - unsigned int bucket; - }; - --static struct hlist_node *get_first(struct seq_file *seq) -+static struct hlist_node *get_first(struct net *net, struct iter_state *st) - { -- struct iter_state *st = seq->private; -- - if (!st) - return NULL; - -- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return instance_table[st->bucket].first; -+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { -+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) -+ return net->nfqnl.instance_table[st->bucket].first; - } - return NULL; - } - --static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) -+static struct hlist_node *get_next(struct net *net, struct iter_state *st, -+ struct hlist_node *h) - { -- struct iter_state *st = seq->private; -- - h = h->next; - while (!h) { -- if (++st->bucket >= INSTANCE_BUCKETS) -+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) - return NULL; - -- h = instance_table[st->bucket].first; -+ h = net->nfqnl.instance_table[st->bucket].first; - } - return h; - } - --static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) -+static struct hlist_node *get_idx(struct net *net, struct iter_state *st, -+ loff_t pos) - { - struct hlist_node *head; -- head = get_first(seq); -+ head = get_first(net, st); - - if (head) -- while (pos && (head = get_next(seq, head))) -+ while (pos && (head = get_next(net, st, head))) - pos--; - return pos ? NULL : head; - } - - static void *seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(instances_lock) - { -- spin_lock(&instances_lock); -- return get_idx(seq, *pos); -+ struct net *net = seq_file_net(seq); -+ spin_lock(&net->nfqnl.instances_lock); -+ return get_idx(net, seq->private, *pos); - } - - static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - { - (*pos)++; -- return get_next(s, v); -+ return get_next(seq_file_net(s), s->private, v); - } - - static void seq_stop(struct seq_file *s, void *v) -- __releases(instances_lock) - { -- spin_unlock(&instances_lock); -+ struct net *net = seq_file_net(s); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static int seq_show(struct seq_file *s, void *v) -@@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = { - - static int nfqnl_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nfqnl_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nfqnl_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nfqnl_file_ops = { -@@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = { - .open = nfqnl_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - - static int __net_init nfnetlink_queue_net_init(struct net *net) - { -+ int i; -+ -+ spin_lock_init(&net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) -+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); -+ - #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - net->proc_net_netfilter, &nfqnl_file_ops)) -@@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { - - static int __init nfnetlink_queue_init(void) - { -- int i, status; -+ int status; - - status = register_pernet_subsys(&nfnetlink_queue_net_ops); - if (status) { -@@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void) - return status; - } - -- for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -- - netlink_register_notifier(&nfqnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfqnl_subsys); - if (status < 0) { --- -1.7.9.5 - diff --git a/kernel/core-kernel-3.5/Makefile b/kernel/core-kernel-3.5/Makefile deleted file mode 100644 index 4a2d0094..00000000 --- a/kernel/core-kernel-3.5/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -VERSION := $(shell dpkg -l linux-source 2> /dev/null | \ - awk '/^i/ {match($$3, "[0-9]+[.][0-9]+[.][0-9]+"); if (RSTART) print substr($$3, RSTART, RLENGTH)}') -TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 - -SUBVERSION := -core -REVISION := 1.0 - -PATCHDIR := patches -PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) - -CONFIG := config.core - -DEPDEBS := linux-source kernel-package po-debconf gettext - -CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \ - awk '/^CPU\(s\)/ {print $$2}') -ifeq ($(strip $(CONCURRENCY_LEVEL)),) -CONCURRENCY_LEVEL := 1 -endif - -MAINTAINER ?= $(shell id -nu) -EMAIL ?= $(MAINTAINER)@$(shell hostname -f) - -MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ - --append-to-version $(SUBVERSION) --revision $(REVISION) - -.PHONY: build -build: debcheck defaultconfig patch - export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ - KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && \ - if [ -f ../$(CONFIG) ]; then \ - cat ../$(CONFIG) >> .config; \ - fi && \ - fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch - -.PHONY: debcheck -debcheck: - for d in $(DEPDEBS); do \ - if ! dpkg-query -s $$d > /dev/null 2>&1; then \ - echo ERROR: build dependency not installed: $$d >&2; \ - exit 1; \ - fi; \ - done - -.PHONY: defaultconfig -defaultconfig: linux-source-$(VERSION) - export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure - -.PHONY: patch -patch: linux-source-$(VERSION) patch-stamp -patch-stamp: $(PATCHES) - for p in $^; do \ - if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ - echo ERROR: applying patch failed: $$p >&2; \ - exit 1; \ - fi; \ - done - touch patch-stamp - -.PHONY: source -source: linux-source-$(VERSION) - -linux-source-$(VERSION): $(TARBALL) - tar -xjf $^ - -.PHONY: clean -clean: - rm -rf linux-source-$(VERSION) patch-stamp diff --git a/kernel/core-kernel-3.5/config.core b/kernel/core-kernel-3.5/config.core deleted file mode 100644 index 27c7ef7a..00000000 --- a/kernel/core-kernel-3.5/config.core +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XFRM_STATISTICS=y diff --git a/kernel/core-kernel-3.5/patches/00-ifindex.patch b/kernel/core-kernel-3.5/patches/00-ifindex.patch deleted file mode 100644 index 4eefa209..00000000 --- a/kernel/core-kernel-3.5/patches/00-ifindex.patch +++ /dev/null @@ -1,60 +0,0 @@ -From e98f08306dd0dc854d93339730a8603638173e23 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Fri, 27 Jul 2012 00:02:50 -0700 -Subject: [PATCH] Make network device ifindex sequential per network - namespace. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 2 ++ - net/core/dev.c | 13 ++++++------- - 2 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index ac9195e..1b9c99a 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -62,6 +62,8 @@ struct net { - struct sock *rtnl; /* rtnetlink socket */ - struct sock *genl_sock; - -+ int ifindex; -+ - struct list_head dev_base_head; - struct hlist_head *dev_name_head; - struct hlist_head *dev_index_head; -diff --git a/net/core/dev.c b/net/core/dev.c -index 3ad746b..7bec156 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -5168,12 +5168,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) - */ - static int dev_new_index(struct net *net) - { -- static int ifindex; - for (;;) { -- if (++ifindex <= 0) -- ifindex = 1; -- if (!__dev_get_by_index(net, ifindex)) -- return ifindex; -+ if (++net->ifindex <= 0) -+ net->ifindex = 1; -+ if (!__dev_get_by_index(net, net->ifindex)) -+ return net->ifindex; - } - } - -@@ -6182,8 +6181,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char - /* Actually switch the network namespace */ - dev_net_set(dev, net); - -- /* If there is an ifindex conflict assign a new one */ -- if (__dev_get_by_index(net, dev->ifindex)) { -+ /* Assign a new ifindex */ -+ { - int iflink = (dev->iflink == dev->ifindex); - dev->ifindex = dev_new_index(net); - if (iflink) --- -1.7.10.4 - diff --git a/kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch b/kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch deleted file mode 100644 index 1534cfa8..00000000 --- a/kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch +++ /dev/null @@ -1,351 +0,0 @@ -From 5af499895ded68e1d42510df30be2004b4b778bf Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Thu, 26 Jul 2012 23:57:06 -0700 -Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per - netns. - -This allows subsystems to create per-netns entries. - -Signed-off-by: Tom Goff ---- - include/linux/netfilter.h | 5 ----- - include/net/net_namespace.h | 3 +++ - net/netfilter/core.c | 35 +++++++++++++++++++++++------- - net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++---- - net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++---- - net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++----------- - net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------ - 7 files changed, 148 insertions(+), 48 deletions(-) - -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index ff9c84c..e28a566 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -350,11 +350,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) - #endif - } - --#ifdef CONFIG_PROC_FS --#include --extern struct proc_dir_entry *proc_net_netfilter; --#endif -- - #else /* !CONFIG_NETFILTER */ - #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) - #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 1b9c99a..449fc8e 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -86,6 +86,9 @@ struct net { - struct netns_dccp dccp; - #endif - #ifdef CONFIG_NETFILTER -+#ifdef CONFIG_PROC_FS -+ struct proc_dir_entry *proc_net_netfilter; -+#endif - struct netns_xt xt; - #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - struct netns_ct ct; -diff --git a/net/netfilter/core.c b/net/netfilter/core.c -index e19f365..c7c9f39 100644 ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -266,25 +266,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) - EXPORT_SYMBOL(nf_conntrack_destroy); - #endif /* CONFIG_NF_CONNTRACK */ - -+static int __net_init netfilter_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", -+ net->proc_net); -+ if (!net->proc_net_netfilter) { -+ pr_err("%s: cannot create netfilter proc entry\n", __func__); -+ return -ENOMEM; -+ } -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_net_exit(struct net *net) -+{ - #ifdef CONFIG_PROC_FS --struct proc_dir_entry *proc_net_netfilter; --EXPORT_SYMBOL(proc_net_netfilter); -+ proc_net_remove(net, "netfilter"); - #endif -+} -+ -+static struct pernet_operations netfilter_net_ops = { -+ .init = netfilter_net_init, -+ .exit = netfilter_net_exit, -+}; - - void __init netfilter_init(void) - { - int i, h; -+ -+ if (register_pernet_subsys(&netfilter_net_ops)) -+ panic("%s: failed to register per netns operations", __func__); -+ - for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - INIT_LIST_HEAD(&nf_hooks[i][h]); - } - --#ifdef CONFIG_PROC_FS -- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); -- if (!proc_net_netfilter) -- panic("cannot create netfilter proc entry"); --#endif -- - if (netfilter_queue_init() < 0) - panic("cannot initialize nf_queue"); - if (netfilter_log_init() < 0) -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index 703fb26..4507932 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void) - } - #endif /* CONFIG_SYSCTL */ - --int __init netfilter_log_init(void) -+static int __net_init netfilter_log_net_init(struct net *net) - { -- int i, r; - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_log", S_IRUGO, -- proc_net_netfilter, &nflog_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nflog_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_log", net->proc_net_netfilter); - #endif -+} -+ -+static struct pernet_operations netfilter_log_net_ops = { -+ .init = netfilter_log_net_init, -+ .exit = netfilter_log_net_exit, -+}; -+ -+int __init netfilter_log_init(void) -+{ -+ int i, r; -+ -+ r = register_pernet_subsys(&netfilter_log_net_ops); -+ if (r) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return r; -+ } - - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index ce60cf0..288c6f5 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -407,14 +407,37 @@ static const struct file_operations nfqueue_file_ops = { - }; - #endif /* PROC_FS */ - -- --int __init netfilter_queue_init(void) -+static int __net_init netfilter_queue_net_init(struct net *net) - { - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_queue", S_IRUGO, -- proc_net_netfilter, &nfqueue_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nfqueue_file_ops)) -+ return -ENOMEM; - #endif -+ - return 0; - } - -+static void __net_exit netfilter_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations netfilter_queue_net_ops = { -+ .init = netfilter_queue_net_init, -+ .exit = netfilter_queue_net_exit, -+}; -+ -+int __init netfilter_queue_init(void) -+{ -+ int err; -+ -+ err = register_pernet_subsys(&netfilter_queue_net_ops); -+ if (err) -+ pr_err("%s: cannot initialize per netns operations\n", -+ __func__); -+ -+ return err; -+} -diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index bbc1d91..e5c1731 100644 ---- a/net/netfilter/nfnetlink_log.c -+++ b/net/netfilter/nfnetlink_log.c -@@ -966,9 +966,39 @@ static const struct file_operations nful_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_log_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_log", 0440, -+ net->proc_net_netfilter, &nful_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_log_net_ops = { -+ .init = nfnetlink_log_net_init, -+ .exit = nfnetlink_log_net_exit, -+}; -+ - static int __init nfnetlink_log_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_log_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -991,17 +1021,8 @@ static int __init nfnetlink_log_init(void) - goto cleanup_subsys; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_log", 0440, -- proc_net_netfilter, &nful_file_ops)) -- goto cleanup_logger; --#endif - return status; - --#ifdef CONFIG_PROC_FS --cleanup_logger: -- nf_log_unregister(&nfulnl_logger); --#endif - cleanup_subsys: - nfnetlink_subsys_unregister(&nfulnl_subsys); - cleanup_netlink_notifier: -@@ -1012,9 +1033,6 @@ cleanup_netlink_notifier: - static void __exit nfnetlink_log_fini(void) - { - nf_log_unregister(&nfulnl_logger); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_log", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfulnl_subsys); - netlink_unregister_notifier(&nfulnl_rtnl_notifier); - } -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index 4162437..add33dc 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -982,9 +982,39 @@ static const struct file_operations nfqnl_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_queue_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_queue", 0440, -+ net->proc_net_netfilter, &nfqnl_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_queue_net_ops = { -+ .init = nfnetlink_queue_net_init, -+ .exit = nfnetlink_queue_net_exit, -+}; -+ - static int __init nfnetlink_queue_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_queue_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -996,19 +1026,9 @@ static int __init nfnetlink_queue_init(void) - goto cleanup_netlink_notifier; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_queue", 0440, -- proc_net_netfilter, &nfqnl_file_ops)) -- goto cleanup_subsys; --#endif -- - register_netdevice_notifier(&nfqnl_dev_notifier); - return status; - --#ifdef CONFIG_PROC_FS --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfqnl_subsys); --#endif - cleanup_netlink_notifier: - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - return status; -@@ -1018,9 +1038,6 @@ static void __exit nfnetlink_queue_fini(void) - { - nf_unregister_queue_handlers(&nfqh); - unregister_netdevice_notifier(&nfqnl_dev_notifier); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_queue", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfqnl_subsys); - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - --- -1.7.10.4 - diff --git a/kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch b/kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch deleted file mode 100644 index eaace654..00000000 --- a/kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch +++ /dev/null @@ -1,494 +0,0 @@ -From 1ede1963c84e15359d4b5bf7fb01587d90bcf1d4 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Thu, 26 Jul 2012 23:58:38 -0700 -Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support. - -Make nfnetlink_queue network namespace aware including a per-netns -/proc/net/netfilter/nfnetlink_queue file. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 6 ++ - include/net/netfilter/nf_queue.h | 3 +- - include/net/netns/nfqnl.h | 14 ++++ - net/netfilter/nf_queue.c | 12 +++- - net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++------------------- - 5 files changed, 101 insertions(+), 70 deletions(-) - create mode 100644 include/net/netns/nfqnl.h - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 449fc8e..c4229f1 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -21,6 +21,9 @@ - #include - #endif - #include -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+#include -+#endif - - struct proc_dir_entry; - struct net_device; -@@ -95,6 +98,9 @@ struct net { - #endif - struct sock *nfnl; - struct sock *nfnl_stash; -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+ struct netns_nfqnl nfqnl; -+#endif - #endif - #ifdef CONFIG_WEXT_CORE - struct sk_buff_head wext_nlevents; -diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h -index 252fd10..3e5bde8 100644 ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -19,7 +19,8 @@ struct nf_queue_entry { - - /* Packet queuing */ - struct nf_queue_handler { -- int (*outfn)(struct nf_queue_entry *entry, -+ int (*outfn)(struct net *net, -+ struct nf_queue_entry *entry, - unsigned int queuenum); - char *name; - }; -diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h -new file mode 100644 -index 0000000..0fe7fbe ---- /dev/null -+++ b/include/net/netns/nfqnl.h -@@ -0,0 +1,14 @@ -+#ifndef __NETNS_NFQNL_H -+#define __NETNS_NFQNL_H -+ -+#include -+#include -+ -+#define NFQNL_INSTANCE_BUCKETS 16 -+ -+struct netns_nfqnl { -+ spinlock_t instances_lock; -+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS]; -+}; -+ -+#endif /* __NETNS_NFQNL_H */ -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index 288c6f5..3cb8733 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb, - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+ struct net *net; -+ -+ if (indev) -+ net = dev_net(indev); -+ else if (skb->sk) -+ net = sock_net(skb->sk); -+ else if (outdev) -+ net = dev_net(outdev); -+ else -+ return status; - - /* QUEUE == DROP if no one is waiting, to be safe. */ - rcu_read_lock(); -@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - skb_dst_force(skb); - afinfo->saveroute(skb, entry); -- status = qh->outfn(entry, queuenum); -+ status = qh->outfn(net, entry, queuenum); - - rcu_read_unlock(); - -diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c -index add33dc..43c50bb 100644 ---- a/net/netfilter/nfnetlink_queue.c -+++ b/net/netfilter/nfnetlink_queue.c -@@ -64,24 +64,19 @@ struct nfqnl_instance { - - typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - --static DEFINE_SPINLOCK(instances_lock); -- --#define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; -- - static inline u_int8_t instance_hashfn(u_int16_t queue_num) - { -- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; -+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; - } - - static struct nfqnl_instance * --instance_lookup(u_int16_t queue_num) -+instance_lookup(struct net *net, u_int16_t queue_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfqnl_instance *inst; - -- head = &instance_table[instance_hashfn(queue_num)]; -+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->queue_num == queue_num) - return inst; -@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_create(u_int16_t queue_num, int pid) -+instance_create(struct net *net, u_int16_t queue_num, int pid) - { - struct nfqnl_instance *inst; - unsigned int h; - int err; - -- spin_lock(&instances_lock); -- if (instance_lookup(queue_num)) { -+ spin_lock(&net->nfqnl.instances_lock); -+ if (instance_lookup(net, queue_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid) - } - - h = instance_hashfn(queue_num); -- hlist_add_head_rcu(&inst->hlist, &instance_table[h]); -+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - - return inst; - - out_free: - kfree(inst); - out_unlock: -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - return ERR_PTR(err); - } - -@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst) - } - - static void --instance_destroy(struct nfqnl_instance *inst) -+instance_destroy(struct net *net, struct nfqnl_instance *inst) - { -- spin_lock(&instances_lock); -+ spin_lock(&net->nfqnl.instances_lock); - __instance_destroy(inst); -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static inline void -@@ -400,7 +395,8 @@ nla_put_failure: - } - - static int --nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - struct sk_buff *nskb; - struct nfqnl_instance *queue; -@@ -408,7 +404,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - __be32 *packet_id_ptr; - - /* rcu_read_lock()ed by nf_hook_slow() */ -- queue = instance_lookup(queuenum); -+ queue = instance_lookup(net, queuenum); - if (!queue) { - err = -ESRCH; - goto err_out; -@@ -440,7 +436,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - *packet_id_ptr = htonl(entry->id); - - /* nfnetlink_unicast will either free the nskb or add it to a socket */ -- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); -+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT); - if (err < 0) { - queue->queue_user_dropped++; - goto err_out_unlock; -@@ -549,16 +545,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) - /* drop all packets with either indev or outdev == ifindex from all queue - * instances */ - static void --nfqnl_dev_drop(int ifindex) -+nfqnl_dev_drop(struct net *net, int ifindex) - { - int i; - - rcu_read_lock(); - -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = &net->nfqnl.instance_table[i]; - - hlist_for_each_entry_rcu(inst, tmp, head, hlist) - nfqnl_flush(inst, dev_cmp, ifindex); -@@ -575,12 +571,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, - { - struct net_device *dev = ptr; - -- if (!net_eq(dev_net(dev), &init_net)) -- return NOTIFY_DONE; -- - /* Drop any packets associated with the downed device */ - if (event == NETDEV_DOWN) -- nfqnl_dev_drop(dev->ifindex); -+ nfqnl_dev_drop(dev_net(dev), dev->ifindex); - return NOTIFY_DONE; - } - -@@ -598,19 +591,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, - int i; - - /* destroy all instances for this pid */ -- spin_lock(&instances_lock); -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ spin_lock(&n->net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &n->net->nfqnl.instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((n->net == &init_net) && -- (n->pid == inst->peer_pid)) -+ if (n->pid == inst->peer_pid) - __instance_destroy(inst); - } - } -- spin_unlock(&instances_lock); -+ spin_unlock(&n->net->nfqnl.instances_lock); - } - return NOTIFY_DONE; - } -@@ -630,11 +623,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { - [NFQA_MARK] = { .type = NLA_U32 }, - }; - --static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) -+static struct nfqnl_instance *verdict_instance_lookup(struct net *net, -+ u16 queue_num, int nlpid) - { - struct nfqnl_instance *queue; - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - return ERR_PTR(-ENODEV); - -@@ -678,7 +672,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, - LIST_HEAD(batch_list); - u16 queue_num = ntohs(nfmsg->res_id); - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); -+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -723,11 +718,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - unsigned int verdict; - struct nf_queue_entry *entry; -+ struct net *net = sock_net(ctnl); - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); -+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -782,6 +778,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - struct nfqnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); - - if (nfqa[NFQA_CFG_CMD]) { - cmd = nla_data(nfqa[NFQA_CFG_CMD]); -@@ -798,7 +795,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { - ret = -EPERM; - goto err_out_unlock; -@@ -811,7 +808,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -EBUSY; - goto err_out_unlock; - } -- queue = instance_create(queue_num, NETLINK_CB(skb).pid); -+ queue = instance_create(net, queue_num, -+ NETLINK_CB(skb).pid); - if (IS_ERR(queue)) { - ret = PTR_ERR(queue); - goto err_out_unlock; -@@ -822,7 +820,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -ENODEV; - goto err_out_unlock; - } -- instance_destroy(queue); -+ instance_destroy(net, queue); - break; - case NFQNL_CFG_CMD_PF_BIND: - case NFQNL_CFG_CMD_PF_UNBIND: -@@ -886,65 +884,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { - - #ifdef CONFIG_PROC_FS - struct iter_state { -+ struct seq_net_private p; - unsigned int bucket; - }; - --static struct hlist_node *get_first(struct seq_file *seq) -+static struct hlist_node *get_first(struct net *net, struct iter_state *st) - { -- struct iter_state *st = seq->private; -- - if (!st) - return NULL; - -- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return instance_table[st->bucket].first; -+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { -+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) -+ return net->nfqnl.instance_table[st->bucket].first; - } - return NULL; - } - --static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) -+static struct hlist_node *get_next(struct net *net, struct iter_state *st, -+ struct hlist_node *h) - { -- struct iter_state *st = seq->private; -- - h = h->next; - while (!h) { -- if (++st->bucket >= INSTANCE_BUCKETS) -+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) - return NULL; - -- h = instance_table[st->bucket].first; -+ h = net->nfqnl.instance_table[st->bucket].first; - } - return h; - } - --static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) -+static struct hlist_node *get_idx(struct net *net, struct iter_state *st, -+ loff_t pos) - { - struct hlist_node *head; -- head = get_first(seq); -+ head = get_first(net, st); - - if (head) -- while (pos && (head = get_next(seq, head))) -+ while (pos && (head = get_next(net, st, head))) - pos--; - return pos ? NULL : head; - } - - static void *seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(instances_lock) - { -- spin_lock(&instances_lock); -- return get_idx(seq, *pos); -+ struct net *net = seq_file_net(seq); -+ spin_lock(&net->nfqnl.instances_lock); -+ return get_idx(net, seq->private, *pos); - } - - static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - { - (*pos)++; -- return get_next(s, v); -+ return get_next(seq_file_net(s), s->private, v); - } - - static void seq_stop(struct seq_file *s, void *v) -- __releases(instances_lock) - { -- spin_unlock(&instances_lock); -+ struct net *net = seq_file_net(s); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static int seq_show(struct seq_file *s, void *v) -@@ -968,8 +965,8 @@ static const struct seq_operations nfqnl_seq_ops = { - - static int nfqnl_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nfqnl_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nfqnl_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nfqnl_file_ops = { -@@ -977,13 +974,19 @@ static const struct file_operations nfqnl_file_ops = { - .open = nfqnl_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - - static int __net_init nfnetlink_queue_net_init(struct net *net) - { -+ int i; -+ -+ spin_lock_init(&net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) -+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); -+ - #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - net->proc_net_netfilter, &nfqnl_file_ops)) -@@ -1007,7 +1010,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { - - static int __init nfnetlink_queue_init(void) - { -- int i, status; -+ int status; - - status = register_pernet_subsys(&nfnetlink_queue_net_ops); - if (status) { -@@ -1016,9 +1019,6 @@ static int __init nfnetlink_queue_init(void) - return status; - } - -- for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -- - netlink_register_notifier(&nfqnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfqnl_subsys); - if (status < 0) { --- -1.7.10.4 - diff --git a/kernel/core-kernel-3.8/Makefile b/kernel/core-kernel-3.8/Makefile deleted file mode 100644 index 4a2d0094..00000000 --- a/kernel/core-kernel-3.8/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -VERSION := $(shell dpkg -l linux-source 2> /dev/null | \ - awk '/^i/ {match($$3, "[0-9]+[.][0-9]+[.][0-9]+"); if (RSTART) print substr($$3, RSTART, RLENGTH)}') -TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2 - -SUBVERSION := -core -REVISION := 1.0 - -PATCHDIR := patches -PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch)) - -CONFIG := config.core - -DEPDEBS := linux-source kernel-package po-debconf gettext - -CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \ - awk '/^CPU\(s\)/ {print $$2}') -ifeq ($(strip $(CONCURRENCY_LEVEL)),) -CONCURRENCY_LEVEL := 1 -endif - -MAINTAINER ?= $(shell id -nu) -EMAIL ?= $(MAINTAINER)@$(shell hostname -f) - -MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \ - --append-to-version $(SUBVERSION) --revision $(REVISION) - -.PHONY: build -build: debcheck defaultconfig patch - export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \ - KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && \ - if [ -f ../$(CONFIG) ]; then \ - cat ../$(CONFIG) >> .config; \ - fi && \ - fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch - -.PHONY: debcheck -debcheck: - for d in $(DEPDEBS); do \ - if ! dpkg-query -s $$d > /dev/null 2>&1; then \ - echo ERROR: build dependency not installed: $$d >&2; \ - exit 1; \ - fi; \ - done - -.PHONY: defaultconfig -defaultconfig: linux-source-$(VERSION) - export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \ - cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure - -.PHONY: patch -patch: linux-source-$(VERSION) patch-stamp -patch-stamp: $(PATCHES) - for p in $^; do \ - if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \ - echo ERROR: applying patch failed: $$p >&2; \ - exit 1; \ - fi; \ - done - touch patch-stamp - -.PHONY: source -source: linux-source-$(VERSION) - -linux-source-$(VERSION): $(TARBALL) - tar -xjf $^ - -.PHONY: clean -clean: - rm -rf linux-source-$(VERSION) patch-stamp diff --git a/kernel/core-kernel-3.8/config.core b/kernel/core-kernel-3.8/config.core deleted file mode 100644 index 27c7ef7a..00000000 --- a/kernel/core-kernel-3.8/config.core +++ /dev/null @@ -1 +0,0 @@ -CONFIG_XFRM_STATISTICS=y diff --git a/kernel/core-kernel-3.8/patches/00-ifindex.patch b/kernel/core-kernel-3.8/patches/00-ifindex.patch deleted file mode 100644 index 3421bcc2..00000000 --- a/kernel/core-kernel-3.8/patches/00-ifindex.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 1d992600b0f1962d0478df2083b76b1ceba50517 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Mon, 3 Jun 2013 18:29:42 -0700 -Subject: [PATCH 1/3] Make network device ifindex sequential per network - namespace. - -Signed-off-by: Tom Goff ---- - net/core/dev.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/net/core/dev.c b/net/core/dev.c -index d592214..4b8da6e 100644 ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -6455,8 +6455,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char - /* Actually switch the network namespace */ - dev_net_set(dev, net); - -- /* If there is an ifindex conflict assign a new one */ -- if (__dev_get_by_index(net, dev->ifindex)) { -+ /* Assign a new ifindex */ -+ { - int iflink = (dev->iflink == dev->ifindex); - dev->ifindex = dev_new_index(net); - if (iflink) --- -1.8.1.2 - diff --git a/kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch b/kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch deleted file mode 100644 index f3f64c6c..00000000 --- a/kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch +++ /dev/null @@ -1,307 +0,0 @@ -From 433bc9e01b6a50db276c0b0d9dcd8bfcc2bc42f8 Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Mon, 3 Jun 2013 18:30:31 -0700 -Subject: [PATCH 2/3] netfilter: Make the /proc/net/netfilter directory per - netns. - -This allows subsystems to create per-netns entries. - -Signed-off-by: Tom Goff ---- - include/linux/netfilter.h | 5 ---- - include/net/net_namespace.h | 3 +++ - net/netfilter/core.c | 35 ++++++++++++++++++++------- - net/netfilter/nf_log.c | 33 ++++++++++++++++++++++---- - net/netfilter/nfnetlink_log.c | 46 ++++++++++++++++++++++++------------ - net/netfilter/nfnetlink_queue_core.c | 45 ++++++++++++++++++++++++----------- - 6 files changed, 121 insertions(+), 46 deletions(-) - -diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h -index ee14284..0060fde 100644 ---- a/include/linux/netfilter.h -+++ b/include/linux/netfilter.h -@@ -289,11 +289,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) - #endif - } - --#ifdef CONFIG_PROC_FS --#include --extern struct proc_dir_entry *proc_net_netfilter; --#endif -- - #else /* !CONFIG_NETFILTER */ - #define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb) - #define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb) -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index de644bc..96b2242 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -94,6 +94,9 @@ struct net { - struct netns_dccp dccp; - #endif - #ifdef CONFIG_NETFILTER -+#ifdef CONFIG_PROC_FS -+ struct proc_dir_entry *proc_net_netfilter; -+#endif - struct netns_xt xt; - #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) - struct netns_ct ct; -diff --git a/net/netfilter/core.c b/net/netfilter/core.c -index a9c488b..00e356d 100644 ---- a/net/netfilter/core.c -+++ b/net/netfilter/core.c -@@ -276,25 +276,44 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); - EXPORT_SYMBOL(nf_nat_decode_session_hook); - #endif - -+static int __net_init netfilter_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter", -+ net->proc_net); -+ if (!net->proc_net_netfilter) { -+ pr_err("%s: cannot create netfilter proc entry\n", __func__); -+ return -ENOMEM; -+ } -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_net_exit(struct net *net) -+{ - #ifdef CONFIG_PROC_FS --struct proc_dir_entry *proc_net_netfilter; --EXPORT_SYMBOL(proc_net_netfilter); -+ proc_net_remove(net, "netfilter"); - #endif -+} -+ -+static struct pernet_operations netfilter_net_ops = { -+ .init = netfilter_net_init, -+ .exit = netfilter_net_exit, -+}; - - void __init netfilter_init(void) - { - int i, h; -+ -+ if (register_pernet_subsys(&netfilter_net_ops)) -+ panic("%s: failed to register per netns operations", __func__); -+ - for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { - for (h = 0; h < NF_MAX_HOOKS; h++) - INIT_LIST_HEAD(&nf_hooks[i][h]); - } - --#ifdef CONFIG_PROC_FS -- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net); -- if (!proc_net_netfilter) -- panic("cannot create netfilter proc entry"); --#endif -- - if (netfilter_log_init() < 0) - panic("cannot initialize nf_log"); - } -diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c -index 9e31269..5f33072 100644 ---- a/net/netfilter/nf_log.c -+++ b/net/netfilter/nf_log.c -@@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void) - } - #endif /* CONFIG_SYSCTL */ - --int __init netfilter_log_init(void) -+static int __net_init netfilter_log_net_init(struct net *net) - { -- int i, r; - #ifdef CONFIG_PROC_FS - if (!proc_create("nf_log", S_IRUGO, -- proc_net_netfilter, &nflog_file_ops)) -- return -1; -+ net->proc_net_netfilter, &nflog_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit netfilter_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nf_log", net->proc_net_netfilter); - #endif -+} -+ -+static struct pernet_operations netfilter_log_net_ops = { -+ .init = netfilter_log_net_init, -+ .exit = netfilter_log_net_exit, -+}; -+ -+int __init netfilter_log_init(void) -+{ -+ int i, r; -+ -+ r = register_pernet_subsys(&netfilter_log_net_ops); -+ if (r) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return r; -+ } - - /* Errors will trigger panic, unroll on error is unnecessary. */ - r = netfilter_log_sysctl_init(); -diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c -index 92fd8ec..9571c43 100644 ---- a/net/netfilter/nfnetlink_log.c -+++ b/net/netfilter/nfnetlink_log.c -@@ -986,9 +986,39 @@ static const struct file_operations nful_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_log_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_log", 0440, -+ net->proc_net_netfilter, &nful_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_log_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_log_net_ops = { -+ .init = nfnetlink_log_net_init, -+ .exit = nfnetlink_log_net_exit, -+}; -+ - static int __init nfnetlink_log_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_log_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -1011,19 +1041,8 @@ static int __init nfnetlink_log_init(void) - goto cleanup_subsys; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_log", 0440, -- proc_net_netfilter, &nful_file_ops)) { -- status = -ENOMEM; -- goto cleanup_logger; -- } --#endif - return status; - --#ifdef CONFIG_PROC_FS --cleanup_logger: -- nf_log_unregister(&nfulnl_logger); --#endif - cleanup_subsys: - nfnetlink_subsys_unregister(&nfulnl_subsys); - cleanup_netlink_notifier: -@@ -1034,9 +1053,6 @@ cleanup_netlink_notifier: - static void __exit nfnetlink_log_fini(void) - { - nf_log_unregister(&nfulnl_logger); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_log", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfulnl_subsys); - netlink_unregister_notifier(&nfulnl_rtnl_notifier); - } -diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c -index 3158d87..8f2d9bb 100644 ---- a/net/netfilter/nfnetlink_queue_core.c -+++ b/net/netfilter/nfnetlink_queue_core.c -@@ -1048,9 +1048,39 @@ static const struct file_operations nfqnl_file_ops = { - - #endif /* PROC_FS */ - -+static int __net_init nfnetlink_queue_net_init(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ if (!proc_create("nfnetlink_queue", 0440, -+ net->proc_net_netfilter, &nfqnl_file_ops)) -+ return -ENOMEM; -+#endif -+ -+ return 0; -+} -+ -+static void __net_exit nfnetlink_queue_net_exit(struct net *net) -+{ -+#ifdef CONFIG_PROC_FS -+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter); -+#endif -+} -+ -+static struct pernet_operations nfnetlink_queue_net_ops = { -+ .init = nfnetlink_queue_net_init, -+ .exit = nfnetlink_queue_net_exit, -+}; -+ - static int __init nfnetlink_queue_init(void) - { -- int i, status = -ENOMEM; -+ int i, status; -+ -+ status = register_pernet_subsys(&nfnetlink_queue_net_ops); -+ if (status) { -+ pr_err("%s: failed to register per netns operations\n", -+ __func__); -+ return status; -+ } - - for (i = 0; i < INSTANCE_BUCKETS; i++) - INIT_HLIST_HEAD(&instance_table[i]); -@@ -1062,20 +1092,10 @@ static int __init nfnetlink_queue_init(void) - goto cleanup_netlink_notifier; - } - --#ifdef CONFIG_PROC_FS -- if (!proc_create("nfnetlink_queue", 0440, -- proc_net_netfilter, &nfqnl_file_ops)) -- goto cleanup_subsys; --#endif -- - register_netdevice_notifier(&nfqnl_dev_notifier); - nf_register_queue_handler(&nfqh); - return status; - --#ifdef CONFIG_PROC_FS --cleanup_subsys: -- nfnetlink_subsys_unregister(&nfqnl_subsys); --#endif - cleanup_netlink_notifier: - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - return status; -@@ -1085,9 +1105,6 @@ static void __exit nfnetlink_queue_fini(void) - { - nf_unregister_queue_handler(); - unregister_netdevice_notifier(&nfqnl_dev_notifier); --#ifdef CONFIG_PROC_FS -- remove_proc_entry("nfnetlink_queue", proc_net_netfilter); --#endif - nfnetlink_subsys_unregister(&nfqnl_subsys); - netlink_unregister_notifier(&nfqnl_rtnl_notifier); - --- -1.8.1.2 - diff --git a/kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch b/kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch deleted file mode 100644 index 7be87c05..00000000 --- a/kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch +++ /dev/null @@ -1,475 +0,0 @@ -From 3d1c0bfef9d6ca43050e7a9077b46e0139ee1e1f Mon Sep 17 00:00:00 2001 -From: Tom Goff -Date: Mon, 3 Jun 2013 18:31:29 -0700 -Subject: [PATCH 3/3] netfilter: nfnetlink_queue: Add netns support. - -Make nfnetlink_queue network namespace aware including a per-netns -/proc/net/netfilter/nfnetlink_queue file. - -Signed-off-by: Tom Goff ---- - include/net/net_namespace.h | 6 ++ - include/net/netfilter/nf_queue.h | 3 +- - net/netfilter/nf_queue.c | 12 ++- - net/netfilter/nfnetlink_queue_core.c | 137 ++++++++++++++++++----------------- - 4 files changed, 88 insertions(+), 70 deletions(-) - -diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h -index 96b2242..1af155b 100644 ---- a/include/net/net_namespace.h -+++ b/include/net/net_namespace.h -@@ -22,6 +22,9 @@ - #include - #endif - #include -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+#include -+#endif - - struct user_namespace; - struct proc_dir_entry; -@@ -106,6 +109,9 @@ struct net { - #endif - struct sock *nfnl; - struct sock *nfnl_stash; -+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE) -+ struct netns_nfqnl nfqnl; -+#endif - #endif - #ifdef CONFIG_WEXT_CORE - struct sk_buff_head wext_nlevents; -diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h -index fb1c0be..484453d 100644 ---- a/include/net/netfilter/nf_queue.h -+++ b/include/net/netfilter/nf_queue.h -@@ -19,7 +19,8 @@ struct nf_queue_entry { - - /* Packet queuing */ - struct nf_queue_handler { -- int (*outfn)(struct nf_queue_entry *entry, -+ int (*outfn)(struct net *net, -+ struct nf_queue_entry *entry, - unsigned int queuenum); - }; - -diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c -index d812c12..0d69be9 100644 ---- a/net/netfilter/nf_queue.c -+++ b/net/netfilter/nf_queue.c -@@ -81,6 +81,16 @@ static int __nf_queue(struct sk_buff *skb, - #endif - const struct nf_afinfo *afinfo; - const struct nf_queue_handler *qh; -+ struct net *net; -+ -+ if (indev) -+ net = dev_net(indev); -+ else if (skb->sk) -+ net = sock_net(skb->sk); -+ else if (outdev) -+ net = dev_net(outdev); -+ else -+ return status; - - /* QUEUE == DROP if no one is waiting, to be safe. */ - rcu_read_lock(); -@@ -133,7 +143,7 @@ static int __nf_queue(struct sk_buff *skb, - #endif - skb_dst_force(skb); - afinfo->saveroute(skb, entry); -- status = qh->outfn(entry, queuenum); -+ status = qh->outfn(net, entry, queuenum); - - rcu_read_unlock(); - -diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c -index 8f2d9bb..1e0a830 100644 ---- a/net/netfilter/nfnetlink_queue_core.c -+++ b/net/netfilter/nfnetlink_queue_core.c -@@ -66,24 +66,19 @@ struct nfqnl_instance { - - typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long); - --static DEFINE_SPINLOCK(instances_lock); -- --#define INSTANCE_BUCKETS 16 --static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly; -- - static inline u_int8_t instance_hashfn(u_int16_t queue_num) - { -- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS; -+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS; - } - - static struct nfqnl_instance * --instance_lookup(u_int16_t queue_num) -+instance_lookup(struct net *net, u_int16_t queue_num) - { - struct hlist_head *head; - struct hlist_node *pos; - struct nfqnl_instance *inst; - -- head = &instance_table[instance_hashfn(queue_num)]; -+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)]; - hlist_for_each_entry_rcu(inst, pos, head, hlist) { - if (inst->queue_num == queue_num) - return inst; -@@ -92,14 +87,14 @@ instance_lookup(u_int16_t queue_num) - } - - static struct nfqnl_instance * --instance_create(u_int16_t queue_num, int portid) -+instance_create(struct net *net, u_int16_t queue_num, int portid) - { - struct nfqnl_instance *inst; - unsigned int h; - int err; - -- spin_lock(&instances_lock); -- if (instance_lookup(queue_num)) { -+ spin_lock(&net->nfqnl.instances_lock); -+ if (instance_lookup(net, queue_num)) { - err = -EEXIST; - goto out_unlock; - } -@@ -124,16 +119,16 @@ instance_create(u_int16_t queue_num, int portid) - } - - h = instance_hashfn(queue_num); -- hlist_add_head_rcu(&inst->hlist, &instance_table[h]); -+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]); - -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - - return inst; - - out_free: - kfree(inst); - out_unlock: -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - return ERR_PTR(err); - } - -@@ -159,11 +154,11 @@ __instance_destroy(struct nfqnl_instance *inst) - } - - static void --instance_destroy(struct nfqnl_instance *inst) -+instance_destroy(struct net *net, struct nfqnl_instance *inst) - { -- spin_lock(&instances_lock); -+ spin_lock(&net->nfqnl.instances_lock); - __instance_destroy(inst); -- spin_unlock(&instances_lock); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static inline void -@@ -417,7 +412,8 @@ nla_put_failure: - } - - static int --nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) -+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry, -+ unsigned int queuenum) - { - struct sk_buff *nskb; - struct nfqnl_instance *queue; -@@ -426,7 +422,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - int failopen = 0; - - /* rcu_read_lock()ed by nf_hook_slow() */ -- queue = instance_lookup(queuenum); -+ queue = instance_lookup(net, queuenum); - if (!queue) { - err = -ESRCH; - goto err_out; -@@ -463,7 +459,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) - *packet_id_ptr = htonl(entry->id); - - /* nfnetlink_unicast will either free the nskb or add it to a socket */ -- err = nfnetlink_unicast(nskb, &init_net, queue->peer_portid, MSG_DONTWAIT); -+ err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT); - if (err < 0) { - queue->queue_user_dropped++; - goto err_out_unlock; -@@ -576,16 +572,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex) - /* drop all packets with either indev or outdev == ifindex from all queue - * instances */ - static void --nfqnl_dev_drop(int ifindex) -+nfqnl_dev_drop(struct net *net, int ifindex) - { - int i; - - rcu_read_lock(); - -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = &net->nfqnl.instance_table[i]; - - hlist_for_each_entry_rcu(inst, tmp, head, hlist) - nfqnl_flush(inst, dev_cmp, ifindex); -@@ -602,12 +598,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this, - { - struct net_device *dev = ptr; - -- if (!net_eq(dev_net(dev), &init_net)) -- return NOTIFY_DONE; -- - /* Drop any packets associated with the downed device */ - if (event == NETDEV_DOWN) -- nfqnl_dev_drop(dev->ifindex); -+ nfqnl_dev_drop(dev_net(dev), dev->ifindex); - return NOTIFY_DONE; - } - -@@ -625,19 +618,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this, - int i; - - /* destroy all instances for this portid */ -- spin_lock(&instances_lock); -- for (i = 0; i < INSTANCE_BUCKETS; i++) { -+ spin_lock(&n->net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) { - struct hlist_node *tmp, *t2; - struct nfqnl_instance *inst; -- struct hlist_head *head = &instance_table[i]; -+ struct hlist_head *head = -+ &n->net->nfqnl.instance_table[i]; - - hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { -- if ((n->net == &init_net) && -- (n->portid == inst->peer_portid)) -+ if (n->portid == inst->peer_portid) - __instance_destroy(inst); - } - } -- spin_unlock(&instances_lock); -+ spin_unlock(&n->net->nfqnl.instances_lock); - } - return NOTIFY_DONE; - } -@@ -658,11 +651,13 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { - [NFQA_MARK] = { .type = NLA_U32 }, - }; - --static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlportid) -+static struct nfqnl_instance *verdict_instance_lookup(struct net *net, -+ u16 queue_num, -+ int nlportid) - { - struct nfqnl_instance *queue; - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - return ERR_PTR(-ENODEV); - -@@ -706,7 +701,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, - LIST_HEAD(batch_list); - u16 queue_num = ntohs(nfmsg->res_id); - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); -+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num, -+ NETLINK_CB(skb).portid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -751,13 +747,14 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - unsigned int verdict; - struct nf_queue_entry *entry; -+ struct net *net = sock_net(ctnl); - enum ip_conntrack_info uninitialized_var(ctinfo); - struct nf_conn *ct = NULL; - -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (!queue) - -- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); -+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).portid); - if (IS_ERR(queue)) - return PTR_ERR(queue); - -@@ -822,6 +819,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - struct nfqnl_instance *queue; - struct nfqnl_msg_config_cmd *cmd = NULL; - int ret = 0; -+ struct net *net = sock_net(ctnl); - - if (nfqa[NFQA_CFG_CMD]) { - cmd = nla_data(nfqa[NFQA_CFG_CMD]); -@@ -834,7 +832,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - } - - rcu_read_lock(); -- queue = instance_lookup(queue_num); -+ queue = instance_lookup(net, queue_num); - if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { - ret = -EPERM; - goto err_out_unlock; -@@ -847,7 +845,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -EBUSY; - goto err_out_unlock; - } -- queue = instance_create(queue_num, NETLINK_CB(skb).portid); -+ queue = instance_create(net, queue_num, -+ NETLINK_CB(skb).portid); - if (IS_ERR(queue)) { - ret = PTR_ERR(queue); - goto err_out_unlock; -@@ -858,7 +857,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, - ret = -ENODEV; - goto err_out_unlock; - } -- instance_destroy(queue); -+ instance_destroy(net, queue); - break; - case NFQNL_CFG_CMD_PF_BIND: - case NFQNL_CFG_CMD_PF_UNBIND: -@@ -952,65 +951,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = { - - #ifdef CONFIG_PROC_FS - struct iter_state { -+ struct seq_net_private p; - unsigned int bucket; - }; - --static struct hlist_node *get_first(struct seq_file *seq) -+static struct hlist_node *get_first(struct net *net, struct iter_state *st) - { -- struct iter_state *st = seq->private; -- - if (!st) - return NULL; - -- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { -- if (!hlist_empty(&instance_table[st->bucket])) -- return instance_table[st->bucket].first; -+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) { -+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket])) -+ return net->nfqnl.instance_table[st->bucket].first; - } - return NULL; - } - --static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h) -+static struct hlist_node *get_next(struct net *net, struct iter_state *st, -+ struct hlist_node *h) - { -- struct iter_state *st = seq->private; -- - h = h->next; - while (!h) { -- if (++st->bucket >= INSTANCE_BUCKETS) -+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS) - return NULL; - -- h = instance_table[st->bucket].first; -+ h = net->nfqnl.instance_table[st->bucket].first; - } - return h; - } - --static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) -+static struct hlist_node *get_idx(struct net *net, struct iter_state *st, -+ loff_t pos) - { - struct hlist_node *head; -- head = get_first(seq); -+ head = get_first(net, st); - - if (head) -- while (pos && (head = get_next(seq, head))) -+ while (pos && (head = get_next(net, st, head))) - pos--; - return pos ? NULL : head; - } - - static void *seq_start(struct seq_file *seq, loff_t *pos) -- __acquires(instances_lock) - { -- spin_lock(&instances_lock); -- return get_idx(seq, *pos); -+ struct net *net = seq_file_net(seq); -+ spin_lock(&net->nfqnl.instances_lock); -+ return get_idx(net, seq->private, *pos); - } - - static void *seq_next(struct seq_file *s, void *v, loff_t *pos) - { - (*pos)++; -- return get_next(s, v); -+ return get_next(seq_file_net(s), s->private, v); - } - - static void seq_stop(struct seq_file *s, void *v) -- __releases(instances_lock) - { -- spin_unlock(&instances_lock); -+ struct net *net = seq_file_net(s); -+ spin_unlock(&net->nfqnl.instances_lock); - } - - static int seq_show(struct seq_file *s, void *v) -@@ -1034,8 +1032,8 @@ static const struct seq_operations nfqnl_seq_ops = { - - static int nfqnl_open(struct inode *inode, struct file *file) - { -- return seq_open_private(file, &nfqnl_seq_ops, -- sizeof(struct iter_state)); -+ return seq_open_net(inode, file, &nfqnl_seq_ops, -+ sizeof(struct iter_state)); - } - - static const struct file_operations nfqnl_file_ops = { -@@ -1043,13 +1041,19 @@ static const struct file_operations nfqnl_file_ops = { - .open = nfqnl_open, - .read = seq_read, - .llseek = seq_lseek, -- .release = seq_release_private, -+ .release = seq_release_net, - }; - - #endif /* PROC_FS */ - - static int __net_init nfnetlink_queue_net_init(struct net *net) - { -+ int i; -+ -+ spin_lock_init(&net->nfqnl.instances_lock); -+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) -+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]); -+ - #ifdef CONFIG_PROC_FS - if (!proc_create("nfnetlink_queue", 0440, - net->proc_net_netfilter, &nfqnl_file_ops)) -@@ -1073,7 +1077,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = { - - static int __init nfnetlink_queue_init(void) - { -- int i, status; -+ int status; - - status = register_pernet_subsys(&nfnetlink_queue_net_ops); - if (status) { -@@ -1082,9 +1086,6 @@ static int __init nfnetlink_queue_init(void) - return status; - } - -- for (i = 0; i < INSTANCE_BUCKETS; i++) -- INIT_HLIST_HEAD(&instance_table[i]); -- - netlink_register_notifier(&nfqnl_rtnl_notifier); - status = nfnetlink_subsys_register(&nfqnl_subsys); - if (status < 0) { --- -1.8.1.2 - From ac705f49082dabca16de4deb401e63d21b006c59 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 8 Mar 2018 14:43:27 -0800 Subject: [PATCH 060/152] initial commit to remove packaging related files --- Makefile.am | 31 +- configure.ac | 6 +- doc/devguide.rst | 1 - packaging/deb.mk | 56 ---- packaging/deb/.gitignore | 3 - packaging/deb/changelog | 65 ---- packaging/deb/compat | 1 - packaging/deb/control | 28 -- packaging/deb/copyright | 35 --- packaging/deb/core-daemon.install.in | 19 -- packaging/deb/core-daemon.prerm.in | 56 ---- packaging/deb/core-gui.install.in | 9 - packaging/deb/rules | 18 -- packaging/rpm.mk | 40 --- packaging/rpm/.gitignore | 1 - packaging/rpm/core.spec.in | 424 --------------------------- packaging/rpm/specfiles.sh | 41 --- 17 files changed, 2 insertions(+), 832 deletions(-) delete mode 100644 packaging/deb.mk delete mode 100644 packaging/deb/.gitignore delete mode 100644 packaging/deb/changelog delete mode 100644 packaging/deb/compat delete mode 100644 packaging/deb/control delete mode 100644 packaging/deb/copyright delete mode 100644 packaging/deb/core-daemon.install.in delete mode 100644 packaging/deb/core-daemon.prerm.in delete mode 100644 packaging/deb/core-gui.install.in delete mode 100755 packaging/deb/rules delete mode 100644 packaging/rpm.mk delete mode 100644 packaging/rpm/.gitignore delete mode 100644 packaging/rpm/core.spec.in delete mode 100755 packaging/rpm/specfiles.sh diff --git a/Makefile.am b/Makefile.am index 4fa80ead..653c4091 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,17 +30,7 @@ EXTRA_DIST = bootstrap.sh LICENSE \ README.md ASSIGNMENT_OF_COPYRIGHT.pdf \ Changelog \ python-prefix.py revision.sh \ - .version .version.date \ - packaging/deb/compat \ - packaging/deb/copyright \ - packaging/deb/changelog \ - packaging/deb/rules \ - packaging/deb/control \ - packaging/deb/core-daemon.install.in \ - packaging/deb/core-daemon.prerm.in \ - packaging/deb/core-gui.install.in \ - packaging/rpm/core.spec.in \ - packaging/rpm/specfiles.sh + .version .version.date DISTCLEAN_TARGETS = aclocal.m4 config.h.in @@ -51,25 +41,6 @@ MAINTAINERCLEANFILES = \ .version \ .version.date -# build a source RPM -.PHONY: rpm -rpm: dist - mkdir -p $(HOME)/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} - echo '%_topdir $(HOME)/rpmbuild' > ~/.rpmmacros - cp -afv core-@CORE_VERSION@.tar.gz ~/rpmbuild/SOURCES - cp -afv packaging/rpm/core.spec ~/rpmbuild/SPECS - rpmbuild -bs ~/rpmbuild/SPECS/core.spec - -# build a Ubuntu deb package using CDBS -.PHONY: deb -deb: - rm -rf debian - mkdir -p debian - cp -vf packaging/deb/* debian/ - @echo "First create source archive with: dpkg-source -b core-@CORE_VERSION@" - @echo "Then build with: pbuilder-dist precise i386 build core*.dsc" - - define fpm-python = fpm -s python -t $1 \ -m "$(CORE_MAINTAINERS)" \ diff --git a/configure.ac b/configure.ac index e643110d..12d90cda 100644 --- a/configure.ac +++ b/configure.ac @@ -320,11 +320,7 @@ AC_CONFIG_FILES([Makefile netns/Makefile netns/version.h ns3/Makefile - ns3/corens3/constants.py - packaging/deb/core-daemon.install - packaging/deb/core-daemon.prerm - packaging/deb/core-gui.install - packaging/rpm/core.spec],) + ns3/corens3/constants.py],) AC_OUTPUT # Summary text diff --git a/doc/devguide.rst b/doc/devguide.rst index 9b703cca..bfb3aa37 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -37,7 +37,6 @@ These are being actively developed as of CORE |version|: * *netns* - Python extension modules for Linux Network Namespace support are in :file:`netns`. * *ns3* - Python ns3 script support for running CORE. * *doc* - Documentation for the manual lives here in reStructuredText format. -* *packaging* - Control files and script for building CORE packages are here. .. _The_CORE_API: diff --git a/packaging/deb.mk b/packaging/deb.mk deleted file mode 100644 index 14116c12..00000000 --- a/packaging/deb.mk +++ /dev/null @@ -1,56 +0,0 @@ -DEBBUILD = .debbuild - -CORE_VERSION = $(shell cat .version 2> /dev/null) - -COREBUILD = $(DEBBUILD)/core-$(CORE_VERSION) - -.PHONY: all -all: clean .version build - -.PHONY: clean -clean: - rm -rf $(DEBBUILD) - -.PHONY: build -build: changelog - cd $(COREBUILD) && dpkg-buildpackage -b -us -uc - @printf "\ndebian packages built in $(DEBBUILD)\n\n" - -.PHONY: changelog -changelog: debian - echo "core ($(CORE_VERSION)-1) unstable; urgency=low" > $(COREBUILD)/debian/changelog.generated - echo " * interim package generated from source" >> $(COREBUILD)/debian/changelog.generated - echo " -- CORE Developers $$(date -R)" >> $(COREBUILD)/debian/changelog.generated - cd $(COREBUILD)/debian && \ - { test ! -L changelog && mv -f changelog changelog.save; } && \ - { test "$$(readlink changelog)" = "changelog.generated" || \ - ln -sf changelog.generated changelog; } - -.PHONY: debian -debian: corebuild - cd $(COREBUILD) && ln -s packaging/deb debian - -.PHONY: corebuild -corebuild: $(DEBBUILD) dist - tar -C $(DEBBUILD) -xzf core-$(CORE_VERSION).tar.gz - -.PHONY: dist -dist: Makefile - $(MAKE) dist - -Makefile: configure - ./configure - -configure: bootstrap.sh - ./bootstrap.sh - -bootstrap.sh: - @printf "\nERROR: make must be called from the top-level directory:\n" - @printf " make -f packaging/$(lastword $(MAKEFILE_LIST))\n\n" - @false - -.version: Makefile - $(MAKE) $@ - -$(DEBBUILD): - mkdir -p $@ diff --git a/packaging/deb/.gitignore b/packaging/deb/.gitignore deleted file mode 100644 index 790c34ec..00000000 --- a/packaging/deb/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -core-daemon.install -core-gui.install -core-daemon.prerm diff --git a/packaging/deb/changelog b/packaging/deb/changelog deleted file mode 100644 index fa84b69b..00000000 --- a/packaging/deb/changelog +++ /dev/null @@ -1,65 +0,0 @@ -core (5.0-0ubuntu1) precise; urgency=low - - * Added Ryu SD and Open vSwitch services, code cleanup and refactoring - - -- CORE Developers Fri, 01 Sep 2017 00:00:00 -0700 - -core (4.8-0ubuntu1) precise; urgency=low - - * Support for NRL Network Modeling Framework (NMF) XML representation, bugfixes - - -- CORE Developers Fri, 05 Jun 2015 00:00:00 -0700 - -core (4.7-0ubuntu1) precise; urgency=low - - * EMANE 0.9.1, asymmetric links, bugfixes - - -- Jeff Ahrenholz Wed, 08 Aug 2014 08:27:18 -0700 - -core (4.6-0ubuntu1) precise; urgency=low - - * Edit Copy and Paste, Edit Find, bugfixes, Debian compliance - - -- Jeff Ahrenholz Wed, 25 Sep 2013 12:36:54 -0700 - -core (4.5-0ubuntu1) precise; urgency=low - - * XML support, SDT3D support, EMANE 0.8.1, ns-3 locations, code cleanup, - bugfixes, and more. - - -- Jeff Ahrenholz Thu, 11 Apr 2013 14:19:05 -0700 - -core (4.4-0ubuntu1) precise; urgency=low - - * Bandwidth plots, event scheduling, EMANE 0.7.4, improved services support, - code cleanup, bugfixes, and more. - - -- Jeff Ahrenholz Tue, 04 Sep 2012 11:53:23 -0700 - -core (4.3-0ubuntu1) oneiric; urgency=low - - * Hook scripts, CEL, EMANE 0.7.3, physical nodes, improved WLAN and service - dialogs, code cleanup, bugfixes, and more. - - -- Jeff Ahrenholz Thu, 09 Feb 2012 08:00:52 -0800 - -core (4.2-0ubuntu1) maverick; urgency=low - - * bugfixes, EMANE 0.7.1 support. - - -- Jeff Ahrenholz Mon, 15 Aug 2011 13:19:16 -0800 - -core (4.1-0ubuntu1) lucid; urgency=low - - * Node services, customizable nodes, traffic flows, IP address allocator, - distributed emulation using GRE tunnels, EMANE 0.6.4 support, and more. - - -- Jeff Ahrenholz Thu, 09 Dec 2010 07:02:16 -0800 - -core (4.0-0ubuntu1) lucid; urgency=low - - * New CORE deb packaging. Extra magic added to omit the horrible - /usr/share/info/dir.gz file from being generated. - - -- Jeff Ahrenholz Wed, 29 Jul 2010 16:07:26 -0700 - diff --git a/packaging/deb/compat b/packaging/deb/compat deleted file mode 100644 index ec635144..00000000 --- a/packaging/deb/compat +++ /dev/null @@ -1 +0,0 @@ -9 diff --git a/packaging/deb/control b/packaging/deb/control deleted file mode 100644 index 15caa7a3..00000000 --- a/packaging/deb/control +++ /dev/null @@ -1,28 +0,0 @@ -Source: core -Section: net -Priority: optional -Maintainer: CORE Developers -Standards-Version: 3.8.4 -Build-Depends: debhelper (>= 9), cdbs, dh-autoreconf, autoconf, automake, gcc, libev-dev, make, python-dev, libreadline-dev, bridge-utils, ebtables, iproute2 | iproute, imagemagick, pkg-config, help2man -# python-sphinx -Homepage: http://www.nrl.navy.mil/itd/ncs/products/core - -Package: core-daemon -Architecture: any -Depends: bash (>=3.0), bridge-utils, ebtables, iproute2 | iproute, libev4, python (>=2.6), dpkg (>=1.15.4), procps, ${shlibs:Depends} -Recommends: quagga -Description: Emulate virtual networks in a box. - The Common Open Research Emulator provides Python modules for building virtual - networks using Linux network namespace containers and bridging. This is the - daemon package containing the backend Python modules and core-daemon. - -Package: core-gui -Architecture: all -Depends: bash (>=3.0), tcl (>= 8.5), tk (>= 8.5), xterm -Recommends: libtk-img -Description: Emulate virtual networks in a box. - The Common Open Research Emulator provides Python modules for building virtual - networks using Linux network namespace containers and bridging. This is the - GUI package containing a canvas-based Tcl/Tk GUI for easily drawing virtual - network topologies. - diff --git a/packaging/deb/copyright b/packaging/deb/copyright deleted file mode 100644 index 04f2a7bd..00000000 --- a/packaging/deb/copyright +++ /dev/null @@ -1,35 +0,0 @@ -This package was debianized by Jeff Ahrenholz -4/3/13 - -It was downloaded from: http://www.nrl.navy.mil/itd/ncs/products/core - -Upstream Author(s): Jeff Ahrenholz - -Copyright: - Copyright (C) 2010-2013, the Boeing Company. - -License: - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -THE POSSIBILITY OF SUCH DAMAGE. - -Packaging: - Copyright (C) 2010-2013, the Boeing Company. diff --git a/packaging/deb/core-daemon.install.in b/packaging/deb/core-daemon.install.in deleted file mode 100644 index 8dda2c9c..00000000 --- a/packaging/deb/core-daemon.install.in +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/dh-exec -@SBINDIR@ -@CORE_CONF_DIR@ -@CORE_DATA_DIR@/examples/corens3 -@CORE_DATA_DIR@/examples/*.py -@CORE_DATA_DIR@/examples/hooks -@CORE_DATA_DIR@/examples/myservices -@CORE_DATA_DIR@/examples/netns -@CORE_DATA_DIR@/examples/services -# ATmandirAT is expanding to ${datarootdir}/man -@datarootdir@/man/man1/vnoded.1 -@datarootdir@/man/man1/vcmd.1 -@datarootdir@/man/man1/netns.1 -@datarootdir@/man/man1/core-daemon.1 -@datarootdir@/man/man1/coresendmsg.1 -@datarootdir@/man/man1/core-cleanup.1 -@pyprefix@/lib/python2.7/dist-packages -/etc/init.d -/etc/logrotate.d diff --git a/packaging/deb/core-daemon.prerm.in b/packaging/deb/core-daemon.prerm.in deleted file mode 100644 index e8f134a9..00000000 --- a/packaging/deb/core-daemon.prerm.in +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -SBINDIR=@SBINDIR@ -pyprefix=@pyprefix@ -pythondir=@pythondir@ - -core_daemon_stop() -{ - if [ -x /etc/init.d/core-daemon ]; then - /etc/init.d/core-daemon stop - fi - - if [ -x $SBINDIR/core-cleanup ]; then - $SBINDIR/core-cleanup - fi - - if [ -d $pythondir/core ]; then - find $pythondir/core -name '*.pyc' -delete - fi -} - -case "$1" in - remove|upgrade|deconfigure) - core_daemon_stop > /dev/null 2>&1 - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/packaging/deb/core-gui.install.in b/packaging/deb/core-gui.install.in deleted file mode 100644 index 89bbc19c..00000000 --- a/packaging/deb/core-gui.install.in +++ /dev/null @@ -1,9 +0,0 @@ -#! /usr/bin/dh-exec -@BINDIR@/core-gui -@CORE_LIB_DIR@ -@CORE_DATA_DIR@/icons -@CORE_DATA_DIR@/examples/configs -@datarootdir@/pixmaps -@datarootdir@/applications -# ATmandirAT is expanding to ${datarootdir}/man -@datarootdir@/man/man1/core-gui.1 diff --git a/packaging/deb/rules b/packaging/deb/rules deleted file mode 100755 index d26bee7e..00000000 --- a/packaging/deb/rules +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/make -f - -# See debhelper(7) (uncomment to enable) -# output every command that modifies files on the build system. -# DH_VERBOSE = 1 - -include /usr/share/cdbs/1/rules/debhelper.mk -include /usr/share/cdbs/1/class/autotools.mk -include /usr/share/cdbs/1/rules/autoreconf.mk - -DEB_DH_AUTORECONF_ARGS += ./bootstrap.sh - -# this prevents 'make install' from invoking install-info that generates a -# $(DEB_DESTDIR)usr/share/info/dir.gz file that causes a lintian error -# the following rule was not enough -# binary-post-install/core:: -# rm -f $(DEB_DESTDIR)usr/share/info/dir.gz -#DEB_CONFIGURE_EXTRA_FLAGS := --disable-install-info diff --git a/packaging/rpm.mk b/packaging/rpm.mk deleted file mode 100644 index cb70c141..00000000 --- a/packaging/rpm.mk +++ /dev/null @@ -1,40 +0,0 @@ -RPMBUILD = .rpmbuild - -CORE_VERSION = $(shell cat .version 2> /dev/null) - -.PHONY: all -all: clean .version build - -.PHONY: clean -clean: - rm -rf $(RPMBUILD) - -.PHONY: build -build: dist - for d in SOURCES SPECS; do mkdir -p $(RPMBUILD)/$$d; done - cp -afv core-$(CORE_VERSION).tar.gz $(RPMBUILD)/SOURCES - cp -afv packaging/rpm/core.spec $(RPMBUILD)/SPECS - rpmbuild -bb --clean $(RPMBUILD)/SPECS/core.spec \ - --define "_topdir $$PWD/.rpmbuild" - @printf "\nRPM packages saved in $(RPMBUILD)/RPMS\n\n" - -.PHONY: dist -dist: Makefile - $(MAKE) dist - -Makefile: configure - ./configure --prefix=/usr --exec-prefix=/usr - -configure: bootstrap.sh - ./bootstrap.sh - -bootstrap.sh: - @printf "\nERROR: make must be called from the top-level directory:\n" - @printf " make -f packaging/$(lastword $(MAKEFILE_LIST))\n\n" - @false - -.version: Makefile - $(MAKE) $@ - -$(RPMBUILD): - mkdir -p $@ diff --git a/packaging/rpm/.gitignore b/packaging/rpm/.gitignore deleted file mode 100644 index c40ee150..00000000 --- a/packaging/rpm/.gitignore +++ /dev/null @@ -1 +0,0 @@ -core.spec diff --git a/packaging/rpm/core.spec.in b/packaging/rpm/core.spec.in deleted file mode 100644 index 90266115..00000000 --- a/packaging/rpm/core.spec.in +++ /dev/null @@ -1,424 +0,0 @@ -%define version @PACKAGE_VERSION@ -%define lib_version @GENERIC_RELEASE@ -%define python_version %(%{__python} -c "import sys; print '%s.%s' % (sys.version_info[0], sys.version_info[1])")%{nil} - -%if 0%{?fedora} >= 17 -%define with_kernel_modules_extra 1 -%else -%define with_kernel_modules_extra 0 -%endif - -Name: core -Summary: Common Open Research Emulator for use with network namespaces -License: BSD -Prefix: /usr -Release: 1%{?dist} -Source: core-%{version}.tar.gz -URL: http://www.nrl.navy.mil/itd/ncs/products/core -Version: %{version} -%description -The Common Open Research Emulator provides Python modules and a GUI for -building virtual networks using Linux network namespace containers and bridging. - -%package daemon -Summary: Common Open Research Emulator daemon back-end -Group: System Tools -Requires: bash bridge-utils ebtables iproute libev python net-tools -%if 0%{?el6} -Requires: procps -%else -Requires: procps-ng -%endif -%if %{with_kernel_modules_extra} -Requires: kernel-modules-extra -%endif -%if 0%{?fedora} >= 25 -Requires: iproute-tc -%endif -BuildRequires: make automake autoconf libev-devel python-devel bridge-utils ebtables iproute net-tools ImageMagick help2man -%if 0%{?el6} -BuildRequires: procps -%else -BuildRequires: procps-ng -%endif -%if 0%{?fedora} >= 25 -BuildRequires: iproute-tc -%endif -Provides: core-daemon -# python-sphinx -%description daemon -The Common Open Research Emulator provides Python modules for building virtual -networks using Linux network namespace containers and bridging. - -%package gui -Summary: Common Open Research Emulator GUI front-end -Group: System Tools -Requires: tcl tk xterm -BuildArch: noarch -BuildRequires: make automake autoconf -Provides: core-gui -%description gui -The Common Open Research Emulator canvas-based Tcl/Tk GUI for easily drawing -virtual network topologies. - -%prep - -%setup -q - -%build - -./bootstrap.sh -# not using --disable-gui/--disable-daemon, because RPM expects both to be -# installed by this build process -# assume Fedora, using systemd startup script -CFLAGS="-fno-strict-aliasing $RPM_OPT_FLAGS" %configure --with-startup=systemd -make -j4 - -%install -rm -rf $RPM_BUILD_ROOT -make DESTDIR=$RPM_BUILD_ROOT install - -%clean -rm -rf $RPM_BUILD_ROOT - -%post - -%post daemon -# don't run EMANE with realtime option under Fedora -sed -i 's/emane_realtime = True/emane_realtime = False/' /etc/core/core.conf - -%preun daemon -if [ "$1" -eq 0 ]; then - systemctl stop core-daemon.service > /dev/null 2>&1 || true - - if [ -x @SBINDIR@/core-cleanup ]; then - @SBINDIR@/core-cleanup > /dev/null 2>&1 || true - fi -fi - -%postun - -%files gui -%{_bindir}/core-gui -%dir @CORE_LIB_DIR@ -%dir @CORE_LIB_DIR@/addons -@CORE_LIB_DIR@/addons/ipsecservice.tcl -@CORE_LIB_DIR@/annotations.tcl -@CORE_LIB_DIR@/api.tcl -@CORE_LIB_DIR@/canvas.tcl -@CORE_LIB_DIR@/cfgparse.tcl -@CORE_LIB_DIR@/core-bsd-cleanup.sh -@CORE_LIB_DIR@/core.tcl -@CORE_LIB_DIR@/debug.tcl -@CORE_LIB_DIR@/editor.tcl -@CORE_LIB_DIR@/exceptions.tcl -@CORE_LIB_DIR@/exec.tcl -@CORE_LIB_DIR@/filemgmt.tcl -@CORE_LIB_DIR@/gpgui.tcl -@CORE_LIB_DIR@/graph_partitioning.tcl -@CORE_LIB_DIR@/help.tcl -%{_datadir}/applications/core-gui.desktop -%{_datadir}/pixmaps/core-gui.xpm -%dir %{_datadir}/%{name} -%dir %{_datadir}/%{name}/icons -%dir %{_datadir}/%{name}/icons/normal -%{_datadir}/%{name}/icons/normal/antenna.gif -%{_datadir}/%{name}/icons/normal/ap.gif -%{_datadir}/%{name}/icons/normal/core-icon.png -%{_datadir}/%{name}/icons/normal/core-icon.xbm -%{_datadir}/%{name}/icons/normal/core-logo-275x75.gif -%{_datadir}/%{name}/icons/normal/document-properties.gif -%{_datadir}/%{name}/icons/normal/gps-diagram.xbm -%{_datadir}/%{name}/icons/normal/host.gif -%{_datadir}/%{name}/icons/normal/hub.gif -%{_datadir}/%{name}/icons/normal/lanswitch.gif -%{_datadir}/%{name}/icons/normal/mdr.gif -%{_datadir}/%{name}/icons/normal/oval.gif -%{_datadir}/%{name}/icons/normal/pc.gif -%{_datadir}/%{name}/icons/normal/rj45.gif -%{_datadir}/%{name}/icons/normal/router_black.gif -%{_datadir}/%{name}/icons/normal/router.gif -%{_datadir}/%{name}/icons/normal/router_green.gif -%{_datadir}/%{name}/icons/normal/router_purple.gif -%{_datadir}/%{name}/icons/normal/router_red.gif -%{_datadir}/%{name}/icons/normal/router_yellow.gif -%{_datadir}/%{name}/icons/normal/simple.xbm -%{_datadir}/%{name}/icons/normal/text.gif -%{_datadir}/%{name}/icons/normal/thumb-unknown.gif -%{_datadir}/%{name}/icons/normal/tunnel.gif -%{_datadir}/%{name}/icons/normal/wlan.gif -%dir %{_datadir}/%{name}/icons/svg -%{_datadir}/%{name}/icons/svg/ap.svg -%{_datadir}/%{name}/icons/svg/cel.svg -%{_datadir}/%{name}/icons/svg/hub.svg -%{_datadir}/%{name}/icons/svg/lanswitch.svg -%{_datadir}/%{name}/icons/svg/mdr.svg -%{_datadir}/%{name}/icons/svg/otr.svg -%{_datadir}/%{name}/icons/svg/rj45.svg -%{_datadir}/%{name}/icons/svg/router_black.svg -%{_datadir}/%{name}/icons/svg/router_green.svg -%{_datadir}/%{name}/icons/svg/router_purple.svg -%{_datadir}/%{name}/icons/svg/router_red.svg -%{_datadir}/%{name}/icons/svg/router.svg -%{_datadir}/%{name}/icons/svg/router_yellow.svg -%{_datadir}/%{name}/icons/svg/start.svg -%{_datadir}/%{name}/icons/svg/tunnel.svg -%{_datadir}/%{name}/icons/svg/vlan.svg -%dir %{_datadir}/%{name}/icons/tiny -%{_datadir}/%{name}/icons/tiny/ap.gif -%{_datadir}/%{name}/icons/tiny/arrow.down.gif -%{_datadir}/%{name}/icons/tiny/arrow.gif -%{_datadir}/%{name}/icons/tiny/arrow.up.gif -%{_datadir}/%{name}/icons/tiny/blank.gif -%{_datadir}/%{name}/icons/tiny/button.play.gif -%{_datadir}/%{name}/icons/tiny/button.stop.gif -%{_datadir}/%{name}/icons/tiny/cel.gif -%{_datadir}/%{name}/icons/tiny/delete.gif -%{_datadir}/%{name}/icons/tiny/document-new.gif -%{_datadir}/%{name}/icons/tiny/document-properties.gif -%{_datadir}/%{name}/icons/tiny/document-save.gif -%{_datadir}/%{name}/icons/tiny/edit-delete.gif -%{_datadir}/%{name}/icons/tiny/eraser.gif -%{_datadir}/%{name}/icons/tiny/fileopen.gif -%{_datadir}/%{name}/icons/tiny/folder.gif -%{_datadir}/%{name}/icons/tiny/host.gif -%{_datadir}/%{name}/icons/tiny/hub.gif -%{_datadir}/%{name}/icons/tiny/lanswitch.gif -%{_datadir}/%{name}/icons/tiny/link.gif -%{_datadir}/%{name}/icons/tiny/marker.gif -%{_datadir}/%{name}/icons/tiny/mdr.gif -%{_datadir}/%{name}/icons/tiny/mobility.gif -%{_datadir}/%{name}/icons/tiny/moboff.gif -%{_datadir}/%{name}/icons/tiny/observe.gif -%{_datadir}/%{name}/icons/tiny/oval.gif -%{_datadir}/%{name}/icons/tiny/pc.gif -%{_datadir}/%{name}/icons/tiny/ping.gif -%{_datadir}/%{name}/icons/tiny/plot.gif -%{_datadir}/%{name}/icons/tiny/rectangle.gif -%{_datadir}/%{name}/icons/tiny/rj45.gif -%{_datadir}/%{name}/icons/tiny/router_black.gif -%{_datadir}/%{name}/icons/tiny/router.gif -%{_datadir}/%{name}/icons/tiny/router_green.gif -%{_datadir}/%{name}/icons/tiny/router_purple.gif -%{_datadir}/%{name}/icons/tiny/router_red.gif -%{_datadir}/%{name}/icons/tiny/router_yellow.gif -%{_datadir}/%{name}/icons/tiny/run.gif -%{_datadir}/%{name}/icons/tiny/script_pause.gif -%{_datadir}/%{name}/icons/tiny/script_play.gif -%{_datadir}/%{name}/icons/tiny/script_stop.gif -%{_datadir}/%{name}/icons/tiny/select.gif -%{_datadir}/%{name}/icons/tiny/start.gif -%{_datadir}/%{name}/icons/tiny/stock_connect.gif -%{_datadir}/%{name}/icons/tiny/stock_disconnect.gif -%{_datadir}/%{name}/icons/tiny/stop.gif -%{_datadir}/%{name}/icons/tiny/text.gif -%{_datadir}/%{name}/icons/tiny/trace.gif -%{_datadir}/%{name}/icons/tiny/tunnel.gif -%{_datadir}/%{name}/icons/tiny/twonode.gif -%{_datadir}/%{name}/icons/tiny/view-refresh.gif -%{_datadir}/%{name}/icons/tiny/wlan.gif -@CORE_LIB_DIR@/initgui.tcl -@CORE_LIB_DIR@/ipv4.tcl -@CORE_LIB_DIR@/ipv6.tcl -@CORE_LIB_DIR@/linkcfg.tcl -@CORE_LIB_DIR@/mobility.tcl -@CORE_LIB_DIR@/nodecfg.tcl -@CORE_LIB_DIR@/nodes.tcl -@CORE_LIB_DIR@/ns2imunes.tcl -@CORE_LIB_DIR@/plugins.tcl -@CORE_LIB_DIR@/services.tcl -@CORE_LIB_DIR@/tooltips.tcl -@CORE_LIB_DIR@/topogen.tcl -@CORE_LIB_DIR@/traffic.tcl -@CORE_LIB_DIR@/util.tcl -@CORE_LIB_DIR@/version.tcl -@CORE_LIB_DIR@/widget.tcl -@CORE_LIB_DIR@/wlanscript.tcl -@CORE_LIB_DIR@/wlan.tcl -%dir %{_datadir}/%{name}/examples -%dir %{_datadir}/%{name}/examples/configs -%{_datadir}/%{name}/examples/configs/sample10-kitchen-sink.imn -%{_datadir}/%{name}/examples/configs/sample1-bg.gif -%{_datadir}/%{name}/examples/configs/sample1.imn -%{_datadir}/%{name}/examples/configs/sample1.scen -%{_datadir}/%{name}/examples/configs/sample2-ssh.imn -%{_datadir}/%{name}/examples/configs/sample3-bgp.imn -%{_datadir}/%{name}/examples/configs/sample4-bg.jpg -%{_datadir}/%{name}/examples/configs/sample4-nrlsmf.imn -%{_datadir}/%{name}/examples/configs/sample4.scen -%{_datadir}/%{name}/examples/configs/sample5-mgen.imn -%{_datadir}/%{name}/examples/configs/sample6-emane-rfpipe.imn -%{_datadir}/%{name}/examples/configs/sample7-emane-ieee80211abg.imn -%{_datadir}/%{name}/examples/configs/sample8-ipsec-service.imn -%{_datadir}/%{name}/examples/configs/sample9-vpn.imn -%doc %{_mandir}/man1/core-gui.1.gz - -%files daemon -%config @CORE_CONF_DIR@/core.conf -%config @CORE_CONF_DIR@/perflogserver.conf -%dir %{_datadir}/%{name} -%dir %{_datadir}/%{name}/examples -%{_datadir}/%{name}/examples/controlnet_updown -%dir %{_datadir}/%{name}/examples/corens3 -%{_datadir}/%{name}/examples/corens3/ns3lte.py* -%{_datadir}/%{name}/examples/corens3/ns3wifi.py* -%{_datadir}/%{name}/examples/corens3/ns3wifirandomwalk.py* -%{_datadir}/%{name}/examples/corens3/ns3wimax.py* -%{_datadir}/%{name}/examples/emanemanifest2core.py* -%{_datadir}/%{name}/examples/emanemodel2core.py* -%{_datadir}/%{name}/examples/findcore.py* -%dir %{_datadir}/%{name}/examples/hooks -%{_datadir}/%{name}/examples/hooks/configuration_hook.sh -%{_datadir}/%{name}/examples/hooks/datacollect_hook.sh -%{_datadir}/%{name}/examples/hooks/perflogserver.py* -%{_datadir}/%{name}/examples/hooks/perflogstart.sh -%{_datadir}/%{name}/examples/hooks/perflogstop.sh -%{_datadir}/%{name}/examples/hooks/sessiondatacollect.sh -%{_datadir}/%{name}/examples/hooks/timesyncstart.sh -%{_datadir}/%{name}/examples/hooks/timesyncstop.sh -%dir %{_datadir}/%{name}/examples/myservices -%{_datadir}/%{name}/examples/myservices/__init__.py* -%{_datadir}/%{name}/examples/myservices/README.txt -%{_datadir}/%{name}/examples/myservices/sample.py* -%dir %{_datadir}/%{name}/examples/netns -%{_datadir}/%{name}/examples/netns/basicrange.py* -%{_datadir}/%{name}/examples/netns/daemonnodes.py* -%{_datadir}/%{name}/examples/netns/distributed.py* -%{_datadir}/%{name}/examples/netns/emane80211.py* -%{_datadir}/%{name}/examples/netns/howmanynodes.py* -%{_datadir}/%{name}/examples/netns/iperf-performance-chain.py* -%{_datadir}/%{name}/examples/netns/iperf-performance.sh -%{_datadir}/%{name}/examples/netns/ospfmanetmdrtest.py* -%{_datadir}/%{name}/examples/netns/switch.py* -%{_datadir}/%{name}/examples/netns/switchtest.py* -%{_datadir}/%{name}/examples/netns/twonodes.sh -%{_datadir}/%{name}/examples/netns/wlanemanetests.py* -%{_datadir}/%{name}/examples/netns/wlantest.py* -%dir %{_datadir}/%{name}/examples/services -%{_datadir}/%{name}/examples/services/sampleFirewall -%{_datadir}/%{name}/examples/services/sampleIPsec -%{_datadir}/%{name}/examples/services/sampleVPNClient -%{_datadir}/%{name}/examples/services/sampleVPNServer -%{_datadir}/%{name}/examples/stopsession.py* -%doc %{_mandir}/man1/core-cleanup.1.gz -%doc %{_mandir}/man1/core-daemon.1.gz -%doc %{_mandir}/man1/core-manage.1.gz -%doc %{_mandir}/man1/coresendmsg.1.gz -%doc %{_mandir}/man1/netns.1.gz -%doc %{_mandir}/man1/vcmd.1.gz -%doc %{_mandir}/man1/vnoded.1.gz -/etc/logrotate.d/core-daemon -/etc/systemd/system/core-daemon.service -%{python_sitearch}/core_python_netns-1.0-py%{python_version}.egg-info -%{python_sitearch}/netns.so -%{python_sitearch}/vcmd.so -%dir %{python_sitelib}/core -%{python_sitelib}/core/sdt.py* -%{python_sitelib}/core/service.py* -%{python_sitelib}/core/coreserver.py* -%dir %{python_sitelib}/core/api -%{python_sitelib}/core/api/coreapi.py* -%{python_sitelib}/core/api/data.py* -%{python_sitelib}/core/api/__init__.py* -%{python_sitelib}/core/broker.py* -%dir %{python_sitelib}/core/bsd -%{python_sitelib}/core/bsd/__init__.py* -%{python_sitelib}/core/bsd/netgraph.py* -%{python_sitelib}/core/bsd/nodes.py* -%{python_sitelib}/core/bsd/vnet.py* -%{python_sitelib}/core/bsd/vnode.py* -%{python_sitelib}/core/conf.py* -%{python_sitelib}/core/constants.py* -%{python_sitelib}/core/coreobj.py* -%dir %{python_sitelib}/core/emane -%{python_sitelib}/core/emane/bypass.py* -%{python_sitelib}/core/emane/commeffect.py* -%{python_sitelib}/core/emane/emane.py* -%{python_sitelib}/core/emane/ieee80211abg.py* -%{python_sitelib}/core/emane/__init__.py* -%{python_sitelib}/core/emane/nodes.py* -%{python_sitelib}/core/emane/rfpipe.py* -%{python_sitelib}/core/emane/tdma.py* -%{python_sitelib}/core/emane/universal.py* -%{python_sitelib}/core/__init__.py* -%{python_sitelib}/core/location.py* -%dir %{python_sitelib}/core/misc -%{python_sitelib}/core/misc/event.py* -%{python_sitelib}/core/misc/__init__.py* -%{python_sitelib}/core/misc/ipaddr.py* -%{python_sitelib}/core/misc/LatLongUTMconversion.py* -%{python_sitelib}/core/misc/quagga.py* -%{python_sitelib}/core/misc/utils.py* -%{python_sitelib}/core/misc/utm.py* -%{python_sitelib}/core/misc/xmldeployment.py* -%{python_sitelib}/core/misc/xmlparser.py* -%{python_sitelib}/core/misc/xmlparser0.py* -%{python_sitelib}/core/misc/xmlparser1.py* -%{python_sitelib}/core/misc/xmlsession.py* -%{python_sitelib}/core/misc/xmlutils.py* -%{python_sitelib}/core/misc/xmlwriter.py* -%{python_sitelib}/core/misc/xmlwriter0.py* -%{python_sitelib}/core/misc/xmlwriter1.py* -%{python_sitelib}/core/mobility.py* -%dir %{python_sitelib}/core/netns -%{python_sitelib}/core/netns/__init__.py* -%{python_sitelib}/core/netns/nodes.py* -%{python_sitelib}/core/netns/vif.py* -%{python_sitelib}/core/netns/vnet.py* -%{python_sitelib}/core/netns/vnodeclient.py* -%{python_sitelib}/core/netns/vnode.py* -%dir %{python_sitelib}/corens3 -%{python_sitelib}/corens3/constants.py* -%{python_sitelib}/corens3/__init__.py* -%{python_sitelib}/corens3/obj.py* -%{python_sitelib}/corens3_python-@COREDPY_VERSION@-py%{python_version}.egg-info -%dir %{python_sitelib}/core/phys -%{python_sitelib}/core/phys/__init__.py* -%{python_sitelib}/core/phys/pnodes.py* -%{python_sitelib}/core_python-@COREDPY_VERSION@-py%{python_version}.egg-info -%dir %{python_sitelib}/core/services -%{python_sitelib}/core/services/bird.py* -%{python_sitelib}/core/services/__init__.py* -%{python_sitelib}/core/services/dockersvc.py* -%{python_sitelib}/core/services/nrl.py* -%{python_sitelib}/core/services/quagga.py* -%{python_sitelib}/core/services/security.py* -%{python_sitelib}/core/services/startup.py* -%{python_sitelib}/core/services/ucarp.py* -%{python_sitelib}/core/services/utility.py* -%{python_sitelib}/core/services/xorp.py* -%{python_sitelib}/core/session.py* -%{_sbindir}/core-cleanup -%{_sbindir}/core-daemon -%{_sbindir}/core-manage -%{_sbindir}/coresendmsg -%{_sbindir}/netns -%{_sbindir}/vcmd -%{_sbindir}/vnoded - -%changelog -* Fri Sep 01 2017 CORE Developers - 5.0 -- Added Ryu SD and Open vSwitch services, code cleanup and refactoring -* Fri Jun 5 2015 CORE Developers - 4.8 -- Support for NRL Network Modeling Framework (NMF) XML representation, bugfixes -* Wed Aug 6 2014 Jeff Ahrenholz - 4.7 -- EMANE 0.9.1, asymmetric links, bugfixes -* Thu Aug 22 2013 Jeff Ahrenholz - 4.6 -- cored now core-daemon, core now core-gui for CORE 4.6 release -* Wed Apr 3 2013 Jeff Ahrenholz - 4.5 -- split into gui and daemon RPMs for CORE 4.5 release -* Tue Sep 4 2012 Jeff Ahrenholz - 4.4 -- update files list for CORE 4.4 release, removed info file -* Tue Feb 7 2012 Jeff Ahrenholz - 4.3 -- update files list for CORE 4.3 release, freshen dependencies -* Tue Aug 16 2011 Jeff Ahrenholz - 4.2 -- update for CORE 4.2 release; use dir variables, more arch independent -* Mon Dec 13 2010 Jeff Ahrenholz - 4.1 -- update for CORE 4.1 release; added calls to ldconfig and removal of pyc files -* Wed Aug 4 2010 Jeff Ahrenholz - 4.0 -- update for CORE 4.0 release for Python and network namespaces -* Thu Sep 10 2009 Jeff Ahrenholz - 3.5 -- update for CORE 3.5 release to include init script -* Fri May 29 2009 Jeff Ahrenholz - 3.4 -- initial spec file for CORE 3.4 release - diff --git a/packaging/rpm/specfiles.sh b/packaging/rpm/specfiles.sh deleted file mode 100755 index 640fb18b..00000000 --- a/packaging/rpm/specfiles.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -OLDDIR=$PWD -cd ../../ - -if [ ! -e Makefile ]; then - echo "Missing file: Makefile" -fi -VER=`grep PACKAGE_VERSION Makefile | awk '{ print $3 }'` -echo "Detected CORE version $VER." - -DESTDIR=/tmp/corerpmspec make install -if [ $? != 0 ]; then - exit 1 -fi -cd /tmp/corerpmspec -find . -type f | sort > newspecfiles.log -# append all .py files with .py* so .pyc files are uninstalled -sed -i 's/\.py$/.py*/g' newspecfiles.log -# directory replacements -sed -i 's/^\.\//\//g' newspecfiles.log -sed -i 's/\/usr\/bin/%{_bindir}/g' newspecfiles.log -sed -i 's/\/usr\/sbin/%{_sbindir}/g' newspecfiles.log -sed -i 's/\/usr\/lib64\/python2.7\/site-packages/%{python_sitearch}/g' newspecfiles.log -sed -i 's/\/usr\/lib\/python2.7\/site-packages/%{python_sitelib}/g' newspecfiles.log -sed -i 's/\/usr\/lib\/python2.7\/dist-packages/%{python_sitelib}/g' newspecfiles.log -sed -i 's/\/usr\/lib\/core/@CORE_LIB_DIR@/g' newspecfiles.log -sed -i 's/\/usr\/share\/applications/%{_datadir}\/applications/g' newspecfiles.log -sed -i 's/\/usr\/share\/pixmaps/%{_datadir}\/pixmaps/g' newspecfiles.log -sed -i 's/\/usr\/share\/core/%{_datadir}\/%{name}/g' newspecfiles.log -sed -i 's/\/etc\/core/%config @CORE_CONF_DIR@/g' newspecfiles.log -sed -i 's/py2.7.egg/py@PYTHON_VERSION@.egg/g' newspecfiles.log -sed -i "s/$VER/@COREDPY_VERSION@/g" newspecfiles.log -sed -i 's/\/usr\/share\/man/%doc %{_mandir}/g' newspecfiles.log -sed -i 's/\.1$/.1.gz/g' newspecfiles.log - -echo . -echo A new filelist is available here: -ls -al /tmp/corerpmspec/newspecfiles.log -echo . -cd $OLDDIR From 6210e70c8019b016c590de3bae3bdf7bd16065cb Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 13 Mar 2018 16:20:50 -0700 Subject: [PATCH 061/152] initial cleanup passing over all makefiles and configure.ac --- Makefile.am | 122 ++++++++---- configure.ac | 308 +++++++++++-------------------- daemon/MANIFEST.in | 4 - daemon/Makefile.am | 113 +++--------- daemon/core/constants.py.in | 38 ++-- daemon/core/netns/vnode.py | 2 +- daemon/core/netns/vnodeclient.py | 8 +- daemon/doc/conf.py.in | 4 +- daemon/setup.py | 38 +--- doc/conf.py.in | 4 +- doc/man/Makefile.am | 8 +- gui/Makefile.am | 57 ++---- gui/core-gui.in | 4 +- gui/icons/Makefile.am | 95 ++-------- gui/icons/normal/OVS.gif | Bin gui/icons/svg/OVS.svg | 0 gui/icons/tiny/OVS.gif | Bin gui/version.tcl.in | 4 +- netns/MANIFEST.in | 1 - netns/Makefile.am | 66 +++---- netns/setup.py | 20 -- netns/version.h.in | 2 +- ns3/Makefile.am | 43 ++--- ns3/corens3/.gitignore | 1 - ns3/corens3/constants.py.in | 18 -- ns3/setup.py | 5 + scripts/core-daemon.service.in | 2 +- scripts/perf/Makefile.am | 2 +- 28 files changed, 328 insertions(+), 641 deletions(-) delete mode 100644 daemon/MANIFEST.in mode change 100755 => 100644 gui/icons/normal/OVS.gif mode change 100755 => 100644 gui/icons/svg/OVS.svg mode change 100755 => 100644 gui/icons/tiny/OVS.gif delete mode 100644 ns3/corens3/.gitignore delete mode 100644 ns3/corens3/constants.py.in diff --git a/Makefile.am b/Makefile.am index 653c4091..4cfea830 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,55 +8,65 @@ # if WANT_DOCS - DOCS = doc + DOCS = doc endif + if WANT_GUI - GUI = gui + GUI = gui endif + if WANT_DAEMON - DAEMON = scripts daemon + DAEMON = scripts daemon endif + if WANT_NETNS - NETNS = netns ns3 + NETNS = netns ns3 endif # keep docs last due to dependencies on binaries -SUBDIRS = ${GUI} ${DAEMON} ${DOCS} ${NETNS} +SUBDIRS = $(GUI) $(DAEMON) $(NETNS) $(DOCS) -ACLOCAL_AMFLAGS = -I config +ACLOCAL_AMFLAGS = -I config # extra files to include with distribution tarball -EXTRA_DIST = bootstrap.sh LICENSE \ - README.md ASSIGNMENT_OF_COPYRIGHT.pdf \ - Changelog \ - python-prefix.py revision.sh \ - .version .version.date +EXTRA_DIST = bootstrap.sh \ + LICENSE \ + README.md \ + ASSIGNMENT_OF_COPYRIGHT.pdf \ + Changelog \ + python-prefix.py \ + revision.sh \ + .version \ + .version.date -DISTCLEAN_TARGETS = aclocal.m4 config.h.in +DISTCLEAN_TARGETS = aclocal.m4 config.h.in # extra cruft to remove -DISTCLEANFILES = aclocal.m4 config.h.in configure Makefile.in config/compile +DISTCLEANFILES = aclocal.m4 \ + config.h.in \ + configure \ + Makefile.in \ + config/compile -MAINTAINERCLEANFILES = \ - .version \ - .version.date +MAINTAINERCLEANFILES = .version \ + .version.date define fpm-python = fpm -s python -t $1 \ - -m "$(CORE_MAINTAINERS)" \ - --vendor "$(CORE_VENDOR)" \ + -m "$(PACKAGE_MAINTAINERS)" \ + --vendor "$(PACKAGE_VENDOR)" \ $2 endef define fpm-gui = fpm -s dir -t $1 -n core-gui \ - -m "$(CORE_MAINTAINERS)" \ + -m "$(PACKAGE_MAINTAINERS)" \ --license "BSD" \ --description "Common Open Research Emulator GUI front-end" \ --url http://www.nrl.navy.mil/itd/ncs/products/core \ - --vendor "$(CORE_VENDOR)" \ + --vendor "$(PACKAGE_VENDOR)" \ -p core-gui_VERSION_ARCH.$1 \ - -v $(CORE_VERSION) \ + -v $(PACKAGE_VERSION) \ -d "bash" \ -d "tcl" \ -d "tk" \ @@ -66,10 +76,13 @@ endef define fpm-daemon-rpm = fpm -s python -t rpm \ - -p NAME_$1_VERSION_ARCH.rpm \ - --python-setup-py-arguments --service=$1 \ - -m "$(CORE_MAINTAINERS)" \ - --vendor "$(CORE_VENDOR)" \ + -p NAME_sysv_VERSION_ARCH.rpm \ + --rpm-init scripts/core-daemon \ + --python-install-bin $(bindir) \ + --python-install-data $(prefix) \ + --python-install-lib $(pythondir) \ + -m "$(PACKAGE_MAINTAINERS)" \ + --vendor "$(PACKAGE_VENDOR)" \ -d "procps-ng" \ -d "bash >= 3.0" \ -d "bridge-utils" \ @@ -84,9 +97,12 @@ endef define fpm-daemon-deb = fpm -s python -t deb \ -p NAME_$1_VERSION_ARCH.deb \ - --python-setup-py-arguments --service=$1 \ - -m "$(CORE_MAINTAINERS)" \ - --vendor "$(CORE_VENDOR)" \ + --python-install-bin $(bindir) \ + --python-install-data $(prefix) \ + --python-install-lib $(pythondir) \ + $2 $3 \ + -m "$(PACKAGE_MAINTAINERS)" \ + --vendor "$(PACKAGE_VENDOR)" \ -d "procps" \ -d "libc6 >= 2.14" \ -d "bash >= 3.0" \ @@ -106,27 +122,51 @@ fpm: clean-local-fpm $(call fpm-gui,deb,-d "libtk-img") $(call fpm-python,rpm,ns3/setup.py) $(call fpm-python,deb,ns3/setup.py) - $(call fpm-daemon-rpm,systemd) - $(call fpm-daemon-rpm,sysv) - $(call fpm-daemon-deb,systemd) - $(call fpm-daemon-deb,sysv) + $(call fpm-daemon-rpm) + $(call fpm-daemon-deb,sysv,--deb-init,scripts/core-daemon) + $(call fpm-daemon-deb,systemd,--deb-systemd,scripts/core-daemon.service) .PHONY: clean-local-fpm clean-local-fpm: -rm -rf *.deb -rm -rf *.rpm -.PHONY: core-restart -core-restart: - /etc/init.d/core-daemon stop - daemon/sbin/core-cleanup - rm -f /var/log/core-daemon.log - /etc/init.d/core-daemon start - clean-local: clean-local-fpm .version: Makefile - echo $(CORE_VERSION) > $@ + echo $(PACKAGE_VERSION) > $@ .version.date: Makefile - echo $(CORE_VERSION_DATE) > $@ + echo $(PACKAGE_DATE) > $@ + +define change-files = +$(info creating file $1 from $1.in) +@$(SED) -e 's,[@]sbindir[@],$(sbindir),g' \ + -e 's,[@]bindir[@],$(bindir),g' \ + -e 's,[@]PYTHON[@],$(PYTHON),g' \ + -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ + -e 's,[@]PACKAGE_DATE[@],$(PACKAGE_DATE),g' \ + -e 's,[@]CORE_LIB_DIR[@],$(CORE_LIB_DIR),g' \ + -e 's,[@]CORE_STATE_DIR[@],$(CORE_STATE_DIR),g' \ + -e 's,[@]CORE_DATA_DIR[@],$(CORE_DATA_DIR),g' \ + -e 's,[@]CORE_CONF_DIR[@],$(CORE_CONF_DIR),g' \ + -e 's,[@]CORE_GUI_CONF_DIR[@],$(CORE_GUI_CONF_DIR),g' \ + -e 's,[@]brctl_path[@],$(brctl_path),g' \ + -e 's,[@]sysctl_path[@],$(sysctl_path),g' \ + -e 's,[@]ip_path[@],$(ip_path),g' \ + -e 's,[@]tc_path[@],$(tc_path),g' \ + -e 's,[@]ebtables_path[@],$(ebtables_path),g' \ + -e 's,[@]mount_path[@],$(mount_path),g' \ + -e 's,[@]umount_path[@],$(umount_path),g' \ + -e 's,[@]ovs_vs_path[@],$(ovs_vs_path),g' \ + -e 's,[@]ovs_of_path[@],$(ovs_of_path),g' \ + < $1.in > $1 +endef + +all: change-files + +.PHONY: change-files +change-files: + $(call change-files,gui/core-gui) + $(call change-files,scripts/core-daemon.service) + $(call change-files,daemon/core/constants.py) diff --git a/configure.ac b/configure.ac index 12d90cda..0ea864ea 100644 --- a/configure.ac +++ b/configure.ac @@ -9,82 +9,37 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -# # this defines the CORE version number, must be static for AC_INIT -# AC_INIT(core, 5.1, core-dev@nrl.navy.mil) -VERSION=$PACKAGE_VERSION -CORE_VERSION=$PACKAGE_VERSION -CORE_VERSION_DATE=m4_esyscmd_s([date +%Y%m%d]) -COREDPY_VERSION=$PACKAGE_VERSION -CORE_MAINTAINERS="CORE Developers " -CORE_VENDOR="CORE Developers" -# # autoconf and automake initialization -# AC_CONFIG_SRCDIR([netns/version.h.in]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_SUBST(CORE_VERSION) -AC_SUBST(CORE_VERSION_DATE) -AC_SUBST(COREDPY_VERSION) -AC_SUBST(CORE_MAINTAINERS) -AC_SUBST(CORE_VENDOR) +# define variables used for packaging and date display +PACKAGE_DATE=m4_esyscmd_s([date +%Y%m%d]) +PACKAGE_VENDOR="CORE Developers" +PACKAGE_MAINTAINERS="$PACKAGE_VENDOR <$PACKAGE_BUGREPORT>" +CORE_LIB_DIR="\${prefix}/lib/core" +# TODO: hard setting path, until support by setup.py +CORE_CONF_DIR="/etc/core" +CORE_DATA_DIR="\${datarootdir}/core" +# TODO: verify there is need to hard set /var +CORE_STATE_DIR="\${localstatedir}" -# -# some of the following directory variables are not expanded at configure-time, -# so we have special checks to expand them -# - -# CORE GUI files in LIBDIR -# AC_PREFIX_DEFAULT is /usr/local, but not expanded yet -if test "x$prefix" = "xNONE" ; then - prefix="/usr/local" -fi -if test "x$exec_prefix" = "xNONE" ; then - exec_prefix="$prefix" -fi -if test "$libdir" = "\${exec_prefix}/lib" ; then - libdir="${exec_prefix}/lib" -fi -if test "$sbindir" = "\${exec_prefix}/sbin" ; then - sbindir="${exec_prefix}/sbin" -fi -if test "$bindir" = "\${exec_prefix}/bin" ; then - bindir="${exec_prefix}/bin" -fi -# this can be /usr/lib or /usr/lib64 -LIB_DIR="${libdir}" -# don't let the Tcl files install to /usr/lib64/core -CORE_LIB_DIR="${prefix}/lib/core" -AC_SUBST(LIB_DIR) +AC_SUBST(PACKAGE_DATE) +AC_SUBST(PACKAGE_MAINTAINERS) +AC_SUBST(PACKAGE_VENDOR) AC_SUBST(CORE_LIB_DIR) -SBINDIR="${sbindir}" -AC_SUBST(SBINDIR) -BINDIR="${bindir}" -AC_SUBST(BINDIR) - -# CORE daemon configuration file (core.conf) in CORE_CONF_DIR -if test "$sysconfdir" = "\${prefix}/etc" ; then - sysconfdir="/etc" - CORE_CONF_DIR="/etc/core" -else - CORE_CONF_DIR="$sysconfdir/core" -fi AC_SUBST(CORE_CONF_DIR) -if test "$datarootdir" = "\${prefix}/share" ; then - datarootdir="${prefix}/share" -fi -CORE_DATA_DIR="$datarootdir/core" AC_SUBST(CORE_DATA_DIR) +AC_SUBST(CORE_STATE_DIR) # CORE GUI configuration files and preferences in CORE_GUI_CONF_DIR # scenario files in ~/.core/configs/ -#AC_ARG_VAR(CORE_GUI_CONF_DIR, [GUI configuration directory.]) AC_ARG_WITH([guiconfdir], [AS_HELP_STRING([--with-guiconfdir=dir], [specify GUI configuration directory])], @@ -102,91 +57,27 @@ AC_ARG_ENABLE([daemon], (default is yes)])], [], [enable_daemon=yes]) AC_SUBST(enable_daemon) -if test "x$enable_daemon" = "xno"; then - want_python=no - want_linux_netns=no -fi -# CORE state files -if test "$localstatedir" = "\${prefix}/var" ; then - # use /var instead of /usr/local/var (/usr/local/var/log isn't standard) - CORE_STATE_DIR="/var" -else - CORE_STATE_DIR="$localstatedir" -fi -AC_SUBST(CORE_STATE_DIR) +SEARCHPATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin" # default compiler flags # _GNU_SOURCE is defined to get c99 defines for lrint() CFLAGS="$CFLAGS -O3 -Werror -Wall -D_GNU_SOURCE" -# debug flags -#CFLAGS="$CFLAGS -g -Werror -Wall -D_GNU_SOURCE" -# Checks for programs. +# checks for programs AC_PROG_AWK AC_PROG_CC AC_PROG_INSTALL AC_PROG_MAKE_SET AC_PROG_RANLIB +AC_PROG_SED -AM_PATH_PYTHON(2.6, want_python=yes, want_python=no) -SEARCHPATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/sbin:/usr/local/bin" -# -# daemon dependencies -# -if test "x$enable_daemon" = "xyes" ; then - AC_CHECK_PROG(brctl_path, brctl, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(sysctl_path, sysctl, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ebtables_path, ebtables, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ip_path, ip, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(tc_path, tc, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ifconfig_path, ifconfig, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ngctl_path, ngctl, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(vimage_path, vimage, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(mount_path, mount, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(umount_path, umount, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(convert, convert, yes, no, $SEARCHPATH) - AC_CHECK_PROG(ovs_vs_path, ovs-vsctl, $as_dir, no, $SEARCHPATH) - AC_CHECK_PROG(ovs_of_path, ovs-ofctl, $as_dir, no, $SEARCHPATH) -fi +want_python=no +want_linux_netns=no +if test "x$enable_daemon" = "xyes"; then + want_python=yes + want_linux_netns=yes -#AC_CHECK_PROG(dia, dia, yes, no) -AC_CHECK_PROG(help2man, help2man, yes, no, $SEARCHPATH) -if test "x$convert" = "xno" ; then - AC_MSG_WARN([Could not locate ImageMagick convert.]) - #want_docs_missing="convert" -fi -#if test "x$dia" = "xno" ; then -# AC_MSG_WARN([Could not locate dia.]) -# want_docs_missing="dia" -#fi -if test "x$help2man" = "xno" ; then - AC_MSG_WARN([Could not locate help2man.]) - want_docs_missing="$want_docs_missing help2man" -fi -if test "x$want_docs_missing" = "x" ; then - want_docs=yes -else - AC_MSG_WARN([Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built.]) - want_docs=no -fi - -# check for sphinx required during make -AC_CHECK_PROG(sphinxapi_path, sphinx-apidoc, $as_dir, no, $SEARCHPATH) -if test "x$sphinxapi_path" = "xno" ; then - AC_MSG_ERROR(["Could not location sphinx-apidoc, from the python-sphinx package"]) -fi - -#AC_PATH_PROGS(tcl_path, [tclsh tclsh8.5 tclsh8.4], no) -#if test "x$tcl_path" = "xno" ; then -# AC_MSG_ERROR([Could not locate tclsh. Please install Tcl/Tk.]) -#fi -#AC_PATH_PROGS(wish_path, [wish wish8.5 wish8.4], no) -#if test "x$wish_path" = "xno" ; then -# AC_MSG_ERROR([Could not locate wish. Please install Tcl/Tk.]) -#fi - -if test "x$enable_daemon" = "xyes" ; then # Checks for libraries. AC_CHECK_LIB([netgraph], [NgMkSockNode]) @@ -207,73 +98,94 @@ if test "x$enable_daemon" = "xyes" ; then AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([atexit dup2 gettimeofday memset socket strerror uname]) + + AM_PATH_PYTHON(2.6) + + AC_CHECK_PROG(brctl_path, brctl, $as_dir, no, $SEARCHPATH) + if test "x$brctl_path" = "xno" ; then + AC_MSG_ERROR([Could not locate brctl (from bridge-utils package).]) + fi + AC_CHECK_PROG(sysctl_path, sysctl, $as_dir, no, $SEARCHPATH) + AC_CHECK_PROG(ebtables_path, ebtables, $as_dir, no, $SEARCHPATH) + if test "x$ebtables_path" = "xno" ; then + AC_MSG_ERROR([Could not locate ebtables (from ebtables package).]) + fi + AC_CHECK_PROG(ip_path, ip, $as_dir, no, $SEARCHPATH) + if test "x$ip_path" = "xno" ; then + AC_MSG_ERROR([Could not locate ip (from iproute package).]) + fi + AC_CHECK_PROG(tc_path, tc, $as_dir, no, $SEARCHPATH) + if test "x$tc_path" = "xno" ; then + AC_MSG_ERROR([Could not locate tc (from iproute package).]) + fi + AC_CHECK_PROG(mount_path, mount, $as_dir, no, $SEARCHPATH) + AC_CHECK_PROG(umount_path, umount, $as_dir, no, $SEARCHPATH) + AC_CHECK_PROG(convert, convert, yes, no, $SEARCHPATH) + if test "x$convert" = "xno" ; then + AC_MSG_WARN([Could not locate ImageMagick convert.]) + fi + AC_CHECK_PROG(ovs_vs_path, ovs-vsctl, $as_dir, no, $SEARCHPATH) + if test "x$ovs_vs_path" = "xno" ; then + AC_MSG_WARN([Could not locate ovs-vsctl cannot use OVS nodes]) + fi + AC_CHECK_PROG(ovs_of_path, ovs-ofctl, $as_dir, no, $SEARCHPATH) + if test "x$ovs_of_path" = "xno" ; then + AC_MSG_WARN([Could not locate ovs-ofctl cannot use OVS nodes]) + fi + + CFLAGS_save=$CFLAGS + CPPFLAGS_save=$CPPFLAGS + if test "x$PYTHON_INCLUDE_DIR" = "x"; then + PYTHON_INCLUDE_DIR=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc()"` + fi + CFLAGS="-I$PYTHON_INCLUDE_DIR" + CPPFLAGS="-I$PYTHON_INCLUDE_DIR" + AC_CHECK_HEADERS([Python.h], [], + AC_MSG_ERROR([Python bindings require Python development headers (try installing your 'python-devel' or 'python-dev' package)])) + CFLAGS=$CFLAGS_save + CPPFLAGS=$CPPFLAGS_save + PKG_CHECK_MODULES(libev, libev, + AC_MSG_RESULT([found libev using pkgconfig OK]) + AC_SUBST(libev_CFLAGS) + AC_SUBST(libev_LIBS), + AC_MSG_RESULT([did not find libev using pkconfig...]) + AC_CHECK_LIB([ev], ev_set_allocator, + AC_MSG_RESULT([found libev OK]) + AC_SUBST(libev_CFLAGS) + AC_SUBST(libev_LIBS, [-lev]), + AC_MSG_ERROR([Python bindings require libev (try installing your 'libev-devel' or 'libev-dev' package)]))) fi -# Host-specific detection -want_linux_netns=yes +AC_CHECK_PROG(help2man, help2man, yes, no, $SEARCHPATH) -if test "x$want_python" = "xno"; then - want_linux_netns=no +if test "x$help2man" = "xno" ; then + AC_MSG_WARN([Could not locate help2man.]) + want_docs_missing="$want_docs_missing help2man" fi -if test "x$want_python" = "xyes"; then - if test "x$want_linux_netns" = "xyes"; then - CFLAGS_save=$CFLAGS - CPPFLAGS_save=$CPPFLAGS - if test "x$PYTHON_INCLUDE_DIR" = "x"; then - PYTHON_INCLUDE_DIR=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc()"` - fi - CFLAGS="-I$PYTHON_INCLUDE_DIR" - CPPFLAGS="-I$PYTHON_INCLUDE_DIR" - AC_CHECK_HEADERS([Python.h], [], - AC_MSG_ERROR([Python bindings require Python development headers (try installing your 'python-devel' or 'python-dev' package)])) - CFLAGS=$CFLAGS_save - CPPFLAGS=$CPPFLAGS_save - PKG_CHECK_MODULES(libev, libev, - AC_MSG_RESULT([found libev using pkgconfig OK]) - AC_SUBST(libev_CFLAGS) - AC_SUBST(libev_LIBS), - AC_MSG_RESULT([did not find libev using pkconfig...]) - AC_CHECK_LIB([ev], ev_set_allocator, - AC_MSG_RESULT([found libev OK]) - AC_SUBST(libev_CFLAGS) - AC_SUBST(libev_LIBS, [-lev]), - AC_MSG_ERROR([Python bindings require libev (try installing your 'libev-devel' or 'libev-dev' package)]))) - fi - AC_SUBST(pyprefix, `eval ${PYTHON} ./python-prefix.py ${PYTHON_PREFIX} ${PYTHON_VERSION}`) - if test "${pyprefix}" != "${PYTHON_PREFIX}"; then - pythondir=`echo ${pythondir} | sed -e 's,[$][{]prefix[}],${pyprefix},g'` - pyexecdir=`echo ${pyexecdir} | sed -e 's,[$][{]exec_prefix[}],${pyprefix},g'` - fi +if test "x$want_docs_missing" = "x" ; then + want_docs=yes else - # Namespace support requires Python support - want_linux_netns=no + AC_MSG_WARN([Could not find required helper utilities (${want_docs_missing}) so the CORE documentation will not be built.]) + want_docs=no fi -progs_missing="" -if test "x$want_linux_netns" = "xyes"; then - if test "x$brctl_path" = "xno" ; then - progs_missing="${progs_missing}brctl " - brctl_path="/usr/sbin" - AC_MSG_ERROR([Could not locate brctl (from bridge-utils package).]) - fi - if test "x$ebtables_path" = "xno" ; then - progs_missing="${progs_missing}ebtables " - ebtables_path="/sbin" - AC_MSG_ERROR([Could not locate ebtables (from ebtables package).]) - fi - if test "x$ip_path" = "xno" ; then - progs_missing="${progs_missing}ip " - ip_path="/sbin" - AC_MSG_ERROR([Could not locate ip (from iproute package).]) - fi - if test "x$tc_path" = "xno" ; then - progs_missing="${progs_missing}tc " - tc_path="/sbin" - AC_MSG_ERROR([Could not locate tc (from iproute package).]) - fi +# check for sphinx required during make +AC_CHECK_PROG(sphinxapi_path, sphinx-apidoc, $as_dir, no, $SEARCHPATH) +if test "x$sphinxapi_path" = "xno" ; then + AC_MSG_ERROR(["Could not location sphinx-apidoc, from the python-sphinx package"]) fi +#AC_PATH_PROGS(tcl_path, [tclsh tclsh8.5 tclsh8.4], no) +#if test "x$tcl_path" = "xno" ; then +# AC_MSG_ERROR([Could not locate tclsh. Please install Tcl/Tk.]) +#fi + +#AC_PATH_PROGS(wish_path, [wish wish8.5 wish8.4], no) +#if test "x$wish_path" = "xno" ; then +# AC_MSG_ERROR([Could not locate wish. Please install Tcl/Tk.]) +#fi + AC_ARG_WITH([startup], [AS_HELP_STRING([--with-startup=option], [option=systemd,suse,none to install systemd/SUSE init scripts])], @@ -288,7 +200,6 @@ AM_CONDITIONAL(WANT_DAEMON, test x$enable_daemon = xyes) AM_CONDITIONAL(WANT_DOCS, test x$want_docs = xyes) AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes) AM_CONDITIONAL(WANT_NETNS, test x$want_linux_netns = xyes) - AM_CONDITIONAL(WANT_INITD, test x$with_startup = xinitd) AM_CONDITIONAL(WANT_SYSTEMD, test x$with_startup = xsystemd) AM_CONDITIONAL(WANT_SUSE, test x$with_startup = xsuse) @@ -299,28 +210,26 @@ else HELP2MAN=: fi - # Output files +#gui/core-gui +#scripts/core-daemon.service +#daemon/core/constants.py AC_CONFIG_FILES([Makefile - gui/core-gui gui/version.tcl gui/Makefile gui/icons/Makefile scripts/Makefile - scripts/core-daemon.service scripts/perf/Makefile doc/Makefile doc/conf.py doc/man/Makefile doc/figures/Makefile daemon/Makefile - daemon/core/constants.py daemon/doc/Makefile daemon/doc/conf.py netns/Makefile netns/version.h - ns3/Makefile - ns3/corens3/constants.py],) + ns3/Makefile],) AC_OUTPUT # Summary text @@ -331,12 +240,12 @@ ${PACKAGE_STRING} Configuration: Host System Type: ${host} C Compiler and flags: ${CC} ${CFLAGS} Install prefix: ${prefix} + Exec prefix: ${exec_prefix} Build GUI: ${enable_gui} GUI path: ${CORE_LIB_DIR} GUI config: ${CORE_GUI_CONF_DIR} - Daemon path: ${SBINDIR} + Daemon path: ${sbindir} Daemon config: ${CORE_CONF_DIR} - Python install prefix: ${pyprefix} Python modules: ${pythondir} Logs: ${CORE_STATE_DIR}/log @@ -352,8 +261,3 @@ if test "x${want_linux_netns}" = "xyes" ; then ------------------------------------------------------------------------" fi -if test "x${progs_missing}" != "x" ; then - echo ">>> NOTE: the following programs could not be found:" - echo " $progs_missing -------------------------------------------------------------------------" -fi diff --git a/daemon/MANIFEST.in b/daemon/MANIFEST.in deleted file mode 100644 index f5aa698b..00000000 --- a/daemon/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -recursive-include sbin *.sh *.py -include data/core.conf -recursive-include examples/netns *.py *.sh -recursive-exclude examples/netns *.pyc *.pyo diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 20ba8b36..24c07196 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -7,73 +7,17 @@ # Makefile for building netns components. # -SETUPPY = setup.py -SETUPPYFLAGS = -v +SETUPPY = setup.py +SETUPPYFLAGS = -v if WANT_DOCS SUBDIRS = doc endif -SBIN_FILES = \ - sbin/core-cleanup \ - sbin/core-daemon \ - sbin/core-manage \ - sbin/coresendmsg +SCRIPT_FILES := $(notdir $(wildcard sbin/*)) +MAN_FILES := $(notdir $(wildcard ../doc/man/*.1)) -dist_sbin_SCRIPTS = $(SBIN_FILES) - -CONF_FILES = \ - data/core.conf - -coreconfdir = $(CORE_CONF_DIR) -dist_coreconf_DATA = $(CONF_FILES) - -EXAMPLE_FILES = \ - examples/controlnet_updown \ - examples/emanemanifest2core.py \ - examples/emanemodel2core.py \ - examples/findcore.py \ - examples/stopsession.py - -coreexdir = $(datadir)/core/examples -dist_coreex_SCRIPTS = $(EXAMPLE_FILES) - -EXAMPLE_MYSERVICES_FILES = \ - examples/myservices/README.txt \ - examples/myservices/__init__.py \ - examples/myservices/sample.py - -coreexmyservicesdir = $(coreexdir)/myservices -dist_coreexmyservices_DATA = $(EXAMPLE_MYSERVICES_FILES) - -EXAMPLE_NETNS_FILES = \ - examples/netns/basicrange.py \ - examples/netns/daemonnodes.py \ - examples/netns/distributed.py \ - examples/netns/emane80211.py \ - examples/netns/howmanynodes.py \ - examples/netns/iperf-performance-chain.py \ - examples/netns/iperf-performance.sh \ - examples/netns/ospfmanetmdrtest.py \ - examples/netns/switch.py \ - examples/netns/switchtest.py \ - examples/netns/twonodes.sh \ - examples/netns/wlanemanetests.py \ - examples/netns/wlantest.py - -coreexnetnsdir = $(coreexdir)/netns -dist_coreexnetns_SCRIPTS= $(EXAMPLE_NETNS_FILES) - -EXAMPLE_SERVICES_FILES = \ - examples/services/sampleFirewall \ - examples/services/sampleIPsec \ - examples/services/sampleVPNClient \ - examples/services/sampleVPNServer - -coreexservicesdir = $(coreexdir)/services -dist_coreexservices_DATA= $(EXAMPLE_SERVICES_FILES) - -LOGROTATE_DIR = $(sysconfdir)/logrotate.d +LOGROTATE_DIR = $(DESTDIR)/$(sysconfdir)/logrotate.d LOGROTATE_FILE = data/core-daemon.logrotate # Python package build @@ -83,47 +27,40 @@ build: # Python package install install-exec-hook: - $(MKDIR_P) ${DESTDIR}/${pythondir} - $(MKDIR_P) ${DESTDIR}/${pyexecdir} - PYTHONPATH=${DESTDIR}/${pythondir} $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ - --prefix=${DESTDIR}/${pyprefix} \ - --install-purelib=${DESTDIR}/${pythondir} \ - --install-platlib=${DESTDIR}/${pyexecdir} + $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ + --root=/$(DESTDIR) \ + --prefix=$(prefix) \ + --install-lib=$(pythondir) \ + --single-version-externally-managed -install-data-local: - $(MKDIR_P) $(DESTDIR)$(LOGROTATE_DIR) - $(INSTALL_DATA) $(LOGROTATE_FILE) \ - $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` +#install-data-local: +# $(MKDIR_P) $(DESTDIR)$(LOGROTATE_DIR) +# $(INSTALL_DATA) $(LOGROTATE_FILE) \ +# $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` -uninstall-local: - rm -f $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` +#uninstall-local: +# rm -f $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` # Python package uninstall +#rmdir -p $(LOGROTATE_DIR) || true uninstall-hook: - rm -rf ${pythondir}/core_python-${COREDPY_VERSION}-py${PYTHON_VERSION}.egg-info - rm -f ${pythondir}/core_python_netns-1.0-py${PYTHON_VERSION}.egg-info - rm -rf ${pythondir}/core - rmdir -p $(coreexservicesdir) || true - rmdir -p $(coreexnetnsdir) || true - rmdir -p $(coreexmyservicesdir) || true - rmdir -p $(coreexdir) || true - rmdir -p $(coreconfdir) || true - rmdir -p $(LOGROTATE_DIR) || true + rm -rf $(DESTDIR)/etc/core + rm -rf $(DESTDIR)/$(datadir)/core + rm -f $(addprefix $(DESTDIR)/$(datadir)/man/man1/, $(MAN_FILES)) + rm -f $(addprefix $(DESTDIR)/$(bindir)/,$(SCRIPT_FILES)) + rm -rf $(DESTDIR)/$(pythondir)/core-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + rm -rf $(DESTDIR)/$(pythondir)/core # Python package cleanup clean-local: -rm -rf build -# Python RPM package -rpm: - $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) bdist_rpm - # because we include entire directories with EXTRA_DIST, we need to clean up # the source control files dist-hook: - rm -rf `find $(distdir)/ -name .svn` `find $(distdir)/ -name '*.pyc'` + rm -rf `find $(distdir)/ -name '*.pyc'` DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST # files to include with distribution tarball -EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) +EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index 1e5db2b6..7dea1ad8 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -1,22 +1,18 @@ -# Constants created by autoconf ./configure script -COREDPY_VERSION = "@COREDPY_VERSION@" -CORE_STATE_DIR = "@CORE_STATE_DIR@" -CORE_CONF_DIR = "@CORE_CONF_DIR@" -CORE_DATA_DIR = "@CORE_DATA_DIR@" -CORE_LIB_DIR = "@CORE_LIB_DIR@" -CORE_SBIN_DIR = "@SBINDIR@" -CORE_BIN_DIR = "@BINDIR@" +COREDPY_VERSION = "@PACKAGE_VERSION@" +CORE_STATE_DIR = "@CORE_STATE_DIR@" +CORE_CONF_DIR = "@CORE_CONF_DIR@" +CORE_DATA_DIR = "@CORE_DATA_DIR@" +CORE_LIB_DIR = "@CORE_LIB_DIR@" -BRCTL_BIN = "@brctl_path@/brctl" -SYSCTL_BIN = "@sysctl_path@/sysctl" -IP_BIN = "@ip_path@/ip" -TC_BIN = "@tc_path@/tc" -EBTABLES_BIN = "@ebtables_path@/ebtables" -IFCONFIG_BIN = "@ifconfig_path@/ifconfig" -NGCTL_BIN = "@ngctl_path@/ngctl" -VIMAGE_BIN = "@vimage_path@/vimage" -QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" -MOUNT_BIN = "@mount_path@/mount" -UMOUNT_BIN = "@umount_path@/umount" -OVS_BIN = "@ovs_vs_path@/ovs-vsctl" -OVS_FLOW_BIN = "@ovs_of_path@/ovs-ofctl" +VNODED_BIN = "@bindir@/vnoded" +VCMD_BIN = "@bindir@/vcmd" +BRCTL_BIN = "@brctl_path@/brctl" +SYSCTL_BIN = "@sysctl_path@/sysctl" +IP_BIN = "@ip_path@/ip" +TC_BIN = "@tc_path@/tc" +EBTABLES_BIN = "@ebtables_path@/ebtables" +QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" +MOUNT_BIN = "@mount_path@/mount" +UMOUNT_BIN = "@umount_path@/umount" +OVS_BIN = "@ovs_vs_path@/ovs-vsctl" +OVS_FLOW_BIN = "@ovs_of_path@/ovs-ofctl" diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 987fdac5..e11c75d3 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -86,7 +86,7 @@ class SimpleLxcNode(PyCoreNode): # create a new namespace for this node using vnoded vnoded = [ - "%s/vnoded" % constants.CORE_BIN_DIR, + constants.VNODED_BIN, "-v", "-c", self.ctrlchnlname, "-l", self.ctrlchnlname + ".log", diff --git a/daemon/core/netns/vnodeclient.py b/daemon/core/netns/vnodeclient.py index 5d5ebea0..5d05d955 100644 --- a/daemon/core/netns/vnodeclient.py +++ b/daemon/core/netns/vnodeclient.py @@ -14,8 +14,6 @@ from core import constants from core import logger from core.misc import utils -VCMD = os.path.join(constants.CORE_BIN_DIR, "vcmd") - class VnodeClient(object): """ @@ -134,7 +132,7 @@ class VnodeClient(object): :rtype: int """ args = utils.split_args(args) - return os.spawnlp(os.P_WAIT, VCMD, VCMD, "-c", self.ctrlchnlname, "--", *args) + return os.spawnlp(os.P_WAIT, constants.VCMD_BIN, constants.VCMD_BIN, "-c", self.ctrlchnlname, "--", *args) def redircmd(self, infd, outfd, errfd, args, wait=True): """ @@ -171,7 +169,7 @@ class VnodeClient(object): :return: terminal command result :rtype: int """ - args = ("xterm", "-ut", "-title", self.name, "-e", VCMD, "-c", self.ctrlchnlname, "--", sh) + args = ("xterm", "-ut", "-title", self.name, "-e", constants.VCMD_BIN, "-c", self.ctrlchnlname, "--", sh) if "SUDO_USER" in os.environ: args = ("su", "-s", "/bin/sh", "-c", "exec " + " ".join(map(lambda x: "'%s'" % x, args)), @@ -185,7 +183,7 @@ class VnodeClient(object): :param str sh: shell to execute command in :return: str """ - return "%s -c %s -- %s" % (VCMD, self.ctrlchnlname, sh) + return "%s -c %s -- %s" % (constants.VCMD_BIN, self.ctrlchnlname, sh) def shcmd(self, cmd, sh="/bin/sh"): """ diff --git a/daemon/doc/conf.py.in b/daemon/doc/conf.py.in index 7b44569f..c9041fae 100644 --- a/daemon/doc/conf.py.in +++ b/daemon/doc/conf.py.in @@ -49,9 +49,9 @@ copyright = u'2017, core-dev' # built documents. # # The short X.Y version. -version = '@CORE_VERSION@' +version = '@PACKAGE_VERSION@' # The full version, including alpha/beta/rc tags. -release = '@CORE_VERSION@' +release = '@PACKAGE_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/daemon/setup.py b/daemon/setup.py index 35769399..2783af42 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -4,13 +4,13 @@ Defines how CORE will be built for installation. import glob import os -from distutils.command.install import install -from setuptools import setup, find_packages +from setuptools import find_packages +from distutils.core import setup _CORE_DIR = "/etc/core" -_MAN_DIR = "/usr/local/share/man/man1" -_SHARE_DIR = "/usr/local/share/core" +_MAN_DIR = "share/man/man1" +_EXAMPLES_DIR = "share/core" _SYSV = "/etc/init.d" _SYSTEMD = "/etc/systemd/system" @@ -30,31 +30,6 @@ def glob_files(glob_path): return glob.glob(glob_path) -class CustomInstall(install): - user_options = install.user_options + [ - ("service=", None, "determine which service file to include") - ] - - def initialize_options(self): - install.initialize_options(self) - self.service = "sysv" - - def finalize_options(self): - install.finalize_options(self) - assert self.service in ("sysv", "systemd"), "must be sysv or systemd" - - def run(self): - if self.service == "sysv": - self.distribution.data_files.append(( - _SYSV, ["../scripts/core-daemon"] - )) - else: - self.distribution.data_files.append(( - _SYSTEMD, ["../scripts/core-daemon.service"] - )) - install.run(self) - - data_files = [ (_CORE_DIR, [ "data/core.conf", @@ -62,7 +37,7 @@ data_files = [ ]), (_MAN_DIR, glob_files("../doc/man/**.1")), ] -data_files.extend(recursive_files(_SHARE_DIR, "examples")) +data_files.extend(recursive_files(_EXAMPLES_DIR, "examples")) setup( name="core", @@ -90,7 +65,4 @@ setup( author_email="core-dev@nrl.navy.mil", license="BSD", long_description="Python scripts and modules for building virtual emulated networks.", - cmdclass={ - "install": CustomInstall - } ) diff --git a/doc/conf.py.in b/doc/conf.py.in index 34655128..210c372f 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -49,9 +49,9 @@ copyright = u'2017, core-dev' # built documents. # # The short X.Y version. -version = '@CORE_VERSION@' +version = '@PACKAGE_VERSION@' # The full version, including alpha/beta/rc tags. -release = '@CORE_VERSION@' +release = '@PACKAGE_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index f76eee84..8479faaa 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -22,10 +22,10 @@ generate-mans: $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vnoded -o vnoded.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vcmd -o vcmd.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/netns -o netns.1.new - $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new - $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new - $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new - $(HELP2MAN) --version-string=$(CORE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-manage -o core-manage.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-manage -o core-manage.1.new .PHONY: diff diff: diff --git a/gui/Makefile.am b/gui/Makefile.am index 65cf085b..3a1a09d0 100644 --- a/gui/Makefile.am +++ b/gui/Makefile.am @@ -10,63 +10,28 @@ SUBDIRS = icons -TCL_FILES = annotations.tcl api.tcl canvas.tcl cfgparse.tcl \ - core.tcl debug.tcl editor.tcl exec.tcl \ - filemgmt.tcl gpgui.tcl \ - graph_partitioning.tcl help.tcl \ - initgui.tcl ipv4.tcl ipv6.tcl \ - linkcfg.tcl mobility.tcl nodecfg.tcl \ - nodes.tcl services.tcl ns2imunes.tcl plugins.tcl \ - tooltips.tcl topogen.tcl traffic.tcl util.tcl \ - version.tcl widget.tcl wlan.tcl wlanscript.tcl \ - exceptions.tcl +TCL_FILES := $(wildcard *.tcl) +ADDONS_FILES := $(wildcard addons/*) +CONFIG_FILES := $(wildcard configs/*) -ADDONS_FILES = addons/ipsecservice.tcl - -CONFIG_FILES = configs/sample1.imn configs/sample1.scen \ - configs/sample1-bg.gif configs/sample2-ssh.imn \ - configs/sample3-bgp.imn configs/sample4-nrlsmf.imn \ - configs/sample4.scen configs/sample4-bg.jpg \ - configs/sample5-mgen.imn configs/sample6-emane-rfpipe.imn \ - configs/sample7-emane-ieee80211abg.imn \ - configs/sample8-ipsec-service.imn \ - configs/sample9-vpn.imn \ - configs/sample10-kitchen-sink.imn - -# # CORE GUI script (/usr/local/bin/core-gui) -# dist_bin_SCRIPTS = core-gui -# # Tcl/Tk scripts (/usr/local/lib/core) -# -coredir = $(CORE_LIB_DIR) -dist_core_DATA = $(TCL_FILES) -dist_core_SCRIPTS = $(OTHER_FILES) +coredir = $(CORE_LIB_DIR) +dist_core_DATA = $(TCL_FILES) +dist_core_SCRIPTS = $(OTHER_FILES) -# # Addon files -# -coreaddonsdir = $(coredir)/addons +coreaddonsdir = $(coredir)/addons dist_coreaddons_DATA = $(ADDONS_FILES) -# # Sample configs (/usr/local/share/core/examples/configs) -# -coreconfigsdir = $(datadir)/core/examples/configs -dist_coreconfigs_DATA = $(CONFIG_FILES) - -dist-hook: - rm -rf $(distdir)/addons/.svn - -uninstall-hook: - rmdir -p $(coreconfigsdir) || true - rmdir -p $(coreaddonsdir) || true - rmdir -p $(coredir) || true +coreconfigsdir = $(datadir)/core/examples/configs +dist_coreconfigs_DATA = $(CONFIG_FILES) # extra cruft to remove -DISTCLEANFILES = Makefile.in +DISTCLEANFILES = Makefile.in # files to include in source tarball not included elsewhere -EXTRA_DIST = addons +EXTRA_DIST = addons diff --git a/gui/core-gui.in b/gui/core-gui.in index a66d7f77..a93fd72b 100755 --- a/gui/core-gui.in +++ b/gui/core-gui.in @@ -54,7 +54,7 @@ case $1 in exit 0 ;; -v | --version) - exec echo "`basename $0` version @CORE_VERSION@ (@CORE_VERSION_DATE@)" + exec echo "`basename $0` version @PACKAGE_VERSION@ (@PACKAGE_DATE@)" exit 0 ;; esac @@ -63,7 +63,7 @@ SHELL=/bin/sh export SHELL export LIBDIR="@CORE_LIB_DIR@" -export SBINDIR="@SBINDIR@" +export SBINDIR="@sbindir@" # eval is used here to expand "~" to user's home dir if [ x$CONFDIR = x ]; then export CONFDIR=`eval "echo @CORE_GUI_CONF_DIR@"` ; fi export CORE_STATE_DIR="@CORE_STATE_DIR@" diff --git a/gui/icons/Makefile.am b/gui/icons/Makefile.am index dc2b2e93..6575fad0 100644 --- a/gui/icons/Makefile.am +++ b/gui/icons/Makefile.am @@ -5,94 +5,25 @@ # author: Jeff Ahrenholz # -TINY_ICONS = tiny/button.play.gif \ - tiny/select.gif tiny/marker.gif \ - tiny/rj45.gif tiny/text.gif \ - tiny/edit-delete.gif tiny/stop.gif \ - tiny/blank.gif tiny/mobility.gif \ - tiny/script_play.gif tiny/arrow.gif \ - tiny/lanswitch.gif tiny/script_pause.gif \ - tiny/pc.gif tiny/rectangle.gif \ - tiny/observe.gif tiny/document-new.gif \ - tiny/document-save.gif \ - tiny/view-refresh.gif tiny/moboff.gif \ - tiny/document-properties.gif tiny/arrow.up.gif \ - tiny/host.gif tiny/hub.gif \ - tiny/twonode.gif tiny/router.gif \ - tiny/eraser.gif \ - tiny/stock_connect.gif tiny/stock_disconnect.gif \ - tiny/ping.gif tiny/link.gif \ - tiny/start.gif \ - tiny/trace.gif tiny/button.stop.gif \ - tiny/arrow.down.gif tiny/oval.gif \ - tiny/wlan.gif tiny/delete.gif \ - tiny/run.gif tiny/tunnel.gif \ - tiny/script_stop.gif \ - tiny/router_black.gif tiny/router_green.gif \ - tiny/router_red.gif tiny/router_yellow.gif \ - tiny/router_purple.gif \ - tiny/ap.gif tiny/mdr.gif \ - tiny/folder.gif \ - tiny/cel.gif \ - tiny/fileopen.gif \ - tiny/plot.gif +TINY_ICONS := $(wildcard tiny/*) +NORM_ICONS := $(wildcard normal/*) +SVG_ICONS := $(wildcard svg/*) -NORM_ICONS = normal/gps-diagram.xbm \ - normal/router_black.gif normal/host.gif \ - normal/hub.gif \ - normal/router.gif \ - normal/rj45.gif normal/antenna.gif \ - normal/text.gif \ - normal/lanswitch.gif normal/core-icon.png \ - normal/core-icon.xbm normal/oval.gif \ - normal/wlan.gif normal/pc.gif \ - normal/tunnel.gif normal/core-logo-275x75.gif \ - normal/router_red.gif normal/router_green.gif \ - normal/simple.xbm \ - normal/document-properties.gif \ - normal/thumb-unknown.gif \ - normal/router_purple.gif normal/router_yellow.gif \ - normal/ap.gif normal/mdr.gif - -SVG_ICONS = svg/ap.svg \ - svg/cel.svg \ - svg/hub.svg \ - svg/lanswitch.svg \ - svg/mdr.svg \ - svg/otr.svg \ - svg/rj45.svg \ - svg/router_black.svg \ - svg/router_green.svg \ - svg/router_purple.svg \ - svg/router_red.svg \ - svg/router.svg \ - svg/router_yellow.svg \ - svg/start.svg \ - svg/tunnel.svg \ - svg/vlan.svg - -# # Icon files (/usr/local/share/core/icons/[tiny,normal,svg]) -# -coreiconnormaldir = $(CORE_DATA_DIR)/icons/normal +coreiconnormaldir = $(CORE_DATA_DIR)/icons/normal dist_coreiconnormal_DATA = $(NORM_ICONS) -coreicontinydir = $(CORE_DATA_DIR)/icons/tiny -dist_coreicontiny_DATA = $(TINY_ICONS) -coreiconsvgdir = $(CORE_DATA_DIR)/icons/svg -dist_coreiconsvg_DATA = $(SVG_ICONS) -iconpixmapdir = $(datarootdir)/pixmaps -dist_iconpixmap_DATA = core-gui.xpm +coreicontinydir = $(CORE_DATA_DIR)/icons/tiny +dist_coreicontiny_DATA = $(TINY_ICONS) -icondesktopdir = $(datarootdir)/applications -dist_icondesktop_DATA = core-gui.desktop +coreiconsvgdir = $(CORE_DATA_DIR)/icons/svg +dist_coreiconsvg_DATA = $(SVG_ICONS) -uninstall-hook: - rmdir -p $(icondesktopdir) || true - rmdir -p $(iconpixmapdir) || true - rmdir -p $(coreiconsvgdir) || true - rmdir -p $(coreicontinydir) || true - rmdir -p $(coreiconnormaldir) || true +iconpixmapdir = $(datarootdir)/pixmaps +dist_iconpixmap_DATA = core-gui.xpm + +icondesktopdir = $(datarootdir)/applications +dist_icondesktop_DATA = core-gui.desktop # extra cruft to remove DISTCLEANFILES = Makefile.in diff --git a/gui/icons/normal/OVS.gif b/gui/icons/normal/OVS.gif old mode 100755 new mode 100644 diff --git a/gui/icons/svg/OVS.svg b/gui/icons/svg/OVS.svg old mode 100755 new mode 100644 diff --git a/gui/icons/tiny/OVS.gif b/gui/icons/tiny/OVS.gif old mode 100755 new mode 100644 diff --git a/gui/version.tcl.in b/gui/version.tcl.in index bc4e42e1..242a0e82 100644 --- a/gui/version.tcl.in +++ b/gui/version.tcl.in @@ -6,5 +6,5 @@ # # define the version number and release date here # -set CORE_VERSION @CORE_VERSION@ -set CORE_VERSION_DATE @CORE_VERSION_DATE@ +set CORE_VERSION @PACKAGE_VERSION@ +set CORE_VERSION_DATE @PACKAGE_DATE@ diff --git a/netns/MANIFEST.in b/netns/MANIFEST.in index c26545b7..e8fb6539 100644 --- a/netns/MANIFEST.in +++ b/netns/MANIFEST.in @@ -1,2 +1 @@ include *.h -include sbin/* diff --git a/netns/Makefile.am b/netns/Makefile.am index 131d593f..ee34df62 100644 --- a/netns/Makefile.am +++ b/netns/Makefile.am @@ -7,26 +7,25 @@ # Makefile for building netns. # -AM_CFLAGS = -Wall -fno-strict-aliasing -O3 -g @libev_CFLAGS@ -SETUPPY = setup.py -SETUPPYFLAGS = -v -# -DDEBUG +AM_CFLAGS = -Wall -fno-strict-aliasing -O3 -g @libev_CFLAGS@ +SETUPPY = setup.py +SETUPPYFLAGS = -v -SRC_COMMON = vnode_msg.c vnode_cmd.c vnode_chnl.c vnode_io.c \ - vnode_msg.h vnode_cmd.h vnode_chnl.h vnode_io.h \ - vnode_tlv.h myerr.h netns.h -SRC_VNODED = vnoded_main.c vnode_server.c netns.c \ - vnode_server.h -SRC_VCMD = vcmd_main.c vnode_client.c \ - vnode_client.h -SRC_NETNS = netns_main.c netns.c netns.h +SRC_COMMON = vnode_msg.c vnode_cmd.c vnode_chnl.c vnode_io.c \ + vnode_msg.h vnode_cmd.h vnode_chnl.h vnode_io.h \ + vnode_tlv.h myerr.h netns.h +SRC_VNODED = vnoded_main.c vnode_server.c netns.c \ + vnode_server.h +SRC_VCMD = vcmd_main.c vnode_client.c \ + vnode_client.h +SRC_NETNS = netns_main.c netns.c netns.h -sbin_PROGRAMS = vnoded vcmd netns -vnoded_LDADD = @libev_LIBS@ -vnoded_SOURCES = ${SRC_COMMON} ${SRC_VNODED} -vcmd_LDADD = @libev_LIBS@ -vcmd_SOURCES = ${SRC_COMMON} ${SRC_VCMD} -netns_SOURCES = ${SRC_NETNS} +noinst_PROGRAMS = vnoded vcmd netns +vnoded_LDADD = @libev_LIBS@ +vnoded_SOURCES = $(SRC_COMMON) $(SRC_VNODED) +vcmd_LDADD = @libev_LIBS@ +vcmd_SOURCES = $(SRC_COMMON) $(SRC_VCMD) +netns_SOURCES = $(SRC_NETNS) # this triggers automake to run setup.py for building the Python libraries # actual library names are netns.so and vcmd.so @@ -34,23 +33,23 @@ netns_SOURCES = ${SRC_NETNS} noinst_LIBRARIES = libnetns.a libnetns_a_SOURCES = netnsmodule.c vcmdmodule.c libnetns.a: - SBINDIR=@SBINDIR@ LDFLAGS="$(LDFLAGS) @libev_LIBS@" CFLAGS="$(CFLAGS) @libev_CFLAGS@" $(PYTHON) setup.py build_ext + LDFLAGS="$(LDFLAGS) @libev_LIBS@" CFLAGS="$(CFLAGS) @libev_CFLAGS@" $(PYTHON) setup.py build_ext # Python libraries install install-exec-local: - $(MKDIR_P) ${DESTDIR}/${pythondir} - $(MKDIR_P) ${DESTDIR}/${pyexecdir} - SBINDIR=${DESTDIR}/@SBINDIR@ PYTHONPATH=${DESTDIR}/${pythondir} $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ - --prefix=${DESTDIR}/${pyprefix} \ - --install-purelib=${DESTDIR}/${pythondir} \ - --install-platlib=${DESTDIR}/${pyexecdir} \ + $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ + --root=/$(DESTDIR) \ + --prefix=$(prefix) \ + --install-lib=$(pythondir) \ + --single-version-externally-managed \ --no-compile # Python libraries uninstall uninstall-hook: - rm -f ${pyexecdir}/core_python_netns-1.0-py${PYTHON_VERSION}.egg-info - rm -f ${pyexecdir}/netns.so - rm -f ${pyexecdir}/vcmd.so + rm -rf core_netns.egg-info + rm -rf $(DESTDIR)/$(pythondir)/core_netns-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + rm -f $(DESTDIR)/$(bindir)/{vnoded,vcmd,netns} + rm -f $(DESTDIR)/$(pythondir)/{netns.so,vcmd.so} # Python libraries cleanup clean-local: clean-local-check @@ -58,16 +57,9 @@ clean-local: clean-local-check clean-local-check: -rm -rf build -rpmbuild.sh: - echo SBINDIR=@SBINDIR@ LDFLAGS="$(LDFLAGS)" CFLAGS="$(CFLAGS) @libev_CFLAGS@" $(PYTHON) setup.py build > rpmbuild.sh - chmod a+x rpmbuild.sh - -rpm: rpmbuild.sh - $(PYTHON) setup.py bdist_rpm --build-script=rpmbuild.sh --requires="libev" --build-requires="libev-devel" - # extra cruft to remove -DISTCLEANFILES = Makefile.in rpmbuild.sh MANIFEST +DISTCLEANFILES = Makefile.in MANIFEST # include source files for Python libraries with distribution tarball -EXTRA_DIST = setup.py MANIFEST.in +EXTRA_DIST = setup.py MANIFEST.in diff --git a/netns/setup.py b/netns/setup.py index 8ef5083f..839faeae 100644 --- a/netns/setup.py +++ b/netns/setup.py @@ -3,25 +3,8 @@ Defines how CORE netns will be build for installation. """ from setuptools import setup, Extension -from distutils.command.install import install -class CustomInstall(install): - user_options = install.user_options + [ - ("service=", None, "determine which service file to include") - ] - - def initialize_options(self): - install.initialize_options(self) - self.service = "sysv" - - def finalize_options(self): - install.finalize_options(self) - assert self.service in ("sysv", "systemd"), "must be sysv or systemd" - - def run(self): - install.run(self) - netns = Extension( "netns", sources=[ @@ -58,7 +41,4 @@ setup( author_email="core-dev@nrl.navy.mil", license="BSD", long_description="Extension modules and utilities to support virtual nodes using Linux network namespaces", - cmdclass={ - "install": CustomInstall - } ) diff --git a/netns/version.h.in b/netns/version.h.in index 557b691d..a7489514 100644 --- a/netns/version.h.in +++ b/netns/version.h.in @@ -11,6 +11,6 @@ #ifndef _VERSION_H_ #define _VERSION_H_ -#define CORE_VERSION "@CORE_VERSION@" +#define CORE_VERSION "@PACKAGE_VERSION@" #endif /* _VERSION_H_ */ diff --git a/ns3/Makefile.am b/ns3/Makefile.am index 346daf5c..bf398426 100644 --- a/ns3/Makefile.am +++ b/ns3/Makefile.am @@ -7,17 +7,12 @@ # Makefile for building corens3 components. # -SETUPPY = setup.py -SETUPPYFLAGS = -v +SETUPPY = setup.py +SETUPPYFLAGS = -v -EXAMPLE_FILES = \ - examples/ns3lte.py \ - examples/ns3wifi.py \ - examples/ns3wifirandomwalk.py \ - examples/ns3wimax.py - -coreexampledir = $(datadir)/core/examples/corens3 -dist_coreexample_SCRIPTS= $(EXAMPLE_FILES) +#EXAMPLE_FILES := $(wildcard examples/*) +#coreexampledir = $(datadir)/core/examples/corens3 +#dist_coreexample_SCRIPTS = $(EXAMPLE_FILES) # Python package build noinst_SCRIPTS = build @@ -26,34 +21,30 @@ build: # Python package install install-exec-hook: - $(MKDIR_P) ${DESTDIR}/${pythondir} - $(MKDIR_P) ${DESTDIR}/${pyexecdir} - PYTHONPATH=${DESTDIR}/${pythondir} $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ - --prefix=${DESTDIR}/${pyprefix} \ - --install-purelib=${DESTDIR}/${pythondir} \ - --install-platlib=${DESTDIR}/${pyexecdir} \ + $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) install \ + --root=/$(DESTDIR) \ + --prefix=$(prefix) \ + --install-lib=$(pythondir) \ + --single-version-externally-managed \ --no-compile # Python package uninstall uninstall-hook: - rm -f ${pythondir}/corens3_python-${COREDPY_VERSION}-py${PYTHON_VERSION}.egg-info - rm -rf ${pythondir}/corens3 - rmdir -p $(coreexampledir) || true + rm -rf core_ns3.egg-info + rm -rf $(DESTDIR)/$(pythondir)/core_ns3-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + rm -rf $(DESTDIR)/$(pythondir)/corens3 + rm -rf $(DESTDIR)/$(datadir)/corens3 # Python package cleanup clean-local: -rm -rf build -# Python RPM package -rpm: - $(PYTHON) $(SETUPPY) $(SETUPPYFLAGS) bdist_rpm - # because we include entire directories with EXTRA_DIST, we need to clean up # the source control files dist-hook: - rm -rf `find $(distdir)/ -name .svn` `find $(distdir)/ -name '*.pyc'` + rm -rf `find $(distdir)/ -name '*.pyc'` -DISTCLEANFILES = Makefile.in *.pyc corens3/*.pyc MANIFEST +DISTCLEANFILES = Makefile.in *.pyc corens3/*.pyc MANIFEST # files to include with distribution tarball -EXTRA_DIST = LICENSE $(SETUPPY) corens3 +EXTRA_DIST = LICENSE $(SETUPPY) corens3 diff --git a/ns3/corens3/.gitignore b/ns3/corens3/.gitignore deleted file mode 100644 index 18b5fbad..00000000 --- a/ns3/corens3/.gitignore +++ /dev/null @@ -1 +0,0 @@ -constants.py diff --git a/ns3/corens3/constants.py.in b/ns3/corens3/constants.py.in deleted file mode 100644 index 05784d6c..00000000 --- a/ns3/corens3/constants.py.in +++ /dev/null @@ -1,18 +0,0 @@ -# Constants created by autoconf ./configure script -COREDPY_VERSION = "@COREDPY_VERSION@" -CORE_STATE_DIR = "@CORE_STATE_DIR@" -CORE_CONF_DIR = "@CORE_CONF_DIR@" -CORE_DATA_DIR = "@CORE_DATA_DIR@" -CORE_LIB_DIR = "@CORE_LIB_DIR@" -CORE_SBIN_DIR = "@SBINDIR@" - -BRCTL_BIN = "@brctl_path@/brctl" -IP_BIN = "@ip_path@/ip" -TC_BIN = "@tc_path@/tc" -EBTABLES_BIN = "@ebtables_path@/ebtables" -IFCONFIG_BIN = "@ifconfig_path@/ifconfig" -NGCTL_BIN = "@ngctl_path@/ngctl" -VIMAGE_BIN = "@vimage_path@/vimage" -QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" -MOUNT_BIN = "@mount_path@/mount" -UMOUNT_BIN = "@umount_path@/umount" diff --git a/ns3/setup.py b/ns3/setup.py index 9154d76e..c49d225e 100644 --- a/ns3/setup.py +++ b/ns3/setup.py @@ -1,11 +1,16 @@ +import glob + from setuptools import setup +_EXAMPLES_DIR = "share/corens3/examples" + setup( name="core-ns3", version="5.1", packages=[ "corens3", ], + data_files=[(_EXAMPLES_DIR, glob.glob("examples/*"))], description="Python ns-3 components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", author="Boeing Research & Technology", diff --git a/scripts/core-daemon.service.in b/scripts/core-daemon.service.in index b0c4a7f2..3d5c05fd 100644 --- a/scripts/core-daemon.service.in +++ b/scripts/core-daemon.service.in @@ -5,7 +5,7 @@ After=network.target [Service] Type=forking PIDFile=/var/run/core-daemon.pid -ExecStart=@PYTHON@ @SBINDIR@/core-daemon -d +ExecStart=@PYTHON@ @bindir@/core-daemon -d TasksMax=infinity [Install] diff --git a/scripts/perf/Makefile.am b/scripts/perf/Makefile.am index b9ea48d7..7531ba82 100644 --- a/scripts/perf/Makefile.am +++ b/scripts/perf/Makefile.am @@ -17,7 +17,7 @@ dist_hooks_SCRIPTS = perflogstart.sh perflogstop.sh sessiondatacollect.sh \ configuration_hook.sh datacollect_hook.sh # Files installed to /etc/core/ -perfconfdir=$(sysconfdir)/core +perfconfdir=$(CORE_CONF_DIR) dist_perfconf_DATA = perflogserver.conf uninstall-hook: From 20305776e4bc7cfcd758d7aeec8c98f862695ed5 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 09:00:19 -0700 Subject: [PATCH 062/152] updated the message at the end of configure --- configure.ac | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 0ea864ea..2d3639b1 100644 --- a/configure.ac +++ b/configure.ac @@ -237,21 +237,25 @@ echo \ "------------------------------------------------------------------------ ${PACKAGE_STRING} Configuration: +Build: Host System Type: ${host} C Compiler and flags: ${CC} ${CFLAGS} - Install prefix: ${prefix} - Exec prefix: ${exec_prefix} - Build GUI: ${enable_gui} + Prefix: ${prefix} + Exec Prefix: ${exec_prefix} + +GUI: GUI path: ${CORE_LIB_DIR} GUI config: ${CORE_GUI_CONF_DIR} - Daemon path: ${sbindir} + +Daemon: + Daemon path: ${bindir} Daemon config: ${CORE_CONF_DIR} Python modules: ${pythondir} Logs: ${CORE_STATE_DIR}/log Features to build: - Python bindings: ${want_python} - Linux Namespaces emulation: ${want_linux_netns} + Build GUI: ${enable_gui} + Build Daemon: ${enable_daemon} Documentation: ${want_docs} ------------------------------------------------------------------------" From 3b568e965d42a1ca1f5ed2951cc2edc784f89ea3 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 09:04:01 -0700 Subject: [PATCH 063/152] removed manifest.in from dist line in daemon makefile --- daemon/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 24c07196..f804b760 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -63,4 +63,4 @@ dist-hook: DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST # files to include with distribution tarball -EXTRA_DIST = $(SETUPPY) MANIFEST.in core doc $(LOGROTATE_FILE) +EXTRA_DIST = $(SETUPPY) core doc $(LOGROTATE_FILE) From 8e3b6b0b95e5e59c63df3c13761fe58b56212565 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 10:43:25 -0700 Subject: [PATCH 064/152] updates to try and resync make dist to include current files --- daemon/Makefile.am | 20 +++++++++++++++++--- doc/Makefile.am | 4 ++-- gui/Makefile.am | 6 +++++- netns/Makefile.am | 3 +++ ns3/Makefile.am | 21 ++++++++++----------- scripts/Makefile.am | 2 +- 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index f804b760..78611022 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -58,9 +58,23 @@ clean-local: # because we include entire directories with EXTRA_DIST, we need to clean up # the source control files dist-hook: - rm -rf `find $(distdir)/ -name '*.pyc'` + -rm -rf `find $(distdir)/ -name '*.pyc'` -DISTCLEANFILES = Makefile.in core/*.pyc MANIFEST +distclean-local: + -rm -rf core.egg-info + + +DISTCLEANFILES = Makefile.in # files to include with distribution tarball -EXTRA_DIST = $(SETUPPY) core doc $(LOGROTATE_FILE) +EXTRA_DIST = $(SETUPPY) \ + core \ + data \ + doc/conf.py.in \ + examples \ + sbin \ + tests \ + test.py \ + setup.cfg \ + requirements.txt \ + $(LOGROTATE_FILE) diff --git a/doc/Makefile.am b/doc/Makefile.am index 379b7d99..781977a0 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -13,9 +13,9 @@ SUBDIRS = man figures # extra cruft to remove DISTCLEANFILES = Makefile.in stamp-vti -rst_files = conf.py constants.txt credits.rst ctrlnet.rst devguide.rst \ +rst_files = conf.py.in constants.txt credits.rst ctrlnet.rst devguide.rst \ emane.rst index.rst install.rst intro.rst machine.rst \ - ns3.rst performance.rst scripting.rst usage.rst + ns3.rst performance.rst scripting.rst usage.rst requirements.txt EXTRA_DIST = $(rst_files) diff --git a/gui/Makefile.am b/gui/Makefile.am index 3a1a09d0..0d0d2b47 100644 --- a/gui/Makefile.am +++ b/gui/Makefile.am @@ -30,8 +30,12 @@ dist_coreaddons_DATA = $(ADDONS_FILES) coreconfigsdir = $(datadir)/core/examples/configs dist_coreconfigs_DATA = $(CONFIG_FILES) +# remove generated file from dist +dist-hook: + -rm -f $(distdir)/version.tcl + # extra cruft to remove DISTCLEANFILES = Makefile.in # files to include in source tarball not included elsewhere -EXTRA_DIST = addons +EXTRA_DIST = core-gui.in diff --git a/netns/Makefile.am b/netns/Makefile.am index ee34df62..f3001ead 100644 --- a/netns/Makefile.am +++ b/netns/Makefile.am @@ -57,6 +57,9 @@ clean-local: clean-local-check clean-local-check: -rm -rf build +distclean-local: + -rm -rf core_netns.egg-info + # extra cruft to remove DISTCLEANFILES = Makefile.in MANIFEST diff --git a/ns3/Makefile.am b/ns3/Makefile.am index bf398426..caa0c1c0 100644 --- a/ns3/Makefile.am +++ b/ns3/Makefile.am @@ -10,10 +10,6 @@ SETUPPY = setup.py SETUPPYFLAGS = -v -#EXAMPLE_FILES := $(wildcard examples/*) -#coreexampledir = $(datadir)/core/examples/corens3 -#dist_coreexample_SCRIPTS = $(EXAMPLE_FILES) - # Python package build noinst_SCRIPTS = build build: @@ -30,10 +26,10 @@ install-exec-hook: # Python package uninstall uninstall-hook: - rm -rf core_ns3.egg-info - rm -rf $(DESTDIR)/$(pythondir)/core_ns3-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info - rm -rf $(DESTDIR)/$(pythondir)/corens3 - rm -rf $(DESTDIR)/$(datadir)/corens3 + -rm -rf core_ns3.egg-info + -rm -rf $(DESTDIR)/$(pythondir)/core_ns3-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info + -rm -rf $(DESTDIR)/$(pythondir)/corens3 + -rm -rf $(DESTDIR)/$(datadir)/corens3 # Python package cleanup clean-local: @@ -42,9 +38,12 @@ clean-local: # because we include entire directories with EXTRA_DIST, we need to clean up # the source control files dist-hook: - rm -rf `find $(distdir)/ -name '*.pyc'` + -rm -rf `find $(distdir)/ -name '*.pyc'` -DISTCLEANFILES = Makefile.in *.pyc corens3/*.pyc MANIFEST +distclean-local: + -rm -rf core_ns3.egg-info + +DISTCLEANFILES = Makefile.in # files to include with distribution tarball -EXTRA_DIST = LICENSE $(SETUPPY) corens3 +EXTRA_DIST = LICENSE $(SETUPPY) corens3 examples diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 4a1cc6ad..9c521923 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -9,7 +9,7 @@ CLEANFILES = core-daemon -DISTCLEANFILES = Makefile.in +DISTCLEANFILES = Makefile.in core-daemon.service EXTRA_DIST = core-daemon-init.d \ core-daemon.service.in \ From 51855831c19e1a5550e89142209f3dfef09365b1 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 10:45:34 -0700 Subject: [PATCH 065/152] formally removing python-prefix and revision scripts --- Makefile.am | 2 - python-prefix.py | 36 ---------- revision.sh | 173 ----------------------------------------------- 3 files changed, 211 deletions(-) delete mode 100755 python-prefix.py delete mode 100755 revision.sh diff --git a/Makefile.am b/Makefile.am index 4cfea830..28043555 100644 --- a/Makefile.am +++ b/Makefile.am @@ -34,8 +34,6 @@ EXTRA_DIST = bootstrap.sh \ README.md \ ASSIGNMENT_OF_COPYRIGHT.pdf \ Changelog \ - python-prefix.py \ - revision.sh \ .version \ .version.date diff --git a/python-prefix.py b/python-prefix.py deleted file mode 100755 index 20a50d75..00000000 --- a/python-prefix.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python - -import os.path -import site -import sys - - -def main(): - """ - Check if the given prefix is included in sys.path for the given - python version; if not find an alternate valid prefix. Print the - result to standard out. - """ - if len(sys.argv) != 3: - msg = "usage: %s \n" % os.path.basename(sys.argv[0]) - sys.stderr.write(msg) - return 1 - python_prefix = sys.argv[1] - python_version = sys.argv[2] - path = "%s/lib/python%s" % (python_prefix, python_version) - path = os.path.normpath(path) - if path[-1] != "/": - path += "/" - prefix = None - for p in sys.path: - if p.startswith(path): - prefix = python_prefix - break - if not prefix: - prefix = site.PREFIXES[-1] - sys.stdout.write("%s\n" % prefix) - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/revision.sh b/revision.sh deleted file mode 100755 index 661506fe..00000000 --- a/revision.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/sh - -usage() -{ - echo "usage: $(basename $0) (-d | [])" >&2 - exit $1 -} - -func=revision -while getopts dh f; do - case $f in - d) - func=date - ;; - - h) - usage 0 - ;; - - *) - usage 1 - ;; - esac -done -shift $(($OPTIND - 1)) - -case $func in - revision) - if [ $# -lt 1 -o $# -gt 2 ]; then - usage 1 - fi - ;; - - date) - if [ $# -gt 0 ]; then - usage 1 - fi - ;; - - *) - usage 1 - ;; -esac - -_revision() -{ - if [ -r .version ]; then - cat .version - else - echo $1$2 - fi -} - -git_revision() -{ - local ver versuffix describe untagged commits branch sha dirty - - ver=$1 - versuffix=$2 - - describe=$(git describe --tags --dirty 2> /dev/null) - if [ "$describe" ]; then - echo "$describe" | sed -e 's/^release-//' - return - fi - - if [ ! "$(git tag -l release-$ver)" ]; then - untagged=".untagged" - else - commits=$(git rev-list release-${ver}^..HEAD | wc -l) - if [ $commits -eq 0 ]; then - commits="" - else - commits=".$commits" - fi - fi - - branch=$(git rev-parse --abbrev-ref HEAD) - if [ "$branch" = master ]; then - branch="" - else - branch=".$(echo -n $branch | tr -sC '.[:alnum:]' '[.*]')" - fi - - if [ "$untagged" -o "$commits" ]; then - sha=.g$(git log -1 --pretty="%h") - fi - - if ! git diff --quiet; then - dirty=".dirty" - else - dirty="" - fi - - echo ${ver}${versuffix}${untagged}${commits}${branch}${sha}${dirty} -} - -svn_revision() -{ - local ver versuffix tagrev untagged commits rev dirty - - ver=$1 - versuffix=$2 - - tagrev=$(svn log -q ^/tags/release-$ver --limit 1 2> /dev/null | \ - awk '/^r/ {print $1}') - if [ ! "$tagrev" ];then - untagged=".untagged" - else - commits=$(svn log -q -r $tagrev:HEAD | grep '^r' | wc -l) - if [ $commits -eq 0 ]; then - commits="" - else - commits=".$commits" - fi - fi - - if [ "$untagged" -o "$commits" ]; then - rev=.s$(svn info | awk '/^Revision:/ {print $2}') - fi - - if (svn status -q | grep -q .); then - dirty=".dirty" - fi - - echo ${ver}${versuffix}${untagged}${commits}${rev}${dirty} -} - -_date() -{ - if [ -r .version.date ]; then - cat .version.date - else - date '+%Y%m%d' - fi -} - -git_date() -{ - local date - - if git diff --quiet; then - date=$(git log -1 --format='%ci' | \ - awk '{gsub("-", "", $1); print $1}') - else - date=$(_date) - fi - - echo $date -} - -svn_date() -{ - local date - - if ! (svn status -q | grep -q .); then - date=$(svn log -q --limit 1 | \ - awk '/^r[0-9]+/ {gsub("-", "", $5); print $5}') - else - date=$(_date) - fi - - echo $date -} - -repo="" -if test -d .git || git rev-parse --git-dir > /dev/null 2>&1; then - repo=git -elif test -d .svn || svn info > /dev/null 2>&1; then - repo=svn -fi - -${repo}_${func} "$@" From 46e057d1ed93a9fc467022f618a5a077553c67fe Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 10:47:31 -0700 Subject: [PATCH 066/152] updated configure to check for python 2.7 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2d3639b1..3881eef5 100644 --- a/configure.ac +++ b/configure.ac @@ -99,7 +99,7 @@ if test "x$enable_daemon" = "xyes"; then AC_FUNC_REALLOC AC_CHECK_FUNCS([atexit dup2 gettimeofday memset socket strerror uname]) - AM_PATH_PYTHON(2.6) + AM_PATH_PYTHON(2.7) AC_CHECK_PROG(brctl_path, brctl, $as_dir, no, $SEARCHPATH) if test "x$brctl_path" = "xno" ; then From 138b2fcc4a3841475ac882cf926cace1095c0e0e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 13:14:14 -0700 Subject: [PATCH 067/152] update to get coresendmsg working again --- daemon/sbin/coresendmsg | 379 ++++++++++++++++++++++------------------ 1 file changed, 206 insertions(+), 173 deletions(-) diff --git a/daemon/sbin/coresendmsg b/daemon/sbin/coresendmsg index ebf56486..85679e9a 100755 --- a/daemon/sbin/coresendmsg +++ b/daemon/sbin/coresendmsg @@ -6,187 +6,207 @@ # # authors: Jeff Ahrenholz # -''' +""" coresendmsg: utility for generating CORE messages -''' +""" -import sys -import socket import optparse import os +import socket +import sys -try: - from core.constants import * -except ImportError: - # hack for Fedora autoconf that uses the following pythondir: - if "/usr/lib/python2.6/site-packages" in sys.path: - sys.path.append("/usr/local/lib/python2.6/site-packages") - if "/usr/lib64/python2.6/site-packages" in sys.path: - sys.path.append("/usr/local/lib64/python2.6/site-packages") - if "/usr/lib/python2.7/site-packages" in sys.path: - sys.path.append("/usr/local/lib/python2.7/site-packages") - if "/usr/lib64/python2.7/site-packages" in sys.path: - sys.path.append("/usr/local/lib64/python2.7/site-packages") - from core.constants import * from core.api import coreapi +from core.enumerations import CORE_API_PORT +from core.enumerations import MessageFlags +from core.enumerations import MessageTypes +from core.enumerations import SessionTlvs -def msgtypenum_to_str(num): - ''' Convert the message type number into a string, such as - 1 = 'CORE_API_NODE_MSG' = 'node' - ''' - fulltypestr = coreapi.message_types[num] - r = fulltypestr.split('_')[2] - return r.lower() +# def msgtypenum_to_str(num): +# """ +# Convert the message type number into a string, such as +# 1 = "CORE_API_NODE_MSG" = "node" +# """ +# fulltypestr = str(MessageTypes(num)) +# r = fulltypestr.split("_")[2] +# return r.lower() -def str_to_msgtypenum(s): - ''' Convert a shorthand string into a message type number. - ''' - fulltypestr = str_to_msgtypename(s) - for k, v in coreapi.message_types.iteritems(): - if v == fulltypestr: - return k - return None -def str_to_msgtypename(s): - ''' Convert a shorthand string into a message type name. - ''' - return "CORE_API_%s_MSG" % s.upper() +# def str_to_msgtypenum(message_string): +# """ +# Convert a shorthand string into a message type number. +# """ +# fulltypestr = str_to_msgtypename(message_string) +# for k, v in coreapi.message_types.iteritems(): +# if v == fulltypestr: +# return k +# return None -def msgflagnum_to_str(num): - ''' Convert the message flag number into a string, such as - 1 = 'CORE_API_ADD_FLAG' = add - ''' - fullflagstr = coreapi.message_flags[num] - r = fullflagstr.split('_')[2] - return r.lower() -def str_to_msgflagname(s): - ''' Convert a shorthand string into a message flag name. - ''' - return "CORE_API_%s_FLAG" % s.upper() +# def str_to_msgtypename(s): +# """ +# Convert a shorthand string into a message type name. +# """ +# return "CORE_API_%s_MSG" % s.upper() -def str_to_msgflagnum(s): - flagname = str_to_msgflagname(s) - for (k, v) in coreapi.message_flags.iteritems(): - if v == flagname: - return k - return None -def tlvname_to_str(name): - ''' Convert a TLV name such as CORE_TLV_CONF_NODE to a short sring 'node'. - ''' - items = name.split('_')[3:] - return '_'.join(items).lower() +# def msgflagnum_to_str(num): +# """ +# Convert the message flag number into a string, such as +# 1 = "CORE_API_ADD_FLAG" = add +# """ +# fullflagstr = coreapi.message_flags[num] +# r = fullflagstr.split("_")[2] +# return r.lower() -def tlvname_to_num(tlv_cls, name): - ''' Convert the given TLV Type class and TLV name to the TLV number. - ''' - for (k, v) in tlv_cls.tlvtypemap.iteritems(): - if v == name: - return k - return None -def str_to_tlvname(t, s): - ''' Convert the given TLV type t and string s to a TLV name. - ''' - return "CORE_TLV_%s_%s" % (t.upper(), s.upper()) +# def str_to_msgflagname(s): +# """ +# Convert a shorthand string into a message flag name. +# """ +# return "CORE_API_%s_FLAG" % s.upper() + + +# def str_to_msgflagnum(s): +# flagname = str_to_msgflagname(s) +# for (k, v) in coreapi.message_flags.iteritems(): +# if v == flagname: +# return k +# return None + + +# def tlvname_to_str(name): +# """ +# Convert a TLV name such as CORE_TLV_CONF_NODE to a short sring "node". +# """ +# items = name.split("_")[3:] +# return "_".join(items).lower() + + +# def tlvname_to_num(tlv_cls, name): +# """ +# Convert the given TLV Type class and TLV name to the TLV number. +# """ +# for k, v in tlv_cls.tlv_type_map.iteritems(): +# if v == name: +# return k +# return None + + +# def str_to_tlvname(t, s): +# """ +# Convert the given TLV type t and string s to a TLV name. +# """ +# return "CORE_TLV_%s_%s" % (t.upper(), s.upper()) def print_available_tlvs(t, tlv_cls): - ''' Print a TLV list. - ''' + """ + Print a TLV list. + """ print "TLVs available for %s message:" % t - for k in sorted(tlv_cls.tlvtypemap.keys()): - print "%d:%s" % (k, tlvname_to_str(tlv_cls.tlvtypemap[k])), + for tlv in sorted([tlv for tlv in tlv_cls], key=lambda x: x.name): + print "%s:%s" % (tlv.value, tlv.name) + def print_examples(name): - ''' Print example usage of this script. - ''' - examples = [ - ('link n1number=2 n2number=3 delay=15000', - 'set a 15ms delay on the link between n2 and n3'), - ('link n1number=2 n2number=3 guiattr=\'color=blue\'', - 'change the color of the link between n2 and n3'), - ('node number=3 xpos=125 ypos=525', - 'move node number 3 to x,y=(125,525)'), - ('node number=4 icon=/usr/local/share/core/icons/normal/router_red.gif', - 'change node number 4\'s icon to red'), - ('node flags=add number=5 type=0 name=\'n5\' xpos=500 ypos=500', - 'add a new router node n5'), - ('link flags=add n1number=4 n2number=5 if1ip4=\'10.0.3.2\' ' \ - 'if1ip4mask=24 if2ip4=\'10.0.3.1\' if2ip4mask=24', - 'link node n5 with n4 using the given interface addresses'), - ('exec flags=str,txt node=1 num=1000 cmd=\'uname -a\' -l', - 'run a command on node 1 and wait for the result'), - ('exec node=2 num=1001 cmd=\'killall ospfd\'', - 'run a command on node 2 and ignore the result'), - ('file flags=add node=1 name=\'/var/log/test.log\' data=\'Hello World.\'', - 'write a test.log file on node 1 with the given contents'), - ('file flags=add node=2 name=\'test.log\' ' \ - 'srcname=\'./test.log\'', - 'move a test.log file from host to node 2'), - ] + """ + Print example usage of this script. + """ + examples = [ + ("link n1number=2 n2number=3 delay=15000", + "set a 15ms delay on the link between n2 and n3"), + ("link n1number=2 n2number=3 guiattr=\"color=blue\"", + "change the color of the link between n2 and n3"), + ("node number=3 xpos=125 ypos=525", + "move node number 3 to x,y=(125,525)"), + ("node number=4 icon=/usr/local/share/core/icons/normal/router_red.gif", + "change node number 4\"s icon to red"), + ("node flags=add number=5 type=0 name=\"n5\" xpos=500 ypos=500", + "add a new router node n5"), + ("link flags=add n1number=4 n2number=5 if1ip4=\"10.0.3.2\" " \ + "if1ip4mask=24 if2ip4=\"10.0.3.1\" if2ip4mask=24", + "link node n5 with n4 using the given interface addresses"), + ("exec flags=str,txt node=1 num=1000 cmd=\"uname -a\" -l", + "run a command on node 1 and wait for the result"), + ("exec node=2 num=1001 cmd=\"killall ospfd\"", + "run a command on node 2 and ignore the result"), + ("file flags=add node=1 name=\"/var/log/test.log\" data=\"Hello World.\"", + "write a test.log file on node 1 with the given contents"), + ("file flags=add node=2 name=\"test.log\" " \ + "srcname=\"./test.log\"", + "move a test.log file from host to node 2"), + ] print "Example %s invocations:" % name for cmd, descr in examples: print " %s %s\n\t\t%s" % (name, cmd, descr) + def receive_message(sock): - ''' Retrieve a message from a socket and return the CoreMessage object or - None upon disconnect. Socket data beyond the first message is dropped. - ''' + """ + Retrieve a message from a socket and return the CoreMessage object or + None upon disconnect. Socket data beyond the first message is dropped. + """ try: # large receive buffer used for UDP sockets, instead of just receiving # the 4-byte header data = sock.recv(4096) - msghdr = data[:coreapi.CoreMessage.hdrsiz] + msghdr = data[:coreapi.CoreMessage.header_len] except KeyboardInterrupt: print "CTRL+C pressed" sys.exit(1) + if len(msghdr) == 0: return None + msgdata = None - msgtype, msgflags, msglen = coreapi.CoreMessage.unpackhdr(msghdr) + msgtype, msgflags, msglen = coreapi.CoreMessage.unpack_header(msghdr) + if msglen: - msgdata = data[coreapi.CoreMessage.hdrsiz:] + msgdata = data[coreapi.CoreMessage.header_len:] try: - msgcls = coreapi.msg_class(msgtype) + msgcls = coreapi.CLASS_MAP[msgtype] except KeyError: msg = coreapi.CoreMessage(msgflags, msghdr, msgdata) - msg.msgtype = msgtype - print "unimplemented CORE message type: %s" % msg.typestr() + msg.message_type = msgtype + print "unimplemented CORE message type: %s" % msg.type_str() return msg - if len(data) > msglen + coreapi.CoreMessage.hdrsiz: + if len(data) > msglen + coreapi.CoreMessage.header_len: print "received a message of type %d, dropping %d bytes of extra data" \ - % (msgtype, len(data) - (msglen + coreapi.CoreMessage.hdrsiz)) + % (msgtype, len(data) - (msglen + coreapi.CoreMessage.header_len)) return msgcls(msgflags, msghdr, msgdata) def connect_to_session(sock, requested): - ''' Use Session Messages to retrieve the current list of sessions and - connect to the first one. - ''' + """ + Use Session Messages to retrieve the current list of sessions and + connect to the first one. + """ # request the session list - tlvdata = coreapi.CoreSessionTlv.pack(coreapi.CORE_TLV_SESS_NUMBER, "0") - flags = coreapi.CORE_API_STR_FLAG + tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, "0") + flags = MessageFlags.STRING.value smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata) sock.sendall(smsg) + print "waiting for session list..." smsgreply = receive_message(sock) if smsgreply is None: print "disconnected" return False - sessstr = smsgreply.gettlv(coreapi.CORE_TLV_SESS_NUMBER) + + sessstr = smsgreply.gettlv(SessionTlvs.NUMBER.value) if sessstr is None: print "missing session numbers" return False + # join the first session (that is not our own connection) - (tmp, localport) = sock.getsockname() - sessions = sessstr.split('|') + tmp, localport = sock.getsockname() + sessions = sessstr.split("|") sessions.remove(str(localport)) if len(sessions) == 0: print "no sessions to join" return False + if not requested: session = sessions[0] elif requested in sessions: @@ -194,17 +214,19 @@ def connect_to_session(sock, requested): else: print "requested session not found!" return False + print "joining session %s..." % session - tlvdata = coreapi.CoreSessionTlv.pack(coreapi.CORE_TLV_SESS_NUMBER, session) - flags = coreapi.CORE_API_ADD_FLAG + tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER, session) + flags = MessageFlags.ADD smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata) sock.sendall(smsg) return True def receive_response(sock, opt): - ''' Receive and print a CORE message from the given socket. - ''' + """ + Receive and print a CORE message from the given socket. + """ print "waiting for response..." msg = receive_message(sock) if msg is None: @@ -214,44 +236,46 @@ def receive_response(sock, opt): def main(): - ''' Parse command-line arguments to build and send a CORE message. - ''' - types = map(msgtypenum_to_str, coreapi.message_types.keys()[:-1]) - flags = map(msgflagnum_to_str, sorted(coreapi.message_flags.keys())) + """ + Parse command-line arguments to build and send a CORE message. + """ + types = [message_type.name for message_type in MessageTypes] + flags = [flag.name for flag in MessageFlags] usagestr = "usage: %prog [-h|-H] [options] [message-type] [flags=flags] " usagestr += "[message-TLVs]\n\n" usagestr += "Supported message types:\n %s\n" % types usagestr += "Supported message flags (flags=f1,f2,...):\n %s" % flags - parser = optparse.OptionParser(usage = usagestr) - parser.set_defaults(port = coreapi.CORE_API_PORT, - address = "localhost", - session = None, - listen = False, - examples = False, - tlvs = False, - tcp = False) + parser = optparse.OptionParser(usage=usagestr) + parser.set_defaults( + port=CORE_API_PORT, + address="localhost", + session=None, + listen=False, + examples=False, + tlvs=False, + tcp=False + ) - parser.add_option("-H", dest = "examples", action = "store_true", - help = "show example usage help message and exit") - parser.add_option("-p", "--port", dest = "port", type = int, - help = "TCP port to connect to, default: %d" % \ - parser.defaults['port']) - parser.add_option("-a", "--address", dest = "address", type = str, - help = "Address to connect to, default: %s" % \ - parser.defaults['address']) - parser.add_option("-s", "--session", dest = "session", type = str, - help = "Session to join, default: %s" % \ - parser.defaults['session']) - parser.add_option("-l", "--listen", dest = "listen", action = "store_true", - help = "Listen for a response message and print it.") - parser.add_option("-t", "--list-tlvs", dest = "tlvs", action = "store_true", - help = "List TLVs for the specified message type.") - parser.add_option("-T", "--tcp", dest = "tcp", action = "store_true", - help = "Use TCP instead of UDP and connect to a session" \ - ", default: %s" % parser.defaults['tcp']) + parser.add_option("-H", dest="examples", action="store_true", + help="show example usage help message and exit") + parser.add_option("-p", "--port", dest="port", type=int, + help="TCP port to connect to, default: %d" % \ + parser.defaults["port"]) + parser.add_option("-a", "--address", dest="address", type=str, + help="Address to connect to, default: %s" % \ + parser.defaults["address"]) + parser.add_option("-s", "--session", dest="session", type=str, + help="Session to join, default: %s" % \ + parser.defaults["session"]) + parser.add_option("-l", "--listen", dest="listen", action="store_true", + help="Listen for a response message and print it.") + parser.add_option("-t", "--list-tlvs", dest="tlvs", action="store_true", + help="List TLVs for the specified message type.") + parser.add_option("-T", "--tcp", dest="tcp", action="store_true", + help="Use TCP instead of UDP and connect to a session" \ + ", default: %s" % parser.defaults["tcp"]) - - def usage(msg = None, err = 0): + def usage(msg=None, err=0): sys.stdout.write("\n") if msg: sys.stdout.write(msg + "\n\n") @@ -259,8 +283,8 @@ def main(): sys.exit(err) # parse command line opt - (opt, args) = parser.parse_args() - if (opt.examples): + opt, args = parser.parse_args() + if opt.examples: print_examples(os.path.basename(sys.argv[0])) sys.exit(0) if len(args) == 0: @@ -270,40 +294,47 @@ def main(): t = args.pop(0) if t not in types: usage("Unknown message type requested: %s" % t) - msg_cls = coreapi.msgclsmap[str_to_msgtypenum(t)] - tlv_cls = msg_cls.tlvcls + message_type = MessageTypes[t] + msg_cls = coreapi.CLASS_MAP[message_type.value] + tlv_cls = msg_cls.tlv_cls # list TLV types for this message type if opt.tlvs: print_available_tlvs(t, tlv_cls) sys.exit(0) - # build a message consisting of TLVs from 'type=value' arguments + # build a message consisting of TLVs from "type=value" arguments flagstr = "" tlvdata = "" for a in args: - typevalue = a.split('=') + typevalue = a.split("=") if len(typevalue) < 2: - usage("Use 'type=value' syntax instead of '%s'." % a) + usage("Use \"type=value\" syntax instead of \"%s\"." % a) tlv_typestr = typevalue[0] - tlv_valstr = '='.join(typevalue[1:]) + tlv_valstr = "=".join(typevalue[1:]) if tlv_typestr == "flags": flagstr = tlv_valstr continue - tlv_name = str_to_tlvname(t, tlv_typestr) - tlv_type = tlvname_to_num(tlv_cls, tlv_name) - if tlv_name not in tlv_cls.tlvtypemap.values(): - usage("Unknown TLV: '%s' / %s" % (tlv_typestr, tlv_name)) - tlvdata += tlv_cls.packstring(tlv_type, tlv_valstr) + + tlv_name = tlv_typestr + tlv_type = tlv_cls[tlv_name].value + try: + tlv_cls.tlv_type_map[tlv_name] + except KeyError: + usage("Unknown TLV: \"%s\"" % tlv_name) + tlvdata += tlv_cls.pack_string(tlv_type, tlv_valstr) flags = 0 for f in flagstr.split(","): - if f == '': + if f == "": continue - n = str_to_msgflagnum(f) - if n is None: - usage("Invalid flag '%s'." % f) - flags |= n + + try: + flag_enum = MessageFlags[f] + n = flag_enum.value + flags |= n + except KeyError: + usage("Invalid flag \"%s\"." % f) msg = msg_cls.pack(flags, tlvdata) @@ -312,11 +343,13 @@ def main(): protocol = socket.SOCK_STREAM else: protocol = socket.SOCK_DGRAM + sock = socket.socket(socket.AF_INET, protocol) sock.setblocking(True) + try: sock.connect((opt.address, opt.port)) - except Exception, e: + except Exception as e: print "Error connecting to %s:%s:\n\t%s" % (opt.address, opt.port, e) sys.exit(1) From b74d3488f7de3091f18f68fa5581516804b49f36 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 14 Mar 2018 13:34:25 -0700 Subject: [PATCH 068/152] fixed coresendmsg after testing --- daemon/sbin/coresendmsg | 99 +++-------------------------------------- 1 file changed, 6 insertions(+), 93 deletions(-) diff --git a/daemon/sbin/coresendmsg b/daemon/sbin/coresendmsg index 85679e9a..43c07cfd 100755 --- a/daemon/sbin/coresendmsg +++ b/daemon/sbin/coresendmsg @@ -22,90 +22,12 @@ from core.enumerations import MessageTypes from core.enumerations import SessionTlvs -# def msgtypenum_to_str(num): -# """ -# Convert the message type number into a string, such as -# 1 = "CORE_API_NODE_MSG" = "node" -# """ -# fulltypestr = str(MessageTypes(num)) -# r = fulltypestr.split("_")[2] -# return r.lower() - - -# def str_to_msgtypenum(message_string): -# """ -# Convert a shorthand string into a message type number. -# """ -# fulltypestr = str_to_msgtypename(message_string) -# for k, v in coreapi.message_types.iteritems(): -# if v == fulltypestr: -# return k -# return None - - -# def str_to_msgtypename(s): -# """ -# Convert a shorthand string into a message type name. -# """ -# return "CORE_API_%s_MSG" % s.upper() - - -# def msgflagnum_to_str(num): -# """ -# Convert the message flag number into a string, such as -# 1 = "CORE_API_ADD_FLAG" = add -# """ -# fullflagstr = coreapi.message_flags[num] -# r = fullflagstr.split("_")[2] -# return r.lower() - - -# def str_to_msgflagname(s): -# """ -# Convert a shorthand string into a message flag name. -# """ -# return "CORE_API_%s_FLAG" % s.upper() - - -# def str_to_msgflagnum(s): -# flagname = str_to_msgflagname(s) -# for (k, v) in coreapi.message_flags.iteritems(): -# if v == flagname: -# return k -# return None - - -# def tlvname_to_str(name): -# """ -# Convert a TLV name such as CORE_TLV_CONF_NODE to a short sring "node". -# """ -# items = name.split("_")[3:] -# return "_".join(items).lower() - - -# def tlvname_to_num(tlv_cls, name): -# """ -# Convert the given TLV Type class and TLV name to the TLV number. -# """ -# for k, v in tlv_cls.tlv_type_map.iteritems(): -# if v == name: -# return k -# return None - - -# def str_to_tlvname(t, s): -# """ -# Convert the given TLV type t and string s to a TLV name. -# """ -# return "CORE_TLV_%s_%s" % (t.upper(), s.upper()) - - -def print_available_tlvs(t, tlv_cls): +def print_available_tlvs(t, tlv_class): """ Print a TLV list. """ print "TLVs available for %s message:" % t - for tlv in sorted([tlv for tlv in tlv_cls], key=lambda x: x.name): + for tlv in sorted([tlv for tlv in tlv_class.tlv_type_map], key=lambda x: x.name): print "%s:%s" % (tlv.value, tlv.name) @@ -194,7 +116,7 @@ def connect_to_session(sock, requested): print "disconnected" return False - sessstr = smsgreply.gettlv(SessionTlvs.NUMBER.value) + sessstr = smsgreply.get_tlv(SessionTlvs.NUMBER.value) if sessstr is None: print "missing session numbers" return False @@ -271,9 +193,6 @@ def main(): help="Listen for a response message and print it.") parser.add_option("-t", "--list-tlvs", dest="tlvs", action="store_true", help="List TLVs for the specified message type.") - parser.add_option("-T", "--tcp", dest="tcp", action="store_true", - help="Use TCP instead of UDP and connect to a session" \ - ", default: %s" % parser.defaults["tcp"]) def usage(msg=None, err=0): sys.stdout.write("\n") @@ -296,7 +215,7 @@ def main(): usage("Unknown message type requested: %s" % t) message_type = MessageTypes[t] msg_cls = coreapi.CLASS_MAP[message_type.value] - tlv_cls = msg_cls.tlv_cls + tlv_cls = msg_cls.tlv_class # list TLV types for this message type if opt.tlvs: @@ -338,13 +257,7 @@ def main(): msg = msg_cls.pack(flags, tlvdata) - # send the message - if opt.tcp: - protocol = socket.SOCK_STREAM - else: - protocol = socket.SOCK_DGRAM - - sock = socket.socket(socket.AF_INET, protocol) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(True) try: @@ -353,7 +266,7 @@ def main(): print "Error connecting to %s:%s:\n\t%s" % (opt.address, opt.port, e) sys.exit(1) - if opt.tcp and not connect_to_session(sock, opt.session): + if not connect_to_session(sock, opt.session): print "warning: continuing without joining a session!" sock.sendall(msg) From 01fe8d708c77a4df8fbacbc13ae44741ac36404c Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 10:36:54 -0700 Subject: [PATCH 069/152] updates to simplify tracking the copyright and an update to 2018, still room for improvement --- LICENSE | 2 +- README.md | 2 +- configure.ac | 8 -------- daemon/doc/conf.py.in | 4 ++-- daemon/examples/emanemodel2core.py | 14 -------------- daemon/examples/myservices/sample.py | 5 ----- daemon/sbin/core-daemon | 9 --------- daemon/sbin/core-manage | 7 ------- daemon/sbin/coresendmsg | 7 ------- doc/conf.py.in | 4 ++-- gui/addons/ipsecservice.tcl | 5 ----- gui/annotations.tcl | 5 ----- gui/api.tcl | 8 -------- gui/canvas.tcl | 5 ----- gui/cfgparse.tcl | 5 ----- gui/core-gui.in | 5 ----- gui/core.tcl | 5 ----- gui/debug.tcl | 8 -------- gui/editor.tcl | 5 ----- gui/exceptions.tcl | 5 ----- gui/exec.tcl | 5 ----- gui/filemgmt.tcl | 5 ----- gui/gpgui.tcl | 5 ----- gui/graph_partitioning.tcl | 5 ----- gui/help.tcl | 7 +------ gui/initgui.tcl | 5 ----- gui/ipv4.tcl | 5 ----- gui/ipv6.tcl | 5 ----- gui/linkcfg.tcl | 5 ----- gui/mobility.tcl | 5 ----- gui/nodecfg.tcl | 5 ----- gui/nodes.tcl | 5 ----- gui/ns2imunes.tcl | 5 ----- gui/plugins.tcl | 5 ----- gui/services.tcl | 5 ----- gui/tooltips.tcl | 5 ----- gui/topogen.tcl | 5 ----- gui/traffic.tcl | 5 ----- gui/util.tcl | 5 ----- gui/version.tcl.in | 5 ----- gui/widget.tcl | 5 ----- gui/wlan.tcl | 5 ----- gui/wlanscript.tcl | 5 ----- 43 files changed, 7 insertions(+), 228 deletions(-) diff --git a/LICENSE b/LICENSE index 657c1a89..768b8d13 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2005-2017, the Boeing Company. +Copyright (c) 2005-2018, the Boeing Company. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index 1b295ecf..78ed828f 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ CORE CORE: Common Open Research Emulator -Copyright (c)2005-2017 the Boeing Company. +Copyright (c)2005-2018 the Boeing Company. See the LICENSE file included in this distribution. diff --git a/configure.ac b/configure.ac index 3881eef5..5d1719a9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,3 @@ -# -# Copyright (c) 2010-2013 the Boeing Company -# See the LICENSE file included in this distribution. -# -# CORE configure script -# -# author: Jeff Ahrenholz -# # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. diff --git a/daemon/doc/conf.py.in b/daemon/doc/conf.py.in index c9041fae..eee03477 100644 --- a/daemon/doc/conf.py.in +++ b/daemon/doc/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = u'CORE Python modules' -copyright = u'2017, core-dev' +copyright = u'2005-2018, core-dev' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -223,7 +223,7 @@ man_pages = [ epub_title = u'CORE Python' epub_author = u'core-dev' epub_publisher = u'core-dev' -epub_copyright = u'2017, core-dev' +epub_copyright = u'2005-2018, core-dev' # The language of the text. It defaults to the language option # or en if the language is not set. diff --git a/daemon/examples/emanemodel2core.py b/daemon/examples/emanemodel2core.py index dd0ffbea..bc48fda2 100755 --- a/daemon/examples/emanemodel2core.py +++ b/daemon/examples/emanemodel2core.py @@ -1,11 +1,4 @@ #!/usr/bin/env python -# -# CORE -# Copyright (c) 2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# ''' emanemodel2core.py: scans an EMANE model source file (e.g. emane/models/rfpipe/maclayer/rfpipemaclayer.cc) and outputs Python @@ -18,13 +11,6 @@ emanemodel2core.py: scans an EMANE model source file import os, sys, optparse MODEL_TEMPLATE_PART1 = """ -# -# CORE -# Copyright (c)2013 Company. -# See the LICENSE file included in this distribution. -# -# author: Name -# ''' xyz.py: EMANE XYZ model bindings for CORE ''' diff --git a/daemon/examples/myservices/sample.py b/daemon/examples/myservices/sample.py index 1beeebf7..bd4a05b3 100644 --- a/daemon/examples/myservices/sample.py +++ b/daemon/examples/myservices/sample.py @@ -1,8 +1,3 @@ -# -# CORE -# Copyright (c)2010-2012 the Boeing Company. -# See the LICENSE file included in this distribution. -# """ Sample user-defined service. """ diff --git a/daemon/sbin/core-daemon b/daemon/sbin/core-daemon index edee959b..495e193f 100755 --- a/daemon/sbin/core-daemon +++ b/daemon/sbin/core-daemon @@ -1,13 +1,4 @@ #!/usr/bin/env python -# -# CORE -# Copyright (c)2010-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# authors: Tom Goff -# Jeff Ahrenholz -# - """ core-daemon: the CORE daemon is a server process that receives CORE API messages and instantiates emulated nodes and networks within the kernel. Various diff --git a/daemon/sbin/core-manage b/daemon/sbin/core-manage index 82857fe5..87d23a24 100755 --- a/daemon/sbin/core-manage +++ b/daemon/sbin/core-manage @@ -1,11 +1,4 @@ #!/usr/bin/env python -# -# CORE -# Copyright (c)2014 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# """ core-manage: Helper tool to add, remove, or check for services, models, and node types in a CORE installation. diff --git a/daemon/sbin/coresendmsg b/daemon/sbin/coresendmsg index 43c07cfd..5470bfca 100755 --- a/daemon/sbin/coresendmsg +++ b/daemon/sbin/coresendmsg @@ -1,11 +1,4 @@ #!/usr/bin/env python -# -# CORE -# Copyright (c)2011-2012 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# authors: Jeff Ahrenholz -# """ coresendmsg: utility for generating CORE messages """ diff --git a/doc/conf.py.in b/doc/conf.py.in index 210c372f..3de261be 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -42,7 +42,7 @@ master_doc = 'index' # General information about the project. project = u'CORE' -copyright = u'2017, core-dev' +copyright = u'2005-2018, core-dev' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -223,7 +223,7 @@ man_pages = [ epub_title = u'CORE' epub_author = u'core-dev' epub_publisher = u'core-dev' -epub_copyright = u'2017, core-dev' +epub_copyright = u'2005-2018, core-dev' # The language of the text. It defaults to the language option # or en if the language is not set. diff --git a/gui/addons/ipsecservice.tcl b/gui/addons/ipsecservice.tcl index aea78b3e..c859852a 100644 --- a/gui/addons/ipsecservice.tcl +++ b/gui/addons/ipsecservice.tcl @@ -1,9 +1,4 @@ # -# Copyright 2012 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# # This is a separate "addons" file because it is closely tied to Python # service definition for the IPsec service. # diff --git a/gui/annotations.tcl b/gui/annotations.tcl index 8352a92d..8a2184d3 100644 --- a/gui/annotations.tcl +++ b/gui/annotations.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2007-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2007-2008 University of Zagreb, Croatia. # diff --git a/gui/api.tcl b/gui/api.tcl index 34658431..310e5ddc 100644 --- a/gui/api.tcl +++ b/gui/api.tcl @@ -1,11 +1,3 @@ -# -# CORE API -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# - # version of the API document that is used set CORE_API_VERSION 1.23 diff --git a/gui/canvas.tcl b/gui/canvas.tcl index bbcdfa24..11c8217b 100644 --- a/gui/canvas.tcl +++ b/gui/canvas.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2005-2008 University of Zagreb, Croatia. # diff --git a/gui/cfgparse.tcl b/gui/cfgparse.tcl index 6e730886..41f25594 100644 --- a/gui/cfgparse.tcl +++ b/gui/cfgparse.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2005-2008 University of Zagreb, Croatia. # diff --git a/gui/core-gui.in b/gui/core-gui.in index a93fd72b..efda3880 100755 --- a/gui/core-gui.in +++ b/gui/core-gui.in @@ -1,9 +1,4 @@ #!/bin/sh -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/core.tcl b/gui/core.tcl index 8ed9c90a..aad43fd4 100644 --- a/gui/core.tcl +++ b/gui/core.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/debug.tcl b/gui/debug.tcl index c1bd0ef1..60e45cbc 100644 --- a/gui/debug.tcl +++ b/gui/debug.tcl @@ -1,11 +1,3 @@ -# -# CORE Debugger -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# - .menubar.tools add command -label "Debugger..." -command popupDebugger set g_last_debug_cmd "puts \"Hello world\"" diff --git a/gui/editor.tcl b/gui/editor.tcl index 1195ee18..fec8a499 100644 --- a/gui/editor.tcl +++ b/gui/editor.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/exceptions.tcl b/gui/exceptions.tcl index 22f3be2f..40fbc6b5 100644 --- a/gui/exceptions.tcl +++ b/gui/exceptions.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2011-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - array set g_exceptions {} global execMode if { $execMode == "interactive" } { diff --git a/gui/exec.tcl b/gui/exec.tcl index 2105ac35..8e60f97b 100644 --- a/gui/exec.tcl +++ b/gui/exec.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/filemgmt.tcl b/gui/filemgmt.tcl index e76874a7..7dc1d795 100644 --- a/gui/filemgmt.tcl +++ b/gui/filemgmt.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2014 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/gpgui.tcl b/gui/gpgui.tcl index e507436a..b7188399 100644 --- a/gui/gpgui.tcl +++ b/gui/gpgui.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2007-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2007 Petra Schilhard. # diff --git a/gui/graph_partitioning.tcl b/gui/graph_partitioning.tcl index e21fe69f..87e215df 100644 --- a/gui/graph_partitioning.tcl +++ b/gui/graph_partitioning.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2007-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2007 Petra Schilhard. # diff --git a/gui/help.tcl b/gui/help.tcl index 9741b570..3d4c4ad9 100644 --- a/gui/help.tcl +++ b/gui/help.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # @@ -86,7 +81,7 @@ proc popupAbout {} { # version info label .about.text1 -text "CORE version $CORE_VERSION ($CORE_VERSION_DATE)" \ -foreground #500000 -padx 5 -pady 10 - label .about.text2 -text "Copyright (c)2005-2013\ + label .about.text2 -text "Copyright \ the Boeing Company. See the LICENSE file included in this\ distribution." pack .about.text1 -side top -anchor n -padx 4 -pady 4 diff --git a/gui/initgui.tcl b/gui/initgui.tcl index ed1a428b..c75acf5c 100644 --- a/gui/initgui.tcl +++ b/gui/initgui.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2014 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/ipv4.tcl b/gui/ipv4.tcl index f1f721d0..76901060 100644 --- a/gui/ipv4.tcl +++ b/gui/ipv4.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2005-2008 University of Zagreb, Croatia. # diff --git a/gui/ipv6.tcl b/gui/ipv6.tcl index 63596512..bb330a23 100644 --- a/gui/ipv6.tcl +++ b/gui/ipv6.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2005-2008 University of Zagreb, Croatia. # diff --git a/gui/linkcfg.tcl b/gui/linkcfg.tcl index adaa75bc..5c773097 100644 --- a/gui/linkcfg.tcl +++ b/gui/linkcfg.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/mobility.tcl b/gui/mobility.tcl index 67a0006c..7c0d46d6 100644 --- a/gui/mobility.tcl +++ b/gui/mobility.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # shows the Two-node Tool proc popupTwoNodeDialog { } { global twonodePID lastTwoNodeHop g_twoNodeSelect g_twoNodeSelectCallback diff --git a/gui/nodecfg.tcl b/gui/nodecfg.tcl index 0a974ebb..b979fdcb 100644 --- a/gui/nodecfg.tcl +++ b/gui/nodecfg.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/nodes.tcl b/gui/nodes.tcl index 1ddcbd6d..cabad158 100644 --- a/gui/nodes.tcl +++ b/gui/nodes.tcl @@ -1,9 +1,4 @@ # -# Copyright 2010-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# # GUI support for node types and profiles. # diff --git a/gui/ns2imunes.tcl b/gui/ns2imunes.tcl index 72cde399..1d5f1a04 100644 --- a/gui/ns2imunes.tcl +++ b/gui/ns2imunes.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2004-2008 University of Zagreb, Croatia. # diff --git a/gui/plugins.tcl b/gui/plugins.tcl index 04376c73..45ad77e1 100644 --- a/gui/plugins.tcl +++ b/gui/plugins.tcl @@ -1,9 +1,4 @@ # -# Copyright 2010-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# # Support for managing CORE plugins from the GUI. # diff --git a/gui/services.tcl b/gui/services.tcl index 2f559e50..305917a5 100644 --- a/gui/services.tcl +++ b/gui/services.tcl @@ -1,9 +1,4 @@ # -# Copyright 2010-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# author: Jeff Ahrenholz -# # GUI support for managing CORE node services. # diff --git a/gui/tooltips.tcl b/gui/tooltips.tcl index 6fbb74c8..91479d84 100644 --- a/gui/tooltips.tcl +++ b/gui/tooltips.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - array set left_tooltips { select "selection tool" start "start the session" diff --git a/gui/topogen.tcl b/gui/topogen.tcl index fd9bd829..2d7f84a6 100644 --- a/gui/topogen.tcl +++ b/gui/topogen.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2007-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2007-2008 University of Zagreb, Croatia. # diff --git a/gui/traffic.tcl b/gui/traffic.tcl index 44354560..41b8ac85 100644 --- a/gui/traffic.tcl +++ b/gui/traffic.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2011-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - set g_traffic_start_opt 0 set g_traffic_flows "" diff --git a/gui/util.tcl b/gui/util.tcl index 3052f73b..8078f447 100644 --- a/gui/util.tcl +++ b/gui/util.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2014 the Boeing Company. -# See the LICENSE file included in this distribution. -# - set g_imageFileTypes {{"images" {.gif}} {"images" {.jpg}} {"images" {.png}} {"images" {.bmp}} {"images" {.pcx}} {"images" {.tga}} {"images" {.tif}} {"images" {.ps}} {"images" {.ppm}} diff --git a/gui/version.tcl.in b/gui/version.tcl.in index 242a0e82..5a2f86be 100644 --- a/gui/version.tcl.in +++ b/gui/version.tcl.in @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # define the version number and release date here # diff --git a/gui/widget.tcl b/gui/widget.tcl index ec1d48e7..1a8f6b7a 100644 --- a/gui/widget.tcl +++ b/gui/widget.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - set vtysh_cmd vtysh set vtysh_search_path {/usr/bin /usr/local/bin /usr/lib/quagga} diff --git a/gui/wlan.tcl b/gui/wlan.tcl index 6136f326..4f103fe0 100644 --- a/gui/wlan.tcl +++ b/gui/wlan.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # Copyright 2005-2008 University of Zagreb, Croatia. # diff --git a/gui/wlanscript.tcl b/gui/wlanscript.tcl index 6b1788f1..f7bfba42 100644 --- a/gui/wlanscript.tcl +++ b/gui/wlanscript.tcl @@ -1,8 +1,3 @@ -# -# Copyright 2005-2013 the Boeing Company. -# See the LICENSE file included in this distribution. -# - # # run a scengen mobility script proc wlanRunMobilityScript { wlan } { From ac81c049ee488d8cc441b0da32e9d56eaa99f381 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 10:40:27 -0700 Subject: [PATCH 070/152] updated links in core gui, fixed broken user list, all updated to https --- gui/initgui.tcl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/initgui.tcl b/gui/initgui.tcl index c75acf5c..042120a0 100644 --- a/gui/initgui.tcl +++ b/gui/initgui.tcl @@ -595,11 +595,11 @@ menu .menubar.session -tearoff 1 # menu .menubar.help -tearoff 0 .menubar.help add command -label "Online manual (www)" -command \ - "_launchBrowser http://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/" + "_launchBrowser https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/" .menubar.help add command -label "CORE website (www)" -command \ - "_launchBrowser http://www.nrl.navy.mil/itd/ncs/products/core" + "_launchBrowser https://www.nrl.navy.mil/itd/ncs/products/core" .menubar.help add command -label "Mailing list (www)" -command \ - "_launchBrowser http://pf.itd.nrl.navy.mil/mailman/listinfo/core-users" + "_launchBrowser https://publists.nrl.navy.mil/mailman/listinfo/core-users" .menubar.help add command -label "About" -command popupAbout # From 09cf40618751edcd1a68125ab60447c0548c89d4 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 11:30:11 -0700 Subject: [PATCH 071/152] moved daemon/sbin to daemon/scripts --- README.md | 2 +- daemon/Makefile.am | 4 ++-- daemon/{sbin => scripts}/core-cleanup | 0 daemon/{sbin => scripts}/core-daemon | 0 daemon/{sbin => scripts}/core-manage | 0 daemon/{sbin => scripts}/coresendmsg | 0 daemon/setup.py | 9 +-------- 7 files changed, 4 insertions(+), 11 deletions(-) rename daemon/{sbin => scripts}/core-cleanup (100%) rename daemon/{sbin => scripts}/core-daemon (100%) rename daemon/{sbin => scripts}/core-manage (100%) rename daemon/{sbin => scripts}/coresendmsg (100%) diff --git a/README.md b/README.md index 78ed828f..d5a1cf82 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Here is what is installed with 'make install': /usr/local/bin/core-gui /usr/local/bin/core-daemon - /usr/local/bin/[vcmd, vnoded, coresendmsg, core-cleanup.sh] + /usr/local/bin/[vcmd, vnoded, coresendmsg, core-cleanup] /usr/local/lib/core/* /usr/local/share/core/* /usr/local/lib/python2.6/dist-packages/core/* diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 78611022..ee8dc238 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -14,7 +14,7 @@ if WANT_DOCS SUBDIRS = doc endif -SCRIPT_FILES := $(notdir $(wildcard sbin/*)) +SCRIPT_FILES := $(notdir $(wildcard scripts/*)) MAN_FILES := $(notdir $(wildcard ../doc/man/*.1)) LOGROTATE_DIR = $(DESTDIR)/$(sysconfdir)/logrotate.d @@ -72,7 +72,7 @@ EXTRA_DIST = $(SETUPPY) \ data \ doc/conf.py.in \ examples \ - sbin \ + scripts \ tests \ test.py \ setup.cfg \ diff --git a/daemon/sbin/core-cleanup b/daemon/scripts/core-cleanup similarity index 100% rename from daemon/sbin/core-cleanup rename to daemon/scripts/core-cleanup diff --git a/daemon/sbin/core-daemon b/daemon/scripts/core-daemon similarity index 100% rename from daemon/sbin/core-daemon rename to daemon/scripts/core-daemon diff --git a/daemon/sbin/core-manage b/daemon/scripts/core-manage similarity index 100% rename from daemon/sbin/core-manage rename to daemon/scripts/core-manage diff --git a/daemon/sbin/coresendmsg b/daemon/scripts/coresendmsg similarity index 100% rename from daemon/sbin/coresendmsg rename to daemon/scripts/coresendmsg diff --git a/daemon/setup.py b/daemon/setup.py index 2783af42..9a3cbefd 100644 --- a/daemon/setup.py +++ b/daemon/setup.py @@ -11,8 +11,6 @@ from distutils.core import setup _CORE_DIR = "/etc/core" _MAN_DIR = "share/man/man1" _EXAMPLES_DIR = "share/core" -_SYSV = "/etc/init.d" -_SYSTEMD = "/etc/systemd/system" def recursive_files(data_path, files_path): @@ -53,12 +51,7 @@ setup( "mock", ], data_files=data_files, - scripts=[ - "sbin/core-cleanup", - "sbin/core-daemon", - "sbin/core-manage", - "sbin/coresendmsg", - ], + scripts=glob.glob("scripts/*"), description="Python components of CORE", url="http://www.nrl.navy.mil/itd/ncs/products/core", author="Boeing Research & Technology", From 89b448f58090bae46f27a94a847858d6c463bfc2 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 11:55:01 -0700 Subject: [PATCH 072/152] added clean for new man pages generated --- doc/man/Makefile.am | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 8479faaa..f411548c 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -10,6 +10,7 @@ if WANT_GUI GUI_MANS = core-gui.1 endif + if WANT_DAEMON DAEMON_MANS = vnoded.1 vcmd.1 netns.1 core-daemon.1 coresendmsg.1 \ core-cleanup.1 core-manage.1 @@ -22,10 +23,10 @@ generate-mans: $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vnoded -o vnoded.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/vcmd -o vcmd.1.new $(HELP2MAN) --no-info --source CORE $(top_srcdir)/netns/netns -o netns.1.new - $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-daemon -o core-daemon.1.new - $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/coresendmsg -o coresendmsg.1.new - $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-cleanup -o core-cleanup.1.new - $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/sbin/core-manage -o core-manage.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-daemon -o core-daemon.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/coresendmsg -o coresendmsg.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-cleanup -o core-cleanup.1.new + $(HELP2MAN) --version-string=$(PACKAGE_VERSION) --no-info --source CORE $(top_srcdir)/daemon/scripts/core-manage -o core-manage.1.new .PHONY: diff diff: @@ -33,5 +34,9 @@ diff: colordiff -u $$m $$m.new | less -R; \ done; +clean-local: + -rm -f $(addsuffix .new,$(GUI_MANS)) + -rm -f $(addsuffix .new,$(DAEMON_MANS)) + DISTCLEANFILES = Makefile.in EXTRA_DIST = $(man_MANS) From 6d3470c95f2cfec641304d6565a232c70f2e99d9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 11:56:30 -0700 Subject: [PATCH 073/152] more corrections for daemon/scripts renaming --- doc/devguide.rst | 2 +- scripts/core-daemon-init.d-SUSE | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/devguide.rst b/doc/devguide.rst index bfb3aa37..296a89ac 100644 --- a/doc/devguide.rst +++ b/doc/devguide.rst @@ -33,7 +33,7 @@ These are being actively developed as of CORE |version|: * *gui* - Tcl/Tk GUI. This uses Tcl/Tk because of its roots with the IMUNES project. * *daemon* - Python modules are found in the :file:`daemon/core` directory, the - daemon under :file:`daemon/sbin/core-daemon` + daemon under :file:`daemon/scripts/core-daemon` * *netns* - Python extension modules for Linux Network Namespace support are in :file:`netns`. * *ns3* - Python ns3 script support for running CORE. * *doc* - Documentation for the manual lives here in reStructuredText format. diff --git a/scripts/core-daemon-init.d-SUSE b/scripts/core-daemon-init.d-SUSE index 9b6a4aea..b3a3d67a 100755 --- a/scripts/core-daemon-init.d-SUSE +++ b/scripts/core-daemon-init.d-SUSE @@ -117,7 +117,7 @@ # Check for missing binaries (stale symlinks should not happen) # Note: Special treatment of stop for LSB conformance -CORE_BIN=/usr/local/sbin/core-daemon +CORE_BIN=/usr/local/bin/core-daemon test -x $CORE_BIN || { echo "$CORE_BIN not installed"; if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; } From 188f9420caf21e16c8069a3636da79be64cfb6b2 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 15 Mar 2018 14:31:07 -0700 Subject: [PATCH 074/152] added a convenience target for generating all documentation based on existing google code example, fixed a few issues with doc strings --- Makefile.am | 24 ++++++++++++++++++++++++ configure.ac | 2 ++ daemon/core/corehandlers.py | 11 +---------- daemon/core/coreobj.py | 4 ++-- daemon/core/netns/vnode.py | 14 +++++++------- daemon/doc/Makefile.am | 2 +- doc/Makefile.am | 2 +- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/Makefile.am b/Makefile.am index 28043555..afb7615c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -168,3 +168,27 @@ change-files: $(call change-files,gui/core-gui) $(call change-files,scripts/core-daemon.service) $(call change-files,daemon/core/constants.py) + +CORE_DOC_HTML = core-html-$(PACKAGE_VERSION) +CORE_DOC_PDF = core-manual-$(PACKAGE_VERSION) +CORE_DOC_SRC = core-python-$(PACKAGE_VERSION) +.PHONY: doc +doc: doc-clean + $(MAKE) -C doc html + mv doc/_build/html doc/$(CORE_DOC_HTML) + tar -C doc -czf $(CORE_DOC_HTML).tgz $(CORE_DOC_HTML) + $(MAKE) -C doc latexpdf + mv doc/_build/latex/CORE.pdf $(CORE_DOC_PDF).pdf + $(MAKE) -C daemon/doc html + mv daemon/doc/_build/html daemon/doc/$(CORE_DOC_SRC) + tar -C daemon/doc -czf $(CORE_DOC_SRC).tgz $(CORE_DOC_SRC) + +.PHONY: doc-clean +doc-clean: + -rm -rf doc/_build + -rm -rf doc/$(CORE_DOC_HTML) + -rm -rf daemon/doc/_build + -rm -rf daemon/doc/$(CORE_DOC_SRC) + -rm -f $(CORE_DOC_HTML).tgz + -rm -f $(CORE_DOC_SRC).tgz + -rm -f $(CORE_DOC_PDF).pdf diff --git a/configure.ac b/configure.ac index 5d1719a9..5ad58c50 100644 --- a/configure.ac +++ b/configure.ac @@ -245,6 +245,8 @@ Daemon: Python modules: ${pythondir} Logs: ${CORE_STATE_DIR}/log +Startup: ${with_startup} + Features to build: Build GUI: ${enable_gui} Build Daemon: ${enable_daemon} diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 73c308e5..af481573 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -42,16 +42,7 @@ from core.xml.xmlsession import save_session_xml class CoreRequestHandler(SocketServer.BaseRequestHandler): """ - The SocketServer class uses the RequestHandler class for servicing - requests, mainly through the handle() method. The CoreRequestHandler - has the following basic flow: - 1. Client connects and request comes in via handle(). - 2. handle() calls recvmsg() in a loop. - 3. recvmsg() does a recv() call on the socket performs basic - checks that this we received a CoreMessage, returning it. - 4. The message data is queued using queuemsg(). - 5. The handlerthread() thread pops messages from the queue and uses - handlemsg() to invoke the appropriate handler for that message type. + The SocketServer class uses the RequestHandler class for servicing requests. """ def __init__(self, request, client_address, server): diff --git a/daemon/core/coreobj.py b/daemon/core/coreobj.py index e9fe024e..742f0e89 100644 --- a/daemon/core/coreobj.py +++ b/daemon/core/coreobj.py @@ -655,8 +655,8 @@ class PyCoreNetIf(object): """ Attach network. - :param core.coreobj.PyCoreNet net: network to attach to - :return:nothing + :param core.coreobj.PyCoreNet net: network to attach + :return: nothing """ if self.net: self.detachnet() diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index e11c75d3..63046501 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -30,13 +30,13 @@ class SimpleLxcNode(PyCoreNode): """ Provides simple lxc functionality for core nodes. - :type nodedir: str - :type ctrlchnlname: str - :type client: core.netns.vnodeclient.VnodeClient - :type pid: int - :type up: bool - :type lock: threading.RLock - :type _mounts: list[tuple[str, str]] + :var nodedir: str + :var ctrlchnlname: str + :var client: core.netns.vnodeclient.VnodeClient + :var pid: int + :var up: bool + :var lock: threading.RLock + :var _mounts: list[tuple[str, str]] """ valid_address_types = {"inet", "inet6", "inet6link"} diff --git a/daemon/doc/Makefile.am b/daemon/doc/Makefile.am index dd2d0bb8..6f287b09 100644 --- a/daemon/doc/Makefile.am +++ b/daemon/doc/Makefile.am @@ -23,7 +23,7 @@ index.rst: # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -q SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build diff --git a/doc/Makefile.am b/doc/Makefile.am index 781977a0..e3d66238 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -26,7 +26,7 @@ EXTRA_DIST = $(rst_files) # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -q SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build From cd7fd43978070bb9740da719a7a96a6e7c6cc0ea Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 09:33:43 -0700 Subject: [PATCH 075/152] updates to support emane 1.2.1 --- daemon/core/emane/emanemanager.py | 20 ++++++++++---------- daemon/core/emane/nodes.py | 13 ++++++------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 4777e050..0af6e477 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -29,21 +29,21 @@ from core.misc import utils from core.misc.ipaddress import MacAddress from core.xml import xmlutils -_PATH = os.path.abspath(os.path.dirname(__file__)) +try: + from emane.events import EventService + from emane.events import LocationEvent +except ImportError: + try: + from emanesh.events import EventService + from emanesh.events import LocationEvent + except ImportError: + logger.info("emane 0.9.1+ not found") -# EMANE 0.7.4/0.8.1 try: import emaneeventservice import emaneeventlocation except ImportError: - logger.error("error importing emaneeventservice and emaneeventlocation") - -# EMANE 0.9.1+ -try: - from emanesh.events import EventService - from emanesh.events import LocationEvent -except ImportError: - logger.error("error importing emanesh") + logger.info("emane < 0.9.1 not found") EMANE_MODELS = [ EmaneRfPipeModel, diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index 55c74bce..f0e5bf57 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -14,19 +14,18 @@ from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs try: - from emanesh.events import LocationEvent + from emane.events import LocationEvent except ImportError: - logger.error("error loading emanesh") + try: + from emanesh.events import LocationEvent + except ImportError: + logger.info("emane 0.9.1+ not found") try: import emaneeventservice import emaneeventlocation except ImportError: - """ - Don't require all CORE users to have EMANE libeventservice and its - Python bindings installed. - """ - logger.error("error loading emaneeventservice and emaneeventlocation") + logger.info("emane < 0.9.1 not found") class EmaneNet(PyCoreNet): From e0bbeaf79cf16b716c01b3c34a00e619cf3a6056 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 09:39:44 -0700 Subject: [PATCH 076/152] update to logging in relation to core --- daemon/core/emane/commeffect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index f99bda78..a93adff3 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -11,7 +11,7 @@ try: import emaneeventservice import emaneeventcommeffect except ImportError: - logger.error("error importing emaneeventservice and emaneeventcommeffect") + logger.info("emane < 0.9.1 not found") class EmaneCommEffectModel(EmaneModel): From 4e5ee1b3ee398bc5790462f83e51b466b217becc Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 11:26:44 -0700 Subject: [PATCH 077/152] removed aux server/handler code --- daemon/core/corehandlers.py | 118 +----------------------------------- daemon/core/coreserver.py | 18 +----- daemon/core/session.py | 2 +- 3 files changed, 5 insertions(+), 133 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index af481573..c2396386 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -450,8 +450,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): logger.exception("%s: exception while handling message: %s", threading.currentThread().getName(), message) - # Added to allow the auxiliary handlers to define a different behavior when replying - # to messages from clients def dispatch_replies(self, replies, message): """ Dispatch replies by CORE to message msg previously received from the client. @@ -1125,9 +1123,9 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if execute_server: try: logger.info("executing: %s", execute_server) - # TODO: remove this, unless we want to support udp/aux at any level - if not isinstance(self.server, CoreServer): # CoreUdpServer): + if not isinstance(self.server, CoreServer): server = self.server.mainserver + # assumed to be udp server else: server = self.server if message.flags & MessageFlags.STRING.value: @@ -1615,6 +1613,7 @@ class CoreDatagramRequestHandler(CoreRequestHandler): header = data[:coreapi.CoreMessage.header_len] if len(header) < coreapi.CoreMessage.header_len: raise IOError("error receiving header (received %d bytes)" % len(header)) + message_type, message_flags, message_len = coreapi.CoreMessage.unpack_header(header) if message_len == 0: logger.warn("received message with no data") @@ -1638,7 +1637,6 @@ class CoreDatagramRequestHandler(CoreRequestHandler): session_ids = message.session_numbers() message.queuedtimes = 0 - # logger.info("UDP message has session numbers: %s" % sids) if len(session_ids) > 0: for session_id in session_ids: @@ -1675,113 +1673,3 @@ class CoreDatagramRequestHandler(CoreRequestHandler): :return: nothing """ self.request[1].sendto(data, self.client_address) - - -class BaseAuxRequestHandler(CoreRequestHandler): - """ - This is the superclass for auxiliary handlers in CORE. A concrete auxiliary handler class - must, at a minimum, define the recvmsg(), sendall(), and dispatchreplies() methods. - See SockerServer.BaseRequestHandler for parameter details. - """ - - def __init__(self, request, client_address, server): - """ - Create a BaseAuxRequestHandler instance. - - :param request: request client - :param str client_address: client address - :param CoreServer server: core server instance - """ - self.message_handlers = { - MessageTypes.NODE.value: self.handle_node_message, - MessageTypes.LINK.value: self.handle_link_message, - MessageTypes.EXECUTE.value: self.handle_execute_message, - MessageTypes.REGISTER.value: self.handle_register_message, - MessageTypes.CONFIG.value: self.handle_config_message, - MessageTypes.FILE.value: self.handle_file_message, - MessageTypes.INTERFACE.value: self.handle_interface_message, - MessageTypes.EVENT.value: self.handle_event_message, - MessageTypes.SESSION.value: self.handle_session_message, - } - self.handler_threads = [] - self.node_status_request = {} - self.master = False - self.session = None - SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) - - def setup(self): - """ - New client has connected to the auxiliary server. - - :return: nothing - """ - logger.info("new auxiliary server client: %s:%s" % self.client_address) - - def handle(self): - """ - The handler main loop - - :return: nothing - """ - port = self.request.getpeername()[1] - self.session = self.server.mainserver.create_session(session_id=port) - self.session.connect(self) - - while True: - try: - messages = self.receive_message() - if messages: - for message in messages: - self.handle_message(message) - except EOFError: - break - except IOError: - logger.exception("IOError in CoreAuxRequestHandler") - break - - def finish(self): - """ - Disconnect the client - - :return: nothing - """ - if self.session: - self.remove_session_handlers() - self.session.shutdown() - return SocketServer.BaseRequestHandler.finish(self) - - def receive_message(self): - """ - Receive data from the client in the supported format. Parse, transform to CORE API format and - return transformed messages. - - EXAMPLE: - return self.handler.request.recv(siz) - - :return: nothing - """ - raise NotImplemented - - def dispatch_replies(self, replies, message): - """ - Dispatch CORE replies to a previously received message msg from a client. - Replies passed to this method follow the CORE API. This method allows transformation to - the form supported by the auxiliary handler and within the context of "msg". - Add transformation and transmission code here. - - :param list replies: replies to dispatch - :param message: message being replied to - :return: nothing - """ - raise NotImplemented - - def sendall(self, data): - """ - CORE calls this method when data needs to be asynchronously sent to a client. The data is - in CORE API format. This method allows transformation to the required format supported by this - handler prior to transmission. - - :param data: data to send - :return: nothing - """ - raise NotImplemented diff --git a/daemon/core/coreserver.py b/daemon/core/coreserver.py index 058d4a0e..4ebe3284 100644 --- a/daemon/core/coreserver.py +++ b/daemon/core/coreserver.py @@ -1,6 +1,5 @@ """ -Defines server classes and request handlers for TCP and UDP. Also defined here is a TCP based -auxiliary server class for supporting externally defined handlers. +Defines server classes and request handlers for TCP and UDP. """ import SocketServer @@ -272,21 +271,6 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): for session_id in self.sessions: logger.info(session_id) - # def set_session_master(self, handler): - # """ - # Call the setmaster() method for every session. Returns True when - # a session having the given handler was updated. - # """ - # found = False - # - # with self._sessions_lock: - # for session_id in self.sessions: - # found = self.sessions[session_id].set_master(handler) - # if found is True: - # break - # - # return found - class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): """ diff --git a/daemon/core/session.py b/daemon/core/session.py index 192e558c..d87d201e 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -132,7 +132,6 @@ class Session(object): self.file_name = None self.thumbnail = None self.user = None - self._state_time = time.time() self.event_loop = EventLoop() # dict of objects: all nodes and nets @@ -145,6 +144,7 @@ class Session(object): # TODO: should the default state be definition? self.state = EventTypes.NONE.value + self._state_time = time.time() self._state_file = os.path.join(self.session_dir, "state") self._hooks = {} From 02bcdf617d7dbf7c566485612ba0c69f7950a100 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 11:46:05 -0700 Subject: [PATCH 078/152] attempt to correct udp handler --- daemon/core/corehandlers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index c2396386..61fdcb68 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -1643,7 +1643,6 @@ class CoreDatagramRequestHandler(CoreRequestHandler): session = self.server.mainserver.get_session(session_id=session_id) if session: self.session = session - session.broadcast(self, message) self.handle_message(message) else: logger.warn("Session %d in %s message not found." % (session_id, message.type_str())) @@ -1652,8 +1651,6 @@ class CoreDatagramRequestHandler(CoreRequestHandler): session = self.server.mainserver.get_session() if session or message.message_type == MessageTypes.REGISTER.value: self.session = session - if session: - session.broadcast(self, message) self.handle_message(message) else: logger.warn("No active session, dropping %s message.", message.type_str()) From 76524abbc26bc07a91c20ff5e19473b0e183e25a Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 12:13:30 -0700 Subject: [PATCH 079/152] adjustment for getting session from udp client --- daemon/core/corehandlers.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 61fdcb68..01102b4f 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -1123,9 +1123,9 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if execute_server: try: logger.info("executing: %s", execute_server) + # assumed to be udp server if not isinstance(self.server, CoreServer): server = self.server.mainserver - # assumed to be udp server else: server = self.server if message.flags & MessageFlags.STRING.value: @@ -1469,8 +1469,13 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): i += 1 else: if message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: + # assumed to be udp server + if not isinstance(self.server, CoreServer): + server = self.server.mainserver + else: + server = self.server # status request flag: send list of sessions - return self.server.to_session_message(), + return server.to_session_message(), # handle ADD or DEL flags for session_id in session_ids: From 7260f823cb5b238d2ba5c2d47d7168f2916a2300 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 12:18:15 -0700 Subject: [PATCH 080/152] updates for dispatching replies from udp handler --- daemon/core/corehandlers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 01102b4f..ff20febb 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -458,7 +458,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): :param message: message for replies :return: nothing """ - logger.info("replies to dispatch: %s", replies) + logger.info("dispatching replies") for reply in replies: message_type, message_flags, message_length = coreapi.CoreMessage.unpack_header(reply) try: @@ -472,12 +472,12 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): reply_message = "CoreMessage (type %d flags %d length %d)" % ( message_type, message_flags, message_length) - logger.info("reply to %s: \n%s", self.request.getpeername(), reply_message) + logger.info("dispatch reply:\n%s", reply_message) try: self.sendall(reply) except IOError: - logger.exception("Error sending reply data") + logger.exception("error dispatching reply") def handle(self): """ From 4540b979395922e97cb72a82b9c90f10746f1a72 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 12:22:19 -0700 Subject: [PATCH 081/152] removed commented out lines in configure.ac --- configure.ac | 3 --- 1 file changed, 3 deletions(-) diff --git a/configure.ac b/configure.ac index 5ad58c50..7cd95b33 100644 --- a/configure.ac +++ b/configure.ac @@ -203,9 +203,6 @@ else fi # Output files -#gui/core-gui -#scripts/core-daemon.service -#daemon/core/constants.py AC_CONFIG_FILES([Makefile gui/version.tcl gui/Makefile From ee5bbdd94966906eebbcab1d63110e55dc1baaae Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 12:39:23 -0700 Subject: [PATCH 082/152] convenience method created for dealing with udp server cases --- daemon/core/corehandlers.py | 38 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index ff20febb..7ed3efd5 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -14,7 +14,7 @@ import time from core import coreobj from core import logger from core.api import coreapi -from core.coreserver import CoreServer +from core.coreserver import CoreServer, CoreUdpServer from core.data import ConfigData from core.data import EventData from core.data import NodeData @@ -87,6 +87,17 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): utils.close_onexec(request.fileno()) SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) + def _get_server(self): + """ + Retrieve server to interface with, in cases where the server is a UDP instance. + + :return: core.coreserver.CoreServer + """ + server = self.server + if isinstance(server, CoreUdpServer): + server = self.server.mainserver + return server + def setup(self): """ Client has connected, set up a new connection. @@ -94,7 +105,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): :return: nothing """ logger.info("new TCP connection: %s", self.client_address) - # self.register() def finish(self): """ @@ -1118,16 +1128,13 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): """ replies = [] + server = self._get_server() + # execute a Python script or XML file execute_server = message.get_tlv(RegisterTlvs.EXECUTE_SERVER.value) if execute_server: try: logger.info("executing: %s", execute_server) - # assumed to be udp server - if not isinstance(self.server, CoreServer): - server = self.server.mainserver - else: - server = self.server if message.flags & MessageFlags.STRING.value: old_session_ids = set(server.get_session_ids()) sys.argv = shlex.split(execute_server) @@ -1159,7 +1166,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): logger.info("executed %s with unknown session ID", execute_server) return replies logger.info("checking session %d for RUNTIME state" % sid) - session = self.server.get_session(session_id=sid) + session = server.get_session(session_id=sid) retries = 10 # wait for session to enter RUNTIME state, to prevent GUI from # connecting while nodes are still being instantiated @@ -1193,14 +1200,14 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # TODO: need to replicate functionality? # self.server.set_session_master(self) # find the session containing this client and set the session to master - for session in self.server.sessions.itervalues(): + for session in server.sessions.itervalues(): if self in session.broker.session_clients: logger.info("setting session to master: %s", session.session_id) session.master = True break replies.append(self.register()) - replies.append(self.server.to_session_message()) + replies.append(server.to_session_message()) return replies @@ -1439,6 +1446,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): node_counts = coreapi.str_to_list(node_count_str) logger.info("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) + server = self._get_server() + if message.flags == 0: # modify a session i = 0 @@ -1447,7 +1456,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if session_id == 0: session = self.session else: - session = self.server.get_session(session_id=session_id) + session = server.get_session(session_id=session_id) if session is None: logger.info("session %s not found", session_id) @@ -1469,18 +1478,13 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): i += 1 else: if message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: - # assumed to be udp server - if not isinstance(self.server, CoreServer): - server = self.server.mainserver - else: - server = self.server # status request flag: send list of sessions return server.to_session_message(), # handle ADD or DEL flags for session_id in session_ids: session_id = int(session_id) - session = self.server.get_session(session_id=session_id) + session = server.get_session(session_id=session_id) if session is None: logger.info("session %s not found (flags=0x%x)", session_id, message.flags) From 34ce98213d404500467a1480b17462351437de73 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 13:00:03 -0700 Subject: [PATCH 083/152] removed udp server due to the hackiness of its interactions with trying to re-use tcp code --- daemon/core/corehandlers.py | 168 +++--------------------------------- daemon/core/coreserver.py | 29 ------- daemon/scripts/core-daemon | 26 +----- 3 files changed, 14 insertions(+), 209 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 7ed3efd5..387b40f6 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -14,7 +14,7 @@ import time from core import coreobj from core import logger from core.api import coreapi -from core.coreserver import CoreServer, CoreUdpServer +from core.coreserver import CoreServer from core.data import ConfigData from core.data import EventData from core.data import NodeData @@ -87,17 +87,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): utils.close_onexec(request.fileno()) SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) - def _get_server(self): - """ - Retrieve server to interface with, in cases where the server is a UDP instance. - - :return: core.coreserver.CoreServer - """ - server = self.server - if isinstance(server, CoreUdpServer): - server = self.server.mainserver - return server - def setup(self): """ Client has connected, set up a new connection. @@ -1128,36 +1117,34 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): """ replies = [] - server = self._get_server() - # execute a Python script or XML file execute_server = message.get_tlv(RegisterTlvs.EXECUTE_SERVER.value) if execute_server: try: logger.info("executing: %s", execute_server) if message.flags & MessageFlags.STRING.value: - old_session_ids = set(server.get_session_ids()) + old_session_ids = set(self.server.get_session_ids()) sys.argv = shlex.split(execute_server) file_name = sys.argv[0] if os.path.splitext(file_name)[1].lower() == ".xml": - session = server.create_session() + session = self.server.create_session() try: open_session_xml(session, file_name, start=True) except: session.shutdown() - server.remove_session(session) + self.server.remove_session(session) raise else: thread = threading.Thread( target=execfile, - args=(file_name, {"__file__": file_name, "server": server}) + args=(file_name, {"__file__": file_name, "server": self.server}) ) thread.daemon = True thread.start() # allow time for session creation time.sleep(0.25) if message.flags & MessageFlags.STRING.value: - new_session_ids = set(server.get_session_ids()) + new_session_ids = set(self.server.get_session_ids()) new_sid = new_session_ids.difference(old_session_ids) try: sid = new_sid.pop() @@ -1166,7 +1153,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): logger.info("executed %s with unknown session ID", execute_server) return replies logger.info("checking session %d for RUNTIME state" % sid) - session = server.get_session(session_id=sid) + session = self.server.get_session(session_id=sid) retries = 10 # wait for session to enter RUNTIME state, to prevent GUI from # connecting while nodes are still being instantiated @@ -1200,14 +1187,14 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # TODO: need to replicate functionality? # self.server.set_session_master(self) # find the session containing this client and set the session to master - for session in server.sessions.itervalues(): + for session in self.server.sessions.itervalues(): if self in session.broker.session_clients: logger.info("setting session to master: %s", session.session_id) session.master = True break replies.append(self.register()) - replies.append(server.to_session_message()) + replies.append(self.server.to_session_message()) return replies @@ -1446,8 +1433,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): node_counts = coreapi.str_to_list(node_count_str) logger.info("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) - server = self._get_server() - if message.flags == 0: # modify a session i = 0 @@ -1456,7 +1441,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): if session_id == 0: session = self.session else: - session = server.get_session(session_id=session_id) + session = self.server.get_session(session_id=session_id) if session is None: logger.info("session %s not found", session_id) @@ -1470,7 +1455,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): session.file_name = files[i] if node_counts is not None: pass - # session.node_count = ncs[i] if thumb is not None: session.set_thumbnail(thumb) if user is not None: @@ -1479,12 +1463,12 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): else: if message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: # status request flag: send list of sessions - return server.to_session_message(), + return self.server.to_session_message(), # handle ADD or DEL flags for session_id in session_ids: session_id = int(session_id) - session = server.get_session(session_id=session_id) + session = self.server.get_session(session_id=session_id) if session is None: logger.info("session %s not found (flags=0x%x)", session_id, message.flags) @@ -1551,131 +1535,3 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): logger.exception("error sending node emulation id message: %s", node_id) del self.node_status_request[node_id] - - -class CoreDatagramRequestHandler(CoreRequestHandler): - """ - A child of the CoreRequestHandler class for handling connectionless - UDP messages. No new session is created; messages are handled immediately or - sometimes queued on existing session handlers. - """ - - def __init__(self, request, client_address, server): - """ - Create a CoreDatagramRequestHandler instance. - - :param request: request object - :param str client_address: client address - :param CoreServer server: core server instance - """ - # TODO: decide which messages cannot be handled with connectionless UDP - self.message_handlers = { - MessageTypes.NODE.value: self.handle_node_message, - MessageTypes.LINK.value: self.handle_link_message, - MessageTypes.EXECUTE.value: self.handle_execute_message, - MessageTypes.REGISTER.value: self.handle_register_message, - MessageTypes.CONFIG.value: self.handle_config_message, - MessageTypes.FILE.value: self.handle_file_message, - MessageTypes.INTERFACE.value: self.handle_interface_message, - MessageTypes.EVENT.value: self.handle_event_message, - MessageTypes.SESSION.value: self.handle_session_message, - } - self.node_status_request = {} - self.master = False - self.session = None - SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) - - def setup(self): - """ - Client has connected, set up a new connection. - - :return: nothing - """ - logger.info("new UDP connection: %s:%s" % self.client_address) - - def handle(self): - """ - Receive a message. - - :return: nothing - """ - self.receive_message() - - def finish(self): - """ - Handle the finish state of a client. - - :return: nothing - """ - return SocketServer.BaseRequestHandler.finish(self) - - def receive_message(self): - """ - Receive data, parse a CoreMessage and queue it onto an existing - session handler"s queue, if available. - - :return: nothing - """ - data = self.request[0] - sock = self.request[1] - - header = data[:coreapi.CoreMessage.header_len] - if len(header) < coreapi.CoreMessage.header_len: - raise IOError("error receiving header (received %d bytes)" % len(header)) - - message_type, message_flags, message_len = coreapi.CoreMessage.unpack_header(header) - if message_len == 0: - logger.warn("received message with no data") - return - - if len(data) != coreapi.CoreMessage.header_len + message_len: - logger.warn("received message length does not match received data (%s != %s)", - len(data), coreapi.CoreMessage.header_len + message_len) - raise IOError - else: - logger.info("UDP socket received message type=%d len=%d", message_type, message_len) - - try: - message_class = coreapi.CLASS_MAP[message_type] - message = message_class(message_flags, header, data[coreapi.CoreMessage.header_len:]) - except KeyError: - message = coreapi.CoreMessage(message_flags, header, data[coreapi.CoreMessage.header_len:]) - message.message_type = message_type - logger.warn("unimplemented core message type: %s" % message.type_str()) - return - - session_ids = message.session_numbers() - message.queuedtimes = 0 - - if len(session_ids) > 0: - for session_id in session_ids: - session = self.server.mainserver.get_session(session_id=session_id) - if session: - self.session = session - self.handle_message(message) - else: - logger.warn("Session %d in %s message not found." % (session_id, message.type_str())) - else: - # no session specified, find an existing one - session = self.server.mainserver.get_session() - if session or message.message_type == MessageTypes.REGISTER.value: - self.session = session - self.handle_message(message) - else: - logger.warn("No active session, dropping %s message.", message.type_str()) - - def queue_message(self, message): - """ - UDP handlers are short-lived and do not have message queues. - - :return: nothing - """ - raise Exception("Unable to queue %s message for later processing using UDP!" % message.type_str()) - - def sendall(self, data): - """ - Use sendto() on the connectionless UDP socket. - - :return: nothing - """ - self.request[1].sendto(data, self.client_address) diff --git a/daemon/core/coreserver.py b/daemon/core/coreserver.py index 4ebe3284..19aeb80c 100644 --- a/daemon/core/coreserver.py +++ b/daemon/core/coreserver.py @@ -270,32 +270,3 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): with self._sessions_lock: for session_id in self.sessions: logger.info(session_id) - - -class CoreUdpServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer): - """ - UDP server class, manages sessions and spawns request handlers for - incoming connections. - """ - daemon_threads = True - allow_reuse_address = True - - def __init__(self, server_address, handler_class, main_server): - """ - Server class initialization takes configuration data and calls - the SocketServer constructor - - :param tuple[str, int] server_address: server address - :param class handler_class: class for handling requests - :param main_server: main server to associate with - """ - self.mainserver = main_server - SocketServer.UDPServer.__init__(self, server_address, handler_class) - - def start(self): - """ - Thread target to run concurrently with the TCP server. - - :return: nothing - """ - self.serve_forever() diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 495e193f..07b97a88 100755 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -12,7 +12,6 @@ import os import signal import socket import sys -import threading import time from core import constants @@ -22,7 +21,6 @@ from core import enumerations from core import logger from core import services from core.api import coreapi -from core.corehandlers import CoreDatagramRequestHandler from core.enumerations import MessageFlags from core.enumerations import RegisterTlvs from core.misc import nodeutils @@ -33,29 +31,13 @@ from core.service import ServiceManager DEFAULT_MAXFD = 1024 -def startudp(core_server, server_address): - """ - Start a thread running a UDP server on the same host,port for connectionless requests. - - :param core.coreserver.CoreServer core_server: core server instance - :param tuple[str, int] server_address: server address - :return: created core udp server - :rtype: core.coreserver.CoreUdpServer - """ - core_server.udpserver = coreserver.CoreUdpServer(server_address, CoreDatagramRequestHandler, core_server) - core_server.udpthread = threading.Thread(target=core_server.udpserver.start) - core_server.udpthread.daemon = True - core_server.udpthread.start() - return core_server.udpserver - - def banner(): """ Output the program banner printed to the terminal or log file. :return: nothing """ - logger.info("CORE daemon v.%s started %s\n" % (constants.COREDPY_VERSION, time.ctime())) + logger.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime()) def cored(cfg=None): @@ -76,11 +58,7 @@ def cored(cfg=None): sys.exit(1) close_onexec(server.fileno()) - logger.info("main server started, listening on: %s:%s\n" % (host, port)) - - udpserver = startudp(server, (host, port)) - close_onexec(udpserver.fileno()) - + logger.info("main server started, listening on: %s:%s", host, port) server.serve_forever() From 0e38304b18c6bf5331be8e036bc8e5404d07c2a7 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 13:01:05 -0700 Subject: [PATCH 084/152] updated tcp handler to not timeout and block waiting for messages --- daemon/core/corehandlers.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index 7ed3efd5..3b39b16e 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -426,11 +426,8 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): :return: nothing """ while not self.done: - try: - message = self.message_queue.get(timeout=5) - self.handle_message(message) - except Queue.Empty: - logger.debug("timeout getting message") + message = self.message_queue.get() + self.handle_message(message) def handle_message(self, message): """ From bc1ef88f824c6de97b207be23430e4787a5761ca Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 16 Mar 2018 13:10:34 -0700 Subject: [PATCH 085/152] small fix to coresendmsg and client disconnects no longer log as an exception --- daemon/core/corehandlers.py | 5 ++++- daemon/scripts/coresendmsg | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index cb571f2c..c9d8f7ed 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -506,7 +506,10 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): while True: try: message = self.receive_message() - except (IOError, EOFError): + except EOFError: + logger.info("client disconnected") + break + except IOError: logger.exception("error receiving message") break diff --git a/daemon/scripts/coresendmsg b/daemon/scripts/coresendmsg index 5470bfca..2f8e3495 100755 --- a/daemon/scripts/coresendmsg +++ b/daemon/scripts/coresendmsg @@ -98,7 +98,7 @@ def connect_to_session(sock, requested): connect to the first one. """ # request the session list - tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, "0") + tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, "") flags = MessageFlags.STRING.value smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata) sock.sendall(smsg) @@ -130,9 +130,9 @@ def connect_to_session(sock, requested): print "requested session not found!" return False - print "joining session %s..." % session - tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER, session) - flags = MessageFlags.ADD + print "joining session: %s" % session + tlvdata = coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session) + flags = MessageFlags.ADD.value smsg = coreapi.CoreSessionMessage.pack(flags, tlvdata) sock.sendall(smsg) return True From 21425861129c7bd0fd24df89110060741e63c4e6 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 19 Mar 2018 16:33:36 -0700 Subject: [PATCH 086/152] initial pass to remove support for legacy emane code and focus on newer releases --- daemon/core/emane/__init__.py | 49 -- daemon/core/emane/bypass.py | 6 +- daemon/core/emane/commeffect.py | 86 ++- daemon/core/emane/emanemanager.py | 743 +++++++++--------------- daemon/core/emane/emanemodel.py | 34 +- daemon/core/emane/ieee80211abg.py | 90 ++- daemon/core/emane/nodes.py | 91 +-- daemon/core/emane/rfpipe.py | 74 +-- daemon/core/emane/tdma.py | 52 +- daemon/core/emane/universal.py | 78 +-- daemon/core/xml/xmldeployment.py | 21 +- daemon/examples/netns/wlanemanetests.py | 7 +- 12 files changed, 451 insertions(+), 880 deletions(-) diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 5446bf88..e69de29b 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -1,49 +0,0 @@ -from core import CoreCommandError -from core import logger -from core.misc import utils - -EMANEUNK = 0 -EMANE074 = 7 -EMANE081 = 8 -EMANE091 = 91 -EMANE092 = 92 -EMANE093 = 93 -EMANE101 = 101 - -VERSION = None -VERSIONSTR = None - - -def emane_version(): - """ - Return the locally installed EMANE version identifier and string. - """ - global VERSION - global VERSIONSTR - args = ["emane", "--version"] - - VERSION = EMANEUNK - - try: - output = utils.check_cmd(args) - if output.startswith("0.7.4"): - VERSION = EMANE074 - elif output.startswith("0.8.1"): - VERSION = EMANE081 - elif output.startswith("0.9.1"): - VERSION = EMANE091 - elif output.startswith("0.9.2"): - VERSION = EMANE092 - elif output.startswith("0.9.3"): - VERSION = EMANE093 - elif output.startswith("1.0.1"): - VERSION = EMANE101 - except CoreCommandError: - logger.exception("error checking emane version") - output = "" - - VERSIONSTR = output.strip() - - -# set version variables for the Emane class -emane_version() diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index e42452ab..8fad0c16 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -7,9 +7,6 @@ from core.enumerations import ConfigDataTypes class EmaneBypassModel(EmaneModel): - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - name = "emane_bypass" config_matrix = [ ("none", ConfigDataTypes.BOOL.value, "0", @@ -19,6 +16,9 @@ class EmaneBypassModel(EmaneModel): # value groupings config_groups = "Bypass Parameters:1-1" + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index a93adff3..5ec67801 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -2,22 +2,32 @@ commeffect.py: EMANE CommEffect model for CORE """ -from core import emane from core import logger from core.emane.emanemodel import EmaneModel from core.enumerations import ConfigDataTypes try: - import emaneeventservice - import emaneeventcommeffect + from emanesh.events.commeffectevent import CommEffectEvent except ImportError: - logger.info("emane < 0.9.1 not found") + try: + from emane.events.commeffectevent import CommEffectEvent + except ImportError: + logger.info("emane 0.9.1+ not found") + + +def convert_none(x): + """ + Helper to use 0 for None values. + """ + if type(x) is str: + x = float(x) + if x is None: + return 0 + else: + return int(x) class EmaneCommEffectModel(EmaneModel): - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - # model name name = "emane_commeffect" # CommEffect parameters @@ -31,25 +41,19 @@ class EmaneCommEffectModel(EmaneModel): ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"), ] - _confmatrix_shim_081 = [ - ("defaultconnectivity", ConfigDataTypes.BOOL.value, "0", - "On,Off", "defaultconnectivity"), - ("enabletighttimingmode", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable tight timing mode"), - ] _confmatrix_shim_091 = [ ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "0", "On,Off", "defaultconnectivity"), ] - if emane.VERSION >= emane.EMANE091: - _confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_091 - else: - _confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_081 + _confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_091 config_matrix = _confmatrix_shim # value groupings config_groups = "CommEffect SHIM Parameters:1-%d" % len(_confmatrix_shim) + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem and commeffect XMLs in the given path. @@ -85,45 +89,35 @@ class EmaneCommEffectModel(EmaneModel): nem.appendChild(e.xmlshimdefinition(nemdoc, self.shimxmlname(ifc))) e.xmlwrite(nemdoc, self.nemxmlname(ifc)) - def linkconfig(self, netif, bw=None, delay=None, - loss=None, duplicate=None, jitter=None, netif2=None): + def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): """ Generate CommEffect events when a Link Message is received having link parameters. """ - if emane.VERSION >= emane.EMANE091: - raise NotImplementedError("CommEffect linkconfig() not implemented for EMANE 0.9.1+") - - def z(x): - """ - Helper to use 0 for None values. - """ - if type(x) is str: - x = float(x) - if x is None: - return 0 - else: - return int(x) - service = self.session.emane.service if service is None: - logger.warn("%s: EMANE event service unavailable" % self.name) + logger.warn("%s: EMANE event service unavailable", self.name) return + if netif is None or netif2 is None: - logger.warn("%s: missing NEM information" % self.name) + logger.warn("%s: missing NEM information", self.name) return + # TODO: batch these into multiple events per transmission # TODO: may want to split out seconds portion of delay and jitter - event = emaneeventcommeffect.EventCommEffect(1) - index = 0 - e = self.session.get_object(self.object_id) - nemid = e.getnemid(netif) - nemid2 = e.getnemid(netif2) + event = CommEffectEvent() + emane_node = self.session.get_object(self.object_id) + nemid = emane_node.getnemid(netif) + nemid2 = emane_node.getnemid(netif2) mbw = bw - event.set(index, nemid, 0, z(delay), 0, z(jitter), z(loss), - z(duplicate), long(z(bw)), long(z(mbw))) - service.publish(emaneeventcommeffect.EVENT_ID, - emaneeventservice.PLATFORMID_ANY, - nemid2, emaneeventservice.COMPONENTID_ANY, - event.export()) + event.append( + nemid, + latency=convert_none(delay), + jitter=convert_none(jitter), + loss=convert_none(loss), + duplicate=convert_none(duplicate), + unicast=long(convert_none(bw)), + broadcast=long(convert_none(mbw)) + ) + service.publish(nemid2, event) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 0af6e477..951c4ea6 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -8,7 +8,6 @@ from xml.dom.minidom import parseString from core import CoreCommandError from core import constants -from core import emane from core import logger from core.api import coreapi from core.conf import ConfigurableManager @@ -32,19 +31,15 @@ from core.xml import xmlutils try: from emane.events import EventService from emane.events import LocationEvent + from emane.events.eventserviceexception import EventServiceException except ImportError: try: from emanesh.events import EventService from emanesh.events import LocationEvent + from emanesh.events.eventserviceexception import EventServiceException except ImportError: logger.info("emane 0.9.1+ not found") -try: - import emaneeventservice - import emaneeventlocation -except ImportError: - logger.info("emane < 0.9.1 not found") - EMANE_MODELS = [ EmaneRfPipeModel, EmaneIeee80211abgModel, @@ -63,7 +58,7 @@ class EmaneManager(ConfigurableManager): name = "emane" config_type = RegisterTlvs.EMULATION_SERVER.value _hwaddr_prefix = "02:02" - (SUCCESS, NOT_NEEDED, NOT_READY) = (0, 1, 2) + SUCCESS, NOT_NEEDED, NOT_READY = (0, 1, 2) EVENTCFGVAR = "LIBEMANEEVENTSERVICECONFIG" DEFAULT_LOG_LEVEL = 3 @@ -76,8 +71,8 @@ class EmaneManager(ConfigurableManager): """ ConfigurableManager.__init__(self) self.session = session - self._objs = {} - self._objslock = threading.Lock() + self._emane_nodes = {} + self._emane_node_lock = threading.Lock() self._ifccounts = {} self._ifccountslock = threading.Lock() # Port numbers are allocated from these counters @@ -103,93 +98,60 @@ class EmaneManager(ConfigurableManager): emane_models = utils.load_classes(custom_models_path, EmaneModel) self.load_models(emane_models) + self.service = None + def logversion(self): """ Log the installed EMANE version. """ - logger.info("using EMANE version: %s", emane.VERSIONSTR) + emane_version = utils.check_cmd(["emane", "--version"]) + logger.info("using EMANE: %s", emane_version) def deleteeventservice(self): - if hasattr(self, "service"): - if self.service: - for fd in self.service._readFd, self.service._writeFd: - if fd >= 0: - os.close(fd) - for f in self.service._socket, self.service._socketOTA: - if f: - f.close() - del self.service + if self.service: + for fd in self.service._readFd, self.service._writeFd: + if fd >= 0: + os.close(fd) + for f in self.service._socket, self.service._socketOTA: + if f: + f.close() + self.service = None def initeventservice(self, filename=None, shutdown=False): """ Re-initialize the EMANE Event service. The multicast group and/or port may be configured. - - For versions < 0.9.1 this can be changed via XML config file and an environment variable - pointing to that file. - - For version >= 0.9.1 this is passed into the EventService constructor. """ - logger.info("initializing emane event service: %s", emane.VERSIONSTR) - self.deleteeventservice() - self.service = None - # EMANE 0.9.1+ does not require event service XML config - if emane.VERSION >= emane.EMANE091: - if shutdown: - return - # Get the control network to be used for events - values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] - group, port = self.emane_config.valueof("eventservicegroup", values).split(":") - eventdev = self.emane_config.valueof("eventservicedevice", values) - eventnetidx = self.session.get_control_net_index(eventdev) - if emane.VERSION > emane.EMANE091: - if eventnetidx < 0: - msg = "Invalid Event Service device provided: %s" % eventdev - logger.error(msg) - return False + if shutdown: + return - # Make sure the event control network is in place - eventnet = self.session.add_remove_control_net(net_index=eventnetidx, - remove=False, - conf_required=False) - if eventnet is not None: - # direct EMANE events towards control net bridge - eventdev = eventnet.brname - eventchannel = (group, int(port), eventdev) + # Get the control network to be used for events + values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] + group, port = self.emane_config.valueof("eventservicegroup", values).split(":") + eventdev = self.emane_config.valueof("eventservicedevice", values) + eventnetidx = self.session.get_control_net_index(eventdev) + if eventnetidx < 0: + logger.error("invalid emane event service device provided: %s", eventdev) + return False - # disabled otachannel for event service - # only needed for e.g. antennaprofile events xmit by models - logger.info("Using %s for event service traffic" % eventdev) - try: - self.service = EventService(eventchannel=eventchannel, otachannel=None) - except: - logger.exception("error instantiating EventService") + # make sure the event control network is in place + eventnet = self.session.add_remove_control_net(net_index=eventnetidx, remove=False, conf_required=False) + if eventnet is not None: + # direct EMANE events towards control net bridge + eventdev = eventnet.brname + eventchannel = (group, int(port), eventdev) - return True - - tmp = None - if filename is not None: - tmp = os.getenv(EmaneManager.EVENTCFGVAR) - os.environ.update({EmaneManager.EVENTCFGVAR: filename}) - - rc = True + # disabled otachannel for event service + # only needed for e.g. antennaprofile events xmit by models + logger.info("Using %s for event service traffic" % eventdev) try: - self.service = emaneeventservice.EventService() - except: - self.service = None - rc = False + self.service = EventService(eventchannel=eventchannel, otachannel=None) + except EventServiceException: + logger.exception("error instantiating emane EventService") - if self.service: - for f in self.service._readFd, self.service._writeFd, self.service._socket, self.service._socketOTA: - if f: - utils.close_onexec(f) - - if filename is not None: - os.environ.pop(EmaneManager.EVENTCFGVAR) - if tmp is not None: - os.environ.update({EmaneManager.EVENTCFGVAR: tmp}) - - return rc + return True def load_models(self, emane_models): """ @@ -199,19 +161,19 @@ class EmaneManager(ConfigurableManager): logger.info("loading emane model: (%s) %s - %s", emane_model, emane_model.name, RegisterTlvs(emane_model.config_type)) self._modelclsmap[emane_model.name] = emane_model - self.session.add_config_object(emane_model.name, emane_model.config_type, - emane_model.configure_emane) + self.session.add_config_object(emane_model.name, emane_model.config_type, emane_model.configure_emane) - def addobj(self, obj): + def add_node(self, emane_node): """ - add a new EmaneNode object to this Emane controller object + Add a new EmaneNode object to this Emane controller object + + :param core.emane.nodes.EmaneNode emane_node: emane node to add + :return: nothing """ - self._objslock.acquire() - if obj.objid in self._objs: - self._objslock.release() - raise KeyError("non-unique EMANE object id %s for %s" % (obj.objid, obj)) - self._objs[obj.objid] = obj - self._objslock.release() + with self._emane_node_lock: + if emane_node.objid in self._emane_nodes: + raise KeyError("non-unique EMANE object id %s for %s" % (emane_node.objid, emane_node)) + self._emane_nodes[emane_node.objid] = emane_node def getnodes(self): """ @@ -219,11 +181,11 @@ class EmaneManager(ConfigurableManager): e.g. containers having one or more radio interfaces. """ # assumes self._objslock already held - r = set() - for e in self._objs.values(): - for netif in e.netifs(): - r.add(netif.node) - return r + nodes = set() + for emane_node in self._emane_nodes.values(): + for netif in emane_node.netifs(): + nodes.add(netif.node) + return nodes def getmodels(self, n): """ @@ -233,8 +195,7 @@ class EmaneManager(ConfigurableManager): # EMANE global params are stored with first EMANE node (if non-default # values are configured) sorted_ids = sorted(self.configs.keys()) - if None in self.configs and len(sorted_ids) > 1 and \ - n.objid == sorted_ids[1]: + if None in self.configs and len(sorted_ids) > 1 and n.objid == sorted_ids[1]: v = self.configs[None] for model in v: cls = self._modelclsmap[model[0]] @@ -249,7 +210,8 @@ class EmaneManager(ConfigurableManager): else: # don"t use default values when interface config is the same as net # note here that using ifc.node.objid as key allows for only one type - # of each model per node; TODO: use both node and interface as key + # of each model per node; + # TODO: use both node and interface as key # Adamson change: first check for iface config keyed by "node:ifc.name" # (so that nodes w/ multiple interfaces of same conftype can have @@ -257,14 +219,16 @@ class EmaneManager(ConfigurableManager): key = 1000 * ifc.node.objid if ifc.netindex is not None: key += ifc.netindex + values = self.getconfig(key, conftype, None)[1] if not values: values = self.getconfig(ifc.node.objid, conftype, None)[1] - if not values and emane.VERSION > emane.EMANE091: + + if not values and ifc.transport_type == "raw": # with EMANE 0.9.2+, we need an extra NEM XML from # model.buildnemxmlfiles(), so defaults are returned here - if ifc.transport_type == "raw": - values = self.getconfig(nodenum, conftype, defaultvalues)[1] + values = self.getconfig(nodenum, conftype, defaultvalues)[1] + return values def setup(self): @@ -274,26 +238,24 @@ class EmaneManager(ConfigurableManager): Emane.(SUCCESS, NOT_NEEDED, NOT_READY) in order to delay session instantiation. """ + + # TODO: drive this from the session object with self.session._objects_lock: - for obj in self.session.objects.itervalues(): - if nodeutils.is_node(obj, NodeTypes.EMANE): - self.addobj(obj) - if len(self._objs) == 0: + for node in self.session.objects.itervalues(): + if nodeutils.is_node(node, NodeTypes.EMANE): + self.add_node(node) + if not self._emane_nodes: return EmaneManager.NOT_NEEDED - if emane.VERSION == emane.EMANEUNK: - raise ValueError, "EMANE version not properly detected" + # control network bridge required for EMANE 0.9.2 # - needs to be configured before checkdistributed() for distributed # - needs to exist when eventservice binds to it (initeventservice) - if emane.VERSION > emane.EMANE091 and self.session.master: - values = self.getconfig(None, "emane", - self.emane_config.getdefaultvalues())[1] + if self.session.master: + values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] otadev = self.emane_config.valueof("otamanagerdevice", values) netidx = self.session.get_control_net_index(otadev) if netidx < 0: - msg = "EMANE cannot be started. " \ - "Invalid OTA device provided: %s. Check core.conf." % otadev - logger.error(msg) + logger.error("EMANE cannot start, check core config. invalid OTA device provided: %s", otadev) return EmaneManager.NOT_READY ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False) @@ -302,9 +264,7 @@ class EmaneManager(ConfigurableManager): if eventdev != otadev: netidx = self.session.get_control_net_index(eventdev) if netidx < 0: - msg = "EMANE cannot be started." \ - "Invalid Event Service device provided: %s. Check core.conf." % eventdev - logger.error(msg) + logger.error("EMANE cannot start, check core config. invalid event service device: %s", eventdev) return EmaneManager.NOT_READY ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False) @@ -312,11 +272,11 @@ class EmaneManager(ConfigurableManager): if self.checkdistributed(): # we are slave, but haven"t received a platformid yet - cfgval = self.getconfig(None, self.emane_config.name, - self.emane_config.getdefaultvalues())[1] + cfgval = self.getconfig(None, self.emane_config.name, self.emane_config.getdefaultvalues())[1] i = self.emane_config.getnames().index("platform_id_start") if cfgval[i] == self.emane_config.getdefaultvalues()[i]: return EmaneManager.NOT_READY + self.setnodemodels() return EmaneManager.SUCCESS @@ -328,34 +288,27 @@ class EmaneManager(ConfigurableManager): """ self.reset() r = self.setup() + + # NOT_NEEDED or NOT_READY if r != EmaneManager.SUCCESS: - return r # NOT_NEEDED or NOT_READY - if emane.VERSIONSTR == "": - raise ValueError("EMANE version not properly detected") + return r + nems = [] - with self._objslock: - if emane.VERSION < emane.EMANE092: - self.buildxml() - self.initeventservice() - self.starteventmonitor() - if self.numnems() > 0: - # TODO: check and return failure for these methods - self.startdaemons() - self.installnetifs() - else: - self.buildxml2() - self.initeventservice() - self.starteventmonitor() - if self.numnems() > 0: - self.startdaemons2() - self.installnetifs(do_netns=False) - for e in self._objs.itervalues(): - for netif in e.netifs(): - nems.append((netif.node.name, netif.name, - e.getnemid(netif))) + with self._emane_node_lock: + self.buildxml() + self.initeventservice() + self.starteventmonitor() + + if self.numnems() > 0: + self.startdaemons() + self.installnetifs(do_netns=False) + + for emane_node in self._emane_nodes.itervalues(): + for netif in emane_node.netifs(): + nems.append((netif.node.name, netif.name, emane_node.getnemid(netif))) + if nems: - emane_nems_filename = os.path.join(self.session.session_dir, - "emane_nems") + emane_nems_filename = os.path.join(self.session.session_dir, "emane_nems") try: with open(emane_nems_filename, "w") as f: for nodename, ifname, nemid in nems: @@ -371,20 +324,22 @@ class EmaneManager(ConfigurableManager): """ if not self.genlocationevents(): return - with self._objslock: - for n in sorted(self._objs.keys()): - e = self._objs[n] - for netif in e.netifs(): - (x, y, z) = netif.node.position.get() - e.setnemposition(netif, x, y, z) + + with self._emane_node_lock: + for key in sorted(self._emane_nodes.keys()): + emane_node = self._emane_nodes[key] + for netif in emane_node.netifs(): + x, y, z = netif.node.position.get() + emane_node.setnemposition(netif, x, y, z) def reset(self): """ remove all EmaneNode objects from the dictionary, reset port numbers and nem id counters """ - with self._objslock: - self._objs.clear() + with self._emane_node_lock: + self._emane_nodes.clear() + # don"t clear self._ifccounts here; NEM counts are needed for buildxml self.platformport = self.session.get_config_item_int("emane_platform_port", 8100) self.transformport = self.session.get_config_item_int("emane_transform_port", 8200) @@ -393,18 +348,16 @@ class EmaneManager(ConfigurableManager): """ stop all EMANE daemons """ - self._ifccountslock.acquire() - self._ifccounts.clear() - self._ifccountslock.release() - self._objslock.acquire() - if len(self._objs) == 0: - self._objslock.release() - return - logger.info("Stopping EMANE daemons.") - self.deinstallnetifs() - self.stopdaemons() - self.stopeventmonitor() - self._objslock.release() + with self._ifccountslock: + self._ifccounts.clear() + + with self._emane_node_lock: + if not self._emane_nodes: + return + logger.info("stopping EMANE daemons.") + self.deinstallnetifs() + self.stopdaemons() + self.stopeventmonitor() def handledistributed(self, message): """ @@ -418,12 +371,11 @@ class EmaneManager(ConfigurableManager): if nn[0] in self.session.broker.network_nodes: serverlist = self.session.broker.getserversbynode(nn[1]) for server in serverlist: - self._ifccountslock.acquire() - if server not in self._ifccounts: - self._ifccounts[server] = 1 - else: - self._ifccounts[server] += 1 - self._ifccountslock.release() + with self._ifccountslock: + if server not in self._ifccounts: + self._ifccounts[server] = 1 + else: + self._ifccounts[server] += 1 def checkdistributed(self): """ @@ -435,37 +387,37 @@ class EmaneManager(ConfigurableManager): """ # check with the session if we are the "master" Emane object? master = False - self._objslock.acquire() - if len(self._objs) > 0: - master = self.session.master - logger.info("Setup EMANE with master=%s." % master) - self._objslock.release() + + with self._emane_node_lock: + if self._emane_nodes: + master = self.session.master + logger.info("Setup EMANE with master=%s." % master) # we are not the master Emane object, wait for nem id and ports if not master: return True - cfgval = self.getconfig(None, self.emane_config.name, - self.emane_config.getdefaultvalues())[1] + cfgval = self.getconfig(None, self.emane_config.name, self.emane_config.getdefaultvalues())[1] values = list(cfgval) nemcount = 0 - self._objslock.acquire() - for n in self._objs: - emanenode = self._objs[n] - nemcount += emanenode.numnetif() - nemid = int(self.emane_config.valueof("nem_id_start", values)) - nemid += nemcount - platformid = int(self.emane_config.valueof("platform_id_start", values)) - names = list(self.emane_config.getnames()) + with self._emane_node_lock: + for key in self._emane_nodes: + emane_node = self._emane_nodes[key] + nemcount += emane_node.numnetif() - # build an ordered list of servers so platform ID is deterministic - servers = [] - for n in sorted(self._objs): - for s in self.session.broker.getserversbynode(n): - if s not in servers: - servers.append(s) - self._objslock.release() + nemid = int(self.emane_config.valueof("nem_id_start", values)) + nemid += nemcount + + platformid = int(self.emane_config.valueof("platform_id_start", values)) + names = list(self.emane_config.getnames()) + + # build an ordered list of servers so platform ID is deterministic + servers = [] + for key in sorted(self._emane_nodes): + for server in self.session.broker.getserversbynode(key): + if server not in servers: + servers.append(server) servers.sort(key=lambda x: x.name) for server in servers: @@ -489,29 +441,16 @@ class EmaneManager(ConfigurableManager): return False def buildxml(self): - """ - Build all of the XML files required to run EMANE on the host. - NEMs run in a single host emane process, with TAP devices pushed - into namespaces. - """ - # assume self._objslock is already held here - logger.info("Emane.buildxml()") - self.buildplatformxml() - self.buildnemxml() - self.buildtransportxml() - self.buildeventservicexml() - - def buildxml2(self): """ Build XML files required to run EMANE on each node. NEMs run inside containers using the control network for passing events and data. """ # assume self._objslock is already held here - logger.info("Emane.buildxml2()") + logger.info("emane building xml...") # on master, control network bridge added earlier in startup() ctrlnet = self.session.add_remove_control_net(net_index=0, remove=False, conf_required=False) - self.buildplatformxml2(ctrlnet) + self.buildplatformxml(ctrlnet) self.buildnemxml() self.buildeventservicexml() @@ -525,16 +464,19 @@ class EmaneManager(ConfigurableManager): # slave server if not session.master: return + servers = session.broker.getservernames() # not distributed if len(servers) < 2: return + prefix = session.config.get("controlnet") prefix = getattr(session.options, "controlnet", prefix) prefixes = prefix.split() # normal Config messaging will distribute controlnets if len(prefixes) >= len(servers): return + # this generates a config message having controlnet prefix assignments logger.info("Setting up default controlnet prefixes for distributed (%d configured)" % len(prefixes)) prefixes = ctrlnet.DEFAULT_PREFIX_LIST[0] @@ -585,32 +527,34 @@ class EmaneManager(ConfigurableManager): Write the given XML document to the specified filename. """ pathname = os.path.join(self.session.session_dir, filename) - f = open(pathname, "w") - doc.writexml(writer=f, indent="", addindent=" ", newl="\n", encoding="UTF-8") - f.close() + with open(pathname, "w") as xml_file: + doc.writexml(writer=xml_file, indent="", addindent=" ", newl="\n", encoding="UTF-8") def setnodemodels(self): """ Associate EmaneModel classes with EmaneNode nodes. The model configurations are stored in self.configs. """ - for n in self._objs: - self.setnodemodel(n) + for emane_node in self._emane_nodes: + self.setnodemodel(emane_node) def setnodemodel(self, n): - emanenode = self._objs[n] + emanenode = self._emane_nodes[n] if n not in self.configs: return False + for t, v in self.configs[n]: if t is None: continue if t == self.emane_config.name: continue + # only use the first valid EmaneModel # convert model name to class (e.g. emane_rfpipe -> EmaneRfPipe) cls = self._modelclsmap[t] emanenode.setmodel(cls, v) return True + # no model has been configured for this EmaneNode return False @@ -619,81 +563,28 @@ class EmaneManager(ConfigurableManager): Look for the given numerical NEM ID and return the first matching EmaneNode and NEM interface. """ - emanenode = None + emane_node = None netif = None - for n in self._objs: - emanenode = self._objs[n] - netif = emanenode.getnemnetif(nemid) + for key in self._emane_nodes: + emane_node = self._emane_nodes[key] + netif = emane_node.getnemnetif(nemid) if netif is not None: break else: - emanenode = None - return emanenode, netif + emane_node = None + + return emane_node, netif def numnems(self): """ Return the number of NEMs emulated locally. """ count = 0 - for o in self._objs.values(): - count += len(o.netifs()) + for emane_node in self._emane_nodes.itervalues(): + count += len(emane_node.netifs()) return count - def buildplatformxml(self): - """ - Build a platform.xml file now that all nodes are configured. - """ - values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] - doc = self.xmldoc("platform") - plat = doc.getElementsByTagName("platform").pop() - if emane.VERSION < emane.EMANE091: - platformid = self.emane_config.valueof("platform_id_start", values) - plat.setAttribute("name", "Platform %s" % platformid) - plat.setAttribute("id", platformid) - - names = list(self.emane_config.getnames()) - platform_names = names[:len(self.emane_config._confmatrix_platform)] - platform_names.remove("platform_id_start") - - # append all platform options (except starting id) to doc - map(lambda n: plat.appendChild(self.xmlparam(doc, n, self.emane_config.valueof(n, values))), platform_names) - - nemid = int(self.emane_config.valueof("nem_id_start", values)) - # assume self._objslock is already held here - for n in sorted(self._objs.keys()): - emanenode = self._objs[n] - nems = emanenode.buildplatformxmlentry(doc) - for netif in sorted(nems, key=lambda n: n.node.objid): - # set ID, endpoints here - nementry = nems[netif] - nementry.setAttribute("id", "%d" % nemid) - if emane.VERSION < emane.EMANE092: - # insert nem options (except nem id) to doc - trans_addr = self.emane_config.valueof("transportendpoint", values) - nementry.insertBefore( - self.xmlparam(doc, "transportendpoint", "%s:%d" % (trans_addr, self.transformport)), - nementry.firstChild - ) - platform_addr = self.emane_config.valueof("platformendpoint", values) - nementry.insertBefore( - self.xmlparam(doc, "platformendpoint", "%s:%d" % (platform_addr, self.platformport)), - nementry.firstChild - ) - plat.appendChild(nementry) - emanenode.setnemid(netif, nemid) - # NOTE: MAC address set before here is incorrect, including the one - # sent from the GUI via link message - # MAC address determined by NEM ID: 02:02:00:00:nn:nn" - macstr = self._hwaddr_prefix + ":00:00:" - macstr += "%02X:%02X" % ((nemid >> 8) & 0xFF, nemid & 0xFF) - netif.sethwaddr(MacAddress.from_string(macstr)) - # increment counters used to manage IDs, endpoint port numbers - nemid += 1 - self.platformport += 1 - self.transformport += 1 - self.xmlwrite(doc, "platform.xml") - def newplatformxmldoc(self, values, otadev=None, eventdev=None): """ Start a new platform XML file. Use global EMANE config values @@ -709,15 +600,17 @@ class EmaneManager(ConfigurableManager): if otadev: i = platform_names.index("otamanagerdevice") platform_values[i] = otadev + if eventdev: i = platform_names.index("eventservicedevice") platform_values[i] = eventdev + # append all platform options (except starting id) to doc map(lambda n: plat.appendChild(self.xmlparam(doc, n, self.emane_config.valueof(n, platform_values))), platform_names) return doc - def buildplatformxml2(self, ctrlnet): + def buildplatformxml(self, ctrlnet): """ Build a platform.xml file now that all nodes are configured. """ @@ -726,45 +619,47 @@ class EmaneManager(ConfigurableManager): platformxmls = {} # assume self._objslock is already held here - for n in sorted(self._objs.keys()): - emanenode = self._objs[n] - nems = emanenode.buildplatformxmlentry(self.xmldoc("platform")) - for netif in sorted(nems, key=lambda n: n.node.objid): + for key in sorted(self._emane_nodes.keys()): + emane_node = self._emane_nodes[key] + nems = emane_node.buildplatformxmlentry(self.xmldoc("platform")) + for netif in sorted(nems, key=lambda x: x.node.objid): nementry = nems[netif] nementry.setAttribute("id", "%d" % nemid) - k = netif.node.objid + key = netif.node.objid if netif.transport_type == "raw": - k = "host" + key = "host" otadev = ctrlnet.brname eventdev = ctrlnet.brname else: otadev = None eventdev = None - if k not in platformxmls: - platformxmls[k] = self.newplatformxmldoc(values, otadev, - eventdev) - doc = platformxmls[k] + + if key not in platformxmls: + platformxmls[key] = self.newplatformxmldoc(values, otadev, eventdev) + + doc = platformxmls[key] plat = doc.getElementsByTagName("platform").pop() plat.appendChild(nementry) - emanenode.setnemid(netif, nemid) + emane_node.setnemid(netif, nemid) macstr = self._hwaddr_prefix + ":00:00:" macstr += "%02X:%02X" % ((nemid >> 8) & 0xFF, nemid & 0xFF) netif.sethwaddr(MacAddress.from_string(macstr)) nemid += 1 - for k in sorted(platformxmls.keys()): - if k == "host": + + for key in sorted(platformxmls.keys()): + if key == "host": self.xmlwrite(platformxmls["host"], "platform.xml") continue - self.xmlwrite(platformxmls[k], "platform%d.xml" % k) + self.xmlwrite(platformxmls[key], "platform%d.xml" % key) def buildnemxml(self): """ Builds the xxxnem.xml, xxxmac.xml, and xxxphy.xml files which are defined on a per-EmaneNode basis. """ - for n in sorted(self._objs.keys()): - emanenode = self._objs[n] - emanenode.buildnemxmlfiles(self) + for key in sorted(self._emane_nodes.keys()): + emane_node = self._emane_nodes[key] + emane_node.buildnemxmlfiles(self) def appendtransporttonem(self, doc, nem, nodenum, ifc=None): """ @@ -772,14 +667,14 @@ class EmaneManager(ConfigurableManager): a tag to the NEM definition, required for using EMANE"s internal transport. """ - if emane.VERSION < emane.EMANE092: - return - emanenode = self._objs[nodenum] + emane_node = self._emane_nodes[nodenum] transtag = doc.createElement("transport") transtypestr = "virtual" + if ifc and ifc.transport_type == "raw": transtypestr = "raw" - transtag.setAttribute("definition", emanenode.transportxmlname(transtypestr)) + + transtag.setAttribute("definition", emane_node.transportxmlname(transtypestr)) nem.appendChild(transtag) def buildtransportxml(self): @@ -813,8 +708,8 @@ class EmaneManager(ConfigurableManager): except ValueError: logger.exception("invalid eventservicegroup in EMANE config") return - dev = self.emane_config.valueof("eventservicedevice", values) + dev = self.emane_config.valueof("eventservicedevice", values) doc = self.xmldoc("emaneeventmsgsvc") es = doc.getElementsByTagName("emaneeventmsgsvc").pop() kvs = (("group", group), ("port", port), ("device", dev), ("mcloop", "1"), ("ttl", "32")) @@ -825,50 +720,19 @@ class EmaneManager(ConfigurableManager): self.initeventservice(filename=pathname) def startdaemons(self): - """ - Start the appropriate EMANE daemons. The transport daemon will - bind to the TAP interfaces. - """ - logger.info("Emane.startdaemons()") - path = self.session.session_dir - loglevel = str(EmaneManager.DEFAULT_LOG_LEVEL) - cfgloglevel = self.session.get_config_item_int("emane_log_level") - realtime = self.session.get_config_item_bool("emane_realtime", True) - if cfgloglevel: - logger.info("setting user-defined EMANE log level: %d" % cfgloglevel) - loglevel = str(cfgloglevel) - emanecmd = ["emane", "-d", "--logl", loglevel, "-f", os.path.join(path, "emane.log")] - if realtime: - emanecmd += "-r", - - args = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons() running %s" % str(args)) - utils.check_cmd(args, cwd=path) - - # start one transport daemon per transportdaemon*.xml file - args = ["emanetransportd", "-d", "--logl", loglevel, "-f", os.path.join(path, "emanetransportd.log")] - if realtime: - args += "-r", - files = os.listdir(path) - for current_file in files: - if current_file[-3:] == "xml" and current_file[:15] == "transportdaemon": - args = args + [os.path.join(path, current_file)] - logger.info("Emane.startdaemons() running %s" % str(args)) - utils.check_cmd(args, cwd=path) - - def startdaemons2(self): """ Start one EMANE daemon per node having a radio. Add a control network even if the user has not configured one. """ - logger.info("Emane.startdaemons()") + logger.info("starting emane daemons...") loglevel = str(EmaneManager.DEFAULT_LOG_LEVEL) cfgloglevel = self.session.get_config_item_int("emane_log_level") realtime = self.session.get_config_item_bool("emane_realtime", True) if cfgloglevel: - logger.info("setting user-defined EMANE log level: %d" % cfgloglevel) + logger.info("setting user-defined EMANE log level: %d", cfgloglevel) loglevel = str(cfgloglevel) - emanecmd = ["emane", "-d", "--logl", loglevel] + + emanecmd = ["emane", "-d", "-l", loglevel] if realtime: emanecmd += "-r", @@ -893,11 +757,11 @@ class EmaneManager(ConfigurableManager): self.session.add_remove_control_interface(node, 0, remove=False, conf_required=False) if otanetidx > 0: - logger.info("adding ota device ctrl%d" % otanetidx) + logger.info("adding ota device ctrl%d", otanetidx) self.session.add_remove_control_interface(node, otanetidx, remove=False, conf_required=False) if eventservicenetidx >= 0: - logger.info("adding event service device ctrl%d" % eventservicenetidx) + logger.info("adding event service device ctrl%d", eventservicenetidx) self.session.add_remove_control_interface(node, eventservicenetidx, remove=False, conf_required=False) # multicast route is needed for OTA data @@ -912,9 +776,9 @@ class EmaneManager(ConfigurableManager): # start emane args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] - logger.info("Emane.startdaemons2() running %s", args) output = node.check_cmd(args) - logger.info("Emane.startdaemons2() output: %s", output) + logger.info("emane daemon running: %s", args) + logger.info("emane daemon output: %s", output) if not run_emane_on_host: return @@ -922,28 +786,24 @@ class EmaneManager(ConfigurableManager): path = self.session.session_dir emanecmd += ["-f", os.path.join(path, "emane.log")] args = emanecmd + [os.path.join(path, "platform.xml")] - logger.info("Emane.startdaemons2() running %s" % args) utils.check_cmd(args, cwd=path) + logger.info("emane daemon running: %s", args) def stopdaemons(self): """ Kill the appropriate EMANE daemons. """ - # TODO: we may want to improve this if we had the PIDs from the - # specific EMANE daemons that we"ve started + # TODO: we may want to improve this if we had the PIDs from the specific EMANE daemons that we"ve started args = ["killall", "-q", "emane"] stop_emane_on_host = False - if emane.VERSION > emane.EMANE091: - for node in self.getnodes(): - if hasattr(node, "transport_type") and \ - node.transport_type == "raw": - stop_emane_on_host = True - continue - if node.up: - node.cmd(args, wait=False) - # TODO: RJ45 node - else: - stop_emane_on_host = True + for node in self.getnodes(): + if hasattr(node, "transport_type") and node.transport_type == "raw": + stop_emane_on_host = True + continue + + if node.up: + node.cmd(args, wait=False) + # TODO: RJ45 node if stop_emane_on_host: try: @@ -957,18 +817,18 @@ class EmaneManager(ConfigurableManager): Install TUN/TAP virtual interfaces into their proper namespaces now that the EMANE daemons are running. """ - for n in sorted(self._objs.keys()): - emanenode = self._objs[n] - logger.info("Emane.installnetifs() for node %d" % n) - emanenode.installnetifs(do_netns) + for key in sorted(self._emane_nodes.keys()): + emane_node = self._emane_nodes[key] + logger.info("emane install netifs for node: %d", key) + emane_node.installnetifs(do_netns) def deinstallnetifs(self): """ Uninstall TUN/TAP virtual interfaces. """ - for n in sorted(self._objs.keys()): - emanenode = self._objs[n] - emanenode.deinstallnetifs() + for key in sorted(self._emane_nodes.keys()): + emane_node = self._emane_nodes[key] + emane_node.deinstallnetifs() def configure(self, session, config_data): """ @@ -978,8 +838,7 @@ class EmaneManager(ConfigurableManager): """ r = self.emane_config.configure_emane(session, config_data) - # extra logic to start slave Emane object after nemid has been - # configured from the master + # extra logic to start slave Emane object after nemid has been configured from the master config_type = config_data.type if config_type == ConfigFlags.UPDATE.value and self.session.master is False: # instantiation was previously delayed by self.setup() @@ -1011,9 +870,10 @@ class EmaneManager(ConfigurableManager): """ Start monitoring EMANE location events if configured to do so. """ - logger.info("Emane.starteventmonitor()") + logger.info("emane start event monitor") if not self.doeventmonitor(): return + if self.service is None: errmsg = "Warning: EMANE events will not be generated " \ "because the emaneeventservice\n binding was " \ @@ -1035,9 +895,10 @@ class EmaneManager(ConfigurableManager): self.service.breakloop() # reset the service, otherwise nextEvent won"t work self.initeventservice(shutdown=True) + if self.eventmonthread is not None: - if emane.VERSION >= emane.EMANE091: - self.eventmonthread._Thread__stop() + # TODO: fix this + self.eventmonthread._Thread__stop() self.eventmonthread.join() self.eventmonthread = None @@ -1047,46 +908,34 @@ class EmaneManager(ConfigurableManager): """ if self.service is None: return - logger.info("Subscribing to EMANE location events (not generating them). " \ - "(%s) " % threading.currentThread().getName()) + logger.info("subscribing to EMANE location events (not generating them). (%s)", + threading.currentThread().getName()) while self.doeventloop is True: - if emane.VERSION >= emane.EMANE091: - uuid, seq, events = self.service.nextEvent() - if not self.doeventloop: - break # this occurs with 0.9.1 event service - for event in events: - (nem, eid, data) = event - if eid == LocationEvent.IDENTIFIER: - self.handlelocationevent2(nem, eid, data) - else: - (event, platform, nem, cmp, data) = self.service.nextEvent() - if event == emaneeventlocation.EVENT_ID: - self.handlelocationevent(event, platform, nem, cmp, data) - logger.info("Unsubscribing from EMANE location events. (%s) " % threading.currentThread().getName()) + uuid, seq, events = self.service.nextEvent() - def handlelocationevent(self, event, platform, nem, component, data): - """ - Handle an EMANE location event (EMANE 0.8.1 and earlier). - """ - event = emaneeventlocation.EventLocation(data) - entries = event.entries() - for e in entries.values(): - # yaw,pitch,roll,azimuth,elevation,velocity are unhandled - (nemid, lat, long, alt) = e[:4] - self.handlelocationeventtoxyz(nemid, lat, long, alt) + # this occurs with 0.9.1 event service + if not self.doeventloop: + break - def handlelocationevent2(self, rxnemid, eid, data): + for event in events: + nem, eid, data = event + if eid == LocationEvent.IDENTIFIER: + self.handlelocationevent(nem, eid, data) + + logger.info("unsubscribing from EMANE location events. (%s)", threading.currentThread().getName()) + + def handlelocationevent(self, rxnemid, eid, data): """ - Handle an EMANE location event (EMANE 0.9.1+). + Handle an EMANE location event. """ events = LocationEvent() events.restore(data) for event in events: - (txnemid, attrs) = event - if "latitude" not in attrs or "longitude" not in attrs or \ - "altitude" not in attrs: + txnemid, attrs = event + if "latitude" not in attrs or "longitude" not in attrs or "altitude" not in attrs: logger.warn("dropped invalid location event") continue + # yaw,pitch,roll,azimuth,elevation,velocity are unhandled lat = attrs["latitude"] long = attrs["longitude"] @@ -1104,25 +953,21 @@ class EmaneManager(ConfigurableManager): if netif is None: logger.info("location event for unknown NEM %s", nemid) return False + n = netif.node.objid # convert from lat/long/alt to x,y,z coordinates x, y, z = self.session.location.getxyz(lat, lon, alt) x = int(x) y = int(y) z = int(z) - logger.info("location event NEM %s (%s, %s, %s) -> (%s, %s, %s)", - nemid, lat, lon, alt, x, y, z) - try: - if (x.bit_length() > 16) or (y.bit_length() > 16) or \ - (z.bit_length() > 16) or (x < 0) or (y < 0) or (z < 0): - warntxt = "Unable to build node location message since " \ - "received lat/long/alt exceeds coordinate " \ - "space: NEM %s (%d, %d, %d)" % (nemid, x, y, z) - logger.error(warntxt) - return False - except AttributeError: - # int.bit_length() not present on Python 2.6 - logger.exception("error using bit_length") + logger.info("location event NEM %s (%s, %s, %s) -> (%s, %s, %s)", nemid, lat, lon, alt, x, y, z) + xbit_check = x.bit_length() > 16 or x < 0 + ybit_check = y.bit_length() > 16 or y < 0 + zbit_check = z.bit_length() > 16 or z < 0 + if any([xbit_check, ybit_check, zbit_check]): + logger.error("Unable to build node location message, received lat/long/alt exceeds coordinate " + "space: NEM %s (%d, %d, %d)", nemid, x, y, z) + return False # generate a node message for this location update try: @@ -1130,24 +975,19 @@ class EmaneManager(ConfigurableManager): except KeyError: logger.exception("location event NEM %s has no corresponding node %s" % (nemid, n)) return False + # don"t use node.setposition(x,y,z) which generates an event node.position.set(x, y, z) - node_data = node.data(message_type=0, lat=lat, lon=lon, alt=alt) self.session.broadcast_node(node_data) - return True def emanerunning(self, node): """ - Return True if an EMANE process associated with the given node - is running, False otherwise. + Return True if an EMANE process associated with the given node is running, False otherwise. """ args = ["pkill", "-0", "-x", "emane"] - if emane.VERSION < emane.EMANE092: - status = utils.cmd(args) - else: - status = node.cmd(args) + status = node.cmd(args) return status == 0 @@ -1156,65 +996,42 @@ class EmaneGlobalModel(EmaneModel): Global EMANE configuration options. """ - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - # Over-The-Air channel required for EMANE 0.9.2 - _DEFAULT_OTA = "0" - _DEFAULT_DEV = "lo" - if emane.VERSION >= emane.EMANE092: - _DEFAULT_OTA = "1" - _DEFAULT_DEV = "ctrl0" + _DEFAULT_OTA = "1" + _DEFAULT_DEV = "ctrl0" name = "emane" _confmatrix_platform_base = [ - ("otamanagerchannelenable", ConfigDataTypes.BOOL.value, _DEFAULT_OTA, - "on,off", "enable OTA Manager channel"), - ("otamanagergroup", ConfigDataTypes.STRING.value, "224.1.2.8:45702", - "", "OTA Manager group"), - ("otamanagerdevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, - "", "OTA Manager device"), - ("eventservicegroup", ConfigDataTypes.STRING.value, "224.1.2.8:45703", - "", "Event Service group"), - ("eventservicedevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, - "", "Event Service device"), - ("platform_id_start", ConfigDataTypes.INT32.value, "1", - "", "starting Platform ID"), - ] - _confmatrix_platform_081 = [ - ("debugportenable", ConfigDataTypes.BOOL.value, "0", - "on,off", "enable debug port"), - ("debugport", ConfigDataTypes.UINT16.value, "47000", - "", "debug port number"), - ] - _confmatrix_platform_091 = [ - ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", - "", "Control port address"), - ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", - "", "antenna profile manifest URI"), - ] - _confmatrix_nem = [ - ("transportendpoint", ConfigDataTypes.STRING.value, "localhost", - "", "Transport endpoint address (port is automatic)"), - ("platformendpoint", ConfigDataTypes.STRING.value, "localhost", - "", "Platform endpoint address (port is automatic)"), - ("nem_id_start", ConfigDataTypes.INT32.value, "1", - "", "starting NEM ID"), - ] - _confmatrix_nem_092 = [ - ("nem_id_start", ConfigDataTypes.INT32.value, "1", - "", "starting NEM ID"), + ("otamanagerchannelenable", ConfigDataTypes.BOOL.value, _DEFAULT_OTA, "on,off", "enable OTA Manager channel"), + ("otamanagergroup", ConfigDataTypes.STRING.value, "224.1.2.8:45702", "", "OTA Manager group"), + ("otamanagerdevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "OTA Manager device"), + ("eventservicegroup", ConfigDataTypes.STRING.value, "224.1.2.8:45703", "", "Event Service group"), + ("eventservicedevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "Event Service device"), + ("platform_id_start", ConfigDataTypes.INT32.value, "1", "", "starting Platform ID"), + ] + + # defined from 0.9.1 + _confmatrix_platform = [ + ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", "", "Control port address"), + ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", "", "antenna profile manifest URI"), + ] + _confmatrix_platform = _confmatrix_platform_base + _confmatrix_platform + + # defined from 0.9.2 + _confmatrix_nem = [ + ("nem_id_start", ConfigDataTypes.INT32.value, "1", "", "starting NEM ID"), ] - if emane.VERSION >= emane.EMANE091: - _confmatrix_platform = _confmatrix_platform_base + \ - _confmatrix_platform_091 - if emane.VERSION >= emane.EMANE092: - _confmatrix_nem = _confmatrix_nem_092 - else: - _confmatrix_platform = _confmatrix_platform_base + \ - _confmatrix_platform_081 config_matrix = _confmatrix_platform + _confmatrix_nem config_groups = "Platform Attributes:1-%d|NEM Parameters:%d-%d" % \ (len(_confmatrix_platform), len(_confmatrix_platform) + 1, len(config_matrix)) + + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + + def buildnemxmlfiles(self, e, ifc): + """ + Build the necessary nem, mac, and phy XMLs in the given path. + """ + raise NotImplementedError diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 9efd54fb..4733160e 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -2,7 +2,6 @@ Defines Emane Models used within CORE. """ -from core import emane from core import logger from core.misc import utils from core.mobility import WirelessModel @@ -47,23 +46,6 @@ class EmaneModel(WirelessModel): """ return cls.configure(session.emane, config_data) - @classmethod - def emane074_fixup(cls, value, div=1.0): - """ - Helper for converting 0.8.1 and newer values to EMANE 0.7.4 - compatible values. - NOTE: This should be removed when support for 0.7.4 has been - deprecated. - """ - if div == 0: - return "0" - if type(value) is not str: - return str(value / div) - if value.endswith(tuple(cls._prefix.keys())): - suffix = value[-1] - value = float(value[:-1]) * cls._prefix[suffix] - return str(int(value / div)) - def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. @@ -98,22 +80,21 @@ class EmaneModel(WirelessModel): """ ttype = ifc.transport_type if not ttype: - logger.info("warning: %s interface type unsupported!" % ifc.name) + logger.info("warning: %s interface type unsupported!", ifc.name) ttype = "raw" + trans = doc.createElement("transport") trans.setAttribute("definition", n.transportxmlname(ttype)) - if emane.VERSION < emane.EMANE092: - trans.setAttribute("group", "1") param = doc.createElement("param") param.setAttribute("name", "device") + if ttype == "raw": # raw RJ45 name e.g. "eth0" param.setAttribute("value", ifc.name) else: # virtual TAP name e.g. "n3.0.17" param.setAttribute("value", ifc.localname) - if emane.VERSION > emane.EMANE091: - param.setAttribute("value", ifc.name) + param.setAttribute("value", ifc.name) trans.appendChild(param) return trans @@ -126,12 +107,14 @@ class EmaneModel(WirelessModel): """ emane = self.session.emane name = "n%s" % self.object_id + if interface is not None: nodenum = interface.node.objid # Adamson change - use getifcconfig() to get proper result # if emane.getconfig(nodenum, self._name, None)[1] is not None: if emane.getifcconfig(nodenum, self.name, None, interface) is not None: name = interface.localname.replace(".", "_") + return "%s%s" % (name, self.name) def nemxmlname(self, interface=None): @@ -139,9 +122,8 @@ class EmaneModel(WirelessModel): Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml" """ append = "" - if emane.VERSION > emane.EMANE091: - if interface and interface.transport_type == "raw": - append = "_raw" + if interface and interface.transport_type == "raw": + append = "_raw" return "%snem%s.xml" % (self.basename(interface), append) def shimxmlname(self, ifc=None): diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 56868201..fecb491d 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -2,80 +2,54 @@ ieee80211abg.py: EMANE IEEE 802.11abg model for CORE """ -from core import emane from core.emane.emanemodel import EmaneModel from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes class EmaneIeee80211abgModel(EmaneModel): - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - # model name name = "emane_ieee80211abg" _80211rates = "1 1 Mbps,2 2 Mbps,3 5.5 Mbps,4 11 Mbps,5 6 Mbps," + \ "6 9 Mbps,7 12 Mbps,8 18 Mbps,9 24 Mbps,10 36 Mbps,11 48 Mbps," + \ "12 54 Mbps" - if emane.VERSION >= emane.EMANE091: - xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" - else: - xml_path = "/usr/share/emane/models/ieee80211abg/xml" + xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" # MAC parameters _confmatrix_mac_base = [ - ("mode", ConfigDataTypes.UINT8.value, "0", - "0 802.11b (DSSS only),1 802.11b (DSSS only)," + + ("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," + "2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable promiscuous mode"), - ("distance", ConfigDataTypes.UINT32.value, "1000", - "", "max distance (m)"), - ("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, - "unicast rate (Mbps)"), - ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, - "multicast rate (Mbps)"), - ("rtsthreshold", ConfigDataTypes.UINT16.value, "0", - "", "RTS threshold (bytes)"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, - "%s/ieee80211pcr.xml" % xml_path, - "", "SINR/PCR curve file"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", - "", "number of flow control tokens"), + ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), + ("distance", ConfigDataTypes.UINT32.value, "1000", "", "max distance (m)"), + ("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, "unicast rate (Mbps)"), + ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"), + ("rtsthreshold", ConfigDataTypes.UINT16.value, "0", "", "RTS threshold (bytes)"), + ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/ieee80211pcr.xml" % xml_path, "", "SINR/PCR curve file"), + ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), + ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), ] + # mac parameters introduced in EMANE 0.8.1 # Note: The entry format for category queue parameters (queuesize, aifs, etc) were changed in # EMANE 9.x, but are being preserved for the time being due to space constraints in the # CORE GUI. A conversion function (get9xmacparamequivalent) has been defined to support this. _confmatrix_mac_extended = [ - ("wmmenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "WiFi Multimedia (WMM)"), - ("queuesize", ConfigDataTypes.STRING.value, "0:255 1:255 2:255 3:255", - "", "queue size (0-4:size)"), - ("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", - "", "min contention window (0-4:minw)"), - ("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", - "", "max contention window (0-4:maxw)"), - ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", - "", "arbitration inter frame space (0-4:aifs)"), - ("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", - "", "txop (0-4:usec)"), - ("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", - "", "retry limit (0-4:numretries)"), + ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), + ("queuesize", ConfigDataTypes.STRING.value, "0:255 1:255 2:255 3:255", "", "queue size (0-4:size)"), + ("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", "", "min contention window (0-4:minw)"), + ("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", "", "max contention window (0-4:maxw)"), + ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), + ("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", "", "txop (0-4:usec)"), + ("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", "", "retry limit (0-4:numretries)"), ] _confmatrix_mac_091 = [ - ("radiometricenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "report radio metrics via R2RI"), - ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", - "", "R2RI radio metric report interval (sec)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", - "", "R2RI neighbor table inactivity time (sec)"), + ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), + ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", + "R2RI radio metric report interval (sec)"), + ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", + "R2RI neighbor table inactivity time (sec)"), ] - _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_extended - if emane.VERSION >= emane.EMANE091: - _confmatrix_mac += _confmatrix_mac_091 + _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_extended + _confmatrix_mac_091 # PHY parameters from Universal PHY _confmatrix_phy = EmaneUniversalModel.config_matrix @@ -85,6 +59,9 @@ class EmaneIeee80211abgModel(EmaneModel): config_groups = "802.11 MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. @@ -118,13 +95,10 @@ class EmaneIeee80211abgModel(EmaneModel): phynames = names[len(self._confmatrix_mac):] # append all MAC options to macdoc - if emane.VERSION >= emane.EMANE091: - for macname in macnames: - mac9xnvpairlist = self.get9xmacparamequivalent(macname, values) - for nvpair in mac9xnvpairlist: - mac.appendChild(e.xmlparam(macdoc, nvpair[0], nvpair[1])) - else: - map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames) + for macname in macnames: + mac9xnvpairlist = self.get9xmacparamequivalent(macname, values) + for nvpair in mac9xnvpairlist: + mac.appendChild(e.xmlparam(macdoc, nvpair[0], nvpair[1])) e.xmlwrite(macdoc, self.macxmlname(ifc)) @@ -145,6 +119,7 @@ class EmaneIeee80211abgModel(EmaneModel): """ nvpairlist = [] macparmval = self.valueof(macname, values) + if macname in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit"]: for catval in macparmval.split(): idx_and_val = catval.split(":") @@ -157,4 +132,5 @@ class EmaneIeee80211abgModel(EmaneModel): nvpairlist.append([name9x, val]) else: nvpairlist.append([macname, macparmval]) + return nvpairlist diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index f0e5bf57..b491f9ce 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -4,9 +4,8 @@ control of an EMANE emulation. An EmaneNode has several attached NEMs that share the same MAC+PHY model. """ -from os import path +import os -from core import emane from core import logger from core.coreobj import PyCoreNet from core.enumerations import LinkTypes @@ -21,12 +20,6 @@ except ImportError: except ImportError: logger.info("emane 0.9.1+ not found") -try: - import emaneeventservice - import emaneeventlocation -except ImportError: - logger.info("emane < 0.9.1 not found") - class EmaneNet(PyCoreNet): """ @@ -125,8 +118,9 @@ class EmaneNode(EmaneNet): """ ret = {} if self.model is None: - logger.info("warning: EmaneNode %s has no associated model" % self.name) + logger.info("warning: EmaneNode %s has no associated model", self.name) return ret + for netif in self.netifs(): # nementry = self.model.buildplatformxmlnementry(doc, self, netif) @@ -145,13 +139,16 @@ class EmaneNode(EmaneNet): """ if self.model is None: return + # build XML for overall network (EmaneNode) configs self.model.buildnemxmlfiles(emane, ifc=None) + # build XML for specific interface (NEM) configs need_virtual = False need_raw = False vtype = "virtual" rtype = "raw" + for netif in self.netifs(): self.model.buildnemxmlfiles(emane, netif) if "virtual" in netif.transport_type: @@ -160,39 +157,42 @@ class EmaneNode(EmaneNet): else: need_raw = True rtype = netif.transport_type + # build transport XML files depending on type of interfaces involved if need_virtual: self.buildtransportxml(emane, vtype) + if need_raw: self.buildtransportxml(emane, rtype) - def buildtransportxml(self, emane, type): + def buildtransportxml(self, emane, transport_type): """ Write a transport XML file for the Virtual or Raw Transport. """ transdoc = emane.xmldoc("transport") trans = transdoc.getElementsByTagName("transport").pop() - trans.setAttribute("name", "%s Transport" % type.capitalize()) - trans.setAttribute("library", "trans%s" % type.lower()) + trans.setAttribute("name", "%s Transport" % transport_type.capitalize()) + trans.setAttribute("library", "trans%s" % transport_type.lower()) trans.appendChild(emane.xmlparam(transdoc, "bitrate", "0")) flowcontrol = False names = self.model.getnames() - values = emane.getconfig(self.objid, self.model.name, - self.model.getdefaultvalues())[1] + values = emane.getconfig(self.objid, self.model.name, self.model.getdefaultvalues())[1] + if "flowcontrolenable" in names and values: i = names.index("flowcontrolenable") if self.model.booltooffon(values[i]) == "on": flowcontrol = True - if "virtual" in type.lower(): - if path.exists("/dev/net/tun_flowctl"): + if "virtual" in transport_type.lower(): + if os.path.exists("/dev/net/tun_flowctl"): trans.appendChild(emane.xmlparam(transdoc, "devicepath", "/dev/net/tun_flowctl")) else: trans.appendChild(emane.xmlparam(transdoc, "devicepath", "/dev/net/tun")) if flowcontrol: trans.appendChild(emane.xmlparam(transdoc, "flowcontrolenable", "on")) - emane.xmlwrite(transdoc, self.transportxmlname(type.lower())) + + emane.xmlwrite(transdoc, self.transportxmlname(transport_type.lower())) def transportxmlname(self, type): """ @@ -247,29 +247,15 @@ class EmaneNode(EmaneNet): if nemid is None: logger.info("nemid for %s is unknown" % ifname) return - (lat, long, alt) = self.session.location.getgeo(x, y, z) - logger.info("setnemposition %s (%s) x,y,z=(%d,%d,%s)" - "(%.6f,%.6f,%.6f)" % \ - (ifname, nemid, x, y, z, lat, long, alt)) - if emane.VERSION >= emane.EMANE091: - event = LocationEvent() - else: - event = emaneeventlocation.EventLocation(1) + lat, long, alt = self.session.location.getgeo(x, y, z) + logger.info("setnemposition %s (%s) x,y,z=(%d,%d,%s)(%.6f,%.6f,%.6f)", ifname, nemid, x, y, z, lat, long, alt) + event = LocationEvent() + # altitude must be an integer or warning is printed # unused: yaw, pitch, roll, azimuth, elevation, velocity alt = int(round(alt)) - if emane.VERSION >= emane.EMANE091: - event.append(nemid, latitude=lat, longitude=long, altitude=alt) - self.session.emane.service.publish(0, event) - else: - event.set(0, nemid, lat, long, alt) - self.session.emane.service.publish( - emaneeventlocation.EVENT_ID, - emaneeventservice.PLATFORMID_ANY, - emaneeventservice.NEMID_ANY, - emaneeventservice.COMPONENTID_ANY, - event.export() - ) + event.append(nemid, latitude=lat, longitude=long, altitude=alt) + self.session.emane.service.publish(0, event) def setnempositions(self, moved_netifs): """ @@ -279,14 +265,12 @@ class EmaneNode(EmaneNet): """ if len(moved_netifs) == 0: return + if self.session.emane.service is None: logger.info("position service not available") return - if emane.VERSION >= emane.EMANE091: - event = LocationEvent() - else: - event = emaneeventlocation.EventLocation(len(moved_netifs)) + event = LocationEvent() i = 0 for netif in moved_netifs: nemid = self.getnemid(netif) @@ -294,26 +278,13 @@ class EmaneNode(EmaneNet): if nemid is None: logger.info("nemid for %s is unknown" % ifname) continue - (x, y, z) = netif.node.getposition() - (lat, long, alt) = self.session.location.getgeo(x, y, z) - logger.info("setnempositions %d %s (%s) x,y,z=(%d,%d,%s)" - "(%.6f,%.6f,%.6f)" % - (i, ifname, nemid, x, y, z, lat, long, alt)) + x, y, z = netif.node.getposition() + lat, long, alt = self.session.location.getgeo(x, y, z) + logger.info("setnempositions %d %s (%s) x,y,z=(%d,%d,%s)(%.6f,%.6f,%.6f)", + i, ifname, nemid, x, y, z, lat, long, alt) # altitude must be an integer or warning is printed alt = int(round(alt)) - if emane.VERSION >= emane.EMANE091: - event.append(nemid, latitude=lat, longitude=long, altitude=alt) - else: - event.set(i, nemid, lat, long, alt) + event.append(nemid, latitude=lat, longitude=long, altitude=alt) i += 1 - if emane.VERSION >= emane.EMANE091: - self.session.emane.service.publish(0, event) - else: - self.session.emane.service.publish( - emaneeventlocation.EVENT_ID, - emaneeventservice.PLATFORMID_ANY, - emaneeventservice.NEMID_ANY, - emaneeventservice.COMPONENTID_ANY, - event.export() - ) + self.session.emane.service.publish(0, event) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 3b88ff5f..26533e27 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -2,65 +2,36 @@ rfpipe.py: EMANE RF-PIPE model for CORE """ -from core import emane from core.emane.emanemodel import EmaneModel from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes class EmaneRfPipeModel(EmaneModel): - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - # model name name = "emane_rfpipe" - if emane.VERSION >= emane.EMANE091: - xml_path = "/usr/share/emane/xml/models/mac/rfpipe" - else: - xml_path = "/usr/share/emane/models/rfpipe/xml" + xml_path = "/usr/share/emane/xml/models/mac/rfpipe" # configuration parameters are # ( "name", "type", "default", "possible-value-list", "caption") # MAC parameters _confmatrix_mac_base = [ - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", - "True,False", "enable promiscuous mode"), - ("datarate", ConfigDataTypes.UINT32.value, "1M", - "", "data rate (bps)"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", - "", "number of flow control tokens"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, - "%s/rfpipepcr.xml" % xml_path, - "", "SINR/PCR curve file"), - ] - _confmatrix_mac_081 = [ - ("jitter", ConfigDataTypes.FLOAT.value, "0.0", - "", "transmission jitter (usec)"), - ("delay", ConfigDataTypes.FLOAT.value, "0.0", - "", "transmission delay (usec)"), - ("transmissioncontrolmap", ConfigDataTypes.STRING.value, "", - "", "tx control map (nem:rate:freq:tx_dBm)"), - ("enabletighttiming", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable tight timing for pkt delay"), + ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), + ("datarate", ConfigDataTypes.UINT32.value, "1M", "", "data rate (bps)"), + ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), + ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), + ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/rfpipepcr.xml" % xml_path, "", "SINR/PCR curve file"), ] _confmatrix_mac_091 = [ - ("jitter", ConfigDataTypes.FLOAT.value, "0.0", - "", "transmission jitter (sec)"), - ("delay", ConfigDataTypes.FLOAT.value, "0.0", - "", "transmission delay (sec)"), - ("radiometricenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "report radio metrics via R2RI"), - ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", - "", "R2RI radio metric report interval (sec)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", - "", "R2RI neighbor table inactivity time (sec)"), + ("jitter", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission jitter (sec)"), + ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), + ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), + ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", + "R2RI radio metric report interval (sec)"), + ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", + "R2RI neighbor table inactivity time (sec)"), ] - if emane.VERSION >= emane.EMANE091: - _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_091 - else: - _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_081 + _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_091 # PHY parameters from Universal PHY _confmatrix_phy = EmaneUniversalModel.config_matrix @@ -71,6 +42,9 @@ class EmaneRfPipeModel(EmaneModel): config_groups = "RF-PIPE MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. @@ -78,10 +52,10 @@ class EmaneRfPipeModel(EmaneModel): that file also. Otherwise the WLAN-wide nXXemane_rfpipenem.xml, nXXemane_rfpipemac.xml, nXXemane_rfpipephy.xml are used. """ - values = e.getifcconfig(self.object_id, self.name, - self.getdefaultvalues(), ifc) + values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) if values is None: return + nemdoc = e.xmldoc("nem") nem = nemdoc.getElementsByTagName("nem").pop() nem.setAttribute("name", "RF-PIPE NEM") @@ -102,15 +76,9 @@ class EmaneRfPipeModel(EmaneModel): mac = macdoc.getElementsByTagName("mac").pop() mac.setAttribute("name", "RF-PIPE MAC") mac.setAttribute("library", "rfpipemaclayer") - if emane.VERSION < emane.EMANE091 and \ - self.valueof("transmissioncontrolmap", values) is "": + if self.valueof("transmissioncontrolmap", values) is "": macnames.remove("transmissioncontrolmap") - # EMANE 0.7.4 support - if emane.VERSION == emane.EMANE074: - # convert datarate from bps to kbps - i = names.index("datarate") - values = list(values) - values[i] = self.emane074_fixup(values[i], 1000) + # append MAC options to macdoc map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames) e.xmlwrite(macdoc, self.macxmlname(ifc)) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index e12eb9b6..91d60f67 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -2,8 +2,6 @@ tdma.py: EMANE TDMA model bindings for CORE """ -from core import emane -from core import logger from core.emane.emanemodel import EmaneModel from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes @@ -16,37 +14,30 @@ class EmaneTdmaModel(EmaneModel): # model name name = "emane_tdma" xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler" - if emane.VERSION < emane.EMANE101: - logger.error("EMANE TDMA requires EMANE 1.0.1 or greater") # MAC parameters _confmatrix_mac = [ - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", - "True,False", "enable promiscuous mode"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", - "", "number of flow control tokens"), - ("fragmentcheckthreshold", ConfigDataTypes.UINT16.value, "2", - "", "rate in seconds for check if fragment reassembly efforts should be abandoned"), - ("fragmenttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", - "", "threshold in seconds to wait for another packet fragment for reassembly"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", - "", "neighbor RF reception timeout for removal from neighbor table (sec)"), - ("neighbormetricupdateinterval", ConfigDataTypes.FLOAT.value, "1.0", - "", "neighbor table update interval (sec)"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/tdmabasemodelpcr.xml" % xml_path, - "", "SINR/PCR curve file"), - ("queue.aggregationenable", ConfigDataTypes.BOOL.value, "1", - "On,Off", "enable transmit packet aggregation"), - ("queue.aggregationslotthreshold", ConfigDataTypes.FLOAT.value, "90.0", - "", "percentage of a slot that must be filled in order to conclude aggregation"), - ("queue.depth", ConfigDataTypes.UINT16.value, "256", - "", "size of the per service class downstream packet queues (packets)"), - ("queue.fragmentationenable", ConfigDataTypes.BOOL.value, "1", - "On,Off", "enable packet fragmentation (over multiple slots)"), - ("queue.strictdequeueenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable strict dequeueing to specified queues only"), + ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), + ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), + ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), + ("fragmentcheckthreshold", ConfigDataTypes.UINT16.value, "2", "", + "rate in seconds for check if fragment reassembly efforts should be abandoned"), + ("fragmenttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", "", + "threshold in seconds to wait for another packet fragment for reassembly"), + ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", + "neighbor RF reception timeout for removal from neighbor table (sec)"), + ("neighbormetricupdateinterval", ConfigDataTypes.FLOAT.value, "1.0", "", + "neighbor table update interval (sec)"), + ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/tdmabasemodelpcr.xml" % xml_path, "", "SINR/PCR curve file"), + ("queue.aggregationenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable transmit packet aggregation"), + ("queue.aggregationslotthreshold", ConfigDataTypes.FLOAT.value, "90.0", "", + "percentage of a slot that must be filled in order to conclude aggregation"), + ("queue.depth", ConfigDataTypes.UINT16.value, "256", "", + "size of the per service class downstream packet queues (packets)"), + ("queue.fragmentationenable", ConfigDataTypes.BOOL.value, "1", "On,Off", + "enable packet fragmentation (over multiple slots)"), + ("queue.strictdequeueenable", ConfigDataTypes.BOOL.value, "0", "On,Off", + "enable strict dequeueing to specified queues only"), ] # PHY parameters from Universal PHY @@ -68,6 +59,7 @@ class EmaneTdmaModel(EmaneModel): values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) if values is None: return + nemdoc = e.xmldoc("nem") nem = nemdoc.getElementsByTagName("nem").pop() nem.setAttribute("name", "TDMA NEM") diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 619606b8..0c7fa355 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -3,7 +3,6 @@ universal.py: EMANE Universal PHY model for CORE. Enumerates configuration items used for the Universal PHY. """ -from core import emane from core.emane.emanemodel import EmaneModel from core.enumerations import ConfigDataTypes @@ -36,28 +35,6 @@ class EmaneUniversalModel(EmaneModel): ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), ] - _confmatrix_081 = [ - ("antennagain", ConfigDataTypes.FLOAT.value, "0.0", - "", "antenna gain (dBi)"), - ("antennaazimuth", ConfigDataTypes.FLOAT.value, "0.0", - "", "antenna azimuth (deg)"), - ("antennaelevation", ConfigDataTypes.FLOAT.value, "0.0", - "", "antenna elevation (deg)"), - ("antennaprofileid", ConfigDataTypes.STRING.value, "1", - "", "antenna profile ID"), - ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", - "", "antenna profile manifest URI"), - ("antennaprofileenable", ConfigDataTypes.BOOL.value, "0", - "On,Off", "antenna profile mode"), - ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", - "On,Off", "default connectivity"), - ("frequencyofinterestfilterenable", ConfigDataTypes.BOOL.value, "1", - "On,Off", "frequency of interest filter enable"), - ("noiseprocessingmode", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable noise processing"), - ("pathlossmode", ConfigDataTypes.STRING.value, "2ray", - "pathloss,2ray,freespace", "path loss mode"), - ] _confmatrix_091 = [ ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), @@ -70,63 +47,24 @@ class EmaneUniversalModel(EmaneModel): ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), ] - if emane.VERSION >= emane.EMANE091: - config_matrix = _confmatrix_base + _confmatrix_091 - else: - config_matrix = _confmatrix_base + _confmatrix_081 - - # old parameters - _confmatrix_ver074 = [ - ("antennaazimuthbeamwidth", ConfigDataTypes.FLOAT.value, "360.0", - "", "azimith beam width (deg)"), - ("antennaelevationbeamwidth", ConfigDataTypes.FLOAT.value, "180.0", - "", "elevation beam width (deg)"), - ("antennatype", ConfigDataTypes.STRING.value, "omnidirectional", - "omnidirectional,unidirectional", "antenna type"), - ] - - # parameters that require unit conversion for 0.7.4 - _update_ver074 = ("bandwidth", "frequency", "frequencyofinterest") - # parameters that should be removed for 0.7.4 - _remove_ver074 = ("antennaprofileenable", "antennaprofileid", - "antennaprofilemanifesturi", - "frequencyofinterestfilterenable") + config_matrix = _confmatrix_base + _confmatrix_091 @classmethod def getphydoc(cls, e, mac, values, phynames): phydoc = e.xmldoc("phy") phy = phydoc.getElementsByTagName("phy").pop() phy.setAttribute("name", cls._xmlname) - if emane.VERSION < emane.EMANE091: - phy.setAttribute("library", cls._xmllibrary) - # EMANE 0.7.4 suppport - to be removed when 0.7.4 support is deprecated - if emane.VERSION == emane.EMANE074: - names = mac.getnames() - values = list(values) - phynames = list(phynames) - # update units for some parameters - for p in cls._update_ver074: - i = names.index(p) - # these all happen to be KHz, so 1000 is used - values[i] = cls.emane074_fixup(values[i], 1000) - # remove new incompatible options - for p in cls._remove_ver074: - phynames.remove(p) - # insert old options with their default values - for old in cls._confmatrix_ver074: - phy.appendChild(e.xmlparam(phydoc, old[0], old[2])) - frequencies = None - if emane.VERSION >= emane.EMANE091: - name = "frequencyofinterest" - value = mac.valueof(name, values) - frequencies = cls.valuestrtoparamlist(phydoc, name, value) - if frequencies: - phynames = list(phynames) - phynames.remove("frequencyofinterest") + name = "frequencyofinterest" + value = mac.valueof(name, values) + frequencies = cls.valuestrtoparamlist(phydoc, name, value) + if frequencies: + phynames = list(phynames) + phynames.remove("frequencyofinterest") # append all PHY options to phydoc map(lambda n: phy.appendChild(e.xmlparam(phydoc, n, mac.valueof(n, values))), phynames) if frequencies: phy.appendChild(frequencies) + return phydoc diff --git a/daemon/core/xml/xmldeployment.py b/daemon/core/xml/xmldeployment.py index 180a56f5..65b496e9 100644 --- a/daemon/core/xml/xmldeployment.py +++ b/daemon/core/xml/xmldeployment.py @@ -2,11 +2,11 @@ import os import socket from core import constants -from core import emane from core import logger from core.enumerations import NodeTypes -from core.misc import ipaddress, utils +from core.misc import ipaddress from core.misc import nodeutils +from core.misc import utils from core.netns import nodes from core.xml import xmlutils @@ -17,9 +17,6 @@ class CoreDeploymentWriter(object): self.root = root self.session = session self.hostname = socket.gethostname() - if emane.VERSION < emane.EMANE092: - self.transport = None - self.platform = None @staticmethod def get_ipv4_addresses(hostname): @@ -185,18 +182,8 @@ class CoreDeploymentWriter(object): def add_emane_interface(self, physical_host, virtual_host, netif, platform_name='p1', transport_name='t1'): nemid = netif.net.nemidmap[netif] - if emane.VERSION < emane.EMANE092: - if self.platform is None: - self.platform = \ - self.add_platform(physical_host, name=platform_name) - platform = self.platform - if self.transport is None: - self.transport = \ - self.add_transport(physical_host, name=transport_name) - transport = self.transport - else: - platform = self.add_platform(virtual_host, name=platform_name) - transport = self.add_transport(virtual_host, name=transport_name) + platform = self.add_platform(virtual_host, name=platform_name) + transport = self.add_transport(virtual_host, name=transport_name) nem_name = 'nem%s' % nemid nem = self.add_nem(platform, nem_name) self.add_parameter(nem, 'nemid', str(nemid)) diff --git a/daemon/examples/netns/wlanemanetests.py b/daemon/examples/netns/wlanemanetests.py index 6c9617a3..172732e3 100755 --- a/daemon/examples/netns/wlanemanetests.py +++ b/daemon/examples/netns/wlanemanetests.py @@ -636,7 +636,7 @@ class Experiment(object): self.info("%s initial test ping (max 1 second)..." % \ self.firstnode.name) (status, result) = self.firstnode.cmd_output(["ping", "-q", "-c", "1", - "-w", "1", self.lastaddr]) + "-w", "1", self.lastaddr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % \ (self.firstnode.name, self.lastaddr, result)) @@ -706,11 +706,6 @@ def main(): exp = Experiment(opt=opt, start=starttime) exp.info("Starting wlanemanetests.py tests %s" % starttime.ctime()) - # system sanity checks here - emanever, emaneverstr = emane.VERSION, emane.VERSIONSTR - if opt.verbose: - exp.info("Detected EMANE version %s" % (emaneverstr,)) - # bridged exp.info("setting up bridged tests 1/2 no link effects") exp.info("creating topology: numnodes = %s" % (opt.numnodes,)) From 79b2fa84689d8e93e607a68b21bd9221481f945e Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 20 Mar 2018 14:35:00 -0700 Subject: [PATCH 087/152] forgot to remove a line of old emane code in rfpipe --- daemon/core/emane/rfpipe.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 26533e27..98eb2337 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -76,8 +76,6 @@ class EmaneRfPipeModel(EmaneModel): mac = macdoc.getElementsByTagName("mac").pop() mac.setAttribute("name", "RF-PIPE MAC") mac.setAttribute("library", "rfpipemaclayer") - if self.valueof("transmissioncontrolmap", values) is "": - macnames.remove("transmissioncontrolmap") # append MAC options to macdoc map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames) From 5629ea02455ffa4c0939994ccabaa073facb0405 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 20 Mar 2018 14:38:48 -0700 Subject: [PATCH 088/152] fixed issue with bad pathing for quagga run state dir --- daemon/core/constants.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index 7dea1ad8..8be82eda 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -11,7 +11,7 @@ SYSCTL_BIN = "@sysctl_path@/sysctl" IP_BIN = "@ip_path@/ip" TC_BIN = "@tc_path@/tc" EBTABLES_BIN = "@ebtables_path@/ebtables" -QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" +QUAGGA_STATE_DIR = "/var/run/quagga" MOUNT_BIN = "@mount_path@/mount" UMOUNT_BIN = "@umount_path@/umount" OVS_BIN = "@ovs_vs_path@/ovs-vsctl" From 5403b10cef6fae64f394517937ddec2dae777404 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 20 Mar 2018 14:49:17 -0700 Subject: [PATCH 089/152] update to set CORE_STATE_DIR to /var --- configure.ac | 2 +- daemon/core/constants.py.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 7cd95b33..7109977e 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ CORE_LIB_DIR="\${prefix}/lib/core" CORE_CONF_DIR="/etc/core" CORE_DATA_DIR="\${datarootdir}/core" # TODO: verify there is need to hard set /var -CORE_STATE_DIR="\${localstatedir}" +CORE_STATE_DIR="/var" AC_SUBST(PACKAGE_DATE) AC_SUBST(PACKAGE_MAINTAINERS) diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index 8be82eda..7dea1ad8 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -11,7 +11,7 @@ SYSCTL_BIN = "@sysctl_path@/sysctl" IP_BIN = "@ip_path@/ip" TC_BIN = "@tc_path@/tc" EBTABLES_BIN = "@ebtables_path@/ebtables" -QUAGGA_STATE_DIR = "/var/run/quagga" +QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" MOUNT_BIN = "@mount_path@/mount" UMOUNT_BIN = "@umount_path@/umount" OVS_BIN = "@ovs_vs_path@/ovs-vsctl" From ba8b73af41a2792160c8212e739903d4d9d7ad68 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 09:57:08 -0700 Subject: [PATCH 090/152] added some more logging to emane setup/startup --- daemon/core/emane/emanemanager.py | 40 +++++++++++++++++++------------ daemon/core/emane/nodes.py | 2 +- daemon/core/session.py | 2 ++ 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 951c4ea6..9f04511b 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -145,7 +145,7 @@ class EmaneManager(ConfigurableManager): # disabled otachannel for event service # only needed for e.g. antennaprofile events xmit by models - logger.info("Using %s for event service traffic" % eventdev) + logger.info("Using %s for event service traffic", eventdev) try: self.service = EventService(eventchannel=eventchannel, otachannel=None) except EventServiceException: @@ -238,22 +238,28 @@ class EmaneManager(ConfigurableManager): Emane.(SUCCESS, NOT_NEEDED, NOT_READY) in order to delay session instantiation. """ + logger.debug("emane setup") # TODO: drive this from the session object with self.session._objects_lock: for node in self.session.objects.itervalues(): if nodeutils.is_node(node, NodeTypes.EMANE): + logger.debug("adding emane node: id(%s) name(%s)", node.objid, node.name) self.add_node(node) + if not self._emane_nodes: + logger.debug("no emane nodes in session") return EmaneManager.NOT_NEEDED # control network bridge required for EMANE 0.9.2 # - needs to be configured before checkdistributed() for distributed # - needs to exist when eventservice binds to it (initeventservice) if self.session.master: - values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] + values = self.getconfig(None, self.emane_config.name, self.emane_config.getdefaultvalues())[1] + logger.debug("emane config default values: %s", values) otadev = self.emane_config.valueof("otamanagerdevice", values) netidx = self.session.get_control_net_index(otadev) + logger.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev) if netidx < 0: logger.error("EMANE cannot start, check core config. invalid OTA device provided: %s", otadev) return EmaneManager.NOT_READY @@ -261,8 +267,10 @@ class EmaneManager(ConfigurableManager): ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False) self.distributedctrlnet(ctrlnet) eventdev = self.emane_config.valueof("eventservicedevice", values) + logger.debug("emane event service device: eventdev(%s)", eventdev) if eventdev != otadev: netidx = self.session.get_control_net_index(eventdev) + logger.debug("emane event service device index: %s", netidx) if netidx < 0: logger.error("EMANE cannot start, check core config. invalid event service device: %s", eventdev) return EmaneManager.NOT_READY @@ -391,7 +399,7 @@ class EmaneManager(ConfigurableManager): with self._emane_node_lock: if self._emane_nodes: master = self.session.master - logger.info("Setup EMANE with master=%s." % master) + logger.info("emane check distributed as master: %s.", master) # we are not the master Emane object, wait for nem id and ports if not master: @@ -535,15 +543,18 @@ class EmaneManager(ConfigurableManager): Associate EmaneModel classes with EmaneNode nodes. The model configurations are stored in self.configs. """ - for emane_node in self._emane_nodes: - self.setnodemodel(emane_node) + for key in self._emane_nodes: + self.setnodemodel(key) - def setnodemodel(self, n): - emanenode = self._emane_nodes[n] - if n not in self.configs: + def setnodemodel(self, key): + logger.debug("setting emane node model: %s", key) + emane_node = self._emane_nodes[key] + if key not in self.configs: + logger.debug("no emane node model configuration, leaving") return False - for t, v in self.configs[n]: + for t, v in self.configs[key]: + logger.debug("configuration: key(%s) value(%s)", t, v) if t is None: continue if t == self.emane_config.name: @@ -552,7 +563,7 @@ class EmaneManager(ConfigurableManager): # only use the first valid EmaneModel # convert model name to class (e.g. emane_rfpipe -> EmaneRfPipe) cls = self._modelclsmap[t] - emanenode.setmodel(cls, v) + emane_node.setmodel(cls, v) return True # no model has been configured for this EmaneNode @@ -777,8 +788,8 @@ class EmaneManager(ConfigurableManager): args = emanecmd + ["-f", os.path.join(path, "emane%d.log" % n), os.path.join(path, "platform%d.xml" % n)] output = node.check_cmd(args) - logger.info("emane daemon running: %s", args) - logger.info("emane daemon output: %s", output) + logger.info("node(%s) emane daemon running: %s", node.name, args) + logger.info("node(%s) emane daemon output: %s", node.name, output) if not run_emane_on_host: return @@ -787,7 +798,7 @@ class EmaneManager(ConfigurableManager): emanecmd += ["-f", os.path.join(path, "emane.log")] args = emanecmd + [os.path.join(path, "platform.xml")] utils.check_cmd(args, cwd=path) - logger.info("emane daemon running: %s", args) + logger.info("host emane daemon running: %s", args) def stopdaemons(self): """ @@ -908,8 +919,7 @@ class EmaneManager(ConfigurableManager): """ if self.service is None: return - logger.info("subscribing to EMANE location events (not generating them). (%s)", - threading.currentThread().getName()) + logger.info("subscribing to EMANE location events. (%s)", threading.currentThread().getName()) while self.doeventloop is True: uuid, seq, events = self.service.nextEvent() diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index b491f9ce..fd7f32b6 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -221,7 +221,7 @@ class EmaneNode(EmaneNet): # at this point we register location handlers for generating # EMANE location events netif.poshook = self.setnemposition - (x, y, z) = netif.node.position.get() + x, y, z = netif.node.position.get() self.setnemposition(netif, x, y, z) def deinstallnetifs(self): diff --git a/daemon/core/session.py b/daemon/core/session.py index d87d201e..81ee8b04 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -1022,6 +1022,7 @@ class Session(object): :return: control net object :rtype: core.netns.nodes.CtrlNet """ + logger.debug("add/remove control net: index(%s) remove(%s) conf_required(%s)", net_index, remove, conf_required) prefix_spec_list = self.get_control_net_prefixes() prefix_spec = prefix_spec_list[net_index] if not prefix_spec: @@ -1031,6 +1032,7 @@ class Session(object): else: control_net_class = nodeutils.get_node_class(NodeTypes.CONTROL_NET) prefix_spec = control_net_class.DEFAULT_PREFIX_LIST[net_index] + logger.debug("prefix spec: %s", prefix_spec) server_interface = self.get_control_net_server_interfaces()[net_index] From 802393725ead4892943dd65c82bb4fb66c9b0052 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 11:58:01 -0700 Subject: [PATCH 091/152] added new emane platform options from older versions and latest 1.2.1 --- daemon/core/emane/emanemanager.py | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 9f04511b..c3f6cba6 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -617,8 +617,11 @@ class EmaneManager(ConfigurableManager): platform_values[i] = eventdev # append all platform options (except starting id) to doc - map(lambda n: plat.appendChild(self.xmlparam(doc, n, self.emane_config.valueof(n, platform_values))), - platform_names) + for name in platform_names: + value = self.emane_config.valueof(name, platform_values) + param = self.xmlparam(doc, name, value) + plat.appendChild(param) + return doc def buildplatformxml(self, ctrlnet): @@ -1024,6 +1027,21 @@ class EmaneGlobalModel(EmaneModel): _confmatrix_platform = [ ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", "", "Control port address"), ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", "", "antenna profile manifest URI"), + ("eventservicettl", ConfigDataTypes.INT8.value, "1", "", "Event Service TTL"), + ("otamanagerloopback", ConfigDataTypes.BOOL.value, "0", "on,off", "Enable OTA multicast loopback"), + ("otamanagermtu", ConfigDataTypes.INT32.value, "0", "", "OTA channel MTU in bytes, 0 to disable"), + ("otamanagerpartcheckthreshold", ConfigDataTypes.INT16.value, "2", "", + "Rate in seconds a check is performed to see if any OTA packet part reassembly efforts should be abandoned"), + ("otamanagerparttimeoutthreshold", ConfigDataTypes.INT16.value, "5", "", + "Threshold in seconds to wait for another OTA packet part for an existing reassembly effort before " + "abandoning the effort"), + ("otamanagerttl", ConfigDataTypes.INT8.value, "1", "", "OTA channel multicast message TTL"), + ("stats.event.maxeventcountrows", ConfigDataTypes.INT32.value, "0", "", + "Event channel max event count table rows"), + ("stats.ota.maxeventcountrows", ConfigDataTypes.INT32.value, "0", "", + "OTA channel max event count table rows"), + ("stats.ota.maxpacketcountrows", ConfigDataTypes.INT32.value, "0", "", + "OTA channel max packet count table rows"), ] _confmatrix_platform = _confmatrix_platform_base + _confmatrix_platform From b6cfc2085c31a6e303ceabed50401cf8210abc41 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 12:54:13 -0700 Subject: [PATCH 092/152] attempt to update physical configuration --- daemon/core/emane/universal.py | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 0c7fa355..1491b089 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -22,30 +22,20 @@ class EmaneUniversalModel(EmaneModel): # universal PHY parameters _confmatrix_base = [ - ("bandwidth", ConfigDataTypes.UINT64.value, "1M", - "", "rf bandwidth (hz)"), - ("frequency", ConfigDataTypes.UINT64.value, "2.347G", - "", "frequency (Hz)"), - ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", - "", "frequency of interest (Hz)"), - ("subid", ConfigDataTypes.UINT16.value, "1", - "", "subid"), - ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", - "", "system noise figure (dB)"), - ("txpower", ConfigDataTypes.FLOAT.value, "0.0", - "", "transmit power (dBm)"), + ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), + ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), + ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), + ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), + ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), + ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), ] _confmatrix_091 = [ - ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", - "", "antenna gain (dBi)"), - ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", - "On,Off", "enable fixed antenna gain"), - ("noisemode", ConfigDataTypes.STRING.value, "none", - "none,all,outofband", "noise processing mode"), - ("noisebinsize", ConfigDataTypes.UINT64.value, "20", - "", "noise bin size in microseconds"), - ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", - "precomputed,2ray,freespace", "path loss mode"), + ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), + ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), + ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), + ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), + ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), + ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), ] config_matrix = _confmatrix_base + _confmatrix_091 From 86afded824b4301b1243d4c57db51780416ce404 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 14:24:33 -0700 Subject: [PATCH 093/152] updated emane options to contain all nakagami settings for display within ui, sorted options --- daemon/core/emane/emanemanager.py | 34 +++++++++++++---------------- daemon/core/emane/universal.py | 36 +++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index c3f6cba6..17b2be9b 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -1014,36 +1014,32 @@ class EmaneGlobalModel(EmaneModel): _DEFAULT_DEV = "ctrl0" name = "emane" - _confmatrix_platform_base = [ - ("otamanagerchannelenable", ConfigDataTypes.BOOL.value, _DEFAULT_OTA, "on,off", "enable OTA Manager channel"), - ("otamanagergroup", ConfigDataTypes.STRING.value, "224.1.2.8:45702", "", "OTA Manager group"), - ("otamanagerdevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "OTA Manager device"), - ("eventservicegroup", ConfigDataTypes.STRING.value, "224.1.2.8:45703", "", "Event Service group"), - ("eventservicedevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "Event Service device"), - ("platform_id_start", ConfigDataTypes.INT32.value, "1", "", "starting Platform ID"), - ] - # defined from 0.9.1 _confmatrix_platform = [ - ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", "", "Control port address"), ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", "", "antenna profile manifest URI"), - ("eventservicettl", ConfigDataTypes.INT8.value, "1", "", "Event Service TTL"), + ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", "", "Control port address"), + ("eventservicedevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "Event Service device"), + ("eventservicegroup", ConfigDataTypes.STRING.value, "224.1.2.8:45703", "", "Event Service group"), + ("eventservicettl", ConfigDataTypes.UINT8.value, "1", "", "Event Service TTL"), + ("otamanagerchannelenable", ConfigDataTypes.BOOL.value, _DEFAULT_OTA, "on,off", "enable OTA Manager channel"), + ("otamanagerdevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "OTA Manager device"), + ("otamanagergroup", ConfigDataTypes.STRING.value, "224.1.2.8:45702", "", "OTA Manager group"), ("otamanagerloopback", ConfigDataTypes.BOOL.value, "0", "on,off", "Enable OTA multicast loopback"), - ("otamanagermtu", ConfigDataTypes.INT32.value, "0", "", "OTA channel MTU in bytes, 0 to disable"), - ("otamanagerpartcheckthreshold", ConfigDataTypes.INT16.value, "2", "", + ("otamanagermtu", ConfigDataTypes.UINT32.value, "0", "", "OTA channel MTU in bytes, 0 to disable"), + ("otamanagerpartcheckthreshold", ConfigDataTypes.UINT16.value, "2", "", "Rate in seconds a check is performed to see if any OTA packet part reassembly efforts should be abandoned"), - ("otamanagerparttimeoutthreshold", ConfigDataTypes.INT16.value, "5", "", + ("otamanagerparttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", "", "Threshold in seconds to wait for another OTA packet part for an existing reassembly effort before " "abandoning the effort"), - ("otamanagerttl", ConfigDataTypes.INT8.value, "1", "", "OTA channel multicast message TTL"), - ("stats.event.maxeventcountrows", ConfigDataTypes.INT32.value, "0", "", + ("otamanagerttl", ConfigDataTypes.UINT8.value, "1", "", "OTA channel multicast message TTL"), + ("stats.event.maxeventcountrows", ConfigDataTypes.UINT32.value, "0", "", "Event channel max event count table rows"), - ("stats.ota.maxeventcountrows", ConfigDataTypes.INT32.value, "0", "", + ("stats.ota.maxeventcountrows", ConfigDataTypes.UINT32.value, "0", "", "OTA channel max event count table rows"), - ("stats.ota.maxpacketcountrows", ConfigDataTypes.INT32.value, "0", "", + ("stats.ota.maxpacketcountrows", ConfigDataTypes.UINT32.value, "0", "", "OTA channel max packet count table rows"), + ("platform_id_start", ConfigDataTypes.INT32.value, "1", "", "starting Platform ID"), ] - _confmatrix_platform = _confmatrix_platform_base + _confmatrix_platform # defined from 0.9.2 _confmatrix_nem = [ diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 1491b089..8b437aaa 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -21,23 +21,37 @@ class EmaneUniversalModel(EmaneModel): _xmllibrary = "universalphylayer" # universal PHY parameters - _confmatrix_base = [ + config_matrix = [ ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), - ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), - ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), - ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), - ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), - ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), - ] - _confmatrix_091 = [ + ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), + ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", + "Nakagami D0: distance lower bound in meters"), + ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", + "Nakagami D1: distance upper bound in meters"), + ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), + ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", + "Nakagami M1: shape factor for distance >= D0 < D1"), + ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", + "Nakagami M2: shape factor for distance >= D1"), ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), - ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), + ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), + ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), + ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), + ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", + "Noise maximum message propagation in microsecond"), + ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", + "Noise maximum segment duration in microseconds"), + ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", + "Noise maximum segment offset in microseconds"), + ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), - ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), + ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), + ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), + ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), + ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), ] - config_matrix = _confmatrix_base + _confmatrix_091 @classmethod def getphydoc(cls, e, mac, values, phynames): From 1a867b9d1b761f300e3e580ebc07514ff7f678cb Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 19:08:47 -0700 Subject: [PATCH 094/152] added debug logging for utility commands that are ran --- daemon/core/misc/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index f13f0152..5513c922 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -176,6 +176,7 @@ def cmd(args, wait=True): :rtype: int """ args = split_args(args) + logger.debug("command: %s", args) try: p = subprocess.Popen(args) if not wait: @@ -196,6 +197,7 @@ def cmd_output(args): :raises CoreCommandError: when the file to execute is not found """ args = split_args(args) + logger.debug("command: %s", args) try: p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, _ = p.communicate() @@ -219,6 +221,7 @@ def check_cmd(args, **kwargs): kwargs["stdout"] = subprocess.PIPE kwargs["stderr"] = subprocess.STDOUT args = split_args(args) + logger.debug("command: %s", args) try: p = subprocess.Popen(args, **kwargs) stdout, _ = p.communicate() From 7ae3385ff0e1cab217b06002770be6a95d60d2d9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 22 Mar 2018 09:58:23 -0700 Subject: [PATCH 095/152] alphabetizing emane options --- daemon/core/emane/rfpipe.py | 15 ++++++--------- daemon/core/emane/tdma.py | 6 +++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 98eb2337..08302018 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -15,23 +15,20 @@ class EmaneRfPipeModel(EmaneModel): # configuration parameters are # ( "name", "type", "default", "possible-value-list", "caption") # MAC parameters - _confmatrix_mac_base = [ + _confmatrix_mac = [ + ("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"), + ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), - ("datarate", ConfigDataTypes.UINT32.value, "1M", "", "data rate (bps)"), ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/rfpipepcr.xml" % xml_path, "", "SINR/PCR curve file"), - ] - _confmatrix_mac_091 = [ ("jitter", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission jitter (sec)"), - ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), + ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", + "R2RI neighbor table inactivity time (sec)"), + ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/rfpipepcr.xml" % xml_path, "", "SINR/PCR curve file"), ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", "R2RI radio metric report interval (sec)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", - "R2RI neighbor table inactivity time (sec)"), ] - _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_091 # PHY parameters from Universal PHY _confmatrix_phy = EmaneUniversalModel.config_matrix diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 91d60f67..18e67258 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -8,9 +8,6 @@ from core.enumerations import ConfigDataTypes class EmaneTdmaModel(EmaneModel): - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - # model name name = "emane_tdma" xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler" @@ -49,6 +46,9 @@ class EmaneTdmaModel(EmaneModel): config_groups = "TDMA MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + def __init__(self, session, object_id=None): + EmaneModel.__init__(self, session, object_id) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. From 4987019cf8374b3ae377d11926ebcde2f17aa0b4 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 22:58:07 -0700 Subject: [PATCH 096/152] fix to account for emane 1.2.1, until later cleanup --- daemon/core/emane/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/daemon/core/emane/__init__.py b/daemon/core/emane/__init__.py index 5446bf88..cb59453b 100644 --- a/daemon/core/emane/__init__.py +++ b/daemon/core/emane/__init__.py @@ -9,6 +9,7 @@ EMANE091 = 91 EMANE092 = 92 EMANE093 = 93 EMANE101 = 101 +EMANE121 = 121 VERSION = None VERSIONSTR = None @@ -38,6 +39,8 @@ def emane_version(): VERSION = EMANE093 elif output.startswith("1.0.1"): VERSION = EMANE101 + elif output.startswith("1.2.1"): + VERSION = EMANE121 except CoreCommandError: logger.exception("error checking emane version") output = "" From 987e6f4f506b3819ac1bc47f1e6cffe7523d7135 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 23:07:34 -0700 Subject: [PATCH 097/152] update to find programs from path instead of being hardcoded when build --- configure.ac | 6 +++--- daemon/Makefile.am | 2 +- daemon/core/constants.py.in | 35 ++++++++++++++++++++++------------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index 7109977e..076dac23 100644 --- a/configure.ac +++ b/configure.ac @@ -15,11 +15,11 @@ AM_INIT_AUTOMAKE([tar-ustar]) PACKAGE_DATE=m4_esyscmd_s([date +%Y%m%d]) PACKAGE_VENDOR="CORE Developers" PACKAGE_MAINTAINERS="$PACKAGE_VENDOR <$PACKAGE_BUGREPORT>" + +# core specific variables CORE_LIB_DIR="\${prefix}/lib/core" -# TODO: hard setting path, until support by setup.py CORE_CONF_DIR="/etc/core" -CORE_DATA_DIR="\${datarootdir}/core" -# TODO: verify there is need to hard set /var +CORE_DATA_DIR="\${datadir}/core" CORE_STATE_DIR="/var" AC_SUBST(PACKAGE_DATE) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index ee8dc238..bf24f512 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -46,7 +46,7 @@ install-exec-hook: uninstall-hook: rm -rf $(DESTDIR)/etc/core rm -rf $(DESTDIR)/$(datadir)/core - rm -f $(addprefix $(DESTDIR)/$(datadir)/man/man1/, $(MAN_FILES)) + rm -f $(addprefix $(DESTDIR)/$(datarootdir)/man/man1/, $(MAN_FILES)) rm -f $(addprefix $(DESTDIR)/$(bindir)/,$(SCRIPT_FILES)) rm -rf $(DESTDIR)/$(pythondir)/core-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg-info rm -rf $(DESTDIR)/$(pythondir)/core diff --git a/daemon/core/constants.py.in b/daemon/core/constants.py.in index 7dea1ad8..fc901893 100644 --- a/daemon/core/constants.py.in +++ b/daemon/core/constants.py.in @@ -1,18 +1,27 @@ +import os + COREDPY_VERSION = "@PACKAGE_VERSION@" CORE_STATE_DIR = "@CORE_STATE_DIR@" CORE_CONF_DIR = "@CORE_CONF_DIR@" CORE_DATA_DIR = "@CORE_DATA_DIR@" -CORE_LIB_DIR = "@CORE_LIB_DIR@" - -VNODED_BIN = "@bindir@/vnoded" -VCMD_BIN = "@bindir@/vcmd" -BRCTL_BIN = "@brctl_path@/brctl" -SYSCTL_BIN = "@sysctl_path@/sysctl" -IP_BIN = "@ip_path@/ip" -TC_BIN = "@tc_path@/tc" -EBTABLES_BIN = "@ebtables_path@/ebtables" QUAGGA_STATE_DIR = "@CORE_STATE_DIR@/run/quagga" -MOUNT_BIN = "@mount_path@/mount" -UMOUNT_BIN = "@umount_path@/umount" -OVS_BIN = "@ovs_vs_path@/ovs-vsctl" -OVS_FLOW_BIN = "@ovs_of_path@/ovs-ofctl" + + +def which(command): + for path in os.environ["PATH"].split(os.pathsep): + command_path = os.path.join(path, command) + if os.path.isfile(command_path) and os.access(command_path, os.X_OK): + return command_path + + +VNODED_BIN = which("vnoded") +VCMD_BIN = which("vcmd") +BRCTL_BIN = which("brctl") +SYSCTL_BIN = which("sysctl") +IP_BIN = which("ip") +TC_BIN = which("tc") +EBTABLES_BIN = which("ebtables") +MOUNT_BIN = which("mount") +UMOUNT_BIN = which("umount") +OVS_BIN = which("ovs-vsctl") +OVS_FLOW_BIN = which("ovs-ofctl") From 31a0224d8e2151a455aaffe22b5357430df5f9e5 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 21 Mar 2018 23:40:07 -0700 Subject: [PATCH 098/152] update to simplify systemd service startup --- scripts/core-daemon.service.in | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/core-daemon.service.in b/scripts/core-daemon.service.in index 3d5c05fd..210de4d5 100644 --- a/scripts/core-daemon.service.in +++ b/scripts/core-daemon.service.in @@ -3,9 +3,8 @@ Description=Common Open Research Emulator Service After=network.target [Service] -Type=forking -PIDFile=/var/run/core-daemon.pid -ExecStart=@PYTHON@ @bindir@/core-daemon -d +Type=simple +ExecStart=@PYTHON@ @bindir@/core-daemon TasksMax=infinity [Install] From 1ac862cc17a24e55f0703debe3043df6854f5f79 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 22 Mar 2018 18:32:58 -0700 Subject: [PATCH 099/152] updates to init scripts and cleanup for unsupported scripts --- Makefile.am | 1 + configure.ac | 1 - scripts/Makefile.am | 19 +-- scripts/core-daemon-init.d | 144 ----------------- scripts/core-daemon-init.d-SUSE | 264 -------------------------------- scripts/core-daemon-rc.d | 50 ------ scripts/core-daemon.in | 112 ++++++++++++++ 7 files changed, 116 insertions(+), 475 deletions(-) delete mode 100755 scripts/core-daemon-init.d delete mode 100755 scripts/core-daemon-init.d-SUSE delete mode 100755 scripts/core-daemon-rc.d create mode 100644 scripts/core-daemon.in diff --git a/Makefile.am b/Makefile.am index afb7615c..f7b604d2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -167,6 +167,7 @@ all: change-files change-files: $(call change-files,gui/core-gui) $(call change-files,scripts/core-daemon.service) + $(call change-files,scripts/core-daemon) $(call change-files,daemon/core/constants.py) CORE_DOC_HTML = core-html-$(PACKAGE_VERSION) diff --git a/configure.ac b/configure.ac index 076dac23..d40bd31f 100644 --- a/configure.ac +++ b/configure.ac @@ -194,7 +194,6 @@ AM_CONDITIONAL(WANT_PYTHON, test x$want_python = xyes) AM_CONDITIONAL(WANT_NETNS, test x$want_linux_netns = xyes) AM_CONDITIONAL(WANT_INITD, test x$with_startup = xinitd) AM_CONDITIONAL(WANT_SYSTEMD, test x$with_startup = xsystemd) -AM_CONDITIONAL(WANT_SUSE, test x$with_startup = xsuse) if test $cross_compiling = no; then AM_MISSING_PROG(HELP2MAN, help2man) diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 9c521923..b52f5f92 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -9,35 +9,22 @@ CLEANFILES = core-daemon -DISTCLEANFILES = Makefile.in core-daemon.service +DISTCLEANFILES = Makefile.in core-daemon.service core-daemon -EXTRA_DIST = core-daemon-init.d \ - core-daemon.service.in \ - core-daemon-rc.d \ - core-daemon-init.d-SUSE +EXTRA_DIST = core-daemon.in core-daemon.service.in SUBDIRS = perf # install startup scripts based on --with-startup=option configure option -# init.d (default), systemd, SUSE +# init.d (default), systemd if WANT_INITD startupdir = /etc/init.d startup_SCRIPTS = core-daemon - -core-daemon: core-daemon-init.d - cp $< $@ endif if WANT_SYSTEMD startupdir = /etc/systemd/system startup_SCRIPTS = core-daemon.service endif -if WANT_SUSE -startupdir = /etc/init.d -startup_SCRIPTS = core-daemon - -core-daemon: core-daemon-init.d-SUSE - cp $< $@ -endif # remove extra scripts and their directories if they are empty uninstall-hook: diff --git a/scripts/core-daemon-init.d b/scripts/core-daemon-init.d deleted file mode 100755 index 1c65c6f0..00000000 --- a/scripts/core-daemon-init.d +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/sh -### BEGIN INIT INFO -# Provides: core-daemon -# Required-Start: $network $remote_fs -# Required-Stop: $network $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Start the core-daemon CORE daemon at boot time -# Description: Starts and stops the core-daemon CORE daemon used to -# provide network emulation services for the CORE GUI -# or scripts. -### END INIT INFO -# -# chkconfig: 35 90 03 -# description: Starts and stops the CORE daemon \ -# used to provide network emulation services. -# -# pidfile: /var/run/core-daemon.pid -# config: /usr/local/etc/core/ - -DEB=no -# Source function library. -if [ -f /etc/init.d/functions ] ; then - . /etc/init.d/functions -elif [ -f /etc/rc.d/init.d/functions ] ; then - . /etc/rc.d/init.d/functions -elif [ -f /lib/lsb/init-functions ] ; then - . /lib/lsb/init-functions - DEB=yes -else - exit 1 -fi - -# search for core-daemon which may or may not be installed -cored= -for p in /usr/local/sbin \ - /usr/sbin \ - /sbin \ - /usr/local/bin \ - /usr/bin \ - /bin -do - if [ -e $p/core-daemon ] ; then - cored=$p/core-daemon - break - fi -done - -# this function comes from /etc/profile -pathmunge () { - if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then - if [ "$2" = "after" ] ; then - PATH=$PATH:$1 - else - PATH=$1:$PATH - fi - fi -} - -# these lines add to the PATH variable used by CORE and its containers -# you can add your own pathmunge statements to change the container's PATH -pathmunge "/usr/local/sbin" -pathmunge "/usr/local/bin" - -RETVAL=0 -PIDFILE=/var/run/core-daemon.pid - -# the /etc/init.d/functions (RedHat) differs from -# /usr/lib/init-functions (Debian) -if [ $DEB = yes ]; then - daemon="start-stop-daemon --start -p ${PIDFILE} --exec /usr/bin/python --" - #daemon=start_daemon - killproc="start-stop-daemon --stop --quiet --oknodo --retry 10" - status=status_of_proc - msg () { - log_daemon_msg "$@" - } - endmsg () { - log_end_msg "$@" - } -else - daemon="daemon /usr/bin/python" - killproc="killproc -d 10" - status=status - msg () { - echo -n $"$@" - } - endmsg () { - echo "" - } -fi - - -start() { - msg "Starting core-daemon" - $daemon $cored -d - RETVAL=$? - endmsg $RETVAL - return $RETVAL -} - -stop() { - msg "Shutting down core-daemon" - $killproc -p ${PIDFILE} $cored - RETVAL=$? - rm -f ${PIDFILE} - endmsg $RETVAL - return $RETVAL -} - -restart() { - stop - start -} - -corestatus() { - $status -p ${PIDFILE} core-daemon core-daemon - return $? -} - - -case "$1" in - start) - start - ;; - stop) - stop - ;; - restart) - restart - ;; - force-reload) - restart - ;; - status) - corestatus - ;; - *) - msg "Usage: $0 {start|stop|restart|status}" - endmsg - exit 2 -esac - -exit $? diff --git a/scripts/core-daemon-init.d-SUSE b/scripts/core-daemon-init.d-SUSE deleted file mode 100755 index b3a3d67a..00000000 --- a/scripts/core-daemon-init.d-SUSE +++ /dev/null @@ -1,264 +0,0 @@ -#!/bin/sh -# -# Template SUSE system startup script for example service/daemon core -# Copyright (C) 1995--2005 Kurt Garloff, SUSE / Novell Inc. -# -# This library is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or (at -# your option) any later version. -# -# This library is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, -# USA. -# -# /etc/init.d/FOO -# and its symbolic link -# /(usr/)sbin/rcFOO -# -# Template system startup script for some example service/daemon FOO -# -# LSB compatible service control script; see http://www.linuxbase.org/spec/ -# -# Note: This template uses functions rc_XXX defined in /etc/rc.status on -# UnitedLinux/SUSE/Novell based Linux distributions. If you want to base your -# script on this template and ensure that it works on non UL based LSB -# compliant Linux distributions, you either have to provide the rc.status -# functions from UL or change the script to work without them. -# See skeleton.compat for a template that works with other distros as well. -# -### BEGIN INIT INFO -# Provides: core-daemon -# Required-Start: $network $remote_fs -# Required-Stop: $network $remote_fs -# Default-Start: 3 5 -# Default-Stop: 0 1 2 6 -# Short-Description: core-daemon -# Description: Start core-daemon -# continued on second line by '#' -# should contain enough info for the runlevel editor -# to give admin some idea what this service does and -# what it's needed for ... -# (The Short-Description should already be a good hint.) -### END INIT INFO -# -# Any extensions to the keywords given above should be preceeded by -# X-VendorTag- (X-UnitedLinux- X-SuSE- for us) according to LSB. -# -# Notes on Required-Start/Should-Start: -# * There are two different issues that are solved by Required-Start -# and Should-Start -# (a) Hard dependencies: This is used by the runlevel editor to determine -# which services absolutely need to be started to make the start of -# this service make sense. Example: nfsserver should have -# Required-Start: $portmap -# Also, required services are started before the dependent ones. -# The runlevel editor will warn about such missing hard dependencies -# and suggest enabling. During system startup, you may expect an error, -# if the dependency is not fulfilled. -# (b) Specifying the init script ordering, not real (hard) dependencies. -# This is needed by insserv to determine which service should be -# started first (and at a later stage what services can be started -# in parallel). The tag Should-Start: is used for this. -# It tells, that if a service is available, it should be started -# before. If not, never mind. -# * When specifying hard dependencies or ordering requirements, you can -# use names of services (contents of their Provides: section) -# or pseudo names starting with a $. The following ones are available -# according to LSB (1.1): -# $local_fs all local file systems are mounted -# (most services should need this!) -# $remote_fs all remote file systems are mounted -# (note that /usr may be remote, so -# many services should Require this!) -# $syslog system logging facility up -# $network low level networking (eth card, ...) -# $named hostname resolution available -# $netdaemons all network daemons are running -# The $netdaemons pseudo service has been removed in LSB 1.2. -# For now, we still offer it for backward compatibility. -# These are new (LSB 1.2): -# $time the system time has been set correctly -# $portmap SunRPC portmapping service available -# UnitedLinux extensions: -# $ALL indicates that a script should be inserted -# at the end -# * The services specified in the stop tags -# (Required-Stop/Should-Stop) -# specify which services need to be still running when this service -# is shut down. Often the entries there are just copies or a subset -# from the respective start tag. -# * Should-Start/Stop are now part of LSB as of 2.0, -# formerly SUSE/Unitedlinux used X-UnitedLinux-Should-Start/-Stop. -# insserv does support both variants. -# * X-UnitedLinux-Default-Enabled: yes/no is used at installation time -# (%fillup_and_insserv macro in %post of many RPMs) to specify whether -# a startup script should default to be enabled after installation. -# It's not used by insserv. -# -# Note on runlevels: -# 0 - halt/poweroff 6 - reboot -# 1 - single user 2 - multiuser without network exported -# 3 - multiuser w/ network (text mode) 5 - multiuser w/ network and X11 (xdm) -# -# Note on script names: -# http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/scrptnames.html -# A registry has been set up to manage the init script namespace. -# http://www.lanana.org/ -# Please use the names already registered or register one or use a -# vendor prefix. - - -# Check for missing binaries (stale symlinks should not happen) -# Note: Special treatment of stop for LSB conformance -CORE_BIN=/usr/local/bin/core-daemon -test -x $CORE_BIN || { echo "$CORE_BIN not installed"; - if [ "$1" = "stop" ]; then exit 0; - else exit 5; fi; } - -# Check for existence of needed config file and read it -CORE_CONFIG=/etc/core -test -r $CORE_CONFIG || { echo "$CORE_CONFIG not existing"; - if [ "$1" = "stop" ]; then exit 0; - else exit 6; fi; } - -# Source LSB init functions -# providing start_daemon, killproc, pidofproc, -# log_success_msg, log_failure_msg and log_warning_msg. -# This is currently not used by UnitedLinux based distributions and -# not needed for init scripts for UnitedLinux only. If it is used, -# the functions from rc.status should not be sourced or used. -#. /lib/lsb/init-functions - -# Shell functions sourced from /etc/rc.status: -# rc_check check and set local and overall rc status -# rc_status check and set local and overall rc status -# rc_status -v be verbose in local rc status and clear it afterwards -# rc_status -v -r ditto and clear both the local and overall rc status -# rc_status -s display "skipped" and exit with status 3 -# rc_status -u display "unused" and exit with status 3 -# rc_failed set local and overall rc status to failed -# rc_failed set local and overall rc status to -# rc_reset clear both the local and overall rc status -# rc_exit exit appropriate to overall rc status -# rc_active checks whether a service is activated by symlinks -. /etc/rc.status - -# Reset status of this service -rc_reset - -# Return values acc. to LSB for all commands but status: -# 0 - success -# 1 - generic or unspecified error -# 2 - invalid or excess argument(s) -# 3 - unimplemented feature (e.g. "reload") -# 4 - user had insufficient privileges -# 5 - program is not installed -# 6 - program is not configured -# 7 - program is not running -# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) -# -# Note that starting an already running service, stopping -# or restarting a not-running service as well as the restart -# with force-reload (in case signaling is not supported) are -# considered a success. - -case "$1" in - start) - echo -n "Starting CORE " - ## Start daemon with startproc(8). If this fails - ## the return value is set appropriately by startproc. - /sbin/startproc $CORE_BIN -d - - # Remember status and be verbose - rc_status -v - ;; - stop) - echo -n "Shutting down CORE " - ## Stop daemon with killproc(8) and if this fails - ## killproc sets the return value according to LSB. - - if [ -r /var/run/core-daemon.pid ] ; then - /bin/kill -TERM `cat /var/run/core-daemon.pid` - /bin/rm -f /var/run/core-daemon.pid - fi - - # Remember status and be verbose - rc_status -v - ;; - try-restart|condrestart) - ## Do a restart only if the service was active before. - ## Note: try-restart is now part of LSB (as of 1.9). - ## RH has a similar command named condrestart. - if test "$1" = "condrestart"; then - echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}" - fi - $0 status - if test $? = 0; then - $0 restart - else - rc_reset # Not running is not a failure. - fi - # Remember status and be quiet - rc_status - ;; - restart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - $0 stop - $0 start - - # Remember status and be quiet - rc_status - ;; - force-reload) - ## Signal the daemon to reload its config. Most daemons - ## do this on signal 1 (SIGHUP). - ## If it does not support it, restart the service if it - ## is running. - - echo -n "Reload service CORE " - $0 try-restart - rc_status - ;; - - reload) - ## Like force-reload, but if daemon does not support - ## signaling, do nothing (!) - - ## It does not support reload: - rc_failed 3 - rc_status -v - ;; - - status) - echo -n "Checking for service CORE " - ## Check status with checkproc(8), if process is running - ## checkproc will return with exit status 0. - - # Return value is slightly different for the status command: - # 0 - service up and running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running (unused) - # 4 - service status unknown :-( - # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) - - # NOTE: checkproc returns LSB compliant status values. - /sbin/checkproc -p /var/run/core-daemon.pid python - # NOTE: rc_status knows that we called this init script with - # "status" option and adapts its messages accordingly. - rc_status -v - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}" - exit 1 - ;; -esac -rc_exit diff --git a/scripts/core-daemon-rc.d b/scripts/core-daemon-rc.d deleted file mode 100755 index 984f5e7b..00000000 --- a/scripts/core-daemon-rc.d +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh -# - -# PROVIDE: core -# REQUIRE: NETWORKING - -# To enable CORE services on startup, add the following line to /etc/rc.conf: -# core_enable="YES" -# - -. /etc/rc.subr - -name="core" -rcvar=`set_rcvar` - -stop_postcmd=stop_postcmd - -stop_postcmd() -{ - rm -f $pidfile -} - -# defaults -load_rc_config $name -: ${core_enable="NO"} -: ${core_flags="-d"} -: ${core_daemons="core-daemon"} - -core_cmd=$1 - -case "${core_cmd}" in - start) - ;; - stop|restart) - core_daemons=$(reverse_list ${core_daemons}) - ;; -esac - -for daemon in ${core_daemons}; do - command=/usr/local/sbin/${daemon} - pidname=`echo ${daemon} | sed 's/\.//g'` - pidfile=/var/run/${pidname}.pid - command_interpreter=python - if [ "${daemon}" = "core-daemon" ]; then - command_interpreter=python - fi - run_rc_command "$1" - _rc_restart_done=false -done - diff --git a/scripts/core-daemon.in b/scripts/core-daemon.in new file mode 100644 index 00000000..37a493c8 --- /dev/null +++ b/scripts/core-daemon.in @@ -0,0 +1,112 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: core-daemon +# Required-Start: $network $remote_fs +# Required-Stop: $network $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start the core-daemon CORE daemon at boot time +# Description: Starts and stops the core-daemon CORE daemon used to +# provide network emulation services for the CORE GUI +# or scripts. +### END INIT INFO +# +# chkconfig: 35 90 03 +# description: Starts and stops the CORE daemon \ +# used to provide network emulation services. +# +# config: /etc/core/ + +NAME=`basename $0` +PIDFILE="@CORE_STATE_DIR@/run/$NAME.pid" +LOG="@CORE_STATE_DIR@/log/$NAME.log" +CMD="@PYTHON@ @bindir@/$NAME" + +get_pid() { + cat "$PIDFILE" +} + +is_alive() { + [ -f "$PIDFILE" ] && ps -p `get_pid` > /dev/null 2>&1 +} + +corestart() { + if is_alive; then + echo "$NAME already started" + else + echo "starting $NAME" + sudo $CMD 2>&1 >> "$LOG" & + fi + + echo $! > "$PIDFILE" + if ! is_alive; then + echo "unable to start $NAME, see $LOG" + exit 1 + fi +} + +corestop() { + if is_alive; then + echo -n "stopping $NAME.." + kill `get_pid` + for i in 1 2 3 4 5; do + sleep 1 + if ! is_alive; then + break + fi + echo -n "." + done + echo + + if is_alive; then + echo "not stopped; may still be shutting down" + exit 1 + else + echo "stopped" + if [ -f "$PIDFILE" ]; then + rm -f "$PIDFILE" + fi + fi + else + echo "$NAME not running" + fi +} + +corerestart() { + corestop + corestart +} + +corestatus() { + if is_alive; then + echo "$NAME is running" + else + echo "$NAME is stopped" + exit 1 + fi +} + + +case "$1" in + start) + corestart + ;; + stop) + corestop + ;; + restart) + corerestart + ;; + force-reload) + corerestart + ;; + status) + corestatus + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 +esac + +exit $? + From 68f6b6af9b2ff10d644d3ecf4c8a288057973a11 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 22 Mar 2018 22:18:27 -0700 Subject: [PATCH 100/152] fixed new 80211 config --- daemon/core/emane/ieee80211abg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index b53a18db..86c3a705 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -29,7 +29,7 @@ class EmaneIeee80211abgModel(EmaneModel): ("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," + "2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"), ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"), - ("msdu", ConfigDataTypes.UINT16.value, "65535", "", "MSDU categories"), + ("msdu", ConfigDataTypes.UINT16.value, "0:65535 1:65535 2:65535 3:65535", "", "MSDU categories (0-4:size)"), ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", "R2RI neighbor table inactivity time (sec)"), ("neighbortimeout", ConfigDataTypes.FLOAT.value, "30.0", "", "Neighbor timeout in seconds for estimation"), From 44363b0500c713a8b2ba0bd8f18797165302f242 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 23 Mar 2018 09:57:37 -0700 Subject: [PATCH 101/152] removed daemonize code that is not needed for services, cleaned up need for logrotate, removed some logging that was not useful --- daemon/Makefile.am | 17 +---- daemon/core/corehandlers.py | 5 +- daemon/core/coreserver.py | 9 --- daemon/core/misc/utils.py | 90 ----------------------- daemon/core/netns/vnode.py | 5 +- daemon/data/core.conf | 6 -- daemon/scripts/core-daemon | 143 ++++-------------------------------- 7 files changed, 20 insertions(+), 255 deletions(-) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index bf24f512..c554b8ce 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -17,9 +17,6 @@ endif SCRIPT_FILES := $(notdir $(wildcard scripts/*)) MAN_FILES := $(notdir $(wildcard ../doc/man/*.1)) -LOGROTATE_DIR = $(DESTDIR)/$(sysconfdir)/logrotate.d -LOGROTATE_FILE = data/core-daemon.logrotate - # Python package build noinst_SCRIPTS = build build: @@ -33,16 +30,7 @@ install-exec-hook: --install-lib=$(pythondir) \ --single-version-externally-managed -#install-data-local: -# $(MKDIR_P) $(DESTDIR)$(LOGROTATE_DIR) -# $(INSTALL_DATA) $(LOGROTATE_FILE) \ -# $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` - -#uninstall-local: -# rm -f $(DESTDIR)$(LOGROTATE_DIR)/`basename $(LOGROTATE_FILE) .logrotate` - # Python package uninstall -#rmdir -p $(LOGROTATE_DIR) || true uninstall-hook: rm -rf $(DESTDIR)/etc/core rm -rf $(DESTDIR)/$(datadir)/core @@ -62,7 +50,7 @@ dist-hook: distclean-local: -rm -rf core.egg-info - + DISTCLEANFILES = Makefile.in @@ -76,5 +64,4 @@ EXTRA_DIST = $(SETUPPY) \ tests \ test.py \ setup.cfg \ - requirements.txt \ - $(LOGROTATE_FILE) + requirements.txt diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py index c9d8f7ed..5e78a39f 100644 --- a/daemon/core/corehandlers.py +++ b/daemon/core/corehandlers.py @@ -360,8 +360,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): """ try: header = self.request.recv(coreapi.CoreMessage.header_len) - if len(header) > 0: - logger.debug("received message header: %s", utils.hex_dump(header)) except IOError as e: raise IOError("error receiving header (%s)" % e) @@ -378,7 +376,6 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): data = "" while len(data) < message_len: data += self.request.recv(message_len - len(data)) - logger.debug("received message data: %s" % utils.hex_dump(data)) if len(data) > message_len: error_message = "received message length does not match received data (%s != %s)" % ( len(data), message_len) @@ -492,7 +489,7 @@ class CoreRequestHandler(SocketServer.BaseRequestHandler): # TODO: hack to associate this handler with this sessions broker for broadcasting # TODO: broker needs to be pulled out of session to the server/handler level if self.master: - logger.info("SESSION SET TO MASTER!") + logger.info("session set to master") self.session.master = True self.session.broker.session_clients.append(self) diff --git a/daemon/core/coreserver.py b/daemon/core/coreserver.py index 19aeb80c..1687aec3 100644 --- a/daemon/core/coreserver.py +++ b/daemon/core/coreserver.py @@ -3,7 +3,6 @@ Defines server classes and request handlers for TCP and UDP. """ import SocketServer -import os import threading import time @@ -72,14 +71,6 @@ class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): for session in self.sessions.values(): session.shutdown() - # if we are a daemon remove pid file - if self.config["daemonize"]: - pid_file = self.config["pidfile"] - try: - os.unlink(pid_file) - except OSError: - logger.exception("error daemon pid file: %s", pid_file) - # remove server from server list CoreServer.remove_server(self) diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index f13f0152..f13c314f 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -10,7 +10,6 @@ import subprocess import sys import fcntl -import resource from core import CoreCommandError from core import logger @@ -337,95 +336,6 @@ def sysctl_devname(devname): return devname.replace(".", "/") -def daemonize(rootdir="/", umask=0, close_fds=False, dontclose=(), - stdin=os.devnull, stdout=os.devnull, stderr=os.devnull, - stdoutmode=0644, stderrmode=0644, pidfilename=None, - defaultmaxfd=1024): - """ - Run the background process as a daemon. - - :param str rootdir: root directory for daemon - :param int umask: umask for daemon - :param bool close_fds: flag to close file descriptors - :param dontclose: dont close options - :param stdin: stdin for daemon - :param stdout: stdout for daemon - :param stderr: stderr for daemon - :param int stdoutmode: stdout mode - :param int stderrmode: stderr mode - :param str pidfilename: pid file name - :param int defaultmaxfd: default max file descriptors - :return: nothing - """ - if not hasattr(dontclose, "__contains__"): - if not isinstance(dontclose, int): - raise TypeError("dontclose must be an integer") - dontclose = (int(dontclose),) - else: - for fd in dontclose: - if not isinstance(fd, int): - raise TypeError("dontclose must contain only integers") - - # redirect stdin - if stdin: - fd = os.open(stdin, os.O_RDONLY) - os.dup2(fd, 0) - os.close(fd) - - # redirect stdout - if stdout: - fd = os.open(stdout, os.O_WRONLY | os.O_CREAT | os.O_APPEND, - stdoutmode) - os.dup2(fd, 1) - if stdout == stderr: - os.dup2(1, 2) - os.close(fd) - - # redirect stderr - if stderr and (stderr != stdout): - fd = os.open(stderr, os.O_WRONLY | os.O_CREAT | os.O_APPEND, - stderrmode) - os.dup2(fd, 2) - os.close(fd) - - if os.fork(): - # parent exits - os._exit(0) - - os.setsid() - pid = os.fork() - if pid: - if pidfilename: - try: - f = open(pidfilename, "w") - f.write("%s\n" % pid) - f.close() - except IOError: - logger.exception("error writing to file: %s", pidfilename) - # parent exits - os._exit(0) - - if rootdir: - os.chdir(rootdir) - - os.umask(umask) - if close_fds: - try: - maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1] - if maxfd == resource.RLIM_INFINITY: - raise ValueError - except: - maxfd = defaultmaxfd - - for fd in xrange(3, maxfd): - if fd in dontclose: - continue - try: - os.close(fd) - except IOError: - logger.exception("error closing file descriptor") - - def load_config(filename, d): """ Read key=value pairs from a file, into a dict. Skip comments; strip newline characters and spacing. diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 63046501..b8ee3924 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -138,8 +138,9 @@ class SimpleLxcNode(PyCoreNode): try: os.kill(self.pid, signal.SIGTERM) os.waitpid(self.pid, 0) - except OSError: - logger.exception("error killing process") + except OSError as e: + if e.errno != 10: + logger.exception("error killing process") # remove node directory if present try: diff --git a/daemon/data/core.conf b/daemon/data/core.conf index 97bb96bb..72ec1638 100644 --- a/daemon/data/core.conf +++ b/daemon/data/core.conf @@ -1,6 +1,4 @@ # Configuration file for CORE (core-gui, core-daemon) -# - ### GUI configuration options ### [core-gui] @@ -8,14 +6,10 @@ ### core-daemon configuration options ### [core-daemon] -pidfile = /var/run/core-daemon.pid -logfile = /var/log/core-daemon.log xmlfilever = 1.0 -# you may want to change the listenaddr below to 0.0.0.0 listenaddr = localhost port = 4038 numthreads = 1 -verbose = False quagga_bin_search = "/usr/local/bin /usr/bin /usr/lib/quagga" quagga_sbin_search = "/usr/local/sbin /usr/sbin /usr/lib/quagga" # uncomment the following line to load custom services from the specified dir diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 07b97a88..a9d92376 100755 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -8,9 +8,7 @@ message handlers are defined and some support for sending messages. import ConfigParser import atexit import optparse -import os import signal -import socket import sys import time @@ -20,16 +18,10 @@ from core import coreserver from core import enumerations from core import logger from core import services -from core.api import coreapi -from core.enumerations import MessageFlags -from core.enumerations import RegisterTlvs from core.misc import nodeutils from core.misc.utils import close_onexec -from core.misc.utils import daemonize from core.service import ServiceManager -DEFAULT_MAXFD = 1024 - def banner(): """ @@ -51,6 +43,7 @@ def cored(cfg=None): port = int(cfg["port"]) if host == "" or host is None: host = "localhost" + try: server = coreserver.CoreServer((host, port), corehandlers.CoreRequestHandler, cfg) except: @@ -62,7 +55,7 @@ def cored(cfg=None): server.serve_forever() -# TODO: should sessions and the main core daemon both catch at exist to shutdown independently? +# TODO: should sessions and the main core daemon both catch exit to shutdown independently? def cleanup(): """ Runs server shutdown and cleanup when catching an exit signal. @@ -74,9 +67,6 @@ def cleanup(): server.shutdown() -atexit.register(cleanup) - - def sighandler(signum, stackframe): """ Signal handler when different signals are sent. @@ -94,43 +84,7 @@ signal.signal(signal.SIGINT, sighandler) signal.signal(signal.SIGTERM, sighandler) signal.signal(signal.SIGUSR1, sighandler) signal.signal(signal.SIGUSR2, sighandler) - - -def logrotate(stdout, stderr, stdoutmode=0644, stderrmode=0644): - """ - Log rotation method. - - :param stdout: stdout - :param stderr: stderr - :param int stdoutmode: stdout mode - :param int stderrmode: stderr mode - :return: - """ - - def reopen(fileno, filename, mode): - err = 0 - fd = -1 - try: - fd = os.open(filename, - os.O_WRONLY | os.O_CREAT | os.O_APPEND, mode) - os.dup2(fd, fileno) - except OSError as e: - err = e.errno - finally: - if fd >= 0: - os.close(fd) - return err - - if stdout: - err = reopen(1, stdout, stdoutmode) - if stderr: - if stderr == stdout and not err: - try: - os.dup2(1, 2) - except OSError as e: - pass - else: - reopen(2, stderr, stderrmode) +atexit.register(cleanup) def get_merged_config(filename): @@ -142,50 +96,23 @@ def get_merged_config(filename): :rtype: dict """ # these are the defaults used in the config file - defaults = {"port": "%d" % enumerations.CORE_API_PORT, - "listenaddr": "localhost", - "pidfile": "%s/run/core-daemon.pid" % constants.CORE_STATE_DIR, - "logfile": "%s/log/core-daemon.log" % constants.CORE_STATE_DIR, - "xmlfilever": "1.0", - "numthreads": "1", - "verbose": "False", - "daemonize": "False", - "debug": "False", - "execfile": None, - } + defaults = { + "port": "%d" % enumerations.CORE_API_PORT, + "listenaddr": "localhost", + "xmlfilever": "1.0", + "numthreads": "1", + } usagestr = "usage: %prog [-h] [options] [args]\n\n" + \ "CORE daemon v.%s instantiates Linux network namespace " \ "nodes." % constants.COREDPY_VERSION parser = optparse.OptionParser(usage=usagestr) - parser.add_option("-f", "--configfile", dest="configfile", - type="string", - help="read config from specified file; default = %s" % - filename) - parser.add_option("-d", "--daemonize", dest="daemonize", - action="store_true", - help="run in background as daemon; default=%s" % \ - defaults["daemonize"]) - parser.add_option("-e", "--execute", dest="execfile", type="string", - help="execute a Python/XML-based session") - parser.add_option("-l", "--logfile", dest="logfile", type="string", - help="log output to specified file; default = %s" % - defaults["logfile"]) + parser.add_option("-f", "--configfile", dest="configfile", type="string", + help="read config from specified file; default = %s" % filename) parser.add_option("-p", "--port", dest="port", type=int, - help="port number to listen on; default = %s" % \ - defaults["port"]) - parser.add_option("-i", "--pidfile", dest="pidfile", - help="filename to write pid to; default = %s" % \ - defaults["pidfile"]) + help="port number to listen on; default = %s" % defaults["port"]) parser.add_option("-t", "--numthreads", dest="numthreads", type=int, - help="number of server threads; default = %s" % \ - defaults["numthreads"]) - parser.add_option("-v", "--verbose", dest="verbose", action="store_true", - help="enable verbose logging; default = %s" % \ - defaults["verbose"]) - parser.add_option("-g", "--debug", dest="debug", action="store_true", - help="enable debug logging; default = %s" % \ - defaults["debug"]) + help="number of server threads; default = %s" % defaults["numthreads"]) # parse command line options options, args = parser.parse_args() @@ -200,19 +127,6 @@ def get_merged_config(filename): section = "core-daemon" if not cfg.has_section(section): cfg.add_section(section) - # gracefully support legacy configs (cored.py/cored now core-daemon) - if cfg.has_section("cored.py"): - for name, val in cfg.items("cored.py"): - if name == "pidfile" or name == "logfile": - bn = os.path.basename(val).replace("coredpy", "core-daemon") - val = os.path.join(os.path.dirname(val), bn) - cfg.set(section, name, val) - if cfg.has_section("cored"): - for name, val in cfg.items("cored"): - if name == "pidfile" or name == "logfile": - bn = os.path.basename(val).replace("cored", "core-daemon") - val = os.path.join(os.path.dirname(val), bn) - cfg.set(section, name, val) # merge command line with config file for opt in options.__dict__: @@ -223,24 +137,6 @@ def get_merged_config(filename): return dict(cfg.items(section)), args -def exec_file(cfg): - """ - Send a Register Message to execute a new session based on XML or Python script file. - - :param dict cfg: configuration settings - :return: 0 - """ - filename = cfg["execfile"] - logger.info("Telling daemon to execute file: %s...", filename) - tlvdata = coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, filename) - msg = coreapi.CoreRegMessage.pack(MessageFlags.ADD.value, tlvdata) - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - # TODO: connect address option - sock.connect(("localhost", int(cfg["port"]))) - sock.sendall(msg) - return 0 - - def main(): """ Main program startup. @@ -260,19 +156,8 @@ def main(): service_path = service_path.strip() ServiceManager.add_services(service_path) - if cfg["daemonize"] == "True": - daemonize(rootdir=None, umask=0, close_fds=False, - stdin=os.devnull, - stdout=cfg["logfile"], stderr=cfg["logfile"], - pidfilename=cfg["pidfile"], - defaultmaxfd=DEFAULT_MAXFD) - signal.signal(signal.SIGUSR1, lambda signum, stackframe: - logrotate(stdout=cfg["logfile"], stderr=cfg["logfile"])) - banner() - if cfg["execfile"]: - cfg["execfile"] = os.path.abspath(cfg["execfile"]) - sys.exit(exec_file(cfg)) + try: cored(cfg) except KeyboardInterrupt: From 4c35aaaa489211ce716a486725616e3231bb3d68 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 23 Mar 2018 10:26:33 -0700 Subject: [PATCH 102/152] fixed default example config for custom emane models --- daemon/data/core.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/data/core.conf b/daemon/data/core.conf index 72ec1638..dff4bdee 100644 --- a/daemon/data/core.conf +++ b/daemon/data/core.conf @@ -51,7 +51,7 @@ emane_platform_port = 8101 emane_transform_port = 8201 emane_event_generate = True emane_event_monitor = False -#emane_models_dir = /home/username/.core/emane +#emane_models_dir = /home/username/.core/myemane # EMANE log level range [0,4] default: 2 #emane_log_level = 2 emane_realtime = True From e4652f6879b5e83e3e379ce0222ba67847eaf1b4 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 23 Mar 2018 13:00:46 -0700 Subject: [PATCH 103/152] tweaks to support latest 80211 config values --- daemon/core/emane/ieee80211abg.py | 48 ++++++++++++++----------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index fecb491d..b53a18db 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -16,40 +16,34 @@ class EmaneIeee80211abgModel(EmaneModel): xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" # MAC parameters - _confmatrix_mac_base = [ - ("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," + - "2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), + _confmatrix_mac = [ + ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), + ("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "", + "Defines channel activity estimation timer in seconds"), + ("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", "", "max contention window (0-4:maxw)"), + ("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", "", "min contention window (0-4:minw)"), ("distance", ConfigDataTypes.UINT32.value, "1000", "", "max distance (m)"), - ("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, "unicast rate (Mbps)"), - ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"), - ("rtsthreshold", ConfigDataTypes.UINT16.value, "0", "", "RTS threshold (bytes)"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/ieee80211pcr.xml" % xml_path, "", "SINR/PCR curve file"), + ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), - ] - - # mac parameters introduced in EMANE 0.8.1 - # Note: The entry format for category queue parameters (queuesize, aifs, etc) were changed in - # EMANE 9.x, but are being preserved for the time being due to space constraints in the - # CORE GUI. A conversion function (get9xmacparamequivalent) has been defined to support this. - _confmatrix_mac_extended = [ - ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), + ("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," + + "2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"), + ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"), + ("msdu", ConfigDataTypes.UINT16.value, "65535", "", "MSDU categories"), + ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", + "R2RI neighbor table inactivity time (sec)"), + ("neighbortimeout", ConfigDataTypes.FLOAT.value, "30.0", "", "Neighbor timeout in seconds for estimation"), + ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/ieee80211pcr.xml" % xml_path, "", "SINR/PCR curve file"), ("queuesize", ConfigDataTypes.STRING.value, "0:255 1:255 2:255 3:255", "", "queue size (0-4:size)"), - ("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", "", "min contention window (0-4:minw)"), - ("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", "", "max contention window (0-4:maxw)"), - ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), - ("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", "", "txop (0-4:usec)"), - ("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", "", "retry limit (0-4:numretries)"), - ] - _confmatrix_mac_091 = [ ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", "R2RI radio metric report interval (sec)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", - "R2RI neighbor table inactivity time (sec)"), + ("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", "", "retry limit (0-4:numretries)"), + ("rtsthreshold", ConfigDataTypes.UINT16.value, "0", "", "RTS threshold (bytes)"), + ("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", "", "txop (0-4:usec)"), + ("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, "unicast rate (Mbps)"), + ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), ] - _confmatrix_mac = _confmatrix_mac_base + _confmatrix_mac_extended + _confmatrix_mac_091 # PHY parameters from Universal PHY _confmatrix_phy = EmaneUniversalModel.config_matrix @@ -120,7 +114,7 @@ class EmaneIeee80211abgModel(EmaneModel): nvpairlist = [] macparmval = self.valueof(macname, values) - if macname in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit"]: + if macname in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit", "msdu"]: for catval in macparmval.split(): idx_and_val = catval.split(":") idx = int(idx_and_val[0]) From 45f041604af5f4b9fb3d3d5649ffd1ee34ab75a9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 26 Mar 2018 10:27:39 -0700 Subject: [PATCH 104/152] adding support to start the tdma schedule after emane startup --- daemon/core/emane/emanemanager.py | 22 +++++++++++------- daemon/core/emane/emanemodel.py | 10 +++++++++ daemon/core/emane/tdma.py | 37 ++++++++++++++++++++++++++++--- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 17b2be9b..77d80458 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -85,6 +85,7 @@ class EmaneManager(ConfigurableManager): self.emane_config = EmaneGlobalModel(session, None) session.broker.handlers.add(self.handledistributed) self.service = None + self.event_device = None self._modelclsmap = { self.emane_config.name: self.emane_config } @@ -104,8 +105,11 @@ class EmaneManager(ConfigurableManager): """ Log the installed EMANE version. """ - emane_version = utils.check_cmd(["emane", "--version"]) - logger.info("using EMANE: %s", emane_version) + try: + emane_version = utils.check_cmd(["emane", "--version"]) + logger.info("using EMANE: %s", emane_version) + except CoreCommandError: + logger.info("emane is not installed") def deleteeventservice(self): if self.service: @@ -116,6 +120,7 @@ class EmaneManager(ConfigurableManager): if f: f.close() self.service = None + self.event_device = None def initeventservice(self, filename=None, shutdown=False): """ @@ -130,22 +135,22 @@ class EmaneManager(ConfigurableManager): # Get the control network to be used for events values = self.getconfig(None, "emane", self.emane_config.getdefaultvalues())[1] group, port = self.emane_config.valueof("eventservicegroup", values).split(":") - eventdev = self.emane_config.valueof("eventservicedevice", values) - eventnetidx = self.session.get_control_net_index(eventdev) + self.event_device = self.emane_config.valueof("eventservicedevice", values) + eventnetidx = self.session.get_control_net_index(self.event_device) if eventnetidx < 0: - logger.error("invalid emane event service device provided: %s", eventdev) + logger.error("invalid emane event service device provided: %s", self.event_device) return False # make sure the event control network is in place eventnet = self.session.add_remove_control_net(net_index=eventnetidx, remove=False, conf_required=False) if eventnet is not None: # direct EMANE events towards control net bridge - eventdev = eventnet.brname - eventchannel = (group, int(port), eventdev) + self.event_device = eventnet.brname + eventchannel = (group, int(port), self.event_device) # disabled otachannel for event service # only needed for e.g. antennaprofile events xmit by models - logger.info("Using %s for event service traffic", eventdev) + logger.info("using %s for event service traffic", self.event_device) try: self.service = EventService(eventchannel=eventchannel, otachannel=None) except EventServiceException: @@ -339,6 +344,7 @@ class EmaneManager(ConfigurableManager): for netif in emane_node.netifs(): x, y, z = netif.node.position.get() emane_node.setnemposition(netif, x, y, z) + emane_node.model.post_startup(self, netif) def reset(self): """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 4733160e..e6a94d8a 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -46,6 +46,16 @@ class EmaneModel(WirelessModel): """ return cls.configure(session.emane, config_data) + def post_startup(self, emane_manager, ifc): + """ + Logic to execute after the emane manager is finished with startup. + + :param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session + :param ifc: an interface for the emane node this model is tied to + :return: nothing + """ + logger.info("%s has no post setup tasks: interface(%s)", ifc) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 18e67258..01850043 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -2,18 +2,26 @@ tdma.py: EMANE TDMA model bindings for CORE """ +import os + +from core import constants +from core import logger from core.emane.emanemodel import EmaneModel from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes +from core.misc import utils class EmaneTdmaModel(EmaneModel): # model name name = "emane_tdma" xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler" + schedule_name = "schedule" + default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") # MAC parameters _confmatrix_mac = [ + (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule that will be set"), ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), @@ -49,6 +57,24 @@ class EmaneTdmaModel(EmaneModel): def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) + def post_startup(self, emane_manager, ifc): + """ + Logic to execute after the emane manager is finished with startup. + + :param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session + :param ifc: an interface for the emane node this model is tied to + :return: nothing + """ + # get configured schedule + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + schedule = self.valueof(EmaneTdmaModel.schedule_name, values) + + event_device = emane_manager.event_device + + # initiate tdma schedule + logger.info("setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device) + utils.check_cmd(["emaneevent-tdmaschedule", "-i", event_device, schedule]) + def buildnemxmlfiles(self, e, ifc): """ Build the necessary nem, mac, and phy XMLs in the given path. @@ -75,15 +101,20 @@ class EmaneTdmaModel(EmaneModel): names = list(self.getnames()) macnames = names[:len(self._confmatrix_mac)] phynames = names[len(self._confmatrix_mac):] - # make any changes to the mac/phy names here to e.g. exclude them from - # the XML output + + # make any changes to the mac/phy names here to e.g. exclude them from the XML output + macnames.remove(EmaneTdmaModel.schedule_name) macdoc = e.xmldoc("mac") mac = macdoc.getElementsByTagName("mac").pop() mac.setAttribute("name", "TDMA MAC") mac.setAttribute("library", "tdmaeventschedulerradiomodel") # append MAC options to macdoc - map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames) + for name in macnames: + value = self.valueof(name, values) + param = e.xmlparam(macdoc, name, value) + mac.appendChild(param) + e.xmlwrite(macdoc, self.macxmlname(ifc)) phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames) From 1f2c78d54a456047746b9dc3975349673436b576 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Sun, 25 Mar 2018 22:08:22 -0700 Subject: [PATCH 105/152] got tdma working, leveraging an example tdma schedule that will be included with packaging --- daemon/core/emane/emanemanager.py | 3 ++- daemon/core/emane/emanemodel.py | 3 +-- daemon/core/emane/tdma.py | 7 ++++--- daemon/examples/tdma/schedule.xml | 17 +++++++++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 daemon/examples/tdma/schedule.xml diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 77d80458..1771b2ff 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -341,10 +341,11 @@ class EmaneManager(ConfigurableManager): with self._emane_node_lock: for key in sorted(self._emane_nodes.keys()): emane_node = self._emane_nodes[key] + logger.debug("post startup for emane node: %s - %s", emane_node.objid, emane_node.name) + emane_node.model.post_startup(self) for netif in emane_node.netifs(): x, y, z = netif.node.position.get() emane_node.setnemposition(netif, x, y, z) - emane_node.model.post_startup(self, netif) def reset(self): """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index e6a94d8a..5752ed7e 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -46,12 +46,11 @@ class EmaneModel(WirelessModel): """ return cls.configure(session.emane, config_data) - def post_startup(self, emane_manager, ifc): + def post_startup(self, emane_manager): """ Logic to execute after the emane manager is finished with startup. :param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session - :param ifc: an interface for the emane node this model is tied to :return: nothing """ logger.info("%s has no post setup tasks: interface(%s)", ifc) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 01850043..19165a4f 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -57,16 +57,17 @@ class EmaneTdmaModel(EmaneModel): def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def post_startup(self, emane_manager, ifc): + def post_startup(self, emane_manager): """ Logic to execute after the emane manager is finished with startup. :param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session - :param ifc: an interface for the emane node this model is tied to :return: nothing """ # get configured schedule - values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getconfig(self.object_id, self.name, self.getdefaultvalues())[1] + if values is None: + return schedule = self.valueof(EmaneTdmaModel.schedule_name, values) event_device = emane_manager.event_device diff --git a/daemon/examples/tdma/schedule.xml b/daemon/examples/tdma/schedule.xml new file mode 100644 index 00000000..6b84a052 --- /dev/null +++ b/daemon/examples/tdma/schedule.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From 2ede524ec36510f1d1ac9617a0b61236f9f104c3 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Sun, 25 Mar 2018 22:16:23 -0700 Subject: [PATCH 106/152] updated tdma schedule file option to leverage gui file widget --- daemon/core/emane/.tdma.py.swp | Bin 0 -> 16384 bytes daemon/core/emane/tdma.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 daemon/core/emane/.tdma.py.swp diff --git a/daemon/core/emane/.tdma.py.swp b/daemon/core/emane/.tdma.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..20b374fcf2d9127f64547b17a8813081d34eba88 GIT binary patch literal 16384 zcmeHOO^h5z6>cYBAYgtH!40X>D~DcX+~YNgA&UZ9+v~8wyK6S0Te(=&R7s34mlve+~5)p960dzy;uD^JN70%p{Pgt zcBZ?kUVZh|tH0O1!{bk`t&5Mj4_WxU-?EN;?dO-KcOSN1IcZseye6Y0l^Lbo=93Te zSm(FNP$WH78SI}){Cp~7t@@`ow^sXsC#Ol=_mfQa<oV{G;FtGURt$U?xbZH_`W|2d zFTB&TE&_*um)~Jo8E`-Fm&2CzP2jV@XMo268~EGXE$gqqPk|SK?*oqm|9KlY12=%@ zfNuj=fG+^|0rvtwL9pYyz&C&^z&*h02$1{%cn)|L*a0p9j{vVhyJrB>aF=v^vma4> zaves>^(WH5I`F4~vt#qi5O@tE*2n0L2!*sDkEGob_OTFuIcb3RDneiOM45bf(JD`As3bIz^U#@;RN7bS*=IAGCC~dausw-F!VI1nv)3R;Tswgx$ zibn-EX@HkJJR;UitV&cr%F0np$!O$W^P*fPBWIP~5!pr)){{U+ZkcTmdsE23xl~P& zw8*5+v$!%Gj*46&RAM8E<#Lr|O79~&mfBC^Q8;#(Niw`5eLV;RC`8Om&HNKN13B{Y zNE=hm;^NNI<;wnoKn7uK<(UjBg{vI4ZCAgS4e@0WCwhXus}oW$^QN$qNtY!xe@k6i zp>-p2Tk>UdDTyo<-eRy2RpgO~JH+`*<)QKN}2+A_d!?s5-** zH`Q=p)<>zwoApF8b_UcXQ%`5%bx`padt%;Q@t{~TDW(UJl}ap{+KYSREXh*^7qYj{ ztgndmmDA!p^_GNwYI*6{(cmi=;_w#uQ34CU5q97|=kuk%mWxQZPEZO6@4PulfQ&AP8Hkb-(Hy5^yynxU1A5KPtMu$_G7zrft^TM5i~5B2suI)tpo;19tAY`yrCBdShs?vb2xTcn614Djwfa~ z!cvs%LOGo!kxs74SRLHZrDABpLGtMk`eHUCGc+xb9rOVkYR#jKdfwQuZO!M+VLKXO zgVL<8Ese3BVyOz1pC`GZfjFm8`xlSxESJ5rUZi-ZZS07KA;FfKt(w__-hOf@wughV zP%#nkW}&>-ng^QeHuff1w|9zlnf4a-x@;EVS@X!AD3@j&_ev7R4mt<>FT8y1(#zL_ zGb`IGgEMPeU?H!2Q!Ibf^ERCj=({AuvzOWCl(%@l4eM1Nvu`cuH%jT}D(kC>SH0Mc z#6C}ms*jfN9LZ;Z(q?9C(0-cAo2?;pDO${h1*KbNq2w)0br>*bgLRs6X@_U=e8jtC z@&XY~Q;aLYC#^=Bg#StmQp{?q%rn!6&D^wKb@OTqR~VhMm)ci|+hdy0EX925%q0bL zdfR`$>OmZ$O@k6_3~855O5wfvWwE-xvau@IrA&3hFb-$~$#WicJm;tL|4p2ue}r>2 zo&U?{`>)|_PiOzH1D^!`iF5offFA=-0-pdJ;3L3cfX?@Hw)cRCfPdgz|9jwvz!-Q8 z_z>_x;B}nyUjm*1o(3KO{*Lqh>%eb-?*LbT2Y~bK&L>bK&QZ4Pyvby(MQr=bT(bMF9^eq zW0eV??)d<17*tK6X5b;hibhyrh>);jN8vE@vc2-a(B8^tUJxd{`?PD``)v>xGEfFf z+nLck!-6_$HIn>qqo?+^z3~RhIW`jQMK?`Sr&R}frW6xDi)?i_q7+Nua@<1R_K8Am zcL7wc;wT>P;q>msW62^>^c?p3@D`R>34|K(I0TV%ckCj3ZX#sJHWhpvp#m4z&k4j% z(p=Z1N_PWsCbvToXztsY1K{Fv9cV3EQWaXhWvRLln@5Q#RNB-4arq{mR@8(V&K}EY z?d-T{JA3KtNND@{WDfzwT0pcA*E2qZ^C~|>N@92cHy7FF+c)K@sZ7W95i-%T@CwI9 za>IFM$v~+V8FPIg8DyJJ#+1J$86-Ez$U+y6HqseXBbGCDOgnnio}%s51C1VHLw+qC zwWdAxsK2Ulv$49~s12EGUh~Hdvg{i-xHmg)I9u%z)X{hHER6;)nuCMuojpRE5u<#d zM0Dbd7x`2@ptCPTr^Nw+Ht)hO=&nE*LgY#Y^^+-%Z&S!sAlj3-Vw1vzyP?AH#UTCM zxs{D$yCK5cEpyO>E3v40`mBvGCtzj`!fRoWBMOS%5ED-c56|s5*b;bIP(1YOiCx%} z2&7|%80J_GEH;8ar|61njuB*43Nx$m3^c2UDgs)OXzD Date: Sun, 25 Mar 2018 22:18:37 -0700 Subject: [PATCH 107/152] removed swap file and added to gitignore --- .gitignore | 3 +++ daemon/core/emane/.tdma.py.swp | Bin 16384 -> 0 bytes 2 files changed, 3 insertions(+) delete mode 100644 daemon/core/emane/.tdma.py.swp diff --git a/.gitignore b/.gitignore index 2a2aeb33..9fb9d6ae 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ coverage.xml # pytest cache files .cache + +# ignore swap files +*.swp diff --git a/daemon/core/emane/.tdma.py.swp b/daemon/core/emane/.tdma.py.swp deleted file mode 100644 index 20b374fcf2d9127f64547b17a8813081d34eba88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeHOO^h5z6>cYBAYgtH!40X>D~DcX+~YNgA&UZ9+v~8wyK6S0Te(=&R7s34mlve+~5)p960dzy;uD^JN70%p{Pgt zcBZ?kUVZh|tH0O1!{bk`t&5Mj4_WxU-?EN;?dO-KcOSN1IcZseye6Y0l^Lbo=93Te zSm(FNP$WH78SI}){Cp~7t@@`ow^sXsC#Ol=_mfQa<oV{G;FtGURt$U?xbZH_`W|2d zFTB&TE&_*um)~Jo8E`-Fm&2CzP2jV@XMo268~EGXE$gqqPk|SK?*oqm|9KlY12=%@ zfNuj=fG+^|0rvtwL9pYyz&C&^z&*h02$1{%cn)|L*a0p9j{vVhyJrB>aF=v^vma4> zaves>^(WH5I`F4~vt#qi5O@tE*2n0L2!*sDkEGob_OTFuIcb3RDneiOM45bf(JD`As3bIz^U#@;RN7bS*=IAGCC~dausw-F!VI1nv)3R;Tswgx$ zibn-EX@HkJJR;UitV&cr%F0np$!O$W^P*fPBWIP~5!pr)){{U+ZkcTmdsE23xl~P& zw8*5+v$!%Gj*46&RAM8E<#Lr|O79~&mfBC^Q8;#(Niw`5eLV;RC`8Om&HNKN13B{Y zNE=hm;^NNI<;wnoKn7uK<(UjBg{vI4ZCAgS4e@0WCwhXus}oW$^QN$qNtY!xe@k6i zp>-p2Tk>UdDTyo<-eRy2RpgO~JH+`*<)QKN}2+A_d!?s5-** zH`Q=p)<>zwoApF8b_UcXQ%`5%bx`padt%;Q@t{~TDW(UJl}ap{+KYSREXh*^7qYj{ ztgndmmDA!p^_GNwYI*6{(cmi=;_w#uQ34CU5q97|=kuk%mWxQZPEZO6@4PulfQ&AP8Hkb-(Hy5^yynxU1A5KPtMu$_G7zrft^TM5i~5B2suI)tpo;19tAY`yrCBdShs?vb2xTcn614Djwfa~ z!cvs%LOGo!kxs74SRLHZrDABpLGtMk`eHUCGc+xb9rOVkYR#jKdfwQuZO!M+VLKXO zgVL<8Ese3BVyOz1pC`GZfjFm8`xlSxESJ5rUZi-ZZS07KA;FfKt(w__-hOf@wughV zP%#nkW}&>-ng^QeHuff1w|9zlnf4a-x@;EVS@X!AD3@j&_ev7R4mt<>FT8y1(#zL_ zGb`IGgEMPeU?H!2Q!Ibf^ERCj=({AuvzOWCl(%@l4eM1Nvu`cuH%jT}D(kC>SH0Mc z#6C}ms*jfN9LZ;Z(q?9C(0-cAo2?;pDO${h1*KbNq2w)0br>*bgLRs6X@_U=e8jtC z@&XY~Q;aLYC#^=Bg#StmQp{?q%rn!6&D^wKb@OTqR~VhMm)ci|+hdy0EX925%q0bL zdfR`$>OmZ$O@k6_3~855O5wfvWwE-xvau@IrA&3hFb-$~$#WicJm;tL|4p2ue}r>2 zo&U?{`>)|_PiOzH1D^!`iF5offFA=-0-pdJ;3L3cfX?@Hw)cRCfPdgz|9jwvz!-Q8 z_z>_x;B}nyUjm*1o(3KO{*Lqh>%eb-?*LbT2Y~bK&L>bK&QZ4Pyvby(MQr=bT(bMF9^eq zW0eV??)d<17*tK6X5b;hibhyrh>);jN8vE@vc2-a(B8^tUJxd{`?PD``)v>xGEfFf z+nLck!-6_$HIn>qqo?+^z3~RhIW`jQMK?`Sr&R}frW6xDi)?i_q7+Nua@<1R_K8Am zcL7wc;wT>P;q>msW62^>^c?p3@D`R>34|K(I0TV%ckCj3ZX#sJHWhpvp#m4z&k4j% z(p=Z1N_PWsCbvToXztsY1K{Fv9cV3EQWaXhWvRLln@5Q#RNB-4arq{mR@8(V&K}EY z?d-T{JA3KtNND@{WDfzwT0pcA*E2qZ^C~|>N@92cHy7FF+c)K@sZ7W95i-%T@CwI9 za>IFM$v~+V8FPIg8DyJJ#+1J$86-Ez$U+y6HqseXBbGCDOgnnio}%s51C1VHLw+qC zwWdAxsK2Ulv$49~s12EGUh~Hdvg{i-xHmg)I9u%z)X{hHER6;)nuCMuojpRE5u<#d zM0Dbd7x`2@ptCPTr^Nw+Ht)hO=&nE*LgY#Y^^+-%Z&S!sAlj3-Vw1vzyP?AH#UTCM zxs{D$yCK5cEpyO>E3v40`mBvGCtzj`!fRoWBMOS%5ED-c56|s5*b;bIP(1YOiCx%} z2&7|%80J_GEH;8ar|61njuB*43Nx$m3^c2UDgs)OXzD Date: Mon, 26 Mar 2018 14:36:43 -0700 Subject: [PATCH 108/152] fixed issue with configuring a couple nrl services, fixed other issues with coresendmsg --- daemon/core/service.py | 2 +- daemon/core/services/nrl.py | 4 ++-- daemon/scripts/coresendmsg | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/daemon/core/service.py b/daemon/core/service.py index 34863afa..47e6eb99 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -639,7 +639,7 @@ class CoreServices(ConfigurableManager): # get the file data data = self.getservicefiledata(svc, filename) if data is None: - data = "%s" % (svc.generateconfig(node, filename, services)) + data = "%s" % svc.generateconfig(node, filename, services) else: data = "%s" % data filetypestr = "service:%s" % svc._name diff --git a/daemon/core/services/nrl.py b/daemon/core/services/nrl.py index a2afbfba..6661ec49 100644 --- a/daemon/core/services/nrl.py +++ b/daemon/core/services/nrl.py @@ -126,7 +126,7 @@ class NrlSmf(NrlService): servicenames = map(lambda x: x._name, services) netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs()) if len(netifs) == 0: - return () + return "" if "arouted" in servicenames: comments += "# arouted service is enabled\n" @@ -606,7 +606,7 @@ class MgenActor(NrlService): servicenames = map(lambda x: x._name, services) netifs = filter(lambda x: not getattr(x, 'control', False), node.netifs()) if len(netifs) == 0: - return () + return "" cfg += comments + cmd + " < /dev/null > /dev/null 2>&1 &\n\n" return cfg diff --git a/daemon/scripts/coresendmsg b/daemon/scripts/coresendmsg index 2f8e3495..be6e030b 100755 --- a/daemon/scripts/coresendmsg +++ b/daemon/scripts/coresendmsg @@ -229,12 +229,11 @@ def main(): continue tlv_name = tlv_typestr - tlv_type = tlv_cls[tlv_name].value try: - tlv_cls.tlv_type_map[tlv_name] + tlv_type = tlv_cls.tlv_type_map[tlv_name] + tlvdata += tlv_cls.pack_string(tlv_type.value, tlv_valstr) except KeyError: usage("Unknown TLV: \"%s\"" % tlv_name) - tlvdata += tlv_cls.pack_string(tlv_type, tlv_valstr) flags = 0 for f in flagstr.split(","): From ef48052d410bce6c2f02288c71f3681b3eb217a3 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Mar 2018 08:24:28 -0700 Subject: [PATCH 109/152] fixed bad logging and updated commeffect to default to connectivity being on, same as emane default --- daemon/core/emane/commeffect.py | 4 ++-- daemon/core/emane/emanemodel.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 5ec67801..05efefc3 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -42,7 +42,7 @@ class EmaneCommEffectModel(EmaneModel): "", "receivebufferperiod"), ] _confmatrix_shim_091 = [ - ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "0", + ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), ] _confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_091 @@ -110,7 +110,7 @@ class EmaneCommEffectModel(EmaneModel): nemid = emane_node.getnemid(netif) nemid2 = emane_node.getnemid(netif2) mbw = bw - + logger.info("sending comm effect event") event.append( nemid, latency=convert_none(delay), diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 5752ed7e..080f4c3f 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -53,7 +53,7 @@ class EmaneModel(WirelessModel): :param core.emane.emanemanager.EmaneManager emane_manager: emane manager for the session :return: nothing """ - logger.info("%s has no post setup tasks: interface(%s)", ifc) + logger.info("emane model(%s) has no post setup tasks", self.name) def buildnemxmlfiles(self, e, ifc): """ From b7327a57989102064a44b86a8733bb8992c83981 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 28 Mar 2018 13:58:49 -0700 Subject: [PATCH 110/152] pass over emane code to cleanup methods and some documentation --- daemon/core/emane/bypass.py | 71 +++++++----- daemon/core/emane/commeffect.py | 66 ++++++----- daemon/core/emane/emanemanager.py | 13 +-- daemon/core/emane/emanemodel.py | 184 +++++++++++++++++------------- daemon/core/emane/ieee80211abg.py | 73 +++++++----- daemon/core/emane/nodes.py | 26 ++--- daemon/core/emane/rfpipe.py | 71 +++++++----- daemon/core/emane/tdma.py | 76 ++++++------ daemon/core/emane/universal.py | 43 ++++--- 9 files changed, 356 insertions(+), 267 deletions(-) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index 8fad0c16..5d0192c1 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -1,5 +1,5 @@ """ -bypass.py: EMANE Bypass model for CORE +EMANE Bypass model for CORE """ from core.emane.emanemodel import EmaneModel @@ -9,8 +9,8 @@ from core.enumerations import ConfigDataTypes class EmaneBypassModel(EmaneModel): name = "emane_bypass" config_matrix = [ - ("none", ConfigDataTypes.BOOL.value, "0", - "True,False", "There are no parameters for the bypass model."), + ("none", ConfigDataTypes.BOOL.value, "0", "True,False", + "There are no parameters for the bypass model."), ] # value groupings @@ -19,36 +19,55 @@ class EmaneBypassModel(EmaneModel): def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. If an individual NEM has a nonstandard config, we need to build that file also. Otherwise the WLAN-wide nXXemane_bypassnem.xml, nXXemane_bypassmac.xml, nXXemane_bypassphy.xml are used. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ - values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) if values is None: return - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "BYPASS NEM") - e.appendtransporttonem(nemdoc, nem, self.object_id, ifc) - mactag = nemdoc.createElement("mac") - mactag.setAttribute("definition", self.macxmlname(ifc)) - nem.appendChild(mactag) - phytag = nemdoc.createElement("phy") - phytag.setAttribute("definition", self.phyxmlname(ifc)) - nem.appendChild(phytag) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) - macdoc = e.xmldoc("mac") - mac = macdoc.getElementsByTagName("mac").pop() - mac.setAttribute("name", "BYPASS MAC") - mac.setAttribute("library", "bypassmaclayer") - e.xmlwrite(macdoc, self.macxmlname(ifc)) + # retrieve xml names + nem_name = self.nem_name(interface) + mac_name = self.mac_name(interface) + phy_name = self.phy_name(interface) - phydoc = e.xmldoc("phy") - phy = phydoc.getElementsByTagName("phy").pop() - phy.setAttribute("name", "BYPASS PHY") - phy.setAttribute("library", "bypassphylayer") - e.xmlwrite(phydoc, self.phyxmlname(ifc)) + # create nem document + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "BYPASS NEM") + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + # create link to mac definition + mac_element = nem_document.createElement("mac") + mac_element.setAttribute("definition", mac_name) + nem_element.appendChild(mac_element) + + # create link to phy definition + phy_element = nem_document.createElement("phy") + phy_element.setAttribute("definition", phy_name) + nem_element.appendChild(phy_element) + + # write nem document + emane_manager.xmlwrite(nem_document, nem_name) + + # create and write mac document + mac_document = emane_manager.xmldoc("mac") + mac_element = mac_document.getElementsByTagName("mac").pop() + mac_element.setAttribute("name", "BYPASS MAC") + mac_element.setAttribute("library", "bypassmaclayer") + emane_manager.xmlwrite(mac_document, mac_name) + + # create and write phy document + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", "BYPASS PHY") + phy_element.setAttribute("library", "bypassphylayer") + emane_manager.xmlwrite(phy_document, phy_name) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 05efefc3..ca53eb5a 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -9,10 +9,7 @@ from core.enumerations import ConfigDataTypes try: from emanesh.events.commeffectevent import CommEffectEvent except ImportError: - try: - from emane.events.commeffectevent import CommEffectEvent - except ImportError: - logger.info("emane 0.9.1+ not found") + logger.info("emane 1.2.1 not found") def convert_none(x): @@ -28,10 +25,9 @@ def convert_none(x): class EmaneCommEffectModel(EmaneModel): - # model name name = "emane_commeffect" - # CommEffect parameters - _confmatrix_shim_base = [ + + config_matrix = [ ("filterfile", ConfigDataTypes.STRING.value, "", "", "filter file"), ("groupid", ConfigDataTypes.UINT32.value, "0", @@ -40,54 +36,64 @@ class EmaneCommEffectModel(EmaneModel): "On,Off", "enable promiscuous mode"), ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"), - ] - _confmatrix_shim_091 = [ ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), ] - _confmatrix_shim = _confmatrix_shim_base + _confmatrix_shim_091 - config_matrix = _confmatrix_shim - # value groupings - config_groups = "CommEffect SHIM Parameters:1-%d" % len(_confmatrix_shim) + config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem and commeffect XMLs in the given path. If an individual NEM has a nonstandard config, we need to build that file also. Otherwise the WLAN-wide nXXemane_commeffectnem.xml, nXXemane_commeffectshim.xml are used. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ - values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) if values is None: return - shimdoc = e.xmldoc("shim") - shim = shimdoc.getElementsByTagName("shim").pop() + + # retrieve xml names + nem_name = self.nem_name(interface) + shim_name = self.shim_name(interface) + + shim_document = emane_manager.xmldoc("shim") + shim = shim_document.getElementsByTagName("shim").pop() shim.setAttribute("name", "commeffect SHIM") shim.setAttribute("library", "commeffectshim") names = self.getnames() - shimnames = list(names[:len(self._confmatrix_shim)]) - shimnames.remove("filterfile") + shim_names = list(names[:len(self.config_matrix)]) + shim_names.remove("filterfile") # append all shim options (except filterfile) to shimdoc - map(lambda n: shim.appendChild(e.xmlparam(shimdoc, n, self.valueof(n, values))), shimnames) + for name in shim_names: + value = self.valueof(name, values) + param = emane_manager.xmlparam(shim_document, name, value) + shim.appendChild(param) + # empty filterfile is not allowed ff = self.valueof("filterfile", values) if ff.strip() != "": - shim.appendChild(e.xmlparam(shimdoc, "filterfile", ff)) - e.xmlwrite(shimdoc, self.shimxmlname(ifc)) + shim.appendChild(emane_manager.xmlparam(shim_document, "filterfile", ff)) + emane_manager.xmlwrite(shim_document, shim_name) - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "commeffect NEM") - nem.setAttribute("type", "unstructured") - e.appendtransporttonem(nemdoc, nem, self.object_id, ifc) - nem.appendChild(e.xmlshimdefinition(nemdoc, self.shimxmlname(ifc))) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "commeffect NEM") + nem_element.setAttribute("type", "unstructured") + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + shim_xml = emane_manager.xmlshimdefinition(nem_document, shim_name) + nem_element.appendChild(shim_xml) + emane_manager.xmlwrite(nem_document, nem_name) def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): """ @@ -110,7 +116,7 @@ class EmaneCommEffectModel(EmaneModel): nemid = emane_node.getnemid(netif) nemid2 = emane_node.getnemid(netif2) mbw = bw - logger.info("sending comm effect event") + logger.info("sending comm effect event") event.append( nemid, latency=convert_none(delay), diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 1771b2ff..e716a548 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -33,12 +33,7 @@ try: from emane.events import LocationEvent from emane.events.eventserviceexception import EventServiceException except ImportError: - try: - from emanesh.events import EventService - from emanesh.events import LocationEvent - from emanesh.events.eventserviceexception import EventServiceException - except ImportError: - logger.info("emane 0.9.1+ not found") + logger.info("emane 1.2.1 not found") EMANE_MODELS = [ EmaneRfPipeModel, @@ -341,7 +336,7 @@ class EmaneManager(ConfigurableManager): with self._emane_node_lock: for key in sorted(self._emane_nodes.keys()): emane_node = self._emane_nodes[key] - logger.debug("post startup for emane node: %s - %s", emane_node.objid, emane_node.name) + logger.debug("post startup for emane node: %s - %s", emane_node.objid, emane_node.name) emane_node.model.post_startup(self) for netif in emane_node.netifs(): x, y, z = netif.node.position.get() @@ -680,7 +675,7 @@ class EmaneManager(ConfigurableManager): """ for key in sorted(self._emane_nodes.keys()): emane_node = self._emane_nodes[key] - emane_node.buildnemxmlfiles(self) + emane_node.build_xml_files(self) def appendtransporttonem(self, doc, nem, nodenum, ifc=None): """ @@ -1061,7 +1056,7 @@ class EmaneGlobalModel(EmaneModel): def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 080f4c3f..90a5ed5f 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -11,35 +11,14 @@ from core.xml import xmlutils class EmaneModel(WirelessModel): """ EMANE models inherit from this parent class, which takes care of - handling configuration messages based on the _confmatrix list of + handling configuration messages based on the list of configurable parameters. Helper functions also live here. """ - _prefix = { - "y": 1e-24, # yocto - "z": 1e-21, # zepto - "a": 1e-18, # atto - "f": 1e-15, # femto - "p": 1e-12, # pico - "n": 1e-9, # nano - "u": 1e-6, # micro - "m": 1e-3, # mili - "c": 1e-2, # centi - "d": 1e-1, # deci - "k": 1e3, # kilo - "M": 1e6, # mega - "G": 1e9, # giga - "T": 1e12, # tera - "P": 1e15, # peta - "E": 1e18, # exa - "Z": 1e21, # zetta - "Y": 1e24, # yotta - } @classmethod def configure_emane(cls, session, config_data): """ - Handle configuration messages for setting up a model. - Pass the Emane object as the manager object. + Handle configuration messages for configuring an emane model. :param core.session.Session session: session to configure emane :param core.conf.ConfigData config_data: configuration data for carrying out a configuration @@ -55,13 +34,17 @@ class EmaneModel(WirelessModel): """ logger.info("emane model(%s) has no post setup tasks", self.name) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ raise NotImplementedError - def buildplatformxmlnementry(self, doc, n, ifc): + def build_nem_xml(self, doc, emane_node, interface): """ Build the NEM definition that goes into the platform.xml file. @@ -71,93 +54,125 @@ class EmaneModel(WirelessModel): or per-EmaneNode config (e.g. . This can be overriden by a model for NEM flexibility; n is the EmaneNode. + + + + :param xml.dom.minidom.Document doc: xml document + :param core.emane.nodes.EmaneNode emane_node: emane node to get information from + :param interface: interface for the emane node + :return: created platform xml """ - nem = doc.createElement("nem") - nem.setAttribute("name", ifc.localname) # if this netif contains a non-standard (per-interface) config, # then we need to use a more specific xml file here - nem.setAttribute("definition", self.nemxmlname(ifc)) + nem_name = self.nem_name(interface) + nem = doc.createElement("nem") + nem.setAttribute("name", interface.localname) + nem.setAttribute("definition", nem_name) return nem - def buildplatformxmltransportentry(self, doc, n, ifc): + def build_transport_xml(self, doc, emane_node, interface): """ Build the transport definition that goes into the platform.xml file. - This returns an XML element that will added to the nem definition. + This returns an XML element that will be added to the nem definition. This default method supports raw and virtual transport types, but may be - overriden by a model to support the e.g. pluggable virtual transport. - n is the EmaneNode. - """ - ttype = ifc.transport_type - if not ttype: - logger.info("warning: %s interface type unsupported!", ifc.name) - ttype = "raw" + overridden by a model to support the e.g. pluggable virtual transport. + + + + + + :param xml.dom.minidom.Document doc: xml document + :param core.emane.nodes.EmaneNode emane_node: emane node to get information from + :param interface: interface for the emane node + :return: created transport xml + """ + transport_type = interface.transport_type + if not transport_type: + logger.info("warning: %s interface type unsupported!", interface.name) + transport_type = "raw" + transport_name = emane_node.transportxmlname(transport_type) + + transport = doc.createElement("transport") + transport.setAttribute("definition", transport_name) - trans = doc.createElement("transport") - trans.setAttribute("definition", n.transportxmlname(ttype)) param = doc.createElement("param") param.setAttribute("name", "device") + param.setAttribute("value", interface.name) - if ttype == "raw": - # raw RJ45 name e.g. "eth0" - param.setAttribute("value", ifc.name) - else: - # virtual TAP name e.g. "n3.0.17" - param.setAttribute("value", ifc.localname) - param.setAttribute("value", ifc.name) + transport.appendChild(param) + return transport - trans.appendChild(param) - return trans - - def basename(self, interface=None): + def _basename(self, interface=None): """ - Return the string that other names are based on. - If a specific config is stored for a node"s interface, a unique - filename is needed; otherwise the name of the EmaneNode is used. + Create name that is leveraged for configuration file creation. + + :param interface: interface for this model + :return: basename used for file creation + :rtype: str """ - emane = self.session.emane name = "n%s" % self.object_id + emane_manager = self.session.emane - if interface is not None: - nodenum = interface.node.objid - # Adamson change - use getifcconfig() to get proper result - # if emane.getconfig(nodenum, self._name, None)[1] is not None: - if emane.getifcconfig(nodenum, self.name, None, interface) is not None: + if interface: + node_id = interface.node.objid + if emane_manager.getifcconfig(node_id, self.name, None, interface) is not None: name = interface.localname.replace(".", "_") return "%s%s" % (name, self.name) - def nemxmlname(self, interface=None): + def nem_name(self, interface=None): """ Return the string name for the NEM XML file, e.g. "n3rfpipenem.xml" + + :param interface: interface for this model + :return: nem xml filename + :rtype: str """ + basename = self._basename(interface) append = "" if interface and interface.transport_type == "raw": append = "_raw" - return "%snem%s.xml" % (self.basename(interface), append) + return "%snem%s.xml" % (basename, append) - def shimxmlname(self, ifc=None): + def shim_name(self, interface=None): """ Return the string name for the SHIM XML file, e.g. "commeffectshim.xml" - """ - return "%sshim.xml" % self.basename(ifc) - def macxmlname(self, ifc=None): + :param interface: interface for this model + :return: shim xml filename + :rtype: str + """ + return "%sshim.xml" % self._basename(interface) + + def mac_name(self, interface=None): """ Return the string name for the MAC XML file, e.g. "n3rfpipemac.xml" - """ - return "%smac.xml" % self.basename(ifc) - def phyxmlname(self, ifc=None): + :param interface: interface for this model + :return: mac xml filename + :rtype: str + """ + return "%smac.xml" % self._basename(interface) + + def phy_name(self, interface=None): """ Return the string name for the PHY XML file, e.g. "n3rfpipephy.xml" + + :param interface: interface for this model + :return: phy xml filename + :rtype: str """ - return "%sphy.xml" % self.basename(ifc) + return "%sphy.xml" % self._basename(interface) def update(self, moved, moved_netifs): """ - invoked from MobilityModel when nodes are moved; this causes - EMANE location events to be generated for the nodes in the moved - list, making EmaneModels compatible with Ns2ScriptedMobility + Invoked from MobilityModel when nodes are moved; this causes + emane location events to be generated for the nodes in the moved + list, making EmaneModels compatible with Ns2ScriptedMobility. + + :param bool moved: were nodes moved + :param list moved_netifs: interfaces that were moved + :return: """ try: wlan = self.session.get_object(self.object_id) @@ -168,17 +183,28 @@ class EmaneModel(WirelessModel): def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): """ Invoked when a Link Message is received. Default is unimplemented. + + :param core.netns.vif.Veth netif: interface one + :param bw: bandwidth to set to + :param delay: packet delay to set to + :param loss: packet loss to set to + :param duplicate: duplicate percentage to set to + :param jitter: jitter to set to + :param core.netns.vif.Veth netif2: interface two + :return: nothing """ - warntxt = "EMANE model %s does not support link " % self.name - warntxt += "configuration, dropping Link Message" - logger.warn(warntxt) + logger.warn("emane model(%s) does not support link configuration", self.name) @staticmethod - def valuestrtoparamlist(dom, name, value): + def value_to_params(doc, name, value): """ - Helper to convert a parameter to a paramlist. - Returns a an XML paramlist, or None if the value does not expand to + Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to multiple values. + + :param xml.dom.minidom.Document doc: xml document + :param name: name of element for params + :param str value: value string to convert to tuple + :return: xml document with added params or None, when an invalid value has been provided """ try: values = utils.make_tuple_fromstr(value, str) @@ -192,4 +218,4 @@ class EmaneModel(WirelessModel): if len(values) < 2: return None - return xmlutils.add_param_list_to_parent(dom, parent=None, name=name, values=values) + return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 86c3a705..2a2c1bf2 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -16,7 +16,7 @@ class EmaneIeee80211abgModel(EmaneModel): xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" # MAC parameters - _confmatrix_mac = [ + _config_mac = [ ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), ("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "", "Defines channel activity estimation timer in seconds"), @@ -46,58 +46,69 @@ class EmaneIeee80211abgModel(EmaneModel): ] # PHY parameters from Universal PHY - _confmatrix_phy = EmaneUniversalModel.config_matrix + _config_phy = EmaneUniversalModel.config_matrix - config_matrix = _confmatrix_mac + _confmatrix_phy + config_matrix = _config_mac + _config_phy # value groupings config_groups = "802.11 MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + len(_config_mac), len(_config_mac) + 1, len(config_matrix)) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. If an individual NEM has a nonstandard config, we need to build that file also. Otherwise the WLAN-wide nXXemane_ieee80211abgnem.xml, nXXemane_ieee80211abgemac.xml, nXXemane_ieee80211abgphy.xml are used. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ - values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) if values is None: return - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "ieee80211abg NEM") - e.appendtransporttonem(nemdoc, nem, self.object_id, ifc) - mactag = nemdoc.createElement("mac") - mactag.setAttribute("definition", self.macxmlname(ifc)) - nem.appendChild(mactag) - phytag = nemdoc.createElement("phy") - phytag.setAttribute("definition", self.phyxmlname(ifc)) - nem.appendChild(phytag) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) - macdoc = e.xmldoc("mac") - mac = macdoc.getElementsByTagName("mac").pop() - mac.setAttribute("name", "ieee80211abg MAC") - mac.setAttribute("library", "ieee80211abgmaclayer") + # retrieve xml names + nem_name = self.nem_name(interface) + mac_name = self.mac_name(interface) + phy_name = self.phy_name(interface) + + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "ieee80211abg NEM") + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + mac_element = nem_document.createElement("mac") + mac_element.setAttribute("definition", mac_name) + nem_element.appendChild(mac_element) + + phy_element = nem_document.createElement("phy") + phy_element.setAttribute("definition", phy_name) + nem_element.appendChild(phy_element) + + emane_manager.xmlwrite(nem_document, nem_name) names = self.getnames() - macnames = names[:len(self._confmatrix_mac)] - phynames = names[len(self._confmatrix_mac):] + mac_names = names[:len(self._config_mac)] + phy_names = names[len(self._config_mac):] - # append all MAC options to macdoc - for macname in macnames: - mac9xnvpairlist = self.get9xmacparamequivalent(macname, values) + mac_document = emane_manager.xmldoc("mac") + mac_element = mac_document.getElementsByTagName("mac").pop() + mac_element.setAttribute("name", "ieee80211abg MAC") + mac_element.setAttribute("library", "ieee80211abgmaclayer") + for name in mac_names: + mac9xnvpairlist = self.get9xmacparamequivalent(name, values) for nvpair in mac9xnvpairlist: - mac.appendChild(e.xmlparam(macdoc, nvpair[0], nvpair[1])) + param = emane_manager.xmlparam(mac_document, nvpair[0], nvpair[1]) + mac_element.appendChild(param) + emane_manager.xmlwrite(mac_document, mac_name) - e.xmlwrite(macdoc, self.macxmlname(ifc)) - - phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames) - e.xmlwrite(phydoc, self.phyxmlname(ifc)) + phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) + emane_manager.xmlwrite(phy_document, phy_name) # # TEMP HACK: Account for parameter convention change in EMANE 9.x diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index fd7f32b6..adcc660b 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -15,10 +15,7 @@ from core.enumerations import RegisterTlvs try: from emane.events import LocationEvent except ImportError: - try: - from emanesh.events import LocationEvent - except ImportError: - logger.info("emane 0.9.1+ not found") + logger.info("emane 1.2.1 not found") class EmaneNet(PyCoreNet): @@ -122,26 +119,25 @@ class EmaneNode(EmaneNet): return ret for netif in self.netifs(): - # - nementry = self.model.buildplatformxmlnementry(doc, self, netif) - # - # - # - trans = self.model.buildplatformxmltransportentry(doc, self, netif) + nementry = self.model.build_nem_xml(doc, self, netif) + trans = self.model.build_transport_xml(doc, self, netif) nementry.appendChild(trans) ret[netif] = nementry return ret - def buildnemxmlfiles(self, emane): + def build_xml_files(self, emane_manager): """ Let the configured model build the necessary nem, mac, and phy XMLs. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :return: nothing """ if self.model is None: return # build XML for overall network (EmaneNode) configs - self.model.buildnemxmlfiles(emane, ifc=None) + self.model.build_xml_files(emane_manager, interface=None) # build XML for specific interface (NEM) configs need_virtual = False @@ -150,7 +146,7 @@ class EmaneNode(EmaneNet): rtype = "raw" for netif in self.netifs(): - self.model.buildnemxmlfiles(emane, netif) + self.model.build_xml_files(emane_manager, netif) if "virtual" in netif.transport_type: need_virtual = True vtype = netif.transport_type @@ -160,10 +156,10 @@ class EmaneNode(EmaneNet): # build transport XML files depending on type of interfaces involved if need_virtual: - self.buildtransportxml(emane, vtype) + self.buildtransportxml(emane_manager, vtype) if need_raw: - self.buildtransportxml(emane, rtype) + self.buildtransportxml(emane_manager, rtype) def buildtransportxml(self, emane, transport_type): """ diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 08302018..55c60533 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -15,7 +15,7 @@ class EmaneRfPipeModel(EmaneModel): # configuration parameters are # ( "name", "type", "default", "possible-value-list", "caption") # MAC parameters - _confmatrix_mac = [ + _config_mac = [ ("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"), ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), @@ -31,52 +31,65 @@ class EmaneRfPipeModel(EmaneModel): ] # PHY parameters from Universal PHY - _confmatrix_phy = EmaneUniversalModel.config_matrix + _config_phy = EmaneUniversalModel.config_matrix - config_matrix = _confmatrix_mac + _confmatrix_phy + config_matrix = _config_mac + _config_phy # value groupings config_groups = "RF-PIPE MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + len(_config_mac), len(_config_mac) + 1, len(config_matrix)) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. If an individual NEM has a nonstandard config, we need to build that file also. Otherwise the WLAN-wide nXXemane_rfpipenem.xml, nXXemane_rfpipemac.xml, nXXemane_rfpipephy.xml are used. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ - values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) if values is None: return - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "RF-PIPE NEM") - e.appendtransporttonem(nemdoc, nem, self.object_id, ifc) - mactag = nemdoc.createElement("mac") - mactag.setAttribute("definition", self.macxmlname(ifc)) - nem.appendChild(mactag) - phytag = nemdoc.createElement("phy") - phytag.setAttribute("definition", self.phyxmlname(ifc)) - nem.appendChild(phytag) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) + # retrieve xml names + nem_name = self.nem_name(interface) + mac_name = self.mac_name(interface) + phy_name = self.phy_name(interface) + + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "RF-PIPE NEM") + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + mac_element = nem_document.createElement("mac") + mac_element.setAttribute("definition", mac_name) + nem_element.appendChild(mac_element) + + phy_element = nem_document.createElement("phy") + phy_element.setAttribute("definition", phy_name) + nem_element.appendChild(phy_element) + + emane_manager.xmlwrite(nem_document, nem_name) names = list(self.getnames()) - macnames = names[:len(self._confmatrix_mac)] - phynames = names[len(self._confmatrix_mac):] + mac_name = names[:len(self._config_mac)] + phy_names = names[len(self._config_mac):] - macdoc = e.xmldoc("mac") - mac = macdoc.getElementsByTagName("mac").pop() - mac.setAttribute("name", "RF-PIPE MAC") - mac.setAttribute("library", "rfpipemaclayer") + mac_document = emane_manager.xmldoc("mac") + mac_element = mac_document.getElementsByTagName("mac").pop() + mac_element.setAttribute("name", "RF-PIPE MAC") + mac_element.setAttribute("library", "rfpipemaclayer") + for name in mac_name: + value = self.valueof(name, values) + param = emane_manager.xmlparam(mac_document, name, value) + mac_element.appendChild(param) + emane_manager.xmlwrite(mac_document, mac_name) - # append MAC options to macdoc - map(lambda n: mac.appendChild(e.xmlparam(macdoc, n, self.valueof(n, values))), macnames) - e.xmlwrite(macdoc, self.macxmlname(ifc)) - - phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames) - e.xmlwrite(phydoc, self.phyxmlname(ifc)) + phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) + emane_manager.xmlwrite(phy_document, phy_name) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index a1cbeac3..34a18348 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -20,7 +20,7 @@ class EmaneTdmaModel(EmaneModel): default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") # MAC parameters - _confmatrix_mac = [ + _config_mac = [ (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file"), ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), @@ -46,13 +46,13 @@ class EmaneTdmaModel(EmaneModel): ] # PHY parameters from Universal PHY - _confmatrix_phy = EmaneUniversalModel.config_matrix + _config_phy = EmaneUniversalModel.config_matrix - config_matrix = _confmatrix_mac + _confmatrix_phy + config_matrix = _config_mac + _config_phy # value groupings config_groups = "TDMA MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(config_matrix)) + len(_config_mac), len(_config_mac) + 1, len(config_matrix)) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) @@ -69,54 +69,64 @@ class EmaneTdmaModel(EmaneModel): if values is None: return schedule = self.valueof(EmaneTdmaModel.schedule_name, values) - + event_device = emane_manager.event_device # initiate tdma schedule logger.info("setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device) utils.check_cmd(["emaneevent-tdmaschedule", "-i", event_device, schedule]) - def buildnemxmlfiles(self, e, ifc): + def build_xml_files(self, emane_manager, interface): """ Build the necessary nem, mac, and phy XMLs in the given path. If an individual NEM has a nonstandard config, we need to build that file also. Otherwise the WLAN-wide nXXemane_tdmanem.xml, nXXemane_tdmamac.xml, nXXemane_tdmaphy.xml are used. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing """ - values = e.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), ifc) + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) if values is None: return - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "TDMA NEM") - e.appendtransporttonem(nemdoc, nem, self.object_id, ifc) - mactag = nemdoc.createElement("mac") - mactag.setAttribute("definition", self.macxmlname(ifc)) - nem.appendChild(mactag) - phytag = nemdoc.createElement("phy") - phytag.setAttribute("definition", self.phyxmlname(ifc)) - nem.appendChild(phytag) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) + # retrieve xml names + nem_name = self.nem_name(interface) + mac_name = self.mac_name(interface) + phy_name = self.phy_name(interface) + + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "TDMA NEM") + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + mac_element = nem_document.createElement("mac") + mac_element.setAttribute("definition", mac_name) + nem_element.appendChild(mac_element) + + phy_element = nem_document.createElement("phy") + phy_element.setAttribute("definition", phy_name) + nem_element.appendChild(phy_element) + + emane_manager.xmlwrite(nem_document, nem_name) names = list(self.getnames()) - macnames = names[:len(self._confmatrix_mac)] - phynames = names[len(self._confmatrix_mac):] + mac_names = names[:len(self._config_mac)] + phy_names = names[len(self._config_mac):] # make any changes to the mac/phy names here to e.g. exclude them from the XML output - macnames.remove(EmaneTdmaModel.schedule_name) + mac_names.remove(EmaneTdmaModel.schedule_name) - macdoc = e.xmldoc("mac") - mac = macdoc.getElementsByTagName("mac").pop() - mac.setAttribute("name", "TDMA MAC") - mac.setAttribute("library", "tdmaeventschedulerradiomodel") - # append MAC options to macdoc - for name in macnames: + mac_document = emane_manager.xmldoc("mac") + mac_element = mac_document.getElementsByTagName("mac").pop() + mac_element.setAttribute("name", "TDMA MAC") + mac_element.setAttribute("library", "tdmaeventschedulerradiomodel") + for name in mac_names: value = self.valueof(name, values) - param = e.xmlparam(macdoc, name, value) - mac.appendChild(param) + param = emane_manager.xmlparam(mac_document, name, value) + mac_element.appendChild(param) + emane_manager.xmlwrite(mac_document, mac_name) - e.xmlwrite(macdoc, self.macxmlname(ifc)) - - phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames) - e.xmlwrite(phydoc, self.phyxmlname(ifc)) + phydoc = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) + emane_manager.xmlwrite(phydoc, phy_name) diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 8b437aaa..6cf108f4 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -13,9 +13,6 @@ class EmaneUniversalModel(EmaneModel): not instantiated. """ - def __init__(self, session, object_id=None): - raise NotImplemented("Cannot use this class directly") - name = "emane_universal" _xmlname = "universalphy" _xmllibrary = "universalphylayer" @@ -53,22 +50,38 @@ class EmaneUniversalModel(EmaneModel): ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), ] + def __init__(self, session, object_id=None): + raise NotImplemented("Cannot use this class directly") + @classmethod - def getphydoc(cls, e, mac, values, phynames): - phydoc = e.xmldoc("phy") - phy = phydoc.getElementsByTagName("phy").pop() - phy.setAttribute("name", cls._xmlname) + def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): + """ + Create a phy doc for a model based on the universal model. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for + :param tuple values: emane model configuration values + :param phy_names: names for phy configuration values + :return: + """ + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", cls._xmlname) name = "frequencyofinterest" - value = mac.valueof(name, values) - frequencies = cls.valuestrtoparamlist(phydoc, name, value) + value = emane_model.valueof(name, values) + frequencies = cls.value_to_params(phy_document, name, value) if frequencies: - phynames = list(phynames) - phynames.remove("frequencyofinterest") + phy_names = list(phy_names) + phy_names.remove("frequencyofinterest") # append all PHY options to phydoc - map(lambda n: phy.appendChild(e.xmlparam(phydoc, n, mac.valueof(n, values))), phynames) - if frequencies: - phy.appendChild(frequencies) + for name in phy_names: + value = emane_model.valueof(name, values) + param = emane_manager.xmlparam(phy_document, name, value) + phy_element.appendChild(param) - return phydoc + if frequencies: + phy_element.appendChild(frequencies) + + return phy_document From 2b2548a9272026f2e93bbcaae67135b10fd73309 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Mar 2018 23:14:04 -0700 Subject: [PATCH 111/152] fixed typo during cleanup pass --- daemon/core/emane/rfpipe.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 55c60533..366fd205 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -78,14 +78,14 @@ class EmaneRfPipeModel(EmaneModel): emane_manager.xmlwrite(nem_document, nem_name) names = list(self.getnames()) - mac_name = names[:len(self._config_mac)] + mac_names = names[:len(self._config_mac)] phy_names = names[len(self._config_mac):] mac_document = emane_manager.xmldoc("mac") mac_element = mac_document.getElementsByTagName("mac").pop() mac_element.setAttribute("name", "RF-PIPE MAC") mac_element.setAttribute("library", "rfpipemaclayer") - for name in mac_name: + for name in mac_names: value = self.valueof(name, values) param = emane_manager.xmlparam(mac_document, name, value) mac_element.appendChild(param) From a48036b353edae63f4517517569045e3b4ca97e1 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 27 Mar 2018 23:38:34 -0700 Subject: [PATCH 112/152] updated emane tests, all currently working --- daemon/tests/test_emane.py | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/daemon/tests/test_emane.py b/daemon/tests/test_emane.py index ebd8cd1b..6c7ade45 100644 --- a/daemon/tests/test_emane.py +++ b/daemon/tests/test_emane.py @@ -15,30 +15,18 @@ from core.emane.rfpipe import EmaneRfPipeModel from core.emane.tdma import EmaneTdmaModel -def setup_commeffect(session, emane_node): - # configure emane to enable default connectivity - config_data = ConfigData( - node=emane_node.objid, - object="emane_commeffect", - type=2, - data_types=(11,), - data_values="defaultconnectivitymode=1" - ) - EmaneCommEffectModel.configure_emane(session, config_data) - - _EMANE_MODELS = [ - (EmaneIeee80211abgModel, None), - (EmaneRfPipeModel, None), - (EmaneBypassModel, None), - (EmaneCommEffectModel, setup_commeffect), - (EmaneTdmaModel, None), + EmaneIeee80211abgModel, + EmaneRfPipeModel, + EmaneBypassModel, + EmaneCommEffectModel, + EmaneTdmaModel, ] class TestEmane: - @pytest.mark.parametrize("model,setup", _EMANE_MODELS) - def test_models(self, core, model, setup): + @pytest.mark.parametrize("model", _EMANE_MODELS) + def test_models(self, core, model): """ Test emane models within a basic network. @@ -54,10 +42,6 @@ class TestEmane: # set the emane model core.set_emane_model(emane_node, model) - # run setup method, if needed - if setup: - setup(core.session, emane_node) - # create nodes core.create_node("n1", objid=1, position=(150, 150), services=EMANE_SERVICES, model="mdr") core.create_node("n2", objid=2, position=(300, 150), services=EMANE_SERVICES, model="mdr") From 81840e501cbd074ea6ae649aa336f6a3e45c00f3 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 28 Mar 2018 00:28:07 -0700 Subject: [PATCH 113/152] added link to emane wiki in anticipation of dynamic configuration, pointing users to the wiki for guidance --- gui/wlan.tcl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gui/wlan.tcl b/gui/wlan.tcl index 4f103fe0..05cb7bc6 100644 --- a/gui/wlan.tcl +++ b/gui/wlan.tcl @@ -491,7 +491,13 @@ proc wlanConfigDialogHelper { wi target apply } { $wi.wl.note add $wi.wl.note.emane -text "EMANE" -underline 0 set txt "The EMANE emulation system provides more complex wireless radio" set txt "$txt emulation\n using pluggable MAC and PHY modules." + set txt "$txt Refer to the wiki for configuration option details" ttk::label $wi.wl.note.emane.tlab -text $txt + ttk::button $wi.wl.note.emane.wiki -text "EMANE Wiki" \ + -image $plugin_img_edit -compound right \ + -command \ + "_launchBrowser https://github.com/adjacentlink/emane/wiki" + pack $wi.wl.note.emane.wiki -side top -anchor w -padx 4 -pady 4 pack $wi.wl.note.emane.tlab -side top -anchor w -padx 4 -pady 4 # models From 9ce8233bc3fffd4ad993c1315d98f4c12ad0b8be Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 13:32:06 -0700 Subject: [PATCH 114/152] effort to consolidate logic for emane models, to avoid redundancy for defining a new model --- daemon/core/emane/bypass.py | 67 +++---------------- daemon/core/emane/commeffect.py | 22 +++---- daemon/core/emane/emanemodel.py | 103 +++++++++++++++++++++++++++--- daemon/core/emane/ieee80211abg.py | 84 +++++------------------- daemon/core/emane/rfpipe.py | 72 +-------------------- daemon/core/emane/tdma.py | 76 ++-------------------- daemon/core/emane/universal.py | 4 +- 7 files changed, 134 insertions(+), 294 deletions(-) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index 5d0192c1..df3e10ed 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -8,66 +8,15 @@ from core.enumerations import ConfigDataTypes class EmaneBypassModel(EmaneModel): name = "emane_bypass" - config_matrix = [ + library = "bypassmaclayer" + + config_ignore = {"none"} + _config_mac = [ ("none", ConfigDataTypes.BOOL.value, "0", "True,False", "There are no parameters for the bypass model."), ] + _config_phy = [] - # value groupings - config_groups = "Bypass Parameters:1-1" - - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - - def build_xml_files(self, emane_manager, interface): - """ - Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to build - that file also. Otherwise the WLAN-wide nXXemane_bypassnem.xml, - nXXemane_bypassmac.xml, nXXemane_bypassphy.xml are used. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param interface: interface for the emane node - :return: nothing - """ - values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) - if values is None: - return - - # retrieve xml names - nem_name = self.nem_name(interface) - mac_name = self.mac_name(interface) - phy_name = self.phy_name(interface) - - # create nem document - nem_document = emane_manager.xmldoc("nem") - nem_element = nem_document.getElementsByTagName("nem").pop() - nem_element.setAttribute("name", "BYPASS NEM") - emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) - - # create link to mac definition - mac_element = nem_document.createElement("mac") - mac_element.setAttribute("definition", mac_name) - nem_element.appendChild(mac_element) - - # create link to phy definition - phy_element = nem_document.createElement("phy") - phy_element.setAttribute("definition", phy_name) - nem_element.appendChild(phy_element) - - # write nem document - emane_manager.xmlwrite(nem_document, nem_name) - - # create and write mac document - mac_document = emane_manager.xmldoc("mac") - mac_element = mac_document.getElementsByTagName("mac").pop() - mac_element.setAttribute("name", "BYPASS MAC") - mac_element.setAttribute("library", "bypassmaclayer") - emane_manager.xmlwrite(mac_document, mac_name) - - # create and write phy document - phy_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", "BYPASS PHY") - phy_element.setAttribute("library", "bypassphylayer") - emane_manager.xmlwrite(phy_document, phy_name) + @property + def config_groups(self): + return "Bypass Parameters:1-1" diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index ca53eb5a..4afd83a5 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -28,22 +28,16 @@ class EmaneCommEffectModel(EmaneModel): name = "emane_commeffect" config_matrix = [ - ("filterfile", ConfigDataTypes.STRING.value, "", - "", "filter file"), - ("groupid", ConfigDataTypes.UINT32.value, "0", - "", "NEM Group ID"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", - "On,Off", "enable promiscuous mode"), - ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", - "", "receivebufferperiod"), - ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", - "On,Off", "defaultconnectivity"), + ("filterfile", ConfigDataTypes.STRING.value, "", "", "filter file"), + ("groupid", ConfigDataTypes.UINT32.value, "0", "", "NEM Group ID"), + ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), + ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"), + ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), ] - config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) - - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) + @property + def config_groups(self): + return "CommEffect SHIM Parameters:1-%d" % len(self.config_matrix) def build_xml_files(self, emane_manager, interface): """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 90a5ed5f..75865286 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -3,6 +3,7 @@ Defines Emane Models used within CORE. """ from core import logger +from core.emane.universal import EmaneUniversalModel from core.misc import utils from core.mobility import WirelessModel from core.xml import xmlutils @@ -14,6 +15,98 @@ class EmaneModel(WirelessModel): handling configuration messages based on the list of configurable parameters. Helper functions also live here. """ + _config_mac = [] + _config_phy = EmaneUniversalModel.config_matrix + library = None + config_ignore = set() + + def __init__(self, session, object_id=None): + WirelessModel.__init__(self, session, object_id) + + @property + def config_matrix(self): + return self._config_mac + self._config_phy + + @property + def config_groups(self): + mac_len = len(self._config_mac) + config_len = len(self.config_matrix) + return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) + + def build_xml_files(self, emane_manager, interface): + """ + Builds xml files for emane. Includes a nem.xml file that points to both mac.xml and phy.xml definitions. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nothing + """ + # retrieve configuration values + values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) + if values is None: + return + + # create document and write to disk + nem_name = self.nem_name(interface) + nem_document = self.create_nem_doc(emane_manager, interface) + emane_manager.xmlwrite(nem_document, nem_name) + + # create mac document and write to disk + mac_name = self.mac_name(interface) + mac_document = self.create_mac_doc(emane_manager, values) + if mac_document: + emane_manager.xmlwrite(mac_document, mac_name) + + # create phy document and write to disk + phy_name = self.phy_name(interface) + phy_document = self.create_phy_doc(emane_manager, values) + if phy_document: + emane_manager.xmlwrite(phy_document, phy_name) + + def create_nem_doc(self, emane_manager, interface): + mac_name = self.mac_name(interface) + phy_name = self.phy_name(interface) + + nem_document = emane_manager.xmldoc("nem") + nem_element = nem_document.getElementsByTagName("nem").pop() + nem_element.setAttribute("name", "%s NEM" % self.name) + emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) + + mac_element = nem_document.createElement("mac") + mac_element.setAttribute("definition", mac_name) + nem_element.appendChild(mac_element) + + phy_element = nem_document.createElement("phy") + phy_element.setAttribute("definition", phy_name) + nem_element.appendChild(phy_element) + + return nem_document + + def create_mac_doc(self, emane_manager, values): + names = list(self.getnames()) + mac_names = names[:len(self._config_mac)] + + mac_document = emane_manager.xmldoc("mac") + mac_element = mac_document.getElementsByTagName("mac").pop() + mac_element.setAttribute("name", "%s MAC" % self.name) + + if not self.library: + raise ValueError("must define emane model library") + mac_element.setAttribute("library", self.library) + + for name in mac_names: + if name in self.config_ignore: + continue + value = self.valueof(name, values) + param = emane_manager.xmlparam(mac_document, name, value) + mac_element.appendChild(param) + + return mac_document + + def create_phy_doc(self, emane_manager, values): + names = list(self.getnames()) + phy_names = names[len(self._config_mac):] + return EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) @classmethod def configure_emane(cls, session, config_data): @@ -34,16 +127,6 @@ class EmaneModel(WirelessModel): """ logger.info("emane model(%s) has no post setup tasks", self.name) - def build_xml_files(self, emane_manager, interface): - """ - Build the necessary nem, mac, and phy XMLs in the given path. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param interface: interface for the emane node - :return: nothing - """ - raise NotImplementedError - def build_nem_xml(self, doc, emane_node, interface): """ Build the NEM definition that goes into the platform.xml file. diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 2a2c1bf2..09c3b7bd 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -3,19 +3,19 @@ ieee80211abg.py: EMANE IEEE 802.11abg model for CORE """ from core.emane.emanemodel import EmaneModel -from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes class EmaneIeee80211abgModel(EmaneModel): # model name name = "emane_ieee80211abg" + library = "ieee80211abgmaclayer" + + # mac configuration _80211rates = "1 1 Mbps,2 2 Mbps,3 5.5 Mbps,4 11 Mbps,5 6 Mbps," + \ "6 9 Mbps,7 12 Mbps,8 18 Mbps,9 24 Mbps,10 36 Mbps,11 48 Mbps," + \ "12 54 Mbps" xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" - - # MAC parameters _config_mac = [ ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), ("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "", @@ -45,97 +45,43 @@ class EmaneIeee80211abgModel(EmaneModel): ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), ] - # PHY parameters from Universal PHY - _config_phy = EmaneUniversalModel.config_matrix - - config_matrix = _config_mac + _config_phy - # value groupings - config_groups = "802.11 MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_config_mac), len(_config_mac) + 1, len(config_matrix)) - - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - - def build_xml_files(self, emane_manager, interface): - """ - Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to build - that file also. Otherwise the WLAN-wide - nXXemane_ieee80211abgnem.xml, nXXemane_ieee80211abgemac.xml, - nXXemane_ieee80211abgphy.xml are used. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param interface: interface for the emane node - :return: nothing - """ - values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) - if values is None: - return - - # retrieve xml names - nem_name = self.nem_name(interface) - mac_name = self.mac_name(interface) - phy_name = self.phy_name(interface) - - nem_document = emane_manager.xmldoc("nem") - nem_element = nem_document.getElementsByTagName("nem").pop() - nem_element.setAttribute("name", "ieee80211abg NEM") - emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) - - mac_element = nem_document.createElement("mac") - mac_element.setAttribute("definition", mac_name) - nem_element.appendChild(mac_element) - - phy_element = nem_document.createElement("phy") - phy_element.setAttribute("definition", phy_name) - nem_element.appendChild(phy_element) - - emane_manager.xmlwrite(nem_document, nem_name) - + def create_mac_doc(self, emane_manager, values): names = self.getnames() mac_names = names[:len(self._config_mac)] - phy_names = names[len(self._config_mac):] - mac_document = emane_manager.xmldoc("mac") mac_element = mac_document.getElementsByTagName("mac").pop() - mac_element.setAttribute("name", "ieee80211abg MAC") - mac_element.setAttribute("library", "ieee80211abgmaclayer") + mac_element.setAttribute("name", "%s MAC" % self.name) + mac_element.setAttribute("library", self.library) for name in mac_names: mac9xnvpairlist = self.get9xmacparamequivalent(name, values) for nvpair in mac9xnvpairlist: param = emane_manager.xmlparam(mac_document, nvpair[0], nvpair[1]) mac_element.appendChild(param) - emane_manager.xmlwrite(mac_document, mac_name) + return mac_document - phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) - emane_manager.xmlwrite(phy_document, phy_name) - - # - # TEMP HACK: Account for parameter convention change in EMANE 9.x - # This allows CORE to preserve the entry layout for the mac "category" parameters - # and work with EMANE 9.x onwards. - # - def get9xmacparamequivalent(self, macname, values): + def get9xmacparamequivalent(self, mac_name, values): """ + This accounts for current config values labeled value0, value1, value2, etc. + Generate a list of 80211abg mac parameters in 0.9.x layout for a given mac parameter in 8.x layout.For mac category parameters, the list returned will contain the four equivalent 9.x parameter and value pairs. Otherwise, the list returned will only contain a single name and value pair. """ nvpairlist = [] - macparmval = self.valueof(macname, values) + macparmval = self.valueof(mac_name, values) - if macname in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit", "msdu"]: + if mac_name in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit", "msdu"]: for catval in macparmval.split(): idx_and_val = catval.split(":") idx = int(idx_and_val[0]) val = idx_and_val[1] # aifs and tx are in microseconds. Convert to seconds. - if macname in ["aifs", "txop"]: + if mac_name in ["aifs", "txop"]: val = "%f" % (float(val) * 1e-6) - name9x = "%s%d" % (macname, idx) + name9x = "%s%d" % (mac_name, idx) nvpairlist.append([name9x, val]) else: - nvpairlist.append([macname, macparmval]) + nvpairlist.append([mac_name, macparmval]) return nvpairlist diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 366fd205..184f32d8 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -3,18 +3,16 @@ rfpipe.py: EMANE RF-PIPE model for CORE """ from core.emane.emanemodel import EmaneModel -from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes class EmaneRfPipeModel(EmaneModel): # model name name = "emane_rfpipe" - xml_path = "/usr/share/emane/xml/models/mac/rfpipe" + library = "rfpipemaclayer" - # configuration parameters are - # ( "name", "type", "default", "possible-value-list", "caption") - # MAC parameters + # mac configuration + xml_path = "/usr/share/emane/xml/models/mac/rfpipe" _config_mac = [ ("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"), ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), @@ -29,67 +27,3 @@ class EmaneRfPipeModel(EmaneModel): ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", "R2RI radio metric report interval (sec)"), ] - - # PHY parameters from Universal PHY - _config_phy = EmaneUniversalModel.config_matrix - - config_matrix = _config_mac + _config_phy - - # value groupings - config_groups = "RF-PIPE MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_config_mac), len(_config_mac) + 1, len(config_matrix)) - - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - - def build_xml_files(self, emane_manager, interface): - """ - Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to build - that file also. Otherwise the WLAN-wide nXXemane_rfpipenem.xml, - nXXemane_rfpipemac.xml, nXXemane_rfpipephy.xml are used. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param interface: interface for the emane node - :return: nothing - """ - values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) - if values is None: - return - - # retrieve xml names - nem_name = self.nem_name(interface) - mac_name = self.mac_name(interface) - phy_name = self.phy_name(interface) - - nem_document = emane_manager.xmldoc("nem") - nem_element = nem_document.getElementsByTagName("nem").pop() - nem_element.setAttribute("name", "RF-PIPE NEM") - emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) - - mac_element = nem_document.createElement("mac") - mac_element.setAttribute("definition", mac_name) - nem_element.appendChild(mac_element) - - phy_element = nem_document.createElement("phy") - phy_element.setAttribute("definition", phy_name) - nem_element.appendChild(phy_element) - - emane_manager.xmlwrite(nem_document, nem_name) - - names = list(self.getnames()) - mac_names = names[:len(self._config_mac)] - phy_names = names[len(self._config_mac):] - - mac_document = emane_manager.xmldoc("mac") - mac_element = mac_document.getElementsByTagName("mac").pop() - mac_element.setAttribute("name", "RF-PIPE MAC") - mac_element.setAttribute("library", "rfpipemaclayer") - for name in mac_names: - value = self.valueof(name, values) - param = emane_manager.xmlparam(mac_document, name, value) - mac_element.appendChild(param) - emane_manager.xmlwrite(mac_document, mac_name) - - phy_document = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) - emane_manager.xmlwrite(phy_document, phy_name) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 34a18348..5f582485 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -7,7 +7,6 @@ import os from core import constants from core import logger from core.emane.emanemodel import EmaneModel -from core.emane.universal import EmaneUniversalModel from core.enumerations import ConfigDataTypes from core.misc import utils @@ -15,11 +14,13 @@ from core.misc import utils class EmaneTdmaModel(EmaneModel): # model name name = "emane_tdma" + library = "tdmaeventschedulerradiomodel" + + # mac configuration xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler" schedule_name = "schedule" default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") - - # MAC parameters + config_ignore = {schedule_name} _config_mac = [ (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file"), ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), @@ -45,18 +46,6 @@ class EmaneTdmaModel(EmaneModel): "enable strict dequeueing to specified queues only"), ] - # PHY parameters from Universal PHY - _config_phy = EmaneUniversalModel.config_matrix - - config_matrix = _config_mac + _config_phy - - # value groupings - config_groups = "TDMA MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" % ( - len(_config_mac), len(_config_mac) + 1, len(config_matrix)) - - def __init__(self, session, object_id=None): - EmaneModel.__init__(self, session, object_id) - def post_startup(self, emane_manager): """ Logic to execute after the emane manager is finished with startup. @@ -68,65 +57,10 @@ class EmaneTdmaModel(EmaneModel): values = emane_manager.getconfig(self.object_id, self.name, self.getdefaultvalues())[1] if values is None: return - schedule = self.valueof(EmaneTdmaModel.schedule_name, values) + schedule = self.valueof(self.schedule_name, values) event_device = emane_manager.event_device # initiate tdma schedule logger.info("setting up tdma schedule: schedule(%s) device(%s)", schedule, event_device) utils.check_cmd(["emaneevent-tdmaschedule", "-i", event_device, schedule]) - - def build_xml_files(self, emane_manager, interface): - """ - Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to build - that file also. Otherwise the WLAN-wide nXXemane_tdmanem.xml, - nXXemane_tdmamac.xml, nXXemane_tdmaphy.xml are used. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param interface: interface for the emane node - :return: nothing - """ - values = emane_manager.getifcconfig(self.object_id, self.name, self.getdefaultvalues(), interface) - if values is None: - return - - # retrieve xml names - nem_name = self.nem_name(interface) - mac_name = self.mac_name(interface) - phy_name = self.phy_name(interface) - - nem_document = emane_manager.xmldoc("nem") - nem_element = nem_document.getElementsByTagName("nem").pop() - nem_element.setAttribute("name", "TDMA NEM") - emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) - - mac_element = nem_document.createElement("mac") - mac_element.setAttribute("definition", mac_name) - nem_element.appendChild(mac_element) - - phy_element = nem_document.createElement("phy") - phy_element.setAttribute("definition", phy_name) - nem_element.appendChild(phy_element) - - emane_manager.xmlwrite(nem_document, nem_name) - - names = list(self.getnames()) - mac_names = names[:len(self._config_mac)] - phy_names = names[len(self._config_mac):] - - # make any changes to the mac/phy names here to e.g. exclude them from the XML output - mac_names.remove(EmaneTdmaModel.schedule_name) - - mac_document = emane_manager.xmldoc("mac") - mac_element = mac_document.getElementsByTagName("mac").pop() - mac_element.setAttribute("name", "TDMA MAC") - mac_element.setAttribute("library", "tdmaeventschedulerradiomodel") - for name in mac_names: - value = self.valueof(name, values) - param = emane_manager.xmlparam(mac_document, name, value) - mac_element.appendChild(param) - emane_manager.xmlwrite(mac_document, mac_name) - - phydoc = EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) - emane_manager.xmlwrite(phydoc, phy_name) diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py index 6cf108f4..5c754dc4 100644 --- a/daemon/core/emane/universal.py +++ b/daemon/core/emane/universal.py @@ -14,10 +14,10 @@ class EmaneUniversalModel(EmaneModel): """ name = "emane_universal" - _xmlname = "universalphy" - _xmllibrary = "universalphylayer" # universal PHY parameters + _xmlname = "universalphy" + _xmllibrary = "universalphylayer" config_matrix = [ ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), From 4df0d78cae8b0926a431aa254c5ee56057941ef0 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 13:48:40 -0700 Subject: [PATCH 115/152] resolved circular import withthe universal model --- daemon/core/emane/emanemodel.py | 82 ++++++++++++++++++++++++++++++- daemon/core/emane/universal.py | 87 --------------------------------- 2 files changed, 81 insertions(+), 88 deletions(-) delete mode 100644 daemon/core/emane/universal.py diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 75865286..84e6022c 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -3,7 +3,7 @@ Defines Emane Models used within CORE. """ from core import logger -from core.emane.universal import EmaneUniversalModel +from core.enumerations import ConfigDataTypes from core.misc import utils from core.mobility import WirelessModel from core.xml import xmlutils @@ -302,3 +302,83 @@ class EmaneModel(WirelessModel): return None return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) + + +class EmaneUniversalModel(EmaneModel): + """ + This Univeral PHY model is meant to be imported by other models, + not instantiated. + """ + + name = "emane_universal" + + # universal PHY parameters + _xmlname = "universalphy" + _xmllibrary = "universalphylayer" + config_matrix = [ + ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), + ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), + ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", + "Nakagami D0: distance lower bound in meters"), + ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", + "Nakagami D1: distance upper bound in meters"), + ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), + ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", + "Nakagami M1: shape factor for distance >= D0 < D1"), + ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", + "Nakagami M2: shape factor for distance >= D1"), + ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), + ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), + ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), + ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), + ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), + ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), + ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", + "Noise maximum message propagation in microsecond"), + ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", + "Noise maximum segment duration in microseconds"), + ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", + "Noise maximum segment offset in microseconds"), + ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), + ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), + ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), + ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), + ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), + ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), + ] + + def __init__(self, session, object_id=None): + raise NotImplemented("Cannot use this class directly") + + @classmethod + def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): + """ + Create a phy doc for a model based on the universal model. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for + :param tuple values: emane model configuration values + :param phy_names: names for phy configuration values + :return: + """ + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", cls._xmlname) + + name = "frequencyofinterest" + value = emane_model.valueof(name, values) + frequencies = cls.value_to_params(phy_document, name, value) + if frequencies: + phy_names = list(phy_names) + phy_names.remove("frequencyofinterest") + + # append all PHY options to phydoc + for name in phy_names: + value = emane_model.valueof(name, values) + param = emane_manager.xmlparam(phy_document, name, value) + phy_element.appendChild(param) + + if frequencies: + phy_element.appendChild(frequencies) + + return phy_document diff --git a/daemon/core/emane/universal.py b/daemon/core/emane/universal.py deleted file mode 100644 index 5c754dc4..00000000 --- a/daemon/core/emane/universal.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -universal.py: EMANE Universal PHY model for CORE. Enumerates configuration items -used for the Universal PHY. -""" - -from core.emane.emanemodel import EmaneModel -from core.enumerations import ConfigDataTypes - - -class EmaneUniversalModel(EmaneModel): - """ - This Univeral PHY model is meant to be imported by other models, - not instantiated. - """ - - name = "emane_universal" - - # universal PHY parameters - _xmlname = "universalphy" - _xmllibrary = "universalphylayer" - config_matrix = [ - ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), - ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), - ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", - "Nakagami D0: distance lower bound in meters"), - ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", - "Nakagami D1: distance upper bound in meters"), - ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), - ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", - "Nakagami M1: shape factor for distance >= D0 < D1"), - ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", - "Nakagami M2: shape factor for distance >= D1"), - ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), - ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), - ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), - ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), - ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), - ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), - ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", - "Noise maximum message propagation in microsecond"), - ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", - "Noise maximum segment duration in microseconds"), - ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", - "Noise maximum segment offset in microseconds"), - ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), - ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), - ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), - ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), - ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), - ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), - ] - - def __init__(self, session, object_id=None): - raise NotImplemented("Cannot use this class directly") - - @classmethod - def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): - """ - Create a phy doc for a model based on the universal model. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for - :param tuple values: emane model configuration values - :param phy_names: names for phy configuration values - :return: - """ - phy_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", cls._xmlname) - - name = "frequencyofinterest" - value = emane_model.valueof(name, values) - frequencies = cls.value_to_params(phy_document, name, value) - if frequencies: - phy_names = list(phy_names) - phy_names.remove("frequencyofinterest") - - # append all PHY options to phydoc - for name in phy_names: - value = emane_model.valueof(name, values) - param = emane_manager.xmlparam(phy_document, name, value) - phy_element.appendChild(param) - - if frequencies: - phy_element.appendChild(frequencies) - - return phy_document From 4f978f5b966f3b94eca9c07de57e6bf71c82b847 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 14:04:15 -0700 Subject: [PATCH 116/152] fixed some emane naming issues --- daemon/core/emane/commeffect.py | 2 +- daemon/core/emane/emanemodel.py | 159 ++++++++++++++++---------------- 2 files changed, 81 insertions(+), 80 deletions(-) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 4afd83a5..73dd5c2a 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -7,7 +7,7 @@ from core.emane.emanemodel import EmaneModel from core.enumerations import ConfigDataTypes try: - from emanesh.events.commeffectevent import CommEffectEvent + from emane.events.commeffectevent import CommEffectEvent except ImportError: logger.info("emane 1.2.1 not found") diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 84e6022c..0a2aedaf 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -9,6 +9,86 @@ from core.mobility import WirelessModel from core.xml import xmlutils +class EmaneUniversalModel(object): + """ + This Univeral PHY model is meant to be imported by other models, + not instantiated. + """ + + name = "emane_universal" + + # universal PHY parameters + _xmlname = "universalphy" + _xmllibrary = "universalphylayer" + config_matrix = [ + ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), + ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), + ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", + "Nakagami D0: distance lower bound in meters"), + ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", + "Nakagami D1: distance upper bound in meters"), + ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), + ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", + "Nakagami M1: shape factor for distance >= D0 < D1"), + ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", + "Nakagami M2: shape factor for distance >= D1"), + ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), + ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), + ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), + ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), + ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), + ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), + ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", + "Noise maximum message propagation in microsecond"), + ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", + "Noise maximum segment duration in microseconds"), + ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", + "Noise maximum segment offset in microseconds"), + ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), + ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), + ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), + ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), + ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), + ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), + ] + + def __init__(self, session, object_id=None): + raise NotImplemented("Cannot use this class directly") + + @classmethod + def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): + """ + Create a phy doc for a model based on the universal model. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for + :param tuple values: emane model configuration values + :param phy_names: names for phy configuration values + :return: + """ + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", cls._xmlname) + + name = "frequencyofinterest" + value = emane_model.valueof(name, values) + frequencies = cls.value_to_params(phy_document, name, value) + if frequencies: + phy_names = list(phy_names) + phy_names.remove("frequencyofinterest") + + # append all PHY options to phydoc + for name in phy_names: + value = emane_model.valueof(name, values) + param = emane_manager.xmlparam(phy_document, name, value) + phy_element.appendChild(param) + + if frequencies: + phy_element.appendChild(frequencies) + + return phy_document + + class EmaneModel(WirelessModel): """ EMANE models inherit from this parent class, which takes care of @@ -303,82 +383,3 @@ class EmaneModel(WirelessModel): return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) - -class EmaneUniversalModel(EmaneModel): - """ - This Univeral PHY model is meant to be imported by other models, - not instantiated. - """ - - name = "emane_universal" - - # universal PHY parameters - _xmlname = "universalphy" - _xmllibrary = "universalphylayer" - config_matrix = [ - ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), - ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), - ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", - "Nakagami D0: distance lower bound in meters"), - ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", - "Nakagami D1: distance upper bound in meters"), - ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), - ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", - "Nakagami M1: shape factor for distance >= D0 < D1"), - ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", - "Nakagami M2: shape factor for distance >= D1"), - ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), - ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), - ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), - ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), - ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), - ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), - ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", - "Noise maximum message propagation in microsecond"), - ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", - "Noise maximum segment duration in microseconds"), - ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", - "Noise maximum segment offset in microseconds"), - ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), - ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), - ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), - ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), - ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), - ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), - ] - - def __init__(self, session, object_id=None): - raise NotImplemented("Cannot use this class directly") - - @classmethod - def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): - """ - Create a phy doc for a model based on the universal model. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for - :param tuple values: emane model configuration values - :param phy_names: names for phy configuration values - :return: - """ - phy_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", cls._xmlname) - - name = "frequencyofinterest" - value = emane_model.valueof(name, values) - frequencies = cls.value_to_params(phy_document, name, value) - if frequencies: - phy_names = list(phy_names) - phy_names.remove("frequencyofinterest") - - # append all PHY options to phydoc - for name in phy_names: - value = emane_model.valueof(name, values) - param = emane_manager.xmlparam(phy_document, name, value) - phy_element.appendChild(param) - - if frequencies: - phy_element.appendChild(frequencies) - - return phy_document From 19ccd6a63b3dce892cff109d1feb3a9a45853903 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 14:14:59 -0700 Subject: [PATCH 117/152] testing hack for class propery --- daemon/core/emane/emanemodel.py | 74 ++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 0a2aedaf..a2fda909 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -9,6 +9,36 @@ from core.mobility import WirelessModel from core.xml import xmlutils +def classproperty(_): + def __get__(self, _, inst): + return self.fget.__get__(None, inst)() + + +def value_to_params(doc, name, value): + """ + Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to + multiple values. + + :param xml.dom.minidom.Document doc: xml document + :param name: name of element for params + :param str value: value string to convert to tuple + :return: xml document with added params or None, when an invalid value has been provided + """ + try: + values = utils.make_tuple_fromstr(value, str) + except SyntaxError: + logger.exception("error in value string to param list") + return None + + if not hasattr(values, "__iter__"): + return None + + if len(values) < 2: + return None + + return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) + + class EmaneUniversalModel(object): """ This Univeral PHY model is meant to be imported by other models, @@ -72,7 +102,7 @@ class EmaneUniversalModel(object): name = "frequencyofinterest" value = emane_model.valueof(name, values) - frequencies = cls.value_to_params(phy_document, name, value) + frequencies = value_to_params(phy_document, name, value) if frequencies: phy_names = list(phy_names) phy_names.remove("frequencyofinterest") @@ -103,14 +133,16 @@ class EmaneModel(WirelessModel): def __init__(self, session, object_id=None): WirelessModel.__init__(self, session, object_id) - @property - def config_matrix(self): - return self._config_mac + self._config_phy + @classproperty + @classmethod + def config_matrix(cls): + return cls._config_mac + cls._config_phy - @property - def config_groups(self): - mac_len = len(self._config_mac) - config_len = len(self.config_matrix) + @classproperty + @classmethod + def config_groups(cls): + mac_len = len(cls._config_mac) + config_len = len(cls.config_matrix) return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) def build_xml_files(self, emane_manager, interface): @@ -357,29 +389,3 @@ class EmaneModel(WirelessModel): :return: nothing """ logger.warn("emane model(%s) does not support link configuration", self.name) - - @staticmethod - def value_to_params(doc, name, value): - """ - Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to - multiple values. - - :param xml.dom.minidom.Document doc: xml document - :param name: name of element for params - :param str value: value string to convert to tuple - :return: xml document with added params or None, when an invalid value has been provided - """ - try: - values = utils.make_tuple_fromstr(value, str) - except SyntaxError: - logger.exception("error in value string to param list") - return None - - if not hasattr(values, "__iter__"): - return None - - if len(values) < 2: - return None - - return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) - From beb5be2ee91b64d6ac4cb71eb0c12c87b519ad87 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 14:38:32 -0700 Subject: [PATCH 118/152] reverted to using class variables for emane models due to inheritence from config class --- daemon/core/emane/bypass.py | 10 ++++------ daemon/core/emane/commeffect.py | 8 +++----- daemon/core/emane/emanemodel.py | 21 ++++++--------------- daemon/core/emane/ieee80211abg.py | 7 +++++-- daemon/core/emane/rfpipe.py | 7 +++++-- daemon/core/emane/tdma.py | 7 +++++-- 6 files changed, 28 insertions(+), 32 deletions(-) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index df3e10ed..b2fce32d 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -2,11 +2,11 @@ EMANE Bypass model for CORE """ -from core.emane.emanemodel import EmaneModel +from core.emane import emanemodel from core.enumerations import ConfigDataTypes -class EmaneBypassModel(EmaneModel): +class EmaneBypassModel(emanemodel.EmaneModel): name = "emane_bypass" library = "bypassmaclayer" @@ -16,7 +16,5 @@ class EmaneBypassModel(EmaneModel): "There are no parameters for the bypass model."), ] _config_phy = [] - - @property - def config_groups(self): - return "Bypass Parameters:1-1" + config_matrix = _config_mac + _config_phy + config_groups = "Bypass Parameters:1-1" diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 73dd5c2a..71f3a37d 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -3,7 +3,7 @@ commeffect.py: EMANE CommEffect model for CORE """ from core import logger -from core.emane.emanemodel import EmaneModel +from core.emane import emanemodel from core.enumerations import ConfigDataTypes try: @@ -24,7 +24,7 @@ def convert_none(x): return int(x) -class EmaneCommEffectModel(EmaneModel): +class EmaneCommEffectModel(emanemodel.EmaneModel): name = "emane_commeffect" config_matrix = [ @@ -35,9 +35,7 @@ class EmaneCommEffectModel(EmaneModel): ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), ] - @property - def config_groups(self): - return "CommEffect SHIM Parameters:1-%d" % len(self.config_matrix) + config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) def build_xml_files(self, emane_manager, interface): """ diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index a2fda909..ef775a93 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -9,9 +9,10 @@ from core.mobility import WirelessModel from core.xml import xmlutils -def classproperty(_): - def __get__(self, _, inst): - return self.fget.__get__(None, inst)() +def create_config_groups(config_mac, config_matrix): + mac_len = len(config_mac) + config_len = len(config_matrix) + return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) def value_to_params(doc, name, value): @@ -129,22 +130,12 @@ class EmaneModel(WirelessModel): _config_phy = EmaneUniversalModel.config_matrix library = None config_ignore = set() + config_matrix = _config_mac + _config_phy + config_groups = create_config_groups(_config_mac, config_matrix) def __init__(self, session, object_id=None): WirelessModel.__init__(self, session, object_id) - @classproperty - @classmethod - def config_matrix(cls): - return cls._config_mac + cls._config_phy - - @classproperty - @classmethod - def config_groups(cls): - mac_len = len(cls._config_mac) - config_len = len(cls.config_matrix) - return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) - def build_xml_files(self, emane_manager, interface): """ Builds xml files for emane. Includes a nem.xml file that points to both mac.xml and phy.xml definitions. diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 09c3b7bd..1bb1b021 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -2,11 +2,11 @@ ieee80211abg.py: EMANE IEEE 802.11abg model for CORE """ -from core.emane.emanemodel import EmaneModel +from core.emane import emanemodel from core.enumerations import ConfigDataTypes -class EmaneIeee80211abgModel(EmaneModel): +class EmaneIeee80211abgModel(emanemodel.EmaneModel): # model name name = "emane_ieee80211abg" library = "ieee80211abgmaclayer" @@ -45,6 +45,9 @@ class EmaneIeee80211abgModel(EmaneModel): ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), ] + config_matrix = _config_mac + emanemodel.EmaneModel._config_phy + config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + def create_mac_doc(self, emane_manager, values): names = self.getnames() mac_names = names[:len(self._config_mac)] diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 184f32d8..b104832c 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -2,11 +2,11 @@ rfpipe.py: EMANE RF-PIPE model for CORE """ -from core.emane.emanemodel import EmaneModel +from core.emane import emanemodel from core.enumerations import ConfigDataTypes -class EmaneRfPipeModel(EmaneModel): +class EmaneRfPipeModel(emanemodel.EmaneModel): # model name name = "emane_rfpipe" library = "rfpipemaclayer" @@ -27,3 +27,6 @@ class EmaneRfPipeModel(EmaneModel): ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", "R2RI radio metric report interval (sec)"), ] + + config_matrix = _config_mac + emanemodel.EmaneModel._config_phy + config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 5f582485..86e7f90a 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -6,12 +6,12 @@ import os from core import constants from core import logger -from core.emane.emanemodel import EmaneModel +from core.emane import emanemodel from core.enumerations import ConfigDataTypes from core.misc import utils -class EmaneTdmaModel(EmaneModel): +class EmaneTdmaModel(emanemodel.EmaneModel): # model name name = "emane_tdma" library = "tdmaeventschedulerradiomodel" @@ -46,6 +46,9 @@ class EmaneTdmaModel(EmaneModel): "enable strict dequeueing to specified queues only"), ] + config_matrix = _config_mac + emanemodel.EmaneModel._config_phy + config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + def post_startup(self, emane_manager): """ Logic to execute after the emane manager is finished with startup. From 8963ef51e387952283bb483d25cc78c862ffcfb0 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 29 Mar 2018 15:13:16 -0700 Subject: [PATCH 119/152] fixed bypass unique phy doc under refactored code --- daemon/core/emane/bypass.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index b2fce32d..b8313e44 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -18,3 +18,10 @@ class EmaneBypassModel(emanemodel.EmaneModel): _config_phy = [] config_matrix = _config_mac + _config_phy config_groups = "Bypass Parameters:1-1" + + def create_phy_doc(self, emane_manager, values): + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", "%s PHY" % self.name) + phy_element.setAttribute("library", "bypassphylayer") + return phy_document From fd32e1cf7864cd9cae1e0b2755c13ad78012deb0 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 30 Mar 2018 12:08:33 -0700 Subject: [PATCH 120/152] added support for emane manifest parsing into core compatible information, refactoring of emane code to align with its usage --- daemon/core/emane/bypass.py | 25 +++-- daemon/core/emane/commeffect.py | 58 +++++----- daemon/core/emane/emanemanifest.py | 112 +++++++++++++++++++ daemon/core/emane/emanemodel.py | 174 +++++++++++++---------------- daemon/core/emane/ieee80211abg.py | 87 ++------------- daemon/core/emane/rfpipe.py | 31 ++--- daemon/core/emane/tdma.py | 43 +++---- 7 files changed, 271 insertions(+), 259 deletions(-) create mode 100644 daemon/core/emane/emanemanifest.py diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index b8313e44..bb1c6f55 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -8,20 +8,23 @@ from core.enumerations import ConfigDataTypes class EmaneBypassModel(emanemodel.EmaneModel): name = "emane_bypass" - library = "bypassmaclayer" + # values to ignore, when writing xml files config_ignore = {"none"} - _config_mac = [ + + # mac definitions + mac_library = "bypassmaclayer" + config_mac = [ ("none", ConfigDataTypes.BOOL.value, "0", "True,False", "There are no parameters for the bypass model."), ] - _config_phy = [] - config_matrix = _config_mac + _config_phy - config_groups = "Bypass Parameters:1-1" - def create_phy_doc(self, emane_manager, values): - phy_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", "%s PHY" % self.name) - phy_element.setAttribute("library", "bypassphylayer") - return phy_document + # phy definitions + phy_library = "bypassphylayer" + config_phy = [] + + # defines overall config + config_matrix = config_mac + config_phy + + # gui display tabs + config_groups = "Bypass Parameters:1-1" diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 71f3a37d..6754c353 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -3,8 +3,8 @@ commeffect.py: EMANE CommEffect model for CORE """ from core import logger +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes try: from emane.events.commeffectevent import CommEffectEvent @@ -27,13 +27,11 @@ def convert_none(x): class EmaneCommEffectModel(emanemodel.EmaneModel): name = "emane_commeffect" - config_matrix = [ - ("filterfile", ConfigDataTypes.STRING.value, "", "", "filter file"), - ("groupid", ConfigDataTypes.UINT32.value, "0", "", "NEM Group ID"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), - ("receivebufferperiod", ConfigDataTypes.FLOAT.value, "1.0", "", "receivebufferperiod"), - ("defaultconnectivitymode", ConfigDataTypes.BOOL.value, "1", "On,Off", "defaultconnectivity"), - ] + shim_library = "commeffectshim" + shim_xml = "/usr/share/emane/manifest/commeffectshim.xml" + shim_defaults = {} + config_shim = emanemanifest.parse(shim_xml, shim_defaults) + config_matrix = config_shim config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) @@ -56,30 +54,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): nem_name = self.nem_name(interface) shim_name = self.shim_name(interface) - shim_document = emane_manager.xmldoc("shim") - shim = shim_document.getElementsByTagName("shim").pop() - shim.setAttribute("name", "commeffect SHIM") - shim.setAttribute("library", "commeffectshim") - - names = self.getnames() - shim_names = list(names[:len(self.config_matrix)]) - shim_names.remove("filterfile") - - # append all shim options (except filterfile) to shimdoc - for name in shim_names: - value = self.valueof(name, values) - param = emane_manager.xmlparam(shim_document, name, value) - shim.appendChild(param) - - # empty filterfile is not allowed - ff = self.valueof("filterfile", values) - if ff.strip() != "": - shim.appendChild(emane_manager.xmlparam(shim_document, "filterfile", ff)) - emane_manager.xmlwrite(shim_document, shim_name) - nem_document = emane_manager.xmldoc("nem") nem_element = nem_document.getElementsByTagName("nem").pop() - nem_element.setAttribute("name", "commeffect NEM") + nem_element.setAttribute("name", "%s NEM" % self.name) nem_element.setAttribute("type", "unstructured") emane_manager.appendtransporttonem(nem_document, nem_element, self.object_id, interface) @@ -87,6 +64,27 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): nem_element.appendChild(shim_xml) emane_manager.xmlwrite(nem_document, nem_name) + names = self.getnames() + shim_names = list(names) + shim_names.remove("filterfile") + + shim_document = emane_manager.xmldoc("shim") + shim_element = shim_document.getElementsByTagName("shim").pop() + shim_element.setAttribute("name", "%s SHIM" % self.name) + shim_element.setAttribute("library", self.shim_library) + + # append all shim options (except filterfile) to shimdoc + for name in shim_names: + value = self.valueof(name, values) + param = emane_manager.xmlparam(shim_document, name, value) + shim_element.appendChild(param) + + # empty filterfile is not allowed + ff = self.valueof("filterfile", values) + if ff.strip() != "": + shim_element.appendChild(emane_manager.xmlparam(shim_document, "filterfile", ff)) + emane_manager.xmlwrite(shim_document, shim_name) + def linkconfig(self, netif, bw=None, delay=None, loss=None, duplicate=None, jitter=None, netif2=None): """ Generate CommEffect events when a Link Message is received having diff --git a/daemon/core/emane/emanemanifest.py b/daemon/core/emane/emanemanifest.py new file mode 100644 index 00000000..5f34ede4 --- /dev/null +++ b/daemon/core/emane/emanemanifest.py @@ -0,0 +1,112 @@ +from core import logger +from core.enumerations import ConfigDataTypes + +try: + from emane.shell import manifest +except ImportError: + logger.info("emane 1.2.1 not found") + + +def _type_value(config_type): + """ + Convert emane configuration type to core configuration value. + + :param str config_type: emane configuration type + :return: + """ + config_type = config_type.upper() + if config_type == "DOUBLE": + config_type = "FLOAT" + return ConfigDataTypes[config_type].value + + +def _get_possible(config_type, config_regex): + """ + Retrieve possible config value options based on emane regexes. + + :param str config_type: emane configuration type + :param str config_regex: emane configuration regex + :return: a string listing comma delimited values, if needed, empty string otherwise + :rtype: str + """ + if config_type == "bool": + return "On,Off" + + if config_type == "string" and config_regex: + possible = config_regex[2:-2] + possible = possible.replace("|", ",") + return possible + + return "" + + +def _get_default(config_type_name, config_value): + """ + Convert default configuration values to one used by core. + + :param str config_type_name: emane configuration type name + :param list config_value: emane configuration value list + :return: default core config value + :rtype: str + """ + + config_default = "" + + if config_type_name == "bool": + if config_value and config_value[0] == "true": + config_default = "1" + else: + config_default = "0" + elif config_value: + config_default = config_value[0] + + if config_default is None: + config_default = "" + return config_default + + +def parse(manifest_path, defaults): + """ + Parses a valid emane manifest file and converts the provided configuration values into ones used by core. + + :param str manifest_path: absolute manifest file path + :param dict defaults: used to override default values for configurations + :return: list of core configuration values + :rtype: list + """ + + # load configuration file + manifest_file = manifest.Manifest(manifest_path) + manifest_configurations = manifest_file.getAllConfiguration() + + configurations = [] + for config_name in sorted(manifest_configurations): + config_info = manifest_file.getConfigurationInfo(config_name) + + # map type to internal config data type value for core + config_type = config_info.get("numeric") + if not config_type: + config_type = config_info.get("nonnumeric") + config_type_name = config_type["type"] + config_type_value = _type_value(config_type_name) + + # get default values, using provided defaults + if config_name in defaults: + config_default = defaults[config_name] + else: + config_value = config_info["values"] + config_default = _get_default(config_type_name, config_value) + + # map to possible values used as options within the gui + config_regex = config_info.get("regex") + possible = _get_possible(config_type_name, config_regex) + + # define description and account for gui quirks + config_descriptions = config_name + if config_name.endswith("uri"): + config_descriptions = "%s file" % config_descriptions + + config_tuple = (config_name, config_type_value, config_default, possible, config_descriptions) + configurations.append(config_tuple) + + return configurations diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index ef775a93..dc1e2b38 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -3,7 +3,7 @@ Defines Emane Models used within CORE. """ from core import logger -from core.enumerations import ConfigDataTypes +from core.emane import emanemanifest from core.misc import utils from core.mobility import WirelessModel from core.xml import xmlutils @@ -40,98 +40,31 @@ def value_to_params(doc, name, value): return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) -class EmaneUniversalModel(object): - """ - This Univeral PHY model is meant to be imported by other models, - not instantiated. - """ - - name = "emane_universal" - - # universal PHY parameters - _xmlname = "universalphy" - _xmllibrary = "universalphylayer" - config_matrix = [ - ("bandwidth", ConfigDataTypes.UINT64.value, "1M", "", "rf bandwidth (Hz)"), - ("fading.model", ConfigDataTypes.STRING.value, "none", "none,event,nakagami", "Defines fading model"), - ("fading.nakagami.distance0", ConfigDataTypes.FLOAT.value, "100.0", "", - "Nakagami D0: distance lower bound in meters"), - ("fading.nakagami.distance1", ConfigDataTypes.FLOAT.value, "250.0", "", - "Nakagami D1: distance upper bound in meters"), - ("fading.nakagami.m0", ConfigDataTypes.FLOAT.value, "0.75", "", "Nakagami M0: shape factor for distance < D0"), - ("fading.nakagami.m1", ConfigDataTypes.FLOAT.value, "1.0", "", - "Nakagami M1: shape factor for distance >= D0 < D1"), - ("fading.nakagami.m2", ConfigDataTypes.FLOAT.value, "200.0", "", - "Nakagami M2: shape factor for distance >= D1"), - ("fixedantennagain", ConfigDataTypes.FLOAT.value, "0.0", "", "antenna gain (dBi)"), - ("fixedantennagainenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable fixed antenna gain"), - ("frequency", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency (Hz)"), - ("frequencyofinterest", ConfigDataTypes.UINT64.value, "2.347G", "", "frequency of interest (Hz)"), - ("noisebinsize", ConfigDataTypes.UINT64.value, "20", "", "noise bin size in microseconds"), - ("noisemaxclampenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "Noise max clamp enable"), - ("noisemaxmessagepropagation", ConfigDataTypes.UINT64.value, "200000", "", - "Noise maximum message propagation in microsecond"), - ("noisemaxsegmentduration", ConfigDataTypes.UINT64.value, "1000000", "", - "Noise maximum segment duration in microseconds"), - ("noisemaxsegmentoffset", ConfigDataTypes.UINT64.value, "300000", "", - "Noise maximum segment offset in microseconds"), - ("noisemode", ConfigDataTypes.STRING.value, "none", "none,all,outofband", "noise processing mode"), - ("propagationmodel", ConfigDataTypes.STRING.value, "2ray", "precomputed,2ray,freespace", "path loss mode"), - ("subid", ConfigDataTypes.UINT16.value, "1", "", "subid"), - ("systemnoisefigure", ConfigDataTypes.FLOAT.value, "4.0", "", "system noise figure (dB)"), - ("timesyncthreshold", ConfigDataTypes.UINT64.value, "10000", "", "Time sync threshold"), - ("txpower", ConfigDataTypes.FLOAT.value, "0.0", "", "transmit power (dBm)"), - ] - - def __init__(self, session, object_id=None): - raise NotImplemented("Cannot use this class directly") - - @classmethod - def get_phy_doc(cls, emane_manager, emane_model, values, phy_names): - """ - Create a phy doc for a model based on the universal model. - - :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager - :param core.emane.emanemodel.EmaneModel emane_model: model to create phy doc for - :param tuple values: emane model configuration values - :param phy_names: names for phy configuration values - :return: - """ - phy_document = emane_manager.xmldoc("phy") - phy_element = phy_document.getElementsByTagName("phy").pop() - phy_element.setAttribute("name", cls._xmlname) - - name = "frequencyofinterest" - value = emane_model.valueof(name, values) - frequencies = value_to_params(phy_document, name, value) - if frequencies: - phy_names = list(phy_names) - phy_names.remove("frequencyofinterest") - - # append all PHY options to phydoc - for name in phy_names: - value = emane_model.valueof(name, values) - param = emane_manager.xmlparam(phy_document, name, value) - phy_element.appendChild(param) - - if frequencies: - phy_element.appendChild(frequencies) - - return phy_document - - class EmaneModel(WirelessModel): """ EMANE models inherit from this parent class, which takes care of handling configuration messages based on the list of configurable parameters. Helper functions also live here. """ - _config_mac = [] - _config_phy = EmaneUniversalModel.config_matrix - library = None + # default mac configuration settings + mac_library = None + mac_xml = None + mac_defaults = {} + config_mac = [] + + # default phy configuration settings, using the universal model + phy_library = None + phy_xml = "/usr/share/emane/manifest/emanephy.xml" + phy_defaults = { + "subid": "1", + "propagationmodel": "2ray", + "noisemode": "none" + } + config_phy = emanemanifest.parse(phy_xml, phy_defaults) + config_ignore = set() - config_matrix = _config_mac + _config_phy - config_groups = create_config_groups(_config_mac, config_matrix) + config_matrix = config_mac + config_phy + config_groups = create_config_groups(config_mac, config_matrix) def __init__(self, session, object_id=None): WirelessModel.__init__(self, session, object_id) @@ -157,16 +90,22 @@ class EmaneModel(WirelessModel): # create mac document and write to disk mac_name = self.mac_name(interface) mac_document = self.create_mac_doc(emane_manager, values) - if mac_document: - emane_manager.xmlwrite(mac_document, mac_name) + emane_manager.xmlwrite(mac_document, mac_name) # create phy document and write to disk phy_name = self.phy_name(interface) phy_document = self.create_phy_doc(emane_manager, values) - if phy_document: - emane_manager.xmlwrite(phy_document, phy_name) + emane_manager.xmlwrite(phy_document, phy_name) def create_nem_doc(self, emane_manager, interface): + """ + Create the nem xml document. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param interface: interface for the emane node + :return: nem document + :rtype: xml.dom.minidom.Document + """ mac_name = self.mac_name(interface) phy_name = self.phy_name(interface) @@ -186,16 +125,24 @@ class EmaneModel(WirelessModel): return nem_document def create_mac_doc(self, emane_manager, values): + """ + Create the mac xml document. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param tuple values: all current configuration values, mac + phy + :return: nem document + :rtype: xml.dom.minidom.Document + """ names = list(self.getnames()) - mac_names = names[:len(self._config_mac)] + mac_names = names[:len(self.config_mac)] mac_document = emane_manager.xmldoc("mac") mac_element = mac_document.getElementsByTagName("mac").pop() mac_element.setAttribute("name", "%s MAC" % self.name) - if not self.library: + if not self.mac_library: raise ValueError("must define emane model library") - mac_element.setAttribute("library", self.library) + mac_element.setAttribute("library", self.mac_library) for name in mac_names: if name in self.config_ignore: @@ -207,9 +154,46 @@ class EmaneModel(WirelessModel): return mac_document def create_phy_doc(self, emane_manager, values): + """ + Create the phy xml document. + + :param core.emane.emanemanager.EmaneManager emane_manager: core emane manager + :param tuple values: all current configuration values, mac + phy + :return: nem document + :rtype: xml.dom.minidom.Document + """ names = list(self.getnames()) - phy_names = names[len(self._config_mac):] - return EmaneUniversalModel.get_phy_doc(emane_manager, self, values, phy_names) + phy_names = names[len(self.config_mac):] + + phy_document = emane_manager.xmldoc("phy") + phy_element = phy_document.getElementsByTagName("phy").pop() + phy_element.setAttribute("name", "%s PHY" % self.name) + + if self.phy_library: + phy_element.setAttribute("library", self.phy_library) + + # hack to account for config that can contain more than 1 value + frequencies = None + name = "frequencyofinterest" + try: + value = self.valueof(name, values) + frequencies = value_to_params(phy_document, name, value) + if frequencies: + phy_names = list(phy_names) + phy_names.remove("frequencyofinterest") + except ValueError: + logger.info("%s is not present in the phy names", name) + + # append all PHY options to phydoc + for name in phy_names: + value = self.valueof(name, values) + param = emane_manager.xmlparam(phy_document, name, value) + phy_element.appendChild(param) + + if frequencies: + phy_element.appendChild(frequencies) + + return phy_document @classmethod def configure_emane(cls, session, config_data): diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index 1bb1b021..b45b19b1 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -2,89 +2,24 @@ ieee80211abg.py: EMANE IEEE 802.11abg model for CORE """ +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes class EmaneIeee80211abgModel(emanemodel.EmaneModel): # model name name = "emane_ieee80211abg" - library = "ieee80211abgmaclayer" # mac configuration - _80211rates = "1 1 Mbps,2 2 Mbps,3 5.5 Mbps,4 11 Mbps,5 6 Mbps," + \ - "6 9 Mbps,7 12 Mbps,8 18 Mbps,9 24 Mbps,10 36 Mbps,11 48 Mbps," + \ - "12 54 Mbps" - xml_path = "/usr/share/emane/xml/models/mac/ieee80211abg" - _config_mac = [ - ("aifs", ConfigDataTypes.STRING.value, "0:2 1:2 2:2 3:1", "", "arbitration inter frame space (0-4:aifs)"), - ("channelactivityestimationtimer", ConfigDataTypes.FLOAT.value, "0.1", "", - "Defines channel activity estimation timer in seconds"), - ("cwmax", ConfigDataTypes.STRING.value, "0:1024 1:1024 2:64 3:16", "", "max contention window (0-4:maxw)"), - ("cwmin", ConfigDataTypes.STRING.value, "0:32 1:32 2:16 3:8", "", "min contention window (0-4:minw)"), - ("distance", ConfigDataTypes.UINT32.value, "1000", "", "max distance (m)"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable promiscuous mode"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), - ("mode", ConfigDataTypes.UINT8.value, "0", "0 802.11b (DSSS only),1 802.11b (DSSS only)," + - "2 802.11a or g (OFDM),3 802.11b/g (DSSS and OFDM)", "mode"), - ("multicastrate", ConfigDataTypes.UINT8.value, "1", _80211rates, "multicast rate (Mbps)"), - ("msdu", ConfigDataTypes.UINT16.value, "0:65535 1:65535 2:65535 3:65535", "", "MSDU categories (0-4:size)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", - "R2RI neighbor table inactivity time (sec)"), - ("neighbortimeout", ConfigDataTypes.FLOAT.value, "30.0", "", "Neighbor timeout in seconds for estimation"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/ieee80211pcr.xml" % xml_path, "", "SINR/PCR curve file"), - ("queuesize", ConfigDataTypes.STRING.value, "0:255 1:255 2:255 3:255", "", "queue size (0-4:size)"), - ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), - ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", - "R2RI radio metric report interval (sec)"), - ("retrylimit", ConfigDataTypes.STRING.value, "0:3 1:3 2:3 3:3", "", "retry limit (0-4:numretries)"), - ("rtsthreshold", ConfigDataTypes.UINT16.value, "0", "", "RTS threshold (bytes)"), - ("txop", ConfigDataTypes.STRING.value, "0:0 1:0 2:0 3:0", "", "txop (0-4:usec)"), - ("unicastrate", ConfigDataTypes.UINT8.value, "4", _80211rates, "unicast rate (Mbps)"), - ("wmmenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "WiFi Multimedia (WMM)"), - ] + mac_library = "ieee80211abgmaclayer" + mac_xml = "/usr/share/emane/manifest/ieee80211abgmaclayer.xml" + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml", + } + config_mac = emanemanifest.parse(mac_xml, mac_defaults) - config_matrix = _config_mac + emanemodel.EmaneModel._config_phy - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + config_matrix = config_mac + emanemodel.EmaneModel.config_phy - def create_mac_doc(self, emane_manager, values): - names = self.getnames() - mac_names = names[:len(self._config_mac)] - mac_document = emane_manager.xmldoc("mac") - mac_element = mac_document.getElementsByTagName("mac").pop() - mac_element.setAttribute("name", "%s MAC" % self.name) - mac_element.setAttribute("library", self.library) - for name in mac_names: - mac9xnvpairlist = self.get9xmacparamequivalent(name, values) - for nvpair in mac9xnvpairlist: - param = emane_manager.xmlparam(mac_document, nvpair[0], nvpair[1]) - mac_element.appendChild(param) - return mac_document - - def get9xmacparamequivalent(self, mac_name, values): - """ - This accounts for current config values labeled value0, value1, value2, etc. - - Generate a list of 80211abg mac parameters in 0.9.x layout for a given mac parameter - in 8.x layout.For mac category parameters, the list returned will contain the four - equivalent 9.x parameter and value pairs. Otherwise, the list returned will only - contain a single name and value pair. - """ - nvpairlist = [] - macparmval = self.valueof(mac_name, values) - - if mac_name in ["queuesize", "aifs", "cwmin", "cwmax", "txop", "retrylimit", "msdu"]: - for catval in macparmval.split(): - idx_and_val = catval.split(":") - idx = int(idx_and_val[0]) - val = idx_and_val[1] - # aifs and tx are in microseconds. Convert to seconds. - if mac_name in ["aifs", "txop"]: - val = "%f" % (float(val) * 1e-6) - name9x = "%s%d" % (mac_name, idx) - nvpairlist.append([name9x, val]) - else: - nvpairlist.append([mac_name, macparmval]) - - return nvpairlist + # gui display tabs + config_groups = emanemodel.create_config_groups(config_mac, config_matrix) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index b104832c..0cb73812 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -2,31 +2,24 @@ rfpipe.py: EMANE RF-PIPE model for CORE """ +from core.emane import emanemanifest from core.emane import emanemodel -from core.enumerations import ConfigDataTypes class EmaneRfPipeModel(emanemodel.EmaneModel): # model name name = "emane_rfpipe" - library = "rfpipemaclayer" # mac configuration - xml_path = "/usr/share/emane/xml/models/mac/rfpipe" - _config_mac = [ - ("datarate", ConfigDataTypes.UINT64.value, "1M", "", "data rate (bps)"), - ("delay", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission delay (sec)"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), - ("jitter", ConfigDataTypes.FLOAT.value, "0.0", "", "transmission jitter (sec)"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", - "R2RI neighbor table inactivity time (sec)"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/rfpipepcr.xml" % xml_path, "", "SINR/PCR curve file"), - ("radiometricenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "report radio metrics via R2RI"), - ("radiometricreportinterval", ConfigDataTypes.FLOAT.value, "1.0", "", - "R2RI radio metric report interval (sec)"), - ] + mac_library = "rfpipemaclayer" + mac_xml = "/usr/share/emane/manifest/rfpipemaclayer.xml" + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/rfpipe/rfpipepcr.xml", + } + config_mac = emanemanifest.parse(mac_xml, mac_defaults) - config_matrix = _config_mac + emanemodel.EmaneModel._config_phy - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + config_matrix = config_mac + emanemodel.EmaneModel.config_phy + + # gui display tabs + config_groups = emanemodel.create_config_groups(config_mac, config_matrix) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index 86e7f90a..c54dcff0 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -6,6 +6,7 @@ import os from core import constants from core import logger +from core.emane import emanemanifest from core.emane import emanemodel from core.enumerations import ConfigDataTypes from core.misc import utils @@ -14,40 +15,26 @@ from core.misc import utils class EmaneTdmaModel(emanemodel.EmaneModel): # model name name = "emane_tdma" - library = "tdmaeventschedulerradiomodel" # mac configuration - xml_path = "/usr/share/emane/xml/models/mac/tdmaeventscheduler" + mac_library = "tdmaeventschedulerradiomodel" + mac_xml = "/usr/share/emane/manifest/tdmaeventschedulerradiomodel.xml" + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml", + } + config_mac = emanemanifest.parse(mac_xml, mac_defaults) + + # add custom schedule options and ignore it when writing emane xml schedule_name = "schedule" default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") + config_mac.insert(0, (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file")) config_ignore = {schedule_name} - _config_mac = [ - (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file"), - ("enablepromiscuousmode", ConfigDataTypes.BOOL.value, "0", "True,False", "enable promiscuous mode"), - ("flowcontrolenable", ConfigDataTypes.BOOL.value, "0", "On,Off", "enable traffic flow control"), - ("flowcontroltokens", ConfigDataTypes.UINT16.value, "10", "", "number of flow control tokens"), - ("fragmentcheckthreshold", ConfigDataTypes.UINT16.value, "2", "", - "rate in seconds for check if fragment reassembly efforts should be abandoned"), - ("fragmenttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", "", - "threshold in seconds to wait for another packet fragment for reassembly"), - ("neighbormetricdeletetime", ConfigDataTypes.FLOAT.value, "60.0", "", - "neighbor RF reception timeout for removal from neighbor table (sec)"), - ("neighbormetricupdateinterval", ConfigDataTypes.FLOAT.value, "1.0", "", - "neighbor table update interval (sec)"), - ("pcrcurveuri", ConfigDataTypes.STRING.value, "%s/tdmabasemodelpcr.xml" % xml_path, "", "SINR/PCR curve file"), - ("queue.aggregationenable", ConfigDataTypes.BOOL.value, "1", "On,Off", "enable transmit packet aggregation"), - ("queue.aggregationslotthreshold", ConfigDataTypes.FLOAT.value, "90.0", "", - "percentage of a slot that must be filled in order to conclude aggregation"), - ("queue.depth", ConfigDataTypes.UINT16.value, "256", "", - "size of the per service class downstream packet queues (packets)"), - ("queue.fragmentationenable", ConfigDataTypes.BOOL.value, "1", "On,Off", - "enable packet fragmentation (over multiple slots)"), - ("queue.strictdequeueenable", ConfigDataTypes.BOOL.value, "0", "On,Off", - "enable strict dequeueing to specified queues only"), - ] - config_matrix = _config_mac + emanemodel.EmaneModel._config_phy - config_groups = emanemodel.create_config_groups(_config_mac, config_matrix) + # defines overall config + config_matrix = config_mac + emanemodel.EmaneModel.config_phy + + # gui display tabs + config_groups = emanemodel.create_config_groups(config_mac, config_matrix) def post_startup(self, emane_manager): """ From 405614bbd8cadaa8ab8a50f653811eb0301d90af Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 30 Mar 2018 12:52:10 -0700 Subject: [PATCH 121/152] added metaclass to reduce emane model code, fixed broken emaneuniversal references --- daemon/core/emane/bypass.py | 11 +++--- daemon/core/emane/commeffect.py | 4 +-- daemon/core/emane/emanemanager.py | 8 ++--- daemon/core/emane/emanemodel.py | 57 ++++++++++++++++++++++++------- daemon/core/emane/ieee80211abg.py | 8 +---- daemon/core/emane/rfpipe.py | 8 +---- daemon/core/emane/tdma.py | 10 ++---- 7 files changed, 59 insertions(+), 47 deletions(-) diff --git a/daemon/core/emane/bypass.py b/daemon/core/emane/bypass.py index bb1c6f55..2e487e9e 100644 --- a/daemon/core/emane/bypass.py +++ b/daemon/core/emane/bypass.py @@ -14,17 +14,14 @@ class EmaneBypassModel(emanemodel.EmaneModel): # mac definitions mac_library = "bypassmaclayer" - config_mac = [ + mac_config = [ ("none", ConfigDataTypes.BOOL.value, "0", "True,False", "There are no parameters for the bypass model."), ] # phy definitions phy_library = "bypassphylayer" - config_phy = [] + phy_config = [] - # defines overall config - config_matrix = config_mac + config_phy - - # gui display tabs - config_groups = "Bypass Parameters:1-1" + # override gui display tabs + config_groups_override = "Bypass Parameters:1-1" diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index 6754c353..ff1c99e0 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -31,9 +31,9 @@ class EmaneCommEffectModel(emanemodel.EmaneModel): shim_xml = "/usr/share/emane/manifest/commeffectshim.xml" shim_defaults = {} config_shim = emanemanifest.parse(shim_xml, shim_defaults) - config_matrix = config_shim - config_groups = "CommEffect SHIM Parameters:1-%d" % len(config_matrix) + config_groups_override = "CommEffect SHIM Parameters:1-%d" % len(config_shim) + config_matrix_override = config_shim def build_xml_files(self, emane_manager, interface): """ diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index e716a548..22061426 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -1048,10 +1048,10 @@ class EmaneGlobalModel(EmaneModel): ("nem_id_start", ConfigDataTypes.INT32.value, "1", "", "starting NEM ID"), ] - config_matrix = _confmatrix_platform + _confmatrix_nem - config_groups = "Platform Attributes:1-%d|NEM Parameters:%d-%d" % \ - (len(_confmatrix_platform), len(_confmatrix_platform) + 1, - len(config_matrix)) + config_matrix_override = _confmatrix_platform + _confmatrix_nem + config_groups_override = "Platform Attributes:1-%d|NEM Parameters:%d-%d" % \ + (len(_confmatrix_platform), len(_confmatrix_platform) + 1, + len(config_matrix_override)) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index dc1e2b38..88644179 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -9,12 +9,6 @@ from core.mobility import WirelessModel from core.xml import xmlutils -def create_config_groups(config_mac, config_matrix): - mac_len = len(config_mac) - config_len = len(config_matrix) - return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) - - def value_to_params(doc, name, value): """ Helper to convert a parameter to a paramlist. Returns an XML paramlist, or None if the value does not expand to @@ -40,17 +34,56 @@ def value_to_params(doc, name, value): return xmlutils.add_param_list_to_parent(doc, parent=None, name=name, values=values) +class EmaneModelMetaClass(type): + """ + Hack into making class level properties to streamline emane model creation, until the Configurable class is + removed or refactored. + """ + + @property + def config_matrix(cls): + """ + Convenience method for creating the config matrix, allow for a custom override. + + :param EmaneModel cls: emane class + :return: config matrix value + :rtype: list + """ + if cls.config_matrix_override: + return cls.config_matrix_override + else: + return cls.mac_config + cls.phy_config + + @property + def config_groups(cls): + """ + Convenience method for creating the config groups, allow for a custom override. + + :param EmaneModel cls: emane class + :return: config groups value + :rtype: str + """ + if cls.config_groups_override: + return cls.config_groups_override + else: + mac_len = len(cls.mac_config) + config_len = len(cls.config_matrix) + return "MAC Parameters:1-%d|PHY Parameters:%d-%d" % (mac_len, mac_len + 1, config_len) + + class EmaneModel(WirelessModel): """ EMANE models inherit from this parent class, which takes care of handling configuration messages based on the list of configurable parameters. Helper functions also live here. """ + __metaclass__ = EmaneModelMetaClass + # default mac configuration settings mac_library = None mac_xml = None mac_defaults = {} - config_mac = [] + mac_config = [] # default phy configuration settings, using the universal model phy_library = None @@ -60,11 +93,11 @@ class EmaneModel(WirelessModel): "propagationmodel": "2ray", "noisemode": "none" } - config_phy = emanemanifest.parse(phy_xml, phy_defaults) + phy_config = emanemanifest.parse(phy_xml, phy_defaults) config_ignore = set() - config_matrix = config_mac + config_phy - config_groups = create_config_groups(config_mac, config_matrix) + config_groups_override = None + config_matrix_override = None def __init__(self, session, object_id=None): WirelessModel.__init__(self, session, object_id) @@ -134,7 +167,7 @@ class EmaneModel(WirelessModel): :rtype: xml.dom.minidom.Document """ names = list(self.getnames()) - mac_names = names[:len(self.config_mac)] + mac_names = names[:len(self.mac_config)] mac_document = emane_manager.xmldoc("mac") mac_element = mac_document.getElementsByTagName("mac").pop() @@ -163,7 +196,7 @@ class EmaneModel(WirelessModel): :rtype: xml.dom.minidom.Document """ names = list(self.getnames()) - phy_names = names[len(self.config_mac):] + phy_names = names[len(self.mac_config):] phy_document = emane_manager.xmldoc("phy") phy_element = phy_document.getElementsByTagName("phy").pop() diff --git a/daemon/core/emane/ieee80211abg.py b/daemon/core/emane/ieee80211abg.py index b45b19b1..9b4e6ea6 100644 --- a/daemon/core/emane/ieee80211abg.py +++ b/daemon/core/emane/ieee80211abg.py @@ -16,10 +16,4 @@ class EmaneIeee80211abgModel(emanemodel.EmaneModel): mac_defaults = { "pcrcurveuri": "/usr/share/emane/xml/models/mac/ieee80211abg/ieee80211pcr.xml", } - config_mac = emanemanifest.parse(mac_xml, mac_defaults) - - # defines overall config - config_matrix = config_mac + emanemodel.EmaneModel.config_phy - - # gui display tabs - config_groups = emanemodel.create_config_groups(config_mac, config_matrix) + mac_config = emanemanifest.parse(mac_xml, mac_defaults) diff --git a/daemon/core/emane/rfpipe.py b/daemon/core/emane/rfpipe.py index 0cb73812..3c600ddd 100644 --- a/daemon/core/emane/rfpipe.py +++ b/daemon/core/emane/rfpipe.py @@ -16,10 +16,4 @@ class EmaneRfPipeModel(emanemodel.EmaneModel): mac_defaults = { "pcrcurveuri": "/usr/share/emane/xml/models/mac/rfpipe/rfpipepcr.xml", } - config_mac = emanemanifest.parse(mac_xml, mac_defaults) - - # defines overall config - config_matrix = config_mac + emanemodel.EmaneModel.config_phy - - # gui display tabs - config_groups = emanemodel.create_config_groups(config_mac, config_matrix) + mac_config = emanemanifest.parse(mac_xml, mac_defaults) diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index c54dcff0..d24a3423 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -22,20 +22,14 @@ class EmaneTdmaModel(emanemodel.EmaneModel): mac_defaults = { "pcrcurveuri": "/usr/share/emane/xml/models/mac/tdmaeventscheduler/tdmabasemodelpcr.xml", } - config_mac = emanemanifest.parse(mac_xml, mac_defaults) + mac_config = emanemanifest.parse(mac_xml, mac_defaults) # add custom schedule options and ignore it when writing emane xml schedule_name = "schedule" default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") - config_mac.insert(0, (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file")) + mac_config.insert(0, (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file")) config_ignore = {schedule_name} - # defines overall config - config_matrix = config_mac + emanemodel.EmaneModel.config_phy - - # gui display tabs - config_groups = emanemodel.create_config_groups(config_mac, config_matrix) - def post_startup(self, emane_manager): """ Logic to execute after the emane manager is finished with startup. From 4d01a49ec217c15ef941f2073d06ace689949c06 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 30 Mar 2018 14:53:02 -0700 Subject: [PATCH 122/152] updated emane model phy/mac parsing to account for values that support multiple values into a param list --- daemon/core/emane/emanemodel.py | 37 ++++++++++++++++----------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/daemon/core/emane/emanemodel.py b/daemon/core/emane/emanemodel.py index 88644179..3c80977f 100644 --- a/daemon/core/emane/emanemodel.py +++ b/daemon/core/emane/emanemodel.py @@ -178,10 +178,16 @@ class EmaneModel(WirelessModel): mac_element.setAttribute("library", self.mac_library) for name in mac_names: + # ignore custom configurations if name in self.config_ignore: continue + + # check if value is a multi param value = self.valueof(name, values) - param = emane_manager.xmlparam(mac_document, name, value) + param = value_to_params(mac_document, name, value) + if not param: + param = emane_manager.xmlparam(mac_document, name, value) + mac_element.appendChild(param) return mac_document @@ -205,26 +211,19 @@ class EmaneModel(WirelessModel): if self.phy_library: phy_element.setAttribute("library", self.phy_library) - # hack to account for config that can contain more than 1 value - frequencies = None - name = "frequencyofinterest" - try: - value = self.valueof(name, values) - frequencies = value_to_params(phy_document, name, value) - if frequencies: - phy_names = list(phy_names) - phy_names.remove("frequencyofinterest") - except ValueError: - logger.info("%s is not present in the phy names", name) - - # append all PHY options to phydoc + # append all phy options for name in phy_names: - value = self.valueof(name, values) - param = emane_manager.xmlparam(phy_document, name, value) - phy_element.appendChild(param) + # ignore custom configurations + if name in self.config_ignore: + continue - if frequencies: - phy_element.appendChild(frequencies) + # check if value is a multi param + value = self.valueof(name, values) + param = value_to_params(phy_document, name, value) + if not param: + param = emane_manager.xmlparam(phy_document, name, value) + + phy_element.appendChild(param) return phy_document From 1ac95d7dca37b364f27b5681aea2058ff711220d Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 30 Mar 2018 15:39:19 -0700 Subject: [PATCH 123/152] added markdown annotated example emane model file --- daemon/examples/myemane/examplemodel.py | 56 +++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 daemon/examples/myemane/examplemodel.py diff --git a/daemon/examples/myemane/examplemodel.py b/daemon/examples/myemane/examplemodel.py new file mode 100644 index 00000000..fe1af9f3 --- /dev/null +++ b/daemon/examples/myemane/examplemodel.py @@ -0,0 +1,56 @@ + + +from core.emane import emanemanifest +from core.emane import emanemodel + +## Custom EMANE Model +class ExampleModel(emanemodel.EmaneModel): + ### MAC Definition + + # Defines the emane model name that will show up in the GUI. + name = "emane_example" + + # Defines that mac library that the model will reference. + mac_library = "rfpipemaclayer" + # Defines the mac manifest file that will be parsed to obtain configuration options, that will be displayed + # within the GUI. + mac_xml = "/usr/share/emane/manifest/rfpipemaclayer.xml" + # Allows you to override options that are maintained within the manifest file above. + mac_defaults = { + "pcrcurveuri": "/usr/share/emane/xml/models/mac/rfpipe/rfpipepcr.xml", + } + # Parses the manifest file and converts configurations into core supported formats. + mac_config = emanemanifest.parse(mac_xml, mac_defaults) + + ### PHY Definition + # **NOTE: phy configuration will default to the universal model as seen below and the below section does not + # have to be included.** + + # Defines that phy library that the model will reference, used if you need to provide a custom phy. + phy_library = None + # Defines the phy manifest file that will be parsed to obtain configuration options, that will be displayed + # within the GUI. + phy_xml = "/usr/share/emane/manifest/emanephy.xml" + # Allows you to override options that are maintained within the manifest file above or for the default universal + # model. + phy_defaults = { + "subid": "1", + "propagationmodel": "2ray", + "noisemode": "none" + } + # Parses the manifest file and converts configurations into core supported formats. + phy_config = emanemanifest.parse(phy_xml, phy_defaults) + + ### Custom override options + # **NOTE: these options default to what's seen below and do not have to be included.** + + # Allows you to ignore options within phy/mac, used typically if you needed to add a custom option for display + # within the gui. + config_ignore = set() + # Allows you to override how options are displayed with the GUI, using the GUI format of + # "name:1-2|othername:3-4". This will be parsed into tabs, split by "|" and account for items based on the indexed + # numbers after ":" for including values in each tab. + config_groups_override = None + # Allows you to override the default config matrix list. This value by default is the mac_config + phy_config, in + # that order. + config_matrix_override = None From ac4460320523d965d5d8197d664cb5ae0d31e664 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 2 Apr 2018 13:18:01 -0700 Subject: [PATCH 124/152] updated core dynamic config dialog to have a large size that can be scrolled, not ideal, but works --- gui/plugins.tcl | 55 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/gui/plugins.tcl b/gui/plugins.tcl index 45ad77e1..95c1a203 100644 --- a/gui/plugins.tcl +++ b/gui/plugins.tcl @@ -611,9 +611,12 @@ proc capTitle { cap } { proc popupCapabilityConfig { channel wlan model types values captions bmp possible_values groups } { global node_list g_node_type_services_hint g_popupcap_keys g_prefs set wi .popupCapabilityConfig + catch {destroy $wi} toplevel $wi set modelname [capTitle $model] + wm maxsize $wi 710 600 + wm minsize $wi 710 600 wm transient $wi . wm title $wi "$modelname configuration" @@ -656,10 +659,27 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib # session options stored in array, not custom-config if { $model == "session" } { set cfg [getSessionOptionsList] } + frame $wi.frame + set windowFrame $wi.frame - ttk::notebook $wi.vals - pack $wi.vals -fill both -expand true -padx 4 -pady 4 - ttk::notebook::enableTraversal $wi.vals + canvas $windowFrame.c -width 700 -height 600 + set windowCanvas $windowFrame.c + + scrollbar $windowFrame.sb -orient vert -command "$windowCanvas yview" + set windowScroll $windowFrame.sb + + $windowCanvas config -yscrollcommand "$windowScroll set" + pack $windowScroll -fill y -side right + pack $windowCanvas -expand yes -fill both -side top + + frame $windowCanvas.notebookFrame -width 700 -height 1200 + set notebookFrame $windowCanvas.notebookFrame + pack $notebookFrame -fill both -expand yes -padx 5 -pady 5 + + ttk::notebook $notebookFrame.vals -width 690 -height 1200 + set configNotebook $notebookFrame.vals + ttk::notebook::enableTraversal $configNotebook + pack $configNotebook -fill both -expand yes set n 0 set gn 0 @@ -688,12 +708,14 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib set gn [lindex $groupinfo 0] set groupcaption [lindex $groupinfo 1] if { $lastgn != $gn } { - ttk::frame $wi.vals.$gn - $wi.vals add $wi.vals.$gn -text $groupcaption -underline 0 + ttk::frame $configNotebook.$gn + $configNotebook add $configNotebook.$gn -text $groupcaption -underline 0 set lastgn $gn } - set fr $wi.vals.$gn.item$n + + set fr $configNotebook.$gn.item$n ttk::frame $fr + if {$type == 11} { ;# boolean value global $fr.entval $fr.entvalhint set optcmd [list tk_optionMenu $fr.ent \ @@ -748,6 +770,7 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib } else { pack $fr.ent $fr.lab -side right -padx 4 -pady 4 } + pack $fr -side top -anchor e incr n }; # end foreach @@ -778,6 +801,11 @@ proc popupCapabilityConfig { channel wlan model types values captions bmp possib bind $wi $apply_cmd bind $wi $cancel_cmd + # pack notebook + $windowCanvas create window 0 0 -anchor nw -window $notebookFrame + $windowCanvas configure -scrollregion [$windowCanvas bbox all] + pack $windowFrame -fill both -expand yes -side top + after 100 { grab .popupCapabilityConfig raise .popupCapabilityConfig @@ -817,22 +845,23 @@ proc popupCapabilityConfigGroup { groups n } { proc popupCapabilityConfigApply { wi channel wlan model types groups } { global node_list MACHINE_TYPES g_popupcap_keys + set configNotebook $wi.frame.c.notebookFrame.vals set n 0 set vals {} foreach type $types { set groupinfo [popupCapabilityConfigGroup $groups [expr {$n + 1}]] set gn [lindex $groupinfo 0] - if { ![winfo exists $wi.vals.$gn.item$n.ent] } { + if { ![winfo exists $configNotebook.$gn.item$n.ent] } { puts "warning: missing dialog value $n for $model" continue } - if { [catch { set val [$wi.vals.$gn.item$n.ent get] }] } { + if { [catch { set val [$configNotebook.$gn.item$n.ent get] }] } { if { $type == 11 } { # convert textual value from tk_optionMenu to boolean 0/1 # using hint - global $wi.vals.$gn.item$n.entval $wi.vals.$gn.item$n.entvalhint - if { [set $wi.vals.$gn.item$n.entval] == \ - [set $wi.vals.$gn.item$n.entvalhint] } { + global $configNotebook.$gn.item$n.entval $configNotebook.$gn.item$n.entvalhint + if { [set $configNotebook.$gn.item$n.entval] == \ + [set $configNotebook.$gn.item$n.entvalhint] } { set val 1 ;# true } else { set val 0 ;# false @@ -840,8 +869,8 @@ proc popupCapabilityConfigApply { wi channel wlan model types groups } { } else { # convert textual dropdown value to numeric using first word # e.g. "0 11 Mbps" has a value of 0 - global $wi.vals.$gn.item$n.entval - set selectedopt [set $wi.vals.$gn.item$n.entval] + global $configNotebook.$gn.item$n.entval + set selectedopt [set $configNotebook.$gn.item$n.entval] set val [lindex $selectedopt 0] } } From b6d891f1240690fed9d67cefb32c2764d0392c79 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 2 Apr 2018 14:00:28 -0700 Subject: [PATCH 125/152] updated emane manager to parse config options from manifest, updates to denote core specific configurations within emane models, update to account for manifest parsing of INETADDR --- daemon/core/emane/emanemanager.py | 57 +++++++++++------------------- daemon/core/emane/emanemanifest.py | 2 ++ daemon/core/emane/tdma.py | 5 ++- 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 22061426..9e9bce42 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -11,6 +11,7 @@ from core import constants from core import logger from core.api import coreapi from core.conf import ConfigurableManager +from core.emane import emanemanifest from core.emane.bypass import EmaneBypassModel from core.emane.commeffect import EmaneCommEffectModel from core.emane.emanemodel import EmaneModel @@ -607,7 +608,7 @@ class EmaneManager(ConfigurableManager): doc = self.xmldoc("platform") plat = doc.getElementsByTagName("platform").pop() names = list(self.emane_config.getnames()) - platform_names = names[:len(self.emane_config._confmatrix_platform)] + platform_names = names[:len(self.emane_config.emulator_config)] platform_names.remove("platform_id_start") platform_values = list(values) if otadev: @@ -1010,48 +1011,30 @@ class EmaneGlobalModel(EmaneModel): """ Global EMANE configuration options. """ - - # Over-The-Air channel required for EMANE 0.9.2 - _DEFAULT_OTA = "1" _DEFAULT_DEV = "ctrl0" name = "emane" - _confmatrix_platform = [ - ("antennaprofilemanifesturi", ConfigDataTypes.STRING.value, "", "", "antenna profile manifest URI"), - ("controlportendpoint", ConfigDataTypes.STRING.value, "0.0.0.0:47000", "", "Control port address"), - ("eventservicedevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "Event Service device"), - ("eventservicegroup", ConfigDataTypes.STRING.value, "224.1.2.8:45703", "", "Event Service group"), - ("eventservicettl", ConfigDataTypes.UINT8.value, "1", "", "Event Service TTL"), - ("otamanagerchannelenable", ConfigDataTypes.BOOL.value, _DEFAULT_OTA, "on,off", "enable OTA Manager channel"), - ("otamanagerdevice", ConfigDataTypes.STRING.value, _DEFAULT_DEV, "", "OTA Manager device"), - ("otamanagergroup", ConfigDataTypes.STRING.value, "224.1.2.8:45702", "", "OTA Manager group"), - ("otamanagerloopback", ConfigDataTypes.BOOL.value, "0", "on,off", "Enable OTA multicast loopback"), - ("otamanagermtu", ConfigDataTypes.UINT32.value, "0", "", "OTA channel MTU in bytes, 0 to disable"), - ("otamanagerpartcheckthreshold", ConfigDataTypes.UINT16.value, "2", "", - "Rate in seconds a check is performed to see if any OTA packet part reassembly efforts should be abandoned"), - ("otamanagerparttimeoutthreshold", ConfigDataTypes.UINT16.value, "5", "", - "Threshold in seconds to wait for another OTA packet part for an existing reassembly effort before " - "abandoning the effort"), - ("otamanagerttl", ConfigDataTypes.UINT8.value, "1", "", "OTA channel multicast message TTL"), - ("stats.event.maxeventcountrows", ConfigDataTypes.UINT32.value, "0", "", - "Event channel max event count table rows"), - ("stats.ota.maxeventcountrows", ConfigDataTypes.UINT32.value, "0", "", - "OTA channel max event count table rows"), - ("stats.ota.maxpacketcountrows", ConfigDataTypes.UINT32.value, "0", "", - "OTA channel max packet count table rows"), - ("platform_id_start", ConfigDataTypes.INT32.value, "1", "", "starting Platform ID"), + emulator_xml = "/usr/share/emane/manifest/nemmanager.xml" + emulator_defaults = { + "eventservicedevice": _DEFAULT_DEV, + "eventservicegroup": "224.1.2.8:45703", + "otamanagerdevice": _DEFAULT_DEV, + "otamanagergroup": "224.1.2.8:45702" + } + emulator_config = emanemanifest.parse(emulator_xml, emulator_defaults) + emulator_config.insert( + 0, + ("platform_id_start", ConfigDataTypes.INT32.value, "1", "", "Starting Platform ID (core)") + ) + + nem_config = [ + ("nem_id_start", ConfigDataTypes.INT32.value, "1", "", "Starting NEM ID (core)"), ] - # defined from 0.9.2 - _confmatrix_nem = [ - ("nem_id_start", ConfigDataTypes.INT32.value, "1", "", "starting NEM ID"), - ] - - config_matrix_override = _confmatrix_platform + _confmatrix_nem - config_groups_override = "Platform Attributes:1-%d|NEM Parameters:%d-%d" % \ - (len(_confmatrix_platform), len(_confmatrix_platform) + 1, - len(config_matrix_override)) + config_matrix_override = emulator_config + nem_config + config_groups_override = "Platform Attributes:1-%d|NEM Parameters:%d-%d" % ( + len(emulator_config), len(emulator_config) + 1, len(config_matrix_override)) def __init__(self, session, object_id=None): EmaneModel.__init__(self, session, object_id) diff --git a/daemon/core/emane/emanemanifest.py b/daemon/core/emane/emanemanifest.py index 5f34ede4..e97349c6 100644 --- a/daemon/core/emane/emanemanifest.py +++ b/daemon/core/emane/emanemanifest.py @@ -17,6 +17,8 @@ def _type_value(config_type): config_type = config_type.upper() if config_type == "DOUBLE": config_type = "FLOAT" + elif config_type == "INETADDR": + config_type = "STRING" return ConfigDataTypes[config_type].value diff --git a/daemon/core/emane/tdma.py b/daemon/core/emane/tdma.py index d24a3423..f3c43541 100644 --- a/daemon/core/emane/tdma.py +++ b/daemon/core/emane/tdma.py @@ -27,7 +27,10 @@ class EmaneTdmaModel(emanemodel.EmaneModel): # add custom schedule options and ignore it when writing emane xml schedule_name = "schedule" default_schedule = os.path.join(constants.CORE_DATA_DIR, "examples", "tdma", "schedule.xml") - mac_config.insert(0, (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file")) + mac_config.insert( + 0, + (schedule_name, ConfigDataTypes.STRING.value, default_schedule, "", "TDMA schedule file (core)") + ) config_ignore = {schedule_name} def post_startup(self, emane_manager): From b9ce2ef4ddfa3d0c619b3d3a7b00a9bc25455081 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 11 Apr 2018 08:47:47 -0700 Subject: [PATCH 126/152] removed dependency for tk, for built rpms, since it is not a hard requirement and unavailable in centos7 --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index f7b604d2..26be7d61 100644 --- a/Makefile.am +++ b/Makefile.am @@ -116,7 +116,7 @@ endef .PHONY: fpm fpm: clean-local-fpm $(MAKE) -C gui install DESTDIR=$(DESTDIR) - $(call fpm-gui,rpm,-d "tkimg") + $(call fpm-gui,rpm) $(call fpm-gui,deb,-d "libtk-img") $(call fpm-python,rpm,ns3/setup.py) $(call fpm-python,deb,ns3/setup.py) From 2662a36f099f5199ecd03c8e92ec801cad0b96f9 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 11 Apr 2018 09:57:02 -0700 Subject: [PATCH 127/152] updated sysv file to provide the python_path environment variable when not already present --- Makefile.am | 1 + scripts/core-daemon.in | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 26be7d61..0354755d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -141,6 +141,7 @@ define change-files = $(info creating file $1 from $1.in) @$(SED) -e 's,[@]sbindir[@],$(sbindir),g' \ -e 's,[@]bindir[@],$(bindir),g' \ + -e 's,[@]pythondir[@],$(pythondir),g' \ -e 's,[@]PYTHON[@],$(PYTHON),g' \ -e 's,[@]PACKAGE_VERSION[@],$(PACKAGE_VERSION),g' \ -e 's,[@]PACKAGE_DATE[@],$(PACKAGE_DATE),g' \ diff --git a/scripts/core-daemon.in b/scripts/core-daemon.in index 37a493c8..36e834de 100644 --- a/scripts/core-daemon.in +++ b/scripts/core-daemon.in @@ -20,7 +20,7 @@ NAME=`basename $0` PIDFILE="@CORE_STATE_DIR@/run/$NAME.pid" LOG="@CORE_STATE_DIR@/log/$NAME.log" -CMD="@PYTHON@ @bindir@/$NAME" +CMD="PYTHON_PATH=@pythondir@ @PYTHON@ @bindir@/$NAME" get_pid() { cat "$PIDFILE" @@ -43,7 +43,7 @@ corestart() { echo "unable to start $NAME, see $LOG" exit 1 fi -} +} corestop() { if is_alive; then @@ -57,7 +57,7 @@ corestop() { echo -n "." done echo - + if is_alive; then echo "not stopped; may still be shutting down" exit 1 @@ -70,12 +70,12 @@ corestop() { else echo "$NAME not running" fi -} +} corerestart() { corestop corestart -} +} corestatus() { if is_alive; then @@ -84,7 +84,7 @@ corestatus() { echo "$NAME is stopped" exit 1 fi -} +} case "$1" in From 7e03202ba40486c57dc32f3a3d07bc58dcbfc672 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 16 Apr 2018 14:00:04 -0700 Subject: [PATCH 128/152] remove old utility examples for now --- daemon/examples/emanemanifest2core.py | 214 -------------------------- daemon/examples/emanemodel2core.py | 173 --------------------- daemon/examples/findcore.py | 78 ---------- 3 files changed, 465 deletions(-) delete mode 100755 daemon/examples/emanemanifest2core.py delete mode 100755 daemon/examples/emanemodel2core.py delete mode 100755 daemon/examples/findcore.py diff --git a/daemon/examples/emanemanifest2core.py b/daemon/examples/emanemanifest2core.py deleted file mode 100755 index a33da0af..00000000 --- a/daemon/examples/emanemanifest2core.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/env python - -from emanesh import manifest -import os.path -import re -import textwrap - -class EmaneManifest2Model(object): - - class EmaneModel(object): - - class EmaneModelParameter(object): - - intfloat_regex = re.compile(r'^([0-9]+)\.(0*)$') - indent = ' ' * 16 - - def __init__(self, name, apitype, default, caption, - possible_values = ()): - self.name = name - self.apitype = apitype - self.default = self.intfloat_regex.sub(r'\1.0', default) - self.possible_values = possible_values - self.caption = caption - - def __str__(self): - return '''%s('%s', %s,\n%s '%s', '%s', '%s')''' % \ - (self.indent, self.name, self.apitype, - self.indent, self.default, - ','.join(self.possible_values), self.caption) - - def __init__(self, name): - self.name = name - self.parameters = [] - - def add_parameter(self, name, apitype, default, caption, - possible_values = ()): - p = self.EmaneModelParameter(name, apitype, default, caption, - possible_values) - self.parameters.append(p) - - mac_xml_path = '/usr/share/emane/xml/models/mac' - - # map emane parameter types to CORE api data types - core_api_type = { - 'uint8': 'coreapi.CONF_DATA_TYPE_UINT8', - 'uint16': 'coreapi.CONF_DATA_TYPE_UINT16', - 'uint32': 'coreapi.CONF_DATA_TYPE_UINT32', - 'uint64': 'coreapi.CONF_DATA_TYPE_UINT64', - 'int8': 'coreapi.CONF_DATA_TYPE_INT8', - 'int16': 'coreapi.CONF_DATA_TYPE_INT16', - 'int32': 'coreapi.CONF_DATA_TYPE_INT32', - 'int64': 'coreapi.CONF_DATA_TYPE_INT64', - 'float': 'coreapi.CONF_DATA_TYPE_FLOAT', - 'double': 'coreapi.CONF_DATA_TYPE_FLOAT', - 'bool': 'coreapi.CONF_DATA_TYPE_BOOL', - 'string': 'coreapi.CONF_DATA_TYPE_STRING', - } - - parameter_regex = re.compile(r'^\^\(([\|\-\w]+)\)\$$') - - @classmethod - def emane_model(cls, xmlfile): - m = manifest.Manifest(xmlfile) - model = cls.EmaneModel(m.getName()) - for name in m.getAllConfiguration(): - info = m.getConfigurationInfo(name) - apitype = None - for t in 'numeric', 'nonnumeric': - if t in info: - apitype = cls.core_api_type[info[t]['type']] - break - default = '' - if info['default']: - values = info['values'] - if values: - default = values[0] - caption = name - possible_values = [] - if apitype == 'coreapi.CONF_DATA_TYPE_BOOL': - possible_values = ['On,Off'] - elif apitype == 'coreapi.CONF_DATA_TYPE_STRING': - if name == 'pcrcurveuri': - default = os.path.join(cls.mac_xml_path, - model.name, model.name + 'pcr.xml') - else: - regex = info['regex'] - if regex: - match = cls.parameter_regex.match(regex) - if match: - possible_values = match.group(1).split('|') - model.add_parameter(name, apitype, default, - caption, possible_values) - model.parameters.sort(key = lambda x: x.name) - return model - - @classmethod - def core_emane_model(cls, class_name, macmanifest_filename, - phymanifest_filename): - template = '''\ - from core.emane.emane import EmaneModel - from core.api import coreapi - - class BaseEmaneModel(EmaneModel): - def __init__(self, session, objid = None, verbose = False): - EmaneModel.__init__(self, session, objid, verbose) - - def buildnemxmlfiles(self, e, ifc): - \'\'\'\\ - Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to - build that file also. Otherwise the WLAN-wide - nXXemane_*nem.xml, nXXemane_*mac.xml, nXXemane_*phy.xml are - used. - \'\'\' - values = e.getifcconfig(self.objid, self._name, - self.getdefaultvalues(), ifc) - if values is None: - return - - nemdoc = e.xmldoc('nem') - nem = nemdoc.getElementsByTagName('nem').pop() - e.appendtransporttonem(nemdoc, nem, self.objid, ifc) - - def append_definition(tag, name, xmlname, doc): - el = doc.createElement(name) - el.setAttribute('definition', xmlname) - tag.appendChild(el) - - append_definition(nem, 'mac', self.macxmlname(ifc), nemdoc) - append_definition(nem, 'phy', self.phyxmlname(ifc), nemdoc) - - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) - - names = list(self.getnames()) - - def append_options(tag, optnames, doc): - for name in optnames: - value = self.valueof(name, values).strip() - if value: - tag.appendChild(e.xmlparam(doc, name, value)) - - macdoc = e.xmldoc('mac') - mac = macdoc.getElementsByTagName('mac').pop() - mac.setAttribute('library', '%(modelLibrary)s') - # append MAC options to macdoc - append_options(mac, names[:len(self._confmatrix_mac)], macdoc) - e.xmlwrite(macdoc, self.macxmlname(ifc)) - - phydoc = e.xmldoc('phy') - phy = phydoc.getElementsByTagName('phy').pop() - # append PHY options to phydoc - append_options(phy, names[len(self._confmatrix_mac):], phydoc) - e.xmlwrite(phydoc, self.phyxmlname(ifc)) - - class %(modelClass)s(BaseEmaneModel): - # model name - _name = 'emane_%(modelName)s' - - # configuration parameters are - # ( 'name', 'type', 'default', 'possible-value-list', 'caption') - # MAC parameters - _confmatrix_mac = [\n%(confMatrixMac)s - ] - - # PHY parameters - _confmatrix_phy = [\n%(confMatrixPhy)s - ] - - _confmatrix = _confmatrix_mac + _confmatrix_phy - - # value groupings - _confgroups = 'MAC Parameters:1-%%s|PHY Parameters:%%s-%%s' %% \\ - (len(_confmatrix_mac), \\ - len(_confmatrix_mac) + 1, len(_confmatrix)) - ''' - macmodel = cls.emane_model(macmanifest_filename) - phymodel = cls.emane_model(phymanifest_filename) - d = { - 'modelClass': 'Emane%sModel' % (class_name), - 'modelName': macmodel.name, - 'confMatrixMac': ',\n'.join(map(str, macmodel.parameters)) + ',', - 'confMatrixPhy': ',\n'.join(map(str, phymodel.parameters)) + ',', - 'modelLibrary': macmodel.name, - } - return textwrap.dedent(template % d) - -def main(): - import argparse - import sys - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description = 'Create skeleton CORE bindings from ' \ - 'EMANE model manifest files.', - epilog = 'example:\n' \ - ' %(prog)s -c RadioX \\\n' \ - ' -m /usr/share/emane/manifest/radiox.xml \\\n' \ - ' -p /usr/share/emane/manifest/emanephy.xml') - parser.add_argument('-c', '--class-name', dest = 'classname', - required = True, help = 'corresponding python ' - 'class name: RadioX -> EmaneRadioXModel') - parser.add_argument('-m', '--mac-xmlfile', dest = 'macxmlfilename', - required = True, - help = 'MAC model manifest XML filename') - parser.add_argument('-p', '--phy-xmlfile', dest = 'phyxmlfilename', - required = True, - help = 'PHY model manifest XML filename') - args = parser.parse_args() - model = EmaneManifest2Model.core_emane_model(args.classname, - args.macxmlfilename, - args.phyxmlfilename) - sys.stdout.write(model) - -if __name__ == "__main__": - main() diff --git a/daemon/examples/emanemodel2core.py b/daemon/examples/emanemodel2core.py deleted file mode 100755 index bc48fda2..00000000 --- a/daemon/examples/emanemodel2core.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python -''' -emanemodel2core.py: scans an EMANE model source file - (e.g. emane/models/rfpipe/maclayer/rfpipemaclayer.cc) and outputs Python - bindings that allow the model to be used in CORE. - - When using this conversion utility, you should replace XYZ, Xyz, and xyz with - the actual model name. Note the capitalization convention. -''' - -import os, sys, optparse - -MODEL_TEMPLATE_PART1 = """ -''' -xyz.py: EMANE XYZ model bindings for CORE -''' - -from core.api import coreapi -from emane import EmaneModel -from universal import EmaneUniversalModel - -class EmaneXyzModel(EmaneModel): - def __init__(self, session, objid = None, verbose = False): - EmaneModel.__init__(self, session, objid, verbose) - - # model name - _name = "emane_xyz" - # MAC parameters - _confmatrix_mac = [ -""" - -MODEL_TEMPLATE_PART2 = """ - ] - - # PHY parameters from Universal PHY - _confmatrix_phy = EmaneUniversalModel._confmatrix - - _confmatrix = _confmatrix_mac + _confmatrix_phy - - # value groupings - _confgroups = "XYZ MAC Parameters:1-%d|Universal PHY Parameters:%d-%d" \ - % ( len(_confmatrix_mac), len(_confmatrix_mac) + 1, len(_confmatrix)) - - def buildnemxmlfiles(self, e, ifc): - ''' Build the necessary nem, mac, and phy XMLs in the given path. - If an individual NEM has a nonstandard config, we need to build - that file also. Otherwise the WLAN-wide nXXemane_xyznem.xml, - nXXemane_xyzmac.xml, nXXemane_xyzphy.xml are used. - ''' - values = e.getifcconfig(self.objid, self._name, - self.getdefaultvalues(), ifc) - if values is None: - return - nemdoc = e.xmldoc("nem") - nem = nemdoc.getElementsByTagName("nem").pop() - nem.setAttribute("name", "XYZ NEM") - mactag = nemdoc.createElement("mac") - mactag.setAttribute("definition", self.macxmlname(ifc)) - nem.appendChild(mactag) - phytag = nemdoc.createElement("phy") - phytag.setAttribute("definition", self.phyxmlname(ifc)) - nem.appendChild(phytag) - e.xmlwrite(nemdoc, self.nemxmlname(ifc)) - - names = list(self.getnames()) - macnames = names[:len(self._confmatrix_mac)] - phynames = names[len(self._confmatrix_mac):] - # make any changes to the mac/phy names here to e.g. exclude them from - # the XML output - - macdoc = e.xmldoc("mac") - mac = macdoc.getElementsByTagName("mac").pop() - mac.setAttribute("name", "XYZ MAC") - mac.setAttribute("library", "xyzmaclayer") - # append MAC options to macdoc - map( lambda n: mac.appendChild(e.xmlparam(macdoc, n, \ - self.valueof(n, values))), macnames) - e.xmlwrite(macdoc, self.macxmlname(ifc)) - - phydoc = EmaneUniversalModel.getphydoc(e, self, values, phynames) - e.xmlwrite(phydoc, self.phyxmlname(ifc)) - -""" - -def emane_model_source_to_core(infile, outfile): - do_parse_line = False - output = MODEL_TEMPLATE_PART1 - - with open(infile, 'r') as f: - for line in f: - # begin marker - if "EMANE::ConfigurationDefinition" in line: - do_parse_line = True - # end marker -- all done - if "{0, 0, 0, 0, 0, 0" in line: - break - if do_parse_line: - outstr = convert_line(line) - if outstr is not None: - output += outstr - continue - output += MODEL_TEMPLATE_PART2 - - if outfile == sys.stdout: - sys.stdout.write(output) - else: - with open(outfile, 'w') as f: - f.write(output) - -def convert_line(line): - line = line.strip() - # skip comments - if line.startswith(('/*', '//')): - return None - items = line.strip('{},').split(',') - if len(items) != 7: - #print "continuning on line=", len(items), items - return None - return convert_items_to_line(items) - -def convert_items_to_line(items): - fields = ('required', 'default', 'count', 'name', 'value', 'type', - 'description') - getfield = lambda(x): items[fields.index(x)].strip() - - output = " (" - output += "%s, " % getfield('name') - value = getfield('value') - if value == '"off"': - type = "coreapi.CONF_DATA_TYPE_BOOL" - value = "0" - defaults = '"On,Off"' - elif value == '"on"': - type = "coreapi.CONF_DATA_TYPE_BOOL" - value = '"1"' - defaults = '"On,Off"' - else: - type = "coreapi.CONF_DATA_TYPE_STRING" - defaults = '""' - output += "%s, %s, %s, " % (type, value, defaults) - output += getfield('description') - output += "),\n" - return output - - -def main(): - usagestr = "usage: %prog [-h] [options] -- ..." - parser = optparse.OptionParser(usage = usagestr) - parser.set_defaults(infile = None, outfile = sys.stdout) - - parser.add_option("-i", "--infile", dest = "infile", - help = "file to read (usually '*mac.cc')") - parser.add_option("-o", "--outfile", dest = "outfile", - help = "file to write (stdout is default)") - - def usage(msg = None, err = 0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.infile is None: - usage("please specify input file with the '-i' option", err=1) - - emane_model_source_to_core(options.infile, options.outfile) - - -if __name__ == "__main__": - main() diff --git a/daemon/examples/findcore.py b/daemon/examples/findcore.py deleted file mode 100755 index 5c45d52e..00000000 --- a/daemon/examples/findcore.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -# Search for installed CORE library files and Python bindings. -# - -import os, glob - -pythondirs = [ - "/usr/lib/python2.7/site-packages", - "/usr/lib/python2.7/dist-packages", - "/usr/lib64/python2.7/site-packages", - "/usr/lib64/python2.7/dist-packages", - "/usr/local/lib/python2.7/site-packages", - "/usr/local/lib/python2.7/dist-packages", - "/usr/local/lib64/python2.7/site-packages", - "/usr/local/lib64/python2.7/dist-packages", - "/usr/lib/python2.6/site-packages", - "/usr/lib/python2.6/dist-packages", - "/usr/lib64/python2.6/site-packages", - "/usr/lib64/python2.6/dist-packages", - "/usr/local/lib/python2.6/site-packages", - "/usr/local/lib/python2.6/dist-packages", - "/usr/local/lib64/python2.6/site-packages", - "/usr/local/lib64/python2.6/dist-packages", - ] - -tcldirs = [ - "/usr/lib/core", - "/usr/local/lib/core", - ] - -def find_in_file(fn, search, column=None): - ''' Find a line starting with 'search' in the file given by the filename - 'fn'. Return True if found, False if not found, or the column text if - column is specified. - ''' - r = False - if not os.path.exists(fn): - return r - f = open(fn, "r") - for line in f: - if line[:len(search)] != search: - continue - r = True - if column is not None: - r = line.split()[column] - break - f.close() - return r - -def main(): - versions = [] - for d in pythondirs: - fn = "%s/core/constants.py" % d - ver = find_in_file(fn, 'COREDPY_VERSION', 2) - if ver: - ver = ver.strip('"') - versions.append((d, ver)) - for e in glob.iglob("%s/core_python*egg-info" % d): - ver = find_in_file(e, 'Version:', 1) - if ver: - versions.append((e, ver)) - for e in glob.iglob("%s/netns*egg-info" % d): - ver = find_in_file(e, 'Version:', 1) - if ver: - versions.append((e, ver)) - for d in tcldirs: - fn = "%s/version.tcl" % d - ver = find_in_file(fn, 'set CORE_VERSION', 2) - if ver: - versions.append((d, ver)) - - for (d, ver) in versions: - print "%8s %s" % (ver, d) - -if __name__ == "__main__": - main() - From 9fe57c6089b9c26abf59b5a22bf455f0424ab24c Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 17 Apr 2018 14:30:34 -0700 Subject: [PATCH 129/152] initial toy code for future core api changes/improvements --- daemon/core/future/__init__.py | 0 daemon/core/future/coreemu.py | 152 +++++++++++++++++++++++++++ daemon/examples/future/emane80211.py | 54 ++++++++++ daemon/examples/future/parser.py | 41 ++++++++ daemon/examples/future/switch.py | 59 +++++++++++ daemon/examples/future/wlan.py | 66 ++++++++++++ 6 files changed, 372 insertions(+) create mode 100644 daemon/core/future/__init__.py create mode 100644 daemon/core/future/coreemu.py create mode 100644 daemon/examples/future/emane80211.py create mode 100644 daemon/examples/future/parser.py create mode 100644 daemon/examples/future/switch.py create mode 100644 daemon/examples/future/wlan.py diff --git a/daemon/core/future/__init__.py b/daemon/core/future/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py new file mode 100644 index 00000000..971399fb --- /dev/null +++ b/daemon/core/future/coreemu.py @@ -0,0 +1,152 @@ +# import itertools + +from core import services +from core.emane.nodes import EmaneNode +from core.misc.ipaddress import Ipv4Prefix +from core.netns.nodes import CoreNode +from core.session import Session + + +class IdGen(object): + def __init__(self): + self.id = 0 + + def next(self): + self.id += 1 + return self.id + + +class FutureIpv4Prefix(Ipv4Prefix): + def get_address(self, node_id): + address = self.addr(node_id) + return "%s/%s" % (address, self.prefixlen) + + +class FutureSession(Session): + def __init__(self, session_id, config=None, persistent=True, mkdir=True): + super(FutureSession, self).__init__(session_id, config, persistent, mkdir) + + # set master + self.master = True + + # object management + self.object_id_gen = IdGen() + + # set default services + self.services.defaultservices = { + "mdr": ("zebra", "OSPFv3MDR", "IPForward"), + "PC": ("DefaultRoute",), + "prouter": ("zebra", "OSPFv2", "OSPFv3", "IPForward"), + "router": ("zebra", "OSPFv2", "OSPFv3", "IPForward"), + "host": ("DefaultRoute", "SSH"), + } + + def create_node(self, cls, name=None, model=None): + object_id = self.object_id_gen.next() + + if not name: + name = "%s%s" % (cls.__name__, object_id) + + node = self.add_object(cls=cls, name=name, objid=object_id) + node.type = model + if node.type: + self.services.addservicestonode(node, node.type, services_str=None) + + return node + + def create_emane_node(self, name=None): + return self.create_node(cls=CoreNode, name=name, model="mdr") + + def create_emane_network(self, model, geo_reference, geo_scale=None, name=None): + """ + Convenience method for creating an emane network. + + :param model: emane model to use for emane network + :param geo_reference: geo reference point to use for emane node locations + :param geo_scale: geo scale to use for emane node locations, defaults to 1.0 + :param name: name for emane network, defaults to node class name + :return: create emane network + """ + # required to be set for emane to function properly + self.location.setrefgeo(*geo_reference) + if geo_scale: + self.location.refscale = geo_scale + + # create and return network + emane_network = self.create_node(cls=EmaneNode, name=name) + self.set_emane_model(emane_network, model) + return emane_network + + def set_emane_model(self, emane_node, model): + """ + Set emane model for a given emane node. + + :param emane_node: emane node to set model for + :param model: emane model to set + :return: nothing + """ + values = list(model.getdefaultvalues()) + self.emane.setconfig(emane_node.objid, model.name, values) + + +class CoreEmu(object): + """ + Provides logic for creating and configuring CORE sessions and the nodes within them. + """ + + def __init__(self, config=None): + # configuration + self.config = config + + # session management + self.session_id_gen = IdGen() + self.sessions = {} + + # load default services + services.load() + + def create_session(self): + """ + Create a new CORE session. + + :return: created session + :rtype: FutureSession + """ + session_id = self.session_id_gen.next() + return FutureSession(session_id, config=self.config) + + def set_wireless_model(self, node, model): + """ + Convenience method for setting a wireless model. + + :param node: node to set wireless model for + :param core.mobility.WirelessModel model: wireless model to set node to + :return: nothing + """ + values = list(model.getdefaultvalues()) + node.setmodel(model, values) + + def wireless_link_all(self, network, nodes): + """ + Link all nodes to the provided wireless network. + + :param network: wireless network to link nodes to + :param nodes: nodes to link to wireless network + :return: nothing + """ + for node in nodes: + for common_network, interface_one, interface_two in node.commonnets(network): + common_network.link(interface_one, interface_two) + + def add_interface(self, network, node, prefix): + """ + Convenience method for adding an interface with a prefix based on node id. + + :param network: network to add interface with + :param node: node to add interface to + :param prefix: prefix to get address from for interface + :return: created interface + """ + address = prefix.get_address(node.objid) + interface_index = node.newnetif(network, [address]) + return node.netif(interface_index) diff --git a/daemon/examples/future/emane80211.py b/daemon/examples/future/emane80211.py new file mode 100644 index 00000000..66c9cd22 --- /dev/null +++ b/daemon/examples/future/emane80211.py @@ -0,0 +1,54 @@ +#!/usr/bin/python -i +# +# Example CORE Python script that attaches N nodes to an EMANE 802.11abg network. + +import datetime + +import parser +from core.emane.ieee80211abg import EmaneIeee80211abgModel +from core.future.coreemu import FutureIpv4Prefix, CoreEmu + + +def example(options): + # ip generator for example + prefix = FutureIpv4Prefix("10.83.0.0/16") + + # create emulator instance for creating sessions and utility methods + coreemu = CoreEmu() + session = coreemu.create_session() + + # create emane network node + emane_network = session.create_emane_network( + model=EmaneIeee80211abgModel, + geo_reference=(47.57917, -122.13232, 2.00000) + ) + emane_network.setposition(x=80, y=50) + + # create nodes + for i in xrange(options.nodes): + node = session.create_emane_node() + coreemu.add_interface(emane_network, node, prefix) + node.setposition(x=150 * (i + 1), y=150) + + # instantiate session + session.instantiate() + + # start a shell on the first node + node = session.get_object(2) + node.client.term("bash") + + # shutdown session + raw_input("press enter to exit...") + session.shutdown() + + +def main(): + options = parser.parse_options("emane80211") + start = datetime.datetime.now() + print "running emane 80211 example: nodes(%s) time(%s)" % (options.nodes, options.time) + example(options) + print "elapsed time: %s" % (datetime.datetime.now() - start) + + +if __name__ == "__main__" or __name__ == "__builtin__": + main() diff --git a/daemon/examples/future/parser.py b/daemon/examples/future/parser.py new file mode 100644 index 00000000..c6523ba1 --- /dev/null +++ b/daemon/examples/future/parser.py @@ -0,0 +1,41 @@ +import argparse + +DEFAULT_NODES = 2 +DEFAULT_TIME = 10 +DEFAULT_STEP = 1 + + +def parse_options(name): + parser = argparse.ArgumentParser(description="Run %s example" % name) + parser.add_argument("-n", "--nodes", type=int, default=DEFAULT_NODES, + help="number of nodes to create in this example") + parser.add_argument("-t", "--time", type=int, default=DEFAULT_TIME, + help="example iperf run time in seconds") + + options = parser.parse_args() + + # usagestr = "usage: %prog [-h] [options] [args]" + # parser = optparse.OptionParser(usage=usagestr) + # + # parser.add_option("-n", "--nodes", dest="nodes", type=int, default=DEFAULT_NODES, + # help="number of nodes to create in this example") + # + # parser.add_option("-t", "--time", dest="time", type=int, default=DEFAULT_TIME, + # help="example iperf run time in seconds") + + # def usage(msg=None, err=0): + # print + # if msg: + # print "%s\n" % msg + # parser.print_help() + # sys.exit(err) + + # parse command line options + # options, args = parser.parse_args() + + if options.nodes < 2: + parser.error("invalid min number of nodes: %s" % options.nodes) + if options.time < 1: + parser.error("invalid test time: %s" % options.time) + + return options diff --git a/daemon/examples/future/switch.py b/daemon/examples/future/switch.py new file mode 100644 index 00000000..7333d567 --- /dev/null +++ b/daemon/examples/future/switch.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# +# run iperf to measure the effective throughput between two nodes when +# n nodes are connected to a virtual wlan; run test for testsec +# and repeat for minnodes <= n <= maxnodes with a step size of +# nodestep + +import datetime + +import parser +from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.netns.nodes import CoreNode, SwitchNode + + +def example(options): + # ip generator for example + prefix = FutureIpv4Prefix("10.83.0.0/16") + + # create emulator instance for creating sessions and utility methods + coreemu = CoreEmu() + session = coreemu.create_session() + + # create switch network node + switch_network = session.create_node(cls=SwitchNode) + + # create nodes + for _ in xrange(options.nodes): + node = session.create_node(cls=CoreNode) + coreemu.add_interface(switch_network, node, prefix) + + # instantiate session + session.instantiate() + + # get nodes to run example + first_node = session.get_object(2) + last_node = session.get_object(options.nodes + 1) + + print "starting iperf server on node: %s" % first_node.name + first_node.cmd(["iperf", "-s", "-D"]) + address = str(prefix.addr(first_node.objid)) + print "node %s connecting to %s" % (last_node.name, address) + last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) + first_node.cmd(["killall", "-9", "iperf"]) + + # shutdown session + session.shutdown() + + +def main(): + options = parser.parse_options("switch") + + start = datetime.datetime.now() + print "running switch example: nodes(%s) time(%s)" % (options.nodes, options.time) + example(options) + print "elapsed time: %s" % (datetime.datetime.now() - start) + + +if __name__ == "__main__": + main() diff --git a/daemon/examples/future/wlan.py b/daemon/examples/future/wlan.py new file mode 100644 index 00000000..efbd725c --- /dev/null +++ b/daemon/examples/future/wlan.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# +# run iperf to measure the effective throughput between two nodes when +# n nodes are connected to a virtual wlan; run test for testsec +# and repeat for minnodes <= n <= maxnodes with a step size of +# nodestep + +import datetime + +import parser +from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.mobility import BasicRangeModel +from core.netns.nodes import WlanNode, CoreNode + + +def example(options): + # ip generator for example + prefix = FutureIpv4Prefix("10.83.0.0/16") + + # create emulator instance for creating sessions and utility methods + coreemu = CoreEmu() + session = coreemu.create_session() + + # create wlan network node + wlan_network = session.create_node(cls=WlanNode) + coreemu.set_wireless_model(wlan_network, BasicRangeModel) + + # create nodes + wireless_nodes = [] + for _ in xrange(options.nodes): + node = session.create_node(cls=CoreNode) + coreemu.add_interface(wlan_network, node, prefix) + wireless_nodes.append(node) + + # link all created nodes with the wireless network + coreemu.wireless_link_all(wlan_network, wireless_nodes) + + # instantiate session + session.instantiate() + + # get nodes for example run + first_node = session.get_object(2) + last_node = session.get_object(options.nodes + 1) + + print "starting iperf server on node: %s" % first_node.name + first_node.cmd(["iperf", "-s", "-D"]) + address = str(prefix.addr(first_node.objid)) + print "node %s connecting to %s" % (last_node.name, address) + last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) + first_node.cmd(["killall", "-9", "iperf"]) + + # shutdown session + session.shutdown() + + +def main(): + options = parser.parse_options("wlan") + + start = datetime.datetime.now() + print "running wlan example: nodes(%s) time(%s)" % (options.nodes, options.time) + example(options) + print "elapsed time: %s" % (datetime.datetime.now() - start) + + +if __name__ == "__main__": + main() From d8796b377fd10b1bec306324340c4fdf431156bd Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 19 Apr 2018 14:25:45 -0700 Subject: [PATCH 130/152] initial working code for consolidated logic into a future session object, for dealing with nodes/links --- daemon/core/future/coreemu.py | 636 ++++++++++++++- daemon/core/future/futurehandler.py | 1127 +++++++++++++++++++++++++++ daemon/core/future/futureserver.py | 263 +++++++ daemon/scripts/core-future | 180 +++++ 4 files changed, 2201 insertions(+), 5 deletions(-) create mode 100644 daemon/core/future/futurehandler.py create mode 100644 daemon/core/future/futureserver.py create mode 100644 daemon/scripts/core-future diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 971399fb..9d5f122a 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -1,10 +1,133 @@ -# import itertools +import os -from core import services +import core.services +from core import logger +from core.coreobj import PyCoreNode, PyCoreNet +from core.data import NodeData from core.emane.nodes import EmaneNode +from core.enumerations import NodeTypes, EventTypes, LinkTypes +from core.misc import nodeutils from core.misc.ipaddress import Ipv4Prefix from core.netns.nodes import CoreNode from core.session import Session +from core.xml.xmlparser import core_document_parser +from core.xml.xmlwriter import core_document_writer + + +class InterfaceData(object): + def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask): + self.id = _id + self.name = name + self.mac = mac + self.ip4 = ip4 + self.ip4_mask = ip4_mask + self.ip6 = ip6 + self.ip6_mask = ip6_mask + + def has_ip4(self): + return all([self.ip4, self.ip4_mask]) + + def has_ip6(self): + return all([self.ip6, self.ip6_mask]) + + def ip4_address(self): + if self.has_ip4(): + return "%s/%s" % (self.ip4, self.ip4_mask) + else: + return None + + def ip6_address(self): + if self.has_ip6(): + return "%s/%s" % (self.ip6, self.ip6_mask) + else: + return None + + def get_addresses(self): + ip4 = self.ip4_address() + ip6 = self.ip6_address() + return [i for i in [ip4, ip6] if i] + + +def get_interfaces(link_data): + interface_one = InterfaceData( + _id=link_data.interface1_id, + name=link_data.interface1_name, + mac=link_data.interface1_mac, + ip4=link_data.interface1_ip4, + ip4_mask=link_data.interface1_ip4_mask, + ip6=link_data.interface1_ip6, + ip6_mask=link_data.interface1_ip6_mask, + ) + interface_two = InterfaceData( + _id=link_data.interface2_id, + name=link_data.interface2_name, + mac=link_data.interface2_mac, + ip4=link_data.interface2_ip4, + ip4_mask=link_data.interface2_ip4_mask, + ip6=link_data.interface2_ip6, + ip6_mask=link_data.interface2_ip6_mask, + ) + return interface_one, interface_two + + +def create_interface(node, network, addresses, interface_data): + """ + Create an interface for a node on a network using provided interface data. + + :param node: node to create interface for + :param network: network to associate interface with + :param list[str] addresses: + :param InterfaceData interface_data: interface data + :return: + """ + node.newnetif( + network, + addrlist=addresses, + hwaddr=interface_data.mac, + ifindex=interface_data.id, + ifname=interface_data.name + ) + return node.netif(interface_data.id, network) + + +def link_config(network, interface, link_data, devname=None, interface_two=None): + config = { + "netif": interface, + "bw": link_data.bandwidth, + "delay": link_data.delay, + "loss": link_data.per, + "duplicate": link_data.dup, + "jitter": link_data.jitter, + "netif2": interface_two + } + + # hacky check here, because physical and emane nodes do not conform to the same linkconfig interface + if not nodeutils.is_node(network, [NodeTypes.EMANE, NodeTypes.PHYSICAL]): + config["devname"] = devname + + network.linkconfig(**config) + + +def is_net_node(node): + """ + Convenience method for testing if a legacy core node is considered a network node. + + :param object node: object to test against + :return: True if object is an instance of a network node, False otherwise + :rtype: bool + """ + return isinstance(node, PyCoreNet) + + +def is_core_node(node): + """ + Convenience method for testing if a legacy core node is considered a core node. + + :param object node: object to test against + :return: True if object is an instance of a core node, False otherwise + :rtype: bool + """ + return isinstance(node, PyCoreNode) class IdGen(object): @@ -30,7 +153,7 @@ class FutureSession(Session): self.master = True # object management - self.object_id_gen = IdGen() + self.node_id_gen = IdGen() # set default services self.services.defaultservices = { @@ -41,8 +164,511 @@ class FutureSession(Session): "host": ("DefaultRoute", "SSH"), } + def link_nodes(self, link_data): + logger.info("link message between node1(%s:%s) and node2(%s:%s)", + link_data.node1_id, link_data.interface1_id, link_data.node2_id, link_data.interface2_id) + + # values to fill + net_one = None + net_two = None + + # retrieve node one + n1_id = link_data.node1_id + n2_id = link_data.node2_id + node_one = self.get_object(n1_id) + node_two = self.get_object(n2_id) + + # both node ids are provided + tunnel = self.broker.gettunnel(n1_id, n2_id) + logger.info("tunnel between nodes: %s", tunnel) + if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE): + net_one = tunnel + if tunnel.remotenum == n1_id: + node_one = None + else: + node_two = None + # PhysicalNode connected via GreTap tunnel; uses adoptnetif() below + elif tunnel: + if tunnel.remotenum == n1_id: + node_one = None + else: + node_two = None + + if is_net_node(node_one): + if not net_one: + net_one = node_one + else: + net_two = node_one + node_one = None + + if is_net_node(node_two): + if not net_one: + net_one = node_two + else: + net_two = node_two + node_two = None + + logger.info("link node types n1(%s) n2(%s) net1(%s) net2(%s) tunnel(%s)", + node_one, node_two, net_one, net_two, tunnel) + return node_one, node_two, net_one, net_two, tunnel + + # TODO: this doesn't appear to ever be used, EMANE or basic wireless range + def _link_wireless(self, objects, connect): + """ + Objects to deal with when connecting/disconnecting wireless links. + + :param list objects: possible objects to deal with + :param bool connect: link interfaces if True, unlink otherwise + :return: nothing + """ + objects = [x for x in objects if x] + if len(objects) < 2: + raise ValueError("wireless link failure: %s", objects) + logger.info("handling wireless linking objects(%) connect(%s)", objects, connect) + common_networks = objects[0].commonnets(objects[1]) + for common_network, interface_one, interface_two in common_networks: + if not nodeutils.is_node(common_network, [NodeTypes.WIRELESS_LAN, NodeTypes.EMANE]): + logger.info("skipping common network that is not wireless/emane: %s", common_network) + continue + + logger.info("wireless linking connect(%s): %s - %s", connect, interface_one, interface_two) + if connect: + common_network.link(interface_one, interface_two) + else: + common_network.unlink(interface_one, interface_two) + else: + raise ValueError("no common network found for wireless link/unlink") + + def link_add(self, link_data): + # interface data + interface_one_data, interface_two_data = get_interfaces(link_data) + + # get node objects identified by link data + node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + + if node_one: + node_one.lock.acquire() + if node_two: + node_two.lock.acquire() + + try: + # wireless link + if link_data.link_type == LinkTypes.WIRELESS.value: + objects = [node_one, node_two, net_one, net_two] + self._link_wireless(objects, connect=True) + # wired link + else: + # 2 nodes being linked, ptp network + if all([node_one, node_two]) and not net_one: + ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER) + start = self.state > EventTypes.DEFINITION_STATE.value + net_one = self.add_object(cls=ptp_class, start=start) + + # node to network + if node_one and net_one: + addresses = [] + addresses.extend(interface_one_data.get_addresses()) + addresses.extend(interface_two_data.get_addresses()) + interface = create_interface(node_one, net_one, addresses, interface_one_data) + link_config(net_one, interface, link_data) + + # network to node + if node_two and net_one: + addresses = [] + addresses.extend(interface_one_data.get_addresses()) + addresses.extend(interface_two_data.get_addresses()) + interface = create_interface(node_two, net_one, addresses, interface_two_data) + if not link_data.unidirectional: + link_config(net_one, interface, link_data) + + # network to network + if net_one and net_two: + if nodeutils.is_node(net_two, NodeTypes.RJ45): + interface = net_two.linknet(net_one) + else: + interface = net_one.linknet(net_two) + + link_config(net_one, interface, link_data) + + if not link_data.unidirectional: + interface.swapparams("_params_up") + link_config(net_two, interface, link_data, devname=interface.name) + interface.swapparams("_params_up") + + # a tunnel was found for the nodes + addresses = [] + if not node_one and net_one: + addresses.extend(interface_one_data.get_addresses()) + + if not node_two and net_two: + addresses.extend(interface_two_data.get_addresses()) + + # tunnel node logic + key = link_data.key + if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL): + net_one.setkey(key) + if addresses: + net_one.addrconfig(addresses) + if key and nodeutils.is_node(net_two, NodeTypes.TUNNEL): + net_two.setkey(key) + if addresses: + net_two.addrconfig(addresses) + + if not net_one and not net_two and (not node_one or not node_two): + addresses = [] + if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL): + addresses.extend(interface_one_data.get_addresses()) + node_one.adoptnetif(tunnel, link_data.interface1_id, link_data.interface1_mac, addresses) + link_config(node_one, tunnel, link_data) + elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): + addresses.extend(interface_two_data.get_addresses()) + node_two.adoptnetif(tunnel, link_data.interface2_id, link_data.interface2_mac, addresses) + link_config(node_two, tunnel, link_data) + finally: + if node_one: + node_one.lock.release() + if node_two: + node_two.lock.release() + + def link_delete(self, link_data): + # interface data + interface_one_data, interface_two_data = get_interfaces(link_data) + + # get node objects identified by link data + node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + + if node_one: + node_one.lock.acquire() + if node_two: + node_two.lock.acquire() + + try: + # wireless link + if link_data.link_type == LinkTypes.WIRELESS.value: + objects = [node_one, node_two, net_one, net_two] + self._link_wireless(objects, connect=False) + # wired link + else: + if all([node_one, node_two]): + # TODO: fix this for the case where ifindex[1,2] are not specified + # a wired unlink event, delete the connecting bridge + interface_one = node_one.netif(interface_one_data.id) + interface_two = node_two.netif(interface_two_data.id) + + # get interfaces from common network, if no network node + # otherwise get interfaces between a node and network + if not interface_one and not interface_two: + common_networks = node_one.commonnets(node_two) + for network, common_interface_one, common_interface_two in common_networks: + if (net_one and network == net_one) or not net_one: + interface_one = common_interface_one + interface_two = common_interface_two + break + + if all([interface_one, interface_two]) and any([interface_one.net, interface_two.net]): + if interface_one.net != interface_two.net and all([interface_one.up, interface_two.up]): + raise ValueError("no common network found") + net_one = interface_one.net + interface_one.detachnet() + interface_two.detachnet() + if net_one.numnetif() == 0: + self.delete_object(net_one.objid) + node_one.delnetif(interface_one_data.id) + node_two.delnetif(interface_two_data.id) + finally: + if node_one: + node_one.lock.release() + if node_two: + node_two.lock.release() + + def link_update(self, link_data): + # interface data + interface_one_data, interface_two_data = get_interfaces(link_data) + + # get node objects identified by link data + node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + + if node_one: + node_one.lock.acquire() + if node_two: + node_two.lock.acquire() + + try: + # wireless link + if link_data.link_type == LinkTypes.WIRELESS.value: + raise ValueError("cannot update wireless link") + else: + if not node_one and not node_two: + if net_one and net_two: + # modify link between nets + interface = net_one.getlinknetif(net_two) + upstream = False + + if not interface: + upstream = True + interface = net_two.getlinknetif(net_one) + + if not interface: + raise ValueError("modify unknown link between nets") + + if upstream: + interface.swapparams("_params_up") + link_config(net_one, interface, link_data, devname=interface.name) + interface.swapparams("_params_up") + else: + link_config(net_one, interface, link_data) + + if not link_data.unidirectional: + if upstream: + link_config(net_two, interface, link_data) + else: + interface.swapparams("_params_up") + link_config(net_two, interface, link_data, devname=interface.name) + interface.swapparams("_params_up") + else: + raise ValueError("modify link for unknown nodes") + elif not node_one: + # node1 = layer 2node, node2 = layer3 node + interface = node_two.netif(interface_two_data.id, net_one) + link_config(net_one, interface, link_data) + elif not node_two: + # node2 = layer 2node, node1 = layer3 node + interface = node_one.netif(interface_one_data.id, net_one) + link_config(net_one, interface, link_data) + else: + common_networks = node_one.commonnets(node_two) + for net_one, interface_one, interface_two in common_networks: + if interface_one_data.id and interface_one_data.id != node_one.getifindex(interface_one): + continue + + link_config(net_one, interface_one, link_data, interface_two=interface_two) + if not link_data.unidirectional: + link_config(net_one, interface_two, link_data, interface_two=interface_one) + else: + raise ValueError("no common network found") + finally: + if node_one: + node_one.lock.release() + if node_two: + node_two.lock.release() + + def node_add(self, node_data): + """ + Add a node to the session, based on the provided node data. + + :param core.data.NodeData node_data: data to create node with + :return: nothing + """ + + # retrieve node class for given node type + try: + node_type = NodeTypes(node_data.node_type) + node_class = nodeutils.get_node_class(node_type) + except KeyError: + logger.error("invalid node type to create: %s", node_data.node_type) + return None + + # set node start based on current session state, override and check when rj45 + start = self.state > EventTypes.DEFINITION_STATE.value + enable_rj45 = getattr(self.options, "enablerj45", "0") == "1" + if node_type == NodeTypes.RJ45 and not enable_rj45: + start = False + + # determine node id + node_id = node_data.id + if not node_id: + node_id = self.node_id_gen.next() + + # generate name if not provided + name = node_data.name + if not name: + name = "%s%s" % (node_class.__name__, node_id) + + # create node + node = self.add_object(cls=node_class, objid=node_id, name=name, start=start) + + # set node attributes + node.type = node_data.model or "router" + node.icon = node_data.icon + node.canvas = node_data.canvas + node.opaque = node_data.opaque + + # set node position and broadcast it + self.node_set_position(node, node_data) + + # add services to default and physical nodes only + services = node_data.services + if node_type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: + logger.info("setting model (%s) with services (%s)", node.type, services) + self.services.addservicestonode(node, node.type, services) + + # boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes + is_boot_node = isinstance(node, PyCoreNode) and not nodeutils.is_node(node, NodeTypes.RJ45) + if self.state == EventTypes.RUNTIME_STATE.value and is_boot_node: + self.write_objects() + self.add_remove_control_interface(node=node, remove=False) + + # TODO: common method to both Physical and LxcNodes, but not the common PyCoreNode + node.boot() + + # return node id, in case it was generated + return node_id + + def node_update(self, node_data): + try: + # get node to update + node = self.get_object(node_data.id) + + # set node position and broadcast it + self.node_set_position(node, node_data) + + # update attributes + node.canvas = node_data.canvas + node.icon = node_data.icon + except KeyError: + logger.error("failure to update node that does not exist: %s", node_data.id) + + def node_delete(self, node_id): + # delete node and check for session shutdown if a node was removed + result = self.custom_delete_object(node_id) + if result: + self.check_shutdown() + return result + + def node_set_position(self, node, node_data): + # extract location values + x = node_data.x_position + y = node_data.y_position + lat = node_data.latitude + lon = node_data.longitude + alt = node_data.altitude + + # check if we need to generate position from lat/lon/alt + has_empty_position = all(i is None for i in [x, y]) + has_lat_lon_alt = all(i is not None for i in [lat, lon, alt]) + using_lat_lon_alt = has_empty_position and has_lat_lon_alt + if using_lat_lon_alt: + x, y, _ = self.location.getxyz(lat, lon, alt) + + # set position and broadcast + node.setposition(x, y, None) + + # broadcast updated location when using lat/lon/alt + if using_lat_lon_alt: + self.broadcast_node_location(node) + + def broadcast_node_location(self, node): + """ + Broadcast node location to all listeners. + + :param core.netns.nodes.PyCoreObj node: node to broadcast location for + :return: nothing + """ + node_data = NodeData( + message_type=0, + id=node.objid, + x_position=node.position.x, + y_position=node.position.y + ) + self.broadcast_node(node_data) + + def shutdown(self): + self.set_state(state=EventTypes.DATACOLLECT_STATE.value, send_event=True) + self.set_state(state=EventTypes.SHUTDOWN_STATE.value, send_event=True) + super(FutureSession, self).shutdown() + + def custom_delete_object(self, object_id): + """ + Remove an emulation object. + + :param int object_id: object id to remove + :return: True if object deleted, False otherwise + """ + result = False + with self._objects_lock: + if object_id in self.objects: + obj = self.objects.pop(object_id) + obj.shutdown() + result = True + return result + + def is_active(self): + return self.state in {EventTypes.RUNTIME_STATE.value, EventTypes.DATACOLLECT_STATE.value} + + def open_xml(self, file_name, start=False): + """ + Import a session from the EmulationScript XML format. + + :param str file_name: xml file to load session from + :param bool start: instantiate session if true, false otherwise + :return: nothing + """ + # clear out existing session + self.clear() + + # set default node class when one is not provided + node_class = nodeutils.get_node_class(NodeTypes.DEFAULT) + options = {"start": start, "nodecls": node_class} + core_document_parser(self, file_name, options) + if start: + self.name = os.path.basename(file_name) + self.file_name = file_name + self.instantiate() + + def save_xml(self, file_name, version): + """ + Export a session to the EmulationScript XML format. + + :param str file_name: file name to write session xml to + :param str version: xml version type + :return: nothing + """ + doc = core_document_writer(self, version) + doc.writexml(file_name) + + def hook_add(self, state, file_name, source_name, data): + """ + Store a hook from a received file message. + + :param int state: when to run hook + :param str file_name: file name for hook + :param str source_name: source name + :param data: hook data + :return: nothing + """ + # hack to conform with old logic until updated + state = ":%s" % state + self.set_hook(state, file_name, source_name, data) + + def node_service_file(self, node_id, service_name, file_name, source_name, data): + # hack to conform with old logic until updated + service_name = ":%s" % service_name + self.services.setservicefile(node_id, service_name, file_name, source_name, data) + + def node_file(self, node_id, source_name, file_name, data): + node = self.get_object(node_id) + + if source_name is not None: + node.addfile(source_name, file_name) + elif data is not None: + node.nodefile(file_name, data) + + def clear(self): + self.delete_objects() + self.del_hooks() + self.broker.reset() + + def start_events(self): + self.event_loop.run() + + def services_event(self, event_data): + self.services.handleevent(event_data) + + def mobility_event(self, event_data): + self.mobility.handleevent(event_data) + def create_node(self, cls, name=None, model=None): - object_id = self.object_id_gen.next() + object_id = self.node_id_gen.next() if not name: name = "%s%s" % (cls.__name__, object_id) @@ -103,7 +729,7 @@ class CoreEmu(object): self.sessions = {} # load default services - services.load() + core.services.load() def create_session(self): """ diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py new file mode 100644 index 00000000..f5b0c088 --- /dev/null +++ b/daemon/core/future/futurehandler.py @@ -0,0 +1,1127 @@ +""" +socket server request handlers leveraged by core servers. +""" + +import Queue +import SocketServer +import os +import shlex +import shutil +import sys +import threading +import time + +from core import logger +from core.api import coreapi +from core.coreserver import CoreServer +from core.data import ConfigData, LinkData +from core.data import EventData +from core.data import NodeData +from core.enumerations import ConfigTlvs +from core.enumerations import EventTlvs +from core.enumerations import EventTypes +from core.enumerations import ExceptionTlvs +from core.enumerations import ExecuteTlvs +from core.enumerations import FileTlvs +from core.enumerations import LinkTlvs +from core.enumerations import MessageFlags +from core.enumerations import MessageTypes +from core.enumerations import NodeTlvs +from core.enumerations import NodeTypes +from core.enumerations import RegisterTlvs +from core.enumerations import SessionTlvs +from core.misc import nodeutils +from core.misc import structutils +from core.misc import utils + + +class FutureHandler(SocketServer.BaseRequestHandler): + """ + The SocketServer class uses the RequestHandler class for servicing requests. + """ + + def __init__(self, request, client_address, server): + """ + Create a CoreRequestHandler instance. + + :param request: request object + :param str client_address: client address + :param CoreServer server: core server instance + :return: + """ + self.done = False + self.message_handlers = { + MessageTypes.NODE.value: self.handle_node_message, + MessageTypes.LINK.value: self.handle_link_message, + MessageTypes.EXECUTE.value: self.handle_execute_message, + MessageTypes.REGISTER.value: self.handle_register_message, + MessageTypes.CONFIG.value: self.handle_config_message, + MessageTypes.FILE.value: self.handle_file_message, + MessageTypes.INTERFACE.value: self.handle_interface_message, + MessageTypes.EVENT.value: self.handle_event_message, + MessageTypes.SESSION.value: self.handle_session_message, + } + self.message_queue = Queue.Queue() + self.node_status_request = {} + self._shutdown_lock = threading.Lock() + + self.handler_threads = [] + num_threads = int(server.config["numthreads"]) + if num_threads < 1: + raise ValueError("invalid number of threads: %s" % num_threads) + + logger.info("launching core server handler threads: %s", num_threads) + for _ in xrange(num_threads): + thread = threading.Thread(target=self.handler_thread) + self.handler_threads.append(thread) + thread.start() + + self.master = False + self.session = None + + utils.close_onexec(request.fileno()) + SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) + + def setup(self): + """ + Client has connected, set up a new connection. + + :return: nothing + """ + logger.info("new TCP connection: %s", self.client_address) + + def finish(self): + """ + Client has disconnected, end this request handler and disconnect + from the session. Shutdown sessions that are not running. + + :return: nothing + """ + logger.info("finishing request handler") + self.done = True + + logger.info("remaining message queue size: %s", self.message_queue.qsize()) + # seconds + timeout = 10.0 + logger.info("client disconnected: notifying threads") + for thread in self.handler_threads: + logger.info("waiting for thread: %s", thread.getName()) + thread.join(timeout) + if thread.isAlive(): + logger.warn("joining %s failed: still alive after %s sec", thread.getName(), timeout) + + logger.info("connection closed: %s", self.client_address) + if self.session: + self.remove_session_handlers() + + # remove client from session broker and shutdown if there are no clients + self.session.broker.session_clients.remove(self) + if not self.session.broker.session_clients: + logger.info("no session clients left, initiating shutdown") + self.session.shutdown() + + return SocketServer.BaseRequestHandler.finish(self) + + def handle_broadcast_event(self, event_data): + """ + Callback to handle an event broadcast out from a session. + + :param core.data.EventData event_data: event data to handle + :return: nothing + """ + logger.info("handling broadcast event: %s", event_data) + + tlv_data = structutils.pack_values(coreapi.CoreEventTlv, [ + (EventTlvs.NODE, event_data.node), + (EventTlvs.TYPE, event_data.event_type), + (EventTlvs.NAME, event_data.name), + (EventTlvs.DATA, event_data.data), + (EventTlvs.TIME, event_data.time), + (EventTlvs.TIME, event_data.session) + ]) + message = coreapi.CoreEventMessage.pack(0, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending event message") + + def handle_broadcast_file(self, file_data): + """ + Callback to handle a file broadcast out from a session. + + :param core.data.FileData file_data: file data to handle + :return: nothing + """ + logger.info("handling broadcast file: %s", file_data) + + tlv_data = structutils.pack_values(coreapi.CoreFileTlv, [ + (FileTlvs.NODE, file_data.node), + (FileTlvs.NAME, file_data.name), + (FileTlvs.MODE, file_data.mode), + (FileTlvs.NUMBER, file_data.number), + (FileTlvs.TYPE, file_data.type), + (FileTlvs.SOURCE_NAME, file_data.source), + (FileTlvs.SESSION, file_data.session), + (FileTlvs.DATA, file_data.data), + (FileTlvs.COMPRESSED_DATA, file_data.compressed_data), + ]) + message = coreapi.CoreFileMessage.pack(file_data.message_type, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending file message") + + def handle_broadcast_config(self, config_data): + """ + Callback to handle a config broadcast out from a session. + + :param core.data.ConfigData config_data: config data to handle + :return: nothing + """ + logger.info("handling broadcast config: %s", config_data) + + tlv_data = structutils.pack_values(coreapi.CoreConfigTlv, [ + (ConfigTlvs.NODE, config_data.node), + (ConfigTlvs.OBJECT, config_data.object), + (ConfigTlvs.TYPE, config_data.type), + (ConfigTlvs.DATA_TYPES, config_data.data_types), + (ConfigTlvs.VALUES, config_data.data_values), + (ConfigTlvs.CAPTIONS, config_data.captions), + (ConfigTlvs.BITMAP, config_data.bitmap), + (ConfigTlvs.POSSIBLE_VALUES, config_data.possible_values), + (ConfigTlvs.GROUPS, config_data.groups), + (ConfigTlvs.SESSION, config_data.session), + (ConfigTlvs.INTERFACE_NUMBER, config_data.interface_number), + (ConfigTlvs.NETWORK_ID, config_data.network_id), + (ConfigTlvs.OPAQUE, config_data.opaque), + ]) + message = coreapi.CoreConfMessage.pack(config_data.message_type, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending config message") + + def handle_broadcast_exception(self, exception_data): + """ + Callback to handle an exception broadcast out from a session. + + :param core.data.ExceptionData exception_data: exception data to handle + :return: nothing + """ + logger.info("handling broadcast exception: %s", exception_data) + tlv_data = structutils.pack_values(coreapi.CoreExceptionTlv, [ + (ExceptionTlvs.NODE, exception_data.node), + (ExceptionTlvs.SESSION, exception_data.session), + (ExceptionTlvs.LEVEL, exception_data.level), + (ExceptionTlvs.SOURCE, exception_data.source), + (ExceptionTlvs.DATE, exception_data.date), + (ExceptionTlvs.TEXT, exception_data.text) + ]) + message = coreapi.CoreExceptionMessage.pack(0, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending exception message") + + def handle_broadcast_node(self, node_data): + """ + Callback to handle an node broadcast out from a session. + + :param core.data.NodeData node_data: node data to handle + :return: nothing + """ + logger.info("handling broadcast node: %s", node_data) + + tlv_data = structutils.pack_values(coreapi.CoreNodeTlv, [ + (NodeTlvs.NUMBER, node_data.id), + (NodeTlvs.TYPE, node_data.node_type), + (NodeTlvs.NAME, node_data.name), + (NodeTlvs.IP_ADDRESS, node_data.ip_address), + (NodeTlvs.MAC_ADDRESS, node_data.mac_address), + (NodeTlvs.IP6_ADDRESS, node_data.ip6_address), + (NodeTlvs.MODEL, node_data.model), + (NodeTlvs.EMULATION_ID, node_data.emulation_id), + (NodeTlvs.EMULATION_SERVER, node_data.emulation_server), + (NodeTlvs.SESSION, node_data.session), + (NodeTlvs.X_POSITION, node_data.x_position), + (NodeTlvs.Y_POSITION, node_data.y_position), + (NodeTlvs.CANVAS, node_data.canvas), + (NodeTlvs.NETWORK_ID, node_data.network_id), + (NodeTlvs.SERVICES, node_data.services), + (NodeTlvs.LATITUDE, node_data.latitude), + (NodeTlvs.LONGITUDE, node_data.longitude), + (NodeTlvs.ALTITUDE, node_data.altitude), + (NodeTlvs.ICON, node_data.icon), + (NodeTlvs.OPAQUE, node_data.opaque) + ]) + message = coreapi.CoreNodeMessage.pack(node_data.message_type, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending node message") + + def handle_broadcast_link(self, link_data): + """ + Callback to handle an link broadcast out from a session. + + :param core.data.LinkData link_data: link data to handle + :return: nothing + """ + logger.info("handling broadcast link: %s", link_data) + + tlv_data = structutils.pack_values(coreapi.CoreLinkTlv, [ + (LinkTlvs.N1_NUMBER, link_data.node1_id), + (LinkTlvs.N2_NUMBER, link_data.node2_id), + (LinkTlvs.DELAY, link_data.delay), + (LinkTlvs.BANDWIDTH, link_data.bandwidth), + (LinkTlvs.PER, link_data.per), + (LinkTlvs.DUP, link_data.dup), + (LinkTlvs.JITTER, link_data.jitter), + (LinkTlvs.MER, link_data.mer), + (LinkTlvs.BURST, link_data.burst), + (LinkTlvs.SESSION, link_data.session), + (LinkTlvs.MBURST, link_data.mburst), + (LinkTlvs.TYPE, link_data.link_type), + (LinkTlvs.GUI_ATTRIBUTES, link_data.gui_attributes), + (LinkTlvs.UNIDIRECTIONAL, link_data.unidirectional), + (LinkTlvs.EMULATION_ID, link_data.emulation_id), + (LinkTlvs.NETWORK_ID, link_data.network_id), + (LinkTlvs.KEY, link_data.key), + (LinkTlvs.INTERFACE1_NUMBER, link_data.interface1_id), + (LinkTlvs.INTERFACE1_NAME, link_data.interface1_name), + (LinkTlvs.INTERFACE1_IP4, link_data.interface1_ip4), + (LinkTlvs.INTERFACE1_IP4_MASK, link_data.interface1_ip4_mask), + (LinkTlvs.INTERFACE1_MAC, link_data.interface1_mac), + (LinkTlvs.INTERFACE1_IP6, link_data.interface1_ip6), + (LinkTlvs.INTERFACE1_IP6_MASK, link_data.interface1_ip6_mask), + (LinkTlvs.INTERFACE2_NUMBER, link_data.interface2_id), + (LinkTlvs.INTERFACE2_NAME, link_data.interface2_name), + (LinkTlvs.INTERFACE2_IP4, link_data.interface2_ip4), + (LinkTlvs.INTERFACE2_IP4_MASK, link_data.interface2_ip4_mask), + (LinkTlvs.INTERFACE2_MAC, link_data.interface2_mac), + (LinkTlvs.INTERFACE2_IP6, link_data.interface2_ip6), + (LinkTlvs.INTERFACE2_IP6_MASK, link_data.interface2_ip6_mask), + (LinkTlvs.OPAQUE, link_data.opaque) + ]) + + message = coreapi.CoreLinkMessage.pack(link_data.message_type, tlv_data) + + try: + self.sendall(message) + except IOError: + logger.exception("error sending Event Message") + + def register(self): + """ + Return a Register Message + + :return: register message data + """ + logger.info("GUI has connected to session %d at %s", self.session.session_id, time.ctime()) + + tlv_data = "" + tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, "core-daemon") + tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.EMULATION_SERVER.value, "core-daemon") + + # get config objects for session + for name in self.session.config_objects: + config_type, callback = self.session.config_objects[name] + # type must be in coreapi.reg_tlvs + tlv_data += coreapi.CoreRegisterTlv.pack(config_type, name) + + return coreapi.CoreRegMessage.pack(MessageFlags.ADD.value, tlv_data) + + def sendall(self, data): + """ + Send raw data to the other end of this TCP connection + using socket"s sendall(). + + :param data: data to send over request socket + :return: data sent + """ + return self.request.sendall(data) + + def receive_message(self): + """ + Receive data and return a CORE API message object. + + :return: received message + :rtype: coreapi.CoreMessage + """ + try: + header = self.request.recv(coreapi.CoreMessage.header_len) + except IOError as e: + raise IOError("error receiving header (%s)" % e) + + if len(header) != coreapi.CoreMessage.header_len: + if len(header) == 0: + raise EOFError("client disconnected") + else: + raise IOError("invalid message header size") + + message_type, message_flags, message_len = coreapi.CoreMessage.unpack_header(header) + if message_len == 0: + logger.warn("received message with no data") + + data = "" + while len(data) < message_len: + data += self.request.recv(message_len - len(data)) + if len(data) > message_len: + error_message = "received message length does not match received data (%s != %s)" % ( + len(data), message_len) + logger.error(error_message) + raise IOError(error_message) + + try: + message_class = coreapi.CLASS_MAP[message_type] + message = message_class(message_flags, header, data) + except KeyError: + message = coreapi.CoreMessage(message_flags, header, data) + message.message_type = message_type + logger.exception("unimplemented core message type: %s", message.type_str()) + + return message + + def queue_message(self, message): + """ + Queue an API message for later processing. + + :param message: message to queue + :return: nothing + """ + logger.info("queueing msg (queuedtimes = %s): type %s", + message.queuedtimes, MessageTypes(message.message_type)) + self.message_queue.put(message) + + def handler_thread(self): + """ + CORE API message handling loop that is spawned for each server + thread; get CORE API messages from the incoming message queue, + and call handlemsg() for processing. + + :return: nothing + """ + while not self.done: + message = self.message_queue.get() + self.handle_message(message) + + def handle_message(self, message): + """ + Handle an incoming message; dispatch based on message type, + optionally sending replies. + + :param message: message to handle + :return: nothing + """ + if self.session and self.session.broker.handle_message(message): + logger.info("message not being handled locally") + return + + logger.info("%s handling message:\n%s", threading.currentThread().getName(), message) + + if message.message_type not in self.message_handlers: + logger.warn("no handler for message type: %s", message.type_str()) + return + + message_handler = self.message_handlers[message.message_type] + + try: + # TODO: this needs to be removed, make use of the broadcast message methods + replies = message_handler(message) + self.dispatch_replies(replies, message) + except: + logger.exception("%s: exception while handling message: %s", + threading.currentThread().getName(), message) + + def dispatch_replies(self, replies, message): + """ + Dispatch replies by CORE to message msg previously received from the client. + + :param list replies: reply messages to dispatch + :param message: message for replies + :return: nothing + """ + logger.info("dispatching replies") + for reply in replies: + message_type, message_flags, message_length = coreapi.CoreMessage.unpack_header(reply) + try: + reply_message = coreapi.CLASS_MAP[message_type]( + message_flags, + reply[:coreapi.CoreMessage.header_len], + reply[coreapi.CoreMessage.header_len:] + ) + except KeyError: + # multiple TLVs of same type cause KeyError exception + reply_message = "CoreMessage (type %d flags %d length %d)" % ( + message_type, message_flags, message_length) + + logger.info("dispatch reply:\n%s", reply_message) + + try: + self.sendall(reply) + except IOError: + logger.exception("error dispatching reply") + + def handle(self): + """ + Handle a new connection request from a client. Dispatch to the + recvmsg() method for receiving data into CORE API messages, and + add them to an incoming message queue. + + :return: nothing + """ + # use port as session id + port = self.request.getpeername()[1] + + logger.info("creating new session for client: %s", port) + self.session = self.server.create_session(session_id=port) + + # TODO: hack to associate this handler with this sessions broker for broadcasting + # TODO: broker needs to be pulled out of session to the server/handler level + if self.master: + logger.info("session set to master") + self.session.master = True + self.session.broker.session_clients.append(self) + + # add handlers for various data + logger.info("adding session broadcast handlers") + self.add_session_handlers() + + # set initial session state + self.session.set_state(state=EventTypes.DEFINITION_STATE.value) + + while True: + try: + message = self.receive_message() + except EOFError: + logger.info("client disconnected") + break + except IOError: + logger.exception("error receiving message") + break + + message.queuedtimes = 0 + self.queue_message(message) + + # delay is required for brief connections, allow session joining + if message.message_type == MessageTypes.SESSION.value: + time.sleep(0.125) + + # broadcast node/link messages to other connected clients + if message.message_type not in [MessageTypes.NODE.value, MessageTypes.LINK.value]: + continue + + for client in self.session.broker.session_clients: + if client == self: + continue + + logger.info("BROADCAST TO OTHER CLIENT: %s", client) + client.sendall(message.raw_message) + + def add_session_handlers(self): + logger.info("adding session broadcast handlers") + self.session.event_handlers.append(self.handle_broadcast_event) + self.session.exception_handlers.append(self.handle_broadcast_exception) + self.session.node_handlers.append(self.handle_broadcast_node) + self.session.link_handlers.append(self.handle_broadcast_link) + self.session.file_handlers.append(self.handle_broadcast_file) + self.session.config_handlers.append(self.handle_broadcast_config) + + def remove_session_handlers(self): + logger.info("removing session broadcast handlers") + self.session.event_handlers.remove(self.handle_broadcast_event) + self.session.exception_handlers.remove(self.handle_broadcast_exception) + self.session.node_handlers.remove(self.handle_broadcast_node) + self.session.link_handlers.remove(self.handle_broadcast_link) + self.session.file_handlers.remove(self.handle_broadcast_file) + self.session.config_handlers.remove(self.handle_broadcast_config) + + def handle_node_message(self, message): + """ + Node Message handler + + :param coreapi.CoreNodeMessage message: node message + :return: replies to node message + """ + replies = [] + if message.flags & MessageFlags.ADD.value and message.flags & MessageFlags.DELETE.value: + logger.warn("ignoring invalid message: add and delete flag both set") + return () + + # create node data from message data + node_data = NodeData( + id=message.get_tlv(NodeTlvs.NUMBER.value), + x_position=message.get_tlv(NodeTlvs.X_POSITION.value), + y_position=message.get_tlv(NodeTlvs.Y_POSITION.value), + canvas=message.get_tlv(NodeTlvs.CANVAS.value), + icon=message.get_tlv(NodeTlvs.ICON.value), + latitude=message.get_tlv(NodeTlvs.LATITUDE.value), + longitude=message.get_tlv(NodeTlvs.LONGITUDE.value), + altitude=message.get_tlv(NodeTlvs.ALTITUDE.value), + node_type=message.get_tlv(NodeTlvs.TYPE.value), + name=message.get_tlv(NodeTlvs.NAME.value), + model=message.get_tlv(NodeTlvs.MODEL.value), + opaque=message.get_tlv(NodeTlvs.OPAQUE.value), + services=message.get_tlv(NodeTlvs.SERVICES.value), + ) + + if message.flags & MessageFlags.ADD.value: + node_id = self.session.node_add(node_data) + if node_id: + if message.flags & MessageFlags.STRING.value: + self.node_status_request[node_id] = True + + if self.session.state == EventTypes.RUNTIME_STATE.value: + self.send_node_emulation_id(node_id) + elif message.flags & MessageFlags.DELETE.value: + with self._shutdown_lock: + result = self.session.node_delete(node_data.id) + + # if we deleted a node broadcast out its removal + if result and message.flags & MessageFlags.STRING.value: + tlvdata = "" + tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_data.id) + flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value + replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata)) + # node update + else: + self.session.node_update(node_data) + + return replies + + def handle_link_message(self, message): + """ + Link Message handler + + :param coreapi.CoreLinkMessage message: link message to handle + :return: link message replies + """ + link_data = LinkData( + session=message.get_tlv(LinkTlvs.SESSION.value), + link_type=message.get_tlv(LinkTlvs.TYPE.value), + node1_id=message.get_tlv(LinkTlvs.N1_NUMBER.value), + node2_id=message.get_tlv(LinkTlvs.N2_NUMBER.value), + delay=message.get_tlv(LinkTlvs.DELAY.value), + bandwidth=message.get_tlv(LinkTlvs.BANDWIDTH.value), + per=message.get_tlv(LinkTlvs.PER.value), + dup=message.get_tlv(LinkTlvs.DUP.value), + jitter=message.get_tlv(LinkTlvs.JITTER.value), + mer=message.get_tlv(LinkTlvs.MER.value), + burst=message.get_tlv(LinkTlvs.BURST.value), + mburst=message.get_tlv(LinkTlvs.MBURST.value), + gui_attributes=message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value), + unidirectional=message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value), + emulation_id=message.get_tlv(LinkTlvs.EMULATION_ID.value), + network_id=message.get_tlv(LinkTlvs.NETWORK_ID.value), + key=message.get_tlv(LinkTlvs.KEY.value), + opaque=message.get_tlv(LinkTlvs.OPAQUE.value), + interface1_id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value), + interface1_name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value), + interface1_ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value), + interface1_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value), + interface1_mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value), + interface1_ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value), + interface1_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value), + interface2_id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value), + interface2_name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value), + interface2_ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value), + interface2_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value), + interface2_mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value), + interface2_ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value), + interface2_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP6_MASK.value), + ) + + if message.flags & MessageFlags.ADD.value: + self.session.link_add(link_data) + elif message.flags & MessageFlags.DELETE.value: + self.session.link_delete(link_data) + else: + self.session.link_update(link_data) + + return () + + def handle_execute_message(self, message): + """ + Execute Message handler + + :param coreapi.CoreExecMessage message: execute message to handle + :return: reply messages + """ + node_num = message.get_tlv(ExecuteTlvs.NODE.value) + execute_num = message.get_tlv(ExecuteTlvs.NUMBER.value) + execute_time = message.get_tlv(ExecuteTlvs.TIME.value) + command = message.get_tlv(ExecuteTlvs.COMMAND.value) + + # local flag indicates command executed locally, not on a node + if node_num is None and not message.flags & MessageFlags.LOCAL.value: + raise ValueError("Execute Message is missing node number.") + + if execute_num is None: + raise ValueError("Execute Message is missing execution number.") + + if execute_time is not None: + self.session.add_event(execute_time, node=node_num, name=None, data=command) + return () + + try: + node = self.session.get_object(node_num) + + # build common TLV items for reply + tlv_data = "" + if node_num is not None: + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.NODE.value, node_num) + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.NUMBER.value, execute_num) + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.COMMAND.value, command) + + if message.flags & MessageFlags.TTY.value: + if node_num is None: + raise NotImplementedError + # echo back exec message with cmd for spawning interactive terminal + if command == "bash": + command = "/bin/bash" + res = node.termcmdstring(command) + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) + reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data) + return reply, + else: + logger.info("execute message with cmd=%s", command) + # execute command and send a response + if message.flags & MessageFlags.STRING.value or message.flags & MessageFlags.TEXT.value: + # shlex.split() handles quotes within the string + if message.flags & MessageFlags.LOCAL.value: + status, res = utils.cmd_output(command) + else: + status, res = node.cmd_output(command) + logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res)) + if message.flags & MessageFlags.TEXT.value: + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) + if message.flags & MessageFlags.STRING.value: + tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.STATUS.value, status) + reply = coreapi.CoreExecMessage.pack(0, tlv_data) + return reply, + # execute the command with no response + else: + if message.flags & MessageFlags.LOCAL.value: + utils.mute_detach(command) + else: + node.cmd(command, wait=False) + except KeyError: + logger.exception("error getting object: %s", node_num) + # XXX wait and queue this message to try again later + # XXX maybe this should be done differently + if not message.flags & MessageFlags.LOCAL.value: + time.sleep(0.125) + self.queue_message(message) + + return () + + def handle_register_message(self, message): + """ + Register Message Handler + + :param coreapi.CoreRegMessage message: register message to handle + :return: reply messages + """ + replies = [] + + # execute a Python script or XML file + execute_server = message.get_tlv(RegisterTlvs.EXECUTE_SERVER.value) + if execute_server: + try: + logger.info("executing: %s", execute_server) + if message.flags & MessageFlags.STRING.value: + old_session_ids = set(self.server.get_session_ids()) + sys.argv = shlex.split(execute_server) + file_name = sys.argv[0] + + if os.path.splitext(file_name)[1].lower() == ".xml": + session = self.server.create_session() + try: + session.open_xml(file_name, start=True) + except: + session.shutdown() + self.server.remove_session(session) + raise + else: + thread = threading.Thread( + target=execfile, + args=(file_name, {"__file__": file_name, "server": self.server}) + ) + thread.daemon = True + thread.start() + # allow time for session creation + time.sleep(0.25) + + if message.flags & MessageFlags.STRING.value: + new_session_ids = set(self.server.get_session_ids()) + new_sid = new_session_ids.difference(old_session_ids) + try: + sid = new_sid.pop() + logger.info("executed: %s as session %d", execute_server, sid) + except KeyError: + logger.info("executed %s with unknown session ID", execute_server) + return replies + + logger.info("checking session %d for RUNTIME state" % sid) + session = self.server.get_session(session_id=sid) + retries = 10 + # wait for session to enter RUNTIME state, to prevent GUI from + # connecting while nodes are still being instantiated + while session.state != EventTypes.RUNTIME_STATE.value: + logger.info("waiting for session %d to enter RUNTIME state" % sid) + time.sleep(1) + retries -= 1 + if retries <= 0: + logger.info("session %d did not enter RUNTIME state" % sid) + return replies + + tlv_data = coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, execute_server) + tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.SESSION.value, "%s" % sid) + message = coreapi.CoreRegMessage.pack(0, tlv_data) + replies.append(message) + except Exception as e: + logger.exception("error executing: %s", execute_server) + tlv_data = coreapi.CoreExceptionTlv.pack(ExceptionTlvs.LEVEL.value, 2) + tlv_data += coreapi.CoreExceptionTlv.pack(ExceptionTlvs.TEXT.value, str(e)) + message = coreapi.CoreExceptionMessage.pack(0, tlv_data) + replies.append(message) + + return replies + + gui = message.get_tlv(RegisterTlvs.GUI.value) + if gui is None: + logger.info("ignoring Register message") + else: + # register capabilities with the GUI + self.master = True + + # TODO: need to replicate functionality? + # self.server.set_session_master(self) + # find the session containing this client and set the session to master + for session in self.server.sessions.itervalues(): + if self in session.broker.session_clients: + logger.info("setting session to master: %s", session.session_id) + session.master = True + break + + replies.append(self.register()) + replies.append(self.server.to_session_message()) + + return replies + + def handle_config_message(self, message): + """ + Configuration Message handler + + :param coreapi.CoreConfMessage message: configuration message to handle + :return: reply messages + """ + # convert config message to standard config data object + config_data = ConfigData( + node=message.get_tlv(ConfigTlvs.NODE.value), + object=message.get_tlv(ConfigTlvs.OBJECT.value), + type=message.get_tlv(ConfigTlvs.TYPE.value), + data_types=message.get_tlv(ConfigTlvs.DATA_TYPES.value), + data_values=message.get_tlv(ConfigTlvs.VALUES.value), + captions=message.get_tlv(ConfigTlvs.CAPTIONS.value), + bitmap=message.get_tlv(ConfigTlvs.BITMAP.value), + possible_values=message.get_tlv(ConfigTlvs.POSSIBLE_VALUES.value), + groups=message.get_tlv(ConfigTlvs.GROUPS.value), + session=message.get_tlv(ConfigTlvs.SESSION.value), + interface_number=message.get_tlv(ConfigTlvs.INTERFACE_NUMBER.value), + network_id=message.get_tlv(ConfigTlvs.NETWORK_ID.value), + opaque=message.get_tlv(ConfigTlvs.OPAQUE.value) + ) + logger.info("Configuration message for %s node %s", config_data.object, config_data.node) + + # dispatch to any registered callback for this object type + replies = self.session.config_object(config_data) + + for reply in replies: + self.handle_broadcast_config(reply) + + return [] + + def handle_file_message(self, message): + """ + File Message handler + + :param coreapi.CoreFileMessage message: file message to handle + :return: reply messages + """ + if message.flags & MessageFlags.ADD.value: + node_num = message.get_tlv(FileTlvs.NUMBER.value) + file_name = message.get_tlv(FileTlvs.NAME.value) + file_type = message.get_tlv(FileTlvs.TYPE.value) + source_name = message.get_tlv(FileTlvs.SOURCE_NAME.value) + data = message.get_tlv(FileTlvs.DATA.value) + compressed_data = message.get_tlv(FileTlvs.COMPRESSED_DATA.value) + + if compressed_data: + logger.warn("Compressed file data not implemented for File message.") + return () + + if source_name and data: + logger.warn("ignoring invalid File message: source and data TLVs are both present") + return () + + # some File Messages store custom files in services, + # prior to node creation + if file_type is not None: + if file_type.startswith("service:"): + _, service_name = file_type.split(':')[:2] + self.session.node_service_file(node_num, service_name, file_name, source_name, data) + return () + elif file_type.startswith("hook:"): + _, state = file_type.split(':')[:2] + if not state.isdigit(): + logger.error("error setting hook having state '%s'", state) + return () + state = int(state) + self.session.hook_add(state, file_name, source_name, data) + return () + + # writing a file to the host + if node_num is None: + if source_name is not None: + shutil.copy2(source_name, file_name) + else: + with open(file_name, "w") as open_file: + open_file.write(data) + return () + + self.session.node_add_file(node_num, source_name, file_name, data) + else: + raise NotImplementedError + + return () + + def handle_interface_message(self, message): + """ + Interface Message handler. + + :param message: interface message to handle + :return: reply messages + """ + logger.info("ignoring Interface message") + return () + + def handle_event_message(self, message): + """ + Event Message handler + + :param coreapi.CoreEventMessage message: event message to handle + :return: reply messages + """ + event_data = EventData( + node=message.get_tlv(EventTlvs.NODE.value), + event_type=message.get_tlv(EventTlvs.TYPE.value), + name=message.get_tlv(EventTlvs.NAME.value), + data=message.get_tlv(EventTlvs.DATA.value), + time=message.get_tlv(EventTlvs.TIME.value), + session=message.get_tlv(EventTlvs.SESSION.value) + ) + + event_type = event_data.event_type + if event_type is None: + raise NotImplementedError("Event message missing event type") + node_id = event_data.node + + logger.info("EVENT %d: %s at %s", event_type, EventTypes(event_type).name, time.ctime()) + if event_type <= EventTypes.SHUTDOWN_STATE.value: + if node_id is not None: + try: + node = self.session.get_object(node_id) + except KeyError: + raise KeyError("Event message for unknown node %d" % node_id) + + # configure mobility models for WLAN added during runtime + if event_type == EventTypes.INSTANTIATION_STATE.value and nodeutils.is_node(node, + NodeTypes.WIRELESS_LAN): + self.session.mobility.startup(node_ids=(node.objid,)) + return () + + logger.warn("dropping unhandled Event message with node number") + return () + self.session.set_state(state=event_type) + + if event_type == EventTypes.DEFINITION_STATE.value: + # clear all session objects in order to receive new definitions + self.session.clear() + elif event_type == EventTypes.INSTANTIATION_STATE.value: + if len(self.handler_threads) > 1: + # TODO: sync handler threads here before continuing + time.sleep(2.0) # XXX + # done receiving node/link configuration, ready to instantiate + self.session.instantiate() + + # after booting nodes attempt to send emulation id for nodes waiting on status + for obj in self.session.objects.itervalues(): + self.send_node_emulation_id(obj.objid) + elif event_type == EventTypes.RUNTIME_STATE.value: + if self.session.master: + logger.warn("Unexpected event message: RUNTIME state received at session master") + else: + # master event queue is started in session.checkruntime() + self.session.start_events() + elif event_type == EventTypes.DATACOLLECT_STATE.value: + self.session.data_collect() + elif event_type == EventTypes.SHUTDOWN_STATE.value: + if self.session.master: + logger.warn("Unexpected event message: SHUTDOWN state received at session master") + elif event_type in (EventTypes.START.value, EventTypes.STOP.value, + EventTypes.RESTART.value, + EventTypes.PAUSE.value, + EventTypes.RECONFIGURE.value): + handled = False + name = event_data.name + if name: + # TODO: register system for event message handlers, + # like confobjs + if name.startswith("service:"): + self.session.services_event(event_data) + handled = True + elif name.startswith("mobility:"): + self.session.mobility_event(event_data) + handled = True + if not handled: + logger.warn("Unhandled event message: event type %s (%s)", + event_type, coreapi.state_name(event_type)) + elif event_type == EventTypes.FILE_OPEN.value: + filename = event_data.name + self.session.open_xml(filename, start=False) + self.session.send_objects() + return () + elif event_type == EventTypes.FILE_SAVE.value: + filename = event_data.name + self.session.save_xml(filename, self.session.config["xmlfilever"]) + elif event_type == EventTypes.SCHEDULED.value: + etime = event_data.time + node = event_data.node + name = event_data.name + data = event_data.data + if etime is None: + logger.warn("Event message scheduled event missing start time") + return () + if message.flags & MessageFlags.ADD.value: + self.session.add_event(float(etime), node=node, name=name, data=data) + else: + raise NotImplementedError + else: + logger.warn("Unhandled event message: event type %d", event_type) + + return () + + def handle_session_message(self, message): + """ + Session Message handler + + :param coreapi.CoreSessionMessage message: session message to handle + :return: reply messages + """ + session_id_str = message.get_tlv(SessionTlvs.NUMBER.value) + session_ids = coreapi.str_to_list(session_id_str) + name_str = message.get_tlv(SessionTlvs.NAME.value) + names = coreapi.str_to_list(name_str) + file_str = message.get_tlv(SessionTlvs.FILE.value) + files = coreapi.str_to_list(file_str) + thumb = message.get_tlv(SessionTlvs.THUMB.value) + user = message.get_tlv(SessionTlvs.USER.value) + logger.info("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) + + if message.flags == 0: + for index, session_id in enumerate(session_ids): + session_id = int(session_id) + if session_id == 0: + session = self.session + else: + session = self.server.get_session(session_id=session_id) + + if session is None: + logger.info("session %s not found", session_id) + continue + + logger.info("request to modify to session %s", session.session_id) + if names is not None: + session.name = names[index] + + if files is not None: + session.file_name = files[index] + + if thumb: + session.set_thumbnail(thumb) + + if user: + session.set_user(user) + elif message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: + # status request flag: send list of sessions + return self.server.to_session_message(), + else: + # handle ADD or DEL flags + for session_id in session_ids: + session_id = int(session_id) + session = self.server.get_session(session_id=session_id) + + if session is None: + logger.info("session %s not found (flags=0x%x)", session_id, message.flags) + continue + + if message.flags & MessageFlags.ADD.value: + # connect to the first session that exists + logger.info("request to connect to session %s" % session_id) + + # remove client from session broker and shutdown if needed + self.session.broker.session_clients.remove(self) + if not self.session.broker.session_clients and not self.session.is_active(): + self.session.shutdown() + + # set session to join + self.session = session + + # add client to session broker and set master if needed + if self.master: + self.session.master = True + self.session.broker.session_clients.append(self) + + # add broadcast handlers + logger.info("adding session broadcast handlers") + self.add_session_handlers() + + if user: + self.session.set_user(user) + + if message.flags & MessageFlags.STRING.value: + self.session.send_objects() + elif message.flags & MessageFlags.DELETE.value: + # shut down the specified session(s) + logger.info("request to terminate session %s" % session_id) + session.shutdown() + else: + logger.warn("unhandled session flags for session %s", session_id) + + return () + + def send_node_emulation_id(self, node_id): + """ + Node emulation id to send. + + :param int node_id: node id to send + :return: nothing + """ + if node_id in self.node_status_request: + tlv_data = "" + tlv_data += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_id) + tlv_data += coreapi.CoreNodeTlv.pack(NodeTlvs.EMULATION_ID.value, node_id) + reply = coreapi.CoreNodeMessage.pack(MessageFlags.ADD.value | MessageFlags.LOCAL.value, tlv_data) + + try: + self.sendall(reply) + except IOError: + logger.exception("error sending node emulation id message: %s", node_id) + + del self.node_status_request[node_id] diff --git a/daemon/core/future/futureserver.py b/daemon/core/future/futureserver.py new file mode 100644 index 00000000..64db9002 --- /dev/null +++ b/daemon/core/future/futureserver.py @@ -0,0 +1,263 @@ +""" +Defines server classes and request handlers for TCP and UDP. +""" + +import SocketServer +import threading +import time + +from core import logger +from core.api import coreapi +from core.enumerations import EventTypes +from core.enumerations import SessionTlvs +from core.future.coreemu import FutureSession + + +class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): + """ + TCP server class, manages sessions and spawns request handlers for + incoming connections. + """ + daemon_threads = True + allow_reuse_address = True + servers = set() + + def __init__(self, server_address, handler_class, config=None): + """ + Server class initialization takes configuration data and calls + the SocketServer constructor + + :param tuple[str, int] server_address: server host and port to use + :param class handler_class: request handler + :param dict config: configuration setting + :return: + """ + self.config = config + self.sessions = {} + self.udpserver = None + self.udpthread = None + self._sessions_lock = threading.Lock() + FutureServer.add_server(self) + SocketServer.TCPServer.__init__(self, server_address, handler_class) + + @classmethod + def add_server(cls, server): + """ + Add a core server to the known servers set. + + :param CoreServer server: server to add + :return: nothing + """ + cls.servers.add(server) + + @classmethod + def remove_server(cls, server): + """ + Remove a core server from the known servers set. + + :param CoreServer server: server to remove + :return: nothing + """ + if server in cls.servers: + cls.servers.remove(server) + + def shutdown(self): + """ + Shutdown the server, all known sessions, and remove server from known servers set. + + :return: nothing + """ + # shutdown all known sessions + for session in self.sessions.values(): + session.shutdown() + + # remove server from server list + FutureServer.remove_server(self) + + def add_session(self, session): + """ + Add a session to our dictionary of sessions, ensuring a unique session number. + + :param core.session.Session session: session to add + :return: added session + :raise KeyError: when a session with the same id already exists + """ + with self._sessions_lock: + if session.session_id in self.sessions: + raise KeyError("non-unique session id %s for %s" % (session.session_id, session)) + self.sessions[session.session_id] = session + + return session + + def remove_session(self, session): + """ + Remove a session from our dictionary of sessions. + + :param core.session.Session session: session to remove + :return: removed session + :rtype: core.session.Session + """ + with self._sessions_lock: + if session.session_id not in self.sessions: + logger.info("session id %s not found (sessions=%s)", session.session_id, self.sessions.keys()) + else: + del self.sessions[session.session_id] + + return session + + def get_session_ids(self): + """ + Return a list of active session numbers. + + :return: known session ids + :rtype: list + """ + with self._sessions_lock: + session_ids = self.sessions.keys() + + return session_ids + + def create_session(self, session_id=None): + """ + Convenience method for creating sessions with the servers config. + + :param int session_id: session id for new session + :return: create session + :rtype: FutureSession + """ + + # create random id when necessary, seems to be 1 case wanted, based on legacy code + # creating a value so high, typical client side generation schemes hopefully wont collide + if not session_id: + session_id = next( + session_id for session_id in xrange(60000, 65000) + if session_id not in self.sessions + ) + + # create and add session to local manager + session = FutureSession(session_id, config=self.config) + self.add_session(session) + + # add shutdown handler to remove session from manager + session.shutdown_handlers.append(self.session_shutdown) + + return session + + def get_session(self, session_id=None): + """ + Create a new session or retrieve an existing one from our + dictionary of sessions. When the session_id=0 and the use_existing + flag is set, return on of the existing sessions. + + :param int session_id: session id of session to retrieve, defaults to returning random session + :return: session + :rtype: core.session.Session + """ + + with self._sessions_lock: + # return specified session or none + if session_id: + return self.sessions.get(session_id) + + # retrieving known session + session = None + + # find runtime session with highest node count + for known_session in filter(lambda x: x.state == EventTypes.RUNTIME_STATE.value, + self.sessions.itervalues()): + if not session or known_session.get_node_count() > session.get_node_count(): + session = known_session + + # return first known session otherwise + if not session: + for known_session in self.sessions.itervalues(): + session = known_session + break + + return session + + def session_shutdown(self, session): + """ + Handler method to be used as a callback when a session has shutdown. + + :param core.session.Session session: session shutting down + :return: nothing + """ + self.remove_session(session) + + def to_session_message(self, flags=0): + """ + Build CORE API Sessions message based on current session info. + + :param int flags: message flags + :return: session message + """ + id_list = [] + name_list = [] + file_list = [] + node_count_list = [] + date_list = [] + thumb_list = [] + num_sessions = 0 + + with self._sessions_lock: + for session_id in self.sessions: + session = self.sessions[session_id] + # debug: session.dumpsession() + num_sessions += 1 + id_list.append(str(session_id)) + + name = session.name + if not name: + name = "" + name_list.append(name) + + file = session.file_name + if not file: + file = "" + file_list.append(file) + + node_count_list.append(str(session.get_node_count())) + + date_list.append(time.ctime(session._state_time)) + + thumb = session.thumbnail + if not thumb: + thumb = "" + thumb_list.append(thumb) + + session_ids = "|".join(id_list) + names = "|".join(name_list) + files = "|".join(file_list) + node_counts = "|".join(node_count_list) + dates = "|".join(date_list) + thumbs = "|".join(thumb_list) + + if num_sessions > 0: + tlv_data = "" + if len(session_ids) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session_ids) + if len(names) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NAME.value, names) + if len(files) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.FILE.value, files) + if len(node_counts) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NODE_COUNT.value, node_counts) + if len(dates) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.DATE.value, dates) + if len(thumbs) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.THUMB.value, thumbs) + message = coreapi.CoreSessionMessage.pack(flags, tlv_data) + else: + message = None + + return message + + def dump_sessions(self): + """ + Log currently known session information. + """ + logger.info("sessions:") + with self._sessions_lock: + for session_id in self.sessions: + logger.info(session_id) diff --git a/daemon/scripts/core-future b/daemon/scripts/core-future new file mode 100644 index 00000000..6afbaa1e --- /dev/null +++ b/daemon/scripts/core-future @@ -0,0 +1,180 @@ +#!/usr/bin/env python +""" +core-daemon: the CORE daemon is a server process that receives CORE API +messages and instantiates emulated nodes and networks within the kernel. Various +message handlers are defined and some support for sending messages. +""" + +import ConfigParser +import atexit +import optparse +import signal +import sys +import time + +from core import constants +from core import coreserver +from core import enumerations +from core import logger +from core import services +from core.future.futurehandler import FutureHandler +from core.future.futureserver import FutureServer +from core.misc import nodeutils +from core.misc.utils import close_onexec +from core.service import ServiceManager + + +def banner(): + """ + Output the program banner printed to the terminal or log file. + + :return: nothing + """ + logger.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime()) + + +def cored(cfg=None): + """ + Start the CoreServer object and enter the server loop. + + :param dict cfg: core configuration + :return: nothing + """ + host = cfg["listenaddr"] + port = int(cfg["port"]) + if host == "" or host is None: + host = "localhost" + + try: + server = FutureServer((host, port), FutureHandler, cfg) + except: + logger.exception("error starting main server on: %s:%s", host, port) + sys.exit(1) + + close_onexec(server.fileno()) + logger.info("main server started, listening on: %s:%s", host, port) + server.serve_forever() + + +# TODO: should sessions and the main core daemon both catch exit to shutdown independently? +def cleanup(): + """ + Runs server shutdown and cleanup when catching an exit signal. + + :return: nothing + """ + while coreserver.CoreServer.servers: + server = coreserver.CoreServer.servers.pop() + server.shutdown() + + +def sighandler(signum, stackframe): + """ + Signal handler when different signals are sent. + + :param int signum: singal number sent + :param stackframe: stack frame sent + :return: nothing + """ + logger.error("terminated by signal: %s", signum) + sys.exit(signum) + + +signal.signal(signal.SIGHUP, sighandler) +signal.signal(signal.SIGINT, sighandler) +signal.signal(signal.SIGTERM, sighandler) +signal.signal(signal.SIGUSR1, sighandler) +signal.signal(signal.SIGUSR2, sighandler) +atexit.register(cleanup) + + +def get_merged_config(filename): + """ + Return a configuration after merging config file and command-line arguments. + + :param str filename: file name to merge configuration settings with + :return: merged configuration + :rtype: dict + """ + # these are the defaults used in the config file + defaults = { + "port": "%d" % enumerations.CORE_API_PORT, + "listenaddr": "localhost", + "xmlfilever": "1.0", + "numthreads": "1", + } + + usagestr = "usage: %prog [-h] [options] [args]\n\n" + \ + "CORE daemon v.%s instantiates Linux network namespace " \ + "nodes." % constants.COREDPY_VERSION + parser = optparse.OptionParser(usage=usagestr) + parser.add_option("-f", "--configfile", dest="configfile", type="string", + help="read config from specified file; default = %s" % filename) + parser.add_option("-p", "--port", dest="port", type=int, + help="port number to listen on; default = %s" % defaults["port"]) + parser.add_option("-t", "--numthreads", dest="numthreads", type=int, + help="number of server threads; default = %s" % defaults["numthreads"]) + + # parse command line options + options, args = parser.parse_args() + + # read the config file + if options.configfile is not None: + filename = options.configfile + del options.configfile + cfg = ConfigParser.SafeConfigParser(defaults) + cfg.read(filename) + + section = "core-daemon" + if not cfg.has_section(section): + cfg.add_section(section) + + # merge command line with config file + for opt in options.__dict__: + val = options.__dict__[opt] + if val is not None: + cfg.set(section, opt, val.__str__()) + + return dict(cfg.items(section)), args + + +def main(): + """ + Main program startup. + + :return: nothing + """ + # get a configuration merged from config file and command-line arguments + cfg, args = get_merged_config("%s/core.conf" % constants.CORE_CONF_DIR) + for a in args: + logger.error("ignoring command line argument: %s", a) + + # attempt load custom services + service_paths = cfg.get("custom_services_dir") + logger.debug("custom service paths: %s", service_paths) + if service_paths: + for service_path in service_paths.split(','): + service_path = service_path.strip() + ServiceManager.add_services(service_path) + + banner() + + try: + cored(cfg) + except KeyboardInterrupt: + logger.info("keyboard interrupt, stopping core daemon") + + sys.exit(0) + + +if __name__ == "__main__": + # configure nodes to use + if len(sys.argv) == 2 and sys.argv[1] == "ovs": + from core.netns.openvswitch import OVS_NODES + + nodeutils.update_node_map(OVS_NODES) + + # load default services + services.load() + + main() From 93394b042ae2c55e021468a802485bc0c0b31eeb Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 19 Apr 2018 17:19:31 -0700 Subject: [PATCH 131/152] slight update to clean up some future link handling code --- daemon/core/future/coreemu.py | 30 +++++++++++++---------------- daemon/core/future/futurehandler.py | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 9d5f122a..bce1840b 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -70,19 +70,18 @@ def get_interfaces(link_data): return interface_one, interface_two -def create_interface(node, network, addresses, interface_data): +def create_interface(node, network, interface_data): """ Create an interface for a node on a network using provided interface data. :param node: node to create interface for :param network: network to associate interface with - :param list[str] addresses: :param InterfaceData interface_data: interface data :return: """ node.newnetif( network, - addrlist=addresses, + addrlist=interface_data.get_addresses(), hwaddr=interface_data.mac, ifindex=interface_data.id, ifname=interface_data.name @@ -187,7 +186,7 @@ class FutureSession(Session): node_one = None else: node_two = None - # PhysicalNode connected via GreTap tunnel; uses adoptnetif() below + # physical node connected via gre tap tunnel elif tunnel: if tunnel.remotenum == n1_id: node_one = None @@ -266,18 +265,12 @@ class FutureSession(Session): # node to network if node_one and net_one: - addresses = [] - addresses.extend(interface_one_data.get_addresses()) - addresses.extend(interface_two_data.get_addresses()) - interface = create_interface(node_one, net_one, addresses, interface_one_data) + interface = create_interface(node_one, net_one, interface_one_data) link_config(net_one, interface, link_data) # network to node if node_two and net_one: - addresses = [] - addresses.extend(interface_one_data.get_addresses()) - addresses.extend(interface_two_data.get_addresses()) - interface = create_interface(node_two, net_one, addresses, interface_two_data) + interface = create_interface(node_two, net_one, interface_two_data) if not link_data.unidirectional: link_config(net_one, interface, link_data) @@ -295,7 +288,7 @@ class FutureSession(Session): link_config(net_two, interface, link_data, devname=interface.name) interface.swapparams("_params_up") - # a tunnel was found for the nodes + # a tunnel node was found for the nodes addresses = [] if not node_one and net_one: addresses.extend(interface_one_data.get_addresses()) @@ -314,14 +307,14 @@ class FutureSession(Session): if addresses: net_two.addrconfig(addresses) - if not net_one and not net_two and (not node_one or not node_two): - addresses = [] + # physical node connected with tunnel + if not net_one and not net_two and (node_one or node_two): if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL): - addresses.extend(interface_one_data.get_addresses()) + addresses = interface_one_data.get_addresses() node_one.adoptnetif(tunnel, link_data.interface1_id, link_data.interface1_mac, addresses) link_config(node_one, tunnel, link_data) elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): - addresses.extend(interface_two_data.get_addresses()) + addresses = interface_two_data.get_addresses() node_two.adoptnetif(tunnel, link_data.interface2_id, link_data.interface2_mac, addresses) link_config(node_two, tunnel, link_data) finally: @@ -572,6 +565,9 @@ class FutureSession(Session): ) self.broadcast_node(node_data) + def start_mobility(self, node_ids=None): + self.mobility.startup(node_ids) + def shutdown(self): self.set_state(state=EventTypes.DATACOLLECT_STATE.value, send_event=True) self.set_state(state=EventTypes.SHUTDOWN_STATE.value, send_event=True) diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py index f5b0c088..f905cec7 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/future/futurehandler.py @@ -943,7 +943,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): # configure mobility models for WLAN added during runtime if event_type == EventTypes.INSTANTIATION_STATE.value and nodeutils.is_node(node, NodeTypes.WIRELESS_LAN): - self.session.mobility.startup(node_ids=(node.objid,)) + self.session.start_mobility(node_ids=(node.objid,)) return () logger.warn("dropping unhandled Event message with node number") From 424c08c5e002c52f166e2866585b44db5ae8dd34 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 20 Apr 2018 17:00:47 -0700 Subject: [PATCH 132/152] updates to drive most core logic from CoreEmu and Sessions themselves instead of outside code, updated an example to leverage new API, fixed issues testing when executing a script --- daemon/core/future/coreemu.py | 248 ++++++++++++++++++-- daemon/core/future/futurehandler.py | 147 +++++++++--- daemon/core/future/futureserver.py | 229 +----------------- daemon/core/netns/vnode.py | 3 +- daemon/examples/future/switch_api.py | 75 ++++++ daemon/examples/future/switch_api_inject.py | 52 ++++ daemon/scripts/core-future | 35 --- 7 files changed, 484 insertions(+), 305 deletions(-) create mode 100644 daemon/examples/future/switch_api.py create mode 100644 daemon/examples/future/switch_api_inject.py diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index bce1840b..704106a6 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -1,4 +1,7 @@ +import atexit import os +import signal +import sys import core.services from core import logger @@ -14,8 +17,42 @@ from core.xml.xmlparser import core_document_parser from core.xml.xmlwriter import core_document_writer +def signal_handler(signal_number, _): + """ + Handle signals and force an exit with cleanup. + + :param int signal_number: signal number + :param _: ignored + :return: nothing + """ + logger.info("caught signal: %s", signal_number) + sys.exit(signal_number) + + +signal.signal(signal.SIGHUP, signal_handler) +signal.signal(signal.SIGINT, signal_handler) +signal.signal(signal.SIGTERM, signal_handler) +signal.signal(signal.SIGUSR1, signal_handler) +signal.signal(signal.SIGUSR2, signal_handler) + + class InterfaceData(object): + """ + Convenience class for storing interface data. + """ + def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask): + """ + Creates an InterfaceData object. + + :param int _id: + :param str name: + :param str mac: + :param str ip4: + :param int ip4_mask: + :param str ip6: + :param int ip6_mask: + """ self.id = _id self.name = name self.mac = mac @@ -49,6 +86,13 @@ class InterfaceData(object): def get_interfaces(link_data): + """ + Creates interface data objects for the interfaces defined within link data. + + :param core.data.LinkData link_data: data to create interface data from + :return: interface one and two data + :rtype: tuple[InterfaceData] + """ interface_one = InterfaceData( _id=link_data.interface1_id, name=link_data.interface1_name, @@ -77,7 +121,7 @@ def create_interface(node, network, interface_data): :param node: node to create interface for :param network: network to associate interface with :param InterfaceData interface_data: interface data - :return: + :return: created interface """ node.newnetif( network, @@ -90,6 +134,16 @@ def create_interface(node, network, interface_data): def link_config(network, interface, link_data, devname=None, interface_two=None): + """ + Convenience method for configuring a link, + + :param network: network to configure link for + :param interface: interface to configure + :param core.data.LinkData link_data: data to configure link with + :param str devname: device name, default is None + :param interface_two: other interface associated, default is None + :return: nothing + """ config = { "netif": interface, "bw": link_data.bandwidth, @@ -130,8 +184,8 @@ def is_core_node(node): class IdGen(object): - def __init__(self): - self.id = 0 + def __init__(self, _id=0): + self.id = _id def next(self): self.id += 1 @@ -148,9 +202,6 @@ class FutureSession(Session): def __init__(self, session_id, config=None, persistent=True, mkdir=True): super(FutureSession, self).__init__(session_id, config, persistent, mkdir) - # set master - self.master = True - # object management self.node_id_gen = IdGen() @@ -164,6 +215,13 @@ class FutureSession(Session): } def link_nodes(self, link_data): + """ + Convenience method for retrieving nodes within link data. + + :param core.data.LinkData link_data: data to retrieve nodes from + :return: nodes, network nodes if presetn, and tunnel + :rtype: tuple + """ logger.info("link message between node1(%s:%s) and node2(%s:%s)", link_data.node1_id, link_data.interface1_id, link_data.node2_id, link_data.interface2_id) @@ -239,6 +297,14 @@ class FutureSession(Session): raise ValueError("no common network found for wireless link/unlink") def link_add(self, link_data): + """ + Add a link between nodes. + + :param core.data.LinkData link_data: data to create a link with + :return: nothing + """ + logger.info("link_data: %s", link_data) + # interface data interface_one_data, interface_two_data = get_interfaces(link_data) @@ -324,6 +390,12 @@ class FutureSession(Session): node_two.lock.release() def link_delete(self, link_data): + """ + Delete a link between nodes. + + :param core.data.LinkData link_data: data to delete link with + :return: nothing + """ # interface data interface_one_data, interface_two_data = get_interfaces(link_data) @@ -375,6 +447,12 @@ class FutureSession(Session): node_two.lock.release() def link_update(self, link_data): + """ + Update link information between nodes. + + :param core.data.LinkData link_data: data to update link with + :return: nothing + """ # interface data interface_one_data, interface_two_data = get_interfaces(link_data) @@ -470,7 +548,10 @@ class FutureSession(Session): # determine node id node_id = node_data.id if not node_id: - node_id = self.node_id_gen.next() + while True: + node_id = self.node_id_gen.next() + if node_id not in self.objects: + break # generate name if not provided name = node_data.name @@ -508,6 +589,12 @@ class FutureSession(Session): return node_id def node_update(self, node_data): + """ + Update node information. + + :param core.data.NodeData node_data: data to update node with + :return: nothing + """ try: # get node to update node = self.get_object(node_data.id) @@ -522,6 +609,12 @@ class FutureSession(Session): logger.error("failure to update node that does not exist: %s", node_data.id) def node_delete(self, node_id): + """ + Delete a node from the session and check if session should shutdown, if no nodes are left. + + :param int node_id: + :return: True if node deleted, False otherwise + """ # delete node and check for session shutdown if a node was removed result = self.custom_delete_object(node_id) if result: @@ -529,6 +622,13 @@ class FutureSession(Session): return result def node_set_position(self, node, node_data): + """ + Set position for a node, use lat/lon/alt if needed. + + :param node: node to set position for + :param NodeData node_data: data for node + :return: nothing + """ # extract location values x = node_data.x_position y = node_data.y_position @@ -566,9 +666,20 @@ class FutureSession(Session): self.broadcast_node(node_data) def start_mobility(self, node_ids=None): + """ + Start mobility for the provided node ids. + + :param list[int] node_ids: nodes to start mobility for + :return: nothing + """ self.mobility.startup(node_ids) def shutdown(self): + """ + Shutdown session. + + :return: nothing + """ self.set_state(state=EventTypes.DATACOLLECT_STATE.value, send_event=True) self.set_state(state=EventTypes.SHUTDOWN_STATE.value, send_event=True) super(FutureSession, self).shutdown() @@ -589,7 +700,14 @@ class FutureSession(Session): return result def is_active(self): - return self.state in {EventTypes.RUNTIME_STATE.value, EventTypes.DATACOLLECT_STATE.value} + """ + Determine if this session is considered to be active. (Runtime or Data collect states) + + :return: True if active, False otherwise + """ + result = self.state in {EventTypes.RUNTIME_STATE.value, EventTypes.DATACOLLECT_STATE.value} + logger.info("checking if session is active: %s", result) + return result def open_xml(self, file_name, start=False): """ @@ -637,11 +755,31 @@ class FutureSession(Session): self.set_hook(state, file_name, source_name, data) def node_service_file(self, node_id, service_name, file_name, source_name, data): + """ + Add a service file for a node. + + :param int node_id: node to add service file to + :param str service_name: service file to add + :param str file_name: file name to use + :param str source_name: source file + :param str data: file data to save + :return: nothing + """ # hack to conform with old logic until updated service_name = ":%s" % service_name self.services.setservicefile(node_id, service_name, file_name, source_name, data) def node_file(self, node_id, source_name, file_name, data): + """ + Add a file to a node. + + :param int node_id: node to add file to + :param str source_name: source file name + :param str file_name: file name to add + :param str data: file data + :return: nothing + """ + node = self.get_object(node_id) if source_name is not None: @@ -650,20 +788,50 @@ class FutureSession(Session): node.nodefile(file_name, data) def clear(self): + """ + Clear all CORE session data. (objects, hooks, broker) + + :return: nothing + """ self.delete_objects() self.del_hooks() self.broker.reset() def start_events(self): + """ + Start event loop. + + :return: nothing + """ self.event_loop.run() def services_event(self, event_data): + """ + Handle a service event. + + :param core.data.EventData event_data: event data to handle + :return: + """ self.services.handleevent(event_data) def mobility_event(self, event_data): + """ + Handle a mobility event. + + :param core.data.EventData event_data: event data to handle + :return: nothing + """ self.mobility.handleevent(event_data) def create_node(self, cls, name=None, model=None): + """ + Create a node + + :param cls: + :param name: + :param model: + :return: + """ object_id = self.node_id_gen.next() if not name: @@ -677,6 +845,12 @@ class FutureSession(Session): return node def create_emane_node(self, name=None): + """ + Create an EMANE node for use within an EMANE network. + + :param str name: name to five node + :return: CoreNode + """ return self.create_node(cls=CoreNode, name=name, model="mdr") def create_emane_network(self, model, geo_reference, geo_scale=None, name=None): @@ -717,25 +891,71 @@ class CoreEmu(object): """ def __init__(self, config=None): + """ + Create a CoreEmu object. + + :param dict config: configuration options + """ # configuration self.config = config # session management - self.session_id_gen = IdGen() + self.session_id_gen = IdGen(_id=59999) self.sessions = {} # load default services core.services.load() - def create_session(self): - """ - Create a new CORE session. + # catch exit event + atexit.register(self.shutdown) + def shutdown(self): + """ + Shutdown all CORE session. + + :return: nothing + """ + logger.info("shutting down all session") + for session in self.sessions.values(): + session.shutdown() + self.sessions.clear() + + def create_session(self, _id=None, master=False): + """ + Create a new CORE session, set to master if running standalone. + + :param int _id: session id for new session + :param bool master: sets session to master :return: created session :rtype: FutureSession """ - session_id = self.session_id_gen.next() - return FutureSession(session_id, config=self.config) + + session_id = _id + if not session_id: + while True: + session_id = self.session_id_gen.next() + if session_id not in self.sessions: + break + + session = FutureSession(session_id, config=self.config) + logger.info("created session: %s", session_id) + if master: + session.master = True + + self.sessions[session_id] = session + return session + + def delete_session(self, _id): + """ + Deletes a CORE session. + + :param int _id: session id to delete + :return: nothing + """ + logger.info("deleting session: %s", _id) + session = self.sessions.pop(_id, None) + if not session: + logger.error("session to delete did not exist: %s", _id) def set_wireless_model(self, node, model): """ diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py index f905cec7..da0d52d6 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/future/futurehandler.py @@ -64,6 +64,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.message_queue = Queue.Queue() self.node_status_request = {} self._shutdown_lock = threading.Lock() + self._sessions_lock = threading.Lock() self.handler_threads = [] num_threads = int(server.config["numthreads"]) @@ -79,6 +80,9 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.master = False self.session = None + # core emulator + self.coreemu = server.coreemu + utils.close_onexec(request.fileno()) SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) @@ -98,12 +102,21 @@ class FutureHandler(SocketServer.BaseRequestHandler): :return: nothing """ logger.info("finishing request handler") - self.done = True - logger.info("remaining message queue size: %s", self.message_queue.qsize()) - # seconds - timeout = 10.0 + + # give some time for message queue to deplete + timeout = 10 + wait = 0 + while not self.message_queue.empty(): + logger.info("waiting for message queue to empty: %s seconds", wait) + time.sleep(1) + wait += 1 + if wait == timeout: + logger.warn("queue failed to be empty, finishing request handler") + break + logger.info("client disconnected: notifying threads") + self.done = True for thread in self.handler_threads: logger.info("waiting for thread: %s", thread.getName()) thread.join(timeout) @@ -112,16 +125,84 @@ class FutureHandler(SocketServer.BaseRequestHandler): logger.info("connection closed: %s", self.client_address) if self.session: - self.remove_session_handlers() - # remove client from session broker and shutdown if there are no clients + self.remove_session_handlers() self.session.broker.session_clients.remove(self) - if not self.session.broker.session_clients: - logger.info("no session clients left, initiating shutdown") + if not self.session.broker.session_clients and not self.session.is_active(): + logger.info("no session clients left and not active, initiating shutdown") self.session.shutdown() + self.coreemu.delete_session(self.session.session_id) return SocketServer.BaseRequestHandler.finish(self) + def session_message(self, flags=0): + """ + Build CORE API Sessions message based on current session info. + + :param int flags: message flags + :return: session message + """ + id_list = [] + name_list = [] + file_list = [] + node_count_list = [] + date_list = [] + thumb_list = [] + num_sessions = 0 + + logger.info("creating session message: %s", self.coreemu.sessions.keys()) + + with self._sessions_lock: + for session_id, session in self.coreemu.sessions.iteritems(): + num_sessions += 1 + id_list.append(str(session_id)) + + name = session.name + if not name: + name = "" + name_list.append(name) + + file = session.file_name + if not file: + file = "" + file_list.append(file) + + node_count_list.append(str(session.get_node_count())) + + date_list.append(time.ctime(session._state_time)) + + thumb = session.thumbnail + if not thumb: + thumb = "" + thumb_list.append(thumb) + + session_ids = "|".join(id_list) + names = "|".join(name_list) + files = "|".join(file_list) + node_counts = "|".join(node_count_list) + dates = "|".join(date_list) + thumbs = "|".join(thumb_list) + + if num_sessions > 0: + tlv_data = "" + if len(session_ids) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session_ids) + if len(names) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NAME.value, names) + if len(files) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.FILE.value, files) + if len(node_counts) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NODE_COUNT.value, node_counts) + if len(dates) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.DATE.value, dates) + if len(thumbs) > 0: + tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.THUMB.value, thumbs) + message = coreapi.CoreSessionMessage.pack(flags, tlv_data) + else: + message = None + + return message + def handle_broadcast_event(self, event_data): """ Callback to handle an event broadcast out from a session. @@ -407,8 +488,11 @@ class FutureHandler(SocketServer.BaseRequestHandler): :return: nothing """ while not self.done: - message = self.message_queue.get() - self.handle_message(message) + try: + message = self.message_queue.get(timeout=1) + self.handle_message(message) + except Queue.Empty: + pass def handle_message(self, message): """ @@ -467,6 +551,9 @@ class FutureHandler(SocketServer.BaseRequestHandler): except IOError: logger.exception("error dispatching reply") + def session_shutdown(self, session): + self.coreemu.delete_session(session.session_id) + def handle(self): """ Handle a new connection request from a client. Dispatch to the @@ -478,8 +565,10 @@ class FutureHandler(SocketServer.BaseRequestHandler): # use port as session id port = self.request.getpeername()[1] - logger.info("creating new session for client: %s", port) - self.session = self.server.create_session(session_id=port) + # TODO: add shutdown handler for session + self.session = self.coreemu.create_session(port) + # self.session.shutdown_handlers.append(self.session_shutdown) + logger.info("created new session for client: %s", self.session.session_id) # TODO: hack to associate this handler with this sessions broker for broadcasting # TODO: broker needs to be pulled out of session to the server/handler level @@ -735,22 +824,22 @@ class FutureHandler(SocketServer.BaseRequestHandler): try: logger.info("executing: %s", execute_server) if message.flags & MessageFlags.STRING.value: - old_session_ids = set(self.server.get_session_ids()) + old_session_ids = set(self.coreemu.sessions.keys()) sys.argv = shlex.split(execute_server) file_name = sys.argv[0] if os.path.splitext(file_name)[1].lower() == ".xml": - session = self.server.create_session() + session = self.coreemu.create_session() try: session.open_xml(file_name, start=True) except: session.shutdown() - self.server.remove_session(session) + self.coreemu.delete_session(session.session_id) raise else: thread = threading.Thread( target=execfile, - args=(file_name, {"__file__": file_name, "server": self.server}) + args=(file_name, {"__file__": file_name, "coreemu": self.coreemu}) ) thread.daemon = True thread.start() @@ -758,7 +847,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): time.sleep(0.25) if message.flags & MessageFlags.STRING.value: - new_session_ids = set(self.server.get_session_ids()) + new_session_ids = set(self.coreemu.sessions.keys()) new_sid = new_session_ids.difference(old_session_ids) try: sid = new_sid.pop() @@ -767,17 +856,17 @@ class FutureHandler(SocketServer.BaseRequestHandler): logger.info("executed %s with unknown session ID", execute_server) return replies - logger.info("checking session %d for RUNTIME state" % sid) - session = self.server.get_session(session_id=sid) + logger.info("checking session %d for RUNTIME state", sid) + session = self.coreemu.sessions.get(sid) retries = 10 # wait for session to enter RUNTIME state, to prevent GUI from # connecting while nodes are still being instantiated while session.state != EventTypes.RUNTIME_STATE.value: - logger.info("waiting for session %d to enter RUNTIME state" % sid) + logger.info("waiting for session %d to enter RUNTIME state", sid) time.sleep(1) retries -= 1 if retries <= 0: - logger.info("session %d did not enter RUNTIME state" % sid) + logger.info("session %d did not enter RUNTIME state", sid) return replies tlv_data = coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, execute_server) @@ -800,17 +889,15 @@ class FutureHandler(SocketServer.BaseRequestHandler): # register capabilities with the GUI self.master = True - # TODO: need to replicate functionality? - # self.server.set_session_master(self) # find the session containing this client and set the session to master - for session in self.server.sessions.itervalues(): + for session in self.coreemu.sessions.itervalues(): if self in session.broker.session_clients: logger.info("setting session to master: %s", session.session_id) session.master = True break replies.append(self.register()) - replies.append(self.server.to_session_message()) + replies.append(self.session_message()) return replies @@ -1040,7 +1127,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): if session_id == 0: session = self.session else: - session = self.server.get_session(session_id=session_id) + session = self.coreemu.sessions.get(session_id) if session is None: logger.info("session %s not found", session_id) @@ -1060,12 +1147,12 @@ class FutureHandler(SocketServer.BaseRequestHandler): session.set_user(user) elif message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: # status request flag: send list of sessions - return self.server.to_session_message(), + return self.session_message(), else: # handle ADD or DEL flags for session_id in session_ids: session_id = int(session_id) - session = self.server.get_session(session_id=session_id) + session = self.coreemu.sessions.get(session_id) if session is None: logger.info("session %s not found (flags=0x%x)", session_id, message.flags) @@ -1073,12 +1160,14 @@ class FutureHandler(SocketServer.BaseRequestHandler): if message.flags & MessageFlags.ADD.value: # connect to the first session that exists - logger.info("request to connect to session %s" % session_id) + logger.info("request to connect to session %s", session_id) # remove client from session broker and shutdown if needed + self.remove_session_handlers() self.session.broker.session_clients.remove(self) if not self.session.broker.session_clients and not self.session.is_active(): self.session.shutdown() + self.coreemu.delete_session(self.session.session_id) # set session to join self.session = session diff --git a/daemon/core/future/futureserver.py b/daemon/core/future/futureserver.py index 64db9002..d37845b4 100644 --- a/daemon/core/future/futureserver.py +++ b/daemon/core/future/futureserver.py @@ -3,14 +3,8 @@ Defines server classes and request handlers for TCP and UDP. """ import SocketServer -import threading -import time -from core import logger -from core.api import coreapi -from core.enumerations import EventTypes -from core.enumerations import SessionTlvs -from core.future.coreemu import FutureSession +from core.future.coreemu import CoreEmu class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): @@ -20,7 +14,6 @@ class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): """ daemon_threads = True allow_reuse_address = True - servers = set() def __init__(self, server_address, handler_class, config=None): """ @@ -32,35 +25,10 @@ class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): :param dict config: configuration setting :return: """ + self.coreemu = CoreEmu(config) self.config = config - self.sessions = {} - self.udpserver = None - self.udpthread = None - self._sessions_lock = threading.Lock() - FutureServer.add_server(self) SocketServer.TCPServer.__init__(self, server_address, handler_class) - @classmethod - def add_server(cls, server): - """ - Add a core server to the known servers set. - - :param CoreServer server: server to add - :return: nothing - """ - cls.servers.add(server) - - @classmethod - def remove_server(cls, server): - """ - Remove a core server from the known servers set. - - :param CoreServer server: server to remove - :return: nothing - """ - if server in cls.servers: - cls.servers.remove(server) - def shutdown(self): """ Shutdown the server, all known sessions, and remove server from known servers set. @@ -68,196 +36,5 @@ class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): :return: nothing """ # shutdown all known sessions - for session in self.sessions.values(): + for session in self.coreemu.sessions.itervalues(): session.shutdown() - - # remove server from server list - FutureServer.remove_server(self) - - def add_session(self, session): - """ - Add a session to our dictionary of sessions, ensuring a unique session number. - - :param core.session.Session session: session to add - :return: added session - :raise KeyError: when a session with the same id already exists - """ - with self._sessions_lock: - if session.session_id in self.sessions: - raise KeyError("non-unique session id %s for %s" % (session.session_id, session)) - self.sessions[session.session_id] = session - - return session - - def remove_session(self, session): - """ - Remove a session from our dictionary of sessions. - - :param core.session.Session session: session to remove - :return: removed session - :rtype: core.session.Session - """ - with self._sessions_lock: - if session.session_id not in self.sessions: - logger.info("session id %s not found (sessions=%s)", session.session_id, self.sessions.keys()) - else: - del self.sessions[session.session_id] - - return session - - def get_session_ids(self): - """ - Return a list of active session numbers. - - :return: known session ids - :rtype: list - """ - with self._sessions_lock: - session_ids = self.sessions.keys() - - return session_ids - - def create_session(self, session_id=None): - """ - Convenience method for creating sessions with the servers config. - - :param int session_id: session id for new session - :return: create session - :rtype: FutureSession - """ - - # create random id when necessary, seems to be 1 case wanted, based on legacy code - # creating a value so high, typical client side generation schemes hopefully wont collide - if not session_id: - session_id = next( - session_id for session_id in xrange(60000, 65000) - if session_id not in self.sessions - ) - - # create and add session to local manager - session = FutureSession(session_id, config=self.config) - self.add_session(session) - - # add shutdown handler to remove session from manager - session.shutdown_handlers.append(self.session_shutdown) - - return session - - def get_session(self, session_id=None): - """ - Create a new session or retrieve an existing one from our - dictionary of sessions. When the session_id=0 and the use_existing - flag is set, return on of the existing sessions. - - :param int session_id: session id of session to retrieve, defaults to returning random session - :return: session - :rtype: core.session.Session - """ - - with self._sessions_lock: - # return specified session or none - if session_id: - return self.sessions.get(session_id) - - # retrieving known session - session = None - - # find runtime session with highest node count - for known_session in filter(lambda x: x.state == EventTypes.RUNTIME_STATE.value, - self.sessions.itervalues()): - if not session or known_session.get_node_count() > session.get_node_count(): - session = known_session - - # return first known session otherwise - if not session: - for known_session in self.sessions.itervalues(): - session = known_session - break - - return session - - def session_shutdown(self, session): - """ - Handler method to be used as a callback when a session has shutdown. - - :param core.session.Session session: session shutting down - :return: nothing - """ - self.remove_session(session) - - def to_session_message(self, flags=0): - """ - Build CORE API Sessions message based on current session info. - - :param int flags: message flags - :return: session message - """ - id_list = [] - name_list = [] - file_list = [] - node_count_list = [] - date_list = [] - thumb_list = [] - num_sessions = 0 - - with self._sessions_lock: - for session_id in self.sessions: - session = self.sessions[session_id] - # debug: session.dumpsession() - num_sessions += 1 - id_list.append(str(session_id)) - - name = session.name - if not name: - name = "" - name_list.append(name) - - file = session.file_name - if not file: - file = "" - file_list.append(file) - - node_count_list.append(str(session.get_node_count())) - - date_list.append(time.ctime(session._state_time)) - - thumb = session.thumbnail - if not thumb: - thumb = "" - thumb_list.append(thumb) - - session_ids = "|".join(id_list) - names = "|".join(name_list) - files = "|".join(file_list) - node_counts = "|".join(node_count_list) - dates = "|".join(date_list) - thumbs = "|".join(thumb_list) - - if num_sessions > 0: - tlv_data = "" - if len(session_ids) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session_ids) - if len(names) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NAME.value, names) - if len(files) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.FILE.value, files) - if len(node_counts) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NODE_COUNT.value, node_counts) - if len(dates) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.DATE.value, dates) - if len(thumbs) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.THUMB.value, thumbs) - message = coreapi.CoreSessionMessage.pack(flags, tlv_data) - else: - message = None - - return message - - def dump_sessions(self): - """ - Log currently known session information. - """ - logger.info("sessions:") - with self._sessions_lock: - for session_id in self.sessions: - logger.info(session_id) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index b8ee3924..49d4e79c 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -17,6 +17,7 @@ from core.coreobj import PyCoreNode from core.enumerations import NodeTypes from core.misc import nodeutils from core.misc import utils +from core.misc.ipaddress import MacAddress from core.netns import vnodeclient from core.netns.vif import TunTap from core.netns.vif import VEth @@ -290,7 +291,7 @@ class SimpleLxcNode(PyCoreNode): output = output.split("\n") veth.flow_id = int(output[0].strip().split(":")[0]) + 1 logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) - veth.hwaddr = output[1].strip().split()[1] + veth.hwaddr = MacAddress.from_string(output[1].strip().split()[1]) logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) try: diff --git a/daemon/examples/future/switch_api.py b/daemon/examples/future/switch_api.py new file mode 100644 index 00000000..b95bd7db --- /dev/null +++ b/daemon/examples/future/switch_api.py @@ -0,0 +1,75 @@ +#!/usr/bin/python +# +# run iperf to measure the effective throughput between two nodes when +# n nodes are connected to a virtual wlan; run test for testsec +# and repeat for minnodes <= n <= maxnodes with a step size of +# nodestep + +import datetime + +import parser +from core.data import NodeData, LinkData +from core.enumerations import NodeTypes, EventTypes +from core.future.coreemu import FutureIpv4Prefix, CoreEmu + + +def example(options): + # ip generator for example + prefix = FutureIpv4Prefix("10.83.0.0/16") + + # create emulator instance for creating sessions and utility methods + coreemu = CoreEmu() + session = coreemu.create_session(master=True) + + # must be in configuration state for nodes to start, when using "node_add" below + session.set_state(EventTypes.CONFIGURATION_STATE.value) + + # create switch network node + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + switch_id = session.node_add(node_data) + + # create nodes + for _ in xrange(options.nodes): + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_id = session.node_add(node_data) + node = session.get_object(node_id) + inteface_index = node.newifindex() + address = prefix.addr(node_id) + link_data = LinkData( + node1_id=node_id, + node2_id=switch_id, + interface1_id=inteface_index, + interface1_ip4=str(address), + interface1_ip4_mask=prefix.prefixlen, + ) + session.link_add(link_data) + + # instantiate session + session.instantiate() + + # get nodes to run example + first_node = session.get_object(2) + last_node = session.get_object(options.nodes + 1) + + print "starting iperf server on node: %s" % first_node.name + first_node.cmd(["iperf", "-s", "-D"]) + address = str(prefix.addr(first_node.objid)) + print "node %s connecting to %s" % (last_node.name, address) + last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) + first_node.cmd(["killall", "-9", "iperf"]) + + # shutdown session + coreemu.shutdown() + + +def main(): + options = parser.parse_options("switch") + + start = datetime.datetime.now() + print "running switch example: nodes(%s) time(%s)" % (options.nodes, options.time) + example(options) + print "elapsed time: %s" % (datetime.datetime.now() - start) + + +if __name__ == "__main__": + main() diff --git a/daemon/examples/future/switch_api_inject.py b/daemon/examples/future/switch_api_inject.py new file mode 100644 index 00000000..1dabd0b0 --- /dev/null +++ b/daemon/examples/future/switch_api_inject.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# +# run iperf to measure the effective throughput between two nodes when +# n nodes are connected to a virtual wlan; run test for testsec +# and repeat for minnodes <= n <= maxnodes with a step size of +# nodestep + +import datetime + +import parser +from core.data import NodeData, LinkData +from core.enumerations import NodeTypes, EventTypes +from core.future.coreemu import FutureIpv4Prefix, CoreEmu + + +def example(nodes): + # ip generator for example + prefix = FutureIpv4Prefix("10.83.0.0/16") + + # create emulator instance for creating sessions and utility methods + coreemu = globals()["coreemu"] + session = coreemu.create_session(master=True) + + # must be in configuration state for nodes to start, when using "node_add" below + session.set_state(EventTypes.CONFIGURATION_STATE.value) + + # create switch network node + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + switch_id = session.node_add(node_data) + + # create nodes + for _ in xrange(nodes): + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_id = session.node_add(node_data) + node = session.get_object(node_id) + inteface_index = node.newifindex() + address = prefix.addr(node_id) + link_data = LinkData( + node1_id=node_id, + node2_id=switch_id, + interface1_id=inteface_index, + interface1_ip4=str(address), + interface1_ip4_mask=prefix.prefixlen, + ) + session.link_add(link_data) + + # instantiate session + session.instantiate() + + +if __name__ in {"__main__", "__builtin__"}: + example(2) diff --git a/daemon/scripts/core-future b/daemon/scripts/core-future index 6afbaa1e..815aa5bb 100644 --- a/daemon/scripts/core-future +++ b/daemon/scripts/core-future @@ -6,14 +6,11 @@ message handlers are defined and some support for sending messages. """ import ConfigParser -import atexit import optparse -import signal import sys import time from core import constants -from core import coreserver from core import enumerations from core import logger from core import services @@ -56,38 +53,6 @@ def cored(cfg=None): server.serve_forever() -# TODO: should sessions and the main core daemon both catch exit to shutdown independently? -def cleanup(): - """ - Runs server shutdown and cleanup when catching an exit signal. - - :return: nothing - """ - while coreserver.CoreServer.servers: - server = coreserver.CoreServer.servers.pop() - server.shutdown() - - -def sighandler(signum, stackframe): - """ - Signal handler when different signals are sent. - - :param int signum: singal number sent - :param stackframe: stack frame sent - :return: nothing - """ - logger.error("terminated by signal: %s", signum) - sys.exit(signum) - - -signal.signal(signal.SIGHUP, sighandler) -signal.signal(signal.SIGINT, sighandler) -signal.signal(signal.SIGTERM, sighandler) -signal.signal(signal.SIGUSR1, sighandler) -signal.signal(signal.SIGUSR2, sighandler) -atexit.register(cleanup) - - def get_merged_config(filename): """ Return a configuration after merging config file and command-line arguments. From 8ed7f7c0ef09def77b334205460d5f7fa2855620 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 20 Apr 2018 20:38:50 -0700 Subject: [PATCH 133/152] fixed typo for sysv script PYTHONPATH --- scripts/core-daemon.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/core-daemon.in b/scripts/core-daemon.in index 36e834de..a865fcef 100644 --- a/scripts/core-daemon.in +++ b/scripts/core-daemon.in @@ -20,7 +20,7 @@ NAME=`basename $0` PIDFILE="@CORE_STATE_DIR@/run/$NAME.pid" LOG="@CORE_STATE_DIR@/log/$NAME.log" -CMD="PYTHON_PATH=@pythondir@ @PYTHON@ @bindir@/$NAME" +CMD="PYTHONPATH=@pythondir@ @PYTHON@ @bindir@/$NAME" get_pid() { cat "$PIDFILE" From ac2b64aaaf73e6a959769322e8c4dc4f7a5f94fd Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 20 Apr 2018 21:22:08 -0700 Subject: [PATCH 134/152] updates to remove restriction for emane in general and emane 1.2.1, should support at leat 1.0.1 possibly further back and can run without emane again, updated gui to ask users to install emane when not preset on the emane models panel --- daemon/core/emane/commeffect.py | 5 ++++- daemon/core/emane/emanemanager.py | 35 +++++++++++++++++++----------- daemon/core/emane/emanemanifest.py | 10 ++++++++- daemon/core/emane/nodes.py | 5 ++++- gui/wlan.tcl | 20 ++++++++--------- 5 files changed, 49 insertions(+), 26 deletions(-) diff --git a/daemon/core/emane/commeffect.py b/daemon/core/emane/commeffect.py index ff1c99e0..cc976f6c 100644 --- a/daemon/core/emane/commeffect.py +++ b/daemon/core/emane/commeffect.py @@ -9,7 +9,10 @@ from core.emane import emanemodel try: from emane.events.commeffectevent import CommEffectEvent except ImportError: - logger.info("emane 1.2.1 not found") + try: + from emanesh.events.commeffectevent import CommEffectEvent + except ImportError: + logger.warn("compatible emane python bindings not installed") def convert_none(x): diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 9e9bce42..841c29dd 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -34,7 +34,12 @@ try: from emane.events import LocationEvent from emane.events.eventserviceexception import EventServiceException except ImportError: - logger.info("emane 1.2.1 not found") + try: + from emanesh.events import EventService + from emanesh.events import LocationEvent + from emanesh.events.eventserviceexception import EventServiceException + except ImportError: + logger.warn("compatible emane python bindings not installed") EMANE_MODELS = [ EmaneRfPipeModel, @@ -76,7 +81,7 @@ class EmaneManager(ConfigurableManager): self.transformport = self.session.get_config_item_int("emane_transform_port", 8200) self.doeventloop = False self.eventmonthread = None - self.logversion() + # model for global EMANE configuration options self.emane_config = EmaneGlobalModel(session, None) session.broker.handlers.add(self.handledistributed) @@ -86,24 +91,28 @@ class EmaneManager(ConfigurableManager): self.emane_config.name: self.emane_config } - # load provided models - self.load_models(EMANE_MODELS) - - # load custom models - custom_models_path = session.config.get("emane_models_dir") - if custom_models_path: - emane_models = utils.load_classes(custom_models_path, EmaneModel) - self.load_models(emane_models) - self.service = None + self.emane_check() - def logversion(self): + def emane_check(self): """ - Log the installed EMANE version. + Check if emane is installed and load models. + + :return: nothing """ try: + # check for emane emane_version = utils.check_cmd(["emane", "--version"]) logger.info("using EMANE: %s", emane_version) + + # load default emane models + self.load_models(EMANE_MODELS) + + # load custom models + custom_models_path = self.session.config.get("emane_models_dir") + if custom_models_path: + emane_models = utils.load_classes(custom_models_path, EmaneModel) + self.load_models(emane_models) except CoreCommandError: logger.info("emane is not installed") diff --git a/daemon/core/emane/emanemanifest.py b/daemon/core/emane/emanemanifest.py index e97349c6..15bdb535 100644 --- a/daemon/core/emane/emanemanifest.py +++ b/daemon/core/emane/emanemanifest.py @@ -1,10 +1,14 @@ from core import logger from core.enumerations import ConfigDataTypes +manifest = None try: from emane.shell import manifest except ImportError: - logger.info("emane 1.2.1 not found") + try: + from emanesh import manifest + except ImportError: + logger.warn("compatible emane python bindings not installed") def _type_value(config_type): @@ -77,6 +81,10 @@ def parse(manifest_path, defaults): :rtype: list """ + # no results when emane bindings are not present + if not manifest: + return [] + # load configuration file manifest_file = manifest.Manifest(manifest_path) manifest_configurations = manifest_file.getAllConfiguration() diff --git a/daemon/core/emane/nodes.py b/daemon/core/emane/nodes.py index adcc660b..bfe3e742 100644 --- a/daemon/core/emane/nodes.py +++ b/daemon/core/emane/nodes.py @@ -15,7 +15,10 @@ from core.enumerations import RegisterTlvs try: from emane.events import LocationEvent except ImportError: - logger.info("emane 1.2.1 not found") + try: + from emanesh.events import LocationEvent + except ImportError: + logger.warn("compatible emane python bindings not installed") class EmaneNet(PyCoreNet): diff --git a/gui/wlan.tcl b/gui/wlan.tcl index 05cb7bc6..b110a4aa 100644 --- a/gui/wlan.tcl +++ b/gui/wlan.tcl @@ -68,7 +68,7 @@ proc findWlanNodes { peer } { # # Returns 1 if the given interface is wireless proc isIfcWireless { node ifc } { - if { $ifc == "wireless" } { + if { $ifc == "wireless" } { # wireless peudo-interface return false } @@ -102,7 +102,7 @@ proc clearWlanLinks { wlan } { proc updateRangeCircles { wlan range } { global .c zoom g_selected_model set c .c - + set radius [expr {$zoom * $range/2}] $c delete -withtag rangecircles if { $radius == 0 } { @@ -171,7 +171,7 @@ proc getWlanColor { wlan } { if {[nodeType $node] != "wlan"} { continue } - if {$node == $wlan} { + if {$node == $wlan} { return [lindex $wlanLinkColors $colornum] } incr colornum @@ -180,7 +180,7 @@ proc getWlanColor { wlan } { # default color return [lindex $wlanLinkColors 0] } - + # move a node given incremental coordinates # dx dy should be adjusted for zoom proc moveNodeIncr { c node dx dy } { @@ -389,7 +389,7 @@ proc wlanConfigDialogHelper { wi target apply } { # use default model/values when none configured for this node if { $mobmodel == "" } { - set mobmodel $DEFAULT_WLAN_MODEL + set mobmodel $DEFAULT_WLAN_MODEL set vals $DEFAULT_WLAN_MODEL_VALS # look for customized range/bw/jitter/delay/per } else { @@ -473,7 +473,7 @@ proc wlanConfigDialogHelper { wi target apply } { -side left -padx 4 -pady 4 pack $de -side top -anchor w -padx 4 -pady 4 - # jitter frame + # jitter frame set jt $wi.wl.note.basic.jt ttk::frame $jt ttk::label $jt.label1 -anchor w -text "Jitter (us):" @@ -528,7 +528,7 @@ proc wlanConfigDialogHelper { wi target apply } { } if { ! $have_emane_models } { # show connection dialog box to indicate why there are no EMANE models - $mod.none configure -text "none - connection to CORE daemon required!" \ + $mod.none configure -text "Please install EMANE" \ -width "45" after 500 { update ;# allow dialog layout, otherwise strange results @@ -608,16 +608,16 @@ proc wlanConfigDialogHelper { wi target apply } { set cmd "linkSelectedNodes $target" button $wi.bottom.memb -text "Choose WLAN members" \ -command "popupSelectNodes \"$msg\" \"\" {$cmd}" - + # layout items - + pack $wi.bottom.ipv4.addrl $wi.bottom.ipv4.addrv -side left pack $wi.bottom.ipv4 -side top -anchor w pack $wi.bottom.ipv6.addrl $wi.bottom.ipv6.addrv -side left pack $wi.bottom.ipv6 -side top -anchor w pack $wi.bottom.script $wi.bottom.linkall $wi.bottom.memb \ -side left -anchor center - + pack $wi.bottom -side top -anchor w } From c65baa9298a807c38fd3a72dd398e72c778a674d Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 20 Apr 2018 21:40:55 -0700 Subject: [PATCH 135/152] update to add a way to avoid loading parent service classes, that inherit from CoreService that should not be loaded on their own --- daemon/core/service.py | 2 ++ daemon/core/services/bird.py | 2 +- daemon/core/services/nrl.py | 2 +- daemon/core/services/quagga.py | 2 +- daemon/core/services/sdn.py | 2 +- daemon/core/services/utility.py | 2 +- daemon/core/services/xorp.py | 2 +- 7 files changed, 8 insertions(+), 6 deletions(-) diff --git a/daemon/core/service.py b/daemon/core/service.py index 47e6eb99..9aadc03b 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -72,6 +72,8 @@ class ServiceManager(object): """ services = utils.load_classes(path, CoreService) for service in services: + if not service._name: + continue service.on_load() cls.add(service) diff --git a/daemon/core/services/bird.py b/daemon/core/services/bird.py index 34884e51..097053c4 100644 --- a/daemon/core/services/bird.py +++ b/daemon/core/services/bird.py @@ -90,7 +90,7 @@ class BirdService(CoreService): common to Bird's routing daemons. """ - _name = "BirdDaemon" + _name = None _group = "BIRD" _depends = ("bird",) _dirs = () diff --git a/daemon/core/services/nrl.py b/daemon/core/services/nrl.py index 6661ec49..5fe74ecd 100644 --- a/daemon/core/services/nrl.py +++ b/daemon/core/services/nrl.py @@ -13,7 +13,7 @@ class NrlService(CoreService): Parent class for NRL services. Defines properties and methods common to NRL's routing daemons. """"" - _name = "Protean" + _name = None _group = "ProtoSvc" _depends = () _dirs = () diff --git a/daemon/core/services/quagga.py b/daemon/core/services/quagga.py index ca6f0ad8..feb4eac7 100644 --- a/daemon/core/services/quagga.py +++ b/daemon/core/services/quagga.py @@ -222,7 +222,7 @@ class QuaggaService(CoreService): Parent class for Quagga services. Defines properties and methods common to Quagga's routing daemons. """ - _name = "QuaggaDaemon" + _name = None _group = "Quagga" _depends = ("zebra",) _dirs = () diff --git a/daemon/core/services/sdn.py b/daemon/core/services/sdn.py index 63ca610a..9d8a26ba 100644 --- a/daemon/core/services/sdn.py +++ b/daemon/core/services/sdn.py @@ -11,7 +11,7 @@ class SdnService(CoreService): """ Parent class for SDN services. """ - _name = "SdnProcess" + _name = None _group = "SDN" _depends = () _dirs = () diff --git a/daemon/core/services/utility.py b/daemon/core/services/utility.py index c0d3a931..e1495ca9 100644 --- a/daemon/core/services/utility.py +++ b/daemon/core/services/utility.py @@ -16,7 +16,7 @@ class UtilService(CoreService): """ Parent class for utility services. """ - _name = "UtilityProcess" + _name = None _group = "Utility" _depends = () _dirs = () diff --git a/daemon/core/services/xorp.py b/daemon/core/services/xorp.py index fff574ea..bbe58769 100644 --- a/daemon/core/services/xorp.py +++ b/daemon/core/services/xorp.py @@ -74,7 +74,7 @@ class XorpService(CoreService): Parent class for XORP services. Defines properties and methods common to XORP's routing daemons. """ - _name = "XorpDaemon" + _name = None _group = "XORP" _depends = ("xorp_rtrmgr",) _dirs = () From 1404ca19c5750ef482b4db508bb36b79df91a2bc Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 23 Apr 2018 15:46:08 -0700 Subject: [PATCH 136/152] added some test cases based on future api interactions, node add/delete/update link add/delete/update --- daemon/core/future/coreemu.py | 9 +- daemon/core/netns/vnode.py | 5 +- daemon/tests/test_future.py | 293 ++++++++++++++++++++++++++++++++++ 3 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 daemon/tests/test_future.py diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 704106a6..c1e08a26 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -303,8 +303,6 @@ class FutureSession(Session): :param core.data.LinkData link_data: data to create a link with :return: nothing """ - logger.info("link_data: %s", link_data) - # interface data interface_one_data, interface_two_data = get_interfaces(link_data) @@ -430,6 +428,8 @@ class FutureSession(Session): interface_two = common_interface_two break + logger.info("deleting link for interfaces interface_one(%s) interface_two(%s)", + interface_one, interface_two) if all([interface_one, interface_two]) and any([interface_one.net, interface_two.net]): if interface_one.net != interface_two.net and all([interface_one.up, interface_two.up]): raise ValueError("no common network found") @@ -438,8 +438,8 @@ class FutureSession(Session): interface_two.detachnet() if net_one.numnetif() == 0: self.delete_object(net_one.objid) - node_one.delnetif(interface_one_data.id) - node_two.delnetif(interface_two_data.id) + node_one.delnetif(interface_one.netindex) + node_two.delnetif(interface_two.netindex) finally: if node_one: node_one.lock.release() @@ -559,6 +559,7 @@ class FutureSession(Session): name = "%s%s" % (node_class.__name__, node_id) # create node + logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, node_id, name, start) node = self.add_object(cls=node_class, objid=node_id, name=name, start=start) # set node attributes diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index 49d4e79c..a874c692 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -110,7 +110,7 @@ class SimpleLxcNode(PyCoreNode): self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"]) # set hostname for node - logger.info("setting hostname: %s" % self.name) + logger.info("setting hostname: %s", self.name) self.check_cmd(["hostname", self.name]) # mark node as up @@ -214,7 +214,7 @@ class SimpleLxcNode(PyCoreNode): :raises CoreCommandError: when a non-zero exit status occurs """ source = os.path.abspath(source) - logger.info("mounting %s at %s" % (source, target)) + logger.info("mounting %s at %s", source, target) cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) status, output = self.client.shcmd_result(cmd) if status: @@ -567,7 +567,6 @@ class LxcNode(SimpleLxcNode): finally: self.rmnodedir() - # TODO: should change how this exception is just swallowed up def privatedir(self, path): """ Create a private directory. diff --git a/daemon/tests/test_future.py b/daemon/tests/test_future.py new file mode 100644 index 00000000..807133f7 --- /dev/null +++ b/daemon/tests/test_future.py @@ -0,0 +1,293 @@ +import os +import time + +import pytest + +from core.data import NodeData, LinkData +from core.enumerations import NodeTypes, EventTypes +from core.future.coreemu import CoreEmu, FutureIpv4Prefix +from core.misc import utils + + +@pytest.fixture +def future_session(): + # use coreemu and create a session + coreemu = CoreEmu() + session = coreemu.create_session(master=True) + session.set_state(EventTypes.CONFIGURATION_STATE.value) + + # return created session + yield session + + # shutdown coreemu + coreemu.shutdown() + + +MODELS = [ + "router", + "host", + "PC", + "mdr", +] + +NET_TYPES = [ + NodeTypes.SWITCH, + NodeTypes.HUB, + NodeTypes.WIRELESS_LAN +] + + +class TestFuture: + @pytest.mark.parametrize("model", MODELS) + def test_node_add(self, future_session, model): + # given + node_data = NodeData(node_type=NodeTypes.DEFAULT.value, model=model) + + # when + node_id = future_session.node_add(node_data) + + # give time for node services to boot + time.sleep(1) + + # then + node = future_session.get_object(node_id) + assert node + assert os.path.exists(node.nodedir) + assert node.alive() + assert node.up + assert node.check_cmd(["ip", "addr", "show", "lo"]) + node.validate() + + def test_node_update(self, future_session): + # given + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_id = future_session.node_add(node_data) + position_value = 100 + update_data = NodeData( + id=node_id, + x_position=position_value, + y_position=position_value + ) + + # when + future_session.node_update(update_data) + + # then + node = future_session.get_object(node_id) + assert node.position.x == position_value + assert node.position.y == position_value + + def test_node_delete(self, future_session): + # given + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_id = future_session.node_add(node_data) + + # when + future_session.node_delete(node_id) + + # then + with pytest.raises(KeyError): + future_session.get_object(node_id) + + @pytest.mark.parametrize("net_type", NET_TYPES) + def test_net(self, future_session, net_type): + # given + node_data = NodeData(node_type=net_type.value) + + # when + node_id = future_session.node_add(node_data) + + # then + node = future_session.get_object(node_id) + assert node + assert node.up + assert utils.check_cmd(["brctl", "show", node.brname]) + + def test_ptp(self, future_session): + # given + prefix = FutureIpv4Prefix("10.83.0.0/16") + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_one_id = future_session.node_add(node_data) + node_two_id = future_session.node_add(node_data) + + node_one = future_session.get_object(node_one_id) + inteface_one_index = node_one.newifindex() + address_one = prefix.addr(node_one_id) + + node_two = future_session.get_object(node_two_id) + inteface_two_index = node_two.newifindex() + address_two = prefix.addr(node_two_id) + + link_data = LinkData( + node1_id=node_one_id, + node2_id=node_two_id, + interface1_id=inteface_one_index, + interface1_ip4=str(address_one), + interface1_ip4_mask=prefix.prefixlen, + interface2_id=inteface_two_index, + interface2_ip4=str(address_two), + interface2_ip4_mask=prefix.prefixlen, + ) + + # when + future_session.link_add(link_data) + + # then + assert node_one.netif(inteface_one_index) + assert node_two.netif(inteface_two_index) + + def test_node_to_net(self, future_session): + # given + prefix = FutureIpv4Prefix("10.83.0.0/16") + + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_one = future_session.node_add(node_data) + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + node_two = future_session.node_add(node_data) + + node = future_session.get_object(node_one) + inteface_index = node.newifindex() + address = prefix.addr(node_one) + + link_data = LinkData( + node1_id=node_one, + node2_id=node_two, + interface1_id=inteface_index, + interface1_ip4=str(address), + interface1_ip4_mask=prefix.prefixlen, + ) + + # when + future_session.link_add(link_data) + + # then + node_two = future_session.get_object(node_two) + assert node_two.all_link_data(0) + assert node.netif(inteface_index) + + def test_net_to_node(self, future_session): + # given + prefix = FutureIpv4Prefix("10.83.0.0/16") + + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + node_one = future_session.node_add(node_data) + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_two = future_session.node_add(node_data) + + node = future_session.get_object(node_two) + inteface_index = node.newifindex() + address = prefix.addr(node_two) + + link_data = LinkData( + node1_id=node_one, + node2_id=node_two, + interface2_id=inteface_index, + interface2_ip4=str(address), + interface2_ip4_mask=prefix.prefixlen, + ) + + # when + future_session.link_add(link_data) + + # then + node_one = future_session.get_object(node_one) + assert node_one.all_link_data(0) + assert node.netif(inteface_index) + + def test_net_to_net(self, future_session): + # given + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + node_one = future_session.node_add(node_data) + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + node_two = future_session.node_add(node_data) + + link_data = LinkData( + node1_id=node_one, + node2_id=node_two, + ) + + # when + future_session.link_add(link_data) + + # then + node_one = future_session.get_object(node_one) + assert node_one.all_link_data(0) + + def test_link_update(self, future_session): + # given + prefix = FutureIpv4Prefix("10.83.0.0/16") + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_one = future_session.node_add(node_data) + node_data = NodeData(node_type=NodeTypes.SWITCH.value) + node_two = future_session.node_add(node_data) + node = future_session.get_object(node_one) + inteface_index = node.newifindex() + address = prefix.addr(node_one) + link_data = LinkData( + node1_id=node_one, + node2_id=node_two, + interface1_id=inteface_index, + interface1_ip4=str(address), + interface1_ip4_mask=prefix.prefixlen, + ) + future_session.link_add(link_data) + update_data = LinkData( + node1_id=node_one, + node2_id=node_two, + interface1_id=inteface_index, + delay=50, + bandwidth=5000000, + per=25, + dup=25 + ) + interface = node.netif(inteface_index) + output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) + assert "delay" not in output + assert "rate" not in output + assert "loss" not in output + assert "duplicate" not in output + + # when + future_session.link_update(update_data) + + # then + output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) + assert "delay" in output + assert "rate" in output + assert "loss" in output + assert "duplicate" in output + + def test_link_delete(self, future_session): + # given + prefix = FutureIpv4Prefix("10.83.0.0/16") + node_data = NodeData(node_type=NodeTypes.DEFAULT.value) + node_one_id = future_session.node_add(node_data) + node_two_id = future_session.node_add(node_data) + node_one = future_session.get_object(node_one_id) + inteface_one_index = node_one.newifindex() + address_one = prefix.addr(node_one_id) + node_two = future_session.get_object(node_two_id) + inteface_two_index = node_two.newifindex() + address_two = prefix.addr(node_two_id) + link_data = LinkData( + node1_id=node_one_id, + node2_id=node_two_id, + interface1_id=inteface_one_index, + interface1_ip4=str(address_one), + interface1_ip4_mask=prefix.prefixlen, + interface2_id=inteface_two_index, + interface2_ip4=str(address_two), + interface2_ip4_mask=prefix.prefixlen, + ) + future_session.link_add(link_data) + assert node_one.netif(inteface_one_index) + assert node_two.netif(inteface_two_index) + assert future_session.get_node_count() == 3 + + # when + future_session.link_delete(link_data) + + # then + assert not node_one.netif(inteface_one_index) + assert not node_two.netif(inteface_two_index) + assert future_session.get_node_count() == 2 From 3ea885e2eb670750cab9839f22314a7d2f2439ba Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 24 Apr 2018 16:24:54 -0700 Subject: [PATCH 137/152] refactored some future naming to be more consistent, added new data objects to pass into coreemu api to help make scripting easier, set sessions to master by default now --- daemon/core/future/coreemu.py | 302 ++++++++------------ daemon/core/future/futuredata.py | 225 +++++++++++++++ daemon/core/future/futurehandler.py | 151 +++++----- daemon/examples/future/emane80211.py | 9 +- daemon/examples/future/switch.py | 11 +- daemon/examples/future/switch_api.py | 35 +-- daemon/examples/future/switch_api_inject.py | 29 +- daemon/examples/future/wlan.py | 11 +- daemon/tests/test_future.py | 226 +++++---------- 9 files changed, 550 insertions(+), 449 deletions(-) create mode 100644 daemon/core/future/futuredata.py diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index c1e08a26..73e948a7 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -9,8 +9,8 @@ from core.coreobj import PyCoreNode, PyCoreNet from core.data import NodeData from core.emane.nodes import EmaneNode from core.enumerations import NodeTypes, EventTypes, LinkTypes +from core.future.futuredata import InterfaceData, LinkOptions from core.misc import nodeutils -from core.misc.ipaddress import Ipv4Prefix from core.netns.nodes import CoreNode from core.session import Session from core.xml.xmlparser import core_document_parser @@ -36,62 +36,13 @@ signal.signal(signal.SIGUSR1, signal_handler) signal.signal(signal.SIGUSR2, signal_handler) -class InterfaceData(object): - """ - Convenience class for storing interface data. - """ - - def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask): - """ - Creates an InterfaceData object. - - :param int _id: - :param str name: - :param str mac: - :param str ip4: - :param int ip4_mask: - :param str ip6: - :param int ip6_mask: - """ - self.id = _id - self.name = name - self.mac = mac - self.ip4 = ip4 - self.ip4_mask = ip4_mask - self.ip6 = ip6 - self.ip6_mask = ip6_mask - - def has_ip4(self): - return all([self.ip4, self.ip4_mask]) - - def has_ip6(self): - return all([self.ip6, self.ip6_mask]) - - def ip4_address(self): - if self.has_ip4(): - return "%s/%s" % (self.ip4, self.ip4_mask) - else: - return None - - def ip6_address(self): - if self.has_ip6(): - return "%s/%s" % (self.ip6, self.ip6_mask) - else: - return None - - def get_addresses(self): - ip4 = self.ip4_address() - ip6 = self.ip6_address() - return [i for i in [ip4, ip6] if i] - - def get_interfaces(link_data): """ Creates interface data objects for the interfaces defined within link data. :param core.data.LinkData link_data: data to create interface data from :return: interface one and two data - :rtype: tuple[InterfaceData] + :rtype: tuple[core.future.futuredata.InterfaceData] """ interface_one = InterfaceData( _id=link_data.interface1_id, @@ -120,7 +71,7 @@ def create_interface(node, network, interface_data): :param node: node to create interface for :param network: network to associate interface with - :param InterfaceData interface_data: interface data + :param core.future.futuredata.InterfaceData interface_data: interface data :return: created interface """ node.newnetif( @@ -133,24 +84,24 @@ def create_interface(node, network, interface_data): return node.netif(interface_data.id, network) -def link_config(network, interface, link_data, devname=None, interface_two=None): +def link_config(network, interface, link_options, devname=None, interface_two=None): """ Convenience method for configuring a link, :param network: network to configure link for :param interface: interface to configure - :param core.data.LinkData link_data: data to configure link with + :param core.future.futuredata.LinkOptions link_options: data to configure link with :param str devname: device name, default is None :param interface_two: other interface associated, default is None :return: nothing """ config = { "netif": interface, - "bw": link_data.bandwidth, - "delay": link_data.delay, - "loss": link_data.per, - "duplicate": link_data.dup, - "jitter": link_data.jitter, + "bw": link_options.bandwidth, + "delay": link_options.delay, + "loss": link_options.per, + "duplicate": link_options.dup, + "jitter": link_options.jitter, "netif2": interface_two } @@ -192,12 +143,6 @@ class IdGen(object): return self.id -class FutureIpv4Prefix(Ipv4Prefix): - def get_address(self, node_id): - address = self.addr(node_id) - return "%s/%s" % (address, self.prefixlen) - - class FutureSession(Session): def __init__(self, session_id, config=None, persistent=True, mkdir=True): super(FutureSession, self).__init__(session_id, config, persistent, mkdir) @@ -214,39 +159,37 @@ class FutureSession(Session): "host": ("DefaultRoute", "SSH"), } - def link_nodes(self, link_data): + def _link_nodes(self, node_one_id, node_two_id): """ Convenience method for retrieving nodes within link data. - :param core.data.LinkData link_data: data to retrieve nodes from - :return: nodes, network nodes if presetn, and tunnel + :param int node_one_id: node one id + :param int node_two_id: node two id + :return: nodes, network nodes if present, and tunnel if present :rtype: tuple """ - logger.info("link message between node1(%s:%s) and node2(%s:%s)", - link_data.node1_id, link_data.interface1_id, link_data.node2_id, link_data.interface2_id) + logger.info("link message between node1(%s) and node2(%s)", node_one_id, node_two_id) # values to fill net_one = None net_two = None # retrieve node one - n1_id = link_data.node1_id - n2_id = link_data.node2_id - node_one = self.get_object(n1_id) - node_two = self.get_object(n2_id) + node_one = self.get_object(node_one_id) + node_two = self.get_object(node_two_id) # both node ids are provided - tunnel = self.broker.gettunnel(n1_id, n2_id) + tunnel = self.broker.gettunnel(node_one_id, node_two_id) logger.info("tunnel between nodes: %s", tunnel) if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE): net_one = tunnel - if tunnel.remotenum == n1_id: + if tunnel.remotenum == node_one_id: node_one = None else: node_two = None # physical node connected via gre tap tunnel elif tunnel: - if tunnel.remotenum == n1_id: + if tunnel.remotenum == node_one_id: node_one = None else: node_two = None @@ -296,18 +239,19 @@ class FutureSession(Session): else: raise ValueError("no common network found for wireless link/unlink") - def link_add(self, link_data): + def add_link(self, node_one_id, node_two_id, interface_one=None, interface_two=None, link_options=LinkOptions()): """ Add a link between nodes. - :param core.data.LinkData link_data: data to create a link with - :return: nothing + :param int node_one_id: node one id + :param int node_two_id: node two id + :param core.future.futuredata.InterfaceData interface_one: node one interface data, defaults to none + :param core.future.futuredata.InterfaceData interface_two: node two interface data, defaults to none + :param core.future.futuredata.LinkOptions link_options: data for creating link, defaults to no options + :return: """ - # interface data - interface_one_data, interface_two_data = get_interfaces(link_data) - # get node objects identified by link data - node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id) if node_one: node_one.lock.acquire() @@ -316,7 +260,7 @@ class FutureSession(Session): try: # wireless link - if link_data.link_type == LinkTypes.WIRELESS.value: + if link_options.type == LinkTypes.WIRELESS: objects = [node_one, node_two, net_one, net_two] self._link_wireless(objects, connect=True) # wired link @@ -329,14 +273,14 @@ class FutureSession(Session): # node to network if node_one and net_one: - interface = create_interface(node_one, net_one, interface_one_data) - link_config(net_one, interface, link_data) + interface = create_interface(node_one, net_one, interface_one) + link_config(net_one, interface, link_options) # network to node if node_two and net_one: - interface = create_interface(node_two, net_one, interface_two_data) - if not link_data.unidirectional: - link_config(net_one, interface, link_data) + interface = create_interface(node_two, net_one, interface_two) + if not link_options.unidirectional: + link_config(net_one, interface, link_options) # network to network if net_one and net_two: @@ -345,23 +289,23 @@ class FutureSession(Session): else: interface = net_one.linknet(net_two) - link_config(net_one, interface, link_data) + link_config(net_one, interface, link_options) - if not link_data.unidirectional: + if not link_options.unidirectional: interface.swapparams("_params_up") - link_config(net_two, interface, link_data, devname=interface.name) + link_config(net_two, interface, link_options, devname=interface.name) interface.swapparams("_params_up") # a tunnel node was found for the nodes addresses = [] - if not node_one and net_one: - addresses.extend(interface_one_data.get_addresses()) + if not node_one and all([net_one, interface_one]): + addresses.extend(interface_one.get_addresses()) - if not node_two and net_two: - addresses.extend(interface_two_data.get_addresses()) + if not node_two and all([net_two, interface_two]): + addresses.extend(interface_two.get_addresses()) # tunnel node logic - key = link_data.key + key = link_options.key if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL): net_one.setkey(key) if addresses: @@ -374,31 +318,35 @@ class FutureSession(Session): # physical node connected with tunnel if not net_one and not net_two and (node_one or node_two): if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL): - addresses = interface_one_data.get_addresses() - node_one.adoptnetif(tunnel, link_data.interface1_id, link_data.interface1_mac, addresses) - link_config(node_one, tunnel, link_data) + addresses = interface_one.get_addresses() + node_one.adoptnetif(tunnel, interface_one.id, interface_one.mac, addresses) + link_config(node_one, tunnel, link_options) elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): - addresses = interface_two_data.get_addresses() - node_two.adoptnetif(tunnel, link_data.interface2_id, link_data.interface2_mac, addresses) - link_config(node_two, tunnel, link_data) + addresses = interface_two.get_addresses() + node_two.adoptnetif(tunnel, interface_two.id, interface_two.mac, addresses) + link_config(node_two, tunnel, link_options) finally: if node_one: node_one.lock.release() if node_two: node_two.lock.release() - def link_delete(self, link_data): + def delete_link(self, node_one_id, node_two_id, interface_one_id, interface_two_id, link_type=LinkTypes.WIRED): """ Delete a link between nodes. - :param core.data.LinkData link_data: data to delete link with + :param int node_one_id: node one id + :param int node_two_id: node two id + :param int interface_one_id: interface id for node one + :param int interface_two_id: interface id for node two + :param core.enumerations.LinkTypes link_type: link type to delete :return: nothing """ # interface data - interface_one_data, interface_two_data = get_interfaces(link_data) + # interface_one_data, interface_two_data = get_interfaces(link_data) # get node objects identified by link data - node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id) if node_one: node_one.lock.acquire() @@ -407,7 +355,7 @@ class FutureSession(Session): try: # wireless link - if link_data.link_type == LinkTypes.WIRELESS.value: + if link_type == LinkTypes.WIRELESS: objects = [node_one, node_two, net_one, net_two] self._link_wireless(objects, connect=False) # wired link @@ -415,8 +363,8 @@ class FutureSession(Session): if all([node_one, node_two]): # TODO: fix this for the case where ifindex[1,2] are not specified # a wired unlink event, delete the connecting bridge - interface_one = node_one.netif(interface_one_data.id) - interface_two = node_two.netif(interface_two_data.id) + interface_one = node_one.netif(interface_one_id) + interface_two = node_two.netif(interface_two_id) # get interfaces from common network, if no network node # otherwise get interfaces between a node and network @@ -446,18 +394,22 @@ class FutureSession(Session): if node_two: node_two.lock.release() - def link_update(self, link_data): + def update_link(self, node_one_id, node_two_id, link_options, interface_one_id=None, interface_two_id=None): """ Update link information between nodes. - :param core.data.LinkData link_data: data to update link with + :param int node_one_id: node one id + :param int node_two_id: node two id + :param int interface_one_id: interface id for node one + :param int interface_two_id: interface id for node two + :param core.future.futuredata.LinkOptions link_options: data to update link with :return: nothing """ # interface data - interface_one_data, interface_two_data = get_interfaces(link_data) + # interface_one_data, interface_two_data = get_interfaces(link_data) # get node objects identified by link data - node_one, node_two, net_one, net_two, tunnel = self.link_nodes(link_data) + node_one, node_two, net_one, net_two, tunnel = self._link_nodes(node_one_id, node_two_id) if node_one: node_one.lock.acquire() @@ -466,7 +418,7 @@ class FutureSession(Session): try: # wireless link - if link_data.link_type == LinkTypes.WIRELESS.value: + if link_options.type == LinkTypes.WIRELESS.value: raise ValueError("cannot update wireless link") else: if not node_one and not node_two: @@ -484,37 +436,37 @@ class FutureSession(Session): if upstream: interface.swapparams("_params_up") - link_config(net_one, interface, link_data, devname=interface.name) + link_config(net_one, interface, link_options, devname=interface.name) interface.swapparams("_params_up") else: - link_config(net_one, interface, link_data) + link_config(net_one, interface, link_options) - if not link_data.unidirectional: + if not link_options.unidirectional: if upstream: - link_config(net_two, interface, link_data) + link_config(net_two, interface, link_options) else: interface.swapparams("_params_up") - link_config(net_two, interface, link_data, devname=interface.name) + link_config(net_two, interface, link_options, devname=interface.name) interface.swapparams("_params_up") else: raise ValueError("modify link for unknown nodes") elif not node_one: # node1 = layer 2node, node2 = layer3 node - interface = node_two.netif(interface_two_data.id, net_one) - link_config(net_one, interface, link_data) + interface = node_two.netif(interface_two_id, net_one) + link_config(net_one, interface, link_options) elif not node_two: # node2 = layer 2node, node1 = layer3 node - interface = node_one.netif(interface_one_data.id, net_one) - link_config(net_one, interface, link_data) + interface = node_one.netif(interface_one_id, net_one) + link_config(net_one, interface, link_options) else: common_networks = node_one.commonnets(node_two) for net_one, interface_one, interface_two in common_networks: - if interface_one_data.id and interface_one_data.id != node_one.getifindex(interface_one): + if interface_one_id and interface_one_id != node_one.getifindex(interface_one): continue - link_config(net_one, interface_one, link_data, interface_two=interface_two) - if not link_data.unidirectional: - link_config(net_one, interface_two, link_data, interface_two=interface_one) + link_config(net_one, interface_one, link_options, interface_two=interface_two) + if not link_options.unidirectional: + link_config(net_one, interface_two, link_options, interface_two=interface_one) else: raise ValueError("no common network found") finally: @@ -523,30 +475,29 @@ class FutureSession(Session): if node_two: node_two.lock.release() - def node_add(self, node_data): + def add_node(self, node_options): """ Add a node to the session, based on the provided node data. - :param core.data.NodeData node_data: data to create node with - :return: nothing + :param core.future.futuredata.NodeOptions node_options: data to create node with + :return: created node """ # retrieve node class for given node type try: - node_type = NodeTypes(node_data.node_type) - node_class = nodeutils.get_node_class(node_type) + node_class = nodeutils.get_node_class(node_options.type) except KeyError: - logger.error("invalid node type to create: %s", node_data.node_type) + logger.error("invalid node type to create: %s", node_options.type) return None # set node start based on current session state, override and check when rj45 start = self.state > EventTypes.DEFINITION_STATE.value enable_rj45 = getattr(self.options, "enablerj45", "0") == "1" - if node_type == NodeTypes.RJ45 and not enable_rj45: + if node_options.type == NodeTypes.RJ45 and not enable_rj45: start = False # determine node id - node_id = node_data.id + node_id = node_options.id if not node_id: while True: node_id = self.node_id_gen.next() @@ -554,7 +505,7 @@ class FutureSession(Session): break # generate name if not provided - name = node_data.name + name = node_options.name if not name: name = "%s%s" % (node_class.__name__, node_id) @@ -563,18 +514,18 @@ class FutureSession(Session): node = self.add_object(cls=node_class, objid=node_id, name=name, start=start) # set node attributes - node.type = node_data.model or "router" - node.icon = node_data.icon - node.canvas = node_data.canvas - node.opaque = node_data.opaque + node.type = node_options.model or "router" + node.icon = node_options.icon + node.canvas = node_options.canvas + node.opaque = node_options.opaque # set node position and broadcast it - self.node_set_position(node, node_data) + self.set_node_position(node, node_options) # add services to default and physical nodes only - services = node_data.services - if node_type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: - logger.info("setting model (%s) with services (%s)", node.type, services) + if node_options.type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: + logger.info("setting model (%s) with services (%s)", node.type, node_options.services) + services = "|".join(node_options.services) or None self.services.addservicestonode(node, node.type, services) # boot nodes if created after runtime, LcxNodes, Physical, and RJ45 are all PyCoreNodes @@ -586,35 +537,35 @@ class FutureSession(Session): # TODO: common method to both Physical and LxcNodes, but not the common PyCoreNode node.boot() - # return node id, in case it was generated - return node_id + return node - def node_update(self, node_data): + def update_node(self, node_options): """ Update node information. - :param core.data.NodeData node_data: data to update node with + :param core.future.futuredata.NodeOptions node_options: data to update node with :return: nothing """ try: # get node to update - node = self.get_object(node_data.id) + node = self.get_object(node_options.id) # set node position and broadcast it - self.node_set_position(node, node_data) + self.set_node_position(node, node_options) # update attributes - node.canvas = node_data.canvas - node.icon = node_data.icon + node.canvas = node_options.canvas + node.icon = node_options.icon except KeyError: - logger.error("failure to update node that does not exist: %s", node_data.id) + logger.error("failure to update node that does not exist: %s", node_options.id) - def node_delete(self, node_id): + def delete_node(self, node_id): """ Delete a node from the session and check if session should shutdown, if no nodes are left. :param int node_id: :return: True if node deleted, False otherwise + :rtype: bool """ # delete node and check for session shutdown if a node was removed result = self.custom_delete_object(node_id) @@ -622,20 +573,20 @@ class FutureSession(Session): self.check_shutdown() return result - def node_set_position(self, node, node_data): + def set_node_position(self, node, node_options): """ Set position for a node, use lat/lon/alt if needed. :param node: node to set position for - :param NodeData node_data: data for node + :param core.future.futuredata.NodeOptions node_options: data for node :return: nothing """ # extract location values - x = node_data.x_position - y = node_data.y_position - lat = node_data.latitude - lon = node_data.longitude - alt = node_data.altitude + x = node_options.x + y = node_options.y + lat = node_options.lat + lon = node_options.lon + alt = node_options.alt # check if we need to generate position from lat/lon/alt has_empty_position = all(i is None for i in [x, y]) @@ -741,7 +692,7 @@ class FutureSession(Session): doc = core_document_writer(self, version) doc.writexml(file_name) - def hook_add(self, state, file_name, source_name, data): + def add_hook(self, state, file_name, source_name, data): """ Store a hook from a received file message. @@ -755,7 +706,7 @@ class FutureSession(Session): state = ":%s" % state self.set_hook(state, file_name, source_name, data) - def node_service_file(self, node_id, service_name, file_name, source_name, data): + def add_node_service_file(self, node_id, service_name, file_name, source_name, data): """ Add a service file for a node. @@ -770,7 +721,7 @@ class FutureSession(Session): service_name = ":%s" % service_name self.services.setservicefile(node_id, service_name, file_name, source_name, data) - def node_file(self, node_id, source_name, file_name, data): + def add_node_file(self, node_id, source_name, file_name, data): """ Add a file to a node. @@ -874,16 +825,16 @@ class FutureSession(Session): self.set_emane_model(emane_network, model) return emane_network - def set_emane_model(self, emane_node, model): + def set_emane_model(self, emane_node, emane_model): """ Set emane model for a given emane node. :param emane_node: emane node to set model for - :param model: emane model to set + :param emane_model: emane model to set :return: nothing """ - values = list(model.getdefaultvalues()) - self.emane.setconfig(emane_node.objid, model.name, values) + values = list(emane_model.getdefaultvalues()) + self.emane.setconfig(emane_node.objid, emane_model.name, values) class CoreEmu(object): @@ -921,7 +872,7 @@ class CoreEmu(object): session.shutdown() self.sessions.clear() - def create_session(self, _id=None, master=False): + def create_session(self, _id=None, master=True): """ Create a new CORE session, set to master if running standalone. @@ -981,15 +932,16 @@ class CoreEmu(object): for common_network, interface_one, interface_two in node.commonnets(network): common_network.link(interface_one, interface_two) - def add_interface(self, network, node, prefix): + def add_interface(self, network, node, prefixes): """ Convenience method for adding an interface with a prefix based on node id. :param network: network to add interface with :param node: node to add interface to - :param prefix: prefix to get address from for interface + :param core.future.futuredata.IpPrefixes prefixes: to get address from for interface :return: created interface """ - address = prefix.get_address(node.objid) - interface_index = node.newnetif(network, [address]) + interface_data = prefixes.create_interface(node) + logger.info("adding interface: %s", interface_data.get_addresses()) + interface_index = node.newnetif(network, interface_data.get_addresses(), ifindex=interface_data.id) return node.netif(interface_index) diff --git a/daemon/core/future/futuredata.py b/daemon/core/future/futuredata.py new file mode 100644 index 00000000..b23189ee --- /dev/null +++ b/daemon/core/future/futuredata.py @@ -0,0 +1,225 @@ +from core.enumerations import LinkTypes +from core.misc.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress + + +class NodeOptions(object): + """ + Options for creating and updating nodes within core. + """ + + def __init__(self, _type=None, _id=None, name=None, model=None): + """ + Create a NodeOptions object. + + :param core.enumerations.NodeType _type: type of node to create + :param int _id: id for node being created, defaults to generated id + :param str name: name of node, defaults to node class name postfix with its id + :param str model: model to use for this node, defines services + """ + self.id = _id + self.name = name + self.type = _type + self.model = model + self.canvas = None + self.icon = None + self.opaque = None + self.services = [] + self.x = None + self.y = None + self.lat = None + self.lon = None + self.alt = None + self.emulation_id = None + self.emulation_server = None + + def set_position(self, x, y): + """ + Convenience method for setting position. + + :param int x: x position + :param int y: y position + :return: nothing + """ + self.x = x + self.y = y + + def set_location(self, lat, lon, alt): + """ + Convenience method for setting location. + + :param float lat: latitude + :param float lon: longitude + :param float alt: altitude + :return: nothing + """ + self.lat = lat + self.lon = lon + self.alt = alt + + +class LinkOptions(object): + """ + Options for creating and updating links within core. + """ + + def __init__(self, _type=LinkTypes.WIRED): + """ + Create a LinkOptions object. + + :param core.enumerations.LinkTypes _type: type of link, defaults to wired + """ + self.type = _type + self.session = None + self.delay = None + self.bandwidth = None + self.per = None + self.dup = None + self.jitter = None + self.mer = None + self.burst = None + self.mburst = None + self.gui_attributes = None + self.unidirectional = None + self.emulation_id = None + self.network_id = None + self.key = None + self.opaque = None + + +class IpPrefixes(object): + """ + Convenience class to help generate IP4 and IP6 addresses for nodes within CORE. + """ + + def __init__(self, ip4_prefix=None, ip6_prefix=None): + """ + Creates an IpPrefixes object. + + :param str ip4_prefix: ip4 prefix to use for generation + :param str ip6_prefix: ip6 prefix to use for generation + :raises ValueError: when both ip4 and ip6 prefixes have not been provided + """ + if not ip4_prefix and not ip6_prefix: + raise ValueError("ip4 or ip6 must be provided") + + self.ip4 = None + if ip4_prefix: + self.ip4 = Ipv4Prefix(ip4_prefix) + self.ip6 = None + if ip6_prefix: + self.ip6 = Ipv6Prefix(ip6_prefix) + + def ip4_address(self, node): + """ + Convenience method to return the IP4 address for a node. + + :param node: node to get IP4 address for + :return: IP4 address or None + :rtype: str + """ + if not self.ip4: + raise ValueError("ip4 prefixes have not been set") + return str(self.ip4.addr(node.objid)) + + def ip6_address(self, node): + """ + Convenience method to return the IP6 address for a node. + + :param node: node to get IP6 address for + :return: IP4 address or None + :rtype: str + """ + if not self.ip6: + raise ValueError("ip6 prefixes have not been set") + return str(self.ip6.addr(node.objid)) + + def create_interface(self, node, name=None, mac=None): + """ + Creates interface data for linking nodes, using the nodes unique id for generation, along with a random + mac address, unless provided. + + :param core.coreobj.PyCoreNode node: node to create interface for + :param str name: name to set for interface, default is eth{id} + :param str mac: mac address to use for this interface, default is random generation + :return: new interface data for the provided node + :rtype: InterfaceData + """ + # interface id + inteface_id = node.newifindex() + + # generate ip4 data + ip4 = None + ip4_mask = None + if self.ip4: + ip4 = str(self.ip4.addr(node.objid)) + ip4_mask = self.ip4.prefixlen + + # generate ip6 data + ip6 = None + ip6_mask = None + if self.ip6: + ip6 = str(self.ip6.addr(node.objid)) + ip6_mask = self.ip6.prefixlen + + # random mac + if not mac: + mac = str(MacAddress.random()) + + return InterfaceData( + _id=inteface_id, + name=name, + ip4=ip4, + ip4_mask=ip4_mask, + ip6=ip6, + ip6_mask=ip6_mask, + mac=mac + ) + + +class InterfaceData(object): + """ + Convenience class for storing interface data. + """ + + def __init__(self, _id, name, mac, ip4, ip4_mask, ip6, ip6_mask): + """ + Creates an InterfaceData object. + + :param int _id: + :param str name: + :param str mac: + :param str ip4: + :param int ip4_mask: + :param str ip6: + :param int ip6_mask: + """ + self.id = _id + self.name = name + self.mac = mac + self.ip4 = ip4 + self.ip4_mask = ip4_mask + self.ip6 = ip6 + self.ip6_mask = ip6_mask + + def has_ip4(self): + return all([self.ip4, self.ip4_mask]) + + def has_ip6(self): + return all([self.ip6, self.ip6_mask]) + + def ip4_address(self): + if self.has_ip4(): + return "%s/%s" % (self.ip4, self.ip4_mask) + else: + return None + + def ip6_address(self): + if self.has_ip6(): + return "%s/%s" % (self.ip6, self.ip6_mask) + else: + return None + + def get_addresses(self): + ip4 = self.ip4_address() + ip6 = self.ip6_address() + return [i for i in [ip4, ip6] if i] diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py index da0d52d6..3f5a63e2 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/future/futurehandler.py @@ -14,10 +14,9 @@ import time from core import logger from core.api import coreapi from core.coreserver import CoreServer -from core.data import ConfigData, LinkData +from core.data import ConfigData from core.data import EventData -from core.data import NodeData -from core.enumerations import ConfigTlvs +from core.enumerations import ConfigTlvs, LinkTypes from core.enumerations import EventTlvs from core.enumerations import EventTypes from core.enumerations import ExceptionTlvs @@ -30,6 +29,7 @@ from core.enumerations import NodeTlvs from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.enumerations import SessionTlvs +from core.future.futuredata import NodeOptions, LinkOptions, InterfaceData from core.misc import nodeutils from core.misc import structutils from core.misc import utils @@ -566,7 +566,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): port = self.request.getpeername()[1] # TODO: add shutdown handler for session - self.session = self.coreemu.create_session(port) + self.session = self.coreemu.create_session(port, master=False) # self.session.shutdown_handlers.append(self.session_shutdown) logger.info("created new session for client: %s", self.session.session_id) @@ -642,44 +642,58 @@ class FutureHandler(SocketServer.BaseRequestHandler): logger.warn("ignoring invalid message: add and delete flag both set") return () - # create node data from message data - node_data = NodeData( - id=message.get_tlv(NodeTlvs.NUMBER.value), - x_position=message.get_tlv(NodeTlvs.X_POSITION.value), - y_position=message.get_tlv(NodeTlvs.Y_POSITION.value), - canvas=message.get_tlv(NodeTlvs.CANVAS.value), - icon=message.get_tlv(NodeTlvs.ICON.value), - latitude=message.get_tlv(NodeTlvs.LATITUDE.value), - longitude=message.get_tlv(NodeTlvs.LONGITUDE.value), - altitude=message.get_tlv(NodeTlvs.ALTITUDE.value), - node_type=message.get_tlv(NodeTlvs.TYPE.value), + node_type = None + node_type_value = message.get_tlv(NodeTlvs.TYPE.value) + if node_type_value is not None: + node_type = NodeTypes(node_type_value) + + node_options = NodeOptions( + _type=node_type, + _id=message.get_tlv(NodeTlvs.NUMBER.value), name=message.get_tlv(NodeTlvs.NAME.value), - model=message.get_tlv(NodeTlvs.MODEL.value), - opaque=message.get_tlv(NodeTlvs.OPAQUE.value), - services=message.get_tlv(NodeTlvs.SERVICES.value), + model=message.get_tlv(NodeTlvs.MODEL.value) ) + node_options.set_position( + x=message.get_tlv(NodeTlvs.X_POSITION.value), + y=message.get_tlv(NodeTlvs.Y_POSITION.value) + ) + + node_options.set_location( + lat=message.get_tlv(NodeTlvs.LATITUDE.value), + lon=message.get_tlv(NodeTlvs.LONGITUDE.value), + alt=message.get_tlv(NodeTlvs.ALTITUDE.value) + ) + + node_options.icon = message.get_tlv(NodeTlvs.ICON.value) + node_options.canvas = message.get_tlv(NodeTlvs.CANVAS.value) + node_options.opaque = message.get_tlv(NodeTlvs.OPAQUE.value) + + services = message.get_tlv(NodeTlvs.SERVICES.value) + if services: + node_options.services = services.split("|") + if message.flags & MessageFlags.ADD.value: - node_id = self.session.node_add(node_data) - if node_id: + node = self.session.add_node(node_options) + if node: if message.flags & MessageFlags.STRING.value: - self.node_status_request[node_id] = True + self.node_status_request[node.objid] = True if self.session.state == EventTypes.RUNTIME_STATE.value: - self.send_node_emulation_id(node_id) + self.send_node_emulation_id(node.objid) elif message.flags & MessageFlags.DELETE.value: with self._shutdown_lock: - result = self.session.node_delete(node_data.id) + result = self.session.delete_node(node_options.id) # if we deleted a node broadcast out its removal if result and message.flags & MessageFlags.STRING.value: tlvdata = "" - tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_data.id) + tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_options.id) flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata)) # node update else: - self.session.node_update(node_data) + self.session.update_node(node_options) return replies @@ -690,47 +704,56 @@ class FutureHandler(SocketServer.BaseRequestHandler): :param coreapi.CoreLinkMessage message: link message to handle :return: link message replies """ - link_data = LinkData( - session=message.get_tlv(LinkTlvs.SESSION.value), - link_type=message.get_tlv(LinkTlvs.TYPE.value), - node1_id=message.get_tlv(LinkTlvs.N1_NUMBER.value), - node2_id=message.get_tlv(LinkTlvs.N2_NUMBER.value), - delay=message.get_tlv(LinkTlvs.DELAY.value), - bandwidth=message.get_tlv(LinkTlvs.BANDWIDTH.value), - per=message.get_tlv(LinkTlvs.PER.value), - dup=message.get_tlv(LinkTlvs.DUP.value), - jitter=message.get_tlv(LinkTlvs.JITTER.value), - mer=message.get_tlv(LinkTlvs.MER.value), - burst=message.get_tlv(LinkTlvs.BURST.value), - mburst=message.get_tlv(LinkTlvs.MBURST.value), - gui_attributes=message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value), - unidirectional=message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value), - emulation_id=message.get_tlv(LinkTlvs.EMULATION_ID.value), - network_id=message.get_tlv(LinkTlvs.NETWORK_ID.value), - key=message.get_tlv(LinkTlvs.KEY.value), - opaque=message.get_tlv(LinkTlvs.OPAQUE.value), - interface1_id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value), - interface1_name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value), - interface1_ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value), - interface1_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value), - interface1_mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value), - interface1_ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value), - interface1_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value), - interface2_id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value), - interface2_name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value), - interface2_ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value), - interface2_ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value), - interface2_mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value), - interface2_ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value), - interface2_ip6_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP6_MASK.value), + node_one_id = message.get_tlv(LinkTlvs.N1_NUMBER.value) + node_two_id = message.get_tlv(LinkTlvs.N2_NUMBER.value) + + interface_one = InterfaceData( + _id=message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value), + name=message.get_tlv(LinkTlvs.INTERFACE1_NAME.value), + mac=message.get_tlv(LinkTlvs.INTERFACE1_MAC.value), + ip4=message.get_tlv(LinkTlvs.INTERFACE1_IP4.value), + ip4_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value), + ip6=message.get_tlv(LinkTlvs.INTERFACE1_IP6.value), + ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value), + ) + interface_two = InterfaceData( + _id=message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value), + name=message.get_tlv(LinkTlvs.INTERFACE2_NAME.value), + mac=message.get_tlv(LinkTlvs.INTERFACE2_MAC.value), + ip4=message.get_tlv(LinkTlvs.INTERFACE2_IP4.value), + ip4_mask=message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value), + ip6=message.get_tlv(LinkTlvs.INTERFACE2_IP6.value), + ip6_mask=message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value), ) + link_type = None + link_type_value = message.get_tlv(LinkTlvs.TYPE.value) + if link_type_value is not None: + link_type = LinkTypes(link_type_value) + + link_options = LinkOptions(_type=link_type) + link_options.delay = message.get_tlv(LinkTlvs.DELAY.value) + link_options.bandwidth = message.get_tlv(LinkTlvs.BANDWIDTH.value) + link_options.session = message.get_tlv(LinkTlvs.SESSION.value) + link_options.per = message.get_tlv(LinkTlvs.PER.value) + link_options.dup = message.get_tlv(LinkTlvs.DUP.value) + link_options.jitter = message.get_tlv(LinkTlvs.JITTER.value) + link_options.mer = message.get_tlv(LinkTlvs.MER.value) + link_options.burst = message.get_tlv(LinkTlvs.BURST.value) + link_options.mburst = message.get_tlv(LinkTlvs.MBURST.value) + link_options.gui_attributes = message.get_tlv(LinkTlvs.GUI_ATTRIBUTES.value) + link_options.unidirectional = message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value) + link_options.emulation_id = message.get_tlv(LinkTlvs.EMULATION_ID.value) + link_options.network_id = message.get_tlv(LinkTlvs.NETWORK_ID.value) + link_options.key = message.get_tlv(LinkTlvs.KEY.value) + link_options.opaque = message.get_tlv(LinkTlvs.OPAQUE.value) + if message.flags & MessageFlags.ADD.value: - self.session.link_add(link_data) + self.session.add_link(node_one_id, node_two_id, interface_one, interface_two, link_options) elif message.flags & MessageFlags.DELETE.value: - self.session.link_delete(link_data) + self.session.delete_link(node_one_id, node_two_id, interface_one.id, interface_two.id) else: - self.session.link_update(link_data) + self.session.update_link(node_one_id, node_two_id, interface_one.id, interface_two.id, link_options) return () @@ -829,7 +852,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): file_name = sys.argv[0] if os.path.splitext(file_name)[1].lower() == ".xml": - session = self.coreemu.create_session() + session = self.coreemu.create_session(master=False) try: session.open_xml(file_name, start=True) except: @@ -962,7 +985,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): if file_type is not None: if file_type.startswith("service:"): _, service_name = file_type.split(':')[:2] - self.session.node_service_file(node_num, service_name, file_name, source_name, data) + self.session.add_node_service_file(node_num, service_name, file_name, source_name, data) return () elif file_type.startswith("hook:"): _, state = file_type.split(':')[:2] @@ -970,7 +993,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): logger.error("error setting hook having state '%s'", state) return () state = int(state) - self.session.hook_add(state, file_name, source_name, data) + self.session.add_hook(state, file_name, source_name, data) return () # writing a file to the host diff --git a/daemon/examples/future/emane80211.py b/daemon/examples/future/emane80211.py index 66c9cd22..03bcd1cf 100644 --- a/daemon/examples/future/emane80211.py +++ b/daemon/examples/future/emane80211.py @@ -6,12 +6,13 @@ import datetime import parser from core.emane.ieee80211abg import EmaneIeee80211abgModel -from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes def example(options): # ip generator for example - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") # create emulator instance for creating sessions and utility methods coreemu = CoreEmu() @@ -27,8 +28,8 @@ def example(options): # create nodes for i in xrange(options.nodes): node = session.create_emane_node() - coreemu.add_interface(emane_network, node, prefix) node.setposition(x=150 * (i + 1), y=150) + coreemu.add_interface(emane_network, node, prefixes) # instantiate session session.instantiate() @@ -39,7 +40,7 @@ def example(options): # shutdown session raw_input("press enter to exit...") - session.shutdown() + coreemu.shutdown() def main(): diff --git a/daemon/examples/future/switch.py b/daemon/examples/future/switch.py index 7333d567..60ea4fb5 100644 --- a/daemon/examples/future/switch.py +++ b/daemon/examples/future/switch.py @@ -8,13 +8,14 @@ import datetime import parser -from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes from core.netns.nodes import CoreNode, SwitchNode def example(options): # ip generator for example - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes("10.83.0.0/16") # create emulator instance for creating sessions and utility methods coreemu = CoreEmu() @@ -26,7 +27,7 @@ def example(options): # create nodes for _ in xrange(options.nodes): node = session.create_node(cls=CoreNode) - coreemu.add_interface(switch_network, node, prefix) + coreemu.add_interface(switch_network, node, prefixes) # instantiate session session.instantiate() @@ -37,13 +38,13 @@ def example(options): print "starting iperf server on node: %s" % first_node.name first_node.cmd(["iperf", "-s", "-D"]) - address = str(prefix.addr(first_node.objid)) + address = prefixes.ip4_address(first_node) print "node %s connecting to %s" % (last_node.name, address) last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) first_node.cmd(["killall", "-9", "iperf"]) # shutdown session - session.shutdown() + coreemu.shutdown() def main(): diff --git a/daemon/examples/future/switch_api.py b/daemon/examples/future/switch_api.py index b95bd7db..8d9e64d3 100644 --- a/daemon/examples/future/switch_api.py +++ b/daemon/examples/future/switch_api.py @@ -8,41 +8,32 @@ import datetime import parser -from core.data import NodeData, LinkData from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes, NodeOptions def example(options): # ip generator for example - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") # create emulator instance for creating sessions and utility methods coreemu = CoreEmu() - session = coreemu.create_session(master=True) + session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below session.set_state(EventTypes.CONFIGURATION_STATE.value) # create switch network node - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - switch_id = session.node_add(node_data) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + switch = session.add_node(node_options) # create nodes for _ in xrange(options.nodes): - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_id = session.node_add(node_data) - node = session.get_object(node_id) - inteface_index = node.newifindex() - address = prefix.addr(node_id) - link_data = LinkData( - node1_id=node_id, - node2_id=switch_id, - interface1_id=inteface_index, - interface1_ip4=str(address), - interface1_ip4_mask=prefix.prefixlen, - ) - session.link_add(link_data) + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node = session.add_node(node_options) + interface = prefixes.create_interface(node) + session.add_link(node.objid, switch.objid, interface_one=interface) # instantiate session session.instantiate() @@ -53,9 +44,9 @@ def example(options): print "starting iperf server on node: %s" % first_node.name first_node.cmd(["iperf", "-s", "-D"]) - address = str(prefix.addr(first_node.objid)) - print "node %s connecting to %s" % (last_node.name, address) - last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) + first_node_address = prefixes.ip4_address(first_node) + print "node %s connecting to %s" % (last_node.name, first_node_address) + last_node.client.icmd(["iperf", "-t", str(options.time), "-c", first_node_address]) first_node.cmd(["killall", "-9", "iperf"]) # shutdown session diff --git a/daemon/examples/future/switch_api_inject.py b/daemon/examples/future/switch_api_inject.py index 1dabd0b0..9444ef65 100644 --- a/daemon/examples/future/switch_api_inject.py +++ b/daemon/examples/future/switch_api_inject.py @@ -5,17 +5,13 @@ # and repeat for minnodes <= n <= maxnodes with a step size of # nodestep -import datetime - -import parser -from core.data import NodeData, LinkData from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.future.futuredata import IpPrefixes, NodeOptions def example(nodes): # ip generator for example - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes("10.83.0.0/16") # create emulator instance for creating sessions and utility methods coreemu = globals()["coreemu"] @@ -25,24 +21,15 @@ def example(nodes): session.set_state(EventTypes.CONFIGURATION_STATE.value) # create switch network node - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - switch_id = session.node_add(node_data) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + switch = session.add_node(node_options) # create nodes for _ in xrange(nodes): - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_id = session.node_add(node_data) - node = session.get_object(node_id) - inteface_index = node.newifindex() - address = prefix.addr(node_id) - link_data = LinkData( - node1_id=node_id, - node2_id=switch_id, - interface1_id=inteface_index, - interface1_ip4=str(address), - interface1_ip4_mask=prefix.prefixlen, - ) - session.link_add(link_data) + node_options = NodeOptions(_type=NodeTypes.DEFAULT.value) + node = session.add_node(node_options) + interface = prefixes.create_interface(node) + session.add_link(node.objid, switch.objid, interface_one=interface) # instantiate session session.instantiate() diff --git a/daemon/examples/future/wlan.py b/daemon/examples/future/wlan.py index efbd725c..1e766846 100644 --- a/daemon/examples/future/wlan.py +++ b/daemon/examples/future/wlan.py @@ -8,14 +8,15 @@ import datetime import parser -from core.future.coreemu import FutureIpv4Prefix, CoreEmu +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes from core.mobility import BasicRangeModel from core.netns.nodes import WlanNode, CoreNode def example(options): # ip generator for example - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes("10.83.0.0/16") # create emulator instance for creating sessions and utility methods coreemu = CoreEmu() @@ -29,7 +30,7 @@ def example(options): wireless_nodes = [] for _ in xrange(options.nodes): node = session.create_node(cls=CoreNode) - coreemu.add_interface(wlan_network, node, prefix) + coreemu.add_interface(wlan_network, node, prefixes) wireless_nodes.append(node) # link all created nodes with the wireless network @@ -44,13 +45,13 @@ def example(options): print "starting iperf server on node: %s" % first_node.name first_node.cmd(["iperf", "-s", "-D"]) - address = str(prefix.addr(first_node.objid)) + address = prefixes.ip4_address(first_node) print "node %s connecting to %s" % (last_node.name, address) last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) first_node.cmd(["killall", "-9", "iperf"]) # shutdown session - session.shutdown() + coreemu.shutdown() def main(): diff --git a/daemon/tests/test_future.py b/daemon/tests/test_future.py index 807133f7..7bf4d0f3 100644 --- a/daemon/tests/test_future.py +++ b/daemon/tests/test_future.py @@ -3,9 +3,9 @@ import time import pytest -from core.data import NodeData, LinkData from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import CoreEmu, FutureIpv4Prefix +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes, NodeOptions, LinkOptions from core.misc import utils @@ -13,7 +13,7 @@ from core.misc import utils def future_session(): # use coreemu and create a session coreemu = CoreEmu() - session = coreemu.create_session(master=True) + session = coreemu.create_session() session.set_state(EventTypes.CONFIGURATION_STATE.value) # return created session @@ -41,16 +41,15 @@ class TestFuture: @pytest.mark.parametrize("model", MODELS) def test_node_add(self, future_session, model): # given - node_data = NodeData(node_type=NodeTypes.DEFAULT.value, model=model) + node_options = NodeOptions(_type=NodeTypes.DEFAULT, model=model) # when - node_id = future_session.node_add(node_data) + node = future_session.add_node(node_options) # give time for node services to boot time.sleep(1) # then - node = future_session.get_object(node_id) assert node assert os.path.exists(node.nodedir) assert node.alive() @@ -60,187 +59,116 @@ class TestFuture: def test_node_update(self, future_session): # given - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_id = future_session.node_add(node_data) + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node = future_session.add_node(node_options) position_value = 100 - update_data = NodeData( - id=node_id, - x_position=position_value, - y_position=position_value - ) + update_options = NodeOptions(_id=node.objid) + update_options.set_position(x=position_value, y=position_value) # when - future_session.node_update(update_data) + future_session.update_node(update_options) # then - node = future_session.get_object(node_id) assert node.position.x == position_value assert node.position.y == position_value def test_node_delete(self, future_session): # given - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_id = future_session.node_add(node_data) + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node = future_session.add_node(node_options) # when - future_session.node_delete(node_id) + future_session.delete_node(node.objid) # then with pytest.raises(KeyError): - future_session.get_object(node_id) + future_session.get_object(node.objid) @pytest.mark.parametrize("net_type", NET_TYPES) def test_net(self, future_session, net_type): # given - node_data = NodeData(node_type=net_type.value) + node_options = NodeOptions(_type=net_type) # when - node_id = future_session.node_add(node_data) + node = future_session.add_node(node_options) # then - node = future_session.get_object(node_id) assert node assert node.up assert utils.check_cmd(["brctl", "show", node.brname]) def test_ptp(self, future_session): # given - prefix = FutureIpv4Prefix("10.83.0.0/16") - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_one_id = future_session.node_add(node_data) - node_two_id = future_session.node_add(node_data) - - node_one = future_session.get_object(node_one_id) - inteface_one_index = node_one.newifindex() - address_one = prefix.addr(node_one_id) - - node_two = future_session.get_object(node_two_id) - inteface_two_index = node_two.newifindex() - address_two = prefix.addr(node_two_id) - - link_data = LinkData( - node1_id=node_one_id, - node2_id=node_two_id, - interface1_id=inteface_one_index, - interface1_ip4=str(address_one), - interface1_ip4_mask=prefix.prefixlen, - interface2_id=inteface_two_index, - interface2_ip4=str(address_two), - interface2_ip4_mask=prefix.prefixlen, - ) + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node_one = future_session.add_node(node_options) + node_two = future_session.add_node(node_options) + interface_one = prefixes.create_interface(node_one) + inteface_two = prefixes.create_interface(node_two) # when - future_session.link_add(link_data) + future_session.add_link(node_one.objid, node_two.objid, interface_one, inteface_two) # then - assert node_one.netif(inteface_one_index) - assert node_two.netif(inteface_two_index) + assert node_one.netif(interface_one.id) + assert node_two.netif(inteface_two.id) def test_node_to_net(self, future_session): # given - prefix = FutureIpv4Prefix("10.83.0.0/16") - - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_one = future_session.node_add(node_data) - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - node_two = future_session.node_add(node_data) - - node = future_session.get_object(node_one) - inteface_index = node.newifindex() - address = prefix.addr(node_one) - - link_data = LinkData( - node1_id=node_one, - node2_id=node_two, - interface1_id=inteface_index, - interface1_ip4=str(address), - interface1_ip4_mask=prefix.prefixlen, - ) + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node_one = future_session.add_node(node_options) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + node_two = future_session.add_node(node_options) + interface_one = prefixes.create_interface(node_one) # when - future_session.link_add(link_data) + future_session.add_link(node_one.objid, node_two.objid, interface_one) # then - node_two = future_session.get_object(node_two) assert node_two.all_link_data(0) - assert node.netif(inteface_index) + assert node_one.netif(interface_one.id) def test_net_to_node(self, future_session): # given - prefix = FutureIpv4Prefix("10.83.0.0/16") + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - node_one = future_session.node_add(node_data) - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_two = future_session.node_add(node_data) - - node = future_session.get_object(node_two) - inteface_index = node.newifindex() - address = prefix.addr(node_two) - - link_data = LinkData( - node1_id=node_one, - node2_id=node_two, - interface2_id=inteface_index, - interface2_ip4=str(address), - interface2_ip4_mask=prefix.prefixlen, - ) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + node_one = future_session.add_node(node_options) + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node_two = future_session.add_node(node_options) + interface_two = prefixes.create_interface(node_two) # when - future_session.link_add(link_data) + future_session.add_link(node_one.objid, node_two.objid, interface_two=interface_two) # then - node_one = future_session.get_object(node_one) assert node_one.all_link_data(0) - assert node.netif(inteface_index) + assert node_two.netif(interface_two.id) def test_net_to_net(self, future_session): # given - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - node_one = future_session.node_add(node_data) - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - node_two = future_session.node_add(node_data) - - link_data = LinkData( - node1_id=node_one, - node2_id=node_two, - ) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + node_one = future_session.add_node(node_options) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + node_two = future_session.add_node(node_options) # when - future_session.link_add(link_data) + future_session.add_link(node_one.objid, node_two.objid) # then - node_one = future_session.get_object(node_one) assert node_one.all_link_data(0) def test_link_update(self, future_session): # given - prefix = FutureIpv4Prefix("10.83.0.0/16") - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_one = future_session.node_add(node_data) - node_data = NodeData(node_type=NodeTypes.SWITCH.value) - node_two = future_session.node_add(node_data) - node = future_session.get_object(node_one) - inteface_index = node.newifindex() - address = prefix.addr(node_one) - link_data = LinkData( - node1_id=node_one, - node2_id=node_two, - interface1_id=inteface_index, - interface1_ip4=str(address), - interface1_ip4_mask=prefix.prefixlen, - ) - future_session.link_add(link_data) - update_data = LinkData( - node1_id=node_one, - node2_id=node_two, - interface1_id=inteface_index, - delay=50, - bandwidth=5000000, - per=25, - dup=25 - ) - interface = node.netif(inteface_index) + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node_one = future_session.add_node(node_options) + node_options = NodeOptions(_type=NodeTypes.SWITCH) + node_two = future_session.add_node(node_options) + interface_one = prefixes.create_interface(node_one) + future_session.add_link(node_one.objid, node_two.objid, interface_one) + interface = node_one.netif(interface_one.id) output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) assert "delay" not in output assert "rate" not in output @@ -248,7 +176,13 @@ class TestFuture: assert "duplicate" not in output # when - future_session.link_update(update_data) + link_options = LinkOptions() + link_options.delay = 50 + link_options.bandwidth = 5000000 + link_options.per = 25 + link_options.dup = 25 + future_session.update_link(node_one.objid, node_two.objid, + interface_one_id=interface_one.id, link_options=link_options) # then output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) @@ -259,35 +193,21 @@ class TestFuture: def test_link_delete(self, future_session): # given - prefix = FutureIpv4Prefix("10.83.0.0/16") - node_data = NodeData(node_type=NodeTypes.DEFAULT.value) - node_one_id = future_session.node_add(node_data) - node_two_id = future_session.node_add(node_data) - node_one = future_session.get_object(node_one_id) - inteface_one_index = node_one.newifindex() - address_one = prefix.addr(node_one_id) - node_two = future_session.get_object(node_two_id) - inteface_two_index = node_two.newifindex() - address_two = prefix.addr(node_two_id) - link_data = LinkData( - node1_id=node_one_id, - node2_id=node_two_id, - interface1_id=inteface_one_index, - interface1_ip4=str(address_one), - interface1_ip4_mask=prefix.prefixlen, - interface2_id=inteface_two_index, - interface2_ip4=str(address_two), - interface2_ip4_mask=prefix.prefixlen, - ) - future_session.link_add(link_data) - assert node_one.netif(inteface_one_index) - assert node_two.netif(inteface_two_index) + prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") + node_options = NodeOptions(_type=NodeTypes.DEFAULT) + node_one = future_session.add_node(node_options) + node_two = future_session.add_node(node_options) + interface_one = prefixes.create_interface(node_one) + interface_two = prefixes.create_interface(node_two) + future_session.add_link(node_one.objid, node_two.objid, interface_one, interface_two) + assert node_one.netif(interface_one.id) + assert node_two.netif(interface_two.id) assert future_session.get_node_count() == 3 # when - future_session.link_delete(link_data) + future_session.delete_link(node_one.objid, node_two.objid, interface_one.id, interface_two.id) # then - assert not node_one.netif(inteface_one_index) - assert not node_two.netif(inteface_two_index) + assert not node_one.netif(interface_one.id) + assert not node_two.netif(interface_two.id) assert future_session.get_node_count() == 2 From c0b450789a804c378450d9414020b05d4fe414e8 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 25 Apr 2018 10:55:48 -0700 Subject: [PATCH 138/152] updates to make future apis a bit better, updated handlers and all tests to account for changes --- daemon/core/future/coreemu.py | 64 +++++++++++-------- daemon/core/future/futuredata.py | 8 +-- daemon/core/future/futurehandler.py | 12 ++-- .../{emane80211.py => emane80211_api.py} | 7 +- daemon/examples/future/switch.py | 60 ----------------- daemon/examples/future/switch_api.py | 8 +-- daemon/examples/future/switch_api_inject.py | 10 ++- .../examples/future/{wlan.py => wlan_api.py} | 16 +++-- daemon/tests/test_future.py | 64 ++++++++----------- 9 files changed, 94 insertions(+), 155 deletions(-) rename daemon/examples/future/{emane80211.py => emane80211_api.py} (82%) delete mode 100644 daemon/examples/future/switch.py rename daemon/examples/future/{wlan.py => wlan_api.py} (76%) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 73e948a7..39ab6b00 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -7,11 +7,9 @@ import core.services from core import logger from core.coreobj import PyCoreNode, PyCoreNet from core.data import NodeData -from core.emane.nodes import EmaneNode from core.enumerations import NodeTypes, EventTypes, LinkTypes -from core.future.futuredata import InterfaceData, LinkOptions +from core.future.futuredata import InterfaceData, LinkOptions, NodeOptions from core.misc import nodeutils -from core.netns.nodes import CoreNode from core.session import Session from core.xml.xmlparser import core_document_parser from core.xml.xmlwriter import core_document_writer @@ -475,46 +473,47 @@ class FutureSession(Session): if node_two: node_two.lock.release() - def add_node(self, node_options): + def add_node(self, _type=NodeTypes.DEFAULT, _id=None, node_options=NodeOptions()): """ Add a node to the session, based on the provided node data. + :param core.enumerations.NodeTypes _type: type of node to create + :param int _id: id for node, defaults to None for generated id :param core.future.futuredata.NodeOptions node_options: data to create node with :return: created node """ # retrieve node class for given node type try: - node_class = nodeutils.get_node_class(node_options.type) + node_class = nodeutils.get_node_class(_type) except KeyError: - logger.error("invalid node type to create: %s", node_options.type) + logger.error("invalid node type to create: %s", _type) return None # set node start based on current session state, override and check when rj45 start = self.state > EventTypes.DEFINITION_STATE.value enable_rj45 = getattr(self.options, "enablerj45", "0") == "1" - if node_options.type == NodeTypes.RJ45 and not enable_rj45: + if _type == NodeTypes.RJ45 and not enable_rj45: start = False # determine node id - node_id = node_options.id - if not node_id: + if not _id: while True: - node_id = self.node_id_gen.next() - if node_id not in self.objects: + _id = self.node_id_gen.next() + if _id not in self.objects: break # generate name if not provided name = node_options.name if not name: - name = "%s%s" % (node_class.__name__, node_id) + name = "%s%s" % (node_class.__name__, _id) # create node - logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, node_id, name, start) - node = self.add_object(cls=node_class, objid=node_id, name=name, start=start) + logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, _id, name, start) + node = self.add_object(cls=node_class, objid=_id, name=name, start=start) # set node attributes - node.type = node_options.model or "router" + node.type = node_options.model node.icon = node_options.icon node.canvas = node_options.canvas node.opaque = node_options.opaque @@ -523,7 +522,7 @@ class FutureSession(Session): self.set_node_position(node, node_options) # add services to default and physical nodes only - if node_options.type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: + if _type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: logger.info("setting model (%s) with services (%s)", node.type, node_options.services) services = "|".join(node_options.services) or None self.services.addservicestonode(node, node.type, services) @@ -539,16 +538,19 @@ class FutureSession(Session): return node - def update_node(self, node_options): + def update_node(self, node_id, node_options): """ Update node information. + :param int node_id: id of node to update :param core.future.futuredata.NodeOptions node_options: data to update node with - :return: nothing + :return: True if node updated, False otherwise + :rtype: bool """ + result = False try: # get node to update - node = self.get_object(node_options.id) + node = self.get_object(node_id) # set node position and broadcast it self.set_node_position(node, node_options) @@ -556,14 +558,19 @@ class FutureSession(Session): # update attributes node.canvas = node_options.canvas node.icon = node_options.icon + + # set node as updated successfully + result = True except KeyError: logger.error("failure to update node that does not exist: %s", node_options.id) + return result + def delete_node(self, node_id): """ Delete a node from the session and check if session should shutdown, if no nodes are left. - :param int node_id: + :param int node_id: id of node to delete :return: True if node deleted, False otherwise :rtype: bool """ @@ -796,23 +803,26 @@ class FutureSession(Session): return node - def create_emane_node(self, name=None): + def create_emane_node(self, _id=None, node_options=NodeOptions()): """ Create an EMANE node for use within an EMANE network. - :param str name: name to five node - :return: CoreNode + :param int _id: int for node, defaults to None and will be generated + :param core.future.futuredata.NodeOptions node_options: options for emane node, model will always be "mdr" + :return: new emane node + :rtype: core.netns.nodes.CoreNode """ - return self.create_node(cls=CoreNode, name=name, model="mdr") + node_options.model = "mdr" + return self.add_node(_type=NodeTypes.DEFAULT, _id=_id, node_options=node_options) - def create_emane_network(self, model, geo_reference, geo_scale=None, name=None): + def create_emane_network(self, model, geo_reference, geo_scale=None, node_options=NodeOptions()): """ Convenience method for creating an emane network. :param model: emane model to use for emane network :param geo_reference: geo reference point to use for emane node locations :param geo_scale: geo scale to use for emane node locations, defaults to 1.0 - :param name: name for emane network, defaults to node class name + :param core.future.futuredata.NodeOptions node_options: options for emane node being created :return: create emane network """ # required to be set for emane to function properly @@ -821,7 +831,7 @@ class FutureSession(Session): self.location.refscale = geo_scale # create and return network - emane_network = self.create_node(cls=EmaneNode, name=name) + emane_network = self.add_node(_type=NodeTypes.EMANE, node_options=node_options) self.set_emane_model(emane_network, model) return emane_network diff --git a/daemon/core/future/futuredata.py b/daemon/core/future/futuredata.py index b23189ee..fac64bf2 100644 --- a/daemon/core/future/futuredata.py +++ b/daemon/core/future/futuredata.py @@ -7,18 +7,14 @@ class NodeOptions(object): Options for creating and updating nodes within core. """ - def __init__(self, _type=None, _id=None, name=None, model=None): + def __init__(self, name=None, model="router"): """ Create a NodeOptions object. - :param core.enumerations.NodeType _type: type of node to create - :param int _id: id for node being created, defaults to generated id :param str name: name of node, defaults to node class name postfix with its id - :param str model: model to use for this node, defines services + :param str model: model to use for this node, defines services, defaults to "router" """ - self.id = _id self.name = name - self.type = _type self.model = model self.canvas = None self.icon = None diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py index 3f5a63e2..3ea50e88 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/future/futurehandler.py @@ -647,9 +647,9 @@ class FutureHandler(SocketServer.BaseRequestHandler): if node_type_value is not None: node_type = NodeTypes(node_type_value) + node_id = message.get_tlv(NodeTlvs.NUMBER.value) + node_options = NodeOptions( - _type=node_type, - _id=message.get_tlv(NodeTlvs.NUMBER.value), name=message.get_tlv(NodeTlvs.NAME.value), model=message.get_tlv(NodeTlvs.MODEL.value) ) @@ -674,7 +674,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): node_options.services = services.split("|") if message.flags & MessageFlags.ADD.value: - node = self.session.add_node(node_options) + node = self.session.add_node(node_type, node_id, node_options) if node: if message.flags & MessageFlags.STRING.value: self.node_status_request[node.objid] = True @@ -683,17 +683,17 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.send_node_emulation_id(node.objid) elif message.flags & MessageFlags.DELETE.value: with self._shutdown_lock: - result = self.session.delete_node(node_options.id) + result = self.session.delete_node(node_id) # if we deleted a node broadcast out its removal if result and message.flags & MessageFlags.STRING.value: tlvdata = "" - tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_options.id) + tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_id) flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata)) # node update else: - self.session.update_node(node_options) + self.session.update_node(node_id, node_options) return replies diff --git a/daemon/examples/future/emane80211.py b/daemon/examples/future/emane80211_api.py similarity index 82% rename from daemon/examples/future/emane80211.py rename to daemon/examples/future/emane80211_api.py index 03bcd1cf..1b16bc96 100644 --- a/daemon/examples/future/emane80211.py +++ b/daemon/examples/future/emane80211_api.py @@ -6,6 +6,7 @@ import datetime import parser from core.emane.ieee80211abg import EmaneIeee80211abgModel +from core.enumerations import EventTypes from core.future.coreemu import CoreEmu from core.future.futuredata import IpPrefixes @@ -18,6 +19,9 @@ def example(options): coreemu = CoreEmu() session = coreemu.create_session() + # must be in configuration state for nodes to start, when using "node_add" below + session.set_state(EventTypes.CONFIGURATION_STATE.value) + # create emane network node emane_network = session.create_emane_network( model=EmaneIeee80211abgModel, @@ -29,7 +33,8 @@ def example(options): for i in xrange(options.nodes): node = session.create_emane_node() node.setposition(x=150 * (i + 1), y=150) - coreemu.add_interface(emane_network, node, prefixes) + interface = prefixes.create_interface(node) + session.add_link(node.objid, emane_network.objid, interface_one=interface) # instantiate session session.instantiate() diff --git a/daemon/examples/future/switch.py b/daemon/examples/future/switch.py deleted file mode 100644 index 60ea4fb5..00000000 --- a/daemon/examples/future/switch.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/python -# -# run iperf to measure the effective throughput between two nodes when -# n nodes are connected to a virtual wlan; run test for testsec -# and repeat for minnodes <= n <= maxnodes with a step size of -# nodestep - -import datetime - -import parser -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes -from core.netns.nodes import CoreNode, SwitchNode - - -def example(options): - # ip generator for example - prefixes = IpPrefixes("10.83.0.0/16") - - # create emulator instance for creating sessions and utility methods - coreemu = CoreEmu() - session = coreemu.create_session() - - # create switch network node - switch_network = session.create_node(cls=SwitchNode) - - # create nodes - for _ in xrange(options.nodes): - node = session.create_node(cls=CoreNode) - coreemu.add_interface(switch_network, node, prefixes) - - # instantiate session - session.instantiate() - - # get nodes to run example - first_node = session.get_object(2) - last_node = session.get_object(options.nodes + 1) - - print "starting iperf server on node: %s" % first_node.name - first_node.cmd(["iperf", "-s", "-D"]) - address = prefixes.ip4_address(first_node) - print "node %s connecting to %s" % (last_node.name, address) - last_node.client.icmd(["iperf", "-t", str(options.time), "-c", address]) - first_node.cmd(["killall", "-9", "iperf"]) - - # shutdown session - coreemu.shutdown() - - -def main(): - options = parser.parse_options("switch") - - start = datetime.datetime.now() - print "running switch example: nodes(%s) time(%s)" % (options.nodes, options.time) - example(options) - print "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__": - main() diff --git a/daemon/examples/future/switch_api.py b/daemon/examples/future/switch_api.py index 8d9e64d3..1dc914ec 100644 --- a/daemon/examples/future/switch_api.py +++ b/daemon/examples/future/switch_api.py @@ -10,7 +10,7 @@ import datetime import parser from core.enumerations import NodeTypes, EventTypes from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes, NodeOptions +from core.future.futuredata import IpPrefixes def example(options): @@ -25,13 +25,11 @@ def example(options): session.set_state(EventTypes.CONFIGURATION_STATE.value) # create switch network node - node_options = NodeOptions(_type=NodeTypes.SWITCH) - switch = session.add_node(node_options) + switch = session.add_node(_type=NodeTypes.SWITCH) # create nodes for _ in xrange(options.nodes): - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node = session.add_node(node_options) + node = session.add_node() interface = prefixes.create_interface(node) session.add_link(node.objid, switch.objid, interface_one=interface) diff --git a/daemon/examples/future/switch_api_inject.py b/daemon/examples/future/switch_api_inject.py index 9444ef65..215bddb8 100644 --- a/daemon/examples/future/switch_api_inject.py +++ b/daemon/examples/future/switch_api_inject.py @@ -6,7 +6,7 @@ # nodestep from core.enumerations import NodeTypes, EventTypes -from core.future.futuredata import IpPrefixes, NodeOptions +from core.future.futuredata import IpPrefixes def example(nodes): @@ -15,19 +15,17 @@ def example(nodes): # create emulator instance for creating sessions and utility methods coreemu = globals()["coreemu"] - session = coreemu.create_session(master=True) + session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below session.set_state(EventTypes.CONFIGURATION_STATE.value) # create switch network node - node_options = NodeOptions(_type=NodeTypes.SWITCH) - switch = session.add_node(node_options) + switch = session.add_node(_type=NodeTypes.SWITCH) # create nodes for _ in xrange(nodes): - node_options = NodeOptions(_type=NodeTypes.DEFAULT.value) - node = session.add_node(node_options) + node = session.add_node() interface = prefixes.create_interface(node) session.add_link(node.objid, switch.objid, interface_one=interface) diff --git a/daemon/examples/future/wlan.py b/daemon/examples/future/wlan_api.py similarity index 76% rename from daemon/examples/future/wlan.py rename to daemon/examples/future/wlan_api.py index 1e766846..ed34ca55 100644 --- a/daemon/examples/future/wlan.py +++ b/daemon/examples/future/wlan_api.py @@ -8,10 +8,10 @@ import datetime import parser +from core.enumerations import NodeTypes, EventTypes from core.future.coreemu import CoreEmu from core.future.futuredata import IpPrefixes from core.mobility import BasicRangeModel -from core.netns.nodes import WlanNode, CoreNode def example(options): @@ -22,19 +22,23 @@ def example(options): coreemu = CoreEmu() session = coreemu.create_session() + # must be in configuration state for nodes to start, when using "node_add" below + session.set_state(EventTypes.CONFIGURATION_STATE.value) + # create wlan network node - wlan_network = session.create_node(cls=WlanNode) - coreemu.set_wireless_model(wlan_network, BasicRangeModel) + wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN) + coreemu.set_wireless_model(wlan, BasicRangeModel) # create nodes wireless_nodes = [] for _ in xrange(options.nodes): - node = session.create_node(cls=CoreNode) - coreemu.add_interface(wlan_network, node, prefixes) + node = session.add_node() + interface = prefixes.create_interface(node) + session.add_link(node.objid, wlan.objid, interface_one=interface) wireless_nodes.append(node) # link all created nodes with the wireless network - coreemu.wireless_link_all(wlan_network, wireless_nodes) + coreemu.wireless_link_all(wlan, wireless_nodes) # instantiate session session.instantiate() diff --git a/daemon/tests/test_future.py b/daemon/tests/test_future.py index 7bf4d0f3..eae42799 100644 --- a/daemon/tests/test_future.py +++ b/daemon/tests/test_future.py @@ -23,6 +23,8 @@ def future_session(): coreemu.shutdown() +IP4_PREFIX = "10.83.0.0/16" + MODELS = [ "router", "host", @@ -41,10 +43,10 @@ class TestFuture: @pytest.mark.parametrize("model", MODELS) def test_node_add(self, future_session, model): # given - node_options = NodeOptions(_type=NodeTypes.DEFAULT, model=model) + node_options = NodeOptions(model=model) # when - node = future_session.add_node(node_options) + node = future_session.add_node(node_options=node_options) # give time for node services to boot time.sleep(1) @@ -59,14 +61,13 @@ class TestFuture: def test_node_update(self, future_session): # given - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node = future_session.add_node(node_options) + node = future_session.add_node() position_value = 100 - update_options = NodeOptions(_id=node.objid) + update_options = NodeOptions() update_options.set_position(x=position_value, y=position_value) # when - future_session.update_node(update_options) + future_session.update_node(node.objid, update_options) # then assert node.position.x == position_value @@ -74,8 +75,7 @@ class TestFuture: def test_node_delete(self, future_session): # given - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node = future_session.add_node(node_options) + node = future_session.add_node() # when future_session.delete_node(node.objid) @@ -87,10 +87,9 @@ class TestFuture: @pytest.mark.parametrize("net_type", NET_TYPES) def test_net(self, future_session, net_type): # given - node_options = NodeOptions(_type=net_type) # when - node = future_session.add_node(node_options) + node = future_session.add_node(_type=net_type) # then assert node @@ -99,10 +98,9 @@ class TestFuture: def test_ptp(self, future_session): # given - prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node_one = future_session.add_node(node_options) - node_two = future_session.add_node(node_options) + prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) + node_one = future_session.add_node() + node_two = future_session.add_node() interface_one = prefixes.create_interface(node_one) inteface_two = prefixes.create_interface(node_two) @@ -115,11 +113,9 @@ class TestFuture: def test_node_to_net(self, future_session): # given - prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node_one = future_session.add_node(node_options) - node_options = NodeOptions(_type=NodeTypes.SWITCH) - node_two = future_session.add_node(node_options) + prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) + node_one = future_session.add_node() + node_two = future_session.add_node(_type=NodeTypes.SWITCH) interface_one = prefixes.create_interface(node_one) # when @@ -131,12 +127,9 @@ class TestFuture: def test_net_to_node(self, future_session): # given - prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - - node_options = NodeOptions(_type=NodeTypes.SWITCH) - node_one = future_session.add_node(node_options) - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node_two = future_session.add_node(node_options) + prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) + node_one = future_session.add_node(_type=NodeTypes.SWITCH) + node_two = future_session.add_node() interface_two = prefixes.create_interface(node_two) # when @@ -148,10 +141,8 @@ class TestFuture: def test_net_to_net(self, future_session): # given - node_options = NodeOptions(_type=NodeTypes.SWITCH) - node_one = future_session.add_node(node_options) - node_options = NodeOptions(_type=NodeTypes.SWITCH) - node_two = future_session.add_node(node_options) + node_one = future_session.add_node(_type=NodeTypes.SWITCH) + node_two = future_session.add_node(_type=NodeTypes.SWITCH) # when future_session.add_link(node_one.objid, node_two.objid) @@ -161,11 +152,9 @@ class TestFuture: def test_link_update(self, future_session): # given - prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node_one = future_session.add_node(node_options) - node_options = NodeOptions(_type=NodeTypes.SWITCH) - node_two = future_session.add_node(node_options) + prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) + node_one = future_session.add_node() + node_two = future_session.add_node(_type=NodeTypes.SWITCH) interface_one = prefixes.create_interface(node_one) future_session.add_link(node_one.objid, node_two.objid, interface_one) interface = node_one.netif(interface_one.id) @@ -193,10 +182,9 @@ class TestFuture: def test_link_delete(self, future_session): # given - prefixes = IpPrefixes(ip4_prefix="10.83.0.0/16") - node_options = NodeOptions(_type=NodeTypes.DEFAULT) - node_one = future_session.add_node(node_options) - node_two = future_session.add_node(node_options) + prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) + node_one = future_session.add_node() + node_two = future_session.add_node() interface_one = prefixes.create_interface(node_one) interface_two = prefixes.create_interface(node_two) future_session.add_link(node_one.objid, node_two.objid, interface_one, interface_two) From f431895357c6e20ab4113fd3e9bcf5dfb8c9ae99 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 25 Apr 2018 11:55:47 -0700 Subject: [PATCH 139/152] removed unused code, updated delete session to shutdown session as well and return if session was deleted or not --- daemon/core/future/coreemu.py | 80 +++++------------------------ daemon/core/future/futurehandler.py | 6 --- 2 files changed, 12 insertions(+), 74 deletions(-) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 39ab6b00..5bb2859e 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -8,7 +8,7 @@ from core import logger from core.coreobj import PyCoreNode, PyCoreNet from core.data import NodeData from core.enumerations import NodeTypes, EventTypes, LinkTypes -from core.future.futuredata import InterfaceData, LinkOptions, NodeOptions +from core.future.futuredata import LinkOptions, NodeOptions from core.misc import nodeutils from core.session import Session from core.xml.xmlparser import core_document_parser @@ -34,35 +34,6 @@ signal.signal(signal.SIGUSR1, signal_handler) signal.signal(signal.SIGUSR2, signal_handler) -def get_interfaces(link_data): - """ - Creates interface data objects for the interfaces defined within link data. - - :param core.data.LinkData link_data: data to create interface data from - :return: interface one and two data - :rtype: tuple[core.future.futuredata.InterfaceData] - """ - interface_one = InterfaceData( - _id=link_data.interface1_id, - name=link_data.interface1_name, - mac=link_data.interface1_mac, - ip4=link_data.interface1_ip4, - ip4_mask=link_data.interface1_ip4_mask, - ip6=link_data.interface1_ip6, - ip6_mask=link_data.interface1_ip6_mask, - ) - interface_two = InterfaceData( - _id=link_data.interface2_id, - name=link_data.interface2_name, - mac=link_data.interface2_mac, - ip4=link_data.interface2_ip4, - ip4_mask=link_data.interface2_ip4_mask, - ip6=link_data.interface2_ip6, - ip6_mask=link_data.interface2_ip6_mask, - ) - return interface_one, interface_two - - def create_interface(node, network, interface_data): """ Create an interface for a node on a network using provided interface data. @@ -782,27 +753,6 @@ class FutureSession(Session): """ self.mobility.handleevent(event_data) - def create_node(self, cls, name=None, model=None): - """ - Create a node - - :param cls: - :param name: - :param model: - :return: - """ - object_id = self.node_id_gen.next() - - if not name: - name = "%s%s" % (cls.__name__, object_id) - - node = self.add_object(cls=cls, name=name, objid=object_id) - node.type = model - if node.type: - self.services.addservicestonode(node, node.type, services_str=None) - - return node - def create_emane_node(self, _id=None, node_options=NodeOptions()): """ Create an EMANE node for use within an EMANE network. @@ -909,16 +859,24 @@ class CoreEmu(object): def delete_session(self, _id): """ - Deletes a CORE session. + Shutdown and delete a CORE session. :param int _id: session id to delete - :return: nothing + :return: True if deleted, False otherwise + :rtype: bool """ logger.info("deleting session: %s", _id) session = self.sessions.pop(_id, None) - if not session: + result = False + if session: + logger.info("shutting session down: %s", _id) + session.shutdown() + result = True + else: logger.error("session to delete did not exist: %s", _id) + return result + def set_wireless_model(self, node, model): """ Convenience method for setting a wireless model. @@ -941,17 +899,3 @@ class CoreEmu(object): for node in nodes: for common_network, interface_one, interface_two in node.commonnets(network): common_network.link(interface_one, interface_two) - - def add_interface(self, network, node, prefixes): - """ - Convenience method for adding an interface with a prefix based on node id. - - :param network: network to add interface with - :param node: node to add interface to - :param core.future.futuredata.IpPrefixes prefixes: to get address from for interface - :return: created interface - """ - interface_data = prefixes.create_interface(node) - logger.info("adding interface: %s", interface_data.get_addresses()) - interface_index = node.newnetif(network, interface_data.get_addresses(), ifindex=interface_data.id) - return node.netif(interface_index) diff --git a/daemon/core/future/futurehandler.py b/daemon/core/future/futurehandler.py index 3ea50e88..7fb90a5a 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/future/futurehandler.py @@ -130,7 +130,6 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.session.broker.session_clients.remove(self) if not self.session.broker.session_clients and not self.session.is_active(): logger.info("no session clients left and not active, initiating shutdown") - self.session.shutdown() self.coreemu.delete_session(self.session.session_id) return SocketServer.BaseRequestHandler.finish(self) @@ -551,9 +550,6 @@ class FutureHandler(SocketServer.BaseRequestHandler): except IOError: logger.exception("error dispatching reply") - def session_shutdown(self, session): - self.coreemu.delete_session(session.session_id) - def handle(self): """ Handle a new connection request from a client. Dispatch to the @@ -856,7 +852,6 @@ class FutureHandler(SocketServer.BaseRequestHandler): try: session.open_xml(file_name, start=True) except: - session.shutdown() self.coreemu.delete_session(session.session_id) raise else: @@ -1189,7 +1184,6 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.remove_session_handlers() self.session.broker.session_clients.remove(self) if not self.session.broker.session_clients and not self.session.is_active(): - self.session.shutdown() self.coreemu.delete_session(self.session.session_id) # set session to join From 8644e9d61e9c3992646cc55a92e4c482369e7b74 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 25 Apr 2018 16:33:58 -0700 Subject: [PATCH 140/152] moved future core server and handler code to act as the default core-daemon, updated future examples and tests to leverage new api --- daemon/core/corehandlers.py | 1534 ----------------- daemon/core/coreserver.py | 263 --- daemon/core/future/coreemu.py | 67 +- daemon/core/legacy/__init__.py | 0 .../corehandler.py} | 52 +- .../futureserver.py => legacy/coreserver.py} | 14 +- daemon/core/session.py | 23 +- daemon/core/xml/xmlparser0.py | 2 +- daemon/examples/future/emane80211_api.py | 4 +- daemon/examples/future/switch_api.py | 2 +- daemon/examples/future/switch_api_inject.py | 2 +- daemon/examples/future/wlan_api.py | 6 +- daemon/examples/netns/daemonnodes.py | 2 +- daemon/examples/netns/distributed.py | 2 +- daemon/scripts/core-daemon | 40 +- daemon/scripts/core-future | 145 -- daemon/tests/conftest.py | 165 +- daemon/tests/test_core.py | 433 ++--- daemon/tests/test_emane.py | 44 +- daemon/tests/test_future.py | 201 --- daemon/tests/test_gui.py | 2 +- daemon/tests/test_links.py | 260 +++ daemon/tests/test_nodes.py | 79 + ns3/corens3/obj.py | 4 +- 24 files changed, 618 insertions(+), 2728 deletions(-) delete mode 100644 daemon/core/corehandlers.py delete mode 100644 daemon/core/coreserver.py create mode 100644 daemon/core/legacy/__init__.py rename daemon/core/{future/futurehandler.py => legacy/corehandler.py} (96%) rename daemon/core/{future/futureserver.py => legacy/coreserver.py} (64%) mode change 100755 => 100644 daemon/scripts/core-daemon delete mode 100644 daemon/scripts/core-future delete mode 100644 daemon/tests/test_future.py create mode 100644 daemon/tests/test_links.py create mode 100644 daemon/tests/test_nodes.py diff --git a/daemon/core/corehandlers.py b/daemon/core/corehandlers.py deleted file mode 100644 index 5e78a39f..00000000 --- a/daemon/core/corehandlers.py +++ /dev/null @@ -1,1534 +0,0 @@ -""" -socket server request handlers leveraged by core servers. -""" - -import Queue -import SocketServer -import os -import shlex -import shutil -import sys -import threading -import time - -from core import coreobj -from core import logger -from core.api import coreapi -from core.coreserver import CoreServer -from core.data import ConfigData -from core.data import EventData -from core.data import NodeData -from core.enumerations import ConfigTlvs -from core.enumerations import EventTlvs -from core.enumerations import EventTypes -from core.enumerations import ExceptionTlvs -from core.enumerations import ExecuteTlvs -from core.enumerations import FileTlvs -from core.enumerations import LinkTlvs -from core.enumerations import LinkTypes -from core.enumerations import MessageFlags -from core.enumerations import MessageTypes -from core.enumerations import NodeTlvs -from core.enumerations import NodeTypes -from core.enumerations import RegisterTlvs -from core.enumerations import SessionTlvs -from core.misc import nodeutils -from core.misc import structutils -from core.misc import utils -from core.netns import nodes -from core.xml.xmlsession import open_session_xml -from core.xml.xmlsession import save_session_xml - - -class CoreRequestHandler(SocketServer.BaseRequestHandler): - """ - The SocketServer class uses the RequestHandler class for servicing requests. - """ - - def __init__(self, request, client_address, server): - """ - Create a CoreRequestHandler instance. - - :param request: request object - :param str client_address: client address - :param CoreServer server: core server instance - :return: - """ - self.done = False - self.message_handlers = { - MessageTypes.NODE.value: self.handle_node_message, - MessageTypes.LINK.value: self.handle_link_message, - MessageTypes.EXECUTE.value: self.handle_execute_message, - MessageTypes.REGISTER.value: self.handle_register_message, - MessageTypes.CONFIG.value: self.handle_config_message, - MessageTypes.FILE.value: self.handle_file_message, - MessageTypes.INTERFACE.value: self.handle_interface_message, - MessageTypes.EVENT.value: self.handle_event_message, - MessageTypes.SESSION.value: self.handle_session_message, - } - self.message_queue = Queue.Queue() - self.node_status_request = {} - self._shutdown_lock = threading.Lock() - - self.handler_threads = [] - num_threads = int(server.config["numthreads"]) - if num_threads < 1: - raise ValueError("invalid number of threads: %s" % num_threads) - - logger.info("launching core server handler threads: %s", num_threads) - for _ in xrange(num_threads): - thread = threading.Thread(target=self.handler_thread) - self.handler_threads.append(thread) - thread.start() - - self.master = False - self.session = None - - utils.close_onexec(request.fileno()) - SocketServer.BaseRequestHandler.__init__(self, request, client_address, server) - - def setup(self): - """ - Client has connected, set up a new connection. - - :return: nothing - """ - logger.info("new TCP connection: %s", self.client_address) - - def finish(self): - """ - Client has disconnected, end this request handler and disconnect - from the session. Shutdown sessions that are not running. - - :return: nothing - """ - logger.info("finishing request handler") - self.done = True - - logger.info("remaining message queue size: %s", self.message_queue.qsize()) - # seconds - timeout = 10.0 - logger.info("client disconnected: notifying threads") - for thread in self.handler_threads: - logger.info("waiting for thread: %s", thread.getName()) - thread.join(timeout) - if thread.isAlive(): - logger.warn("joining %s failed: still alive after %s sec", thread.getName(), timeout) - - logger.info("connection closed: %s", self.client_address) - if self.session: - self.remove_session_handlers() - - # remove client from session broker and shutdown if there are no clients - self.session.broker.session_clients.remove(self) - if not self.session.broker.session_clients: - logger.info("no session clients left, initiating shutdown") - self.session.shutdown() - - return SocketServer.BaseRequestHandler.finish(self) - - def handle_broadcast_event(self, event_data): - """ - Callback to handle an event broadcast out from a session. - - :param core.data.EventData event_data: event data to handle - :return: nothing - """ - logger.info("handling broadcast event: %s", event_data) - - tlv_data = structutils.pack_values(coreapi.CoreEventTlv, [ - (EventTlvs.NODE, event_data.node), - (EventTlvs.TYPE, event_data.event_type), - (EventTlvs.NAME, event_data.name), - (EventTlvs.DATA, event_data.data), - (EventTlvs.TIME, event_data.time), - (EventTlvs.TIME, event_data.session) - ]) - message = coreapi.CoreEventMessage.pack(0, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending event message") - - def handle_broadcast_file(self, file_data): - """ - Callback to handle a file broadcast out from a session. - - :param core.data.FileData file_data: file data to handle - :return: nothing - """ - logger.info("handling broadcast file: %s", file_data) - - tlv_data = structutils.pack_values(coreapi.CoreFileTlv, [ - (FileTlvs.NODE, file_data.node), - (FileTlvs.NAME, file_data.name), - (FileTlvs.MODE, file_data.mode), - (FileTlvs.NUMBER, file_data.number), - (FileTlvs.TYPE, file_data.type), - (FileTlvs.SOURCE_NAME, file_data.source), - (FileTlvs.SESSION, file_data.session), - (FileTlvs.DATA, file_data.data), - (FileTlvs.COMPRESSED_DATA, file_data.compressed_data), - ]) - message = coreapi.CoreFileMessage.pack(file_data.message_type, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending file message") - - def handle_broadcast_config(self, config_data): - """ - Callback to handle a config broadcast out from a session. - - :param core.data.ConfigData config_data: config data to handle - :return: nothing - """ - logger.info("handling broadcast config: %s", config_data) - - tlv_data = structutils.pack_values(coreapi.CoreConfigTlv, [ - (ConfigTlvs.NODE, config_data.node), - (ConfigTlvs.OBJECT, config_data.object), - (ConfigTlvs.TYPE, config_data.type), - (ConfigTlvs.DATA_TYPES, config_data.data_types), - (ConfigTlvs.VALUES, config_data.data_values), - (ConfigTlvs.CAPTIONS, config_data.captions), - (ConfigTlvs.BITMAP, config_data.bitmap), - (ConfigTlvs.POSSIBLE_VALUES, config_data.possible_values), - (ConfigTlvs.GROUPS, config_data.groups), - (ConfigTlvs.SESSION, config_data.session), - (ConfigTlvs.INTERFACE_NUMBER, config_data.interface_number), - (ConfigTlvs.NETWORK_ID, config_data.network_id), - (ConfigTlvs.OPAQUE, config_data.opaque), - ]) - message = coreapi.CoreConfMessage.pack(config_data.message_type, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending config message") - - def handle_broadcast_exception(self, exception_data): - """ - Callback to handle an exception broadcast out from a session. - - :param core.data.ExceptionData exception_data: exception data to handle - :return: nothing - """ - logger.info("handling broadcast exception: %s", exception_data) - tlv_data = structutils.pack_values(coreapi.CoreExceptionTlv, [ - (ExceptionTlvs.NODE, exception_data.node), - (ExceptionTlvs.SESSION, exception_data.session), - (ExceptionTlvs.LEVEL, exception_data.level), - (ExceptionTlvs.SOURCE, exception_data.source), - (ExceptionTlvs.DATE, exception_data.date), - (ExceptionTlvs.TEXT, exception_data.text) - ]) - message = coreapi.CoreExceptionMessage.pack(0, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending exception message") - - def handle_broadcast_node(self, node_data): - """ - Callback to handle an node broadcast out from a session. - - :param core.data.NodeData node_data: node data to handle - :return: nothing - """ - logger.info("handling broadcast node: %s", node_data) - - tlv_data = structutils.pack_values(coreapi.CoreNodeTlv, [ - (NodeTlvs.NUMBER, node_data.id), - (NodeTlvs.TYPE, node_data.node_type), - (NodeTlvs.NAME, node_data.name), - (NodeTlvs.IP_ADDRESS, node_data.ip_address), - (NodeTlvs.MAC_ADDRESS, node_data.mac_address), - (NodeTlvs.IP6_ADDRESS, node_data.ip6_address), - (NodeTlvs.MODEL, node_data.model), - (NodeTlvs.EMULATION_ID, node_data.emulation_id), - (NodeTlvs.EMULATION_SERVER, node_data.emulation_server), - (NodeTlvs.SESSION, node_data.session), - (NodeTlvs.X_POSITION, node_data.x_position), - (NodeTlvs.Y_POSITION, node_data.y_position), - (NodeTlvs.CANVAS, node_data.canvas), - (NodeTlvs.NETWORK_ID, node_data.network_id), - (NodeTlvs.SERVICES, node_data.services), - (NodeTlvs.LATITUDE, node_data.latitude), - (NodeTlvs.LONGITUDE, node_data.longitude), - (NodeTlvs.ALTITUDE, node_data.altitude), - (NodeTlvs.ICON, node_data.icon), - (NodeTlvs.OPAQUE, node_data.opaque) - ]) - message = coreapi.CoreNodeMessage.pack(node_data.message_type, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending node message") - - def handle_broadcast_link(self, link_data): - """ - Callback to handle an link broadcast out from a session. - - :param core.data.LinkData link_data: link data to handle - :return: nothing - """ - logger.info("handling broadcast link: %s", link_data) - - tlv_data = structutils.pack_values(coreapi.CoreLinkTlv, [ - (LinkTlvs.N1_NUMBER, link_data.node1_id), - (LinkTlvs.N2_NUMBER, link_data.node2_id), - (LinkTlvs.DELAY, link_data.delay), - (LinkTlvs.BANDWIDTH, link_data.bandwidth), - (LinkTlvs.PER, link_data.per), - (LinkTlvs.DUP, link_data.dup), - (LinkTlvs.JITTER, link_data.jitter), - (LinkTlvs.MER, link_data.mer), - (LinkTlvs.BURST, link_data.burst), - (LinkTlvs.SESSION, link_data.session), - (LinkTlvs.MBURST, link_data.mburst), - (LinkTlvs.TYPE, link_data.link_type), - (LinkTlvs.GUI_ATTRIBUTES, link_data.gui_attributes), - (LinkTlvs.UNIDIRECTIONAL, link_data.unidirectional), - (LinkTlvs.EMULATION_ID, link_data.emulation_id), - (LinkTlvs.NETWORK_ID, link_data.network_id), - (LinkTlvs.KEY, link_data.key), - (LinkTlvs.INTERFACE1_NUMBER, link_data.interface1_id), - (LinkTlvs.INTERFACE1_NAME, link_data.interface1_name), - (LinkTlvs.INTERFACE1_IP4, link_data.interface1_ip4), - (LinkTlvs.INTERFACE1_IP4_MASK, link_data.interface1_ip4_mask), - (LinkTlvs.INTERFACE1_MAC, link_data.interface1_mac), - (LinkTlvs.INTERFACE1_IP6, link_data.interface1_ip6), - (LinkTlvs.INTERFACE1_IP6_MASK, link_data.interface1_ip6_mask), - (LinkTlvs.INTERFACE2_NUMBER, link_data.interface2_id), - (LinkTlvs.INTERFACE2_NAME, link_data.interface2_name), - (LinkTlvs.INTERFACE2_IP4, link_data.interface2_ip4), - (LinkTlvs.INTERFACE2_IP4_MASK, link_data.interface2_ip4_mask), - (LinkTlvs.INTERFACE2_MAC, link_data.interface2_mac), - (LinkTlvs.INTERFACE2_IP6, link_data.interface2_ip6), - (LinkTlvs.INTERFACE2_IP6_MASK, link_data.interface2_ip6_mask), - (LinkTlvs.OPAQUE, link_data.opaque) - ]) - - message = coreapi.CoreLinkMessage.pack(link_data.message_type, tlv_data) - - try: - self.sendall(message) - except IOError: - logger.exception("error sending Event Message") - - def register(self): - """ - Return a Register Message - - :return: register message data - """ - logger.info("GUI has connected to session %d at %s", self.session.session_id, time.ctime()) - - tlv_data = "" - tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, "core-daemon") - tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.EMULATION_SERVER.value, "core-daemon") - - # get config objects for session - for name in self.session.config_objects: - config_type, callback = self.session.config_objects[name] - # type must be in coreapi.reg_tlvs - tlv_data += coreapi.CoreRegisterTlv.pack(config_type, name) - - return coreapi.CoreRegMessage.pack(MessageFlags.ADD.value, tlv_data) - - def sendall(self, data): - """ - Send raw data to the other end of this TCP connection - using socket"s sendall(). - - :param data: data to send over request socket - :return: data sent - """ - return self.request.sendall(data) - - def receive_message(self): - """ - Receive data and return a CORE API message object. - - :return: received message - :rtype: coreapi.CoreMessage - """ - try: - header = self.request.recv(coreapi.CoreMessage.header_len) - except IOError as e: - raise IOError("error receiving header (%s)" % e) - - if len(header) != coreapi.CoreMessage.header_len: - if len(header) == 0: - raise EOFError("client disconnected") - else: - raise IOError("invalid message header size") - - message_type, message_flags, message_len = coreapi.CoreMessage.unpack_header(header) - if message_len == 0: - logger.warn("received message with no data") - - data = "" - while len(data) < message_len: - data += self.request.recv(message_len - len(data)) - if len(data) > message_len: - error_message = "received message length does not match received data (%s != %s)" % ( - len(data), message_len) - logger.error(error_message) - raise IOError(error_message) - - try: - message_class = coreapi.CLASS_MAP[message_type] - message = message_class(message_flags, header, data) - except KeyError: - message = coreapi.CoreMessage(message_flags, header, data) - message.message_type = message_type - logger.exception("unimplemented core message type: %s", message.type_str()) - - return message - - def queue_message(self, message): - """ - Queue an API message for later processing. - - :param message: message to queue - :return: nothing - """ - logger.info("queueing msg (queuedtimes = %s): type %s", - message.queuedtimes, MessageTypes(message.message_type)) - self.message_queue.put(message) - - def handler_thread(self): - """ - CORE API message handling loop that is spawned for each server - thread; get CORE API messages from the incoming message queue, - and call handlemsg() for processing. - - :return: nothing - """ - while not self.done: - message = self.message_queue.get() - self.handle_message(message) - - def handle_message(self, message): - """ - Handle an incoming message; dispatch based on message type, - optionally sending replies. - - :param message: message to handle - :return: nothing - """ - if self.session and self.session.broker.handle_message(message): - logger.info("message not being handled locally") - return - - logger.info("%s handling message:\n%s", threading.currentThread().getName(), message) - - if message.message_type not in self.message_handlers: - logger.warn("no handler for message type: %s", message.type_str()) - return - - message_handler = self.message_handlers[message.message_type] - - try: - # TODO: this needs to be removed, make use of the broadcast message methods - replies = message_handler(message) - self.dispatch_replies(replies, message) - except: - logger.exception("%s: exception while handling message: %s", - threading.currentThread().getName(), message) - - def dispatch_replies(self, replies, message): - """ - Dispatch replies by CORE to message msg previously received from the client. - - :param list replies: reply messages to dispatch - :param message: message for replies - :return: nothing - """ - logger.info("dispatching replies") - for reply in replies: - message_type, message_flags, message_length = coreapi.CoreMessage.unpack_header(reply) - try: - reply_message = coreapi.CLASS_MAP[message_type]( - message_flags, - reply[:coreapi.CoreMessage.header_len], - reply[coreapi.CoreMessage.header_len:] - ) - except KeyError: - # multiple TLVs of same type cause KeyError exception - reply_message = "CoreMessage (type %d flags %d length %d)" % ( - message_type, message_flags, message_length) - - logger.info("dispatch reply:\n%s", reply_message) - - try: - self.sendall(reply) - except IOError: - logger.exception("error dispatching reply") - - def handle(self): - """ - Handle a new connection request from a client. Dispatch to the - recvmsg() method for receiving data into CORE API messages, and - add them to an incoming message queue. - - :return: nothing - """ - # use port as session id - port = self.request.getpeername()[1] - - logger.info("creating new session for client: %s", port) - self.session = self.server.create_session(session_id=port) - - # TODO: hack to associate this handler with this sessions broker for broadcasting - # TODO: broker needs to be pulled out of session to the server/handler level - if self.master: - logger.info("session set to master") - self.session.master = True - self.session.broker.session_clients.append(self) - - # add handlers for various data - logger.info("adding session broadcast handlers") - self.add_session_handlers() - - # set initial session state - self.session.set_state(state=EventTypes.DEFINITION_STATE.value) - - while True: - try: - message = self.receive_message() - except EOFError: - logger.info("client disconnected") - break - except IOError: - logger.exception("error receiving message") - break - - message.queuedtimes = 0 - self.queue_message(message) - - # delay is required for brief connections, allow session joining - if message.message_type == MessageTypes.SESSION.value: - time.sleep(0.125) - - # broadcast node/link messages to other connected clients - if message.message_type not in [MessageTypes.NODE.value, MessageTypes.LINK.value]: - continue - - for client in self.session.broker.session_clients: - if client == self: - continue - - logger.info("BROADCAST TO OTHER CLIENT: %s", client) - client.sendall(message.raw_message) - - def add_session_handlers(self): - logger.info("adding session broadcast handlers") - self.session.event_handlers.append(self.handle_broadcast_event) - self.session.exception_handlers.append(self.handle_broadcast_exception) - self.session.node_handlers.append(self.handle_broadcast_node) - self.session.link_handlers.append(self.handle_broadcast_link) - self.session.file_handlers.append(self.handle_broadcast_file) - self.session.config_handlers.append(self.handle_broadcast_config) - - def remove_session_handlers(self): - logger.info("removing session broadcast handlers") - self.session.event_handlers.remove(self.handle_broadcast_event) - self.session.exception_handlers.remove(self.handle_broadcast_exception) - self.session.node_handlers.remove(self.handle_broadcast_node) - self.session.link_handlers.remove(self.handle_broadcast_link) - self.session.file_handlers.remove(self.handle_broadcast_file) - self.session.config_handlers.remove(self.handle_broadcast_config) - - def handle_node_message(self, message): - """ - Node Message handler - - :param coreapi.CoreNodeMessage message: node message - :return: replies to node message - """ - replies = [] - if message.flags & MessageFlags.ADD.value and message.flags & MessageFlags.DELETE.value: - logger.warn("ignoring invalid message: add and delete flag both set") - return () - - node_id = message.tlv_data[NodeTlvs.NUMBER.value] - x_position = message.get_tlv(NodeTlvs.X_POSITION.value) - y_position = message.get_tlv(NodeTlvs.Y_POSITION.value) - canvas = message.get_tlv(NodeTlvs.CANVAS.value) - icon = message.get_tlv(NodeTlvs.ICON.value) - lat = message.get_tlv(NodeTlvs.LATITUDE.value) - lng = message.get_tlv(NodeTlvs.LONGITUDE.value) - alt = message.get_tlv(NodeTlvs.ALTITUDE.value) - - if x_position is None and y_position is None and \ - lat is not None and lng is not None and alt is not None: - x, y, z = self.session.location.getxyz(float(lat), float(lng), float(alt)) - x_position = int(x) - y_position = int(y) - - # GUI can"t handle lat/long, so generate another X/Y position message - node_data = NodeData( - id=node_id, - x_position=x_position, - y_position=y_position - ) - - self.session.broadcast_node(node_data) - - if message.flags & MessageFlags.ADD.value: - node_type = message.tlv_data[NodeTlvs.TYPE.value] - try: - node_class = nodeutils.get_node_class(NodeTypes(node_type)) - except KeyError: - try: - node_type_str = " (%s)" % NodeTypes(node_type).name - except KeyError: - node_type_str = "" - - logger.warn("warning: unimplemented node type: %s%s" % (node_type, node_type_str)) - return () - - start = False - if self.session.state > EventTypes.DEFINITION_STATE.value: - start = True - - node_name = message.tlv_data[NodeTlvs.NAME.value] - model = message.get_tlv(NodeTlvs.MODEL.value) - class_args = {"start": start} - - if node_type == NodeTypes.RJ45.value and hasattr( - self.session.options, "enablerj45") and self.session.options.enablerj45 == "0": - class_args["start"] = False - - # this instantiates an object of class nodecls, creating the node or network - node = self.session.add_object(cls=node_class, objid=node_id, name=node_name, **class_args) - if x_position is not None and y_position is not None: - node.setposition(x_position, y_position, None) - if canvas is not None: - node.canvas = canvas - if icon is not None: - node.icon = icon - opaque = message.get_tlv(NodeTlvs.OPAQUE.value) - if opaque is not None: - node.opaque = opaque - - # add services to a node, either from its services TLV or - # through the configured defaults for this node type - if node_type in [NodeTypes.DEFAULT.value, NodeTypes.PHYSICAL.value]: - if model is None: - # TODO: default model from conf file? - model = "router" - node.type = model - services_str = message.get_tlv(NodeTlvs.SERVICES.value) - logger.info("setting model (%s) with services (%s)", model, services_str) - self.session.services.addservicestonode(node, model, services_str) - - # boot nodes if they are added after runtime (like - # session.bootnodes()) - if self.session.state == EventTypes.RUNTIME_STATE.value: - if isinstance(node, nodes.PyCoreNode) and not nodeutils.is_node(node, NodeTypes.RJ45): - self.session.write_objects() - self.session.add_remove_control_interface(node=node, remove=False) - node.boot() - - if message.flags & MessageFlags.STRING.value: - self.node_status_request[node_id] = True - self.send_node_emulation_id(node_id) - elif message.flags & MessageFlags.STRING.value: - self.node_status_request[node_id] = True - - elif message.flags & MessageFlags.DELETE.value: - with self._shutdown_lock: - self.session.delete_object(node_id) - - if message.flags & MessageFlags.STRING.value: - tlvdata = "" - tlvdata += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_id) - flags = MessageFlags.DELETE.value | MessageFlags.LOCAL.value - replies.append(coreapi.CoreNodeMessage.pack(flags, tlvdata)) - - if self.session.check_shutdown(): - tlvdata = "" - tlvdata += coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, self.session.state) - replies.append(coreapi.CoreEventMessage.pack(0, tlvdata)) - # Node modify message (no add/del flag) - else: - try: - node = self.session.get_object(node_id) - - if x_position is not None and y_position is not None: - node.setposition(x_position, y_position, None) - - if canvas is not None: - node.canvas = canvas - - if icon is not None: - node.icon = icon - except KeyError: - logger.exception("ignoring node message: unknown node number %s", node_id) - - return replies - - def handle_link_message(self, message): - """ - Link Message handler - - :param coreapi.CoreLinkMessage message: link message to handle - :return: link message replies - """ - # get node classes - ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER) - - node_num1 = message.get_tlv(LinkTlvs.N1_NUMBER.value) - interface_index1 = message.get_tlv(LinkTlvs.INTERFACE1_NUMBER.value) - ipv41 = message.get_tlv(LinkTlvs.INTERFACE1_IP4.value) - ipv4_mask1 = message.get_tlv(LinkTlvs.INTERFACE1_IP4_MASK.value) - mac1 = message.get_tlv(LinkTlvs.INTERFACE1_MAC.value) - ipv61 = message.get_tlv(LinkTlvs.INTERFACE1_IP6.value) - ipv6_mask1 = message.get_tlv(LinkTlvs.INTERFACE1_IP6_MASK.value) - interface_name1 = message.get_tlv(LinkTlvs.INTERFACE1_NAME.value) - - node_num2 = message.get_tlv(LinkTlvs.N2_NUMBER.value) - interface_index2 = message.get_tlv(LinkTlvs.INTERFACE2_NUMBER.value) - ipv42 = message.get_tlv(LinkTlvs.INTERFACE2_IP4.value) - ipv4_mask2 = message.get_tlv(LinkTlvs.INTERFACE2_IP4_MASK.value) - mac2 = message.get_tlv(LinkTlvs.INTERFACE2_MAC.value) - ipv62 = message.get_tlv(LinkTlvs.INTERFACE2_IP6.value) - ipv6_mask2 = message.get_tlv(LinkTlvs.INTERFACE2_IP6_MASK.value) - interface_name2 = message.get_tlv(LinkTlvs.INTERFACE2_NAME.value) - - node1 = None - node2 = None - net = None - net2 = None - - unidirectional_value = message.get_tlv(LinkTlvs.UNIDIRECTIONAL.value) - if unidirectional_value == 1: - unidirectional = True - else: - unidirectional = False - - # one of the nodes may exist on a remote server - logger.info("link message between node1(%s:%s) and node2(%s:%s)", - node_num1, interface_index1, node_num2, interface_index2) - if node_num1 is not None and node_num2 is not None: - tunnel = self.session.broker.gettunnel(node_num1, node_num2) - logger.info("tunnel between nodes: %s", tunnel) - if isinstance(tunnel, coreobj.PyCoreNet): - net = tunnel - if tunnel.remotenum == node_num1: - node_num1 = None - else: - node_num2 = None - # PhysicalNode connected via GreTap tunnel; uses adoptnetif() below - elif tunnel is not None: - if tunnel.remotenum == node_num1: - node_num1 = None - else: - node_num2 = None - - if node_num1 is not None: - try: - n = self.session.get_object(node_num1) - except KeyError: - # XXX wait and queue this message to try again later - # XXX maybe this should be done differently - time.sleep(0.125) - self.queue_message(message) - return () - if isinstance(n, nodes.PyCoreNode): - node1 = n - elif isinstance(n, coreobj.PyCoreNet): - if net is None: - net = n - else: - net2 = n - else: - raise ValueError("unexpected object class: %s" % n) - - if node_num2 is not None: - try: - n = self.session.get_object(node_num2) - except KeyError: - # XXX wait and queue this message to try again later - # XXX maybe this should be done differently - time.sleep(0.125) - self.queue_message(message) - return () - if isinstance(n, nodes.PyCoreNode): - node2 = n - elif isinstance(n, coreobj.PyCoreNet): - if net is None: - net = n - else: - net2 = n - else: - raise ValueError("unexpected object class: %s" % n) - - link_msg_type = message.get_tlv(LinkTlvs.TYPE.value) - - if node1: - node1.lock.acquire() - if node2: - node2.lock.acquire() - - try: - if link_msg_type == LinkTypes.WIRELESS.value: - """ - Wireless link/unlink event - """ - numwlan = 0 - objs = [node1, node2, net, net2] - objs = filter(lambda (x): x is not None, objs) - if len(objs) < 2: - raise ValueError("wireless link/unlink message between unknown objects") - - nets = objs[0].commonnets(objs[1]) - for netcommon, netif1, netif2 in nets: - if not nodeutils.is_node(netcommon, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): - continue - if message.flags & MessageFlags.ADD.value: - netcommon.link(netif1, netif2) - elif message.flags & MessageFlags.DELETE.value: - netcommon.unlink(netif1, netif2) - else: - raise ValueError("invalid flags for wireless link/unlink message") - numwlan += 1 - if numwlan == 0: - raise ValueError("no common network found for wireless link/unlink") - - elif message.flags & MessageFlags.ADD.value: - """ - Add a new link. - """ - start = False - if self.session.state > EventTypes.DEFINITION_STATE.value: - start = True - - if node1 and node2 and not net: - # a new wired link - net = self.session.add_object(cls=ptp_class, start=start) - - bw = message.get_tlv(LinkTlvs.BANDWIDTH.value) - delay = message.get_tlv(LinkTlvs.DELAY.value) - loss = message.get_tlv(LinkTlvs.PER.value) - duplicate = message.get_tlv(LinkTlvs.DUP.value) - jitter = message.get_tlv(LinkTlvs.JITTER.value) - key = message.get_tlv(LinkTlvs.KEY.value) - - netaddrlist = [] - if node1 and net: - addrlist = [] - if ipv41 is not None and ipv4_mask1 is not None: - addrlist.append("%s/%s" % (ipv41, ipv4_mask1)) - if ipv61 is not None and ipv6_mask1 is not None: - addrlist.append("%s/%s" % (ipv61, ipv6_mask1)) - if ipv42 is not None and ipv4_mask2 is not None: - netaddrlist.append("%s/%s" % (ipv42, ipv4_mask2)) - if ipv62 is not None and ipv6_mask2 is not None: - netaddrlist.append("%s/%s" % (ipv62, ipv6_mask2)) - interface_index1 = node1.newnetif( - net, addrlist=addrlist, - hwaddr=mac1, ifindex=interface_index1, ifname=interface_name1 - ) - net.linkconfig( - node1.netif(interface_index1, net), bw=bw, - delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter - ) - if node1 is None and net: - if ipv41 is not None and ipv4_mask1 is not None: - netaddrlist.append("%s/%s" % (ipv41, ipv4_mask1)) - # don"t add this address again if node2 and net - ipv41 = None - if ipv61 is not None and ipv6_mask1 is not None: - netaddrlist.append("%s/%s" % (ipv61, ipv6_mask1)) - # don"t add this address again if node2 and net - ipv61 = None - if node2 and net: - addrlist = [] - if ipv42 is not None and ipv4_mask2 is not None: - addrlist.append("%s/%s" % (ipv42, ipv4_mask2)) - if ipv62 is not None and ipv6_mask2 is not None: - addrlist.append("%s/%s" % (ipv62, ipv6_mask2)) - if ipv41 is not None and ipv4_mask1 is not None: - netaddrlist.append("%s/%s" % (ipv41, ipv4_mask1)) - if ipv61 is not None and ipv6_mask1 is not None: - netaddrlist.append("%s/%s" % (ipv61, ipv6_mask1)) - interface_index2 = node2.newnetif( - net, addrlist=addrlist, - hwaddr=mac2, ifindex=interface_index2, ifname=interface_name2 - ) - if not unidirectional: - net.linkconfig( - node2.netif(interface_index2, net), bw=bw, - delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter - ) - if node2 is None and net2: - if ipv42 is not None and ipv4_mask2 is not None: - netaddrlist.append("%s/%s" % (ipv42, ipv4_mask2)) - if ipv62 is not None and ipv6_mask2 is not None: - netaddrlist.append("%s/%s" % (ipv62, ipv6_mask2)) - - # tunnel node finalized with this link message - if key and nodeutils.is_node(net, NodeTypes.TUNNEL): - net.setkey(key) - if len(netaddrlist) > 0: - net.addrconfig(netaddrlist) - if key and nodeutils.is_node(net2, NodeTypes.TUNNEL): - net2.setkey(key) - if len(netaddrlist) > 0: - net2.addrconfig(netaddrlist) - - if net and net2: - # two layer-2 networks linked together - if nodeutils.is_node(net2, NodeTypes.RJ45): - # RJ45 nodes have different linknet() - netif = net2.linknet(net) - else: - netif = net.linknet(net2) - net.linkconfig(netif, bw=bw, delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter) - if not unidirectional: - netif.swapparams("_params_up") - net2.linkconfig(netif, bw=bw, delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter, - devname=netif.name) - netif.swapparams("_params_up") - elif net is None and net2 is None and (node1 is None or node2 is None): - # apply address/parameters to PhysicalNodes - fx = (bw, delay, loss, duplicate, jitter) - addrlist = [] - if node1 and nodeutils.is_node(node1, NodeTypes.PHYSICAL): - if ipv41 is not None and ipv4_mask1 is not None: - addrlist.append("%s/%s" % (ipv41, ipv4_mask1)) - if ipv61 is not None and ipv6_mask1 is not None: - addrlist.append("%s/%s" % (ipv61, ipv6_mask1)) - node1.adoptnetif(tunnel, interface_index1, mac1, addrlist) - node1.linkconfig(tunnel, bw, delay, loss, duplicate, jitter) - elif node2 and nodeutils.is_node(node2, NodeTypes.PHYSICAL): - if ipv42 is not None and ipv4_mask2 is not None: - addrlist.append("%s/%s" % (ipv42, ipv4_mask2)) - if ipv62 is not None and ipv6_mask2 is not None: - addrlist.append("%s/%s" % (ipv62, ipv6_mask2)) - node2.adoptnetif(tunnel, interface_index2, mac2, addrlist) - node2.linkconfig(tunnel, bw, delay, loss, duplicate, jitter) - # delete a link - elif message.flags & MessageFlags.DELETE.value: - """ - Remove a link. - """ - if node1 and node2: - # TODO: fix this for the case where ifindex[1,2] are not specified - # a wired unlink event, delete the connecting bridge - netif1 = node1.netif(interface_index1) - netif2 = node2.netif(interface_index2) - if netif1 is None and netif2 is None: - nets = node1.commonnets(node2) - for netcommon, tmp1, tmp2 in nets: - if (net and netcommon == net) or net is None: - netif1 = tmp1 - netif2 = tmp2 - break - - if all([netif1, netif2]) and any([netif1.net, netif2.net]): - if netif1.net != netif2.net and all([netif1.up, netif2.up]): - raise ValueError("no common network found") - net = netif1.net - netif1.detachnet() - netif2.detachnet() - if net.numnetif() == 0: - self.session.delete_object(net.objid) - node1.delnetif(interface_index1) - node2.delnetif(interface_index2) - else: - """ - Modify a link. - """ - bw = message.get_tlv(LinkTlvs.BANDWIDTH.value) - delay = message.get_tlv(LinkTlvs.DELAY.value) - loss = message.get_tlv(LinkTlvs.PER.value) - duplicate = message.get_tlv(LinkTlvs.DUP.value) - jitter = message.get_tlv(LinkTlvs.JITTER.value) - numnet = 0 - # TODO: clean up all this logic. Having the add flag or not - # should use the same code block. - if node1 is None and node2 is None: - if net and net2: - # modify link between nets - netif = net.getlinknetif(net2) - upstream = False - if netif is None: - upstream = True - netif = net2.getlinknetif(net) - if netif is None: - raise ValueError("modify unknown link between nets") - if upstream: - netif.swapparams("_params_up") - net.linkconfig(netif, bw=bw, delay=delay, - loss=loss, duplicate=duplicate, - jitter=jitter, devname=netif.name) - netif.swapparams("_params_up") - else: - net.linkconfig(netif, bw=bw, delay=delay, - loss=loss, duplicate=duplicate, - jitter=jitter) - if not unidirectional: - if upstream: - net2.linkconfig(netif, bw=bw, delay=delay, - loss=loss, - duplicate=duplicate, - jitter=jitter) - else: - netif.swapparams("_params_up") - net2.linkconfig(netif, bw=bw, delay=delay, - loss=loss, - duplicate=duplicate, - jitter=jitter, - devname=netif.name) - netif.swapparams("_params_up") - else: - raise ValueError("modify link for unknown nodes") - elif node1 is None: - # node1 = layer 2node, node2 = layer3 node - net.linkconfig(node2.netif(interface_index2, net), bw=bw, - delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter) - elif node2 is None: - # node2 = layer 2node, node1 = layer3 node - net.linkconfig(node1.netif(interface_index1, net), bw=bw, - delay=delay, loss=loss, - duplicate=duplicate, jitter=jitter) - else: - nets = node1.commonnets(node2) - for net, netif1, netif2 in nets: - if interface_index1 is not None and interface_index1 != node1.getifindex(netif1): - continue - net.linkconfig(netif1, bw=bw, delay=delay, - loss=loss, duplicate=duplicate, - jitter=jitter, netif2=netif2) - if not unidirectional: - net.linkconfig(netif2, bw=bw, delay=delay, - loss=loss, duplicate=duplicate, - jitter=jitter, netif2=netif1) - numnet += 1 - if numnet == 0: - raise ValueError("no common network found") - finally: - if node1: - node1.lock.release() - if node2: - node2.lock.release() - - return () - - def handle_execute_message(self, message): - """ - Execute Message handler - - :param coreapi.CoreExecMessage message: execute message to handle - :return: reply messages - """ - node_num = message.get_tlv(ExecuteTlvs.NODE.value) - execute_num = message.get_tlv(ExecuteTlvs.NUMBER.value) - execute_time = message.get_tlv(ExecuteTlvs.TIME.value) - command = message.get_tlv(ExecuteTlvs.COMMAND.value) - - # local flag indicates command executed locally, not on a node - if node_num is None and not message.flags & MessageFlags.LOCAL.value: - raise ValueError("Execute Message is missing node number.") - - if execute_num is None: - raise ValueError("Execute Message is missing execution number.") - - if execute_time is not None: - self.session.add_event(execute_time, node=node_num, name=None, data=command) - return () - - try: - node = self.session.get_object(node_num) - - # build common TLV items for reply - tlv_data = "" - if node_num is not None: - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.NODE.value, node_num) - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.NUMBER.value, execute_num) - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.COMMAND.value, command) - - if message.flags & MessageFlags.TTY.value: - if node_num is None: - raise NotImplementedError - # echo back exec message with cmd for spawning interactive terminal - if command == "bash": - command = "/bin/bash" - res = node.termcmdstring(command) - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) - reply = coreapi.CoreExecMessage.pack(MessageFlags.TTY.value, tlv_data) - return reply, - else: - logger.info("execute message with cmd=%s", command) - # execute command and send a response - if message.flags & MessageFlags.STRING.value or message.flags & MessageFlags.TEXT.value: - # shlex.split() handles quotes within the string - if message.flags & MessageFlags.LOCAL.value: - status, res = utils.cmd_output(command) - else: - status, res = node.cmd_output(command) - logger.info("done exec cmd=%s with status=%d res=(%d bytes)", command, status, len(res)) - if message.flags & MessageFlags.TEXT.value: - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.RESULT.value, res) - if message.flags & MessageFlags.STRING.value: - tlv_data += coreapi.CoreExecuteTlv.pack(ExecuteTlvs.STATUS.value, status) - reply = coreapi.CoreExecMessage.pack(0, tlv_data) - return reply, - # execute the command with no response - else: - if message.flags & MessageFlags.LOCAL.value: - utils.mute_detach(command) - else: - node.cmd(command, wait=False) - except KeyError: - logger.exception("error getting object: %s", node_num) - # XXX wait and queue this message to try again later - # XXX maybe this should be done differently - if not message.flags & MessageFlags.LOCAL.value: - time.sleep(0.125) - self.queue_message(message) - - return () - - def handle_register_message(self, message): - """ - Register Message Handler - - :param coreapi.CoreRegMessage message: register message to handle - :return: reply messages - """ - replies = [] - - # execute a Python script or XML file - execute_server = message.get_tlv(RegisterTlvs.EXECUTE_SERVER.value) - if execute_server: - try: - logger.info("executing: %s", execute_server) - if message.flags & MessageFlags.STRING.value: - old_session_ids = set(self.server.get_session_ids()) - sys.argv = shlex.split(execute_server) - file_name = sys.argv[0] - if os.path.splitext(file_name)[1].lower() == ".xml": - session = self.server.create_session() - try: - open_session_xml(session, file_name, start=True) - except: - session.shutdown() - self.server.remove_session(session) - raise - else: - thread = threading.Thread( - target=execfile, - args=(file_name, {"__file__": file_name, "server": self.server}) - ) - thread.daemon = True - thread.start() - # allow time for session creation - time.sleep(0.25) - if message.flags & MessageFlags.STRING.value: - new_session_ids = set(self.server.get_session_ids()) - new_sid = new_session_ids.difference(old_session_ids) - try: - sid = new_sid.pop() - logger.info("executed: %s as session %d", execute_server, sid) - except KeyError: - logger.info("executed %s with unknown session ID", execute_server) - return replies - logger.info("checking session %d for RUNTIME state" % sid) - session = self.server.get_session(session_id=sid) - retries = 10 - # wait for session to enter RUNTIME state, to prevent GUI from - # connecting while nodes are still being instantiated - while session.state != EventTypes.RUNTIME_STATE.value: - logger.info("waiting for session %d to enter RUNTIME state" % sid) - time.sleep(1) - retries -= 1 - if retries <= 0: - logger.info("session %d did not enter RUNTIME state" % sid) - return replies - tlv_data = coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, execute_server) - tlv_data += coreapi.CoreRegisterTlv.pack(RegisterTlvs.SESSION.value, "%s" % sid) - message = coreapi.CoreRegMessage.pack(0, tlv_data) - replies.append(message) - except Exception as e: - logger.exception("error executing: %s", execute_server) - tlv_data = coreapi.CoreExceptionTlv.pack(ExceptionTlvs.LEVEL.value, 2) - tlv_data += coreapi.CoreExceptionTlv.pack(ExceptionTlvs.TEXT.value, str(e)) - message = coreapi.CoreExceptionMessage.pack(0, tlv_data) - replies.append(message) - - return replies - - gui = message.get_tlv(RegisterTlvs.GUI.value) - if gui is None: - logger.info("ignoring Register message") - else: - # register capabilities with the GUI - self.master = True - - # TODO: need to replicate functionality? - # self.server.set_session_master(self) - # find the session containing this client and set the session to master - for session in self.server.sessions.itervalues(): - if self in session.broker.session_clients: - logger.info("setting session to master: %s", session.session_id) - session.master = True - break - - replies.append(self.register()) - replies.append(self.server.to_session_message()) - - return replies - - def handle_config_message(self, message): - """ - Configuration Message handler - - :param coreapi.CoreConfMessage message: configuration message to handle - :return: reply messages - """ - # convert config message to standard config data object - config_data = ConfigData( - node=message.get_tlv(ConfigTlvs.NODE.value), - object=message.get_tlv(ConfigTlvs.OBJECT.value), - type=message.get_tlv(ConfigTlvs.TYPE.value), - data_types=message.get_tlv(ConfigTlvs.DATA_TYPES.value), - data_values=message.get_tlv(ConfigTlvs.VALUES.value), - captions=message.get_tlv(ConfigTlvs.CAPTIONS.value), - bitmap=message.get_tlv(ConfigTlvs.BITMAP.value), - possible_values=message.get_tlv(ConfigTlvs.POSSIBLE_VALUES.value), - groups=message.get_tlv(ConfigTlvs.GROUPS.value), - session=message.get_tlv(ConfigTlvs.SESSION.value), - interface_number=message.get_tlv(ConfigTlvs.INTERFACE_NUMBER.value), - network_id=message.get_tlv(ConfigTlvs.NETWORK_ID.value), - opaque=message.get_tlv(ConfigTlvs.OPAQUE.value) - ) - logger.info("Configuration message for %s node %s", config_data.object, config_data.node) - - # dispatch to any registered callback for this object type - replies = self.session.config_object(config_data) - - for reply in replies: - self.handle_broadcast_config(reply) - - return [] - - def handle_file_message(self, message): - """ - File Message handler - - :param coreapi.CoreFileMessage message: file message to handle - :return: reply messages - """ - if message.flags & MessageFlags.ADD.value: - node_num = message.get_tlv(NodeTlvs.NUMBER.value) - file_name = message.get_tlv(FileTlvs.NAME.value) - file_type = message.get_tlv(FileTlvs.TYPE.value) - source_name = message.get_tlv(FileTlvs.SOURCE_NAME.value) - data = message.get_tlv(FileTlvs.DATA.value) - compressed_data = message.get_tlv(FileTlvs.COMPRESSED_DATA.value) - - if compressed_data: - logger.warn("Compressed file data not implemented for File message.") - return () - - if source_name and data: - logger.warn("ignoring invalid File message: source and data TLVs are both present") - return () - - # some File Messages store custom files in services, - # prior to node creation - if file_type is not None: - if file_type[:8] == "service:": - self.session.services.setservicefile(node_num, file_type, file_name, source_name, data) - return () - elif file_type[:5] == "hook:": - self.session.set_hook(file_type, file_name, source_name, data) - return () - - # writing a file to the host - if node_num is None: - if source_name is not None: - shutil.copy2(source_name, file_name) - else: - with open(file_name, "w") as open_file: - open_file.write(data) - return () - - try: - node = self.session.get_object(node_num) - if source_name is not None: - node.addfile(source_name, file_name) - elif data is not None: - node.nodefile(file_name, data) - except KeyError: - # XXX wait and queue this message to try again later - # XXX maybe this should be done differently - logger.warn("File message for %s for node number %s queued." % (file_name, node_num)) - time.sleep(0.125) - self.queue_message(message) - return () - else: - raise NotImplementedError - - return () - - def handle_interface_message(self, message): - """ - Interface Message handler. - - :param message: interface message to handle - :return: reply messages - """ - logger.info("ignoring Interface message") - return () - - def handle_event_message(self, message): - """ - Event Message handler - - :param coreapi.CoreEventMessage message: event message to handle - :return: reply messages - """ - event_data = EventData( - node=message.get_tlv(EventTlvs.NODE.value), - event_type=message.get_tlv(EventTlvs.TYPE.value), - name=message.get_tlv(EventTlvs.NAME.value), - data=message.get_tlv(EventTlvs.DATA.value), - time=message.get_tlv(EventTlvs.TIME.value), - session=message.get_tlv(EventTlvs.SESSION.value) - ) - - event_type = event_data.event_type - if event_type is None: - raise NotImplementedError("Event message missing event type") - node_id = event_data.node - - logger.info("EVENT %d: %s at %s", event_type, EventTypes(event_type).name, time.ctime()) - if event_type <= EventTypes.SHUTDOWN_STATE.value: - if node_id is not None: - try: - node = self.session.get_object(node_id) - except KeyError: - raise KeyError("Event message for unknown node %d" % node_id) - - # configure mobility models for WLAN added during runtime - if event_type == EventTypes.INSTANTIATION_STATE.value and nodeutils.is_node(node, - NodeTypes.WIRELESS_LAN): - self.session.mobility.startup(node_ids=(node.objid,)) - return () - - logger.warn("dropping unhandled Event message with node number") - return () - self.session.set_state(state=event_type) - - if event_type == EventTypes.DEFINITION_STATE.value: - # clear all session objects in order to receive new definitions - self.session.delete_objects() - self.session.del_hooks() - self.session.broker.reset() - elif event_type == EventTypes.INSTANTIATION_STATE.value: - if len(self.handler_threads) > 1: - # TODO: sync handler threads here before continuing - time.sleep(2.0) # XXX - # done receiving node/link configuration, ready to instantiate - self.session.instantiate() - - # after booting nodes attempt to send emulation id for nodes waiting on status - for obj in self.session.objects.itervalues(): - self.send_node_emulation_id(obj.objid) - elif event_type == EventTypes.RUNTIME_STATE.value: - if self.session.master: - logger.warn("Unexpected event message: RUNTIME state received at session master") - else: - # master event queue is started in session.checkruntime() - self.session.event_loop.run() - elif event_type == EventTypes.DATACOLLECT_STATE.value: - self.session.data_collect() - elif event_type == EventTypes.SHUTDOWN_STATE.value: - if self.session.master: - logger.warn("Unexpected event message: SHUTDOWN state received at session master") - elif event_type in (EventTypes.START.value, EventTypes.STOP.value, - EventTypes.RESTART.value, - EventTypes.PAUSE.value, - EventTypes.RECONFIGURE.value): - handled = False - name = event_data.name - if name: - # TODO: register system for event message handlers, - # like confobjs - if name.startswith("service:"): - self.session.services.handleevent(event_data) - handled = True - elif name.startswith("mobility:"): - self.session.mobility.handleevent(event_data) - handled = True - if not handled: - logger.warn("Unhandled event message: event type %s (%s)", - event_type, coreapi.state_name(event_type)) - elif event_type == EventTypes.FILE_OPEN.value: - self.session.delete_objects() - self.session.del_hooks() - self.session.broker.reset() - filename = event_data.name - open_session_xml(self.session, filename) - - # trigger session to send out messages out itself - self.session.send_objects() - return () - elif event_type == EventTypes.FILE_SAVE.value: - filename = event_data.name - save_session_xml(self.session, filename, self.session.config["xmlfilever"]) - elif event_type == EventTypes.SCHEDULED.value: - etime = event_data.time - node = event_data.node - name = event_data.name - data = event_data.data - if etime is None: - logger.warn("Event message scheduled event missing start time") - return () - if message.flags & MessageFlags.ADD.value: - self.session.add_event(float(etime), node=node, name=name, data=data) - else: - raise NotImplementedError - else: - logger.warn("Unhandled event message: event type %d", event_type) - - return () - - def handle_session_message(self, message): - """ - Session Message handler - - :param coreapi.CoreSessionMessage message: session message to handle - :return: reply messages - """ - session_id_str = message.get_tlv(SessionTlvs.NUMBER.value) - name_str = message.get_tlv(SessionTlvs.NAME.value) - file_str = message.get_tlv(SessionTlvs.FILE.value) - node_count_str = message.get_tlv(SessionTlvs.NODE_COUNT.value) - thumb = message.get_tlv(SessionTlvs.THUMB.value) - user = message.get_tlv(SessionTlvs.USER.value) - session_ids = coreapi.str_to_list(session_id_str) - names = coreapi.str_to_list(name_str) - files = coreapi.str_to_list(file_str) - node_counts = coreapi.str_to_list(node_count_str) - logger.info("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) - - if message.flags == 0: - # modify a session - i = 0 - for session_id in session_ids: - session_id = int(session_id) - if session_id == 0: - session = self.session - else: - session = self.server.get_session(session_id=session_id) - - if session is None: - logger.info("session %s not found", session_id) - i += 1 - continue - - logger.info("request to modify to session %s", session.session_id) - if names is not None: - session.name = names[i] - if files is not None: - session.file_name = files[i] - if node_counts is not None: - pass - if thumb is not None: - session.set_thumbnail(thumb) - if user is not None: - session.set_user(user) - i += 1 - else: - if message.flags & MessageFlags.STRING.value and not message.flags & MessageFlags.ADD.value: - # status request flag: send list of sessions - return self.server.to_session_message(), - - # handle ADD or DEL flags - for session_id in session_ids: - session_id = int(session_id) - session = self.server.get_session(session_id=session_id) - - if session is None: - logger.info("session %s not found (flags=0x%x)", session_id, message.flags) - continue - - if message.flags & MessageFlags.ADD.value: - # connect to the first session that exists - logger.info("request to connect to session %s" % session_id) - - # remove client from session broker and shutdown if needed - self.session.broker.session_clients.remove(self) - active_states = [ - EventTypes.RUNTIME_STATE.value, - EventTypes.RUNTIME_STATE.value, - EventTypes.DATACOLLECT_STATE.value - ] - if not self.session.broker.session_clients and self.session.state not in active_states: - self.session.shutdown() - - # set session to join - self.session = session - - # add client to session broker and set master if needed - if self.master: - self.session.master = True - self.session.broker.session_clients.append(self) - - # add broadcast handlers - logger.info("adding session broadcast handlers") - self.add_session_handlers() - - if user is not None: - self.session.set_user(user) - - if message.flags & MessageFlags.STRING.value: - self.session.send_objects() - elif message.flags & MessageFlags.DELETE.value: - # shut down the specified session(s) - logger.info("request to terminate session %s" % session_id) - session.set_state(state=EventTypes.DATACOLLECT_STATE.value, send_event=True) - session.set_state(state=EventTypes.SHUTDOWN_STATE.value, send_event=True) - session.shutdown() - else: - logger.warn("unhandled session flags for session %s", session_id) - - return () - - def send_node_emulation_id(self, node_id): - """ - Node emulation id to send. - - :param int node_id: node id to send - :return: nothing - """ - if node_id in self.node_status_request: - tlv_data = "" - tlv_data += coreapi.CoreNodeTlv.pack(NodeTlvs.NUMBER.value, node_id) - tlv_data += coreapi.CoreNodeTlv.pack(NodeTlvs.EMULATION_ID.value, node_id) - reply = coreapi.CoreNodeMessage.pack(MessageFlags.ADD.value | MessageFlags.LOCAL.value, tlv_data) - - try: - self.sendall(reply) - except IOError: - logger.exception("error sending node emulation id message: %s", node_id) - - del self.node_status_request[node_id] diff --git a/daemon/core/coreserver.py b/daemon/core/coreserver.py deleted file mode 100644 index 1687aec3..00000000 --- a/daemon/core/coreserver.py +++ /dev/null @@ -1,263 +0,0 @@ -""" -Defines server classes and request handlers for TCP and UDP. -""" - -import SocketServer -import threading -import time - -from core import logger -from core.api import coreapi -from core.enumerations import EventTypes -from core.enumerations import SessionTlvs -from core.session import Session - - -class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): - """ - TCP server class, manages sessions and spawns request handlers for - incoming connections. - """ - daemon_threads = True - allow_reuse_address = True - servers = set() - - def __init__(self, server_address, handler_class, config=None): - """ - Server class initialization takes configuration data and calls - the SocketServer constructor - - :param tuple[str, int] server_address: server host and port to use - :param class handler_class: request handler - :param dict config: configuration setting - :return: - """ - self.config = config - self.sessions = {} - self.udpserver = None - self.udpthread = None - self._sessions_lock = threading.Lock() - CoreServer.add_server(self) - SocketServer.TCPServer.__init__(self, server_address, handler_class) - - @classmethod - def add_server(cls, server): - """ - Add a core server to the known servers set. - - :param CoreServer server: server to add - :return: nothing - """ - cls.servers.add(server) - - @classmethod - def remove_server(cls, server): - """ - Remove a core server from the known servers set. - - :param CoreServer server: server to remove - :return: nothing - """ - if server in cls.servers: - cls.servers.remove(server) - - def shutdown(self): - """ - Shutdown the server, all known sessions, and remove server from known servers set. - - :return: nothing - """ - # shutdown all known sessions - for session in self.sessions.values(): - session.shutdown() - - # remove server from server list - CoreServer.remove_server(self) - - def add_session(self, session): - """ - Add a session to our dictionary of sessions, ensuring a unique session number. - - :param core.session.Session session: session to add - :return: added session - :raise KeyError: when a session with the same id already exists - """ - with self._sessions_lock: - if session.session_id in self.sessions: - raise KeyError("non-unique session id %s for %s" % (session.session_id, session)) - self.sessions[session.session_id] = session - - return session - - def remove_session(self, session): - """ - Remove a session from our dictionary of sessions. - - :param core.session.Session session: session to remove - :return: removed session - :rtype: core.session.Session - """ - with self._sessions_lock: - if session.session_id not in self.sessions: - logger.info("session id %s not found (sessions=%s)", session.session_id, self.sessions.keys()) - else: - del self.sessions[session.session_id] - - return session - - def get_session_ids(self): - """ - Return a list of active session numbers. - - :return: known session ids - :rtype: list - """ - with self._sessions_lock: - session_ids = self.sessions.keys() - - return session_ids - - def create_session(self, session_id=None): - """ - Convenience method for creating sessions with the servers config. - - :param int session_id: session id for new session - :return: create session - :rtype: core.session.Session - """ - - # create random id when necessary, seems to be 1 case wanted, based on legacy code - # creating a value so high, typical client side generation schemes hopefully wont collide - if not session_id: - session_id = next( - session_id for session_id in xrange(60000, 65000) - if session_id not in self.sessions - ) - - # create and add session to local manager - session = Session(session_id, config=self.config) - self.add_session(session) - - # add shutdown handler to remove session from manager - session.shutdown_handlers.append(self.session_shutdown) - - return session - - def get_session(self, session_id=None): - """ - Create a new session or retrieve an existing one from our - dictionary of sessions. When the session_id=0 and the use_existing - flag is set, return on of the existing sessions. - - :param int session_id: session id of session to retrieve, defaults to returning random session - :return: session - :rtype: core.session.Session - """ - - with self._sessions_lock: - # return specified session or none - if session_id: - return self.sessions.get(session_id) - - # retrieving known session - session = None - - # find runtime session with highest node count - for known_session in filter(lambda x: x.state == EventTypes.RUNTIME_STATE.value, - self.sessions.itervalues()): - if not session or known_session.get_node_count() > session.get_node_count(): - session = known_session - - # return first known session otherwise - if not session: - for known_session in self.sessions.itervalues(): - session = known_session - break - - return session - - def session_shutdown(self, session): - """ - Handler method to be used as a callback when a session has shutdown. - - :param core.session.Session session: session shutting down - :return: nothing - """ - self.remove_session(session) - - def to_session_message(self, flags=0): - """ - Build CORE API Sessions message based on current session info. - - :param int flags: message flags - :return: session message - """ - id_list = [] - name_list = [] - file_list = [] - node_count_list = [] - date_list = [] - thumb_list = [] - num_sessions = 0 - - with self._sessions_lock: - for session_id in self.sessions: - session = self.sessions[session_id] - # debug: session.dumpsession() - num_sessions += 1 - id_list.append(str(session_id)) - - name = session.name - if not name: - name = "" - name_list.append(name) - - file = session.file_name - if not file: - file = "" - file_list.append(file) - - node_count_list.append(str(session.get_node_count())) - - date_list.append(time.ctime(session._state_time)) - - thumb = session.thumbnail - if not thumb: - thumb = "" - thumb_list.append(thumb) - - session_ids = "|".join(id_list) - names = "|".join(name_list) - files = "|".join(file_list) - node_counts = "|".join(node_count_list) - dates = "|".join(date_list) - thumbs = "|".join(thumb_list) - - if num_sessions > 0: - tlv_data = "" - if len(session_ids) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NUMBER.value, session_ids) - if len(names) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NAME.value, names) - if len(files) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.FILE.value, files) - if len(node_counts) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.NODE_COUNT.value, node_counts) - if len(dates) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.DATE.value, dates) - if len(thumbs) > 0: - tlv_data += coreapi.CoreSessionTlv.pack(SessionTlvs.THUMB.value, thumbs) - message = coreapi.CoreSessionMessage.pack(flags, tlv_data) - else: - message = None - - return message - - def dump_sessions(self): - """ - Log currently known session information. - """ - logger.info("sessions:") - with self._sessions_lock: - for session_id in self.sessions: - logger.info(session_id) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 5bb2859e..4b906fcf 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -195,6 +195,9 @@ class FutureSession(Session): raise ValueError("wireless link failure: %s", objects) logger.info("handling wireless linking objects(%) connect(%s)", objects, connect) common_networks = objects[0].commonnets(objects[1]) + if not common_networks: + raise ValueError("no common network found for wireless link/unlink") + for common_network, interface_one, interface_two in common_networks: if not nodeutils.is_node(common_network, [NodeTypes.WIRELESS_LAN, NodeTypes.EMANE]): logger.info("skipping common network that is not wireless/emane: %s", common_network) @@ -205,8 +208,6 @@ class FutureSession(Session): common_network.link(interface_one, interface_two) else: common_network.unlink(interface_one, interface_two) - else: - raise ValueError("no common network found for wireless link/unlink") def add_link(self, node_one_id, node_two_id, interface_one=None, interface_two=None, link_options=LinkOptions()): """ @@ -429,15 +430,17 @@ class FutureSession(Session): link_config(net_one, interface, link_options) else: common_networks = node_one.commonnets(node_two) + if not common_networks: + raise ValueError("no common network found") + for net_one, interface_one, interface_two in common_networks: - if interface_one_id and interface_one_id != node_one.getifindex(interface_one): + if interface_one_id is not None and interface_one_id != node_one.getifindex(interface_one): continue link_config(net_one, interface_one, link_options, interface_two=interface_two) if not link_options.unidirectional: link_config(net_one, interface_two, link_options, interface_two=interface_one) - else: - raise ValueError("no common network found") + finally: if node_one: node_one.lock.release() @@ -610,8 +613,8 @@ class FutureSession(Session): :return: nothing """ - self.set_state(state=EventTypes.DATACOLLECT_STATE.value, send_event=True) - self.set_state(state=EventTypes.SHUTDOWN_STATE.value, send_event=True) + self.set_state(EventTypes.DATACOLLECT_STATE, send_event=True) + self.set_state(EventTypes.SHUTDOWN_STATE, send_event=True) super(FutureSession, self).shutdown() def custom_delete_object(self, object_id): @@ -753,9 +756,9 @@ class FutureSession(Session): """ self.mobility.handleevent(event_data) - def create_emane_node(self, _id=None, node_options=NodeOptions()): + def create_wireless_node(self, _id=None, node_options=NodeOptions()): """ - Create an EMANE node for use within an EMANE network. + Create a wireless node for use within an wireless/EMANE networks. :param int _id: int for node, defaults to None and will be generated :param core.future.futuredata.NodeOptions node_options: options for emane node, model will always be "mdr" @@ -796,6 +799,29 @@ class FutureSession(Session): values = list(emane_model.getdefaultvalues()) self.emane.setconfig(emane_node.objid, emane_model.name, values) + def set_wireless_model(self, node, model): + """ + Convenience method for setting a wireless model. + + :param node: node to set wireless model for + :param core.mobility.WirelessModel model: wireless model to set node to + :return: nothing + """ + values = list(model.getdefaultvalues()) + node.setmodel(model, values) + + def wireless_link_all(self, network, nodes): + """ + Link all nodes to the provided wireless network. + + :param network: wireless network to link nodes to + :param nodes: nodes to link to wireless network + :return: nothing + """ + for node in nodes: + for common_network, interface_one, interface_two in node.commonnets(network): + common_network.link(interface_one, interface_two) + class CoreEmu(object): """ @@ -876,26 +902,3 @@ class CoreEmu(object): logger.error("session to delete did not exist: %s", _id) return result - - def set_wireless_model(self, node, model): - """ - Convenience method for setting a wireless model. - - :param node: node to set wireless model for - :param core.mobility.WirelessModel model: wireless model to set node to - :return: nothing - """ - values = list(model.getdefaultvalues()) - node.setmodel(model, values) - - def wireless_link_all(self, network, nodes): - """ - Link all nodes to the provided wireless network. - - :param network: wireless network to link nodes to - :param nodes: nodes to link to wireless network - :return: nothing - """ - for node in nodes: - for common_network, interface_one, interface_two in node.commonnets(network): - common_network.link(interface_one, interface_two) diff --git a/daemon/core/legacy/__init__.py b/daemon/core/legacy/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/daemon/core/future/futurehandler.py b/daemon/core/legacy/corehandler.py similarity index 96% rename from daemon/core/future/futurehandler.py rename to daemon/core/legacy/corehandler.py index 7fb90a5a..2b358f1b 100644 --- a/daemon/core/future/futurehandler.py +++ b/daemon/core/legacy/corehandler.py @@ -13,29 +13,31 @@ import time from core import logger from core.api import coreapi -from core.coreserver import CoreServer from core.data import ConfigData from core.data import EventData -from core.enumerations import ConfigTlvs, LinkTypes +from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs from core.enumerations import EventTypes from core.enumerations import ExceptionTlvs from core.enumerations import ExecuteTlvs from core.enumerations import FileTlvs from core.enumerations import LinkTlvs +from core.enumerations import LinkTypes from core.enumerations import MessageFlags from core.enumerations import MessageTypes from core.enumerations import NodeTlvs from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.enumerations import SessionTlvs -from core.future.futuredata import NodeOptions, LinkOptions, InterfaceData +from core.future.futuredata import InterfaceData +from core.future.futuredata import LinkOptions +from core.future.futuredata import NodeOptions from core.misc import nodeutils from core.misc import structutils from core.misc import utils -class FutureHandler(SocketServer.BaseRequestHandler): +class CoreHandler(SocketServer.BaseRequestHandler): """ The SocketServer class uses the RequestHandler class for servicing requests. """ @@ -578,7 +580,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.add_session_handlers() # set initial session state - self.session.set_state(state=EventTypes.DEFINITION_STATE.value) + self.session.set_state(EventTypes.DEFINITION_STATE) while True: try: @@ -1032,13 +1034,13 @@ class FutureHandler(SocketServer.BaseRequestHandler): session=message.get_tlv(EventTlvs.SESSION.value) ) - event_type = event_data.event_type - if event_type is None: + if event_data.event_type is None: raise NotImplementedError("Event message missing event type") + event_type = EventTypes(event_data.event_type) node_id = event_data.node - logger.info("EVENT %d: %s at %s", event_type, EventTypes(event_type).name, time.ctime()) - if event_type <= EventTypes.SHUTDOWN_STATE.value: + logger.info("EVENT %s at %s", event_type.name, time.ctime()) + if event_type.value <= EventTypes.SHUTDOWN_STATE.value: if node_id is not None: try: node = self.session.get_object(node_id) @@ -1046,19 +1048,18 @@ class FutureHandler(SocketServer.BaseRequestHandler): raise KeyError("Event message for unknown node %d" % node_id) # configure mobility models for WLAN added during runtime - if event_type == EventTypes.INSTANTIATION_STATE.value and nodeutils.is_node(node, - NodeTypes.WIRELESS_LAN): + if event_type == EventTypes.INSTANTIATION_STATE and nodeutils.is_node(node, NodeTypes.WIRELESS_LAN): self.session.start_mobility(node_ids=(node.objid,)) return () logger.warn("dropping unhandled Event message with node number") return () - self.session.set_state(state=event_type) + self.session.set_state(event_type) - if event_type == EventTypes.DEFINITION_STATE.value: + if event_type == EventTypes.DEFINITION_STATE: # clear all session objects in order to receive new definitions self.session.clear() - elif event_type == EventTypes.INSTANTIATION_STATE.value: + elif event_type == EventTypes.INSTANTIATION_STATE: if len(self.handler_threads) > 1: # TODO: sync handler threads here before continuing time.sleep(2.0) # XXX @@ -1068,21 +1069,19 @@ class FutureHandler(SocketServer.BaseRequestHandler): # after booting nodes attempt to send emulation id for nodes waiting on status for obj in self.session.objects.itervalues(): self.send_node_emulation_id(obj.objid) - elif event_type == EventTypes.RUNTIME_STATE.value: + elif event_type == EventTypes.RUNTIME_STATE: if self.session.master: logger.warn("Unexpected event message: RUNTIME state received at session master") else: # master event queue is started in session.checkruntime() self.session.start_events() - elif event_type == EventTypes.DATACOLLECT_STATE.value: + elif event_type == EventTypes.DATACOLLECT_STATE: self.session.data_collect() - elif event_type == EventTypes.SHUTDOWN_STATE.value: + elif event_type == EventTypes.SHUTDOWN_STATE: if self.session.master: logger.warn("Unexpected event message: SHUTDOWN state received at session master") - elif event_type in (EventTypes.START.value, EventTypes.STOP.value, - EventTypes.RESTART.value, - EventTypes.PAUSE.value, - EventTypes.RECONFIGURE.value): + elif event_type in {EventTypes.START, EventTypes.STOP, EventTypes.RESTART, EventTypes.PAUSE, + EventTypes.RECONFIGURE}: handled = False name = event_data.name if name: @@ -1095,17 +1094,16 @@ class FutureHandler(SocketServer.BaseRequestHandler): self.session.mobility_event(event_data) handled = True if not handled: - logger.warn("Unhandled event message: event type %s (%s)", - event_type, coreapi.state_name(event_type)) - elif event_type == EventTypes.FILE_OPEN.value: + logger.warn("Unhandled event message: event type %s ", event_type.name) + elif event_type == EventTypes.FILE_OPEN: filename = event_data.name self.session.open_xml(filename, start=False) self.session.send_objects() return () - elif event_type == EventTypes.FILE_SAVE.value: + elif event_type == EventTypes.FILE_SAVE: filename = event_data.name self.session.save_xml(filename, self.session.config["xmlfilever"]) - elif event_type == EventTypes.SCHEDULED.value: + elif event_type == EventTypes.SCHEDULED: etime = event_data.time node = event_data.node name = event_data.name @@ -1118,7 +1116,7 @@ class FutureHandler(SocketServer.BaseRequestHandler): else: raise NotImplementedError else: - logger.warn("Unhandled event message: event type %d", event_type) + logger.warn("Unhandled event message: event type %s", event_type) return () diff --git a/daemon/core/future/futureserver.py b/daemon/core/legacy/coreserver.py similarity index 64% rename from daemon/core/future/futureserver.py rename to daemon/core/legacy/coreserver.py index d37845b4..5b57ca51 100644 --- a/daemon/core/future/futureserver.py +++ b/daemon/core/legacy/coreserver.py @@ -1,5 +1,5 @@ """ -Defines server classes and request handlers for TCP and UDP. +Defines core server for handling TCP connections. """ import SocketServer @@ -7,7 +7,7 @@ import SocketServer from core.future.coreemu import CoreEmu -class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): +class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): """ TCP server class, manages sessions and spawns request handlers for incoming connections. @@ -28,13 +28,3 @@ class FutureServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): self.coreemu = CoreEmu(config) self.config = config SocketServer.TCPServer.__init__(self, server_address, handler_class) - - def shutdown(self): - """ - Shutdown the server, all known sessions, and remove server from known servers set. - - :return: nothing - """ - # shutdown all known sessions - for session in self.coreemu.sessions.itervalues(): - session.shutdown() diff --git a/daemon/core/session.py b/daemon/core/session.py index 81ee8b04..a7149c34 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -300,27 +300,28 @@ class Session(object): """ Set the session's current state. - :param int state: state to set to + :param core.enumerations.EventTypes state: state to set to :param send_event: if true, generate core API event messages :return: nothing """ - state_name = coreapi.state_name(state) + state_value = state.value + state_name = state.name - if self.state == state: + if self.state == state_value: logger.info("session is already in state: %s, skipping change", state_name) return - self.state = state + self.state = state_value self._state_time = time.time() logger.info("changing session %s to state %s(%s) at %s", - self.session_id, state, state_name, self._state_time) + self.session_id, state_value, state_name, self._state_time) - self.write_state(state) - self.run_hooks(state) - self.run_state_hooks(state) + self.write_state(state_value) + self.run_hooks(state_value) + self.run_state_hooks(state_value) if send_event: - event_data = EventData(event_type=state, time="%s" % time.time()) + event_data = EventData(event_type=state_value, time="%s" % time.time()) self.broadcast_event(event_data) def write_state(self, state): @@ -868,7 +869,7 @@ class Session(object): # start event loop and set to runtime self.event_loop.run() - self.set_state(EventTypes.RUNTIME_STATE.value, send_event=True) + self.set_state(EventTypes.RUNTIME_STATE, send_event=True) def data_collect(self): """ @@ -908,7 +909,7 @@ class Session(object): shutdown = False if node_count == 0: shutdown = True - self.set_state(state=EventTypes.SHUTDOWN_STATE.value) + self.set_state(EventTypes.SHUTDOWN_STATE) return shutdown diff --git a/daemon/core/xml/xmlparser0.py b/daemon/core/xml/xmlparser0.py index 936c7b6f..e13e61c5 100644 --- a/daemon/core/xml/xmlparser0.py +++ b/daemon/core/xml/xmlparser0.py @@ -250,7 +250,7 @@ class CoreDocumentParser0(object): geo.append(a) location.setrefgeo(geo[0], geo[1], geo[2]) scale = origin.getAttribute("scale100") - if scale is not None: + if scale is not None and scale: location.refscale = float(scale) point = xmlutils.get_one_element(origin, "point") if point is not None and point.firstChild is not None: diff --git a/daemon/examples/future/emane80211_api.py b/daemon/examples/future/emane80211_api.py index 1b16bc96..e60c2871 100644 --- a/daemon/examples/future/emane80211_api.py +++ b/daemon/examples/future/emane80211_api.py @@ -20,7 +20,7 @@ def example(options): session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) # create emane network node emane_network = session.create_emane_network( @@ -31,7 +31,7 @@ def example(options): # create nodes for i in xrange(options.nodes): - node = session.create_emane_node() + node = session.create_wireless_node() node.setposition(x=150 * (i + 1), y=150) interface = prefixes.create_interface(node) session.add_link(node.objid, emane_network.objid, interface_one=interface) diff --git a/daemon/examples/future/switch_api.py b/daemon/examples/future/switch_api.py index 1dc914ec..9e50085f 100644 --- a/daemon/examples/future/switch_api.py +++ b/daemon/examples/future/switch_api.py @@ -22,7 +22,7 @@ def example(options): session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) # create switch network node switch = session.add_node(_type=NodeTypes.SWITCH) diff --git a/daemon/examples/future/switch_api_inject.py b/daemon/examples/future/switch_api_inject.py index 215bddb8..647f3423 100644 --- a/daemon/examples/future/switch_api_inject.py +++ b/daemon/examples/future/switch_api_inject.py @@ -18,7 +18,7 @@ def example(nodes): session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) # create switch network node switch = session.add_node(_type=NodeTypes.SWITCH) diff --git a/daemon/examples/future/wlan_api.py b/daemon/examples/future/wlan_api.py index ed34ca55..5fa16cc0 100644 --- a/daemon/examples/future/wlan_api.py +++ b/daemon/examples/future/wlan_api.py @@ -23,11 +23,11 @@ def example(options): session = coreemu.create_session() # must be in configuration state for nodes to start, when using "node_add" below - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) # create wlan network node wlan = session.add_node(_type=NodeTypes.WIRELESS_LAN) - coreemu.set_wireless_model(wlan, BasicRangeModel) + session.set_wireless_model(wlan, BasicRangeModel) # create nodes wireless_nodes = [] @@ -38,7 +38,7 @@ def example(options): wireless_nodes.append(node) # link all created nodes with the wireless network - coreemu.wireless_link_all(wlan, wireless_nodes) + session.wireless_link_all(wlan, wireless_nodes) # instantiate session session.instantiate() diff --git a/daemon/examples/netns/daemonnodes.py b/daemon/examples/netns/daemonnodes.py index 2f8b7f81..76e3f9ce 100755 --- a/daemon/examples/netns/daemonnodes.py +++ b/daemon/examples/netns/daemonnodes.py @@ -132,7 +132,7 @@ def main(): session.broker.dorecvloop = False # Change to configuration state on both machines - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value) session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata)) diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index a76388b1..6ffd49f1 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -69,7 +69,7 @@ def main(): print "connecting to slave at %s:%d" % (slave, port) session.broker.addserver(slave, slave, port) session.broker.setupserver(slave) - session.set_state(EventTypes.CONFIGURATION_STATE.value) + session.set_state(EventTypes.CONFIGURATION_STATE) tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value) session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata)) diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon old mode 100755 new mode 100644 index a9d92376..744d202b --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -6,18 +6,16 @@ message handlers are defined and some support for sending messages. """ import ConfigParser -import atexit import optparse -import signal import sys import time from core import constants -from core import corehandlers -from core import coreserver from core import enumerations from core import logger from core import services +from core.legacy.corehandler import CoreHandler +from core.legacy.coreserver import CoreServer from core.misc import nodeutils from core.misc.utils import close_onexec from core.service import ServiceManager @@ -45,7 +43,7 @@ def cored(cfg=None): host = "localhost" try: - server = coreserver.CoreServer((host, port), corehandlers.CoreRequestHandler, cfg) + server = CoreServer((host, port), CoreHandler, cfg) except: logger.exception("error starting main server on: %s:%s", host, port) sys.exit(1) @@ -55,38 +53,6 @@ def cored(cfg=None): server.serve_forever() -# TODO: should sessions and the main core daemon both catch exit to shutdown independently? -def cleanup(): - """ - Runs server shutdown and cleanup when catching an exit signal. - - :return: nothing - """ - while coreserver.CoreServer.servers: - server = coreserver.CoreServer.servers.pop() - server.shutdown() - - -def sighandler(signum, stackframe): - """ - Signal handler when different signals are sent. - - :param int signum: singal number sent - :param stackframe: stack frame sent - :return: nothing - """ - logger.error("terminated by signal: %s", signum) - sys.exit(signum) - - -signal.signal(signal.SIGHUP, sighandler) -signal.signal(signal.SIGINT, sighandler) -signal.signal(signal.SIGTERM, sighandler) -signal.signal(signal.SIGUSR1, sighandler) -signal.signal(signal.SIGUSR2, sighandler) -atexit.register(cleanup) - - def get_merged_config(filename): """ Return a configuration after merging config file and command-line arguments. diff --git a/daemon/scripts/core-future b/daemon/scripts/core-future deleted file mode 100644 index 815aa5bb..00000000 --- a/daemon/scripts/core-future +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python -""" -core-daemon: the CORE daemon is a server process that receives CORE API -messages and instantiates emulated nodes and networks within the kernel. Various -message handlers are defined and some support for sending messages. -""" - -import ConfigParser -import optparse -import sys -import time - -from core import constants -from core import enumerations -from core import logger -from core import services -from core.future.futurehandler import FutureHandler -from core.future.futureserver import FutureServer -from core.misc import nodeutils -from core.misc.utils import close_onexec -from core.service import ServiceManager - - -def banner(): - """ - Output the program banner printed to the terminal or log file. - - :return: nothing - """ - logger.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime()) - - -def cored(cfg=None): - """ - Start the CoreServer object and enter the server loop. - - :param dict cfg: core configuration - :return: nothing - """ - host = cfg["listenaddr"] - port = int(cfg["port"]) - if host == "" or host is None: - host = "localhost" - - try: - server = FutureServer((host, port), FutureHandler, cfg) - except: - logger.exception("error starting main server on: %s:%s", host, port) - sys.exit(1) - - close_onexec(server.fileno()) - logger.info("main server started, listening on: %s:%s", host, port) - server.serve_forever() - - -def get_merged_config(filename): - """ - Return a configuration after merging config file and command-line arguments. - - :param str filename: file name to merge configuration settings with - :return: merged configuration - :rtype: dict - """ - # these are the defaults used in the config file - defaults = { - "port": "%d" % enumerations.CORE_API_PORT, - "listenaddr": "localhost", - "xmlfilever": "1.0", - "numthreads": "1", - } - - usagestr = "usage: %prog [-h] [options] [args]\n\n" + \ - "CORE daemon v.%s instantiates Linux network namespace " \ - "nodes." % constants.COREDPY_VERSION - parser = optparse.OptionParser(usage=usagestr) - parser.add_option("-f", "--configfile", dest="configfile", type="string", - help="read config from specified file; default = %s" % filename) - parser.add_option("-p", "--port", dest="port", type=int, - help="port number to listen on; default = %s" % defaults["port"]) - parser.add_option("-t", "--numthreads", dest="numthreads", type=int, - help="number of server threads; default = %s" % defaults["numthreads"]) - - # parse command line options - options, args = parser.parse_args() - - # read the config file - if options.configfile is not None: - filename = options.configfile - del options.configfile - cfg = ConfigParser.SafeConfigParser(defaults) - cfg.read(filename) - - section = "core-daemon" - if not cfg.has_section(section): - cfg.add_section(section) - - # merge command line with config file - for opt in options.__dict__: - val = options.__dict__[opt] - if val is not None: - cfg.set(section, opt, val.__str__()) - - return dict(cfg.items(section)), args - - -def main(): - """ - Main program startup. - - :return: nothing - """ - # get a configuration merged from config file and command-line arguments - cfg, args = get_merged_config("%s/core.conf" % constants.CORE_CONF_DIR) - for a in args: - logger.error("ignoring command line argument: %s", a) - - # attempt load custom services - service_paths = cfg.get("custom_services_dir") - logger.debug("custom service paths: %s", service_paths) - if service_paths: - for service_path in service_paths.split(','): - service_path = service_path.strip() - ServiceManager.add_services(service_path) - - banner() - - try: - cored(cfg) - except KeyboardInterrupt: - logger.info("keyboard interrupt, stopping core daemon") - - sys.exit(0) - - -if __name__ == "__main__": - # configure nodes to use - if len(sys.argv) == 2 and sys.argv[1] == "ovs": - from core.netns.openvswitch import OVS_NODES - - nodeutils.update_node_map(OVS_NODES) - - # load default services - services.load() - - main() diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index 50b088d7..bf478d4a 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -13,8 +13,6 @@ from core.api.coreapi import CoreEventMessage from core.api.coreapi import CoreExecMessage from core.api.coreapi import CoreLinkMessage from core.api.coreapi import CoreNodeMessage -from core.corehandlers import CoreRequestHandler -from core.coreserver import CoreServer from core.enumerations import CORE_API_PORT from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs @@ -25,10 +23,12 @@ from core.enumerations import LinkTypes from core.enumerations import MessageFlags from core.enumerations import NodeTlvs from core.enumerations import NodeTypes +from core.future.coreemu import CoreEmu +from core.future.futuredata import IpPrefixes +from core.legacy.corehandler import CoreHandler +from core.legacy.coreserver import CoreServer from core.misc import ipaddress from core.misc.ipaddress import MacAddress -from core.netns import nodes -from core.session import Session EMANE_SERVICES = "zebra|OSPFv3MDR|IPForward" @@ -133,110 +133,12 @@ def state_message(state): ]) -class Core(object): - def __init__(self, session, ip_prefix): - self.session = session - self.ip_prefix = ip_prefix - self.current_ip = 1 - self.nodes = {} - self.node_ips = {} - - def create_node(self, name, cls=nodes.CoreNode, objid=None, position=None, services=None, model="host"): - node = self.session.add_object(cls=cls, name=name, objid=objid) - node.type = model - if position: - node.setposition(*position) - if services: - self.session.services.addservicestonode(node, model, services) - self.nodes[name] = node - - def add_interface(self, network, name): - node_ip = self.ip_prefix.addr(self.current_ip) - self.current_ip += 1 - self.node_ips[name] = node_ip - node = self.nodes[name] - interface_id = node.newnetif(network, ["%s/%s" % (node_ip, self.ip_prefix.prefixlen)]) - return node.netif(interface_id) - - def get_node(self, name): - """ - Retrieve node from current session. - - :param str name: name of node to retrieve - :return: core node - :rtype: core.netns.nodes.CoreNode - """ - return self.nodes[name] - - def get_ip(self, name): - return self.node_ips[name] - - def link(self, network, from_interface, to_interface): - network.link(from_interface, to_interface) - - def configure_link(self, network, interface_one, interface_two, values, unidirectional=False): - network.linkconfig(netif=interface_one, netif2=interface_two, **values) - - if not unidirectional: - network.linkconfig(netif=interface_two, netif2=interface_one, **values) - - def ping(self, from_name, to_name): - from_node = self.nodes[from_name] - to_ip = str(self.get_ip(to_name)) - return from_node.cmd(["ping", "-c", "3", to_ip]) - - def ping_output(self, from_name, to_name): - from_node = self.nodes[from_name] - to_ip = str(self.get_ip(to_name)) - output = from_node.check_cmd(["ping", "-i", "0.05", "-c", "3", to_ip]) - return output - - def iperf(self, from_name, to_name): - from_node = self.nodes[from_name] - to_node = self.nodes[to_name] - to_ip = str(self.get_ip(to_name)) - - # run iperf server, run client, kill iperf server - vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"]) - from_node.cmd(["iperf", "-u", "-t", "5", "-c", to_ip]) - to_node.cmd(["killall", "-9", "iperf"]) - - return stdout.read().strip() - - def assert_nodes(self): - for node in self.nodes.itervalues(): - assert os.path.exists(node.nodedir) - - def create_link_network(self): - # create switch - ptp_node = self.session.add_object(cls=nodes.PtpNet) - - # create nodes - self.create_node("n1") - self.create_node("n2") - - # add interfaces - interface_one = self.add_interface(ptp_node, "n1") - interface_two = self.add_interface(ptp_node, "n2") - - # instantiate session - self.session.instantiate() - - # assert node directories created - self.assert_nodes() - - return ptp_node, interface_one, interface_two - - def set_emane_model(self, emane_node, emane_model): - # set the emane model - values = emane_model.getdefaultvalues() - self.session.emane.setconfig(emane_node.objid, emane_model.name, values) - - class CoreServerTest(object): - def __init__(self): - address = ("localhost", CORE_API_PORT) - self.server = CoreServer(address, CoreRequestHandler, { + def __init__(self, port=CORE_API_PORT): + self.host = "localhost" + self.port = port + address = (self.host, self.port) + self.server = CoreServer(address, CoreHandler, { "numthreads": 1, "daemonize": False, }) @@ -246,29 +148,29 @@ class CoreServerTest(object): self.session = None self.request_handler = None - def setup(self, distributed_address): + def setup(self, distributed_address, port): # validate address assert distributed_address, "distributed server address was not provided" # create session - self.session = self.server.create_session(1) + self.session = self.server.coreemu.create_session(1) self.session.master = True # create request handler request_mock = MagicMock() request_mock.fileno = MagicMock(return_value=1) - self.request_handler = CoreRequestHandler(request_mock, "", self.server) + self.request_handler = CoreHandler(request_mock, "", self.server) self.request_handler.session = self.session self.request_handler.add_session_handlers() self.session.broker.session_clients.append(self.request_handler) # have broker handle a configuration state change - self.session.set_state(state=EventTypes.DEFINITION_STATE.value) + self.session.set_state(EventTypes.DEFINITION_STATE) message = state_message(EventTypes.CONFIGURATION_STATE) self.request_handler.handle_message(message) # add broker server for distributed core - distributed = "%s:%s:%s" % (self.distributed_server, distributed_address, CORE_API_PORT) + distributed = "%s:%s:%s" % (self.distributed_server, distributed_address, port) message = CoreConfMessage.create(0, [ (ConfigTlvs.OBJECT, "broker"), (ConfigTlvs.TYPE, 0), @@ -301,38 +203,24 @@ class CoreServerTest(object): self.server.server_close() -@pytest.fixture() +@pytest.fixture def session(): - # load default services - services.load() - - # create and return session - session_fixture = Session(1, persistent=True) - session_fixture.master = True + # use coreemu and create a session + coreemu = CoreEmu() + session_fixture = coreemu.create_session() + session_fixture.set_state(EventTypes.CONFIGURATION_STATE) assert os.path.exists(session_fixture.session_dir) - # set location - # session_fixture.master = True - session_fixture.location.setrefgeo(47.57917, -122.13232, 2.00000) - session_fixture.location.refscale = 150.0 - - # return session fixture + # return created session yield session_fixture - # cleanup - print "shutting down session" - session_fixture.shutdown() - assert not os.path.exists(session_fixture.session_dir) + # shutdown coreemu + coreemu.shutdown() @pytest.fixture(scope="module") -def ip_prefix(): - return ipaddress.Ipv4Prefix("10.83.0.0/16") - - -@pytest.fixture() -def core(session, ip_prefix): - return Core(session, ip_prefix) +def ip_prefixes(): + return IpPrefixes(ip4_prefix="10.83.0.0/16") @pytest.fixture() @@ -348,6 +236,11 @@ def cored(): server.shutdown() +def ping(from_node, to_node, ip_prefixes, count=3): + address = ip_prefixes.ip4_address(to_node) + return from_node.cmd(["ping", "-c", str(count), address]) + + def pytest_addoption(parser): parser.addoption("--distributed", help="distributed server address") diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 2340f2fb..6a0f50d5 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -11,22 +11,22 @@ from xml.etree import ElementTree import pytest from mock import MagicMock -from conftest import EMANE_SERVICES from core.data import ConfigData -from core.enumerations import MessageFlags +from core.enumerations import MessageFlags, NodeTypes +from core.future.futuredata import NodeOptions from core.mobility import BasicRangeModel -from core.netns import nodes -from core.netns import vnodeclient from core.netns.vnodeclient import VnodeClient -from core.phys.pnodes import PhysicalNode from core.service import ServiceManager -from core.xml import xmlsession _PATH = os.path.abspath(os.path.dirname(__file__)) _SERVICES_PATH = os.path.join(_PATH, "myservices") _MOBILITY_FILE = os.path.join(_PATH, "mobility.scen") _XML_VERSIONS = ["0.0", "1.0"] -_NODE_CLASSES = [nodes.PtpNet, nodes.HubNode, nodes.SwitchNode] +_WIRED = [ + NodeTypes.PEER_TO_PEER, + NodeTypes.HUB, + NodeTypes.SWITCH +] def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None): @@ -47,8 +47,13 @@ def createclients(sessiondir, clientcls=VnodeClient, cmdchnlfilterfunc=None): return map(lambda x: clientcls(os.path.basename(x), x), cmdchnls) +def ping(from_node, to_node, ip_prefixes): + address = ip_prefixes.ip4_address(to_node) + return from_node.cmd(["ping", "-c", "3", address]) + + class TestCore: - def test_import_service(self, core): + def test_import_service(self): """ Test importing a custom service. @@ -58,118 +63,115 @@ class TestCore: assert ServiceManager.get("MyService") assert ServiceManager.get("MyService2") - @pytest.mark.parametrize("cls", _NODE_CLASSES) - def test_nodes(self, core, cls): + @pytest.mark.parametrize("net_type", _WIRED) + def test_wired_ping(self, session, net_type, ip_prefixes): """ Test ptp node network. - :param conftest.Core core: core fixture to test with - :param cls: node classes that work within a simple network + :param session: session for test + :param core.enumerations.NodeTypes net_type: type of net node to create + :param ip_prefixes: generates ip addresses for nodes """ - # create ptp - network_node = core.session.add_object(cls=cls) + # create net node + net_node = session.add_node(_type=net_type) # create nodes - core.create_node("n1") - core.create_node("n2") + node_one = session.add_node() + node_two = session.add_node() - # add interfaces - core.add_interface(network_node, "n1") - core.add_interface(network_node, "n2") + # link nodes to net node + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, net_node.objid, interface_one=interface) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # ping n2 from n1 and assert success - status = core.ping("n1", "n2") + status = ping(node_one, node_two, ip_prefixes) assert not status @pytest.mark.parametrize("version", _XML_VERSIONS) - def test_xml(self, core, tmpdir, version): + def test_xml(self, session, tmpdir, version, ip_prefixes): """ Test xml client methods. - :param conftest.Core core: core fixture to test with + :param session: session for test + :param tmpdir: tmpdir to create data in :param str version: xml version to write and parse + :param ip_prefixes: generates ip addresses for nodes """ # create ptp - ptp_node = core.session.add_object(cls=nodes.PtpNet) + ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER) # create nodes - core.create_node("n1") - core.create_node("n2") + node_one = session.add_node() + node_two = session.add_node() - # add interfaces - core.add_interface(ptp_node, "n1") - core.add_interface(ptp_node, "n2") + # link nodes to ptp net + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, ptp_node.objid, interface_one=interface) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # get ids for nodes - n1_id = core.get_node("n1").objid - n2_id = core.get_node("n2").objid + n1_id = node_one.objid + n2_id = node_two.objid # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath - xmlsession.save_session_xml(core.session, file_path, version) + session.save_xml(file_path, version) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data - core.session.shutdown() + session.shutdown() # verify nodes have been removed from session with pytest.raises(KeyError): - assert not core.session.get_object_by_name(n1_id) + assert not session.get_object(n1_id) with pytest.raises(KeyError): - assert not core.session.get_object(n2_id) + assert not session.get_object(n2_id) # load saved xml - xmlsession.open_session_xml(core.session, file_path, start=True) + session.open_xml(file_path, start=True) # verify nodes have been recreated - assert core.session.get_object(n1_id) - assert core.session.get_object(n2_id) + assert session.get_object(n1_id) + assert session.get_object(n2_id) - def test_vnode_client(self, core): + def test_vnode_client(self, session, ip_prefixes): """ Test vnode client methods. - :param conftest.Core core: core fixture to test with + :param session: session for test + :param ip_prefixes: generates ip addresses for nodes """ # create ptp - ptp_node = core.session.add_object(cls=nodes.PtpNet) + ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER) # create nodes - core.create_node("n1") - core.create_node("n2") + node_one = session.add_node() + node_two = session.add_node() - # add interfaces - core.add_interface(ptp_node, "n1") - core.add_interface(ptp_node, "n2") + # link nodes to ptp net + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, ptp_node.objid, interface_one=interface) # get node client for testing - n1 = core.get_node("n1") - client = n1.client + client = node_one.client # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # check we are connected assert client.connected() @@ -195,183 +197,154 @@ class TestCore: assert not client.shcmd(command[0]) # check module methods - assert createclients(core.session.session_dir) + assert createclients(session.session_dir) # check convenience methods for interface information assert client.getaddr("eth0") assert client.netifstats() - def test_netif(self, core): + def test_netif(self, session, ip_prefixes): """ Test netif methods. - :param conftest.Core core: core fixture to test with + :param session: session for test + :param ip_prefixes: generates ip addresses for nodes """ # create ptp - ptp_node = core.session.add_object(cls=nodes.PtpNet) + ptp_node = session.add_node(_type=NodeTypes.PEER_TO_PEER) # create nodes - core.create_node("n1") - core.create_node("n2") + node_one = session.add_node() + node_two = session.add_node() - # add interfaces - n1_interface = core.add_interface(ptp_node, "n1") - n2_interface = core.add_interface(ptp_node, "n2") - - # get nodes - n1 = core.get_node("n1") - n2 = core.get_node("n2") + # link nodes to ptp net + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, ptp_node.objid, interface_one=interface) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # check link data gets generated assert ptp_node.all_link_data(MessageFlags.ADD.value) # check common nets exist between linked nodes - assert n1.commonnets(n2) - assert n2.commonnets(n1) + assert node_one.commonnets(node_two) + assert node_two.commonnets(node_one) # check we can retrieve netif index - assert n1.getifindex(n1_interface) == 0 - assert n2.getifindex(n2_interface) == 0 + assert node_one.getifindex(0) + assert node_two.getifindex(0) # check interface parameters - n1_interface.setparam("test", 1) - assert n1_interface.getparam("test") == 1 - assert n1_interface.getparams() + interface = node_one.netif(0) + interface.setparam("test", 1) + assert interface.getparam("test") == 1 + assert interface.getparams() # delete netif and test that if no longer exists - n1.delnetif(0) - assert not n1.netif(0) + node_one.delnetif(0) + assert not node_one.netif(0) - def test_physical(self, core): - """ - Test physical node network. - - :param conftest.Core core: core fixture to test with - """ - - # create switch node - switch_node = core.session.add_object(cls=nodes.SwitchNode) - - # create a physical node - core.create_node(cls=PhysicalNode, name="p1") - - # mock method that will not work - physical_node = core.get_node("p1") - physical_node.newnetif = MagicMock(return_value=0) - - # create regular node - core.create_node("n1") - - # add interface - core.add_interface(switch_node, "n1") - core.add_interface(switch_node, "p1") - - # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() - - def test_wlan_basic_range_good(self, core): + def test_wlan_good(self, session, ip_prefixes): """ Test basic wlan network. - :param conftest.Core core: core fixture to test with + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes """ # create wlan - wlan_node = core.session.add_object(cls=nodes.WlanNode) - values = BasicRangeModel.getdefaultvalues() - wlan_node.setmodel(BasicRangeModel, values) + wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN) + session.set_wireless_model(wlan_node, BasicRangeModel) # create nodes - core.create_node("n1", position=(0, 0), services=EMANE_SERVICES, model="mdr") - core.create_node("n2", position=(0, 0), services=EMANE_SERVICES, model="mdr") + node_options = NodeOptions() + node_options.set_position(0, 0) + node_one = session.create_wireless_node(node_options=node_options) + node_two = session.create_wireless_node(node_options=node_options) - # add interfaces - interface_one = core.add_interface(wlan_node, "n1") - interface_two = core.add_interface(wlan_node, "n2") + # link nodes + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, wlan_node.objid, interface_one=interface) # link nodes in wlan - core.link(wlan_node, interface_one, interface_two) + session.wireless_link_all(wlan_node, [node_one, node_two]) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # ping n2 from n1 and assert success - status = core.ping("n1", "n2") + status = ping(node_one, node_two, ip_prefixes) assert not status - def test_wlan_basic_range_bad(self, core): + def test_wlan_bad(self, session, ip_prefixes): """ Test basic wlan network with leveraging basic range model. - :param conftest.Core core: core fixture to test with + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes """ # create wlan - wlan_node = core.session.add_object(cls=nodes.WlanNode) - values = BasicRangeModel.getdefaultvalues() - wlan_node.setmodel(BasicRangeModel, values) + wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN) + session.set_wireless_model(wlan_node, BasicRangeModel) # create nodes - core.create_node("n1", position=(0, 0), services=EMANE_SERVICES, model="mdr") - core.create_node("n2", position=(0, 0), services=EMANE_SERVICES, model="mdr") + node_options = NodeOptions() + node_options.set_position(0, 0) + node_one = session.create_wireless_node(node_options=node_options) + node_two = session.create_wireless_node(node_options=node_options) - # add interfaces - interface_one = core.add_interface(wlan_node, "n1") - interface_two = core.add_interface(wlan_node, "n2") + # link nodes + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, wlan_node.objid, interface_one=interface) # link nodes in wlan - core.link(wlan_node, interface_one, interface_two) - - # move nodes out of range, default range check is 275 - core.get_node("n1").setposition(0, 0) - core.get_node("n2").setposition(500, 500) + session.wireless_link_all(wlan_node, [node_one, node_two]) # instantiate session - core.session.instantiate() + session.instantiate() - # assert node directories created - core.assert_nodes() + # move node two out of range, default range check is 275 + time.sleep(5) + update_options = NodeOptions() + update_options.set_position(500, 500) + session.update_node(node_two.objid, update_options) - # ping n2 from n1 and assert failure ) - time.sleep(3) - status = core.ping("n1", "n2") + # ping n2 from n1 and assert failure + time.sleep(5) + status = ping(node_one, node_two, ip_prefixes) assert status - def test_mobility(self, core): + def test_mobility(self, session, ip_prefixes): """ Test basic wlan network. - :param conftest.Core core: core fixture to test with + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes """ # create wlan - wlan_node = core.session.add_object(cls=nodes.WlanNode) - values = BasicRangeModel.getdefaultvalues() - wlan_node.setmodel(BasicRangeModel, values) + wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN) + session.set_wireless_model(wlan_node, BasicRangeModel) # create nodes - core.create_node("n1", objid=1, position=(0, 0), services=EMANE_SERVICES, model="mdr") - core.create_node("n2", objid=2, position=(0, 0), services=EMANE_SERVICES, model="mdr") + node_options = NodeOptions() + node_options.set_position(0, 0) + node_one = session.create_wireless_node(node_options=node_options) + node_two = session.create_wireless_node(node_options=node_options) - # add interfaces - interface_one = core.add_interface(wlan_node, "n1") - interface_two = core.add_interface(wlan_node, "n2") + # link nodes + for node in [node_one, node_two]: + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, wlan_node.objid, interface_one=interface) # link nodes in wlan - core.link(wlan_node, interface_one, interface_two) + session.wireless_link_all(wlan_node, [node_one, node_two]) # configure mobility script for session config = ConfigData( @@ -382,7 +355,7 @@ class TestCore: data_values="file=%s|refresh_ms=50|loop=1|autostart=0.0|" "map=|script_start=|script_pause=|script_stop=" % _MOBILITY_FILE ) - core.session.config_object(config) + session.config_object(config) # add handler for receiving node updates event = threading.Event() @@ -390,138 +363,10 @@ class TestCore: def node_update(_): event.set() - core.session.node_handlers.append(node_update) + session.node_handlers.append(node_update) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # validate we receive a node message for updating its location assert event.wait(5) - - def test_link_bandwidth(self, core): - """ - Test ptp node network with modifying link bandwidth. - - :param conftest.Core core: core fixture to test with - """ - - # create link network - ptp_node, interface_one, interface_two = core.create_link_network() - - # output csv index - bandwidth_index = 8 - - # run iperf, validate normal bandwidth - stdout = core.iperf("n1", "n2") - assert stdout - value = int(stdout.split(',')[bandwidth_index]) - assert 900000 <= value <= 1100000 - - # change bandwidth in bits per second - bandwidth = 500000 - core.configure_link(ptp_node, interface_one, interface_two, { - "bw": bandwidth - }) - - # run iperf again - stdout = core.iperf("n1", "n2") - assert stdout - value = int(stdout.split(',')[bandwidth_index]) - assert 400000 <= value <= 600000 - - def test_link_loss(self, core): - """ - Test ptp node network with modifying link packet loss. - - :param conftest.Core core: core fixture to test with - """ - - # create link network - ptp_node, interface_one, interface_two = core.create_link_network() - - # output csv index - loss_index = -2 - - # run iperf, validate normal bandwidth - stdout = core.iperf("n1", "n2") - assert stdout - value = float(stdout.split(',')[loss_index]) - assert 0 <= value <= 0.5 - - # change bandwidth in bits per second - loss = 50 - core.configure_link(ptp_node, interface_one, interface_two, { - "loss": loss - }) - - # run iperf again - stdout = core.iperf("n1", "n2") - assert stdout - value = float(stdout.split(',')[loss_index]) - assert 40 <= value <= 60 - - def test_link_delay(self, core): - """ - Test ptp node network with modifying link packet delay. - - :param conftest.Core core: core fixture to test with - """ - - # create link network - ptp_node, interface_one, interface_two = core.create_link_network() - - # run ping for delay information - stdout = core.ping_output("n1", "n2") - assert stdout - rtt_line = stdout.split("\n")[-1] - rtt_values = rtt_line.split("=")[1].split("ms")[0].strip() - rtt_avg = float(rtt_values.split("/")[2]) - assert 0 <= rtt_avg <= 0.2 - - # change delay in microseconds - delay = 1000000 - core.configure_link(ptp_node, interface_one, interface_two, { - "delay": delay - }) - - # run ping for delay information again - stdout = core.ping_output("n1", "n2") - assert stdout - rtt_line = stdout.split("\n")[-1] - rtt_values = rtt_line.split("=")[1].split("ms")[0].strip() - rtt_avg = float(rtt_values.split("/")[2]) - assert 1800 <= rtt_avg <= 2200 - - def test_link_jitter(self, core): - """ - Test ptp node network with modifying link packet jitter. - - :param conftest.Core core: core fixture to test with - """ - - # create link network - ptp_node, interface_one, interface_two = core.create_link_network() - - # output csv index - jitter_index = 9 - - # run iperf - stdout = core.iperf("n1", "n2") - assert stdout - value = float(stdout.split(",")[jitter_index]) - assert -0.5 <= value <= 0.05 - - # change jitter in microseconds - jitter = 1000000 - core.configure_link(ptp_node, interface_one, interface_two, { - "jitter": jitter - }) - - # run iperf again - stdout = core.iperf("n1", "n2") - assert stdout - value = float(stdout.split(",")[jitter_index]) - assert 200 <= value <= 500 diff --git a/daemon/tests/test_emane.py b/daemon/tests/test_emane.py index 6c7ade45..c6644cf9 100644 --- a/daemon/tests/test_emane.py +++ b/daemon/tests/test_emane.py @@ -4,16 +4,13 @@ Unit tests for testing CORE EMANE networks. import pytest -from conftest import EMANE_SERVICES - -from core.data import ConfigData +from conftest import ping from core.emane.bypass import EmaneBypassModel from core.emane.commeffect import EmaneCommEffectModel from core.emane.ieee80211abg import EmaneIeee80211abgModel -from core.emane.nodes import EmaneNode from core.emane.rfpipe import EmaneRfPipeModel from core.emane.tdma import EmaneTdmaModel - +from core.future.futuredata import NodeOptions _EMANE_MODELS = [ EmaneIeee80211abgModel, @@ -26,36 +23,37 @@ _EMANE_MODELS = [ class TestEmane: @pytest.mark.parametrize("model", _EMANE_MODELS) - def test_models(self, core, model): + def test_models(self, session, model, ip_prefixes): """ Test emane models within a basic network. - :param conftest.Core core: core fixture to test with + :param core.future.coreemu.FutureSession session: session for test :param model: emane model to test - :param func setup: setup function to configure emane node + :param ip_prefixes: generates ip addresses for nodes """ # create emane node for networking the core nodes - emane_node = core.session.add_object(name="emane", cls=EmaneNode) - emane_node.setposition(x=80, y=50) - - # set the emane model - core.set_emane_model(emane_node, model) + emane_network = session.create_emane_network( + model, + geo_reference=(47.57917, -122.13232, 2.00000) + ) + emane_network.setposition(x=80, y=50) # create nodes - core.create_node("n1", objid=1, position=(150, 150), services=EMANE_SERVICES, model="mdr") - core.create_node("n2", objid=2, position=(300, 150), services=EMANE_SERVICES, model="mdr") + node_options = NodeOptions() + node_options.set_position(150, 150) + node_one = session.create_wireless_node(node_options=node_options) + node_options.set_position(300, 150) + node_two = session.create_wireless_node(node_options=node_options) - # add interfaces to nodes - core.add_interface(emane_node, "n1") - core.add_interface(emane_node, "n2") + for i, node in enumerate([node_one, node_two]): + node.setposition(x=150 * (i + 1), y=150) + interface = ip_prefixes.create_interface(node) + session.add_link(node.objid, emane_network.objid, interface_one=interface) # instantiate session - core.session.instantiate() - - # assert node directories created - core.assert_nodes() + session.instantiate() # ping n2 from n1 and assert success - status = core.ping("n1", "n2") + status = ping(node_one, node_two, ip_prefixes, count=5) assert not status diff --git a/daemon/tests/test_future.py b/daemon/tests/test_future.py deleted file mode 100644 index eae42799..00000000 --- a/daemon/tests/test_future.py +++ /dev/null @@ -1,201 +0,0 @@ -import os -import time - -import pytest - -from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes, NodeOptions, LinkOptions -from core.misc import utils - - -@pytest.fixture -def future_session(): - # use coreemu and create a session - coreemu = CoreEmu() - session = coreemu.create_session() - session.set_state(EventTypes.CONFIGURATION_STATE.value) - - # return created session - yield session - - # shutdown coreemu - coreemu.shutdown() - - -IP4_PREFIX = "10.83.0.0/16" - -MODELS = [ - "router", - "host", - "PC", - "mdr", -] - -NET_TYPES = [ - NodeTypes.SWITCH, - NodeTypes.HUB, - NodeTypes.WIRELESS_LAN -] - - -class TestFuture: - @pytest.mark.parametrize("model", MODELS) - def test_node_add(self, future_session, model): - # given - node_options = NodeOptions(model=model) - - # when - node = future_session.add_node(node_options=node_options) - - # give time for node services to boot - time.sleep(1) - - # then - assert node - assert os.path.exists(node.nodedir) - assert node.alive() - assert node.up - assert node.check_cmd(["ip", "addr", "show", "lo"]) - node.validate() - - def test_node_update(self, future_session): - # given - node = future_session.add_node() - position_value = 100 - update_options = NodeOptions() - update_options.set_position(x=position_value, y=position_value) - - # when - future_session.update_node(node.objid, update_options) - - # then - assert node.position.x == position_value - assert node.position.y == position_value - - def test_node_delete(self, future_session): - # given - node = future_session.add_node() - - # when - future_session.delete_node(node.objid) - - # then - with pytest.raises(KeyError): - future_session.get_object(node.objid) - - @pytest.mark.parametrize("net_type", NET_TYPES) - def test_net(self, future_session, net_type): - # given - - # when - node = future_session.add_node(_type=net_type) - - # then - assert node - assert node.up - assert utils.check_cmd(["brctl", "show", node.brname]) - - def test_ptp(self, future_session): - # given - prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) - node_one = future_session.add_node() - node_two = future_session.add_node() - interface_one = prefixes.create_interface(node_one) - inteface_two = prefixes.create_interface(node_two) - - # when - future_session.add_link(node_one.objid, node_two.objid, interface_one, inteface_two) - - # then - assert node_one.netif(interface_one.id) - assert node_two.netif(inteface_two.id) - - def test_node_to_net(self, future_session): - # given - prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) - node_one = future_session.add_node() - node_two = future_session.add_node(_type=NodeTypes.SWITCH) - interface_one = prefixes.create_interface(node_one) - - # when - future_session.add_link(node_one.objid, node_two.objid, interface_one) - - # then - assert node_two.all_link_data(0) - assert node_one.netif(interface_one.id) - - def test_net_to_node(self, future_session): - # given - prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) - node_one = future_session.add_node(_type=NodeTypes.SWITCH) - node_two = future_session.add_node() - interface_two = prefixes.create_interface(node_two) - - # when - future_session.add_link(node_one.objid, node_two.objid, interface_two=interface_two) - - # then - assert node_one.all_link_data(0) - assert node_two.netif(interface_two.id) - - def test_net_to_net(self, future_session): - # given - node_one = future_session.add_node(_type=NodeTypes.SWITCH) - node_two = future_session.add_node(_type=NodeTypes.SWITCH) - - # when - future_session.add_link(node_one.objid, node_two.objid) - - # then - assert node_one.all_link_data(0) - - def test_link_update(self, future_session): - # given - prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) - node_one = future_session.add_node() - node_two = future_session.add_node(_type=NodeTypes.SWITCH) - interface_one = prefixes.create_interface(node_one) - future_session.add_link(node_one.objid, node_two.objid, interface_one) - interface = node_one.netif(interface_one.id) - output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) - assert "delay" not in output - assert "rate" not in output - assert "loss" not in output - assert "duplicate" not in output - - # when - link_options = LinkOptions() - link_options.delay = 50 - link_options.bandwidth = 5000000 - link_options.per = 25 - link_options.dup = 25 - future_session.update_link(node_one.objid, node_two.objid, - interface_one_id=interface_one.id, link_options=link_options) - - # then - output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) - assert "delay" in output - assert "rate" in output - assert "loss" in output - assert "duplicate" in output - - def test_link_delete(self, future_session): - # given - prefixes = IpPrefixes(ip4_prefix=IP4_PREFIX) - node_one = future_session.add_node() - node_two = future_session.add_node() - interface_one = prefixes.create_interface(node_one) - interface_two = prefixes.create_interface(node_two) - future_session.add_link(node_one.objid, node_two.objid, interface_one, interface_two) - assert node_one.netif(interface_one.id) - assert node_two.netif(interface_two.id) - assert future_session.get_node_count() == 3 - - # when - future_session.delete_link(node_one.objid, node_two.objid, interface_one.id, interface_two.id) - - # then - assert not node_one.netif(interface_one.id) - assert not node_two.netif(interface_two.id) - assert future_session.get_node_count() == 2 diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index 5fa0f7ed..77c8b9fe 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -128,7 +128,7 @@ class TestGui: core.session.broker.dorecvloop = False # have broker handle a configuration state change - core.session.set_state(EventTypes.CONFIGURATION_STATE.value) + core.session.set_state(EventTypes.CONFIGURATION_STATE) event_message = state_message(EventTypes.CONFIGURATION_STATE) core.session.broker.handlerawmsg(event_message) diff --git a/daemon/tests/test_links.py b/daemon/tests/test_links.py new file mode 100644 index 00000000..4b5085e4 --- /dev/null +++ b/daemon/tests/test_links.py @@ -0,0 +1,260 @@ +from core.enumerations import NodeTypes +from core.future.futuredata import LinkOptions +from core.misc import utils + + +def create_ptp_network(session, ip_prefixes): + # create nodes + node_one = session.add_node() + node_two = session.add_node() + + # link nodes to net node + interface_one = ip_prefixes.create_interface(node_one) + interface_two = ip_prefixes.create_interface(node_two) + session.add_link(node_one.objid, node_two.objid, interface_one, interface_two) + + # instantiate session + session.instantiate() + + return node_one, node_two + + +def ping_output(from_node, to_node, ip_prefixes): + address = ip_prefixes.ip4_address(to_node) + output = from_node.check_cmd(["ping", "-i", "0.05", "-c", "3", address]) + return output + + +def iperf(from_node, to_node, ip_prefixes): + # run iperf server, run client, kill iperf server + address = ip_prefixes.ip4_address(to_node) + vcmd, stdin, stdout, stderr = to_node.client.popen(["iperf", "-s", "-u", "-y", "C"]) + from_node.cmd(["iperf", "-u", "-t", "5", "-c", address]) + to_node.cmd(["killall", "-9", "iperf"]) + return stdout.read().strip() + + +class TestLinks: + def test_ptp(self, session, ip_prefixes): + # given + node_one = session.add_node() + node_two = session.add_node() + interface_one = ip_prefixes.create_interface(node_one) + inteface_two = ip_prefixes.create_interface(node_two) + + # when + session.add_link(node_one.objid, node_two.objid, interface_one, inteface_two) + + # then + assert node_one.netif(interface_one.id) + assert node_two.netif(inteface_two.id) + + def test_node_to_net(self, session, ip_prefixes): + # given + node_one = session.add_node() + node_two = session.add_node(_type=NodeTypes.SWITCH) + interface_one = ip_prefixes.create_interface(node_one) + + # when + session.add_link(node_one.objid, node_two.objid, interface_one) + + # then + assert node_two.all_link_data(0) + assert node_one.netif(interface_one.id) + + def test_net_to_node(self, session, ip_prefixes): + # given + node_one = session.add_node(_type=NodeTypes.SWITCH) + node_two = session.add_node() + interface_two = ip_prefixes.create_interface(node_two) + + # when + session.add_link(node_one.objid, node_two.objid, interface_two=interface_two) + + # then + assert node_one.all_link_data(0) + assert node_two.netif(interface_two.id) + + def test_net_to_net(self, session): + # given + node_one = session.add_node(_type=NodeTypes.SWITCH) + node_two = session.add_node(_type=NodeTypes.SWITCH) + + # when + session.add_link(node_one.objid, node_two.objid) + + # then + assert node_one.all_link_data(0) + + def test_link_update(self, session, ip_prefixes): + # given + node_one = session.add_node() + node_two = session.add_node(_type=NodeTypes.SWITCH) + interface_one = ip_prefixes.create_interface(node_one) + session.add_link(node_one.objid, node_two.objid, interface_one) + interface = node_one.netif(interface_one.id) + output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) + assert "delay" not in output + assert "rate" not in output + assert "loss" not in output + assert "duplicate" not in output + + # when + link_options = LinkOptions() + link_options.delay = 50 + link_options.bandwidth = 5000000 + link_options.per = 25 + link_options.dup = 25 + session.update_link(node_one.objid, node_two.objid, + interface_one_id=interface_one.id, link_options=link_options) + + # then + output = utils.check_cmd(["tc", "qdisc", "show", "dev", interface.localname]) + assert "delay" in output + assert "rate" in output + assert "loss" in output + assert "duplicate" in output + + def test_link_delete(self, session, ip_prefixes): + # given + node_one = session.add_node() + node_two = session.add_node() + interface_one = ip_prefixes.create_interface(node_one) + interface_two = ip_prefixes.create_interface(node_two) + session.add_link(node_one.objid, node_two.objid, interface_one, interface_two) + assert node_one.netif(interface_one.id) + assert node_two.netif(interface_two.id) + assert session.get_node_count() == 3 + + # when + session.delete_link(node_one.objid, node_two.objid, interface_one.id, interface_two.id) + + # then + assert not node_one.netif(interface_one.id) + assert not node_two.netif(interface_two.id) + assert session.get_node_count() == 2 + + def test_link_bandwidth(self, session, ip_prefixes): + """ + Test ptp node network with modifying link bandwidth. + + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes + """ + + # create link network + node_one, node_two = create_ptp_network(session, ip_prefixes) + + # output csv index + bandwidth_index = 8 + + # run iperf, validate normal bandwidth + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = int(stdout.split(',')[bandwidth_index]) + assert 900000 <= value <= 1100000 + + # change bandwidth in bits per second + link_options = LinkOptions() + link_options.bandwidth = 500000 + session.update_link(node_one.objid, node_two.objid, link_options=link_options) + + # run iperf again + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = int(stdout.split(',')[bandwidth_index]) + assert 400000 <= value <= 600000 + + def test_link_loss(self, session, ip_prefixes): + """ + Test ptp node network with modifying link packet loss. + + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes + """ + + # create link network + node_one, node_two = create_ptp_network(session, ip_prefixes) + + # output csv index + loss_index = -2 + + # run iperf, validate normal bandwidth + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = float(stdout.split(',')[loss_index]) + assert 0 <= value <= 0.5 + + # change bandwidth in bits per second + link_options = LinkOptions() + link_options.per = 50 + session.update_link(node_one.objid, node_two.objid, link_options=link_options) + + # run iperf again + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = float(stdout.split(',')[loss_index]) + assert 40 <= value <= 60 + + def test_link_delay(self, session, ip_prefixes): + """ + Test ptp node network with modifying link packet delay. + + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes + """ + + # create link network + node_one, node_two = create_ptp_network(session, ip_prefixes) + + # run ping for delay information + stdout = ping_output(node_one, node_two, ip_prefixes) + assert stdout + rtt_line = stdout.split("\n")[-1] + rtt_values = rtt_line.split("=")[1].split("ms")[0].strip() + rtt_avg = float(rtt_values.split("/")[2]) + assert 0 <= rtt_avg <= 0.2 + + # change delay in microseconds + link_options = LinkOptions() + link_options.delay = 1000000 + session.update_link(node_one.objid, node_two.objid, link_options=link_options) + + # run ping for delay information again + stdout = ping_output(node_one, node_two, ip_prefixes) + assert stdout + rtt_line = stdout.split("\n")[-1] + rtt_values = rtt_line.split("=")[1].split("ms")[0].strip() + rtt_avg = float(rtt_values.split("/")[2]) + assert 1800 <= rtt_avg <= 2200 + + def test_link_jitter(self, session, ip_prefixes): + """ + Test ptp node network with modifying link packet jitter. + + :param core.future.coreemu.FutureSession session: session for test + :param ip_prefixes: generates ip addresses for nodes + """ + + # create link network + node_one, node_two = create_ptp_network(session, ip_prefixes) + + # output csv index + jitter_index = 9 + + # run iperf + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = float(stdout.split(",")[jitter_index]) + assert -0.5 <= value <= 0.05 + + # change jitter in microseconds + link_options = LinkOptions() + link_options.jitter = 1000000 + session.update_link(node_one.objid, node_two.objid, link_options=link_options) + + # run iperf again + stdout = iperf(node_one, node_two, ip_prefixes) + assert stdout + value = float(stdout.split(",")[jitter_index]) + assert 200 <= value <= 500 diff --git a/daemon/tests/test_nodes.py b/daemon/tests/test_nodes.py new file mode 100644 index 00000000..94a757a5 --- /dev/null +++ b/daemon/tests/test_nodes.py @@ -0,0 +1,79 @@ +import os +import time + +import pytest + +from core.enumerations import NodeTypes +from core.future.futuredata import NodeOptions +from core.misc import utils + +MODELS = [ + "router", + "host", + "PC", + "mdr", +] + +NET_TYPES = [ + NodeTypes.SWITCH, + NodeTypes.HUB, + NodeTypes.WIRELESS_LAN +] + + +class TestNodes: + @pytest.mark.parametrize("model", MODELS) + def test_node_add(self, session, model): + # given + node_options = NodeOptions(model=model) + + # when + node = session.add_node(node_options=node_options) + + # give time for node services to boot + time.sleep(1) + + # then + assert node + assert os.path.exists(node.nodedir) + assert node.alive() + assert node.up + assert node.check_cmd(["ip", "addr", "show", "lo"]) + node.validate() + + def test_node_update(self, session): + # given + node = session.add_node() + position_value = 100 + update_options = NodeOptions() + update_options.set_position(x=position_value, y=position_value) + + # when + session.update_node(node.objid, update_options) + + # then + assert node.position.x == position_value + assert node.position.y == position_value + + def test_node_delete(self, session): + # given + node = session.add_node() + + # when + session.delete_node(node.objid) + + # then + with pytest.raises(KeyError): + session.get_object(node.objid) + + @pytest.mark.parametrize("net_type", NET_TYPES) + def test_net(self, session, net_type): + # given + + # when + node = session.add_node(_type=net_type) + + # then + assert node + assert node.up + assert utils.check_cmd(["brctl", "show", node.brname]) diff --git a/ns3/corens3/obj.py b/ns3/corens3/obj.py index e076e8f4..229288d2 100644 --- a/ns3/corens3/obj.py +++ b/ns3/corens3/obj.py @@ -386,7 +386,7 @@ class Ns3Session(Session): ns.core.Simulator.Run() # self.evq.run() # event queue may have WayPointMobility events - self.set_state(EventTypes.RUNTIME_STATE.value, send_event=True) + self.set_state(EventTypes.RUNTIME_STATE, send_event=True) t = threading.Thread(target=runthread) t.daemon = True t.start() @@ -454,7 +454,7 @@ class Ns3Session(Session): Start a thread that updates CORE nodes based on their ns-3 positions. """ - self.set_state(EventTypes.INSTANTIATION_STATE.value) + self.set_state(EventTypes.INSTANTIATION_STATE) self.mobilitythread = threading.Thread( target=self.ns3mobilitythread, args=(refresh_ms,)) From dc751dde2bf29f06937e359fae4f188ba672f26f Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 26 Apr 2018 13:06:18 -0700 Subject: [PATCH 141/152] removed session manager, since CoreEmu does this now, set future examples to serve as API examples, removed netns examples that are replaced by these API variations --- daemon/core/future/coreemu.py | 4 +- daemon/core/session.py | 64 +--- .../emane80211_api.py => api/emane80211.py} | 0 daemon/examples/{future => api}/parser.py | 0 .../{future/switch_api.py => api/switch.py} | 0 .../switch_inject.py} | 0 .../{future/wlan_api.py => api/wlan.py} | 0 daemon/examples/netns/basicrange.py | 109 ------- daemon/examples/netns/daemonnodes.py | 3 +- daemon/examples/netns/distributed.py | 2 +- daemon/examples/netns/emane80211.py | 102 ------ daemon/examples/netns/howmanynodes.py | 16 +- .../examples/netns/iperf-performance-chain.py | 103 ------- daemon/examples/netns/iperf-performance.sh | 290 ------------------ daemon/examples/netns/switch.py | 76 ----- daemon/examples/netns/switchtest.py | 104 ------- daemon/examples/netns/twonodes.sh | 33 -- daemon/examples/netns/wlantest.py | 102 ------ 18 files changed, 12 insertions(+), 996 deletions(-) rename daemon/examples/{future/emane80211_api.py => api/emane80211.py} (100%) rename daemon/examples/{future => api}/parser.py (100%) rename daemon/examples/{future/switch_api.py => api/switch.py} (100%) rename daemon/examples/{future/switch_api_inject.py => api/switch_inject.py} (100%) rename daemon/examples/{future/wlan_api.py => api/wlan.py} (100%) delete mode 100755 daemon/examples/netns/basicrange.py delete mode 100755 daemon/examples/netns/emane80211.py delete mode 100755 daemon/examples/netns/iperf-performance-chain.py delete mode 100755 daemon/examples/netns/iperf-performance.sh delete mode 100755 daemon/examples/netns/switch.py delete mode 100755 daemon/examples/netns/switchtest.py delete mode 100755 daemon/examples/netns/twonodes.sh delete mode 100755 daemon/examples/netns/wlantest.py diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 4b906fcf..f571f08c 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -113,8 +113,8 @@ class IdGen(object): class FutureSession(Session): - def __init__(self, session_id, config=None, persistent=True, mkdir=True): - super(FutureSession, self).__init__(session_id, config, persistent, mkdir) + def __init__(self, session_id, config=None, mkdir=True): + super(FutureSession, self).__init__(session_id, config, mkdir) # object management self.node_id_gen = IdGen() diff --git a/daemon/core/session.py b/daemon/core/session.py index a7149c34..69a6c1a7 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -3,7 +3,6 @@ session.py: defines the Session class used by the core-daemon daemon program that manages a CORE session. """ -import atexit import os import pprint import random @@ -52,68 +51,17 @@ node_map = nodemaps.NODES nodeutils.set_node_map(node_map) -class SessionManager(object): - """ - Manages currently known sessions. - """ - sessions = set() - session_lock = threading.Lock() - - @classmethod - def add(cls, session): - """ - Add a session to the manager. - - :param Session session: session to add - :return: nothing - """ - with cls.session_lock: - logger.info("adding session to manager: %s", session.session_id) - cls.sessions.add(session) - - @classmethod - def remove(cls, session): - """ - Remove session from the manager. - - :param Session session: session to remove - :return: nothing - """ - with cls.session_lock: - logger.info("removing session from manager: %s", session.session_id) - if session in cls.sessions: - cls.sessions.remove(session) - else: - logger.info("session was already removed: %s", session.session_id) - - @classmethod - def on_exit(cls): - """ - Method used to shutdown all currently known sessions, in case of unexpected exit. - - :return: nothing - """ - logger.info("caught program exit, shutting down all known sessions") - while cls.sessions: - with cls.session_lock: - session = cls.sessions.pop() - logger.error("WARNING: automatically shutting down non-persistent session %s - %s", - session.session_id, session.name) - session.shutdown() - - class Session(object): """ CORE session manager. """ - def __init__(self, session_id, config=None, persistent=False, mkdir=True): + def __init__(self, session_id, config=None, mkdir=True): """ Create a Session instance. :param int session_id: session id :param dict config: session configuration - :param bool persistent: flag is session is considered persistent :param bool mkdir: flag to determine if a directory should be made """ self.session_id = session_id @@ -152,9 +100,6 @@ class Session(object): self.add_state_hook(state=EventTypes.RUNTIME_STATE.value, hook=self.runtime_state_hook) - if not persistent: - SessionManager.add(self) - self.master = False # handlers for broadcasting information @@ -227,9 +172,6 @@ class Session(object): for handler in self.shutdown_handlers: handler(self) - # remove this session from the manager - SessionManager.remove(self) - def broadcast_event(self, event_data): """ Handle event data that should be provided to event handler. @@ -1514,7 +1456,3 @@ class SessionMetaData(ConfigurableManager): :return: configuration items iterator """ return self.configs.iteritems() - - -# configure the program exit function to run -atexit.register(SessionManager.on_exit) diff --git a/daemon/examples/future/emane80211_api.py b/daemon/examples/api/emane80211.py similarity index 100% rename from daemon/examples/future/emane80211_api.py rename to daemon/examples/api/emane80211.py diff --git a/daemon/examples/future/parser.py b/daemon/examples/api/parser.py similarity index 100% rename from daemon/examples/future/parser.py rename to daemon/examples/api/parser.py diff --git a/daemon/examples/future/switch_api.py b/daemon/examples/api/switch.py similarity index 100% rename from daemon/examples/future/switch_api.py rename to daemon/examples/api/switch.py diff --git a/daemon/examples/future/switch_api_inject.py b/daemon/examples/api/switch_inject.py similarity index 100% rename from daemon/examples/future/switch_api_inject.py rename to daemon/examples/api/switch_inject.py diff --git a/daemon/examples/future/wlan_api.py b/daemon/examples/api/wlan.py similarity index 100% rename from daemon/examples/future/wlan_api.py rename to daemon/examples/api/wlan.py diff --git a/daemon/examples/netns/basicrange.py b/daemon/examples/netns/basicrange.py deleted file mode 100755 index ca33bccb..00000000 --- a/daemon/examples/netns/basicrange.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c)2011-2012 the Boeing Company. -# See the LICENSE file included in this distribution. -# -# Test 3D range calculation of the BasicRangeModel by adding n nodes to a WLAN -# stacked 100 units above each other (using z-axis). -# - - -import datetime -import optparse -import sys -import time - -from core.misc import ipaddress -from core.mobility import BasicRangeModel -from core.netns.nodes import WlanNode -from core.netns.vnet import EbtablesQueue -from core.netns.vnode import LxcNode -from core.session import Session - -# node list - global so you can play using 'python -i' -# e.g. >>> n[0].session.shutdown() -n = [] - - -def test(options): - prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1, persistent=True) - if options.enablesdt: - # GUI default - session.location.setrefgeo(47.57917, -122.13232, 50.0) - session.location.refscale = 100.0 - session.options.enablesdt = True - session.options.sdturl = options.sdturl - wlanid = options.numnodes + 1 - net = session.add_object( - cls=WlanNode, - name="wlan%d" % wlanid, - objid=wlanid - ) - - values = list(BasicRangeModel.getdefaultvalues()) - # values[0] = 5000000 # 5000km range - net.setmodel(BasicRangeModel, values) - for i in xrange(1, options.numnodes + 1): - node = session.add_object(cls=LxcNode, name="n%d" % i, objid=i) - address = "%s/%s" % (prefix.addr(i), prefix.prefixlen) - print "setting node address: %s - %s" % (node.objid, address) - node.newnetif(net, [address]) - # set increasing Z coordinates - node.setposition(10, 10, 100) - n.append(node) - - # example setting node n2 to a high altitude - # n[1].setposition(10, 10, 2000000) # 2000km - # session.sdt.updatenode(n[1].objid, 0, 10, 10, 2000000) - - # launches terminal for the first node - n[0].client.icmd(["ping", "-c", "5", "127.0.0.1"]) - - # wait for rate seconds to allow ebtables commands to commit - time.sleep(EbtablesQueue.rate) - - raw_input("press enter to exit") - session.shutdown() - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - - parser.set_defaults(numnodes=2, enablesdt=False, sdturl="tcp://127.0.0.1:50000/") - parser.add_option( - "-n", "--numnodes", dest="numnodes", type=int, - help="number of nodes to test; default = %s" % parser.defaults["numnodes"] - ) - parser.add_option("-s", "--sdt", dest="enablesdt", action="store_true", help="enable SDT output") - parser.add_option( - "-u", "--sdturl", dest="sdturl", type="string", - help="URL for SDT connection, default = %s" % parser.defaults["sdturl"] - ) - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.numnodes < 2: - usage("invalid number of nodes: %s" % options.numnodes) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - test(options) - - print >> sys.stderr, "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__": - main() diff --git a/daemon/examples/netns/daemonnodes.py b/daemon/examples/netns/daemonnodes.py index 76e3f9ce..3fe1d599 100755 --- a/daemon/examples/netns/daemonnodes.py +++ b/daemon/examples/netns/daemonnodes.py @@ -105,7 +105,7 @@ def main(): start = datetime.datetime.now() prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1, persistent=True) + session = Session(1) if "server" in globals(): server.addsession(session) @@ -125,7 +125,6 @@ def main(): # Set the local session id to match the port. # Not necessary but seems neater. - # session.sessionid = session.broker.getserver("localhost")[2].getsockname()[1] session.broker.setupserver(daemon) # We do not want the recvloop running as we will deal ourselves diff --git a/daemon/examples/netns/distributed.py b/daemon/examples/netns/distributed.py index 6ffd49f1..b84450af 100755 --- a/daemon/examples/netns/distributed.py +++ b/daemon/examples/netns/distributed.py @@ -55,7 +55,7 @@ def main(): start = datetime.datetime.now() prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1, persistent=True) + session = Session(1) if 'server' in globals(): server.addsession(session) diff --git a/daemon/examples/netns/emane80211.py b/daemon/examples/netns/emane80211.py deleted file mode 100755 index e9f30ef6..00000000 --- a/daemon/examples/netns/emane80211.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/python -i - -# Copyright (c)2010-2014 the Boeing Company. -# See the LICENSE file included in this distribution. - -# Example CORE Python script that attaches N nodes to an EMANE 802.11abg -# network. One of the parameters is changed, the pathloss mode. - -import datetime -import optparse -import sys - -from core import constants -from core.emane.ieee80211abg import EmaneIeee80211abgModel -from core.emane.nodes import EmaneNode -from core.misc import ipaddress -from core.netns import nodes - -# node list (count from 1) -from core.session import Session - -n = [None] - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - parser.set_defaults(numnodes=5) - - parser.add_option("-n", "--numnodes", dest="numnodes", type=int, - help="number of nodes") - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.numnodes < 1: - usage("invalid number of nodes: %s" % options.numnodes) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - # IP subnet - prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - # session with some EMANE initialization - cfg = {'verbose': 'false'} - session = Session(1, config=cfg, persistent=True) - session.master = True - session.location.setrefgeo(47.57917, -122.13232, 2.00000) - session.location.refscale = 150.0 - session.config['emane_models'] = "RfPipe, Ieee80211abg, Bypass" - session.emane.loadmodels() - if 'server' in globals(): - server.addsession(session) - - # EMANE WLAN - print "creating EMANE WLAN wlan1" - wlan = session.add_object(cls=EmaneNode, name="wlan1") - wlan.setposition(x=80, y=50) - names = EmaneIeee80211abgModel.getnames() - values = list(EmaneIeee80211abgModel.getdefaultvalues()) - # TODO: change any of the EMANE 802.11 parameter values here - for i in range(0, len(names)): - print "EMANE 80211 \"%s\" = \"%s\"" % (names[i], values[i]) - try: - values[names.index('pathlossmode')] = '2ray' - except ValueError: - values[names.index('propagationmodel')] = '2ray' - - session.emane.setconfig(wlan.objid, EmaneIeee80211abgModel.name, values) - services_str = "zebra|OSPFv3MDR|IPForward" - - print "creating %d nodes with addresses from %s" % \ - (options.numnodes, prefix) - for i in xrange(1, options.numnodes + 1): - tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) - tmp.newnetif(wlan, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) - tmp.setposition(x=150 * i, y=150) - session.services.addservicestonode(tmp, "", services_str) - n.append(tmp) - - # this starts EMANE, etc. - session.node_count = str(options.numnodes + 1) - session.instantiate() - - # start a shell on node 1 - n[1].client.term("bash") - - print "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__" or __name__ == "__builtin__": - main() diff --git a/daemon/examples/netns/howmanynodes.py b/daemon/examples/netns/howmanynodes.py index 8803d872..1a20e013 100755 --- a/daemon/examples/netns/howmanynodes.py +++ b/daemon/examples/netns/howmanynodes.py @@ -106,7 +106,7 @@ def main(): parser.print_help() sys.exit(err) - (options, args) = parser.parse_args() + options, args = parser.parse_args() for a in args: sys.stderr.write("ignoring command line argument: %s\n" % a) @@ -117,8 +117,7 @@ def main(): print "Testing how many network namespace nodes this machine can create." print " - %s" % linuxversion() mem = memfree() - print " - %.02f GB total memory (%.02f GB swap)" % \ - (mem["total"] / GBD, mem["stotal"] / GBD) + print " - %.02f GB total memory (%.02f GB swap)" % (mem["total"] / GBD, mem["stotal"] / GBD) print " - using IPv4 network prefix %s" % prefix print " - using wait time of %s" % options.waittime print " - using %d nodes per bridge" % options.bridges @@ -135,7 +134,7 @@ def main(): lfp.write("# numnodes,%s\n" % ",".join(MEMKEYS)) lfp.flush() - session = Session(1, persistent=True) + session = Session(1) switch = session.add_object(cls=nodes.SwitchNode) switchlist.append(switch) print "Added bridge %s (%d)." % (switch.brname, len(switchlist)) @@ -146,15 +145,14 @@ def main(): i += 1 # optionally add a bridge (options.bridges nodes per bridge) try: - if options.bridges > 0 and switch.numnetif() >= options.bridges: + if 0 < options.bridges <= switch.numnetif(): switch = session.add_object(cls=nodes.SwitchNode) switchlist.append(switch) - print "\nAdded bridge %s (%d) for node %d." % \ - (switch.brname, len(switchlist), i) + print "\nAdded bridge %s (%d) for node %d." % (switch.brname, len(switchlist), i) except Exception, e: - print "At %d bridges (%d nodes) caught exception:\n%s\n" % \ - (len(switchlist), i - 1, e) + print "At %d bridges (%d nodes) caught exception:\n%s\n" % (len(switchlist), i - 1, e) break + # create a node try: n = session.add_object(cls=nodes.LxcNode, name="n%d" % i) diff --git a/daemon/examples/netns/iperf-performance-chain.py b/daemon/examples/netns/iperf-performance-chain.py deleted file mode 100755 index 412dd9a6..00000000 --- a/daemon/examples/netns/iperf-performance-chain.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/python - -# Copyright (c)2013 the Boeing Company. -# See the LICENSE file included in this distribution. - -# This script creates a CORE session, that will connect n nodes together -# in a chain, with static routes between nodes -# number of nodes / number of hops -# 2 0 -# 3 1 -# 4 2 -# n n - 2 -# -# Use core-cleanup to clean up after this script as the session is left running. -# - -import datetime -import optparse -import sys - -from core import constants -from core.misc import ipaddress -from core.netns import nodes - -# node list (count from 1) -from core.session import Session - -n = [None] - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - parser.set_defaults(numnodes=5) - - parser.add_option("-n", "--numnodes", dest="numnodes", type=int, - help="number of nodes") - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.numnodes < 1: - usage("invalid number of nodes: %s" % options.numnodes) - - if options.numnodes >= 255: - usage("invalid number of nodes: %s" % options.numnodes) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - session = Session(1, persistent=True) - if 'server' in globals(): - server.addsession(session) - print "creating %d nodes" % options.numnodes - left = None - prefix = None - for i in xrange(1, options.numnodes + 1): - tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) - if left: - tmp.newnetif(left, ["%s/%s" % (prefix.addr(2), prefix.prefixlen)]) - - # limit: i < 255 - prefix = ipaddress.Ipv4Prefix("10.83.%d.0/24" % i) - right = session.add_object(cls=nodes.PtpNet) - tmp.newnetif(right, ["%s/%s" % (prefix.addr(1), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.all.forwarding=1"]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.conf.default.rp_filter=0"]) - tmp.setposition(x=100 * i, y=150) - n.append(tmp) - left = right - - prefixes = map(lambda (x): ipaddress.Ipv4Prefix("10.83.%d.0/24" % x), - xrange(1, options.numnodes + 1)) - - # set up static routing in the chain - for i in xrange(1, options.numnodes + 1): - for j in xrange(1, options.numnodes + 1): - if j < i - 1: - gw = prefixes[i - 2].addr(1) - elif j > i: - if i > len(prefixes) - 1: - continue - gw = prefixes[i - 1].addr(2) - else: - continue - net = prefixes[j - 1] - n[i].cmd([constants.IP_BIN, "route", "add", str(net), "via", str(gw)]) - - print "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__" or __name__ == "__builtin__": - main() diff --git a/daemon/examples/netns/iperf-performance.sh b/daemon/examples/netns/iperf-performance.sh deleted file mode 100755 index 0301c508..00000000 --- a/daemon/examples/netns/iperf-performance.sh +++ /dev/null @@ -1,290 +0,0 @@ -#!/bin/sh -e -# -# iperf-performance.sh -# -# (c)2013 the Boeing Company -# authors: Jeff Ahrenholz -# -# Utility script to automate several iperf runs. -# - -# number of iperf runs per test -NUMRUNS=10 -# number of seconds per run (10s is iperf default) -RUNTIME=10 -# logging -LOG=/tmp/${0}.log -STAMP=`date +%Y%m%d%H%M%S` - -# -# client---(loopback)---server -# -loopbacktest () { - killall iperf 2> /dev/null || true - - echo ">> loopback iperf test" - echo "loopback" > ${LOG} - - # start an iperf server in the background - # -s = server - # -y c = CSV output - echo "starting local iperf server" - iperf -s -y c >> ${LOG} & - - # run an iperf client NUMRUNS times - i=1 - while [ $i -le $NUMRUNS ]; do - echo "run $i/$NUMRUNS:" - iperf -t ${RUNTIME} -c localhost - sleep 0.3 - i=$((i+1)) - done - - sleep 1 - echo "stopping local iperf server" - killall -v iperf - -} - -# -# lxc1( client )---veth-pair---lxc2( server ) -# -lxcvethtest () { - SERVERIP=10.0.0.1 - CLIENTIP=10.0.0.2 - SERVER=/tmp/${0}-server - CLIENT=/tmp/${0}-client - - echo ">> lxc veth iperf test" - echo "lxcveth" >> ${LOG} - - echo "starting lxc iperf server" - vnoded -l $SERVER.log -p $SERVER.pid -c $SERVER - ip link add name veth0.1 type veth peer name veth0 - ip link set veth0 netns `cat $SERVER.pid` up - vcmd -c $SERVER -- ip link set lo up - vcmd -c $SERVER -- ip addr add $SERVERIP/24 dev veth0 - vcmd -c $SERVER -- iperf -s -y c >> ${LOG} & - - echo "starting lxc iperf client" - vnoded -l $CLIENT.log -p $CLIENT.pid -c $CLIENT - ip link set veth0.1 netns `cat $CLIENT.pid` up - vcmd -c $CLIENT -- ip link set lo up - vcmd -c $CLIENT -- ip addr add $CLIENTIP/24 dev veth0.1 - - i=1 - while [ $i -le $NUMRUNS ]; do - echo "run $i/$NUMRUNS:" - vcmd -c $CLIENT -- iperf -t ${RUNTIME} -c ${SERVERIP} - sleep 0.3 - i=$((i+1)) - done - - sleep 1 - echo "stopping lxc iperf server" - vcmd -c $SERVER -- killall -v iperf - echo "stopping containers" - kill -9 `cat $SERVER.pid` - kill -9 `cat $CLIENT.pid` - - echo "cleaning up" - rm -f ${SERVER}* - rm -f ${CLIENT}* -} - -# -# lxc1( client veth:):veth---bridge---veth:(:veth server )lxc2 -# -lxcbrtest () { - SERVERIP=10.0.0.1 - CLIENTIP=10.0.0.2 - SERVER=/tmp/${0}-server - CLIENT=/tmp/${0}-client - BRIDGE="lxcbrtest" - - echo ">> lxc bridge iperf test" - echo "lxcbr" >> ${LOG} - - echo "building bridge" - brctl addbr $BRIDGE - brctl stp $BRIDGE off # disable spanning tree protocol - brctl setfd $BRIDGE 0 # disable forwarding delay - ip link set $BRIDGE up - - echo "starting lxc iperf server" - vnoded -l $SERVER.log -p $SERVER.pid -c $SERVER - ip link add name veth0.1 type veth peer name veth0 - ip link set veth0 netns `cat $SERVER.pid` up - vcmd -c $SERVER -- ip link set lo up - vcmd -c $SERVER -- ip addr add $SERVERIP/24 dev veth0 - brctl addif $BRIDGE veth0.1 - ip link set veth0.1 up - vcmd -c $SERVER -- iperf -s -y c >> ${LOG} & - - echo "starting lxc iperf client" - vnoded -l $CLIENT.log -p $CLIENT.pid -c $CLIENT - ip link add name veth1.1 type veth peer name veth1 - ip link set veth1 netns `cat $CLIENT.pid` up - vcmd -c $CLIENT -- ip link set lo up - vcmd -c $CLIENT -- ip addr add $CLIENTIP/24 dev veth1 - brctl addif $BRIDGE veth1.1 - ip link set veth1.1 up - - i=1 - while [ $i -le $NUMRUNS ]; do - echo "run $i/$NUMRUNS:" - vcmd -c $CLIENT -- iperf -t ${RUNTIME} -c ${SERVERIP} - sleep 0.3 - i=$((i+1)) - done - - sleep 1 - echo "stopping lxc iperf server" - vcmd -c $SERVER -- killall -v iperf - echo "stopping containers" - kill -9 `cat $SERVER.pid` - kill -9 `cat $CLIENT.pid` - - echo "cleaning up" - ip link set $BRIDGE down - brctl delbr $BRIDGE - rm -f ${SERVER}* - rm -f ${CLIENT}* -} - -# -# n1---n2---n3--- ... ---nN -# N nodes (N-2 hops) in chain with static routing -# -chaintest () { - NUMNODES=$1 - SERVERIP=10.83.$NUMNODES.1 - - if [ -d /tmp/pycore.* ]; then - echo "/tmp/pycore.* already exists, skipping chaintest $NUMNODES" - return - fi - - echo ">> n=$NUMNODES node chain iperf test" - echo "chain$NUMNODES" >> ${LOG} - - echo "running external chain CORE script with '-n $NUMNODES'" - python iperf-performance-chain.py -n $NUMNODES - - echo "starting lxc iperf server on node $NUMNODES" - vcmd -c /tmp/pycore.*/n$NUMNODES -- iperf -s -y c >> ${LOG} & - - echo "starting lxc iperf client" - i=1 - while [ $i -le $NUMRUNS ]; do - echo "run $i/$NUMRUNS:" - vcmd -c /tmp/pycore.*/n1 -- iperf -t ${RUNTIME} -c ${SERVERIP} - sleep 0.3 - i=$((i+1)) - done - - sleep 1 - echo "stopping lxc iperf server" - vcmd -c /tmp/pycore.*/n$NUMNODES -- killall -v iperf - echo "cleaning up" - core-cleanup -} -if [ "z$1" != "z" ]; then - echo "This script takes no parameters and must be run as root." - exit 1 -fi -if [ `id -u` != 0 ]; then - echo "This script must be run as root." - exit 1 -fi - - -# -# N lxc clients >---bridge---veth:(:veth server ) -# -clientstest () { - NUMCLIENTS=$1 - SERVERIP=10.0.0.1 - SERVER=/tmp/${0}-server - BRIDGE="lxcbrtest" - - echo ">> n=$NUMCLIENTS clients iperf test" - echo "clients$NUMCLIENTS" >> ${LOG} - - echo "building bridge" - brctl addbr $BRIDGE - brctl stp $BRIDGE off # disable spanning tree protocol - brctl setfd $BRIDGE 0 # disable forwarding delay - ip link set $BRIDGE up - - echo "starting lxc iperf server" - vnoded -l $SERVER.log -p $SERVER.pid -c $SERVER - ip link add name veth0.1 type veth peer name veth0 - ip link set veth0 netns `cat $SERVER.pid` up - vcmd -c $SERVER -- ip link set lo up - vcmd -c $SERVER -- ip addr add $SERVERIP/24 dev veth0 - brctl addif $BRIDGE veth0.1 - ip link set veth0.1 up - vcmd -c $SERVER -- iperf -s -y c >> ${LOG} & - - i=1 - CLIENTS="" - while [ $i -le $NUMCLIENTS ]; do - echo "starting lxc iperf client $i/$NUMCLIENTS" - CLIENT=/tmp/${0}-client$i - CLIENTIP=10.0.0.1$i - vnoded -l $CLIENT.log -p $CLIENT.pid -c $CLIENT - ip link add name veth1.$i type veth peer name veth1 - ip link set veth1 netns `cat $CLIENT.pid` up - vcmd -c $CLIENT -- ip link set lo up - vcmd -c $CLIENT -- ip addr add $CLIENTIP/24 dev veth1 - brctl addif $BRIDGE veth1.$i - ip link set veth1.$i up - i=$((i+1)) - CLIENTS="$CLIENTS $CLIENT" - done - - j=1 - while [ $j -le $NUMRUNS ]; do - echo "run $j/$NUMRUNS iperf:" - for CLIENT in $CLIENTS; do - vcmd -c $CLIENT -- iperf -t ${RUNTIME} -c ${SERVERIP} & - done - sleep ${RUNTIME} 1 - j=$((j+1)) - done - - sleep 1 - echo "stopping lxc iperf server" - vcmd -c $SERVER -- killall -v iperf - echo "stopping containers" - kill -9 `cat $SERVER.pid` - for CLIENT in $CLIENTS; do - kill -9 `cat $CLIENT.pid` - done - # time needed for processes/containers to shut down - sleep 2 - - echo "cleaning up" - ip link set $BRIDGE down - brctl delbr $BRIDGE - rm -f ${SERVER}* - rm -f /tmp/${0}-client* - # time needed for bridge clean-up - sleep 1 -} - -# -# run all tests -# -loopbacktest -lxcvethtest -lxcbrtest -chaintest 5 -chaintest 10 -clientstest 5 -clientstest 10 -clientstest 15 - -mv ${LOG} ${PWD}/${0}-${STAMP}.log -echo "===> results in ${PWD}/${0}-${STAMP}.log" diff --git a/daemon/examples/netns/switch.py b/daemon/examples/netns/switch.py deleted file mode 100755 index bf43562f..00000000 --- a/daemon/examples/netns/switch.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/python -i - -# Copyright (c)2010-2013 the Boeing Company. -# See the LICENSE file included in this distribution. - -# connect n nodes to a virtual switch/hub - -import datetime -import optparse -import sys - -from core import constants -from core.misc import ipaddress -from core.netns import nodes - -# node list (count from 1) -from core.session import Session - -n = [None] - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - parser.set_defaults(numnodes=5) - - parser.add_option("-n", "--numnodes", dest="numnodes", type=int, - help="number of nodes") - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.numnodes < 1: - usage("invalid number of nodes: %s" % options.numnodes) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - # IP subnet - prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1, persistent=True) - if 'server' in globals(): - server.addsession(session) - # emulated Ethernet switch - switch = session.add_object(cls=nodes.SwitchNode, name="switch") - switch.setposition(x=80, y=50) - print "creating %d nodes with addresses from %s" % (options.numnodes, prefix) - for i in xrange(1, options.numnodes + 1): - tmp = session.add_object(cls=nodes.CoreNode, name="n%d" % i, objid=i) - tmp.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - tmp.cmd([constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) - tmp.setposition(x=150 * i, y=150) - n.append(tmp) - - session.node_count = str(options.numnodes + 1) - session.instantiate() - print "elapsed time: %s" % (datetime.datetime.now() - start) - - # start a shell on node 1 - n[1].client.term("bash") - - raw_input("press enter to exit") - session.shutdown() - - -if __name__ == "__main__" or __name__ == "__builtin__": - main() diff --git a/daemon/examples/netns/switchtest.py b/daemon/examples/netns/switchtest.py deleted file mode 100755 index f31a1fc6..00000000 --- a/daemon/examples/netns/switchtest.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/python - -# Copyright (c)2010-2012 the Boeing Company. -# See the LICENSE file included in this distribution. - -# run iperf to measure the effective throughput between two nodes when -# n nodes are connected to a virtual hub/switch; run test for testsec -# and repeat for minnodes <= n <= maxnodes with a step size of -# nodestep - -import datetime -import optparse -import sys - -from core.misc import ipaddress -from core.misc.utils import check_cmd -from core.netns import nodes -from core.session import Session - -try: - check_cmd(["iperf", "-v"]) -except OSError: - sys.stderr.write("ERROR: running iperf failed\n") - sys.exit(1) - - -def test(numnodes, testsec): - # node list - n = [] - # IP subnet - prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1) - # emulated network - net = session.add_object(cls=nodes.SwitchNode) - for i in xrange(1, numnodes + 1): - tmp = session.add_object(cls=nodes.LxcNode, name="n%d" % i) - tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - n.append(tmp) - n[0].cmd(["iperf", "-s", "-D"]) - n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].cmd(["killall", "-9", "iperf"]) - - raw_input("press enter to exit") - session.shutdown() - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - - parser.set_defaults(minnodes=2) - parser.add_option("-m", "--minnodes", dest="minnodes", type=int, - help="min number of nodes to test; default = %s" % - parser.defaults["minnodes"]) - - parser.set_defaults(maxnodes=2) - parser.add_option("-n", "--maxnodes", dest="maxnodes", type=int, - help="max number of nodes to test; default = %s" % - parser.defaults["maxnodes"]) - - parser.set_defaults(testsec=10) - parser.add_option("-t", "--testsec", dest="testsec", type=int, - help="test time in seconds; default = %s" % - parser.defaults["testsec"]) - - parser.set_defaults(nodestep=1) - parser.add_option("-s", "--nodestep", dest="nodestep", type=int, - help="number of nodes step size; default = %s" % - parser.defaults["nodestep"]) - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.minnodes < 2: - usage("invalid min number of nodes: %s" % options.minnodes) - if options.maxnodes < options.minnodes: - usage("invalid max number of nodes: %s" % options.maxnodes) - if options.testsec < 1: - usage("invalid test time: %s" % options.testsec) - if options.nodestep < 1: - usage("invalid node step: %s" % options.nodestep) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - for i in xrange(options.minnodes, options.maxnodes + 1, options.nodestep): - print >> sys.stderr, "%s node test:" % i - test(i, options.testsec) - print >> sys.stderr, "" - - print >> sys.stderr, "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__": - main() diff --git a/daemon/examples/netns/twonodes.sh b/daemon/examples/netns/twonodes.sh deleted file mode 100755 index 0593ef08..00000000 --- a/daemon/examples/netns/twonodes.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh -e -# Below is a transcript of creating two emulated nodes and connecting them -# together with a wired link. You can run the core-cleanup script to clean -# up after this script. - -# create node 1 namespace container -vnoded -c /tmp/n1.ctl -l /tmp/n1.log -p /tmp/n1.pid -# create a virtual Ethernet (veth) pair, installing one end into node 1 -ip link add name n1.0.1 type veth peer name n1.0 -ip link set n1.0 netns `cat /tmp/n1.pid` -vcmd -c /tmp/n1.ctl -- /bin/sh -e -c \ - "ip link set lo up && ip link set n1.0 name eth0 up && ip addr add 10.0.0.1/24 dev eth0" - -# create node 2 namespace container -vnoded -c /tmp/n2.ctl -l /tmp/n2.log -p /tmp/n2.pid -# create a virtual Ethernet (veth) pair, installing one end into node 2 -ip link add name n2.0.1 type veth peer name n2.0 -ip link set n2.0 netns `cat /tmp/n2.pid` -vcmd -c /tmp/n2.ctl -- /bin/sh -e -c \ - "ip link set lo up && ip link set n2.0 name eth0 up && ip addr add 10.0.0.2/24 dev eth0" - -# bridge together nodes 1 and 2 using the other end of each veth pair -brctl addbr b.1.1 -brctl setfd b.1.1 0 -brctl addif b.1.1 n1.0.1 -brctl addif b.1.1 n2.0.1 -ip link set n1.0.1 up -ip link set n2.0.1 up -ip link set b.1.1 up - -# display connectivity and ping from node 1 to node 2 -brctl show -vcmd -c /tmp/n1.ctl -- ping 10.0.0.2 diff --git a/daemon/examples/netns/wlantest.py b/daemon/examples/netns/wlantest.py deleted file mode 100755 index 1679c81c..00000000 --- a/daemon/examples/netns/wlantest.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/python - -# Copyright (c)2010-2012 the Boeing Company. -# See the LICENSE file included in this distribution. - -# run iperf to measure the effective throughput between two nodes when -# n nodes are connected to a virtual wlan; run test for testsec -# and repeat for minnodes <= n <= maxnodes with a step size of -# nodestep - -import datetime -import optparse -import sys - -from core.misc import ipaddress -from core.misc.utils import check_cmd -from core.netns import nodes -from core.session import Session - -try: - check_cmd(["iperf", "-v"]) -except OSError: - sys.stderr.write("ERROR: running iperf failed\n") - sys.exit(1) - - -def test(numnodes, testsec): - # node list - n = [] - # IP subnet - prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") - session = Session(1) - # emulated network - net = session.add_object(cls=nodes.WlanNode) - for i in xrange(1, numnodes + 1): - tmp = session.add_object(cls=nodes.LxcNode, objid="%d" % i, name="n%d" % i) - tmp.newnetif(net, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) - n.append(tmp) - net.link(n[0].netif(0), n[-1].netif(0)) - n[0].cmd(["iperf", "-s", "-D"]) - n[-1].client.icmd(["iperf", "-t", str(int(testsec)), "-c", str(prefix.addr(1))]) - n[0].cmd(["killall", "-9", "iperf"]) - session.shutdown() - - -def main(): - usagestr = "usage: %prog [-h] [options] [args]" - parser = optparse.OptionParser(usage=usagestr) - - parser.set_defaults(minnodes=2) - parser.add_option("-m", "--minnodes", dest="minnodes", type=int, - help="min number of nodes to test; default = %s" % parser.defaults["minnodes"]) - - parser.set_defaults(maxnodes=2) - parser.add_option("-n", "--maxnodes", dest="maxnodes", type=int, - help="max number of nodes to test; default = %s" % - parser.defaults["maxnodes"]) - - parser.set_defaults(testsec=10) - parser.add_option("-t", "--testsec", dest="testsec", type=int, - help="test time in seconds; default = %s" % - parser.defaults["testsec"]) - - parser.set_defaults(nodestep=1) - parser.add_option("-s", "--nodestep", dest="nodestep", type=int, - help="number of nodes step size; default = %s" % - parser.defaults["nodestep"]) - - def usage(msg=None, err=0): - sys.stdout.write("\n") - if msg: - sys.stdout.write(msg + "\n\n") - parser.print_help() - sys.exit(err) - - # parse command line options - (options, args) = parser.parse_args() - - if options.minnodes < 2: - usage("invalid min number of nodes: %s" % options.minnodes) - if options.maxnodes < options.minnodes: - usage("invalid max number of nodes: %s" % options.maxnodes) - if options.testsec < 1: - usage("invalid test time: %s" % options.testsec) - if options.nodestep < 1: - usage("invalid node step: %s" % options.nodestep) - - for a in args: - sys.stderr.write("ignoring command line argument: '%s'\n" % a) - - start = datetime.datetime.now() - - for i in xrange(options.minnodes, options.maxnodes + 1, options.nodestep): - print >> sys.stderr, "%s node test:" % i - test(i, options.testsec) - print >> sys.stderr, "" - - print >> sys.stderr, "elapsed time: %s" % (datetime.datetime.now() - start) - - -if __name__ == "__main__": - main() From 4a2810e9b23dbf882c6dfb9536b80ddd483e151d Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 26 Apr 2018 14:26:39 -0700 Subject: [PATCH 142/152] removed issue with double loading services from core-daemon, fixed exceptions noted as not an error previously and updated code to more gracefully handle those cases, fixed issue with add_node when setting node.ype for all nodes --- daemon/core/future/coreemu.py | 3 ++- daemon/core/future/futuredata.py | 2 +- daemon/core/mobility.py | 6 +---- daemon/core/xml/xmlwriter1.py | 39 +++++++++++++++----------------- daemon/scripts/core-daemon | 4 ---- 5 files changed, 22 insertions(+), 32 deletions(-) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index f571f08c..9e9133bc 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -487,7 +487,6 @@ class FutureSession(Session): node = self.add_object(cls=node_class, objid=_id, name=name, start=start) # set node attributes - node.type = node_options.model node.icon = node_options.icon node.canvas = node_options.canvas node.opaque = node_options.opaque @@ -497,6 +496,8 @@ class FutureSession(Session): # add services to default and physical nodes only if _type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: + node.type = node_options.model + logger.debug("set node type: %s", node.type) logger.info("setting model (%s) with services (%s)", node.type, node_options.services) services = "|".join(node_options.services) or None self.services.addservicestonode(node, node.type, services) diff --git a/daemon/core/future/futuredata.py b/daemon/core/future/futuredata.py index fac64bf2..98ffeb5e 100644 --- a/daemon/core/future/futuredata.py +++ b/daemon/core/future/futuredata.py @@ -12,7 +12,7 @@ class NodeOptions(object): Create a NodeOptions object. :param str name: name of node, defaults to node class name postfix with its id - :param str model: model to use for this node, defines services, defaults to "router" + :param str model: defines services for default and physical nodes, defaults to "router" """ self.name = name self.model = model diff --git a/daemon/core/mobility.py b/daemon/core/mobility.py index 58c1b162..021a6366 100644 --- a/daemon/core/mobility.py +++ b/daemon/core/mobility.py @@ -1152,11 +1152,7 @@ class Ns2ScriptedMobility(WayPointMobility): :rtype: int """ nodenum = int(nodenum) - try: - return self.nodemap[nodenum] - except KeyError: - logger.exception("error finding value in node map, ignored and returns node id") - return nodenum + return self.nodemap.get(nodenum, nodenum) def startup(self): """ diff --git a/daemon/core/xml/xmlwriter1.py b/daemon/core/xml/xmlwriter1.py index c113ff31..7959b204 100644 --- a/daemon/core/xml/xmlwriter1.py +++ b/daemon/core/xml/xmlwriter1.py @@ -213,7 +213,7 @@ class ScenarioPlan(XmlElement): self.setAttribute('xmlns:CORE', 'coreSpecific') self.setAttribute('compiled', 'true') - self.all_channel_members = dict() + self.all_channel_members = {} self.last_network_id = 0 self.addNetworks() self.addDevices() @@ -795,26 +795,23 @@ class InterfaceElement(NamedXmlElement): """ Add a reference to the channel that uses this interface """ - try: - cm = self.scenPlan.all_channel_members[self.id] - if cm is not None: - ch = cm.base_element.parentNode - if ch is not None: - net = ch.parentNode - if net is not None: - MemberElement(self.scenPlan, - self, - referenced_type=MembType.CHANNEL, - referenced_id=ch.getAttribute("id"), - index=int(cm.getAttribute("index"))) - MemberElement(self.scenPlan, - self, - referenced_type=MembType.NETWORK, - referenced_id=net.getAttribute("id")) - except KeyError: - # Not an error. This occurs when an interface belongs to a switch - # or a hub within a network and the channel is yet to be defined - logger.exception("noted as not an error, add channel reference error") + # cm is None when an interface belongs to a switch + # or a hub within a network and the channel is yet to be defined + cm = self.scenPlan.all_channel_members.get(self.id) + if cm is not None: + ch = cm.base_element.parentNode + if ch is not None: + net = ch.parentNode + if net is not None: + MemberElement(self.scenPlan, + self, + referenced_type=MembType.CHANNEL, + referenced_id=ch.getAttribute("id"), + index=int(cm.getAttribute("index"))) + MemberElement(self.scenPlan, + self, + referenced_type=MembType.NETWORK, + referenced_id=net.getAttribute("id")) def addAddresses(self, interface_object): """ diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 744d202b..ee4cbf6b 100644 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -13,7 +13,6 @@ import time from core import constants from core import enumerations from core import logger -from core import services from core.legacy.corehandler import CoreHandler from core.legacy.coreserver import CoreServer from core.misc import nodeutils @@ -139,7 +138,4 @@ if __name__ == "__main__": nodeutils.update_node_map(OVS_NODES) - # load default services - services.load() - main() From 164f02e5acaad9115ed996c759f74c6fa2fdac5f Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 26 Apr 2018 15:52:34 -0700 Subject: [PATCH 143/152] better handling for deleting node directories --- daemon/core/netns/vnode.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index a874c692..a28ea5c4 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -2,6 +2,7 @@ PyCoreNode and LxcNode classes that implement the network namespac virtual node. """ +import errno import os import random import shutil @@ -145,10 +146,11 @@ class SimpleLxcNode(PyCoreNode): # remove node directory if present try: - if os.path.exists(self.ctrlchnlname): - os.unlink(self.ctrlchnlname) - except OSError: - logger.exception("error removing node directory") + os.unlink(self.ctrlchnlname) + except OSError as e: + # no such file or directory + if e.errno != errno.ENOENT: + logger.exception("error removing node directory") # clear interface data, close client, and mark self and not up self._netif.clear() From fe4c21bad4dd439e6d0b22ec83ad8fda9f0fe293 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Thu, 26 Apr 2018 16:05:47 -0700 Subject: [PATCH 144/152] updates to how and where the node map is populated, now done in CoreEmu and CoreEmu provides a method for updating the map if desired --- daemon/core/future/coreemu.py | 25 ++++++++++++++++++++++--- daemon/core/session.py | 5 ----- daemon/scripts/core-daemon | 18 +++++++++--------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 9e9133bc..98e6ec4d 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -5,10 +5,15 @@ import sys import core.services from core import logger -from core.coreobj import PyCoreNode, PyCoreNet +from core.coreobj import PyCoreNet +from core.coreobj import PyCoreNode from core.data import NodeData -from core.enumerations import NodeTypes, EventTypes, LinkTypes -from core.future.futuredata import LinkOptions, NodeOptions +from core.enumerations import EventTypes +from core.enumerations import LinkTypes +from core.enumerations import NodeTypes +from core.future.futuredata import LinkOptions +from core.future.futuredata import NodeOptions +from core.misc import nodemaps from core.misc import nodeutils from core.session import Session from core.xml.xmlparser import core_document_parser @@ -842,12 +847,26 @@ class CoreEmu(object): self.session_id_gen = IdGen(_id=59999) self.sessions = {} + # set default nodes + # set default node map + node_map = nodemaps.NODES + nodeutils.set_node_map(node_map) + # load default services core.services.load() # catch exit event atexit.register(self.shutdown) + def update_nodes(self, node_map): + """ + Updates node map used by core. + + :param dict node_map: node map to update existing node map with + :return: nothing + """ + nodeutils.update_node_map(node_map) + def shutdown(self): """ Shutdown all CORE session. diff --git a/daemon/core/session.py b/daemon/core/session.py index 69a6c1a7..1540e1f6 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -33,7 +33,6 @@ from core.enumerations import MessageFlags from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.location import CoreLocation -from core.misc import nodemaps from core.misc import nodeutils from core.misc import utils from core.misc.event import EventLoop @@ -46,10 +45,6 @@ from core.sdt import Sdt from core.service import CoreServices from core.xml.xmlsession import save_session_xml -# set default node map -node_map = nodemaps.NODES -nodeutils.set_node_map(node_map) - class Session(object): """ diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index ee4cbf6b..016120d0 100644 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -15,7 +15,6 @@ from core import enumerations from core import logger from core.legacy.corehandler import CoreHandler from core.legacy.coreserver import CoreServer -from core.misc import nodeutils from core.misc.utils import close_onexec from core.service import ServiceManager @@ -29,11 +28,12 @@ def banner(): logger.info("CORE daemon v.%s started %s", constants.COREDPY_VERSION, time.ctime()) -def cored(cfg=None): +def cored(cfg, use_ovs): """ Start the CoreServer object and enter the server loop. :param dict cfg: core configuration + :param bool use_ovs: flag to determine if ovs nodes should be used :return: nothing """ host = cfg["listenaddr"] @@ -43,6 +43,9 @@ def cored(cfg=None): try: server = CoreServer((host, port), CoreHandler, cfg) + if use_ovs: + from core.netns.openvswitch import OVS_NODES + server.coreemu.update_nodes(OVS_NODES) except: logger.exception("error starting main server on: %s:%s", host, port) sys.exit(1) @@ -123,8 +126,11 @@ def main(): banner() + # check if ovs flag was provided + use_ovs = len(sys.argv) == 2 and sys.argv[1] == "ovs" + try: - cored(cfg) + cored(cfg, use_ovs) except KeyboardInterrupt: logger.info("keyboard interrupt, stopping core daemon") @@ -132,10 +138,4 @@ def main(): if __name__ == "__main__": - # configure nodes to use - if len(sys.argv) == 2 and sys.argv[1] == "ovs": - from core.netns.openvswitch import OVS_NODES - - nodeutils.update_node_map(OVS_NODES) - main() From ba3669712a99974118ead4cc7f3ef350f1502fc7 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 27 Apr 2018 10:12:01 -0700 Subject: [PATCH 145/152] updated gui test to working order, moved distributed test to a sub directory to be ignored by default, added pytest.ini to ignore distributed directory by default --- .../{ => distributed}/test_distributed.py | 0 daemon/tests/pytest.ini | 2 + daemon/tests/test_core.py | 43 +------------------ daemon/tests/test_gui.py | 34 +++++++-------- 4 files changed, 19 insertions(+), 60 deletions(-) rename daemon/tests/{ => distributed}/test_distributed.py (100%) create mode 100644 daemon/tests/pytest.ini diff --git a/daemon/tests/test_distributed.py b/daemon/tests/distributed/test_distributed.py similarity index 100% rename from daemon/tests/test_distributed.py rename to daemon/tests/distributed/test_distributed.py diff --git a/daemon/tests/pytest.ini b/daemon/tests/pytest.ini new file mode 100644 index 00000000..880841eb --- /dev/null +++ b/daemon/tests/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +norecursedirs = distributed diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 6a0f50d5..2e866c85 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -5,7 +5,6 @@ Unit tests for testing basic CORE networks. import os import stat import threading -import time from xml.etree import ElementTree import pytest @@ -247,7 +246,7 @@ class TestCore: node_one.delnetif(0) assert not node_one.netif(0) - def test_wlan_good(self, session, ip_prefixes): + def test_wlan_ping(self, session, ip_prefixes): """ Test basic wlan network. @@ -280,46 +279,6 @@ class TestCore: status = ping(node_one, node_two, ip_prefixes) assert not status - def test_wlan_bad(self, session, ip_prefixes): - """ - Test basic wlan network with leveraging basic range model. - - :param core.future.coreemu.FutureSession session: session for test - :param ip_prefixes: generates ip addresses for nodes - """ - - # create wlan - wlan_node = session.add_node(_type=NodeTypes.WIRELESS_LAN) - session.set_wireless_model(wlan_node, BasicRangeModel) - - # create nodes - node_options = NodeOptions() - node_options.set_position(0, 0) - node_one = session.create_wireless_node(node_options=node_options) - node_two = session.create_wireless_node(node_options=node_options) - - # link nodes - for node in [node_one, node_two]: - interface = ip_prefixes.create_interface(node) - session.add_link(node.objid, wlan_node.objid, interface_one=interface) - - # link nodes in wlan - session.wireless_link_all(wlan_node, [node_one, node_two]) - - # instantiate session - session.instantiate() - - # move node two out of range, default range check is 275 - time.sleep(5) - update_options = NodeOptions() - update_options.set_position(500, 500) - session.update_node(node_two.objid, update_options) - - # ping n2 from n1 and assert failure - time.sleep(5) - status = ping(node_one, node_two, ip_prefixes) - assert status - def test_mobility(self, session, ip_prefixes): """ Test basic wlan network. diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index 77c8b9fe..8da33dc3 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -6,7 +6,7 @@ import threading from core.api import coreapi, dataconversion from core.api.coreapi import CoreExecuteTlv -from core.enumerations import CORE_API_PORT +from core.enumerations import CORE_API_PORT, NodeTypes from core.enumerations import EventTlvs from core.enumerations import EventTypes from core.enumerations import ExecuteTlvs @@ -15,7 +15,6 @@ from core.enumerations import LinkTypes from core.enumerations import MessageFlags from core.enumerations import MessageTypes from core.misc import ipaddress -from core.netns.nodes import SwitchNode def command_message(node, command): @@ -102,11 +101,12 @@ def run_cmd(node, exec_cmd): class TestGui: - def test_broker(self, core, cored): + def test_broker(self, session, cored): """ Test session broker creation. - :param conftest.Core core: core fixture to test with + :param core.future.coreemu.FutureSession session: session for test + :param cored: cored daemon server to test with """ # set core daemon to run in the background @@ -119,54 +119,52 @@ class TestGui: daemon = "localhost" # add server - core.session.broker.addserver(daemon, "127.0.0.1", CORE_API_PORT) + session.broker.addserver(daemon, "127.0.0.1", CORE_API_PORT) # setup server - core.session.broker.setupserver(daemon) + session.broker.setupserver(daemon) # do not want the recvloop running as we will deal ourselves - core.session.broker.dorecvloop = False + session.broker.dorecvloop = False # have broker handle a configuration state change - core.session.set_state(EventTypes.CONFIGURATION_STATE) + session.set_state(EventTypes.CONFIGURATION_STATE) event_message = state_message(EventTypes.CONFIGURATION_STATE) - core.session.broker.handlerawmsg(event_message) + session.broker.handlerawmsg(event_message) # create a switch node - switch = core.session.add_object(cls=SwitchNode, name="switch", start=False) + switch = session.add_node(_type=NodeTypes.SWITCH) switch.setposition(x=80, y=50) switch.server = daemon # retrieve switch data representation, create a switch message for broker to handle switch_data = switch.data(MessageFlags.ADD.value) switch_message = dataconversion.convert_node(switch_data) - core.session.broker.handlerawmsg(switch_message) + session.broker.handlerawmsg(switch_message) # create node one - core.create_node("n1") - node_one = core.get_node("n1") + node_one = session.add_node() node_one.server = daemon # create node two - core.create_node("n2") - node_two = core.get_node("n2") + node_two = session.add_node() node_two.server = daemon # create node messages for the broker to handle for node in [node_one, node_two]: node_data = node.data(MessageFlags.ADD.value) node_message = dataconversion.convert_node(node_data) - core.session.broker.handlerawmsg(node_message) + session.broker.handlerawmsg(node_message) # create links to switch from nodes for broker to handle for index, node in enumerate([node_one, node_two], start=1): ip4_address = prefix.addr(index) link_message = switch_link_message(switch, node, ip4_address, prefix.prefixlen) - core.session.broker.handlerawmsg(link_message) + session.broker.handlerawmsg(link_message) # change session to instantiation state event_message = state_message(EventTypes.INSTANTIATION_STATE) - core.session.broker.handlerawmsg(event_message) + session.broker.handlerawmsg(event_message) # Get the ip or last node and ping it from the first output, status = run_cmd(node_one, "ip -4 -o addr show dev eth0") From 44781d0aec8e7247a68897587f3a7bc7eb18be50 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Fri, 27 Apr 2018 12:09:31 -0700 Subject: [PATCH 146/152] set default logging to INFO, cleaned up logging to help isolate debug type messages to DEBUG level, fixed issue with shutdown --- daemon/core/api/coreapi.py | 2 - daemon/core/broker.py | 20 ++++----- daemon/core/conf.py | 7 ++- daemon/core/emane/emanemanager.py | 3 +- daemon/core/future/coreemu.py | 31 ++++++++----- daemon/core/legacy/corehandler.py | 74 +++++++++++++++---------------- daemon/core/location.py | 2 +- daemon/core/misc/nodeutils.py | 9 ++-- daemon/core/misc/structutils.py | 2 +- daemon/core/misc/utils.py | 6 +-- daemon/core/mobility.py | 4 +- daemon/core/netns/vnode.py | 18 ++++---- daemon/core/service.py | 21 +++++---- daemon/core/session.py | 21 ++++----- daemon/core/xml/xmlwriter1.py | 2 +- daemon/data/logging.conf | 2 +- daemon/scripts/core-daemon | 2 +- daemon/tests/test_gui.py | 2 +- 18 files changed, 114 insertions(+), 114 deletions(-) diff --git a/daemon/core/api/coreapi.py b/daemon/core/api/coreapi.py index 096b3568..b5d5bc65 100644 --- a/daemon/core/api/coreapi.py +++ b/daemon/core/api/coreapi.py @@ -10,7 +10,6 @@ import struct from enum import Enum -from core import logger from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs from core.enumerations import EventTypes @@ -275,7 +274,6 @@ class CoreTlvDataIpv4Addr(CoreTlvDataObj): :return: Ipv4 address :rtype: core.misc.ipaddress.IpAddress """ - logger.info("getting new ipv4 address for: %s", value) return IpAddress(af=socket.AF_INET, address=value) diff --git a/daemon/core/broker.py b/daemon/core/broker.py index 294fcd65..ed073fb5 100644 --- a/daemon/core/broker.py +++ b/daemon/core/broker.py @@ -158,7 +158,7 @@ class CoreBroker(ConfigurableManager): """ Reset to initial state. """ - logger.info("broker reset") + logger.info("clearing state") self.nodemap_lock.acquire() self.nodemap.clear() for server, count in self.nodecounts.iteritems(): @@ -302,7 +302,7 @@ class CoreBroker(ConfigurableManager): server.close() del self.servers[name] - logger.info("adding server: %s @ %s:%s" % (name, host, port)) + logger.info("adding broker server(%s): %s:%s" % (name, host, port)) server = CoreDistributedServer(name, host, port) if host is not None and port is not None: try: @@ -432,7 +432,7 @@ class CoreBroker(ConfigurableManager): Add GreTaps between network devices on different machines. The GreTapBridge is not used since that would add an extra bridge. """ - logger.info("adding network tunnels for nodes: %s", self.network_nodes) + logger.debug("adding network tunnels for nodes: %s", self.network_nodes) for n in self.network_nodes: self.addnettunnel(n) @@ -531,7 +531,7 @@ class CoreBroker(ConfigurableManager): :return: gre tap between nodes or none """ key = self.tunnelkey(n1num, n2num) - logger.info("checking for tunnel(%s) in: %s", key, self.tunnels.keys()) + logger.debug("checking for tunnel(%s) in: %s", key, self.tunnels.keys()) if key in self.tunnels.keys(): return self.tunnels[key] else: @@ -709,8 +709,6 @@ class CoreBroker(ConfigurableManager): if message.message_type == MessageTypes.LINK.value: # prepare a server list from two node numbers in link message handle_locally, servers, message = self.handlelinkmsg(message) - logger.info("broker handle link message: %s - %s", handle_locally, - map(lambda x: "%s:%s" % (x.host, x.port), servers)) elif len(servers) == 0: # check for servers based on node numbers in all messages but link nn = message.node_numbers() @@ -868,7 +866,7 @@ class CoreBroker(ConfigurableManager): # determine link message destination using non-network nodes nn = message.node_numbers() - logger.info("checking link nodes (%s) with network nodes (%s)", nn, self.network_nodes) + logger.debug("checking link nodes (%s) with network nodes (%s)", nn, self.network_nodes) if nn[0] in self.network_nodes: if nn[1] in self.network_nodes: # two network nodes linked together - prevent loops caused by @@ -879,11 +877,11 @@ class CoreBroker(ConfigurableManager): elif nn[1] in self.network_nodes: servers = self.getserversbynode(nn[0]) else: - logger.info("link nodes are not network nodes") + logger.debug("link nodes are not network nodes") servers1 = self.getserversbynode(nn[0]) - logger.info("servers for node(%s): %s", nn[0], servers1) + logger.debug("servers for node(%s): %s", nn[0], servers1) servers2 = self.getserversbynode(nn[1]) - logger.info("servers for node(%s): %s", nn[1], servers2) + logger.debug("servers for node(%s): %s", nn[1], servers2) # nodes are on two different servers, build tunnels as needed if servers1 != servers2: localn = None @@ -912,7 +910,7 @@ class CoreBroker(ConfigurableManager): if host is None: host = self.getlinkendpoint(message, localn == nn[0]) - logger.info("handle locally(%s) and local node(%s)", handle_locally, localn) + logger.debug("handle locally(%s) and local node(%s)", handle_locally, localn) if localn is None: message = self.addlinkendpoints(message, servers1, servers2) elif message.flags & MessageFlags.ADD.value: diff --git a/daemon/core/conf.py b/daemon/core/conf.py index 0e8f82bd..335db819 100644 --- a/daemon/core/conf.py +++ b/daemon/core/conf.py @@ -212,7 +212,7 @@ class ConfigurableManager(object): :return: nothing """ if conftype not in self._modelclsmap: - logger.warn("Unknown model type '%s'" % conftype) + logger.warn("unknown model type '%s'", conftype) return model = self._modelclsmap[conftype] keys = model.getnames() @@ -220,8 +220,7 @@ class ConfigurableManager(object): values = list(model.getdefaultvalues()) for key, value in keyvalues: if key not in keys: - logger.warn("Skipping unknown configuration key for %s: '%s'" % \ - (conftype, key)) + logger.warn("Skipping unknown configuration key for %s: '%s'", conftype, key) continue i = keys.index(key) values[i] = value @@ -327,7 +326,7 @@ class Configurable(object): if interface_id is not None: node_id = node_id * 1000 + interface_id - logger.info("received configure message for %s nodenum:%s", cls.name, str(node_id)) + logger.debug("received configure message for %s nodenum:%s", cls.name, str(node_id)) if config_type == ConfigFlags.REQUEST.value: logger.info("replying to configure request for %s model", cls.name) # when object name is "all", the reply to this request may be None diff --git a/daemon/core/emane/emanemanager.py b/daemon/core/emane/emanemanager.py index 841c29dd..2463a619 100644 --- a/daemon/core/emane/emanemanager.py +++ b/daemon/core/emane/emanemanager.py @@ -168,8 +168,7 @@ class EmaneManager(ConfigurableManager): load EMANE models and make them available. """ for emane_model in emane_models: - logger.info("loading emane model: (%s) %s - %s", - emane_model, emane_model.name, RegisterTlvs(emane_model.config_type)) + logger.info("loading emane model: %s", emane_model.__name__) self._modelclsmap[emane_model.name] = emane_model self.session.add_config_object(emane_model.name, emane_model.config_type, emane_model.configure_emane) diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 98e6ec4d..648a14b2 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -142,7 +142,7 @@ class FutureSession(Session): :return: nodes, network nodes if present, and tunnel if present :rtype: tuple """ - logger.info("link message between node1(%s) and node2(%s)", node_one_id, node_two_id) + logger.debug("link message between node1(%s) and node2(%s)", node_one_id, node_two_id) # values to fill net_one = None @@ -154,7 +154,7 @@ class FutureSession(Session): # both node ids are provided tunnel = self.broker.gettunnel(node_one_id, node_two_id) - logger.info("tunnel between nodes: %s", tunnel) + logger.debug("tunnel between nodes: %s", tunnel) if nodeutils.is_node(tunnel, NodeTypes.TAP_BRIDGE): net_one = tunnel if tunnel.remotenum == node_one_id: @@ -182,8 +182,8 @@ class FutureSession(Session): net_two = node_two node_two = None - logger.info("link node types n1(%s) n2(%s) net1(%s) net2(%s) tunnel(%s)", - node_one, node_two, net_one, net_two, tunnel) + logger.debug("link node types n1(%s) n2(%s) net1(%s) net2(%s) tunnel(%s)", + node_one, node_two, net_one, net_two, tunnel) return node_one, node_two, net_one, net_two, tunnel # TODO: this doesn't appear to ever be used, EMANE or basic wireless range @@ -198,7 +198,7 @@ class FutureSession(Session): objects = [x for x in objects if x] if len(objects) < 2: raise ValueError("wireless link failure: %s", objects) - logger.info("handling wireless linking objects(%) connect(%s)", objects, connect) + logger.debug("handling wireless linking objects(%) connect(%s)", objects, connect) common_networks = objects[0].commonnets(objects[1]) if not common_networks: raise ValueError("no common network found for wireless link/unlink") @@ -242,23 +242,27 @@ class FutureSession(Session): else: # 2 nodes being linked, ptp network if all([node_one, node_two]) and not net_one: + logger.info("adding link for peer to peer nodes: %s - %s", node_one.name, node_two.name) ptp_class = nodeutils.get_node_class(NodeTypes.PEER_TO_PEER) start = self.state > EventTypes.DEFINITION_STATE.value net_one = self.add_object(cls=ptp_class, start=start) # node to network if node_one and net_one: + logger.info("adding link from node to network: %s - %s", node_one.name, net_one.name) interface = create_interface(node_one, net_one, interface_one) link_config(net_one, interface, link_options) # network to node if node_two and net_one: + logger.info("adding link from network to node: %s - %s", node_two.name, net_one.name) interface = create_interface(node_two, net_one, interface_two) if not link_options.unidirectional: link_config(net_one, interface, link_options) # network to network if net_one and net_two: + logger.info("adding link from network to network: %s", net_one.name, net_two.name) if nodeutils.is_node(net_two, NodeTypes.RJ45): interface = net_two.linknet(net_one) else: @@ -282,10 +286,12 @@ class FutureSession(Session): # tunnel node logic key = link_options.key if key and nodeutils.is_node(net_one, NodeTypes.TUNNEL): + logger.info("setting tunnel key for: %s", net_one.name) net_one.setkey(key) if addresses: net_one.addrconfig(addresses) if key and nodeutils.is_node(net_two, NodeTypes.TUNNEL): + logger.info("setting tunnel key for: %s", net_two.name) net_two.setkey(key) if addresses: net_two.addrconfig(addresses) @@ -293,10 +299,12 @@ class FutureSession(Session): # physical node connected with tunnel if not net_one and not net_two and (node_one or node_two): if node_one and nodeutils.is_node(node_one, NodeTypes.PHYSICAL): + logger.info("adding link for physical node: %s", node_one.name) addresses = interface_one.get_addresses() node_one.adoptnetif(tunnel, interface_one.id, interface_one.mac, addresses) link_config(node_one, tunnel, link_options) elif node_two and nodeutils.is_node(node_two, NodeTypes.PHYSICAL): + logger.info("adding link for physical node: %s", node_two.name) addresses = interface_two.get_addresses() node_two.adoptnetif(tunnel, interface_two.id, interface_two.mac, addresses) link_config(node_two, tunnel, link_options) @@ -351,11 +359,12 @@ class FutureSession(Session): interface_two = common_interface_two break - logger.info("deleting link for interfaces interface_one(%s) interface_two(%s)", - interface_one, interface_two) if all([interface_one, interface_two]) and any([interface_one.net, interface_two.net]): if interface_one.net != interface_two.net and all([interface_one.up, interface_two.up]): raise ValueError("no common network found") + + logger.info("deleting link node(%s):interface(%s) node(%s):interface(%s)", + node_one.name, interface_one.name, node_two.name, interface_two.name) net_one = interface_one.net interface_one.detachnet() interface_two.detachnet() @@ -488,7 +497,7 @@ class FutureSession(Session): name = "%s%s" % (node_class.__name__, _id) # create node - logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class, _id, name, start) + logger.info("creating node(%s) id(%s) name(%s) start(%s)", node_class.__name__, _id, name, start) node = self.add_object(cls=node_class, objid=_id, name=name, start=start) # set node attributes @@ -503,7 +512,6 @@ class FutureSession(Session): if _type in [NodeTypes.DEFAULT, NodeTypes.PHYSICAL]: node.type = node_options.model logger.debug("set node type: %s", node.type) - logger.info("setting model (%s) with services (%s)", node.type, node_options.services) services = "|".join(node_options.services) or None self.services.addservicestonode(node, node.type, services) @@ -874,9 +882,10 @@ class CoreEmu(object): :return: nothing """ logger.info("shutting down all session") - for session in self.sessions.values(): - session.shutdown() + sessions = self.sessions.copy() self.sessions.clear() + for session in sessions.itervalues(): + session.shutdown() def create_session(self, _id=None, master=True): """ diff --git a/daemon/core/legacy/corehandler.py b/daemon/core/legacy/corehandler.py index 2b358f1b..d28c3e5a 100644 --- a/daemon/core/legacy/corehandler.py +++ b/daemon/core/legacy/corehandler.py @@ -73,7 +73,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): if num_threads < 1: raise ValueError("invalid number of threads: %s" % num_threads) - logger.info("launching core server handler threads: %s", num_threads) + logger.debug("launching core server handler threads: %s", num_threads) for _ in xrange(num_threads): thread = threading.Thread(target=self.handler_thread) self.handler_threads.append(thread) @@ -94,7 +94,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :return: nothing """ - logger.info("new TCP connection: %s", self.client_address) + logger.debug("new TCP connection: %s", self.client_address) def finish(self): """ @@ -103,14 +103,14 @@ class CoreHandler(SocketServer.BaseRequestHandler): :return: nothing """ - logger.info("finishing request handler") - logger.info("remaining message queue size: %s", self.message_queue.qsize()) + logger.debug("finishing request handler") + logger.debug("remaining message queue size: %s", self.message_queue.qsize()) # give some time for message queue to deplete timeout = 10 wait = 0 while not self.message_queue.empty(): - logger.info("waiting for message queue to empty: %s seconds", wait) + logger.debug("waiting for message queue to empty: %s seconds", wait) time.sleep(1) wait += 1 if wait == timeout: @@ -151,8 +151,6 @@ class CoreHandler(SocketServer.BaseRequestHandler): thumb_list = [] num_sessions = 0 - logger.info("creating session message: %s", self.coreemu.sessions.keys()) - with self._sessions_lock: for session_id, session in self.coreemu.sessions.iteritems(): num_sessions += 1 @@ -211,7 +209,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.EventData event_data: event data to handle :return: nothing """ - logger.info("handling broadcast event: %s", event_data) + logger.debug("handling broadcast event: %s", event_data) tlv_data = structutils.pack_values(coreapi.CoreEventTlv, [ (EventTlvs.NODE, event_data.node), @@ -235,7 +233,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.FileData file_data: file data to handle :return: nothing """ - logger.info("handling broadcast file: %s", file_data) + logger.debug("handling broadcast file: %s", file_data) tlv_data = structutils.pack_values(coreapi.CoreFileTlv, [ (FileTlvs.NODE, file_data.node), @@ -262,7 +260,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.ConfigData config_data: config data to handle :return: nothing """ - logger.info("handling broadcast config: %s", config_data) + logger.debug("handling broadcast config: %s", config_data) tlv_data = structutils.pack_values(coreapi.CoreConfigTlv, [ (ConfigTlvs.NODE, config_data.node), @@ -293,7 +291,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.ExceptionData exception_data: exception data to handle :return: nothing """ - logger.info("handling broadcast exception: %s", exception_data) + logger.debug("handling broadcast exception: %s", exception_data) tlv_data = structutils.pack_values(coreapi.CoreExceptionTlv, [ (ExceptionTlvs.NODE, exception_data.node), (ExceptionTlvs.SESSION, exception_data.session), @@ -316,7 +314,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.NodeData node_data: node data to handle :return: nothing """ - logger.info("handling broadcast node: %s", node_data) + logger.debug("handling broadcast node: %s", node_data) tlv_data = structutils.pack_values(coreapi.CoreNodeTlv, [ (NodeTlvs.NUMBER, node_data.id), @@ -354,7 +352,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param core.data.LinkData link_data: link data to handle :return: nothing """ - logger.info("handling broadcast link: %s", link_data) + logger.debug("handling broadcast link: %s", link_data) tlv_data = structutils.pack_values(coreapi.CoreLinkTlv, [ (LinkTlvs.N1_NUMBER, link_data.node1_id), @@ -476,8 +474,8 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param message: message to queue :return: nothing """ - logger.info("queueing msg (queuedtimes = %s): type %s", - message.queuedtimes, MessageTypes(message.message_type)) + logger.debug("queueing msg (queuedtimes = %s): type %s", message.queuedtimes, MessageTypes( + message.message_type)) self.message_queue.put(message) def handler_thread(self): @@ -504,13 +502,13 @@ class CoreHandler(SocketServer.BaseRequestHandler): :return: nothing """ if self.session and self.session.broker.handle_message(message): - logger.info("message not being handled locally") + logger.debug("message not being handled locally") return - logger.info("%s handling message:\n%s", threading.currentThread().getName(), message) + logger.debug("%s handling message:\n%s", threading.currentThread().getName(), message) if message.message_type not in self.message_handlers: - logger.warn("no handler for message type: %s", message.type_str()) + logger.error("no handler for message type: %s", message.type_str()) return message_handler = self.message_handlers[message.message_type] @@ -520,8 +518,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): replies = message_handler(message) self.dispatch_replies(replies, message) except: - logger.exception("%s: exception while handling message: %s", - threading.currentThread().getName(), message) + logger.exception("%s: exception while handling message: %s", threading.currentThread().getName(), message) def dispatch_replies(self, replies, message): """ @@ -531,7 +528,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): :param message: message for replies :return: nothing """ - logger.info("dispatching replies") + logger.debug("dispatching replies") for reply in replies: message_type, message_flags, message_length = coreapi.CoreMessage.unpack_header(reply) try: @@ -545,7 +542,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): reply_message = "CoreMessage (type %d flags %d length %d)" % ( message_type, message_flags, message_length) - logger.info("dispatch reply:\n%s", reply_message) + logger.debug("dispatch reply:\n%s", reply_message) try: self.sendall(reply) @@ -566,17 +563,16 @@ class CoreHandler(SocketServer.BaseRequestHandler): # TODO: add shutdown handler for session self.session = self.coreemu.create_session(port, master=False) # self.session.shutdown_handlers.append(self.session_shutdown) - logger.info("created new session for client: %s", self.session.session_id) + logger.debug("created new session for client: %s", self.session.session_id) # TODO: hack to associate this handler with this sessions broker for broadcasting # TODO: broker needs to be pulled out of session to the server/handler level if self.master: - logger.info("session set to master") + logger.debug("session set to master") self.session.master = True self.session.broker.session_clients.append(self) # add handlers for various data - logger.info("adding session broadcast handlers") self.add_session_handlers() # set initial session state @@ -607,11 +603,11 @@ class CoreHandler(SocketServer.BaseRequestHandler): if client == self: continue - logger.info("BROADCAST TO OTHER CLIENT: %s", client) + logger.debug("BROADCAST TO OTHER CLIENT: %s", client) client.sendall(message.raw_message) def add_session_handlers(self): - logger.info("adding session broadcast handlers") + logger.debug("adding session broadcast handlers") self.session.event_handlers.append(self.handle_broadcast_event) self.session.exception_handlers.append(self.handle_broadcast_exception) self.session.node_handlers.append(self.handle_broadcast_node) @@ -620,7 +616,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): self.session.config_handlers.append(self.handle_broadcast_config) def remove_session_handlers(self): - logger.info("removing session broadcast handlers") + logger.debug("removing session broadcast handlers") self.session.event_handlers.remove(self.handle_broadcast_event) self.session.exception_handlers.remove(self.handle_broadcast_exception) self.session.node_handlers.remove(self.handle_broadcast_node) @@ -876,17 +872,17 @@ class CoreHandler(SocketServer.BaseRequestHandler): logger.info("executed %s with unknown session ID", execute_server) return replies - logger.info("checking session %d for RUNTIME state", sid) + logger.debug("checking session %d for RUNTIME state", sid) session = self.coreemu.sessions.get(sid) retries = 10 # wait for session to enter RUNTIME state, to prevent GUI from # connecting while nodes are still being instantiated while session.state != EventTypes.RUNTIME_STATE.value: - logger.info("waiting for session %d to enter RUNTIME state", sid) + logger.debug("waiting for session %d to enter RUNTIME state", sid) time.sleep(1) retries -= 1 if retries <= 0: - logger.info("session %d did not enter RUNTIME state", sid) + logger.debug("session %d did not enter RUNTIME state", sid) return replies tlv_data = coreapi.CoreRegisterTlv.pack(RegisterTlvs.EXECUTE_SERVER.value, execute_server) @@ -904,7 +900,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): gui = message.get_tlv(RegisterTlvs.GUI.value) if gui is None: - logger.info("ignoring Register message") + logger.debug("ignoring Register message") else: # register capabilities with the GUI self.master = True @@ -912,7 +908,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): # find the session containing this client and set the session to master for session in self.coreemu.sessions.itervalues(): if self in session.broker.session_clients: - logger.info("setting session to master: %s", session.session_id) + logger.debug("setting session to master: %s", session.session_id) session.master = True break @@ -944,7 +940,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): network_id=message.get_tlv(ConfigTlvs.NETWORK_ID.value), opaque=message.get_tlv(ConfigTlvs.OPAQUE.value) ) - logger.info("Configuration message for %s node %s", config_data.object, config_data.node) + logger.debug("configuration message for %s node %s", config_data.object, config_data.node) # dispatch to any registered callback for this object type replies = self.session.config_object(config_data) @@ -1039,7 +1035,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): event_type = EventTypes(event_data.event_type) node_id = event_data.node - logger.info("EVENT %s at %s", event_type.name, time.ctime()) + logger.debug("handling event %s at %s", event_type.name, time.ctime()) if event_type.value <= EventTypes.SHUTDOWN_STATE.value: if node_id is not None: try: @@ -1116,7 +1112,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): else: raise NotImplementedError else: - logger.warn("Unhandled event message: event type %s", event_type) + logger.warn("unhandled event message: event type %s", event_type) return () @@ -1135,7 +1131,7 @@ class CoreHandler(SocketServer.BaseRequestHandler): files = coreapi.str_to_list(file_str) thumb = message.get_tlv(SessionTlvs.THUMB.value) user = message.get_tlv(SessionTlvs.USER.value) - logger.info("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) + logger.debug("SESSION message flags=0x%x sessions=%s" % (message.flags, session_id_str)) if message.flags == 0: for index, session_id in enumerate(session_ids): @@ -1146,10 +1142,10 @@ class CoreHandler(SocketServer.BaseRequestHandler): session = self.coreemu.sessions.get(session_id) if session is None: - logger.info("session %s not found", session_id) + logger.warn("session %s not found", session_id) continue - logger.info("request to modify to session %s", session.session_id) + logger.info("request to modify to session: %s", session.session_id) if names is not None: session.name = names[index] diff --git a/daemon/core/location.py b/daemon/core/location.py index 6915fc4b..b7d1bd1a 100644 --- a/daemon/core/location.py +++ b/daemon/core/location.py @@ -63,7 +63,7 @@ class CoreLocation(ConfigurableManager): values = config_data.data_values if values is None: - logger.info("location data missing") + logger.warn("location data missing") return None values = values.split('|') diff --git a/daemon/core/misc/nodeutils.py b/daemon/core/misc/nodeutils.py index 503daaa3..d6e3808d 100644 --- a/daemon/core/misc/nodeutils.py +++ b/daemon/core/misc/nodeutils.py @@ -2,8 +2,6 @@ Serves as a global point for storing and retrieving node types needed during simulation. """ -import pprint - from core import logger _NODE_MAP = None @@ -11,8 +9,11 @@ _NODE_MAP = None def _log_map(): global _NODE_MAP - print_map = reduce(lambda x, y: _convert_map(x, y), _NODE_MAP.items(), {}) - logger.info("node class map: \n%s", pprint.pformat(print_map, indent=4)) + for key, value in _NODE_MAP.iteritems(): + name = None + if value: + name = value.__name__ + logger.info("node type (%s) - class (%s)", key.name, name) def _convert_map(x, y): diff --git a/daemon/core/misc/structutils.py b/daemon/core/misc/structutils.py index 657f623c..fe0f8d9c 100644 --- a/daemon/core/misc/structutils.py +++ b/daemon/core/misc/structutils.py @@ -40,7 +40,7 @@ def pack_values(clazz, packers): value = transformer(value) # pack and add to existing data - logger.info("packing: %s - %s", tlv_type, value) + logger.debug("packing: %s - %s", tlv_type, value) data += clazz.pack(tlv_type.value, value) return data diff --git a/daemon/core/misc/utils.py b/daemon/core/misc/utils.py index 0bff4b1c..e20ecd3c 100644 --- a/daemon/core/misc/utils.py +++ b/daemon/core/misc/utils.py @@ -370,13 +370,13 @@ def load_classes(path, clazz): :return: list of classes loaded """ # validate path exists - logger.info("attempting to load modules from path: %s", path) + logger.debug("attempting to load modules from path: %s", path) if not os.path.isdir(path): logger.warn("invalid custom module directory specified" ": %s" % path) # check if path is in sys.path parent_path = os.path.dirname(path) if parent_path not in sys.path: - logger.info("adding parent path to allow imports: %s", parent_path) + logger.debug("adding parent path to allow imports: %s", parent_path) sys.path.append(parent_path) # retrieve potential service modules, and filter out invalid modules @@ -389,7 +389,7 @@ def load_classes(path, clazz): classes = [] for module_name in module_names: import_statement = "%s.%s" % (base_module, module_name) - logger.info("importing custom module: %s", import_statement) + logger.debug("importing custom module: %s", import_statement) try: module = importlib.import_module(import_statement) members = inspect.getmembers(module, lambda x: _is_class(module, x, clazz)) diff --git a/daemon/core/mobility.py b/daemon/core/mobility.py index 021a6366..73facd8a 100644 --- a/daemon/core/mobility.py +++ b/daemon/core/mobility.py @@ -525,8 +525,8 @@ class BasicRangeModel(WirelessModel): with self.wlan._linked_lock: linked = self.wlan.linked(a, b) - logger.info("checking range netif1(%s) netif2(%s): linked(%s) actual(%s) > config(%s)", - a.name, b.name, linked, d, self.range) + logger.debug("checking range netif1(%s) netif2(%s): linked(%s) actual(%s) > config(%s)", + a.name, b.name, linked, d, self.range) if d > self.range: if linked: logger.info("was linked, unlinking") diff --git a/daemon/core/netns/vnode.py b/daemon/core/netns/vnode.py index a28ea5c4..e26f700e 100644 --- a/daemon/core/netns/vnode.py +++ b/daemon/core/netns/vnode.py @@ -107,11 +107,11 @@ class SimpleLxcNode(PyCoreNode): self.client = vnodeclient.VnodeClient(self.name, self.ctrlchnlname) # bring up the loopback interface - logger.info("bringing up loopback interface") + logger.debug("bringing up loopback interface") self.check_cmd([constants.IP_BIN, "link", "set", "lo", "up"]) # set hostname for node - logger.info("setting hostname: %s", self.name) + logger.debug("setting hostname: %s", self.name) self.check_cmd(["hostname", self.name]) # mark node as up @@ -216,7 +216,7 @@ class SimpleLxcNode(PyCoreNode): :raises CoreCommandError: when a non-zero exit status occurs """ source = os.path.abspath(source) - logger.info("mounting %s at %s", source, target) + logger.info("node(%s) mounting: %s at %s", self.name, source, target) cmd = 'mkdir -p "%s" && %s -n --bind "%s" "%s"' % (target, constants.MOUNT_BIN, source, target) status, output = self.client.shcmd_result(cmd) if status: @@ -230,7 +230,7 @@ class SimpleLxcNode(PyCoreNode): :param str target: target directory to unmount :return: nothing """ - logger.info("unmounting: %s", target) + logger.info("node(%s) unmounting: %s", self.name, target) try: self.check_cmd([constants.UMOUNT_BIN, "-n", "-l", target]) except CoreCommandError: @@ -289,12 +289,12 @@ class SimpleLxcNode(PyCoreNode): # TODO: potentially find better way to query interface ID # retrieve interface information output = self.check_cmd(["ip", "link", "show", veth.name]) - logger.info("interface command output: %s", output) + logger.debug("interface command output: %s", output) output = output.split("\n") veth.flow_id = int(output[0].strip().split(":")[0]) + 1 - logger.info("interface flow index: %s - %s", veth.name, veth.flow_id) + logger.debug("interface flow index: %s - %s", veth.name, veth.flow_id) veth.hwaddr = MacAddress.from_string(output[1].strip().split()[1]) - logger.info("interface mac: %s - %s", veth.name, veth.hwaddr) + logger.debug("interface mac: %s - %s", veth.name, veth.hwaddr) try: self.addnetif(veth, ifindex) @@ -625,7 +625,7 @@ class LxcNode(SimpleLxcNode): with self.opennodefile(filename, "w") as open_file: open_file.write(contents) os.chmod(open_file.name, mode) - logger.info("created nodefile: %s; mode: 0%o", open_file.name, mode) + logger.info("node(%s) added file: %s; mode: 0%o", self.name, open_file.name, mode) def nodefilecopy(self, filename, srcfilename, mode=None): """ @@ -641,4 +641,4 @@ class LxcNode(SimpleLxcNode): shutil.copy2(srcfilename, hostfilename) if mode is not None: os.chmod(hostfilename, mode) - logger.info("copied nodefile: %s; mode: %s", hostfilename, mode) + logger.info("node(%s) copied file: %s; mode: %s", self.name, hostfilename, mode) diff --git a/daemon/core/service.py b/daemon/core/service.py index 9aadc03b..a62cf84b 100644 --- a/daemon/core/service.py +++ b/daemon/core/service.py @@ -44,7 +44,7 @@ class ServiceManager(object): insert = index + 1 break - logger.info("loading service: %s - %s: %s", insert, service, service._name) + logger.info("loading service: %s", service.__name__) cls.services.insert(insert, service) @classmethod @@ -89,7 +89,7 @@ class CoreServices(ConfigurableManager): name = "services" config_type = RegisterTlvs.UTILITY.value - _invalid_custom_names = ('core', 'api', 'emane', 'misc', 'netns', 'phys', 'services') + _invalid_custom_names = ("core", "api", "emane", "misc", "netns", "phys", "services") def __init__(self, session): """ @@ -200,21 +200,21 @@ class CoreServices(ConfigurableManager): :return: nothing """ if services_str is not None: - logger.info("setting node specific services: %s", services_str) + logger.info("setting custom services for node(%s)", node.name) services = services_str.split("|") for name in services: s = ServiceManager.get(name) if s is None: logger.warn("configured service %s for node %s is unknown", name, node.name) continue - logger.info("adding configured service %s to node %s", s._name, node.name) + logger.info("adding service to node(%s): %s", node.name, s._name) s = self.getcustomservice(node.objid, s) node.addservice(s) else: - logger.info("setting default services for node (%s) type (%s)", node.objid, nodetype) + logger.info("setting default services for node(%s) type (%s)", node.name, nodetype) services = self.getdefaultservices(nodetype) for s in services: - logger.info("adding default service %s to node %s", s._name, node.name) + logger.info("adding service to node(%s): %s", node.name, s._name) s = self.getcustomservice(node.objid, s) node.addservice(s) @@ -290,7 +290,7 @@ class CoreServices(ConfigurableManager): self.bootnodecustomservice(node, service, services, use_startup_service) return - logger.info("starting service %s (%s)", service._name, service._startindex) + logger.info("starting node(%s) service: %s (%s)", node.name, service._name, service._startindex) for directory in service._dirs: node.privatedir(directory) @@ -386,8 +386,7 @@ class CoreServices(ConfigurableManager): :return: service validation status :rtype: int """ - logger.info("validating service for node (%s - %s): %s (%s)", - node.objid, node.name, service._name, service._startindex) + logger.info("validating service for node (%s): %s (%s)", node.name, service._name, service._startindex) if service._custom: validate_cmds = service._validate else: @@ -452,7 +451,7 @@ class CoreServices(ConfigurableManager): session_id = config_data.session opaque = config_data.opaque - logger.info("configuration request: node(%s) session(%s) opaque(%s)", node_id, session_id, opaque) + logger.debug("configuration request: node(%s) session(%s) opaque(%s)", node_id, session_id, opaque) # send back a list of available services if opaque is None: @@ -545,7 +544,7 @@ class CoreServices(ConfigurableManager): return None key = values.pop(0) self.defaultservices[key] = values - logger.info("default services for type %s set to %s" % (key, values)) + logger.debug("default services for type %s set to %s", key, values) else: # store service customized config in self.customservices[] if node_id is None: diff --git a/daemon/core/session.py b/daemon/core/session.py index 1540e1f6..55bd6c38 100644 --- a/daemon/core/session.py +++ b/daemon/core/session.py @@ -245,13 +245,12 @@ class Session(object): state_name = state.name if self.state == state_value: - logger.info("session is already in state: %s, skipping change", state_name) + logger.info("session(%s) is already in state: %s, skipping change", self.session_id, state_name) return self.state = state_value self._state_time = time.time() - logger.info("changing session %s to state %s(%s) at %s", - self.session_id, state_value, state_name, self._state_time) + logger.info("changing session(%s) to state %s", self.session_id, state_name) self.write_state(state_value) self.run_hooks(state_value) @@ -462,7 +461,7 @@ class Session(object): try: utils.load_config(environment_user_file, env) except IOError: - logger.info("error reading user core environment settings file: %s", environment_user_file) + logger.debug("user core environment settings file not present: %s", environment_user_file) return env @@ -610,7 +609,7 @@ class Session(object): :return: nothing """ register_tlv = RegisterTlvs(object_type) - logger.info("adding config object callback: %s - %s", name, register_tlv) + logger.debug("adding config object callback: %s - %s", name, register_tlv) with self._config_objects_lock: self.config_objects[name] = (object_type, callback) @@ -624,8 +623,9 @@ class Session(object): :rtype: list """ name = config_data.object - logger.info("session(%s): handling config message(%s): \n%s", - self.session_id, name, config_data) + logger.info("session(%s) setting config(%s)", self.session_id, name) + for key, value in config_data.__dict__.iteritems(): + logger.debug("%s = %s", key, value) replies = [] @@ -795,7 +795,8 @@ class Session(object): # this is called from instantiate() after receiving an event message # for the instantiation state, and from the broker when distributed # nodes have been started - logger.info("checking runtime: %s", self.state) + logger.info("session(%s) checking if not in runtime state, current state: %s", self.session_id, + coreapi.state_name(self.state)) if self.state == EventTypes.RUNTIME_STATE.value: logger.info("valid runtime state found, returning") return @@ -841,7 +842,7 @@ class Session(object): and links remain. """ node_count = self.get_node_count() - logger.info("checking shutdown for session %d: %d nodes remaining", self.session_id, node_count) + logger.info("session(%s) checking shutdown: %s nodes remaining", self.session_id, node_count) shutdown = False if node_count == 0: @@ -869,7 +870,7 @@ class Session(object): # TODO: PyCoreNode is not the type to check if isinstance(obj, nodes.PyCoreNode) and not nodeutils.is_node(obj, NodeTypes.RJ45): # add a control interface if configured - logger.info("booting node: %s - %s", obj.objid, obj.name) + logger.info("booting node: %s", obj.name) self.add_remove_control_interface(node=obj, remove=False) obj.boot() diff --git a/daemon/core/xml/xmlwriter1.py b/daemon/core/xml/xmlwriter1.py index 7959b204..4d4ce35b 100644 --- a/daemon/core/xml/xmlwriter1.py +++ b/daemon/core/xml/xmlwriter1.py @@ -77,7 +77,7 @@ class CoreDocumentWriter1(Document): objects from the given session. """ Document.__init__(self) - logger.info('Exporting to NMF XML version 1.0') + logger.debug('Exporting to NMF XML version 1.0') with session._objects_lock: self.scenarioPlan = ScenarioPlan(self, session) if session.state == EventTypes.RUNTIME_STATE.value: diff --git a/daemon/data/logging.conf b/daemon/data/logging.conf index 46de6e92..7f3d496f 100644 --- a/daemon/data/logging.conf +++ b/daemon/data/logging.conf @@ -14,7 +14,7 @@ } }, "root": { - "level": "DEBUG", + "level": "INFO", "handlers": ["console"] } } diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 016120d0..07c688bd 100644 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -51,7 +51,7 @@ def cored(cfg, use_ovs): sys.exit(1) close_onexec(server.fileno()) - logger.info("main server started, listening on: %s:%s", host, port) + logger.debug("main server started, listening on: %s:%s", host, port) server.serve_forever() diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index 8da33dc3..ca865ca0 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -90,7 +90,7 @@ def run_cmd(node, exec_cmd): message_data = server.sock.recv(message_length) # If we get the right response return the results - print "received response message: %s" % MessageTypes(message_type) + print "received response message: %s" % message_type if message_type == MessageTypes.EXECUTE.value: message = coreapi.CoreExecMessage(message_flags, message_header, message_data) result = message.get_tlv(ExecuteTlvs.RESULT.value) From 9cb15139332c365dd9686bad15de13c757065195 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Mon, 30 Apr 2018 16:28:00 -0700 Subject: [PATCH 147/152] fixed refactoring bug in broker.py --- daemon/core/broker.py | 2 +- daemon/core/future/coreemu.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/daemon/core/broker.py b/daemon/core/broker.py index ed073fb5..7b879e72 100644 --- a/daemon/core/broker.py +++ b/daemon/core/broker.py @@ -1163,5 +1163,5 @@ class CoreBroker(ConfigurableManager): control_nets = map(lambda x: "%s:%s" % (x[0], x[1]), zip(servers, control_nets)) values[index] = "controlnet=%s" % (" ".join(control_nets)) values_str = "|".join(values) - message.tlvdata[ConfigTlvs.VALUES.value] = values_str + message.tlv_data[ConfigTlvs.VALUES.value] = values_str message.repack() diff --git a/daemon/core/future/coreemu.py b/daemon/core/future/coreemu.py index 648a14b2..a517823a 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/future/coreemu.py @@ -856,7 +856,6 @@ class CoreEmu(object): self.sessions = {} # set default nodes - # set default node map node_map = nodemaps.NODES nodeutils.set_node_map(node_map) From f5bff494c7b656cd0c0d64fd9f1318706f734f31 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 1 May 2018 10:40:25 -0700 Subject: [PATCH 148/152] refactored new apis to sit under the emulator module, also reverted moving files under a legacy module to help avoid breaking code using core internals for 5.0+ --- .../corehandler.py => corehandlers.py} | 6 +-- daemon/core/{legacy => }/coreserver.py | 2 +- daemon/core/{future => emulator}/__init__.py | 0 daemon/core/{future => emulator}/coreemu.py | 41 ++++++++++--------- .../futuredata.py => emulator/emudata.py} | 4 +- daemon/core/legacy/__init__.py | 0 daemon/examples/api/emane80211.py | 4 +- daemon/examples/api/switch.py | 4 +- daemon/examples/api/switch_inject.py | 2 +- daemon/examples/api/wlan.py | 4 +- daemon/scripts/core-daemon | 4 +- daemon/tests/conftest.py | 8 ++-- daemon/tests/test_core.py | 6 +-- daemon/tests/test_emane.py | 4 +- daemon/tests/test_gui.py | 2 +- daemon/tests/test_links.py | 10 ++--- daemon/tests/test_nodes.py | 2 +- 17 files changed, 53 insertions(+), 50 deletions(-) rename daemon/core/{legacy/corehandler.py => corehandlers.py} (99%) rename daemon/core/{legacy => }/coreserver.py (95%) rename daemon/core/{future => emulator}/__init__.py (100%) rename daemon/core/{future => emulator}/coreemu.py (95%) rename daemon/core/{future/futuredata.py => emulator/emudata.py} (97%) delete mode 100644 daemon/core/legacy/__init__.py diff --git a/daemon/core/legacy/corehandler.py b/daemon/core/corehandlers.py similarity index 99% rename from daemon/core/legacy/corehandler.py rename to daemon/core/corehandlers.py index d28c3e5a..362f4d54 100644 --- a/daemon/core/legacy/corehandler.py +++ b/daemon/core/corehandlers.py @@ -15,6 +15,9 @@ from core import logger from core.api import coreapi from core.data import ConfigData from core.data import EventData +from core.emulator.emudata import InterfaceData +from core.emulator.emudata import LinkOptions +from core.emulator.emudata import NodeOptions from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs from core.enumerations import EventTypes @@ -29,9 +32,6 @@ from core.enumerations import NodeTlvs from core.enumerations import NodeTypes from core.enumerations import RegisterTlvs from core.enumerations import SessionTlvs -from core.future.futuredata import InterfaceData -from core.future.futuredata import LinkOptions -from core.future.futuredata import NodeOptions from core.misc import nodeutils from core.misc import structutils from core.misc import utils diff --git a/daemon/core/legacy/coreserver.py b/daemon/core/coreserver.py similarity index 95% rename from daemon/core/legacy/coreserver.py rename to daemon/core/coreserver.py index 5b57ca51..2c052b05 100644 --- a/daemon/core/legacy/coreserver.py +++ b/daemon/core/coreserver.py @@ -4,7 +4,7 @@ Defines core server for handling TCP connections. import SocketServer -from core.future.coreemu import CoreEmu +from core.emulator.coreemu import CoreEmu class CoreServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): diff --git a/daemon/core/future/__init__.py b/daemon/core/emulator/__init__.py similarity index 100% rename from daemon/core/future/__init__.py rename to daemon/core/emulator/__init__.py diff --git a/daemon/core/future/coreemu.py b/daemon/core/emulator/coreemu.py similarity index 95% rename from daemon/core/future/coreemu.py rename to daemon/core/emulator/coreemu.py index a517823a..6712227c 100644 --- a/daemon/core/future/coreemu.py +++ b/daemon/core/emulator/coreemu.py @@ -8,11 +8,11 @@ from core import logger from core.coreobj import PyCoreNet from core.coreobj import PyCoreNode from core.data import NodeData +from core.emulator.emudata import LinkOptions +from core.emulator.emudata import NodeOptions from core.enumerations import EventTypes from core.enumerations import LinkTypes from core.enumerations import NodeTypes -from core.future.futuredata import LinkOptions -from core.future.futuredata import NodeOptions from core.misc import nodemaps from core.misc import nodeutils from core.session import Session @@ -45,7 +45,7 @@ def create_interface(node, network, interface_data): :param node: node to create interface for :param network: network to associate interface with - :param core.future.futuredata.InterfaceData interface_data: interface data + :param core.emulator.emudata.InterfaceData interface_data: interface data :return: created interface """ node.newnetif( @@ -64,7 +64,7 @@ def link_config(network, interface, link_options, devname=None, interface_two=No :param network: network to configure link for :param interface: interface to configure - :param core.future.futuredata.LinkOptions link_options: data to configure link with + :param core.emulator.emudata.LinkOptions link_options: data to configure link with :param str devname: device name, default is None :param interface_two: other interface associated, default is None :return: nothing @@ -117,9 +117,9 @@ class IdGen(object): return self.id -class FutureSession(Session): +class EmuSession(Session): def __init__(self, session_id, config=None, mkdir=True): - super(FutureSession, self).__init__(session_id, config, mkdir) + super(EmuSession, self).__init__(session_id, config, mkdir) # object management self.node_id_gen = IdGen() @@ -220,9 +220,9 @@ class FutureSession(Session): :param int node_one_id: node one id :param int node_two_id: node two id - :param core.future.futuredata.InterfaceData interface_one: node one interface data, defaults to none - :param core.future.futuredata.InterfaceData interface_two: node two interface data, defaults to none - :param core.future.futuredata.LinkOptions link_options: data for creating link, defaults to no options + :param core.emulator.emudata.InterfaceData interface_one: node one interface data, defaults to none + :param core.emulator.emudata.InterfaceData interface_two: node two interface data, defaults to none + :param core.emulator.emudata.LinkOptions link_options: data for creating link, defaults to no options :return: """ # get node objects identified by link data @@ -386,7 +386,7 @@ class FutureSession(Session): :param int node_two_id: node two id :param int interface_one_id: interface id for node one :param int interface_two_id: interface id for node two - :param core.future.futuredata.LinkOptions link_options: data to update link with + :param core.emulator.emudata.LinkOptions link_options: data to update link with :return: nothing """ # interface data @@ -467,7 +467,7 @@ class FutureSession(Session): :param core.enumerations.NodeTypes _type: type of node to create :param int _id: id for node, defaults to None for generated id - :param core.future.futuredata.NodeOptions node_options: data to create node with + :param core.emulator.emudata.NodeOptions node_options: data to create node with :return: created node """ @@ -531,7 +531,7 @@ class FutureSession(Session): Update node information. :param int node_id: id of node to update - :param core.future.futuredata.NodeOptions node_options: data to update node with + :param core.emulator.emudata.NodeOptions node_options: data to update node with :return: True if node updated, False otherwise :rtype: bool """ @@ -573,7 +573,7 @@ class FutureSession(Session): Set position for a node, use lat/lon/alt if needed. :param node: node to set position for - :param core.future.futuredata.NodeOptions node_options: data for node + :param core.emulator.emudata.NodeOptions node_options: data for node :return: nothing """ # extract location values @@ -627,9 +627,10 @@ class FutureSession(Session): :return: nothing """ + logger.info("session(%s) shutting down", self.session_id) self.set_state(EventTypes.DATACOLLECT_STATE, send_event=True) self.set_state(EventTypes.SHUTDOWN_STATE, send_event=True) - super(FutureSession, self).shutdown() + super(EmuSession, self).shutdown() def custom_delete_object(self, object_id): """ @@ -653,7 +654,7 @@ class FutureSession(Session): :return: True if active, False otherwise """ result = self.state in {EventTypes.RUNTIME_STATE.value, EventTypes.DATACOLLECT_STATE.value} - logger.info("checking if session is active: %s", result) + logger.info("session(%s) checking if active: %s", self.session_id, result) return result def open_xml(self, file_name, start=False): @@ -775,7 +776,7 @@ class FutureSession(Session): Create a wireless node for use within an wireless/EMANE networks. :param int _id: int for node, defaults to None and will be generated - :param core.future.futuredata.NodeOptions node_options: options for emane node, model will always be "mdr" + :param core.emulator.emudata.NodeOptions node_options: options for emane node, model will always be "mdr" :return: new emane node :rtype: core.netns.nodes.CoreNode """ @@ -789,7 +790,7 @@ class FutureSession(Session): :param model: emane model to use for emane network :param geo_reference: geo reference point to use for emane node locations :param geo_scale: geo scale to use for emane node locations, defaults to 1.0 - :param core.future.futuredata.NodeOptions node_options: options for emane node being created + :param core.emulator.emudata.NodeOptions node_options: options for emane node being created :return: create emane network """ # required to be set for emane to function properly @@ -880,7 +881,7 @@ class CoreEmu(object): :return: nothing """ - logger.info("shutting down all session") + logger.info("shutting down all sessions") sessions = self.sessions.copy() self.sessions.clear() for session in sessions.itervalues(): @@ -893,7 +894,7 @@ class CoreEmu(object): :param int _id: session id for new session :param bool master: sets session to master :return: created session - :rtype: FutureSession + :rtype: EmuSession """ session_id = _id @@ -903,7 +904,7 @@ class CoreEmu(object): if session_id not in self.sessions: break - session = FutureSession(session_id, config=self.config) + session = EmuSession(session_id, config=self.config) logger.info("created session: %s", session_id) if master: session.master = True diff --git a/daemon/core/future/futuredata.py b/daemon/core/emulator/emudata.py similarity index 97% rename from daemon/core/future/futuredata.py rename to daemon/core/emulator/emudata.py index 98ffeb5e..c231b743 100644 --- a/daemon/core/future/futuredata.py +++ b/daemon/core/emulator/emudata.py @@ -1,5 +1,7 @@ from core.enumerations import LinkTypes -from core.misc.ipaddress import Ipv4Prefix, Ipv6Prefix, MacAddress +from core.misc.ipaddress import Ipv4Prefix +from core.misc.ipaddress import Ipv6Prefix +from core.misc.ipaddress import MacAddress class NodeOptions(object): diff --git a/daemon/core/legacy/__init__.py b/daemon/core/legacy/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/daemon/examples/api/emane80211.py b/daemon/examples/api/emane80211.py index e60c2871..e6f08d9e 100644 --- a/daemon/examples/api/emane80211.py +++ b/daemon/examples/api/emane80211.py @@ -6,9 +6,9 @@ import datetime import parser from core.emane.ieee80211abg import EmaneIeee80211abgModel +from core.emulator.coreemu import CoreEmu +from core.emulator.emudata import IpPrefixes from core.enumerations import EventTypes -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes def example(options): diff --git a/daemon/examples/api/switch.py b/daemon/examples/api/switch.py index 9e50085f..5f63bb8e 100644 --- a/daemon/examples/api/switch.py +++ b/daemon/examples/api/switch.py @@ -8,9 +8,9 @@ import datetime import parser +from core.emulator.coreemu import CoreEmu +from core.emulator.emudata import IpPrefixes from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes def example(options): diff --git a/daemon/examples/api/switch_inject.py b/daemon/examples/api/switch_inject.py index 647f3423..374f1a18 100644 --- a/daemon/examples/api/switch_inject.py +++ b/daemon/examples/api/switch_inject.py @@ -5,8 +5,8 @@ # and repeat for minnodes <= n <= maxnodes with a step size of # nodestep +from core.emulator.emudata import IpPrefixes from core.enumerations import NodeTypes, EventTypes -from core.future.futuredata import IpPrefixes def example(nodes): diff --git a/daemon/examples/api/wlan.py b/daemon/examples/api/wlan.py index 5fa16cc0..c3b29431 100644 --- a/daemon/examples/api/wlan.py +++ b/daemon/examples/api/wlan.py @@ -8,9 +8,9 @@ import datetime import parser +from core.emulator.coreemu import CoreEmu +from core.emulator.emudata import IpPrefixes from core.enumerations import NodeTypes, EventTypes -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes from core.mobility import BasicRangeModel diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 07c688bd..4c177cdf 100644 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -13,8 +13,8 @@ import time from core import constants from core import enumerations from core import logger -from core.legacy.corehandler import CoreHandler -from core.legacy.coreserver import CoreServer +from core.corehandlers import CoreHandler +from core.coreserver import CoreServer from core.misc.utils import close_onexec from core.service import ServiceManager diff --git a/daemon/tests/conftest.py b/daemon/tests/conftest.py index bf478d4a..e1f3fb34 100644 --- a/daemon/tests/conftest.py +++ b/daemon/tests/conftest.py @@ -13,6 +13,10 @@ from core.api.coreapi import CoreEventMessage from core.api.coreapi import CoreExecMessage from core.api.coreapi import CoreLinkMessage from core.api.coreapi import CoreNodeMessage +from core.corehandlers import CoreHandler +from core.coreserver import CoreServer +from core.emulator.coreemu import CoreEmu +from core.emulator.emudata import IpPrefixes from core.enumerations import CORE_API_PORT from core.enumerations import ConfigTlvs from core.enumerations import EventTlvs @@ -23,10 +27,6 @@ from core.enumerations import LinkTypes from core.enumerations import MessageFlags from core.enumerations import NodeTlvs from core.enumerations import NodeTypes -from core.future.coreemu import CoreEmu -from core.future.futuredata import IpPrefixes -from core.legacy.corehandler import CoreHandler -from core.legacy.coreserver import CoreServer from core.misc import ipaddress from core.misc.ipaddress import MacAddress diff --git a/daemon/tests/test_core.py b/daemon/tests/test_core.py index 2e866c85..544b05f9 100644 --- a/daemon/tests/test_core.py +++ b/daemon/tests/test_core.py @@ -11,8 +11,8 @@ import pytest from mock import MagicMock from core.data import ConfigData +from core.emulator.emudata import NodeOptions from core.enumerations import MessageFlags, NodeTypes -from core.future.futuredata import NodeOptions from core.mobility import BasicRangeModel from core.netns.vnodeclient import VnodeClient from core.service import ServiceManager @@ -250,7 +250,7 @@ class TestCore: """ Test basic wlan network. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ @@ -283,7 +283,7 @@ class TestCore: """ Test basic wlan network. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ diff --git a/daemon/tests/test_emane.py b/daemon/tests/test_emane.py index c6644cf9..7720e285 100644 --- a/daemon/tests/test_emane.py +++ b/daemon/tests/test_emane.py @@ -10,7 +10,7 @@ from core.emane.commeffect import EmaneCommEffectModel from core.emane.ieee80211abg import EmaneIeee80211abgModel from core.emane.rfpipe import EmaneRfPipeModel from core.emane.tdma import EmaneTdmaModel -from core.future.futuredata import NodeOptions +from core.emulator.emudata import NodeOptions _EMANE_MODELS = [ EmaneIeee80211abgModel, @@ -27,7 +27,7 @@ class TestEmane: """ Test emane models within a basic network. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param model: emane model to test :param ip_prefixes: generates ip addresses for nodes """ diff --git a/daemon/tests/test_gui.py b/daemon/tests/test_gui.py index ca865ca0..bf6d3b01 100644 --- a/daemon/tests/test_gui.py +++ b/daemon/tests/test_gui.py @@ -105,7 +105,7 @@ class TestGui: """ Test session broker creation. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param cored: cored daemon server to test with """ diff --git a/daemon/tests/test_links.py b/daemon/tests/test_links.py index 4b5085e4..75475388 100644 --- a/daemon/tests/test_links.py +++ b/daemon/tests/test_links.py @@ -1,5 +1,5 @@ +from core.emulator.emudata import LinkOptions from core.enumerations import NodeTypes -from core.future.futuredata import LinkOptions from core.misc import utils @@ -138,7 +138,7 @@ class TestLinks: """ Test ptp node network with modifying link bandwidth. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ @@ -169,7 +169,7 @@ class TestLinks: """ Test ptp node network with modifying link packet loss. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ @@ -200,7 +200,7 @@ class TestLinks: """ Test ptp node network with modifying link packet delay. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ @@ -232,7 +232,7 @@ class TestLinks: """ Test ptp node network with modifying link packet jitter. - :param core.future.coreemu.FutureSession session: session for test + :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ diff --git a/daemon/tests/test_nodes.py b/daemon/tests/test_nodes.py index 94a757a5..68872dbe 100644 --- a/daemon/tests/test_nodes.py +++ b/daemon/tests/test_nodes.py @@ -3,8 +3,8 @@ import time import pytest +from core.emulator.emudata import NodeOptions from core.enumerations import NodeTypes -from core.future.futuredata import NodeOptions from core.misc import utils MODELS = [ From 181a47b8ca0a637e44a3c448adb6cdb7038927eb Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Tue, 1 May 2018 12:28:20 -0700 Subject: [PATCH 149/152] updates to some log statements and fix to avoid an exception for finding enpoints in xml --- daemon/core/broker.py | 57 ++++++++++++++++------------------- daemon/core/xml/xmlwriter1.py | 6 +++- daemon/scripts/core-daemon | 2 +- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/daemon/core/broker.py b/daemon/core/broker.py index 7b879e72..8b25e751 100644 --- a/daemon/core/broker.py +++ b/daemon/core/broker.py @@ -142,14 +142,13 @@ class CoreBroker(ConfigurableManager): Close all active sockets; called when the session enters the data collect state """ + self.reset() with self.servers_lock: while len(self.servers) > 0: name, server = self.servers.popitem() if server.sock is not None: - logger.info("closing connection with %s @ %s:%s" % - (name, server.host, server.port)) + logger.info("closing connection with %s: %s:%s", name, server.host, server.port) server.close() - self.reset() self.dorecvloop = False if self.recvthread is not None: self.recvthread.join() @@ -214,8 +213,7 @@ class CoreBroker(ConfigurableManager): continue rcvlen = self.recv(server) if rcvlen == 0: - logger.info("connection with %s @ %s:%s has closed" % ( - server.name, server.host, server.port)) + logger.info("connection with server(%s) closed: %s:%s", server.name, server.host, server.port) def recv(self, server): """ @@ -236,18 +234,18 @@ class CoreBroker(ConfigurableManager): return 0 if len(msghdr) != coreapi.CoreMessage.header_len: - logger.info("warning: broker received not enough data len=%s" % len(msghdr)) + logger.warn("warning: broker received not enough data len=%s", len(msghdr)) return len(msghdr) msgtype, msgflags, msglen = coreapi.CoreMessage.unpack_header(msghdr) msgdata = server.sock.recv(msglen) data = msghdr + msgdata count = None - logger.info("received message type: %s", MessageTypes(msgtype)) + logger.debug("received message type: %s", MessageTypes(msgtype)) # snoop exec response for remote interactive TTYs if msgtype == MessageTypes.EXECUTE.value and msgflags & MessageFlags.TTY.value: data = self.fixupremotetty(msghdr, msgdata, server.host) - logger.info("created remote tty message: %s", data) + logger.debug("created remote tty message: %s", data) elif msgtype == MessageTypes.NODE.value: # snoop node delete response to decrement node counts if msgflags & MessageFlags.DELETE.value: @@ -293,22 +291,21 @@ class CoreBroker(ConfigurableManager): with self.servers_lock: server = self.servers.get(name) if server is not None: - if host == server.host and port == server.port and \ - server.sock is not None: + if host == server.host and port == server.port and server.sock is not None: # leave this socket connected return - logger.info("closing connection with %s @ %s:%s" % (name, server.host, server.port)) + logger.info("closing connection with %s @ %s:%s", name, server.host, server.port) server.close() del self.servers[name] - logger.info("adding broker server(%s): %s:%s" % (name, host, port)) + logger.info("adding broker server(%s): %s:%s", name, host, port) server = CoreDistributedServer(name, host, port) if host is not None and port is not None: try: server.connect() except IOError: - logger.exception("error connecting to server %s:%s" % (host, port)) + logger.exception("error connecting to server(%s): %s:%s", name, host, port) if server.sock is not None: self.startrecvloop() self.servers[name] = server @@ -328,7 +325,7 @@ class CoreBroker(ConfigurableManager): logger.exception("error deleting server") if server.sock is not None: - logger.info("closing connection with %s @ %s:%s" % (server.name, server.host, server.port)) + logger.info("closing connection with %s @ %s:%s", server.name, server.host, server.port) server.close() def getserverbyname(self, name): @@ -412,7 +409,7 @@ class CoreBroker(ConfigurableManager): remotenum = n2num if key in self.tunnels.keys(): - logger.warn("tunnel with key %s (%s-%s) already exists!" % (key, n1num, n2num)) + logger.warn("tunnel with key %s (%s-%s) already exists!", key, n1num, n2num) else: objid = key & ((1 << 16) - 1) logger.info("adding tunnel for %s-%s to %s with key %s", n1num, n2num, remoteip, key) @@ -494,7 +491,7 @@ class CoreBroker(ConfigurableManager): gt = self.tunnels[key] r.append(gt) continue - logger.info("adding tunnel for net %s to %s with key %s" % (node_id, host, key)) + logger.info("adding tunnel for net %s to %s with key %s", node_id, host, key) gt = GreTap(node=None, name=None, session=self.session, remoteip=host, key=key) self.tunnels[key] = gt r.append(gt) @@ -698,8 +695,7 @@ class CoreBroker(ConfigurableManager): elif message.message_type == MessageTypes.CONFIG.value: # broadcast location and services configuration everywhere confobj = message.get_tlv(ConfigTlvs.OBJECT.value) - if confobj == "location" or confobj == "services" or \ - confobj == "session" or confobj == "all": + if confobj == "location" or confobj == "services" or confobj == "session" or confobj == "all": servers = self.getservers() elif message.message_type == MessageTypes.FILE.value: # broadcast hook scripts and custom service files everywhere @@ -735,10 +731,10 @@ class CoreBroker(ConfigurableManager): """ server = self.getserverbyname(servername) if server is None: - logger.warn("ignoring unknown server: %s" % servername) + logger.warn("ignoring unknown server: %s", servername) return if server.sock is None or server.host is None or server.port is None: - logger.info("ignoring disconnected server: %s" % servername) + logger.info("ignoring disconnected server: %s", servername) return # communicate this session"s current state to the server @@ -811,10 +807,10 @@ class CoreBroker(ConfigurableManager): try: nodecls = nodeutils.get_node_class(NodeTypes(nodetype)) except KeyError: - logger.warn("broker invalid node type %s" % nodetype) + logger.warn("broker invalid node type %s", nodetype) return handle_locally, servers if nodecls is None: - logger.warn("broker unimplemented node type %s" % nodetype) + logger.warn("broker unimplemented node type %s", nodetype) return handle_locally, servers if issubclass(nodecls, PyCoreNet) and nodetype != NodeTypes.WIRELESS_LAN.value: # network node replicated on all servers; could be optimized @@ -1013,11 +1009,10 @@ class CoreBroker(ConfigurableManager): # local emulation server, handle this locally handle_locally = True elif server.sock is None: - logger.info("server %s @ %s:%s is disconnected" % ( - server.name, server.host, server.port)) + logger.info("server %s @ %s:%s is disconnected", server.name, server.host, server.port) else: - logger.info("forwarding message to server: %s - %s:\n%s", - server.host, server.port, message) + logger.info("forwarding message to server(%s): %s:%s", server.name, server.host, server.port) + logger.debug("message being forwarded:\n%s", message) server.sock.send(message.raw_message) return handle_locally @@ -1045,7 +1040,7 @@ class CoreBroker(ConfigurableManager): lhost, lport = server.sock.getsockname() f.write("%s %s %s %s %s\n" % (server.name, server.host, server.port, lhost, lport)) except IOError: - logger.exception("error writing server list to the file: %s" % filename) + logger.exception("error writing server list to the file: %s", filename) def writenodeserver(self, nodestr, server): """ @@ -1072,7 +1067,7 @@ class CoreBroker(ConfigurableManager): with open(filename, "w") as f: f.write("%s\n%s\n" % (serverstr, nodestr)) except IOError: - logger.exception("error writing server file %s for node %s" % (filename, name)) + logger.exception("error writing server file %s for node %s", filename, name) def local_instantiation_complete(self): """ @@ -1126,9 +1121,9 @@ class CoreBroker(ConfigurableManager): if values_str is None: return - value_strings = values_str.split('|') + value_strings = values_str.split("|") for value_string in value_strings: - key, value = value_string.split('=', 1) + key, value = value_string.split("=", 1) if key == "controlnet": self.handle_distributed_control_net(message, value_strings, value_strings.index(value_string)) @@ -1144,7 +1139,7 @@ class CoreBroker(ConfigurableManager): :return: nothing """ key_value = values[index] - key, value = key_value.split('=', 1) + key, value = key_value.split("=", 1) control_nets = value.split() if len(control_nets) < 2: diff --git a/daemon/core/xml/xmlwriter1.py b/daemon/core/xml/xmlwriter1.py index 4d4ce35b..235b4d56 100644 --- a/daemon/core/xml/xmlwriter1.py +++ b/daemon/core/xml/xmlwriter1.py @@ -891,6 +891,10 @@ def get_endpoint(network_object, interface_object): ep = None l2devport = None + # skip if either are none + if not network_object or not interface_object: + return ep + # if ifcObj references an interface of a node and is part of this network if interface_object.net.objid == network_object.objid and hasattr(interface_object, 'node') and interface_object.node: @@ -957,7 +961,7 @@ def get_endpoints(network_object): if ep is not None: endpoints.append(ep) except: - logger.exception("error geting endpoints, was skipped before") + logger.debug("error geting endpoints, was skipped before") return endpoints diff --git a/daemon/scripts/core-daemon b/daemon/scripts/core-daemon index 4c177cdf..86c5cd47 100644 --- a/daemon/scripts/core-daemon +++ b/daemon/scripts/core-daemon @@ -51,7 +51,7 @@ def cored(cfg, use_ovs): sys.exit(1) close_onexec(server.fileno()) - logger.debug("main server started, listening on: %s:%s", host, port) + logger.info("server started, listening on: %s:%s", host, port) server.serve_forever() From 088260abf2fb0d72ab1064b2de94c137fdea5887 Mon Sep 17 00:00:00 2001 From: "Blake J. Harnden" Date: Wed, 2 May 2018 08:50:38 -0700 Subject: [PATCH 150/152] updates to README to add Discord and online documentation link --- README.md | 91 ++++++++++++++++++++++++------------------------------- 1 file changed, 40 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index d5a1cf82..25ffc6d3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -CORE -==== +# CORE CORE: Common Open Research Emulator @@ -7,24 +6,39 @@ Copyright (c)2005-2018 the Boeing Company. See the LICENSE file included in this distribution. -About ------ +## About -CORE is a tool for emulating networks using a GUI or Python scripts. The CORE -project site (1) is a good source of introductory information, with a manual, -screenshots, and demos about this software. The GitHub project (2) hosts the -source repos, wiki, and bug tracker. There is a deprecated -Google Code page (3) with the old wiki, blog, bug tracker, and quickstart guide. +The Common Open Research Emulator (CORE) is a tool for emulating +networks on one or more machines. You can connect these emulated +networks to live networks. CORE consists of a GUI for drawing +topologies of lightweight virtual machines, and Python modules for +scripting network emulation. -1. http://www.nrl.navy.mil/itd/ncs/products/core -1. https://github.com/coreemu/core -1. http://code.google.com/p/coreemu/ -1. [Official Documentation](https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/index.html) +## Documentation and Examples -Building CORE -------------- +* Documentation hosted on GitHub + * http://coreemu.github.io/core/ +* Basic Script Examples + * [Examples](daemon/examples/api) +* Custom Service Example + * [sample.py](daemon/examples/myservices/sample.py) +* Custom Emane Model Example + * [examplemodel.py](daemon/examples/myemane/examplemodel.py) -To build this software you should use: +## Support + +We are leveraging Discord for persistent chat rooms, voice chat, and +GitHub integration. This allows for more dynamic conversations and the +capability to respond faster. Feel free to join us at the link below. +https://discord.gg/AKd7kmP + +You can also get help with questions, comments, or trouble, by using +the CORE mailing lists: + +* [core-users](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-users) for general comments and questions +* [core-dev](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-dev) for bugs, compile errors, and other development issues + +## Building CORE ```shell ./bootstrap.sh @@ -33,42 +47,19 @@ make sudo make install ``` -Note: You may need to pass the proxy settings to sudo make install: - sudo make install HTTP_PROXY= - -Here is what is installed with 'make install': - - /usr/local/bin/core-gui - /usr/local/bin/core-daemon - /usr/local/bin/[vcmd, vnoded, coresendmsg, core-cleanup] - /usr/local/lib/core/* - /usr/local/share/core/* - /usr/local/lib/python2.6/dist-packages/core/* - /usr/local/lib/python2.6/dist-packages/[netns,vcmd].so - /etc/core/* - /etc/init.d/core - -See the manual for the software required for building CORE. - Building Documentation ---------------------- -Being able to build documentation depends on help2man being installed. - -Once that has been done you can run the following commands: - ```shell ./bootstrap.sh ./configure -make html +make doc ``` Building Packages ----------------- -Install fpm - - http://fpm.readthedocs.io/en/latest/installing.html +Install fpm: http://fpm.readthedocs.io/en/latest/installing.html Build package commands, DESTDIR is used for gui packaging only @@ -83,8 +74,12 @@ make fpm DESTDIR=/tmp/core-gui This will produce: * CORE GUI rpm/deb files + * core-gui_$VERSION_$ARCH * CORE ns3 rpm/deb files + * python-core-ns3_$VERSION_$ARCH * CORE python rpm/deb files for SysV and systemd service types + * python-core-sysv_$VERSION_$ARCH + * python-core-systemd_$VERSION_$ARCH Running CORE ------------ @@ -92,7 +87,10 @@ Running CORE First start the CORE services: ```shell -sudo /etc/init.d/core-daemon start +# sysv +sudo service core-daemon start +# systemd +sudo systemctl start core-daemon ``` This automatically runs the core-daemon program. @@ -103,12 +101,3 @@ core-gui ``` This launches the CORE GUI. You do not need to run the GUI as root. - - -Support -------- - -If you have questions, comments, or trouble, please use the CORE mailing lists: - -- [core-users](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-users) for general comments and questions -- [core-dev](https://pf.itd.nrl.navy.mil/mailman/listinfo/core-dev) for bugs, compile errors, and other development issues From 67a78828c3166be7fe2cfaa4aad58a9ce8c37376 Mon Sep 17 00:00:00 2001 From: stuartmarsden Date: Sun, 20 May 2018 22:21:19 +0400 Subject: [PATCH 151/152] update_link had wrong arg order --- daemon/core/emulator/coreemu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/core/emulator/coreemu.py b/daemon/core/emulator/coreemu.py index 6712227c..8fa6ffb9 100644 --- a/daemon/core/emulator/coreemu.py +++ b/daemon/core/emulator/coreemu.py @@ -378,7 +378,7 @@ class EmuSession(Session): if node_two: node_two.lock.release() - def update_link(self, node_one_id, node_two_id, link_options, interface_one_id=None, interface_two_id=None): + def update_link(self, node_one_id, node_two_id, interface_one_id=None, interface_two_id=None, link_options=LinkOptions()): """ Update link information between nodes. From aa6b83f29bc51c6740947c0b7d7393ec8e0712c5 Mon Sep 17 00:00:00 2001 From: stuartmarsden Date: Sun, 20 May 2018 23:14:29 +0400 Subject: [PATCH 152/152] fix netem 0% loss and duplicate issue --- daemon/core/netns/openvswitch.py | 4 ++-- daemon/core/netns/vnet.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/daemon/core/netns/openvswitch.py b/daemon/core/netns/openvswitch.py index 341ab92a..46ba2f2c 100644 --- a/daemon/core/netns/openvswitch.py +++ b/daemon/core/netns/openvswitch.py @@ -248,10 +248,10 @@ class OvsNet(PyCoreNet): if jitter is not None: netem += ["%sus" % jitter, "25%"] - if loss is not None: + if loss is not None and loss > 0: netem += ["loss", "%s%%" % min(loss, 100)] - if duplicate is not None: + if duplicate is not None and duplicate > 0: netem += ["duplicate", "%s%%" % min(duplicate, 100)] if delay <= 0 and jitter <= 0 and loss <= 0 and duplicate <= 0: diff --git a/daemon/core/netns/vnet.py b/daemon/core/netns/vnet.py index 545ca648..7a517d08 100644 --- a/daemon/core/netns/vnet.py +++ b/daemon/core/netns/vnet.py @@ -475,9 +475,9 @@ class LxBrNet(PyCoreNet): else: netem += ["%sus" % jitter, "25%"] - if loss is not None: + if loss is not None and loss > 0: netem += ["loss", "%s%%" % min(loss, 100)] - if duplicate is not None: + if duplicate is not None and duplicate > 0: netem += ["duplicate", "%s%%" % min(duplicate, 100)] if delay <= 0 and jitter <= 0 and loss <= 0 and duplicate <= 0: # possibly remove netem if it exists and parent queue wasn't removed