vpp/test/test_lisp.py
Klement Sekera d9b0c6fbf7 tests: replace pycodestyle with black
Drop pycodestyle for code style checking in favor of black. Black is
much faster, stable PEP8 compliant code style checker offering also
automatic formatting. It aims to be very stable and produce smallest
diffs. It's used by many small and big projects.

Running checkstyle with black takes a few seconds with a terse output.
Thus, test-checkstyle-diff is no longer necessary.

Expand scope of checkstyle to all python files in the repo, replacing
test-checkstyle with checkstyle-python.

Also, fixstyle-python is now available for automatic style formatting.

Note: python virtualenv has been consolidated in test/Makefile,
test/requirements*.txt which will eventually be moved to a central
location.  This is required to simply the automated generation of
docker executor images in the CI.

Type: improvement
Change-Id: I022a326603485f58585e879ac0f697fceefbc9c8
Signed-off-by: Klement Sekera <klement.sekera@gmail.com>
Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
2022-05-10 18:52:08 +00:00

231 lines
6.7 KiB
Python

#!/usr/bin/env python3
import abc
import unittest
from scapy.fields import BitField, ByteField, FlagsField, IntField
from scapy.packet import bind_layers, Packet, Raw
from scapy.layers.inet import IP, UDP, Ether
from scapy.layers.inet6 import IPv6
from framework import VppTestCase, VppTestRunner
from lisp import (
VppLocalMapping,
VppLispAdjacency,
VppLispLocator,
VppLispLocatorSet,
VppRemoteMapping,
LispRemoteLocator,
)
from util import ppp
# From py_lispnetworking.lisp.py: # GNU General Public License v2.0
class LISP_GPE_Header(Packet):
name = "LISP GPE Header"
fields_desc = [
FlagsField("gpe_flags", None, 6, ["N", "L", "E", "V", "I", "P"]),
BitField("reserved", 0, 18),
ByteField("next_proto", 0),
IntField("iid", 0),
]
bind_layers(UDP, LISP_GPE_Header, dport=4341)
bind_layers(UDP, LISP_GPE_Header, sport=4341)
bind_layers(LISP_GPE_Header, IP, next_proto=1)
bind_layers(LISP_GPE_Header, IPv6, next_proto=2)
bind_layers(LISP_GPE_Header, Ether, next_proto=3)
class ForeignAddressFactory(object):
count = 0
prefix_len = 24
net_template = "10.10.10.{}"
net = net_template.format(0) + "/" + str(prefix_len)
def get_ip4(self):
if self.count > 255:
raise Exception("Network host address exhaustion")
self.count += 1
return self.net_template.format(self.count)
class Driver(metaclass=abc.ABCMeta):
config_order = [
"locator-sets",
"locators",
"local-mappings",
"remote-mappings",
"adjacencies",
]
""" Basic class for data driven testing """
def __init__(self, test, test_cases):
self._test_cases = test_cases
self._test = test
@property
def test_cases(self):
return self._test_cases
@property
def test(self):
return self._test
def create_packet(self, src_if, dst_if, deid, payload=""):
"""
Create IPv4 packet
param: src_if
param: dst_if
"""
packet = (
Ether(dst=src_if.local_mac, src=src_if.remote_mac)
/ IP(src=src_if.remote_ip4, dst=deid)
/ Raw(payload)
)
return packet
@abc.abstractmethod
def run(self):
"""testing procedure"""
pass
class SimpleDriver(Driver):
"""Implements simple test procedure"""
def __init__(self, test, test_cases):
super(SimpleDriver, self).__init__(test, test_cases)
def verify_capture(self, src_loc, dst_loc, capture):
"""
Verify captured packet
:param src_loc: source locator address
:param dst_loc: destination locator address
:param capture: list of captured packets
"""
self.test.assertEqual(
len(capture),
1,
"Unexpected number of "
"packets! Expected 1 but {} received".format(len(capture)),
)
packet = capture[0]
try:
ip_hdr = packet[IP]
# assert the values match
self.test.assertEqual(ip_hdr.src, src_loc, "IP source address")
self.test.assertEqual(ip_hdr.dst, dst_loc, "IP destination address")
gpe_hdr = packet[LISP_GPE_Header]
self.test.assertEqual(gpe_hdr.next_proto, 1, "next_proto is not ipv4!")
ih = gpe_hdr[IP]
self.test.assertEqual(
ih.src, self.test.pg0.remote_ip4, "unexpected source EID!"
)
self.test.assertEqual(ih.dst, self.test.deid_ip4, "unexpected dest EID!")
except:
self.test.logger.error(ppp("Unexpected or invalid packet:", packet))
raise
def configure_tc(self, tc):
for config_item in self.config_order:
for vpp_object in tc[config_item]:
vpp_object.add_vpp_config()
def run(self, dest):
"""Send traffic for each test case and verify that it
is encapsulated"""
for tc in enumerate(self.test_cases):
self.test.logger.info("Running {}".format(tc[1]["name"]))
self.configure_tc(tc[1])
packet = self.create_packet(self.test.pg0, self.test.pg1, dest, "data")
self.test.pg0.add_stream(packet)
self.test.pg0.enable_capture()
self.test.pg1.enable_capture()
self.test.pg_start()
capture = self.test.pg1.get_capture(1)
self.verify_capture(
self.test.pg1.local_ip4, self.test.pg1.remote_ip4, capture
)
self.test.pg0.assert_nothing_captured()
class TestLisp(VppTestCase):
"""Basic LISP test"""
@classmethod
def setUpClass(cls):
super(TestLisp, cls).setUpClass()
cls.faf = ForeignAddressFactory()
cls.create_pg_interfaces(range(2)) # create pg0 and pg1
for i in cls.pg_interfaces:
i.admin_up() # put the interface upsrc_if
i.config_ip4() # configure IPv4 address on the interface
i.resolve_arp() # resolve ARP, so that we know VPP MAC
@classmethod
def tearDownClass(cls):
super(TestLisp, cls).tearDownClass()
def setUp(self):
super(TestLisp, self).setUp()
self.vapi.lisp_enable_disable(is_enable=1)
def test_lisp_basic_encap(self):
"""Test case for basic encapsulation"""
self.deid_ip4_net = self.faf.net
self.deid_ip4 = self.faf.get_ip4()
self.seid_ip4 = "{!s}/{!s}".format(self.pg0.local_ip4, 32)
self.rloc_ip4 = self.pg1.remote_ip4
test_cases = [
{
"name": "basic ip4 over ip4",
"locator-sets": [VppLispLocatorSet(self, "ls-4o4")],
"locators": [VppLispLocator(self, self.pg1.sw_if_index, "ls-4o4")],
"local-mappings": [VppLocalMapping(self, self.seid_ip4, "ls-4o4")],
"remote-mappings": [
VppRemoteMapping(
self, self.deid_ip4_net, [LispRemoteLocator(self.rloc_ip4)]
)
],
"adjacencies": [
VppLispAdjacency(self, self.seid_ip4, self.deid_ip4_net)
],
}
]
self.test_driver = SimpleDriver(self, test_cases)
self.test_driver.run(self.deid_ip4)
class TestLispUT(VppTestCase):
"""Lisp UT"""
@classmethod
def setUpClass(cls):
super(TestLispUT, cls).setUpClass()
@classmethod
def tearDownClass(cls):
super(TestLispUT, cls).tearDownClass()
def test_fib(self):
"""LISP Unit Tests"""
error = self.vapi.cli("test lisp cp")
if error:
self.logger.critical(error)
self.assertNotIn("Failed", error)
if __name__ == "__main__":
unittest.main(testRunner=VppTestRunner)