aboutsummaryrefslogtreecommitdiffstats
path: root/test/doc
diff options
context:
space:
mode:
authorKlement Sekera <ksekera@cisco.com>2016-10-28 13:20:27 +0200
committerDamjan Marion <dmarion.lists@gmail.com>2016-10-31 23:48:25 +0000
commit277b89c946e6fdc764ee48726fcd3df1c189eda9 (patch)
tree1ced5e4a47a00290251e89929df0945ae64370c8 /test/doc
parentcede3798b7f3c35cab2a8268c584fd22bf3a34f6 (diff)
add vpp debugging support to test framework
improve test documentation Change-Id: Ia9678aa2532ecb4cb33736aedb4a31aa3f2a3f93 Signed-off-by: Klement Sekera <ksekera@cisco.com>
Diffstat (limited to 'test/doc')
-rw-r--r--test/doc/Makefile188
-rw-r--r--test/doc/conf.py1
2 files changed, 102 insertions, 87 deletions
diff --git a/test/doc/Makefile b/test/doc/Makefile
index 00655389e94..809abef846e 100644
--- a/test/doc/Makefile
+++ b/test/doc/Makefile
@@ -3,20 +3,34 @@
# You can set these variables from the command line.
SPHINXOPTS =
-SPHINXBUILD = sphinx-build
+SRC_DOC_DIR = $(WS_ROOT)/test/doc
+SPHINXBUILD = sphinx-build
PAPER =
-BUILDDIR = _build
+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 $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+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
+verify-virtualenv:
+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:
- sphinx-apidoc -o . ..
+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:
@@ -48,182 +62,182 @@ help:
@echo " coverage to run coverage check of the documentation (if enabled)"
@echo " dummy to check syntax errors of document sources"
-.PHONY: clean
-clean:
- rm -rf $(BUILDDIR)/*
+.PHONY: wipe
+wipe:
+ rm -rf $(BUILD_DOC_ROOT)
.PHONY: html
-html: regen-api-doc
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+html: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/html
@echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+ @echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/html."
.PHONY: dirhtml
-dirhtml: regen-api-doc
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+dirhtml: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/dirhtml
@echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+ @echo "Build finished. The HTML pages are in $(BUILD_DOC_DIR)/dirhtml."
.PHONY: singlehtml
-singlehtml: regen-api-doc
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+singlehtml: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/singlehtml
@echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+ @echo "Build finished. The HTML page is in $(BUILD_DOC_DIR)/singlehtml."
.PHONY: pickle
-pickle: regen-api-doc
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+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: regen-api-doc
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+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: regen-api-doc
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+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 $(BUILDDIR)/htmlhelp."
+ ".hhp project file in $(BUILD_DOC_DIR)/htmlhelp."
.PHONY: qthelp
-qthelp: regen-api-doc
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+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" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/VPPtestframework.qhcp"
+ ".qhcp project file in $(BUILD_DOC_DIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILD_DOC_DIR)/qthelp/VPPtestframework.qhcp"
@echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/VPPtestframework.qhc"
+ @echo "# assistant -collectionFile $(BUILD_DOC_DIR)/qthelp/VPPtestframework.qhc"
.PHONY: applehelp
-applehelp: regen-api-doc
- $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
+applehelp: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/applehelp
@echo
- @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
+ @echo "Build finished. The help book is in $(BUILD_DOC_DIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
-devhelp: regen-api-doc
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+devhelp: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/VPPtestframework"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/VPPtestframework"
+ @echo "# ln -s $(BUILD_DOC_DIR)/devhelp $$HOME/.local/share/devhelp/VPPtestframework"
@echo "# devhelp"
.PHONY: epub
-epub: regen-api-doc
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+epub: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/epub
@echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+ @echo "Build finished. The epub file is in $(BUILD_DOC_DIR)/epub."
.PHONY: epub3
epub3:
- $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
+ $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/epub3
@echo
- @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
+ @echo "Build finished. The epub3 file is in $(BUILD_DOC_DIR)/epub3."
.PHONY: latex
-latex: regen-api-doc
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+latex: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Build finished; the LaTeX files are in $(BUILD_DOC_DIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
-latexpdf: regen-api-doc
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+latexpdf: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+ $(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex."
.PHONY: latexpdfja
-latexpdfja: regen-api-doc
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+latexpdfja: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+ $(MAKE) -C $(BUILD_DOC_DIR)/latex all-pdf-ja
+ @echo "pdflatex finished; the PDF files are in $(BUILD_DOC_DIR)/latex."
.PHONY: text
-text: regen-api-doc
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+text: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/text
@echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
+ @echo "Build finished. The text files are in $(BUILD_DOC_DIR)/text."
.PHONY: man
-man: regen-api-doc
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+man: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/man
@echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+ @echo "Build finished. The manual pages are in $(BUILD_DOC_DIR)/man."
.PHONY: texinfo
-texinfo: regen-api-doc
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+texinfo: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo
@echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Build finished. The Texinfo files are in $(BUILD_DOC_DIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info
-info: regen-api-doc
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+info: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+ make -C $(BUILD_DOC_DIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILD_DOC_DIR)/texinfo."
.PHONY: gettext
-gettext: regen-api-doc
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+gettext: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILD_DOC_DIR)/locale
@echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+ @echo "Build finished. The message catalogs are in $(BUILD_DOC_DIR)/locale."
.PHONY: changes
-changes: regen-api-doc
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+changes: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/changes
@echo
- @echo "The overview file is in $(BUILDDIR)/changes."
+ @echo "The overview file is in $(BUILD_DOC_DIR)/changes."
.PHONY: linkcheck
-linkcheck: regen-api-doc
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+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 $(BUILDDIR)/linkcheck/output.txt."
+ "or in $(BUILD_DOC_DIR)/linkcheck/output.txt."
.PHONY: doctest
-doctest: regen-api-doc
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+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 $(BUILDDIR)/doctest/output.txt."
+ "results in $(BUILD_DOC_DIR)/doctest/output.txt."
.PHONY: coverage
-coverage: regen-api-doc
- $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
+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 $(BUILDDIR)/coverage/python.txt."
+ "results in $(BUILD_DOC_DIR)/coverage/python.txt."
.PHONY: xml
-xml: regen-api-doc
- $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+xml: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/xml
@echo
- @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+ @echo "Build finished. The XML files are in $(BUILD_DOC_DIR)/xml."
.PHONY: pseudoxml
-pseudoxml: regen-api-doc
- $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+pseudoxml: regen-api-doc verify-virtualenv
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILD_DOC_DIR)/pseudoxml
@echo
- @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+ @echo "Build finished. The pseudo-XML files are in $(BUILD_DOC_DIR)/pseudoxml."
.PHONY: dummy
-dummy: regen-api-doc
- $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
+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/conf.py b/test/doc/conf.py
index aa8417149df..cec9ddee4b4 100644
--- a/test/doc/conf.py
+++ b/test/doc/conf.py
@@ -20,6 +20,7 @@ import os
import sys
sys.path.insert(0, os.path.abspath('..'))
+
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
rt IP, UDP from scapy.layers.inet6 import IPv6 from scapy.contrib.mpls import MPLS from vpp_papi import VppEnum from vpp_qos import VppQosRecord, VppQosEgressMap, VppQosMark, VppQosStore NUM_PKTS = 67 class TestQOS(VppTestCase): """ QOS Test Case """ # Note: Since the enums aren't created dynamically until after # the papi client attaches to VPP, we put it in a property to # ensure it is the value at runtime, not at module load time. @property def QOS_SOURCE(self): return VppEnum.vl_api_qos_source_t @classmethod def setUpClass(cls): super(TestQOS, cls).setUpClass() @classmethod def tearDownClass(cls): super(TestQOS, cls).tearDownClass() def setUp(self): super(TestQOS, self).setUp() self.create_pg_interfaces(range(5)) tbl = VppMplsTable(self, 0) tbl.add_vpp_config() for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.resolve_arp() i.config_ip6() i.resolve_ndp() i.enable_mpls() def tearDown(self): for i in self.pg_interfaces: i.unconfig_ip4() i.unconfig_ip6() i.disable_mpls() super(TestQOS, self).tearDown() def test_qos_ip(self): """ QoS Mark/Record/Store IP """ # # for table 1 map the n=0xff possible values of input QoS mark, # n to 1-n # output = [scapy.compat.chb(0)] * 256 for i in range(0, 255): output[i] = scapy.compat.chb(255 - i) os = b''.join(output) rows = [{'outputs': os}, {'outputs': os}, {'outputs': os}, {'outputs': os}] qem1 = VppQosEgressMap(self, 1, rows).add_vpp_config() # # For table 2 (and up) use the value n for everything # output = [scapy.compat.chb(2)] * 256 os = b''.join(output) rows = [{'outputs': os}, {'outputs': os}, {'outputs': os}, {'outputs': os}] qem2 = VppQosEgressMap(self, 2, rows).add_vpp_config() output = [scapy.compat.chb(3)] * 256 os = b''.join(output) rows = [{'outputs': os}, {'outputs': os}, {'outputs': os}, {'outputs': os}] qem3 = VppQosEgressMap(self, 3, rows).add_vpp_config() output = [scapy.compat.chb(4)] * 256 os = b''.join(output) rows = [{'outputs': os}, {'outputs': os}, {'outputs': os}, {'outputs': os}] qem4 = VppQosEgressMap(self, 4, rows).add_vpp_config() qem5 = VppQosEgressMap(self, 5, rows).add_vpp_config() qem6 = VppQosEgressMap(self, 6, rows).add_vpp_config() qem7 = VppQosEgressMap(self, 7, rows).add_vpp_config() self.assertTrue(qem7.query_vpp_config()) self.logger.info(self.vapi.cli("sh qos eg map")) # # Bind interface pgN to table n # qm1 = VppQosMark(self, self.pg1, qem1, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() qm2 = VppQosMark(self, self.pg2, qem2, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() qm3 = VppQosMark(self, self.pg3, qem3, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() qm4 = VppQosMark(self, self.pg4, qem4, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() self.assertTrue(qm3.query_vpp_config()) self.logger.info(self.vapi.cli("sh qos mark")) # # packets ingress on Pg0 # p_v4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_v6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6, tc=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) # # Since we have not yet enabled the recording of the input QoS # from the input iP header, the egress packet's ToS will be unchanged # rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) rx = self.send_and_expect(self.pg0, p_v6 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 1) # # Enable QoS recording on IP input for pg0 # qr1 = VppQosRecord(self, self.pg0, self.QOS_SOURCE.QOS_API_SOURCE_IP) qr1.add_vpp_config() self.logger.info(self.vapi.cli("sh qos record")) # # send the same packets, this time expect the input TOS of 1 # to be mapped to pg1's egress value of 254 # rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) rx = self.send_and_expect(self.pg0, p_v6 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 254) # # different input ToS to test the mapping # p_v4[IP].tos = 127 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 128) p_v6[IPv6].tc = 127 rx = self.send_and_expect(self.pg0, p_v6 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 128) p_v4[IP].tos = 254 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) p_v6[IPv6].tc = 254 rx = self.send_and_expect(self.pg0, p_v6 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 1) # # send packets out the other interfaces to test the maps are # correctly applied # p_v4[IP].dst = self.pg2.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg2) for p in rx: self.assertEqual(p[IP].tos, 2) p_v4[IP].dst = self.pg3.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg3) for p in rx: self.assertEqual(p[IP].tos, 3) p_v6[IPv6].dst = self.pg3.remote_ip6 rx = self.send_and_expect(self.pg0, p_v6 * NUM_PKTS, self.pg3) for p in rx: self.assertEqual(p[IPv6].tc, 3) # # remove the map on pg2 and pg3, now expect an unchanged IP tos # qm2.remove_vpp_config() qm3.remove_vpp_config() self.logger.info(self.vapi.cli("sh qos mark")) self.assertFalse(qm3.query_vpp_config()) self.logger.info(self.vapi.cli("sh int feat pg2")) p_v4[IP].dst = self.pg2.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg2) for p in rx: self.assertEqual(p[IP].tos, 254) p_v4[IP].dst = self.pg3.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg3) for p in rx: self.assertEqual(p[IP].tos, 254) # # still mapping out of pg1 # p_v4[IP].dst = self.pg1.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) # # disable the input recording on pg0 # self.assertTrue(qr1.query_vpp_config()) qr1.remove_vpp_config() # # back to an unchanged TOS value # rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) # # enable QoS stroe instead of record # qst1 = VppQosStore(self, self.pg0, self.QOS_SOURCE.QOS_API_SOURCE_IP, 5).add_vpp_config() self.logger.info(self.vapi.cli("sh qos store")) p_v4[IP].dst = self.pg1.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 250) # # disable the input storing on pg0 # self.assertTrue(qst1.query_vpp_config()) qst1.remove_vpp_config() # # back to an unchanged TOS value # rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) # # disable the egress map on pg1 and pg4 # qm1.remove_vpp_config() qm4.remove_vpp_config() # # unchanged Tos on pg1 # rx = self.send_and_expect(self.pg0, p_v4 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) def test_qos_mpls(self): """ QoS Mark/Record MPLS """ # # 255 QoS for all input values # from_ext = 7 from_ip = 6 from_mpls = 5 from_vlan = 4 output = [scapy.compat.chb(from_ext)] * 256 os1 = b''.join(output) output = [scapy.compat.chb(from_vlan)] * 256 os2 = b''.join(output) output = [scapy.compat.chb(from_mpls)] * 256 os3 = b''.join(output) output = [scapy.compat.chb(from_ip)] * 256 os4 = b''.join(output) rows = [{'outputs': os1}, {'outputs': os2}, {'outputs': os3}, {'outputs': os4}] qem1 = VppQosEgressMap(self, 1, rows).add_vpp_config() # # a route with 1 MPLS label # route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[32])]) route_10_0_0_1.add_vpp_config() # # a route with 3 MPLS labels # route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[63, 33, 34])]) route_10_0_0_3.add_vpp_config() # # enable IP QoS recording on the input Pg0 and MPLS egress marking # on Pg1 # qr1 = VppQosRecord(self, self.pg0, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() qm1 = VppQosMark(self, self.pg1, qem1, self.QOS_SOURCE.QOS_API_SOURCE_MPLS).add_vpp_config() # # packet that will get one label added and 3 labels added resp. # p_1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_3 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.3", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_1 * NUM_PKTS, self.pg1) # # only 3 bits of ToS value in MPLS make sure tos is correct # and the label and EOS bit have not been corrupted # for p in rx: self.assertEqual(p[MPLS].cos, from_ip) self.assertEqual(p[MPLS].label, 32) self.assertEqual(p[MPLS].s, 1) rx = self.send_and_expect(self.pg0, p_3 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[MPLS].cos, from_ip) self.assertEqual(p[MPLS].label, 63) self.assertEqual(p[MPLS].s, 0) h = p[MPLS].payload self.assertEqual(h[MPLS].cos, from_ip) self.assertEqual(h[MPLS].label, 33) self.assertEqual(h[MPLS].s, 0) h = h[MPLS].payload self.assertEqual(h[MPLS].cos, from_ip) self.assertEqual(h[MPLS].label, 34) self.assertEqual(h[MPLS].s, 1) # # enable MPLS QoS recording on the input Pg0 and IP egress marking # on Pg1 # qr2 = VppQosRecord( self, self.pg0, self.QOS_SOURCE.QOS_API_SOURCE_MPLS).add_vpp_config() qm2 = VppQosMark( self, self.pg1, qem1, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() # # MPLS x-connect - COS according to pg1 map # route_32_eos = VppMplsRoute(self, 32, 1, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(33)])]) route_32_eos.add_vpp_config() p_m1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=32, cos=3, ttl=2) / IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_m1 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[MPLS].cos, from_mpls) self.assertEqual(p[MPLS].label, 33) self.assertEqual(p[MPLS].s, 1) # # MPLS deag - COS is copied from MPLS to IP # route_33_eos = VppMplsRoute(self, 33, 1, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=0)]) route_33_eos.add_vpp_config() route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)]) route_10_0_0_4.add_vpp_config() p_m2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=33, ttl=2, cos=3) / IP(src=self.pg0.remote_ip4, dst="10.0.0.4", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_m2 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, from_mpls) def test_qos_vlan(self): """QoS mark/record VLAN """ # # QoS for all input values # output = [scapy.compat.chb(0)] * 256 for i in range(0, 255): output[i] = scapy.compat.chb(255 - i) os = b''.join(output) rows = [{'outputs': os}, {'outputs': os}, {'outputs': os}, {'outputs': os}] qem1 = VppQosEgressMap(self, 1, rows).add_vpp_config() sub_if = VppDot1QSubint(self, self.pg0, 11) sub_if.admin_up() sub_if.config_ip4() sub_if.resolve_arp() sub_if.config_ip6() sub_if.resolve_ndp() # # enable VLAN QoS recording/marking on the input Pg0 subinterface and # qr_v = VppQosRecord( self, sub_if, self.QOS_SOURCE.QOS_API_SOURCE_VLAN).add_vpp_config() qm_v = VppQosMark( self, sub_if, qem1, self.QOS_SOURCE.QOS_API_SOURCE_VLAN).add_vpp_config() # # IP marking/recording on pg1 # qr_ip = VppQosRecord( self, self.pg1, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() qm_ip = VppQosMark( self, self.pg1, qem1, self.QOS_SOURCE.QOS_API_SOURCE_IP).add_vpp_config() # # a routes to/from sub-interface # route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, [VppRoutePath(sub_if.remote_ip4, sub_if.sw_if_index)]) route_10_0_0_1.add_vpp_config() route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)]) route_10_0_0_2.add_vpp_config() route_2001_1 = VppIpRoute(self, "2001::1", 128, [VppRoutePath(sub_if.remote_ip6, sub_if.sw_if_index)]) route_2001_1.add_vpp_config() route_2001_2 = VppIpRoute(self, "2001::2", 128, [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index)]) route_2001_2.add_vpp_config() p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / Dot1Q(vlan=11, prio=1) / IP(src="1.1.1.1", dst="10.0.0.2", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="1.1.1.1", dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_v3 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / Dot1Q(vlan=11, prio=1, id=1) / IP(src="1.1.1.1", dst="10.0.0.2", tos=2) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg1, p_v2 * NUM_PKTS, self.pg0) for p in rx: self.assertEqual(p[Dot1Q].prio, 7) self.assertEqual(p[Dot1Q].id, 0) rx = self.send_and_expect(self.pg0, p_v3 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 252) rx = self.send_and_expect(self.pg0, p_v1 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 253) p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / Dot1Q(vlan=11, prio=2) / IPv6(src="2001::1", dst="2001::2", tc=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IPv6(src="3001::1", dst="2001::1", tc=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg1, p_v2 * NUM_PKTS, self.pg0) for p in rx: self.assertEqual(p[Dot1Q].prio, 7) self.assertEqual(p[Dot1Q].id, 0) rx = self.send_and_expect(self.pg0, p_v1 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 251) # # cleanup # sub_if.unconfig_ip4() sub_if.unconfig_ip6() if __name__ == '__main__': unittest.main(testRunner=VppTestRunner)