diff options
Diffstat (limited to 'src/vnet')
22 files changed, 0 insertions, 10139 deletions
diff --git a/src/vnet/bfd/test/bfd.py b/src/vnet/bfd/test/bfd.py deleted file mode 100644 index 9d44425ec9f..00000000000 --- a/src/vnet/bfd/test/bfd.py +++ /dev/null @@ -1,423 +0,0 @@ -""" BFD protocol implementation """ - -from random import randint -from socket import AF_INET, AF_INET6, inet_pton -from scapy.all import bind_layers -from scapy.layers.inet import UDP -from scapy.packet import Packet -from scapy.fields import BitField, BitEnumField, XByteField, FlagsField,\ - ConditionalField, StrField -from vpp_object import VppObject -from util import NumericConstant -from vpp_papi import VppEnum - - -class BFDDiagCode(NumericConstant): - """ BFD Diagnostic Code """ - no_diagnostic = 0 - control_detection_time_expired = 1 - echo_function_failed = 2 - neighbor_signaled_session_down = 3 - forwarding_plane_reset = 4 - path_down = 5 - concatenated_path_down = 6 - administratively_down = 7 - reverse_concatenated_path_down = 8 - - desc_dict = { - no_diagnostic: "No diagnostic", - control_detection_time_expired: "Control Detection Time Expired", - echo_function_failed: "Echo Function Failed", - neighbor_signaled_session_down: "Neighbor Signaled Session Down", - forwarding_plane_reset: "Forwarding Plane Reset", - path_down: "Path Down", - concatenated_path_down: "Concatenated Path Down", - administratively_down: "Administratively Down", - reverse_concatenated_path_down: "Reverse Concatenated Path Down", - } - - -class BFDState(NumericConstant): - """ BFD State """ - admin_down = 0 - down = 1 - init = 2 - up = 3 - - desc_dict = { - admin_down: "AdminDown", - down: "Down", - init: "Init", - up: "Up", - } - - -class BFDAuthType(NumericConstant): - """ BFD Authentication Type """ - no_auth = 0 - simple_pwd = 1 - keyed_md5 = 2 - meticulous_keyed_md5 = 3 - keyed_sha1 = 4 - meticulous_keyed_sha1 = 5 - - desc_dict = { - no_auth: "No authentication", - simple_pwd: "Simple Password", - keyed_md5: "Keyed MD5", - meticulous_keyed_md5: "Meticulous Keyed MD5", - keyed_sha1: "Keyed SHA1", - meticulous_keyed_sha1: "Meticulous Keyed SHA1", - } - - -def bfd_is_auth_used(pkt): - """ is packet authenticated? """ - return "A" in pkt.sprintf("%BFD.flags%") - - -def bfd_is_simple_pwd_used(pkt): - """ is simple password authentication used? """ - return bfd_is_auth_used(pkt) and pkt.auth_type == BFDAuthType.simple_pwd - - -def bfd_is_sha1_used(pkt): - """ is sha1 authentication used? """ - return bfd_is_auth_used(pkt) and pkt.auth_type in \ - (BFDAuthType.keyed_sha1, BFDAuthType.meticulous_keyed_sha1) - - -def bfd_is_md5_used(pkt): - """ is md5 authentication used? """ - return bfd_is_auth_used(pkt) and pkt.auth_type in \ - (BFDAuthType.keyed_md5, BFDAuthType.meticulous_keyed_md5) - - -def bfd_is_md5_or_sha1_used(pkt): - """ is md5 or sha1 used? """ - return bfd_is_md5_used(pkt) or bfd_is_sha1_used(pkt) - - -class BFD(Packet): - """ BFD protocol layer for scapy """ - - udp_dport = 3784 #: BFD destination port per RFC 5881 - udp_dport_echo = 3785 # : BFD destination port for ECHO per RFC 5881 - udp_sport_min = 49152 #: BFD source port min value per RFC 5881 - udp_sport_max = 65535 #: BFD source port max value per RFC 5881 - bfd_pkt_len = 24 # : length of BFD pkt without authentication section - sha1_auth_len = 28 # : length of authentication section if SHA1 used - - name = "BFD" - - fields_desc = [ - BitField("version", 1, 3), - BitEnumField("diag", 0, 5, BFDDiagCode.desc_dict), - BitEnumField("state", 0, 2, BFDState.desc_dict), - FlagsField("flags", 0, 6, ['M', 'D', 'A', 'C', 'F', 'P']), - XByteField("detect_mult", 0), - BitField("length", bfd_pkt_len, 8), - BitField("my_discriminator", 0, 32), - BitField("your_discriminator", 0, 32), - BitField("desired_min_tx_interval", 0, 32), - BitField("required_min_rx_interval", 0, 32), - BitField("required_min_echo_rx_interval", 0, 32), - ConditionalField( - BitEnumField("auth_type", 0, 8, BFDAuthType.desc_dict), - bfd_is_auth_used), - ConditionalField(BitField("auth_len", 0, 8), bfd_is_auth_used), - ConditionalField(BitField("auth_key_id", 0, 8), bfd_is_auth_used), - ConditionalField(BitField("auth_reserved", 0, 8), - bfd_is_md5_or_sha1_used), - ConditionalField( - BitField("auth_seq_num", 0, 32), bfd_is_md5_or_sha1_used), - ConditionalField(StrField("auth_key_hash", "0" * 16), bfd_is_md5_used), - ConditionalField( - StrField("auth_key_hash", "0" * 20), bfd_is_sha1_used), - ] - - def mysummary(self): - return self.sprintf("BFD(my_disc=%BFD.my_discriminator%," - "your_disc=%BFD.your_discriminator%)") - - -# glue the BFD packet class to scapy parser -bind_layers(UDP, BFD, dport=BFD.udp_dport) - - -class BFD_vpp_echo(Packet): - """ BFD echo packet as used by VPP (non-rfc, as rfc doesn't define one) """ - - udp_dport = 3785 #: BFD echo destination port per RFC 5881 - name = "BFD_VPP_ECHO" - - fields_desc = [ - BitField("discriminator", 0, 32), - BitField("expire_time_clocks", 0, 64), - BitField("checksum", 0, 64) - ] - - def mysummary(self): - return self.sprintf( - "BFD_VPP_ECHO(disc=%BFD_VPP_ECHO.discriminator%," - "expire_time_clocks=%BFD_VPP_ECHO.expire_time_clocks%)") - - -# glue the BFD echo packet class to scapy parser -bind_layers(UDP, BFD_vpp_echo, dport=BFD_vpp_echo.udp_dport) - - -class VppBFDAuthKey(VppObject): - """ Represents BFD authentication key in VPP """ - - def __init__(self, test, conf_key_id, auth_type, key): - self._test = test - self._key = key - self._auth_type = auth_type - test.assertIn(auth_type, BFDAuthType.desc_dict) - self._conf_key_id = conf_key_id - - @property - def test(self): - """ Test which created this key """ - return self._test - - @property - def auth_type(self): - """ Authentication type for this key """ - return self._auth_type - - @property - def key(self): - """ key data """ - return self._key - - @key.setter - def key(self, value): - self._key = value - - @property - def conf_key_id(self): - """ configuration key ID """ - return self._conf_key_id - - def add_vpp_config(self): - self.test.vapi.bfd_auth_set_key( - conf_key_id=self._conf_key_id, auth_type=self._auth_type, - key=self._key, key_len=len(self._key)) - self._test.registry.register(self, self.test.logger) - - def get_bfd_auth_keys_dump_entry(self): - """ get the entry in the auth keys dump corresponding to this key """ - result = self.test.vapi.bfd_auth_keys_dump() - for k in result: - if k.conf_key_id == self._conf_key_id: - return k - return None - - def query_vpp_config(self): - return self.get_bfd_auth_keys_dump_entry() is not None - - def remove_vpp_config(self): - self.test.vapi.bfd_auth_del_key(conf_key_id=self._conf_key_id) - - def object_id(self): - return "bfd-auth-key-%s" % self._conf_key_id - - -class VppBFDUDPSession(VppObject): - """ Represents BFD UDP session in VPP """ - - def __init__(self, test, interface, peer_addr, local_addr=None, af=AF_INET, - desired_min_tx=300000, required_min_rx=300000, detect_mult=3, - sha1_key=None, bfd_key_id=None, is_tunnel=False): - self._test = test - self._interface = interface - self._af = af - if local_addr: - self._local_addr = local_addr - else: - self._local_addr = None - self._peer_addr = peer_addr - self._desired_min_tx = desired_min_tx - self._required_min_rx = required_min_rx - self._detect_mult = detect_mult - self._sha1_key = sha1_key - if bfd_key_id is not None: - self._bfd_key_id = bfd_key_id - else: - self._bfd_key_id = randint(0, 255) - self._is_tunnel = is_tunnel - - @property - def test(self): - """ Test which created this session """ - return self._test - - @property - def interface(self): - """ Interface on which this session lives """ - return self._interface - - @property - def af(self): - """ Address family - AF_INET or AF_INET6 """ - return self._af - - @property - def local_addr(self): - """ BFD session local address (VPP address) """ - if self._local_addr is None: - if self.af == AF_INET: - return self._interface.local_ip4 - elif self.af == AF_INET6: - return self._interface.local_ip6 - else: - raise Exception("Unexpected af '%s'" % self.af) - return self._local_addr - - @property - def peer_addr(self): - """ BFD session peer address """ - return self._peer_addr - - def get_bfd_udp_session_dump_entry(self): - """ get the namedtuple entry from bfd udp session dump """ - result = self.test.vapi.bfd_udp_session_dump() - for s in result: - self.test.logger.debug("session entry: %s" % str(s)) - if s.sw_if_index == self.interface.sw_if_index: - if self.af == AF_INET \ - and self.interface.local_ip4 == str(s.local_addr) \ - and self.interface.remote_ip4 == str(s.peer_addr): - return s - if self.af == AF_INET6 \ - and self.interface.local_ip6 == str(s.local_addr) \ - and self.interface.remote_ip6 == str(s.peer_addr): - return s - return None - - @property - def state(self): - """ BFD session state """ - session = self.get_bfd_udp_session_dump_entry() - if session is None: - raise Exception("Could not find BFD session in VPP response") - return session.state - - @property - def desired_min_tx(self): - """ desired minimum tx interval """ - return self._desired_min_tx - - @property - def required_min_rx(self): - """ required minimum rx interval """ - return self._required_min_rx - - @property - def detect_mult(self): - """ detect multiplier """ - return self._detect_mult - - @property - def sha1_key(self): - """ sha1 key """ - return self._sha1_key - - @property - def bfd_key_id(self): - """ bfd key id in use """ - return self._bfd_key_id - - @property - def is_tunnel(self): - return self._is_tunnel - - def activate_auth(self, key, bfd_key_id=None, delayed=False): - """ activate authentication for this session """ - self._bfd_key_id = bfd_key_id if bfd_key_id else randint(0, 255) - self._sha1_key = key - conf_key_id = self._sha1_key.conf_key_id - is_delayed = 1 if delayed else 0 - self.test.vapi.bfd_udp_auth_activate( - sw_if_index=self._interface.sw_if_index, - local_addr=self.local_addr, - peer_addr=self.peer_addr, - bfd_key_id=self._bfd_key_id, - conf_key_id=conf_key_id, - is_delayed=is_delayed) - - def deactivate_auth(self, delayed=False): - """ deactivate authentication """ - self._bfd_key_id = None - self._sha1_key = None - is_delayed = 1 if delayed else 0 - self.test.vapi.bfd_udp_auth_deactivate( - sw_if_index=self._interface.sw_if_index, - local_addr=self.local_addr, - peer_addr=self.peer_addr, - is_delayed=is_delayed) - - def modify_parameters(self, - detect_mult=None, - desired_min_tx=None, - required_min_rx=None): - """ modify session parameters """ - if detect_mult: - self._detect_mult = detect_mult - if desired_min_tx: - self._desired_min_tx = desired_min_tx - if required_min_rx: - self._required_min_rx = required_min_rx - self.test.vapi.bfd_udp_mod(sw_if_index=self._interface.sw_if_index, - desired_min_tx=self.desired_min_tx, - required_min_rx=self.required_min_rx, - detect_mult=self.detect_mult, - local_addr=self.local_addr, - peer_addr=self.peer_addr) - - def add_vpp_config(self): - bfd_key_id = self._bfd_key_id if self._sha1_key else None - conf_key_id = self._sha1_key.conf_key_id if self._sha1_key else None - is_authenticated = True if self._sha1_key else False - self.test.vapi.bfd_udp_add(sw_if_index=self._interface.sw_if_index, - desired_min_tx=self.desired_min_tx, - required_min_rx=self.required_min_rx, - detect_mult=self.detect_mult, - local_addr=self.local_addr, - peer_addr=self.peer_addr, - bfd_key_id=bfd_key_id, - conf_key_id=conf_key_id, - is_authenticated=is_authenticated) - self._test.registry.register(self, self.test.logger) - - def query_vpp_config(self): - session = self.get_bfd_udp_session_dump_entry() - return session is not None - - def remove_vpp_config(self): - self.test.vapi.bfd_udp_del(self._interface.sw_if_index, - local_addr=self.local_addr, - peer_addr=self.peer_addr) - - def object_id(self): - return "bfd-udp-%s-%s-%s-%s" % (self._interface.sw_if_index, - self.local_addr, - self.peer_addr, - self.af) - - def admin_up(self): - """ set bfd session admin-up """ - self.test.vapi.bfd_udp_session_set_flags( - flags=VppEnum.vl_api_if_status_flags_t.IF_STATUS_API_FLAG_ADMIN_UP, - sw_if_index=self._interface.sw_if_index, - local_addr=self.local_addr, - peer_addr=self.peer_addr) - - def admin_down(self): - """ set bfd session admin-down """ - self.test.vapi.bfd_udp_session_set_flags( - flags=0, sw_if_index=self._interface.sw_if_index, - local_addr=self.local_addr, - peer_addr=self.peer_addr) diff --git a/src/vnet/bfd/test/test_bfd.py b/src/vnet/bfd/test/test_bfd.py deleted file mode 100644 index 01b468c8e27..00000000000 --- a/src/vnet/bfd/test/test_bfd.py +++ /dev/null @@ -1,2763 +0,0 @@ -#!/usr/bin/env python3 -""" BFD tests """ - -from __future__ import division - -import binascii -import hashlib -import ipaddress -import reprlib -import time -import unittest -from random import randint, shuffle, getrandbits -from socket import AF_INET, AF_INET6, inet_ntop -from struct import pack, unpack - -import scapy.compat -from scapy.layers.inet import UDP, IP -from scapy.layers.inet6 import IPv6 -from scapy.layers.l2 import Ether, GRE -from scapy.packet import Raw - -from bfd import VppBFDAuthKey, BFD, BFDAuthType, VppBFDUDPSession, \ - BFDDiagCode, BFDState, BFD_vpp_echo -from framework import tag_fixme_vpp_workers -from framework import VppTestCase, VppTestRunner, running_extended_tests -from framework import tag_run_solo -from util import ppp -from vpp_ip import DpoProto -from vpp_ip_route import VppIpRoute, VppRoutePath -from vpp_lo_interface import VppLoInterface -from vpp_papi_provider import UnexpectedApiReturnValueError, \ - CliFailedCommandError -from vpp_pg_interface import CaptureTimeoutError, is_ipv6_misc -from vpp_gre_interface import VppGreInterface -from vpp_papi import VppEnum - -USEC_IN_SEC = 1000000 - - -class AuthKeyFactory(object): - """Factory class for creating auth keys with unique conf key ID""" - - def __init__(self): - self._conf_key_ids = {} - - def create_random_key(self, test, auth_type=BFDAuthType.keyed_sha1): - """ create a random key with unique conf key id """ - conf_key_id = randint(0, 0xFFFFFFFF) - while conf_key_id in self._conf_key_ids: - conf_key_id = randint(0, 0xFFFFFFFF) - self._conf_key_ids[conf_key_id] = 1 - key = scapy.compat.raw( - bytearray([randint(0, 255) for _ in range(randint(1, 20))])) - return VppBFDAuthKey(test=test, auth_type=auth_type, - conf_key_id=conf_key_id, key=key) - - -class BFDAPITestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD) - API""" - - pg0 = None - pg1 = None - - @classmethod - def setUpClass(cls): - super(BFDAPITestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces(range(2)) - for i in cls.pg_interfaces: - i.config_ip4() - i.config_ip6() - i.resolve_arp() - - except Exception: - super(BFDAPITestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFDAPITestCase, cls).tearDownClass() - - def setUp(self): - super(BFDAPITestCase, self).setUp() - self.factory = AuthKeyFactory() - - def test_add_bfd(self): - """ create a BFD session """ - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - - def test_double_add(self): - """ create the same BFD session twice (negative case) """ - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - session.add_vpp_config() - - with self.vapi.assert_negative_api_retval(): - session.add_vpp_config() - - session.remove_vpp_config() - - def test_add_bfd6(self): - """ create IPv6 BFD session """ - session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip6, af=AF_INET6) - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - - def test_mod_bfd(self): - """ modify BFD session parameters """ - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - desired_min_tx=50000, - required_min_rx=10000, - detect_mult=1) - session.add_vpp_config() - s = session.get_bfd_udp_session_dump_entry() - self.assert_equal(session.desired_min_tx, - s.desired_min_tx, - "desired min transmit interval") - self.assert_equal(session.required_min_rx, - s.required_min_rx, - "required min receive interval") - self.assert_equal(session.detect_mult, s.detect_mult, "detect mult") - session.modify_parameters(desired_min_tx=session.desired_min_tx * 2, - required_min_rx=session.required_min_rx * 2, - detect_mult=session.detect_mult * 2) - s = session.get_bfd_udp_session_dump_entry() - self.assert_equal(session.desired_min_tx, - s.desired_min_tx, - "desired min transmit interval") - self.assert_equal(session.required_min_rx, - s.required_min_rx, - "required min receive interval") - self.assert_equal(session.detect_mult, s.detect_mult, "detect mult") - - def test_add_sha1_keys(self): - """ add SHA1 keys """ - key_count = 10 - keys = [self.factory.create_random_key( - self) for i in range(0, key_count)] - for key in keys: - self.assertFalse(key.query_vpp_config()) - for key in keys: - key.add_vpp_config() - for key in keys: - self.assertTrue(key.query_vpp_config()) - # remove randomly - indexes = list(range(key_count)) - shuffle(indexes) - removed = [] - for i in indexes: - key = keys[i] - key.remove_vpp_config() - removed.append(i) - for j in range(key_count): - key = keys[j] - if j in removed: - self.assertFalse(key.query_vpp_config()) - else: - self.assertTrue(key.query_vpp_config()) - # should be removed now - for key in keys: - self.assertFalse(key.query_vpp_config()) - # add back and remove again - for key in keys: - key.add_vpp_config() - for key in keys: - self.assertTrue(key.query_vpp_config()) - for key in keys: - key.remove_vpp_config() - for key in keys: - self.assertFalse(key.query_vpp_config()) - - def test_add_bfd_sha1(self): - """ create a BFD session (SHA1) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key) - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - session.add_vpp_config() - self.logger.debug("Session state is %s", session.state) - session.remove_vpp_config() - - def test_double_add_sha1(self): - """ create the same BFD session twice (negative case) (SHA1) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key) - session.add_vpp_config() - with self.assertRaises(Exception): - session.add_vpp_config() - - def test_add_auth_nonexistent_key(self): - """ create BFD session using non-existent SHA1 (negative case) """ - session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, - sha1_key=self.factory.create_random_key(self)) - with self.assertRaises(Exception): - session.add_vpp_config() - - def test_shared_sha1_key(self): - """ share single SHA1 key between multiple BFD sessions """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - sessions = [ - VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key), - VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip6, - sha1_key=key, af=AF_INET6), - VppBFDUDPSession(self, self.pg1, self.pg1.remote_ip4, - sha1_key=key), - VppBFDUDPSession(self, self.pg1, self.pg1.remote_ip6, - sha1_key=key, af=AF_INET6)] - for s in sessions: - s.add_vpp_config() - removed = 0 - for s in sessions: - e = key.get_bfd_auth_keys_dump_entry() - self.assert_equal(e.use_count, len(sessions) - removed, - "Use count for shared key") - s.remove_vpp_config() - removed += 1 - e = key.get_bfd_auth_keys_dump_entry() - self.assert_equal(e.use_count, len(sessions) - removed, - "Use count for shared key") - - def test_activate_auth(self): - """ activate SHA1 authentication """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - session.add_vpp_config() - session.activate_auth(key) - - def test_deactivate_auth(self): - """ deactivate SHA1 authentication """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - session.add_vpp_config() - session.activate_auth(key) - session.deactivate_auth() - - def test_change_key(self): - """ change SHA1 key """ - key1 = self.factory.create_random_key(self) - key2 = self.factory.create_random_key(self) - while key2.conf_key_id == key1.conf_key_id: - key2 = self.factory.create_random_key(self) - key1.add_vpp_config() - key2.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key1) - session.add_vpp_config() - session.activate_auth(key2) - - def test_set_del_udp_echo_source(self): - """ set/del udp echo source """ - self.create_loopback_interfaces(1) - self.loopback0 = self.lo_interfaces[0] - self.loopback0.admin_up() - echo_source = self.vapi.bfd_udp_get_echo_source() - self.assertFalse(echo_source.is_set) - self.assertFalse(echo_source.have_usable_ip4) - self.assertFalse(echo_source.have_usable_ip6) - - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - echo_source = self.vapi.bfd_udp_get_echo_source() - self.assertTrue(echo_source.is_set) - self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index) - self.assertFalse(echo_source.have_usable_ip4) - self.assertFalse(echo_source.have_usable_ip6) - - self.loopback0.config_ip4() - echo_ip4 = ipaddress.IPv4Address(int(ipaddress.IPv4Address( - self.loopback0.local_ip4)) ^ 1).packed - echo_source = self.vapi.bfd_udp_get_echo_source() - self.assertTrue(echo_source.is_set) - self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index) - self.assertTrue(echo_source.have_usable_ip4) - self.assertEqual(echo_source.ip4_addr.packed, echo_ip4) - self.assertFalse(echo_source.have_usable_ip6) - - self.loopback0.config_ip6() - echo_ip6 = ipaddress.IPv6Address(int(ipaddress.IPv6Address( - self.loopback0.local_ip6)) ^ 1).packed - - echo_source = self.vapi.bfd_udp_get_echo_source() - self.assertTrue(echo_source.is_set) - self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index) - self.assertTrue(echo_source.have_usable_ip4) - self.assertEqual(echo_source.ip4_addr.packed, echo_ip4) - self.assertTrue(echo_source.have_usable_ip6) - self.assertEqual(echo_source.ip6_addr.packed, echo_ip6) - - self.vapi.bfd_udp_del_echo_source() - echo_source = self.vapi.bfd_udp_get_echo_source() - self.assertFalse(echo_source.is_set) - self.assertFalse(echo_source.have_usable_ip4) - self.assertFalse(echo_source.have_usable_ip6) - - -class BFDTestSession(object): - """ BFD session as seen from test framework side """ - - def __init__(self, test, interface, af, detect_mult=3, sha1_key=None, - bfd_key_id=None, our_seq_number=None, - tunnel_header=None, phy_interface=None): - self.test = test - self.af = af - self.sha1_key = sha1_key - self.bfd_key_id = bfd_key_id - self.interface = interface - if phy_interface: - self.phy_interface = phy_interface - else: - self.phy_interface = self.interface - self.udp_sport = randint(49152, 65535) - if our_seq_number is None: - self.our_seq_number = randint(0, 40000000) - else: - self.our_seq_number = our_seq_number - self.vpp_seq_number = None - self.my_discriminator = 0 - self.desired_min_tx = 300000 - self.required_min_rx = 300000 - self.required_min_echo_rx = None - self.detect_mult = detect_mult - self.diag = BFDDiagCode.no_diagnostic - self.your_discriminator = None - self.state = BFDState.down - self.auth_type = BFDAuthType.no_auth - self.tunnel_header = tunnel_header - - def inc_seq_num(self): - """ increment sequence number, wrapping if needed """ - if self.our_seq_number == 0xFFFFFFFF: - self.our_seq_number = 0 - else: - self.our_seq_number += 1 - - def update(self, my_discriminator=None, your_discriminator=None, - desired_min_tx=None, required_min_rx=None, - required_min_echo_rx=None, detect_mult=None, - diag=None, state=None, auth_type=None): - """ update BFD parameters associated with session """ - if my_discriminator is not None: - self.my_discriminator = my_discriminator - if your_discriminator is not None: - self.your_discriminator = your_discriminator - if required_min_rx is not None: - self.required_min_rx = required_min_rx - if required_min_echo_rx is not None: - self.required_min_echo_rx = required_min_echo_rx - if desired_min_tx is not None: - self.desired_min_tx = desired_min_tx - if detect_mult is not None: - self.detect_mult = detect_mult - if diag is not None: - self.diag = diag - if state is not None: - self.state = state - if auth_type is not None: - self.auth_type = auth_type - - def fill_packet_fields(self, packet): - """ set packet fields with known values in packet """ - bfd = packet[BFD] - if self.my_discriminator: - self.test.logger.debug("BFD: setting packet.my_discriminator=%s", - self.my_discriminator) - bfd.my_discriminator = self.my_discriminator - if self.your_discriminator: - self.test.logger.debug("BFD: setting packet.your_discriminator=%s", - self.your_discriminator) - bfd.your_discriminator = self.your_discriminator - if self.required_min_rx: - self.test.logger.debug( - "BFD: setting packet.required_min_rx_interval=%s", - self.required_min_rx) - bfd.required_min_rx_interval = self.required_min_rx - if self.required_min_echo_rx: - self.test.logger.debug( - "BFD: setting packet.required_min_echo_rx=%s", - self.required_min_echo_rx) - bfd.required_min_echo_rx_interval = self.required_min_echo_rx - if self.desired_min_tx: - self.test.logger.debug( - "BFD: setting packet.desired_min_tx_interval=%s", - self.desired_min_tx) - bfd.desired_min_tx_interval = self.desired_min_tx - if self.detect_mult: - self.test.logger.debug( - "BFD: setting packet.detect_mult=%s", self.detect_mult) - bfd.detect_mult = self.detect_mult - if self.diag: - self.test.logger.debug("BFD: setting packet.diag=%s", self.diag) - bfd.diag = self.diag - if self.state: - self.test.logger.debug("BFD: setting packet.state=%s", self.state) - bfd.state = self.state - if self.auth_type: - # this is used by a negative test-case - self.test.logger.debug("BFD: setting packet.auth_type=%s", - self.auth_type) - bfd.auth_type = self.auth_type - - def create_packet(self): - """ create a BFD packet, reflecting the current state of session """ - if self.sha1_key: - bfd = BFD(flags="A") - bfd.auth_type = self.sha1_key.auth_type - bfd.auth_len = BFD.sha1_auth_len - bfd.auth_key_id = self.bfd_key_id - bfd.auth_seq_num = self.our_seq_number - bfd.length = BFD.sha1_auth_len + BFD.bfd_pkt_len - else: - bfd = BFD() - packet = Ether(src=self.phy_interface.remote_mac, - dst=self.phy_interface.local_mac) - if self.tunnel_header: - packet = packet / self.tunnel_header - if self.af == AF_INET6: - packet = (packet / - IPv6(src=self.interface.remote_ip6, - dst=self.interface.local_ip6, - hlim=255) / - UDP(sport=self.udp_sport, dport=BFD.udp_dport) / - bfd) - else: - packet = (packet / - IP(src=self.interface.remote_ip4, - dst=self.interface.local_ip4, - ttl=255) / - UDP(sport=self.udp_sport, dport=BFD.udp_dport) / - bfd) - self.test.logger.debug("BFD: Creating packet") - self.fill_packet_fields(packet) - if self.sha1_key: - hash_material = scapy.compat.raw( - packet[BFD])[:32] + self.sha1_key.key + \ - b"\0" * (20 - len(self.sha1_key.key)) - self.test.logger.debug("BFD: Calculated SHA1 hash: %s" % - hashlib.sha1(hash_material).hexdigest()) - packet[BFD].auth_key_hash = hashlib.sha1(hash_material).digest() - return packet - - def send_packet(self, packet=None, interface=None): - """ send packet on interface, creating the packet if needed """ - if packet is None: - packet = self.create_packet() - if interface is None: - interface = self.phy_interface - self.test.logger.debug(ppp("Sending packet:", packet)) - interface.add_stream(packet) - self.test.pg_start() - - def verify_sha1_auth(self, packet): - """ Verify correctness of authentication in BFD layer. """ - bfd = packet[BFD] - self.test.assert_equal(bfd.auth_len, 28, "Auth section length") - self.test.assert_equal(bfd.auth_type, self.sha1_key.auth_type, - BFDAuthType) - self.test.assert_equal(bfd.auth_key_id, self.bfd_key_id, "Key ID") - self.test.assert_equal(bfd.auth_reserved, 0, "Reserved") - if self.vpp_seq_number is None: - self.vpp_seq_number = bfd.auth_seq_num - self.test.logger.debug("Received initial sequence number: %s" % - self.vpp_seq_number) - else: - recvd_seq_num = bfd.auth_seq_num - self.test.logger.debug("Received followup sequence number: %s" % - recvd_seq_num) - if self.vpp_seq_number < 0xffffffff: - if self.sha1_key.auth_type == \ - BFDAuthType.meticulous_keyed_sha1: - self.test.assert_equal(recvd_seq_num, - self.vpp_seq_number + 1, - "BFD sequence number") - else: - self.test.assert_in_range(recvd_seq_num, - self.vpp_seq_number, - self.vpp_seq_number + 1, - "BFD sequence number") - else: - if self.sha1_key.auth_type == \ - BFDAuthType.meticulous_keyed_sha1: - self.test.assert_equal(recvd_seq_num, 0, - "BFD sequence number") - else: - self.test.assertIn(recvd_seq_num, (self.vpp_seq_number, 0), - "BFD sequence number not one of " - "(%s, 0)" % self.vpp_seq_number) - self.vpp_seq_number = recvd_seq_num - # last 20 bytes represent the hash - so replace them with the key, - # pad the result with zeros and hash the result - hash_material = bfd.original[:-20] + self.sha1_key.key + \ - b"\0" * (20 - len(self.sha1_key.key)) - expected_hash = hashlib.sha1(hash_material).hexdigest() - self.test.assert_equal(binascii.hexlify(bfd.auth_key_hash), - expected_hash.encode(), "Auth key hash") - - def verify_bfd(self, packet): - """ Verify correctness of BFD layer. """ - bfd = packet[BFD] - self.test.assert_equal(bfd.version, 1, "BFD version") - self.test.assert_equal(bfd.your_discriminator, - self.my_discriminator, - "BFD - your discriminator") - if self.sha1_key: - self.verify_sha1_auth(packet) - - -def bfd_session_up(test): - """ Bring BFD session up """ - test.logger.info("BFD: Waiting for slow hello") - p = wait_for_bfd_packet(test, 2, is_tunnel=test.vpp_session.is_tunnel) - old_offset = None - if hasattr(test, 'vpp_clock_offset'): - old_offset = test.vpp_clock_offset - test.vpp_clock_offset = time.time() - float(p.time) - test.logger.debug("BFD: Calculated vpp clock offset: %s", - test.vpp_clock_offset) - if old_offset: - test.assertAlmostEqual( - old_offset, test.vpp_clock_offset, delta=0.5, - msg="vpp clock offset not stable (new: %s, old: %s)" % - (test.vpp_clock_offset, old_offset)) - test.logger.info("BFD: Sending Init") - test.test_session.update(my_discriminator=randint(0, 40000000), - your_discriminator=p[BFD].my_discriminator, - state=BFDState.init) - if test.test_session.sha1_key and test.test_session.sha1_key.auth_type == \ - BFDAuthType.meticulous_keyed_sha1: - test.test_session.inc_seq_num() - test.test_session.send_packet() - test.logger.info("BFD: Waiting for event") - e = test.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(test, e, expected_state=BFDState.up) - test.logger.info("BFD: Session is Up") - test.test_session.update(state=BFDState.up) - if test.test_session.sha1_key and test.test_session.sha1_key.auth_type == \ - BFDAuthType.meticulous_keyed_sha1: - test.test_session.inc_seq_num() - test.test_session.send_packet() - test.assert_equal(test.vpp_session.state, BFDState.up, BFDState) - - -def bfd_session_down(test): - """ Bring BFD session down """ - test.assert_equal(test.vpp_session.state, BFDState.up, BFDState) - test.test_session.update(state=BFDState.down) - if test.test_session.sha1_key and test.test_session.sha1_key.auth_type == \ - BFDAuthType.meticulous_keyed_sha1: - test.test_session.inc_seq_num() - test.test_session.send_packet() - test.logger.info("BFD: Waiting for event") - e = test.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(test, e, expected_state=BFDState.down) - test.logger.info("BFD: Session is Down") - test.assert_equal(test.vpp_session.state, BFDState.down, BFDState) - - -def verify_bfd_session_config(test, session, state=None): - dump = session.get_bfd_udp_session_dump_entry() - test.assertIsNotNone(dump) - # since dump is not none, we have verified that sw_if_index and addresses - # are valid (in get_bfd_udp_session_dump_entry) - if state: - test.assert_equal(dump.state, state, "session state") - test.assert_equal(dump.required_min_rx, session.required_min_rx, - "required min rx interval") - test.assert_equal(dump.desired_min_tx, session.desired_min_tx, - "desired min tx interval") - test.assert_equal(dump.detect_mult, session.detect_mult, - "detect multiplier") - if session.sha1_key is None: - test.assert_equal(dump.is_authenticated, 0, "is_authenticated flag") - else: - test.assert_equal(dump.is_authenticated, 1, "is_authenticated flag") - test.assert_equal(dump.bfd_key_id, session.bfd_key_id, - "bfd key id") - test.assert_equal(dump.conf_key_id, - session.sha1_key.conf_key_id, - "config key id") - - -def verify_ip(test, packet): - """ Verify correctness of IP layer. """ - if test.vpp_session.af == AF_INET6: - ip = packet[IPv6] - local_ip = test.vpp_session.interface.local_ip6 - remote_ip = test.vpp_session.interface.remote_ip6 - test.assert_equal(ip.hlim, 255, "IPv6 hop limit") - else: - ip = packet[IP] - local_ip = test.vpp_session.interface.local_ip4 - remote_ip = test.vpp_session.interface.remote_ip4 - test.assert_equal(ip.ttl, 255, "IPv4 TTL") - test.assert_equal(ip.src, local_ip, "IP source address") - test.assert_equal(ip.dst, remote_ip, "IP destination address") - - -def verify_udp(test, packet): - """ Verify correctness of UDP layer. """ - udp = packet[UDP] - test.assert_equal(udp.dport, BFD.udp_dport, "UDP destination port") - test.assert_in_range(udp.sport, BFD.udp_sport_min, BFD.udp_sport_max, - "UDP source port") - - -def verify_event(test, event, expected_state): - """ Verify correctness of event values. """ - e = event - test.logger.debug("BFD: Event: %s" % reprlib.repr(e)) - test.assert_equal(e.sw_if_index, - test.vpp_session.interface.sw_if_index, - "BFD interface index") - - test.assert_equal(str(e.local_addr), test.vpp_session.local_addr, - "Local IPv6 address") - test.assert_equal(str(e.peer_addr), test.vpp_session.peer_addr, - "Peer IPv6 address") - test.assert_equal(e.state, expected_state, BFDState) - - -def wait_for_bfd_packet(test, timeout=1, pcap_time_min=None, is_tunnel=False): - """ wait for BFD packet and verify its correctness - - :param timeout: how long to wait - :param pcap_time_min: ignore packets with pcap timestamp lower than this - - :returns: tuple (packet, time spent waiting for packet) - """ - test.logger.info("BFD: Waiting for BFD packet") - deadline = time.time() + timeout - counter = 0 - while True: - counter += 1 - # sanity check - test.assert_in_range(counter, 0, 100, "number of packets ignored") - time_left = deadline - time.time() - if time_left < 0: - raise CaptureTimeoutError("Packet did not arrive within timeout") - p = test.pg0.wait_for_packet(timeout=time_left) - test.logger.debug(ppp("BFD: Got packet:", p)) - if pcap_time_min is not None and p.time < pcap_time_min: - test.logger.debug(ppp("BFD: ignoring packet (pcap time %s < " - "pcap time min %s):" % - (p.time, pcap_time_min), p)) - else: - break - if is_tunnel: - # strip an IP layer and move to the next - p = p[IP].payload - - bfd = p[BFD] - if bfd is None: - raise Exception(ppp("Unexpected or invalid BFD packet:", p)) - if bfd.payload: - raise Exception(ppp("Unexpected payload in BFD packet:", bfd)) - verify_ip(test, p) - verify_udp(test, p) - test.test_session.verify_bfd(p) - return p - - -@tag_run_solo -class BFD4TestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD)""" - - pg0 = None - vpp_clock_offset = None - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFD4TestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces([0]) - cls.create_loopback_interfaces(1) - cls.loopback0 = cls.lo_interfaces[0] - cls.loopback0.config_ip4() - cls.loopback0.admin_up() - cls.pg0.config_ip4() - cls.pg0.configure_ipv4_neighbors() - cls.pg0.admin_up() - cls.pg0.resolve_arp() - - except Exception: - super(BFD4TestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFD4TestCase, cls).tearDownClass() - - def setUp(self): - super(BFD4TestCase, self).setUp() - self.factory = AuthKeyFactory() - self.vapi.want_bfd_events() - self.pg0.enable_capture() - try: - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession(self, self.pg0, AF_INET) - except BaseException: - self.vapi.want_bfd_events(enable_disable=0) - raise - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=0) - self.vapi.collect_events() # clear the event queue - super(BFD4TestCase, self).tearDown() - - def test_session_up(self): - """ bring BFD session up """ - bfd_session_up(self) - - def test_session_up_by_ip(self): - """ bring BFD session up - first frame looked up by address pair """ - self.logger.info("BFD: Sending Slow control frame") - self.test_session.update(my_discriminator=randint(0, 40000000)) - self.test_session.send_packet() - self.pg0.enable_capture() - p = self.pg0.wait_for_packet(1) - self.assert_equal(p[BFD].your_discriminator, - self.test_session.my_discriminator, - "BFD - your discriminator") - self.assert_equal(p[BFD].state, BFDState.init, BFDState) - self.test_session.update(your_discriminator=p[BFD].my_discriminator, - state=BFDState.up) - self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.init) - self.logger.info("BFD: Sending Up") - self.test_session.send_packet() - self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.up) - self.logger.info("BFD: Session is Up") - self.test_session.update(state=BFDState.up) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_session_down(self): - """ bring BFD session down """ - bfd_session_up(self) - bfd_session_down(self) - - def test_hold_up(self): - """ hold BFD session up """ - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - wait_for_bfd_packet(self) - self.test_session.send_packet() - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_slow_timer(self): - """ verify slow periodic control frames while session down """ - packet_count = 3 - self.logger.info("BFD: Waiting for %d BFD packets", packet_count) - prev_packet = wait_for_bfd_packet(self, 2) - for dummy in range(packet_count): - next_packet = wait_for_bfd_packet(self, 2) - time_diff = next_packet.time - prev_packet.time - # spec says the range should be <0.75, 1>, allow extra 0.05 margin - # to work around timing issues - self.assert_in_range( - time_diff, 0.70, 1.05, "time between slow packets") - prev_packet = next_packet - - def test_zero_remote_min_rx(self): - """ no packets when zero remote required min rx interval """ - bfd_session_up(self) - self.test_session.update(required_min_rx=0) - self.test_session.send_packet() - for dummy in range(self.test_session.detect_mult): - self.sleep(self.vpp_session.required_min_rx / USEC_IN_SEC, - "sleep before transmitting bfd packet") - self.test_session.send_packet() - try: - p = wait_for_bfd_packet(self, timeout=0) - self.logger.error(ppp("Received unexpected packet:", p)) - except CaptureTimeoutError: - pass - self.assert_equal( - len(self.vapi.collect_events()), 0, "number of bfd events") - self.test_session.update(required_min_rx=300000) - for dummy in range(3): - self.test_session.send_packet() - wait_for_bfd_packet( - self, timeout=self.test_session.required_min_rx / USEC_IN_SEC) - self.assert_equal( - len(self.vapi.collect_events()), 0, "number of bfd events") - - def test_conn_down(self): - """ verify session goes down after inactivity """ - bfd_session_up(self) - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - self.sleep(detection_time, "waiting for BFD session time-out") - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.down) - - def test_peer_discr_reset_sess_down(self): - """ peer discriminator reset after session goes down """ - bfd_session_up(self) - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - self.sleep(detection_time, "waiting for BFD session time-out") - self.test_session.my_discriminator = 0 - wait_for_bfd_packet(self, - pcap_time_min=time.time() - self.vpp_clock_offset) - - def test_large_required_min_rx(self): - """ large remote required min rx interval """ - bfd_session_up(self) - p = wait_for_bfd_packet(self) - interval = 3000000 - self.test_session.update(required_min_rx=interval) - self.test_session.send_packet() - time_mark = time.time() - count = 0 - # busy wait here, trying to collect a packet or event, vpp is not - # allowed to send packets and the session will timeout first - so the - # Up->Down event must arrive before any packets do - while time.time() < time_mark + interval / USEC_IN_SEC: - try: - p = wait_for_bfd_packet(self, timeout=0) - # if vpp managed to send a packet before we did the session - # session update, then that's fine, ignore it - if p.time < time_mark - self.vpp_clock_offset: - continue - self.logger.error(ppp("Received unexpected packet:", p)) - count += 1 - except CaptureTimeoutError: - pass - events = self.vapi.collect_events() - if len(events) > 0: - verify_event(self, events[0], BFDState.down) - break - self.assert_equal(count, 0, "number of packets received") - - def test_immediate_remote_min_rx_reduction(self): - """ immediately honor remote required min rx reduction """ - self.vpp_session.remove_vpp_config() - self.vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, desired_min_tx=10000) - self.pg0.enable_capture() - self.vpp_session.add_vpp_config() - self.test_session.update(desired_min_tx=1000000, - required_min_rx=1000000) - bfd_session_up(self) - reference_packet = wait_for_bfd_packet(self) - time_mark = time.time() - interval = 300000 - self.test_session.update(required_min_rx=interval) - self.test_session.send_packet() - extra_time = time.time() - time_mark - p = wait_for_bfd_packet(self) - # first packet is allowed to be late by time we spent doing the update - # calculated in extra_time - self.assert_in_range(p.time - reference_packet.time, - .95 * 0.75 * interval / USEC_IN_SEC, - 1.05 * interval / USEC_IN_SEC + extra_time, - "time between BFD packets") - reference_packet = p - for dummy in range(3): - p = wait_for_bfd_packet(self) - diff = p.time - reference_packet.time - self.assert_in_range(diff, .95 * .75 * interval / USEC_IN_SEC, - 1.05 * interval / USEC_IN_SEC, - "time between BFD packets") - reference_packet = p - - def test_modify_req_min_rx_double(self): - """ modify session - double required min rx """ - bfd_session_up(self) - p = wait_for_bfd_packet(self) - self.test_session.update(desired_min_tx=10000, - required_min_rx=10000) - self.test_session.send_packet() - # double required min rx - self.vpp_session.modify_parameters( - required_min_rx=2 * self.vpp_session.required_min_rx) - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - # poll bit needs to be set - self.assertIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - # finish poll sequence with final packet - final = self.test_session.create_packet() - final[BFD].flags = "F" - timeout = self.test_session.detect_mult * \ - max(self.test_session.desired_min_tx, - self.vpp_session.required_min_rx) / USEC_IN_SEC - self.test_session.send_packet(final) - time_mark = time.time() - e = self.vapi.wait_for_event(2 * timeout, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.down) - time_to_event = time.time() - time_mark - self.assert_in_range(time_to_event, .9 * timeout, - 1.1 * timeout, "session timeout") - - def test_modify_req_min_rx_halve(self): - """ modify session - halve required min rx """ - self.vpp_session.modify_parameters( - required_min_rx=2 * self.vpp_session.required_min_rx) - bfd_session_up(self) - p = wait_for_bfd_packet(self) - self.test_session.update(desired_min_tx=10000, - required_min_rx=10000) - self.test_session.send_packet() - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - # halve required min rx - old_required_min_rx = self.vpp_session.required_min_rx - self.vpp_session.modify_parameters( - required_min_rx=self.vpp_session.required_min_rx // 2) - # now we wait 0.8*3*old-req-min-rx and the session should still be up - self.sleep(0.8 * self.vpp_session.detect_mult * - old_required_min_rx / USEC_IN_SEC, - "wait before finishing poll sequence") - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - p = wait_for_bfd_packet(self) - # poll bit needs to be set - self.assertIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - # finish poll sequence with final packet - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - # now the session should time out under new conditions - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - before = time.time() - e = self.vapi.wait_for_event( - 2 * detection_time, "bfd_udp_session_event") - after = time.time() - self.assert_in_range(after - before, - 0.9 * detection_time, - 1.1 * detection_time, - "time before bfd session goes down") - verify_event(self, e, expected_state=BFDState.down) - - def test_modify_detect_mult(self): - """ modify detect multiplier """ - bfd_session_up(self) - p = wait_for_bfd_packet(self) - self.vpp_session.modify_parameters(detect_mult=1) - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(self.vpp_session.detect_mult, - p[BFD].detect_mult, - "detect mult") - # poll bit must not be set - self.assertNotIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - self.vpp_session.modify_parameters(detect_mult=10) - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(self.vpp_session.detect_mult, - p[BFD].detect_mult, - "detect mult") - # poll bit must not be set - self.assertNotIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - - def test_queued_poll(self): - """ test poll sequence queueing """ - bfd_session_up(self) - p = wait_for_bfd_packet(self) - self.vpp_session.modify_parameters( - required_min_rx=2 * self.vpp_session.required_min_rx) - p = wait_for_bfd_packet(self) - poll_sequence_start = time.time() - poll_sequence_length_min = 0.5 - send_final_after = time.time() + poll_sequence_length_min - # poll bit needs to be set - self.assertIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - self.assert_equal(p[BFD].required_min_rx_interval, - self.vpp_session.required_min_rx, - "BFD required min rx interval") - self.vpp_session.modify_parameters( - required_min_rx=2 * self.vpp_session.required_min_rx) - # 2nd poll sequence should be queued now - # don't send the reply back yet, wait for some time to emulate - # longer round-trip time - packet_count = 0 - while time.time() < send_final_after: - self.test_session.send_packet() - p = wait_for_bfd_packet(self) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - self.assert_equal(p[BFD].required_min_rx_interval, - self.vpp_session.required_min_rx, - "BFD required min rx interval") - packet_count += 1 - # poll bit must be set - self.assertIn("P", p.sprintf("%BFD.flags%"), - "Poll bit not set in BFD packet") - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - # finish 1st with final - poll_sequence_length = time.time() - poll_sequence_start - # vpp must wait for some time before starting new poll sequence - poll_no_2_started = False - for dummy in range(2 * packet_count): - p = wait_for_bfd_packet(self) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - if "P" in p.sprintf("%BFD.flags%"): - poll_no_2_started = True - if time.time() < poll_sequence_start + poll_sequence_length: - raise Exception("VPP started 2nd poll sequence too soon") - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - break - else: - self.test_session.send_packet() - self.assertTrue(poll_no_2_started, "2nd poll sequence not performed") - # finish 2nd with final - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - p = wait_for_bfd_packet(self) - # poll bit must not be set - self.assertNotIn("P", p.sprintf("%BFD.flags%"), - "Poll bit set in BFD packet") - - # returning inconsistent results requiring retries in per-patch tests - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_poll_response(self): - """ test correct response to control frame with poll bit set """ - bfd_session_up(self) - poll = self.test_session.create_packet() - poll[BFD].flags = "P" - self.test_session.send_packet(poll) - final = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assertIn("F", final.sprintf("%BFD.flags%")) - - def test_no_periodic_if_remote_demand(self): - """ no periodic frames outside poll sequence if remote demand set """ - bfd_session_up(self) - demand = self.test_session.create_packet() - demand[BFD].flags = "D" - self.test_session.send_packet(demand) - transmit_time = 0.9 \ - * max(self.vpp_session.required_min_rx, - self.test_session.desired_min_tx) \ - / USEC_IN_SEC - count = 0 - for dummy in range(self.test_session.detect_mult * 2): - self.sleep(transmit_time) - self.test_session.send_packet(demand) - try: - p = wait_for_bfd_packet(self, timeout=0) - self.logger.error(ppp("Received unexpected packet:", p)) - count += 1 - except CaptureTimeoutError: - pass - events = self.vapi.collect_events() - for e in events: - self.logger.error("Received unexpected event: %s", e) - self.assert_equal(count, 0, "number of packets received") - self.assert_equal(len(events), 0, "number of events received") - - def test_echo_looped_back(self): - """ echo packets looped back """ - # don't need a session in this case.. - self.vpp_session.remove_vpp_config() - self.pg0.enable_capture() - echo_packet_count = 10 - # random source port low enough to increment a few times.. - udp_sport_tx = randint(1, 50000) - udp_sport_rx = udp_sport_tx - echo_packet = (Ether(src=self.pg0.remote_mac, - dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, - dst=self.pg0.remote_ip4) / - UDP(dport=BFD.udp_dport_echo) / - Raw("this should be looped back")) - for dummy in range(echo_packet_count): - self.sleep(.01, "delay between echo packets") - echo_packet[UDP].sport = udp_sport_tx - udp_sport_tx += 1 - self.logger.debug(ppp("Sending packet:", echo_packet)) - self.pg0.add_stream(echo_packet) - self.pg_start() - for dummy in range(echo_packet_count): - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - ether = p[Ether] - self.assert_equal(self.pg0.remote_mac, - ether.dst, "Destination MAC") - self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC") - ip = p[IP] - self.assert_equal(self.pg0.remote_ip4, ip.dst, "Destination IP") - self.assert_equal(self.pg0.remote_ip4, ip.src, "Destination IP") - udp = p[UDP] - self.assert_equal(udp.dport, BFD.udp_dport_echo, - "UDP destination port") - self.assert_equal(udp.sport, udp_sport_rx, "UDP source port") - udp_sport_rx += 1 - # need to compare the hex payload here, otherwise BFD_vpp_echo - # gets in way - self.assertEqual(scapy.compat.raw(p[UDP].payload), - scapy.compat.raw(echo_packet[UDP].payload), - "Received packet is not the echo packet sent") - self.assert_equal(udp_sport_tx, udp_sport_rx, "UDP source port (== " - "ECHO packet identifier for test purposes)") - - def test_echo(self): - """ echo function """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.test_session.send_packet() - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - # echo shouldn't work without echo source set - for dummy in range(10): - sleep = self.vpp_session.required_min_rx / USEC_IN_SEC - self.sleep(sleep, "delay before sending bfd packet") - self.test_session.send_packet() - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(p[BFD].required_min_rx_interval, - self.vpp_session.required_min_rx, - "BFD required min rx interval") - self.test_session.send_packet() - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - echo_seen = False - # should be turned on - loopback echo packets - for dummy in range(3): - loop_until = time.time() + 0.75 * detection_time - while time.time() < loop_until: - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - if p[UDP].dport == BFD.udp_dport_echo: - self.assert_equal( - p[IP].dst, self.pg0.local_ip4, "BFD ECHO dst IP") - self.assertNotEqual(p[IP].src, self.loopback0.local_ip4, - "BFD ECHO src IP equal to loopback IP") - self.logger.debug(ppp("Looping back packet:", p)) - self.assert_equal(p[Ether].dst, self.pg0.remote_mac, - "ECHO packet destination MAC address") - p[Ether].dst = self.pg0.local_mac - self.pg0.add_stream(p) - self.pg_start() - echo_seen = True - elif p.haslayer(BFD): - if echo_seen: - self.assertGreaterEqual( - p[BFD].required_min_rx_interval, - 1000000) - if "P" in p.sprintf("%BFD.flags%"): - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - else: - raise Exception(ppp("Received unknown packet:", p)) - - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - self.test_session.send_packet() - self.assertTrue(echo_seen, "No echo packets received") - - def test_echo_fail(self): - """ session goes down if echo function fails """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.test_session.send_packet() - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - # echo function should be used now, but we will drop the echo packets - verified_diag = False - for dummy in range(3): - loop_until = time.time() + 0.75 * detection_time - while time.time() < loop_until: - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - if p[UDP].dport == BFD.udp_dport_echo: - # dropped - pass - elif p.haslayer(BFD): - if "P" in p.sprintf("%BFD.flags%"): - self.assertGreaterEqual( - p[BFD].required_min_rx_interval, - 1000000) - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - if p[BFD].state == BFDState.down: - self.assert_equal(p[BFD].diag, - BFDDiagCode.echo_function_failed, - BFDDiagCode) - verified_diag = True - else: - raise Exception(ppp("Received unknown packet:", p)) - self.test_session.send_packet() - events = self.vapi.collect_events() - self.assert_equal(len(events), 1, "number of bfd events") - self.assert_equal(events[0].state, BFDState.down, BFDState) - self.assertTrue(verified_diag, "Incorrect diagnostics code received") - - def test_echo_stop(self): - """ echo function stops if peer sets required min echo rx zero """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.test_session.send_packet() - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - # wait for first echo packet - while True: - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - if p[UDP].dport == BFD.udp_dport_echo: - self.logger.debug(ppp("Looping back packet:", p)) - p[Ether].dst = self.pg0.local_mac - self.pg0.add_stream(p) - self.pg_start() - break - elif p.haslayer(BFD): - # ignore BFD - pass - else: - raise Exception(ppp("Received unknown packet:", p)) - self.test_session.update(required_min_echo_rx=0) - self.test_session.send_packet() - # echo packets shouldn't arrive anymore - for dummy in range(5): - wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.test_session.send_packet() - events = self.vapi.collect_events() - self.assert_equal(len(events), 0, "number of bfd events") - - def test_echo_source_removed(self): - """ echo function stops if echo source is removed """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.test_session.send_packet() - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - # wait for first echo packet - while True: - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - if p[UDP].dport == BFD.udp_dport_echo: - self.logger.debug(ppp("Looping back packet:", p)) - p[Ether].dst = self.pg0.local_mac - self.pg0.add_stream(p) - self.pg_start() - break - elif p.haslayer(BFD): - # ignore BFD - pass - else: - raise Exception(ppp("Received unknown packet:", p)) - self.vapi.bfd_udp_del_echo_source() - self.test_session.send_packet() - # echo packets shouldn't arrive anymore - for dummy in range(5): - wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.test_session.send_packet() - events = self.vapi.collect_events() - self.assert_equal(len(events), 0, "number of bfd events") - - def test_stale_echo(self): - """ stale echo packets don't keep a session up """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - self.test_session.send_packet() - # should be turned on - loopback echo packets - echo_packet = None - timeout_at = None - timeout_ok = False - for dummy in range(10 * self.vpp_session.detect_mult): - p = self.pg0.wait_for_packet(1) - if p[UDP].dport == BFD.udp_dport_echo: - if echo_packet is None: - self.logger.debug(ppp("Got first echo packet:", p)) - echo_packet = p - timeout_at = time.time() + self.vpp_session.detect_mult * \ - self.test_session.required_min_echo_rx / USEC_IN_SEC - else: - self.logger.debug(ppp("Got followup echo packet:", p)) - self.logger.debug(ppp("Looping back first echo packet:", p)) - echo_packet[Ether].dst = self.pg0.local_mac - self.pg0.add_stream(echo_packet) - self.pg_start() - elif p.haslayer(BFD): - self.logger.debug(ppp("Got packet:", p)) - if "P" in p.sprintf("%BFD.flags%"): - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - if p[BFD].state == BFDState.down: - self.assertIsNotNone( - timeout_at, - "Session went down before first echo packet received") - now = time.time() - self.assertGreaterEqual( - now, timeout_at, - "Session timeout at %s, but is expected at %s" % - (now, timeout_at)) - self.assert_equal(p[BFD].diag, - BFDDiagCode.echo_function_failed, - BFDDiagCode) - events = self.vapi.collect_events() - self.assert_equal(len(events), 1, "number of bfd events") - self.assert_equal(events[0].state, BFDState.down, BFDState) - timeout_ok = True - break - else: - raise Exception(ppp("Received unknown packet:", p)) - self.test_session.send_packet() - self.assertTrue(timeout_ok, "Expected timeout event didn't occur") - - def test_invalid_echo_checksum(self): - """ echo packets with invalid checksum don't keep a session up """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - self.test_session.send_packet() - # should be turned on - loopback echo packets - timeout_at = None - timeout_ok = False - for dummy in range(10 * self.vpp_session.detect_mult): - p = self.pg0.wait_for_packet(1) - if p[UDP].dport == BFD.udp_dport_echo: - self.logger.debug(ppp("Got echo packet:", p)) - if timeout_at is None: - timeout_at = time.time() + self.vpp_session.detect_mult * \ - self.test_session.required_min_echo_rx / USEC_IN_SEC - p[BFD_vpp_echo].checksum = getrandbits(64) - p[Ether].dst = self.pg0.local_mac - self.logger.debug(ppp("Looping back modified echo packet:", p)) - self.pg0.add_stream(p) - self.pg_start() - elif p.haslayer(BFD): - self.logger.debug(ppp("Got packet:", p)) - if "P" in p.sprintf("%BFD.flags%"): - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - if p[BFD].state == BFDState.down: - self.assertIsNotNone( - timeout_at, - "Session went down before first echo packet received") - now = time.time() - self.assertGreaterEqual( - now, timeout_at, - "Session timeout at %s, but is expected at %s" % - (now, timeout_at)) - self.assert_equal(p[BFD].diag, - BFDDiagCode.echo_function_failed, - BFDDiagCode) - events = self.vapi.collect_events() - self.assert_equal(len(events), 1, "number of bfd events") - self.assert_equal(events[0].state, BFDState.down, BFDState) - timeout_ok = True - break - else: - raise Exception(ppp("Received unknown packet:", p)) - self.test_session.send_packet() - self.assertTrue(timeout_ok, "Expected timeout event didn't occur") - - def test_admin_up_down(self): - """ put session admin-up and admin-down """ - bfd_session_up(self) - self.vpp_session.admin_down() - self.pg0.enable_capture() - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.admin_down) - for dummy in range(2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.admin_down, BFDState) - # try to bring session up - shouldn't be possible - self.test_session.update(state=BFDState.init) - self.test_session.send_packet() - for dummy in range(2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.admin_down, BFDState) - self.vpp_session.admin_up() - self.test_session.update(state=BFDState.down) - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.down) - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(p[BFD].state, BFDState.down, BFDState) - self.test_session.send_packet() - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(p[BFD].state, BFDState.init, BFDState) - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.init) - self.test_session.update(state=BFDState.up) - self.test_session.send_packet() - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.up) - - def test_config_change_remote_demand(self): - """ configuration change while peer in demand mode """ - bfd_session_up(self) - demand = self.test_session.create_packet() - demand[BFD].flags = "D" - self.test_session.send_packet(demand) - self.vpp_session.modify_parameters( - required_min_rx=2 * self.vpp_session.required_min_rx) - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - # poll bit must be set - self.assertIn("P", p.sprintf("%BFD.flags%"), "Poll bit not set") - # terminate poll sequence - final = self.test_session.create_packet() - final[BFD].flags = "D+F" - self.test_session.send_packet(final) - # vpp should be quiet now again - transmit_time = 0.9 \ - * max(self.vpp_session.required_min_rx, - self.test_session.desired_min_tx) \ - / USEC_IN_SEC - count = 0 - for dummy in range(self.test_session.detect_mult * 2): - self.sleep(transmit_time) - self.test_session.send_packet(demand) - try: - p = wait_for_bfd_packet(self, timeout=0) - self.logger.error(ppp("Received unexpected packet:", p)) - count += 1 - except CaptureTimeoutError: - pass - events = self.vapi.collect_events() - for e in events: - self.logger.error("Received unexpected event: %s", e) - self.assert_equal(count, 0, "number of packets received") - self.assert_equal(len(events), 0, "number of events received") - - def test_intf_deleted(self): - """ interface with bfd session deleted """ - intf = VppLoInterface(self) - intf.config_ip4() - intf.admin_up() - sw_if_index = intf.sw_if_index - vpp_session = VppBFDUDPSession(self, intf, intf.remote_ip4) - vpp_session.add_vpp_config() - vpp_session.admin_up() - intf.remove_vpp_config() - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index") - self.assertFalse(vpp_session.query_vpp_config()) - - -@tag_run_solo -@tag_fixme_vpp_workers -class BFD6TestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD) (IPv6) """ - - pg0 = None - vpp_clock_offset = None - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFD6TestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces([0]) - cls.pg0.config_ip6() - cls.pg0.configure_ipv6_neighbors() - cls.pg0.admin_up() - cls.pg0.resolve_ndp() - cls.create_loopback_interfaces(1) - cls.loopback0 = cls.lo_interfaces[0] - cls.loopback0.config_ip6() - cls.loopback0.admin_up() - - except Exception: - super(BFD6TestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFD6TestCase, cls).tearDownClass() - - def setUp(self): - super(BFD6TestCase, self).setUp() - self.factory = AuthKeyFactory() - self.vapi.want_bfd_events() - self.pg0.enable_capture() - try: - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip6, - af=AF_INET6) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession(self, self.pg0, AF_INET6) - self.logger.debug(self.vapi.cli("show adj nbr")) - except BaseException: - self.vapi.want_bfd_events(enable_disable=0) - raise - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=0) - self.vapi.collect_events() # clear the event queue - super(BFD6TestCase, self).tearDown() - - def test_session_up(self): - """ bring BFD session up """ - bfd_session_up(self) - - def test_session_up_by_ip(self): - """ bring BFD session up - first frame looked up by address pair """ - self.logger.info("BFD: Sending Slow control frame") - self.test_session.update(my_discriminator=randint(0, 40000000)) - self.test_session.send_packet() - self.pg0.enable_capture() - p = self.pg0.wait_for_packet(1) - self.assert_equal(p[BFD].your_discriminator, - self.test_session.my_discriminator, - "BFD - your discriminator") - self.assert_equal(p[BFD].state, BFDState.init, BFDState) - self.test_session.update(your_discriminator=p[BFD].my_discriminator, - state=BFDState.up) - self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.init) - self.logger.info("BFD: Sending Up") - self.test_session.send_packet() - self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - verify_event(self, e, expected_state=BFDState.up) - self.logger.info("BFD: Session is Up") - self.test_session.update(state=BFDState.up) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_hold_up(self): - """ hold BFD session up """ - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - wait_for_bfd_packet(self) - self.test_session.send_packet() - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_echo_looped_back(self): - """ echo packets looped back """ - # don't need a session in this case.. - self.vpp_session.remove_vpp_config() - self.pg0.enable_capture() - echo_packet_count = 10 - # random source port low enough to increment a few times.. - udp_sport_tx = randint(1, 50000) - udp_sport_rx = udp_sport_tx - echo_packet = (Ether(src=self.pg0.remote_mac, - dst=self.pg0.local_mac) / - IPv6(src=self.pg0.remote_ip6, - dst=self.pg0.remote_ip6) / - UDP(dport=BFD.udp_dport_echo) / - Raw("this should be looped back")) - for dummy in range(echo_packet_count): - self.sleep(.01, "delay between echo packets") - echo_packet[UDP].sport = udp_sport_tx - udp_sport_tx += 1 - self.logger.debug(ppp("Sending packet:", echo_packet)) - self.pg0.add_stream(echo_packet) - self.pg_start() - for dummy in range(echo_packet_count): - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - ether = p[Ether] - self.assert_equal(self.pg0.remote_mac, - ether.dst, "Destination MAC") - self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC") - ip = p[IPv6] - self.assert_equal(self.pg0.remote_ip6, ip.dst, "Destination IP") - self.assert_equal(self.pg0.remote_ip6, ip.src, "Destination IP") - udp = p[UDP] - self.assert_equal(udp.dport, BFD.udp_dport_echo, - "UDP destination port") - self.assert_equal(udp.sport, udp_sport_rx, "UDP source port") - udp_sport_rx += 1 - # need to compare the hex payload here, otherwise BFD_vpp_echo - # gets in way - self.assertEqual(scapy.compat.raw(p[UDP].payload), - scapy.compat.raw(echo_packet[UDP].payload), - "Received packet is not the echo packet sent") - self.assert_equal(udp_sport_tx, udp_sport_rx, "UDP source port (== " - "ECHO packet identifier for test purposes)") - self.assert_equal(udp_sport_tx, udp_sport_rx, "UDP source port (== " - "ECHO packet identifier for test purposes)") - - def test_echo(self): - """ echo function """ - bfd_session_up(self) - self.test_session.update(required_min_echo_rx=150000) - self.test_session.send_packet() - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - # echo shouldn't work without echo source set - for dummy in range(10): - sleep = self.vpp_session.required_min_rx / USEC_IN_SEC - self.sleep(sleep, "delay before sending bfd packet") - self.test_session.send_packet() - p = wait_for_bfd_packet( - self, pcap_time_min=time.time() - self.vpp_clock_offset) - self.assert_equal(p[BFD].required_min_rx_interval, - self.vpp_session.required_min_rx, - "BFD required min rx interval") - self.test_session.send_packet() - self.vapi.bfd_udp_set_echo_source( - sw_if_index=self.loopback0.sw_if_index) - echo_seen = False - # should be turned on - loopback echo packets - for dummy in range(3): - loop_until = time.time() + 0.75 * detection_time - while time.time() < loop_until: - p = self.pg0.wait_for_packet(1) - self.logger.debug(ppp("Got packet:", p)) - if p[UDP].dport == BFD.udp_dport_echo: - self.assert_equal( - p[IPv6].dst, self.pg0.local_ip6, "BFD ECHO dst IP") - self.assertNotEqual(p[IPv6].src, self.loopback0.local_ip6, - "BFD ECHO src IP equal to loopback IP") - self.logger.debug(ppp("Looping back packet:", p)) - self.assert_equal(p[Ether].dst, self.pg0.remote_mac, - "ECHO packet destination MAC address") - p[Ether].dst = self.pg0.local_mac - self.pg0.add_stream(p) - self.pg_start() - echo_seen = True - elif p.haslayer(BFD): - if echo_seen: - self.assertGreaterEqual( - p[BFD].required_min_rx_interval, - 1000000) - if "P" in p.sprintf("%BFD.flags%"): - final = self.test_session.create_packet() - final[BFD].flags = "F" - self.test_session.send_packet(final) - else: - raise Exception(ppp("Received unknown packet:", p)) - - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - self.test_session.send_packet() - self.assertTrue(echo_seen, "No echo packets received") - - def test_intf_deleted(self): - """ interface with bfd session deleted """ - intf = VppLoInterface(self) - intf.config_ip6() - intf.admin_up() - sw_if_index = intf.sw_if_index - vpp_session = VppBFDUDPSession( - self, intf, intf.remote_ip6, af=AF_INET6) - vpp_session.add_vpp_config() - vpp_session.admin_up() - intf.remove_vpp_config() - e = self.vapi.wait_for_event(1, "bfd_udp_session_event") - self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index") - self.assertFalse(vpp_session.query_vpp_config()) - - -@tag_run_solo -class BFDFIBTestCase(VppTestCase): - """ BFD-FIB interactions (IPv6) """ - - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFDFIBTestCase, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(BFDFIBTestCase, cls).tearDownClass() - - def setUp(self): - super(BFDFIBTestCase, self).setUp() - self.create_pg_interfaces(range(1)) - - self.vapi.want_bfd_events() - self.pg0.enable_capture() - - for i in self.pg_interfaces: - i.admin_up() - i.config_ip6() - i.configure_ipv6_neighbors() - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=False) - - super(BFDFIBTestCase, self).tearDown() - - @staticmethod - def pkt_is_not_data_traffic(p): - """ not data traffic implies BFD or the usual IPv6 ND/RA""" - if p.haslayer(BFD) or is_ipv6_misc(p): - return True - return False - - def test_session_with_fib(self): - """ BFD-FIB interactions """ - - # packets to match against both of the routes - p = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IPv6(src="3001::1", dst="2001::1") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)), - (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IPv6(src="3001::1", dst="2002::1") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100))] - - # A recursive and a non-recursive route via a next-hop that - # will have a BFD session - ip_2001_s_64 = VppIpRoute(self, "2001::", 64, - [VppRoutePath(self.pg0.remote_ip6, - self.pg0.sw_if_index)]) - ip_2002_s_64 = VppIpRoute(self, "2002::", 64, - [VppRoutePath(self.pg0.remote_ip6, - 0xffffffff)]) - ip_2001_s_64.add_vpp_config() - ip_2002_s_64.add_vpp_config() - - # bring the session up now the routes are present - self.vpp_session = VppBFDUDPSession(self, - self.pg0, - self.pg0.remote_ip6, - af=AF_INET6) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession(self, self.pg0, AF_INET6) - - # session is up - traffic passes - bfd_session_up(self) - - self.pg0.add_stream(p) - self.pg_start() - for packet in p: - captured = self.pg0.wait_for_packet( - 1, - filter_out_fn=self.pkt_is_not_data_traffic) - self.assertEqual(captured[IPv6].dst, - packet[IPv6].dst) - - # session is up - traffic is dropped - bfd_session_down(self) - - self.pg0.add_stream(p) - self.pg_start() - with self.assertRaises(CaptureTimeoutError): - self.pg0.wait_for_packet(1, self.pkt_is_not_data_traffic) - - # session is up - traffic passes - bfd_session_up(self) - - self.pg0.add_stream(p) - self.pg_start() - for packet in p: - captured = self.pg0.wait_for_packet( - 1, - filter_out_fn=self.pkt_is_not_data_traffic) - self.assertEqual(captured[IPv6].dst, - packet[IPv6].dst) - - -@unittest.skipUnless(running_extended_tests, "part of extended tests") -class BFDTunTestCase(VppTestCase): - """ BFD over GRE tunnel """ - - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFDTunTestCase, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(BFDTunTestCase, cls).tearDownClass() - - def setUp(self): - super(BFDTunTestCase, self).setUp() - self.create_pg_interfaces(range(1)) - - self.vapi.want_bfd_events() - self.pg0.enable_capture() - - for i in self.pg_interfaces: - i.admin_up() - i.config_ip4() - i.resolve_arp() - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=0) - - super(BFDTunTestCase, self).tearDown() - - @staticmethod - def pkt_is_not_data_traffic(p): - """ not data traffic implies BFD or the usual IPv6 ND/RA""" - if p.haslayer(BFD) or is_ipv6_misc(p): - return True - return False - - def test_bfd_o_gre(self): - """ BFD-o-GRE """ - - # A GRE interface over which to run a BFD session - gre_if = VppGreInterface(self, - self.pg0.local_ip4, - self.pg0.remote_ip4) - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip4() - - # bring the session up now the routes are present - self.vpp_session = VppBFDUDPSession(self, - gre_if, - gre_if.remote_ip4, - is_tunnel=True) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - - self.test_session = BFDTestSession( - self, gre_if, AF_INET, - tunnel_header=(IP(src=self.pg0.remote_ip4, - dst=self.pg0.local_ip4) / - GRE()), - phy_interface=self.pg0) - - # packets to match against both of the routes - p = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(src=self.pg0.remote_ip4, dst=gre_if.remote_ip4) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100))] - - # session is up - traffic passes - bfd_session_up(self) - - self.send_and_expect(self.pg0, p, self.pg0) - - # bring session down - bfd_session_down(self) - - -@tag_run_solo -class BFDSHA1TestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD) (SHA1 auth) """ - - pg0 = None - vpp_clock_offset = None - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFDSHA1TestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces([0]) - cls.pg0.config_ip4() - cls.pg0.admin_up() - cls.pg0.resolve_arp() - - except Exception: - super(BFDSHA1TestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFDSHA1TestCase, cls).tearDownClass() - - def setUp(self): - super(BFDSHA1TestCase, self).setUp() - self.factory = AuthKeyFactory() - self.vapi.want_bfd_events() - self.pg0.enable_capture() - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=False) - self.vapi.collect_events() # clear the event queue - super(BFDSHA1TestCase, self).tearDown() - - def test_session_up(self): - """ bring BFD session up """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, - sha1_key=key) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - - def test_hold_up(self): - """ hold BFD session up """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, - sha1_key=key) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - wait_for_bfd_packet(self) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_hold_up_meticulous(self): - """ hold BFD session up - meticulous auth """ - key = self.factory.create_random_key( - self, BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - # specify sequence number so that it wraps - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id, - our_seq_number=0xFFFFFFFF - 4) - bfd_session_up(self) - for dummy in range(30): - wait_for_bfd_packet(self) - self.test_session.inc_seq_num() - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_send_bad_seq_number(self): - """ session is not kept alive by msgs with bad sequence numbers""" - key = self.factory.create_random_key( - self, BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - send_until = time.time() + 2 * detection_time - while time.time() < send_until: - self.test_session.send_packet() - self.sleep(0.7 * self.vpp_session.required_min_rx / USEC_IN_SEC, - "time between bfd packets") - e = self.vapi.collect_events() - # session should be down now, because the sequence numbers weren't - # updated - self.assert_equal(len(e), 1, "number of bfd events") - verify_event(self, e[0], expected_state=BFDState.down) - - def execute_rogue_session_scenario(self, vpp_bfd_udp_session, - legitimate_test_session, - rogue_test_session, - rogue_bfd_values=None): - """ execute a rogue session interaction scenario - - 1. create vpp session, add config - 2. bring the legitimate session up - 3. copy the bfd values from legitimate session to rogue session - 4. apply rogue_bfd_values to rogue session - 5. set rogue session state to down - 6. send message to take the session down from the rogue session - 7. assert that the legitimate session is unaffected - """ - - self.vpp_session = vpp_bfd_udp_session - self.vpp_session.add_vpp_config() - self.test_session = legitimate_test_session - # bring vpp session up - bfd_session_up(self) - # send packet from rogue session - rogue_test_session.update( - my_discriminator=self.test_session.my_discriminator, - your_discriminator=self.test_session.your_discriminator, - desired_min_tx=self.test_session.desired_min_tx, - required_min_rx=self.test_session.required_min_rx, - detect_mult=self.test_session.detect_mult, - diag=self.test_session.diag, - state=self.test_session.state, - auth_type=self.test_session.auth_type) - if rogue_bfd_values: - rogue_test_session.update(**rogue_bfd_values) - rogue_test_session.update(state=BFDState.down) - rogue_test_session.send_packet() - wait_for_bfd_packet(self) - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - - def test_mismatch_auth(self): - """ session is not brought down by unauthenticated msg """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=key) - legitimate_test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id) - rogue_test_session = BFDTestSession(self, self.pg0, AF_INET) - self.execute_rogue_session_scenario(vpp_session, - legitimate_test_session, - rogue_test_session) - - def test_mismatch_bfd_key_id(self): - """ session is not brought down by msg with non-existent key-id """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=key) - # pick a different random bfd key id - x = randint(0, 255) - while x == vpp_session.bfd_key_id: - x = randint(0, 255) - legitimate_test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id) - rogue_test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, bfd_key_id=x) - self.execute_rogue_session_scenario(vpp_session, - legitimate_test_session, - rogue_test_session) - - def test_mismatched_auth_type(self): - """ session is not brought down by msg with wrong auth type """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=key) - legitimate_test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id) - rogue_test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id) - self.execute_rogue_session_scenario( - vpp_session, legitimate_test_session, rogue_test_session, - {'auth_type': BFDAuthType.keyed_md5}) - - def test_restart(self): - """ simulate remote peer restart and resynchronization """ - key = self.factory.create_random_key( - self, BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id, our_seq_number=0) - bfd_session_up(self) - # don't send any packets for 2*detection_time - detection_time = self.test_session.detect_mult *\ - self.vpp_session.required_min_rx / USEC_IN_SEC - self.sleep(2 * detection_time, "simulating peer restart") - events = self.vapi.collect_events() - self.assert_equal(len(events), 1, "number of bfd events") - verify_event(self, events[0], expected_state=BFDState.down) - self.test_session.update(state=BFDState.down) - # reset sequence number - self.test_session.our_seq_number = 0 - self.test_session.vpp_seq_number = None - # now throw away any pending packets - self.pg0.enable_capture() - self.test_session.my_discriminator = 0 - bfd_session_up(self) - - -@tag_run_solo -class BFDAuthOnOffTestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD) (changing auth) """ - - pg0 = None - vpp_session = None - test_session = None - - @classmethod - def setUpClass(cls): - super(BFDAuthOnOffTestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces([0]) - cls.pg0.config_ip4() - cls.pg0.admin_up() - cls.pg0.resolve_arp() - - except Exception: - super(BFDAuthOnOffTestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFDAuthOnOffTestCase, cls).tearDownClass() - - def setUp(self): - super(BFDAuthOnOffTestCase, self).setUp() - self.factory = AuthKeyFactory() - self.vapi.want_bfd_events() - self.pg0.enable_capture() - - def tearDown(self): - if not self.vpp_dead: - self.vapi.want_bfd_events(enable_disable=False) - self.vapi.collect_events() # clear the event queue - super(BFDAuthOnOffTestCase, self).tearDown() - - def test_auth_on_immediate(self): - """ turn auth on without disturbing session state (immediate) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession(self, self.pg0, AF_INET) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.vpp_session.activate_auth(key) - self.test_session.bfd_key_id = self.vpp_session.bfd_key_id - self.test_session.sha1_key = key - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_auth_off_immediate(self): - """ turn auth off without disturbing session state (immediate) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - # self.vapi.want_bfd_events(enable_disable=0) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.inc_seq_num() - self.test_session.send_packet() - self.vpp_session.deactivate_auth() - self.test_session.bfd_key_id = None - self.test_session.sha1_key = None - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.inc_seq_num() - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_auth_change_key_immediate(self): - """ change auth key without disturbing session state (immediate) """ - key1 = self.factory.create_random_key(self) - key1.add_vpp_config() - key2 = self.factory.create_random_key(self) - key2.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key1) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key1, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.vpp_session.activate_auth(key2) - self.test_session.bfd_key_id = self.vpp_session.bfd_key_id - self.test_session.sha1_key = key2 - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_auth_on_delayed(self): - """ turn auth on without disturbing session state (delayed) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession(self, self.pg0, AF_INET) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - wait_for_bfd_packet(self) - self.test_session.send_packet() - self.vpp_session.activate_auth(key, delayed=True) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.test_session.bfd_key_id = self.vpp_session.bfd_key_id - self.test_session.sha1_key = key - self.test_session.send_packet() - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_auth_off_delayed(self): - """ turn auth off without disturbing session state (delayed) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key) - self.vpp_session.add_vpp_config() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.vpp_session.deactivate_auth(delayed=True) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.test_session.bfd_key_id = None - self.test_session.sha1_key = None - self.test_session.send_packet() - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - def test_auth_change_key_delayed(self): - """ change auth key without disturbing session state (delayed) """ - key1 = self.factory.create_random_key(self) - key1.add_vpp_config() - key2 = self.factory.create_random_key(self) - key2.add_vpp_config() - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip4, sha1_key=key1) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = BFDTestSession( - self, self.pg0, AF_INET, sha1_key=key1, - bfd_key_id=self.vpp_session.bfd_key_id) - bfd_session_up(self) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.vpp_session.activate_auth(key2, delayed=True) - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.test_session.bfd_key_id = self.vpp_session.bfd_key_id - self.test_session.sha1_key = key2 - self.test_session.send_packet() - for dummy in range(self.test_session.detect_mult * 2): - p = wait_for_bfd_packet(self) - self.assert_equal(p[BFD].state, BFDState.up, BFDState) - self.test_session.send_packet() - self.assert_equal(self.vpp_session.state, BFDState.up, BFDState) - self.assert_equal(len(self.vapi.collect_events()), 0, - "number of bfd events") - - -@tag_run_solo -class BFDCLITestCase(VppTestCase): - """Bidirectional Forwarding Detection (BFD) (CLI) """ - pg0 = None - - @classmethod - def setUpClass(cls): - super(BFDCLITestCase, cls).setUpClass() - cls.vapi.cli("set log class bfd level debug") - try: - cls.create_pg_interfaces((0,)) - cls.pg0.config_ip4() - cls.pg0.config_ip6() - cls.pg0.resolve_arp() - cls.pg0.resolve_ndp() - - except Exception: - super(BFDCLITestCase, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(BFDCLITestCase, cls).tearDownClass() - - def setUp(self): - super(BFDCLITestCase, self).setUp() - self.factory = AuthKeyFactory() - self.pg0.enable_capture() - - def tearDown(self): - try: - self.vapi.want_bfd_events(enable_disable=False) - except UnexpectedApiReturnValueError: - # some tests aren't subscribed, so this is not an issue - pass - self.vapi.collect_events() # clear the event queue - super(BFDCLITestCase, self).tearDown() - - def cli_verify_no_response(self, cli): - """ execute a CLI, asserting that the response is empty """ - self.assert_equal(self.vapi.cli(cli), - "", - "CLI command response") - - def cli_verify_response(self, cli, expected): - """ execute a CLI, asserting that the response matches expectation """ - try: - reply = self.vapi.cli(cli) - except CliFailedCommandError as cli_error: - reply = str(cli_error) - self.assert_equal(reply.strip(), - expected, - "CLI command response") - - def test_show(self): - """ show commands """ - k1 = self.factory.create_random_key(self) - k1.add_vpp_config() - k2 = self.factory.create_random_key( - self, auth_type=BFDAuthType.meticulous_keyed_sha1) - k2.add_vpp_config() - s1 = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - s1.add_vpp_config() - s2 = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip6, af=AF_INET6, - sha1_key=k2) - s2.add_vpp_config() - self.logger.info(self.vapi.ppcli("show bfd keys")) - self.logger.info(self.vapi.ppcli("show bfd sessions")) - self.logger.info(self.vapi.ppcli("show bfd")) - - def test_set_del_sha1_key(self): - """ set/delete SHA1 auth key """ - k = self.factory.create_random_key(self) - self.registry.register(k, self.logger) - self.cli_verify_no_response( - "bfd key set conf-key-id %s type keyed-sha1 secret %s" % - (k.conf_key_id, - "".join("{:02x}".format(scapy.compat.orb(c)) for c in k.key))) - self.assertTrue(k.query_vpp_config()) - self.vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=k) - self.vpp_session.add_vpp_config() - self.test_session = \ - BFDTestSession(self, self.pg0, AF_INET, sha1_key=k, - bfd_key_id=self.vpp_session.bfd_key_id) - self.vapi.want_bfd_events() - bfd_session_up(self) - bfd_session_down(self) - # try to replace the secret for the key - should fail because the key - # is in-use - k2 = self.factory.create_random_key(self) - self.cli_verify_response( - "bfd key set conf-key-id %s type keyed-sha1 secret %s" % - (k.conf_key_id, - "".join("{:02x}".format(scapy.compat.orb(c)) for c in k2.key)), - "bfd key set: `bfd_auth_set_key' API call failed, " - "rv=-103:BFD object in use") - # manipulating the session using old secret should still work - bfd_session_up(self) - bfd_session_down(self) - self.vpp_session.remove_vpp_config() - self.cli_verify_no_response( - "bfd key del conf-key-id %s" % k.conf_key_id) - self.assertFalse(k.query_vpp_config()) - - def test_set_del_meticulous_sha1_key(self): - """ set/delete meticulous SHA1 auth key """ - k = self.factory.create_random_key( - self, auth_type=BFDAuthType.meticulous_keyed_sha1) - self.registry.register(k, self.logger) - self.cli_verify_no_response( - "bfd key set conf-key-id %s type meticulous-keyed-sha1 secret %s" % - (k.conf_key_id, - "".join("{:02x}".format(scapy.compat.orb(c)) for c in k.key))) - self.assertTrue(k.query_vpp_config()) - self.vpp_session = VppBFDUDPSession(self, self.pg0, - self.pg0.remote_ip6, af=AF_INET6, - sha1_key=k) - self.vpp_session.add_vpp_config() - self.vpp_session.admin_up() - self.test_session = \ - BFDTestSession(self, self.pg0, AF_INET6, sha1_key=k, - bfd_key_id=self.vpp_session.bfd_key_id) - self.vapi.want_bfd_events() - bfd_session_up(self) - bfd_session_down(self) - # try to replace the secret for the key - should fail because the key - # is in-use - k2 = self.factory.create_random_key(self) - self.cli_verify_response( - "bfd key set conf-key-id %s type keyed-sha1 secret %s" % - (k.conf_key_id, - "".join("{:02x}".format(scapy.compat.orb(c)) for c in k2.key)), - "bfd key set: `bfd_auth_set_key' API call failed, " - "rv=-103:BFD object in use") - # manipulating the session using old secret should still work - bfd_session_up(self) - bfd_session_down(self) - self.vpp_session.remove_vpp_config() - self.cli_verify_no_response( - "bfd key del conf-key-id %s" % k.conf_key_id) - self.assertFalse(k.query_vpp_config()) - - def test_add_mod_del_bfd_udp(self): - """ create/modify/delete IPv4 BFD UDP session """ - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4) - self.registry.register(vpp_session, self.logger) - cli_add_cmd = "bfd udp session add interface %s local-addr %s " \ - "peer-addr %s desired-min-tx %s required-min-rx %s "\ - "detect-mult %s" % (self.pg0.name, self.pg0.local_ip4, - self.pg0.remote_ip4, - vpp_session.desired_min_tx, - vpp_session.required_min_rx, - vpp_session.detect_mult) - self.cli_verify_no_response(cli_add_cmd) - # 2nd add should fail - self.cli_verify_response( - cli_add_cmd, - "bfd udp session add: `bfd_add_add_session' API call" - " failed, rv=-101:Duplicate BFD object") - verify_bfd_session_config(self, vpp_session) - mod_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, - required_min_rx=2 * vpp_session.required_min_rx, - desired_min_tx=3 * vpp_session.desired_min_tx, - detect_mult=4 * vpp_session.detect_mult) - self.cli_verify_no_response( - "bfd udp session mod interface %s local-addr %s peer-addr %s " - "desired-min-tx %s required-min-rx %s detect-mult %s" % - (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4, - mod_session.desired_min_tx, mod_session.required_min_rx, - mod_session.detect_mult)) - verify_bfd_session_config(self, mod_session) - cli_del_cmd = "bfd udp session del interface %s local-addr %s "\ - "peer-addr %s" % (self.pg0.name, - self.pg0.local_ip4, self.pg0.remote_ip4) - self.cli_verify_no_response(cli_del_cmd) - # 2nd del is expected to fail - self.cli_verify_response( - cli_del_cmd, "bfd udp session del: `bfd_udp_del_session' API call" - " failed, rv=-102:No such BFD object") - self.assertFalse(vpp_session.query_vpp_config()) - - def test_add_mod_del_bfd_udp6(self): - """ create/modify/delete IPv6 BFD UDP session """ - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip6, af=AF_INET6) - self.registry.register(vpp_session, self.logger) - cli_add_cmd = "bfd udp session add interface %s local-addr %s " \ - "peer-addr %s desired-min-tx %s required-min-rx %s "\ - "detect-mult %s" % (self.pg0.name, self.pg0.local_ip6, - self.pg0.remote_ip6, - vpp_session.desired_min_tx, - vpp_session.required_min_rx, - vpp_session.detect_mult) - self.cli_verify_no_response(cli_add_cmd) - # 2nd add should fail - self.cli_verify_response( - cli_add_cmd, - "bfd udp session add: `bfd_add_add_session' API call" - " failed, rv=-101:Duplicate BFD object") - verify_bfd_session_config(self, vpp_session) - mod_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip6, af=AF_INET6, - required_min_rx=2 * vpp_session.required_min_rx, - desired_min_tx=3 * vpp_session.desired_min_tx, - detect_mult=4 * vpp_session.detect_mult) - self.cli_verify_no_response( - "bfd udp session mod interface %s local-addr %s peer-addr %s " - "desired-min-tx %s required-min-rx %s detect-mult %s" % - (self.pg0.name, self.pg0.local_ip6, self.pg0.remote_ip6, - mod_session.desired_min_tx, - mod_session.required_min_rx, mod_session.detect_mult)) - verify_bfd_session_config(self, mod_session) - cli_del_cmd = "bfd udp session del interface %s local-addr %s "\ - "peer-addr %s" % (self.pg0.name, - self.pg0.local_ip6, self.pg0.remote_ip6) - self.cli_verify_no_response(cli_del_cmd) - # 2nd del is expected to fail - self.cli_verify_response( - cli_del_cmd, - "bfd udp session del: `bfd_udp_del_session' API call" - " failed, rv=-102:No such BFD object") - self.assertFalse(vpp_session.query_vpp_config()) - - def test_add_mod_del_bfd_udp_auth(self): - """ create/modify/delete IPv4 BFD UDP session (authenticated) """ - key = self.factory.create_random_key(self) - key.add_vpp_config() - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=key) - self.registry.register(vpp_session, self.logger) - cli_add_cmd = "bfd udp session add interface %s local-addr %s " \ - "peer-addr %s desired-min-tx %s required-min-rx %s "\ - "detect-mult %s conf-key-id %s bfd-key-id %s"\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4, - vpp_session.desired_min_tx, vpp_session.required_min_rx, - vpp_session.detect_mult, key.conf_key_id, - vpp_session.bfd_key_id) - self.cli_verify_no_response(cli_add_cmd) - # 2nd add should fail - self.cli_verify_response( - cli_add_cmd, - "bfd udp session add: `bfd_add_add_session' API call" - " failed, rv=-101:Duplicate BFD object") - verify_bfd_session_config(self, vpp_session) - mod_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip4, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id, - required_min_rx=2 * vpp_session.required_min_rx, - desired_min_tx=3 * vpp_session.desired_min_tx, - detect_mult=4 * vpp_session.detect_mult) - self.cli_verify_no_response( - "bfd udp session mod interface %s local-addr %s peer-addr %s " - "desired-min-tx %s required-min-rx %s detect-mult %s" % - (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4, - mod_session.desired_min_tx, - mod_session.required_min_rx, mod_session.detect_mult)) - verify_bfd_session_config(self, mod_session) - cli_del_cmd = "bfd udp session del interface %s local-addr %s "\ - "peer-addr %s" % (self.pg0.name, - self.pg0.local_ip4, self.pg0.remote_ip4) - self.cli_verify_no_response(cli_del_cmd) - # 2nd del is expected to fail - self.cli_verify_response( - cli_del_cmd, - "bfd udp session del: `bfd_udp_del_session' API call" - " failed, rv=-102:No such BFD object") - self.assertFalse(vpp_session.query_vpp_config()) - - def test_add_mod_del_bfd_udp6_auth(self): - """ create/modify/delete IPv6 BFD UDP session (authenticated) """ - key = self.factory.create_random_key( - self, auth_type=BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - vpp_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip6, af=AF_INET6, sha1_key=key) - self.registry.register(vpp_session, self.logger) - cli_add_cmd = "bfd udp session add interface %s local-addr %s " \ - "peer-addr %s desired-min-tx %s required-min-rx %s "\ - "detect-mult %s conf-key-id %s bfd-key-id %s" \ - % (self.pg0.name, self.pg0.local_ip6, self.pg0.remote_ip6, - vpp_session.desired_min_tx, vpp_session.required_min_rx, - vpp_session.detect_mult, key.conf_key_id, - vpp_session.bfd_key_id) - self.cli_verify_no_response(cli_add_cmd) - # 2nd add should fail - self.cli_verify_response( - cli_add_cmd, - "bfd udp session add: `bfd_add_add_session' API call" - " failed, rv=-101:Duplicate BFD object") - verify_bfd_session_config(self, vpp_session) - mod_session = VppBFDUDPSession( - self, self.pg0, self.pg0.remote_ip6, af=AF_INET6, sha1_key=key, - bfd_key_id=vpp_session.bfd_key_id, - required_min_rx=2 * vpp_session.required_min_rx, - desired_min_tx=3 * vpp_session.desired_min_tx, - detect_mult=4 * vpp_session.detect_mult) - self.cli_verify_no_response( - "bfd udp session mod interface %s local-addr %s peer-addr %s " - "desired-min-tx %s required-min-rx %s detect-mult %s" % - (self.pg0.name, self.pg0.local_ip6, self.pg0.remote_ip6, - mod_session.desired_min_tx, - mod_session.required_min_rx, mod_session.detect_mult)) - verify_bfd_session_config(self, mod_session) - cli_del_cmd = "bfd udp session del interface %s local-addr %s "\ - "peer-addr %s" % (self.pg0.name, - self.pg0.local_ip6, self.pg0.remote_ip6) - self.cli_verify_no_response(cli_del_cmd) - # 2nd del is expected to fail - self.cli_verify_response( - cli_del_cmd, - "bfd udp session del: `bfd_udp_del_session' API call" - " failed, rv=-102:No such BFD object") - self.assertFalse(vpp_session.query_vpp_config()) - - def test_auth_on_off(self): - """ turn authentication on and off """ - key = self.factory.create_random_key( - self, auth_type=BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - auth_session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key) - session.add_vpp_config() - cli_activate = \ - "bfd udp session auth activate interface %s local-addr %s "\ - "peer-addr %s conf-key-id %s bfd-key-id %s"\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4, - key.conf_key_id, auth_session.bfd_key_id) - self.cli_verify_no_response(cli_activate) - verify_bfd_session_config(self, auth_session) - self.cli_verify_no_response(cli_activate) - verify_bfd_session_config(self, auth_session) - cli_deactivate = \ - "bfd udp session auth deactivate interface %s local-addr %s "\ - "peer-addr %s "\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4) - self.cli_verify_no_response(cli_deactivate) - verify_bfd_session_config(self, session) - self.cli_verify_no_response(cli_deactivate) - verify_bfd_session_config(self, session) - - def test_auth_on_off_delayed(self): - """ turn authentication on and off (delayed) """ - key = self.factory.create_random_key( - self, auth_type=BFDAuthType.meticulous_keyed_sha1) - key.add_vpp_config() - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - auth_session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4, - sha1_key=key) - session.add_vpp_config() - cli_activate = \ - "bfd udp session auth activate interface %s local-addr %s "\ - "peer-addr %s conf-key-id %s bfd-key-id %s delayed yes"\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4, - key.conf_key_id, auth_session.bfd_key_id) - self.cli_verify_no_response(cli_activate) - verify_bfd_session_config(self, auth_session) - self.cli_verify_no_response(cli_activate) - verify_bfd_session_config(self, auth_session) - cli_deactivate = \ - "bfd udp session auth deactivate interface %s local-addr %s "\ - "peer-addr %s delayed yes"\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4) - self.cli_verify_no_response(cli_deactivate) - verify_bfd_session_config(self, session) - self.cli_verify_no_response(cli_deactivate) - verify_bfd_session_config(self, session) - - def test_admin_up_down(self): - """ put session admin-up and admin-down """ - session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4) - session.add_vpp_config() - cli_down = \ - "bfd udp session set-flags admin down interface %s local-addr %s "\ - "peer-addr %s "\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4) - cli_up = \ - "bfd udp session set-flags admin up interface %s local-addr %s "\ - "peer-addr %s "\ - % (self.pg0.name, self.pg0.local_ip4, self.pg0.remote_ip4) - self.cli_verify_no_response(cli_down) - verify_bfd_session_config(self, session, state=BFDState.admin_down) - self.cli_verify_no_response(cli_up) - verify_bfd_session_config(self, session, state=BFDState.down) - - def test_set_del_udp_echo_source(self): - """ set/del udp echo source """ - self.create_loopback_interfaces(1) - self.loopback0 = self.lo_interfaces[0] - self.loopback0.admin_up() - self.cli_verify_response("show bfd echo-source", - "UDP echo source is not set.") - cli_set = "bfd udp echo-source set interface %s" % self.loopback0.name - self.cli_verify_no_response(cli_set) - self.cli_verify_response("show bfd echo-source", - "UDP echo source is: %s\n" - "IPv4 address usable as echo source: none\n" - "IPv6 address usable as echo source: none" % - self.loopback0.name) - self.loopback0.config_ip4() - echo_ip4 = str(ipaddress.IPv4Address(int(ipaddress.IPv4Address( - self.loopback0.local_ip4)) ^ 1)) - self.cli_verify_response("show bfd echo-source", - "UDP echo source is: %s\n" - "IPv4 address usable as echo source: %s\n" - "IPv6 address usable as echo source: none" % - (self.loopback0.name, echo_ip4)) - echo_ip6 = str(ipaddress.IPv6Address(int(ipaddress.IPv6Address( - self.loopback0.local_ip6)) ^ 1)) - self.loopback0.config_ip6() - self.cli_verify_response("show bfd echo-source", - "UDP echo source is: %s\n" - "IPv4 address usable as echo source: %s\n" - "IPv6 address usable as echo source: %s" % - (self.loopback0.name, echo_ip4, echo_ip6)) - cli_del = "bfd udp echo-source del" - self.cli_verify_no_response(cli_del) - self.cli_verify_response("show bfd echo-source", - "UDP echo source is not set.") - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/bier/test/test_bier.py b/src/vnet/bier/test/test_bier.py deleted file mode 100644 index 2f649bbde53..00000000000 --- a/src/vnet/bier/test/test_bier.py +++ /dev/null @@ -1,862 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -from framework import VppTestCase, VppTestRunner, running_extended_tests -from vpp_ip import DpoProto -from vpp_ip_route import VppIpRoute, VppRoutePath, \ - VppMplsTable, VppIpMRoute, VppMRoutePath, VppIpTable, \ - MPLS_LABEL_INVALID, \ - VppMplsLabel, FibPathProto, FibPathType -from vpp_bier import BIER_HDR_PAYLOAD, VppBierImp, VppBierDispEntry, \ - VppBierDispTable, VppBierTable, VppBierTableID, VppBierRoute -from vpp_udp_encap import VppUdpEncap -from vpp_papi import VppEnum - -import scapy.compat -from scapy.packet import Raw -from scapy.layers.l2 import Ether -from scapy.layers.inet import IP, UDP -from scapy.layers.inet6 import IPv6 -from scapy.contrib.mpls import MPLS -from scapy.contrib.bier import BIER, BIERLength, BIFT - -NUM_PKTS = 67 - - -class TestBFIB(VppTestCase): - """ BIER FIB Test Case """ - - def test_bfib(self): - """ BFIB Unit Tests """ - error = self.vapi.cli("test bier") - - if error: - self.logger.critical(error) - self.assertNotIn("Failed", error) - - -class TestBier(VppTestCase): - """ BIER Test Case """ - - def setUp(self): - super(TestBier, self).setUp() - - # create 2 pg interfaces - self.create_pg_interfaces(range(3)) - - # create the default MPLS table - self.tables = [] - tbl = VppMplsTable(self, 0) - tbl.add_vpp_config() - self.tables.append(tbl) - - tbl = VppIpTable(self, 10) - tbl.add_vpp_config() - self.tables.append(tbl) - - # setup both interfaces - for i in self.pg_interfaces: - if i == self.pg2: - i.set_table_ip4(10) - i.admin_up() - i.config_ip4() - i.resolve_arp() - i.enable_mpls() - - def tearDown(self): - for i in self.pg_interfaces: - i.disable_mpls() - i.unconfig_ip4() - i.set_table_ip4(0) - i.admin_down() - super(TestBier, self).tearDown() - - def bier_midpoint(self, hdr_len_id, n_bytes, max_bp): - """BIER midpoint""" - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(0, 0, hdr_len_id) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - # - # A packet with no bits set gets dropped - # - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=hdr_len_id) / - IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / - UDP(sport=1234, dport=1234) / - Raw()) - pkts = [p] - - self.send_and_assert_no_replies(self.pg0, pkts, - "Empty Bit-String") - - # - # Add a BIER route for each bit-position in the table via a different - # next-hop. Testing whether the BIER walk and replicate forwarding - # function works for all bit posisitons. - # - nh_routes = [] - bier_routes = [] - for i in range(1, max_bp+1): - nh = "10.0.%d.%d" % (i / 255, i % 255) - nh_routes.append( - VppIpRoute(self, nh, 32, - [VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index, - labels=[VppMplsLabel(2000+i)])])) - nh_routes[-1].add_vpp_config() - - bier_routes.append( - VppBierRoute(self, bti, i, - [VppRoutePath(nh, 0xffffffff, - labels=[VppMplsLabel(100+i)])])) - bier_routes[-1].add_vpp_config() - - # - # A packet with all bits set gets replicated once for each bit - # - pkt_sizes = [64, 1400] - - for pkt_size in pkt_sizes: - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=hdr_len_id, - BitString=scapy.compat.chb(255)*n_bytes) / - IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / - UDP(sport=1234, dport=1234) / - Raw(scapy.compat.chb(5) * pkt_size)) - pkts = p - - self.pg0.add_stream(pkts) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - rx = self.pg1.get_capture(max_bp) - - for rxp in rx: - # - # The packets are not required to be sent in bit-position order - # when we setup the routes above we used the bit-position to - # construct the out-label. so use that here to determine the BP - # - olabel = rxp[MPLS] - bp = olabel.label - 2000 - - blabel = olabel[MPLS].payload - self.assertEqual(blabel.label, 100+bp) - self.assertEqual(blabel.ttl, 254) - - bier_hdr = blabel[MPLS].payload - - self.assertEqual(bier_hdr.id, 5) - self.assertEqual(bier_hdr.version, 0) - self.assertEqual(bier_hdr.length, hdr_len_id) - self.assertEqual(bier_hdr.entropy, 0) - self.assertEqual(bier_hdr.OAM, 0) - self.assertEqual(bier_hdr.RSV, 0) - self.assertEqual(bier_hdr.DSCP, 0) - self.assertEqual(bier_hdr.Proto, 5) - - # The bit-string should consist only of the BP given by i. - byte_array = [b'\0'] * (n_bytes) - byte_val = scapy.compat.chb(1 << (bp - 1) % 8) - byte_pos = n_bytes - (((bp - 1) // 8) + 1) - byte_array[byte_pos] = byte_val - bitstring = b''.join(byte_array) - - self.assertEqual(len(bitstring), len(bier_hdr.BitString)) - self.assertEqual(bitstring, bier_hdr.BitString) - - # - # cleanup. not strictly necessary, but it's much quicker this way - # because the bier_fib_dump and ip_fib_dump will be empty when the - # auto-cleanup kicks in - # - for br in bier_routes: - br.remove_vpp_config() - for nhr in nh_routes: - nhr.remove_vpp_config() - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_midpoint_1024(self): - """BIER midpoint BSL:1024""" - self.bier_midpoint(BIERLength.BIER_LEN_1024, 128, 1024) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_midpoint_512(self): - """BIER midpoint BSL:512""" - self.bier_midpoint(BIERLength.BIER_LEN_512, 64, 512) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_midpoint_256(self): - """BIER midpoint BSL:256""" - self.bier_midpoint(BIERLength.BIER_LEN_256, 32, 256) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_midpoint_128(self): - """BIER midpoint BSL:128""" - self.bier_midpoint(BIERLength.BIER_LEN_128, 16, 128) - - def test_bier_midpoint_64(self): - """BIER midpoint BSL:64""" - self.bier_midpoint(BIERLength.BIER_LEN_64, 8, 64) - - def test_bier_load_balance(self): - """BIER load-balance""" - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - # - # packets with varying entropy - # - pkts = [] - for ii in range(257): - pkts.append((Ether(dst=self.pg0.local_mac, - src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=BIERLength.BIER_LEN_64, - entropy=ii, - BitString=scapy.compat.chb(255)*16) / - IPv6(src=self.pg0.remote_ip6, - dst=self.pg0.remote_ip6) / - UDP(sport=1234, dport=1234) / - Raw())) - - # - # 4 next hops - # - nhs = [{'ip': "10.0.0.1", 'label': 201}, - {'ip': "10.0.0.2", 'label': 202}, - {'ip': "10.0.0.3", 'label': 203}, - {'ip': "10.0.0.4", 'label': 204}] - - for nh in nhs: - ipr = VppIpRoute( - self, nh['ip'], 32, - [VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index, - labels=[VppMplsLabel(nh['label'])])]) - ipr.add_vpp_config() - - bier_route = VppBierRoute( - self, bti, 1, - [VppRoutePath(nhs[0]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)]), - VppRoutePath(nhs[1]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)])]) - bier_route.add_vpp_config() - - rx = self.send_and_expect(self.pg0, pkts, self.pg1) - - # - # we should have recieved a packet from each neighbor - # - for nh in nhs[:2]: - self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) - - # - # add the other paths - # - bier_route.update_paths( - [VppRoutePath(nhs[0]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)]), - VppRoutePath(nhs[1]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)]), - VppRoutePath(nhs[2]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)]), - VppRoutePath(nhs[3]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)])]) - - rx = self.send_and_expect(self.pg0, pkts, self.pg1) - - for nh in nhs: - self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) - - # - # remove first two paths - # - bier_route.remove_path(VppRoutePath(nhs[0]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)])) - bier_route.remove_path(VppRoutePath(nhs[1]['ip'], 0xffffffff, - labels=[VppMplsLabel(101)])) - - rx = self.send_and_expect(self.pg0, pkts, self.pg1) - for nh in nhs[2:]: - self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) - - # - # remove the last of the paths, deleteing the entry - # - bier_route.remove_all_paths() - - self.send_and_assert_no_replies(self.pg0, pkts) - - def test_bier_head(self): - """BIER head""" - - MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t - MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - # - # 2 bit positions via two next hops - # - nh1 = "10.0.0.1" - nh2 = "10.0.0.2" - ip_route_1 = VppIpRoute(self, nh1, 32, - [VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index, - labels=[VppMplsLabel(2001)])]) - ip_route_2 = VppIpRoute(self, nh2, 32, - [VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index, - labels=[VppMplsLabel(2002)])]) - ip_route_1.add_vpp_config() - ip_route_2.add_vpp_config() - - bier_route_1 = VppBierRoute(self, bti, 1, - [VppRoutePath(nh1, 0xffffffff, - labels=[VppMplsLabel(101)])]) - bier_route_2 = VppBierRoute(self, bti, 2, - [VppRoutePath(nh2, 0xffffffff, - labels=[VppMplsLabel(102)])]) - bier_route_1.add_vpp_config() - bier_route_2.add_vpp_config() - - # - # An imposition object with both bit-positions set - # - bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32) - bi.add_vpp_config() - - # - # Add a multicast route that will forward into the BIER doamin - # - route_ing_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg0.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), - VppMRoutePath(0xffffffff, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - type=FibPathType.FIB_PATH_TYPE_BIER_IMP, - bier_imp=bi.bi_index)]) - route_ing_232_1_1_1.add_vpp_config() - - # - # inject an IP packet. We expect it to be BIER encapped and - # replicated. - # - p = (Ether(dst=self.pg0.local_mac, - src=self.pg0.remote_mac) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234)) - - self.pg0.add_stream([p]) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - rx = self.pg1.get_capture(2) - - # - # Encap Stack is; eth, MPLS, MPLS, BIER - # - igp_mpls = rx[0][MPLS] - self.assertEqual(igp_mpls.label, 2001) - self.assertEqual(igp_mpls.ttl, 64) - self.assertEqual(igp_mpls.s, 0) - bier_mpls = igp_mpls[MPLS].payload - self.assertEqual(bier_mpls.label, 101) - self.assertEqual(bier_mpls.ttl, 64) - self.assertEqual(bier_mpls.s, 1) - self.assertEqual(rx[0][BIER].length, 2) - - igp_mpls = rx[1][MPLS] - self.assertEqual(igp_mpls.label, 2002) - self.assertEqual(igp_mpls.ttl, 64) - self.assertEqual(igp_mpls.s, 0) - bier_mpls = igp_mpls[MPLS].payload - self.assertEqual(bier_mpls.label, 102) - self.assertEqual(bier_mpls.ttl, 64) - self.assertEqual(bier_mpls.s, 1) - self.assertEqual(rx[0][BIER].length, 2) - - def test_bier_tail(self): - """BIER Tail""" - - MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t - MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - # - # disposition table - # - bdt = VppBierDispTable(self, 8) - bdt.add_vpp_config() - - # - # BIER route in table that's for-us - # - bier_route_1 = VppBierRoute( - self, bti, 1, - [VppRoutePath("0.0.0.0", - 0xffffffff, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - nh_table_id=8)]) - bier_route_1.add_vpp_config() - - # - # An entry in the disposition table - # - bier_de_1 = VppBierDispEntry(self, bdt.id, 99, - BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, - FibPathProto.FIB_PATH_NH_PROTO_BIER, - "0.0.0.0", 0, rpf_id=8192) - bier_de_1.add_vpp_config() - - # - # A multicast route to forward post BIER disposition - # - route_eg_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) - route_eg_232_1_1_1.add_vpp_config() - route_eg_232_1_1_1.update_rpf_id(8192) - - # - # A packet with all bits set gets spat out to BP:1 - # - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=BIERLength.BIER_LEN_256, - BitString=scapy.compat.chb(255)*32, - BFRID=99) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw()) - - self.send_and_expect(self.pg0, [p], self.pg1) - - # - # A packet that does not match the Disposition entry gets dropped - # - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=BIERLength.BIER_LEN_256, - BitString=scapy.compat.chb(255)*32, - BFRID=77) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw()) - self.send_and_assert_no_replies(self.pg0, p*2, - "no matching disposition entry") - - # - # Add the default route to the disposition table - # - bier_de_2 = VppBierDispEntry(self, bdt.id, 0, - BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, - FibPathProto.FIB_PATH_NH_PROTO_BIER, - "0.0.0.0", 0, rpf_id=8192) - bier_de_2.add_vpp_config() - - # - # now the previous packet is forwarded - # - self.send_and_expect(self.pg0, [p], self.pg1) - - # - # A multicast route to forward post BIER disposition that needs - # a check against sending back into the BIER core - # - bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32) - bi.add_vpp_config() - - route_eg_232_1_1_2 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.2", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(0xffffffff, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, - proto=DpoProto.DPO_PROTO_BIER, - type=FibPathType.FIB_PATH_TYPE_BIER_IMP, - bier_imp=bi.bi_index), - VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) - route_eg_232_1_1_2.add_vpp_config() - route_eg_232_1_1_2.update_rpf_id(8192) - - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - MPLS(label=77, ttl=255) / - BIER(length=BIERLength.BIER_LEN_256, - BitString=scapy.compat.chb(255)*32, - BFRID=77) / - IP(src="1.1.1.1", dst="232.1.1.2") / - UDP(sport=1234, dport=1234) / - Raw()) - self.send_and_expect(self.pg0, [p], self.pg1) - - def bier_e2e(self, hdr_len_id, n_bytes, max_bp): - """ BIER end-to-end""" - - MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t - MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(0, 0, hdr_len_id) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - lowest = [b'\0'] * (n_bytes) - lowest[-1] = scapy.compat.chb(1) - highest = [b'\0'] * (n_bytes) - highest[0] = scapy.compat.chb(128) - - # - # Impostion Sets bit strings - # - bi_low = VppBierImp(self, bti, 333, lowest) - bi_low.add_vpp_config() - bi_high = VppBierImp(self, bti, 334, highest) - bi_high.add_vpp_config() - - # - # Add a multicast route that will forward into the BIER doamin - # - route_ing_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg0.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), - VppMRoutePath(0xffffffff, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - type=FibPathType.FIB_PATH_TYPE_BIER_IMP, - bier_imp=bi_low.bi_index)]) - route_ing_232_1_1_1.add_vpp_config() - route_ing_232_1_1_2 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.2", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg0.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), - VppMRoutePath(0xffffffff, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - type=FibPathType.FIB_PATH_TYPE_BIER_IMP, - bier_imp=bi_high.bi_index)]) - route_ing_232_1_1_2.add_vpp_config() - - # - # disposition table 8 - # - bdt = VppBierDispTable(self, 8) - bdt.add_vpp_config() - - # - # BIER routes in table that are for-us, resolving through - # disp table 8. - # - bier_route_1 = VppBierRoute( - self, bti, 1, - [VppRoutePath("0.0.0.0", - 0xffffffff, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - nh_table_id=8)]) - bier_route_1.add_vpp_config() - bier_route_max = VppBierRoute( - self, bti, max_bp, - [VppRoutePath("0.0.0.0", - 0xffffffff, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - nh_table_id=8)]) - bier_route_max.add_vpp_config() - - # - # An entry in the disposition table for sender 333 - # lookup in VRF 10 - # - bier_de_1 = VppBierDispEntry(self, bdt.id, 333, - BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, - FibPathProto.FIB_PATH_NH_PROTO_BIER, - "0.0.0.0", 10, rpf_id=8192) - bier_de_1.add_vpp_config() - bier_de_1 = VppBierDispEntry(self, bdt.id, 334, - BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, - FibPathProto.FIB_PATH_NH_PROTO_BIER, - "0.0.0.0", 10, rpf_id=8193) - bier_de_1.add_vpp_config() - - # - # Add a multicast routes that will forward the traffic - # post-disposition - # - route_eg_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - table_id=10, - paths=[VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) - route_eg_232_1_1_1.add_vpp_config() - route_eg_232_1_1_1.update_rpf_id(8192) - route_eg_232_1_1_2 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.2", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - table_id=10, - paths=[VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) - route_eg_232_1_1_2.add_vpp_config() - route_eg_232_1_1_2.update_rpf_id(8193) - - # - # inject a packet in VRF-0. We expect it to be BIER encapped, - # replicated, then hit the disposition and be forwarded - # out of VRF 10, i.e. on pg1 - # - p = (Ether(dst=self.pg0.local_mac, - src=self.pg0.remote_mac) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw(scapy.compat.chb(5) * 32)) - - rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1) - - self.assertEqual(rx[0][IP].src, "1.1.1.1") - self.assertEqual(rx[0][IP].dst, "232.1.1.1") - - p = (Ether(dst=self.pg0.local_mac, - src=self.pg0.remote_mac) / - IP(src="1.1.1.1", dst="232.1.1.2") / - UDP(sport=1234, dport=1234) / - Raw(scapy.compat.chb(5) * 512)) - - rx = self.send_and_expect(self.pg0, p*NUM_PKTS, self.pg1) - self.assertEqual(rx[0][IP].src, "1.1.1.1") - self.assertEqual(rx[0][IP].dst, "232.1.1.2") - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_e2e_1024(self): - """ BIER end-to-end BSL:1024""" - self.bier_e2e(BIERLength.BIER_LEN_1024, 128, 1024) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_e2e_512(self): - """ BIER end-to-end BSL:512""" - self.bier_e2e(BIERLength.BIER_LEN_512, 64, 512) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_e2e_256(self): - """ BIER end-to-end BSL:256""" - self.bier_e2e(BIERLength.BIER_LEN_256, 32, 256) - - @unittest.skipUnless(running_extended_tests, "part of extended tests") - def test_bier_e2e_128(self): - """ BIER end-to-end BSL:128""" - self.bier_e2e(BIERLength.BIER_LEN_128, 16, 128) - - def test_bier_e2e_64(self): - """ BIER end-to-end BSL:64""" - self.bier_e2e(BIERLength.BIER_LEN_64, 8, 64) - - def test_bier_head_o_udp(self): - """BIER head over UDP""" - - MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t - MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t - - # - # Add a BIER table for sub-domain 1, set 0, and BSL 256 - # - bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256) - bt = VppBierTable(self, bti, 77) - bt.add_vpp_config() - - # - # 1 bit positions via 1 next hops - # - nh1 = "10.0.0.1" - ip_route = VppIpRoute(self, nh1, 32, - [VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index, - labels=[VppMplsLabel(2001)])]) - ip_route.add_vpp_config() - - udp_encap = VppUdpEncap(self, - self.pg0.local_ip4, - nh1, - 330, 8138) - udp_encap.add_vpp_config() - - bier_route = VppBierRoute( - self, bti, 1, - [VppRoutePath("0.0.0.0", - 0xFFFFFFFF, - type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, - next_hop_id=udp_encap.id)]) - bier_route.add_vpp_config() - - # - # An 2 imposition objects with all bit-positions set - # only use the second, but creating 2 tests with a non-zero - # value index in the route add - # - bi = VppBierImp(self, bti, 333, scapy.compat.chb(0xff) * 32) - bi.add_vpp_config() - bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(0xff) * 32) - bi2.add_vpp_config() - - # - # Add a multicast route that will forward into the BIER doamin - # - route_ing_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg0.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), - VppMRoutePath(0xffffffff, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - type=FibPathType.FIB_PATH_TYPE_BIER_IMP, - bier_imp=bi2.bi_index)]) - route_ing_232_1_1_1.add_vpp_config() - - # - # inject a packet an IP. We expect it to be BIER and UDP encapped, - # - p = (Ether(dst=self.pg0.local_mac, - src=self.pg0.remote_mac) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234)) - - self.pg0.add_stream([p]) - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - rx = self.pg1.get_capture(1) - - # - # Encap Stack is, eth, IP, UDP, BIFT, BIER - # - self.assertEqual(rx[0][IP].src, self.pg0.local_ip4) - self.assertEqual(rx[0][IP].dst, nh1) - self.assertEqual(rx[0][UDP].sport, 330) - self.assertEqual(rx[0][UDP].dport, 8138) - self.assertEqual(rx[0][BIFT].bsl, BIERLength.BIER_LEN_256) - self.assertEqual(rx[0][BIFT].sd, 1) - self.assertEqual(rx[0][BIFT].set, 0) - self.assertEqual(rx[0][BIFT].ttl, 64) - self.assertEqual(rx[0][BIER].length, 2) - - def test_bier_tail_o_udp(self): - """BIER Tail over UDP""" - - MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t - MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t - - # - # Add a BIER table for sub-domain 0, set 0, and BSL 256 - # - bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256) - bt = VppBierTable(self, bti, MPLS_LABEL_INVALID) - bt.add_vpp_config() - - # - # disposition table - # - bdt = VppBierDispTable(self, 8) - bdt.add_vpp_config() - - # - # BIER route in table that's for-us - # - bier_route_1 = VppBierRoute( - self, bti, 1, - [VppRoutePath("0.0.0.0", - 0xffffffff, - proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, - nh_table_id=8)]) - bier_route_1.add_vpp_config() - - # - # An entry in the disposition table - # - bier_de_1 = VppBierDispEntry(self, bdt.id, 99, - BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, - FibPathProto.FIB_PATH_NH_PROTO_BIER, - "0.0.0.0", 0, rpf_id=8192) - bier_de_1.add_vpp_config() - - # - # A multicast route to forward post BIER disposition - # - route_eg_232_1_1_1 = VppIpMRoute( - self, - "0.0.0.0", - "232.1.1.1", 32, - MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, - paths=[VppMRoutePath(self.pg1.sw_if_index, - MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD)]) - route_eg_232_1_1_1.add_vpp_config() - route_eg_232_1_1_1.update_rpf_id(8192) - - # - # A packet with all bits set gets spat out to BP:1 - # - p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / - UDP(sport=333, dport=8138) / - BIFT(sd=1, set=0, bsl=2, ttl=255) / - BIER(length=BIERLength.BIER_LEN_256, - BitString=scapy.compat.chb(255)*32, - BFRID=99) / - IP(src="1.1.1.1", dst="232.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw()) - - rx = self.send_and_expect(self.pg0, [p], self.pg1) - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/bier/test/vpp_bier.py b/src/vnet/bier/test/vpp_bier.py deleted file mode 100644 index 6e087a8ee0b..00000000000 --- a/src/vnet/bier/test/vpp_bier.py +++ /dev/null @@ -1,293 +0,0 @@ -""" - BIER Tables and Routes -""" - -import socket -from vpp_object import VppObject -from vpp_ip_route import MPLS_LABEL_INVALID, VppRoutePath, VppMplsLabel - - -class BIER_HDR_PAYLOAD: - BIER_HDR_PROTO_MPLS_DOWN_STREAM = 1 - BIER_HDR_PROTO_MPLS_UP_STREAM = 2 - BIER_HDR_PROTO_ETHERNET = 3 - BIER_HDR_PROTO_IPV4 = 4 - BIER_HDR_PROTO_IPV6 = 5 - BIER_HDR_PROTO_VXLAN = 6 - BIER_HDR_PROTO_CTRL = 7 - BIER_HDR_PROTO_OAM = 8 - - -class VppBierTableID(): - def __init__(self, sub_domain_id, set_id, hdr_len_id): - self.set_id = set_id - self.sub_domain_id = sub_domain_id - self.hdr_len_id = hdr_len_id - - -def find_bier_table(test, bti): - tables = test.vapi.bier_table_dump() - for t in tables: - if bti.set_id == t.bt_tbl_id.bt_set \ - and bti.sub_domain_id == t.bt_tbl_id.bt_sub_domain \ - and bti.hdr_len_id == t.bt_tbl_id.bt_hdr_len_id: - return True - return False - - -def find_bier_route(test, bti, bp): - routes = test.vapi.bier_route_dump(bti) - for r in routes: - if bti.set_id == r.br_route.br_tbl_id.bt_set \ - and bti.sub_domain_id == r.br_route.br_tbl_id.bt_sub_domain \ - and bti.hdr_len_id == r.br_route.br_tbl_id.bt_hdr_len_id \ - and bp == r.br_route.br_bp: - return True - return False - - -def find_bier_disp_table(test, bdti): - tables = test.vapi.bier_disp_table_dump() - for t in tables: - if bdti == t.bdt_tbl_id: - return True - return False - - -def find_bier_disp_entry(test, bdti, bp): - entries = test.vapi.bier_disp_entry_dump(bdti) - for e in entries: - if bp == e.bde_bp \ - and bdti == e.bde_tbl_id: - return True - return False - - -def find_bier_imp(test, bti, bp): - imps = test.vapi.bier_imp_dump() - for i in imps: - if bti.set_id == i.bi_tbl_id.bt_set \ - and bti.sub_domain_id == i.bi_tbl_id.bt_sub_domain \ - and bti.hdr_len_id == i.bi_tbl_id.bt_hdr_len_id \ - and bp == i.bi_src: - return True - return False - - -class VppBierTable(VppObject): - """ - BIER Table - """ - - def __init__(self, test, id, mpls_label): - self._test = test - self.id = id - self.mpls_label = mpls_label - - def add_vpp_config(self): - self._test.vapi.bier_table_add_del( - self.id, - self.mpls_label, - is_add=1) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self._test.vapi.bier_table_add_del( - self.id, - self.mpls_label, - is_add=0) - - def object_id(self): - return "bier-table;[%d:%d:%d]" % (self.id.set_id, - self.id.sub_domain_id, - self.id.hdr_len_id) - - def query_vpp_config(self): - return find_bier_table(self._test, self.id) - - -class VppBierRoute(VppObject): - """ - BIER route - """ - - def __init__(self, test, tbl_id, bp, paths): - self._test = test - self.tbl_id = tbl_id - self.bp = bp - self.paths = paths - self.encoded_paths = [] - for path in self.paths: - self.encoded_paths.append(path.encode()) - - def add_vpp_config(self): - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - self.encoded_paths, - is_add=1) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - self.encoded_paths, - is_add=0) - - def update_paths(self, paths): - self.paths = paths - self.encoded_paths = [] - for path in self.paths: - self.encoded_paths.append(path.encode()) - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - self.encoded_paths, - is_replace=1) - - def add_path(self, path): - self.encoded_paths.append(path.encode()) - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - [path.encode()], - is_add=1, - is_replace=0) - self.paths.append(path) - self._test.registry.register(self, self._test.logger) - - def remove_path(self, path): - self.encoded_paths.remove(path.encode()) - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - [path.encode()], - is_add=0, - is_replace=0) - self.paths.remove(path) - - def remove_all_paths(self): - self._test.vapi.bier_route_add_del( - self.tbl_id, - self.bp, - [], - is_add=0, - is_replace=1) - self.paths = [] - - def object_id(self): - return "bier-route;[%d:%d:%d:%d]" % (self.tbl_id.set_id, - self.tbl_id.sub_domain_id, - self.tbl_id.hdr_len_id, - self.bp) - - def query_vpp_config(self): - return find_bier_route(self._test, self.tbl_id, self.bp) - - -class VppBierImp(VppObject): - """ - BIER route - """ - - def __init__(self, test, tbl_id, src, ibytes): - self._test = test - self.tbl_id = tbl_id - self.ibytes = ibytes - self.src = src - - def add_vpp_config(self): - res = self._test.vapi.bier_imp_add( - self.tbl_id, - self.src, - self.ibytes) - self.bi_index = res.bi_index - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self._test.vapi.bier_imp_del( - self.bi_index) - - def object_id(self): - return "bier-imp;[%d:%d:%d:%d]" % (self.tbl_id.set_id, - self.tbl_id.sub_domain_id, - self.tbl_id.hdr_len_id, - self.src) - - def query_vpp_config(self): - return find_bier_imp(self._test, self.tbl_id, self.src) - - -class VppBierDispTable(VppObject): - """ - BIER Disposition Table - """ - - def __init__(self, test, id): - self._test = test - self.id = id - - def add_vpp_config(self): - self._test.vapi.bier_disp_table_add_del( - self.id, - is_add=1) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self._test.vapi.bier_disp_table_add_del( - self.id, - is_add=0) - - def object_id(self): - return "bier-disp-table;[%d]" % (self.id) - - def query_vpp_config(self): - return find_bier_disp_table(self._test, self.id) - - -class VppBierDispEntry(VppObject): - """ - BIER Disposition Entry - """ - - def __init__(self, test, tbl_id, bp, payload_proto, nh_proto, - nh, nh_tbl, rpf_id=~0): - self._test = test - self.tbl_id = tbl_id - self.nh_tbl = nh_tbl - self.nh_proto = nh_proto - self.bp = bp - self.payload_proto = payload_proto - self.rpf_id = rpf_id - self.nh = socket.inet_pton(socket.AF_INET, nh) - - def add_vpp_config(self): - self._test.vapi.bier_disp_entry_add_del( - self.tbl_id, - self.bp, - self.payload_proto, - self.nh_proto, - self.nh, - self.nh_tbl, - self.rpf_id, - is_add=1) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self._test.vapi.bier_disp_entry_add_del( - self.tbl_id, - self.bp, - self.payload_proto, - self.nh_proto, - self.nh, - self.nh_tbl, - self.rpf_id, - is_add=0) - - def object_id(self): - return "bier-disp-entry;[%d:%d]" % (self.tbl_id, - self.bp) - - def query_vpp_config(self): - return find_bier_disp_entry(self._test, self.tbl_id, self.bp) diff --git a/src/vnet/bonding/test/test_bond.py b/src/vnet/bonding/test/test_bond.py deleted file mode 100644 index 5df86ae5b0f..00000000000 --- a/src/vnet/bonding/test/test_bond.py +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/bin/env python3 - -import socket -import unittest - -from scapy.packet import Raw -from scapy.layers.l2 import Ether -from scapy.layers.inet import IP, UDP - -from framework import VppTestCase, VppTestRunner -from vpp_bond_interface import VppBondInterface -from vpp_papi import MACAddress, VppEnum - - -class TestBondInterface(VppTestCase): - """Bond Test Case - - """ - - @classmethod - def setUpClass(cls): - super(TestBondInterface, cls).setUpClass() - # Test variables - cls.pkts_per_burst = 257 # Number of packets per burst - # create 3 pg interfaces - cls.create_pg_interfaces(range(4)) - - # packet sizes - cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018] - - # setup all interfaces - for i in cls.pg_interfaces: - i.admin_up() - - @classmethod - def tearDownClass(cls): - super(TestBondInterface, cls).tearDownClass() - - def setUp(self): - super(TestBondInterface, self).setUp() - - def tearDown(self): - super(TestBondInterface, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.ppcli("show interface")) - - def test_bond_traffic(self): - """ Bond traffic test """ - - # topology - # - # RX-> TX-> - # - # pg2 ------+ +------pg0 (member) - # | | - # BondEthernet0 (10.10.10.1) - # | | - # pg3 ------+ +------pg1 (memberx) - # - - # create interface (BondEthernet0) - # self.logger.info("create bond") - bond0_mac = "02:fe:38:30:59:3c" - mac = MACAddress(bond0_mac).packed - bond0 = VppBondInterface( - self, - mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR, - lb=VppEnum.vl_api_bond_lb_algo_t.BOND_API_LB_ALGO_L34, - numa_only=0, - use_custom_mac=1, - mac_address=mac) - bond0.add_vpp_config() - bond0.admin_up() - self.vapi.sw_interface_add_del_address( - sw_if_index=bond0.sw_if_index, - prefix="10.10.10.1/24") - - self.pg2.config_ip4() - self.pg2.resolve_arp() - self.pg3.config_ip4() - self.pg3.resolve_arp() - - self.logger.info(self.vapi.cli("show interface")) - self.logger.info(self.vapi.cli("show interface address")) - self.logger.info(self.vapi.cli("show ip neighbors")) - - # add member pg0 and pg1 to BondEthernet0 - self.logger.info("bond add member interface pg0 to BondEthernet0") - bond0.add_member_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index) - self.logger.info("bond add_member interface pg1 to BondEthernet0") - bond0.add_member_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index) - - # verify both members in BondEthernet0 - if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index) - self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump)) - self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump)) - - # generate a packet from pg2 -> BondEthernet0 -> pg1 - # BondEthernet0 TX hashes this packet to pg1 - p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.local_ip4, dst="10.10.10.12") / - UDP(sport=1235, dport=1235) / - Raw(b'\xa5' * 100)) - self.pg2.add_stream(p2) - - # generate a packet from pg3 -> BondEthernet0 -> pg0 - # BondEthernet0 TX hashes this packet to pg0 - # notice the ip address and ports are different than p2 packet - p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) / - IP(src=self.pg3.local_ip4, dst="10.10.10.11") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - self.pg3.add_stream(p3) - - self.pg_enable_capture(self.pg_interfaces) - - # set up the static arp entries pointing to the BondEthernet0 interface - # so that it does not try to resolve the ip address - self.logger.info(self.vapi.cli( - "set ip neighbor static BondEthernet0 10.10.10.12 abcd.abcd.0002")) - self.logger.info(self.vapi.cli( - "set ip neighbor static BondEthernet0 10.10.10.11 abcd.abcd.0004")) - - # clear the interface counters - self.logger.info(self.vapi.cli("clear interfaces")) - - self.pg_start() - - self.logger.info("check the interface counters") - - # verify counters - - # BondEthernet0 tx bytes = 284 - intfs = self.vapi.cli("show interface BondEthernet0").split("\n") - found = 0 - for intf in intfs: - if "tx bytes" in intf and "284" in intf: - found = 1 - self.assertEqual(found, 1) - - # BondEthernet0 tx bytes = 284 - intfs = self.vapi.cli("show interface BondEthernet0").split("\n") - found = 0 - for intf in intfs: - if "tx bytes" in intf and "284" in intf: - found = 1 - self.assertEqual(found, 1) - - # pg2 rx bytes = 142 - intfs = self.vapi.cli("show interface pg2").split("\n") - found = 0 - for intf in intfs: - if "rx bytes" in intf and "142" in intf: - found = 1 - self.assertEqual(found, 1) - - # pg3 rx bytes = 142 - intfs = self.vapi.cli("show interface pg3").split("\n") - found = 0 - for intf in intfs: - if "rx bytes" in intf and "142" in intf: - found = 1 - self.assertEqual(found, 1) - - bond0.remove_vpp_config() - - def test_bond_add_member(self): - """ Bond add_member/detach member test """ - - # create interface (BondEthernet0) and set bond mode to LACP - self.logger.info("create bond") - bond0 = VppBondInterface( - self, - mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP, - enable_gso=0) - bond0.add_vpp_config() - bond0.admin_up() - - # verify that interfaces can be added as_member and detached two times - for i in range(2): - # verify pg0 and pg1 not in BondEthernet0 - if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index) - self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump)) - self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump)) - - # add_member pg0 and pg1 to BondEthernet0 - self.logger.info("bond add_member interface pg0 to BondEthernet0") - bond0.add_member_vpp_bond_interface( - sw_if_index=self.pg0.sw_if_index, - is_passive=0, - is_long_timeout=0) - - self.logger.info("bond add_member interface pg1 to BondEthernet0") - bond0.add_member_vpp_bond_interface( - sw_if_index=self.pg1.sw_if_index, - is_passive=0, - is_long_timeout=0) - # verify both members in BondEthernet0 - if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index) - self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump)) - self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump)) - - # detach interface pg0 - self.logger.info("detach interface pg0") - bond0.detach_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index) - - # verify pg0 is not in BondEthernet0, but pg1 is - if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index) - self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump)) - self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump)) - - # detach interface pg1 - self.logger.info("detach interface pg1") - bond0.detach_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index) - - # verify pg0 and pg1 not in BondEthernet0 - if_dump = self.vapi.sw_member_interface_dump(bond0.sw_if_index) - self.assertFalse(self.pg0.is_interface_config_in_dump(if_dump)) - self.assertFalse(self.pg1.is_interface_config_in_dump(if_dump)) - - bond0.remove_vpp_config() - - def test_bond(self): - """ Bond add/delete interface test """ - self.logger.info("Bond add interfaces") - - # create interface 1 (BondEthernet0) - bond0 = VppBondInterface( - self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_LACP) - bond0.add_vpp_config() - bond0.admin_up() - - # create interface 2 (BondEthernet1) - bond1 = VppBondInterface( - self, mode=VppEnum.vl_api_bond_mode_t.BOND_API_MODE_XOR) - bond1.add_vpp_config() - bond1.admin_up() - - # verify both interfaces in the show - ifs = self.vapi.cli("show interface") - self.assertIn('BondEthernet0', ifs) - self.assertIn('BondEthernet1', ifs) - - # verify they are in the dump also - if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF) - self.assertTrue(bond0.is_interface_config_in_dump(if_dump)) - self.assertTrue(bond1.is_interface_config_in_dump(if_dump)) - - # delete BondEthernet1 - self.logger.info("Deleting BondEthernet1") - bond1.remove_vpp_config() - - self.logger.info("Verifying BondEthernet1 is deleted") - - ifs = self.vapi.cli("show interface") - # verify BondEthernet0 still in the show - self.assertIn('BondEthernet0', ifs) - - # verify BondEthernet1 not in the show - self.assertNotIn('BondEthernet1', ifs) - - # verify BondEthernet1 is not in the dump - if_dump = self.vapi.sw_bond_interface_dump(sw_if_index=0xFFFFFFFF) - self.assertFalse(bond1.is_interface_config_in_dump(if_dump)) - - # verify BondEthernet0 is still in the dump - self.assertTrue(bond0.is_interface_config_in_dump(if_dump)) - - # delete BondEthernet0 - self.logger.info("Deleting BondEthernet0") - bond0.remove_vpp_config() - - self.logger.info("Verifying BondEthernet0 is deleted") - - # verify BondEthernet0 not in the show - ifs = self.vapi.cli("show interface") - self.assertNotIn('BondEthernet0', ifs) - - # verify BondEthernet0 is not in the dump - if_dump = self.vapi.sw_bond_interface_dump( - sw_if_index=bond0.sw_if_index) - self.assertFalse(bond0.is_interface_config_in_dump(if_dump)) - - def test_bond_link(self): - """ Bond hw interface link state test """ - - # for convenience - bond_modes = VppEnum.vl_api_bond_mode_t - intf_flags = VppEnum.vl_api_if_status_flags_t - - # create interface 1 (BondEthernet0) - self.logger.info("Create bond interface") - # use round-robin mode to avoid negotiation required by LACP - bond0 = VppBondInterface(self, - mode=bond_modes.BOND_API_MODE_ROUND_ROBIN) - bond0.add_vpp_config() - - # set bond admin up. - self.logger.info("set interface BondEthernet0 admin up") - bond0.admin_up() - # confirm link up - bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP, - intf_flags.IF_STATUS_API_FLAG_LINK_UP) - - # toggle bond admin state - self.logger.info("toggle interface BondEthernet0") - bond0.admin_down() - bond0.admin_up() - - # confirm link is still up - bond0.assert_interface_state(intf_flags.IF_STATUS_API_FLAG_ADMIN_UP, - intf_flags.IF_STATUS_API_FLAG_LINK_UP) - - # delete BondEthernet0 - self.logger.info("Deleting BondEthernet0") - bond0.remove_vpp_config() - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/bonding/test/vpp_bond_interface.py b/src/vnet/bonding/test/vpp_bond_interface.py deleted file mode 100644 index 60c1ac1557b..00000000000 --- a/src/vnet/bonding/test/vpp_bond_interface.py +++ /dev/null @@ -1,52 +0,0 @@ -from vpp_object import VppObject -from vpp_interface import VppInterface - - -class VppBondInterface(VppInterface): - """VPP bond interface.""" - - def __init__(self, test, mode, lb=0, numa_only=0, enable_gso=0, - use_custom_mac=0, mac_address='', id=0xFFFFFFFF): - - """ Create VPP Bond interface """ - super(VppBondInterface, self).__init__(test) - self.mode = mode - self.lb = lb - self.numa_only = numa_only - self.enable_gso = enable_gso - self.use_custom_mac = use_custom_mac - self.mac_address = mac_address - self.id = id - - def add_vpp_config(self): - r = self.test.vapi.bond_create2(self.mode, - self.lb, - self.numa_only, - self.enable_gso, - self.use_custom_mac, - self.mac_address, - self.id) - self.set_sw_if_index(r.sw_if_index) - - def remove_vpp_config(self): - self.test.vapi.bond_delete(self.sw_if_index) - - def add_member_vpp_bond_interface(self, - sw_if_index, - is_passive=0, - is_long_timeout=0): - self.test.vapi.bond_add_member(sw_if_index, - self.sw_if_index, - is_passive, - is_long_timeout) - - def detach_vpp_bond_interface(self, - sw_if_index): - self.test.vapi.bond_detach_member(sw_if_index) - - def is_interface_config_in_dump(self, dump): - for i in dump: - if i.sw_if_index == self.sw_if_index: - return True - else: - return False diff --git a/src/vnet/classify/test/test_classifier.py b/src/vnet/classify/test/test_classifier.py deleted file mode 100644 index 11c0985f4d4..00000000000 --- a/src/vnet/classify/test/test_classifier.py +++ /dev/null @@ -1,569 +0,0 @@ -#!/usr/bin/env python3 - -import binascii -import socket -import unittest - -from framework import VppTestCase, VppTestRunner - -from scapy.packet import Raw -from scapy.layers.l2 import Ether -from scapy.layers.inet import IP, UDP, TCP -from util import ppp -from template_classifier import TestClassifier -from vpp_ip_route import VppIpRoute, VppRoutePath -from vpp_ip import INVALID_INDEX - - -# Tests split to different test case classes because of issue reported in -# ticket VPP-1336 -class TestClassifierIP(TestClassifier): - """ Classifier IP Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierIP, cls).tearDownClass() - - def test_iacl_src_ip(self): - """ Source IP iACL test - - Test scenario for basic IP ACL with source IP - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with source IP address. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with source IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip_src' - self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(src_ip=self.pg0.remote_ip4)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_dst_ip(self): - """ Destination IP iACL test - - Test scenario for basic IP ACL with destination IP - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with destination IP address. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with destination IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip_dst' - self.create_classify_table(key, self.build_ip_mask(dst_ip='ffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(dst_ip=self.pg1.remote_ip4)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_src_dst_ip(self): - """ Source and destination IP iACL test - - Test scenario for basic IP ACL with source and destination IP - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with source and destination IP addresses. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with source and destination IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip' - self.create_classify_table( - key, self.build_ip_mask(src_ip='ffffffff', dst_ip='ffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(src_ip=self.pg0.remote_ip4, - dst_ip=self.pg1.remote_ip4)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierUDP(TestClassifier): - """ Classifier UDP proto Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierUDP, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierUDP, cls).tearDownClass() - - def test_iacl_proto_udp(self): - """ UDP protocol iACL test - - Test scenario for basic protocol ACL with UDP protocol - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP protocol - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'proto_udp' - self.create_classify_table(key, self.build_ip_mask(proto='ff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_UDP)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_sport(self): - """ UDP source port iACL test - - Test scenario for basic protocol ACL with UDP and sport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined sport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and sport - sport = 38 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=sport, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'proto_udp_sport' - self.create_classify_table( - key, self.build_ip_mask(proto='ff', src_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_dport(self): - """ UDP destination port iACL test - - Test scenario for basic protocol ACL with UDP and dport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and dport - dport = 427 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=1234, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'proto_udp_dport' - self.create_classify_table( - key, self.build_ip_mask(proto='ff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_UDP, dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_sport_dport(self): - """ UDP source and destination ports iACL test - - Test scenario for basic protocol ACL with UDP and sport and dport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined sport and dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and sport and dport - sport = 13720 - dport = 9080 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=sport, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'proto_udp_ports' - self.create_classify_table( - key, - self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_UDP, src_port=sport, - dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierTCP(TestClassifier): - """ Classifier TCP proto Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierTCP, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierTCP, cls).tearDownClass() - - def test_iacl_proto_tcp(self): - """ TCP protocol iACL test - - Test scenario for basic protocol ACL with TCP protocol - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP protocol - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=1234, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'proto_tcp' - self.create_classify_table(key, self.build_ip_mask(proto='ff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_TCP)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_sport(self): - """ TCP source port iACL test - - Test scenario for basic protocol ACL with TCP and sport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined sport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and sport - sport = 38 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=sport, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'proto_tcp_sport' - self.create_classify_table( - key, self.build_ip_mask(proto='ff', src_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_dport(self): - """ TCP destination port iACL test - - Test scenario for basic protocol ACL with TCP and dport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and dport - dport = 427 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=1234, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'proto_tcp_sport' - self.create_classify_table( - key, self.build_ip_mask(proto='ff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_TCP, dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_sport_dport(self): - """ TCP source and destination ports iACL test - - Test scenario for basic protocol ACL with TCP and sport and dport - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined sport and dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and sport and dport - sport = 13720 - dport = 9080 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=sport, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'proto_tcp_ports' - self.create_classify_table( - key, - self.build_ip_mask(proto='ff', src_port='ffff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(proto=socket.IPPROTO_TCP, src_port=sport, - dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierIPOut(TestClassifier): - """ Classifier output IP Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIPOut, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierIPOut, cls).tearDownClass() - - def test_acl_ip_out(self): - """ Output IP ACL test - - Test scenario for basic IP ACL with source IP - - Create IPv4 stream for pg1 -> pg0 interface. - - Create ACL with source IP address. - - Send and verify received packets on pg0 interface. - """ - - # Basic oACL testing with source IP - pkts = self.create_stream(self.pg1, self.pg0, self.pg_if_packet_sizes) - self.pg1.add_stream(pkts) - - key = 'ip_out' - self.create_classify_table( - key, self.build_ip_mask(src_ip='ffffffff'), data_offset=0) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(src_ip=self.pg1.remote_ip4)) - self.output_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg0.get_capture(len(pkts)) - self.verify_capture(self.pg0, pkts) - self.pg1.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierMAC(TestClassifier): - """ Classifier MAC Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierMAC, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierMAC, cls).tearDownClass() - - def test_acl_mac(self): - """ MAC ACL test - - Test scenario for basic MAC ACL with source MAC - - Create IPv4 stream for pg0 -> pg2 interface. - - Create ACL with source MAC address. - - Send and verify received packets on pg2 interface. - """ - - # Basic iACL testing with source MAC - pkts = self.create_stream(self.pg0, self.pg2, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'mac' - self.create_classify_table( - key, self.build_mac_mask(src_mac='ffffffffffff'), data_offset=-14) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_mac_match(src_mac=self.pg0.remote_mac)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg2.get_capture(len(pkts)) - self.verify_capture(self.pg2, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg1.assert_nothing_captured(remark="packets forwarded") - self.pg3.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierPBR(TestClassifier): - """ Classifier PBR Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierPBR, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestClassifierPBR, cls).tearDownClass() - - def test_acl_pbr(self): - """ IP PBR test - - Test scenario for PBR with source IP - - Create IPv4 stream for pg0 -> pg3 interface. - - Configure PBR fib entry for packet forwarding. - - Send and verify received packets on pg3 interface. - """ - - # PBR testing with source IP - pkts = self.create_stream(self.pg0, self.pg3, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'pbr' - self.create_classify_table(key, self.build_ip_mask(src_ip='ffffffff')) - pbr_option = 1 - # this will create the VRF/table in which we will insert the route - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(src_ip=self.pg0.remote_ip4), - pbr_option, self.pbr_vrfid) - self.assertTrue(self.verify_vrf(self.pbr_vrfid)) - r = VppIpRoute(self, self.pg3.local_ip4, 24, - [VppRoutePath(self.pg3.remote_ip4, - INVALID_INDEX)], - table_id=self.pbr_vrfid) - r.add_vpp_config() - - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg3.get_capture(len(pkts)) - self.verify_capture(self.pg3, pkts) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key), 0) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg1.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - # remove the classify session and the route - r.remove_vpp_config() - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip_match(src_ip=self.pg0.remote_ip4), - pbr_option, self.pbr_vrfid, is_add=0) - - # and the table should be gone. - self.assertFalse(self.verify_vrf(self.pbr_vrfid)) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/classify/test/test_classifier_ip6.py b/src/vnet/classify/test/test_classifier_ip6.py deleted file mode 100644 index 211374b5ec6..00000000000 --- a/src/vnet/classify/test/test_classifier_ip6.py +++ /dev/null @@ -1,490 +0,0 @@ -#!/usr/bin/env python3 - -import unittest -import socket -import binascii - -from framework import VppTestCase, VppTestRunner - -from scapy.packet import Raw -from scapy.layers.l2 import Ether -from scapy.layers.inet6 import IPv6, UDP, TCP -from util import ppp -from template_classifier import TestClassifier - - -class TestClassifierIP6(TestClassifier): - """ Classifier IP6 Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP6, cls).setUpClass() - cls.af = socket.AF_INET6 - - @classmethod - def tearDownClass(cls): - super(TestClassifierIP6, cls).tearDownClass() - - def test_iacl_src_ip(self): - """ Source IP6 iACL test - - Test scenario for basic IP ACL with source IP - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with source IP address. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with source IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip6_src' - self.create_classify_table( - key, - self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(src_ip=self.pg0.remote_ip6)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_dst_ip(self): - """ Destination IP6 iACL test - - Test scenario for basic IP ACL with destination IP - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with destination IP address. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with destination IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip6_dst' - self.create_classify_table( - key, - self.build_ip6_mask(dst_ip='ffffffffffffffffffffffffffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(dst_ip=self.pg1.remote_ip6)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_src_dst_ip(self): - """ Source and destination IP6 iACL test - - Test scenario for basic IP ACL with source and destination IP - - Create IPv4 stream for pg0 -> pg1 interface. - - Create iACL with source and destination IP addresses. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with source and destination IP - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'ip6' - self.create_classify_table( - key, - self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff', - dst_ip='ffffffffffffffffffffffffffffffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(src_ip=self.pg0.remote_ip6, - dst_ip=self.pg1.remote_ip6)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - -# Tests split to different test case classes because of issue reported in -# ticket VPP-1336 -class TestClassifierIP6UDP(TestClassifier): - """ Classifier IP6 UDP proto Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP6UDP, cls).setUpClass() - cls.af = socket.AF_INET6 - - def test_iacl_proto_udp(self): - """ IP6 UDP protocol iACL test - - Test scenario for basic protocol ACL with UDP protocol - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP protocol - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'nh_udp' - self.create_classify_table(key, self.build_ip6_mask(nh='ff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_UDP)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_sport(self): - """ IP6 UDP source port iACL test - - Test scenario for basic protocol ACL with UDP and sport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined sport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and sport - sport = 38 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=sport, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'nh_udp_sport' - self.create_classify_table( - key, self.build_ip6_mask(nh='ff', src_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_UDP, src_port=sport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_dport(self): - """ IP6 UDP destination port iACL test - - Test scenario for basic protocol ACL with UDP and dport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and dport - dport = 427 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=1234, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'nh_udp_dport' - self.create_classify_table( - key, self.build_ip6_mask(nh='ff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_UDP, dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_udp_sport_dport(self): - """ IP6 UDP source and destination ports iACL test - - Test scenario for basic protocol ACL with UDP and sport and dport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with UDP IP protocol and defined sport and dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with UDP and sport and dport - sport = 13720 - dport = 9080 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - UDP(sport=sport, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'nh_udp_ports' - self.create_classify_table( - key, - self.build_ip6_mask(nh='ff', src_port='ffff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_UDP, src_port=sport, - dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierIP6TCP(TestClassifier): - """ Classifier IP6 TCP proto Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP6TCP, cls).setUpClass() - cls.af = socket.AF_INET6 - - def test_iacl_proto_tcp(self): - """ IP6 TCP protocol iACL test - - Test scenario for basic protocol ACL with TCP protocol - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP protocol - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=1234, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'nh_tcp' - self.create_classify_table(key, self.build_ip6_mask(nh='ff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_TCP)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_sport(self): - """ IP6 TCP source port iACL test - - Test scenario for basic protocol ACL with TCP and sport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined sport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and sport - sport = 38 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=sport, dport=5678)) - self.pg0.add_stream(pkts) - - key = 'nh_tcp_sport' - self.create_classify_table( - key, self.build_ip6_mask(nh='ff', src_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_TCP, src_port=sport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_dport(self): - """ IP6 TCP destination port iACL test - - Test scenario for basic protocol ACL with TCP and dport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and dport - dport = 427 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=1234, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'nh_tcp_dport' - self.create_classify_table( - key, self.build_ip6_mask(nh='ff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_TCP, dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - def test_iacl_proto_tcp_sport_dport(self): - """ IP6 TCP source and destination ports iACL test - - Test scenario for basic protocol ACL with TCP and sport and dport - - Create IPv6 stream for pg0 -> pg1 interface. - - Create iACL with TCP IP protocol and defined sport and dport. - - Send and verify received packets on pg1 interface. - """ - - # Basic iACL testing with TCP and sport and dport - sport = 13720 - dport = 9080 - pkts = self.create_stream(self.pg0, self.pg1, self.pg_if_packet_sizes, - TCP(sport=sport, dport=dport)) - self.pg0.add_stream(pkts) - - key = 'nh_tcp_ports' - self.create_classify_table( - key, - self.build_ip6_mask(nh='ff', src_port='ffff', dst_port='ffff')) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(nh=socket.IPPROTO_TCP, src_port=sport, - dst_port=dport)) - self.input_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg1.get_capture(len(pkts)) - self.verify_capture(self.pg1, pkts, TCP) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierIP6Out(TestClassifier): - """ Classifier output IP6 Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP6Out, cls).setUpClass() - cls.af = socket.AF_INET6 - - def test_acl_ip_out(self): - """ Output IP6 ACL test - - Test scenario for basic IP ACL with source IP - - Create IPv6 stream for pg1 -> pg0 interface. - - Create ACL with source IP address. - - Send and verify received packets on pg0 interface. - """ - - # Basic oACL testing with source IP - pkts = self.create_stream(self.pg1, self.pg0, self.pg_if_packet_sizes) - self.pg1.add_stream(pkts) - - key = 'ip6_out' - self.create_classify_table( - key, - self.build_ip6_mask(src_ip='ffffffffffffffffffffffffffffffff'), - data_offset=0) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_ip6_match(src_ip=self.pg1.remote_ip6)) - self.output_acl_set_interface( - self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg0.get_capture(len(pkts)) - self.verify_capture(self.pg0, pkts) - self.pg1.assert_nothing_captured(remark="packets forwarded") - self.pg2.assert_nothing_captured(remark="packets forwarded") - - -class TestClassifierIP6MAC(TestClassifier): - """ Classifier IP6 MAC Test Case """ - - @classmethod - def setUpClass(cls): - super(TestClassifierIP6MAC, cls).setUpClass() - cls.af = socket.AF_INET6 - - def test_acl_mac(self): - """ IP6 MAC iACL test - - Test scenario for basic MAC ACL with source MAC - - Create IPv6 stream for pg0 -> pg2 interface. - - Create ACL with source MAC address. - - Send and verify received packets on pg2 interface. - """ - - # Basic iACL testing with source MAC - pkts = self.create_stream(self.pg0, self.pg2, self.pg_if_packet_sizes) - self.pg0.add_stream(pkts) - - key = 'mac' - self.create_classify_table( - key, self.build_mac_mask(src_mac='ffffffffffff'), data_offset=-14) - self.create_classify_session( - self.acl_tbl_idx.get(key), - self.build_mac_match(src_mac=self.pg0.remote_mac)) - self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key)) - self.acl_active_table = key - - self.pg_enable_capture(self.pg_interfaces) - self.pg_start() - - pkts = self.pg2.get_capture(len(pkts)) - self.verify_capture(self.pg2, pkts) - self.pg0.assert_nothing_captured(remark="packets forwarded") - self.pg1.assert_nothing_captured(remark="packets forwarded") - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/crypto/test/test_crypto.py b/src/vnet/crypto/test/test_crypto.py deleted file mode 100644 index aa62dba1bab..00000000000 --- a/src/vnet/crypto/test/test_crypto.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -from framework import VppTestCase, VppTestRunner - - -class TestCrypto(VppTestCase): - """ Crypto Test Case """ - - @classmethod - def setUpClass(cls): - super(TestCrypto, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestCrypto, cls).tearDownClass() - - def test_crypto(self): - """ Crypto Unit Tests """ - error = self.vapi.cli("test crypto") - - if error: - self.logger.critical(error) - self.assertNotIn("FAIL", error) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/fib/test/test_dvr.py b/src/vnet/fib/test/test_dvr.py deleted file mode 100644 index 8531b8553ca..00000000000 --- a/src/vnet/fib/test/test_dvr.py +++ /dev/null @@ -1,410 +0,0 @@ -#!/usr/bin/env python3 -import unittest - -from framework import VppTestCase, VppTestRunner -from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType -from vpp_l2 import L2_PORT_TYPE -from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint -from vpp_acl import AclRule, VppAcl, VppAclInterface - -from scapy.packet import Raw -from scapy.layers.l2 import Ether, Dot1Q -from scapy.layers.inet import IP, UDP -from socket import AF_INET, inet_pton -from ipaddress import IPv4Network - -NUM_PKTS = 67 - - -class TestDVR(VppTestCase): - """ Distributed Virtual Router """ - - @classmethod - def setUpClass(cls): - super(TestDVR, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestDVR, cls).tearDownClass() - - def setUp(self): - super(TestDVR, self).setUp() - - self.create_pg_interfaces(range(4)) - self.create_loopback_interfaces(1) - - for i in self.pg_interfaces: - i.admin_up() - - self.loop0.config_ip4() - - def tearDown(self): - for i in self.pg_interfaces: - i.admin_down() - self.loop0.unconfig_ip4() - - super(TestDVR, self).tearDown() - - def assert_same_mac_addr(self, tx, rx): - t_eth = tx[Ether] - for p in rx: - r_eth = p[Ether] - self.assertEqual(t_eth.src, r_eth.src) - self.assertEqual(t_eth.dst, r_eth.dst) - - def assert_has_vlan_tag(self, tag, rx): - for p in rx: - r_1q = p[Dot1Q] - self.assertEqual(tag, r_1q.vlan) - - def assert_has_no_tag(self, rx): - for p in rx: - self.assertFalse(p.haslayer(Dot1Q)) - - def test_dvr(self): - """ Distributed Virtual Router """ - - # - # A packet destined to an IP address that is L2 bridged via - # a non-tag interface - # - ip_non_tag_bridged = "10.10.10.10" - ip_tag_bridged = "10.10.10.11" - any_src_addr = "1.1.1.1" - - pkt_no_tag = (Ether(src=self.pg0.remote_mac, - dst=self.loop0.local_mac) / - IP(src=any_src_addr, - dst=ip_non_tag_bridged) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - pkt_tag = (Ether(src=self.pg0.remote_mac, - dst=self.loop0.local_mac) / - IP(src=any_src_addr, - dst=ip_tag_bridged) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - - # - # Two sub-interfaces so we can test VLAN tag push/pop - # - sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92) - sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93) - sub_if_on_pg2.admin_up() - sub_if_on_pg3.admin_up() - - # - # Put all the interfaces into a new bridge domain - # - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg0.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, - port_type=L2_PORT_TYPE.BVI) - - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=92) - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=93) - - # - # Add routes to bridge the traffic via a tagged an nontagged interface - # - route_no_tag = VppIpRoute( - self, ip_non_tag_bridged, 32, - [VppRoutePath("0.0.0.0", - self.pg1.sw_if_index, - type=FibPathType.FIB_PATH_TYPE_DVR)]) - route_no_tag.add_vpp_config() - - # - # Inject the packet that arrives and leaves on a non-tagged interface - # Since it's 'bridged' expect that the MAC headed is unchanged. - # - rx = self.send_and_expect(self.pg0, pkt_no_tag * NUM_PKTS, self.pg1) - self.assert_same_mac_addr(pkt_no_tag, rx) - self.assert_has_no_tag(rx) - - # - # Add routes to bridge the traffic via a tagged interface - # - route_with_tag = VppIpRoute( - self, ip_tag_bridged, 32, - [VppRoutePath("0.0.0.0", - sub_if_on_pg3.sw_if_index, - type=FibPathType.FIB_PATH_TYPE_DVR)]) - route_with_tag.add_vpp_config() - - # - # Inject the packet that arrives non-tag and leaves on a tagged - # interface - # - rx = self.send_and_expect(self.pg0, pkt_tag * NUM_PKTS, self.pg3) - self.assert_same_mac_addr(pkt_tag, rx) - self.assert_has_vlan_tag(93, rx) - - # - # Tag to tag - # - pkt_tag_to_tag = (Ether(src=self.pg2.remote_mac, - dst=self.loop0.local_mac) / - Dot1Q(vlan=92) / - IP(src=any_src_addr, - dst=ip_tag_bridged) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - - rx = self.send_and_expect(self.pg2, - pkt_tag_to_tag * NUM_PKTS, - self.pg3) - self.assert_same_mac_addr(pkt_tag_to_tag, rx) - self.assert_has_vlan_tag(93, rx) - - # - # Tag to non-Tag - # - pkt_tag_to_non_tag = (Ether(src=self.pg2.remote_mac, - dst=self.loop0.local_mac) / - Dot1Q(vlan=92) / - IP(src=any_src_addr, - dst=ip_non_tag_bridged) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - - rx = self.send_and_expect(self.pg2, - pkt_tag_to_non_tag * NUM_PKTS, - self.pg1) - self.assert_same_mac_addr(pkt_tag_to_tag, rx) - self.assert_has_no_tag(rx) - - # - # Add an output L3 ACL that will block the traffic - # - rule_1 = AclRule(is_permit=0, proto=17, ports=1234, - src_prefix=IPv4Network((any_src_addr, 32)), - dst_prefix=IPv4Network((ip_non_tag_bridged, 32))) - acl = VppAcl(self, rules=[rule_1]) - acl.add_vpp_config() - - # - # Apply the ACL on the output interface - # - acl_if1 = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index, - n_input=0, acls=[acl]) - acl_if1.add_vpp_config() - - # - # Send packet's that should match the ACL and be dropped - # - rx = self.send_and_assert_no_replies(self.pg2, - pkt_tag_to_non_tag * NUM_PKTS) - - # - # cleanup - # - acl_if1.remove_vpp_config() - acl.remove_vpp_config() - - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, - port_type=L2_PORT_TYPE.BVI, enable=0) - - # - # Do a FIB dump to make sure the paths are correctly reported as DVR - # - routes = self.vapi.ip_route_dump(0) - - for r in routes: - if (ip_tag_bridged == str(r.route.prefix.network_address)): - self.assertEqual(r.route.paths[0].sw_if_index, - sub_if_on_pg3.sw_if_index) - self.assertEqual(r.route.paths[0].type, - FibPathType.FIB_PATH_TYPE_DVR) - if (ip_non_tag_bridged == str(r.route.prefix.network_address)): - self.assertEqual(r.route.paths[0].sw_if_index, - self.pg1.sw_if_index) - self.assertEqual(r.route.paths[0].type, - FibPathType.FIB_PATH_TYPE_DVR) - - # - # the explicit route delete is require so it happens before - # the sbu-interface delete. subinterface delete is required - # because that object type does not use the object registry - # - route_no_tag.remove_vpp_config() - route_with_tag.remove_vpp_config() - sub_if_on_pg3.remove_vpp_config() - sub_if_on_pg2.remove_vpp_config() - - def test_l2_emulation(self): - """ L2 Emulation """ - - # - # non distinct L3 packets, in the tag/non-tag combos - # - pkt_no_tag = (Ether(src=self.pg0.remote_mac, - dst=self.pg1.remote_mac) / - IP(src="2.2.2.2", - dst="1.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - pkt_to_tag = (Ether(src=self.pg0.remote_mac, - dst=self.pg2.remote_mac) / - IP(src="2.2.2.2", - dst="1.1.1.2") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - pkt_from_tag = (Ether(src=self.pg3.remote_mac, - dst=self.pg2.remote_mac) / - Dot1Q(vlan=93) / - IP(src="2.2.2.2", - dst="1.1.1.1") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - pkt_from_to_tag = (Ether(src=self.pg3.remote_mac, - dst=self.pg2.remote_mac) / - Dot1Q(vlan=93) / - IP(src="2.2.2.2", - dst="1.1.1.2") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - pkt_bcast = (Ether(src=self.pg0.remote_mac, - dst="ff:ff:ff:ff:ff:ff") / - IP(src="2.2.2.2", - dst="255.255.255.255") / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - - # - # A couple of sub-interfaces for tags - # - sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92) - sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93) - sub_if_on_pg2.admin_up() - sub_if_on_pg3.admin_up() - - # - # Put all the interfaces into a new bridge domain - # - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg0.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1) - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=92) - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=93) - - # - # Disable UU flooding, learning and ARP termination. makes this test - # easier as unicast packets are dropped if not extracted. - # - self.vapi.bridge_flags(bd_id=1, is_set=0, - flags=(1 << 0) | (1 << 3) | (1 << 4)) - - # - # Add a DVR route to steer traffic at L3 - # - route_1 = VppIpRoute( - self, "1.1.1.1", 32, - [VppRoutePath("0.0.0.0", - self.pg1.sw_if_index, - type=FibPathType.FIB_PATH_TYPE_DVR)]) - route_2 = VppIpRoute( - self, "1.1.1.2", 32, - [VppRoutePath("0.0.0.0", - sub_if_on_pg2.sw_if_index, - type=FibPathType.FIB_PATH_TYPE_DVR)]) - route_1.add_vpp_config() - route_2.add_vpp_config() - - # - # packets are dropped because bridge does not flood unknown unicast - # - self.send_and_assert_no_replies(self.pg0, pkt_no_tag) - - # - # Enable L3 extraction on pgs - # - self.vapi.l2_emulation(self.pg0.sw_if_index) - self.vapi.l2_emulation(self.pg1.sw_if_index) - self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index) - self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index) - - # - # now we expect the packet forward according to the DVR route - # - rx = self.send_and_expect(self.pg0, pkt_no_tag * NUM_PKTS, self.pg1) - self.assert_same_mac_addr(pkt_no_tag, rx) - self.assert_has_no_tag(rx) - - rx = self.send_and_expect(self.pg0, pkt_to_tag * NUM_PKTS, self.pg2) - self.assert_same_mac_addr(pkt_to_tag, rx) - self.assert_has_vlan_tag(92, rx) - - rx = self.send_and_expect(self.pg3, pkt_from_tag * NUM_PKTS, self.pg1) - self.assert_same_mac_addr(pkt_from_tag, rx) - self.assert_has_no_tag(rx) - - rx = self.send_and_expect(self.pg3, - pkt_from_to_tag * NUM_PKTS, - self.pg2) - self.assert_same_mac_addr(pkt_from_tag, rx) - self.assert_has_vlan_tag(92, rx) - - # - # but broadcast packets are still flooded - # - self.send_and_expect(self.pg0, pkt_bcast * 33, self.pg2) - - # - # cleanup - # - self.vapi.l2_emulation(self.pg0.sw_if_index, - enable=0) - self.vapi.l2_emulation(self.pg1.sw_if_index, - enable=0) - self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index, - enable=0) - self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index, - enable=0) - - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0) - - route_1.remove_vpp_config() - route_2.remove_vpp_config() - sub_if_on_pg3.remove_vpp_config() - sub_if_on_pg2.remove_vpp_config() - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/fib/test/test_fib.py b/src/vnet/fib/test/test_fib.py deleted file mode 100644 index 7c08722d803..00000000000 --- a/src/vnet/fib/test/test_fib.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -from framework import tag_fixme_vpp_workers -from framework import VppTestCase, VppTestRunner - - -@tag_fixme_vpp_workers -class TestFIB(VppTestCase): - """ FIB Test Case """ - - @classmethod - def setUpClass(cls): - super(TestFIB, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestFIB, cls).tearDownClass() - - def test_fib(self): - """ FIB Unit Tests """ - error = self.vapi.cli("test fib") - - # shameless test of CLIs to bump lcov results... - # no i mean to ensure they don't crash - self.logger.info(self.vapi.cli("sh fib source")) - self.logger.info(self.vapi.cli("sh fib source prio")) - self.logger.info(self.vapi.cli("sh fib memory")) - self.logger.info(self.vapi.cli("sh fib entry")) - self.logger.info(self.vapi.cli("sh fib entry 0")) - self.logger.info(self.vapi.cli("sh fib entry 10000")) - self.logger.info(self.vapi.cli("sh fib entry-delegate")) - self.logger.info(self.vapi.cli("sh fib paths")) - self.logger.info(self.vapi.cli("sh fib paths 0")) - self.logger.info(self.vapi.cli("sh fib paths 10000")) - self.logger.info(self.vapi.cli("sh fib path-list")) - self.logger.info(self.vapi.cli("sh fib path-list 0")) - self.logger.info(self.vapi.cli("sh fib path-list 10000")) - self.logger.info(self.vapi.cli("sh fib walk")) - self.logger.info(self.vapi.cli("sh fib uRPF")) - - if error: - self.logger.critical(error) - self.assertNotIn("Failed", error) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/gre/test/test_gre.py b/src/vnet/gre/test/test_gre.py deleted file mode 100644 index ba20ba8dec0..00000000000 --- a/src/vnet/gre/test/test_gre.py +++ /dev/null @@ -1,1296 +0,0 @@ -#!/usr/bin/env python3 - -import unittest - -import scapy.compat -from scapy.packet import Raw -from scapy.layers.l2 import Ether, Dot1Q, GRE -from scapy.layers.inet import IP, UDP -from scapy.layers.inet6 import IPv6 -from scapy.volatile import RandMAC, RandIP - -from framework import tag_fixme_vpp_workers -from framework import VppTestCase, VppTestRunner -from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint -from vpp_gre_interface import VppGreInterface -from vpp_teib import VppTeib -from vpp_ip import DpoProto -from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto, \ - VppMplsLabel -from vpp_mpls_tunnel_interface import VppMPLSTunnelInterface -from util import ppp, ppc -from vpp_papi import VppEnum - - -@tag_fixme_vpp_workers -class TestGREInputNodes(VppTestCase): - """ GRE Input Nodes Test Case """ - - def setUp(self): - super(TestGREInputNodes, self).setUp() - - # create 3 pg interfaces - set one in a non-default table. - self.create_pg_interfaces(range(1)) - - for i in self.pg_interfaces: - i.admin_up() - i.config_ip4() - - def tearDown(self): - for i in self.pg_interfaces: - i.unconfig_ip4() - i.admin_down() - super(TestGREInputNodes, self).tearDown() - - def test_gre_input_node(self): - """ GRE gre input nodes not registerd unless configured """ - pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / - GRE()) - - self.pg0.add_stream(pkt) - self.pg_start() - # no tunnel created, gre-input not registered - err = self.statistics.get_counter( - '/err/ip4-local/unknown ip protocol')[0] - self.assertEqual(err, 1) - err_count = err - - # create gre tunnel - gre_if = VppGreInterface(self, self.pg0.local_ip4, "1.1.1.2") - gre_if.add_vpp_config() - - self.pg0.add_stream(pkt) - self.pg_start() - # tunnel created, gre-input registered - err = self.statistics.get_counter( - '/err/ip4-local/unknown ip protocol')[0] - # expect no new errors - self.assertEqual(err, err_count) - - -class TestGRE(VppTestCase): - """ GRE Test Case """ - - @classmethod - def setUpClass(cls): - super(TestGRE, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - super(TestGRE, cls).tearDownClass() - - def setUp(self): - super(TestGRE, self).setUp() - - # create 3 pg interfaces - set one in a non-default table. - self.create_pg_interfaces(range(5)) - - self.tbl = VppIpTable(self, 1) - self.tbl.add_vpp_config() - self.pg1.set_table_ip4(1) - - for i in self.pg_interfaces: - i.admin_up() - - self.pg0.config_ip4() - self.pg0.resolve_arp() - self.pg1.config_ip4() - self.pg1.resolve_arp() - self.pg2.config_ip6() - self.pg2.resolve_ndp() - self.pg3.config_ip4() - self.pg3.resolve_arp() - self.pg4.config_ip4() - self.pg4.resolve_arp() - - def tearDown(self): - for i in self.pg_interfaces: - i.unconfig_ip4() - i.unconfig_ip6() - i.admin_down() - self.pg1.set_table_ip4(0) - super(TestGRE, self).tearDown() - - def create_stream_ip4(self, src_if, src_ip, dst_ip, dscp=0, ecn=0): - pkts = [] - tos = (dscp << 2) | ecn - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=src_ip, dst=dst_ip, tos=tos) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_stream_ip6(self, src_if, src_ip, dst_ip, dscp=0, ecn=0): - pkts = [] - tc = (dscp << 2) | ecn - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IPv6(src=src_ip, dst=dst_ip, tc=tc) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_tunnel_stream_4o4(self, src_if, - tunnel_src, tunnel_dst, - src_ip, dst_ip): - pkts = [] - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=tunnel_src, dst=tunnel_dst) / - GRE() / - IP(src=src_ip, dst=dst_ip) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_tunnel_stream_6o4(self, src_if, - tunnel_src, tunnel_dst, - src_ip, dst_ip): - pkts = [] - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=tunnel_src, dst=tunnel_dst) / - GRE() / - IPv6(src=src_ip, dst=dst_ip) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_tunnel_stream_6o6(self, src_if, - tunnel_src, tunnel_dst, - src_ip, dst_ip): - pkts = [] - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IPv6(src=tunnel_src, dst=tunnel_dst) / - GRE() / - IPv6(src=src_ip, dst=dst_ip) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_tunnel_stream_l2o4(self, src_if, - tunnel_src, tunnel_dst): - pkts = [] - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=tunnel_src, dst=tunnel_dst) / - GRE() / - Ether(dst=RandMAC('*:*:*:*:*:*'), - src=RandMAC('*:*:*:*:*:*')) / - IP(src=scapy.compat.raw(RandIP()), - dst=scapy.compat.raw(RandIP())) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def create_tunnel_stream_vlano4(self, src_if, - tunnel_src, tunnel_dst, vlan): - pkts = [] - for i in range(0, 257): - info = self.create_packet_info(src_if, src_if) - payload = self.info_to_payload(info) - p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / - IP(src=tunnel_src, dst=tunnel_dst) / - GRE() / - Ether(dst=RandMAC('*:*:*:*:*:*'), - src=RandMAC('*:*:*:*:*:*')) / - Dot1Q(vlan=vlan) / - IP(src=scapy.compat.raw(RandIP()), - dst=scapy.compat.raw(RandIP())) / - UDP(sport=1234, dport=1234) / - Raw(payload)) - info.data = p.copy() - pkts.append(p) - return pkts - - def verify_tunneled_4o4(self, src_if, capture, sent, - tunnel_src, tunnel_dst, - dscp=0, ecn=0): - - self.assertEqual(len(capture), len(sent)) - tos = (dscp << 2) | ecn - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IP] - rx_ip = rx[IP] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - self.assertEqual(rx_ip.tos, tos) - self.assertEqual(rx_ip.len, len(rx_ip)) - - rx_gre = rx[GRE] - rx_ip = rx_gre[IP] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - # IP processing post pop has decremented the TTL - self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_tunneled_6o6(self, src_if, capture, sent, - tunnel_src, tunnel_dst, - dscp=0, ecn=0): - - self.assertEqual(len(capture), len(sent)) - tc = (dscp << 2) | ecn - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IPv6] - rx_ip = rx[IPv6] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - self.assertEqual(rx_ip.tc, tc) - - rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload)) - - self.assertEqual(rx_ip.plen, len(rx_gre)) - - rx_ip = rx_gre[IPv6] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_tunneled_4o6(self, src_if, capture, sent, - tunnel_src, tunnel_dst): - - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - rx_ip = rx[IPv6] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - - rx_gre = GRE(scapy.compat.raw(rx_ip[IPv6].payload)) - - self.assertEqual(rx_ip.plen, len(rx_gre)) - - tx_ip = tx[IP] - rx_ip = rx_gre[IP] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_tunneled_6o4(self, src_if, capture, sent, - tunnel_src, tunnel_dst): - - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - rx_ip = rx[IP] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - self.assertEqual(rx_ip.len, len(rx_ip)) - - rx_gre = GRE(scapy.compat.raw(rx_ip[IP].payload)) - rx_ip = rx_gre[IPv6] - tx_ip = tx[IPv6] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_tunneled_l2o4(self, src_if, capture, sent, - tunnel_src, tunnel_dst): - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IP] - rx_ip = rx[IP] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - self.assertEqual(rx_ip.len, len(rx_ip)) - - rx_gre = rx[GRE] - rx_l2 = rx_gre[Ether] - rx_ip = rx_l2[IP] - tx_gre = tx[GRE] - tx_l2 = tx_gre[Ether] - tx_ip = tx_l2[IP] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - # bridged, not L3 forwarded, so no TTL decrement - self.assertEqual(rx_ip.ttl, tx_ip.ttl) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_tunneled_vlano4(self, src_if, capture, sent, - tunnel_src, tunnel_dst, vlan): - try: - self.assertEqual(len(capture), len(sent)) - except: - ppc("Unexpected packets captured:", capture) - raise - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IP] - rx_ip = rx[IP] - - self.assertEqual(rx_ip.src, tunnel_src) - self.assertEqual(rx_ip.dst, tunnel_dst) - - rx_gre = rx[GRE] - rx_l2 = rx_gre[Ether] - rx_vlan = rx_l2[Dot1Q] - rx_ip = rx_l2[IP] - - self.assertEqual(rx_vlan.vlan, vlan) - - tx_gre = tx[GRE] - tx_l2 = tx_gre[Ether] - tx_ip = tx_l2[IP] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - # bridged, not L3 forwarded, so no TTL decrement - self.assertEqual(rx_ip.ttl, tx_ip.ttl) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_decapped_4o4(self, src_if, capture, sent): - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IP] - rx_ip = rx[IP] - tx_gre = tx[GRE] - tx_ip = tx_gre[IP] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - # IP processing post pop has decremented the TTL - self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_decapped_6o4(self, src_if, capture, sent): - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IP] - rx_ip = rx[IPv6] - tx_gre = tx[GRE] - tx_ip = tx_gre[IPv6] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def verify_decapped_6o6(self, src_if, capture, sent): - self.assertEqual(len(capture), len(sent)) - - for i in range(len(capture)): - try: - tx = sent[i] - rx = capture[i] - - tx_ip = tx[IPv6] - rx_ip = rx[IPv6] - tx_gre = tx[GRE] - tx_ip = tx_gre[IPv6] - - self.assertEqual(rx_ip.src, tx_ip.src) - self.assertEqual(rx_ip.dst, tx_ip.dst) - self.assertEqual(rx_ip.hlim + 1, tx_ip.hlim) - - except: - self.logger.error(ppp("Rx:", rx)) - self.logger.error(ppp("Tx:", tx)) - raise - - def test_gre(self): - """ GRE IPv4 tunnel Tests """ - - # - # Create an L3 GRE tunnel. - # - set it admin up - # - assign an IP Addres - # - Add a route via the tunnel - # - gre_if = VppGreInterface(self, - self.pg0.local_ip4, - "1.1.1.2") - gre_if.add_vpp_config() - - # - # The double create (create the same tunnel twice) should fail, - # and we should still be able to use the original - # - try: - gre_if.add_vpp_config() - except Exception: - pass - else: - self.fail("Double GRE tunnel add does not fail") - - gre_if.admin_up() - gre_if.config_ip4() - - route_via_tun = VppIpRoute(self, "4.4.4.4", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index)]) - - route_via_tun.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - they are all dropped since the tunnel's destintation IP - # is unresolved - or resolves via the default route - which - # which is a drop. - # - tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4") - - self.send_and_assert_no_replies(self.pg0, tx) - - # - # Add a route that resolves the tunnel's destination - # - route_tun_dst = VppIpRoute(self, "1.1.1.2", 32, - [VppRoutePath(self.pg0.remote_ip4, - self.pg0.sw_if_index)]) - route_tun_dst.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - packets are GRE encapped - # - tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "4.4.4.4") - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_4o4(self.pg0, rx, tx, - self.pg0.local_ip4, "1.1.1.2") - - # - # Send tunneled packets that match the created tunnel and - # are decapped and forwarded - # - tx = self.create_tunnel_stream_4o4(self.pg0, - "1.1.1.2", - self.pg0.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_decapped_4o4(self.pg0, rx, tx) - - # - # Send tunneled packets that do not match the tunnel's src - # - self.vapi.cli("clear trace") - tx = self.create_tunnel_stream_4o4(self.pg0, - "1.1.1.3", - self.pg0.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - self.send_and_assert_no_replies( - self.pg0, tx, - remark="GRE packets forwarded despite no SRC address match") - - # - # Configure IPv6 on the PG interface so we can route IPv6 - # packets - # - self.pg0.config_ip6() - self.pg0.resolve_ndp() - - # - # Send IPv6 tunnel encapslated packets - # - dropped since IPv6 is not enabled on the tunnel - # - tx = self.create_tunnel_stream_6o4(self.pg0, - "1.1.1.2", - self.pg0.local_ip4, - self.pg0.local_ip6, - self.pg0.remote_ip6) - self.send_and_assert_no_replies(self.pg0, tx, - "IPv6 GRE packets forwarded " - "despite IPv6 not enabled on tunnel") - - # - # Enable IPv6 on the tunnel - # - gre_if.config_ip6() - - # - # Send IPv6 tunnel encapslated packets - # - forwarded since IPv6 is enabled on the tunnel - # - tx = self.create_tunnel_stream_6o4(self.pg0, - "1.1.1.2", - self.pg0.local_ip4, - self.pg0.local_ip6, - self.pg0.remote_ip6) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_decapped_6o4(self.pg0, rx, tx) - - # - # Send v6 packets for v4 encap - # - route6_via_tun = VppIpRoute( - self, "2001::1", 128, - [VppRoutePath("::", - gre_if.sw_if_index, - proto=DpoProto.DPO_PROTO_IP6)]) - route6_via_tun.add_vpp_config() - - tx = self.create_stream_ip6(self.pg0, "2001::2", "2001::1") - rx = self.send_and_expect(self.pg0, tx, self.pg0) - - self.verify_tunneled_6o4(self.pg0, rx, tx, - self.pg0.local_ip4, "1.1.1.2") - - # - # add a labelled route through the tunnel - # - label_via_tun = VppIpRoute(self, "5.4.3.2", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index, - labels=[VppMplsLabel(33)])]) - label_via_tun.add_vpp_config() - - tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.2") - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_4o4(self.pg0, rx, tx, - self.pg0.local_ip4, "1.1.1.2") - - # - # an MPLS tunnel over the GRE tunnel add a route through - # the mpls tunnel - # - mpls_tun = VppMPLSTunnelInterface( - self, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index, - labels=[VppMplsLabel(44), - VppMplsLabel(46)])]) - mpls_tun.add_vpp_config() - mpls_tun.admin_up() - - label_via_mpls = VppIpRoute(self, "5.4.3.1", 32, - [VppRoutePath("0.0.0.0", - mpls_tun.sw_if_index, - labels=[VppMplsLabel(33)])]) - label_via_mpls.add_vpp_config() - - tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "5.4.3.1") - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_4o4(self.pg0, rx, tx, - self.pg0.local_ip4, "1.1.1.2") - - mpls_tun_l2 = VppMPLSTunnelInterface( - self, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index, - labels=[VppMplsLabel(44), - VppMplsLabel(46)])], - is_l2=1) - mpls_tun_l2.add_vpp_config() - mpls_tun_l2.admin_up() - - # - # test case cleanup - # - route_tun_dst.remove_vpp_config() - route_via_tun.remove_vpp_config() - route6_via_tun.remove_vpp_config() - label_via_mpls.remove_vpp_config() - label_via_tun.remove_vpp_config() - mpls_tun.remove_vpp_config() - mpls_tun_l2.remove_vpp_config() - gre_if.remove_vpp_config() - - self.pg0.unconfig_ip6() - - def test_gre6(self): - """ GRE IPv6 tunnel Tests """ - - self.pg1.config_ip6() - self.pg1.resolve_ndp() - - # - # Create an L3 GRE tunnel. - # - set it admin up - # - assign an IP Address - # - Add a route via the tunnel - # - gre_if = VppGreInterface(self, - self.pg2.local_ip6, - "1002::1") - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip6() - - route_via_tun = VppIpRoute(self, "4004::1", 128, - [VppRoutePath("0::0", - gre_if.sw_if_index)]) - - route_via_tun.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - they are all dropped since the tunnel's destintation IP - # is unresolved - or resolves via the default route - which - # which is a drop. - # - tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") - self.send_and_assert_no_replies( - self.pg2, tx, - "GRE packets forwarded without DIP resolved") - - # - # Add a route that resolves the tunnel's destination - # - route_tun_dst = VppIpRoute(self, "1002::1", 128, - [VppRoutePath(self.pg2.remote_ip6, - self.pg2.sw_if_index)]) - route_tun_dst.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - packets are GRE encapped - # - tx = self.create_stream_ip6(self.pg2, "5005::1", "4004::1") - rx = self.send_and_expect(self.pg2, tx, self.pg2) - self.verify_tunneled_6o6(self.pg2, rx, tx, - self.pg2.local_ip6, "1002::1") - - # - # Test decap. decapped packets go out pg1 - # - tx = self.create_tunnel_stream_6o6(self.pg2, - "1002::1", - self.pg2.local_ip6, - "2001::1", - self.pg1.remote_ip6) - rx = self.send_and_expect(self.pg2, tx, self.pg1) - - # - # RX'd packet is UDP over IPv6, test the GRE header is gone. - # - self.assertFalse(rx[0].haslayer(GRE)) - self.assertEqual(rx[0][IPv6].dst, self.pg1.remote_ip6) - - # - # Send v4 over v6 - # - route4_via_tun = VppIpRoute(self, "1.1.1.1", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index)]) - route4_via_tun.add_vpp_config() - - tx = self.create_stream_ip4(self.pg0, "1.1.1.2", "1.1.1.1") - rx = self.send_and_expect(self.pg0, tx, self.pg2) - - self.verify_tunneled_4o6(self.pg0, rx, tx, - self.pg2.local_ip6, "1002::1") - - # - # test case cleanup - # - route_tun_dst.remove_vpp_config() - route_via_tun.remove_vpp_config() - route4_via_tun.remove_vpp_config() - gre_if.remove_vpp_config() - - self.pg2.unconfig_ip6() - self.pg1.unconfig_ip6() - - def test_gre_vrf(self): - """ GRE tunnel VRF Tests """ - - e = VppEnum.vl_api_tunnel_encap_decap_flags_t - - # - # Create an L3 GRE tunnel whose destination is in the non-default - # table. The underlay is thus non-default - the overlay is still - # the default. - # - set it admin up - # - assign an IP Addres - # - gre_if = VppGreInterface( - self, self.pg1.local_ip4, - "2.2.2.2", - outer_table_id=1, - flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP | - e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN)) - - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip4() - - # - # Add a route via the tunnel - in the overlay - # - route_via_tun = VppIpRoute(self, "9.9.9.9", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index)]) - route_via_tun.add_vpp_config() - - # - # Add a route that resolves the tunnel's destination - in the - # underlay table - # - route_tun_dst = VppIpRoute(self, "2.2.2.2", 32, table_id=1, - paths=[VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index)]) - route_tun_dst.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # packets are sent in on pg0 which is in the default table - # - packets are GRE encapped - # - self.vapi.cli("clear trace") - tx = self.create_stream_ip4(self.pg0, "5.5.5.5", "9.9.9.9", - dscp=5, ecn=3) - rx = self.send_and_expect(self.pg0, tx, self.pg1) - self.verify_tunneled_4o4(self.pg1, rx, tx, - self.pg1.local_ip4, "2.2.2.2", - dscp=5, ecn=3) - - # - # Send tunneled packets that match the created tunnel and - # are decapped and forwarded. This tests the decap lookup - # does not happen in the encap table - # - self.vapi.cli("clear trace") - tx = self.create_tunnel_stream_4o4(self.pg1, - "2.2.2.2", - self.pg1.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - rx = self.send_and_expect(self.pg1, tx, self.pg0) - self.verify_decapped_4o4(self.pg0, rx, tx) - - # - # Send tunneled packets that match the created tunnel - # but arrive on an interface that is not in the tunnel's - # encap VRF, these are dropped. - # IP enable the interface so they aren't dropped due to - # IP not being enabled. - # - self.pg2.config_ip4() - self.vapi.cli("clear trace") - tx = self.create_tunnel_stream_4o4(self.pg2, - "2.2.2.2", - self.pg1.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - rx = self.send_and_assert_no_replies( - self.pg2, tx, - "GRE decap packets in wrong VRF") - - self.pg2.unconfig_ip4() - - # - # test case cleanup - # - route_tun_dst.remove_vpp_config() - route_via_tun.remove_vpp_config() - gre_if.remove_vpp_config() - - def test_gre_l2(self): - """ GRE tunnel L2 Tests """ - - # - # Add routes to resolve the tunnel destinations - # - route_tun1_dst = VppIpRoute(self, "2.2.2.2", 32, - [VppRoutePath(self.pg0.remote_ip4, - self.pg0.sw_if_index)]) - route_tun2_dst = VppIpRoute(self, "2.2.2.3", 32, - [VppRoutePath(self.pg0.remote_ip4, - self.pg0.sw_if_index)]) - - route_tun1_dst.add_vpp_config() - route_tun2_dst.add_vpp_config() - - # - # Create 2 L2 GRE tunnels and x-connect them - # - gre_if1 = VppGreInterface(self, self.pg0.local_ip4, - "2.2.2.2", - type=(VppEnum.vl_api_gre_tunnel_type_t. - GRE_API_TUNNEL_TYPE_TEB)) - gre_if2 = VppGreInterface(self, self.pg0.local_ip4, - "2.2.2.3", - type=(VppEnum.vl_api_gre_tunnel_type_t. - GRE_API_TUNNEL_TYPE_TEB)) - gre_if1.add_vpp_config() - gre_if2.add_vpp_config() - - gre_if1.admin_up() - gre_if2.admin_up() - - self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index, - gre_if2.sw_if_index, - enable=1) - self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index, - gre_if1.sw_if_index, - enable=1) - - # - # Send in tunnel encapped L2. expect out tunnel encapped L2 - # in both directions - # - tx = self.create_tunnel_stream_l2o4(self.pg0, - "2.2.2.2", - self.pg0.local_ip4) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_l2o4(self.pg0, rx, tx, - self.pg0.local_ip4, - "2.2.2.3") - - tx = self.create_tunnel_stream_l2o4(self.pg0, - "2.2.2.3", - self.pg0.local_ip4) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_l2o4(self.pg0, rx, tx, - self.pg0.local_ip4, - "2.2.2.2") - - self.vapi.sw_interface_set_l2_xconnect(gre_if1.sw_if_index, - gre_if2.sw_if_index, - enable=0) - self.vapi.sw_interface_set_l2_xconnect(gre_if2.sw_if_index, - gre_if1.sw_if_index, - enable=0) - - # - # Create a VLAN sub-interfaces on the GRE TEB interfaces - # then x-connect them - # - gre_if_11 = VppDot1QSubint(self, gre_if1, 11) - gre_if_12 = VppDot1QSubint(self, gre_if2, 12) - - # gre_if_11.add_vpp_config() - # gre_if_12.add_vpp_config() - - gre_if_11.admin_up() - gre_if_12.admin_up() - - self.vapi.sw_interface_set_l2_xconnect(gre_if_11.sw_if_index, - gre_if_12.sw_if_index, - enable=1) - self.vapi.sw_interface_set_l2_xconnect(gre_if_12.sw_if_index, - gre_if_11.sw_if_index, - enable=1) - - # - # Configure both to pop thier respective VLAN tags, - # so that during the x-coonect they will subsequently push - # - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=gre_if_12.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=12) - self.vapi.l2_interface_vlan_tag_rewrite( - sw_if_index=gre_if_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, - push_dot1q=11) - - # - # Send traffic in both directiond - expect the VLAN tags to - # be swapped. - # - tx = self.create_tunnel_stream_vlano4(self.pg0, - "2.2.2.2", - self.pg0.local_ip4, - 11) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_vlano4(self.pg0, rx, tx, - self.pg0.local_ip4, - "2.2.2.3", - 12) - - tx = self.create_tunnel_stream_vlano4(self.pg0, - "2.2.2.3", - self.pg0.local_ip4, - 12) - rx = self.send_and_expect(self.pg0, tx, self.pg0) - self.verify_tunneled_vlano4(self.pg0, rx, tx, - self.pg0.local_ip4, - "2.2.2.2", - 11) - - # - # Cleanup Test resources - # - gre_if_11.remove_vpp_config() - gre_if_12.remove_vpp_config() - gre_if1.remove_vpp_config() - gre_if2.remove_vpp_config() - route_tun1_dst.add_vpp_config() - route_tun2_dst.add_vpp_config() - - def test_gre_loop(self): - """ GRE tunnel loop Tests """ - - # - # Create an L3 GRE tunnel. - # - set it admin up - # - assign an IP Addres - # - gre_if = VppGreInterface(self, - self.pg0.local_ip4, - "1.1.1.2") - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip4() - - # - # add a route to the tunnel's destination that points - # through the tunnel, hence forming a loop in the forwarding - # graph - # - route_dst = VppIpRoute(self, "1.1.1.2", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index)]) - route_dst.add_vpp_config() - - # - # packets to the tunnels destination should be dropped - # - tx = self.create_stream_ip4(self.pg0, "1.1.1.1", "1.1.1.2") - self.send_and_assert_no_replies(self.pg2, tx) - - self.logger.info(self.vapi.ppcli("sh adj 7")) - - # - # break the loop - # - route_dst.modify([VppRoutePath(self.pg1.remote_ip4, - self.pg1.sw_if_index)]) - route_dst.add_vpp_config() - - rx = self.send_and_expect(self.pg0, tx, self.pg1) - - # - # a good route throught the tunnel to check it restacked - # - route_via_tun_2 = VppIpRoute(self, "2.2.2.2", 32, - [VppRoutePath("0.0.0.0", - gre_if.sw_if_index)]) - route_via_tun_2.add_vpp_config() - - tx = self.create_stream_ip4(self.pg0, "2.2.2.3", "2.2.2.2") - rx = self.send_and_expect(self.pg0, tx, self.pg1) - self.verify_tunneled_4o4(self.pg1, rx, tx, - self.pg0.local_ip4, "1.1.1.2") - - # - # cleanup - # - route_via_tun_2.remove_vpp_config() - gre_if.remove_vpp_config() - - def test_mgre(self): - """ mGRE IPv4 tunnel Tests """ - - for itf in self.pg_interfaces[3:]: - # - # one underlay nh for each overlay/tunnel peer - # - itf.generate_remote_hosts(4) - itf.configure_ipv4_neighbors() - - # - # Create an L3 GRE tunnel. - # - set it admin up - # - assign an IP Addres - # - Add a route via the tunnel - # - gre_if = VppGreInterface(self, - itf.local_ip4, - "0.0.0.0", - mode=(VppEnum.vl_api_tunnel_mode_t. - TUNNEL_API_MODE_MP)) - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip4() - gre_if.generate_remote_hosts(4) - - self.logger.info(self.vapi.cli("sh adj")) - self.logger.info(self.vapi.cli("sh ip fib")) - - # - # ensure we don't match to the tunnel if the source address - # is all zeros - # - tx = self.create_tunnel_stream_4o4(self.pg0, - "0.0.0.0", - itf.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - self.send_and_assert_no_replies(self.pg0, tx) - - # - # for-each peer - # - for ii in range(1, 4): - route_addr = "4.4.4.%d" % ii - tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr) - - # - # route traffic via the peer - # - route_via_tun = VppIpRoute( - self, route_addr, 32, - [VppRoutePath(gre_if._remote_hosts[ii].ip4, - gre_if.sw_if_index)]) - route_via_tun.add_vpp_config() - - # all packets dropped at this point - rx = self.send_and_assert_no_replies(self.pg0, tx_e) - - gre_if.admin_down() - gre_if.admin_up() - rx = self.send_and_assert_no_replies(self.pg0, tx_e) - - # - # Add a TEIB entry resolves the peer - # - teib = VppTeib(self, gre_if, - gre_if._remote_hosts[ii].ip4, - itf._remote_hosts[ii].ip4) - teib.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - packets are GRE encapped - # - rx = self.send_and_expect(self.pg0, tx_e, itf) - self.verify_tunneled_4o4(self.pg0, rx, tx_e, - itf.local_ip4, - itf._remote_hosts[ii].ip4) - - tx_i = self.create_tunnel_stream_4o4(self.pg0, - itf._remote_hosts[ii].ip4, - itf.local_ip4, - self.pg0.local_ip4, - self.pg0.remote_ip4) - rx = self.send_and_expect(self.pg0, tx_i, self.pg0) - self.verify_decapped_4o4(self.pg0, rx, tx_i) - - # - # delete and re-add the TEIB - # - teib.remove_vpp_config() - self.send_and_assert_no_replies(self.pg0, tx_e) - self.send_and_assert_no_replies(self.pg0, tx_i) - - teib.add_vpp_config() - rx = self.send_and_expect(self.pg0, tx_e, itf) - self.verify_tunneled_4o4(self.pg0, rx, tx_e, - itf.local_ip4, - itf._remote_hosts[ii].ip4) - rx = self.send_and_expect(self.pg0, tx_i, self.pg0) - self.verify_decapped_4o4(self.pg0, rx, tx_i) - - # - # bounce the interface state and try packets again - # - gre_if.admin_down() - gre_if.admin_up() - rx = self.send_and_expect(self.pg0, tx_e, itf) - self.verify_tunneled_4o4(self.pg0, rx, tx_e, - itf.local_ip4, - itf._remote_hosts[ii].ip4) - rx = self.send_and_expect(self.pg0, tx_i, self.pg0) - self.verify_decapped_4o4(self.pg0, rx, tx_i) - - gre_if.admin_down() - gre_if.unconfig_ip4() - - def test_mgre6(self): - """ mGRE IPv6 tunnel Tests """ - - self.pg0.config_ip6() - self.pg0.resolve_ndp() - - e = VppEnum.vl_api_tunnel_encap_decap_flags_t - - for itf in self.pg_interfaces[3:]: - # - # one underlay nh for each overlay/tunnel peer - # - itf.config_ip6() - itf.generate_remote_hosts(4) - itf.configure_ipv6_neighbors() - - # - # Create an L3 GRE tunnel. - # - set it admin up - # - assign an IP Addres - # - Add a route via the tunnel - # - gre_if = VppGreInterface( - self, - itf.local_ip6, - "::", - mode=(VppEnum.vl_api_tunnel_mode_t. - TUNNEL_API_MODE_MP), - flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP) - - gre_if.add_vpp_config() - gre_if.admin_up() - gre_if.config_ip6() - gre_if.generate_remote_hosts(4) - - # - # for-each peer - # - for ii in range(1, 4): - route_addr = "4::%d" % ii - - # - # Add a TEIB entry resolves the peer - # - teib = VppTeib(self, gre_if, - gre_if._remote_hosts[ii].ip6, - itf._remote_hosts[ii].ip6) - teib.add_vpp_config() - - # - # route traffic via the peer - # - route_via_tun = VppIpRoute( - self, route_addr, 128, - [VppRoutePath(gre_if._remote_hosts[ii].ip6, - gre_if.sw_if_index)]) - route_via_tun.add_vpp_config() - - # - # Send a packet stream that is routed into the tunnel - # - packets are GRE encapped - # - tx_e = self.create_stream_ip6(self.pg0, "5::5", route_addr, - dscp=2, ecn=1) - rx = self.send_and_expect(self.pg0, tx_e, itf) - self.verify_tunneled_6o6(self.pg0, rx, tx_e, - itf.local_ip6, - itf._remote_hosts[ii].ip6, - dscp=2) - tx_i = self.create_tunnel_stream_6o6(self.pg0, - itf._remote_hosts[ii].ip6, - itf.local_ip6, - self.pg0.local_ip6, - self.pg0.remote_ip6) - rx = self.send_and_expect(self.pg0, tx_i, self.pg0) - self.verify_decapped_6o6(self.pg0, rx, tx_i) - - # - # delete and re-add the TEIB - # - teib.remove_vpp_config() - self.send_and_assert_no_replies(self.pg0, tx_e) - - teib.add_vpp_config() - rx = self.send_and_expect(self.pg0, tx_e, itf) - self.verify_tunneled_6o6(self.pg0, rx, tx_e, - itf.local_ip6, - itf._remote_hosts[ii].ip6, - dscp=2) - rx = self.send_and_expect(self.pg0, tx_i, self.pg0) - self.verify_decapped_6o6(self.pg0, rx, tx_i) - - gre_if.admin_down() - gre_if.unconfig_ip4() - itf.unconfig_ip6() - self.pg0.unconfig_ip6() - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/gso/test/test_gro.py b/src/vnet/gso/test/test_gro.py deleted file mode 100644 index 33215d65fa7..00000000000 --- a/src/vnet/gso/test/test_gro.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 -"""GRO functional tests""" - -# -# Add tests for: -# - GRO -# - Verify that sending 1500 Bytes frame without GRO enabled correctly -# - Verify that sending 1500 Bytes frame with GRO enabled correctly -# -import unittest - -from scapy.packet import Raw -from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig -from scapy.layers.inet6 import ipv6nh, IPerror6 -from scapy.layers.inet import TCP, ICMP -from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP - -from framework import VppTestCase, VppTestRunner -from vpp_object import VppObject -from vpp_interface import VppInterface - - -""" Test_gro is a subclass of VPPTestCase classes. - GRO tests. -""" - - -class TestGRO(VppTestCase): - """ GRO Test Case """ - - @classmethod - def setUpClass(self): - super(TestGRO, self).setUpClass() - res = self.create_pg_interfaces(range(2)) - res_gro = self.create_pg_interfaces(range(2, 3), 1, 1460) - self.create_pg_interfaces(range(3, 4), 1, 8940) - self.pg_interfaces.append(res[0]) - self.pg_interfaces.append(res[1]) - self.pg_interfaces.append(res_gro[0]) - self.pg2.coalesce_enable() - self.pg3.coalesce_enable() - - @classmethod - def tearDownClass(self): - super(TestGRO, self).tearDownClass() - - def setUp(self): - super(TestGRO, self).setUp() - for i in self.pg_interfaces: - i.admin_up() - i.config_ip4() - i.config_ip6() - i.disable_ipv6_ra() - i.resolve_arp() - i.resolve_ndp() - - def tearDown(self): - super(TestGRO, self).tearDown() - if not self.vpp_dead: - for i in self.pg_interfaces: - i.unconfig_ip4() - i.unconfig_ip6() - i.admin_down() - - def test_gro(self): - """ GRO test """ - - n_packets = 124 - # - # Send 1500 bytes frame with gro disabled - # - p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=4321) / - Raw(b'\xa5' * 1460)) - - rxs = self.send_and_expect(self.pg0, n_packets * p4, self.pg1) - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg1.local_mac) - self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 4321) - - # - # Send 1500 bytes frame with gro enabled on - # output interfaces support GRO - # - p = [] - s = 0 - for n in range(0, n_packets): - p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg2.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=4321, seq=s, ack=n, flags='A') / - Raw(b'\xa5' * 1460))) - s += 1460 - - rxs = self.send_and_expect(self.pg0, p, self.pg2, n_rx=2) - - i = 0 - for rx in rxs: - i += 1 - self.assertEqual(rx[Ether].src, self.pg2.local_mac) - self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg2.remote_ip4) - self.assertEqual(rx[IP].len, 64280) # 1460 * 44 + 40 < 65536 - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 4321) - self.assertEqual(rx[TCP].ack, (44*i - 1)) - - p4_temp = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=4321, flags='F')) - - rxs = self.send_and_expect(self.pg2, 100*[p4_temp], self.pg0, n_rx=100) - rx_coalesce = self.pg2.get_capture(1, timeout=1) - - rx0 = rx_coalesce[0] - self.assertEqual(rx0[Ether].src, self.pg2.local_mac) - self.assertEqual(rx0[Ether].dst, self.pg2.remote_mac) - self.assertEqual(rx0[IP].src, self.pg0.remote_ip4) - self.assertEqual(rx0[IP].dst, self.pg2.remote_ip4) - self.assertEqual(rx0[IP].len, 52600) # 1460 * 36 + 40 - self.assertEqual(rx0[TCP].sport, 1234) - self.assertEqual(rx0[TCP].dport, 4321) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg2.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assertEqual(rx[IP].len, 40) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 4321) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/gso/test/test_gso.py b/src/vnet/gso/test/test_gso.py deleted file mode 100644 index 094600eb74c..00000000000 --- a/src/vnet/gso/test/test_gso.py +++ /dev/null @@ -1,722 +0,0 @@ -#!/usr/bin/env python3 -"""GSO functional tests""" - -# -# Add tests for: -# - GSO -# - Verify that sending Jumbo frame without GSO enabled correctly -# - Verify that sending Jumbo frame with GSO enabled correctly -# - Verify that sending Jumbo frame with GSO enabled only on ingress interface -# -import unittest - -from scapy.packet import Raw -from scapy.layers.inet6 import IPv6, Ether, IP, UDP, ICMPv6PacketTooBig -from scapy.layers.inet6 import ipv6nh, IPerror6 -from scapy.layers.inet import TCP, ICMP -from scapy.layers.vxlan import VXLAN -from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP - -from framework import VppTestCase, VppTestRunner -from vpp_object import VppObject -from vpp_interface import VppInterface -from vpp_ip import DpoProto -from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto -from vpp_ipip_tun_interface import VppIpIpTunInterface -from vpp_vxlan_tunnel import VppVxlanTunnel -from socket import AF_INET, AF_INET6, inet_pton -from util import reassemble4 - - -""" Test_gso is a subclass of VPPTestCase classes. - GSO tests. -""" - - -class TestGSO(VppTestCase): - """ GSO Test Case """ - - def __init__(self, *args): - VppTestCase.__init__(self, *args) - - @classmethod - def setUpClass(self): - super(TestGSO, self).setUpClass() - res = self.create_pg_interfaces(range(2)) - res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460) - self.create_pg_interfaces(range(4, 5), 1, 8940) - self.pg_interfaces.append(res[0]) - self.pg_interfaces.append(res[1]) - self.pg_interfaces.append(res_gso[0]) - self.pg_interfaces.append(res_gso[1]) - - @classmethod - def tearDownClass(self): - super(TestGSO, self).tearDownClass() - - def setUp(self): - super(TestGSO, self).setUp() - for i in self.pg_interfaces: - i.admin_up() - i.config_ip4() - i.config_ip6() - i.disable_ipv6_ra() - i.resolve_arp() - i.resolve_ndp() - - self.single_tunnel_bd = 10 - self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4, - dst=self.pg0.remote_ip4, - vni=self.single_tunnel_bd) - - self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6, - dst=self.pg0.remote_ip6, - vni=self.single_tunnel_bd) - - self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4, - self.pg0.remote_ip4) - self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6, - self.pg0.remote_ip6) - - def tearDown(self): - super(TestGSO, self).tearDown() - if not self.vpp_dead: - for i in self.pg_interfaces: - i.unconfig_ip4() - i.unconfig_ip6() - i.admin_down() - - def test_gso(self): - """ GSO test """ - # - # Send jumbo frame with gso disabled and DF bit is set - # - p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg0, [p4], self.pg0) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assertEqual(rx[ICMP].type, 3) # "dest-unreach" - self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed" - - # - # Send checksum offload frames - # - p40 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 1460)) - - rxs = self.send_and_expect(self.pg2, 100*[p40], self.pg0) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg2.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - payload_len = rx[IP].len - 20 - 20 - self.assert_ip_checksum_valid(rx) - self.assert_tcp_checksum_valid(rx) - self.assertEqual(payload_len, len(rx[Raw])) - - p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 1440)) - - rxs = self.send_and_expect(self.pg2, 100*[p60], self.pg0) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - payload_len = rx[IPv6].plen - 20 - self.assert_tcp_checksum_valid(rx) - self.assertEqual(payload_len, len(rx[Raw])) - - # - # Send jumbo frame with gso enabled and DF bit is set - # input and output interfaces support GSO - # - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg3.sw_if_index, - enable_disable=1) - p41 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 100*[p41], self.pg3, 100) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg3.local_mac) - self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) - self.assertEqual(rx[IP].src, self.pg2.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg3.remote_ip4) - self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 1234) - - # - # ipv6 - # - p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 100*[p61], self.pg3, 100) - - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg3.local_mac) - self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6) - self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 1234) - - # - # Send jumbo frame with gso enabled only on input interface - # and DF bit is set. GSO packet will be chunked into gso_size - # data payload - # - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=1) - p42 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, - flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p42], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg2.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) - self.assert_ip_checksum_valid(rx) - self.assert_tcp_checksum_valid(rx) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 1234) - self.assertEqual(payload_len, len(rx[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # ipv6 - # - p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p62], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - payload_len = rx[IPv6].plen - 20 - self.assert_tcp_checksum_valid(rx) - self.assertEqual(rx[TCP].sport, 1234) - self.assertEqual(rx[TCP].dport, 1234) - self.assertEqual(payload_len, len(rx[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # Send jumbo frame with gso enabled only on input interface - # and DF bit is unset. GSO packet will be fragmented. - # - self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index, - enable_disable=1) - - p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p43], self.pg1, 5*119) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg1.local_mac) - self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) - self.assertEqual(rx[IP].src, self.pg2.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) - self.assert_ip_checksum_valid(rx) - size += rx[IP].len - 20 - size -= 20*5 # TCP header - self.assertEqual(size, 65200*5) - - # - # IPv6 - # Send jumbo frame with gso enabled only on input interface. - # ICMPv6 Packet Too Big will be sent back to sender. - # - self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) - p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / - IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p63], self.pg2, 5) - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg2.local_mac) - self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg2.local_ip6) - self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) - self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header - self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6") - self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280) - self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6) - self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6) - self.assertEqual(rx[IPerror6].plen - 20, 65200) - - # - # Send jumbo frame with gso enabled only on input interface with 9K MTU - # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO - # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size - # - self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) - self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0]) - p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / - IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg4, 5*[p44], self.pg1, 165) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg1.local_mac) - self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) - self.assertEqual(rx[IP].src, self.pg4.remote_ip4) - self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) - payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) - self.assert_ip_checksum_valid(rx) - self.assert_tcp_checksum_valid(rx) - self.assertEqual(payload_len, len(rx[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # IPv6 - # - p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / - IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg4, 5*[p64], self.pg1, 170) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg1.local_mac) - self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6) - self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) - payload_len = rx[IPv6].plen - 20 - self.assert_tcp_checksum_valid(rx) - self.assertEqual(payload_len, len(rx[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=0) - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg1.sw_if_index, - enable_disable=0) - - def test_gso_vxlan(self): - """ GSO VXLAN test """ - self.logger.info(self.vapi.cli("sh int addr")) - # - # Send jumbo frame with gso enabled only on input interface and - # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2 - # into BD. - # - - # - # enable ipv4/vxlan - # - self.vxlan.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd) - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=1) - - # - # IPv4/IPv4 - VXLAN - # - p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p45], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assert_ip_checksum_valid(rx) - self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) - self.assertEqual(rx[VXLAN].vni, 10) - inner = rx[VXLAN].payload - self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) - self.assertEqual(inner[Ether].src, self.pg2.remote_mac) - self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") - self.assertEqual(inner[IP].src, self.pg2.remote_ip4) - self.assertEqual(inner[IP].dst, "172.16.3.3") - self.assert_ip_checksum_valid(inner) - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IP].len - 20 - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # IPv4/IPv6 - VXLAN - # - p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p65], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assert_ip_checksum_valid(rx) - self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) - self.assertEqual(rx[VXLAN].vni, 10) - inner = rx[VXLAN].payload - self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) - self.assertEqual(inner[Ether].src, self.pg2.remote_mac) - self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") - self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(inner[IPv6].dst, "fd01:3::3") - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IPv6].plen - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # disable ipv4/vxlan - # - self.vxlan.remove_vpp_config() - - # - # enable ipv6/vxlan - # - self.vxlan2.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.vxlan2.sw_if_index, - bd_id=self.single_tunnel_bd) - - # - # IPv6/IPv4 - VXLAN - # - p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p46], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) - self.assertEqual(rx[VXLAN].vni, 10) - inner = rx[VXLAN].payload - self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) - self.assertEqual(inner[Ether].src, self.pg2.remote_mac) - self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") - self.assertEqual(inner[IP].src, self.pg2.remote_ip4) - self.assertEqual(inner[IP].dst, "172.16.3.3") - self.assert_ip_checksum_valid(inner) - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IP].len - 20 - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # IPv6/IPv6 - VXLAN - # - p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p66], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - self.assert_udp_checksum_valid(rx, ignore_zero_checksum=False) - self.assertEqual(rx[VXLAN].vni, 10) - inner = rx[VXLAN].payload - self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) - self.assertEqual(inner[Ether].src, self.pg2.remote_mac) - self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") - self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(inner[IPv6].dst, "fd01:3::3") - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IPv6].plen - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # disable ipv4/vxlan - # - self.vxlan2.remove_vpp_config() - - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=0) - - def test_gso_ipip(self): - """ GSO IPIP test """ - self.logger.info(self.vapi.cli("sh int addr")) - # - # Send jumbo frame with gso enabled only on input interface and - # create IPIP tunnel on VPP pg0. - # - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=1) - - # - # enable ipip4 - # - self.ipip4.add_vpp_config() - - # Set interface up and enable IP on it - self.ipip4.admin_up() - self.ipip4.set_unnumbered(self.pg0.sw_if_index) - - # Add IPv4 routes via tunnel interface - self.ip4_via_ip4_tunnel = VppIpRoute( - self, "172.16.10.0", 24, - [VppRoutePath("0.0.0.0", - self.ipip4.sw_if_index, - proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)]) - self.ip4_via_ip4_tunnel.add_vpp_config() - - # - # IPv4/IPv4 - IPIP - # - p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assert_ip_checksum_valid(rx) - self.assertEqual(rx[IP].proto, 4) # ipencap - inner = rx[IP].payload - self.assertEqual(rx[IP].len - 20, len(inner)) - self.assertEqual(inner[IP].src, self.pg2.remote_ip4) - self.assertEqual(inner[IP].dst, "172.16.10.3") - self.assert_ip_checksum_valid(inner) - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IP].len - 20 - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - self.ip6_via_ip4_tunnel = VppIpRoute( - self, "fd01:10::", 64, - [VppRoutePath("::", - self.ipip4.sw_if_index, - proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)]) - self.ip6_via_ip4_tunnel.add_vpp_config() - # - # IPv4/IPv6 - IPIP - # - p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p67], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assert_ip_checksum_valid(rx) - self.assertEqual(rx[IP].proto, 41) # ipv6 - inner = rx[IP].payload - self.assertEqual(rx[IP].len - 20, len(inner)) - self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(inner[IPv6].dst, "fd01:10::3") - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IPv6].plen - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # Send jumbo frame with gso enabled only on input interface and - # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip - # tunnel - IPSec use case - # - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=0) - self.vapi.feature_gso_enable_disable( - sw_if_index=self.ipip4.sw_if_index, - enable_disable=1) - - rxs = self.send_and_expect(self.pg2, 5*[p47], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IP].src, self.pg0.local_ip4) - self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) - self.assert_ip_checksum_valid(rx) - self.assertEqual(rx[IP].proto, 4) # ipencap - inner = rx[IP].payload - self.assertEqual(rx[IP].len - 20, len(inner)) - self.assertEqual(inner[IP].src, self.pg2.remote_ip4) - self.assertEqual(inner[IP].dst, "172.16.10.3") - self.assert_ip_checksum_valid(inner) - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IP].len - 20 - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # disable ipip4 - # - self.vapi.feature_gso_enable_disable( - sw_if_index=self.ipip4.sw_if_index, - enable_disable=0) - self.ip4_via_ip4_tunnel.remove_vpp_config() - self.ip6_via_ip4_tunnel.remove_vpp_config() - self.ipip4.remove_vpp_config() - - # - # enable ipip6 - # - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=1) - self.ipip6.add_vpp_config() - - # Set interface up and enable IP on it - self.ipip6.admin_up() - self.ipip6.set_unnumbered(self.pg0.sw_if_index) - - # Add IPv4 routes via tunnel interface - self.ip4_via_ip6_tunnel = VppIpRoute( - self, "172.16.10.0", 24, - [VppRoutePath("0.0.0.0", - self.ipip6.sw_if_index, - proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)]) - self.ip4_via_ip6_tunnel.add_vpp_config() - - # - # IPv6/IPv4 - IPIP - # - p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p48], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - self.assertEqual(ipv6nh[rx[IPv6].nh], "IP") - inner = rx[IPv6].payload - self.assertEqual(rx[IPv6].plen, len(inner)) - self.assertEqual(inner[IP].src, self.pg2.remote_ip4) - self.assertEqual(inner[IP].dst, "172.16.10.3") - self.assert_ip_checksum_valid(inner) - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IP].len - 20 - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - self.ip6_via_ip6_tunnel = VppIpRoute( - self, "fd01:10::", 64, - [VppRoutePath("::", - self.ipip6.sw_if_index, - proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)]) - self.ip6_via_ip6_tunnel.add_vpp_config() - - # - # IPv6/IPv6 - IPIP - # - p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / - IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / - TCP(sport=1234, dport=1234) / - Raw(b'\xa5' * 65200)) - - rxs = self.send_and_expect(self.pg2, 5*[p68], self.pg0, 225) - size = 0 - for rx in rxs: - self.assertEqual(rx[Ether].src, self.pg0.local_mac) - self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) - self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) - self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) - self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6") - inner = rx[IPv6].payload - self.assertEqual(rx[IPv6].plen, len(inner)) - self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) - self.assertEqual(inner[IPv6].dst, "fd01:10::3") - self.assert_tcp_checksum_valid(inner) - payload_len = inner[IPv6].plen - 20 - self.assertEqual(payload_len, len(inner[Raw])) - size += payload_len - self.assertEqual(size, 65200*5) - - # - # disable ipip6 - # - self.ip4_via_ip6_tunnel.remove_vpp_config() - self.ip6_via_ip6_tunnel.remove_vpp_config() - self.ipip6.remove_vpp_config() - - self.vapi.feature_gso_enable_disable(sw_if_index=self.pg0.sw_if_index, - enable_disable=0) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/policer/test/test_policer.py b/src/vnet/policer/test/test_policer.py deleted file mode 100644 index 6b15a0234a3..00000000000 --- a/src/vnet/policer/test/test_policer.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2021 Graphiant, Inc. - -import unittest - -from framework import VppTestCase, VppTestRunner -from vpp_policer import VppPolicer, PolicerAction - -# Default for the tests is 10s of "Green" packets at 8Mbps, ie. 10M bytes. -# The policer helper CLI "sends" 500 byte packets, so default is 20000. - -TEST_RATE = 8000 # kbps -TEST_BURST = 10000 # ms - -CIR_OK = 8500 # CIR in kbps, above test rate -CIR_LOW = 7000 # CIR in kbps, below test rate -EIR_OK = 9000 # EIR in kbps, above test rate -EIR_LOW = 7500 # EIR in kbps, below test rate - -NUM_PKTS = 20000 - -CBURST = 100000 # Committed burst in bytes -EBURST = 200000 # Excess burst in bytes - - -class TestPolicer(VppTestCase): - """ Policer Test Case """ - - def run_policer_test(self, type, cir, cb, eir, eb, rate=8000, burst=10000, - colour=0): - """ - Configure a Policer and push traffic through it. - """ - types = { - '1R2C': 0, - '1R3C': 1, - '2R3C': 3, - } - - pol_type = types.get(type) - policer = VppPolicer(self, "pol1", cir, eir, cb, eb, rate_type=0, - type=pol_type, color_aware=colour) - policer.add_vpp_config() - - error = self.vapi.cli( - f"test policing index {policer.policer_index} rate {rate} " - f"burst {burst} colour {colour}") - - stats = policer.get_stats() - policer.remove_vpp_config() - - return stats - - def test_policer_1r2c(self): - """ Single rate, 2 colour policer """ - stats = self.run_policer_test("1R2C", CIR_OK, CBURST, 0, 0) - self.assertEqual(stats['conform_packets'], NUM_PKTS) - - stats = self.run_policer_test("1R2C", CIR_LOW, CBURST, 0, 0) - self.assertLess(stats['conform_packets'], NUM_PKTS) - self.assertEqual(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - stats = self.run_policer_test("1R2C", CIR_LOW, CBURST, 0, 0, colour=2) - self.assertEqual(stats['violate_packets'], NUM_PKTS) - - def test_policer_1r3c(self): - """ Single rate, 3 colour policer """ - stats = self.run_policer_test("1R3C", CIR_OK, CBURST, 0, 0) - self.assertEqual(stats['conform_packets'], NUM_PKTS) - - stats = self.run_policer_test("1R3C", CIR_LOW, CBURST, 0, EBURST) - self.assertLess(stats['conform_packets'], NUM_PKTS) - self.assertGreater(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - stats = self.run_policer_test("1R3C", CIR_LOW, CBURST, 0, EBURST, - colour=1) - self.assertEqual(stats['conform_packets'], 0) - self.assertGreater(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - stats = self.run_policer_test("1R3C", CIR_LOW, CBURST, 0, EBURST, - colour=2) - self.assertEqual(stats['violate_packets'], NUM_PKTS) - - def test_policer_2r3c(self): - """ Dual rate, 3 colour policer """ - stats = self.run_policer_test("2R3C", CIR_OK, CBURST, EIR_OK, EBURST) - self.assertEqual(stats['conform_packets'], NUM_PKTS) - - stats = self.run_policer_test("2R3C", CIR_LOW, CBURST, EIR_OK, EBURST) - self.assertLess(stats['conform_packets'], NUM_PKTS) - self.assertGreater(stats['exceed_packets'], 0) - self.assertEqual(stats['violate_packets'], 0) - - stats = self.run_policer_test("2R3C", CIR_LOW, CBURST, EIR_LOW, EBURST) - self.assertLess(stats['conform_packets'], NUM_PKTS) - self.assertGreater(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - stats = self.run_policer_test("2R3C", CIR_LOW, CBURST, EIR_OK, EBURST, - colour=1) - self.assertEqual(stats['exceed_packets'], NUM_PKTS) - - stats = self.run_policer_test("2R3C", CIR_LOW, CBURST, EIR_LOW, EBURST, - colour=1) - self.assertEqual(stats['conform_packets'], 0) - self.assertGreater(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - stats = self.run_policer_test("2R3C", CIR_LOW, CBURST, EIR_OK, EBURST, - colour=2) - self.assertEqual(stats['violate_packets'], NUM_PKTS) - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/policer/test/test_policer_input.py b/src/vnet/policer/test/test_policer_input.py deleted file mode 100644 index c95f6643ff2..00000000000 --- a/src/vnet/policer/test/test_policer_input.py +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2021 Graphiant, Inc. - -import unittest -import scapy.compat -from scapy.layers.inet import IP, UDP -from scapy.layers.l2 import Ether -from scapy.packet import Raw -from framework import VppTestCase, VppTestRunner -from vpp_papi import VppEnum -from vpp_policer import VppPolicer, PolicerAction - -NUM_PKTS = 67 - - -class TestPolicerInput(VppTestCase): - """ Policer on an input interface """ - vpp_worker_count = 2 - - def setUp(self): - super(TestPolicerInput, self).setUp() - - self.create_pg_interfaces(range(2)) - for i in self.pg_interfaces: - i.admin_up() - i.config_ip4() - i.resolve_arp() - - self.pkt = (Ether(src=self.pg0.remote_mac, - dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) / - UDP(sport=1234, dport=1234) / - Raw(b'\xa5' * 100)) - - def tearDown(self): - for i in self.pg_interfaces: - i.unconfig_ip4() - i.admin_down() - super(TestPolicerInput, self).tearDown() - - def test_policer_input(self): - """ Input Policing """ - pkts = self.pkt * NUM_PKTS - - action_tx = PolicerAction( - VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, - 0) - policer = VppPolicer(self, "pol1", 80, 0, 1000, 0, - conform_action=action_tx, - exceed_action=action_tx, - violate_action=action_tx) - policer.add_vpp_config() - - # Start policing on pg0 - policer.apply_vpp_config(self.pg0.sw_if_index, True) - - rx = self.send_and_expect(self.pg0, pkts, self.pg1, worker=0) - stats = policer.get_stats() - - # Single rate, 2 colour policer - expect conform, violate but no exceed - self.assertGreater(stats['conform_packets'], 0) - self.assertEqual(stats['exceed_packets'], 0) - self.assertGreater(stats['violate_packets'], 0) - - # Stop policing on pg0 - policer.apply_vpp_config(self.pg0.sw_if_index, False) - - rx = self.send_and_expect(self.pg0, pkts, self.pg1, worker=0) - - statsnew = policer.get_stats() - - # No new packets counted - self.assertEqual(stats, statsnew) - - policer.remove_vpp_config() - - def test_policer_handoff(self): - """ Worker thread handoff """ - pkts = self.pkt * NUM_PKTS - - action_tx = PolicerAction( - VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, - 0) - policer = VppPolicer(self, "pol2", 80, 0, 1000, 0, - conform_action=action_tx, - exceed_action=action_tx, - violate_action=action_tx) - policer.add_vpp_config() - - # Bind the policer to worker 1 - policer.bind_vpp_config(1, True) - - # Start policing on pg0 - policer.apply_vpp_config(self.pg0.sw_if_index, True) - - for worker in [0, 1]: - self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker) - self.logger.debug(self.vapi.cli("show trace max 100")) - - stats = policer.get_stats() - stats0 = policer.get_stats(worker=0) - stats1 = policer.get_stats(worker=1) - - # Worker 1, should have done all the policing - self.assertEqual(stats, stats1) - - # Worker 0, should have handed everything off - self.assertEqual(stats0['conform_packets'], 0) - self.assertEqual(stats0['exceed_packets'], 0) - self.assertEqual(stats0['violate_packets'], 0) - - # Unbind the policer from worker 1 and repeat - policer.bind_vpp_config(1, False) - for worker in [0, 1]: - self.send_and_expect(self.pg0, pkts, self.pg1, worker=worker) - self.logger.debug(self.vapi.cli("show trace max 100")) - - # The policer should auto-bind to worker 0 when packets arrive - stats = policer.get_stats() - - # The 2 workers should now have policed the same amount - stats = policer.get_stats() - stats0 = policer.get_stats(worker=0) - stats1 = policer.get_stats(worker=1) - - self.assertGreater(stats0['conform_packets'], 0) - self.assertEqual(stats0['exceed_packets'], 0) - self.assertGreater(stats0['violate_packets'], 0) - - self.assertGreater(stats1['conform_packets'], 0) - self.assertEqual(stats1['exceed_packets'], 0) - self.assertGreater(stats1['violate_packets'], 0) - - self.assertEqual(stats0['conform_packets'] + stats1['conform_packets'], - stats['conform_packets']) - - self.assertEqual(stats0['violate_packets'] + stats1['violate_packets'], - stats['violate_packets']) - - # Stop policing on pg0 - policer.apply_vpp_config(self.pg0.sw_if_index, False) - - policer.remove_vpp_config() - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/vxlan/test/test_vxlan.py b/src/vnet/vxlan/test/test_vxlan.py deleted file mode 100644 index 028275ccedf..00000000000 --- a/src/vnet/vxlan/test/test_vxlan.py +++ /dev/null @@ -1,421 +0,0 @@ -#!/usr/bin/env python3 - -import socket -from util import ip4_range, reassemble4 -import unittest -from framework import VppTestCase, VppTestRunner -from template_bd import BridgeDomain - -from scapy.layers.l2 import Ether -from scapy.packet import Raw, bind_layers -from scapy.layers.inet import IP, UDP -from scapy.layers.vxlan import VXLAN - -import util -from vpp_ip_route import VppIpRoute, VppRoutePath -from vpp_vxlan_tunnel import VppVxlanTunnel -from vpp_ip import INVALID_INDEX - - -class TestVxlan(BridgeDomain, VppTestCase): - """ VXLAN Test Case """ - - def __init__(self, *args): - BridgeDomain.__init__(self) - VppTestCase.__init__(self, *args) - - def encapsulate(self, pkt, vni): - """ - Encapsulate the original payload frame by adding VXLAN header with its - UDP, IP and Ethernet fields - """ - return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - def ip_range(self, start, end): - """ range of remote ip's """ - return ip4_range(self.pg0.remote_ip4, start, end) - - def encap_mcast(self, pkt, src_ip, src_mac, vni): - """ - Encapsulate the original payload frame by adding VXLAN header with its - UDP, IP and Ethernet fields - """ - return (Ether(src=src_mac, dst=self.mcast_mac) / - IP(src=src_ip, dst=self.mcast_ip4) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - def decapsulate(self, pkt): - """ - Decapsulate the original payload frame by removing VXLAN header - """ - # check if is set I flag - self.assertEqual(pkt[VXLAN].flags, int('0x8', 16)) - return pkt[VXLAN].payload - - # Method for checking VXLAN encapsulation. - # - def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False): - # TODO: add error messages - # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved - # by VPP using ARP. - self.assertEqual(pkt[Ether].src, self.pg0.local_mac) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac) - else: - self.assertEqual(pkt[Ether].dst, type(self).mcast_mac) - # Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP. - self.assertEqual(pkt[IP].src, self.pg0.local_ip4) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4) - else: - self.assertEqual(pkt[IP].dst, type(self).mcast_ip4) - # Verify UDP destination port is VXLAN 4789, source UDP port could be - # arbitrary. - self.assertEqual(pkt[UDP].dport, self.dport) - # Verify UDP checksum - self.assert_udp_checksum_valid(pkt) - # Verify VNI - self.assertEqual(pkt[VXLAN].vni, vni) - - @classmethod - def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port): - # Create 10 ucast vxlan tunnels under bd - ip_range_start = 10 - ip_range_end = ip_range_start + n_ucast_tunnels - next_hop_address = cls.pg0.remote_ip4 - for dest_ip4 in ip4_range(next_hop_address, ip_range_start, - ip_range_end): - # add host route so dest_ip4 will not be resolved - rip = VppIpRoute(cls, dest_ip4, 32, - [VppRoutePath(next_hop_address, - INVALID_INDEX)], - register=False) - rip.add_vpp_config() - - r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4, - src_port=port, dst_port=port, - dst=dest_ip4, vni=vni) - r.add_vpp_config() - cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni) - - @classmethod - def add_del_shared_mcast_dst_load(cls, port, is_add): - """ - add or del tunnels sharing the same mcast dst - to test vxlan ref_count mechanism - """ - n_shared_dst_tunnels = 20 - vni_start = 10000 - vni_end = vni_start + n_shared_dst_tunnels - for vni in range(vni_start, vni_end): - r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4, - src_port=port, dst_port=port, - dst=cls.mcast_ip4, mcast_sw_if_index=1, vni=vni) - if is_add: - r.add_vpp_config() - if r.sw_if_index == 0xffffffff: - raise ValueError("bad sw_if_index: ~0") - else: - r.remove_vpp_config() - - @classmethod - def add_shared_mcast_dst_load(cls, port): - cls.add_del_shared_mcast_dst_load(port=port, is_add=1) - - @classmethod - def del_shared_mcast_dst_load(cls, port): - cls.add_del_shared_mcast_dst_load(port=port, is_add=0) - - @classmethod - def add_del_mcast_tunnels_load(cls, port, is_add): - """ - add or del tunnels to test vxlan stability - """ - n_distinct_dst_tunnels = 200 - ip_range_start = 10 - ip_range_end = ip_range_start + n_distinct_dst_tunnels - for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start, - ip_range_end): - vni = bytearray(socket.inet_pton(socket.AF_INET, dest_ip4))[3] - r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4, - src_port=port, dst_port=port, - dst=dest_ip4, mcast_sw_if_index=1, vni=vni) - if is_add: - r.add_vpp_config() - else: - r.remove_vpp_config() - - @classmethod - def add_mcast_tunnels_load(cls, port): - cls.add_del_mcast_tunnels_load(port=port, is_add=1) - - @classmethod - def del_mcast_tunnels_load(cls, port): - cls.add_del_mcast_tunnels_load(port=port, is_add=0) - - # Class method to start the VXLAN test case. - # Overrides setUpClass method in VppTestCase class. - # Python try..except statement is used to ensure that the tear down of - # the class will be executed even if exception is raised. - # @param cls The class pointer. - @classmethod - def setUpClass(cls): - super(TestVxlan, cls).setUpClass() - - try: - cls.flags = 0x8 - - # Create 2 pg interfaces. - cls.create_pg_interfaces(range(4)) - for pg in cls.pg_interfaces: - pg.admin_up() - - # Configure IPv4 addresses on VPP pg0. - cls.pg0.config_ip4() - - # Resolve MAC address for VPP's IP address on pg0. - cls.pg0.resolve_arp() - - # Our Multicast address - cls.mcast_ip4 = '239.1.1.1' - cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip4) - except Exception: - cls.tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestVxlan, cls).tearDownClass() - - def setUp(self): - super(TestVxlan, self).setUp() - - def createVxLANInterfaces(self, port=4789): - # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1 - # into BD. - self.dport = port - - self.single_tunnel_vni = 0x12345 - self.single_tunnel_bd = 1 - r = VppVxlanTunnel(self, src=self.pg0.local_ip4, - dst=self.pg0.remote_ip4, - src_port=self.dport, dst_port=self.dport, - vni=self.single_tunnel_vni) - r.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=self.single_tunnel_bd) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd) - - # Setup vni 2 to test multicast flooding - self.n_ucast_tunnels = 10 - self.mcast_flood_bd = 2 - self.create_vxlan_flood_test_bd(self.mcast_flood_bd, - self.n_ucast_tunnels, - self.dport) - r = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.mcast_ip4, - src_port=self.dport, dst_port=self.dport, - mcast_sw_if_index=1, vni=self.mcast_flood_bd) - r.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=self.mcast_flood_bd) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd) - - # Add and delete mcast tunnels to check stability - self.add_shared_mcast_dst_load(self.dport) - self.add_mcast_tunnels_load(self.dport) - self.del_shared_mcast_dst_load(self.dport) - self.del_mcast_tunnels_load(self.dport) - - # Setup vni 3 to test unicast flooding - self.ucast_flood_bd = 3 - self.create_vxlan_flood_test_bd(self.ucast_flood_bd, - self.n_ucast_tunnels, - self.dport) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd) - - # Set scapy listen custom port for VxLAN - bind_layers(UDP, VXLAN, dport=self.dport) - - def encap_big_packet(self): - self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) - - frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / - IP(src='4.3.2.1', dst='1.2.3.4') / - UDP(sport=20000, dport=10000) / - Raw(b'\xa5' * 1450)) - - self.pg1.add_stream([frame]) - - self.pg0.enable_capture() - - self.pg_start() - - # Pick first received frame and check if it's correctly encapsulated. - out = self.pg0.get_capture(2) - ether = out[0] - pkt = reassemble4(out) - pkt = ether / pkt - self.check_encapsulation(pkt, self.single_tunnel_vni) - - payload = self.decapsulate(pkt) - # TODO: Scapy bug? - # self.assert_eq_pkts(payload, frame) - - """ - Tests with default port (4789) - """ - def test_decap(self): - """ Decapsulation test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan, self).test_decap() - - def test_encap(self): - """ Encapsulation test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan, self).test_encap() - - def test_encap_big_packet(self): - """ Encapsulation test send big frame from pg1 - Verify receipt of encapsulated frames on pg0 - """ - self.createVxLANInterfaces() - self.encap_big_packet() - - def test_ucast_flood(self): - """ Unicast flood test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan, self).test_ucast_flood() - - def test_mcast_flood(self): - """ Multicast flood test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan, self).test_mcast_flood() - - def test_mcast_rcv(self): - """ Multicast receive test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan, self).test_mcast_rcv() - - """ - Tests with custom port - """ - def test_decap_custom_port(self): - """ Decapsulation test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan, self).test_decap() - - def test_encap_custom_port(self): - """ Encapsulation test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan, self).test_encap() - - def test_ucast_flood_custom_port(self): - """ Unicast flood test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan, self).test_ucast_flood() - - def test_mcast_flood_custom_port(self): - """ Multicast flood test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan, self).test_mcast_flood() - - def test_mcast_rcv_custom_port(self): - """ Multicast receive test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan, self).test_mcast_rcv() - - # Method to define VPP actions before tear down of the test case. - # Overrides tearDown method in VppTestCase class. - # @param self The object pointer. - - def tearDown(self): - super(TestVxlan, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show bridge-domain 1 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 2 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 3 detail")) - self.logger.info(self.vapi.cli("show vxlan tunnel")) - - -class TestVxlan2(VppTestCase): - """ VXLAN Test Case """ - def setUp(self): - super(TestVxlan2, self).setUp() - - # Create 2 pg interfaces. - self.create_pg_interfaces(range(4)) - for pg in self.pg_interfaces: - pg.admin_up() - - # Configure IPv4 addresses on VPP pg0. - self.pg0.config_ip4() - self.pg0.resolve_arp() - - def tearDown(self): - super(TestVxlan2, self).tearDown() - - def test_xconnect(self): - """ VXLAN source address not local """ - - # - # test the broken configuration of a VXLAN tunnel whose - # source address is not local ot the box. packets sent - # through the tunnel should be dropped - # - t = VppVxlanTunnel(self, - src="10.0.0.5", - dst=self.pg0.local_ip4, - vni=1000) - t.add_vpp_config() - t.admin_up() - - self.vapi.sw_interface_set_l2_xconnect(t.sw_if_index, - self.pg1.sw_if_index, - enable=1) - self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index, - t.sw_if_index, - enable=1) - - p = (Ether(src="00:11:22:33:44:55", - dst="00:00:00:11:22:33") / - IP(src="4.3.2.1", dst="1.2.3.4") / - UDP(sport=20000, dport=10000) / - Raw(b'\xa5' * 1450)) - - rx = self.send_and_assert_no_replies(self.pg1, [p]) - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/vxlan/test/test_vxlan6.py b/src/vnet/vxlan/test/test_vxlan6.py deleted file mode 100644 index 123cce9b7ba..00000000000 --- a/src/vnet/vxlan/test/test_vxlan6.py +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/env python3 - -import socket -import unittest -from framework import VppTestCase, VppTestRunner -from template_bd import BridgeDomain - -from scapy.layers.l2 import Ether -from scapy.packet import Raw, bind_layers -from scapy.layers.inet6 import IP, IPv6, UDP -from scapy.layers.vxlan import VXLAN - -import util -from vpp_ip_route import VppIpRoute, VppRoutePath -from vpp_vxlan_tunnel import VppVxlanTunnel -from vpp_ip import INVALID_INDEX - - -class TestVxlan6(BridgeDomain, VppTestCase): - """ VXLAN over IPv6 Test Case """ - - def __init__(self, *args): - BridgeDomain.__init__(self) - VppTestCase.__init__(self, *args) - - def encapsulate(self, pkt, vni): - """ - Encapsulate the original payload frame by adding VXLAN header with its - UDP, IP and Ethernet fields - """ - return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - @classmethod - def ip_range(cls, s, e): - """ range of remote ip's """ - tmp = cls.pg0.remote_ip6.rsplit(':', 1)[0] - return ("%s:%x" % (tmp, i) for i in range(s, e)) - - def encap_mcast(self, pkt, src_ip, src_mac, vni): - """ - Encapsulate the original payload frame by adding VXLAN header with its - UDP, IP and Ethernet fields - """ - return (Ether(src=src_mac, dst=self.mcast_mac) / - IPv6(src=src_ip, dst=self.mcast_ip6) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - def decapsulate(self, pkt): - """ - Decapsulate the original payload frame by removing VXLAN header - """ - # check if is set I flag - self.assertEqual(pkt[VXLAN].flags, int('0x8', 16)) - return pkt[VXLAN].payload - - # Method for checking VXLAN encapsulation. - # - def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False): - # TODO: add error messages - # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved - # by VPP using ARP. - self.assertEqual(pkt[Ether].src, self.pg0.local_mac) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac) - else: - self.assertEqual(pkt[Ether].dst, type(self).mcast_mac) - # Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP. - self.assertEqual(pkt[IPv6].src, self.pg0.local_ip6) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[IPv6].dst, self.pg0.remote_ip6) - else: - self.assertEqual(pkt[IPv6].dst, type(self).mcast_ip6) - # Verify UDP destination port is VXLAN 4789, source UDP port could be - # arbitrary. - self.assertEqual(pkt[UDP].dport, self.dport) - # Verify UDP checksum - self.assert_udp_checksum_valid(pkt, ignore_zero_checksum=False) - # Verify VNI - self.assertEqual(pkt[VXLAN].vni, vni) - - @classmethod - def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port): - # Create 10 ucast vxlan tunnels under bd - start = 10 - end = start + n_ucast_tunnels - for dest_ip6 in cls.ip_range(start, end): - # add host route so dest ip will not be resolved - rip = VppIpRoute(cls, dest_ip6, 128, - [VppRoutePath(cls.pg0.remote_ip6, INVALID_INDEX)], - register=False) - rip.add_vpp_config() - r = VppVxlanTunnel(cls, src=cls.pg0.local_ip6, - src_port=port, dst_port=port, - dst=dest_ip6, vni=vni) - r.add_vpp_config() - cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni) - - @classmethod - def add_mcast_tunnels_load(cls): - cls.add_del_mcast_tunnels_load(is_add=1) - - @classmethod - def del_mcast_tunnels_load(cls): - cls.add_del_mcast_tunnels_load(is_add=0) - - # Class method to start the VXLAN test case. - # Overrides setUpClass method in VppTestCase class. - # Python try..except statement is used to ensure that the tear down of - # the class will be executed even if exception is raised. - # @param cls The class pointer. - @classmethod - def setUpClass(cls): - super(TestVxlan6, cls).setUpClass() - - try: - cls.flags = 0x8 - - # Create 2 pg interfaces. - cls.create_pg_interfaces(range(4)) - for pg in cls.pg_interfaces: - pg.admin_up() - - # Configure IPv6 addresses on VPP pg0. - cls.pg0.config_ip6() - - # Resolve MAC address for VPP's IP address on pg0. - cls.pg0.resolve_ndp() - - # Our Multicast address - cls.mcast_ip6 = 'ff0e::1' - cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip6) - except Exception: - super(TestVxlan6, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestVxlan6, cls).tearDownClass() - - def setUp(self): - super(TestVxlan6, self).setUp() - - def createVxLANInterfaces(self, port=4789): - # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1 - # into BD. - self.dport = port - - self.single_tunnel_vni = 0x12345 - self.single_tunnel_bd = 1 - r = VppVxlanTunnel(self, src=self.pg0.local_ip6, - dst=self.pg0.remote_ip6, - src_port=self.dport, dst_port=self.dport, - vni=self.single_tunnel_vni) - r.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=self.single_tunnel_bd) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd) - - # Setup vni 2 to test multicast flooding - self.n_ucast_tunnels = 10 - self.mcast_flood_bd = 2 - self.create_vxlan_flood_test_bd(self.mcast_flood_bd, - self.n_ucast_tunnels, - self.dport) - r = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.mcast_ip6, - src_port=self.dport, dst_port=self.dport, - mcast_sw_if_index=1, vni=self.mcast_flood_bd) - r.add_vpp_config() - self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=self.mcast_flood_bd) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd) - - # Setup vni 3 to test unicast flooding - self.ucast_flood_bd = 3 - self.create_vxlan_flood_test_bd(self.ucast_flood_bd, - self.n_ucast_tunnels, - self.dport) - self.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd) - - # Set scapy listen custom port for VxLAN - bind_layers(UDP, VXLAN, dport=self.dport) - - # Method to define VPP actions before tear down of the test case. - # Overrides tearDown method in VppTestCase class. - # @param self The object pointer. - def tearDown(self): - super(TestVxlan6, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show bridge-domain 1 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 2 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 3 detail")) - self.logger.info(self.vapi.cli("show vxlan tunnel")) - - def encap_fragmented_packet(self): - frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / - IP(src='4.3.2.1', dst='1.2.3.4') / - UDP(sport=20000, dport=10000) / - Raw(b'\xa5' * 1000)) - - frags = util.fragment_rfc791(frame, 400) - - self.pg1.add_stream(frags) - - self.pg0.enable_capture() - - self.pg_start() - - out = self.pg0.get_capture(3) - - payload = [] - for pkt in out: - payload.append(self.decapsulate(pkt)) - self.check_encapsulation(pkt, self.single_tunnel_vni) - - reassembled = util.reassemble4(payload) - - self.assertEqual(Ether(raw(frame))[IP], reassembled[IP]) - - """ - Tests with default port (4789) - """ - def test_decap(self): - """ Decapsulation test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan6, self).test_decap() - - def test_encap(self): - """ Encapsulation test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan6, self).test_encap() - - def test_encap_fragmented_packet(self): - """ Encapsulation test send fragments from pg1 - Verify receipt of encapsulated frames on pg0 - """ - self.createVxLANInterfaces() - self.encap_fragmented_packet() - - def test_ucast_flood(self): - """ Unicast flood test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan6, self).test_ucast_flood() - - def test_mcast_flood(self): - """ Multicast flood test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan6, self).test_mcast_flood() - - def test_mcast_rcv(self): - """ Multicast receive test - from BridgeDoman - """ - self.createVxLANInterfaces() - super(TestVxlan6, self).test_mcast_rcv() - - """ - Tests with custom port - """ - def test_decap_custom_port(self): - """ Decapsulation test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan6, self).test_decap() - - def test_encap_custom_port(self): - """ Encapsulation test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan6, self).test_encap() - - def test_ucast_flood_custom_port(self): - """ Unicast flood test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan6, self).test_ucast_flood() - - def test_mcast_flood_custom_port(self): - """ Multicast flood test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan6, self).test_mcast_flood() - - def test_mcast_rcv_custom_port(self): - """ Multicast receive test custom port - from BridgeDoman - """ - self.createVxLANInterfaces(1111) - super(TestVxlan6, self).test_mcast_rcv() - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/vxlan/test/test_vxlan_gbp.py b/src/vnet/vxlan/test/test_vxlan_gbp.py deleted file mode 100644 index f332aced7d8..00000000000 --- a/src/vnet/vxlan/test/test_vxlan_gbp.py +++ /dev/null @@ -1,293 +0,0 @@ -#!/usr/bin/env python3 - -import socket -from util import ip4_range, reassemble4_ether -import unittest -from framework import VppTestCase, VppTestRunner -from template_bd import BridgeDomain - -from scapy.layers.l2 import Ether -from scapy.packet import Raw -from scapy.layers.inet import IP, UDP -from scapy.layers.vxlan import VXLAN - -from vpp_ip_route import VppIpRoute, VppRoutePath -from vpp_ip import INVALID_INDEX - - -class TestVxlanGbp(VppTestCase): - """ VXLAN GBP Test Case """ - - @property - def frame_request(self): - """ Ethernet frame modeling a generic request """ - return (Ether(src='00:00:00:00:00:01', dst='00:00:00:00:00:02') / - IP(src='1.2.3.4', dst='4.3.2.1') / - UDP(sport=10000, dport=20000) / - Raw(b'\xa5' * 100)) - - @property - def frame_reply(self): - """ Ethernet frame modeling a generic reply """ - return (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / - IP(src='4.3.2.1', dst='1.2.3.4') / - UDP(sport=20000, dport=10000) / - Raw(b'\xa5' * 100)) - - def encapsulate(self, pkt, vni): - """ - Encapsulate the original payload frame by adding VXLAN GBP header with - its UDP, IP and Ethernet fields - """ - return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags, gpflags=self.gpflags, - gpid=self.sclass) / pkt) - - def ip_range(self, start, end): - """ range of remote ip's """ - return ip4_range(self.pg0.remote_ip4, start, end) - - def decapsulate(self, pkt): - """ - Decapsulate the original payload frame by removing VXLAN header - """ - # check if is set G and I flag - self.assertEqual(pkt[VXLAN].flags, int('0x88', 16)) - return pkt[VXLAN].payload - - # Method for checking VXLAN GBP encapsulation. - # - def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False): - # TODO: add error messages - # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved - # by VPP using ARP. - self.assertEqual(pkt[Ether].src, self.pg0.local_mac) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac) - else: - self.assertEqual(pkt[Ether].dst, type(self).mcast_mac) - # Verify VXLAN GBP tunnel source IP is VPP_IP and destination IP is - # MY_IP. - self.assertEqual(pkt[IP].src, self.pg0.local_ip4) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4) - else: - self.assertEqual(pkt[IP].dst, type(self).mcast_ip4) - # Verify UDP destination port is VXLAN GBP 48879, source UDP port could - # be arbitrary. - self.assertEqual(pkt[UDP].dport, type(self).dport) - # Verify UDP checksum - self.assert_udp_checksum_valid(pkt) - # Verify VNI - # pkt.show() - self.assertEqual(pkt[VXLAN].vni, vni) - # Verify Source Class - self.assertEqual(pkt[VXLAN].gpid, 0) - - @classmethod - def create_vxlan_gbp_flood_test_bd(cls, vni, n_ucast_tunnels): - # Create 2 ucast vxlan tunnels under bd - ip_range_start = 10 - ip_range_end = ip_range_start + n_ucast_tunnels - next_hop_address = cls.pg0.remote_ip4 - for dest_ip4 in ip4_range(cls.pg0.remote_ip4, - ip_range_start, - ip_range_end): - # add host route so dest_ip4 will not be resolved - rip = VppIpRoute(cls, dest_ip4, 32, - [VppRoutePath(next_hop_address, - INVALID_INDEX)], - register=False) - rip.add_vpp_config() - r = cls.vapi.vxlan_gbp_tunnel_add_del( - tunnel={ - 'src': cls.pg0.local_ip4, - 'dst': dest_ip4, - 'vni': vni, - 'instance': INVALID_INDEX, - 'mcast_sw_if_index': INVALID_INDEX, - 'mode': 1, - }, - is_add=1 - ) - cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=vni) - - # Class method to start the VXLAN GBP test case. - # Overrides setUpClass method in VppTestCase class. - # Python try..except statement is used to ensure that the tear down of - # the class will be executed even if exception is raised. - # @param cls The class pointer. - @classmethod - def setUpClass(cls): - super(TestVxlanGbp, cls).setUpClass() - - try: - cls.dport = 48879 - cls.flags = 0x88 - cls.gpflags = 0x0 - cls.sclass = 0 - - # Create 2 pg interfaces. - cls.create_pg_interfaces(range(4)) - for pg in cls.pg_interfaces: - pg.admin_up() - - # Configure IPv4 addresses on VPP pg0. - cls.pg0.config_ip4() - - # Resolve MAC address for VPP's IP address on pg0. - cls.pg0.resolve_arp() - - # Create VXLAN GBP VTEP on VPP pg0, and put vxlan_gbp_tunnel0 and - # pg1 into BD. - cls.single_tunnel_bd = 1 - cls.single_tunnel_vni = 0xabcde - r = cls.vapi.vxlan_gbp_tunnel_add_del( - tunnel={ - 'src': cls.pg0.local_ip4, - 'dst': cls.pg0.remote_ip4, - 'vni': cls.single_tunnel_vni, - 'instance': INVALID_INDEX, - 'mcast_sw_if_index': INVALID_INDEX, - 'mode': 1, - }, - is_add=1 - ) - cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=cls.single_tunnel_bd) - cls.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=cls.pg1.sw_if_index, - bd_id=cls.single_tunnel_bd) - - # Setup vni 2 to test multicast flooding - cls.n_ucast_tunnels = 2 - # Setup vni 3 to test unicast flooding - cls.ucast_flood_bd = 3 - cls.create_vxlan_gbp_flood_test_bd(cls.ucast_flood_bd, - cls.n_ucast_tunnels) - cls.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=cls.pg3.sw_if_index, - bd_id=cls.ucast_flood_bd) - except Exception: - super(TestVxlanGbp, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestVxlanGbp, cls).tearDownClass() - - def assert_eq_pkts(self, pkt1, pkt2): - """ Verify the Ether, IP, UDP, payload are equal in both - packets - """ - self.assertEqual(pkt1[Ether].src, pkt2[Ether].src) - self.assertEqual(pkt1[Ether].dst, pkt2[Ether].dst) - self.assertEqual(pkt1[IP].src, pkt2[IP].src) - self.assertEqual(pkt1[IP].dst, pkt2[IP].dst) - self.assertEqual(pkt1[UDP].sport, pkt2[UDP].sport) - self.assertEqual(pkt1[UDP].dport, pkt2[UDP].dport) - self.assertEqual(pkt1[Raw], pkt2[Raw]) - - def test_decap(self): - """ Decapsulation test - Send encapsulated frames from pg0 - Verify receipt of decapsulated frames on pg1 - """ - encapsulated_pkt = self.encapsulate(self.frame_request, - self.single_tunnel_vni) - - self.pg0.add_stream([encapsulated_pkt, ]) - - self.pg1.enable_capture() - - self.pg_start() - - # Pick first received frame and check if it's the non-encapsulated - # frame - out = self.pg1.get_capture(1) - pkt = out[0] - self.assert_eq_pkts(pkt, self.frame_request) - - def test_encap(self): - """ Encapsulation test - Send frames from pg1 - Verify receipt of encapsulated frames on pg0 - """ - self.pg1.add_stream([self.frame_reply]) - - self.pg0.enable_capture() - - self.pg_start() - - # Pick first received frame and check if it's correctly encapsulated. - out = self.pg0.get_capture(1) - pkt = out[0] - self.check_encapsulation(pkt, self.single_tunnel_vni) - - payload = self.decapsulate(pkt) - self.assert_eq_pkts(payload, self.frame_reply) - - def test_ucast_flood(self): - """ Unicast flood test - Send frames from pg3 - Verify receipt of encapsulated frames on pg0 - """ - self.pg3.add_stream([self.frame_reply]) - - self.pg0.enable_capture() - - self.pg_start() - - # Get packet from each tunnel and assert it's correctly encapsulated. - out = self.pg0.get_capture(self.n_ucast_tunnels) - for pkt in out: - self.check_encapsulation(pkt, self.ucast_flood_bd, True) - payload = self.decapsulate(pkt) - self.assert_eq_pkts(payload, self.frame_reply) - - def test_encap_big_packet(self): - """ Encapsulation test send big frame from pg1 - Verify receipt of encapsulated frames on pg0 - """ - - self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1500, 0, 0, 0]) - - frame = (Ether(src='00:00:00:00:00:02', dst='00:00:00:00:00:01') / - IP(src='4.3.2.1', dst='1.2.3.4') / - UDP(sport=20000, dport=10000) / - Raw(b'\xa5' * 1450)) - - self.pg1.add_stream([frame]) - - self.pg0.enable_capture() - - self.pg_start() - - # Pick first received frame and check if it's correctly encapsulated. - out = self.pg0.get_capture(2) - pkt = reassemble4_ether(out) - self.check_encapsulation(pkt, self.single_tunnel_vni) - - payload = self.decapsulate(pkt) - self.assert_eq_pkts(payload, frame) - -# Method to define VPP actions before tear down of the test case. -# Overrides tearDown method in VppTestCase class. -# @param self The object pointer. - def tearDown(self): - super(TestVxlanGbp, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show bridge-domain 1 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 3 detail")) - self.logger.info(self.vapi.cli("show vxlan-gbp tunnel")) - self.logger.info(self.vapi.cli("show error")) - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/vxlan/test/test_vxlan_gpe.py b/src/vnet/vxlan/test/test_vxlan_gpe.py deleted file mode 100644 index c5d6bf07f7c..00000000000 --- a/src/vnet/vxlan/test/test_vxlan_gpe.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env python3 - -import socket -from util import ip4_range -import unittest -from framework import VppTestCase, VppTestRunner, running_extended_tests -from template_bd import BridgeDomain - -from scapy.layers.l2 import Ether -from scapy.packet import Raw -from scapy.layers.inet import IP, UDP -from scapy.layers.vxlan import VXLAN - -import util -from vpp_ip_route import VppIpRoute, VppRoutePath - -from vpp_ip import INVALID_INDEX - - -@unittest.skipUnless(running_extended_tests, "part of extended tests") -class TestVxlanGpe(BridgeDomain, VppTestCase): - """ VXLAN-GPE Test Case """ - - def __init__(self, *args): - BridgeDomain.__init__(self) - VppTestCase.__init__(self, *args) - - def encapsulate(self, pkt, vni): - """ - Encapsulate the original payload frame by adding VXLAN-GPE header - with its UDP, IP and Ethernet fields - """ - return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / - IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - def ip_range(self, start, end): - """ range of remote ip's """ - return ip4_range(self.pg0.remote_ip4, start, end) - - def encap_mcast(self, pkt, src_ip, src_mac, vni): - """ - Encapsulate the original payload frame by adding VXLAN-GPE header - with its UDP, IP and Ethernet fields - """ - return (Ether(src=src_mac, dst=self.mcast_mac) / - IP(src=src_ip, dst=self.mcast_ip4) / - UDP(sport=self.dport, dport=self.dport, chksum=0) / - VXLAN(vni=vni, flags=self.flags) / - pkt) - - def decapsulate(self, pkt): - """ - Decapsulate the original payload frame by removing VXLAN-GPE header - """ - # check if is set I and P flag - self.assertEqual(pkt[VXLAN].flags, 0x0c) - return pkt[VXLAN].payload - - # Method for checking VXLAN-GPE encapsulation. - # - def check_encapsulation(self, pkt, vni, local_only=False, mcast_pkt=False): - # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved - # by VPP using ARP. - self.assertEqual(pkt[Ether].src, self.pg0.local_mac) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac) - else: - self.assertEqual(pkt[Ether].dst, type(self).mcast_mac) - # Verify VXLAN-GPE tunnel src IP is VPP_IP and dst IP is MY_IP. - self.assertEqual(pkt[IP].src, self.pg0.local_ip4) - if not local_only: - if not mcast_pkt: - self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4) - else: - self.assertEqual(pkt[IP].dst, type(self).mcast_ip4) - # Verify UDP destination port is VXLAN-GPE 4790, source UDP port - # could be arbitrary. - self.assertEqual(pkt[UDP].dport, type(self).dport) - # Verify UDP checksum - self.assert_udp_checksum_valid(pkt) - # Verify VNI - self.assertEqual(pkt[VXLAN].vni, vni) - - @classmethod - def create_vxlan_gpe_flood_test_bd(cls, vni, n_ucast_tunnels): - # Create 10 ucast vxlan tunnels under bd - ip_range_start = 10 - ip_range_end = ip_range_start + n_ucast_tunnels - next_hop_address = cls.pg0.remote_ip4 - for dest_ip4 in ip4_range(next_hop_address, ip_range_start, - ip_range_end): - # add host route so dest_ip4n will not be resolved - rip = VppIpRoute(cls, dest_ip4, 32, - [VppRoutePath(next_hop_address, - INVALID_INDEX)], - register=False) - rip.add_vpp_config() - - r = cls.vapi.vxlan_gpe_add_del_tunnel( - src_addr=cls.pg0.local_ip4, - dst_addr=dest_ip4, - vni=vni) - cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=vni) - - @classmethod - def add_del_shared_mcast_dst_load(cls, is_add): - """ - add or del tunnels sharing the same mcast dst - to test vxlan_gpe ref_count mechanism - """ - n_shared_dst_tunnels = 20 - vni_start = 1000 - vni_end = vni_start + n_shared_dst_tunnels - for vni in range(vni_start, vni_end): - r = cls.vapi.vxlan_gpe_add_del_tunnel( - local=cls.pg0.local_ip4, - remote=cls.mcast_ip4, - mcast_sw_if_index=1, - vni=vni, - is_add=is_add) - if r.sw_if_index == 0xffffffff: - raise ValueError("bad sw_if_index: ~0") - - @classmethod - def add_shared_mcast_dst_load(cls): - cls.add_del_shared_mcast_dst_load(is_add=1) - - @classmethod - def del_shared_mcast_dst_load(cls): - cls.add_del_shared_mcast_dst_load(is_add=0) - - @classmethod - def add_del_mcast_tunnels_load(cls, is_add): - """ - add or del tunnels to test vxlan_gpe stability - """ - n_distinct_dst_tunnels = 20 - ip_range_start = 10 - ip_range_end = ip_range_start + n_distinct_dst_tunnels - for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start, - ip_range_end): - vni = int(dest_ip4.split(".")[3]) - cls.vapi.vxlan_gpe_add_del_tunnel( - src_addr=cls.pg0.local_ip4, - dst_addr=dest_ip4, - mcast_sw_if_index=1, - vni=vni, - is_add=is_add) - - @classmethod - def add_mcast_tunnels_load(cls): - cls.add_del_mcast_tunnels_load(is_add=1) - - @classmethod - def del_mcast_tunnels_load(cls): - cls.add_del_mcast_tunnels_load(is_add=0) - - # Class method to start the VXLAN-GPE test case. - # Overrides setUpClass method in VppTestCase class. - # Python try..except statement is used to ensure that the tear down of - # the class will be executed even if exception is raised. - # @param cls The class pointer. - @classmethod - def setUpClass(cls): - super(TestVxlanGpe, cls).setUpClass() - - try: - cls.dport = 4790 - cls.flags = 0x0c - - # Create 2 pg interfaces. - cls.create_pg_interfaces(range(4)) - for pg in cls.pg_interfaces: - pg.admin_up() - - # Configure IPv4 addresses on VPP pg0. - cls.pg0.config_ip4() - - # Resolve MAC address for VPP's IP address on pg0. - cls.pg0.resolve_arp() - - # Our Multicast address - cls.mcast_ip4 = '239.1.1.1' - cls.mcast_mac = util.mcast_ip_to_mac(cls.mcast_ip4) - - # Create VXLAN-GPE VTEP on VPP pg0, and put vxlan_gpe_tunnel0 - # and pg1 into BD. - cls.single_tunnel_vni = 0xabcde - cls.single_tunnel_bd = 11 - r = cls.vapi.vxlan_gpe_add_del_tunnel( - src_addr=cls.pg0.local_ip4, - dst_addr=cls.pg0.remote_ip4, - vni=cls.single_tunnel_vni) - cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=cls.single_tunnel_bd) - cls.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.single_tunnel_bd) - - # Setup vni 2 to test multicast flooding - cls.n_ucast_tunnels = 10 - cls.mcast_flood_bd = 12 - cls.create_vxlan_gpe_flood_test_bd(cls.mcast_flood_bd, - cls.n_ucast_tunnels) - r = cls.vapi.vxlan_gpe_add_del_tunnel( - src_addr=cls.pg0.local_ip4, - dst_addr=cls.mcast_ip4, - mcast_sw_if_index=1, - vni=cls.mcast_flood_bd) - cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, - bd_id=cls.mcast_flood_bd) - cls.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=cls.pg2.sw_if_index, bd_id=cls.mcast_flood_bd) - - # Add and delete mcast tunnels to check stability - cls.add_shared_mcast_dst_load() - cls.add_mcast_tunnels_load() - cls.del_shared_mcast_dst_load() - cls.del_mcast_tunnels_load() - - # Setup vni 3 to test unicast flooding - cls.ucast_flood_bd = 13 - cls.create_vxlan_gpe_flood_test_bd(cls.ucast_flood_bd, - cls.n_ucast_tunnels) - cls.vapi.sw_interface_set_l2_bridge( - rx_sw_if_index=cls.pg3.sw_if_index, bd_id=cls.ucast_flood_bd) - except Exception: - super(TestVxlanGpe, cls).tearDownClass() - raise - - @classmethod - def tearDownClass(cls): - super(TestVxlanGpe, cls).tearDownClass() - - @unittest.skip("test disabled for vxlan-gpe") - def test_mcast_flood(self): - """ inherited from BridgeDomain """ - pass - - @unittest.skip("test disabled for vxlan-gpe") - def test_mcast_rcv(self): - """ inherited from BridgeDomain """ - pass - - # Method to define VPP actions before tear down of the test case. - # Overrides tearDown method in VppTestCase class. - # @param self The object pointer. - def tearDown(self): - super(TestVxlanGpe, self).tearDown() - - def show_commands_at_teardown(self): - self.logger.info(self.vapi.cli("show bridge-domain 11 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 12 detail")) - self.logger.info(self.vapi.cli("show bridge-domain 13 detail")) - self.logger.info(self.vapi.cli("show int")) - self.logger.info(self.vapi.cli("show vxlan-gpe")) - self.logger.info(self.vapi.cli("show trace")) - - -if __name__ == '__main__': - unittest.main(testRunner=VppTestRunner) diff --git a/src/vnet/vxlan/test/vpp_vxlan_gbp_tunnel.py b/src/vnet/vxlan/test/vpp_vxlan_gbp_tunnel.py deleted file mode 100644 index 0898bd9f810..00000000000 --- a/src/vnet/vxlan/test/vpp_vxlan_gbp_tunnel.py +++ /dev/null @@ -1,75 +0,0 @@ - -from vpp_interface import VppInterface -from vpp_papi import VppEnum - - -INDEX_INVALID = 0xffffffff - - -def find_vxlan_gbp_tunnel(test, src, dst, vni): - ts = test.vapi.vxlan_gbp_tunnel_dump(INDEX_INVALID) - for t in ts: - if src == str(t.tunnel.src) and \ - dst == str(t.tunnel.dst) and \ - t.tunnel.vni == vni: - return t.tunnel.sw_if_index - return INDEX_INVALID - - -class VppVxlanGbpTunnel(VppInterface): - """ - VPP VXLAN GBP interface - """ - - def __init__(self, test, src, dst, vni, mcast_itf=None, mode=None, - is_ipv6=None, encap_table_id=None, instance=0xffffffff): - """ Create VXLAN-GBP Tunnel interface """ - super(VppVxlanGbpTunnel, self).__init__(test) - self.src = src - self.dst = dst - self.vni = vni - self.mcast_itf = mcast_itf - self.ipv6 = is_ipv6 - self.encap_table_id = encap_table_id - self.instance = instance - if not mode: - self.mode = (VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t. - VXLAN_GBP_API_TUNNEL_MODE_L2) - else: - self.mode = mode - - def encode(self): - return { - 'src': self.src, - 'dst': self.dst, - 'mode': self.mode, - 'vni': self.vni, - 'mcast_sw_if_index': self.mcast_itf.sw_if_index - if self.mcast_itf else INDEX_INVALID, - 'encap_table_id': self.encap_table_id, - 'instance': self.instance, - } - - def add_vpp_config(self): - reply = self.test.vapi.vxlan_gbp_tunnel_add_del( - is_add=1, - tunnel=self.encode(), - ) - self.set_sw_if_index(reply.sw_if_index) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self.test.vapi.vxlan_gbp_tunnel_add_del( - is_add=0, - tunnel=self.encode(), - ) - - def query_vpp_config(self): - return (INDEX_INVALID != find_vxlan_gbp_tunnel(self._test, - self.src, - self.dst, - self.vni)) - - def object_id(self): - return "vxlan-gbp-%d-%d-%s-%s" % (self.sw_if_index, self.vni, - self.src, self.dst) diff --git a/src/vnet/vxlan/test/vpp_vxlan_tunnel.py b/src/vnet/vxlan/test/vpp_vxlan_tunnel.py deleted file mode 100644 index d7e087da6f8..00000000000 --- a/src/vnet/vxlan/test/vpp_vxlan_tunnel.py +++ /dev/null @@ -1,87 +0,0 @@ -from vpp_interface import VppInterface -from vpp_papi import VppEnum - - -INDEX_INVALID = 0xffffffff -DEFAULT_PORT = 4789 -UNDEFINED_PORT = 0 - - -def find_vxlan_tunnel(test, src, dst, s_port, d_port, vni): - ts = test.vapi.vxlan_tunnel_v2_dump(INDEX_INVALID) - - src_port = DEFAULT_PORT - if s_port != UNDEFINED_PORT: - src_port = s_port - - dst_port = DEFAULT_PORT - if d_port != UNDEFINED_PORT: - dst_port = d_port - - for t in ts: - if src == str(t.src_address) and \ - dst == str(t.dst_address) and \ - src_port == t.src_port and \ - dst_port == t.dst_port and \ - t.vni == vni: - return t.sw_if_index - return INDEX_INVALID - - -class VppVxlanTunnel(VppInterface): - """ - VPP VXLAN interface - """ - - def __init__(self, test, src, dst, vni, - src_port=UNDEFINED_PORT, dst_port=UNDEFINED_PORT, - mcast_itf=None, - mcast_sw_if_index=INDEX_INVALID, - decap_next_index=INDEX_INVALID, - encap_vrf_id=None, instance=0xffffffff, is_l3=False): - """ Create VXLAN Tunnel interface """ - super(VppVxlanTunnel, self).__init__(test) - self.src = src - self.dst = dst - self.vni = vni - self.src_port = src_port - self.dst_port = dst_port - self.mcast_itf = mcast_itf - self.mcast_sw_if_index = mcast_sw_if_index - self.encap_vrf_id = encap_vrf_id - self.decap_next_index = decap_next_index - self.instance = instance - self.is_l3 = is_l3 - - if (self.mcast_itf): - self.mcast_sw_if_index = self.mcast_itf.sw_if_index - - def add_vpp_config(self): - reply = self.test.vapi.vxlan_add_del_tunnel_v3( - is_add=1, src_address=self.src, dst_address=self.dst, vni=self.vni, - src_port=self.src_port, dst_port=self.dst_port, - mcast_sw_if_index=self.mcast_sw_if_index, - encap_vrf_id=self.encap_vrf_id, is_l3=self.is_l3, - instance=self.instance, decap_next_index=self.decap_next_index) - self.set_sw_if_index(reply.sw_if_index) - self._test.registry.register(self, self._test.logger) - - def remove_vpp_config(self): - self.test.vapi.vxlan_add_del_tunnel_v2( - is_add=0, src_address=self.src, dst_address=self.dst, vni=self.vni, - src_port=self.src_port, dst_port=self.dst_port, - mcast_sw_if_index=self.mcast_sw_if_index, - encap_vrf_id=self.encap_vrf_id, instance=self.instance, - decap_next_index=self.decap_next_index) - - def query_vpp_config(self): - return (INDEX_INVALID != find_vxlan_tunnel(self._test, - self.src, - self.dst, - self.src_port, - self.dst_port, - self.vni)) - - def object_id(self): - return "vxlan-%d-%d-%s-%s" % (self.sw_if_index, self.vni, - self.src, self.dst) |