d9b0c6fbf7
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>
231 lines
6.7 KiB
Python
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)
|