summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatej Klotton <mklotton@cisco.com>2016-11-11 11:38:55 +0100
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-15 15:32:48 +0000
commit86d87c40dd97ced69c939299204fadf1859a2f50 (patch)
tree892a3adc4906186922354ef4f9381ff490dd9415
parentb7c3f2c61c25e3a9e729c5ea7e4a0117f717a2c5 (diff)
Update test documentation.
- update IRB, IPv4, ipv6 doc - revert 778c2765c8ea5c6628f6d668847f0b9ae06dbf3d Change-Id: I9af5ed9329ce5fe01392cf28d5bf321cfc647e48 Signed-off-by: Matej Klotton <mklotton@cisco.com>
-rw-r--r--Makefile2
-rw-r--r--test/doc/Makefile61
-rw-r--r--test/doc/framework.rst7
-rw-r--r--test/doc/hook.rst7
-rw-r--r--test/doc/index.rst10
-rw-r--r--test/doc/log.rst7
-rw-r--r--test/doc/modules.rst24
-rw-r--r--test/doc/run_tests.rst7
-rw-r--r--test/doc/scapy_handlers.rst22
-rw-r--r--test/doc/template_bd.rst7
-rw-r--r--test/doc/test_ip4.rst7
-rw-r--r--test/doc/test_ip6.rst7
-rw-r--r--test/doc/test_l2bd.rst7
-rw-r--r--test/doc/test_l2xc.rst7
-rw-r--r--test/doc/test_lb.rst7
-rw-r--r--test/doc/test_mpls.rst7
-rw-r--r--test/doc/test_vxlan.rst7
-rw-r--r--test/doc/util.rst7
-rw-r--r--test/doc/vpp_interface.rst7
-rw-r--r--test/doc/vpp_papi_provider.rst7
-rw-r--r--test/doc/vpp_pg_interface.rst7
-rw-r--r--test/doc/vpp_sub_interface.rst7
-rw-r--r--test/framework.py27
-rw-r--r--test/test_ip4.py78
-rw-r--r--test/test_ip4_irb.py83
-rw-r--r--test/test_ip6.py77
-rw-r--r--test/vpp_interface.py85
-rw-r--r--test/vpp_lo_interface.py4
28 files changed, 277 insertions, 315 deletions
diff --git a/Makefile b/Makefile
index 41a45c88beb..4e084d4dfe0 100644
--- a/Makefile
+++ b/Makefile
@@ -212,7 +212,7 @@ build-vpp-api: $(BR)/.bootstrap.ok
VPP_PYTHON_PREFIX=$(BR)/python
define test
- $(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=$(1) TAG=$(2) vpp-api-install plugins-install vpp-install vpp-api-test-install,)
+ $(if $(filter-out $(3),retest),make -C $(BR) PLATFORM=$(1) TAG=$(2) vpp-api-install plugins-install vpp-install,)
make -C test \
VPP_TEST_BIN=$(BR)/install-$(2)-native/vpp/bin/vpp \
VPP_TEST_API_TEST_BIN=$(BR)/install-$(2)-native/vpp-api-test/bin/vpp_api_test \
diff --git a/test/doc/Makefile b/test/doc/Makefile
index 3b4c02b8420..809abef846e 100644
--- a/test/doc/Makefile
+++ b/test/doc/Makefile
@@ -8,13 +8,15 @@ SPHINXBUILD = sphinx-build
PAPER =
BUILD_DOC_ROOT = $(BR)/test-doc
BUILD_DOC_DIR = $(BUILD_DOC_ROOT)/build
+API_DOC_GEN_DIR = $(BUILD_DOC_ROOT)/apidoc
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILD_DOC_DIR)/.sphinx-cache $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRC_DOC_DIR)
+ALLSPHINXOPTS = -d $(BUILD_DOC_DIR)/.sphinx-cache $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(API_DOC_GEN_DIR) -c $(SRC_DOC_DIR)
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+INDEX_REL_PATH:=$(shell realpath --relative-to=$(API_DOC_GEN_DIR) $(SRC_DOC_DIR)/index.rst)
IN_VENV:=$(shell if pip -V | grep "virtualenv" 2>&1 > /dev/null; then echo 1; else echo 0; fi)
.PHONY: verify-virtualenv
@@ -23,6 +25,13 @@ ifeq ($(IN_VENV),0)
$(error "Not running inside virtualenv (are you running 'make test-doc' from root?)")
endif
+.PHONY: regen-api-doc
+regen-api-doc: verify-virtualenv
+ @mkdir -p $(API_DOC_GEN_DIR)
+ #@echo ".. include:: $(INDEX_REL_PATH)" > $(API_DOC_GEN_DIR)/index.rst
+ @cp $(SRC_DOC_DIR)/index.rst $(API_DOC_GEN_DIR)
+ sphinx-apidoc -o $(API_DOC_GEN_DIR) ..
+
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@@ -58,44 +67,44 @@ wipe:
rm -rf $(BUILD_DOC_ROOT)
.PHONY: html
-html: verify-virtualenv
+html: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/html."
.PHONY: dirhtml
-dirhtml: verify-virtualenv
+dirhtml: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/dirhtml."
.PHONY: singlehtml
-singlehtml: verify-virtualenv
+singlehtml: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILD_DOC_DIR)/singlehtml."
.PHONY: pickle
-pickle: verify-virtualenv
+pickle: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
-json: verify-virtualenv
+json: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
-htmlhelp: verify-virtualenv
+htmlhelp: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILD_DOC_DIR)/htmlhelp."
.PHONY: qthelp
-qthelp: verify-virtualenv
+qthelp: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
@@ -105,7 +114,7 @@ qthelp: verify-virtualenv
@echo "# assistant -collectionFile $(BUILD_DOC_DIR)/qthelp/VPPtestframework.qhc"
.PHONY: applehelp
-applehelp: verify-virtualenv
+applehelp: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILD_DOC_DIR)/applehelp."
@@ -114,7 +123,7 @@ applehelp: verify-virtualenv
"bundle."
.PHONY: devhelp
-devhelp: verify-virtualenv
+devhelp: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/devhelp
@echo
@echo "Build finished."
@@ -124,7 +133,7 @@ devhelp: verify-virtualenv
@echo "# devhelp"
.PHONY: epub
-epub: verify-virtualenv
+epub: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILD_DOC_DIR)/epub."
@@ -136,7 +145,7 @@ epub3:
@echo "Build finished. The epub3 file is in $(BUILD_DOC_DIR)/epub3."
.PHONY: latex
-latex: verify-virtualenv
+latex: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILD_DOC_DIR)/latex."
@@ -144,33 +153,33 @@ latex: verify-virtualenv
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
-latexpdf: verify-virtualenv
+latexpdf: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex."
.PHONY: latexpdfja
-latexpdfja: verify-virtualenv
+latexpdfja: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex."
.PHONY: text
-text: verify-virtualenv
+text: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/text
@echo
@echo "Build finished. The text files are in $(BUILD_DOC_DIR)/text."
.PHONY: man
-man: verify-virtualenv
+man: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILD_DOC_DIR)/man."
.PHONY: texinfo
-texinfo: verify-virtualenv
+texinfo: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILD_DOC_DIR)/texinfo."
@@ -178,57 +187,57 @@ texinfo: verify-virtualenv
"(use \`make info' here to do that automatically)."
.PHONY: info
-info: verify-virtualenv
+info: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILD_DOC_DIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILD_DOC_DIR)/texinfo."
.PHONY: gettext
-gettext: verify-virtualenv
+gettext: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILD_DOC_DIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILD_DOC_DIR)/locale."
.PHONY: changes
-changes: verify-virtualenv
+changes: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/changes
@echo
@echo "The overview file is in $(BUILD_DOC_DIR)/changes."
.PHONY: linkcheck
-linkcheck: verify-virtualenv
+linkcheck: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILD_DOC_DIR)/linkcheck/output.txt."
.PHONY: doctest
-doctest: verify-virtualenv
+doctest: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILD_DOC_DIR)/doctest/output.txt."
.PHONY: coverage
-coverage: verify-virtualenv
+coverage: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILD_DOC_DIR)/coverage/python.txt."
.PHONY: xml
-xml: verify-virtualenv
+xml: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILD_DOC_DIR)/xml."
.PHONY: pseudoxml
-pseudoxml: verify-virtualenv
+pseudoxml: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILD_DOC_DIR)/pseudoxml."
.PHONY: dummy
-dummy: verify-virtualenv
+dummy: regen-api-doc verify-virtualenv
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."
diff --git a/test/doc/framework.rst b/test/doc/framework.rst
deleted file mode 100644
index ce5e16e2eab..00000000000
--- a/test/doc/framework.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-framework module
-================
-
-.. automodule:: framework
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/hook.rst b/test/doc/hook.rst
deleted file mode 100644
index f856e51972b..00000000000
--- a/test/doc/hook.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-hook module
-===========
-
-.. automodule:: hook
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/index.rst b/test/doc/index.rst
index 323b608fdfb..8cbe961f887 100644
--- a/test/doc/index.rst
+++ b/test/doc/index.rst
@@ -22,7 +22,7 @@ Anatomy of a test case
######################
Python's unittest_ is used as the base framework upon which the VPP test
-framework is built. A test suite in the |vtf| constists of multiple classes
+framework is built. A test suite in the |vtf| consists of multiple classes
derived from `VppTestCase`, which is itself derived from TestCase_.
The test class defines one or more test functions, which act as test cases.
@@ -44,11 +44,11 @@ Function flow when running a test case is:
The tearDown function is called after each test function with the purpose
of doing partial cleanup.
5. `tearDownClass <VppTestCase.tearDownClass>`:
- Method called once after running all of the test funnctions to perform
+ Method called once after running all of the test functions to perform
the final cleanup.
Test temporary directory and VPP life cycle
-################################################
+###########################################
Test separation is achieved by separating the test files and vpp instances.
Each test creates a temporary directory and it's name is used to create
@@ -60,7 +60,7 @@ are stored in this temporary test directory.
Virtual environment
###################
-Virtualenv_ is a python module which provides a means to crate an environment
+Virtualenv_ is a python module which provides a means to create an environment
containing the dependencies required by the |vtf|, allowing a separation
from any existing system-wide packages. |vtf|'s Makefile automatically
creates a virtualenv_ inside build-root and installs the required packages
@@ -72,7 +72,7 @@ Naming conventions
Most unit tests do some kind of packet manipulation - sending and receiving
packets between VPP and virtual hosts connected to the VPP. Referring
-to the sides, addresses, etc.. is always done as if looking from the VPP side,
+to the sides, addresses, etc. is always done as if looking from the VPP side,
thus:
* *local_* prefix is used for the VPP side.
diff --git a/test/doc/log.rst b/test/doc/log.rst
deleted file mode 100644
index 5965d5adff5..00000000000
--- a/test/doc/log.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-log module
-==========
-
-.. automodule:: log
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/modules.rst b/test/doc/modules.rst
deleted file mode 100644
index 773283e399a..00000000000
--- a/test/doc/modules.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-test
-====
-
-.. toctree::
- :maxdepth: 4
-
- framework
- hook
- log
- run_tests
- scapy_handlers
- template_bd
- test_ip4
- test_ip6
- test_l2bd
- test_l2xc
- test_lb
- test_mpls
- test_vxlan
- util
- vpp_interface
- vpp_papi_provider
- vpp_pg_interface
- vpp_sub_interface
diff --git a/test/doc/run_tests.rst b/test/doc/run_tests.rst
deleted file mode 100644
index 30cec4e3055..00000000000
--- a/test/doc/run_tests.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-run_tests module
-================
-
-.. automodule:: run_tests
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/scapy_handlers.rst b/test/doc/scapy_handlers.rst
deleted file mode 100644
index 6717326a2fe..00000000000
--- a/test/doc/scapy_handlers.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-scapy_handlers package
-======================
-
-Submodules
-----------
-
-scapy_handlers.vxlan module
----------------------------
-
-.. automodule:: scapy_handlers.vxlan
- :members:
- :undoc-members:
- :show-inheritance:
-
-
-Module contents
----------------
-
-.. automodule:: scapy_handlers
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/template_bd.rst b/test/doc/template_bd.rst
deleted file mode 100644
index e173d27aaf6..00000000000
--- a/test/doc/template_bd.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-template_bd module
-==================
-
-.. automodule:: template_bd
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_ip4.rst b/test/doc/test_ip4.rst
deleted file mode 100644
index c3c3a23a8b8..00000000000
--- a/test/doc/test_ip4.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_ip module
-==============
-
-.. automodule:: test_ip4
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_ip6.rst b/test/doc/test_ip6.rst
deleted file mode 100644
index 63461c3cbe9..00000000000
--- a/test/doc/test_ip6.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_ip6 module
-===============
-
-.. automodule:: test_ip6
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_l2bd.rst b/test/doc/test_l2bd.rst
deleted file mode 100644
index 8a80dfe6a5b..00000000000
--- a/test/doc/test_l2bd.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_l2bd module
-================
-
-.. automodule:: test_l2bd
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_l2xc.rst b/test/doc/test_l2xc.rst
deleted file mode 100644
index caf99badf2d..00000000000
--- a/test/doc/test_l2xc.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_l2xc module
-================
-
-.. automodule:: test_l2xc
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_lb.rst b/test/doc/test_lb.rst
deleted file mode 100644
index e134b29c940..00000000000
--- a/test/doc/test_lb.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_lb module
-==============
-
-.. automodule:: test_lb
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_mpls.rst b/test/doc/test_mpls.rst
deleted file mode 100644
index e4c8ce0e718..00000000000
--- a/test/doc/test_mpls.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_mpls module
-================
-
-.. automodule:: test_mpls
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/test_vxlan.rst b/test/doc/test_vxlan.rst
deleted file mode 100644
index 7f40c319013..00000000000
--- a/test/doc/test_vxlan.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-test_vxlan module
-=================
-
-.. automodule:: test_vxlan
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/util.rst b/test/doc/util.rst
deleted file mode 100644
index d8ad0d148dc..00000000000
--- a/test/doc/util.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-util module
-===========
-
-.. automodule:: util
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/vpp_interface.rst b/test/doc/vpp_interface.rst
deleted file mode 100644
index 32bb009b6e4..00000000000
--- a/test/doc/vpp_interface.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-vpp_interface module
-====================
-
-.. automodule:: vpp_interface
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/vpp_papi_provider.rst b/test/doc/vpp_papi_provider.rst
deleted file mode 100644
index c9efe85a3c3..00000000000
--- a/test/doc/vpp_papi_provider.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-vpp_papi_provider module
-========================
-
-.. automodule:: vpp_papi_provider
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/vpp_pg_interface.rst b/test/doc/vpp_pg_interface.rst
deleted file mode 100644
index 85f54f625e5..00000000000
--- a/test/doc/vpp_pg_interface.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-vpp_pg_interface module
-=======================
-
-.. automodule:: vpp_pg_interface
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/doc/vpp_sub_interface.rst b/test/doc/vpp_sub_interface.rst
deleted file mode 100644
index 5ff5300b415..00000000000
--- a/test/doc/vpp_sub_interface.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-vpp_sub_interface module
-========================
-
-.. automodule:: vpp_sub_interface
- :members:
- :undoc-members:
- :show-inheritance:
diff --git a/test/framework.py b/test/framework.py
index fdb600c4093..227428ef9c2 100644
--- a/test/framework.py
+++ b/test/framework.py
@@ -29,22 +29,15 @@ class _PacketInfo(object):
Help process information about the next packet.
Set variables to default values.
- @property index
- Integer variable to store the index of the packet.
- @property src
- Integer variable to store the index of the source packet generator
- interface of the packet.
- @property dst
- Integer variable to store the index of the destination packet generator
- interface of the packet.
- @property data
- Object variable to store the copy of the former packet.
-
-
"""
+ #: Store the index of the packet.
index = -1
+ #: Store the index of the source packet generator interface of the packet.
src = -1
+ #: Store the index of the destination packet generator interface
+ #: of the packet.
dst = -1
+ #: Store the copy of the former packet.
data = None
@@ -54,12 +47,8 @@ def pump_output(out, queue):
class VppTestCase(unittest.TestCase):
- """
- Subclass of the python unittest.TestCase class.
-
- This subclass is a base class for test cases that are implemented as classes
- It provides methods to create and run test case.
-
+ """This subclass is a base class for VPP test cases that are implemented as
+ classes. It provides methods to create and run test case.
"""
@property
@@ -189,7 +178,7 @@ class VppTestCase(unittest.TestCase):
cls.packet_infos = {}
cls.verbose = 0
print(double_line_delim)
- print(colorize(getdoc(cls), YELLOW))
+ print(colorize(getdoc(cls).splitlines()[0], YELLOW))
print(double_line_delim)
# need to catch exceptions here because if we raise, then the cleanup
# doesn't get called and we might end with a zombie vpp
diff --git a/test/test_ip4.py b/test/test_ip4.py
index 48155a5a025..36a907a66df 100644
--- a/test/test_ip4.py
+++ b/test/test_ip4.py
@@ -2,24 +2,38 @@
import unittest
import socket
-from logging import *
from framework import VppTestCase, VppTestRunner
+from vpp_interface import VppInterface
from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
from scapy.packet import Raw
-from scapy.layers.l2 import Ether, Dot1Q, ARP
+from scapy.layers.l2 import Ether, Dot1Q
from scapy.layers.inet import IP, UDP
class TestIPv4(VppTestCase):
""" IPv4 Test Case """
- @classmethod
- def setUpClass(cls):
- super(TestIPv4, cls).setUpClass()
-
def setUp(self):
+ """
+ Perform test setup before test case.
+
+ **Config:**
+ - create 3 pg interfaces
+ - untagged pg0 interface
+ - Dot1Q subinterface on pg1
+ - Dot1AD subinterface on pg2
+ - setup interfaces:
+ - put it into UP state
+ - set IPv4 addresses
+ - resolve neighbor address using ARP
+ - configure 200 fib entries
+
+ :ivar list interfaces: pg interfaces and subinterfaces.
+ :ivar dict flows: IPv4 packet flows in test.
+ :ivar list pg_if_packet_sizes: packet sizes in test.
+ """
super(TestIPv4, self).setUp()
# create 3 pg interfaces
@@ -49,16 +63,26 @@ class TestIPv4(VppTestCase):
i.config_ip4()
i.resolve_arp()
- # config 2M FIB enries
+ # config 2M FIB entries
self.config_fib_entries(200)
def tearDown(self):
+ """Run standard test teardown and log ``show ip arp``."""
super(TestIPv4, self).tearDown()
if not self.vpp_dead:
- info(self.vapi.cli("show ip arp"))
+ self.logger.info(self.vapi.cli("show ip arp"))
# info(self.vapi.cli("show ip fib")) # many entries
def config_fib_entries(self, count):
+ """For each interface add to the FIB table *count* routes to
+ "10.0.0.1/32" destination with interface's local address as next-hop
+ address.
+
+ :param int count: Number of FIB entries.
+
+ - *TODO:* check if the next-hop address shouldn't be remote address
+ instead of local address.
+ """
n_int = len(self.interfaces)
percent = 0
counter = 0.0
@@ -69,13 +93,18 @@ class TestIPv4(VppTestCase):
for j in range(count / n_int):
self.vapi.ip_add_del_route(
dest_addr, dest_addr_len, next_hop_address)
- counter = counter + 1
+ counter += 1
if counter / count * 100 > percent:
- info("Configure %d FIB entries .. %d%% done" %
- (count, percent))
- percent = percent + 1
+ self.logger.info("Configure %d FIB entries .. %d%% done" %
+ (count, percent))
+ percent += 1
def create_stream(self, src_if, packet_sizes):
+ """Create input packet stream for defined interface.
+
+ :param VppInterface src_if: Interface to create packet stream for.
+ :param list packet_sizes: Required packet sizes.
+ """
pkts = []
for i in range(0, 257):
dst_if = self.flows[src_if][i % 2]
@@ -95,7 +124,13 @@ class TestIPv4(VppTestCase):
return pkts
def verify_capture(self, dst_if, capture):
- info("Verifying capture on interface %s" % dst_if.name)
+ """Verify captured input packet stream for defined interface.
+
+ :param VppInterface dst_if: Interface to verify captured packet stream
+ for.
+ :param list capture: Captured packet stream.
+ """
+ self.logger.info("Verifying capture on interface %s" % dst_if.name)
last_info = dict()
for i in self.interfaces:
last_info[i.sw_if_index] = None
@@ -114,8 +149,8 @@ class TestIPv4(VppTestCase):
payload_info = self.payload_to_info(str(packet[Raw]))
packet_index = payload_info.index
self.assertEqual(payload_info.dst, dst_sw_if_index)
- debug("Got packet on port %s: src=%u (id=%u)" %
- (dst_if.name, payload_info.src, packet_index))
+ self.logger.debug("Got packet on port %s: src=%u (id=%u)" %
+ (dst_if.name, payload_info.src, packet_index))
next_info = self.get_next_packet_info_for_interface2(
payload_info.src, dst_sw_if_index,
last_info[payload_info.src])
@@ -129,8 +164,8 @@ class TestIPv4(VppTestCase):
self.assertEqual(udp.sport, saved_packet[UDP].sport)
self.assertEqual(udp.dport, saved_packet[UDP].dport)
except:
- error("Unexpected or invalid packet:")
- error(packet.show())
+ self.logger.error("Unexpected or invalid packet:")
+ self.logger.error(packet.show())
raise
for i in self.interfaces:
remaining_packet = self.get_next_packet_info_for_interface2(
@@ -141,7 +176,14 @@ class TestIPv4(VppTestCase):
(dst_if.name, i.name))
def test_fib(self):
- """ IPv4 FIB test """
+ """ IPv4 FIB test
+
+ Test scenario:
+
+ - Create IPv4 stream for pg0 interface
+ - Create IPv4 tagged streams for pg1's and pg2's subinterface.
+ - Send and verify received packets on each interface.
+ """
pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes)
self.pg0.add_stream(pkts)
diff --git a/test/test_ip4_irb.py b/test/test_ip4_irb.py
index 412575dbd3c..cf2bb150b90 100644
--- a/test/test_ip4_irb.py
+++ b/test/test_ip4_irb.py
@@ -1,39 +1,51 @@
#!/usr/bin/env python
+"""IRB Test Case HLD:
+
+**config**
+ - L2 MAC learning enabled in l2bd
+ - 2 routed interfaces untagged, bvi (Bridge Virtual Interface)
+ - 2 bridged interfaces in l2bd with bvi
+
+**test**
+ - sending ip4 eth pkts between routed interfaces
+ - 2 routed interfaces
+ - 2 bridged interfaces
+
+ - 64B, 512B, 1518B, 9200B (ether_size)
+
+ - burst of pkts per interface
+ - 257pkts per burst
+ - routed pkts hitting different FIB entries
+ - bridged pkts hitting different MAC entries
+
+**verify**
+ - all packets received correctly
+
+"""
+
import unittest
-from random import choice, randint
+from random import choice
from scapy.packet import Raw
from scapy.layers.l2 import Ether
from scapy.layers.inet import IP, UDP
-from logging import *
from framework import VppTestCase, VppTestRunner
-""" IRB Test Case
-
-config
- L2 MAC learning enabled in l2bd
- 2 routed interfaces untagged, bvi
- 2 bridged interfaces in l2bd with bvi
-test
- sending ip4 eth pkts between routed interfaces
- 2 routed interfaces
- 2 bridged interfaces
- 64B, 512B, 1518B, 9200B (ether_size)
- burst of pkts per interface
- 257pkts per burst
- routed pkts hitting different FIB entries
- bridged pkts hitting different MAC entries
-verify
- all packets received correctly
-"""
-
class TestIpIrb(VppTestCase):
- """ IRB Test Case """
+ """IRB Test Case"""
@classmethod
def setUpClass(cls):
+ """
+ #. Create BD with MAC learning enabled and put interfaces to this BD.
+ #. Configure IPv4 addresses on loopback interface and routed interface.
+ #. Configure MAC address binding to IPv4 neighbors on loop0.
+ #. Configure MAC address on pg2.
+ #. Loopback BVI interface has remote hosts, one half of hosts are
+ behind pg0 second behind pg1.
+ """
super(TestIpIrb, cls).setUpClass()
cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes
@@ -58,27 +70,34 @@ class TestIpIrb(VppTestCase):
cls.vapi.sw_interface_set_l2_bridge(
cls.pg1.sw_if_index, bd_id=cls.bd_id)
+ # Configure IPv4 addresses on loopback interface and routed interface
cls.loop0.config_ip4()
cls.pg2.config_ip4()
- # configure MAC address binding to IPv4 neighbors on loop0
+ # Configure MAC address binding to IPv4 neighbors on loop0
cls.loop0.generate_remote_hosts(cls.remote_hosts_count)
- cls.loop0.configure_extend_ipv4_mac_binding()
+ cls.loop0.configure_ipv4_neighbors()
# configure MAC address on pg2
cls.pg2.resolve_arp()
- # one half of hosts are behind pg0 second behind pg1
+ # Loopback BVI interface has remote hosts, one half of hosts are behind
+ # pg0 second behind pg1
half = cls.remote_hosts_count // 2
cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half]
cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:]
def tearDown(self):
+ """Run standard test teardown and log ``show l2patch``,
+ ``show l2fib verbose``,``show bridge-domain <bd_id> detail``,
+ ``show ip arp``.
+ """
super(TestIpIrb, self).tearDown()
if not self.vpp_dead:
- info(self.vapi.cli("show l2patch"))
- info(self.vapi.cli("show l2fib verbose"))
- info(self.vapi.cli("show bridge-domain %s detail" % self.bd_id))
- info(self.vapi.cli("show ip arp"))
+ self.logger.info(self.vapi.cli("show l2patch"))
+ self.logger.info(self.vapi.cli("show l2fib verbose"))
+ self.logger.info(self.vapi.cli("show bridge-domain %s detail" %
+ self.bd_id))
+ self.logger.info(self.vapi.cli("show ip arp"))
def create_stream(self, src_ip_if, dst_ip_if, packet_sizes):
pkts = []
@@ -200,8 +219,8 @@ class TestIpIrb(VppTestCase):
""" IPv4 IRB test 1
Test scenario:
- ip traffic from pg2 interface must ends in both pg0 and pg1
- - arp entry present in loop0 interface for dst IP
+ - ip traffic from pg2 interface must ends in both pg0 and pg1
+ - arp entry present in loop0 interface for destination IP
- no l2 entree configured, pg0 and pg1 are same
"""
@@ -224,7 +243,7 @@ class TestIpIrb(VppTestCase):
""" IPv4 IRB test 2
Test scenario:
- ip traffic from pg0 and pg1 ends on pg2
+ - ip traffic from pg0 and pg1 ends on pg2
"""
stream1 = self.create_stream_l2_to_ip(
diff --git a/test/test_ip6.py b/test/test_ip6.py
index 92bb350d1b9..bff829b7015 100644
--- a/test/test_ip6.py
+++ b/test/test_ip6.py
@@ -2,14 +2,13 @@
import unittest
import socket
-from logging import *
from framework import VppTestCase, VppTestRunner
-from vpp_sub_interface import VppSubInterface, VppDot1QSubint, VppDot1ADSubint
+from vpp_sub_interface import VppSubInterface, VppDot1QSubint
from scapy.packet import Raw
from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet6 import ICMPv6ND_NS, IPv6, UDP
+from scapy.layers.inet6 import IPv6, UDP
class TestIPv6(VppTestCase):
@@ -20,6 +19,26 @@ class TestIPv6(VppTestCase):
super(TestIPv6, cls).setUpClass()
def setUp(self):
+ """
+ Perform test setup before test case.
+
+ **Config:**
+ - create 3 pg interfaces
+ - untagged pg0 interface
+ - Dot1Q subinterface on pg1
+ - Dot1AD subinterface on pg2
+ - setup interfaces:
+ - put it into UP state
+ - set IPv6 addresses
+ - resolve neighbor address using NDP
+ - configure 200 fib entries
+
+ :ivar list interfaces: pg interfaces and subinterfaces.
+ :ivar dict flows: IPv4 packet flows in test.
+ :ivar list pg_if_packet_sizes: packet sizes in test.
+
+ *TODO:* Create AD sub interface
+ """
super(TestIPv6, self).setUp()
# create 3 pg interfaces
@@ -28,8 +47,9 @@ class TestIPv6(VppTestCase):
# create 2 subinterfaces for p1 and pg2
self.sub_interfaces = [
VppDot1QSubint(self, self.pg1, 100),
- VppDot1QSubint(self, self.pg2, 200)]
+ VppDot1QSubint(self, self.pg2, 200)
# TODO: VppDot1ADSubint(self, self.pg2, 200, 300, 400)
+ ]
# packet flows mapping pg0 -> pg1.sub, pg2.sub, etc.
self.flows = dict()
@@ -50,16 +70,26 @@ class TestIPv6(VppTestCase):
i.config_ip6()
i.resolve_ndp()
- # config 2M FIB enries
+ # config 2M FIB entries
self.config_fib_entries(200)
def tearDown(self):
+ """Run standard test teardown and log ``show ip6 neighbors``."""
super(TestIPv6, self).tearDown()
if not self.vpp_dead:
- info(self.vapi.cli("show ip6 neighbors"))
+ self.logger.info(self.vapi.cli("show ip6 neighbors"))
# info(self.vapi.cli("show ip6 fib")) # many entries
def config_fib_entries(self, count):
+ """For each interface add to the FIB table *count* routes to
+ "fd02::1/128" destination with interface's local address as next-hop
+ address.
+
+ :param int count: Number of FIB entries.
+
+ - *TODO:* check if the next-hop address shouldn't be remote address
+ instead of local address.
+ """
n_int = len(self.interfaces)
percent = 0
counter = 0.0
@@ -70,13 +100,18 @@ class TestIPv6(VppTestCase):
for j in range(count / n_int):
self.vapi.ip_add_del_route(
dest_addr, dest_addr_len, next_hop_address, is_ipv6=1)
- counter = counter + 1
+ counter += 1
if counter / count * 100 > percent:
- info("Configure %d FIB entries .. %d%% done" %
+ self.logger.info("Configure %d FIB entries .. %d%% done" %
(count, percent))
- percent = percent + 1
+ percent += 1
def create_stream(self, src_if, packet_sizes):
+ """Create input packet stream for defined interface.
+
+ :param VppInterface src_if: Interface to create packet stream for.
+ :param list packet_sizes: Required packet sizes.
+ """
pkts = []
for i in range(0, 257):
dst_if = self.flows[src_if][i % 2]
@@ -96,7 +131,13 @@ class TestIPv6(VppTestCase):
return pkts
def verify_capture(self, dst_if, capture):
- info("Verifying capture on interface %s" % dst_if.name)
+ """Verify captured input packet stream for defined interface.
+
+ :param VppInterface dst_if: Interface to verify captured packet stream
+ for.
+ :param list capture: Captured packet stream.
+ """
+ self.logger.info("Verifying capture on interface %s" % dst_if.name)
last_info = dict()
for i in self.interfaces:
last_info[i.sw_if_index] = None
@@ -115,8 +156,8 @@ class TestIPv6(VppTestCase):
payload_info = self.payload_to_info(str(packet[Raw]))
packet_index = payload_info.index
self.assertEqual(payload_info.dst, dst_sw_if_index)
- debug("Got packet on port %s: src=%u (id=%u)" %
- (dst_if.name, payload_info.src, packet_index))
+ self.logger.debug("Got packet on port %s: src=%u (id=%u)" %
+ (dst_if.name, payload_info.src, packet_index))
next_info = self.get_next_packet_info_for_interface2(
payload_info.src, dst_sw_if_index,
last_info[payload_info.src])
@@ -130,8 +171,8 @@ class TestIPv6(VppTestCase):
self.assertEqual(udp.sport, saved_packet[UDP].sport)
self.assertEqual(udp.dport, saved_packet[UDP].dport)
except:
- error("Unexpected or invalid packet:")
- error(packet.show())
+ self.logger.error("Unexpected or invalid packet:")
+ self.logger.error(packet.show())
raise
for i in self.interfaces:
remaining_packet = self.get_next_packet_info_for_interface2(
@@ -142,7 +183,13 @@ class TestIPv6(VppTestCase):
(dst_if.name, i.name))
def test_fib(self):
- """ IPv6 FIB test """
+ """ IPv6 FIB test
+
+ Test scenario:
+ - Create IPv6 stream for pg0 interface
+ - Create IPv6 tagged streams for pg1's and pg2's subinterface.
+ - Send and verify received packets on each interface.
+ """
pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes)
self.pg0.add_stream(pkts)
diff --git a/test/vpp_interface.py b/test/vpp_interface.py
index d74248a39b3..30ef8ae7a0a 100644
--- a/test/vpp_interface.py
+++ b/test/vpp_interface.py
@@ -6,59 +6,57 @@ from util import Host
class VppInterface(object):
- """
- Generic VPP interface
- """
+ """Generic VPP interface."""
__metaclass__ = ABCMeta
@property
def sw_if_index(self):
- """Interface index assigned by VPP"""
+ """Interface index assigned by VPP."""
return self._sw_if_index
@property
def remote_mac(self):
- """MAC-address of the remote interface "connected" to this interface"""
+ """MAC-address of the remote interface "connected" to this interface."""
return self._remote_hosts[0].mac
@property
def local_mac(self):
- """MAC-address of the VPP interface"""
+ """MAC-address of the VPP interface."""
return self._local_mac
@property
def local_ip4(self):
- """Local IPv4 address on VPP interface (string)"""
+ """Local IPv4 address on VPP interface (string)."""
return self._local_ip4
@property
def local_ip4n(self):
- """Local IPv4 address - raw, suitable as API parameter"""
+ """Local IPv4 address - raw, suitable as API parameter."""
return socket.inet_pton(socket.AF_INET, self._local_ip4)
@property
def remote_ip4(self):
- """IPv4 address of remote peer "connected" to this interface"""
+ """IPv4 address of remote peer "connected" to this interface."""
return self._remote_hosts[0].ip4
@property
def remote_ip4n(self):
- """IPv4 address of remote peer - raw, suitable as API parameter"""
+ """IPv4 address of remote peer - raw, suitable as API parameter."""
return socket.inet_pton(socket.AF_INET, self.remote_ip4)
@property
def local_ip6(self):
- """Local IPv6 address on VPP interface (string)"""
+ """Local IPv6 address on VPP interface (string)."""
return self._local_ip6
@property
def local_ip6n(self):
- """Local IPv6 address - raw, suitable as API parameter"""
+ """Local IPv6 address - raw, suitable as API parameter."""
return socket.inet_pton(socket.AF_INET6, self.local_ip6)
@property
def remote_ip6(self):
- """IPv6 address of remote peer "connected" to this interface"""
+ """IPv6 address of remote peer "connected" to this interface."""
return self._remote_hosts[0].ip6
@property
@@ -68,17 +66,17 @@ class VppInterface(object):
@property
def name(self):
- """Name of the interface"""
+ """Name of the interface."""
return self._name
@property
def dump(self):
- """Raw result of sw_interface_dump for this interface"""
+ """RAW result of sw_interface_dump for this interface."""
return self._dump
@property
def test(self):
- """Test case creating this interface"""
+ """Test case creating this interface."""
return self._test
@property
@@ -88,20 +86,44 @@ class VppInterface(object):
@remote_hosts.setter
def remote_hosts(self, value):
+ """
+ :param list value: List of remote hosts.
+ """
self._remote_hosts = value
- #TODO: set hosts_by dicts
+ self._hosts_by_mac = {}
+ self._hosts_by_ip4 = {}
+ self._hosts_by_ip6 = {}
+ for host in self._remote_hosts:
+ self._hosts_by_mac[host.mac] = host
+ self._hosts_by_ip4[host.ip4] = host
+ self._hosts_by_ip6[host.ip6] = host
def host_by_mac(self, mac):
+ """
+ :param ip: MAC address to find host by.
+ :return: Host object assigned to interface.
+ """
return self._hosts_by_mac[mac]
def host_by_ip4(self, ip):
+ """
+ :param ip: IPv4 address to find host by.
+ :return: Host object assigned to interface.
+ """
return self._hosts_by_ip4[ip]
def host_by_ip6(self, ip):
+ """
+ :param ip: IPv6 address to find host by.
+ :return: Host object assigned to interface.
+ """
return self._hosts_by_ip6[ip]
def generate_remote_hosts(self, count=1):
- """Generate and add remote hosts for the interface."""
+ """Generate and add remote hosts for the interface.
+
+ :param int count: Number of generated remote hosts.
+ """
self._remote_hosts = []
self._hosts_by_mac = {}
self._hosts_by_ip4 = {}
@@ -117,7 +139,7 @@ class VppInterface(object):
self._hosts_by_ip6[ip6] = host
def post_init_setup(self):
- """Additional setup run after creating an interface object"""
+ """Additional setup run after creating an interface object."""
self.generate_remote_hosts()
@@ -149,21 +171,21 @@ class VppInterface(object):
(self.__name__, self.remote_mac, self.remote_ip4, self.local_ip4))
def config_ip4(self):
- """Configure IPv4 address on the VPP interface"""
+ """Configure IPv4 address on the VPP interface."""
addr = self.local_ip4n
addr_len = 24
self.test.vapi.sw_interface_add_del_address(
self.sw_if_index, addr, addr_len)
- def configure_extend_ipv4_mac_binding(self):
- """Configure neighbor MAC to IPv4 addresses."""
+ def configure_ipv4_neighbors(self):
+ """For every remote host assign neighbor's MAC to IPv4 addresses."""
for host in self._remote_hosts:
macn = host.mac.replace(":", "").decode('hex')
ipn = host.ip4n
self.test.vapi.ip_neighbor_add_del(self.sw_if_index, macn, ipn)
def config_ip6(self):
- """Configure IPv6 address on the VPP interface"""
+ """Configure IPv6 address on the VPP interface."""
addr = self._local_ip6n
addr_len = 64
self.test.vapi.sw_interface_add_del_address(
@@ -171,30 +193,31 @@ class VppInterface(object):
def set_table_ip4(self, table_id):
"""Set the interface in a IPv4 Table.
- Must be called before configuring IP4 addresses"""
+
+ .. note:: Must be called before configuring IP4 addresses."""
self.test.vapi.sw_interface_set_table(
self.sw_if_index, 0, table_id)
def set_table_ip6(self, table_id):
"""Set the interface in a IPv6 Table.
- Must be called before configuring IP6 addresses"""
+
+ .. note:: Must be called before configuring IP6 addresses.
+ """
self.test.vapi.sw_interface_set_table(
self.sw_if_index, 1, table_id)
def disable_ipv6_ra(self):
- """Configure IPv6 RA suppress on the VPP interface"""
+ """Configure IPv6 RA suppress on the VPP interface."""
self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
def admin_up(self):
- """ Put interface ADMIN-UP """
+ """Put interface ADMIN-UP."""
self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
def add_sub_if(self, sub_if):
- """
- Register a sub-interface with this interface
+ """Register a sub-interface with this interface.
:param sub_if: sub-interface
-
"""
if not hasattr(self, 'sub_if'):
self.sub_if = sub_if
@@ -205,6 +228,6 @@ class VppInterface(object):
self.sub_if = sub_if
def enable_mpls(self):
- """Enable MPLS on the VPP interface"""
+ """Enable MPLS on the VPP interface."""
self.test.vapi.sw_interface_enable_disable_mpls(
self.sw_if_index)
diff --git a/test/vpp_lo_interface.py b/test/vpp_lo_interface.py
index ed9ac725db5..ef8152513ac 100644
--- a/test/vpp_lo_interface.py
+++ b/test/vpp_lo_interface.py
@@ -3,9 +3,7 @@ from vpp_interface import VppInterface
class VppLoInterface(VppInterface):
- """
- VPP loopback interface
- """
+ """VPP loopback interface."""
def __init__(self, test, lo_index):
""" Create VPP loopback interface """