aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Makefile9
-rw-r--r--test/test_abf.py344
-rw-r--r--test/test_acl_plugin.py1519
-rw-r--r--test/test_acl_plugin_conns.py411
-rw-r--r--test/test_acl_plugin_l2l3.py871
-rw-r--r--test/test_acl_plugin_macip.py1295
-rw-r--r--test/test_cdp.py171
-rw-r--r--test/test_classify_l2_acl.py689
-rw-r--r--test/test_flowprobe.py1082
-rw-r--r--test/test_gbp.py5278
-rw-r--r--test/test_gtpu.py393
-rw-r--r--test/test_igmp.py834
-rw-r--r--test/test_ipsec_nat.py271
-rw-r--r--test/test_l3xc.py153
-rw-r--r--test/test_lb.py502
-rw-r--r--test/test_lb_api.py76
-rw-r--r--test/test_mactime.py155
-rw-r--r--test/test_map.py437
-rw-r--r--test/test_memif.py275
-rw-r--r--test/test_nat.py9576
-rw-r--r--test/test_pppoe.py606
-rw-r--r--test/test_quic.py248
-rw-r--r--test/test_sctp.py92
-rw-r--r--test/test_srv6.py2141
-rw-r--r--test/test_srv6_ad.py811
-rwxr-xr-xtest/test_srv6_as.py889
-rw-r--r--test/test_svs.py322
-rw-r--r--test/vpp_igmp.py75
-rw-r--r--test/vpp_lb.py84
-rw-r--r--test/vpp_memif.py153
-rw-r--r--test/vpp_pppoe_interface.py39
-rw-r--r--test/vpp_srv6.py222
32 files changed, 8 insertions, 30015 deletions
diff --git a/test/Makefile b/test/Makefile
index 3a92f1413b5..66c8f8a9bb7 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -135,8 +135,15 @@ refresh-deps: clean-deps $(PYTHON_DEPENDS)
clean-deps:
@rm -f $(PYTHON_DEPENDS)
+ifneq ($(EXTERN_PLUGIN_SRC_DIR),)
+PLUGIN_SRC_DIR=$(EXTERN_PLUGIN_SRC_DIR)
+else
+PLUGIN_SRC_DIR=$(WS_ROOT)/src/plugins
+endif
+PLUGIN_TEST_DIRS=$(shell find $(PLUGIN_SRC_DIR) -type d -name test -exec echo -n " -d {}" \;)
+
define retest-func
-@env FORCE_FOREGROUND=$(FORCE_FOREGROUND) FAILED_DIR=$(FAILED_DIR) VENV_PATH=$(VENV_PATH) scripts/setsid_wrapper.sh $(FORCE_FOREGROUND) $(VENV_PATH)/bin/activate $(PYTHON_INTERP) $(PYTHON_PROFILE_OPTS) run_tests.py -d $(TEST_DIR) $(UNITTEST_EXTRA_OPTS) || env FAILED_DIR=$(FAILED_DIR) COMPRESS_FAILED_TEST_LOGS=$(COMPRESS_FAILED_TEST_LOGS) scripts/compress_failed.sh
+@env FORCE_FOREGROUND=$(FORCE_FOREGROUND) FAILED_DIR=$(FAILED_DIR) VENV_PATH=$(VENV_PATH) scripts/setsid_wrapper.sh $(FORCE_FOREGROUND) $(VENV_PATH)/bin/activate $(PYTHON_INTERP) $(PYTHON_PROFILE_OPTS) run_tests.py -d $(TEST_DIR)$(PLUGIN_TEST_DIRS) $(UNITTEST_EXTRA_OPTS) || env FAILED_DIR=$(FAILED_DIR) COMPRESS_FAILED_TEST_LOGS=$(COMPRESS_FAILED_TEST_LOGS) scripts/compress_failed.sh
endef
.PHONY: sanity
diff --git a/test/test_abf.py b/test/test_abf.py
deleted file mode 100644
index 221a793fed3..00000000000
--- a/test/test_abf.py
+++ /dev/null
@@ -1,344 +0,0 @@
-#!/usr/bin/env python
-
-from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
-import unittest
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip import DpoProto
-from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsLabel, \
- VppIpTable, FibPathProto
-
-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 vpp_object import VppObject
-
-NUM_PKTS = 67
-
-
-def find_abf_policy(test, id):
- policies = test.vapi.abf_policy_dump()
- for p in policies:
- if id == p.policy.policy_id:
- return True
- return False
-
-
-def find_abf_itf_attach(test, id, sw_if_index):
- attachs = test.vapi.abf_itf_attach_dump()
- for a in attachs:
- if id == a.attach.policy_id and \
- sw_if_index == a.attach.sw_if_index:
- return True
- return False
-
-
-class VppAbfPolicy(VppObject):
-
- def __init__(self,
- test,
- policy_id,
- acl,
- paths):
- self._test = test
- self.policy_id = policy_id
- self.acl = acl
- 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.abf_policy_add_del(
- 1,
- {'policy_id': self.policy_id,
- 'acl_index': self.acl.acl_index,
- 'n_paths': len(self.paths),
- 'paths': self.encoded_paths})
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.abf_policy_add_del(
- 0,
- {'policy_id': self.policy_id,
- 'acl_index': self.acl.acl_index,
- 'n_paths': len(self.paths),
- 'paths': self.encoded_paths})
-
- def query_vpp_config(self):
- return find_abf_policy(self._test, self.policy_id)
-
- def object_id(self):
- return ("abf-policy-%d" % self.policy_id)
-
-
-class VppAbfAttach(VppObject):
-
- def __init__(self,
- test,
- policy_id,
- sw_if_index,
- priority,
- is_ipv6=0):
- self._test = test
- self.policy_id = policy_id
- self.sw_if_index = sw_if_index
- self.priority = priority
- self.is_ipv6 = is_ipv6
-
- def add_vpp_config(self):
- self._test.vapi.abf_itf_attach_add_del(
- 1,
- {'policy_id': self.policy_id,
- 'sw_if_index': self.sw_if_index,
- 'priority': self.priority,
- 'is_ipv6': self.is_ipv6})
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.abf_itf_attach_add_del(
- 0,
- {'policy_id': self.policy_id,
- 'sw_if_index': self.sw_if_index,
- 'priority': self.priority,
- 'is_ipv6': self.is_ipv6})
-
- def query_vpp_config(self):
- return find_abf_itf_attach(self._test,
- self.policy_id,
- self.sw_if_index)
-
- def object_id(self):
- return ("abf-attach-%d-%d" % (self.policy_id, self.sw_if_index))
-
-
-class TestAbf(VppTestCase):
- """ ABF Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestAbf, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestAbf, cls).tearDownClass()
-
- def setUp(self):
- super(TestAbf, self).setUp()
-
- self.create_pg_interfaces(range(5))
-
- for i in self.pg_interfaces[:4]:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
- i.config_ip6()
- i.resolve_ndp()
-
- def tearDown(self):
- for i in self.pg_interfaces:
- i.unconfig_ip4()
- i.unconfig_ip6()
- i.ip6_disable()
- i.admin_down()
- super(TestAbf, self).tearDown()
-
- def test_abf4(self):
- """ IPv4 ACL Based Forwarding
- """
-
- #
- # We are not testing the various matching capabilities
- # of ACLs, that's done elsewhere. Here ware are testing
- # the application of ACLs to a forwarding path to achieve
- # ABF
- # So we construct just a few ACLs to ensure the ABF policies
- # are correctly constructed and used. And a few path types
- # to test the API path decoding.
- #
-
- #
- # Rule 1
- #
- rule_1 = ({'is_permit': 1,
- 'is_ipv6': 0,
- 'proto': 17,
- 'srcport_or_icmptype_first': 1234,
- 'srcport_or_icmptype_last': 1234,
- 'src_ip_prefix_len': 32,
- 'src_ip_addr': inet_pton(AF_INET, "1.1.1.1"),
- 'dstport_or_icmpcode_first': 1234,
- 'dstport_or_icmpcode_last': 1234,
- 'dst_ip_prefix_len': 32,
- 'dst_ip_addr': inet_pton(AF_INET, "1.1.1.2")})
- acl_1 = self.vapi.acl_add_replace(acl_index=4294967295, r=[rule_1])
-
- #
- # ABF policy for ACL 1 - path via interface 1
- #
- abf_1 = VppAbfPolicy(self, 10, acl_1,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- abf_1.add_vpp_config()
-
- #
- # Attach the policy to input interface Pg0
- #
- attach_1 = VppAbfAttach(self, 10, self.pg0.sw_if_index, 50)
- attach_1.add_vpp_config()
-
- #
- # fire in packet matching the ACL src,dst. If it's forwarded
- # then the ABF was successful, since default routing will drop it
- #
- p_1 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg0.local_mac) /
- IP(src="1.1.1.1", dst="1.1.1.2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg1)
-
- #
- # Attach a 'better' priority policy to the same interface
- #
- abf_2 = VppAbfPolicy(self, 11, acl_1,
- [VppRoutePath(self.pg2.remote_ip4,
- self.pg2.sw_if_index)])
- abf_2.add_vpp_config()
- attach_2 = VppAbfAttach(self, 11, self.pg0.sw_if_index, 40)
- attach_2.add_vpp_config()
-
- self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg2)
-
- #
- # Attach a policy with priority in the middle
- #
- abf_3 = VppAbfPolicy(self, 12, acl_1,
- [VppRoutePath(self.pg3.remote_ip4,
- self.pg3.sw_if_index)])
- abf_3.add_vpp_config()
- attach_3 = VppAbfAttach(self, 12, self.pg0.sw_if_index, 45)
- attach_3.add_vpp_config()
-
- self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg2)
-
- #
- # remove the best priority
- #
- attach_2.remove_vpp_config()
- self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg3)
-
- #
- # Attach one of the same policies to Pg1
- #
- attach_4 = VppAbfAttach(self, 12, self.pg1.sw_if_index, 45)
- attach_4.add_vpp_config()
-
- p_2 = (Ether(src=self.pg1.remote_mac,
- dst=self.pg1.local_mac) /
- IP(src="1.1.1.1", dst="1.1.1.2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg1, p_2 * NUM_PKTS, self.pg3)
-
- #
- # detach the policy from PG1, now expect traffic to be dropped
- #
- attach_4.remove_vpp_config()
-
- self.send_and_assert_no_replies(self.pg1, p_2 * NUM_PKTS, "Detached")
-
- #
- # Swap to route via a next-hop in the non-default table
- #
- table_20 = VppIpTable(self, 20)
- table_20.add_vpp_config()
-
- self.pg4.set_table_ip4(table_20.table_id)
- self.pg4.admin_up()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- abf_13 = VppAbfPolicy(self, 13, acl_1,
- [VppRoutePath(self.pg4.remote_ip4,
- 0xffffffff,
- nh_table_id=table_20.table_id)])
- abf_13.add_vpp_config()
- attach_5 = VppAbfAttach(self, 13, self.pg0.sw_if_index, 30)
- attach_5.add_vpp_config()
-
- self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg4)
-
- self.pg4.unconfig_ip4()
- self.pg4.set_table_ip4(0)
-
- def test_abf6(self):
- """ IPv6 ACL Based Forwarding
- """
-
- #
- # Simple test for matching IPv6 packets
- #
-
- #
- # Rule 1
- #
- rule_1 = ({'is_permit': 1,
- 'is_ipv6': 1,
- 'proto': 17,
- 'srcport_or_icmptype_first': 1234,
- 'srcport_or_icmptype_last': 1234,
- 'src_ip_prefix_len': 128,
- 'src_ip_addr': inet_pton(AF_INET6, "2001::2"),
- 'dstport_or_icmpcode_first': 1234,
- 'dstport_or_icmpcode_last': 1234,
- 'dst_ip_prefix_len': 128,
- 'dst_ip_addr': inet_pton(AF_INET6, "2001::1")})
- acl_1 = self.vapi.acl_add_replace(acl_index=4294967295,
- r=[rule_1])
-
- #
- # ABF policy for ACL 1 - path via interface 1
- #
- abf_1 = VppAbfPolicy(self, 10, acl_1,
- [VppRoutePath("3001::1",
- 0xffffffff)])
- abf_1.add_vpp_config()
-
- attach_1 = VppAbfAttach(self, 10, self.pg0.sw_if_index,
- 45, is_ipv6=True)
- attach_1.add_vpp_config()
-
- #
- # a packet matching the rule
- #
- p = (Ether(src=self.pg0.remote_mac,
- dst=self.pg0.local_mac) /
- IPv6(src="2001::2", dst="2001::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- #
- # packets are dropped because there is no route to the policy's
- # next hop
- #
- self.send_and_assert_no_replies(self.pg1, p * NUM_PKTS, "no route")
-
- #
- # add a route resolving the next-hop
- #
- route = VppIpRoute(self, "3001::1", 32,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- #
- # now expect packets forwarded.
- #
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_acl_plugin.py b/test/test_acl_plugin.py
deleted file mode 100644
index eca02316bf6..00000000000
--- a/test/test_acl_plugin.py
+++ /dev/null
@@ -1,1519 +0,0 @@
-#!/usr/bin/env python
-"""ACL plugin Test Case HLD:
-"""
-
-import unittest
-import random
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, TCP, UDP, ICMP
-from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest
-from scapy.layers.inet6 import IPv6ExtHdrFragment
-from framework import VppTestCase, VppTestRunner
-from util import Host, ppp
-
-from vpp_lo_interface import VppLoInterface
-
-
-class TestACLplugin(VppTestCase):
- """ ACL plugin Test Case """
-
- # traffic types
- IP = 0
- ICMP = 1
-
- # IP version
- IPRANDOM = -1
- IPV4 = 0
- IPV6 = 1
-
- # rule types
- DENY = 0
- PERMIT = 1
-
- # supported protocols
- proto = [[6, 17], [1, 58]]
- proto_map = {1: 'ICMP', 58: 'ICMPv6EchoRequest', 6: 'TCP', 17: 'UDP'}
- ICMPv4 = 0
- ICMPv6 = 1
- TCP = 0
- UDP = 1
- PROTO_ALL = 0
-
- # port ranges
- PORTS_ALL = -1
- PORTS_RANGE = 0
- PORTS_RANGE_2 = 1
- udp_sport_from = 10
- udp_sport_to = udp_sport_from + 5
- udp_dport_from = 20000
- udp_dport_to = udp_dport_from + 5000
- tcp_sport_from = 30
- tcp_sport_to = tcp_sport_from + 5
- tcp_dport_from = 40000
- tcp_dport_to = tcp_dport_from + 5000
-
- udp_sport_from_2 = 90
- udp_sport_to_2 = udp_sport_from_2 + 5
- udp_dport_from_2 = 30000
- udp_dport_to_2 = udp_dport_from_2 + 5000
- tcp_sport_from_2 = 130
- tcp_sport_to_2 = tcp_sport_from_2 + 5
- tcp_dport_from_2 = 20000
- tcp_dport_to_2 = tcp_dport_from_2 + 5000
-
- icmp4_type = 8 # echo request
- icmp4_code = 3
- icmp6_type = 128 # echo request
- icmp6_code = 3
-
- icmp4_type_2 = 8
- icmp4_code_from_2 = 5
- icmp4_code_to_2 = 20
- icmp6_type_2 = 128
- icmp6_code_from_2 = 8
- icmp6_code_to_2 = 42
-
- # Test variables
- bd_id = 1
-
- @classmethod
- def setUpClass(cls):
- """
- Perform standard class setup (defined by class method setUpClass in
- class VppTestCase) before running the test case, set test case related
- variables and configure VPP.
- """
- super(TestACLplugin, cls).setUpClass()
-
- try:
- # Create 2 pg interfaces
- cls.create_pg_interfaces(range(2))
-
- # Packet flows mapping pg0 -> pg1, pg2 etc.
- cls.flows = dict()
- cls.flows[cls.pg0] = [cls.pg1]
-
- # Packet sizes
- cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
-
- # Create BD with MAC learning and unknown unicast flooding disabled
- # and put interfaces to this BD
- cls.vapi.bridge_domain_add_del(bd_id=cls.bd_id, uu_flood=1,
- learn=1)
- for pg_if in cls.pg_interfaces:
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id)
-
- # Set up all interfaces
- for i in cls.pg_interfaces:
- i.admin_up()
-
- # Mapping between packet-generator index and lists of test hosts
- cls.hosts_by_pg_idx = dict()
- for pg_if in cls.pg_interfaces:
- cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
-
- # Create list of deleted hosts
- cls.deleted_hosts_by_pg_idx = dict()
- for pg_if in cls.pg_interfaces:
- cls.deleted_hosts_by_pg_idx[pg_if.sw_if_index] = []
-
- # warm-up the mac address tables
- # self.warmup_test()
- count = 16
- start = 0
- n_int = len(cls.pg_interfaces)
- macs_per_if = count / n_int
- i = -1
- for pg_if in cls.pg_interfaces:
- i += 1
- start_nr = macs_per_if * i + start
- end_nr = count + start if i == (n_int - 1) \
- else macs_per_if * (i + 1) + start
- hosts = cls.hosts_by_pg_idx[pg_if.sw_if_index]
- for j in range(start_nr, end_nr):
- host = Host(
- "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
- "172.17.1%02x.%u" % (pg_if.sw_if_index, j),
- "2017:dead:%02x::%u" % (pg_if.sw_if_index, j))
- hosts.append(host)
-
- except Exception:
- super(TestACLplugin, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestACLplugin, cls).tearDownClass()
-
- def setUp(self):
- super(TestACLplugin, self).setUp()
- self.reset_packet_infos()
-
- def tearDown(self):
- """
- Show various debug prints after each test.
- """
- super(TestACLplugin, self).tearDown()
-
- def show_commands_at_teardown(self):
- cli = "show vlib graph l2-input-feat-arc"
- self.logger.info(self.vapi.ppcli(cli))
- cli = "show vlib graph l2-input-feat-arc-end"
- self.logger.info(self.vapi.ppcli(cli))
- cli = "show vlib graph l2-output-feat-arc"
- self.logger.info(self.vapi.ppcli(cli))
- cli = "show vlib graph l2-output-feat-arc-end"
- self.logger.info(self.vapi.ppcli(cli))
- self.logger.info(self.vapi.ppcli("show l2fib verbose"))
- self.logger.info(self.vapi.ppcli("show acl-plugin acl"))
- self.logger.info(self.vapi.ppcli("show acl-plugin interface"))
- self.logger.info(self.vapi.ppcli("show acl-plugin tables"))
- self.logger.info(self.vapi.ppcli("show bridge-domain %s detail"
- % self.bd_id))
-
- def create_rule(self, ip=0, permit_deny=0, ports=PORTS_ALL, proto=-1,
- s_prefix=0, s_ip='\x00\x00\x00\x00',
- d_prefix=0, d_ip='\x00\x00\x00\x00'):
- if proto == -1:
- return
- if ports == self.PORTS_ALL:
- sport_from = 0
- dport_from = 0
- sport_to = 65535 if proto != 1 and proto != 58 else 255
- dport_to = sport_to
- elif ports == self.PORTS_RANGE:
- if proto == 1:
- sport_from = self.icmp4_type
- sport_to = self.icmp4_type
- dport_from = self.icmp4_code
- dport_to = self.icmp4_code
- elif proto == 58:
- sport_from = self.icmp6_type
- sport_to = self.icmp6_type
- dport_from = self.icmp6_code
- dport_to = self.icmp6_code
- elif proto == self.proto[self.IP][self.TCP]:
- sport_from = self.tcp_sport_from
- sport_to = self.tcp_sport_to
- dport_from = self.tcp_dport_from
- dport_to = self.tcp_dport_to
- elif proto == self.proto[self.IP][self.UDP]:
- sport_from = self.udp_sport_from
- sport_to = self.udp_sport_to
- dport_from = self.udp_dport_from
- dport_to = self.udp_dport_to
- elif ports == self.PORTS_RANGE_2:
- if proto == 1:
- sport_from = self.icmp4_type_2
- sport_to = self.icmp4_type_2
- dport_from = self.icmp4_code_from_2
- dport_to = self.icmp4_code_to_2
- elif proto == 58:
- sport_from = self.icmp6_type_2
- sport_to = self.icmp6_type_2
- dport_from = self.icmp6_code_from_2
- dport_to = self.icmp6_code_to_2
- elif proto == self.proto[self.IP][self.TCP]:
- sport_from = self.tcp_sport_from_2
- sport_to = self.tcp_sport_to_2
- dport_from = self.tcp_dport_from_2
- dport_to = self.tcp_dport_to_2
- elif proto == self.proto[self.IP][self.UDP]:
- sport_from = self.udp_sport_from_2
- sport_to = self.udp_sport_to_2
- dport_from = self.udp_dport_from_2
- dport_to = self.udp_dport_to_2
- else:
- sport_from = ports
- sport_to = ports
- dport_from = ports
- dport_to = ports
-
- rule = ({'is_permit': permit_deny, 'is_ipv6': ip, 'proto': proto,
- 'srcport_or_icmptype_first': sport_from,
- 'srcport_or_icmptype_last': sport_to,
- 'src_ip_prefix_len': s_prefix,
- 'src_ip_addr': s_ip,
- 'dstport_or_icmpcode_first': dport_from,
- 'dstport_or_icmpcode_last': dport_to,
- 'dst_ip_prefix_len': d_prefix,
- 'dst_ip_addr': d_ip})
- return rule
-
- def apply_rules(self, rules, tag=b''):
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=rules,
- tag=tag)
- self.logger.info("Dumped ACL: " + str(
- self.vapi.acl_dump(reply.acl_index)))
- # Apply a ACL on the interface as inbound
- for i in self.pg_interfaces:
- self.vapi.acl_interface_set_acl_list(sw_if_index=i.sw_if_index,
- n_input=1,
- acls=[reply.acl_index])
- return reply.acl_index
-
- def apply_rules_to(self, rules, tag=b'', sw_if_index=0xFFFFFFFF):
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=rules,
- tag=tag)
- self.logger.info("Dumped ACL: " + str(
- self.vapi.acl_dump(reply.acl_index)))
- # Apply a ACL on the interface as inbound
- self.vapi.acl_interface_set_acl_list(sw_if_index=sw_if_index,
- n_input=1,
- acls=[reply.acl_index])
- return reply.acl_index
-
- def etype_whitelist(self, whitelist, n_input):
- # Apply whitelists on all the interfaces
- for i in self.pg_interfaces:
- # checkstyle can't read long names. Help them.
- fun = self.vapi.acl_interface_set_etype_whitelist
- fun(sw_if_index=i.sw_if_index, n_input=n_input,
- whitelist=whitelist)
- return
-
- def create_upper_layer(self, packet_index, proto, ports=0):
- p = self.proto_map[proto]
- if p == 'UDP':
- if ports == 0:
- return UDP(sport=random.randint(self.udp_sport_from,
- self.udp_sport_to),
- dport=random.randint(self.udp_dport_from,
- self.udp_dport_to))
- else:
- return UDP(sport=ports, dport=ports)
- elif p == 'TCP':
- if ports == 0:
- return TCP(sport=random.randint(self.tcp_sport_from,
- self.tcp_sport_to),
- dport=random.randint(self.tcp_dport_from,
- self.tcp_dport_to))
- else:
- return TCP(sport=ports, dport=ports)
- return ''
-
- def create_stream(self, src_if, packet_sizes, traffic_type=0, ipv6=0,
- proto=-1, ports=0, fragments=False,
- pkt_raw=True, etype=-1):
- """
- Create input packet stream for defined interface using hosts or
- deleted_hosts list.
-
- :param object src_if: Interface to create packet stream for.
- :param list packet_sizes: List of required packet sizes.
- :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
- :return: Stream of packets.
- """
- pkts = []
- if self.flows.__contains__(src_if):
- src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
- for dst_if in self.flows[src_if]:
- dst_hosts = self.hosts_by_pg_idx[dst_if.sw_if_index]
- n_int = len(dst_hosts) * len(src_hosts)
- for i in range(0, n_int):
- dst_host = dst_hosts[i / len(src_hosts)]
- src_host = src_hosts[i % len(src_hosts)]
- pkt_info = self.create_packet_info(src_if, dst_if)
- if ipv6 == 1:
- pkt_info.ip = 1
- elif ipv6 == 0:
- pkt_info.ip = 0
- else:
- pkt_info.ip = random.choice([0, 1])
- if proto == -1:
- pkt_info.proto = random.choice(self.proto[self.IP])
- else:
- pkt_info.proto = proto
- payload = self.info_to_payload(pkt_info)
- p = Ether(dst=dst_host.mac, src=src_host.mac)
- if etype > 0:
- p = Ether(dst=dst_host.mac,
- src=src_host.mac,
- type=etype)
- if pkt_info.ip:
- p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
- if fragments:
- p /= IPv6ExtHdrFragment(offset=64, m=1)
- else:
- if fragments:
- p /= IP(src=src_host.ip4, dst=dst_host.ip4,
- flags=1, frag=64)
- else:
- p /= IP(src=src_host.ip4, dst=dst_host.ip4)
- if traffic_type == self.ICMP:
- if pkt_info.ip:
- p /= ICMPv6EchoRequest(type=self.icmp6_type,
- code=self.icmp6_code)
- else:
- p /= ICMP(type=self.icmp4_type,
- code=self.icmp4_code)
- else:
- p /= self.create_upper_layer(i, pkt_info.proto, ports)
- if pkt_raw:
- p /= Raw(payload)
- pkt_info.data = p.copy()
- if pkt_raw:
- size = random.choice(packet_sizes)
- self.extend_packet(p, size)
- pkts.append(p)
- return pkts
-
- def verify_capture(self, pg_if, capture,
- traffic_type=0, ip_type=0, etype=-1):
- """
- Verify captured input packet stream for defined interface.
-
- :param object pg_if: Interface to verify captured packet stream for.
- :param list capture: Captured packet stream.
- :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
- """
- last_info = dict()
- for i in self.pg_interfaces:
- last_info[i.sw_if_index] = None
- dst_sw_if_index = pg_if.sw_if_index
- for packet in capture:
- if etype > 0:
- if packet[Ether].type != etype:
- self.logger.error(ppp("Unexpected ethertype in packet:",
- packet))
- else:
- continue
- try:
- # Raw data for ICMPv6 are stored in ICMPv6EchoRequest.data
- if traffic_type == self.ICMP and ip_type == self.IPV6:
- payload_info = self.payload_to_info(
- packet[ICMPv6EchoRequest], 'data')
- payload = packet[ICMPv6EchoRequest]
- else:
- payload_info = self.payload_to_info(packet[Raw])
- payload = packet[self.proto_map[payload_info.proto]]
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- if ip_type != 0:
- self.assertEqual(payload_info.ip, ip_type)
- if traffic_type == self.ICMP:
- try:
- if payload_info.ip == 0:
- self.assertEqual(payload.type, self.icmp4_type)
- self.assertEqual(payload.code, self.icmp4_code)
- else:
- self.assertEqual(payload.type, self.icmp6_type)
- self.assertEqual(payload.code, self.icmp6_code)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
- else:
- try:
- ip_version = IPv6 if payload_info.ip == 1 else IP
-
- ip = packet[ip_version]
- packet_index = payload_info.index
-
- self.assertEqual(payload_info.dst, dst_sw_if_index)
- self.logger.debug("Got packet on port %s: src=%u (id=%u)" %
- (pg_if.name, payload_info.src,
- packet_index))
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- self.assertTrue(next_info is not None)
- self.assertEqual(packet_index, next_info.index)
- saved_packet = next_info.data
- # Check standard fields
- self.assertEqual(ip.src, saved_packet[ip_version].src)
- self.assertEqual(ip.dst, saved_packet[ip_version].dst)
- p = self.proto_map[payload_info.proto]
- if p == 'TCP':
- tcp = packet[TCP]
- self.assertEqual(tcp.sport, saved_packet[
- TCP].sport)
- self.assertEqual(tcp.dport, saved_packet[
- TCP].dport)
- elif p == 'UDP':
- udp = packet[UDP]
- self.assertEqual(udp.sport, saved_packet[
- UDP].sport)
- self.assertEqual(udp.dport, saved_packet[
- UDP].dport)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:",
- packet))
- raise
- for i in self.pg_interfaces:
- remaining_packet = self.get_next_packet_info_for_interface2(
- i, dst_sw_if_index, last_info[i.sw_if_index])
- self.assertTrue(
- remaining_packet is None,
- "Port %u: Packet expected from source %u didn't arrive" %
- (dst_sw_if_index, i.sw_if_index))
-
- def run_traffic_no_check(self):
- # Test
- # Create incoming packet streams for packet-generator interfaces
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes)
- if len(pkts) > 0:
- i.add_stream(pkts)
-
- # Enable packet capture and start packet sending
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- def run_verify_test(self, traffic_type=0, ip_type=0, proto=-1, ports=0,
- frags=False, pkt_raw=True, etype=-1):
- # Test
- # Create incoming packet streams for packet-generator interfaces
- pkts_cnt = 0
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes,
- traffic_type, ip_type, proto, ports,
- frags, pkt_raw, etype)
- if len(pkts) > 0:
- i.add_stream(pkts)
- pkts_cnt += len(pkts)
-
- # Enable packet capture and start packet sendingself.IPV
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.logger.info("sent packets count: %d" % pkts_cnt)
-
- # Verify
- # Verify outgoing packet streams per packet-generator interface
- for src_if in self.pg_interfaces:
- if self.flows.__contains__(src_if):
- for dst_if in self.flows[src_if]:
- capture = dst_if.get_capture(pkts_cnt)
- self.logger.info("Verifying capture on interface %s" %
- dst_if.name)
- self.verify_capture(dst_if, capture,
- traffic_type, ip_type, etype)
-
- def run_verify_negat_test(self, traffic_type=0, ip_type=0, proto=-1,
- ports=0, frags=False, etype=-1):
- # Test
- pkts_cnt = 0
- self.reset_packet_infos()
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes,
- traffic_type, ip_type, proto, ports,
- frags, True, etype)
- if len(pkts) > 0:
- i.add_stream(pkts)
- pkts_cnt += len(pkts)
-
- # Enable packet capture and start packet sending
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.logger.info("sent packets count: %d" % pkts_cnt)
-
- # Verify
- # Verify outgoing packet streams per packet-generator interface
- for src_if in self.pg_interfaces:
- if self.flows.__contains__(src_if):
- for dst_if in self.flows[src_if]:
- self.logger.info("Verifying capture on interface %s" %
- dst_if.name)
- capture = dst_if.get_capture(0)
- self.assertEqual(len(capture), 0)
-
- def test_0000_warmup_test(self):
- """ ACL plugin version check; learn MACs
- """
- reply = self.vapi.papi.acl_plugin_get_version()
- self.assertEqual(reply.major, 1)
- self.logger.info("Working with ACL plugin version: %d.%d" % (
- reply.major, reply.minor))
- # minor version changes are non breaking
- # self.assertEqual(reply.minor, 0)
-
- def test_0001_acl_create(self):
- """ ACL create/delete test
- """
-
- self.logger.info("ACLP_TEST_START_0001")
- # Add an ACL
- r = [{'is_permit': 1, 'is_ipv6': 0, 'proto': 17,
- 'srcport_or_icmptype_first': 1234,
- 'srcport_or_icmptype_last': 1235,
- 'src_ip_prefix_len': 0,
- 'src_ip_addr': b'\x00\x00\x00\x00',
- 'dstport_or_icmpcode_first': 1234,
- 'dstport_or_icmpcode_last': 1234,
- 'dst_ip_addr': b'\x00\x00\x00\x00',
- 'dst_ip_prefix_len': 0}]
- # Test 1: add a new ACL
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r,
- tag=b"permit 1234")
- self.assertEqual(reply.retval, 0)
- # The very first ACL gets #0
- self.assertEqual(reply.acl_index, 0)
- first_acl = reply.acl_index
- rr = self.vapi.acl_dump(reply.acl_index)
- self.logger.info("Dumped ACL: " + str(rr))
- self.assertEqual(len(rr), 1)
- # We should have the same number of ACL entries as we had asked
- self.assertEqual(len(rr[0].r), len(r))
- # The rules should be the same. But because the submitted and returned
- # are different types, we need to iterate over rules and keys to get
- # to basic values.
- for i_rule in range(0, len(r) - 1):
- for rule_key in r[i_rule]:
- self.assertEqual(rr[0].r[i_rule][rule_key],
- r[i_rule][rule_key])
-
- # Add a deny-1234 ACL
- r_deny = [{'is_permit': 0, 'is_ipv6': 0, 'proto': 17,
- 'srcport_or_icmptype_first': 1234,
- 'srcport_or_icmptype_last': 1235,
- 'src_ip_prefix_len': 0,
- 'src_ip_addr': b'\x00\x00\x00\x00',
- 'dstport_or_icmpcode_first': 1234,
- 'dstport_or_icmpcode_last': 1234,
- 'dst_ip_addr': b'\x00\x00\x00\x00',
- 'dst_ip_prefix_len': 0},
- {'is_permit': 1, 'is_ipv6': 0, 'proto': 17,
- 'srcport_or_icmptype_first': 0,
- 'srcport_or_icmptype_last': 0,
- 'src_ip_prefix_len': 0,
- 'src_ip_addr': b'\x00\x00\x00\x00',
- 'dstport_or_icmpcode_first': 0,
- 'dstport_or_icmpcode_last': 0,
- 'dst_ip_addr': b'\x00\x00\x00\x00',
- 'dst_ip_prefix_len': 0}]
-
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r_deny,
- tag=b"deny 1234;permit all")
- self.assertEqual(reply.retval, 0)
- # The second ACL gets #1
- self.assertEqual(reply.acl_index, 1)
- second_acl = reply.acl_index
-
- # Test 2: try to modify a nonexistent ACL
- reply = self.vapi.acl_add_replace(acl_index=432, r=r,
- tag=b"FFFF:FFFF", expected_retval=-6)
- self.assertEqual(reply.retval, -6)
- # The ACL number should pass through
- self.assertEqual(reply.acl_index, 432)
- # apply an ACL on an interface inbound, try to delete ACL, must fail
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=1,
- acls=[first_acl])
- reply = self.vapi.acl_del(acl_index=first_acl, expected_retval=-142)
- # Unapply an ACL and then try to delete it - must be ok
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=0,
- acls=[])
- reply = self.vapi.acl_del(acl_index=first_acl, expected_retval=0)
-
- # apply an ACL on an interface outbound, try to delete ACL, must fail
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=0,
- acls=[second_acl])
- reply = self.vapi.acl_del(acl_index=second_acl, expected_retval=-143)
- # Unapply the ACL and then try to delete it - must be ok
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=0,
- acls=[])
- reply = self.vapi.acl_del(acl_index=second_acl, expected_retval=0)
-
- # try to apply a nonexistent ACL - must fail
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=1,
- acls=[first_acl],
- expected_retval=-6)
-
- self.logger.info("ACLP_TEST_FINISH_0001")
-
- def test_0002_acl_permit_apply(self):
- """ permit ACL apply test
- """
- self.logger.info("ACLP_TEST_START_0002")
-
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- 0, self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- 0, self.proto[self.IP][self.TCP]))
-
- # Apply rules
- acl_idx = self.apply_rules(rules, b"permit per-flow")
-
- # enable counters
- reply = self.vapi.papi.acl_stats_intf_counters_enable(enable=1)
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- matches = self.statistics.get_counter('/acl/%d/matches' % acl_idx)
- self.logger.info("stat segment counters: %s" % repr(matches))
- cli = "show acl-plugin acl"
- self.logger.info(self.vapi.ppcli(cli))
- cli = "show acl-plugin tables"
- self.logger.info(self.vapi.ppcli(cli))
-
- total_hits = matches[0][0]['packets'] + matches[0][1]['packets']
- self.assertEqual(total_hits, 64)
-
- # disable counters
- reply = self.vapi.papi.acl_stats_intf_counters_enable(enable=0)
-
- self.logger.info("ACLP_TEST_FINISH_0002")
-
- def test_0003_acl_deny_apply(self):
- """ deny ACL apply test
- """
- self.logger.info("ACLP_TEST_START_0003")
- # Add a deny-flows ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY,
- self.PORTS_ALL, self.proto[self.IP][self.UDP]))
- # Permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- acl_idx = self.apply_rules(rules, b"deny per-flow;permit all")
-
- # enable counters
- reply = self.vapi.papi.acl_stats_intf_counters_enable(enable=1)
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPV4,
- self.proto[self.IP][self.UDP])
-
- matches = self.statistics.get_counter('/acl/%d/matches' % acl_idx)
- self.logger.info("stat segment counters: %s" % repr(matches))
- cli = "show acl-plugin acl"
- self.logger.info(self.vapi.ppcli(cli))
- cli = "show acl-plugin tables"
- self.logger.info(self.vapi.ppcli(cli))
- self.assertEqual(matches[0][0]['packets'], 64)
- # disable counters
- reply = self.vapi.papi.acl_stats_intf_counters_enable(enable=0)
- self.logger.info("ACLP_TEST_FINISH_0003")
- # self.assertEqual(, 0)
-
- def test_0004_vpp624_permit_icmpv4(self):
- """ VPP_624 permit ICMPv4
- """
- self.logger.info("ACLP_TEST_START_0004")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.ICMP][self.ICMPv4]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit icmpv4")
-
- # Traffic should still pass
- self.run_verify_test(self.ICMP, self.IPV4,
- self.proto[self.ICMP][self.ICMPv4])
-
- self.logger.info("ACLP_TEST_FINISH_0004")
-
- def test_0005_vpp624_permit_icmpv6(self):
- """ VPP_624 permit ICMPv6
- """
- self.logger.info("ACLP_TEST_START_0005")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.ICMP][self.ICMPv6]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit icmpv6")
-
- # Traffic should still pass
- self.run_verify_test(self.ICMP, self.IPV6,
- self.proto[self.ICMP][self.ICMPv6])
-
- self.logger.info("ACLP_TEST_FINISH_0005")
-
- def test_0006_vpp624_deny_icmpv4(self):
- """ VPP_624 deny ICMPv4
- """
- self.logger.info("ACLP_TEST_START_0006")
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE,
- self.proto[self.ICMP][self.ICMPv4]))
- # permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny icmpv4")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.ICMP, self.IPV4, 0)
-
- self.logger.info("ACLP_TEST_FINISH_0006")
-
- def test_0007_vpp624_deny_icmpv6(self):
- """ VPP_624 deny ICMPv6
- """
- self.logger.info("ACLP_TEST_START_0007")
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE,
- self.proto[self.ICMP][self.ICMPv6]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny icmpv6")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.ICMP, self.IPV6, 0)
-
- self.logger.info("ACLP_TEST_FINISH_0007")
-
- def test_0008_tcp_permit_v4(self):
- """ permit TCPv4
- """
- self.logger.info("ACLP_TEST_START_0008")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0008")
-
- def test_0009_tcp_permit_v6(self):
- """ permit TCPv6
- """
- self.logger.info("ACLP_TEST_START_0009")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip6 tcp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6, self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0008")
-
- def test_0010_udp_permit_v4(self):
- """ permit UDPv4
- """
- self.logger.info("ACLP_TEST_START_0010")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv udp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0010")
-
- def test_0011_udp_permit_v6(self):
- """ permit UDPv6
- """
- self.logger.info("ACLP_TEST_START_0011")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip6 udp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6, self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0011")
-
- def test_0012_tcp_deny(self):
- """ deny TCPv4/v6
- """
- self.logger.info("ACLP_TEST_START_0012")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 tcp")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0012")
-
- def test_0013_udp_deny(self):
- """ deny UDPv4/v6
- """
- self.logger.info("ACLP_TEST_START_0013")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 udp")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0013")
-
- def test_0014_acl_dump(self):
- """ verify add/dump acls
- """
- self.logger.info("ACLP_TEST_START_0014")
-
- r = [[self.IPV4, self.PERMIT, 1234, self.proto[self.IP][self.TCP]],
- [self.IPV4, self.PERMIT, 2345, self.proto[self.IP][self.UDP]],
- [self.IPV4, self.PERMIT, 0, self.proto[self.IP][self.TCP]],
- [self.IPV4, self.PERMIT, 0, self.proto[self.IP][self.UDP]],
- [self.IPV4, self.PERMIT, 5, self.proto[self.ICMP][self.ICMPv4]],
- [self.IPV6, self.PERMIT, 4321, self.proto[self.IP][self.TCP]],
- [self.IPV6, self.PERMIT, 5432, self.proto[self.IP][self.UDP]],
- [self.IPV6, self.PERMIT, 0, self.proto[self.IP][self.TCP]],
- [self.IPV6, self.PERMIT, 0, self.proto[self.IP][self.UDP]],
- [self.IPV6, self.PERMIT, 6, self.proto[self.ICMP][self.ICMPv6]],
- [self.IPV4, self.DENY, self.PORTS_ALL, 0],
- [self.IPV4, self.DENY, 1234, self.proto[self.IP][self.TCP]],
- [self.IPV4, self.DENY, 2345, self.proto[self.IP][self.UDP]],
- [self.IPV4, self.DENY, 5, self.proto[self.ICMP][self.ICMPv4]],
- [self.IPV6, self.DENY, 4321, self.proto[self.IP][self.TCP]],
- [self.IPV6, self.DENY, 5432, self.proto[self.IP][self.UDP]],
- [self.IPV6, self.DENY, 6, self.proto[self.ICMP][self.ICMPv6]],
- [self.IPV6, self.DENY, self.PORTS_ALL, 0]
- ]
-
- # Add and verify new ACLs
- rules = []
- for i in range(len(r)):
- rules.append(self.create_rule(r[i][0], r[i][1], r[i][2], r[i][3]))
-
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=rules)
- result = self.vapi.acl_dump(reply.acl_index)
-
- i = 0
- for drules in result:
- for dr in drules.r:
- self.assertEqual(dr.is_ipv6, r[i][0])
- self.assertEqual(dr.is_permit, r[i][1])
- self.assertEqual(dr.proto, r[i][3])
-
- if r[i][2] > 0:
- self.assertEqual(dr.srcport_or_icmptype_first, r[i][2])
- else:
- if r[i][2] < 0:
- self.assertEqual(dr.srcport_or_icmptype_first, 0)
- self.assertEqual(dr.srcport_or_icmptype_last, 65535)
- else:
- if dr.proto == self.proto[self.IP][self.TCP]:
- self.assertGreater(dr.srcport_or_icmptype_first,
- self.tcp_sport_from-1)
- self.assertLess(dr.srcport_or_icmptype_first,
- self.tcp_sport_to+1)
- self.assertGreater(dr.dstport_or_icmpcode_last,
- self.tcp_dport_from-1)
- self.assertLess(dr.dstport_or_icmpcode_last,
- self.tcp_dport_to+1)
- elif dr.proto == self.proto[self.IP][self.UDP]:
- self.assertGreater(dr.srcport_or_icmptype_first,
- self.udp_sport_from-1)
- self.assertLess(dr.srcport_or_icmptype_first,
- self.udp_sport_to+1)
- self.assertGreater(dr.dstport_or_icmpcode_last,
- self.udp_dport_from-1)
- self.assertLess(dr.dstport_or_icmpcode_last,
- self.udp_dport_to+1)
- i += 1
-
- self.logger.info("ACLP_TEST_FINISH_0014")
-
- def test_0015_tcp_permit_port_v4(self):
- """ permit single TCPv4
- """
- self.logger.info("ACLP_TEST_START_0015")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, port,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip4 tcp %d" % port)
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4,
- self.proto[self.IP][self.TCP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0015")
-
- def test_0016_udp_permit_port_v4(self):
- """ permit single UDPv4
- """
- self.logger.info("ACLP_TEST_START_0016")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, port,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip4 tcp %d" % port)
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4,
- self.proto[self.IP][self.UDP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0016")
-
- def test_0017_tcp_permit_port_v6(self):
- """ permit single TCPv6
- """
- self.logger.info("ACLP_TEST_START_0017")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, port,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip4 tcp %d" % port)
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6,
- self.proto[self.IP][self.TCP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0017")
-
- def test_0018_udp_permit_port_v6(self):
- """ permit single UPPv6
- """
- self.logger.info("ACLP_TEST_START_0018")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, port,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip4 tcp %d" % port)
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6,
- self.proto[self.IP][self.UDP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0018")
-
- def test_0019_udp_deny_port(self):
- """ deny single TCPv4/v6
- """
- self.logger.info("ACLP_TEST_START_0019")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, port,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, port,
- self.proto[self.IP][self.TCP]))
- # Permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 udp %d" % port)
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.TCP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0019")
-
- def test_0020_udp_deny_port(self):
- """ deny single UDPv4/v6
- """
- self.logger.info("ACLP_TEST_START_0020")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, port,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, port,
- self.proto[self.IP][self.UDP]))
- # Permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 udp %d" % port)
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.UDP], port)
-
- self.logger.info("ACLP_TEST_FINISH_0020")
-
- def test_0021_udp_deny_port_verify_fragment_deny(self):
- """ deny single UDPv4/v6, permit ip any, verify non-initial fragment
- blocked
- """
- self.logger.info("ACLP_TEST_START_0021")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, port,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, port,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 udp %d" % port)
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.UDP], port, True)
-
- self.logger.info("ACLP_TEST_FINISH_0021")
-
- def test_0022_zero_length_udp_ipv4(self):
- """ VPP-687 zero length udp ipv4 packet"""
- self.logger.info("ACLP_TEST_START_0022")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT, port,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(
- self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit empty udp ip4 %d" % port)
-
- # Traffic should still pass
- # Create incoming packet streams for packet-generator interfaces
- pkts_cnt = 0
- pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes,
- self.IP, self.IPV4,
- self.proto[self.IP][self.UDP], port,
- False, False)
- if len(pkts) > 0:
- self.pg0.add_stream(pkts)
- pkts_cnt += len(pkts)
-
- # Enable packet capture and start packet sendingself.IPV
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.pg1.get_capture(pkts_cnt)
-
- self.logger.info("ACLP_TEST_FINISH_0022")
-
- def test_0023_zero_length_udp_ipv6(self):
- """ VPP-687 zero length udp ipv6 packet"""
- self.logger.info("ACLP_TEST_START_0023")
-
- port = random.randint(0, 65535)
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.PERMIT, port,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit empty udp ip6 %d" % port)
-
- # Traffic should still pass
- # Create incoming packet streams for packet-generator interfaces
- pkts_cnt = 0
- pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes,
- self.IP, self.IPV6,
- self.proto[self.IP][self.UDP], port,
- False, False)
- if len(pkts) > 0:
- self.pg0.add_stream(pkts)
- pkts_cnt += len(pkts)
-
- # Enable packet capture and start packet sendingself.IPV
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Verify outgoing packet streams per packet-generator interface
- self.pg1.get_capture(pkts_cnt)
-
- self.logger.info("ACLP_TEST_FINISH_0023")
-
- def test_0108_tcp_permit_v4(self):
- """ permit TCPv4 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0108")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0108")
-
- def test_0109_tcp_permit_v6(self):
- """ permit TCPv6 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0109")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV6, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip6 tcp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6, self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0109")
-
- def test_0110_udp_permit_v4(self):
- """ permit UDPv4 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0110")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 udp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0110")
-
- def test_0111_udp_permit_v6(self):
- """ permit UDPv6 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0111")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ip6 udp")
-
- # Traffic should still pass
- self.run_verify_test(self.IP, self.IPV6, self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0111")
-
- def test_0112_tcp_deny(self):
- """ deny TCPv4/v6 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0112")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 tcp")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.TCP])
-
- self.logger.info("ACLP_TEST_FINISH_0112")
-
- def test_0113_udp_deny(self):
- """ deny UDPv4/v6 + non-match range
- """
- self.logger.info("ACLP_TEST_START_0113")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_RANGE_2,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_RANGE_2,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- rules.append(self.create_rule(self.IPV6, self.DENY, self.PORTS_RANGE,
- self.proto[self.IP][self.UDP]))
- # permit ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.PERMIT,
- self.PORTS_ALL, 0))
- rules.append(self.create_rule(self.IPV6, self.PERMIT,
- self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"deny ip4/ip6 udp")
-
- # Traffic should not pass
- self.run_verify_negat_test(self.IP, self.IPRANDOM,
- self.proto[self.IP][self.UDP])
-
- self.logger.info("ACLP_TEST_FINISH_0113")
-
- def test_0300_tcp_permit_v4_etype_aaaa(self):
- """ permit TCPv4, send 0xAAAA etype
- """
- self.logger.info("ACLP_TEST_START_0300")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # Traffic should still pass also for an odd ethertype
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
- 0, False, True, 0xaaaa)
- self.logger.info("ACLP_TEST_FINISH_0300")
-
- def test_0305_tcp_permit_v4_etype_blacklist_aaaa(self):
- """ permit TCPv4, whitelist 0x0BBB ethertype, send 0xAAAA-blocked
- """
- self.logger.info("ACLP_TEST_START_0305")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # whitelist the 0xbbbb etype - so the 0xaaaa should be blocked
- self.etype_whitelist([0xbbb], 1)
-
- # The oddball ethertype should be blocked
- self.run_verify_negat_test(self.IP, self.IPV4,
- self.proto[self.IP][self.TCP],
- 0, False, 0xaaaa)
-
- # remove the whitelist
- self.etype_whitelist([], 0)
-
- self.logger.info("ACLP_TEST_FINISH_0305")
-
- def test_0306_tcp_permit_v4_etype_blacklist_aaaa(self):
- """ permit TCPv4, whitelist 0x0BBB ethertype, send 0x0BBB - pass
- """
- self.logger.info("ACLP_TEST_START_0306")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # whitelist the 0xbbbb etype - so the 0xaaaa should be blocked
- self.etype_whitelist([0xbbb], 1)
-
- # The whitelisted traffic, should pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
- 0, False, True, 0x0bbb)
-
- # remove the whitelist, the previously blocked 0xAAAA should pass now
- self.etype_whitelist([], 0)
-
- self.logger.info("ACLP_TEST_FINISH_0306")
-
- def test_0307_tcp_permit_v4_etype_blacklist_aaaa(self):
- """ permit TCPv4, whitelist 0x0BBB, remove, send 0xAAAA - pass
- """
- self.logger.info("ACLP_TEST_START_0307")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # Apply rules
- self.apply_rules(rules, b"permit ipv4 tcp")
-
- # whitelist the 0xbbbb etype - so the 0xaaaa should be blocked
- self.etype_whitelist([0xbbb], 1)
- # remove the whitelist, the previously blocked 0xAAAA should pass now
- self.etype_whitelist([], 0)
-
- # The whitelisted traffic, should pass
- self.run_verify_test(self.IP, self.IPV4, self.proto[self.IP][self.TCP],
- 0, False, True, 0xaaaa)
-
- self.logger.info("ACLP_TEST_FINISH_0306")
-
- def test_0315_del_intf(self):
- """ apply an acl and delete the interface
- """
- self.logger.info("ACLP_TEST_START_0315")
-
- # Add an ACL
- rules = []
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_RANGE_2,
- self.proto[self.IP][self.TCP]))
- rules.append(self.create_rule(self.IPV4, self.PERMIT, self.PORTS_RANGE,
- self.proto[self.IP][self.TCP]))
- # deny ip any any in the end
- rules.append(self.create_rule(self.IPV4, self.DENY, self.PORTS_ALL, 0))
-
- # create an interface
- intf = []
- intf.append(VppLoInterface(self))
-
- # Apply rules
- self.apply_rules_to(rules, b"permit ipv4 tcp", intf[0].sw_if_index)
-
- # Remove the interface
- intf[0].remove_vpp_config()
-
- self.logger.info("ACLP_TEST_FINISH_0315")
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_acl_plugin_conns.py b/test/test_acl_plugin_conns.py
deleted file mode 100644
index 58c44e68262..00000000000
--- a/test/test_acl_plugin_conns.py
+++ /dev/null
@@ -1,411 +0,0 @@
-#!/usr/bin/env python
-""" ACL plugin extended stateful tests """
-
-import unittest
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-from scapy.layers.l2 import Ether
-from scapy.packet import Raw
-from scapy.layers.inet import IP, UDP, TCP
-from scapy.packet import Packet
-from socket import inet_pton, AF_INET, AF_INET6
-from scapy.layers.inet6 import IPv6, ICMPv6Unknown, ICMPv6EchoRequest
-from scapy.layers.inet6 import ICMPv6EchoReply, IPv6ExtHdrRouting
-from scapy.layers.inet6 import IPv6ExtHdrFragment
-from pprint import pprint
-from random import randint
-from util import L4_Conn
-
-
-def to_acl_rule(self, is_permit, wildcard_sport=False):
- p = self
- rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET
- rule_prefix_len = 128 if p.haslayer(IPv6) else 32
- rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP
- rule_l4_sport = p.sport
- rule_l4_dport = p.dport
- if p.haslayer(IPv6):
- rule_l4_proto = p[IPv6].nh
- else:
- rule_l4_proto = p[IP].proto
-
- if wildcard_sport:
- rule_l4_sport_first = 0
- rule_l4_sport_last = 65535
- else:
- rule_l4_sport_first = rule_l4_sport
- rule_l4_sport_last = rule_l4_sport
-
- new_rule = {
- 'is_permit': is_permit,
- 'is_ipv6': p.haslayer(IPv6),
- 'src_ip_addr': inet_pton(rule_family,
- p[rule_l3_layer].src),
- 'src_ip_prefix_len': rule_prefix_len,
- 'dst_ip_addr': inet_pton(rule_family,
- p[rule_l3_layer].dst),
- 'dst_ip_prefix_len': rule_prefix_len,
- 'srcport_or_icmptype_first': rule_l4_sport_first,
- 'srcport_or_icmptype_last': rule_l4_sport_last,
- 'dstport_or_icmpcode_first': rule_l4_dport,
- 'dstport_or_icmpcode_last': rule_l4_dport,
- 'proto': rule_l4_proto,
- }
- return new_rule
-
-Packet.to_acl_rule = to_acl_rule
-
-
-class IterateWithSleep():
- def __init__(self, testcase, n_iters, description, sleep_sec):
- self.curr = 0
- self.testcase = testcase
- self.n_iters = n_iters
- self.sleep_sec = sleep_sec
- self.description = description
-
- def __iter__(self):
- for x in range(0, self.n_iters):
- yield x
- self.testcase.sleep(self.sleep_sec)
-
-
-class Conn(L4_Conn):
- def apply_acls(self, reflect_side, acl_side):
- pkts = []
- pkts.append(self.pkt(0))
- pkts.append(self.pkt(1))
- pkt = pkts[reflect_side]
-
- r = []
- r.append(pkt.to_acl_rule(2, wildcard_sport=True))
- r.append(self.wildcard_rule(0))
- res = self.testcase.vapi.acl_add_replace(0xffffffff, r)
- self.testcase.assert_equal(res.retval, 0, "error adding ACL")
- reflect_acl_index = res.acl_index
-
- r = []
- r.append(self.wildcard_rule(0))
- res = self.testcase.vapi.acl_add_replace(0xffffffff, r)
- self.testcase.assert_equal(res.retval, 0, "error adding deny ACL")
- deny_acl_index = res.acl_index
-
- if reflect_side == acl_side:
- self.testcase.vapi.acl_interface_set_acl_list(
- self.ifs[acl_side].sw_if_index, 1,
- [reflect_acl_index,
- deny_acl_index])
- self.testcase.vapi.acl_interface_set_acl_list(
- self.ifs[1-acl_side].sw_if_index, 0, [])
- else:
- self.testcase.vapi.acl_interface_set_acl_list(
- self.ifs[acl_side].sw_if_index, 1,
- [deny_acl_index,
- reflect_acl_index])
- self.testcase.vapi.acl_interface_set_acl_list(
- self.ifs[1-acl_side].sw_if_index, 0, [])
-
- def wildcard_rule(self, is_permit):
- any_addr = ["0.0.0.0", "::"]
- rule_family = self.address_family
- is_ip6 = 1 if rule_family == AF_INET6 else 0
- new_rule = {
- 'is_permit': is_permit,
- 'is_ipv6': is_ip6,
- 'src_ip_addr': inet_pton(rule_family, any_addr[is_ip6]),
- 'src_ip_prefix_len': 0,
- 'dst_ip_addr': inet_pton(rule_family, any_addr[is_ip6]),
- 'dst_ip_prefix_len': 0,
- 'srcport_or_icmptype_first': 0,
- 'srcport_or_icmptype_last': 65535,
- 'dstport_or_icmpcode_first': 0,
- 'dstport_or_icmpcode_last': 65535,
- 'proto': 0,
- }
- return new_rule
-
-
-@unittest.skipUnless(running_extended_tests, "part of extended tests")
-class ACLPluginConnTestCase(VppTestCase):
- """ ACL plugin connection-oriented extended testcases """
-
- @classmethod
- def setUpClass(cls):
- super(ACLPluginConnTestCase, cls).setUpClass()
- # create pg0 and pg1
- cls.create_pg_interfaces(range(2))
- cmd = "set acl-plugin session table event-trace 1"
- cls.logger.info(cls.vapi.cli(cmd))
- for i in cls.pg_interfaces:
- i.admin_up()
- i.config_ip4()
- i.config_ip6()
- i.resolve_arp()
- i.resolve_ndp()
-
- @classmethod
- def tearDownClass(cls):
- super(ACLPluginConnTestCase, cls).tearDownClass()
-
- def tearDown(self):
- """Run standard test teardown and log various show commands
- """
- super(ACLPluginConnTestCase, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show ip arp"))
- self.logger.info(self.vapi.cli("show ip6 neighbors"))
- self.logger.info(self.vapi.cli("show acl-plugin sessions"))
- self.logger.info(self.vapi.cli("show acl-plugin acl"))
- self.logger.info(self.vapi.cli("show acl-plugin interface"))
- self.logger.info(self.vapi.cli("show acl-plugin tables"))
- self.logger.info(self.vapi.cli("show event-logger all"))
-
- def run_basic_conn_test(self, af, acl_side):
- """ Basic conn timeout test """
- conn1 = Conn(self, self.pg0, self.pg1, af, UDP, 42001, 4242)
- conn1.apply_acls(0, acl_side)
- conn1.send_through(0)
- # the return packets should pass
- conn1.send_through(1)
- # send some packets on conn1, ensure it doesn't go away
- for i in IterateWithSleep(self, 20, "Keep conn active", 0.3):
- conn1.send_through(1)
- # allow the conn to time out
- for i in IterateWithSleep(self, 30, "Wait for timeout", 0.1):
- pass
- # now try to send a packet on the reflected side
- try:
- p2 = conn1.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- self.assert_equal(p2, None, "packet on long-idle conn")
-
- def run_active_conn_test(self, af, acl_side):
- """ Idle connection behind active connection test """
- base = 10000 + 1000*acl_side
- conn1 = Conn(self, self.pg0, self.pg1, af, UDP, base + 1, 2323)
- conn2 = Conn(self, self.pg0, self.pg1, af, UDP, base + 2, 2323)
- conn3 = Conn(self, self.pg0, self.pg1, af, UDP, base + 3, 2323)
- conn1.apply_acls(0, acl_side)
- conn1.send(0)
- conn1.recv(1)
- # create and check that the conn2/3 work
- self.sleep(0.1)
- conn2.send_pingpong(0)
- self.sleep(0.1)
- conn3.send_pingpong(0)
- # send some packets on conn1, keep conn2/3 idle
- for i in IterateWithSleep(self, 20, "Keep conn active", 0.2):
- conn1.send_through(1)
- try:
- p2 = conn2.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- # We should have not received the packet on a long-idle
- # connection, because it should have timed out
- # If it didn't - it is a problem
- self.assert_equal(p2, None, "packet on long-idle conn")
-
- def run_clear_conn_test(self, af, acl_side):
- """ Clear the connections via CLI """
- conn1 = Conn(self, self.pg0, self.pg1, af, UDP, 42001, 4242)
- conn1.apply_acls(0, acl_side)
- conn1.send_through(0)
- # the return packets should pass
- conn1.send_through(1)
- # send some packets on conn1, ensure it doesn't go away
- for i in IterateWithSleep(self, 20, "Keep conn active", 0.3):
- conn1.send_through(1)
- # clear all connections
- self.vapi.ppcli("clear acl-plugin sessions")
- # now try to send a packet on the reflected side
- try:
- p2 = conn1.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- self.assert_equal(p2, None, "packet on supposedly deleted conn")
-
- def run_tcp_transient_setup_conn_test(self, af, acl_side):
- conn1 = Conn(self, self.pg0, self.pg1, af, TCP, 53001, 5151)
- conn1.apply_acls(0, acl_side)
- conn1.send_through(0, 'S')
- # the return packets should pass
- conn1.send_through(1, 'SA')
- # allow the conn to time out
- for i in IterateWithSleep(self, 30, "Wait for timeout", 0.1):
- pass
- # ensure conn times out
- try:
- p2 = conn1.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- self.assert_equal(p2, None, "packet on supposedly deleted conn")
-
- def run_tcp_established_conn_test(self, af, acl_side):
- conn1 = Conn(self, self.pg0, self.pg1, af, TCP, 53002, 5052)
- conn1.apply_acls(0, acl_side)
- conn1.send_through(0, 'S')
- # the return packets should pass
- conn1.send_through(1, 'SA')
- # complete the threeway handshake
- # (NB: sequence numbers not tracked, so not set!)
- conn1.send_through(0, 'A')
- # allow the conn to time out if it's in embryonic timer
- for i in IterateWithSleep(self, 30, "Wait for transient timeout", 0.1):
- pass
- # Try to send the packet from the "forbidden" side - it must pass
- conn1.send_through(1, 'A')
- # ensure conn times out for real
- for i in IterateWithSleep(self, 130, "Wait for timeout", 0.1):
- pass
- try:
- p2 = conn1.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- self.assert_equal(p2, None, "packet on supposedly deleted conn")
-
- def run_tcp_transient_teardown_conn_test(self, af, acl_side):
- conn1 = Conn(self, self.pg0, self.pg1, af, TCP, 53002, 5052)
- conn1.apply_acls(0, acl_side)
- conn1.send_through(0, 'S')
- # the return packets should pass
- conn1.send_through(1, 'SA')
- # complete the threeway handshake
- # (NB: sequence numbers not tracked, so not set!)
- conn1.send_through(0, 'A')
- # allow the conn to time out if it's in embryonic timer
- for i in IterateWithSleep(self, 30, "Wait for transient timeout", 0.1):
- pass
- # Try to send the packet from the "forbidden" side - it must pass
- conn1.send_through(1, 'A')
- # Send the FIN to bounce the session out of established
- conn1.send_through(1, 'FA')
- # If conn landed on transient timer it will time out here
- for i in IterateWithSleep(self, 30, "Wait for transient timeout", 0.1):
- pass
- # Now it should have timed out already
- try:
- p2 = conn1.send_through(1).command()
- except:
- # If we asserted while waiting, it's good.
- # the conn should have timed out.
- p2 = None
- self.assert_equal(p2, None, "packet on supposedly deleted conn")
-
- def test_0000_conn_prepare_test(self):
- """ Prepare the settings """
- self.vapi.ppcli("set acl-plugin session timeout udp idle 1")
-
- def test_0001_basic_conn_test(self):
- """ IPv4: Basic conn timeout test reflect on ingress """
- self.run_basic_conn_test(AF_INET, 0)
-
- def test_0002_basic_conn_test(self):
- """ IPv4: Basic conn timeout test reflect on egress """
- self.run_basic_conn_test(AF_INET, 1)
-
- def test_0005_clear_conn_test(self):
- """ IPv4: reflect egress, clear conn """
- self.run_clear_conn_test(AF_INET, 1)
-
- def test_0006_clear_conn_test(self):
- """ IPv4: reflect ingress, clear conn """
- self.run_clear_conn_test(AF_INET, 0)
-
- def test_0011_active_conn_test(self):
- """ IPv4: Idle conn behind active conn, reflect on ingress """
- self.run_active_conn_test(AF_INET, 0)
-
- def test_0012_active_conn_test(self):
- """ IPv4: Idle conn behind active conn, reflect on egress """
- self.run_active_conn_test(AF_INET, 1)
-
- def test_1001_basic_conn_test(self):
- """ IPv6: Basic conn timeout test reflect on ingress """
- self.run_basic_conn_test(AF_INET6, 0)
-
- def test_1002_basic_conn_test(self):
- """ IPv6: Basic conn timeout test reflect on egress """
- self.run_basic_conn_test(AF_INET6, 1)
-
- def test_1005_clear_conn_test(self):
- """ IPv6: reflect egress, clear conn """
- self.run_clear_conn_test(AF_INET6, 1)
-
- def test_1006_clear_conn_test(self):
- """ IPv6: reflect ingress, clear conn """
- self.run_clear_conn_test(AF_INET6, 0)
-
- def test_1011_active_conn_test(self):
- """ IPv6: Idle conn behind active conn, reflect on ingress """
- self.run_active_conn_test(AF_INET6, 0)
-
- def test_1012_active_conn_test(self):
- """ IPv6: Idle conn behind active conn, reflect on egress """
- self.run_active_conn_test(AF_INET6, 1)
-
- def test_2000_prepare_for_tcp_test(self):
- """ Prepare for TCP session tests """
- # ensure the session hangs on if it gets treated as UDP
- self.vapi.ppcli("set acl-plugin session timeout udp idle 200")
- # let the TCP connection time out at 5 seconds
- self.vapi.ppcli("set acl-plugin session timeout tcp idle 10")
- self.vapi.ppcli("set acl-plugin session timeout tcp transient 1")
-
- def test_2001_tcp_transient_conn_test(self):
- """ IPv4: transient TCP session (incomplete 3WHS), ref. on ingress """
- self.run_tcp_transient_setup_conn_test(AF_INET, 0)
-
- def test_2002_tcp_transient_conn_test(self):
- """ IPv4: transient TCP session (incomplete 3WHS), ref. on egress """
- self.run_tcp_transient_setup_conn_test(AF_INET, 1)
-
- def test_2003_tcp_transient_conn_test(self):
- """ IPv4: established TCP session (complete 3WHS), ref. on ingress """
- self.run_tcp_established_conn_test(AF_INET, 0)
-
- def test_2004_tcp_transient_conn_test(self):
- """ IPv4: established TCP session (complete 3WHS), ref. on egress """
- self.run_tcp_established_conn_test(AF_INET, 1)
-
- def test_2005_tcp_transient_teardown_conn_test(self):
- """ IPv4: transient TCP session (3WHS,ACK,FINACK), ref. on ingress """
- self.run_tcp_transient_teardown_conn_test(AF_INET, 0)
-
- def test_2006_tcp_transient_teardown_conn_test(self):
- """ IPv4: transient TCP session (3WHS,ACK,FINACK), ref. on egress """
- self.run_tcp_transient_teardown_conn_test(AF_INET, 1)
-
- def test_3001_tcp_transient_conn_test(self):
- """ IPv6: transient TCP session (incomplete 3WHS), ref. on ingress """
- self.run_tcp_transient_setup_conn_test(AF_INET6, 0)
-
- def test_3002_tcp_transient_conn_test(self):
- """ IPv6: transient TCP session (incomplete 3WHS), ref. on egress """
- self.run_tcp_transient_setup_conn_test(AF_INET6, 1)
-
- def test_3003_tcp_transient_conn_test(self):
- """ IPv6: established TCP session (complete 3WHS), ref. on ingress """
- self.run_tcp_established_conn_test(AF_INET6, 0)
-
- def test_3004_tcp_transient_conn_test(self):
- """ IPv6: established TCP session (complete 3WHS), ref. on egress """
- self.run_tcp_established_conn_test(AF_INET6, 1)
-
- def test_3005_tcp_transient_teardown_conn_test(self):
- """ IPv6: transient TCP session (3WHS,ACK,FINACK), ref. on ingress """
- self.run_tcp_transient_teardown_conn_test(AF_INET6, 0)
-
- def test_3006_tcp_transient_teardown_conn_test(self):
- """ IPv6: transient TCP session (3WHS,ACK,FINACK), ref. on egress """
- self.run_tcp_transient_teardown_conn_test(AF_INET6, 1)
diff --git a/test/test_acl_plugin_l2l3.py b/test/test_acl_plugin_l2l3.py
deleted file mode 100644
index 31b4058fc69..00000000000
--- a/test/test_acl_plugin_l2l3.py
+++ /dev/null
@@ -1,871 +0,0 @@
-#!/usr/bin/env python
-"""ACL IRB Test Case HLD:
-
-**config**
- - L2 MAC learning enabled in l2bd
- - 2 routed interfaces untagged, bvi (Bridge Virtual Interface)
- - 2 bridged interfaces in l2bd with bvi
-
-**test**
- - sending ip4 eth pkts between routed interfaces
- - 2 routed interfaces
- - 2 bridged interfaces
-
- - 64B, 512B, 1518B, 9200B (ether_size)
-
- - burst of pkts per interface
- - 257pkts per burst
- - routed pkts hitting different FIB entries
- - bridged pkts hitting different MAC entries
-
-**verify**
- - all packets received correctly
-
-"""
-
-import unittest
-from socket import inet_pton, AF_INET, AF_INET6
-from random import choice, shuffle
-from pprint import pprint
-
-import scapy.compat
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, UDP, ICMP, TCP
-from scapy.layers.inet6 import IPv6, ICMPv6Unknown, ICMPv6EchoRequest
-from scapy.layers.inet6 import ICMPv6EchoReply, IPv6ExtHdrRouting
-from scapy.layers.inet6 import IPv6ExtHdrFragment
-
-from framework import VppTestCase, VppTestRunner
-from vpp_l2 import L2_PORT_TYPE
-import time
-
-
-class TestACLpluginL2L3(VppTestCase):
- """TestACLpluginL2L3 Test Case"""
-
- @classmethod
- def setUpClass(cls):
- """
- #. Create BD with MAC learning enabled and put interfaces to this BD.
- #. Configure IPv4 addresses on loopback interface and routed interface.
- #. Configure MAC address binding to IPv4 neighbors on loop0.
- #. Configure MAC address on pg2.
- #. Loopback BVI interface has remote hosts, one half of hosts are
- behind pg0 second behind pg1.
- """
- super(TestACLpluginL2L3, cls).setUpClass()
-
- cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes
- cls.bd_id = 10
- cls.remote_hosts_count = 250
-
- # create 3 pg interfaces, 1 loopback interface
- cls.create_pg_interfaces(range(3))
- cls.create_loopback_interfaces(1)
-
- cls.interfaces = list(cls.pg_interfaces)
- cls.interfaces.extend(cls.lo_interfaces)
-
- for i in cls.interfaces:
- i.admin_up()
-
- # Create BD with MAC learning enabled and put interfaces to this BD
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.loop0.sw_if_index, bd_id=cls.bd_id,
- port_type=L2_PORT_TYPE.BVI)
- cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=cls.pg0.sw_if_index,
- bd_id=cls.bd_id)
- cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=cls.pg1.sw_if_index,
- bd_id=cls.bd_id)
-
- # Configure IPv4 addresses on loopback interface and routed interface
- cls.loop0.config_ip4()
- cls.loop0.config_ip6()
- cls.pg2.config_ip4()
- cls.pg2.config_ip6()
-
- # Configure MAC address binding to IPv4 neighbors on loop0
- cls.loop0.generate_remote_hosts(cls.remote_hosts_count)
- cls.loop0.configure_ipv4_neighbors()
- cls.loop0.configure_ipv6_neighbors()
- # configure MAC address on pg2
- cls.pg2.resolve_arp()
- cls.pg2.resolve_ndp()
-
- cls.WITHOUT_EH = False
- cls.WITH_EH = True
- cls.STATELESS_ICMP = False
- cls.STATEFUL_ICMP = True
-
- # Loopback BVI interface has remote hosts, one half of hosts are behind
- # pg0 second behind pg1
- half = cls.remote_hosts_count // 2
- cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half]
- cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:]
- reply = cls.vapi.papi.acl_stats_intf_counters_enable(enable=1)
-
- @classmethod
- def tearDownClass(cls):
- reply = cls.vapi.papi.acl_stats_intf_counters_enable(enable=0)
- super(TestACLpluginL2L3, cls).tearDownClass()
-
- def tearDown(self):
- """Run standard test teardown and log ``show l2patch``,
- ``show l2fib verbose``,``show bridge-domain <bd_id> detail``,
- ``show ip arp``.
- """
- super(TestACLpluginL2L3, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show l2patch"))
- self.logger.info(self.vapi.cli("show classify tables"))
- self.logger.info(self.vapi.cli("show l2fib verbose"))
- self.logger.info(self.vapi.cli("show bridge-domain %s detail" %
- self.bd_id))
- self.logger.info(self.vapi.cli("show ip arp"))
- self.logger.info(self.vapi.cli("show ip6 neighbors"))
- cmd = "show acl-plugin sessions verbose 1"
- self.logger.info(self.vapi.cli(cmd))
- self.logger.info(self.vapi.cli("show acl-plugin acl"))
- self.logger.info(self.vapi.cli("show acl-plugin interface"))
- self.logger.info(self.vapi.cli("show acl-plugin tables"))
-
- def create_stream(self, src_ip_if, dst_ip_if, reverse, packet_sizes,
- is_ip6, expect_blocked, expect_established,
- add_extension_header, icmp_stateful=False):
- pkts = []
- rules = []
- permit_rules = []
- permit_and_reflect_rules = []
- total_packet_count = 8
- for i in range(0, total_packet_count):
- modulo = (i//2) % 2
- icmp_type_delta = i % 2
- icmp_code = i
- is_udp_packet = (modulo == 0)
- if is_udp_packet and icmp_stateful:
- continue
- is_reflectable_icmp = (icmp_stateful and icmp_type_delta == 0 and
- not is_udp_packet)
- is_reflected_icmp = is_reflectable_icmp and expect_established
- can_reflect_this_packet = is_udp_packet or is_reflectable_icmp
- is_permit = i % 2
- remote_dst_index = i % len(dst_ip_if.remote_hosts)
- remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index]
- if is_permit == 1:
- info = self.create_packet_info(src_ip_if, dst_ip_if)
- payload = self.info_to_payload(info)
- else:
- to_be_blocked = False
- if (expect_blocked and not expect_established):
- to_be_blocked = True
- if (not can_reflect_this_packet):
- to_be_blocked = True
- if to_be_blocked:
- payload = "to be blocked"
- else:
- info = self.create_packet_info(src_ip_if, dst_ip_if)
- payload = self.info_to_payload(info)
- if reverse:
- dst_mac = 'de:ad:00:00:00:00'
- src_mac = remote_dst_host._mac
- dst_ip6 = src_ip_if.remote_ip6
- src_ip6 = remote_dst_host.ip6
- dst_ip4 = src_ip_if.remote_ip4
- src_ip4 = remote_dst_host.ip4
- dst_l4 = 1234 + i
- src_l4 = 4321 + i
- else:
- dst_mac = src_ip_if.local_mac
- src_mac = src_ip_if.remote_mac
- src_ip6 = src_ip_if.remote_ip6
- dst_ip6 = remote_dst_host.ip6
- src_ip4 = src_ip_if.remote_ip4
- dst_ip4 = remote_dst_host.ip4
- src_l4 = 1234 + i
- dst_l4 = 4321 + i
- if is_reflected_icmp:
- icmp_type_delta = 1
-
- # default ULP should be something we do not use in tests
- ulp_l4 = TCP(sport=src_l4, dport=dst_l4)
- # potentially a chain of protocols leading to ULP
- ulp = ulp_l4
-
- if is_udp_packet:
- if is_ip6:
- ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
- if add_extension_header:
- # prepend some extension headers
- ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() /
- IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4)
- # uncomment below to test invalid ones
- # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4
- else:
- ulp = ulp_l4
- p = (Ether(dst=dst_mac, src=src_mac) /
- IPv6(src=src_ip6, dst=dst_ip6) /
- ulp /
- Raw(payload))
- else:
- ulp_l4 = UDP(sport=src_l4, dport=dst_l4)
- # IPv4 does not allow extension headers,
- # but we rather make it a first fragment
- flags = 1 if add_extension_header else 0
- ulp = ulp_l4
- p = (Ether(dst=dst_mac, src=src_mac) /
- IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) /
- ulp /
- Raw(payload))
- elif modulo == 1:
- if is_ip6:
- ulp_l4 = ICMPv6Unknown(type=128 + icmp_type_delta,
- code=icmp_code)
- ulp = ulp_l4
- p = (Ether(dst=dst_mac, src=src_mac) /
- IPv6(src=src_ip6, dst=dst_ip6) /
- ulp /
- Raw(payload))
- else:
- ulp_l4 = ICMP(type=8 - 8*icmp_type_delta, code=icmp_code)
- ulp = ulp_l4
- p = (Ether(dst=dst_mac, src=src_mac) /
- IP(src=src_ip4, dst=dst_ip4) /
- ulp /
- Raw(payload))
-
- if i % 2 == 1:
- info.data = p.copy()
- size = packet_sizes[(i // 2) % len(packet_sizes)]
- self.extend_packet(p, size)
- pkts.append(p)
-
- rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET
- rule_prefix_len = 128 if p.haslayer(IPv6) else 32
- rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP
-
- if p.haslayer(UDP):
- rule_l4_sport = p[UDP].sport
- rule_l4_dport = p[UDP].dport
- else:
- if p.haslayer(ICMP):
- rule_l4_sport = p[ICMP].type
- rule_l4_dport = p[ICMP].code
- else:
- rule_l4_sport = p[ICMPv6Unknown].type
- rule_l4_dport = p[ICMPv6Unknown].code
- if p.haslayer(IPv6):
- rule_l4_proto = ulp_l4.overload_fields[IPv6]['nh']
- else:
- rule_l4_proto = p[IP].proto
-
- new_rule = {
- 'is_permit': is_permit,
- 'is_ipv6': p.haslayer(IPv6),
- 'src_ip_addr': inet_pton(rule_family,
- p[rule_l3_layer].src),
- 'src_ip_prefix_len': rule_prefix_len,
- 'dst_ip_addr': inet_pton(rule_family,
- p[rule_l3_layer].dst),
- 'dst_ip_prefix_len': rule_prefix_len,
- 'srcport_or_icmptype_first': rule_l4_sport,
- 'srcport_or_icmptype_last': rule_l4_sport,
- 'dstport_or_icmpcode_first': rule_l4_dport,
- 'dstport_or_icmpcode_last': rule_l4_dport,
- 'proto': rule_l4_proto,
- }
- rules.append(new_rule)
- new_rule_permit = new_rule.copy()
- new_rule_permit['is_permit'] = 1
- permit_rules.append(new_rule_permit)
-
- new_rule_permit_and_reflect = new_rule.copy()
- if can_reflect_this_packet:
- new_rule_permit_and_reflect['is_permit'] = 2
- else:
- new_rule_permit_and_reflect['is_permit'] = is_permit
-
- permit_and_reflect_rules.append(new_rule_permit_and_reflect)
- self.logger.info("create_stream pkt#%d: %s" % (i, payload))
-
- return {'stream': pkts,
- 'rules': rules,
- 'permit_rules': permit_rules,
- 'permit_and_reflect_rules': permit_and_reflect_rules}
-
- def verify_capture(self, dst_ip_if, src_ip_if, capture, reverse):
- last_info = dict()
- for i in self.interfaces:
- last_info[i.sw_if_index] = None
-
- dst_ip_sw_if_index = dst_ip_if.sw_if_index
-
- for packet in capture:
- l3 = IP if packet.haslayer(IP) else IPv6
- ip = packet[l3]
- if packet.haslayer(UDP):
- l4 = UDP
- else:
- if packet.haslayer(ICMP):
- l4 = ICMP
- else:
- l4 = ICMPv6Unknown
-
- # Scapy IPv6 stuff is too smart for its own good.
- # So we do this and coerce the ICMP into unknown type
- if packet.haslayer(UDP):
- data = scapy.compat.raw(packet[UDP][Raw])
- else:
- if l3 == IP:
- data = scapy.compat.raw(ICMP(
- scapy.compat.raw(packet[l3].payload))[Raw])
- else:
- data = scapy.compat.raw(ICMPv6Unknown(
- scapy.compat.raw(packet[l3].payload)).msgbody)
- udp_or_icmp = packet[l3].payload
- data_obj = Raw(data)
- # FIXME: make framework believe we are on object
- payload_info = self.payload_to_info(data_obj)
- packet_index = payload_info.index
-
- self.assertEqual(payload_info.dst, dst_ip_sw_if_index)
-
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_ip_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- self.assertTrue(next_info is not None)
- self.assertEqual(packet_index, next_info.index)
- saved_packet = next_info.data
- self.assertTrue(next_info is not None)
-
- # MAC: src, dst
- if not reverse:
- self.assertEqual(packet.src, dst_ip_if.local_mac)
- host = dst_ip_if.host_by_mac(packet.dst)
-
- # IP: src, dst
- # self.assertEqual(ip.src, src_ip_if.remote_ip4)
- if saved_packet is not None:
- self.assertEqual(ip.src, saved_packet[l3].src)
- self.assertEqual(ip.dst, saved_packet[l3].dst)
- if l4 == UDP:
- self.assertEqual(udp_or_icmp.sport, saved_packet[l4].sport)
- self.assertEqual(udp_or_icmp.dport, saved_packet[l4].dport)
- # self.assertEqual(ip.dst, host.ip4)
-
- # UDP:
-
- def applied_acl_shuffle(self, sw_if_index):
- # first collect what ACLs are applied and what they look like
- r = self.vapi.acl_interface_list_dump(sw_if_index=sw_if_index)
- orig_applied_acls = r[0]
-
- # we will collect these just to save and generate additional rulesets
- orig_acls = []
- for acl_num in orig_applied_acls.acls:
- rr = self.vapi.acl_dump(acl_num)
- orig_acls.append(rr[0])
-
- # now create a list of all the rules in all ACLs
- all_rules = []
- for old_acl in orig_acls:
- for rule in old_acl.r:
- all_rules.append(dict(rule._asdict()))
-
- # Add a few ACLs made from shuffled rules
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=4294967295,
- r=all_rules[::2],
- tag=b"shuffle 1. acl")
- shuffle_acl_1 = reply.acl_index
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=4294967295,
- r=all_rules[::3],
- tag=b"shuffle 2. acl")
- shuffle_acl_2 = reply.acl_index
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=4294967295,
- r=all_rules[::2],
- tag=b"shuffle 3. acl")
- shuffle_acl_3 = reply.acl_index
-
- # apply the shuffle ACLs in front
- input_acls = [shuffle_acl_1, shuffle_acl_2]
- output_acls = [shuffle_acl_1, shuffle_acl_2]
-
- # add the currently applied ACLs
- n_input = orig_applied_acls.n_input
- input_acls.extend(orig_applied_acls.acls[:n_input])
- output_acls.extend(orig_applied_acls.acls[n_input:])
-
- # and the trailing shuffle ACL(s)
- input_acls.extend([shuffle_acl_3])
- output_acls.extend([shuffle_acl_3])
-
- # set the interface ACL list to the result
- self.vapi.acl_interface_set_acl_list(sw_if_index=sw_if_index,
- n_input=len(input_acls),
- acls=input_acls + output_acls)
- # change the ACLs a few times
- for i in range(1, 10):
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_1,
- r=all_rules[::1+(i % 2)],
- tag=b"shuffle 1. acl")
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_2,
- r=all_rules[::1+(i % 3)],
- tag=b"shuffle 2. acl")
- shuffle(all_rules)
- reply = self.vapi.acl_add_replace(acl_index=shuffle_acl_2,
- r=all_rules[::1+(i % 5)],
- tag=b"shuffle 3. acl")
-
- # restore to how it was before and clean up
- self.vapi.acl_interface_set_acl_list(sw_if_index=sw_if_index,
- n_input=orig_applied_acls.n_input,
- acls=orig_applied_acls.acls)
- reply = self.vapi.acl_del(acl_index=shuffle_acl_1)
- reply = self.vapi.acl_del(acl_index=shuffle_acl_2)
- reply = self.vapi.acl_del(acl_index=shuffle_acl_3)
-
- def create_acls_for_a_stream(self, stream_dict,
- test_l2_action, is_reflect):
- r = stream_dict['rules']
- r_permit = stream_dict['permit_rules']
- r_permit_reflect = stream_dict['permit_and_reflect_rules']
- r_action = r_permit_reflect if is_reflect else r
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r_action,
- tag=b"act. acl")
- action_acl_index = reply.acl_index
- reply = self.vapi.acl_add_replace(acl_index=4294967295, r=r_permit,
- tag=b"perm. acl")
- permit_acl_index = reply.acl_index
- return {'L2': action_acl_index if test_l2_action else permit_acl_index,
- 'L3': permit_acl_index if test_l2_action else action_acl_index,
- 'permit': permit_acl_index, 'action': action_acl_index}
-
- def apply_acl_ip46_x_to_y(self, bridged_to_routed, test_l2_deny,
- is_ip6, is_reflect, add_eh):
- """ Apply the ACLs
- """
- self.reset_packet_infos()
- stream_dict = self.create_stream(
- self.pg2, self.loop0,
- bridged_to_routed,
- self.pg_if_packet_sizes, is_ip6,
- not is_reflect, False, add_eh)
- stream = stream_dict['stream']
- acl_idx = self.create_acls_for_a_stream(stream_dict, test_l2_deny,
- is_reflect)
- n_input_l3 = 0 if bridged_to_routed else 1
- n_input_l2 = 1 if bridged_to_routed else 0
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg2.sw_if_index,
- n_input=n_input_l3,
- acls=[acl_idx['L3']])
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=n_input_l2,
- acls=[acl_idx['L2']])
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
- n_input=n_input_l2,
- acls=[acl_idx['L2']])
- self.applied_acl_shuffle(self.pg0.sw_if_index)
- self.applied_acl_shuffle(self.pg2.sw_if_index)
- return {'L2': acl_idx['L2'], 'L3': acl_idx['L3']}
-
- def apply_acl_ip46_both_directions_reflect(self,
- primary_is_bridged_to_routed,
- reflect_on_l2, is_ip6, add_eh,
- stateful_icmp):
- primary_is_routed_to_bridged = not primary_is_bridged_to_routed
- self.reset_packet_infos()
- stream_dict_fwd = self.create_stream(self.pg2, self.loop0,
- primary_is_bridged_to_routed,
- self.pg_if_packet_sizes, is_ip6,
- False, False, add_eh,
- stateful_icmp)
- acl_idx_fwd = self.create_acls_for_a_stream(stream_dict_fwd,
- reflect_on_l2, True)
-
- stream_dict_rev = self.create_stream(self.pg2, self.loop0,
- not primary_is_bridged_to_routed,
- self.pg_if_packet_sizes, is_ip6,
- True, True, add_eh, stateful_icmp)
- # We want the primary action to be "deny" rather than reflect
- acl_idx_rev = self.create_acls_for_a_stream(stream_dict_rev,
- reflect_on_l2, False)
-
- if primary_is_bridged_to_routed:
- inbound_l2_acl = acl_idx_fwd['L2']
- else:
- inbound_l2_acl = acl_idx_rev['L2']
-
- if primary_is_routed_to_bridged:
- outbound_l2_acl = acl_idx_fwd['L2']
- else:
- outbound_l2_acl = acl_idx_rev['L2']
-
- if primary_is_routed_to_bridged:
- inbound_l3_acl = acl_idx_fwd['L3']
- else:
- inbound_l3_acl = acl_idx_rev['L3']
-
- if primary_is_bridged_to_routed:
- outbound_l3_acl = acl_idx_fwd['L3']
- else:
- outbound_l3_acl = acl_idx_rev['L3']
-
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg2.sw_if_index,
- n_input=1,
- acls=[inbound_l3_acl,
- outbound_l3_acl])
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg0.sw_if_index,
- n_input=1,
- acls=[inbound_l2_acl,
- outbound_l2_acl])
- self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
- n_input=1,
- acls=[inbound_l2_acl,
- outbound_l2_acl])
- self.applied_acl_shuffle(self.pg0.sw_if_index)
- self.applied_acl_shuffle(self.pg2.sw_if_index)
-
- def apply_acl_ip46_routed_to_bridged(self, test_l2_deny, is_ip6,
- is_reflect, add_eh):
- return self.apply_acl_ip46_x_to_y(False, test_l2_deny, is_ip6,
- is_reflect, add_eh)
-
- def apply_acl_ip46_bridged_to_routed(self, test_l2_deny, is_ip6,
- is_reflect, add_eh):
- return self.apply_acl_ip46_x_to_y(True, test_l2_deny, is_ip6,
- is_reflect, add_eh)
-
- def verify_acl_packet_count(self, acl_idx, packet_count):
- matches = self.statistics.get_counter('/acl/%d/matches' % acl_idx)
- self.logger.info("stat seg for ACL %d: %s" % (acl_idx, repr(matches)))
- total_count = 0
- for p in matches[0]:
- total_count = total_count + p['packets']
- self.assertEqual(total_count, packet_count)
-
- def run_traffic_ip46_x_to_y(self, bridged_to_routed,
- test_l2_deny, is_ip6,
- is_reflect, is_established, add_eh,
- stateful_icmp=False):
- self.reset_packet_infos()
- stream_dict = self.create_stream(self.pg2, self.loop0,
- bridged_to_routed,
- self.pg_if_packet_sizes, is_ip6,
- not is_reflect, is_established,
- add_eh, stateful_icmp)
- stream = stream_dict['stream']
-
- tx_if = self.pg0 if bridged_to_routed else self.pg2
- rx_if = self.pg2 if bridged_to_routed else self.pg0
-
- tx_if.add_stream(stream)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- packet_count = self.get_packet_count_for_if_idx(self.loop0.sw_if_index)
- rcvd1 = rx_if.get_capture(packet_count)
- self.verify_capture(self.loop0, self.pg2, rcvd1, bridged_to_routed)
- return len(stream)
-
- def run_traffic_ip46_routed_to_bridged(self, test_l2_deny, is_ip6,
- is_reflect, is_established, add_eh,
- stateful_icmp=False):
- return self.run_traffic_ip46_x_to_y(False, test_l2_deny, is_ip6,
- is_reflect, is_established, add_eh,
- stateful_icmp)
-
- def run_traffic_ip46_bridged_to_routed(self, test_l2_deny, is_ip6,
- is_reflect, is_established, add_eh,
- stateful_icmp=False):
- return self.run_traffic_ip46_x_to_y(True, test_l2_deny, is_ip6,
- is_reflect, is_established, add_eh,
- stateful_icmp)
-
- def run_test_ip46_routed_to_bridged(self, test_l2_deny,
- is_ip6, is_reflect, add_eh):
- acls = self.apply_acl_ip46_routed_to_bridged(test_l2_deny,
- is_ip6, is_reflect,
- add_eh)
- pkts = self.run_traffic_ip46_routed_to_bridged(test_l2_deny, is_ip6,
- is_reflect, False,
- add_eh)
- self.verify_acl_packet_count(acls['L3'], pkts)
-
- def run_test_ip46_bridged_to_routed(self, test_l2_deny,
- is_ip6, is_reflect, add_eh):
- acls = self.apply_acl_ip46_bridged_to_routed(test_l2_deny,
- is_ip6, is_reflect,
- add_eh)
- pkts = self.run_traffic_ip46_bridged_to_routed(test_l2_deny, is_ip6,
- is_reflect, False,
- add_eh)
- self.verify_acl_packet_count(acls['L2'], pkts)
-
- def run_test_ip46_routed_to_bridged_and_back(self, test_l2_action,
- is_ip6, add_eh,
- stateful_icmp=False):
- self.apply_acl_ip46_both_directions_reflect(False, test_l2_action,
- is_ip6, add_eh,
- stateful_icmp)
- self.run_traffic_ip46_routed_to_bridged(test_l2_action, is_ip6,
- True, False, add_eh,
- stateful_icmp)
- self.run_traffic_ip46_bridged_to_routed(test_l2_action, is_ip6,
- False, True, add_eh,
- stateful_icmp)
-
- def run_test_ip46_bridged_to_routed_and_back(self, test_l2_action,
- is_ip6, add_eh,
- stateful_icmp=False):
- self.apply_acl_ip46_both_directions_reflect(True, test_l2_action,
- is_ip6, add_eh,
- stateful_icmp)
- self.run_traffic_ip46_bridged_to_routed(test_l2_action, is_ip6,
- True, False, add_eh,
- stateful_icmp)
- self.run_traffic_ip46_routed_to_bridged(test_l2_action, is_ip6,
- False, True, add_eh,
- stateful_icmp)
-
- def test_0000_ip6_irb_1(self):
- """ ACL plugin prepare"""
- if not self.vpp_dead:
- cmd = "set acl-plugin session timeout udp idle 2000"
- self.logger.info(self.vapi.ppcli(cmd))
- # uncomment to not skip past the routing header
- # and watch the EH tests fail
- # self.logger.info(self.vapi.ppcli(
- # "set acl-plugin skip-ipv6-extension-header 43 0"))
- # uncomment to test the session limit (stateful tests will fail)
- # self.logger.info(self.vapi.ppcli(
- # "set acl-plugin session table max-entries 1"))
- # new datapath is the default, but just in case
- # self.logger.info(self.vapi.ppcli(
- # "set acl-plugin l2-datapath new"))
- # If you want to see some tests fail, uncomment the next line
- # self.logger.info(self.vapi.ppcli(
- # "set acl-plugin l2-datapath old"))
-
- def test_0001_ip6_irb_1(self):
- """ ACL IPv6 routed -> bridged, L2 ACL deny"""
- self.run_test_ip46_routed_to_bridged(True, True, False,
- self.WITHOUT_EH)
-
- def test_0002_ip6_irb_1(self):
- """ ACL IPv6 routed -> bridged, L3 ACL deny"""
- self.run_test_ip46_routed_to_bridged(False, True, False,
- self.WITHOUT_EH)
-
- def test_0003_ip4_irb_1(self):
- """ ACL IPv4 routed -> bridged, L2 ACL deny"""
- self.run_test_ip46_routed_to_bridged(True, False, False,
- self.WITHOUT_EH)
-
- def test_0004_ip4_irb_1(self):
- """ ACL IPv4 routed -> bridged, L3 ACL deny"""
- self.run_test_ip46_routed_to_bridged(False, False, False,
- self.WITHOUT_EH)
-
- def test_0005_ip6_irb_1(self):
- """ ACL IPv6 bridged -> routed, L2 ACL deny """
- self.run_test_ip46_bridged_to_routed(True, True, False,
- self.WITHOUT_EH)
-
- def test_0006_ip6_irb_1(self):
- """ ACL IPv6 bridged -> routed, L3 ACL deny """
- self.run_test_ip46_bridged_to_routed(False, True, False,
- self.WITHOUT_EH)
-
- def test_0007_ip6_irb_1(self):
- """ ACL IPv4 bridged -> routed, L2 ACL deny """
- self.run_test_ip46_bridged_to_routed(True, False, False,
- self.WITHOUT_EH)
-
- def test_0008_ip6_irb_1(self):
- """ ACL IPv4 bridged -> routed, L3 ACL deny """
- self.run_test_ip46_bridged_to_routed(False, False, False,
- self.WITHOUT_EH)
-
- # Stateful ACL tests
- def test_0101_ip6_irb_1(self):
- """ ACL IPv6 routed -> bridged, L2 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, True,
- self.WITHOUT_EH)
-
- def test_0102_ip6_irb_1(self):
- """ ACL IPv6 bridged -> routed, L2 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, True,
- self.WITHOUT_EH)
-
- def test_0103_ip6_irb_1(self):
- """ ACL IPv4 routed -> bridged, L2 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, False,
- self.WITHOUT_EH)
-
- def test_0104_ip6_irb_1(self):
- """ ACL IPv4 bridged -> routed, L2 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, False,
- self.WITHOUT_EH)
-
- def test_0111_ip6_irb_1(self):
- """ ACL IPv6 routed -> bridged, L3 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, True,
- self.WITHOUT_EH)
-
- def test_0112_ip6_irb_1(self):
- """ ACL IPv6 bridged -> routed, L3 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, True,
- self.WITHOUT_EH)
-
- def test_0113_ip6_irb_1(self):
- """ ACL IPv4 routed -> bridged, L3 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, False,
- self.WITHOUT_EH)
-
- def test_0114_ip6_irb_1(self):
- """ ACL IPv4 bridged -> routed, L3 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, False,
- self.WITHOUT_EH)
-
- # A block of tests with extension headers
-
- def test_1001_ip6_irb_1(self):
- """ ACL IPv6+EH routed -> bridged, L2 ACL deny"""
- self.run_test_ip46_routed_to_bridged(True, True, False,
- self.WITH_EH)
-
- def test_1002_ip6_irb_1(self):
- """ ACL IPv6+EH routed -> bridged, L3 ACL deny"""
- self.run_test_ip46_routed_to_bridged(False, True, False,
- self.WITH_EH)
-
- def test_1005_ip6_irb_1(self):
- """ ACL IPv6+EH bridged -> routed, L2 ACL deny """
- self.run_test_ip46_bridged_to_routed(True, True, False,
- self.WITH_EH)
-
- def test_1006_ip6_irb_1(self):
- """ ACL IPv6+EH bridged -> routed, L3 ACL deny """
- self.run_test_ip46_bridged_to_routed(False, True, False,
- self.WITH_EH)
-
- def test_1101_ip6_irb_1(self):
- """ ACL IPv6+EH routed -> bridged, L2 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, True,
- self.WITH_EH)
-
- def test_1102_ip6_irb_1(self):
- """ ACL IPv6+EH bridged -> routed, L2 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, True,
- self.WITH_EH)
-
- def test_1111_ip6_irb_1(self):
- """ ACL IPv6+EH routed -> bridged, L3 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, True,
- self.WITH_EH)
-
- def test_1112_ip6_irb_1(self):
- """ ACL IPv6+EH bridged -> routed, L3 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, True,
- self.WITH_EH)
-
- # IPv4 with "MF" bit set
-
- def test_1201_ip6_irb_1(self):
- """ ACL IPv4+MF routed -> bridged, L2 ACL deny"""
- self.run_test_ip46_routed_to_bridged(True, False, False,
- self.WITH_EH)
-
- def test_1202_ip6_irb_1(self):
- """ ACL IPv4+MF routed -> bridged, L3 ACL deny"""
- self.run_test_ip46_routed_to_bridged(False, False, False,
- self.WITH_EH)
-
- def test_1205_ip6_irb_1(self):
- """ ACL IPv4+MF bridged -> routed, L2 ACL deny """
- self.run_test_ip46_bridged_to_routed(True, False, False,
- self.WITH_EH)
-
- def test_1206_ip6_irb_1(self):
- """ ACL IPv4+MF bridged -> routed, L3 ACL deny """
- self.run_test_ip46_bridged_to_routed(False, False, False,
- self.WITH_EH)
-
- def test_1301_ip6_irb_1(self):
- """ ACL IPv4+MF routed -> bridged, L2 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, False,
- self.WITH_EH)
-
- def test_1302_ip6_irb_1(self):
- """ ACL IPv4+MF bridged -> routed, L2 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, False,
- self.WITH_EH)
-
- def test_1311_ip6_irb_1(self):
- """ ACL IPv4+MF routed -> bridged, L3 ACL permit+reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, False,
- self.WITH_EH)
-
- def test_1312_ip6_irb_1(self):
- """ ACL IPv4+MF bridged -> routed, L3 ACL permit+reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, False,
- self.WITH_EH)
- # Stateful ACL tests with stateful ICMP
-
- def test_1401_ip6_irb_1(self):
- """ IPv6 routed -> bridged, L2 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, True,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1402_ip6_irb_1(self):
- """ IPv6 bridged -> routed, L2 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, True,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1403_ip4_irb_1(self):
- """ IPv4 routed -> bridged, L2 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(True, False,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1404_ip4_irb_1(self):
- """ IPv4 bridged -> routed, L2 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(True, False,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1411_ip6_irb_1(self):
- """ IPv6 routed -> bridged, L3 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, True,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1412_ip6_irb_1(self):
- """ IPv6 bridged -> routed, L3 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, True,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1413_ip4_irb_1(self):
- """ IPv4 routed -> bridged, L3 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_routed_to_bridged_and_back(False, False,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
- def test_1414_ip4_irb_1(self):
- """ IPv4 bridged -> routed, L3 ACL permit+reflect, ICMP reflect"""
- self.run_test_ip46_bridged_to_routed_and_back(False, False,
- self.WITHOUT_EH,
- self.STATEFUL_ICMP)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_acl_plugin_macip.py b/test/test_acl_plugin_macip.py
deleted file mode 100644
index 41735251792..00000000000
--- a/test/test_acl_plugin_macip.py
+++ /dev/null
@@ -1,1295 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-"""ACL plugin - MACIP tests
-"""
-import binascii
-import ipaddress
-import random
-from socket import inet_ntop, inet_pton, AF_INET, AF_INET6
-from struct import pack, unpack
-import re
-import unittest
-
-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 framework import VppTestCase, VppTestRunner, running_extended_tests
-from vpp_lo_interface import VppLoInterface
-from vpp_l2 import L2_PORT_TYPE
-from vpp_sub_interface import L2_VTR_OP, VppSubInterface, VppDot1QSubint, \
- VppDot1ADSubint
-
-
-class MethodHolder(VppTestCase):
- DEBUG = False
-
- BRIDGED = True
- ROUTED = False
-
- IS_IP4 = False
- IS_IP6 = True
-
- DOT1AD = "dot1ad"
- DOT1Q = "dot1q"
- PERMIT_TAGS = True
- DENY_TAGS = False
-
- # rule types
- DENY = 0
- PERMIT = 1
-
- # ACL types
- EXACT_IP = 1
- SUBNET_IP = 2
- WILD_IP = 3
-
- EXACT_MAC = 1
- WILD_MAC = 2
- OUI_MAC = 3
-
- ACLS = []
-
- @classmethod
- def setUpClass(cls):
- """
- Perform standard class setup (defined by class method setUpClass in
- class VppTestCase) before running the test case, set test case related
- variables and configure VPP.
- """
- super(MethodHolder, cls).setUpClass()
-
- cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes
- cls.bd_id = 111
- cls.remote_hosts_count = 200
-
- try:
- # create 4 pg interfaces, 1 loopback interface
- cls.create_pg_interfaces(range(4))
- cls.create_loopback_interfaces(1)
-
- # create 2 subinterfaces
- cls.subifs = [
- VppDot1QSubint(cls, cls.pg1, 10),
- VppDot1ADSubint(cls, cls.pg2, 20, 300, 400),
- VppDot1QSubint(cls, cls.pg3, 30),
- VppDot1ADSubint(cls, cls.pg3, 40, 600, 700)]
-
- cls.subifs[0].set_vtr(L2_VTR_OP.L2_POP_1,
- inner=10, push1q=1)
- cls.subifs[1].set_vtr(L2_VTR_OP.L2_POP_2,
- outer=300, inner=400, push1q=1)
- cls.subifs[2].set_vtr(L2_VTR_OP.L2_POP_1,
- inner=30, push1q=1)
- cls.subifs[3].set_vtr(L2_VTR_OP.L2_POP_2,
- outer=600, inner=700, push1q=1)
-
- cls.interfaces = list(cls.pg_interfaces)
- cls.interfaces.extend(cls.lo_interfaces)
- cls.interfaces.extend(cls.subifs)
-
- for i in cls.interfaces:
- i.admin_up()
-
- # Create BD with MAC learning enabled and put interfaces to this BD
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.loop0.sw_if_index, bd_id=cls.bd_id,
- port_type=L2_PORT_TYPE.BVI)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg0.sw_if_index, bd_id=cls.bd_id)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg1.sw_if_index, bd_id=cls.bd_id)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.subifs[0].sw_if_index, bd_id=cls.bd_id)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.subifs[1].sw_if_index, bd_id=cls.bd_id)
-
- # Configure IPv4/6 addresses on loop interface and routed interface
- cls.loop0.config_ip4()
- cls.loop0.config_ip6()
- cls.pg2.config_ip4()
- cls.pg2.config_ip6()
- cls.pg3.config_ip4()
- cls.pg3.config_ip6()
-
- # Configure MAC address binding to IPv4 neighbors on loop0
- cls.loop0.generate_remote_hosts(cls.remote_hosts_count)
- # Modify host mac addresses to have different OUI parts
- for i in range(2, cls.remote_hosts_count + 2):
- mac = cls.loop0.remote_hosts[i-2]._mac.split(':')
- mac[2] = format(int(mac[2], 16) + i, "02x")
- cls.loop0.remote_hosts[i - 2]._mac = ":".join(mac)
-
- cls.loop0.configure_ipv4_neighbors()
- cls.loop0.configure_ipv6_neighbors()
-
- # configure MAC address on pg3
- cls.pg3.resolve_arp()
- cls.pg3.resolve_ndp()
-
- # configure MAC address on subifs
- for i in cls.subifs:
- i.config_ip4()
- i.resolve_arp()
- i.config_ip6()
-
- # configure MAC address on pg2
- cls.pg2.resolve_arp()
- cls.pg2.resolve_ndp()
-
- # Loopback BVI interface has remote hosts
- # one half of hosts are behind pg0 second behind pg1,pg2,pg3 subifs
- cls.pg0.remote_hosts = cls.loop0.remote_hosts[:100]
- cls.subifs[0].remote_hosts = cls.loop0.remote_hosts[100:125]
- cls.subifs[1].remote_hosts = cls.loop0.remote_hosts[125:150]
- cls.subifs[2].remote_hosts = cls.loop0.remote_hosts[150:175]
- cls.subifs[3].remote_hosts = cls.loop0.remote_hosts[175:]
-
- except Exception:
- super(MethodHolder, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(MethodHolder, cls).tearDownClass()
-
- def setUp(self):
- super(MethodHolder, self).setUp()
- self.reset_packet_infos()
- del self.ACLS[:]
-
- def tearDown(self):
- super(MethodHolder, self).tearDown()
- self.delete_acls()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.ppcli("show interface address"))
- self.logger.info(self.vapi.ppcli("show hardware"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip interface"))
- self.logger.info(self.vapi.ppcli("sh classify tables verbose"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin acl"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin interface"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin tables"))
- # print(self.vapi.ppcli("show interface address"))
- # print(self.vapi.ppcli("show hardware"))
- # print(self.vapi.ppcli("sh acl-plugin macip interface"))
- # print(self.vapi.ppcli("sh acl-plugin macip acl"))
-
- def macip_acl_dump_debug(self):
- acls = self.vapi.macip_acl_dump()
- if self.DEBUG:
- for acl in acls:
- print("ACL #"+str(acl.acl_index))
- for r in acl.r:
- rule = "ACTION"
- if r.is_permit == 1:
- rule = "PERMIT"
- elif r.is_permit == 0:
- rule = "DENY "
- print(" IP6" if r.is_ipv6 else " IP4",
- rule,
- binascii.hexlify(r.src_mac),
- binascii.hexlify(r.src_mac_mask),
- unpack('<16B', r.src_ip_addr),
- r.src_ip_prefix_len)
- return acls
-
- def create_rules(self, mac_type=EXACT_MAC, ip_type=EXACT_IP,
- acl_count=1, rules_count=None):
- acls = []
- if rules_count is None:
- rules_count = [1]
- src_mac = int("220000dead00", 16)
- for acl in range(2, (acl_count+1) * 2):
- rules = []
- host = random.choice(self.loop0.remote_hosts)
- is_ip6 = acl % 2
- ip4 = host.ip4.split('.')
- ip6 = list(unpack('<16B', inet_pton(AF_INET6, host.ip6)))
-
- if ip_type == self.EXACT_IP:
- prefix_len4 = 32
- prefix_len6 = 128
- elif ip_type == self.WILD_IP:
- ip4 = [0, 0, 0, 0]
- ip6 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- prefix_len4 = 0
- prefix_len6 = 0
- rules_count[(acl / 2) - 1] = 1
- else:
- prefix_len4 = 24
- prefix_len6 = 64
-
- if mac_type == self.EXACT_MAC:
- mask = "ff:ff:ff:ff:ff:ff"
- elif mac_type == self.WILD_MAC:
- mask = "00:00:00:00:00:00"
- elif mac_type == self.OUI_MAC:
- mask = "ff:ff:ff:00:00:00"
- else:
- mask = "ff:ff:ff:ff:ff:00"
-
- ip = ip6 if is_ip6 else ip4
- ip_len = prefix_len6 if is_ip6 else prefix_len4
-
- for i in range(0, rules_count[(acl / 2) - 1]):
- src_mac += 16777217
- if mac_type == self.WILD_MAC:
- mac = "00:00:00:00:00:00"
- elif mac_type == self.OUI_MAC:
- mac = ':'.join(re.findall('..', '{:02x}'.format(
- src_mac))[:3])+":00:00:00"
- else:
- mac = ':'.join(re.findall(
- '..', '{:02x}'.format(src_mac)))
-
- if ip_type == self.EXACT_IP:
- ip4[3] = random.randint(100, 200)
- ip6[15] = random.randint(100, 200)
- elif ip_type == self.SUBNET_IP:
- ip4[2] = random.randint(100, 200)
- ip4[3] = 0
- ip6[8] = random.randint(100, 200)
- ip6[15] = 0
- ip_pack = b''
- for j in range(0, len(ip)):
- ip_pack += pack('<B', int(ip[j]))
-
- rule = ({'is_permit': self.PERMIT,
- 'is_ipv6': is_ip6,
- 'src_ip_addr': ip_pack,
- 'src_ip_prefix_len': ip_len,
- 'src_mac': binascii.unhexlify(mac.replace(':', '')),
- 'src_mac_mask': binascii.unhexlify(
- mask.replace(':', ''))})
- rules.append(rule)
- if ip_type == self.WILD_IP:
- break
-
- acls.append(rules)
- src_mac += 1099511627776
- return acls
-
- def apply_macip_rules(self, acls):
- for acl in acls:
- reply = self.vapi.macip_acl_add(acl)
- self.assertEqual(reply.retval, 0)
- self.ACLS.append(reply.acl_index)
-
- def verify_macip_acls(self, acl_count, rules_count, expected_count=2):
- reply = self.macip_acl_dump_debug()
- for acl in range(2, (acl_count+1) * 2):
- self.assertEqual(reply[acl - 2].count, rules_count[acl//2-1])
-
- self.vapi.macip_acl_interface_get()
-
- self.vapi.macip_acl_interface_add_del(sw_if_index=0, acl_index=0)
- self.vapi.macip_acl_interface_add_del(sw_if_index=1, acl_index=1)
-
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, expected_count)
-
- def delete_acls(self):
- for acl in range(len(self.ACLS)-1, -1, -1):
- self.vapi.macip_acl_del(self.ACLS[acl])
-
- reply = self.vapi.macip_acl_dump()
- self.assertEqual(len(reply), 0)
-
- intf_acls = self.vapi.acl_interface_list_dump()
- for i_a in intf_acls:
- sw_if_index = i_a.sw_if_index
- for acl_index in i_a.acls:
- self.vapi.acl_interface_add_del(sw_if_index, acl_index, 0)
- self.vapi.acl_del(acl_index)
-
- def create_stream(self, mac_type, ip_type, packet_count,
- src_if, dst_if, traffic, is_ip6, tags=PERMIT_TAGS):
- # exact MAC and exact IP
- # exact MAC and subnet of IPs
- # exact MAC and wildcard IP
- # wildcard MAC and exact IP
- # wildcard MAC and subnet of IPs
- # wildcard MAC and wildcard IP
- # OUI restricted MAC and exact IP
- # OUI restricted MAC and subnet of IPs
- # OUI restricted MAC and wildcard IP
-
- packets = []
- macip_rules = []
- acl_rules = []
- ip_permit = ""
- mac_permit = ""
- dst_mac = ""
- mac_rule = "00:00:00:00:00:00"
- mac_mask = "00:00:00:00:00:00"
- for p in range(0, packet_count):
- remote_dst_index = p % len(dst_if.remote_hosts)
- remote_dst_host = dst_if.remote_hosts[remote_dst_index]
-
- dst_port = 1234 + p
- src_port = 4321 + p
- is_permit = self.PERMIT if p % 3 == 0 else self.DENY
- denyMAC = True if not is_permit and p % 3 == 1 else False
- denyIP = True if not is_permit and p % 3 == 2 else False
- if not is_permit and ip_type == self.WILD_IP:
- denyMAC = True
- if not is_permit and mac_type == self.WILD_MAC:
- denyIP = True
-
- if traffic == self.BRIDGED:
- if is_permit:
- src_mac = remote_dst_host._mac
- dst_mac = 'de:ad:00:00:00:00'
- src_ip4 = remote_dst_host.ip4
- dst_ip4 = src_if.remote_ip4
- src_ip6 = remote_dst_host.ip6
- dst_ip6 = src_if.remote_ip6
- ip_permit = src_ip6 if is_ip6 else src_ip4
- mac_permit = src_mac
- if denyMAC:
- mac = src_mac.split(':')
- mac[0] = format(int(mac[0], 16)+1, "02x")
- src_mac = ":".join(mac)
- if is_ip6:
- src_ip6 = ip_permit
- else:
- src_ip4 = ip_permit
- if denyIP:
- if ip_type != self.WILD_IP:
- src_mac = mac_permit
- src_ip4 = remote_dst_host.ip4
- dst_ip4 = src_if.remote_ip4
- src_ip6 = remote_dst_host.ip6
- dst_ip6 = src_if.remote_ip6
- else:
- if is_permit:
- src_mac = remote_dst_host._mac
- dst_mac = src_if.local_mac
- src_ip4 = src_if.remote_ip4
- dst_ip4 = remote_dst_host.ip4
- src_ip6 = src_if.remote_ip6
- dst_ip6 = remote_dst_host.ip6
- ip_permit = src_ip6 if is_ip6 else src_ip4
- mac_permit = src_mac
- if denyMAC:
- mac = src_mac.split(':')
- mac[0] = format(int(mac[0], 16) + 1, "02x")
- src_mac = ":".join(mac)
- if is_ip6:
- src_ip6 = ip_permit
- else:
- src_ip4 = ip_permit
- if denyIP:
- src_mac = remote_dst_host._mac
- if ip_type != self.WILD_IP:
- src_mac = mac_permit
- src_ip4 = remote_dst_host.ip4
- dst_ip4 = src_if.remote_ip4
- src_ip6 = remote_dst_host.ip6
- dst_ip6 = src_if.remote_ip6
-
- if is_permit:
- info = self.create_packet_info(src_if, dst_if)
- payload = self.info_to_payload(info)
- else:
- payload = "to be blocked"
-
- if mac_type == self.WILD_MAC:
- mac = src_mac.split(':')
- for i in range(1, 5):
- mac[i] = format(random.randint(0, 255), "02x")
- src_mac = ":".join(mac)
-
- # create packet
- packet = Ether(src=src_mac, dst=dst_mac)
- ip_rule = src_ip6 if is_ip6 else src_ip4
- if is_ip6:
- if ip_type != self.EXACT_IP:
- sub_ip = list(unpack('<16B', inet_pton(AF_INET6, ip_rule)))
- if ip_type == self.WILD_IP:
- sub_ip[0] = random.randint(240, 254)
- sub_ip[1] = random.randint(230, 239)
- sub_ip[14] = random.randint(100, 199)
- sub_ip[15] = random.randint(200, 255)
- elif ip_type == self.SUBNET_IP:
- if denyIP:
- sub_ip[2] = int(sub_ip[2]) + 1
- sub_ip[14] = random.randint(100, 199)
- sub_ip[15] = random.randint(200, 255)
- packed_src_ip6 = b''.join(
- [scapy.compat.chb(x) for x in sub_ip])
- src_ip6 = inet_ntop(AF_INET6, packed_src_ip6)
- packet /= IPv6(src=src_ip6, dst=dst_ip6)
- else:
- if ip_type != self.EXACT_IP:
- sub_ip = ip_rule.split('.')
- if ip_type == self.WILD_IP:
- sub_ip[0] = random.randint(1, 49)
- sub_ip[1] = random.randint(50, 99)
- sub_ip[2] = random.randint(100, 199)
- sub_ip[3] = random.randint(200, 255)
- elif ip_type == self.SUBNET_IP:
- if denyIP:
- sub_ip[1] = int(sub_ip[1])+1
- sub_ip[2] = random.randint(100, 199)
- sub_ip[3] = random.randint(200, 255)
- src_ip4 = '.'.join(['{!s}'.format(x) for x in sub_ip])
- packet /= IP(src=src_ip4, dst=dst_ip4, frag=0, flags=0)
-
- packet /= UDP(sport=src_port, dport=dst_port)/Raw(payload)
-
- packet[Raw].load += b" mac:%s" % scapy.compat.raw(src_mac)
-
- size = self.pg_if_packet_sizes[p % len(self.pg_if_packet_sizes)]
- if isinstance(src_if, VppSubInterface):
- size = size + 4
- if isinstance(src_if, VppDot1QSubint):
- if src_if is self.subifs[0]:
- if tags == self.PERMIT_TAGS:
- packet = src_if.add_dot1q_layer(packet, 10)
- else:
- packet = src_if.add_dot1q_layer(packet, 11)
- else:
- if tags == self.PERMIT_TAGS:
- packet = src_if.add_dot1q_layer(packet, 30)
- else:
- packet = src_if.add_dot1q_layer(packet, 33)
- elif isinstance(src_if, VppDot1ADSubint):
- if src_if is self.subifs[1]:
- if tags == self.PERMIT_TAGS:
- packet = src_if.add_dot1ad_layer(packet, 300, 400)
- else:
- packet = src_if.add_dot1ad_layer(packet, 333, 444)
- else:
- if tags == self.PERMIT_TAGS:
- packet = src_if.add_dot1ad_layer(packet, 600, 700)
- else:
- packet = src_if.add_dot1ad_layer(packet, 666, 777)
- self.extend_packet(packet, size)
- packets.append(packet)
-
- # create suitable MACIP rule
- if mac_type == self.EXACT_MAC:
- mac_rule = src_mac
- mac_mask = "ff:ff:ff:ff:ff:ff"
- elif mac_type == self.WILD_MAC:
- mac_rule = "00:00:00:00:00:00"
- mac_mask = "00:00:00:00:00:00"
- elif mac_type == self.OUI_MAC:
- mac = src_mac.split(':')
- mac[3] = mac[4] = mac[5] = '00'
- mac_rule = ":".join(mac)
- mac_mask = "ff:ff:ff:00:00:00"
-
- if is_ip6:
- if ip_type == self.WILD_IP:
- ip = "0::0"
- else:
- ip = src_ip6
- if ip_type == self.SUBNET_IP:
- sub_ip = list(unpack('<16B', inet_pton(AF_INET6, ip)))
- for i in range(8, 16):
- sub_ip[i] = 0
- packed_ip = b''.join(
- [scapy.compat.chb(x) for x in sub_ip])
- ip = inet_ntop(AF_INET6, packed_ip)
- else:
- if ip_type == self.WILD_IP:
- ip = "0.0.0.0"
- else:
- ip = src_ip4
- if ip_type == self.SUBNET_IP:
- sub_ip = ip.split('.')
- sub_ip[2] = sub_ip[3] = '0'
- ip = ".".join(sub_ip)
-
- prefix_len = 128 if is_ip6 else 32
- if ip_type == self.WILD_IP:
- prefix_len = 0
- elif ip_type == self.SUBNET_IP:
- prefix_len = 64 if is_ip6 else 16
- ip_rule = inet_pton(AF_INET6 if is_ip6 else AF_INET, ip)
-
- # create suitable ACL rule
- if is_permit:
- rule_l4_sport = packet[UDP].sport
- rule_l4_dport = packet[UDP].dport
- rule_family = AF_INET6 if packet.haslayer(IPv6) else AF_INET
- rule_prefix_len = 128 if packet.haslayer(IPv6) else 32
- rule_l3_layer = IPv6 if packet.haslayer(IPv6) else IP
- if packet.haslayer(IPv6):
- rule_l4_proto = packet[UDP].overload_fields[IPv6]['nh']
- else:
- rule_l4_proto = packet[IP].proto
-
- acl_rule = {
- 'is_permit': is_permit,
- 'is_ipv6': is_ip6,
- 'src_ip_addr': inet_pton(rule_family,
- packet[rule_l3_layer].src),
- 'src_ip_prefix_len': rule_prefix_len,
- 'dst_ip_addr': inet_pton(rule_family,
- packet[rule_l3_layer].dst),
- 'dst_ip_prefix_len': rule_prefix_len,
- 'srcport_or_icmptype_first': rule_l4_sport,
- 'srcport_or_icmptype_last': rule_l4_sport,
- 'dstport_or_icmpcode_first': rule_l4_dport,
- 'dstport_or_icmpcode_last': rule_l4_dport,
- 'proto': rule_l4_proto}
- acl_rules.append(acl_rule)
-
- if mac_type == self.WILD_MAC and ip_type == self.WILD_IP and p > 0:
- continue
-
- if is_permit:
- macip_rule = ({
- 'is_permit': is_permit,
- 'is_ipv6': is_ip6,
- 'src_ip_addr': ip_rule,
- 'src_ip_prefix_len': prefix_len,
- 'src_mac': binascii.unhexlify(mac_rule.replace(':', '')),
- 'src_mac_mask': binascii.unhexlify(
- mac_mask.replace(':', ''))})
- macip_rules.append(macip_rule)
-
- # deny all other packets
- if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP):
- macip_rule = ({'is_permit': 0,
- 'is_ipv6': is_ip6,
- 'src_ip_addr': "",
- 'src_ip_prefix_len': 0,
- 'src_mac': "",
- 'src_mac_mask': ""})
- macip_rules.append(macip_rule)
-
- acl_rule = {'is_permit': 0,
- 'is_ipv6': is_ip6}
- acl_rules.append(acl_rule)
- return {'stream': packets,
- 'macip_rules': macip_rules,
- 'acl_rules': acl_rules}
-
- def verify_capture(self, stream, capture, is_ip6):
- """
- :param stream:
- :param capture:
- :param is_ip6:
- :return:
- """
- # p_l3 = IPv6 if is_ip6 else IP
- # if self.DEBUG:
- # for p in stream:
- # print(p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst)
- #
- # acls = self.macip_acl_dump_debug()
-
- # TODO : verify
- # for acl in acls:
- # for r in acl.r:
- # print(binascii.hexlify(r.src_mac), \
- # binascii.hexlify(r.src_mac_mask),\
- # unpack('<16B', r.src_ip_addr), \
- # r.src_ip_prefix_len)
- #
- # for p in capture:
- # print(p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst
- # data = p[Raw].load.split(':',1)[1])
- # print(p[p_l3].src, data)
-
- def run_traffic(self, mac_type, ip_type, traffic, is_ip6, packets,
- do_not_expected_capture=False, tags=None,
- apply_rules=True, isMACIP=True, permit_tags=PERMIT_TAGS,
- try_replace=False):
- self.reset_packet_infos()
-
- if tags is None:
- tx_if = self.pg0 if traffic == self.BRIDGED else self.pg3
- rx_if = self.pg3 if traffic == self.BRIDGED else self.pg0
- src_if = self.pg3
- dst_if = self.loop0
- else:
- if tags == self.DOT1Q:
- if traffic == self.BRIDGED:
- tx_if = self.subifs[0]
- rx_if = self.pg0
- src_if = self.subifs[0]
- dst_if = self.loop0
- else:
- tx_if = self.subifs[2]
- rx_if = self.pg0
- src_if = self.subifs[2]
- dst_if = self.loop0
- elif tags == self.DOT1AD:
- if traffic == self.BRIDGED:
- tx_if = self.subifs[1]
- rx_if = self.pg0
- src_if = self.subifs[1]
- dst_if = self.loop0
- else:
- tx_if = self.subifs[3]
- rx_if = self.pg0
- src_if = self.subifs[3]
- dst_if = self.loop0
- else:
- return
-
- test_dict = self.create_stream(mac_type, ip_type, packets,
- src_if, dst_if,
- traffic, is_ip6,
- tags=permit_tags)
-
- if apply_rules:
- if isMACIP:
- reply = self.vapi.macip_acl_add(test_dict['macip_rules'])
- else:
- reply = self.vapi.acl_add_replace(acl_index=4294967295,
- r=test_dict['acl_rules'])
- self.assertEqual(reply.retval, 0)
- acl_index = reply.acl_index
-
- if isMACIP:
- self.vapi.macip_acl_interface_add_del(
- sw_if_index=tx_if.sw_if_index,
- acl_index=acl_index)
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.acls[tx_if.sw_if_index], acl_index)
- self.ACLS.append(reply.acls[tx_if.sw_if_index])
- else:
- self.vapi.acl_interface_add_del(
- sw_if_index=tx_if.sw_if_index, acl_index=acl_index)
- else:
- self.vapi.macip_acl_interface_add_del(
- sw_if_index=tx_if.sw_if_index,
- acl_index=0)
- if try_replace:
- if isMACIP:
- reply = self.vapi.macip_acl_add_replace(
- test_dict['macip_rules'],
- acl_index)
- else:
- reply = self.vapi.acl_add_replace(acl_index=acl_index,
- r=test_dict['acl_rules'])
- self.assertEqual(reply.retval, 0)
-
- if not isinstance(src_if, VppSubInterface):
- tx_if.add_stream(test_dict['stream'])
- else:
- tx_if.parent.add_stream(test_dict['stream'])
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- if do_not_expected_capture:
- rx_if.get_capture(0)
- else:
- if traffic == self.BRIDGED and mac_type == self.WILD_MAC and \
- ip_type == self.WILD_IP:
- capture = rx_if.get_capture(packets)
- else:
- capture = rx_if.get_capture(
- self.get_packet_count_for_if_idx(dst_if.sw_if_index))
- self.verify_capture(test_dict['stream'], capture, is_ip6)
- if not isMACIP:
- self.vapi.acl_interface_add_del(sw_if_index=tx_if.sw_if_index,
- acl_index=acl_index, is_add=0)
- self.vapi.acl_del(acl_index)
-
- def run_test_acls(self, mac_type, ip_type, acl_count,
- rules_count, traffic=None, ip=None):
- self.apply_macip_rules(self.create_rules(mac_type, ip_type, acl_count,
- rules_count))
- self.verify_macip_acls(acl_count, rules_count)
-
- if traffic is not None:
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, traffic, ip, 9)
-
-
-class TestMACIP_IP4(MethodHolder):
- """MACIP with IP4 traffic"""
-
- @classmethod
- def setUpClass(cls):
- super(TestMACIP_IP4, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestMACIP_IP4, cls).tearDownClass()
-
- def test_acl_bridged_ip4_exactMAC_exactIP(self):
- """ IP4 MACIP exactMAC|exactIP ACL bridged traffic
- """
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_exactMAC_subnetIP(self):
- """ IP4 MACIP exactMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_exactMAC_wildIP(self):
- """ IP4 MACIP exactMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_ouiMAC_exactIP(self):
- """ IP4 MACIP ouiMAC|exactIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP4, 3)
-
- def test_acl_bridged_ip4_ouiMAC_subnetIP(self):
- """ IP4 MACIP ouiMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_ouiMAC_wildIP(self):
- """ IP4 MACIP ouiMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_ac_bridgedl_ip4_wildMAC_exactIP(self):
- """ IP4 MACIP wildcardMAC|exactIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_wildMAC_subnetIP(self):
- """ IP4 MACIP wildcardMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_bridged_ip4_wildMAC_wildIP(self):
- """ IP4 MACIP wildcardMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_exactMAC_exactIP(self):
- """ IP4 MACIP exactMAC|exactIP ACL routed traffic
- """
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_exactMAC_subnetIP(self):
- """ IP4 MACIP exactMAC|subnetIP ACL routed traffic
- """
- self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_exactMAC_wildIP(self):
- """ IP4 MACIP exactMAC|wildIP ACL routed traffic
- """
- self.run_traffic(self.EXACT_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_ouiMAC_exactIP(self):
- """ IP4 MACIP ouiMAC|exactIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_ouiMAC_subnetIP(self):
- """ IP4 MACIP ouiMAC|subnetIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_ouiMAC_wildIP(self):
- """ IP4 MACIP ouiMAC|wildIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_wildMAC_exactIP(self):
- """ IP4 MACIP wildcardMAC|exactIP ACL routed traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_wildMAC_subnetIP(self):
- """ IP4 MACIP wildcardMAC|subnetIP ACL routed traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_routed_ip4_wildMAC_wildIP(self):
- """ IP4 MACIP wildcardMAC|wildIP ACL
- """
-
- self.run_traffic(self.WILD_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP4, 9)
-
- def test_acl_replace_traffic_ip4(self):
- """ MACIP replace ACL with IP4 traffic
- """
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP4, 9, try_replace=True)
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP4, 9, try_replace=True)
-
-
-class TestMACIP_IP6(MethodHolder):
- """MACIP with IP6 traffic"""
-
- @classmethod
- def setUpClass(cls):
- super(TestMACIP_IP6, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestMACIP_IP6, cls).tearDownClass()
-
- def test_acl_bridged_ip6_exactMAC_exactIP(self):
- """ IP6 MACIP exactMAC|exactIP ACL bridged traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_exactMAC_subnetIP(self):
- """ IP6 MACIP exactMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_exactMAC_wildIP(self):
- """ IP6 MACIP exactMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_ouiMAC_exactIP(self):
- """ IP6 MACIP oui_MAC|exactIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_ouiMAC_subnetIP(self):
- """ IP6 MACIP ouiMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_ouiMAC_wildIP(self):
- """ IP6 MACIP ouiMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_wildMAC_exactIP(self):
- """ IP6 MACIP wildcardMAC|exactIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_wildMAC_subnetIP(self):
- """ IP6 MACIP wildcardMAC|subnetIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_bridged_ip6_wildMAC_wildIP(self):
- """ IP6 MACIP wildcardMAC|wildIP ACL bridged traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.WILD_IP,
- self.BRIDGED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_exactMAC_exactIP(self):
- """ IP6 MACIP exactMAC|exactIP ACL routed traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_exactMAC_subnetIP(self):
- """ IP6 MACIP exactMAC|subnetIP ACL routed traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_exactMAC_wildIP(self):
- """ IP6 MACIP exactMAC|wildIP ACL routed traffic
- """
-
- self.run_traffic(self.EXACT_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_ouiMAC_exactIP(self):
- """ IP6 MACIP ouiMAC|exactIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_ouiMAC_subnetIP(self):
- """ IP6 MACIP ouiMAC|subnetIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_ouiMAC_wildIP(self):
- """ IP6 MACIP ouiMAC|wildIP ACL routed traffic
- """
-
- self.run_traffic(self.OUI_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_wildMAC_exactIP(self):
- """ IP6 MACIP wildcardMAC|exactIP ACL routed traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.EXACT_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_wildMAC_subnetIP(self):
- """ IP6 MACIP wildcardMAC|subnetIP ACL routed traffic
- """
-
- self.run_traffic(self.WILD_MAC, self.SUBNET_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_routed_ip6_wildMAC_wildIP(self):
- """ IP6 MACIP wildcardMAC|wildIP ACL
- """
-
- self.run_traffic(self.WILD_MAC, self.WILD_IP,
- self.ROUTED, self.IS_IP6, 9)
-
- def test_acl_replace_traffic_ip6(self):
- """ MACIP replace ACL with IP6 traffic
- """
- self.run_traffic(self.OUI_MAC, self.SUBNET_IP,
- self.BRIDGED, self.IS_IP6, 9, try_replace=True)
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP,
- self.BRIDGED, self.IS_IP6, 9, try_replace=True)
-
-
-class TestMACIP(MethodHolder):
- """MACIP Tests"""
-
- @classmethod
- def setUpClass(cls):
- super(TestMACIP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestMACIP, cls).tearDownClass()
-
- def test_acl_1_2(self):
- """ MACIP ACL with 2 entries
- """
-
- self.run_test_acls(self.EXACT_MAC, self.WILD_IP, 1, [2])
-
- def test_acl_1_5(self):
- """ MACIP ACL with 5 entries
- """
-
- self.run_test_acls(self.EXACT_MAC, self.SUBNET_IP, 1, [5])
-
- def test_acl_1_10(self):
- """ MACIP ACL with 10 entries
- """
-
- self.run_test_acls(self.EXACT_MAC, self.EXACT_IP, 1, [10])
-
- def test_acl_1_20(self):
- """ MACIP ACL with 20 entries
- """
-
- self.run_test_acls(self.OUI_MAC, self.WILD_IP, 1, [20])
-
- def test_acl_1_50(self):
- """ MACIP ACL with 50 entries
- """
-
- self.run_test_acls(self.OUI_MAC, self.SUBNET_IP, 1, [50])
-
- def test_acl_1_100(self):
- """ MACIP ACL with 100 entries
- """
-
- self.run_test_acls(self.OUI_MAC, self.EXACT_IP, 1, [100])
-
- def test_acl_2_X(self):
- """ MACIP 2 ACLs each with 100+ entries
- """
-
- self.run_test_acls(self.OUI_MAC, self.SUBNET_IP, 2, [100, 200])
-
- def test_acl_10_X(self):
- """ MACIP 10 ACLs each with 100+ entries
- """
-
- self.run_test_acls(self.EXACT_MAC, self.EXACT_IP, 10,
- [100, 120, 140, 160, 180, 200, 210, 220, 230, 240])
-
- def test_acl_10_X_traffic_ip4(self):
- """ MACIP 10 ACLs each with 100+ entries with IP4 traffic
- """
-
- self.run_test_acls(self.EXACT_MAC, self.EXACT_IP, 10,
- [100, 120, 140, 160, 180, 200, 210, 220, 230, 240],
- self.BRIDGED, self.IS_IP4)
-
- def test_acl_10_X_traffic_ip6(self):
- """ MACIP 10 ACLs each with 100+ entries with IP6 traffic
- """
-
- self.run_test_acls(self.EXACT_MAC, self.EXACT_IP, 10,
- [100, 120, 140, 160, 180, 200, 210, 220, 230, 240],
- self.BRIDGED, self.IS_IP6)
-
- def test_acl_replace(self):
- """ MACIP replace ACL
- """
-
- r1 = self.create_rules(acl_count=3, rules_count=[2, 2, 2])
- r2 = self.create_rules(mac_type=self.OUI_MAC, ip_type=self.SUBNET_IP)
- self.apply_macip_rules(r1)
-
- acls_before = self.macip_acl_dump_debug()
-
- # replace acls #2, #3 with new
- reply = self.vapi.macip_acl_add_replace(r2[0], 2)
- self.assertEqual(reply.retval, 0)
- self.assertEqual(reply.acl_index, 2)
- reply = self.vapi.macip_acl_add_replace(r2[1], 3)
- self.assertEqual(reply.retval, 0)
- self.assertEqual(reply.acl_index, 3)
-
- acls_after = self.macip_acl_dump_debug()
-
- # verify changes
- self.assertEqual(len(acls_before), len(acls_after))
- for acl1, acl2 in zip(
- acls_before[:2]+acls_before[4:],
- acls_after[:2]+acls_after[4:]):
- self.assertEqual(len(acl1), len(acl2))
-
- self.assertEqual(len(acl1.r), len(acl2.r))
- for r1, r2 in zip(acl1.r, acl2.r):
- self.assertEqual(len(acl1.r), len(acl2.r))
- self.assertEqual(acl1.r, acl2.r)
- for acl1, acl2 in zip(
- acls_before[2:4],
- acls_after[2:4]):
- self.assertEqual(len(acl1), len(acl2))
-
- self.assertNotEqual(len(acl1.r), len(acl2.r))
- for r1, r2 in zip(acl1.r, acl2.r):
- self.assertNotEqual(len(acl1.r), len(acl2.r))
- self.assertNotEqual(acl1.r, acl2.r)
-
- def test_delete_intf(self):
- """ MACIP ACL delete intf with acl
- """
-
- intf_count = len(self.interfaces)+1
- intf = []
- self.apply_macip_rules(self.create_rules(acl_count=3,
- rules_count=[3, 5, 4]))
-
- intf.append(VppLoInterface(self))
- intf.append(VppLoInterface(self))
-
- sw_if_index0 = intf[0].sw_if_index
- self.vapi.macip_acl_interface_add_del(sw_if_index0, 1)
-
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, intf_count+1)
- self.assertEqual(reply.acls[sw_if_index0], 1)
-
- sw_if_index1 = intf[1].sw_if_index
- self.vapi.macip_acl_interface_add_del(sw_if_index1, 0)
-
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, intf_count+2)
- self.assertEqual(reply.acls[sw_if_index1], 0)
-
- intf[0].remove_vpp_config()
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, intf_count+2)
- self.assertEqual(reply.acls[sw_if_index0], 4294967295)
- self.assertEqual(reply.acls[sw_if_index1], 0)
-
- intf.append(VppLoInterface(self))
- intf.append(VppLoInterface(self))
- sw_if_index2 = intf[2].sw_if_index
- sw_if_index3 = intf[3].sw_if_index
- self.vapi.macip_acl_interface_add_del(sw_if_index2, 1)
- self.vapi.macip_acl_interface_add_del(sw_if_index3, 1)
-
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, intf_count+3)
- self.assertEqual(reply.acls[sw_if_index1], 0)
- self.assertEqual(reply.acls[sw_if_index2], 1)
- self.assertEqual(reply.acls[sw_if_index3], 1)
- self.logger.info("MACIP ACL on multiple interfaces:")
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl index 1234"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl index 1"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl index 0"))
- self.logger.info(self.vapi.ppcli("sh acl-plugin macip interface"))
-
- intf[2].remove_vpp_config()
- intf[1].remove_vpp_config()
-
- reply = self.vapi.macip_acl_interface_get()
- self.assertEqual(reply.count, intf_count+3)
- self.assertEqual(reply.acls[sw_if_index0], 4294967295)
- self.assertEqual(reply.acls[sw_if_index1], 4294967295)
- self.assertEqual(reply.acls[sw_if_index2], 4294967295)
- self.assertEqual(reply.acls[sw_if_index3], 1)
-
- intf[3].remove_vpp_config()
- reply = self.vapi.macip_acl_interface_get()
-
- self.assertEqual(len([x for x in reply.acls if x != 4294967295]), 0)
-
-
-class TestACL_dot1q_bridged(MethodHolder):
- """ACL on dot1q bridged subinterfaces Tests"""
-
- @classmethod
- def setUpClass(cls):
- super(TestACL_dot1q_bridged, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestACL_dot1q_bridged, cls).tearDownClass()
-
- def test_acl_bridged_ip4_subif_dot1q(self):
- """ IP4 ACL SubIf Dot1Q bridged traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
- self.IS_IP4, 9, tags=self.DOT1Q, isMACIP=False)
-
- def test_acl_bridged_ip6_subif_dot1q(self):
- """ IP6 ACL SubIf Dot1Q bridged traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
- self.IS_IP6, 9, tags=self.DOT1Q, isMACIP=False)
-
-
-class TestACL_dot1ad_bridged(MethodHolder):
- """ACL on dot1ad bridged subinterfaces Tests"""
-
- @classmethod
- def setUpClass(cls):
- super(TestACL_dot1ad_bridged, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestACL_dot1ad_bridged, cls).tearDownClass()
-
- def test_acl_bridged_ip4_subif_dot1ad(self):
- """ IP4 ACL SubIf Dot1AD bridged traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
- self.IS_IP4, 9, tags=self.DOT1AD, isMACIP=False)
-
- def test_acl_bridged_ip6_subif_dot1ad(self):
- """ IP6 ACL SubIf Dot1AD bridged traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED,
- self.IS_IP6, 9, tags=self.DOT1AD, isMACIP=False)
-
-
-class TestACL_dot1q_routed(MethodHolder):
- """ACL on dot1q routed subinterfaces Tests"""
-
- @classmethod
- def setUpClass(cls):
- super(TestACL_dot1q_routed, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestACL_dot1q_routed, cls).tearDownClass()
-
- def test_acl_routed_ip4_subif_dot1q(self):
- """ IP4 ACL SubIf Dot1Q routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP4, 9, tags=self.DOT1Q, isMACIP=False)
-
- def test_acl_routed_ip6_subif_dot1q(self):
- """ IP6 ACL SubIf Dot1Q routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP6, 9, tags=self.DOT1Q, isMACIP=False)
-
- def test_acl_routed_ip4_subif_dot1q_deny_by_tags(self):
- """ IP4 ACL SubIf wrong tags Dot1Q routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP4, 9, True, tags=self.DOT1Q, isMACIP=False,
- permit_tags=self.DENY_TAGS)
-
- def test_acl_routed_ip6_subif_dot1q_deny_by_tags(self):
- """ IP6 ACL SubIf wrong tags Dot1Q routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP6, 9, True, tags=self.DOT1Q, isMACIP=False,
- permit_tags=self.DENY_TAGS)
-
-
-class TestACL_dot1ad_routed(MethodHolder):
- """ACL on dot1ad routed subinterfaces Tests"""
-
- @classmethod
- def setUpClass(cls):
- super(TestACL_dot1ad_routed, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestACL_dot1ad_routed, cls).tearDownClass()
-
- def test_acl_routed_ip6_subif_dot1ad(self):
- """ IP6 ACL SubIf Dot1AD routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP6, 9, tags=self.DOT1AD, isMACIP=False)
-
- def test_acl_routed_ip4_subif_dot1ad(self):
- """ IP4 ACL SubIf Dot1AD routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP4, 9, tags=self.DOT1AD, isMACIP=False)
-
- def test_acl_routed_ip6_subif_dot1ad_deny_by_tags(self):
- """ IP6 ACL SubIf wrong tags Dot1AD routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP6, 9, True, tags=self.DOT1AD, isMACIP=False,
- permit_tags=self.DENY_TAGS)
-
- def test_acl_routed_ip4_subif_dot1ad_deny_by_tags(self):
- """ IP4 ACL SubIf wrong tags Dot1AD routed traffic"""
- self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.ROUTED,
- self.IS_IP4, 9, True, tags=self.DOT1AD, isMACIP=False,
- permit_tags=self.DENY_TAGS)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_cdp.py b/test/test_cdp.py
deleted file mode 100644
index 7f77b4bbb01..00000000000
--- a/test/test_cdp.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/env python
-""" CDP tests """
-
-from scapy.packet import Packet
-from scapy.all import ShortField, StrField
-from scapy.layers.l2 import Dot3, LLC, SNAP
-from scapy.contrib.cdp import CDPMsgDeviceID, CDPMsgSoftwareVersion, \
- CDPMsgPlatform, CDPMsgPortID, CDPv2_HDR
-
-from framework import VppTestCase
-from scapy.all import raw
-from re import compile
-from time import sleep
-from util import ppp
-import platform
-
-
-""" TestCDP is a subclass of VPPTestCase classes.
-
-CDP test.
-
-"""
-
-
-class CustomTLV(Packet):
- """ Custom TLV protocol layer for scapy """
-
- fields_desc = [
- ShortField("type", 0),
- ShortField("length", 4),
- StrField("value", "")
-
- ]
-
-
-class TestCDP(VppTestCase):
- """ CDP Test Case """
-
- nen_ptr = compile(r"not enabled")
- cdp_ptr = compile(r"^([-\.\w]+)\s+([-\.\w]+)\s+([-\.\w]+)\s+([-\.\w]+)$")
- err_ptr = compile(r"^([\d]+)\s+([-\w]+)\s+([ -\.\w)(]+)$")
-
- @property
- def device_id(self):
- return platform.node()
-
- @property
- def version(self):
- return platform.release()
-
- @property
- def port_id(self):
- return self.interface.name
-
- @property
- def platform(self):
- return platform.system()
-
- @classmethod
- def setUpClass(cls):
- super(TestCDP, cls).setUpClass()
- try:
- cls.create_pg_interfaces(range(1))
- cls.interface = cls.pg_interfaces[0]
-
- cls.interface.admin_up()
- cls.interface.config_ip4()
- cls.interface.resolve_arp()
-
- except Exception:
- super(TestCDP, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestCDP, cls).tearDownClass()
-
- def test_enable_cdp(self):
- self.logger.info(self.vapi.cdp_enable_disable(enable_disable=1))
- ret = self.vapi.cli("show cdp")
- self.logger.info(ret)
- not_enabled = self.nen_ptr.search(ret)
- self.assertFalse(not_enabled, "CDP isn't enabled")
-
- def test_send_cdp_packet(self):
- self.logger.info(self.vapi.cdp_enable_disable(enable_disable=1))
- self.send_packet(self.create_packet())
-
- neighbors = list(self.show_cdp())
- self.assertTrue(neighbors, "CDP didn't register neighbor")
-
- port, system = neighbors[0]
- length = min(len(system), len(self.device_id))
-
- self.assert_equal(port, self.port_id, "CDP received invalid port id")
- self.assert_equal(system[:length], self.device_id[:length],
- "CDP received invalid device id")
-
- def test_cdp_underflow_tlv(self):
- self.send_bad_packet(3, ".")
-
- def test_cdp_overflow_tlv(self):
- self.send_bad_packet(8, ".")
-
- def send_bad_packet(self, l, v):
- self.logger.info(self.vapi.cdp_enable_disable(enable_disable=1))
- self.send_packet(self.create_bad_packet(l, v))
-
- errors = list(self.show_errors())
- self.assertTrue(errors)
-
- expected_errors = False
- for count, node, reason in errors:
- if (node == u'cdp-input' and
- reason == u'cdp packets with bad TLVs' and
- int(count) >= 1):
-
- expected_errors = True
- break
- self.assertTrue(expected_errors, "CDP didn't drop bad packet")
-
- def send_packet(self, packet):
- self.logger.debug(ppp("Sending packet:", packet))
- self.interface.add_stream(packet)
- self.pg_start()
-
- def create_base_packet(self):
- packet = (Dot3(src=self.interface.remote_mac,
- dst="01:00:0c:cc:cc:cc") /
- LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03) /
- SNAP()/CDPv2_HDR())
- return packet
-
- def create_packet(self):
- packet = (self.create_base_packet() /
- CDPMsgDeviceID(val=self.device_id) /
- CDPMsgSoftwareVersion(val=self.version) /
- CDPMsgPortID(iface=self.port_id) /
- CDPMsgPlatform(val=self.platform))
- return packet
-
- def create_bad_packet(self, tl=4, tv=""):
- packet = (self.create_base_packet() /
- CustomTLV(type=1,
- length=tl,
- value=tv))
- return packet
-
- def process_cli(self, exp, ptr):
- for line in self.vapi.cli(exp).split('\n')[1:]:
- m = ptr.match(line.strip())
- if m:
- yield m.groups()
-
- def show_cdp(self):
- for pack in self.process_cli("show cdp", self.cdp_ptr):
- try:
- port, system, _, _ = pack
- except ValueError:
- pass
- else:
- yield port, system
-
- def show_errors(self):
- for pack in self.process_cli("show errors", self.err_ptr):
- try:
- count, node, reason = pack
- except ValueError:
- pass
- else:
- yield count, node, reason
diff --git a/test/test_classify_l2_acl.py b/test/test_classify_l2_acl.py
deleted file mode 100644
index 8ba7181aef1..00000000000
--- a/test/test_classify_l2_acl.py
+++ /dev/null
@@ -1,689 +0,0 @@
-#!/usr/bin/env python
-""" Classifier-based L2 ACL Test Case HLD:
-"""
-
-import unittest
-import random
-import binascii
-import socket
-
-
-from scapy.packet import Raw
-from scapy.data import ETH_P_IP
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, TCP, UDP, ICMP
-from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest
-from scapy.layers.inet6 import IPv6ExtHdrFragment
-from framework import VppTestCase, VppTestRunner
-from util import Host, ppp
-
-
-class TestClassifyAcl(VppTestCase):
- """ Classifier-based L2 input and output ACL Test Case """
-
- # traffic types
- IP = 0
- ICMP = 1
-
- # IP version
- IPRANDOM = -1
- IPV4 = 0
- IPV6 = 1
-
- # rule types
- DENY = 0
- PERMIT = 1
-
- # supported protocols
- proto = [[6, 17], [1, 58]]
- proto_map = {1: 'ICMP', 58: 'ICMPv6EchoRequest', 6: 'TCP', 17: 'UDP'}
- ICMPv4 = 0
- ICMPv6 = 1
- TCP = 0
- UDP = 1
- PROTO_ALL = 0
-
- # port ranges
- PORTS_ALL = -1
- PORTS_RANGE = 0
- PORTS_RANGE_2 = 1
- udp_sport_from = 10
- udp_sport_to = udp_sport_from + 5
- udp_dport_from = 20000
- udp_dport_to = udp_dport_from + 5000
- tcp_sport_from = 30
- tcp_sport_to = tcp_sport_from + 5
- tcp_dport_from = 40000
- tcp_dport_to = tcp_dport_from + 5000
-
- udp_sport_from_2 = 90
- udp_sport_to_2 = udp_sport_from_2 + 5
- udp_dport_from_2 = 30000
- udp_dport_to_2 = udp_dport_from_2 + 5000
- tcp_sport_from_2 = 130
- tcp_sport_to_2 = tcp_sport_from_2 + 5
- tcp_dport_from_2 = 20000
- tcp_dport_to_2 = tcp_dport_from_2 + 5000
-
- icmp4_type = 8 # echo request
- icmp4_code = 3
- icmp6_type = 128 # echo request
- icmp6_code = 3
-
- icmp4_type_2 = 8
- icmp4_code_from_2 = 5
- icmp4_code_to_2 = 20
- icmp6_type_2 = 128
- icmp6_code_from_2 = 8
- icmp6_code_to_2 = 42
-
- # Test variables
- bd_id = 1
-
- @classmethod
- def setUpClass(cls):
- """
- Perform standard class setup (defined by class method setUpClass in
- class VppTestCase) before running the test case, set test case related
- variables and configure VPP.
- """
- super(TestClassifyAcl, cls).setUpClass()
-
- try:
- # Create 2 pg interfaces
- cls.create_pg_interfaces(range(2))
-
- # Packet flows mapping pg0 -> pg1, pg2 etc.
- cls.flows = dict()
- cls.flows[cls.pg0] = [cls.pg1]
-
- # Packet sizes
- cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
-
- # Create BD with MAC learning and unknown unicast flooding disabled
- # and put interfaces to this BD
- cls.vapi.bridge_domain_add_del(bd_id=cls.bd_id, uu_flood=1,
- learn=1)
- for pg_if in cls.pg_interfaces:
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id)
-
- # Set up all interfaces
- for i in cls.pg_interfaces:
- i.admin_up()
-
- # Mapping between packet-generator index and lists of test hosts
- cls.hosts_by_pg_idx = dict()
- for pg_if in cls.pg_interfaces:
- cls.hosts_by_pg_idx[pg_if.sw_if_index] = []
-
- # Create list of deleted hosts
- cls.deleted_hosts_by_pg_idx = dict()
- for pg_if in cls.pg_interfaces:
- cls.deleted_hosts_by_pg_idx[pg_if.sw_if_index] = []
-
- # warm-up the mac address tables
- # self.warmup_test()
-
- # Holder of the active classify table key
- cls.acl_active_table = ''
-
- except Exception:
- super(TestClassifyAcl, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestClassifyAcl, cls).tearDownClass()
-
- def setUp(self):
- super(TestClassifyAcl, self).setUp()
-
- self.acl_tbl_idx = {}
- self.reset_packet_infos()
-
- def tearDown(self):
- """
- Show various debug prints after each test.
- """
- if not self.vpp_dead:
- if self.acl_active_table == 'mac_inout':
- self.output_acl_set_interface(
- self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0)
- self.input_acl_set_interface(
- self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0)
- self.acl_active_table = ''
- elif self.acl_active_table == 'mac_out':
- self.output_acl_set_interface(
- self.pg1, self.acl_tbl_idx.get(self.acl_active_table), 0)
- self.acl_active_table = ''
- elif self.acl_active_table == 'mac_in':
- self.input_acl_set_interface(
- self.pg0, self.acl_tbl_idx.get(self.acl_active_table), 0)
- self.acl_active_table = ''
-
- super(TestClassifyAcl, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.ppcli("show inacl type l2"))
- self.logger.info(self.vapi.ppcli("show outacl type l2"))
- self.logger.info(self.vapi.ppcli("show classify tables verbose"))
- self.logger.info(self.vapi.ppcli("show bridge-domain %s detail"
- % self.bd_id))
-
- @staticmethod
- def build_mac_mask(dst_mac='', src_mac='', ether_type=''):
- """Build MAC ACL mask data with hexstring format
-
- :param str dst_mac: source MAC address <0-ffffffffffff>
- :param str src_mac: destination MAC address <0-ffffffffffff>
- :param str ether_type: ethernet type <0-ffff>
- """
-
- return ('{!s:0>12}{!s:0>12}{!s:0>4}'.format(
- dst_mac, src_mac, ether_type)).rstrip('0')
-
- @staticmethod
- def build_mac_match(dst_mac='', src_mac='', ether_type=''):
- """Build MAC ACL match data with hexstring format
-
- :param str dst_mac: source MAC address <x:x:x:x:x:x>
- :param str src_mac: destination MAC address <x:x:x:x:x:x>
- :param str ether_type: ethernet type <0-ffff>
- """
- if dst_mac:
- dst_mac = dst_mac.replace(':', '')
- if src_mac:
- src_mac = src_mac.replace(':', '')
-
- return ('{!s:0>12}{!s:0>12}{!s:0>4}'.format(
- dst_mac, src_mac, ether_type)).rstrip('0')
-
- def create_classify_table(self, key, mask, data_offset=0, is_add=1):
- """Create Classify Table
-
- :param str key: key for classify table (ex, ACL name).
- :param str mask: mask value for interested traffic.
- :param int match_n_vectors:
- :param int is_add: option to configure classify table.
- - create(1) or delete(0)
- """
- r = self.vapi.classify_add_del_table(
- is_add,
- binascii.unhexlify(mask),
- match_n_vectors=(len(mask) - 1) // 32 + 1,
- miss_next_index=0,
- current_data_flag=1,
- current_data_offset=data_offset)
- self.assertIsNotNone(r, 'No response msg for add_del_table')
- self.acl_tbl_idx[key] = r.new_table_index
-
- def create_classify_session(self, intf, table_index, match,
- hit_next_index=0xffffffff, is_add=1):
- """Create Classify Session
-
- :param VppInterface intf: Interface to apply classify session.
- :param int table_index: table index to identify classify table.
- :param str match: matched value for interested traffic.
- :param int pbr_action: enable/disable PBR feature.
- :param int vrfid: VRF id.
- :param int is_add: option to configure classify session.
- - create(1) or delete(0)
- """
- r = self.vapi.classify_add_del_session(
- is_add,
- table_index,
- binascii.unhexlify(match),
- hit_next_index=hit_next_index)
- self.assertIsNotNone(r, 'No response msg for add_del_session')
-
- def input_acl_set_interface(self, intf, table_index, is_add=1):
- """Configure Input ACL interface
-
- :param VppInterface intf: Interface to apply Input ACL feature.
- :param int table_index: table index to identify classify table.
- :param int is_add: option to configure classify session.
- - enable(1) or disable(0)
- """
- r = self.vapi.input_acl_set_interface(
- is_add,
- intf.sw_if_index,
- l2_table_index=table_index)
- self.assertIsNotNone(r, 'No response msg for acl_set_interface')
-
- def output_acl_set_interface(self, intf, table_index, is_add=1):
- """Configure Output ACL interface
-
- :param VppInterface intf: Interface to apply Output ACL feature.
- :param int table_index: table index to identify classify table.
- :param int is_add: option to configure classify session.
- - enable(1) or disable(0)
- """
- r = self.vapi.output_acl_set_interface(
- is_add,
- intf.sw_if_index,
- l2_table_index=table_index)
- self.assertIsNotNone(r, 'No response msg for acl_set_interface')
-
- def create_hosts(self, count, start=0):
- """
- Create required number of host MAC addresses and distribute them among
- interfaces. Create host IPv4 address for every host MAC address.
-
- :param int count: Number of hosts to create MAC/IPv4 addresses for.
- :param int start: Number to start numbering from.
- """
- n_int = len(self.pg_interfaces)
- macs_per_if = count / n_int
- i = -1
- for pg_if in self.pg_interfaces:
- i += 1
- start_nr = macs_per_if * i + start
- end_nr = count + start if i == (n_int - 1) \
- else macs_per_if * (i + 1) + start
- hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
- for j in range(start_nr, end_nr):
- host = Host(
- "00:00:00:ff:%02x:%02x" % (pg_if.sw_if_index, j),
- "172.17.1%02x.%u" % (pg_if.sw_if_index, j),
- "2017:dead:%02x::%u" % (pg_if.sw_if_index, j))
- hosts.append(host)
-
- def create_upper_layer(self, packet_index, proto, ports=0):
- p = self.proto_map[proto]
- if p == 'UDP':
- if ports == 0:
- return UDP(sport=random.randint(self.udp_sport_from,
- self.udp_sport_to),
- dport=random.randint(self.udp_dport_from,
- self.udp_dport_to))
- else:
- return UDP(sport=ports, dport=ports)
- elif p == 'TCP':
- if ports == 0:
- return TCP(sport=random.randint(self.tcp_sport_from,
- self.tcp_sport_to),
- dport=random.randint(self.tcp_dport_from,
- self.tcp_dport_to))
- else:
- return TCP(sport=ports, dport=ports)
- return ''
-
- def create_stream(self, src_if, packet_sizes, traffic_type=0, ipv6=0,
- proto=-1, ports=0, fragments=False,
- pkt_raw=True, etype=-1):
- """
- Create input packet stream for defined interface using hosts or
- deleted_hosts list.
-
- :param object src_if: Interface to create packet stream for.
- :param list packet_sizes: List of required packet sizes.
- :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
- :return: Stream of packets.
- """
- pkts = []
- if self.flows.__contains__(src_if):
- src_hosts = self.hosts_by_pg_idx[src_if.sw_if_index]
- for dst_if in self.flows[src_if]:
- dst_hosts = self.hosts_by_pg_idx[dst_if.sw_if_index]
- n_int = len(dst_hosts) * len(src_hosts)
- for i in range(0, n_int):
- dst_host = dst_hosts[i / len(src_hosts)]
- src_host = src_hosts[i % len(src_hosts)]
- pkt_info = self.create_packet_info(src_if, dst_if)
- if ipv6 == 1:
- pkt_info.ip = 1
- elif ipv6 == 0:
- pkt_info.ip = 0
- else:
- pkt_info.ip = random.choice([0, 1])
- if proto == -1:
- pkt_info.proto = random.choice(self.proto[self.IP])
- else:
- pkt_info.proto = proto
- payload = self.info_to_payload(pkt_info)
- p = Ether(dst=dst_host.mac, src=src_host.mac)
- if etype > 0:
- p = Ether(dst=dst_host.mac,
- src=src_host.mac,
- type=etype)
- if pkt_info.ip:
- p /= IPv6(dst=dst_host.ip6, src=src_host.ip6)
- if fragments:
- p /= IPv6ExtHdrFragment(offset=64, m=1)
- else:
- if fragments:
- p /= IP(src=src_host.ip4, dst=dst_host.ip4,
- flags=1, frag=64)
- else:
- p /= IP(src=src_host.ip4, dst=dst_host.ip4)
- if traffic_type == self.ICMP:
- if pkt_info.ip:
- p /= ICMPv6EchoRequest(type=self.icmp6_type,
- code=self.icmp6_code)
- else:
- p /= ICMP(type=self.icmp4_type,
- code=self.icmp4_code)
- else:
- p /= self.create_upper_layer(i, pkt_info.proto, ports)
- if pkt_raw:
- p /= Raw(payload)
- pkt_info.data = p.copy()
- if pkt_raw:
- size = random.choice(packet_sizes)
- self.extend_packet(p, size)
- pkts.append(p)
- return pkts
-
- def verify_capture(self, pg_if, capture,
- traffic_type=0, ip_type=0, etype=-1):
- """
- Verify captured input packet stream for defined interface.
-
- :param object pg_if: Interface to verify captured packet stream for.
- :param list capture: Captured packet stream.
- :param traffic_type: 1: ICMP packet, 2: IPv6 with EH, 0: otherwise.
- """
- last_info = dict()
- for i in self.pg_interfaces:
- last_info[i.sw_if_index] = None
- dst_sw_if_index = pg_if.sw_if_index
- for packet in capture:
- if etype > 0:
- if packet[Ether].type != etype:
- self.logger.error(ppp("Unexpected ethertype in packet:",
- packet))
- else:
- continue
- try:
- # Raw data for ICMPv6 are stored in ICMPv6EchoRequest.data
- if traffic_type == self.ICMP and ip_type == self.IPV6:
- payload_info = self.payload_to_info(
- packet[ICMPv6EchoRequest].data)
- payload = packet[ICMPv6EchoRequest]
- else:
- payload_info = self.payload_to_info(packet[Raw])
- payload = packet[self.proto_map[payload_info.proto]]
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- if ip_type != 0:
- self.assertEqual(payload_info.ip, ip_type)
- if traffic_type == self.ICMP:
- try:
- if payload_info.ip == 0:
- self.assertEqual(payload.type, self.icmp4_type)
- self.assertEqual(payload.code, self.icmp4_code)
- else:
- self.assertEqual(payload.type, self.icmp6_type)
- self.assertEqual(payload.code, self.icmp6_code)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
- else:
- try:
- ip_version = IPv6 if payload_info.ip == 1 else IP
-
- ip = packet[ip_version]
- packet_index = payload_info.index
-
- self.assertEqual(payload_info.dst, dst_sw_if_index)
- self.logger.debug("Got packet on port %s: src=%u (id=%u)" %
- (pg_if.name, payload_info.src,
- packet_index))
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- self.assertTrue(next_info is not None)
- self.assertEqual(packet_index, next_info.index)
- saved_packet = next_info.data
- # Check standard fields
- self.assertEqual(ip.src, saved_packet[ip_version].src)
- self.assertEqual(ip.dst, saved_packet[ip_version].dst)
- p = self.proto_map[payload_info.proto]
- if p == 'TCP':
- tcp = packet[TCP]
- self.assertEqual(tcp.sport, saved_packet[
- TCP].sport)
- self.assertEqual(tcp.dport, saved_packet[
- TCP].dport)
- elif p == 'UDP':
- udp = packet[UDP]
- self.assertEqual(udp.sport, saved_packet[
- UDP].sport)
- self.assertEqual(udp.dport, saved_packet[
- UDP].dport)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:",
- packet))
- raise
- for i in self.pg_interfaces:
- remaining_packet = self.get_next_packet_info_for_interface2(
- i, dst_sw_if_index, last_info[i.sw_if_index])
- self.assertTrue(
- remaining_packet is None,
- "Port %u: Packet expected from source %u didn't arrive" %
- (dst_sw_if_index, i.sw_if_index))
-
- def run_traffic_no_check(self):
- # Test
- # Create incoming packet streams for packet-generator interfaces
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes)
- if len(pkts) > 0:
- i.add_stream(pkts)
-
- # Enable packet capture and start packet sending
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- def run_verify_test(self, traffic_type=0, ip_type=0, proto=-1, ports=0,
- frags=False, pkt_raw=True, etype=-1):
- # Test
- # Create incoming packet streams for packet-generator interfaces
- pkts_cnt = 0
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes,
- traffic_type, ip_type, proto, ports,
- frags, pkt_raw, etype)
- if len(pkts) > 0:
- i.add_stream(pkts)
- pkts_cnt += len(pkts)
-
- # Enable packet capture and start packet sendingself.IPV
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Verify
- # Verify outgoing packet streams per packet-generator interface
- for src_if in self.pg_interfaces:
- if self.flows.__contains__(src_if):
- for dst_if in self.flows[src_if]:
- capture = dst_if.get_capture(pkts_cnt)
- self.logger.info("Verifying capture on interface %s" %
- dst_if.name)
- self.verify_capture(dst_if, capture,
- traffic_type, ip_type, etype)
-
- def run_verify_negat_test(self, traffic_type=0, ip_type=0, proto=-1,
- ports=0, frags=False, etype=-1):
- # Test
- self.reset_packet_infos()
- for i in self.pg_interfaces:
- if self.flows.__contains__(i):
- pkts = self.create_stream(i, self.pg_if_packet_sizes,
- traffic_type, ip_type, proto, ports,
- frags, True, etype)
- if len(pkts) > 0:
- i.add_stream(pkts)
-
- # Enable packet capture and start packet sending
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Verify
- # Verify outgoing packet streams per packet-generator interface
- for src_if in self.pg_interfaces:
- if self.flows.__contains__(src_if):
- for dst_if in self.flows[src_if]:
- self.logger.info("Verifying capture on interface %s" %
- dst_if.name)
- capture = dst_if.get_capture(0)
- self.assertEqual(len(capture), 0)
-
- def build_classify_table(self, src_mac='', dst_mac='', ether_type='',
- etype='', key='mac', hit_next_index=0xffffffff):
- # Basic ACL testing
- a_mask = self.build_mac_mask(src_mac=src_mac, dst_mac=dst_mac,
- ether_type=ether_type)
- self.create_classify_table(key, a_mask)
- for host in self.hosts_by_pg_idx[self.pg0.sw_if_index]:
- s_mac = host.mac if src_mac else ''
- if dst_mac:
- for dst_if in self.flows[self.pg0]:
- for dst_host in self.hosts_by_pg_idx[dst_if.sw_if_index]:
- self.create_classify_session(
- self.pg0, self.acl_tbl_idx.get(key),
- self.build_mac_match(src_mac=s_mac,
- dst_mac=dst_host.mac,
- ether_type=etype),
- hit_next_index=hit_next_index)
- else:
- self.create_classify_session(
- self.pg0, self.acl_tbl_idx.get(key),
- self.build_mac_match(src_mac=s_mac, dst_mac='',
- ether_type=etype),
- hit_next_index=hit_next_index)
-
- def test_0000_warmup_test(self):
- """ Learn the MAC addresses
- """
- self.create_hosts(2)
- self.run_traffic_no_check()
-
- def test_0010_inacl_permit_src_mac(self):
- """ Input L2 ACL test - permit source MAC
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with source MAC address.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_in'
- self.build_classify_table(src_mac='ffffffffffff', key=key)
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- def test_0011_inacl_permit_dst_mac(self):
- """ Input L2 ACL test - permit destination MAC
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with destination MAC address.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_in'
- self.build_classify_table(dst_mac='ffffffffffff', key=key)
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- def test_0012_inacl_permit_src_dst_mac(self):
- """ Input L2 ACL test - permit source and destination MAC
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with source and destination MAC addresses.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_in'
- self.build_classify_table(
- src_mac='ffffffffffff', dst_mac='ffffffffffff', key=key)
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- def test_0013_inacl_permit_ether_type(self):
- """ Input L2 ACL test - permit ether_type
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with destination MAC address.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_in'
- self.build_classify_table(
- ether_type='ffff', etype=hex(ETH_P_IP)[2:], key=key)
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- def test_0015_inacl_deny(self):
- """ Input L2 ACL test - deny
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
-
- - Create ACL with source MAC address.
- - Send and verify no received packets on pg1 interface.
- """
- key = 'mac_in'
- self.build_classify_table(
- src_mac='ffffffffffff', hit_next_index=0, key=key)
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_negat_test(self.IP, self.IPV4, -1)
-
- def test_0020_outacl_permit(self):
- """ Output L2 ACL test - permit
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with source MAC address.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_out'
- self.build_classify_table(src_mac='ffffffffffff', key=key)
- self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
- def test_0025_outacl_deny(self):
- """ Output L2 ACL test - deny
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACL with source MAC address.
- - Send and verify no received packets on pg1 interface.
- """
- key = 'mac_out'
- self.build_classify_table(
- src_mac='ffffffffffff', hit_next_index=0, key=key)
- self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_negat_test(self.IP, self.IPV4, -1)
-
- def test_0030_inoutacl_permit(self):
- """ Input+Output L2 ACL test - permit
-
- Test scenario for basic IP ACL with source IP
- - Create IPv4 stream for pg0 -> pg1 interface.
- - Create ACLs with source MAC address.
- - Send and verify received packets on pg1 interface.
- """
- key = 'mac_inout'
- self.build_classify_table(src_mac='ffffffffffff', key=key)
- self.output_acl_set_interface(self.pg1, self.acl_tbl_idx.get(key))
- self.input_acl_set_interface(self.pg0, self.acl_tbl_idx.get(key))
- self.acl_active_table = key
- self.run_verify_test(self.IP, self.IPV4, -1)
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_flowprobe.py b/test/test_flowprobe.py
deleted file mode 100644
index 9ffe84b8c2c..00000000000
--- a/test/test_flowprobe.py
+++ /dev/null
@@ -1,1082 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import binascii
-import random
-import socket
-import unittest
-import time
-import re
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, TCP, UDP
-from scapy.layers.inet6 import IPv6
-
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-from vpp_object import VppObject
-from vpp_pg_interface import CaptureTimeoutError
-from util import ppp
-from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
-from vpp_ip_route import VppIpRoute, VppRoutePath
-
-
-class VppCFLOW(VppObject):
- """CFLOW object for IPFIX exporter and Flowprobe feature"""
-
- def __init__(self, test, intf='pg2', active=0, passive=0, timeout=100,
- mtu=1024, datapath='l2', layer='l2 l3 l4'):
- self._test = test
- self._intf = intf
- self._active = active
- if passive == 0 or passive < active:
- self._passive = active+1
- else:
- self._passive = passive
- self._datapath = datapath # l2 ip4 ip6
- self._collect = layer # l2 l3 l4
- self._timeout = timeout
- self._mtu = mtu
- self._configured = False
-
- def add_vpp_config(self):
- self.enable_exporter()
- self._test.vapi.flowprobe_params(
- record_l2=1 if 'l2' in self._collect.lower() else 0,
- record_l3=1 if 'l3' in self._collect.lower() else 0,
- record_l4=1 if 'l4' in self._collect.lower() else 0,
- active_timer=self._active, passive_timer=self._passive)
- self.enable_flowprobe_feature()
- self._test.vapi.cli("ipfix flush")
- self._configured = True
-
- def remove_vpp_config(self):
- self.disable_exporter()
- self.disable_flowprobe_feature()
- self._test.vapi.cli("ipfix flush")
- self._configured = False
-
- def enable_exporter(self):
- self._test.vapi.set_ipfix_exporter(
- collector_address=self._test.pg0.remote_ip4n,
- src_address=self._test.pg0.local_ip4n,
- path_mtu=self._mtu,
- template_interval=self._timeout)
-
- def enable_flowprobe_feature(self):
- self._test.vapi.ppcli("flowprobe feature add-del %s %s" %
- (self._intf, self._datapath))
-
- def disable_exporter(self):
- self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
-
- def disable_flowprobe_feature(self):
- self._test.vapi.cli("flowprobe feature add-del %s %s disable" %
- (self._intf, self._datapath))
-
- def object_id(self):
- return "ipfix-collector-%s-%s" % (self._src, self.dst)
-
- def query_vpp_config(self):
- return self._configured
-
- def verify_templates(self, decoder=None, timeout=1, count=3):
- templates = []
- p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
- self._test.assertTrue(p.haslayer(IPFIX))
- if decoder is not None and p.haslayer(Template):
- templates.append(p[Template].templateID)
- decoder.add_template(p.getlayer(Template))
- if count > 1:
- p = self._test.wait_for_cflow_packet(self._test.collector, 2)
- self._test.assertTrue(p.haslayer(IPFIX))
- if decoder is not None and p.haslayer(Template):
- templates.append(p[Template].templateID)
- decoder.add_template(p.getlayer(Template))
- if count > 2:
- p = self._test.wait_for_cflow_packet(self._test.collector, 2)
- self._test.assertTrue(p.haslayer(IPFIX))
- if decoder is not None and p.haslayer(Template):
- templates.append(p[Template].templateID)
- decoder.add_template(p.getlayer(Template))
- return templates
-
-
-class MethodHolder(VppTestCase):
- """ Flow-per-packet plugin: test L2, IP4, IP6 reporting """
-
- # Test variables
- debug_print = False
- max_number_of_packets = 10
- pkts = []
-
- @classmethod
- def setUpClass(cls):
- """
- Perform standard class setup (defined by class method setUpClass in
- class VppTestCase) before running the test case, set test case related
- variables and configure VPP.
- """
- super(MethodHolder, cls).setUpClass()
- try:
- # Create pg interfaces
- cls.create_pg_interfaces(range(9))
-
- # Packet sizes
- cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
-
- # Create BD with MAC learning and unknown unicast flooding disabled
- # and put interfaces to this BD
- cls.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1, learn=1)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1)
- cls.vapi.sw_interface_set_l2_bridge(
- rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1)
-
- # Set up all interfaces
- for i in cls.pg_interfaces:
- i.admin_up()
-
- cls.pg0.config_ip4()
- cls.pg0.configure_ipv4_neighbors()
- cls.collector = cls.pg0
-
- cls.pg1.config_ip4()
- cls.pg1.resolve_arp()
- cls.pg2.config_ip4()
- cls.pg2.resolve_arp()
- cls.pg3.config_ip4()
- cls.pg3.resolve_arp()
- cls.pg4.config_ip4()
- cls.pg4.resolve_arp()
- cls.pg7.config_ip4()
- cls.pg8.config_ip4()
- cls.pg8.configure_ipv4_neighbors()
-
- cls.pg5.config_ip6()
- cls.pg5.resolve_ndp()
- cls.pg5.disable_ipv6_ra()
- cls.pg6.config_ip6()
- cls.pg6.resolve_ndp()
- cls.pg6.disable_ipv6_ra()
- except Exception:
- super(MethodHolder, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(MethodHolder, cls).tearDownClass()
-
- def create_stream(self, src_if=None, dst_if=None, packets=None,
- size=None, ip_ver='v4'):
- """Create a packet stream to tickle the plugin
-
- :param VppInterface src_if: Source interface for packet stream
- :param VppInterface src_if: Dst interface for packet stream
- """
- if src_if is None:
- src_if = self.pg1
- if dst_if is None:
- dst_if = self.pg2
- self.pkts = []
- if packets is None:
- packets = random.randint(1, self.max_number_of_packets)
- pkt_size = size
- for p in range(0, packets):
- if size is None:
- pkt_size = random.choice(self.pg_if_packet_sizes)
- info = self.create_packet_info(src_if, dst_if)
- payload = self.info_to_payload(info)
- p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
- if ip_ver == 'v4':
- p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
- else:
- p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
- p /= UDP(sport=1234, dport=4321)
- p /= Raw(payload)
- info.data = p.copy()
- self.extend_packet(p, pkt_size)
- self.pkts.append(p)
-
- def verify_cflow_data(self, decoder, capture, cflow):
- octets = 0
- packets = 0
- for p in capture:
- octets += p[IP].len
- packets += 1
- if cflow.haslayer(Data):
- data = decoder.decode_data_set(cflow.getlayer(Set))
- for record in data:
- self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
- self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
-
- def send_packets(self, src_if=None, dst_if=None):
- if src_if is None:
- src_if = self.pg1
- if dst_if is None:
- dst_if = self.pg2
- self.pg_enable_capture([dst_if])
- src_if.add_stream(self.pkts)
- self.pg_start()
- return dst_if.get_capture(len(self.pkts))
-
- def verify_cflow_data_detail(self, decoder, capture, cflow,
- data_set={1: 'octets', 2: 'packets'},
- ip_ver='v4'):
- if self.debug_print:
- print(capture[0].show())
- if cflow.haslayer(Data):
- data = decoder.decode_data_set(cflow.getlayer(Set))
- if self.debug_print:
- print(data)
- if ip_ver == 'v4':
- ip_layer = capture[0][IP]
- else:
- ip_layer = capture[0][IPv6]
- if data_set is not None:
- for record in data:
- # skip flow if ingress/egress interface is 0
- if int(binascii.hexlify(record[10]), 16) == 0:
- continue
- if int(binascii.hexlify(record[14]), 16) == 0:
- continue
-
- for field in data_set:
- if field not in record.keys():
- continue
- value = data_set[field]
- if value == 'octets':
- value = ip_layer.len
- if ip_ver == 'v6':
- value += 40 # ??? is this correct
- elif value == 'packets':
- value = 1
- elif value == 'src_ip':
- if ip_ver == 'v4':
- ip = socket.inet_pton(socket.AF_INET,
- ip_layer.src)
- else:
- ip = socket.inet_pton(socket.AF_INET6,
- ip_layer.src)
- value = int(binascii.hexlify(ip), 16)
- elif value == 'dst_ip':
- if ip_ver == 'v4':
- ip = socket.inet_pton(socket.AF_INET,
- ip_layer.dst)
- else:
- ip = socket.inet_pton(socket.AF_INET6,
- ip_layer.dst)
- value = int(binascii.hexlify(ip), 16)
- elif value == 'sport':
- value = int(capture[0][UDP].sport)
- elif value == 'dport':
- value = int(capture[0][UDP].dport)
- self.assertEqual(int(binascii.hexlify(
- record[field]), 16),
- value)
-
- def verify_cflow_data_notimer(self, decoder, capture, cflows):
- idx = 0
- for cflow in cflows:
- if cflow.haslayer(Data):
- data = decoder.decode_data_set(cflow.getlayer(Set))
- else:
- raise Exception("No CFLOW data")
-
- for rec in data:
- p = capture[idx]
- idx += 1
- self.assertEqual(p[IP].len, int(
- binascii.hexlify(rec[1]), 16))
- self.assertEqual(1, int(
- binascii.hexlify(rec[2]), 16))
- self.assertEqual(len(capture), idx)
-
- def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1,
- expected=True):
- """ wait for CFLOW packet and verify its correctness
-
- :param timeout: how long to wait
-
- :returns: tuple (packet, time spent waiting for packet)
- """
- self.logger.info("IPFIX: Waiting for CFLOW packet")
- deadline = time.time() + timeout
- counter = 0
- # self.logger.debug(self.vapi.ppcli("show flow table"))
- while True:
- counter += 1
- # sanity check
- self.assert_in_range(counter, 0, 100, "number of packets ignored")
- time_left = deadline - time.time()
- try:
- if time_left < 0 and expected:
- # self.logger.debug(self.vapi.ppcli("show flow table"))
- raise CaptureTimeoutError(
- "Packet did not arrive within timeout")
- p = collector_intf.wait_for_packet(timeout=time_left)
- except CaptureTimeoutError:
- if expected:
- # self.logger.debug(self.vapi.ppcli("show flow table"))
- raise CaptureTimeoutError(
- "Packet did not arrive within timeout")
- else:
- return
- if not expected:
- raise CaptureTimeoutError("Packet arrived even not expected")
- self.assertEqual(p[Set].setID, set_id)
- # self.logger.debug(self.vapi.ppcli("show flow table"))
- self.logger.debug(ppp("IPFIX: Got packet:", p))
- break
- return p
-
-
-class Flowprobe(MethodHolder):
- """Template verification, timer tests"""
-
- @classmethod
- def setUpClass(cls):
- super(Flowprobe, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(Flowprobe, cls).tearDownClass()
-
- def test_0001(self):
- """ timer less than template timeout"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, active=2)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream(packets=1)
- self.send_packets()
- capture = self.pg2.get_capture(1)
-
- # make sure the one packet we expect actually showed up
- cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
- self.verify_cflow_data(ipfix_decoder, capture, cflow)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
- def test_0002(self):
- """ timer greater than template timeout"""
- self.logger.info("FFP_TEST_START_0002")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, timeout=3, active=4)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- ipfix.verify_templates()
-
- self.create_stream(packets=2)
- self.send_packets()
- capture = self.pg2.get_capture(2)
-
- # next set of template packet should arrive after 20 seconds
- # template packet should arrive within 20 s
- templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
-
- # make sure the one packet we expect actually showed up
- cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
- self.verify_cflow_data(ipfix_decoder, capture, cflow)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0002")
-
- def test_cflow_packet(self):
- """verify cflow packet fields"""
- self.logger.info("FFP_TEST_START_0000")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg8', datapath="ip4",
- layer='l2 l3 l4', active=2)
- ipfix.add_vpp_config()
-
- route_9001 = VppIpRoute(self, "9.0.0.0", 24,
- [VppRoutePath(self.pg8._remote_hosts[0].ip4,
- self.pg8.sw_if_index)])
- route_9001.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.pkts = [(Ether(dst=self.pg7.local_mac,
- src=self.pg7.remote_mac) /
- IP(src=self.pg7.remote_ip4, dst="9.0.0.100") /
- TCP(sport=1234, dport=4321, flags=80) /
- Raw('\xa5' * 100))]
-
- nowUTC = int(time.time())
- nowUNIX = nowUTC+2208988800
- self.send_packets(src_if=self.pg7, dst_if=self.pg8)
-
- cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
- self.collector.get_capture(2)
-
- if cflow[0].haslayer(IPFIX):
- self.assertEqual(cflow[IPFIX].version, 10)
- self.assertEqual(cflow[IPFIX].observationDomainID, 1)
- self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
- self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
- if cflow.haslayer(Data):
- record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
- # ingress interface
- self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
- # egress interface
- self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
- # packets
- self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
- # src mac
- self.assertEqual(':'.join(re.findall('..', record[56].encode(
- 'hex'))), self.pg8.local_mac)
- # dst mac
- self.assertEqual(':'.join(re.findall('..', record[80].encode(
- 'hex'))), self.pg8.remote_mac)
- flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
- # flow start timestamp
- self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
- flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
- # flow end timestamp
- self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
- # ethernet type
- self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
- # src ip
- self.assertEqual('.'.join(re.findall('..', record[8].encode(
- 'hex'))),
- '.'.join('{:02x}'.format(int(n)) for n in
- self.pg7.remote_ip4.split('.')))
- # dst ip
- self.assertEqual('.'.join(re.findall('..', record[12].encode(
- 'hex'))),
- '.'.join('{:02x}'.format(int(n)) for n in
- "9.0.0.100".split('.')))
- # protocol (TCP)
- self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
- # src port
- self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
- # dst port
- self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
- # tcp flags
- self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0000")
-
-
-class Datapath(MethodHolder):
- """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
-
- @classmethod
- def setUpClass(cls):
- super(Datapath, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(Datapath, cls).tearDownClass()
-
- def test_templatesL2(self):
- """ verify template on L2 datapath"""
- self.logger.info("FFP_TEST_START_0000")
- self.pg_enable_capture(self.pg_interfaces)
-
- ipfix = VppCFLOW(test=self, layer='l2')
- ipfix.add_vpp_config()
-
- # template packet should arrive immediately
- self.vapi.ipfix_flush()
- ipfix.verify_templates(timeout=3, count=1)
- self.collector.get_capture(1)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0000")
-
- def test_L2onL2(self):
- """ L2 data on L2 datapath"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, layer='l2')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(packets=1)
- capture = self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 256: 8})
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
- def test_L3onL2(self):
- """ L3 data on L2 datapath"""
- self.logger.info("FFP_TEST_START_0002")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, layer='l3')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=2)
-
- self.create_stream(packets=1)
- capture = self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 4: 17,
- 8: 'src_ip', 12: 'dst_ip'})
-
- self.collector.get_capture(3)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0002")
-
- def test_L4onL2(self):
- """ L4 data on L2 datapath"""
- self.logger.info("FFP_TEST_START_0003")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, layer='l4')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=2)
-
- self.create_stream(packets=1)
- capture = self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 7: 'sport', 11: 'dport'})
-
- self.collector.get_capture(3)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0003")
-
- def test_templatesIp4(self):
- """ verify templates on IP4 datapath"""
- self.logger.info("FFP_TEST_START_0000")
-
- self.pg_enable_capture(self.pg_interfaces)
-
- ipfix = VppCFLOW(test=self, datapath='ip4')
- ipfix.add_vpp_config()
-
- # template packet should arrive immediately
- self.vapi.ipfix_flush()
- ipfix.verify_templates(timeout=3, count=1)
- self.collector.get_capture(1)
-
- ipfix.remove_vpp_config()
-
- self.logger.info("FFP_TEST_FINISH_0000")
-
- def test_L2onIP4(self):
- """ L2 data on IP4 datapath"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg4', layer='l2', datapath='ip4')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
- capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 256: 8})
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
- def test_L3onIP4(self):
- """ L3 data on IP4 datapath"""
- self.logger.info("FFP_TEST_START_0002")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg4', layer='l3', datapath='ip4')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
- capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {1: 'octets', 2: 'packets',
- 8: 'src_ip', 12: 'dst_ip'})
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0002")
-
- def test_L4onIP4(self):
- """ L4 data on IP4 datapath"""
- self.logger.info("FFP_TEST_START_0003")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg4', layer='l4', datapath='ip4')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
- capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 7: 'sport', 11: 'dport'})
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0003")
-
- def test_templatesIP6(self):
- """ verify templates on IP6 datapath"""
- self.logger.info("FFP_TEST_START_0000")
- self.pg_enable_capture(self.pg_interfaces)
-
- ipfix = VppCFLOW(test=self, datapath='ip6')
- ipfix.add_vpp_config()
-
- # template packet should arrive immediately
- ipfix.verify_templates(count=1)
- self.collector.get_capture(1)
-
- ipfix.remove_vpp_config()
-
- self.logger.info("FFP_TEST_FINISH_0000")
-
- def test_L2onIP6(self):
- """ L2 data on IP6 datapath"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg6', layer='l2', datapath='ip6')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
- ip_ver='IPv6')
- capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 256: 56710},
- ip_ver='v6')
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
- def test_L3onIP6(self):
- """ L3 data on IP6 datapath"""
- self.logger.info("FFP_TEST_START_0002")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg6', layer='l3', datapath='ip6')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
- ip_ver='IPv6')
- capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets',
- 27: 'src_ip', 28: 'dst_ip'},
- ip_ver='v6')
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0002")
-
- def test_L4onIP6(self):
- """ L4 data on IP6 datapath"""
- self.logger.info("FFP_TEST_START_0003")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, intf='pg6', layer='l4', datapath='ip6')
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder, count=1)
-
- self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
- ip_ver='IPv6')
- capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[0])
- self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
- {2: 'packets', 7: 'sport', 11: 'dport'},
- ip_ver='v6')
-
- # expected two templates and one cflow packet
- self.collector.get_capture(2)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0003")
-
- def test_0001(self):
- """ no timers, one CFLOW packet, 9 Flows inside"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream(packets=9)
- capture = self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- cflow = self.wait_for_cflow_packet(self.collector, templates[1])
- self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
- self.collector.get_capture(4)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
- def test_0002(self):
- """ no timers, two CFLOW packets (mtu=256), 3 Flows in each"""
- self.logger.info("FFP_TEST_START_0002")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self, mtu=256)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- self.vapi.ipfix_flush()
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream(packets=6)
- capture = self.send_packets()
-
- # make sure the one packet we expect actually showed up
- cflows = []
- self.vapi.ipfix_flush()
- cflows.append(self.wait_for_cflow_packet(self.collector,
- templates[1]))
- cflows.append(self.wait_for_cflow_packet(self.collector,
- templates[1]))
- self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
- self.collector.get_capture(5)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0002")
-
-
-@unittest.skipUnless(running_extended_tests, "part of extended tests")
-class DisableIPFIX(MethodHolder):
- """Disable IPFIX"""
-
- @classmethod
- def setUpClass(cls):
- super(DisableIPFIX, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(DisableIPFIX, cls).tearDownClass()
-
- def test_0001(self):
- """ disable IPFIX after first packets"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream()
- self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1])
- self.collector.get_capture(4)
-
- # disable IPFIX
- ipfix.disable_exporter()
- self.pg_enable_capture([self.collector])
-
- self.send_packets()
-
- # make sure no one packet arrived in 1 minute
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1],
- expected=False)
- self.collector.get_capture(0)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
-
-@unittest.skipUnless(running_extended_tests, "part of extended tests")
-class ReenableIPFIX(MethodHolder):
- """Re-enable IPFIX"""
-
- @classmethod
- def setUpClass(cls):
- super(ReenableIPFIX, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(ReenableIPFIX, cls).tearDownClass()
-
- def test_0011(self):
- """ disable IPFIX after first packets and re-enable after few packets
- """
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream(packets=5)
- self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1])
- self.collector.get_capture(4)
-
- # disable IPFIX
- ipfix.disable_exporter()
- self.vapi.ipfix_flush()
- self.pg_enable_capture([self.collector])
-
- self.send_packets()
-
- # make sure no one packet arrived in active timer span
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1],
- expected=False)
- self.collector.get_capture(0)
- self.pg2.get_capture(5)
-
- # enable IPFIX
- ipfix.enable_exporter()
-
- capture = self.collector.get_capture(4)
- nr_templates = 0
- nr_data = 0
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- if p.haslayer(Template):
- nr_templates += 1
- self.assertTrue(nr_templates, 3)
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- if p.haslayer(Data):
- nr_data += 1
- self.assertTrue(nr_templates, 1)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
-
-@unittest.skipUnless(running_extended_tests, "part of extended tests")
-class DisableFP(MethodHolder):
- """Disable Flowprobe feature"""
-
- @classmethod
- def setUpClass(cls):
- super(DisableFP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(DisableFP, cls).tearDownClass()
-
- def test_0001(self):
- """ disable flowprobe feature after first packets"""
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
- ipfix = VppCFLOW(test=self)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- templates = ipfix.verify_templates(ipfix_decoder)
-
- self.create_stream()
- self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1])
- self.collector.get_capture(4)
-
- # disable IPFIX
- ipfix.disable_flowprobe_feature()
- self.pg_enable_capture([self.collector])
-
- self.send_packets()
-
- # make sure no one packet arrived in active timer span
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1],
- expected=False)
- self.collector.get_capture(0)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
-
-@unittest.skipUnless(running_extended_tests, "part of extended tests")
-class ReenableFP(MethodHolder):
- """Re-enable Flowprobe feature"""
-
- @classmethod
- def setUpClass(cls):
- super(ReenableFP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(ReenableFP, cls).tearDownClass()
-
- def test_0001(self):
- """ disable flowprobe feature after first packets and re-enable
- after few packets """
- self.logger.info("FFP_TEST_START_0001")
- self.pg_enable_capture(self.pg_interfaces)
- self.pkts = []
-
- ipfix = VppCFLOW(test=self)
- ipfix.add_vpp_config()
-
- ipfix_decoder = IPFIXDecoder()
- # template packet should arrive immediately
- self.vapi.ipfix_flush()
- templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
-
- self.create_stream()
- self.send_packets()
-
- # make sure the one packet we expect actually showed up
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1], 5)
- self.collector.get_capture(4)
-
- # disable FPP feature
- ipfix.disable_flowprobe_feature()
- self.pg_enable_capture([self.collector])
-
- self.send_packets()
-
- # make sure no one packet arrived in active timer span
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1], 5,
- expected=False)
- self.collector.get_capture(0)
-
- # enable FPP feature
- ipfix.enable_flowprobe_feature()
- self.vapi.ipfix_flush()
- templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
-
- self.send_packets()
-
- # make sure the next packets (templates and data) we expect actually
- # showed up
- self.vapi.ipfix_flush()
- self.wait_for_cflow_packet(self.collector, templates[1], 5)
- self.collector.get_capture(4)
-
- ipfix.remove_vpp_config()
- self.logger.info("FFP_TEST_FINISH_0001")
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_gbp.py b/test/test_gbp.py
deleted file mode 100644
index 0c9cdb415dd..00000000000
--- a/test/test_gbp.py
+++ /dev/null
@@ -1,5278 +0,0 @@
-#!/usr/bin/env python
-
-from socket import AF_INET, AF_INET6
-import unittest
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether, ARP, Dot1Q
-from scapy.layers.inet import IP, UDP, ICMP
-from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6NDOptSrcLLAddr, \
- ICMPv6ND_NA, ICMPv6EchoRequest
-from scapy.utils6 import in6_getnsma, in6_getnsmac
-from scapy.layers.vxlan import VXLAN
-from scapy.data import ETH_P_IP, ETH_P_IPV6, ETH_P_ARP
-from scapy.utils import inet_pton, inet_ntop
-
-from framework import VppTestCase, VppTestRunner
-from vpp_object import VppObject
-from vpp_interface import VppInterface
-from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, \
- VppIpInterfaceAddress, VppIpInterfaceBind, find_route, FibPathProto, \
- FibPathType
-from vpp_l2 import VppBridgeDomain, VppBridgeDomainPort, \
- VppBridgeDomainArpEntry, VppL2FibEntry, find_bridge_domain_port, VppL2Vtr
-from vpp_sub_interface import L2_VTR_OP, VppDot1QSubint
-from vpp_ip import VppIpAddress, VppIpPrefix, DpoProto
-from vpp_papi import VppEnum, MACAddress
-from vpp_vxlan_gbp_tunnel import find_vxlan_gbp_tunnel, INDEX_INVALID, \
- VppVxlanGbpTunnel
-from vpp_neighbor import VppNeighbor
-try:
- text_type = unicode
-except NameError:
- text_type = str
-
-NUM_PKTS = 67
-
-
-def find_gbp_endpoint(test, sw_if_index=None, ip=None, mac=None,
- tep=None, sclass=None):
- if ip:
- vip = VppIpAddress(ip)
- if mac:
- vmac = MACAddress(mac)
-
- eps = test.vapi.gbp_endpoint_dump()
-
- for ep in eps:
- if tep:
- src = VppIpAddress(tep[0])
- dst = VppIpAddress(tep[1])
- if src != ep.endpoint.tun.src or dst != ep.endpoint.tun.dst:
- continue
- if sw_if_index:
- if ep.endpoint.sw_if_index != sw_if_index:
- continue
- if sclass:
- if ep.endpoint.sclass != sclass:
- continue
- if ip:
- for eip in ep.endpoint.ips:
- if vip == eip:
- return True
- if mac:
- if vmac.packed == ep.endpoint.mac:
- return True
-
- return False
-
-
-def find_gbp_vxlan(test, vni):
- ts = test.vapi.gbp_vxlan_tunnel_dump()
- for t in ts:
- if t.tunnel.vni == vni:
- return True
- return False
-
-
-class VppGbpEndpoint(VppObject):
- """
- GBP Endpoint
- """
-
- @property
- def mac(self):
- return str(self.vmac)
-
- @property
- def ip4(self):
- return self._ip4
-
- @property
- def fip4(self):
- return self._fip4
-
- @property
- def ip6(self):
- return self._ip6
-
- @property
- def fip6(self):
- return self._fip6
-
- @property
- def ips(self):
- return [self.ip4, self.ip6]
-
- @property
- def fips(self):
- return [self.fip4, self.fip6]
-
- def __init__(self, test, itf, epg, recirc, ip4, fip4, ip6, fip6,
- flags=0,
- tun_src="0.0.0.0",
- tun_dst="0.0.0.0",
- mac=True):
- self._test = test
- self.itf = itf
- self.epg = epg
- self.recirc = recirc
-
- self._ip4 = VppIpAddress(ip4)
- self._fip4 = VppIpAddress(fip4)
- self._ip6 = VppIpAddress(ip6)
- self._fip6 = VppIpAddress(fip6)
-
- if mac:
- self.vmac = MACAddress(self.itf.remote_mac)
- else:
- self.vmac = MACAddress("00:00:00:00:00:00")
-
- self.flags = flags
- self.tun_src = VppIpAddress(tun_src)
- self.tun_dst = VppIpAddress(tun_dst)
-
- def add_vpp_config(self):
- res = self._test.vapi.gbp_endpoint_add(
- self.itf.sw_if_index,
- [self.ip4.encode(), self.ip6.encode()],
- self.vmac.packed,
- self.epg.sclass,
- self.flags,
- self.tun_src.encode(),
- self.tun_dst.encode())
- self.handle = res.handle
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_endpoint_del(self.handle)
-
- def object_id(self):
- return "gbp-endpoint:[%d==%d:%s:%d]" % (self.handle,
- self.itf.sw_if_index,
- self.ip4.address,
- self.epg.sclass)
-
- def query_vpp_config(self):
- return find_gbp_endpoint(self._test,
- self.itf.sw_if_index,
- self.ip4.address)
-
-
-class VppGbpRecirc(VppObject):
- """
- GBP Recirculation Interface
- """
-
- def __init__(self, test, epg, recirc, is_ext=False):
- self._test = test
- self.recirc = recirc
- self.epg = epg
- self.is_ext = is_ext
-
- def add_vpp_config(self):
- self._test.vapi.gbp_recirc_add_del(
- 1,
- self.recirc.sw_if_index,
- self.epg.sclass,
- self.is_ext)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_recirc_add_del(
- 0,
- self.recirc.sw_if_index,
- self.epg.sclass,
- self.is_ext)
-
- def object_id(self):
- return "gbp-recirc:[%d]" % (self.recirc.sw_if_index)
-
- def query_vpp_config(self):
- rs = self._test.vapi.gbp_recirc_dump()
- for r in rs:
- if r.recirc.sw_if_index == self.recirc.sw_if_index:
- return True
- return False
-
-
-class VppGbpExtItf(VppObject):
- """
- GBP ExtItfulation Interface
- """
-
- def __init__(self, test, itf, bd, rd, anon=False):
- self._test = test
- self.itf = itf
- self.bd = bd
- self.rd = rd
- self.flags = 1 if anon else 0
-
- def add_vpp_config(self):
- self._test.vapi.gbp_ext_itf_add_del(
- 1, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_ext_itf_add_del(
- 0, self.itf.sw_if_index, self.bd.bd_id, self.rd.rd_id, self.flags)
-
- def object_id(self):
- return "gbp-ext-itf:[%d]%s" % (self.itf.sw_if_index,
- " [anon]" if self.flags else "")
-
- def query_vpp_config(self):
- rs = self._test.vapi.gbp_ext_itf_dump()
- for r in rs:
- if r.ext_itf.sw_if_index == self.itf.sw_if_index:
- return True
- return False
-
-
-class VppGbpSubnet(VppObject):
- """
- GBP Subnet
- """
-
- def __init__(self, test, rd, address, address_len,
- type, sw_if_index=None, sclass=None):
- self._test = test
- self.rd_id = rd.rd_id
- self.prefix = VppIpPrefix(address, address_len)
- self.type = type
- self.sw_if_index = sw_if_index
- self.sclass = sclass
-
- def add_vpp_config(self):
- self._test.vapi.gbp_subnet_add_del(
- 1,
- self.rd_id,
- self.prefix.encode(),
- self.type,
- sw_if_index=self.sw_if_index if self.sw_if_index else 0xffffffff,
- sclass=self.sclass if self.sclass else 0xffff)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_subnet_add_del(
- 0,
- self.rd_id,
- self.prefix.encode(),
- self.type)
-
- def object_id(self):
- return "gbp-subnet:[%d-%s]" % (self.rd_id, self.prefix)
-
- def query_vpp_config(self):
- ss = self._test.vapi.gbp_subnet_dump()
- for s in ss:
- if s.subnet.rd_id == self.rd_id and \
- s.subnet.type == self.type and \
- s.subnet.prefix == self.prefix:
- return True
- return False
-
-
-class VppGbpEndpointRetention(object):
- def __init__(self, remote_ep_timeout=0xffffffff):
- self.remote_ep_timeout = remote_ep_timeout
-
- def encode(self):
- return {'remote_ep_timeout': self.remote_ep_timeout}
-
-
-class VppGbpEndpointGroup(VppObject):
- """
- GBP Endpoint Group
- """
-
- def __init__(self, test, vnid, sclass, rd, bd, uplink,
- bvi, bvi_ip4, bvi_ip6=None,
- retention=VppGbpEndpointRetention()):
- self._test = test
- self.uplink = uplink
- self.bvi = bvi
- self.bvi_ip4 = VppIpAddress(bvi_ip4)
- self.bvi_ip6 = VppIpAddress(bvi_ip6)
- self.vnid = vnid
- self.bd = bd
- self.rd = rd
- self.sclass = sclass
- if 0 == self.sclass:
- self.sclass = 0xffff
- self.retention = retention
-
- def add_vpp_config(self):
- self._test.vapi.gbp_endpoint_group_add(
- self.vnid,
- self.sclass,
- self.bd.bd.bd_id,
- self.rd.rd_id,
- self.uplink.sw_if_index if self.uplink else INDEX_INVALID,
- self.retention.encode())
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_endpoint_group_del(self.sclass)
-
- def object_id(self):
- return "gbp-endpoint-group:[%d]" % (self.vnid)
-
- def query_vpp_config(self):
- epgs = self._test.vapi.gbp_endpoint_group_dump()
- for epg in epgs:
- if epg.epg.vnid == self.vnid:
- return True
- return False
-
-
-class VppGbpBridgeDomain(VppObject):
- """
- GBP Bridge Domain
- """
-
- def __init__(self, test, bd, rd, bvi, uu_fwd=None,
- bm_flood=None, learn=True,
- uu_drop=False, bm_drop=False,
- ucast_arp=False):
- self._test = test
- self.bvi = bvi
- self.uu_fwd = uu_fwd
- self.bm_flood = bm_flood
- self.bd = bd
- self.rd = rd
-
- e = VppEnum.vl_api_gbp_bridge_domain_flags_t
-
- self.flags = e.GBP_BD_API_FLAG_NONE
- if not learn:
- self.flags |= e.GBP_BD_API_FLAG_DO_NOT_LEARN
- if uu_drop:
- self.flags |= e.GBP_BD_API_FLAG_UU_FWD_DROP
- if bm_drop:
- self.flags |= e.GBP_BD_API_FLAG_MCAST_DROP
- if ucast_arp:
- self.flags |= e.GBP_BD_API_FLAG_UCAST_ARP
-
- def add_vpp_config(self):
- self._test.vapi.gbp_bridge_domain_add(
- self.bd.bd_id,
- self.rd.rd_id,
- self.flags,
- self.bvi.sw_if_index,
- self.uu_fwd.sw_if_index if self.uu_fwd else INDEX_INVALID,
- self.bm_flood.sw_if_index if self.bm_flood else INDEX_INVALID)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_bridge_domain_del(self.bd.bd_id)
-
- def object_id(self):
- return "gbp-bridge-domain:[%d]" % (self.bd.bd_id)
-
- def query_vpp_config(self):
- bds = self._test.vapi.gbp_bridge_domain_dump()
- for bd in bds:
- if bd.bd.bd_id == self.bd.bd_id:
- return True
- return False
-
-
-class VppGbpRouteDomain(VppObject):
- """
- GBP Route Domain
- """
-
- def __init__(self, test, rd_id, scope, t4, t6, ip4_uu=None, ip6_uu=None):
- self._test = test
- self.rd_id = rd_id
- self.scope = scope
- self.t4 = t4
- self.t6 = t6
- self.ip4_uu = ip4_uu
- self.ip6_uu = ip6_uu
-
- def add_vpp_config(self):
- self._test.vapi.gbp_route_domain_add(
- self.rd_id,
- self.scope,
- self.t4.table_id,
- self.t6.table_id,
- self.ip4_uu.sw_if_index if self.ip4_uu else INDEX_INVALID,
- self.ip6_uu.sw_if_index if self.ip6_uu else INDEX_INVALID)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_route_domain_del(self.rd_id)
-
- def object_id(self):
- return "gbp-route-domain:[%d]" % (self.rd_id)
-
- def query_vpp_config(self):
- rds = self._test.vapi.gbp_route_domain_dump()
- for rd in rds:
- if rd.rd.rd_id == self.rd_id:
- return True
- return False
-
-
-class VppGbpContractNextHop():
- def __init__(self, mac, bd, ip, rd):
- self.mac = mac
- self.ip = ip
- self.bd = bd
- self.rd = rd
-
- def encode(self):
- return {'ip': self.ip.encode(),
- 'mac': self.mac.packed,
- 'bd_id': self.bd.bd.bd_id,
- 'rd_id': self.rd.rd_id}
-
-
-class VppGbpContractRule():
- def __init__(self, action, hash_mode, nhs=None):
- self.action = action
- self.hash_mode = hash_mode
- self.nhs = [] if nhs is None else nhs
-
- def encode(self):
- nhs = []
- for nh in self.nhs:
- nhs.append(nh.encode())
- while len(nhs) < 8:
- nhs.append({})
- return {'action': self.action,
- 'nh_set': {
- 'hash_mode': self.hash_mode,
- 'n_nhs': len(self.nhs),
- 'nhs': nhs}}
-
- def __repr__(self):
- return '<VppGbpContractRule action=%s, hash_mode=%s>' % (
- self.action, self.hash_mode)
-
-
-class VppGbpContract(VppObject):
- """
- GBP Contract
- """
-
- def __init__(self, test, scope, sclass, dclass, acl_index,
- rules, allowed_ethertypes):
- self._test = test
- if not isinstance(rules, list):
- raise ValueError("'rules' must be a list.")
- if not isinstance(allowed_ethertypes, list):
- raise ValueError("'allowed_ethertypes' must be a list.")
- self.scope = scope
- self.acl_index = acl_index
- self.sclass = sclass
- self.dclass = dclass
- self.rules = rules
- self.allowed_ethertypes = allowed_ethertypes
- while (len(self.allowed_ethertypes) < 16):
- self.allowed_ethertypes.append(0)
-
- def add_vpp_config(self):
- rules = []
- for r in self.rules:
- rules.append(r.encode())
- r = self._test.vapi.gbp_contract_add_del(
- is_add=1,
- contract={
- 'acl_index': self.acl_index,
- 'scope': self.scope,
- 'sclass': self.sclass,
- 'dclass': self.dclass,
- 'n_rules': len(rules),
- 'rules': rules,
- 'n_ether_types': len(self.allowed_ethertypes),
- 'allowed_ethertypes': self.allowed_ethertypes})
- self.stats_index = r.stats_index
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_contract_add_del(
- is_add=0,
- contract={
- 'acl_index': self.acl_index,
- 'scope': self.scope,
- 'sclass': self.sclass,
- 'dclass': self.dclass,
- 'n_rules': 0,
- 'rules': [],
- 'n_ether_types': len(self.allowed_ethertypes),
- 'allowed_ethertypes': self.allowed_ethertypes})
-
- def object_id(self):
- return "gbp-contract:[%d:%d:%d:%d]" % (self.scope,
- self.sclass,
- self.dclass,
- self.acl_index)
-
- def query_vpp_config(self):
- cs = self._test.vapi.gbp_contract_dump()
- for c in cs:
- if c.contract.scope == self.scope \
- and c.contract.sclass == self.sclass \
- and c.contract.dclass == self.dclass:
- return True
- return False
-
- def get_drop_stats(self):
- c = self._test.statistics.get_counter("/net/gbp/contract/drop")
- return c[0][self.stats_index]
-
- def get_permit_stats(self):
- c = self._test.statistics.get_counter("/net/gbp/contract/permit")
- return c[0][self.stats_index]
-
-
-class VppGbpVxlanTunnel(VppInterface):
- """
- GBP VXLAN tunnel
- """
-
- def __init__(self, test, vni, bd_rd_id, mode, src):
- super(VppGbpVxlanTunnel, self).__init__(test)
- self._test = test
- self.vni = vni
- self.bd_rd_id = bd_rd_id
- self.mode = mode
- self.src = src
-
- def add_vpp_config(self):
- r = self._test.vapi.gbp_vxlan_tunnel_add(
- self.vni,
- self.bd_rd_id,
- self.mode,
- self.src)
- self.set_sw_if_index(r.sw_if_index)
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.gbp_vxlan_tunnel_del(self.vni)
-
- def object_id(self):
- return "gbp-vxlan:%d" % (self.sw_if_index)
-
- def query_vpp_config(self):
- return find_gbp_vxlan(self._test, self.vni)
-
-
-class VppGbpAcl(VppObject):
- """
- GBP Acl
- """
-
- def __init__(self, test):
- self._test = test
- self.acl_index = 4294967295
-
- def create_rule(self, is_ipv6=0, permit_deny=0, proto=-1,
- s_prefix=0, s_ip=b'\x00\x00\x00\x00', sport_from=0,
- sport_to=65535, d_prefix=0, d_ip=b'\x00\x00\x00\x00',
- dport_from=0, dport_to=65535):
- if proto == -1 or proto == 0:
- sport_to = 0
- dport_to = sport_to
- elif proto == 1 or proto == 58:
- sport_to = 255
- dport_to = sport_to
- rule = ({'is_permit': permit_deny, 'is_ipv6': is_ipv6, 'proto': proto,
- 'srcport_or_icmptype_first': sport_from,
- 'srcport_or_icmptype_last': sport_to,
- 'src_ip_prefix_len': s_prefix,
- 'src_ip_addr': s_ip,
- 'dstport_or_icmpcode_first': dport_from,
- 'dstport_or_icmpcode_last': dport_to,
- 'dst_ip_prefix_len': d_prefix,
- 'dst_ip_addr': d_ip})
- return rule
-
- def add_vpp_config(self, rules):
-
- reply = self._test.vapi.acl_add_replace(acl_index=self.acl_index,
- r=rules,
- tag=b'GBPTest')
- self.acl_index = reply.acl_index
- return self.acl_index
-
- def remove_vpp_config(self):
- self._test.vapi.acl_del(self.acl_index)
-
- def object_id(self):
- return "gbp-acl:[%d]" % (self.acl_index)
-
- def query_vpp_config(self):
- cs = self._test.vapi.acl_dump()
- for c in cs:
- if c.acl_index == self.acl_index:
- return True
- return False
-
-
-class TestGBP(VppTestCase):
- """ GBP Test Case """
-
- @property
- def config_flags(self):
- return VppEnum.vl_api_nat_config_flags_t
-
- @classmethod
- def setUpClass(cls):
- super(TestGBP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestGBP, cls).tearDownClass()
-
- def setUp(self):
- super(TestGBP, self).setUp()
-
- self.create_pg_interfaces(range(9))
- self.create_loopback_interfaces(8)
-
- self.router_mac = MACAddress("00:11:22:33:44:55")
-
- for i in self.pg_interfaces:
- i.admin_up()
- for i in self.lo_interfaces:
- i.admin_up()
-
- self.vlan_100 = VppDot1QSubint(self, self.pg0, 100)
- self.vlan_100.admin_up()
- self.vlan_101 = VppDot1QSubint(self, self.pg0, 101)
- self.vlan_101.admin_up()
- self.vlan_102 = VppDot1QSubint(self, self.pg0, 102)
- self.vlan_102.admin_up()
-
- def tearDown(self):
- for i in self.pg_interfaces:
- i.admin_down()
- super(TestGBP, self).tearDown()
- self.vlan_102.remove_vpp_config()
- self.vlan_101.remove_vpp_config()
- self.vlan_100.remove_vpp_config()
-
- def send_and_expect_bridged(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_bridged6(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_routed(self, src, tx, dst, src_mac):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, src_mac)
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_routed6(self, src, tx, dst, src_mac):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, src_mac)
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_natted(self, src, tx, dst, src_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].src, src_ip)
- self.assertEqual(r[IP].dst, tx[0][IP].dst)
- return rx
-
- def send_and_expect_natted6(self, src, tx, dst, src_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].src, src_ip)
- self.assertEqual(r[IPv6].dst, tx[0][IPv6].dst)
- return rx
-
- def send_and_expect_unnatted(self, src, tx, dst, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IP].dst, dst_ip)
- self.assertEqual(r[IP].src, tx[0][IP].src)
- return rx
-
- def send_and_expect_unnatted6(self, src, tx, dst, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[IPv6].dst, dst_ip)
- self.assertEqual(r[IPv6].src, tx[0][IPv6].src)
- return rx
-
- def send_and_expect_double_natted(self, src, tx, dst, src_ip, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, str(self.router_mac))
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IP].dst, dst_ip)
- self.assertEqual(r[IP].src, src_ip)
- return rx
-
- def send_and_expect_double_natted6(self, src, tx, dst, src_ip, dst_ip):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, str(self.router_mac))
- self.assertEqual(r[Ether].dst, dst.remote_mac)
- self.assertEqual(r[IPv6].dst, dst_ip)
- self.assertEqual(r[IPv6].src, src_ip)
- return rx
-
- def send_and_expect_no_arp(self, src, tx, dst):
- self.pg_send(src, tx)
- dst.get_capture(0, timeout=1)
- dst.assert_nothing_captured(remark="")
- timeout = 0.1
-
- def send_and_expect_arp(self, src, tx, dst):
- rx = self.send_and_expect(src, tx, dst)
-
- for r in rx:
- self.assertEqual(r[Ether].src, tx[0][Ether].src)
- self.assertEqual(r[Ether].dst, tx[0][Ether].dst)
- self.assertEqual(r[ARP].psrc, tx[0][ARP].psrc)
- self.assertEqual(r[ARP].pdst, tx[0][ARP].pdst)
- self.assertEqual(r[ARP].hwsrc, tx[0][ARP].hwsrc)
- self.assertEqual(r[ARP].hwdst, tx[0][ARP].hwdst)
- return rx
-
- def test_gbp(self):
- """ Group Based Policy """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
-
- #
- # Route Domains
- #
- gt4 = VppIpTable(self, 0)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 0, is_ip6=True)
- gt6.add_vpp_config()
- nt4 = VppIpTable(self, 20)
- nt4.add_vpp_config()
- nt6 = VppIpTable(self, 20, is_ip6=True)
- nt6.add_vpp_config()
-
- rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
- rd20 = VppGbpRouteDomain(self, 20, 420, nt4, nt6, None, None)
-
- rd0.add_vpp_config()
- rd20.add_vpp_config()
-
- #
- # Bridge Domains
- #
- bd1 = VppBridgeDomain(self, 1)
- bd2 = VppBridgeDomain(self, 2)
- bd20 = VppBridgeDomain(self, 20)
-
- bd1.add_vpp_config()
- bd2.add_vpp_config()
- bd20.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
- gbd20 = VppGbpBridgeDomain(self, bd20, rd20, self.loop2)
-
- gbd1.add_vpp_config()
- gbd2.add_vpp_config()
- gbd20.add_vpp_config()
-
- #
- # 3 EPGs, 2 of which share a BD.
- # 2 NAT EPGs, one for floating-IP subnets, the other for internet
- #
- epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
- self.pg4, self.loop0,
- "10.0.0.128", "2001:10::128"),
- VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
- self.pg5, self.loop0,
- "10.0.1.128", "2001:10:1::128"),
- VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
- self.pg6, self.loop1,
- "10.0.2.128", "2001:10:2::128"),
- VppGbpEndpointGroup(self, 333, 1333, rd20, gbd20,
- self.pg7, self.loop2,
- "11.0.0.128", "3001::128"),
- VppGbpEndpointGroup(self, 444, 1444, rd20, gbd20,
- self.pg8, self.loop2,
- "11.0.0.129", "3001::129")]
- recircs = [VppGbpRecirc(self, epgs[0], self.loop3),
- VppGbpRecirc(self, epgs[1], self.loop4),
- VppGbpRecirc(self, epgs[2], self.loop5),
- VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True),
- VppGbpRecirc(self, epgs[4], self.loop7, is_ext=True)]
-
- epg_nat = epgs[3]
- recirc_nat = recircs[3]
-
- #
- # 4 end-points, 2 in the same subnet, 3 in the same BD
- #
- eps = [VppGbpEndpoint(self, self.pg0,
- epgs[0], recircs[0],
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1"),
- VppGbpEndpoint(self, self.pg1,
- epgs[0], recircs[0],
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2"),
- VppGbpEndpoint(self, self.pg2,
- epgs[1], recircs[1],
- "10.0.1.1", "11.0.0.3",
- "2001:10:1::1", "3001::3"),
- VppGbpEndpoint(self, self.pg3,
- epgs[2], recircs[2],
- "10.0.2.1", "11.0.0.4",
- "2001:10:2::1", "3001::4")]
-
- #
- # Config related to each of the EPGs
- #
- for epg in epgs:
- # IP config on the BVI interfaces
- if epg != epgs[1] and epg != epgs[4]:
- VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
- self.vapi.sw_interface_set_mac_address(
- epg.bvi.sw_if_index,
- self.router_mac.packed)
-
- # The BVIs are NAT inside interfaces
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=epg.bvi.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat66_add_del_interface(
- is_add=1, flags=flags,
- sw_if_index=epg.bvi.sw_if_index)
-
- if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
- if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
- if_ip4.add_vpp_config()
- if_ip6.add_vpp_config()
-
- # EPG uplink interfaces in the RD
- VppIpInterfaceBind(self, epg.uplink, epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, epg.uplink, epg.rd.t6).add_vpp_config()
-
- # add the BD ARP termination entry for BVI IP
- epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip4.address)
- epg.bd_arp_ip6 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip6.address)
- epg.bd_arp_ip4.add_vpp_config()
- epg.bd_arp_ip6.add_vpp_config()
-
- # EPG in VPP
- epg.add_vpp_config()
-
- for recirc in recircs:
- # EPG's ingress recirculation interface maps to its RD
- VppIpInterfaceBind(self, recirc.recirc,
- recirc.epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, recirc.recirc,
- recirc.epg.rd.t6).add_vpp_config()
-
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=recirc.recirc.sw_if_index, is_add=1)
- self.vapi.nat66_add_del_interface(
- is_add=1,
- sw_if_index=recirc.recirc.sw_if_index)
-
- recirc.add_vpp_config()
-
- for recirc in recircs:
- self.assertTrue(find_bridge_domain_port(self,
- recirc.epg.bd.bd.bd_id,
- recirc.recirc.sw_if_index))
-
- for ep in eps:
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- #
- # routes to the endpoints. We need these since there are no
- # adj-fibs due to the fact the the BVI address has /32 and
- # the subnet is not attached.
- #
- for (ip, fip) in zip(ep.ips, ep.fips):
- # Add static mappings for each EP from the 10/8 to 11/8 network
- if ip.af == AF_INET:
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(
- is_add=1,
- local_ip_address=ip.bytes,
- external_ip_address=fip.bytes,
- external_sw_if_index=0xFFFFFFFF,
- vrf_id=0,
- flags=flags)
- else:
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=ip.bytes,
- external_ip_address=fip.bytes,
- vrf_id=0, is_add=1)
-
- # VPP EP create ...
- ep.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
-
- # ... results in a Gratuitous ARP/ND on the EPG's uplink
- rx = ep.epg.uplink.get_capture(len(ep.ips), timeout=0.2)
-
- for ii, ip in enumerate(ep.ips):
- p = rx[ii]
-
- if ip.is_ip6:
- self.assertTrue(p.haslayer(ICMPv6ND_NA))
- self.assertEqual(p[ICMPv6ND_NA].tgt, ip.address)
- else:
- self.assertTrue(p.haslayer(ARP))
- self.assertEqual(p[ARP].psrc, ip.address)
- self.assertEqual(p[ARP].pdst, ip.address)
-
- # add the BD ARP termination entry for floating IP
- for fip in ep.fips:
- ba = VppBridgeDomainArpEntry(self, epg_nat.bd.bd, ep.mac,
- fip.address)
- ba.add_vpp_config()
-
- # floating IPs route via EPG recirc
- r = VppIpRoute(
- self, fip.address, fip.length,
- [VppRoutePath(fip.address,
- ep.recirc.recirc.sw_if_index,
- type=FibPathType.FIB_PATH_TYPE_DVR,
- proto=fip.dpo_proto)],
- table_id=20)
- r.add_vpp_config()
-
- # L2 FIB entries in the NAT EPG BD to bridge the packets from
- # the outside direct to the internal EPG
- lf = VppL2FibEntry(self, epg_nat.bd.bd, ep.mac,
- ep.recirc.recirc, bvi_mac=0)
- lf.add_vpp_config()
-
- #
- # ARP packets for unknown IP are sent to the EPG uplink
- #
- pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- ARP(op="who-has",
- hwdst="ff:ff:ff:ff:ff:ff",
- hwsrc=self.pg0.remote_mac,
- pdst="10.0.0.88",
- psrc="10.0.0.99"))
-
- self.vapi.cli("clear trace")
- self.pg0.add_stream(pkt_arp)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rxd = epgs[0].uplink.get_capture(1)
-
- #
- # ARP/ND packets get a response
- #
- pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- ARP(op="who-has",
- hwdst="ff:ff:ff:ff:ff:ff",
- hwsrc=self.pg0.remote_mac,
- pdst=epgs[0].bvi_ip4.address,
- psrc=eps[0].ip4.address))
-
- self.send_and_expect(self.pg0, [pkt_arp], self.pg0)
-
- nsma = in6_getnsma(inet_pton(AF_INET6, eps[0].ip6.address))
- d = inet_ntop(AF_INET6, nsma)
- pkt_nd = (Ether(dst=in6_getnsmac(nsma),
- src=self.pg0.remote_mac) /
- IPv6(dst=d, src=eps[0].ip6.address) /
- ICMPv6ND_NS(tgt=epgs[0].bvi_ip6.address) /
- ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
- self.send_and_expect(self.pg0, [pkt_nd], self.pg0)
-
- #
- # broadcast packets are flooded
- #
- pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg0.remote_mac) /
- IP(src=eps[0].ip4.address, dst="232.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.vapi.cli("clear trace")
- self.pg0.add_stream(pkt_bcast)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rxd = eps[1].itf.get_capture(1)
- self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
- rxd = epgs[0].uplink.get_capture(1)
- self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst)
-
- #
- # packets to non-local L3 destinations dropped
- #
- pkt_intra_epg_220_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- pkt_inter_epg_222_ip4 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst="10.0.1.99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0,
- pkt_intra_epg_220_ip4 * NUM_PKTS)
-
- pkt_inter_epg_222_ip6 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6.address,
- dst="2001:10::99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_assert_no_replies(self.pg0,
- pkt_inter_epg_222_ip6 * NUM_PKTS)
-
- #
- # Add the subnet routes
- #
- s41 = VppGbpSubnet(
- self, rd0, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s42 = VppGbpSubnet(
- self, rd0, "10.0.1.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s43 = VppGbpSubnet(
- self, rd0, "10.0.2.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s61 = VppGbpSubnet(
- self, rd0, "2001:10::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s62 = VppGbpSubnet(
- self, rd0, "2001:10:1::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s63 = VppGbpSubnet(
- self, rd0, "2001:10:2::1", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_INTERNAL)
- s41.add_vpp_config()
- s42.add_vpp_config()
- s43.add_vpp_config()
- s61.add_vpp_config()
- s62.add_vpp_config()
- s63.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_ip4 * NUM_PKTS,
- eps[0].epg.uplink)
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_222_ip4 * NUM_PKTS,
- eps[0].epg.uplink)
- self.send_and_expect_bridged6(eps[0].itf,
- pkt_inter_epg_222_ip6 * NUM_PKTS,
- eps[0].epg.uplink)
-
- self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2"))
- self.logger.info(self.vapi.cli("sh gbp endpoint-group"))
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- self.logger.info(self.vapi.cli("sh gbp recirc"))
- self.logger.info(self.vapi.cli("sh int"))
- self.logger.info(self.vapi.cli("sh int addr"))
- self.logger.info(self.vapi.cli("sh int feat loop6"))
- self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify"))
- self.logger.info(self.vapi.cli("sh int feat loop3"))
- self.logger.info(self.vapi.cli("sh int feat pg0"))
-
- #
- # Packet destined to unknown unicast is sent on the epg uplink ...
- #
- pkt_intra_epg_220_to_uplink = (Ether(src=self.pg0.remote_mac,
- dst="00:00:00:33:44:55") /
- IP(src=eps[0].ip4.address,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg_220_to_uplink * NUM_PKTS,
- eps[0].epg.uplink)
- # ... and nowhere else
- self.pg1.get_capture(0, timeout=0.1)
- self.pg1.assert_nothing_captured(remark="Flood onto other VMS")
-
- pkt_intra_epg_221_to_uplink = (Ether(src=self.pg2.remote_mac,
- dst="00:00:00:33:44:66") /
- IP(src=eps[0].ip4.address,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged(eps[2].itf,
- pkt_intra_epg_221_to_uplink * NUM_PKTS,
- eps[2].epg.uplink)
-
- #
- # Packets from the uplink are forwarded in the absence of a contract
- #
- pkt_intra_epg_220_from_uplink = (Ether(src="00:00:00:33:44:55",
- dst=self.pg0.remote_mac) /
- IP(src=eps[0].ip4.address,
- dst="10.0.0.99") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg4,
- pkt_intra_epg_220_from_uplink * NUM_PKTS,
- self.pg0)
-
- #
- # in the absence of policy, endpoints in the same EPG
- # can communicate
- #
- pkt_intra_epg = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IP(src=eps[0].ip4.address,
- dst=eps[1].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg0,
- pkt_intra_epg * NUM_PKTS,
- self.pg1)
-
- #
- # in the absence of policy, endpoints in the different EPG
- # cannot communicate
- #
- pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- IP(src=eps[0].ip4.address,
- dst=eps[2].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=self.pg0.remote_mac) /
- IP(src=eps[2].ip4.address,
- dst=eps[0].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst=eps[3].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # A uni-directional contract from EPG 220 -> 221
- #
- acl = VppGbpAcl(self)
- rule = acl.create_rule(permit_deny=1, proto=17)
- rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule, rule2])
- c1 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS,
- eps[2].itf)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # contract for the return direction
- #
- c2 = VppGbpContract(
- self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS,
- eps[2].itf)
- self.send_and_expect_bridged(eps[2].itf,
- pkt_inter_epg_221_to_220 * NUM_PKTS,
- eps[0].itf)
-
- ds = c2.get_drop_stats()
- self.assertEqual(ds['packets'], 0)
- ps = c2.get_permit_stats()
- self.assertEqual(ps['packets'], NUM_PKTS)
-
- #
- # the contract does not allow non-IP
- #
- pkt_non_ip_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- ARP())
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_non_ip_inter_epg_220_to_221 * 17)
-
- #
- # check that inter group is still disabled for the groups
- # not in the contract.
- #
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS)
-
- #
- # A uni-directional contract from EPG 220 -> 222 'L3 routed'
- #
- c3 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh gbp contract"))
-
- self.send_and_expect_routed(eps[0].itf,
- pkt_inter_epg_220_to_222 * NUM_PKTS,
- eps[3].itf,
- str(self.router_mac))
-
- #
- # remove both contracts, traffic stops in both directions
- #
- c2.remove_vpp_config()
- c1.remove_vpp_config()
- c3.remove_vpp_config()
- acl.remove_vpp_config()
-
- self.send_and_assert_no_replies(eps[2].itf,
- pkt_inter_epg_221_to_220 * NUM_PKTS)
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_221 * NUM_PKTS)
- self.send_and_expect_bridged(eps[0].itf,
- pkt_intra_epg * NUM_PKTS,
- eps[1].itf)
-
- #
- # EPs to the outside world
- #
-
- # in the EP's RD an external subnet via the NAT EPG's recirc
- se1 = VppGbpSubnet(
- self, rd0, "0.0.0.0", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- se2 = VppGbpSubnet(
- self, rd0, "11.0.0.0", 8,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- se16 = VppGbpSubnet(
- self, rd0, "::", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=recirc_nat.recirc.sw_if_index,
- sclass=epg_nat.sclass)
- # in the NAT RD an external subnet via the NAT EPG's uplink
- se3 = VppGbpSubnet(
- self, rd20, "0.0.0.0", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se36 = VppGbpSubnet(
- self, rd20, "::", 0,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se4 = VppGbpSubnet(
- self, rd20, "11.0.0.0", 8,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_STITCHED_EXTERNAL,
- sw_if_index=epg_nat.uplink.sw_if_index,
- sclass=epg_nat.sclass)
- se1.add_vpp_config()
- se2.add_vpp_config()
- se16.add_vpp_config()
- se3.add_vpp_config()
- se36.add_vpp_config()
- se4.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0"))
- self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1"))
- self.logger.info(self.vapi.cli("sh ip6 fib ::/0"))
- self.logger.info(self.vapi.cli("sh ip6 fib %s" %
- eps[0].fip6))
-
- #
- # From an EP to an outside address: IN2OUT
- #
- pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst="1.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- # no policy yet
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_global * NUM_PKTS)
-
- acl2 = VppGbpAcl(self)
- rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234,
- sport_to=1234, dport_from=1234, dport_to=1234)
- rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17,
- sport_from=1234, sport_to=1234,
- dport_from=1234, dport_to=1234)
-
- acl_index2 = acl2.add_vpp_config([rule, rule2])
- c4 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[3].sclass, acl_index2,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- self.send_and_expect_natted(eps[0].itf,
- pkt_inter_epg_220_to_global * NUM_PKTS,
- self.pg7,
- eps[0].fip4.address)
-
- pkt_inter_epg_220_to_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6.address,
- dst="6001::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_natted6(self.pg0,
- pkt_inter_epg_220_to_global * NUM_PKTS,
- self.pg7,
- eps[0].fip6.address)
-
- #
- # From a global address to an EP: OUT2IN
- #
- pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
- dst=self.pg0.remote_mac) /
- IP(dst=eps[0].fip4.address,
- src="1.1.1.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(
- self.pg7, pkt_inter_epg_220_from_global * NUM_PKTS)
-
- c5 = VppGbpContract(
- self, 400, epgs[3].sclass, epgs[0].sclass, acl_index2,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c5.add_vpp_config()
-
- self.send_and_expect_unnatted(self.pg7,
- pkt_inter_epg_220_from_global * NUM_PKTS,
- eps[0].itf,
- eps[0].ip4.address)
-
- pkt_inter_epg_220_from_global = (Ether(src=str(self.router_mac),
- dst=self.pg0.remote_mac) /
- IPv6(dst=eps[0].fip6.address,
- src="6001::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_unnatted6(
- self.pg7,
- pkt_inter_epg_220_from_global * NUM_PKTS,
- eps[0].itf,
- eps[0].ip6.address)
-
- #
- # From a local VM to another local VM using resp. public addresses:
- # IN2OUT2IN
- #
- pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst=eps[1].fip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_double_natted(eps[0].itf,
- pkt_intra_epg_220_global * NUM_PKTS,
- eps[1].itf,
- eps[0].fip4.address,
- eps[1].ip4.address)
-
- pkt_intra_epg_220_global = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6.address,
- dst=eps[1].fip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_double_natted6(
- eps[0].itf,
- pkt_intra_epg_220_global * NUM_PKTS,
- eps[1].itf,
- eps[0].fip6.address,
- eps[1].ip6.address)
-
- #
- # cleanup
- #
- for ep in eps:
- # del static mappings for each EP from the 10/8 to 11/8 network
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(
- is_add=0,
- local_ip_address=ep.ip4.bytes,
- external_ip_address=ep.fip4.bytes,
- external_sw_if_index=0xFFFFFFFF,
- vrf_id=0,
- flags=flags)
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=ep.ip6.bytes,
- external_ip_address=ep.fip6.bytes,
- vrf_id=0, is_add=0)
-
- for epg in epgs:
- # IP config on the BVI interfaces
- if epg != epgs[0] and epg != epgs[3]:
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=epg.bvi.sw_if_index,
- flags=flags,
- is_add=0)
- self.vapi.nat66_add_del_interface(
- is_add=0, flags=flags,
- sw_if_index=epg.bvi.sw_if_index)
-
- for recirc in recircs:
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=recirc.recirc.sw_if_index,
- is_add=0)
- self.vapi.nat66_add_del_interface(
- is_add=0,
- sw_if_index=recirc.recirc.sw_if_index)
-
- def wait_for_ep_timeout(self, sw_if_index=None, ip=None, mac=None,
- tep=None, n_tries=100, s_time=1):
- while (n_tries):
- if not find_gbp_endpoint(self, sw_if_index, ip, mac, tep=tep):
- return True
- n_tries = n_tries - 1
- self.sleep(s_time)
- self.assertFalse(find_gbp_endpoint(self, sw_if_index, ip, mac))
- return False
-
- def test_gbp_learn_l2(self):
- """ GBP L2 Endpoint Learning """
-
- drop_no_contract = self.statistics.get_err_counter(
- '/err/gbp-policy-port/drop-no-contract')
- allow_intra_class = self.statistics.get_err_counter(
- '/err/gbp-policy-port/allow-intra-sclass')
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- learnt = [{'mac': '00:00:11:11:11:01',
- 'ip': '10.0.0.1',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:02',
- 'ip': '10.0.0.2',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
- # Pg3 hosts the IP4 UU-flood VXLAN tunnel
- # Pg4 hosts the IP6 UU-flood VXLAN tunnel
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
- #
- tun_bm = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg4)
- tun_bm.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- self.pg3, tun_bm)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip_addr.add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
- epg_330 = VppGbpEndpointGroup(self, 330, 113, rd1, gbd1,
- None, self.loop1,
- "10.0.1.128",
- "2001:11::128",
- VppGbpEndpointRetention(2))
- epg_330.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # learning enabled
- #
- vx_tun_l2_1 = VppGbpVxlanTunnel(
- self, 99, bd1.bd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
- self.pg2.local_ip4)
- vx_tun_l2_1.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
-
- # a packet with an sclass from an unknown EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[0].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=88, flags=0x88) /
- Ether(src=learnt[0]["mac"], dst=ep.mac) /
- IP(src=learnt[0]["ip"], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg2, p)
-
- self.logger.info(self.vapi.cli("sh error"))
- self.assert_error_counter_equal(
- '/err/gbp-policy-port/drop-no-contract',
- drop_no_contract + 1)
-
- #
- # we should not have learnt a new tunnel endpoint, since
- # the EPG was not learnt.
- #
- self.assertEqual(INDEX_INVALID,
- find_vxlan_gbp_tunnel(self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[0].ip4,
- 99))
-
- # ep is not learnt, because the EPG is unknown
- self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
-
- #
- # Learn new EPs from IP packets
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip']))
-
- self.assert_error_counter_equal(
- '/err/gbp-policy-port/allow-intra-sclass',
- allow_intra_class + 2)
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show ip mfib"))
-
- #
- # If we sleep for the threshold time, the learnt endpoints should
- # age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # Learn new EPs from GARP packets received on the BD's mcast tunnel
- #
- for ii, l in enumerate(learnt):
- # add some junk in the reserved field of the vxlan-header
- # next to the VNI. we should accept since reserved bits are
- # ignored on rx.
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst="239.1.1.1") /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=88, reserved2=0x80, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst="ff:ff:ff:ff:ff:ff") /
- ARP(op="who-has",
- psrc=l['ip'], pdst=l['ip'],
- hwsrc=l['mac'], hwdst="ff:ff:ff:ff:ff:ff"))
-
- rx = self.send_and_expect(self.pg4, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip']))
-
- #
- # wait for the learnt endpoints to age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # Learn new EPs from L2 packets
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- #
- # the EP is learnt via the learnt TEP
- # both from its MAC and its IP
- #
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
-
- #
- # wait for the learnt endpoints to age out
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # repeat. the do not learn bit is set so the EPs are not learnt
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88, gpflags="D") /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # repeat
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- # set a reserved bit in addition to the G and I
- # reserved bits should not be checked on rx.
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0xc8) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # Static EP replies to dynamics
- #
- self.logger.info(self.vapi.cli("sh l2fib bd_id 1"))
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=l['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 17, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
-
- #
- # repeat in the other EPG
- # there's no contract between 220 and 330, but the A-bit is set
- # so the packet is cleared for delivery
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # static EP cannot reach the learnt EPs since there is no contract
- # only test 1 EP as the others could timeout
- #
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=learnt[0]['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, [p])
-
- #
- # refresh the entries after the check for no replies above
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88, gpflags='A') /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
-
- #
- # Add the contract so they can talk
- #
- acl = VppGbpAcl(self)
- rule = acl.create_rule(permit_deny=1, proto=17)
- rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule, rule2])
- c1 = VppGbpContract(
- self, 401, epg_220.sclass, epg_330.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IP(dst=l['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect(self.pg0, [p], self.pg2)
-
- #
- # send UU packets from the local EP
- #
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- self.logger.info(self.vapi.cli("sh bridge-domain 1 detail"))
- p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
- IP(dst="10.0.0.133", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(ep.itf, [p_uu], gbd1.uu_fwd)
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
-
- p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- IP(dst="10.0.0.133", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect_only(ep.itf, [p_bm], tun_bm.mcast_itf)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg4.local_ip4)
- self.assertEqual(rx[IP].dst, "239.1.1.1")
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 88)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- acl = VppGbpAcl(self)
- rule = acl.create_rule(permit_deny=1, proto=17)
- rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule, rule2])
- c2 = VppGbpContract(
- self, 401, epg_330.sclass, epg_220.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
- #
- # Check v6 Endpoints learning
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- ip=l['ip6'],
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4]))
-
- self.logger.info(self.vapi.cli("sh int"))
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
- self.logger.info(self.vapi.cli("sh gbp vxlan"))
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- self.logger.info(self.vapi.cli("sh gbp interface"))
-
- #
- # EP moves to a different TEP
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=113, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- sclass=113,
- mac=l['mac'],
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- #
- # v6 remote EP reachability
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IPv6(dst=l['ip6'], src=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- self.assertEqual(rx[IPv6].dst, l['ip6'])
-
- #
- # EP changes sclass
- #
- for l in learnt:
- # a packet with an sclass from a known EPG
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=112, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IPv6(src=l['ip6'], dst=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, p * 1, self.pg0)
- rx = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(
- self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac'],
- sclass=112,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- #
- # check reachability and contract intra-epg
- #
- allow_intra_class = self.statistics.get_err_counter(
- '/err/gbp-policy-mac/allow-intra-sclass')
-
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- IPv6(dst=l['ip6'], src=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- self.assertEqual(rx[VXLAN].gpid, 112)
- self.assertEqual(rx[VXLAN].vni, 99)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
- self.assertEqual(rx[IPv6].dst, l['ip6'])
-
- allow_intra_class += NUM_PKTS
-
- self.assert_error_counter_equal(
- '/err/gbp-policy-mac/allow-intra-sclass',
- allow_intra_class)
-
- #
- # clean up
- #
- for l in learnt:
- self.wait_for_ep_timeout(vx_tun_l2_1.sw_if_index,
- mac=l['mac'])
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
- self.pg4.unconfig_ip4()
-
- def test_gbp_contract(self):
- """ GBP Contracts """
-
- #
- # Route Domains
- #
- gt4 = VppIpTable(self, 0)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 0, is_ip6=True)
- gt6.add_vpp_config()
-
- rd0 = VppGbpRouteDomain(self, 0, 400, gt4, gt6, None, None)
-
- rd0.add_vpp_config()
-
- #
- # Bridge Domains
- #
- bd1 = VppBridgeDomain(self, 1, arp_term=0)
- bd2 = VppBridgeDomain(self, 2, arp_term=0)
-
- bd1.add_vpp_config()
- bd2.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd0, self.loop0)
- gbd2 = VppGbpBridgeDomain(self, bd2, rd0, self.loop1)
-
- gbd1.add_vpp_config()
- gbd2.add_vpp_config()
-
- #
- # 3 EPGs, 2 of which share a BD.
- #
- epgs = [VppGbpEndpointGroup(self, 220, 1220, rd0, gbd1,
- None, self.loop0,
- "10.0.0.128", "2001:10::128"),
- VppGbpEndpointGroup(self, 221, 1221, rd0, gbd1,
- None, self.loop0,
- "10.0.1.128", "2001:10:1::128"),
- VppGbpEndpointGroup(self, 222, 1222, rd0, gbd2,
- None, self.loop1,
- "10.0.2.128", "2001:10:2::128")]
- #
- # 4 end-points, 2 in the same subnet, 3 in the same BD
- #
- eps = [VppGbpEndpoint(self, self.pg0,
- epgs[0], None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1"),
- VppGbpEndpoint(self, self.pg1,
- epgs[0], None,
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2"),
- VppGbpEndpoint(self, self.pg2,
- epgs[1], None,
- "10.0.1.1", "11.0.0.3",
- "2001:10:1::1", "3001::3"),
- VppGbpEndpoint(self, self.pg3,
- epgs[2], None,
- "10.0.2.1", "11.0.0.4",
- "2001:10:2::1", "3001::4")]
-
- #
- # Config related to each of the EPGs
- #
- for epg in epgs:
- # IP config on the BVI interfaces
- if epg != epgs[1]:
- VppIpInterfaceBind(self, epg.bvi, epg.rd.t4).add_vpp_config()
- VppIpInterfaceBind(self, epg.bvi, epg.rd.t6).add_vpp_config()
- self.vapi.sw_interface_set_mac_address(
- epg.bvi.sw_if_index,
- self.router_mac.packed)
-
- if_ip4 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip4, 32)
- if_ip6 = VppIpInterfaceAddress(self, epg.bvi, epg.bvi_ip6, 128)
- if_ip4.add_vpp_config()
- if_ip6.add_vpp_config()
-
- # add the BD ARP termination entry for BVI IP
- epg.bd_arp_ip4 = VppBridgeDomainArpEntry(self, epg.bd.bd,
- str(self.router_mac),
- epg.bvi_ip4.address)
- epg.bd_arp_ip4.add_vpp_config()
-
- # EPG in VPP
- epg.add_vpp_config()
-
- #
- # config ep
- #
- for ep in eps:
- ep.add_vpp_config()
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show interface"))
- self.logger.info(self.vapi.cli("show br"))
-
- #
- # Intra epg allowed without contract
- #
- pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IP(src=eps[0].ip4.address,
- dst=eps[1].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged(self.pg0,
- pkt_intra_epg_220_to_220 * 65,
- self.pg1)
-
- pkt_intra_epg_220_to_220 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg1.remote_mac) /
- IPv6(src=eps[0].ip6.address,
- dst=eps[1].ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect_bridged6(self.pg0,
- pkt_intra_epg_220_to_220 * 65,
- self.pg1)
-
- #
- # Inter epg denied without contract
- #
- pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg2.remote_mac) /
- IP(src=eps[0].ip4.address,
- dst=eps[2].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221)
-
- #
- # A uni-directional contract from EPG 220 -> 221
- #
- acl = VppGbpAcl(self)
- rule = acl.create_rule(permit_deny=1, proto=17)
- rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- rule3 = acl.create_rule(permit_deny=1, proto=1)
- acl_index = acl.add_vpp_config([rule, rule2, rule3])
- c1 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[1].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65,
- eps[2].itf)
-
- pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst=eps[3].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_assert_no_replies(eps[0].itf,
- pkt_inter_epg_220_to_222 * 65)
-
- #
- # ping router IP in different BD
- #
- pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[0].ip4.address,
- dst=epgs[1].bvi_ip4.address) /
- ICMP(type='echo-request'))
-
- self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
-
- pkt_router_ping_220_to_221 = (Ether(src=self.pg0.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[0].ip6.address,
- dst=epgs[1].bvi_ip6.address) /
- ICMPv6EchoRequest())
-
- self.send_and_expect(self.pg0, [pkt_router_ping_220_to_221], self.pg0)
-
- #
- # contract for the return direction
- #
- c2 = VppGbpContract(
- self, 400, epgs[1].sclass, epgs[0].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- self.send_and_expect_bridged(eps[0].itf,
- pkt_inter_epg_220_to_221 * 65,
- eps[2].itf)
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=self.pg0.remote_mac) /
- IP(src=eps[2].ip4.address,
- dst=eps[0].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect_bridged(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf)
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=str(self.router_mac)) /
- IP(src=eps[2].ip4.address,
- dst=eps[0].ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect_routed(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf,
- str(self.router_mac))
- pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac,
- dst=str(self.router_mac)) /
- IPv6(src=eps[2].ip6.address,
- dst=eps[0].ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect_routed6(eps[2].itf,
- pkt_inter_epg_221_to_220 * 65,
- eps[0].itf,
- str(self.router_mac))
-
- #
- # contract between 220 and 222 uni-direction
- #
- c3 = VppGbpContract(
- self, 400, epgs[0].sclass, epgs[2].sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- self.send_and_expect(eps[0].itf,
- pkt_inter_epg_220_to_222 * 65,
- eps[3].itf)
-
- c3.remove_vpp_config()
- c1.remove_vpp_config()
- c2.remove_vpp_config()
- acl.remove_vpp_config()
-
- def test_gbp_bd_drop_flags(self):
- """ GBP BD drop flags """
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI only
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- None, None,
- uu_drop=True, bm_drop=True)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip_addr.add_vpp_config()
-
- #
- # The Endpoint-group
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # send UU/BM packet from the local EP with UU drop and BM drop enabled
- # in bd
- #
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- p_uu = (Ether(src=ep.mac, dst="00:11:11:11:11:11") /
- IP(dst="10.0.0.133", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_assert_no_replies(ep.itf, [p_uu])
-
- p_bm = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- IP(dst="10.0.0.133", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_assert_no_replies(ep.itf, [p_bm])
-
- self.pg3.unconfig_ip4()
-
- self.logger.info(self.vapi.cli("sh int"))
-
- def test_gbp_bd_arp_flags(self):
- """ GBP BD arp flags """
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg4 hosts the IP6 UU-flood VXLAN tunnel
- #
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # Add a mcast destination VXLAN-GBP tunnel for B&M traffic
- #
- tun_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg4)
- tun_uu.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
-
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0,
- tun_uu, None,
- ucast_arp=True)
- gbd1.add_vpp_config()
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip_addr.add_vpp_config()
-
- #
- # The Endpoint-group
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 112, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # send ARP packet from the local EP expect it on the uu interface
- #
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- p_arp = (Ether(src=ep.mac, dst="ff:ff:ff:ff:ff:ff") /
- ARP(op="who-has",
- psrc=ep.ip4.address, pdst="10.0.0.99",
- hwsrc=ep.mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- self.send_and_expect(ep.itf, [p_arp], self.pg4)
-
- self.pg4.unconfig_ip4()
-
- def test_gbp_learn_vlan_l2(self):
- """ GBP L2 Endpoint w/ VLANs"""
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- learnt = [{'mac': '00:00:11:11:11:01',
- 'ip': '10.0.0.1',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:02',
- 'ip': '10.0.0.2',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- gt4 = VppIpTable(self, 1)
- gt4.add_vpp_config()
- gt6 = VppIpTable(self, 1, is_ip6=True)
- gt6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 1, 401, gt4, gt6)
- rd1.add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel, hosts on pg2 to act as TEPs
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
-
- #
- # The EP will be on a vlan sub-interface
- #
- vlan_11 = VppDot1QSubint(self, self.pg0, 11)
- vlan_11.admin_up()
- self.vapi.l2_interface_vlan_tag_rewrite(
- sw_if_index=vlan_11.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1,
- push_dot1q=11)
-
- bd_uu_fwd = VppVxlanGbpTunnel(self, self.pg3.local_ip4,
- self.pg3.remote_ip4, 116)
- bd_uu_fwd.add_vpp_config()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- # The BD is marked as do not learn, so no endpoints are ever
- # learnt in this BD.
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, bd_uu_fwd,
- learn=False)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
-
- # ... and has a /32 applied
- ip_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip_addr.add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is a bridge-port and has L2 endpoint
- # learning enabled
- #
- vx_tun_l2_1 = VppGbpVxlanTunnel(
- self, 99, bd1.bd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L2,
- self.pg2.local_ip4)
- vx_tun_l2_1.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, vlan_11,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- self.assertTrue(find_route(self, ep.ip4.address, 32, table_id=1))
-
- #
- # Send to the static EP
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=99, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst=ep.mac) /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg2, [p], self.pg0)
-
- #
- # packet to EP has the EP's vlan tag
- #
- for rx in rxs:
- self.assertEqual(rx[Dot1Q].vlan, 11)
-
- #
- # the EP is not learnt since the BD setting prevents it
- # also no TEP too
- #
- self.assertFalse(find_gbp_endpoint(self,
- vx_tun_l2_1.sw_if_index,
- mac=l['mac']))
- self.assertEqual(INDEX_INVALID,
- find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- 99))
-
- self.assertEqual(len(self.vapi.gbp_endpoint_dump()), 1)
-
- #
- # static to remotes
- # we didn't learn the remotes so they are sent to the UU-fwd
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=l['mac']) /
- Dot1Q(vlan=11) /
- IP(dst=l['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 17, self.pg3)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg3.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 116)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
-
- def test_gbp_learn_l3(self):
- """ GBP L3 Endpoint Learning """
-
- self.vapi.cli("set logging class gbp level debug")
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- learnt = [{'mac': '00:00:11:11:11:02',
- 'ip': '10.0.1.2',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:03',
- 'ip': '10.0.1.3',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- tun_ip4_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- self.pg4.remote_ip4, 114)
- tun_ip6_uu = VppVxlanGbpTunnel(self, self.pg4.local_ip4,
- self.pg4.remote_ip4, 116)
- tun_ip4_uu.add_vpp_config()
- tun_ip6_uu.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 401, t4, t6, tun_ip4_uu, tun_ip6_uu)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg2 hosts the vxlan tunnel
- # hosts on pg2 to act as TEPs
- # pg3 is BD uu-fwd
- # pg4 is RD uu-fwd
- #
- self.pg2.config_ip4()
- self.pg2.resolve_arp()
- self.pg2.generate_remote_hosts(4)
- self.pg2.configure_ipv4_neighbors()
- self.pg3.config_ip4()
- self.pg3.resolve_arp()
- self.pg4.config_ip4()
- self.pg4.resolve_arp()
-
- #
- # a GBP bridge domain with a BVI and a UU-flood interface
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, self.pg3)
- gbd1.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh bridge 1 detail"))
- self.logger.info(self.vapi.cli("sh gbp bridge"))
- self.logger.info(self.vapi.cli("sh gbp route"))
-
- # ... and has a /32 and /128 applied
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip4_addr.add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
- ip6_addr.add_vpp_config()
-
- #
- # The Endpoint-group in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 441, rd1, gbd1,
- None, self.loop0,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- #
- # The VXLAN GBP tunnel is in L3 mode with learning enabled
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 101, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # A static endpoint that the learnt endpoints are trying to
- # talk to
- #
- ep = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.127", "11.0.0.127",
- "2001:10::1", "3001::1")
- ep.add_vpp_config()
-
- #
- # learn some remote IPv4 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # Static IPv4 EP replies to learnt
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=l['ip'], src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IP].src, ep.ip4.address)
- self.assertEqual(inner[IP].dst, l['ip'])
-
- for l in learnt:
- self.assertFalse(find_gbp_endpoint(self,
- tep1_sw_if_index,
- ip=l['ip']))
-
- #
- # learn some remote IPv6 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IPv6(src=l['ip6'], dst=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- self.logger.info(self.vapi.cli("show gbp bridge"))
- self.logger.info(self.vapi.cli("show vxlan-gbp tunnel"))
- self.logger.info(self.vapi.cli("show gbp vxlan"))
- self.logger.info(self.vapi.cli("show int addr"))
-
- # endpoint learnt via the TEP
- self.assertTrue(find_gbp_endpoint(self, ip=l['ip6']))
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
- self.logger.info(self.vapi.cli("show ip fib index 1 %s" % l['ip']))
-
- #
- # Static EP replies to learnt
- #
- for l in learnt:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IPv6(dst=l['ip6'], src=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IPv6].src, ep.ip6.address)
- self.assertEqual(inner[IPv6].dst, l['ip6'])
-
- self.logger.info(self.vapi.cli("sh gbp endpoint"))
- for l in learnt:
- self.wait_for_ep_timeout(ip=l['ip'])
-
- #
- # Static sends to unknown EP with no route
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.0.99", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_no_replies(self.pg0, [p])
-
- #
- # Add a route to static EP's v4 and v6 subnet
- #
- se_10_24 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
- se_10_24.add_vpp_config()
-
- #
- # static pings router
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=epg_220.bvi_ip4.address, src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IPv6(dst=epg_220.bvi_ip6.address, src=ep.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- #
- # packets to address in the subnet are sent on the uu-fwd
- #
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.0.99", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, [p], self.pg4)
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg4.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg4.remote_ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 114)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # policy is not applied to packets sent to the uu-fwd interfaces
- self.assertFalse(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- #
- # learn some remote IPv4 EPs
- #
- for ii, l in enumerate(learnt):
- # a packet with an sclass from a known EPG
- # arriving on an unknown TEP
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=l['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # the new TEP
- tep1_sw_if_index = find_vxlan_gbp_tunnel(
- self,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4,
- vx_tun_l3.vni)
- self.assertNotEqual(INDEX_INVALID, tep1_sw_if_index)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # Add a remote endpoint from the API
- #
- rep_88 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.88", "11.0.0.88",
- "2001:10::88", "3001::88",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4,
- mac=None)
- rep_88.add_vpp_config()
-
- #
- # Add a remote endpoint from the API that matches an existing one
- # this is a lower priority, hence the packet is sent to the DP leanrt
- # TEP
- #
- rep_2 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- learnt[0]['ip'], "11.0.0.101",
- learnt[0]['ip6'], "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- mac=None)
- rep_2.add_vpp_config()
-
- #
- # Add a route to the learned EP's v4 subnet
- # packets should be send on the v4/v6 uu=fwd interface resp.
- #
- se_10_1_24 = VppGbpSubnet(
- self, rd1, "10.0.1.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_TRANSPORT)
- se_10_1_24.add_vpp_config()
-
- self.logger.info(self.vapi.cli("show gbp endpoint"))
-
- ips = ["10.0.0.88", learnt[0]['ip']]
- for ip in ips:
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst=ip, src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
- self.assertEqual(rx[UDP].dport, 48879)
- # the UDP source port is a random value for hashing
- self.assertEqual(rx[VXLAN].gpid, 441)
- self.assertEqual(rx[VXLAN].vni, 101)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, routed_dst_mac)
- self.assertEqual(inner[IP].src, ep.ip4.address)
- self.assertEqual(inner[IP].dst, ip)
-
- #
- # remove the API remote EPs, only API sourced is gone, the DP
- # learnt one remains
- #
- rep_88.remove_vpp_config()
- rep_2.remove_vpp_config()
-
- self.assertTrue(find_gbp_endpoint(self, ip=rep_2.ip4.address))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(src=ep.ip4.address, dst=rep_2.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, [p], self.pg2)
-
- self.assertFalse(find_gbp_endpoint(self, ip=rep_88.ip4.address))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(src=ep.ip4.address, dst=rep_88.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, [p], self.pg4)
-
- #
- # to appease the testcase we cannot have the registered EP still
- # present (because it's DP learnt) when the TC ends so wait until
- # it is removed
- #
- self.wait_for_ep_timeout(ip=rep_88.ip4.address)
- self.wait_for_ep_timeout(ip=rep_2.ip4.address)
-
- #
- # Same as above, learn a remote EP via CP and DP
- # this time remove the DP one first. expect the CP data to remain
- #
- rep_3 = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.1.4", "11.0.0.103",
- "2001::10:3", "3001::103",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg2.local_ip4,
- self.pg2.remote_hosts[1].ip4,
- mac=None)
- rep_3.add_vpp_config()
-
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[2].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src="10.0.1.4", dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg2, p * NUM_PKTS, self.pg0)
-
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=rep_3.ip4.address,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4]))
-
- p = (Ether(src=ep.mac, dst=self.loop0.local_mac) /
- IP(dst="10.0.1.4", src=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- # host 2 is the DP learned TEP
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[2].ip4)
-
- self.wait_for_ep_timeout(ip=rep_3.ip4.address,
- tep=[self.pg2.local_ip4,
- self.pg2.remote_hosts[2].ip4])
-
- rxs = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg2)
-
- # host 1 is the CP learned TEP
- for rx in rxs:
- self.assertEqual(rx[IP].src, self.pg2.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg2.remote_hosts[1].ip4)
-
- #
- # shutdown with learnt endpoint present
- #
- p = (Ether(src=self.pg2.remote_mac,
- dst=self.pg2.local_mac) /
- IP(src=self.pg2.remote_hosts[1].ip4,
- dst=self.pg2.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=101, gpid=441, flags=0x88) /
- Ether(src=l['mac'], dst="00:00:00:11:11:11") /
- IP(src=learnt[1]['ip'], dst=ep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg2, [p], self.pg0)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip=l['ip']))
-
- #
- # TODO
- # remote endpoint becomes local
- #
- self.pg2.unconfig_ip4()
- self.pg3.unconfig_ip4()
- self.pg4.unconfig_ip4()
-
- def test_gbp_redirect(self):
- """ GBP Endpoint Redirect """
-
- self.vapi.cli("set logging class gbp level debug")
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- learnt = [{'mac': '00:00:11:11:11:02',
- 'ip': '10.0.1.2',
- 'ip6': '2001:10::2'},
- {'mac': '00:00:11:11:11:03',
- 'ip': '10.0.1.3',
- 'ip6': '2001:10::3'}]
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 402, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's UU-fwd
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a GBP bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0)
- gbd1.add_vpp_config()
-
- bd2 = VppBridgeDomain(self, 2)
- bd2.add_vpp_config()
- gbd2 = VppGbpBridgeDomain(self, bd2, rd1, self.loop1)
- gbd2.add_vpp_config()
-
- # ... and has a /32 and /128 applied
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 32)
- ip4_addr.add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 128)
- ip6_addr.add_vpp_config()
- ip4_addr = VppIpInterfaceAddress(self, gbd2.bvi, "10.0.1.128", 32)
- ip4_addr.add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd2.bvi, "2001:11::128", 128)
- ip6_addr.add_vpp_config()
-
- #
- # The Endpoint-groups in which we are learning endpoints
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 440, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
- epg_221 = VppGbpEndpointGroup(self, 221, 441, rd1, gbd2,
- None, gbd2.bvi,
- "10.0.1.128",
- "2001:11::128",
- VppGbpEndpointRetention(2))
- epg_221.add_vpp_config()
- epg_222 = VppGbpEndpointGroup(self, 222, 442, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.2.128",
- "2001:12::128",
- VppGbpEndpointRetention(2))
- epg_222.add_vpp_config()
-
- #
- # a GBP bridge domains for the SEPs
- #
- bd_uu1 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 116)
- bd_uu1.add_vpp_config()
- bd_uu2 = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 117)
- bd_uu2.add_vpp_config()
-
- bd3 = VppBridgeDomain(self, 3)
- bd3.add_vpp_config()
- gbd3 = VppGbpBridgeDomain(self, bd3, rd1, self.loop2,
- bd_uu1, learn=False)
- gbd3.add_vpp_config()
- bd4 = VppBridgeDomain(self, 4)
- bd4.add_vpp_config()
- gbd4 = VppGbpBridgeDomain(self, bd4, rd1, self.loop3,
- bd_uu2, learn=False)
- gbd4.add_vpp_config()
-
- #
- # EPGs in which the service endpoints exist
- #
- epg_320 = VppGbpEndpointGroup(self, 320, 550, rd1, gbd3,
- None, gbd1.bvi,
- "12.0.0.128",
- "4001:10::128",
- VppGbpEndpointRetention(2))
- epg_320.add_vpp_config()
- epg_321 = VppGbpEndpointGroup(self, 321, 551, rd1, gbd4,
- None, gbd2.bvi,
- "12.0.1.128",
- "4001:11::128",
- VppGbpEndpointRetention(2))
- epg_321.add_vpp_config()
-
- #
- # three local endpoints
- #
- ep1 = VppGbpEndpoint(self, self.pg0,
- epg_220, None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001:10::1")
- ep1.add_vpp_config()
- ep2 = VppGbpEndpoint(self, self.pg1,
- epg_221, None,
- "10.0.1.1", "11.0.1.1",
- "2001:11::1", "3001:11::1")
- ep2.add_vpp_config()
- ep3 = VppGbpEndpoint(self, self.pg2,
- epg_222, None,
- "10.0.2.2", "11.0.2.2",
- "2001:12::1", "3001:12::1")
- ep3.add_vpp_config()
-
- #
- # service endpoints
- #
- sep1 = VppGbpEndpoint(self, self.pg3,
- epg_320, None,
- "12.0.0.1", "13.0.0.1",
- "4001:10::1", "5001:10::1")
- sep1.add_vpp_config()
- sep2 = VppGbpEndpoint(self, self.pg4,
- epg_320, None,
- "12.0.0.2", "13.0.0.2",
- "4001:10::2", "5001:10::2")
- sep2.add_vpp_config()
- sep3 = VppGbpEndpoint(self, self.pg5,
- epg_321, None,
- "12.0.1.1", "13.0.1.1",
- "4001:11::1", "5001:11::1")
- sep3.add_vpp_config()
- # this EP is not installed immediately
- sep4 = VppGbpEndpoint(self, self.pg6,
- epg_321, None,
- "12.0.1.2", "13.0.1.2",
- "4001:11::2", "5001:11::2")
-
- #
- # an L2 switch packet between local EPs in different EPGs
- # different dest ports on each so the are LB hashed differently
- #
- p4 = [(Ether(src=ep1.mac, dst=ep3.mac) /
- IP(src=ep1.ip4.address, dst=ep3.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=ep3.mac, dst=ep1.mac) /
- IP(src=ep3.ip4.address, dst=ep1.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=ep3.mac) /
- IPv6(src=ep1.ip6.address, dst=ep3.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=ep3.mac, dst=ep1.mac) /
- IPv6(src=ep3.ip6.address, dst=ep1.ip6.address) /
- UDP(sport=1234, dport=1230) /
- Raw('\xa5' * 100))]
-
- # should be dropped since no contract yet
- self.send_and_assert_no_replies(self.pg0, [p4[0]])
- self.send_and_assert_no_replies(self.pg0, [p6[0]])
-
- #
- # Add a contract with a rule to load-balance redirect via SEP1 and SEP2
- # one of the next-hops is via an EP that is not known
- #
- acl = VppGbpAcl(self)
- rule4 = acl.create_rule(permit_deny=1, proto=17)
- rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule4, rule6])
-
- #
- # test the src-ip hash mode
- #
- c1 = VppGbpContract(
- self, 402, epg_220.sclass, epg_222.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 402, epg_222.sclass, epg_220.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- #
- # send again with the contract preset, now packets arrive
- # at SEP1 or SEP2 depending on the hashing
- #
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4.address)
- self.assertEqual(rx[IP].dst, ep3.ip4.address)
-
- rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep2.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep2.mac)
- self.assertEqual(rx[IP].src, ep3.ip4.address)
- self.assertEqual(rx[IP].dst, ep1.ip4.address)
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 117)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep4.mac)
- self.assertEqual(inner[IPv6].src, ep1.ip6.address)
- self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
-
- rxs = self.send_and_expect(self.pg2, p6[1] * 17, sep3.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep3.mac)
- self.assertEqual(rx[IPv6].src, ep3.ip6.address)
- self.assertEqual(rx[IPv6].dst, ep1.ip6.address)
-
- #
- # programme the unknown EP
- #
- sep4.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep4.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6.address)
- self.assertEqual(rx[IPv6].dst, ep3.ip6.address)
-
- #
- # and revert back to unprogrammed
- #
- sep4.remove_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 117)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertEqual(inner[Ether].src, routed_src_mac)
- self.assertEqual(inner[Ether].dst, sep4.mac)
- self.assertEqual(inner[IPv6].src, ep1.ip6.address)
- self.assertEqual(inner[IPv6].dst, ep3.ip6.address)
-
- c1.remove_vpp_config()
- c2.remove_vpp_config()
-
- #
- # test the symmetric hash mode
- #
- c1 = VppGbpContract(
- self, 402, epg_220.sclass, epg_222.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- c2 = VppGbpContract(
- self, 402, epg_222.sclass, epg_220.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
-
- #
- # send again with the contract preset, now packets arrive
- # at SEP1 for both directions
- #
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4.address)
- self.assertEqual(rx[IP].dst, ep3.ip4.address)
-
- rxs = self.send_and_expect(self.pg2, p4[1] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep3.ip4.address)
- self.assertEqual(rx[IP].dst, ep1.ip4.address)
-
- #
- # programme the unknown EP for the L3 tests
- #
- sep4.add_vpp_config()
-
- #
- # an L3 switch packet between local EPs in different EPGs
- # different dest ports on each so the are LB hashed differently
- #
- p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IP(src=ep1.ip4.address, dst=ep2.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IP(src=ep2.ip4.address, dst=ep1.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IPv6(src=ep1.ip6.address, dst=ep2.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=ep2.mac, dst=str(self.router_mac)) /
- IPv6(src=ep2.ip6.address, dst=ep1.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
-
- c3 = VppGbpContract(
- self, 402, epg_220.sclass, epg_221.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SYMMETRIC,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4.address)
- self.assertEqual(rx[IP].dst, ep2.ip4.address)
-
- #
- # learn a remote EP in EPG 221
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- c4 = VppGbpContract(
- self, 402, epg_221.sclass, epg_220.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=441, flags=0x88) /
- Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
- IP(src="10.0.0.88", dst=ep1.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg7, [p], self.pg0)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="10.0.0.88"))
-
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=441, flags=0x88) /
- Ether(src="00:22:22:22:22:33", dst=str(self.router_mac)) /
- IPv6(src="2001:10::88", dst=ep1.ip6.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rx = self.send_and_expect(self.pg7, [p], self.pg0)
-
- # endpoint learnt via the parent GBP-vxlan interface
- self.assertTrue(find_gbp_endpoint(self,
- vx_tun_l3._sw_if_index,
- ip="2001:10::88"))
-
- #
- # L3 switch from local to remote EP
- #
- p4 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IP(src=ep1.ip4.address, dst="10.0.0.88") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
- p6 = [(Ether(src=ep1.mac, dst=str(self.router_mac)) /
- IPv6(src=ep1.ip6.address, dst="2001:10::88") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4.address)
- self.assertEqual(rx[IP].dst, "10.0.0.88")
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep4.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep4.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6.address)
- self.assertEqual(rx[IPv6].dst, "2001:10::88")
-
- #
- # test the dst-ip hash mode
- #
- c5 = VppGbpContract(
- self, 402, epg_220.sclass, epg_221.sclass, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep1.vmac, sep1.epg.bd,
- sep1.ip4, sep1.epg.rd),
- VppGbpContractNextHop(sep2.vmac, sep2.epg.bd,
- sep2.ip4, sep2.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep3.vmac, sep3.epg.bd,
- sep3.ip6, sep3.epg.rd),
- VppGbpContractNextHop(sep4.vmac, sep4.epg.bd,
- sep4.ip6, sep4.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6])
- c5.add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p4[0] * 17, sep1.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep1.mac)
- self.assertEqual(rx[IP].src, ep1.ip4.address)
- self.assertEqual(rx[IP].dst, "10.0.0.88")
-
- rxs = self.send_and_expect(self.pg0, p6[0] * 17, sep3.itf)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, routed_src_mac)
- self.assertEqual(rx[Ether].dst, sep3.mac)
- self.assertEqual(rx[IPv6].src, ep1.ip6.address)
- self.assertEqual(rx[IPv6].dst, "2001:10::88")
-
- #
- # redirect to programmed remote SEP in EPG 320
- #
-
- # gbp vxlan tunnel for the remote SEP
- vx_tun_l3_sep = VppGbpVxlanTunnel(
- self, 555, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3_sep.add_vpp_config()
-
- # remote SEP
- sep5 = VppGbpEndpoint(self, vx_tun_l3_sep,
- epg_320, None,
- "12.0.0.10", "13.0.0.10",
- "4001:10::10", "5001:10::10",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- sep5.add_vpp_config()
-
- #
- # redirect from local l3out to remote (known, then unknown) SEP
- #
-
- # add local l3out
- # the external bd
- self.loop4.set_mac(self.router_mac)
- VppIpInterfaceBind(self, self.loop4, t4).add_vpp_config()
- VppIpInterfaceBind(self, self.loop4, t6).add_vpp_config()
- ebd = VppBridgeDomain(self, 100)
- ebd.add_vpp_config()
- gebd = VppGbpBridgeDomain(self, ebd, rd1, self.loop4, None, None)
- gebd.add_vpp_config()
- # the external epg
- eepg = VppGbpEndpointGroup(self, 888, 765, rd1, gebd,
- None, gebd.bvi,
- "10.1.0.128",
- "2001:10:1::128",
- VppGbpEndpointRetention(2))
- eepg.add_vpp_config()
- # add subnets to BVI
- VppIpInterfaceAddress(
- self,
- gebd.bvi,
- "10.1.0.128",
- 24).add_vpp_config()
- VppIpInterfaceAddress(
- self,
- gebd.bvi,
- "2001:10:1::128",
- 64).add_vpp_config()
- # ... which are L3-out subnets
- VppGbpSubnet(self, rd1, "10.1.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=765).add_vpp_config()
- VppGbpSubnet(self, rd1, "2001:10:1::128", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=765).add_vpp_config()
- # external endpoints
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- eep1 = VppGbpEndpoint(self, self.vlan_100, eepg, None, "10.1.0.1",
- "11.1.0.1", "2001:10:1::1", "3001:10:1::1",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep1.add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
- eep2 = VppGbpEndpoint(self, self.vlan_101, eepg, None, "10.1.0.2",
- "11.1.0.2", "2001:10:1::2", "3001:10:1::2",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep2.add_vpp_config()
-
- # external subnets reachable though eep1 and eep2 respectively
- VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath(eep1.ip4.address, eep1.epg.bvi.sw_if_index)],
- table_id=t4.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10.220.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220).add_vpp_config()
- VppIpRoute(self, "10:220::", 64,
- [VppRoutePath(eep1.ip6.address, eep1.epg.bvi.sw_if_index)],
- table_id=t6.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10:220::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220).add_vpp_config()
- VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath(eep2.ip4.address, eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10.221.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221).add_vpp_config()
- VppIpRoute(self, "10:221::", 64,
- [VppRoutePath(eep2.ip6.address, eep2.epg.bvi.sw_if_index)],
- table_id=t6.table_id).add_vpp_config()
- VppGbpSubnet(self, rd1, "10:221::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221).add_vpp_config()
-
- # packets from 1 external subnet to the other
- p = [(Ether(src=eep1.mac, dst=self.router_mac) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.17", dst="10.221.0.65") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=eep1.mac, dst=self.router_mac) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::17", dst="10:221::65") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
-
- # packets should be dropped in absence of contract
- self.send_and_assert_no_replies(self.pg0, p)
-
- # contract redirecting to sep5
- VppGbpContract(
- self, 402, 4220, 4221, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip4, sep5.epg.rd)]),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_REDIRECT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_DST_IP,
- [VppGbpContractNextHop(sep5.vmac, sep5.epg.bd,
- sep5.ip6, sep5.epg.rd)])],
- [ETH_P_IP, ETH_P_IPV6]).add_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the programmed remote leaf TEP
- self.assertEqual(rx[VXLAN].vni, 555)
- self.assertEqual(rx[VXLAN].gpid, 4220)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertTrue(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[Dot1Q].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- # remove SEP: it is now an unknown remote SEP and should go
- # to spine proxy
- sep5.remove_vpp_config()
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- for rx, tx in zip(rxs, p):
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- # this should use the spine proxy TEP
- self.assertEqual(rx[VXLAN].vni, epg_320.bd.uu_fwd.vni)
- self.assertEqual(rx[VXLAN].gpid, 4220)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # redirect policy has been applied
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertTrue(rx[VXLAN].gpflags.D)
- rxip = rx[VXLAN][Ether].payload
- txip = tx[Dot1Q].payload
- self.assertEqual(rxip.src, txip.src)
- self.assertEqual(rxip.dst, txip.dst)
-
- #
- # cleanup
- #
- self.pg7.unconfig_ip4()
-
- def test_gbp_l3_out(self):
- """ GBP L3 Out """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- self.vapi.cli("set logging class gbp level debug")
-
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's BUM
- # Pg1 some other l3 interface
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a multicast vxlan-gbp tunnel for broadcast in the BD
- #
- tun_bm = VppVxlanGbpTunnel(self, self.pg7.local_ip4,
- "239.1.1.1", 88,
- mcast_itf=self.pg7)
- tun_bm.add_vpp_config()
-
- #
- # a GBP external bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, tun_bm)
- gbd1.add_vpp_config()
-
- #
- # The Endpoint-groups in which the external endpoints exist
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- # the BVIs have the subnets applied ...
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
- ip4_addr.add_vpp_config()
- ip6_addr = VppIpInterfaceAddress(self, gbd1.bvi, "2001:10::128", 64)
- ip6_addr.add_vpp_config()
-
- # ... which are L3-out subnets
- l3o_1 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=113)
- l3o_1.add_vpp_config()
-
- #
- # an external interface attached to the outside world and the
- # external BD
- #
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
- vlan_144 = VppDot1QSubint(self, self.pg0, 144)
- vlan_144.admin_up()
- # vlan_102 is not poped
-
- #
- # an unicast vxlan-gbp for inter-RD traffic
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # External Endpoints
- #
- eep1 = VppGbpEndpoint(self, self.vlan_100,
- epg_220, None,
- "10.0.0.1", "11.0.0.1",
- "2001:10::1", "3001::1",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep1.add_vpp_config()
- eep2 = VppGbpEndpoint(self, self.vlan_101,
- epg_220, None,
- "10.0.0.2", "11.0.0.2",
- "2001:10::2", "3001::2",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep2.add_vpp_config()
- eep3 = VppGbpEndpoint(self, self.vlan_102,
- epg_220, None,
- "10.0.0.3", "11.0.0.3",
- "2001:10::3", "3001::3",
- ep_flags.GBP_API_ENDPOINT_FLAG_EXTERNAL)
- eep3.add_vpp_config()
-
- #
- # A remote external endpoint
- #
- rep = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.101", "11.0.0.101",
- "2001:10::101", "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- rep.add_vpp_config()
-
- #
- # EP1 impersonating EP3 is dropped
- #
- p = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc="10.0.0.3", pdst="10.0.0.128",
- hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- self.send_and_assert_no_replies(self.pg0, p)
-
- #
- # ARP packet from External EPs are accepted and replied to
- #
- p_arp = (Ether(src=eep1.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc=eep1.ip4.address, pdst="10.0.0.128",
- hwsrc=eep1.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
-
- #
- # ARP packet from host in remote subnet are accepted and replied to
- #
- p_arp = (Ether(src=eep3.mac, dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=102) /
- ARP(op="who-has",
- psrc=eep3.ip4.address, pdst="10.0.0.128",
- hwsrc=eep3.mac, hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0)
-
- #
- # packets destined to unknown addresses in the BVI's subnet
- # are ARP'd for
- #
- p4 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.1", dst="10.0.0.88") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- p6 = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="2001:10::1", dst="2001:10::88") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p4 * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, "239.1.1.1")
- self.assertEqual(rx[VXLAN].vni, 88)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # policy was applied to the original IP packet
- self.assertEqual(rx[VXLAN].gpid, 113)
- self.assertTrue(rx[VXLAN].gpflags.A)
- self.assertFalse(rx[VXLAN].gpflags.D)
-
- inner = rx[VXLAN].payload
-
- self.assertTrue(inner.haslayer(ARP))
-
- #
- # remote to external
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.0.0.101", dst="10.0.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # local EP pings router
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src=eep1.ip4.address, dst="10.0.0.128") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP pings other local EP
- #
- p = (Ether(src=eep1.mac, dst=eep2.mac) /
- Dot1Q(vlan=100) /
- IP(src=eep1.ip4.address, dst=eep2.ip4.address) /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, eep1.mac)
- self.assertEqual(rx[Ether].dst, eep2.mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- #
- # local EP pings router w/o vlan tag poped
- #
- p = (Ether(src=eep3.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=102) /
- IP(src=eep3.ip4.address, dst="10.0.0.128") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_102.remote_mac)
-
- #
- # A ip4 subnet reachable through the external EP1
- #
- ip_220 = VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath(eep1.ip4.address,
- eep1.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_220.add_vpp_config()
-
- l3o_220 = VppGbpSubnet(
- self, rd1, "10.220.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_220.add_vpp_config()
-
- #
- # An ip6 subnet reachable through the external EP1
- #
- ip6_220 = VppIpRoute(self, "10:220::", 64,
- [VppRoutePath(eep1.ip6.address,
- eep1.epg.bvi.sw_if_index)],
- table_id=t6.table_id)
- ip6_220.add_vpp_config()
-
- l3o6_220 = VppGbpSubnet(
- self, rd1, "10:220::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o6_220.add_vpp_config()
-
- #
- # A subnet reachable through the external EP2
- #
- ip_221 = VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath(eep2.ip4.address,
- eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_221.add_vpp_config()
-
- l3o_221 = VppGbpSubnet(
- self, rd1, "10.221.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221)
- l3o_221.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- # dropped without a contract
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- ICMP(type='echo-request'))
-
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # contract for the external nets to communicate
- #
- acl = VppGbpAcl(self)
- rule4 = acl.create_rule(permit_deny=1, proto=17)
- rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule4, rule6])
-
- #
- # A contract with the wrong scope is not matched
- #
- c_44 = VppGbpContract(
- self, 44, 4220, 4221, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c_44.add_vpp_config()
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- c1 = VppGbpContract(
- self, 55, 4220, 4221, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- #
- # Contracts allowing ext-net 200 to talk with external EPs
- #
- c2 = VppGbpContract(
- self, 55, 4220, 113, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
- c3 = VppGbpContract(
- self, 55, 113, 4220, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep2.mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- # we did not learn these external hosts
- self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
- self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
-
- #
- # from remote external EP to local external EP
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.0.0.101", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # ping from an external host to the remote external EP
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst=rep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 444)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, rep.ip4.address)
-
- #
- # An external subnet reachable via the remote external EP
- #
-
- #
- # first the VXLAN-GBP tunnel over which it is reached
- #
- vx_tun_r1 = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 445,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r1.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r1, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- #
- # then the special adj to resolve through on that tunnel
- #
- n1 = VppNeighbor(self,
- vx_tun_r1.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n1.add_vpp_config()
-
- #
- # the route via the adj above
- #
- ip_222 = VppIpRoute(self, "10.222.0.0", 24,
- [VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r1.sw_if_index)],
- table_id=t4.table_id)
- ip_222.add_vpp_config()
-
- l3o_222 = VppGbpSubnet(
- self, rd1, "10.222.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222.add_vpp_config()
-
- #
- # ping between hosts in local and remote external subnets
- # dropped without a contract
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add contracts ext-nets for 220 -> 222
- #
- c4 = VppGbpContract(
- self, 55, 4220, 4222, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- #
- # ping from host in local to remote external subnets
- #
- p = (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 445)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, "10.222.0.1")
-
- #
- # make the external subnet ECMP
- #
- vx_tun_r2 = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 446,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r2.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r2, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- n2 = VppNeighbor(self,
- vx_tun_r2.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n2.add_vpp_config()
-
- ip_222.modify([VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r1.sw_if_index),
- VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r2.sw_if_index)])
-
- #
- # now expect load-balance
- #
- p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1222, dport=1235) /
- Raw('\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- self.assertEqual(rxs[0][VXLAN].vni, 445)
- self.assertEqual(rxs[1][VXLAN].vni, 446)
-
- #
- # Same LB test for v6
- #
- n3 = VppNeighbor(self,
- vx_tun_r1.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip6)
- n3.add_vpp_config()
- n4 = VppNeighbor(self,
- vx_tun_r2.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip6)
- n4.add_vpp_config()
-
- ip_222_6 = VppIpRoute(self, "10:222::", 64,
- [VppRoutePath(self.pg7.remote_ip6,
- vx_tun_r1.sw_if_index),
- VppRoutePath(self.pg7.remote_ip6,
- vx_tun_r2.sw_if_index)],
- table_id=t6.table_id)
- ip_222_6.add_vpp_config()
-
- l3o_222_6 = VppGbpSubnet(
- self, rd1, "10:222::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222_6.add_vpp_config()
-
- p = [(Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::1", dst="10:222::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=eep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IPv6(src="10:220::1", dst="10:222::1") /
- UDP(sport=7777, dport=8881) /
- Raw('\xa5' * 100))]
-
- self.logger.info(self.vapi.cli("sh ip6 fib 10:222::1"))
- rxs = self.send_and_expect(self.pg0, p, self.pg7)
-
- self.assertEqual(rxs[0][VXLAN].vni, 445)
- self.assertEqual(rxs[1][VXLAN].vni, 446)
-
- #
- # ping from host in remote to local external subnets
- # there's no contract for this, but the A bit is set.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
- self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
-
- #
- # ping from host in remote to remote external subnets
- # this is dropped by reflection check.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.222.0.2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IPv6(src="10:222::1", dst="10:222::2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- #
- # local EP
- #
- lep1 = VppGbpEndpoint(self, vlan_144,
- epg_220, None,
- "10.0.0.44", "11.0.0.44",
- "2001:10::44", "3001::44")
- lep1.add_vpp_config()
-
- #
- # local EP to local ip4 external subnet
- #
- p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4.address, dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP to local ip6 external subnet
- #
- p = (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6.address, dst="10:220::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, eep1.mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # ip4 and ip6 subnets that load-balance
- #
- ip_20 = VppIpRoute(self, "10.20.0.0", 24,
- [VppRoutePath(eep1.ip4.address,
- eep1.epg.bvi.sw_if_index),
- VppRoutePath(eep2.ip4.address,
- eep2.epg.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_20.add_vpp_config()
-
- l3o_20 = VppGbpSubnet(
- self, rd1, "10.20.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_20.add_vpp_config()
-
- ip6_20 = VppIpRoute(self, "10:20::", 64,
- [VppRoutePath(eep1.ip6.address,
- eep1.epg.bvi.sw_if_index),
- VppRoutePath(eep2.ip6.address,
- eep2.epg.bvi.sw_if_index)],
- table_id=t6.table_id)
- ip6_20.add_vpp_config()
-
- l3o6_20 = VppGbpSubnet(
- self, rd1, "10:20::", 64,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o6_20.add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh ip fib 10.20.0.1"))
- self.logger.info(self.vapi.cli("sh ip6 fib 10:20::1"))
-
- # two ip6 packets whose port are chosen so they load-balance
- p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6.address, dst="10:20::1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IPv6(src=lep1.ip6.address, dst="10:20::1") /
- UDP(sport=124, dport=1230) /
- Raw('\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
-
- self.assertEqual(rxs[0][Dot1Q].vlan, 101)
- self.assertEqual(rxs[1][Dot1Q].vlan, 100)
-
- # two ip4 packets whose port are chosen so they load-balance
- p = [(Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4.address, dst="10.20.0.1") /
- UDP(sport=1235, dport=1235) /
- Raw('\xa5' * 100)),
- (Ether(src=lep1.mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=144) /
- IP(src=lep1.ip4.address, dst="10.20.0.1") /
- UDP(sport=124, dport=1230) /
- Raw('\xa5' * 100))]
-
- rxs = self.send_and_expect(self.pg0, p, self.pg0, 2)
-
- self.assertEqual(rxs[0][Dot1Q].vlan, 101)
- self.assertEqual(rxs[1][Dot1Q].vlan, 100)
-
- #
- # cleanup
- #
- ip_222.remove_vpp_config()
- self.pg7.unconfig_ip4()
- self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
-
- def test_gbp_anon_l3_out(self):
- """ GBP Anonymous L3 Out """
-
- ep_flags = VppEnum.vl_api_gbp_endpoint_flags_t
- self.vapi.cli("set logging class gbp level debug")
-
- routed_dst_mac = "00:0c:0c:0c:0c:0c"
- routed_src_mac = "00:22:bd:f8:19:ff"
-
- #
- # IP tables
- #
- t4 = VppIpTable(self, 1)
- t4.add_vpp_config()
- t6 = VppIpTable(self, 1, True)
- t6.add_vpp_config()
-
- rd1 = VppGbpRouteDomain(self, 2, 55, t4, t6)
- rd1.add_vpp_config()
-
- self.loop0.set_mac(self.router_mac)
-
- #
- # Bind the BVI to the RD
- #
- VppIpInterfaceBind(self, self.loop0, t4).add_vpp_config()
- VppIpInterfaceBind(self, self.loop0, t6).add_vpp_config()
-
- #
- # Pg7 hosts a BD's BUM
- # Pg1 some other l3 interface
- #
- self.pg7.config_ip4()
- self.pg7.resolve_arp()
-
- #
- # a GBP external bridge domains for the EPs
- #
- bd1 = VppBridgeDomain(self, 1)
- bd1.add_vpp_config()
- gbd1 = VppGbpBridgeDomain(self, bd1, rd1, self.loop0, None, None)
- gbd1.add_vpp_config()
-
- #
- # The Endpoint-groups in which the external endpoints exist
- #
- epg_220 = VppGbpEndpointGroup(self, 220, 113, rd1, gbd1,
- None, gbd1.bvi,
- "10.0.0.128",
- "2001:10::128",
- VppGbpEndpointRetention(2))
- epg_220.add_vpp_config()
-
- # the BVIs have the subnet applied ...
- ip4_addr = VppIpInterfaceAddress(self, gbd1.bvi, "10.0.0.128", 24)
- ip4_addr.add_vpp_config()
-
- # ... which is an Anonymous L3-out subnets
- l3o_1 = VppGbpSubnet(
- self, rd1, "10.0.0.0", 24,
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_ANON_L3_OUT,
- sclass=113)
- l3o_1.add_vpp_config()
-
- #
- # an external interface attached to the outside world and the
- # external BD
- #
- VppL2Vtr(self, self.vlan_100, L2_VTR_OP.L2_POP_1).add_vpp_config()
- VppL2Vtr(self, self.vlan_101, L2_VTR_OP.L2_POP_1).add_vpp_config()
-
- #
- # vlan_100 and vlan_101 are anonymous l3-out interfaces
- #
- ext_itf = VppGbpExtItf(self, self.vlan_100, bd1, rd1, anon=True)
- ext_itf.add_vpp_config()
- ext_itf = VppGbpExtItf(self, self.vlan_101, bd1, rd1, anon=True)
- ext_itf.add_vpp_config()
-
- #
- # an unicast vxlan-gbp for inter-RD traffic
- #
- vx_tun_l3 = VppGbpVxlanTunnel(
- self, 444, rd1.rd_id,
- VppEnum.vl_api_gbp_vxlan_tunnel_mode_t.GBP_VXLAN_TUNNEL_MODE_L3,
- self.pg2.local_ip4)
- vx_tun_l3.add_vpp_config()
-
- #
- # A remote external endpoint
- #
- rep = VppGbpEndpoint(self, vx_tun_l3,
- epg_220, None,
- "10.0.0.201", "11.0.0.201",
- "2001:10::201", "3001::101",
- ep_flags.GBP_API_ENDPOINT_FLAG_REMOTE,
- self.pg7.local_ip4,
- self.pg7.remote_ip4,
- mac=None)
- rep.add_vpp_config()
-
- #
- # ARP packet from host in external subnet are accepted, flooded and
- # replied to. We expect 2 packets:
- # - APR request flooded over the other vlan subif
- # - ARP reply from BVI
- #
- p_arp = (Ether(src=self.vlan_100.remote_mac,
- dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=100) /
- ARP(op="who-has",
- psrc="10.0.0.100",
- pdst="10.0.0.128",
- hwsrc=self.vlan_100.remote_mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
-
- p_arp = (Ether(src=self.vlan_101.remote_mac,
- dst="ff:ff:ff:ff:ff:ff") /
- Dot1Q(vlan=101) /
- ARP(op="who-has",
- psrc='10.0.0.101',
- pdst="10.0.0.128",
- hwsrc=self.vlan_101.remote_mac,
- hwdst="ff:ff:ff:ff:ff:ff"))
- rxs = self.send_and_expect(self.pg0, p_arp * 1, self.pg0, n_rx=2)
-
- #
- # remote to external
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=vx_tun_l3.vni, gpid=epg_220.sclass, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src=str(rep.ip4), dst="10.0.0.100") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # local EP pings router
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.100", dst="10.0.0.128") /
- ICMP(type='echo-request'))
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_100.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 100)
-
- #
- # local EP pings other local EP
- #
- p = (Ether(src=self.vlan_100.remote_mac,
- dst=self.vlan_101.remote_mac) /
- Dot1Q(vlan=100) /
- IP(src="10.0.0.100", dst="10.0.0.101") /
- ICMP(type='echo-request'))
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.vlan_100.remote_mac)
- self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- #
- # A subnet reachable through an external router on vlan 100
- #
- ip_220 = VppIpRoute(self, "10.220.0.0", 24,
- [VppRoutePath("10.0.0.100",
- epg_220.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_220.add_vpp_config()
-
- l3o_220 = VppGbpSubnet(
- self, rd1, "10.220.0.0", 24,
- # note: this a "regular" L3 out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4220)
- l3o_220.add_vpp_config()
-
- #
- # A subnet reachable through an external router on vlan 101
- #
- ip_221 = VppIpRoute(self, "10.221.0.0", 24,
- [VppRoutePath("10.0.0.101",
- epg_220.bvi.sw_if_index)],
- table_id=t4.table_id)
- ip_221.add_vpp_config()
-
- l3o_221 = VppGbpSubnet(
- self, rd1, "10.221.0.0", 24,
- # note: this a "regular" L3 out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4221)
- l3o_221.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- # dropped without a contract
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- ICMP(type='echo-request'))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # contract for the external nets to communicate
- #
- acl = VppGbpAcl(self)
- rule4 = acl.create_rule(permit_deny=1, proto=17)
- rule6 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17)
- acl_index = acl.add_vpp_config([rule4, rule6])
-
- c1 = VppGbpContract(
- self, 55, 4220, 4221, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c1.add_vpp_config()
-
- #
- # Contracts allowing ext-net 200 to talk with external EPs
- #
- c2 = VppGbpContract(
- self, 55, 4220, 113, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c2.add_vpp_config()
- c3 = VppGbpContract(
- self, 55, 113, 4220, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c3.add_vpp_config()
-
- #
- # ping between hosts in remote subnets
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.221.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg0)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, str(self.router_mac))
- self.assertEqual(rx[Ether].dst, self.vlan_101.remote_mac)
- self.assertEqual(rx[Dot1Q].vlan, 101)
-
- # we did not learn these external hosts
- self.assertFalse(find_gbp_endpoint(self, ip="10.220.0.1"))
- self.assertFalse(find_gbp_endpoint(self, ip="10.221.0.1"))
-
- #
- # from remote external EP to local external EP
- #
- p = (Ether(src=self.pg7.remote_mac,
- dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4,
- dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=444, gpid=113, flags=0x88) /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src=rep.ip4.address, dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 1, self.pg0)
-
- #
- # ping from an external host to the remote external EP
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst=rep.ip4.address) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 1, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- # self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 444)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, rep.ip4.address)
-
- #
- # An external subnet reachable via the remote external EP
- #
-
- #
- # first the VXLAN-GBP tunnel over which it is reached
- #
- vx_tun_r = VppVxlanGbpTunnel(
- self, self.pg7.local_ip4,
- self.pg7.remote_ip4, 445,
- mode=(VppEnum.vl_api_vxlan_gbp_api_tunnel_mode_t.
- VXLAN_GBP_API_TUNNEL_MODE_L3))
- vx_tun_r.add_vpp_config()
- VppIpInterfaceBind(self, vx_tun_r, t4).add_vpp_config()
-
- self.logger.info(self.vapi.cli("sh vxlan-gbp tunnel"))
-
- #
- # then the special adj to resolve through on that tunnel
- #
- n1 = VppNeighbor(self,
- vx_tun_r.sw_if_index,
- "00:0c:0c:0c:0c:0c",
- self.pg7.remote_ip4)
- n1.add_vpp_config()
-
- #
- # the route via the adj above
- #
- ip_222 = VppIpRoute(self, "10.222.0.0", 24,
- [VppRoutePath(self.pg7.remote_ip4,
- vx_tun_r.sw_if_index)],
- table_id=t4.table_id)
- ip_222.add_vpp_config()
-
- l3o_222 = VppGbpSubnet(
- self, rd1, "10.222.0.0", 24,
- # note: this a "regular" l3out subnet (not connected)
- VppEnum.vl_api_gbp_subnet_type_t.GBP_API_SUBNET_L3_OUT,
- sclass=4222)
- l3o_222.add_vpp_config()
-
- #
- # ping between hosts in local and remote external subnets
- # dropped without a contract
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add contracts ext-nets for 220 -> 222
- #
- c4 = VppGbpContract(
- self, 55, 4220, 4222, acl_index,
- [VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- []),
- VppGbpContractRule(
- VppEnum.vl_api_gbp_rule_action_t.GBP_API_RULE_PERMIT,
- VppEnum.vl_api_gbp_hash_mode_t.GBP_API_HASH_MODE_SRC_IP,
- [])],
- [ETH_P_IP, ETH_P_IPV6])
- c4.add_vpp_config()
-
- #
- # ping from host in local to remote external subnets
- #
- p = (Ether(src=self.vlan_100.remote_mac, dst=str(self.router_mac)) /
- Dot1Q(vlan=100) /
- IP(src="10.220.0.1", dst="10.222.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg0, p * 3, self.pg7)
-
- for rx in rxs:
- self.assertEqual(rx[Ether].src, self.pg7.local_mac)
- self.assertEqual(rx[Ether].dst, self.pg7.remote_mac)
- self.assertEqual(rx[IP].src, self.pg7.local_ip4)
- self.assertEqual(rx[IP].dst, self.pg7.remote_ip4)
- self.assertEqual(rx[VXLAN].vni, 445)
- self.assertTrue(rx[VXLAN].flags.G)
- self.assertTrue(rx[VXLAN].flags.Instance)
- # the sclass of the ext-net the packet came from
- self.assertEqual(rx[VXLAN].gpid, 4220)
- # policy was applied to the original IP packet
- self.assertTrue(rx[VXLAN].gpflags.A)
- # since it's an external host the reciever should not learn it
- self.assertTrue(rx[VXLAN].gpflags.D)
- inner = rx[VXLAN].payload
- self.assertEqual(inner[Ether].dst, "00:0c:0c:0c:0c:0c")
- self.assertEqual(inner[IP].src, "10.220.0.1")
- self.assertEqual(inner[IP].dst, "10.222.0.1")
-
- #
- # ping from host in remote to local external subnets
- # there's no contract for this, but the A bit is set.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.220.0.1") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_expect(self.pg7, p * 3, self.pg0)
- self.assertFalse(find_gbp_endpoint(self, ip="10.222.0.1"))
-
- #
- # ping from host in remote to remote external subnets
- # this is dropped by reflection check.
- #
- p = (Ether(src=self.pg7.remote_mac, dst=self.pg7.local_mac) /
- IP(src=self.pg7.remote_ip4, dst=self.pg7.local_ip4) /
- UDP(sport=1234, dport=48879) /
- VXLAN(vni=445, gpid=4222, flags=0x88, gpflags='A') /
- Ether(src=self.pg0.remote_mac, dst=str(self.router_mac)) /
- IP(src="10.222.0.1", dst="10.222.0.2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
-
- rxs = self.send_and_assert_no_replies(self.pg7, p * 3)
-
- #
- # cleanup
- #
- self.vlan_101.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.vlan_100.set_vtr(L2_VTR_OP.L2_DISABLED)
- self.pg7.unconfig_ip4()
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_gtpu.py b/test/test_gtpu.py
deleted file mode 100644
index 957181a71e4..00000000000
--- a/test/test_gtpu.py
+++ /dev/null
@@ -1,393 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-from util import ip4n_range, ip4_range
-import unittest
-from framework import VppTestCase, VppTestRunner
-from template_bd import BridgeDomain
-
-from scapy.layers.l2 import Ether, Raw
-from scapy.layers.inet import IP, UDP
-from scapy.layers.inet6 import IPv6
-from scapy.contrib.gtp import GTP_U_Header
-from scapy.utils import atol
-from vpp_ip_route import VppIpRoute, VppRoutePath
-from vpp_ip import INVALID_INDEX
-
-
-class TestGtpuUDP(VppTestCase):
- """ GTPU UDP ports Test Case """
-
- def setUp(self):
- super(TestGtpuUDP, self).setUp()
-
- self.dport = 2152
-
- self.ip4_err = 0
- self.ip6_err = 0
-
- self.create_pg_interfaces(range(1))
- for pg in self.pg_interfaces:
- pg.admin_up()
- self.pg0.config_ip4()
- self.pg0.config_ip6()
-
- def _check_udp_port_ip4(self, enabled=True):
-
- pkt = (Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
- UDP(sport=self.dport, dport=self.dport, chksum=0))
-
- self.pg0.add_stream(pkt)
- self.pg_start()
-
- err = self.statistics.get_counter(
- '/err/ip4-udp-lookup/no listener for dst port')[0]
-
- if enabled:
- self.assertEqual(err, self.ip4_err)
- else:
- self.assertEqual(err, self.ip4_err + 1)
-
- self.ip4_err = err
-
- def _check_udp_port_ip6(self, enabled=True):
-
- pkt = (Ether(src=self.pg0.local_mac, dst=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg0.local_ip6) /
- UDP(sport=self.dport, dport=self.dport, chksum=0))
-
- self.pg0.add_stream(pkt)
- self.pg_start()
-
- err = self.statistics.get_counter(
- '/err/ip6-udp-lookup/no listener for dst port')[0]
-
- if enabled:
- self.assertEqual(err, self.ip6_err)
- else:
- self.assertEqual(err, self.ip6_err + 1)
-
- self.ip6_err = err
-
- def test_udp_port(self):
- """ test UDP ports
- Check if there are no udp listeners before gtpu is enabled
- """
-
- # UDP ports should be disabled unless a tunnel is configured
- self._check_udp_port_ip4(False)
- self._check_udp_port_ip6(False)
-
- r = self.vapi.gtpu_add_del_tunnel(src_addr=self.pg0.local_ip4n,
- dst_addr=self.pg0.remote_ip4n)
-
- # UDP port 2152 enabled for ip4
- self._check_udp_port_ip4()
-
- r = self.vapi.gtpu_add_del_tunnel(is_ipv6=1,
- src_addr=self.pg0.local_ip6n,
- dst_addr=self.pg0.remote_ip6n)
-
- # UDP port 2152 enabled for ip6
- self._check_udp_port_ip6()
-
- r = self.vapi.gtpu_add_del_tunnel(is_add=0,
- src_addr=self.pg0.local_ip4n,
- dst_addr=self.pg0.remote_ip4n)
-
- r = self.vapi.gtpu_add_del_tunnel(is_add=0, is_ipv6=1,
- src_addr=self.pg0.local_ip6n,
- dst_addr=self.pg0.remote_ip6n)
-
-
-class TestGtpu(BridgeDomain, VppTestCase):
- """ GTPU 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 GTPU 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) /
- GTP_U_Header(teid=vni, gtp_type=self.gtp_type, length=150) /
- 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 GTPU 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) /
- GTP_U_Header(teid=vni, gtp_type=self.gtp_type, length=150) /
- pkt)
-
- def decapsulate(self, pkt):
- """
- Decapsulate the original payload frame by removing GTPU header
- """
- return pkt[GTP_U_Header].payload
-
- # Method for checking GTPU 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 GTPU 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 GTPU 2152, source UDP port could be
- # arbitrary.
- self.assertEqual(pkt[UDP].dport, type(self).dport)
- # Verify teid
- self.assertEqual(pkt[GTP_U_Header].teid, vni)
-
- 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_bd)
-
- # 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_mcast_flood(self):
- """ Multicast flood test
- Send frames from pg2
- Verify receipt of encapsulated frames on pg0
- """
- self.pg2.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.mcast_flood_bd,
- local_only=False, mcast_pkt=True)
-
- # payload = self.decapsulate(pkt)
- # self.assert_eq_pkts(payload, self.frame_reply)
-
- @classmethod
- def create_gtpu_flood_test_bd(cls, teid, n_ucast_tunnels):
- # Create 10 ucast gtpu 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()
- dest_ip4n = socket.inet_pton(socket.AF_INET, dest_ip4)
- r = cls.vapi.gtpu_add_del_tunnel(
- src_addr=cls.pg0.local_ip4n,
- dst_addr=dest_ip4n,
- teid=teid)
- cls.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index,
- bd_id=teid)
-
- @classmethod
- def add_del_shared_mcast_dst_load(cls, is_add):
- """
- add or del tunnels sharing the same mcast dst
- to test gtpu ref_count mechanism
- """
- n_shared_dst_tunnels = 20
- teid_start = 1000
- teid_end = teid_start + n_shared_dst_tunnels
- for teid in range(teid_start, teid_end):
- r = cls.vapi.gtpu_add_del_tunnel(
- src_addr=cls.pg0.local_ip4n,
- dst_addr=cls.mcast_ip4n,
- mcast_sw_if_index=1,
- teid=teid,
- 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 gtpu stability
- """
- n_distinct_dst_tunnels = 20
- ip_range_start = 10
- ip_range_end = ip_range_start + n_distinct_dst_tunnels
- for dest_ip4n in ip4n_range(cls.mcast_ip4n, ip_range_start,
- ip_range_end):
- teid = bytearray(dest_ip4n)[3]
- cls.vapi.gtpu_add_del_tunnel(
- src_addr=cls.pg0.local_ip4n,
- dst_addr=dest_ip4n,
- mcast_sw_if_index=1,
- teid=teid,
- 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 GTPU 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(TestGtpu, cls).setUpClass()
-
- try:
- cls.dport = 2152
- cls.gtp_type = 0xff
-
- # 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_ip4n = socket.inet_pton(socket.AF_INET, cls.mcast_ip4)
- iplong = atol(cls.mcast_ip4)
- cls.mcast_mac = "01:00:5e:%02x:%02x:%02x" % (
- (iplong >> 16) & 0x7F, (iplong >> 8) & 0xFF, iplong & 0xFF)
-
- # Create GTPU VTEP on VPP pg0, and put gtpu_tunnel0 and pg1
- # into BD.
- cls.single_tunnel_bd = 11
- r = cls.vapi.gtpu_add_del_tunnel(
- src_addr=cls.pg0.local_ip4n,
- dst_addr=cls.pg0.remote_ip4n,
- teid=cls.single_tunnel_bd)
- 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 teid 2 to test multicast flooding
- cls.n_ucast_tunnels = 10
- cls.mcast_flood_bd = 12
- cls.create_gtpu_flood_test_bd(cls.mcast_flood_bd,
- cls.n_ucast_tunnels)
- r = cls.vapi.gtpu_add_del_tunnel(
- src_addr=cls.pg0.local_ip4n,
- dst_addr=cls.mcast_ip4n,
- mcast_sw_if_index=1,
- teid=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 teid 3 to test unicast flooding
- cls.ucast_flood_bd = 13
- cls.create_gtpu_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(TestGtpu, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestGtpu, cls).tearDownClass()
-
- # 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(TestGtpu, 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 gtpu tunnel"))
- self.logger.info(self.vapi.cli("show trace"))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_igmp.py b/test/test_igmp.py
deleted file mode 100644
index f1c49acba4c..00000000000
--- a/test/test_igmp.py
+++ /dev/null
@@ -1,834 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-
-from scapy.layers.l2 import Ether, Raw
-from scapy.layers.inet import IP, IPOption
-from scapy.contrib.igmpv3 import IGMPv3, IGMPv3gr, IGMPv3mq, IGMPv3mr
-
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-from vpp_igmp import find_igmp_state, IGMP_FILTER, IgmpRecord, IGMP_MODE, \
- IgmpSG, VppHostState, wait_for_igmp_event
-from vpp_ip_route import find_mroute, VppIpTable
-
-
-class IgmpMode:
- HOST = 1
- ROUTER = 0
-
-
-class TestIgmp(VppTestCase):
- """ IGMP Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestIgmp, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestIgmp, cls).tearDownClass()
-
- def setUp(self):
- super(TestIgmp, self).setUp()
-
- self.create_pg_interfaces(range(4))
- self.sg_list = []
- self.config_list = []
-
- self.ip_addr = []
- self.ip_table = VppIpTable(self, 1)
- self.ip_table.add_vpp_config()
-
- for pg in self.pg_interfaces[2:]:
- pg.set_table_ip4(1)
- for pg in self.pg_interfaces:
- pg.admin_up()
- pg.config_ip4()
- pg.resolve_arp()
-
- def tearDown(self):
- for pg in self.pg_interfaces:
- self.vapi.igmp_clear_interface(pg.sw_if_index)
- pg.unconfig_ip4()
- pg.set_table_ip4(0)
- pg.admin_down()
- super(TestIgmp, self).tearDown()
-
- def send(self, ti, pkts):
- ti.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- def test_igmp_flush(self):
- """ IGMP Link Up/down and Flush """
-
- #
- # FIX THIS. Link down.
- #
-
- def test_igmp_enable(self):
- """ IGMP enable/disable on an interface
-
- check for the addition/removal of the IGMP mroutes """
-
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 1, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg1.sw_if_index, 1, IGMP_MODE.HOST)
-
- self.assertTrue(find_mroute(self, "224.0.0.1", "0.0.0.0", 32))
- self.assertTrue(find_mroute(self, "224.0.0.22", "0.0.0.0", 32))
-
- self.vapi.igmp_enable_disable(self.pg2.sw_if_index, 1, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg3.sw_if_index, 1, IGMP_MODE.HOST)
-
- self.assertTrue(find_mroute(self, "224.0.0.1", "0.0.0.0", 32,
- table_id=1))
- self.assertTrue(find_mroute(self, "224.0.0.22", "0.0.0.0", 32,
- table_id=1))
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 0, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg1.sw_if_index, 0, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg2.sw_if_index, 0, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg3.sw_if_index, 0, IGMP_MODE.HOST)
-
- self.assertFalse(find_mroute(self, "224.0.0.1", "0.0.0.0", 32))
- self.assertFalse(find_mroute(self, "224.0.0.22", "0.0.0.0", 32))
- self.assertFalse(find_mroute(self, "224.0.0.1", "0.0.0.0", 32,
- table_id=1))
- self.assertFalse(find_mroute(self, "224.0.0.22", "0.0.0.0", 32,
- table_id=1))
-
- def verify_general_query(self, p):
- ip = p[IP]
- self.assertEqual(len(ip.options), 1)
- self.assertEqual(ip.options[0].option, 20)
- self.assertEqual(ip.dst, "224.0.0.1")
- self.assertEqual(ip.proto, 2)
- igmp = p[IGMPv3]
- self.assertEqual(igmp.type, 0x11)
- self.assertEqual(igmp.gaddr, "0.0.0.0")
-
- def verify_group_query(self, p, grp, srcs):
- ip = p[IP]
- self.assertEqual(ip.dst, grp)
- self.assertEqual(ip.proto, 2)
- self.assertEqual(len(ip.options), 1)
- self.assertEqual(ip.options[0].option, 20)
- self.assertEqual(ip.proto, 2)
- igmp = p[IGMPv3]
- self.assertEqual(igmp.type, 0x11)
- self.assertEqual(igmp.gaddr, grp)
-
- def verify_report(self, rx, records):
- ip = rx[IP]
- self.assertEqual(rx[IP].dst, "224.0.0.22")
- self.assertEqual(len(ip.options), 1)
- self.assertEqual(ip.options[0].option, 20)
- self.assertEqual(ip.proto, 2)
- self.assertEqual(IGMPv3.igmpv3types[rx[IGMPv3].type],
- "Version 3 Membership Report")
- self.assertEqual(rx[IGMPv3mr].numgrp, len(records))
-
- received = rx[IGMPv3mr].records
-
- for ii in range(len(records)):
- gr = received[ii]
- r = records[ii]
- self.assertEqual(IGMPv3gr.igmpv3grtypes[gr.rtype], r.type)
- self.assertEqual(gr.numsrc, len(r.sg.saddrs))
- self.assertEqual(gr.maddr, r.sg.gaddr)
- self.assertEqual(len(gr.srcaddrs), len(r.sg.saddrs))
-
- self.assertEqual(sorted(gr.srcaddrs),
- sorted(r.sg.saddrs))
-
- def add_group(self, itf, sg, n_pkts=2):
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- hs = VppHostState(self,
- IGMP_FILTER.INCLUDE,
- itf.sw_if_index,
- sg)
- hs.add_vpp_config()
-
- capture = itf.get_capture(n_pkts, timeout=10)
-
- # reports are transmitted twice due to default rebostness value=2
- self.verify_report(capture[0],
- [IgmpRecord(sg, "Allow New Sources")]),
- self.verify_report(capture[1],
- [IgmpRecord(sg, "Allow New Sources")]),
-
- return hs
-
- def remove_group(self, hs):
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- hs.remove_vpp_config()
-
- capture = self.pg0.get_capture(1, timeout=10)
-
- self.verify_report(capture[0],
- [IgmpRecord(hs.sg, "Block Old Sources")])
-
- def test_igmp_host(self):
- """ IGMP Host functions """
-
- #
- # Enable interface for host functions
- #
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index,
- 1,
- IGMP_MODE.HOST)
-
- #
- # Add one S,G of state and expect a state-change event report
- # indicating the addition of the S,G
- #
- h1 = self.add_group(self.pg0, IgmpSG("239.1.1.1", ["1.1.1.1"]))
-
- # search for the corresponding state created in VPP
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 1)
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", "1.1.1.1"))
-
- #
- # Send a general query (to the all router's address)
- # expect VPP to respond with a membership report.
- # Pad the query with 0 - some devices in the big wild
- # internet are prone to this.
- #
- p_g = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='224.0.0.1', tos=0xc0) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="0.0.0.0") /
- Raw('\x00' * 10))
-
- self.send(self.pg0, p_g)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- #
- # Group specific query
- #
- p_gs = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1"))
-
- self.send(self.pg0, p_gs)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- #
- # A group and source specific query, with the source matching
- # the source VPP has
- #
- p_gs1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1", srcaddrs=["1.1.1.1"]))
-
- self.send(self.pg0, p_gs1)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- #
- # A group and source specific query that reports more sources
- # than the packet actually has.
- #
- p_gs2 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1", numsrc=4, srcaddrs=["1.1.1.1"]))
-
- self.send_and_assert_no_replies(self.pg0, p_gs2, timeout=10)
-
- #
- # A group and source specific query, with the source NOT matching
- # the source VPP has. There should be no response.
- #
- p_gs2 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1", srcaddrs=["1.1.1.2"]))
-
- self.send_and_assert_no_replies(self.pg0, p_gs2, timeout=10)
-
- #
- # A group and source specific query, with the multiple sources
- # one of which matches the source VPP has.
- # The report should contain only the source VPP has.
- #
- p_gs3 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1",
- srcaddrs=["1.1.1.1", "1.1.1.2", "1.1.1.3"]))
-
- self.send(self.pg0, p_gs3)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- #
- # Two source and group specific queries in quick succession, the
- # first does not have VPPs source the second does. then vice-versa
- #
- self.send(self.pg0, [p_gs2, p_gs1])
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- self.send(self.pg0, [p_gs1, p_gs2])
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h1.sg, "Mode Is Include")])
-
- #
- # remove state, expect the report for the removal
- #
- self.remove_group(h1)
-
- dump = self.vapi.igmp_dump()
- self.assertFalse(dump)
-
- #
- # A group with multiple sources
- #
- h2 = self.add_group(self.pg0,
- IgmpSG("239.1.1.1",
- ["1.1.1.1", "1.1.1.2", "1.1.1.3"]))
-
- # search for the corresponding state created in VPP
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 3)
- for s in h2.sg.saddrs:
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", s))
- #
- # Send a general query (to the all router's address)
- # expect VPP to respond with a membership report will all sources
- #
- self.send(self.pg0, p_g)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(h2.sg, "Mode Is Include")])
-
- #
- # Group and source specific query; some present some not
- #
- p_gs = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Membership Query", mrcode=100) /
- IGMPv3mq(gaddr="239.1.1.1",
- srcaddrs=["1.1.1.1", "1.1.1.2", "1.1.1.4"]))
-
- self.send(self.pg0, p_gs)
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(
- IgmpSG('239.1.1.1', ["1.1.1.1", "1.1.1.2"]),
- "Mode Is Include")])
-
- #
- # add loads more groups
- #
- h3 = self.add_group(self.pg0,
- IgmpSG("239.1.1.2",
- ["2.1.1.1", "2.1.1.2", "2.1.1.3"]))
- h4 = self.add_group(self.pg0,
- IgmpSG("239.1.1.3",
- ["3.1.1.1", "3.1.1.2", "3.1.1.3"]))
- h5 = self.add_group(self.pg0,
- IgmpSG("239.1.1.4",
- ["4.1.1.1", "4.1.1.2", "4.1.1.3"]))
- h6 = self.add_group(self.pg0,
- IgmpSG("239.1.1.5",
- ["5.1.1.1", "5.1.1.2", "5.1.1.3"]))
- h7 = self.add_group(self.pg0,
- IgmpSG("239.1.1.6",
- ["6.1.1.1", "6.1.1.2",
- "6.1.1.3", "6.1.1.4",
- "6.1.1.5", "6.1.1.6",
- "6.1.1.7", "6.1.1.8",
- "6.1.1.9", "6.1.1.10",
- "6.1.1.11", "6.1.1.12",
- "6.1.1.13", "6.1.1.14",
- "6.1.1.15", "6.1.1.16"]))
-
- #
- # general query.
- # the order the groups come in is not important, so what is
- # checked for is what VPP is sending today.
- #
- self.send(self.pg0, p_g)
-
- capture = self.pg0.get_capture(1, timeout=10)
-
- self.verify_report(capture[0],
- [IgmpRecord(h3.sg, "Mode Is Include"),
- IgmpRecord(h2.sg, "Mode Is Include"),
- IgmpRecord(h6.sg, "Mode Is Include"),
- IgmpRecord(h4.sg, "Mode Is Include"),
- IgmpRecord(h5.sg, "Mode Is Include"),
- IgmpRecord(h7.sg, "Mode Is Include")])
-
- #
- # modify a group to add and remove some sources
- #
- h7.sg = IgmpSG("239.1.1.6",
- ["6.1.1.1", "6.1.1.2",
- "6.1.1.5", "6.1.1.6",
- "6.1.1.7", "6.1.1.8",
- "6.1.1.9", "6.1.1.10",
- "6.1.1.11", "6.1.1.12",
- "6.1.1.13", "6.1.1.14",
- "6.1.1.15", "6.1.1.16",
- "6.1.1.17", "6.1.1.18"])
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- h7.add_vpp_config()
-
- capture = self.pg0.get_capture(1, timeout=10)
- self.verify_report(capture[0],
- [IgmpRecord(IgmpSG("239.1.1.6",
- ["6.1.1.17", "6.1.1.18"]),
- "Allow New Sources"),
- IgmpRecord(IgmpSG("239.1.1.6",
- ["6.1.1.3", "6.1.1.4"]),
- "Block Old Sources")])
-
- #
- # add an additional groups with many sources so that each group
- # consumes the link MTU. We should therefore see multiple state
- # state reports when queried.
- #
- self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [560, 0, 0, 0])
-
- src_list = []
- for i in range(128):
- src_list.append("10.1.1.%d" % i)
-
- h8 = self.add_group(self.pg0,
- IgmpSG("238.1.1.1", src_list))
- h9 = self.add_group(self.pg0,
- IgmpSG("238.1.1.2", src_list))
-
- self.send(self.pg0, p_g)
-
- capture = self.pg0.get_capture(4, timeout=10)
-
- self.verify_report(capture[0],
- [IgmpRecord(h3.sg, "Mode Is Include"),
- IgmpRecord(h2.sg, "Mode Is Include"),
- IgmpRecord(h6.sg, "Mode Is Include"),
- IgmpRecord(h4.sg, "Mode Is Include"),
- IgmpRecord(h5.sg, "Mode Is Include")])
- self.verify_report(capture[1],
- [IgmpRecord(h8.sg, "Mode Is Include")])
- self.verify_report(capture[2],
- [IgmpRecord(h7.sg, "Mode Is Include")])
- self.verify_report(capture[3],
- [IgmpRecord(h9.sg, "Mode Is Include")])
-
- #
- # drop the MTU further (so a 128 sized group won't fit)
- #
- self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [512, 0, 0, 0])
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- h10 = VppHostState(self,
- IGMP_FILTER.INCLUDE,
- self.pg0.sw_if_index,
- IgmpSG("238.1.1.3", src_list))
- h10.add_vpp_config()
-
- capture = self.pg0.get_capture(2, timeout=10)
- # wait for a little bit
- self.sleep(1)
-
- #
- # remove state, expect the report for the removal
- # the dump should be empty
- #
- self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [600, 0, 0, 0])
- self.remove_group(h8)
- self.remove_group(h9)
- self.remove_group(h2)
- self.remove_group(h3)
- self.remove_group(h4)
- self.remove_group(h5)
- self.remove_group(h6)
- self.remove_group(h7)
- self.remove_group(h10)
-
- self.logger.info(self.vapi.cli("sh igmp config"))
- self.assertFalse(self.vapi.igmp_dump())
-
- #
- # TODO
- # ADD STATE ON MORE INTERFACES
- #
-
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index,
- 0,
- IGMP_MODE.HOST)
-
- def test_igmp_router(self):
- """ IGMP Router Functions """
-
- #
- # Drop reports when not enabled
- #
- p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Allow New Sources",
- maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"]))
- p_l = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Block Old Sources",
- maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"]))
-
- self.send(self.pg0, p_j)
- self.assertFalse(self.vapi.igmp_dump())
-
- #
- # drop the default timer values so these tests execute in a
- # reasonable time frame
- #
- self.vapi.cli("test igmp timers query 1 src 3 leave 1")
-
- #
- # enable router functions on the interface
- #
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index,
- 1,
- IGMP_MODE.ROUTER)
- self.vapi.want_igmp_events(1)
-
- #
- # wait for router to send general query
- #
- for ii in range(3):
- capture = self.pg0.get_capture(1, timeout=2)
- self.verify_general_query(capture[0])
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- #
- # re-send the report. VPP should now hold state for the new group
- # VPP sends a notification that a new group has been joined
- #
- self.send(self.pg0, p_j)
-
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.1", 1))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 1))
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 2)
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", "10.1.1.1"))
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", "10.1.1.2"))
-
- #
- # wait for the per-source timer to expire
- # the state should be reaped
- # VPP sends a notification that the group has been left
- #
- self.assertTrue(wait_for_igmp_event(self, 4, self.pg0,
- "239.1.1.1", "10.1.1.1", 0))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 0))
- self.assertFalse(self.vapi.igmp_dump())
-
- #
- # resend the join. wait for two queries and then send a current-state
- # record to include all sources. this should reset the expiry time
- # on the sources and thus they will still be present in 2 seconds time.
- # If the source timer was not refreshed, then the state would have
- # expired in 3 seconds.
- #
- self.send(self.pg0, p_j)
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.1", 1))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 1))
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 2)
-
- capture = self.pg0.get_capture(2, timeout=3)
- self.verify_general_query(capture[0])
- self.verify_general_query(capture[1])
-
- p_cs = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Mode Is Include",
- maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"]))
-
- self.send(self.pg0, p_cs)
-
- self.sleep(2)
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 2)
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", "10.1.1.1"))
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.1", "10.1.1.2"))
-
- #
- # wait for the per-source timer to expire
- # the state should be reaped
- #
- self.assertTrue(wait_for_igmp_event(self, 4, self.pg0,
- "239.1.1.1", "10.1.1.1", 0))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 0))
- self.assertFalse(self.vapi.igmp_dump())
-
- #
- # resend the join, then a leave. Router sends a group+source
- # specific query containing both sources
- #
- self.send(self.pg0, p_j)
-
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.1", 1))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 1))
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertEqual(len(dump), 2)
-
- self.send(self.pg0, p_l)
- capture = self.pg0.get_capture(1, timeout=3)
- self.verify_group_query(capture[0], "239.1.1.1",
- ["10.1.1.1", "10.1.1.2"])
-
- #
- # the group specific query drops the timeout to leave (=1) seconds
- #
- self.assertTrue(wait_for_igmp_event(self, 2, self.pg0,
- "239.1.1.1", "10.1.1.1", 0))
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.1", "10.1.1.2", 0))
- self.assertFalse(self.vapi.igmp_dump())
- self.assertFalse(self.vapi.igmp_dump())
-
- #
- # a TO_EX({}) / IN_EX({}) is treated like a (*,G) join
- #
- p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Change To Exclude Mode", maddr="239.1.1.2"))
-
- self.send(self.pg0, p_j)
-
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.2", "0.0.0.0", 1))
-
- p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Mode Is Exclude", maddr="239.1.1.3"))
-
- self.send(self.pg0, p_j)
-
- self.assertTrue(wait_for_igmp_event(self, 1, self.pg0,
- "239.1.1.3", "0.0.0.0", 1))
-
- #
- # A 'allow sources' for {} should be ignored as it should
- # never be sent.
- #
- p_j = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Allow New Sources", maddr="239.1.1.4"))
-
- self.send(self.pg0, p_j)
-
- dump = self.vapi.igmp_dump(self.pg0.sw_if_index)
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.2", "0.0.0.0"))
- self.assertTrue(find_igmp_state(dump, self.pg0,
- "239.1.1.3", "0.0.0.0"))
- self.assertFalse(find_igmp_state(dump, self.pg0,
- "239.1.1.4", "0.0.0.0"))
-
- #
- # a TO_IN({}) and IS_IN({}) are treated like a (*,G) leave
- #
- self.vapi.cli("set logging class igmp level debug")
- p_l = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Change To Include Mode", maddr="239.1.1.2"))
-
- self.send(self.pg0, p_l)
- self.assertTrue(wait_for_igmp_event(self, 2, self.pg0,
- "239.1.1.2", "0.0.0.0", 0))
-
- p_l = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype="Mode Is Include", maddr="239.1.1.3"))
-
- self.send(self.pg0, p_l)
-
- self.assertTrue(wait_for_igmp_event(self, 2, self.pg0,
- "239.1.1.3", "0.0.0.0", 0))
- self.assertFalse(self.vapi.igmp_dump(self.pg0.sw_if_index))
-
- #
- # disable router config
- #
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index,
- 0,
- IGMP_MODE.ROUTER)
-
- def _create_igmpv3_pck(self, itf, rtype, maddr, srcaddrs):
- p = (Ether(dst=itf.local_mac, src=itf.remote_mac) /
- IP(src=itf.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1,
- options=[IPOption(copy_flag=1, optclass="control",
- option="router_alert")]) /
- IGMPv3(type="Version 3 Membership Report") /
- IGMPv3mr(numgrp=1) /
- IGMPv3gr(rtype=rtype,
- maddr=maddr, srcaddrs=srcaddrs))
- return p
-
- def test_igmp_proxy_device(self):
- """ IGMP proxy device """
- self.pg2.admin_down()
- self.pg2.unconfig_ip4()
- self.pg2.set_table_ip4(0)
- self.pg2.config_ip4()
- self.pg2.admin_up()
-
- self.vapi.cli('test igmp timers query 10 src 3 leave 1')
-
- # enable IGMP
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 1, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg1.sw_if_index, 1,
- IGMP_MODE.ROUTER)
- self.vapi.igmp_enable_disable(self.pg2.sw_if_index, 1,
- IGMP_MODE.ROUTER)
-
- # create IGMP proxy device
- self.vapi.igmp_proxy_device_add_del(0, self.pg0.sw_if_index, 1)
- self.vapi.igmp_proxy_device_add_del_interface(0,
- self.pg1.sw_if_index, 1)
- self.vapi.igmp_proxy_device_add_del_interface(0,
- self.pg2.sw_if_index, 1)
-
- # send join on pg1. join should be proxied by pg0
- p_j = self._create_igmpv3_pck(self.pg1, "Allow New Sources",
- "239.1.1.1", ["10.1.1.1", "10.1.1.2"])
- self.send(self.pg1, p_j)
-
- capture = self.pg0.get_capture(1, timeout=1)
- self.verify_report(capture[0], [IgmpRecord(IgmpSG("239.1.1.1",
- ["10.1.1.1", "10.1.1.2"]), "Allow New Sources")])
- self.assertTrue(find_mroute(self, "239.1.1.1", "0.0.0.0", 32))
-
- # send join on pg2. join should be proxied by pg0.
- # the group should contain only 10.1.1.3 as
- # 10.1.1.1 was already reported
- p_j = self._create_igmpv3_pck(self.pg2, "Allow New Sources",
- "239.1.1.1", ["10.1.1.1", "10.1.1.3"])
- self.send(self.pg2, p_j)
-
- capture = self.pg0.get_capture(1, timeout=1)
- self.verify_report(capture[0], [IgmpRecord(IgmpSG("239.1.1.1",
- ["10.1.1.3"]), "Allow New Sources")])
- self.assertTrue(find_mroute(self, "239.1.1.1", "0.0.0.0", 32))
-
- # send leave on pg2. leave for 10.1.1.3 should be proxyed
- # as pg2 was the only interface interested in 10.1.1.3
- p_l = self._create_igmpv3_pck(self.pg2, "Block Old Sources",
- "239.1.1.1", ["10.1.1.3"])
- self.send(self.pg2, p_l)
-
- capture = self.pg0.get_capture(1, timeout=2)
- self.verify_report(capture[0], [IgmpRecord(IgmpSG("239.1.1.1",
- ["10.1.1.3"]), "Block Old Sources")])
- self.assertTrue(find_mroute(self, "239.1.1.1", "0.0.0.0", 32))
-
- # disable igmp on pg1 (also removes interface from proxy device)
- # proxy leave for 10.1.1.2. pg2 is still interested in 10.1.1.1
- self.pg_enable_capture(self.pg_interfaces)
- self.vapi.igmp_enable_disable(self.pg1.sw_if_index, 0,
- IGMP_MODE.ROUTER)
-
- capture = self.pg0.get_capture(1, timeout=1)
- self.verify_report(capture[0], [IgmpRecord(IgmpSG("239.1.1.1",
- ["10.1.1.2"]), "Block Old Sources")])
- self.assertTrue(find_mroute(self, "239.1.1.1", "0.0.0.0", 32))
-
- # disable IGMP on pg0 and pg1.
- # disabling IGMP on pg0 (proxy device upstream interface)
- # removes this proxy device
- self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 0, IGMP_MODE.HOST)
- self.vapi.igmp_enable_disable(self.pg2.sw_if_index, 0,
- IGMP_MODE.ROUTER)
- self.assertFalse(find_mroute(self, "239.1.1.1", "0.0.0.0", 32))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_ipsec_nat.py b/test/test_ipsec_nat.py
deleted file mode 100644
index 07670d71b03..00000000000
--- a/test/test_ipsec_nat.py
+++ /dev/null
@@ -1,271 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-
-import scapy.compat
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import ICMP, IP, TCP, UDP
-from scapy.layers.ipsec import SecurityAssociation, ESP
-
-from util import ppp, ppc
-from template_ipsec import TemplateIpsec
-from vpp_ipsec import VppIpsecSA, VppIpsecSpd, VppIpsecSpdEntry,\
- VppIpsecSpdItfBinding
-from vpp_ip_route import VppIpRoute, VppRoutePath
-from vpp_ip import DpoProto
-from vpp_papi import VppEnum
-
-
-class IPSecNATTestCase(TemplateIpsec):
- """ IPSec/NAT
- TUNNEL MODE:
-
-
- public network | private network
- --- encrypt --- plain ---
- |pg0| <------- |VPP| <------ |pg1|
- --- --- ---
-
- --- decrypt --- plain ---
- |pg0| -------> |VPP| ------> |pg1|
- --- --- ---
- """
-
- tcp_port_in = 6303
- tcp_port_out = 6303
- udp_port_in = 6304
- udp_port_out = 6304
- icmp_id_in = 6305
- icmp_id_out = 6305
-
- @classmethod
- def setUpClass(cls):
- super(IPSecNATTestCase, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(IPSecNATTestCase, cls).tearDownClass()
-
- def setUp(self):
- super(IPSecNATTestCase, self).setUp()
- self.tun_if = self.pg0
-
- self.tun_spd = VppIpsecSpd(self, self.tun_spd_id)
- self.tun_spd.add_vpp_config()
- VppIpsecSpdItfBinding(self, self.tun_spd,
- self.tun_if).add_vpp_config()
-
- p = self.ipv4_params
- self.config_esp_tun(p)
- self.logger.info(self.vapi.ppcli("show ipsec all"))
-
- d = DpoProto.DPO_PROTO_IP6 if p.is_ipv6 else DpoProto.DPO_PROTO_IP4
- VppIpRoute(self, p.remote_tun_if_host, p.addr_len,
- [VppRoutePath(self.tun_if.remote_addr[p.addr_type],
- 0xffffffff,
- proto=d)]).add_vpp_config()
-
- def tearDown(self):
- super(IPSecNATTestCase, self).tearDown()
-
- def create_stream_plain(self, src_mac, dst_mac, src_ip, dst_ip):
- return [
- # TCP
- Ether(src=src_mac, dst=dst_mac) /
- IP(src=src_ip, dst=dst_ip) /
- TCP(sport=self.tcp_port_in, dport=20),
- # UDP
- Ether(src=src_mac, dst=dst_mac) /
- IP(src=src_ip, dst=dst_ip) /
- UDP(sport=self.udp_port_in, dport=20),
- # ICMP
- Ether(src=src_mac, dst=dst_mac) /
- IP(src=src_ip, dst=dst_ip) /
- ICMP(id=self.icmp_id_in, type='echo-request')
- ]
-
- def create_stream_encrypted(self, src_mac, dst_mac, src_ip, dst_ip, sa):
- return [
- # TCP
- Ether(src=src_mac, dst=dst_mac) /
- sa.encrypt(IP(src=src_ip, dst=dst_ip) /
- TCP(dport=self.tcp_port_out, sport=20)),
- # UDP
- Ether(src=src_mac, dst=dst_mac) /
- sa.encrypt(IP(src=src_ip, dst=dst_ip) /
- UDP(dport=self.udp_port_out, sport=20)),
- # ICMP
- Ether(src=src_mac, dst=dst_mac) /
- sa.encrypt(IP(src=src_ip, dst=dst_ip) /
- ICMP(id=self.icmp_id_out, type='echo-request'))
- ]
-
- def verify_capture_plain(self, capture):
- for packet in capture:
- try:
- self.assert_packet_checksums_valid(packet)
- self.assert_equal(packet[IP].src, self.tun_if.remote_ip4,
- "decrypted packet source address")
- self.assert_equal(packet[IP].dst, self.pg1.remote_ip4,
- "decrypted packet destination address")
- if packet.haslayer(TCP):
- self.assertFalse(
- packet.haslayer(UDP),
- "unexpected UDP header in decrypted packet")
- self.assert_equal(packet[TCP].dport, self.tcp_port_in,
- "decrypted packet TCP destination port")
- elif packet.haslayer(UDP):
- if packet[UDP].payload:
- self.assertFalse(
- packet[UDP][1].haslayer(UDP),
- "unexpected UDP header in decrypted packet")
- self.assert_equal(packet[UDP].dport, self.udp_port_in,
- "decrypted packet UDP destination port")
- else:
- self.assertFalse(
- packet.haslayer(UDP),
- "unexpected UDP header in decrypted packet")
- self.assert_equal(packet[ICMP].id, self.icmp_id_in,
- "decrypted packet ICMP ID")
- except Exception:
- self.logger.error(
- ppp("Unexpected or invalid plain packet:", packet))
- raise
-
- def verify_capture_encrypted(self, capture, sa):
- for packet in capture:
- try:
- copy = packet.__class__(scapy.compat.raw(packet))
- del copy[UDP].len
- copy = packet.__class__(scapy.compat.raw(copy))
- self.assert_equal(packet[UDP].len, copy[UDP].len,
- "UDP header length")
- self.assert_packet_checksums_valid(packet)
- self.assertIn(ESP, packet[IP])
- decrypt_pkt = sa.decrypt(packet[IP])
- self.assert_packet_checksums_valid(decrypt_pkt)
- self.assert_equal(decrypt_pkt[IP].src, self.pg1.remote_ip4,
- "encrypted packet source address")
- self.assert_equal(decrypt_pkt[IP].dst, self.tun_if.remote_ip4,
- "encrypted packet destination address")
- except Exception:
- self.logger.error(
- ppp("Unexpected or invalid encrypted packet:", packet))
- raise
-
- def config_esp_tun(self, params):
- addr_type = params.addr_type
- scapy_tun_sa_id = params.scapy_tun_sa_id
- scapy_tun_spi = params.scapy_tun_spi
- vpp_tun_sa_id = params.vpp_tun_sa_id
- vpp_tun_spi = params.vpp_tun_spi
- auth_algo_vpp_id = params.auth_algo_vpp_id
- auth_key = params.auth_key
- crypt_algo_vpp_id = params.crypt_algo_vpp_id
- crypt_key = params.crypt_key
- addr_any = params.addr_any
- addr_bcast = params.addr_bcast
- flags = (VppEnum.vl_api_ipsec_sad_flags_t.
- IPSEC_API_SAD_FLAG_UDP_ENCAP)
- e = VppEnum.vl_api_ipsec_spd_action_t
-
- VppIpsecSA(self, scapy_tun_sa_id, scapy_tun_spi,
- auth_algo_vpp_id, auth_key,
- crypt_algo_vpp_id, crypt_key,
- self.vpp_esp_protocol,
- self.pg1.remote_addr[addr_type],
- self.tun_if.remote_addr[addr_type],
- flags=flags).add_vpp_config()
- VppIpsecSA(self, vpp_tun_sa_id, vpp_tun_spi,
- auth_algo_vpp_id, auth_key,
- crypt_algo_vpp_id, crypt_key,
- self.vpp_esp_protocol,
- self.tun_if.remote_addr[addr_type],
- self.pg1.remote_addr[addr_type],
- flags=flags).add_vpp_config()
-
- VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
- addr_any, addr_bcast,
- addr_any, addr_bcast,
- socket.IPPROTO_ESP).add_vpp_config()
- VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
- addr_any, addr_bcast,
- addr_any, addr_bcast,
- socket.IPPROTO_ESP,
- is_outbound=0).add_vpp_config()
- VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
- addr_any, addr_bcast,
- addr_any, addr_bcast,
- socket.IPPROTO_UDP,
- remote_port_start=4500,
- remote_port_stop=4500).add_vpp_config()
- VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
- addr_any, addr_bcast,
- addr_any, addr_bcast,
- socket.IPPROTO_UDP,
- remote_port_start=4500,
- remote_port_stop=4500,
- is_outbound=0).add_vpp_config()
- VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id,
- self.tun_if.remote_addr[addr_type],
- self.tun_if.remote_addr[addr_type],
- self.pg1.remote_addr[addr_type],
- self.pg1.remote_addr[addr_type],
- 0, priority=10,
- policy=e.IPSEC_API_SPD_ACTION_PROTECT,
- is_outbound=0).add_vpp_config()
- VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id,
- self.pg1.remote_addr[addr_type],
- self.pg1.remote_addr[addr_type],
- self.tun_if.remote_addr[addr_type],
- self.tun_if.remote_addr[addr_type],
- 0, policy=e.IPSEC_API_SPD_ACTION_PROTECT,
- priority=10).add_vpp_config()
-
- def test_ipsec_nat_tun(self):
- """ IPSec/NAT tunnel test case """
- p = self.ipv4_params
- scapy_tun_sa = SecurityAssociation(ESP, spi=p.scapy_tun_spi,
- crypt_algo=p.crypt_algo,
- crypt_key=p.crypt_key,
- auth_algo=p.auth_algo,
- auth_key=p.auth_key,
- tunnel_header=IP(
- src=self.pg1.remote_ip4,
- dst=self.tun_if.remote_ip4),
- nat_t_header=UDP(
- sport=4500,
- dport=4500))
- # in2out - from private network to public
- pkts = self.create_stream_plain(
- self.pg1.remote_mac, self.pg1.local_mac,
- self.pg1.remote_ip4, self.tun_if.remote_ip4)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.tun_if.get_capture(len(pkts))
- self.verify_capture_encrypted(capture, scapy_tun_sa)
-
- vpp_tun_sa = SecurityAssociation(ESP,
- spi=p.vpp_tun_spi,
- crypt_algo=p.crypt_algo,
- crypt_key=p.crypt_key,
- auth_algo=p.auth_algo,
- auth_key=p.auth_key,
- tunnel_header=IP(
- src=self.tun_if.remote_ip4,
- dst=self.pg1.remote_ip4),
- nat_t_header=UDP(
- sport=4500,
- dport=4500))
-
- # out2in - from public network to private
- pkts = self.create_stream_encrypted(
- self.tun_if.remote_mac, self.tun_if.local_mac,
- self.tun_if.remote_ip4, self.pg1.remote_ip4, vpp_tun_sa)
- self.logger.info(ppc("Sending packets:", pkts))
- self.tun_if.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_plain(capture)
diff --git a/test/test_l3xc.py b/test/test_l3xc.py
deleted file mode 100644
index 696e23507ac..00000000000
--- a/test/test_l3xc.py
+++ /dev/null
@@ -1,153 +0,0 @@
-#!/usr/bin/env python
-
-from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
-import unittest
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip import DpoProto
-from vpp_ip_route import VppIpRoute, VppRoutePath, VppMplsLabel, VppIpTable
-
-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 vpp_object import VppObject
-
-NUM_PKTS = 67
-
-
-def find_l3xc(test, sw_if_index, dump_sw_if_index=None):
- if not dump_sw_if_index:
- dump_sw_if_index = sw_if_index
- xcs = test.vapi.l3xc_dump(dump_sw_if_index)
- for xc in xcs:
- if sw_if_index == xc.l3xc.sw_if_index:
- return True
- return False
-
-
-class VppL3xc(VppObject):
-
- def __init__(self, test, intf, paths, is_ip6=False):
- self._test = test
- self.intf = intf
- self.is_ip6 = is_ip6
- 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.l3xc_update(
- l3xc={
- 'is_ip6': self.is_ip6,
- 'sw_if_index': self.intf.sw_if_index,
- 'n_paths': len(self.paths),
- 'paths': self.encoded_paths
- })
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.l3xc_del(
- is_ip6=self.is_ip6,
- sw_if_index=self.intf.sw_if_index)
-
- def query_vpp_config(self):
- return find_l3xc(self._test, self.intf.sw_if_index)
-
- def object_id(self):
- return ("l3xc-%d" % self.intf.sw_if_index)
-
-
-class TestL3xc(VppTestCase):
- """ L3XC Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestL3xc, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestL3xc, cls).tearDownClass()
-
- def setUp(self):
- super(TestL3xc, self).setUp()
-
- self.create_pg_interfaces(range(6))
-
- for i in self.pg_interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
- i.config_ip6()
- i.resolve_ndp()
-
- def tearDown(self):
- for i in self.pg_interfaces:
- i.unconfig_ip4()
- i.unconfig_ip6()
- i.ip6_disable()
- i.admin_down()
- super(TestL3xc, self).tearDown()
-
- def send_and_expect_load_balancing(self, input, pkts, outputs):
- self.pg_send(input, pkts)
- rxs = []
- for oo in outputs:
- rx = oo._get_capture(1)
- self.assertNotEqual(0, len(rx))
- for r in rx:
- rxs.append(r)
- return rxs
-
- def test_l3xc4(self):
- """ IPv4 X-Connect """
-
- #
- # x-connect pg0 to pg1 and pg2 to pg3->5
- #
- l3xc_1 = VppL3xc(self, self.pg0,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- l3xc_1.add_vpp_config()
- l3xc_2 = VppL3xc(self, self.pg2,
- [VppRoutePath(self.pg3.remote_ip4,
- self.pg3.sw_if_index),
- VppRoutePath(self.pg4.remote_ip4,
- self.pg4.sw_if_index),
- VppRoutePath(self.pg5.remote_ip4,
- self.pg5.sw_if_index)])
- l3xc_2.add_vpp_config()
-
- self.assertTrue(find_l3xc(self, self.pg2.sw_if_index, 0xffffffff))
-
- self.logger.info(self.vapi.cli("sh l3xc"))
-
- #
- # fire in packets. If it's forwarded then the L3XC was successful,
- # since default routing will drop it
- #
- p_1 = (Ether(src=self.pg0.remote_mac,
- dst=self.pg0.local_mac) /
- IP(src="1.1.1.1", dst="1.1.1.2") /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- # self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg1)
-
- p_2 = []
- for ii in range(NUM_PKTS):
- p_2.append(Ether(src=self.pg0.remote_mac,
- dst=self.pg0.local_mac) /
- IP(src="1.1.1.1", dst="1.1.1.2") /
- UDP(sport=1000 + ii, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect_load_balancing(self.pg2, p_2,
- [self.pg3, self.pg4, self.pg5])
-
- l3xc_2.remove_vpp_config()
- self.send_and_assert_no_replies(self.pg2, p_2)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_lb.py b/test/test_lb.py
deleted file mode 100644
index 4603bd10db8..00000000000
--- a/test/test_lb.py
+++ /dev/null
@@ -1,502 +0,0 @@
-import socket
-
-import scapy.compat
-from scapy.layers.inet import IP, UDP
-from scapy.layers.inet6 import IPv6
-from scapy.layers.l2 import Ether, GRE
-from scapy.packet import Raw
-from scapy.data import IP_PROTOS
-
-from framework import VppTestCase
-from util import ppp
-from vpp_ip_route import VppIpRoute, VppRoutePath
-from vpp_ip import INVALID_INDEX
-
-""" TestLB is a subclass of VPPTestCase classes.
-
- TestLB class defines Load Balancer test cases for:
- - IP4 to GRE4 encap on per-port vip case
- - IP4 to GRE6 encap on per-port vip case
- - IP6 to GRE4 encap on per-port vip case
- - IP6 to GRE6 encap on per-port vip case
- - IP4 to L3DSR encap on vip case
- - IP4 to L3DSR encap on per-port vip case
- - IP4 to NAT4 encap on per-port vip case
- - IP6 to NAT6 encap on per-port vip case
-
- As stated in comments below, GRE has issues with IPv6.
- All test cases involving IPv6 are executed, but
- received packets are not parsed and checked.
-
-"""
-
-
-class TestLB(VppTestCase):
- """ Load Balancer Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestLB, cls).setUpClass()
-
- cls.ass = range(5)
- cls.packets = range(1)
-
- try:
- cls.create_pg_interfaces(range(2))
- cls.interfaces = list(cls.pg_interfaces)
-
- for i in cls.interfaces:
- i.admin_up()
- i.config_ip4()
- i.config_ip6()
- i.disable_ipv6_ra()
- i.resolve_arp()
- i.resolve_ndp()
-
- dst4 = VppIpRoute(cls, "10.0.0.0", 24,
- [VppRoutePath(cls.pg1.remote_ip4,
- INVALID_INDEX)],
- register=False)
- dst4.add_vpp_config()
- dst6 = VppIpRoute(cls, "2002::", 16,
- [VppRoutePath(cls.pg1.remote_ip6,
- INVALID_INDEX)],
- register=False)
- dst6.add_vpp_config()
- cls.vapi.lb_conf(ip4_src_address="39.40.41.42",
- ip6_src_address="2004::1")
- except Exception:
- super(TestLB, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestLB, cls).tearDownClass()
-
- def tearDown(self):
- super(TestLB, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show lb vip verbose"))
-
- def getIPv4Flow(self, id):
- return (IP(dst="90.0.%u.%u" % (id / 255, id % 255),
- src="40.0.%u.%u" % (id / 255, id % 255)) /
- UDP(sport=10000 + id, dport=20000))
-
- def getIPv6Flow(self, id):
- return (IPv6(dst="2001::%u" % (id), src="fd00:f00d:ffff::%u" % (id)) /
- UDP(sport=10000 + id, dport=20000))
-
- def generatePackets(self, src_if, isv4):
- self.reset_packet_infos()
- pkts = []
- for pktid in self.packets:
- info = self.create_packet_info(src_if, self.pg1)
- payload = self.info_to_payload(info)
- ip = self.getIPv4Flow(pktid) if isv4 else self.getIPv6Flow(pktid)
- packet = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
- ip /
- Raw(payload))
- self.extend_packet(packet, 128)
- info.data = packet.copy()
- pkts.append(packet)
- return pkts
-
- def checkInner(self, gre, isv4):
- IPver = IP if isv4 else IPv6
- self.assertEqual(gre.proto, 0x0800 if isv4 else 0x86DD)
- self.assertEqual(gre.flags, 0)
- self.assertEqual(gre.version, 0)
- inner = IPver(scapy.compat.raw(gre.payload))
- payload_info = self.payload_to_info(inner[Raw])
- self.info = self.packet_infos[payload_info.index]
- self.assertEqual(payload_info.src, self.pg0.sw_if_index)
- self.assertEqual(scapy.compat.raw(inner),
- scapy.compat.raw(self.info.data[IPver]))
-
- def checkCapture(self, encap, isv4):
- self.pg0.assert_nothing_captured()
- out = self.pg1.get_capture(len(self.packets))
-
- load = [0] * len(self.ass)
- self.info = None
- for p in out:
- try:
- asid = 0
- gre = None
- if (encap == 'gre4'):
- ip = p[IP]
- asid = int(ip.dst.split(".")[3])
- self.assertEqual(ip.version, 4)
- self.assertEqual(ip.flags, 0)
- self.assertEqual(ip.src, "39.40.41.42")
- self.assertEqual(ip.dst, "10.0.0.%u" % asid)
- self.assertEqual(ip.proto, 47)
- self.assertEqual(len(ip.options), 0)
- gre = p[GRE]
- self.checkInner(gre, isv4)
- elif (encap == 'gre6'):
- ip = p[IPv6]
- asid = ip.dst.split(":")
- asid = asid[len(asid) - 1]
- asid = 0 if asid == "" else int(asid)
- self.assertEqual(ip.version, 6)
- self.assertEqual(ip.tc, 0)
- self.assertEqual(ip.fl, 0)
- self.assertEqual(ip.src, "2004::1")
- self.assertEqual(
- socket.inet_pton(socket.AF_INET6, ip.dst),
- socket.inet_pton(socket.AF_INET6, "2002::%u" % asid)
- )
- self.assertEqual(ip.nh, 47)
- # self.assertEqual(len(ip.options), 0)
- gre = GRE(scapy.compat.raw(p[IPv6].payload))
- self.checkInner(gre, isv4)
- elif (encap == 'l3dsr'):
- ip = p[IP]
- asid = int(ip.dst.split(".")[3])
- self.assertEqual(ip.version, 4)
- self.assertEqual(ip.flags, 0)
- self.assertEqual(ip.dst, "10.0.0.%u" % asid)
- self.assertEqual(ip.tos, 0x1c)
- self.assertEqual(len(ip.options), 0)
- self.assert_ip_checksum_valid(p)
- if ip.proto == IP_PROTOS.tcp:
- self.assert_tcp_checksum_valid(p)
- elif ip.proto == IP_PROTOS.udp:
- self.assert_udp_checksum_valid(p)
- elif (encap == 'nat4'):
- ip = p[IP]
- asid = int(ip.dst.split(".")[3])
- self.assertEqual(ip.version, 4)
- self.assertEqual(ip.flags, 0)
- self.assertEqual(ip.dst, "10.0.0.%u" % asid)
- self.assertEqual(ip.proto, 17)
- self.assertEqual(len(ip.options), 0)
- udp = p[UDP]
- self.assertEqual(udp.dport, 3307)
- elif (encap == 'nat6'):
- ip = p[IPv6]
- asid = ip.dst.split(":")
- asid = asid[len(asid) - 1]
- asid = 0 if asid == "" else int(asid)
- self.assertEqual(ip.version, 6)
- self.assertEqual(ip.tc, 0)
- self.assertEqual(ip.fl, 0)
- self.assertEqual(
- socket.inet_pton(socket.AF_INET6, ip.dst),
- socket.inet_pton(socket.AF_INET6, "2002::%u" % asid)
- )
- self.assertEqual(ip.nh, 17)
- self.assertGreaterEqual(ip.hlim, 63)
- udp = UDP(scapy.compat.raw(p[IPv6].payload))
- self.assertEqual(udp.dport, 3307)
- load[asid] += 1
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # This is just to roughly check that the balancing algorithm
- # is not completely biased.
- for asid in self.ass:
- if load[asid] < len(self.packets) / (len(self.ass) * 2):
- self.logger.error(
- "ASS is not balanced: load[%d] = %d" % (asid, load[asid]))
- raise Exception("Load Balancer algorithm is biased")
-
- def test_lb_ip4_gre4(self):
- """ Load Balancer IP4 GRE4 on vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap gre4")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='gre4', isv4=True)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap gre4 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip6_gre4(self):
- """ Load Balancer IP6 GRE4 on vip case """
-
- try:
- self.vapi.cli(
- "lb vip 2001::/16 encap gre4")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre4', isv4=False)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 2001::/16 encap gre4 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_gre6(self):
- """ Load Balancer IP4 GRE6 on vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap gre6")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 2002::%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre6', isv4=True)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 2002::%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap gre6 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip6_gre6(self):
- """ Load Balancer IP6 GRE6 on vip case """
- try:
- self.vapi.cli(
- "lb vip 2001::/16 encap gre6")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 2002::%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre6', isv4=False)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 2002::%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 2001::/16 encap gre6 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_gre4_port(self):
- """ Load Balancer IP4 GRE4 on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap gre4")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='gre4', isv4=True)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap gre4 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip6_gre4_port(self):
- """ Load Balancer IP6 GRE4 on per-port-vip case """
-
- try:
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap gre4")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre4', isv4=False)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap gre4 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_gre6_port(self):
- """ Load Balancer IP4 GRE6 on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap gre6")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 2002::%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre6', isv4=True)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 2002::%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap gre6 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip6_gre6_port(self):
- """ Load Balancer IP6 GRE6 on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap gre6")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 2002::%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.checkCapture(encap='gre6', isv4=False)
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 2002::%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap gre6 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_l3dsr(self):
- """ Load Balancer IP4 L3DSR on vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap l3dsr dscp 7")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='l3dsr', isv4=True)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 encap l3dsr"
- " dscp 7 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_l3dsr_port(self):
- """ Load Balancer IP4 L3DSR on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap l3dsr dscp 7")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='l3dsr', isv4=True)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap l3dsr"
- " dscp 7 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip4_nat4_port(self):
- """ Load Balancer IP4 NAT4 on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap nat4"
- " type clusterip target_port 3307")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=True))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='nat4', isv4=True)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 90.0.0.0/8 protocol udp port 20000 10.0.0.%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 90.0.0.0/8 protocol udp port 20000 encap nat4"
- " type clusterip target_port 3307 del")
- self.vapi.cli("test lb flowtable flush")
-
- def test_lb_ip6_nat6_port(self):
- """ Load Balancer IP6 NAT6 on per-port-vip case """
- try:
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap nat6"
- " type clusterip target_port 3307")
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 2002::%u"
- % (asid))
-
- self.pg0.add_stream(self.generatePackets(self.pg0, isv4=False))
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.checkCapture(encap='nat6', isv4=False)
-
- finally:
- for asid in self.ass:
- self.vapi.cli(
- "lb as 2001::/16 protocol udp port 20000 2002::%u del"
- % (asid))
- self.vapi.cli(
- "lb vip 2001::/16 protocol udp port 20000 encap nat6"
- " type clusterip target_port 3307 del")
- self.vapi.cli("test lb flowtable flush")
diff --git a/test/test_lb_api.py b/test/test_lb_api.py
deleted file mode 100644
index 70d41d432a7..00000000000
--- a/test/test_lb_api.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright (c) 2019. Vinci Consulting Corp. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import framework
-import ipaddress
-
-DEFAULT_VIP = "lb_vip_details(_0=978, context=12, vip=vl_api_lb_ip_addr_t(pfx=IPv6Network(u'::/0'), protocol=<vl_api_ip_proto_t.IP_API_PROTO_RESERVED: 255>, port=0), encap=<vl_api_lb_encap_type_t.LB_API_ENCAP_TYPE_GRE4: 0>, dscp=<vl_api_ip_dscp_t.IP_API_DSCP_CS0: 0>, srv_type=<vl_api_lb_srv_type_t.LB_API_SRV_TYPE_CLUSTERIP: 0>, target_port=0, flow_table_length=0)" # noqa
-
-
-class TestLbEmptyApi(framework.VppTestCase):
- """TestLbEmptyApi """
-
- def test_lb_empty_vip_dump(self):
-
- # no records should normally return [], but
- # lb initializes with a default VIP
- rv = self.vapi.lb_vip_dump()
- # print(rv)
- self.assertEqual(rv, [], 'Expected: [] Received: %r.' % rv)
-
- def test_lb_empty_as_dump(self):
-
- # no records should return []
- rv = self.vapi.lb_as_dump()
- # print(rv)
- self.assertEqual(rv, [], 'Expected: [] Received: %r.' % rv)
-
-
-class TestLbApi(framework.VppTestCase):
- """TestLbApi """
-
- def test_lb_vip_dump(self):
- # add some vips
- # rv = self.vapi.lb_add_del_vip(pfx=ipaddress.IPv4Network(u'1.2.3.0/24'), # noqa
- # protocol=17,
- # encap=0)
- # print(rv)
- self.vapi.cli("lb vip 2001::/16 encap gre6")
- rv = self.vapi.lb_vip_dump()
- # print(rv)
- self.assertEqual(str(rv[-1].vip.pfx), "2001::/16",
- 'Expected: 2001::/16 Received: %r.' % rv[-1].vip.pfx)
-
- self.vapi.cli("lb vip 2001::/16 del")
-
-
-class TestLbAsApi(framework.VppTestCase):
- """TestLbAsApi """
-
- def test_lb_as_dump(self):
- # add some vips
- self.vapi.cli("lb vip 2001::/16 encap gre6")
- self.vapi.cli("lb as 2001::/16 2000::1")
- # add some as's for the vips
- # rv = self.vapi.lb_add_del_as(
- # pfx=ipaddress.IPv4Network(u"10.0.0.0/24"),
- # as_address=ipaddress.IPv4Address(u"192.168.1.1"))
-
- # print(rv)
- rv = self.vapi.lb_as_dump()
- # print(rv)
- self.assertEqual(str(rv[0].vip.pfx), "2001::/16",
- 'Expected: "2001::/16" Received: %r.' % rv[0].vip.pfx)
- self.assertEqual(str(rv[0].app_srv), "2000::1",
- 'Expected: "2000::1" Received: %r.' % rv[0].app_srv)
diff --git a/test/test_mactime.py b/test/test_mactime.py
deleted file mode 100644
index ab3d5371815..00000000000
--- a/test/test_mactime.py
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
-
-
-class TestMactime(VppTestCase):
- """ Mactime Unit Test Cases """
-
- @classmethod
- def setUpClass(cls):
- super(TestMactime, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestMactime, cls).tearDownClass()
-
- def setUp(self):
- super(TestMactime, self).setUp()
-
- def tearDown(self):
- super(TestMactime, self).tearDown()
-
- def test_mactime_range_unittest(self):
- """ Time Range Test """
- error = self.vapi.cli("test time-range")
-
- if error:
- self.logger.critical(error)
- self.assertNotIn('FAILED', error)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_mactime_unittest(self):
- """ Mactime Plugin Code Coverage Test """
- cmds = ["loopback create",
- "mactime enable-disable disable",
- "mactime enable-disable loop0",
- "mactime enable-disable loop0 disable",
- "mactime enable-disable sw_if_index 9999",
- "bin mactime_enable_disable loop0",
- "bin mactime_enable_disable loop0 disable",
- "bin mactime_enable_disable sw_if_index 1",
- "set interface state loop0 up",
- "clear mactime",
- "set ip arp loop0 192.168.1.1 00:d0:2d:5e:86:85",
- "bin mactime_add_del_range name sallow "
- "mac 00:d0:2d:5e:86:85 allow-static del",
- "bin mactime_add_del_range name sallow "
- "mac 00:d0:2d:5e:86:85 allow-static",
- "bin mactime_add_del_range name sallow "
- "mac 00:d0:2d:5e:86:85 allow-static del",
- "bin mactime_add_del_range name sallow "
- "mac 00:d0:2d:5e:86:85 allow-static",
- "bin mactime_add_del_range name sblock "
- "mac 01:00:5e:7f:ff:fa drop-static",
- "bin mactime_add_del_range name ddrop "
- "mac c8:bc:c8:5a:ba:f3 drop-range Sun - Sat "
- "00:00 - 23:59",
- "bin mactime_add_del_range name dallow "
- "mac c8:bc:c8:5a:ba:f4 allow-range Sun - Sat "
- "00:00 - 23:59",
- "bin mactime_add_del_range name multi "
- "mac c8:bc:c8:f0:f0:f0 allow-range Sun - Mon "
- "00:00 - 23:59 Tue - Sat 00:00 - 23:59",
- "bin mactime_add_del_range bogus",
- "bin mactime_add_del_range mac 01:00:5e:7f:f0:f0 allow-static",
- "bin mactime_add_del_range "
- "name tooloooooooooooooooooooooooooooooooooooooooooooooooo"
- "nnnnnnnnnnnnnnnnnnnnnnnnnnnng mac 00:00:de:ad:be:ef "
- "allow-static",
- "packet-generator new {\n"
- " name allow\n"
- " limit 15\n"
- " size 128-128\n"
- " interface loop0\n"
- " node ethernet-input\n"
- " data {\n"
- " IP6: 00:d0:2d:5e:86:85 -> 00:0d:ea:d0:00:00\n"
- " ICMP: db00::1 -> db00::2\n"
- " incrementing 30\n"
- " }\n",
- "}\n",
- "packet-generator new {\n"
- " name deny\n"
- " limit 15\n"
- " size 128-128\n"
- " interface loop0\n"
- " node ethernet-input\n"
- " data {\n"
- " IP6: 01:00:5e:7f:ff:fa -> 00:0d:ea:d0:00:00\n"
- " ICMP: db00::1 -> db00::2\n"
- " incrementing 30\n"
- " }\n",
- "}\n",
- "packet-generator new {\n"
- " name ddrop\n"
- " limit 15\n"
- " size 128-128\n"
- " interface loop0\n"
- " node ethernet-input\n"
- " data {\n"
- " IP6: c8:bc:c8:5a:ba:f3 -> 00:0d:ea:d0:00:00\n"
- " ICMP: db00::1 -> db00::2\n"
- " incrementing 30\n"
- " }\n",
- "}\n",
- "packet-generator new {\n"
- " name dallow\n"
- " limit 15\n"
- " size 128-128\n"
- " interface loop0\n"
- " node ethernet-input\n"
- " data {\n"
- " IP6: c8:bc:c8:5a:ba:f4 -> 00:0d:ea:d0:00:00\n"
- " ICMP: db00::1 -> db00::2\n"
- " incrementing 30\n"
- " }\n"
- "}\n"
- "packet-generator new {\n"
- " name makeentry\n"
- " limit 15\n"
- " size 128-128\n"
- " interface loop0\n"
- " node ethernet-input\n"
- " data {\n"
- " IP6: c8:bc:c8:5a:b0:0b -> 00:0d:ea:d0:00:00\n"
- " ICMP: db00::1 -> db00::2\n"
- " incrementing 30\n"
- " }\n"
- "}\n"
- "packet-generator new {\n"
- " name tx\n"
- " limit 15\n"
- " size 128-128\n"
- " interface local0\n"
- " tx-interface loop0\n"
- " node loop0-output\n"
- " data {\n"
- " hex 0x01005e7ffffa000dead000000800"
- "0102030405060708090a0b0c0d0e0f0102030405\n"
- " }\n"
- "}\n"
- "trace add pg-input 2",
- "pa en",
- "show mactime verbose 2",
- "show trace",
- "show error"]
-
- for cmd in cmds:
- self.logger.info(self.vapi.cli(cmd))
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_map.py b/test/test_map.py
deleted file mode 100644
index f1388b39c65..00000000000
--- a/test/test_map.py
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/usr/bin/env python
-
-import ipaddress
-import unittest
-from ipaddress import IPv6Network, IPv4Network
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip import DpoProto
-from vpp_ip_route import VppIpRoute, VppRoutePath
-
-import scapy.compat
-from scapy.layers.l2 import Ether, Raw
-from scapy.layers.inet import IP, UDP, ICMP, TCP, fragment
-from scapy.layers.inet6 import IPv6, ICMPv6TimeExceeded
-
-
-class TestMAP(VppTestCase):
- """ MAP Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestMAP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestMAP, cls).tearDownClass()
-
- def setUp(self):
- super(TestMAP, self).setUp()
-
- # create 2 pg interfaces
- self.create_pg_interfaces(range(4))
-
- # pg0 is 'inside' IPv4
- self.pg0.admin_up()
- self.pg0.config_ip4()
- self.pg0.resolve_arp()
-
- # pg1 is 'outside' IPv6
- self.pg1.admin_up()
- self.pg1.config_ip6()
- self.pg1.generate_remote_hosts(4)
- self.pg1.configure_ipv6_neighbors()
-
- def tearDown(self):
- super(TestMAP, self).tearDown()
- for i in self.pg_interfaces:
- i.unconfig_ip4()
- i.unconfig_ip6()
- i.admin_down()
-
- def send_and_assert_encapped(self, tx, ip6_src, ip6_dst, dmac=None):
- if not dmac:
- dmac = self.pg1.remote_mac
-
- self.pg0.add_stream(tx)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx = self.pg1.get_capture(1)
- rx = rx[0]
-
- self.assertEqual(rx[Ether].dst, dmac)
- self.assertEqual(rx[IP].src, tx[IP].src)
- self.assertEqual(rx[IPv6].src, ip6_src)
- self.assertEqual(rx[IPv6].dst, ip6_dst)
-
- def test_api_map_domain_dump(self):
- map_dst = '2001::/64'
- map_src = '3000::1/128'
- client_pfx = '192.168.0.0/16'
- tag = 'MAP-E tag.'
- index = self.vapi.map_add_domain(ip4_prefix=client_pfx,
- ip6_prefix=map_dst,
- ip6_src=map_src,
- tag=tag).index
-
- rv = self.vapi.map_domain_dump()
-
- # restore the state early so as to not impact subsequent tests.
- # If an assert fails, we will not get the chance to do it at the end.
- self.vapi.map_del_domain(index=index)
-
- self.assertGreater(len(rv), 0,
- "Expected output from 'map_domain_dump'")
-
- # typedefs are returned as ipaddress objects.
- # wrap results in str() ugh! to avoid the need to call unicode.
- self.assertEqual(str(rv[0].ip4_prefix), client_pfx)
- self.assertEqual(str(rv[0].ip6_prefix), map_dst)
- self.assertEqual(str(rv[0].ip6_src), map_src)
-
- self.assertEqual(rv[0].tag, tag,
- "output produced incorrect tag value.")
-
- def test_map_e(self):
- """ MAP-E """
-
- #
- # Add a route to the MAP-BR
- #
- map_br_pfx = "2001::"
- map_br_pfx_len = 64
- map_route = VppIpRoute(self,
- map_br_pfx,
- map_br_pfx_len,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- map_route.add_vpp_config()
-
- #
- # Add a domain that maps from pg0 to pg1
- #
- map_dst = '2001::/64'
- map_src = '3000::1/128'
- client_pfx = '192.168.0.0/16'
- tag = 'MAP-E tag.'
- self.vapi.map_add_domain(ip4_prefix=client_pfx,
- ip6_prefix=map_dst,
- ip6_src=map_src,
- tag=tag)
-
- # Enable MAP on interface.
- self.vapi.map_if_enable_disable(is_enable=1,
- sw_if_index=self.pg0.sw_if_index,
- is_translation=0)
-
- # Ensure MAP doesn't steal all packets!
- v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg0, v4*1, self.pg0)
- v4_reply = v4[1]
- v4_reply.ttl -= 1
- for p in rx:
- self.validate(p[1], v4_reply)
-
- #
- # Fire in a v4 packet that will be encapped to the BR
- #
- v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst='192.168.1.1') /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
-
- self.send_and_assert_encapped(v4, "3000::1", "2001::c0a8:0:0")
-
- # Enable MAP on interface.
- self.vapi.map_if_enable_disable(is_enable=1,
- sw_if_index=self.pg1.sw_if_index,
- is_translation=0)
-
- # Ensure MAP doesn't steal all packets
- v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg1, v6*1, self.pg1)
- v6_reply = v6[1]
- v6_reply.hlim -= 1
- for p in rx:
- self.validate(p[1], v6_reply)
-
- #
- # Fire in a V6 encapped packet.
- # expect a decapped packet on the inside ip4 link
- #
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(dst='3000::1', src="2001::1") /
- IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
-
- self.pg1.add_stream(p)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx = self.pg0.get_capture(1)
- rx = rx[0]
-
- self.assertFalse(rx.haslayer(IPv6))
- self.assertEqual(rx[IP].src, p[IP].src)
- self.assertEqual(rx[IP].dst, p[IP].dst)
-
- #
- # Pre-resolve. No API for this!!
- #
- self.vapi.ppcli("map params pre-resolve ip6-nh 4001::1")
-
- self.send_and_assert_no_replies(self.pg0, v4,
- "resolved via default route")
-
- #
- # Add a route to 4001::1. Expect the encapped traffic to be
- # sent via that routes next-hop
- #
- pre_res_route = VppIpRoute(self, "4001::1", 128,
- [VppRoutePath(self.pg1.remote_hosts[2].ip6,
- self.pg1.sw_if_index)])
- pre_res_route.add_vpp_config()
-
- self.send_and_assert_encapped(v4, "3000::1",
- "2001::c0a8:0:0",
- dmac=self.pg1.remote_hosts[2].mac)
-
- #
- # change the route to the pre-solved next-hop
- #
- pre_res_route.modify([VppRoutePath(self.pg1.remote_hosts[3].ip6,
- self.pg1.sw_if_index)])
- pre_res_route.add_vpp_config()
-
- self.send_and_assert_encapped(v4, "3000::1",
- "2001::c0a8:0:0",
- dmac=self.pg1.remote_hosts[3].mac)
-
- #
- # cleanup. The test infra's object registry will ensure
- # the route is really gone and thus that the unresolve worked.
- #
- pre_res_route.remove_vpp_config()
- self.vapi.ppcli("map params pre-resolve del ip6-nh 4001::1")
-
- def validate(self, rx, expected):
- self.assertEqual(rx, expected.__class__(scapy.compat.raw(expected)))
-
- def payload(self, len):
- return 'x' * len
-
- def test_map_t(self):
- """ MAP-T """
-
- #
- # Add a domain that maps from pg0 to pg1
- #
- map_dst = '2001:db8::/32'
- map_src = '1234:5678:90ab:cdef::/64'
- ip4_pfx = '192.168.0.0/24'
- tag = 'MAP-T Tag.'
-
- self.vapi.map_add_domain(ip6_prefix=map_dst,
- ip4_prefix=ip4_pfx,
- ip6_src=map_src,
- ea_bits_len=16,
- psid_offset=6,
- psid_length=4,
- mtu=1500,
- tag=tag)
-
- # Enable MAP-T on interfaces.
- self.vapi.map_if_enable_disable(is_enable=1,
- sw_if_index=self.pg0.sw_if_index,
- is_translation=1)
- self.vapi.map_if_enable_disable(is_enable=1,
- sw_if_index=self.pg1.sw_if_index,
- is_translation=1)
-
- # Ensure MAP doesn't steal all packets!
- v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg0, v4*1, self.pg0)
- v4_reply = v4[1]
- v4_reply.ttl -= 1
- for p in rx:
- self.validate(p[1], v4_reply)
- # Ensure MAP doesn't steal all packets
- v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
- UDP(sport=20000, dport=10000) /
- Raw('\xa5' * 100))
- rx = self.send_and_expect(self.pg1, v6*1, self.pg1)
- v6_reply = v6[1]
- v6_reply.hlim -= 1
- for p in rx:
- self.validate(p[1], v6_reply)
-
- map_route = VppIpRoute(self,
- "2001:db8::",
- 32,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index,
- proto=DpoProto.DPO_PROTO_IP6)])
- map_route.add_vpp_config()
-
- #
- # Send a v4 packet that will be translated
- #
- p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
- p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1')
- payload = TCP(sport=0xabcd, dport=0xabcd)
-
- p4 = (p_ether / p_ip4 / payload)
- p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0",
- dst="2001:db8:1f0::c0a8:1:f") / payload)
- p6_translated.hlim -= 1
- rx = self.send_and_expect(self.pg0, p4*1, self.pg1)
- for p in rx:
- self.validate(p[1], p6_translated)
-
- # Send back an IPv6 packet that will be "untranslated"
- p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
- p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f',
- dst='1234:5678:90ab:cdef:ac:1001:200:0')
- p6 = (p_ether6 / p_ip6 / payload)
- p4_translated = (IP(src='192.168.0.1',
- dst=self.pg0.remote_ip4) / payload)
- p4_translated.id = 0
- p4_translated.ttl -= 1
- rx = self.send_and_expect(self.pg1, p6*1, self.pg0)
- for p in rx:
- self.validate(p[1], p4_translated)
-
- # IPv4 TTL
- ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0)
- p4 = (p_ether / ip4_ttl_expired / payload)
-
- icmp4_reply = (IP(id=0, ttl=254, src=self.pg0.local_ip4,
- dst=self.pg0.remote_ip4) /
- ICMP(type='time-exceeded',
- code='ttl-zero-during-transit') /
- IP(src=self.pg0.remote_ip4,
- dst='192.168.0.1', ttl=0) / payload)
- rx = self.send_and_expect(self.pg0, p4*1, self.pg0)
- for p in rx:
- self.validate(p[1], icmp4_reply)
-
- '''
- This one is broken, cause it would require hairpinning...
- # IPv4 TTL TTL1
- ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=1)
- p4 = (p_ether / ip4_ttl_expired / payload)
-
- icmp4_reply = IP(id=0, ttl=254, src=self.pg0.local_ip4,
- dst=self.pg0.remote_ip4) / \
- ICMP(type='time-exceeded', code='ttl-zero-during-transit' ) / \
- IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload
- rx = self.send_and_expect(self.pg0, p4*1, self.pg0)
- for p in rx:
- self.validate(p[1], icmp4_reply)
- '''
-
- # IPv6 Hop limit
- ip6_hlim_expired = IPv6(hlim=0, src='2001:db8:1ab::c0a8:1:ab',
- dst='1234:5678:90ab:cdef:ac:1001:200:0')
- p6 = (p_ether6 / ip6_hlim_expired / payload)
-
- icmp6_reply = (IPv6(hlim=255, src=self.pg1.local_ip6,
- dst="2001:db8:1ab::c0a8:1:ab") /
- ICMPv6TimeExceeded(code=0) /
- IPv6(src="2001:db8:1ab::c0a8:1:ab",
- dst='1234:5678:90ab:cdef:ac:1001:200:0',
- hlim=0) / payload)
- rx = self.send_and_expect(self.pg1, p6*1, self.pg1)
- for p in rx:
- self.validate(p[1], icmp6_reply)
-
- # IPv4 Well-known port
- p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1')
- payload = UDP(sport=200, dport=200)
- p4 = (p_ether / p_ip4 / payload)
- self.send_and_assert_no_replies(self.pg0, p4*1)
-
- # IPv6 Well-known port
- payload = UDP(sport=200, dport=200)
- p6 = (p_ether6 / p_ip6 / payload)
- self.send_and_assert_no_replies(self.pg1, p6*1)
-
- # Packet fragmentation
- payload = UDP(sport=40000, dport=4000) / self.payload(1453)
- p4 = (p_ether / p_ip4 / payload)
- self.pg_enable_capture()
- self.pg0.add_stream(p4)
- self.pg_start()
- rx = self.pg1.get_capture(2)
- for p in rx:
- pass
- # TODO: Manual validation
- # self.validate(p[1], icmp4_reply)
-
- # Packet fragmentation send fragments
- payload = UDP(sport=40000, dport=4000) / self.payload(1453)
- p4 = (p_ether / p_ip4 / payload)
- frags = fragment(p4, fragsize=1000)
- self.pg_enable_capture()
- self.pg0.add_stream(frags)
- self.pg_start()
- rx = self.pg1.get_capture(2)
- for p in rx:
- pass
- # p.show2()
- # reass_pkt = reassemble(rx)
- # p4_reply.ttl -= 1
- # p4_reply.id = 256
- # self.validate(reass_pkt, p4_reply)
-
- # TCP MSS clamping
- self.vapi.map_param_set_tcp(1300)
-
- #
- # Send a v4 TCP SYN packet that will be translated and MSS clamped
- #
- p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
- p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1')
- payload = TCP(sport=0xabcd, dport=0xabcd, flags="S",
- options=[('MSS', 1460)])
-
- p4 = (p_ether / p_ip4 / payload)
- p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0",
- dst="2001:db8:1f0::c0a8:1:f") / payload)
- p6_translated.hlim -= 1
- p6_translated[TCP].options = [('MSS', 1300)]
- rx = self.send_and_expect(self.pg0, p4*1, self.pg1)
- for p in rx:
- self.validate(p[1], p6_translated)
-
- # Send back an IPv6 packet that will be "untranslated"
- p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
- p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f',
- dst='1234:5678:90ab:cdef:ac:1001:200:0')
- p6 = (p_ether6 / p_ip6 / payload)
- p4_translated = (IP(src='192.168.0.1',
- dst=self.pg0.remote_ip4) / payload)
- p4_translated.id = 0
- p4_translated.ttl -= 1
- p4_translated[TCP].options = [('MSS', 1300)]
- rx = self.send_and_expect(self.pg1, p6*1, self.pg0)
- for p in rx:
- self.validate(p[1], p4_translated)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_memif.py b/test/test_memif.py
deleted file mode 100644
index aae5b3c1efb..00000000000
--- a/test/test_memif.py
+++ /dev/null
@@ -1,275 +0,0 @@
-import socket
-import unittest
-
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, ICMP
-import six
-
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-from remote_test import RemoteClass, RemoteVppTestCase
-from vpp_memif import MEMIF_MODE, MEMIF_ROLE, remove_all_memif_vpp_config, \
- VppSocketFilename, VppMemif
-from vpp_ip_route import VppIpRoute, VppRoutePath
-
-
-class TestMemif(VppTestCase):
- """ Memif Test Case """
-
- @classmethod
- def setUpClass(cls):
- # fork new process before client connects to VPP
- cls.remote_test = RemoteClass(RemoteVppTestCase)
- cls.remote_test.start_remote()
- cls.remote_test.set_request_timeout(10)
- super(TestMemif, cls).setUpClass()
- cls.remote_test.setUpClass(cls.tempdir)
- cls.create_pg_interfaces(range(1))
- for pg in cls.pg_interfaces:
- pg.config_ip4()
- pg.admin_up()
- pg.resolve_arp()
-
- @classmethod
- def tearDownClass(cls):
- cls.remote_test.tearDownClass()
- cls.remote_test.quit_remote()
- for pg in cls.pg_interfaces:
- pg.unconfig_ip4()
- pg.set_table_ip4(0)
- pg.admin_down()
- super(TestMemif, cls).tearDownClass()
-
- def tearDown(self):
- remove_all_memif_vpp_config(self)
- remove_all_memif_vpp_config(self.remote_test)
- super(TestMemif, self).tearDown()
-
- def _check_socket_filename(self, dump, socket_id, filename):
- for d in dump:
- if (d.socket_id == socket_id) and (
- d.socket_filename.rstrip(b"\0") == filename):
- return True
- return False
-
- def test_memif_socket_filename_add_del(self):
- """ Memif socket filename add/del """
-
- # dump default socket filename
- dump = self.vapi.memif_socket_filename_dump()
- self.assertTrue(
- self._check_socket_filename(
- dump, 0, b"%s/memif.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8')))
-
- memif_sockets = []
- # existing path
- memif_sockets.append(
- VppSocketFilename(
- self, 1, b"%s/memif1.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8')))
- # default path (test tempdir)
- memif_sockets.append(
- VppSocketFilename(
- self,
- 2,
- b"memif2.sock",
- add_default_folder=True))
- # create new folder in default folder
- memif_sockets.append(
- VppSocketFilename(
- self,
- 3,
- b"sock/memif3.sock",
- add_default_folder=True))
-
- for sock in memif_sockets:
- sock.add_vpp_config()
- dump = sock.query_vpp_config()
- self.assertTrue(
- self._check_socket_filename(
- dump,
- sock.socket_id,
- sock.socket_filename))
-
- for sock in memif_sockets:
- sock.remove_vpp_config()
-
- dump = self.vapi.memif_socket_filename_dump()
- self.assertTrue(
- self._check_socket_filename(
- dump, 0, b"%s/memif.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8')))
-
- def _create_delete_test_one_interface(self, memif):
- memif.add_vpp_config()
-
- dump = memif.query_vpp_config()
-
- self.assertTrue(dump)
- self.assertEqual(dump.sw_if_index, memif.sw_if_index)
- self.assertEqual(dump.role, memif.role)
- self.assertEqual(dump.mode, memif.mode)
- if (memif.socket_id is not None):
- self.assertEqual(dump.socket_id, memif.socket_id)
-
- memif.remove_vpp_config()
-
- dump = memif.query_vpp_config()
-
- self.assertFalse(dump)
-
- def _connect_test_one_interface(self, memif):
- self.assertTrue(memif.wait_for_link_up(5))
- dump = memif.query_vpp_config()
-
- if memif.role == MEMIF_ROLE.SLAVE:
- self.assertEqual(dump.ring_size, memif.ring_size)
- self.assertEqual(dump.buffer_size, memif.buffer_size)
- else:
- self.assertEqual(dump.ring_size, 1)
- self.assertEqual(dump.buffer_size, 0)
-
- def _connect_test_interface_pair(self, memif0, memif1):
- memif0.add_vpp_config()
- memif1.add_vpp_config()
-
- memif0.admin_up()
- memif1.admin_up()
-
- self._connect_test_one_interface(memif0)
- self._connect_test_one_interface(memif1)
-
- memif0.remove_vpp_config()
- memif1.remove_vpp_config()
-
- def test_memif_create_delete(self):
- """ Memif create/delete interface """
-
- memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET)
- self._create_delete_test_one_interface(memif)
- memif.role = MEMIF_ROLE.MASTER
- self._create_delete_test_one_interface(memif)
-
- def test_memif_create_custom_socket(self):
- """ Memif create with non-default socket filename """
-
- memif_sockets = []
- # existing path
- memif_sockets.append(
- VppSocketFilename(
- self, 1, b"%s/memif1.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8')))
- # default path (test tempdir)
- memif_sockets.append(
- VppSocketFilename(
- self,
- 2,
- b"memif2.sock",
- add_default_folder=True))
- # create new folder in default folder
- memif_sockets.append(
- VppSocketFilename(
- self,
- 3,
- b"sock/memif3.sock",
- add_default_folder=True))
-
- memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET)
-
- for sock in memif_sockets:
- sock.add_vpp_config()
- memif.socket_id = sock.socket_id
- memif.role = MEMIF_ROLE.SLAVE
- self._create_delete_test_one_interface(memif)
- memif.role = MEMIF_ROLE.MASTER
- self._create_delete_test_one_interface(memif)
-
- def test_memif_connect(self):
- """ Memif connect """
- memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET,
- ring_size=1024, buffer_size=2048)
-
- remote_socket = VppSocketFilename(self.remote_test, 1,
- b"%s/memif.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8'))
- remote_socket.add_vpp_config()
-
- remote_memif = VppMemif(self.remote_test, MEMIF_ROLE.MASTER,
- MEMIF_MODE.ETHERNET, socket_id=1,
- ring_size=1024, buffer_size=2048)
-
- self._connect_test_interface_pair(memif, remote_memif)
-
- memif.role = MEMIF_ROLE.MASTER
- remote_memif.role = MEMIF_ROLE.SLAVE
-
- self._connect_test_interface_pair(memif, remote_memif)
-
- def _create_icmp(self, pg, memif, num):
- pkts = []
- for i in range(num):
- pkt = (Ether(dst=pg.local_mac, src=pg.remote_mac) /
- IP(src=pg.remote_ip4, dst=memif.ip4_addr) /
- ICMP(id=memif.if_id, type='echo-request', seq=i))
- pkts.append(pkt)
- return pkts
-
- def _verify_icmp(self, pg, memif, rx, seq):
- ip = rx[IP]
- self.assertEqual(ip.src, memif.ip4_addr)
- self.assertEqual(ip.dst, pg.remote_ip4)
- self.assertEqual(ip.proto, 1)
- icmp = rx[ICMP]
- self.assertEqual(icmp.type, 0) # echo-reply
- self.assertEqual(icmp.id, memif.if_id)
- self.assertEqual(icmp.seq, seq)
-
- def test_memif_ping(self):
- """ Memif ping """
-
- memif = VppMemif(self, MEMIF_ROLE.SLAVE, MEMIF_MODE.ETHERNET)
-
- remote_socket = VppSocketFilename(self.remote_test, 1,
- b"%s/memif.sock" % six.ensure_binary(
- self.tempdir, encoding='utf-8'))
- remote_socket.add_vpp_config()
-
- remote_memif = VppMemif(self.remote_test, MEMIF_ROLE.MASTER,
- MEMIF_MODE.ETHERNET, socket_id=1)
-
- memif.add_vpp_config()
- memif.config_ip4()
- memif.admin_up()
-
- remote_memif.add_vpp_config()
- remote_memif.config_ip4()
- remote_memif.admin_up()
-
- self.assertTrue(memif.wait_for_link_up(5))
- self.assertTrue(remote_memif.wait_for_link_up(5))
-
- # add routing to remote vpp
- route = VppIpRoute(self.remote_test, self.pg0._local_ip4_subnet, 24,
- [VppRoutePath(memif.ip4_addr, 0xffffffff)],
- register=False)
-
- route.add_vpp_config()
-
- # create ICMP echo-request from local pg to remote memif
- packet_num = 10
- pkts = self._create_icmp(self.pg0, remote_memif, packet_num)
-
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(packet_num, timeout=2)
- seq = 0
- for c in capture:
- self._verify_icmp(self.pg0, remote_memif, c, seq)
- seq += 1
-
- route.remove_vpp_config()
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_nat.py b/test/test_nat.py
deleted file mode 100644
index 773eb51d4ee..00000000000
--- a/test/test_nat.py
+++ /dev/null
@@ -1,9576 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-import unittest
-import struct
-import random
-
-from framework import VppTestCase, VppTestRunner, running_extended_tests
-
-import scapy.compat
-from scapy.layers.inet import IP, TCP, UDP, ICMP
-from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
-from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
- ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
-from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
-from scapy.layers.l2 import Ether, ARP, GRE
-from scapy.data import IP_PROTOS
-from scapy.packet import bind_layers, Raw
-from util import ppp
-from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
-from time import sleep
-from util import ip4_range
-from vpp_papi import mac_pton
-from syslog_rfc5424_parser import SyslogMessage, ParseError
-from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
-from io import BytesIO
-from vpp_papi import VppEnum
-from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType
-from vpp_neighbor import VppNeighbor
-from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
- IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
- PacketListField
-from ipaddress import IPv6Network
-
-
-# NAT HA protocol event data
-class Event(Packet):
- name = "Event"
- fields_desc = [ByteEnumField("event_type", None,
- {1: "add", 2: "del", 3: "refresh"}),
- ByteEnumField("protocol", None,
- {0: "udp", 1: "tcp", 2: "icmp"}),
- ShortField("flags", 0),
- IPField("in_addr", None),
- IPField("out_addr", None),
- ShortField("in_port", None),
- ShortField("out_port", None),
- IPField("eh_addr", None),
- IPField("ehn_addr", None),
- ShortField("eh_port", None),
- ShortField("ehn_port", None),
- IntField("fib_index", None),
- IntField("total_pkts", 0),
- LongField("total_bytes", 0)]
-
- def extract_padding(self, s):
- return "", s
-
-
-# NAT HA protocol header
-class HANATStateSync(Packet):
- name = "HA NAT state sync"
- fields_desc = [XByteField("version", 1),
- FlagsField("flags", 0, 8, ['ACK']),
- FieldLenField("count", None, count_of="events"),
- IntField("sequence_number", 1),
- IntField("thread_index", 0),
- PacketListField("events", [], Event,
- count_from=lambda pkt: pkt.count)]
-
-
-class MethodHolder(VppTestCase):
- """ NAT create capture and verify method holder """
-
- @property
- def config_flags(self):
- return VppEnum.vl_api_nat_config_flags_t
-
- @property
- def SYSLOG_SEVERITY(self):
- return VppEnum.vl_api_syslog_severity_t
-
- def clear_nat44(self):
- """
- Clear NAT44 configuration.
- """
- if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
- if self.pg7.has_ip4_config:
- self.pg7.unconfig_ip4()
-
- self.vapi.nat44_forwarding_enable_disable(enable=0)
-
- interfaces = self.vapi.nat44_interface_addr_dump()
- for intf in interfaces:
- self.vapi.nat44_add_del_interface_addr(
- is_add=0,
- sw_if_index=intf.sw_if_index,
- flags=intf.flags)
-
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=0)
- self.ipfix_src_port = 4739
- self.ipfix_domain_id = 1
-
- self.vapi.syslog_set_filter(
- self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
-
- self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
- path_mtu=512)
- self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
- session_refresh_interval=10)
-
- interfaces = self.vapi.nat44_interface_dump()
- for intf in interfaces:
- if intf.flags & self.config_flags.NAT_IS_INSIDE and \
- intf.flags & self.config_flags.NAT_IS_OUTSIDE:
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=intf.sw_if_index)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=intf.sw_if_index,
- flags=intf.flags)
-
- interfaces = self.vapi.nat44_interface_output_feature_dump()
- for intf in interfaces:
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=0,
- flags=intf.flags,
- sw_if_index=intf.sw_if_index)
- static_mappings = self.vapi.nat44_static_mapping_dump()
- for sm in static_mappings:
- self.vapi.nat44_add_del_static_mapping(
- is_add=0,
- local_ip_address=sm.local_ip_address,
- external_ip_address=sm.external_ip_address,
- external_sw_if_index=sm.external_sw_if_index,
- local_port=sm.local_port,
- external_port=sm.external_port,
- vrf_id=sm.vrf_id,
- protocol=sm.protocol,
- flags=sm.flags, tag=sm.tag)
-
- lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
- for lb_sm in lb_static_mappings:
- self.vapi.nat44_add_del_lb_static_mapping(
- is_add=0,
- flags=lb_sm.flags,
- external_addr=lb_sm.external_addr,
- external_port=lb_sm.external_port,
- protocol=lb_sm.protocol,
- local_num=0, locals=[],
- tag=lb_sm.tag)
-
- identity_mappings = self.vapi.nat44_identity_mapping_dump()
- for id_m in identity_mappings:
- self.vapi.nat44_add_del_identity_mapping(
- ip_address=id_m.ip_address,
- sw_if_index=id_m.sw_if_index,
- port=id_m.port,
- flags=id_m.flags,
- vrf_id=id_m.vrf_id,
- protocol=id_m.protocol)
-
- addresses = self.vapi.nat44_address_dump()
- for addr in addresses:
- self.vapi.nat44_add_del_address_range(
- first_ip_address=addr.ip_address,
- last_ip_address=addr.ip_address,
- vrf_id=0xFFFFFFFF, flags=addr.flags)
-
- self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
- drop_frag=0)
- self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
- drop_frag=0, is_ip6=1)
- self.verify_no_nat44_user()
- self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
- tcp_transitory=240, icmp=60)
- self.vapi.nat_set_addr_and_port_alloc_alg()
- self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
-
- def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
- local_port=0, external_port=0, vrf_id=0,
- is_add=1, external_sw_if_index=0xFFFFFFFF,
- proto=0, tag="", flags=0):
- """
- Add/delete NAT44 static mapping
-
- :param local_ip: Local IP address
- :param external_ip: External IP address
- :param local_port: Local port number (Optional)
- :param external_port: External port number (Optional)
- :param vrf_id: VRF ID (Default 0)
- :param is_add: 1 if add, 0 if delete (Default add)
- :param external_sw_if_index: External interface instead of IP address
- :param proto: IP protocol (Mandatory if port specified)
- :param tag: Opaque string tag
- :param flags: NAT configuration flags
- """
-
- if not (local_port and external_port):
- flags |= self.config_flags.NAT_IS_ADDR_ONLY
-
- self.vapi.nat44_add_del_static_mapping(
- is_add=is_add,
- local_ip_address=local_ip,
- external_ip_address=external_ip,
- external_sw_if_index=external_sw_if_index,
- local_port=local_port,
- external_port=external_port,
- vrf_id=vrf_id, protocol=proto,
- flags=flags,
- tag=tag)
-
- def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
- """
- Add/delete NAT44 address
-
- :param ip: IP address
- :param is_add: 1 if add, 0 if delete (Default add)
- :param twice_nat: twice NAT address for external hosts
- """
- flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
- self.vapi.nat44_add_del_address_range(first_ip_address=ip,
- last_ip_address=ip,
- vrf_id=vrf_id,
- is_add=is_add,
- flags=flags)
-
- def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
- """
- Create packet stream for inside network
-
- :param in_if: Inside interface
- :param out_if: Outside interface
- :param dst_ip: Destination address
- :param ttl: TTL of generated packets
- """
- if dst_ip is None:
- dst_ip = out_if.remote_ip4
-
- pkts = []
- # TCP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- TCP(sport=self.tcp_port_in, dport=20))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- UDP(sport=self.udp_port_in, dport=20))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- ICMP(id=self.icmp_id_in, type='echo-request'))
- pkts.append(p)
-
- return pkts
-
- def compose_ip6(self, ip4, pref, plen):
- """
- Compose IPv4-embedded IPv6 addresses
-
- :param ip4: IPv4 address
- :param pref: IPv6 prefix
- :param plen: IPv6 prefix length
- :returns: IPv4-embedded IPv6 addresses
- """
- pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
- ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
- if plen == 32:
- pref_n[4] = ip4_n[0]
- pref_n[5] = ip4_n[1]
- pref_n[6] = ip4_n[2]
- pref_n[7] = ip4_n[3]
- elif plen == 40:
- pref_n[5] = ip4_n[0]
- pref_n[6] = ip4_n[1]
- pref_n[7] = ip4_n[2]
- pref_n[9] = ip4_n[3]
- elif plen == 48:
- pref_n[6] = ip4_n[0]
- pref_n[7] = ip4_n[1]
- pref_n[9] = ip4_n[2]
- pref_n[10] = ip4_n[3]
- elif plen == 56:
- pref_n[7] = ip4_n[0]
- pref_n[9] = ip4_n[1]
- pref_n[10] = ip4_n[2]
- pref_n[11] = ip4_n[3]
- elif plen == 64:
- pref_n[9] = ip4_n[0]
- pref_n[10] = ip4_n[1]
- pref_n[11] = ip4_n[2]
- pref_n[12] = ip4_n[3]
- elif plen == 96:
- pref_n[12] = ip4_n[0]
- pref_n[13] = ip4_n[1]
- pref_n[14] = ip4_n[2]
- pref_n[15] = ip4_n[3]
- packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
- return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
-
- def extract_ip4(self, ip6, plen):
- """
- Extract IPv4 address embedded in IPv6 addresses
-
- :param ip6: IPv6 address
- :param plen: IPv6 prefix length
- :returns: extracted IPv4 address
- """
- ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
- ip4_n = [None] * 4
- if plen == 32:
- ip4_n[0] = ip6_n[4]
- ip4_n[1] = ip6_n[5]
- ip4_n[2] = ip6_n[6]
- ip4_n[3] = ip6_n[7]
- elif plen == 40:
- ip4_n[0] = ip6_n[5]
- ip4_n[1] = ip6_n[6]
- ip4_n[2] = ip6_n[7]
- ip4_n[3] = ip6_n[9]
- elif plen == 48:
- ip4_n[0] = ip6_n[6]
- ip4_n[1] = ip6_n[7]
- ip4_n[2] = ip6_n[9]
- ip4_n[3] = ip6_n[10]
- elif plen == 56:
- ip4_n[0] = ip6_n[7]
- ip4_n[1] = ip6_n[9]
- ip4_n[2] = ip6_n[10]
- ip4_n[3] = ip6_n[11]
- elif plen == 64:
- ip4_n[0] = ip6_n[9]
- ip4_n[1] = ip6_n[10]
- ip4_n[2] = ip6_n[11]
- ip4_n[3] = ip6_n[12]
- elif plen == 96:
- ip4_n[0] = ip6_n[12]
- ip4_n[1] = ip6_n[13]
- ip4_n[2] = ip6_n[14]
- ip4_n[3] = ip6_n[15]
- return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
-
- def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
- """
- Create IPv6 packet stream for inside network
-
- :param in_if: Inside interface
- :param out_if: Outside interface
- :param ttl: Hop Limit of generated packets
- :param pref: NAT64 prefix
- :param plen: NAT64 prefix length
- """
- pkts = []
- if pref is None:
- dst = ''.join(['64:ff9b::', out_if.remote_ip4])
- else:
- dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
-
- # TCP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
- TCP(sport=self.tcp_port_in, dport=20))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
- UDP(sport=self.udp_port_in, dport=20))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
- ICMPv6EchoRequest(id=self.icmp_id_in))
- pkts.append(p)
-
- return pkts
-
- def create_stream_out(self, out_if, dst_ip=None, ttl=64,
- use_inside_ports=False):
- """
- Create packet stream for outside network
-
- :param out_if: Outside interface
- :param dst_ip: Destination IP address (Default use global NAT address)
- :param ttl: TTL of generated packets
- :param use_inside_ports: Use inside NAT ports as destination ports
- instead of outside ports
- """
- if dst_ip is None:
- dst_ip = self.nat_addr
- if not use_inside_ports:
- tcp_port = self.tcp_port_out
- udp_port = self.udp_port_out
- icmp_id = self.icmp_id_out
- else:
- tcp_port = self.tcp_port_in
- udp_port = self.udp_port_in
- icmp_id = self.icmp_id_in
- pkts = []
- # TCP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- TCP(dport=tcp_port, sport=20))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- UDP(dport=udp_port, sport=20))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- ICMP(id=icmp_id, type='echo-reply'))
- pkts.append(p)
-
- return pkts
-
- def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
- """
- Create packet stream for outside network
-
- :param out_if: Outside interface
- :param dst_ip: Destination IP address (Default use global NAT address)
- :param hl: HL of generated packets
- """
- pkts = []
- # TCP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
- TCP(dport=self.tcp_port_out, sport=20))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
- UDP(dport=self.udp_port_out, sport=20))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
- ICMPv6EchoReply(id=self.icmp_id_out))
- pkts.append(p)
-
- return pkts
-
- def verify_capture_out(self, capture, nat_ip=None, same_port=False,
- dst_ip=None, is_ip6=False):
- """
- Verify captured packets on outside network
-
- :param capture: Captured packets
- :param nat_ip: Translated IP address (Default use global NAT address)
- :param same_port: Source port number is not translated (Default False)
- :param dst_ip: Destination IP address (Default do not verify)
- :param is_ip6: If L3 protocol is IPv6 (Default False)
- """
- if is_ip6:
- IP46 = IPv6
- ICMP46 = ICMPv6EchoRequest
- else:
- IP46 = IP
- ICMP46 = ICMP
- if nat_ip is None:
- nat_ip = self.nat_addr
- for packet in capture:
- try:
- if not is_ip6:
- self.assert_packet_checksums_valid(packet)
- self.assertEqual(packet[IP46].src, nat_ip)
- if dst_ip is not None:
- self.assertEqual(packet[IP46].dst, dst_ip)
- if packet.haslayer(TCP):
- if same_port:
- self.assertEqual(packet[TCP].sport, self.tcp_port_in)
- else:
- self.assertNotEqual(
- packet[TCP].sport, self.tcp_port_in)
- self.tcp_port_out = packet[TCP].sport
- self.assert_packet_checksums_valid(packet)
- elif packet.haslayer(UDP):
- if same_port:
- self.assertEqual(packet[UDP].sport, self.udp_port_in)
- else:
- self.assertNotEqual(
- packet[UDP].sport, self.udp_port_in)
- self.udp_port_out = packet[UDP].sport
- else:
- if same_port:
- self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
- else:
- self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
- self.icmp_id_out = packet[ICMP46].id
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
- dst_ip=None):
- """
- Verify captured packets on outside network
-
- :param capture: Captured packets
- :param nat_ip: Translated IP address
- :param same_port: Source port number is not translated (Default False)
- :param dst_ip: Destination IP address (Default do not verify)
- """
- return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
- True)
-
- def verify_capture_in(self, capture, in_if):
- """
- Verify captured packets on inside network
-
- :param capture: Captured packets
- :param in_if: Inside interface
- """
- for packet in capture:
- try:
- self.assert_packet_checksums_valid(packet)
- self.assertEqual(packet[IP].dst, in_if.remote_ip4)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].dport, self.tcp_port_in)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].dport, self.udp_port_in)
- else:
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(inside network):", packet))
- raise
-
- def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
- """
- Verify captured IPv6 packets on inside network
-
- :param capture: Captured packets
- :param src_ip: Source IP
- :param dst_ip: Destination IP address
- """
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, src_ip)
- self.assertEqual(packet[IPv6].dst, dst_ip)
- self.assert_packet_checksums_valid(packet)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].dport, self.tcp_port_in)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].dport, self.udp_port_in)
- else:
- self.assertEqual(packet[ICMPv6EchoReply].id,
- self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(inside network):", packet))
- raise
-
- def verify_capture_no_translation(self, capture, ingress_if, egress_if):
- """
- Verify captured packet that don't have to be translated
-
- :param capture: Captured packets
- :param ingress_if: Ingress interface
- :param egress_if: Egress interface
- """
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
- self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].sport, self.tcp_port_in)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].sport, self.udp_port_in)
- else:
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(inside network):", packet))
- raise
-
- def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
- icmp_type=11):
- """
- Verify captured packets with ICMP errors on outside network
-
- :param capture: Captured packets
- :param src_ip: Translated IP address or IP address of VPP
- (Default use global NAT address)
- :param icmp_type: Type of error ICMP packet
- we are expecting (Default 11)
- """
- if src_ip is None:
- src_ip = self.nat_addr
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, src_ip)
- self.assertEqual(packet.haslayer(ICMP), 1)
- icmp = packet[ICMP]
- self.assertEqual(icmp.type, icmp_type)
- self.assertTrue(icmp.haslayer(IPerror))
- inner_ip = icmp[IPerror]
- if inner_ip.haslayer(TCPerror):
- self.assertEqual(inner_ip[TCPerror].dport,
- self.tcp_port_out)
- elif inner_ip.haslayer(UDPerror):
- self.assertEqual(inner_ip[UDPerror].dport,
- self.udp_port_out)
- else:
- self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
- """
- Verify captured packets with ICMP errors on inside network
-
- :param capture: Captured packets
- :param in_if: Inside interface
- :param icmp_type: Type of error ICMP packet
- we are expecting (Default 11)
- """
- for packet in capture:
- try:
- self.assertEqual(packet[IP].dst, in_if.remote_ip4)
- self.assertEqual(packet.haslayer(ICMP), 1)
- icmp = packet[ICMP]
- self.assertEqual(icmp.type, icmp_type)
- self.assertTrue(icmp.haslayer(IPerror))
- inner_ip = icmp[IPerror]
- if inner_ip.haslayer(TCPerror):
- self.assertEqual(inner_ip[TCPerror].sport,
- self.tcp_port_in)
- elif inner_ip.haslayer(UDPerror):
- self.assertEqual(inner_ip[UDPerror].sport,
- self.udp_port_in)
- else:
- self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(inside network):", packet))
- raise
-
- def create_stream_frag(self, src_if, dst, sport, dport, data,
- proto=IP_PROTOS.tcp, echo_reply=False):
- """
- Create fragmented packet stream
-
- :param src_if: Source interface
- :param dst: Destination IPv4 address
- :param sport: Source port
- :param dport: Destination port
- :param data: Payload data
- :param proto: protocol (TCP, UDP, ICMP)
- :param echo_reply: use echo_reply if protocol is ICMP
- :returns: Fragments
- """
- if proto == IP_PROTOS.tcp:
- p = (IP(src=src_if.remote_ip4, dst=dst) /
- TCP(sport=sport, dport=dport) /
- Raw(data))
- p = p.__class__(scapy.compat.raw(p))
- chksum = p[TCP].chksum
- proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
- elif proto == IP_PROTOS.udp:
- proto_header = UDP(sport=sport, dport=dport)
- elif proto == IP_PROTOS.icmp:
- if not echo_reply:
- proto_header = ICMP(id=sport, type='echo-request')
- else:
- proto_header = ICMP(id=sport, type='echo-reply')
- else:
- raise Exception("Unsupported protocol")
- id = random.randint(0, 65535)
- pkts = []
- if proto == IP_PROTOS.tcp:
- raw = Raw(data[0:4])
- else:
- raw = Raw(data[0:16])
- p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
- IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
- proto_header /
- raw)
- pkts.append(p)
- if proto == IP_PROTOS.tcp:
- raw = Raw(data[4:20])
- else:
- raw = Raw(data[16:32])
- p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
- IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
- proto=proto) /
- raw)
- pkts.append(p)
- if proto == IP_PROTOS.tcp:
- raw = Raw(data[20:])
- else:
- raw = Raw(data[32:])
- p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
- IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
- id=id) /
- raw)
- pkts.append(p)
- return pkts
-
- def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
- pref=None, plen=0, frag_size=128):
- """
- Create fragmented packet stream
-
- :param src_if: Source interface
- :param dst: Destination IPv4 address
- :param sport: Source TCP port
- :param dport: Destination TCP port
- :param data: Payload data
- :param pref: NAT64 prefix
- :param plen: NAT64 prefix length
- :param fragsize: size of fragments
- :returns: Fragments
- """
- if pref is None:
- dst_ip6 = ''.join(['64:ff9b::', dst])
- else:
- dst_ip6 = self.compose_ip6(dst, pref, plen)
-
- p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
- IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
- IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
- TCP(sport=sport, dport=dport) /
- Raw(data))
-
- return fragment6(p, frag_size)
-
- def reass_frags_and_verify(self, frags, src, dst):
- """
- Reassemble and verify fragmented packet
-
- :param frags: Captured fragments
- :param src: Source IPv4 address to verify
- :param dst: Destination IPv4 address to verify
-
- :returns: Reassembled IPv4 packet
- """
- buffer = BytesIO()
- for p in frags:
- self.assertEqual(p[IP].src, src)
- self.assertEqual(p[IP].dst, dst)
- self.assert_ip_checksum_valid(p)
- buffer.seek(p[IP].frag * 8)
- buffer.write(bytes(p[IP].payload))
- ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
- proto=frags[0][IP].proto)
- if ip.proto == IP_PROTOS.tcp:
- p = (ip / TCP(buffer.getvalue()))
- self.assert_tcp_checksum_valid(p)
- elif ip.proto == IP_PROTOS.udp:
- p = (ip / UDP(buffer.getvalue()[:8]) /
- Raw(buffer.getvalue()[8:]))
- elif ip.proto == IP_PROTOS.icmp:
- p = (ip / ICMP(buffer.getvalue()))
- return p
-
- def reass_frags_and_verify_ip6(self, frags, src, dst):
- """
- Reassemble and verify fragmented packet
-
- :param frags: Captured fragments
- :param src: Source IPv6 address to verify
- :param dst: Destination IPv6 address to verify
-
- :returns: Reassembled IPv6 packet
- """
- buffer = BytesIO()
- for p in frags:
- self.assertEqual(p[IPv6].src, src)
- self.assertEqual(p[IPv6].dst, dst)
- buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
- buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
- ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
- nh=frags[0][IPv6ExtHdrFragment].nh)
- if ip.nh == IP_PROTOS.tcp:
- p = (ip / TCP(buffer.getvalue()))
- elif ip.nh == IP_PROTOS.udp:
- p = (ip / UDP(buffer.getvalue()))
- self.assert_packet_checksums_valid(p)
- return p
-
- def initiate_tcp_session(self, in_if, out_if):
- """
- Initiates TCP session
-
- :param in_if: Inside interface
- :param out_if: Outside interface
- """
- try:
- # SYN packet in->out
- p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
- IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="S"))
- in_if.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = out_if.get_capture(1)
- p = capture[0]
- self.tcp_port_out = p[TCP].sport
-
- # SYN + ACK packet out->in
- p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
- IP(src=out_if.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="SA"))
- out_if.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- in_if.get_capture(1)
-
- # ACK packet in->out
- p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
- IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A"))
- in_if.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- out_if.get_capture(1)
-
- except:
- self.logger.error("TCP 3 way handshake failed")
- raise
-
- def verify_ipfix_nat44_ses(self, data):
- """
- Verify IPFIX NAT44 session create/delete event
-
- :param data: Decoded IPFIX data records
- """
- nat44_ses_create_num = 0
- nat44_ses_delete_num = 0
- self.assertEqual(6, len(data))
- for record in data:
- # natEvent
- self.assertIn(scapy.compat.orb(record[230]), [4, 5])
- if scapy.compat.orb(record[230]) == 4:
- nat44_ses_create_num += 1
- else:
- nat44_ses_delete_num += 1
- # sourceIPv4Address
- self.assertEqual(self.pg0.remote_ip4n, record[8])
- # postNATSourceIPv4Address
- self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
- record[225])
- # ingressVRFID
- self.assertEqual(struct.pack("!I", 0), record[234])
- # protocolIdentifier/sourceTransportPort
- # /postNAPTSourceTransportPort
- if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
- self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
- self.assertEqual(struct.pack("!H", self.icmp_id_out),
- record[227])
- elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
- self.assertEqual(struct.pack("!H", self.tcp_port_in),
- record[7])
- self.assertEqual(struct.pack("!H", self.tcp_port_out),
- record[227])
- elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
- self.assertEqual(struct.pack("!H", self.udp_port_in),
- record[7])
- self.assertEqual(struct.pack("!H", self.udp_port_out),
- record[227])
- else:
- self.fail("Invalid protocol")
- self.assertEqual(3, nat44_ses_create_num)
- self.assertEqual(3, nat44_ses_delete_num)
-
- def verify_ipfix_addr_exhausted(self, data):
- """
- Verify IPFIX NAT addresses event
-
- :param data: Decoded IPFIX data records
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 3)
- # natPoolID
- self.assertEqual(struct.pack("!I", 0), record[283])
-
- def verify_ipfix_max_sessions(self, data, limit):
- """
- Verify IPFIX maximum session entries exceeded event
-
- :param data: Decoded IPFIX data records
- :param limit: Number of maximum session entries that can be created.
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 13)
- # natQuotaExceededEvent
- self.assertEqual(struct.pack("I", 1), record[466])
- # maxSessionEntries
- self.assertEqual(struct.pack("I", limit), record[471])
-
- def verify_ipfix_max_bibs(self, data, limit):
- """
- Verify IPFIX maximum BIB entries exceeded event
-
- :param data: Decoded IPFIX data records
- :param limit: Number of maximum BIB entries that can be created.
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 13)
- # natQuotaExceededEvent
- self.assertEqual(struct.pack("I", 2), record[466])
- # maxBIBEntries
- self.assertEqual(struct.pack("I", limit), record[472])
-
- def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
- """
- Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
-
- :param data: Decoded IPFIX data records
- :param limit: Number of maximum fragments pending reassembly
- :param src_addr: IPv6 source address
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 13)
- # natQuotaExceededEvent
- self.assertEqual(struct.pack("I", 5), record[466])
- # maxFragmentsPendingReassembly
- self.assertEqual(struct.pack("I", limit), record[475])
- # sourceIPv6Address
- self.assertEqual(src_addr, record[27])
-
- def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
- """
- Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
-
- :param data: Decoded IPFIX data records
- :param limit: Number of maximum fragments pending reassembly
- :param src_addr: IPv4 source address
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 13)
- # natQuotaExceededEvent
- self.assertEqual(struct.pack("I", 5), record[466])
- # maxFragmentsPendingReassembly
- self.assertEqual(struct.pack("I", limit), record[475])
- # sourceIPv4Address
- self.assertEqual(src_addr, record[8])
-
- def verify_ipfix_bib(self, data, is_create, src_addr):
- """
- Verify IPFIX NAT64 BIB create and delete events
-
- :param data: Decoded IPFIX data records
- :param is_create: Create event if nonzero value otherwise delete event
- :param src_addr: IPv6 source address
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- if is_create:
- self.assertEqual(scapy.compat.orb(record[230]), 10)
- else:
- self.assertEqual(scapy.compat.orb(record[230]), 11)
- # sourceIPv6Address
- self.assertEqual(src_addr, record[27])
- # postNATSourceIPv4Address
- self.assertEqual(self.nat_addr_n, record[225])
- # protocolIdentifier
- self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
- # ingressVRFID
- self.assertEqual(struct.pack("!I", 0), record[234])
- # sourceTransportPort
- self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
- # postNAPTSourceTransportPort
- self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
-
- def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
- dst_port):
- """
- Verify IPFIX NAT64 session create and delete events
-
- :param data: Decoded IPFIX data records
- :param is_create: Create event if nonzero value otherwise delete event
- :param src_addr: IPv6 source address
- :param dst_addr: IPv4 destination address
- :param dst_port: destination TCP port
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- if is_create:
- self.assertEqual(scapy.compat.orb(record[230]), 6)
- else:
- self.assertEqual(scapy.compat.orb(record[230]), 7)
- # sourceIPv6Address
- self.assertEqual(src_addr, record[27])
- # destinationIPv6Address
- self.assertEqual(socket.inet_pton(socket.AF_INET6,
- self.compose_ip6(dst_addr,
- '64:ff9b::',
- 96)),
- record[28])
- # postNATSourceIPv4Address
- self.assertEqual(self.nat_addr_n, record[225])
- # postNATDestinationIPv4Address
- self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
- record[226])
- # protocolIdentifier
- self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
- # ingressVRFID
- self.assertEqual(struct.pack("!I", 0), record[234])
- # sourceTransportPort
- self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
- # postNAPTSourceTransportPort
- self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
- # destinationTransportPort
- self.assertEqual(struct.pack("!H", dst_port), record[11])
- # postNAPTDestinationTransportPort
- self.assertEqual(struct.pack("!H", dst_port), record[228])
-
- def verify_no_nat44_user(self):
- """ Verify that there is no NAT44 user """
- users = self.vapi.nat44_user_dump()
- self.assertEqual(len(users), 0)
- users = self.statistics.get_counter('/nat44/total-users')
- self.assertEqual(users[0][0], 0)
- sessions = self.statistics.get_counter('/nat44/total-sessions')
- self.assertEqual(sessions[0][0], 0)
-
- def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
- """
- Verify IPFIX maximum entries per user exceeded event
-
- :param data: Decoded IPFIX data records
- :param limit: Number of maximum entries per user
- :param src_addr: IPv4 source address
- """
- self.assertEqual(1, len(data))
- record = data[0]
- # natEvent
- self.assertEqual(scapy.compat.orb(record[230]), 13)
- # natQuotaExceededEvent
- self.assertEqual(struct.pack("I", 3), record[466])
- # maxEntriesPerUser
- self.assertEqual(struct.pack("I", limit), record[473])
- # sourceIPv4Address
- self.assertEqual(src_addr, record[8])
-
- def verify_syslog_apmap(self, data, is_add=True):
- message = data.decode('utf-8')
- try:
- message = SyslogMessage.parse(message)
- except ParseError as e:
- self.logger.error(e)
- raise
- else:
- self.assertEqual(message.severity, SyslogSeverity.info)
- self.assertEqual(message.appname, 'NAT')
- self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
- sd_params = message.sd.get('napmap')
- self.assertTrue(sd_params is not None)
- self.assertEqual(sd_params.get('IATYP'), 'IPv4')
- self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
- self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
- self.assertEqual(sd_params.get('XATYP'), 'IPv4')
- self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
- self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
- self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
- self.assertTrue(sd_params.get('SSUBIX') is not None)
- self.assertEqual(sd_params.get('SVLAN'), '0')
-
- def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
- message = data.decode('utf-8')
- try:
- message = SyslogMessage.parse(message)
- except ParseError as e:
- self.logger.error(e)
- raise
- else:
- self.assertEqual(message.severity, SyslogSeverity.info)
- self.assertEqual(message.appname, 'NAT')
- self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
- sd_params = message.sd.get('nsess')
- self.assertTrue(sd_params is not None)
- if is_ip6:
- self.assertEqual(sd_params.get('IATYP'), 'IPv6')
- self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
- else:
- self.assertEqual(sd_params.get('IATYP'), 'IPv4')
- self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
- self.assertTrue(sd_params.get('SSUBIX') is not None)
- self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
- self.assertEqual(sd_params.get('XATYP'), 'IPv4')
- self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
- self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
- self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
- self.assertEqual(sd_params.get('SVLAN'), '0')
- self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
- self.assertEqual(sd_params.get('XDPORT'),
- "%d" % self.tcp_external_port)
-
- def verify_mss_value(self, pkt, mss):
- """
- Verify TCP MSS value
-
- :param pkt:
- :param mss:
- """
- if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
- raise TypeError("Not a TCP/IP packet")
-
- for option in pkt[TCP].options:
- if option[0] == 'MSS':
- self.assertEqual(option[1], mss)
- self.assert_tcp_checksum_valid(pkt)
-
- @staticmethod
- def proto2layer(proto):
- if proto == IP_PROTOS.tcp:
- return TCP
- elif proto == IP_PROTOS.udp:
- return UDP
- elif proto == IP_PROTOS.icmp:
- return ICMP
- else:
- raise Exception("Unsupported protocol")
-
- def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
- layer = self.proto2layer(proto)
-
- if proto == IP_PROTOS.tcp:
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- else:
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
- self.port_in = random.randint(1025, 65535)
-
- reass = self.vapi.nat_reass_dump()
- reass_n_start = len(reass)
-
- # in2out
- pkts = self.create_stream_frag(self.pg0,
- self.pg1.remote_ip4,
- self.port_in,
- 20,
- data,
- proto)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- if not dont_translate:
- p = self.reass_frags_and_verify(frags,
- self.nat_addr,
- self.pg1.remote_ip4)
- else:
- p = self.reass_frags_and_verify(frags,
- self.pg0.remote_ip4,
- self.pg1.remote_ip4)
- if proto != IP_PROTOS.icmp:
- if not dont_translate:
- self.assertEqual(p[layer].dport, 20)
- self.assertNotEqual(p[layer].sport, self.port_in)
- else:
- self.assertEqual(p[layer].sport, self.port_in)
- else:
- if not dont_translate:
- self.assertNotEqual(p[layer].id, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- # out2in
- if not dont_translate:
- dst_addr = self.nat_addr
- else:
- dst_addr = self.pg0.remote_ip4
- if proto != IP_PROTOS.icmp:
- sport = 20
- dport = p[layer].sport
- else:
- sport = p[layer].id
- dport = 0
- pkts = self.create_stream_frag(self.pg1,
- dst_addr,
- sport,
- dport,
- data,
- proto,
- echo_reply=True)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.pg1.remote_ip4,
- self.pg0.remote_ip4)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].sport, 20)
- self.assertEqual(p[layer].dport, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- reass = self.vapi.nat_reass_dump()
- reass_n_end = len(reass)
-
- self.assertEqual(reass_n_end - reass_n_start, 2)
-
- def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
- layer = self.proto2layer(proto)
-
- if proto == IP_PROTOS.tcp:
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- else:
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
- self.port_in = random.randint(1025, 65535)
-
- for i in range(2):
- reass = self.vapi.nat_reass_dump()
- reass_n_start = len(reass)
-
- # out2in
- pkts = self.create_stream_frag(self.pg0,
- self.server_out_addr,
- self.port_in,
- self.server_out_port,
- data,
- proto)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.pg0.remote_ip4,
- self.server_in_addr)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].sport, self.port_in)
- self.assertEqual(p[layer].dport, self.server_in_port)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- # in2out
- if proto != IP_PROTOS.icmp:
- pkts = self.create_stream_frag(self.pg1,
- self.pg0.remote_ip4,
- self.server_in_port,
- p[layer].sport,
- data,
- proto)
- else:
- pkts = self.create_stream_frag(self.pg1,
- self.pg0.remote_ip4,
- p[layer].id,
- 0,
- data,
- proto,
- echo_reply=True)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.server_out_addr,
- self.pg0.remote_ip4)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].sport, self.server_out_port)
- self.assertEqual(p[layer].dport, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- reass = self.vapi.nat_reass_dump()
- reass_n_end = len(reass)
-
- self.assertEqual(reass_n_end - reass_n_start, 2)
-
- def reass_hairpinning(self, proto=IP_PROTOS.tcp):
- layer = self.proto2layer(proto)
-
- if proto == IP_PROTOS.tcp:
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- else:
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
-
- # send packet from host to server
- pkts = self.create_stream_frag(self.pg0,
- self.nat_addr,
- self.host_in_port,
- self.server_out_port,
- data,
- proto)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.nat_addr,
- self.server.ip4)
- if proto != IP_PROTOS.icmp:
- self.assertNotEqual(p[layer].sport, self.host_in_port)
- self.assertEqual(p[layer].dport, self.server_in_port)
- else:
- self.assertNotEqual(p[layer].id, self.host_in_port)
- self.assertEqual(data, p[Raw].load)
-
- def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
- layer = self.proto2layer(proto)
-
- if proto == IP_PROTOS.tcp:
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- else:
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
- self.port_in = random.randint(1025, 65535)
-
- for i in range(2):
- # in2out
- pkts = self.create_stream_frag(self.pg0,
- self.pg1.remote_ip4,
- self.port_in,
- 20,
- data,
- proto)
- pkts.reverse()
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- if not dont_translate:
- p = self.reass_frags_and_verify(frags,
- self.nat_addr,
- self.pg1.remote_ip4)
- else:
- p = self.reass_frags_and_verify(frags,
- self.pg0.remote_ip4,
- self.pg1.remote_ip4)
- if proto != IP_PROTOS.icmp:
- if not dont_translate:
- self.assertEqual(p[layer].dport, 20)
- self.assertNotEqual(p[layer].sport, self.port_in)
- else:
- self.assertEqual(p[layer].sport, self.port_in)
- else:
- if not dont_translate:
- self.assertNotEqual(p[layer].id, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- # out2in
- if not dont_translate:
- dst_addr = self.nat_addr
- else:
- dst_addr = self.pg0.remote_ip4
- if proto != IP_PROTOS.icmp:
- sport = 20
- dport = p[layer].sport
- else:
- sport = p[layer].id
- dport = 0
- pkts = self.create_stream_frag(self.pg1,
- dst_addr,
- sport,
- dport,
- data,
- proto,
- echo_reply=True)
- pkts.reverse()
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.pg1.remote_ip4,
- self.pg0.remote_ip4)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].sport, 20)
- self.assertEqual(p[layer].dport, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
- layer = self.proto2layer(proto)
-
- if proto == IP_PROTOS.tcp:
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- else:
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
- self.port_in = random.randint(1025, 65535)
-
- for i in range(2):
- # out2in
- pkts = self.create_stream_frag(self.pg0,
- self.server_out_addr,
- self.port_in,
- self.server_out_port,
- data,
- proto)
- pkts.reverse()
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.pg0.remote_ip4,
- self.server_in_addr)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].dport, self.server_in_port)
- self.assertEqual(p[layer].sport, self.port_in)
- self.assertEqual(p[layer].dport, self.server_in_port)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
- # in2out
- if proto != IP_PROTOS.icmp:
- pkts = self.create_stream_frag(self.pg1,
- self.pg0.remote_ip4,
- self.server_in_port,
- p[layer].sport,
- data,
- proto)
- else:
- pkts = self.create_stream_frag(self.pg1,
- self.pg0.remote_ip4,
- p[layer].id,
- 0,
- data,
- proto,
- echo_reply=True)
- pkts.reverse()
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.server_out_addr,
- self.pg0.remote_ip4)
- if proto != IP_PROTOS.icmp:
- self.assertEqual(p[layer].sport, self.server_out_port)
- self.assertEqual(p[layer].dport, self.port_in)
- else:
- self.assertEqual(p[layer].id, self.port_in)
- self.assertEqual(data, p[Raw].load)
-
-
-class TestNAT44(MethodHolder):
- """ NAT44 Test Cases """
-
- @classmethod
- def setUpClass(cls):
- super(TestNAT44, cls).setUpClass()
- cls.vapi.cli("set log class nat level debug")
-
- try:
- cls.tcp_port_in = 6303
- cls.tcp_port_out = 6303
- cls.udp_port_in = 6304
- cls.udp_port_out = 6304
- cls.icmp_id_in = 6305
- cls.icmp_id_out = 6305
- cls.nat_addr = '10.0.0.3'
- cls.ipfix_src_port = 4739
- cls.ipfix_domain_id = 1
- cls.tcp_external_port = 80
- cls.udp_external_port = 69
-
- cls.create_pg_interfaces(range(10))
- cls.interfaces = list(cls.pg_interfaces[0:4])
-
- for i in cls.interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
-
- cls.pg0.generate_remote_hosts(3)
- cls.pg0.configure_ipv4_neighbors()
-
- cls.pg1.generate_remote_hosts(1)
- cls.pg1.configure_ipv4_neighbors()
-
- cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
- cls.vapi.ip_table_add_del(is_add=1, table_id=10)
- cls.vapi.ip_table_add_del(is_add=1, table_id=20)
-
- cls.pg4._local_ip4 = "172.16.255.1"
- cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
- cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
- cls.pg4.set_table_ip4(10)
- cls.pg5._local_ip4 = "172.17.255.3"
- cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
- cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
- cls.pg5.set_table_ip4(10)
- cls.pg6._local_ip4 = "172.16.255.1"
- cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
- cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
- cls.pg6.set_table_ip4(20)
- for i in cls.overlapping_interfaces:
- i.config_ip4()
- i.admin_up()
- i.resolve_arp()
-
- cls.pg7.admin_up()
- cls.pg8.admin_up()
-
- cls.pg9.generate_remote_hosts(2)
- cls.pg9.config_ip4()
- ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
- cls.vapi.sw_interface_add_del_address(
- sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
- address_length=24)
- cls.pg9.admin_up()
- cls.pg9.resolve_arp()
- cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
- cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
- cls.pg9.resolve_arp()
-
- except Exception:
- super(TestNAT44, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestNAT44, cls).tearDownClass()
-
- def test_dynamic(self):
- """ NAT44 dynamic translation test """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # in2out
- tcpn = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/TCP packets')
- udpn = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/good in2out packets processed')
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- err = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-in2out-slowpath/good in2out packets processed')
- self.assertEqual(err - totaln, 3)
-
- # out2in
- tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
- udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat44-out2in/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat44-out2in/good out2in packets processed')
-
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-out2in/good out2in packets processed')
- self.assertEqual(err - totaln, 3)
-
- users = self.statistics.get_counter('/nat44/total-users')
- self.assertEqual(users[0][0], 1)
- sessions = self.statistics.get_counter('/nat44/total-sessions')
- self.assertEqual(sessions[0][0], 3)
-
- def test_dynamic_icmp_errors_in2out_ttl_1(self):
- """ NAT44 handling of client packets with TTL=1 """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # Client side - generate traffic
- pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Client side - verify ICMP type 11 packets
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in_with_icmp_errors(capture, self.pg0)
-
- def test_dynamic_icmp_errors_out2in_ttl_1(self):
- """ NAT44 handling of server packets with TTL=1 """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # Client side - create sessions
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Server side - generate traffic
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
- pkts = self.create_stream_out(self.pg1, ttl=1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Server side - verify ICMP type 11 packets
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out_with_icmp_errors(capture,
- src_ip=self.pg1.local_ip4)
-
- def test_dynamic_icmp_errors_in2out_ttl_2(self):
- """ NAT44 handling of error responses to client packets with TTL=2 """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # Client side - generate traffic
- pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Server side - simulate ICMP type 11 response
- capture = self.pg1.get_capture(len(pkts))
- pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- ICMP(type=11) / packet[IP] for packet in capture]
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Client side - verify ICMP type 11 packets
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in_with_icmp_errors(capture, self.pg0)
-
- def test_dynamic_icmp_errors_out2in_ttl_2(self):
- """ NAT44 handling of error responses to server packets with TTL=2 """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # Client side - create sessions
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Server side - generate traffic
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
- pkts = self.create_stream_out(self.pg1, ttl=2)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Client side - simulate ICMP type 11 response
- capture = self.pg0.get_capture(len(pkts))
- pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- ICMP(type=11) / packet[IP] for packet in capture]
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Server side - verify ICMP type 11 packets
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out_with_icmp_errors(capture)
-
- def test_ping_out_interface_from_outside(self):
- """ Ping NAT44 out interface from outside network """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
- ICMP(id=self.icmp_id_out, type='echo-request'))
- pkts = [p]
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- packet = capture[0]
- try:
- self.assertEqual(packet[IP].src, self.pg1.local_ip4)
- self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- self.assertEqual(packet[ICMP].type, 0) # echo reply
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- def test_ping_internal_host_from_outside(self):
- """ Ping internal host from outside network """
-
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # out2in
- pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
- ICMP(id=self.icmp_id_out, type='echo-request'))
- self.pg1.add_stream(pkt)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- self.verify_capture_in(capture, self.pg0)
- self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
-
- # in2out
- pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
- ICMP(id=self.icmp_id_in, type='echo-reply'))
- self.pg0.add_stream(pkt)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- self.verify_capture_out(capture, same_port=True)
- self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
-
- def test_forwarding(self):
- """ NAT44 forwarding test """
-
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_forwarding_enable_disable(enable=1)
-
- real_ip = self.pg0.remote_ip4n
- alias_ip = self.nat_addr
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(is_add=1,
- local_ip_address=real_ip,
- external_ip_address=alias_ip,
- external_sw_if_index=0xFFFFFFFF,
- flags=flags)
-
- try:
- # static mapping match
-
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, same_port=True)
-
- # no static mapping match
-
- host0 = self.pg0.remote_hosts[0]
- self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
- try:
- pkts = self.create_stream_out(self.pg1,
- dst_ip=self.pg0.remote_ip4,
- use_inside_ports=True)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
- same_port=True)
- finally:
- self.pg0.remote_hosts[0] = host0
-
- finally:
- self.vapi.nat44_forwarding_enable_disable(enable=0)
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(
- is_add=0,
- local_ip_address=real_ip,
- external_ip_address=alias_ip,
- external_sw_if_index=0xFFFFFFFF,
- flags=flags)
-
- def test_static_in(self):
- """ 1:1 NAT initialized from inside network """
-
- nat_ip = "10.0.0.10"
- self.tcp_port_out = 6303
- self.udp_port_out = 6304
- self.icmp_id_out = 6305
-
- self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- sm = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(len(sm), 1)
- self.assertEqual((sm[0].tag).split(b'\0', 1)[0], b'')
- self.assertEqual(sm[0].protocol, 0)
- self.assertEqual(sm[0].local_port, 0)
- self.assertEqual(sm[0].external_port, 0)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip, True)
-
- # out2in
- pkts = self.create_stream_out(self.pg1, nat_ip)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- def test_static_out(self):
- """ 1:1 NAT initialized from outside network """
-
- nat_ip = "10.0.0.20"
- self.tcp_port_out = 6303
- self.udp_port_out = 6304
- self.icmp_id_out = 6305
- tag = b"testTAG"
-
- self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- sm = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(len(sm), 1)
- self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
-
- # out2in
- pkts = self.create_stream_out(self.pg1, nat_ip)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip, True)
-
- def test_static_with_port_in(self):
- """ 1:1 NAPT initialized from inside network """
-
- self.tcp_port_out = 3606
- self.udp_port_out = 3607
- self.icmp_id_out = 3608
-
- self.nat44_add_address(self.nat_addr)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.tcp_port_in, self.tcp_port_out,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.udp_port_in, self.udp_port_out,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.icmp_id_in, self.icmp_id_out,
- proto=IP_PROTOS.icmp)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- def test_static_with_port_out(self):
- """ 1:1 NAPT initialized from outside network """
-
- self.tcp_port_out = 30606
- self.udp_port_out = 30607
- self.icmp_id_out = 30608
-
- self.nat44_add_address(self.nat_addr)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.tcp_port_in, self.tcp_port_out,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.udp_port_in, self.udp_port_out,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- self.icmp_id_in, self.icmp_id_out,
- proto=IP_PROTOS.icmp)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # out2in
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- def test_static_vrf_aware(self):
- """ 1:1 NAT VRF awareness """
-
- nat_ip1 = "10.0.0.30"
- nat_ip2 = "10.0.0.40"
- self.tcp_port_out = 6303
- self.udp_port_out = 6304
- self.icmp_id_out = 6305
-
- self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
- vrf_id=10)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
- vrf_id=10)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg3.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg4.sw_if_index,
- flags=flags, is_add=1)
-
- # inside interface VRF match NAT44 static mapping VRF
- pkts = self.create_stream_in(self.pg4, self.pg3)
- self.pg4.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip1, True)
-
- # inside interface VRF don't match NAT44 static mapping VRF (packets
- # are dropped)
- pkts = self.create_stream_in(self.pg0, self.pg3)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg3.assert_nothing_captured()
-
- def test_dynamic_to_static(self):
- """ Switch from dynamic translation to 1:1NAT """
- nat_ip = "10.0.0.10"
- self.tcp_port_out = 6303
- self.udp_port_out = 6304
- self.icmp_id_out = 6305
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # dynamic
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # 1:1NAT
- self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- self.assertEqual(len(sessions), 0)
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip, True)
-
- def test_identity_nat(self):
- """ Identity NAT """
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_identity_mapping(
- ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
- flags=flags, is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
- TCP(sport=12345, dport=56789))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(ip.src, self.pg1.remote_ip4)
- self.assertEqual(tcp.dport, 56789)
- self.assertEqual(tcp.sport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- self.assertEqual(len(sessions), 0)
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_identity_mapping(
- ip_address=self.pg0.remote_ip4n, sw_if_index=0xFFFFFFFF,
- flags=flags, vrf_id=1, is_add=1)
- identity_mappings = self.vapi.nat44_identity_mapping_dump()
- self.assertEqual(len(identity_mappings), 2)
-
- def test_multiple_inside_interfaces(self):
- """ NAT44 multiple non-overlapping address space inside interfaces """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg3.sw_if_index,
- is_add=1)
-
- # between two NAT44 inside interfaces (no translation)
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_no_translation(capture, self.pg0, self.pg1)
-
- # from NAT44 inside to interface without NAT44 feature (no translation)
- pkts = self.create_stream_in(self.pg0, self.pg2)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_no_translation(capture, self.pg0, self.pg2)
-
- # in2out 1st interface
- pkts = self.create_stream_in(self.pg0, self.pg3)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in 1st interface
- pkts = self.create_stream_out(self.pg3)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # in2out 2nd interface
- pkts = self.create_stream_in(self.pg1, self.pg3)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in 2nd interface
- pkts = self.create_stream_out(self.pg3)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg1)
-
- def test_inside_overlapping_interfaces(self):
- """ NAT44 multiple inside interfaces with overlapping address space """
-
- static_nat_ip = "10.0.0.10"
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg3.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg4.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg5.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg6.sw_if_index,
- flags=flags, is_add=1)
- self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
- vrf_id=20)
-
- # between NAT44 inside interfaces with same VRF (no translation)
- pkts = self.create_stream_in(self.pg4, self.pg5)
- self.pg4.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(len(pkts))
- self.verify_capture_no_translation(capture, self.pg4, self.pg5)
-
- # between NAT44 inside interfaces with different VRF (hairpinning)
- p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
- IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
- TCP(sport=1234, dport=5678))
- self.pg4.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, self.pg6.remote_ip4)
- self.assertNotEqual(tcp.sport, 1234)
- self.assertEqual(tcp.dport, 5678)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # in2out 1st interface
- pkts = self.create_stream_in(self.pg4, self.pg3)
- self.pg4.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in 1st interface
- pkts = self.create_stream_out(self.pg3)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg4.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg4)
-
- # in2out 2nd interface
- pkts = self.create_stream_in(self.pg5, self.pg3)
- self.pg5.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in 2nd interface
- pkts = self.create_stream_out(self.pg3)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg5)
-
- # pg5 session dump
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(len(addresses), 1)
- sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
- self.assertEqual(len(sessions), 3)
- for session in sessions:
- self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
- self.assertEqual(str(session.inside_ip_address),
- self.pg5.remote_ip4)
- self.assertEqual(session.outside_ip_address,
- addresses[0].ip_address)
- self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
- self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
- self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
- self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
- self.assertEqual(sessions[1].inside_port, self.udp_port_in)
- self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
- self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
- self.assertEqual(sessions[1].outside_port, self.udp_port_out)
- self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
-
- # in2out 3rd interface
- pkts = self.create_stream_in(self.pg6, self.pg3)
- self.pg6.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture, static_nat_ip, True)
-
- # out2in 3rd interface
- pkts = self.create_stream_out(self.pg3, static_nat_ip)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg6)
-
- # general user and session dump verifications
- users = self.vapi.nat44_user_dump()
- self.assertGreaterEqual(len(users), 3)
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(len(addresses), 1)
- for user in users:
- sessions = self.vapi.nat44_user_session_dump(user.ip_address,
- user.vrf_id)
- for session in sessions:
- self.assertEqual(user.ip_address, session.inside_ip_address)
- self.assertTrue(session.total_bytes > session.total_pkts > 0)
- self.assertTrue(session.protocol in
- [IP_PROTOS.tcp, IP_PROTOS.udp,
- IP_PROTOS.icmp])
- self.assertFalse(session.flags &
- self.config_flags.NAT_IS_EXT_HOST_VALID)
-
- # pg4 session dump
- sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
- self.assertGreaterEqual(len(sessions), 4)
- for session in sessions:
- self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
- self.assertEqual(str(session.inside_ip_address),
- self.pg4.remote_ip4)
- self.assertEqual(session.outside_ip_address,
- addresses[0].ip_address)
-
- # pg6 session dump
- sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
- self.assertGreaterEqual(len(sessions), 3)
- for session in sessions:
- self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
- self.assertEqual(str(session.inside_ip_address),
- self.pg6.remote_ip4)
- self.assertEqual(str(session.outside_ip_address),
- static_nat_ip)
- self.assertTrue(session.inside_port in
- [self.tcp_port_in, self.udp_port_in,
- self.icmp_id_in])
-
- def test_hairpinning(self):
- """ NAT44 hairpinning - 1:1 NAPT """
-
- host = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
- host_in_port = 1234
- host_out_port = 0
- server_in_port = 5678
- server_out_port = 8765
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # add static mapping for server
- self.nat44_add_static_mapping(server.ip4, self.nat_addr,
- server_in_port, server_out_port,
- proto=IP_PROTOS.tcp)
-
- # send packet from host to server
- p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
- IP(src=host.ip4, dst=self.nat_addr) /
- TCP(sport=host_in_port, dport=server_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, server.ip4)
- self.assertNotEqual(tcp.sport, host_in_port)
- self.assertEqual(tcp.dport, server_in_port)
- self.assert_packet_checksums_valid(p)
- host_out_port = tcp.sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # send reply from server to host
- p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
- IP(src=server.ip4, dst=self.nat_addr) /
- TCP(sport=server_in_port, dport=host_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, host.ip4)
- self.assertEqual(tcp.sport, server_out_port)
- self.assertEqual(tcp.dport, host_in_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_hairpinning2(self):
- """ NAT44 hairpinning - 1:1 NAT"""
-
- server1_nat_ip = "10.0.0.10"
- server2_nat_ip = "10.0.0.11"
- host = self.pg0.remote_hosts[0]
- server1 = self.pg0.remote_hosts[1]
- server2 = self.pg0.remote_hosts[2]
- server_tcp_port = 22
- server_udp_port = 20
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # add static mapping for servers
- self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
- self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
-
- # host to server1
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=host.ip4, dst=server1_nat_ip) /
- TCP(sport=self.tcp_port_in, dport=server_tcp_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=host.ip4, dst=server1_nat_ip) /
- UDP(sport=self.udp_port_in, dport=server_udp_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=host.ip4, dst=server1_nat_ip) /
- ICMP(id=self.icmp_id_in, type='echo-request'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, self.nat_addr)
- self.assertEqual(packet[IP].dst, server1.ip4)
- if packet.haslayer(TCP):
- self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
- self.assertEqual(packet[TCP].dport, server_tcp_port)
- self.tcp_port_out = packet[TCP].sport
- self.assert_packet_checksums_valid(packet)
- elif packet.haslayer(UDP):
- self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
- self.assertEqual(packet[UDP].dport, server_udp_port)
- self.udp_port_out = packet[UDP].sport
- else:
- self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
- self.icmp_id_out = packet[ICMP].id
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server1 to host
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=self.nat_addr) /
- TCP(sport=server_tcp_port, dport=self.tcp_port_out))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=self.nat_addr) /
- UDP(sport=server_udp_port, dport=self.udp_port_out))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=self.nat_addr) /
- ICMP(id=self.icmp_id_out, type='echo-reply'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, server1_nat_ip)
- self.assertEqual(packet[IP].dst, host.ip4)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].dport, self.tcp_port_in)
- self.assertEqual(packet[TCP].sport, server_tcp_port)
- self.assert_packet_checksums_valid(packet)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].dport, self.udp_port_in)
- self.assertEqual(packet[UDP].sport, server_udp_port)
- else:
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server2 to server1
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server2.ip4, dst=server1_nat_ip) /
- TCP(sport=self.tcp_port_in, dport=server_tcp_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server2.ip4, dst=server1_nat_ip) /
- UDP(sport=self.udp_port_in, dport=server_udp_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server2.ip4, dst=server1_nat_ip) /
- ICMP(id=self.icmp_id_in, type='echo-request'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, server2_nat_ip)
- self.assertEqual(packet[IP].dst, server1.ip4)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].sport, self.tcp_port_in)
- self.assertEqual(packet[TCP].dport, server_tcp_port)
- self.tcp_port_out = packet[TCP].sport
- self.assert_packet_checksums_valid(packet)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].sport, self.udp_port_in)
- self.assertEqual(packet[UDP].dport, server_udp_port)
- self.udp_port_out = packet[UDP].sport
- else:
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- self.icmp_id_out = packet[ICMP].id
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server1 to server2
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=server2_nat_ip) /
- TCP(sport=server_tcp_port, dport=self.tcp_port_out))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=server2_nat_ip) /
- UDP(sport=server_udp_port, dport=self.udp_port_out))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=server1.ip4, dst=server2_nat_ip) /
- ICMP(id=self.icmp_id_out, type='echo-reply'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, server1_nat_ip)
- self.assertEqual(packet[IP].dst, server2.ip4)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].dport, self.tcp_port_in)
- self.assertEqual(packet[TCP].sport, server_tcp_port)
- self.assert_packet_checksums_valid(packet)
- elif packet.haslayer(UDP):
- self.assertEqual(packet[UDP].dport, self.udp_port_in)
- self.assertEqual(packet[UDP].sport, server_udp_port)
- else:
- self.assertEqual(packet[ICMP].id, self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_max_translations_per_user(self):
- """ MAX translations per user - recycle the least recently used """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # get maximum number of translations per user
- nat44_config = self.vapi.nat_show_config()
-
- # send more than maximum number of translations per user packets
- pkts_num = nat44_config.max_translations_per_user + 5
- pkts = []
- for port in range(0, pkts_num):
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=1025 + port))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # verify number of translated packet
- self.pg1.get_capture(pkts_num)
-
- users = self.vapi.nat44_user_dump()
- for user in users:
- if user.ip_address == self.pg0.remote_ip4n:
- self.assertEqual(user.nsessions,
- nat44_config.max_translations_per_user)
- self.assertEqual(user.nstaticsessions, 0)
-
- tcp_port = 22
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- tcp_port, tcp_port,
- proto=IP_PROTOS.tcp)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=tcp_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
- users = self.vapi.nat44_user_dump()
- for user in users:
- if user.ip_address == self.pg0.remote_ip4n:
- self.assertEqual(user.nsessions,
- nat44_config.max_translations_per_user - 1)
- self.assertEqual(user.nstaticsessions, 1)
-
- def test_interface_addr(self):
- """ Acquire NAT44 addresses from interface """
- self.vapi.nat44_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg7.sw_if_index)
-
- # no address in NAT pool
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(0, len(addresses))
-
- # configure interface address and check NAT address pool
- self.pg7.config_ip4()
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(1, len(addresses))
- self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
-
- # remove interface address and check NAT address pool
- self.pg7.unconfig_ip4()
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(0, len(addresses))
-
- def test_interface_addr_static_mapping(self):
- """ Static mapping with addresses from interface """
- tag = b"testTAG"
-
- self.vapi.nat44_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg7.sw_if_index)
- self.nat44_add_static_mapping(
- '1.2.3.4',
- external_sw_if_index=self.pg7.sw_if_index,
- tag=tag)
-
- # static mappings with external interface
- static_mappings = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(1, len(static_mappings))
- self.assertEqual(self.pg7.sw_if_index,
- static_mappings[0].external_sw_if_index)
- self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
-
- # configure interface address and check static mappings
- self.pg7.config_ip4()
- static_mappings = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(2, len(static_mappings))
- resolved = False
- for sm in static_mappings:
- if sm.external_sw_if_index == 0xFFFFFFFF:
- self.assertEqual(str(sm.external_ip_address),
- self.pg7.local_ip4)
- self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
- resolved = True
- self.assertTrue(resolved)
-
- # remove interface address and check static mappings
- self.pg7.unconfig_ip4()
- static_mappings = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(1, len(static_mappings))
- self.assertEqual(self.pg7.sw_if_index,
- static_mappings[0].external_sw_if_index)
- self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
-
- # configure interface address again and check static mappings
- self.pg7.config_ip4()
- static_mappings = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(2, len(static_mappings))
- resolved = False
- for sm in static_mappings:
- if sm.external_sw_if_index == 0xFFFFFFFF:
- self.assertEqual(str(sm.external_ip_address),
- self.pg7.local_ip4)
- self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
- resolved = True
- self.assertTrue(resolved)
-
- # remove static mapping
- self.nat44_add_static_mapping(
- '1.2.3.4',
- external_sw_if_index=self.pg7.sw_if_index,
- tag=tag,
- is_add=0)
- static_mappings = self.vapi.nat44_static_mapping_dump()
- self.assertEqual(0, len(static_mappings))
-
- def test_interface_addr_identity_nat(self):
- """ Identity NAT with addresses from interface """
-
- port = 53053
- self.vapi.nat44_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg7.sw_if_index)
- self.vapi.nat44_add_del_identity_mapping(
- ip_address=b'0',
- sw_if_index=self.pg7.sw_if_index,
- port=port,
- protocol=IP_PROTOS.tcp,
- is_add=1)
-
- # identity mappings with external interface
- identity_mappings = self.vapi.nat44_identity_mapping_dump()
- self.assertEqual(1, len(identity_mappings))
- self.assertEqual(self.pg7.sw_if_index,
- identity_mappings[0].sw_if_index)
-
- # configure interface address and check identity mappings
- self.pg7.config_ip4()
- identity_mappings = self.vapi.nat44_identity_mapping_dump()
- resolved = False
- self.assertEqual(2, len(identity_mappings))
- for sm in identity_mappings:
- if sm.sw_if_index == 0xFFFFFFFF:
- self.assertEqual(str(identity_mappings[0].ip_address),
- self.pg7.local_ip4)
- self.assertEqual(port, identity_mappings[0].port)
- self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
- resolved = True
- self.assertTrue(resolved)
-
- # remove interface address and check identity mappings
- self.pg7.unconfig_ip4()
- identity_mappings = self.vapi.nat44_identity_mapping_dump()
- self.assertEqual(1, len(identity_mappings))
- self.assertEqual(self.pg7.sw_if_index,
- identity_mappings[0].sw_if_index)
-
- def test_ipfix_nat44_sess(self):
- """ IPFIX logging NAT44 session created/deleted """
- self.ipfix_domain_id = 10
- self.ipfix_src_port = 20202
- collector_port = 30303
- bind_layers(UDP, IPFIX, dport=30303)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10,
- collector_port=collector_port)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
- self.nat44_add_address(self.nat_addr, is_add=0)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, collector_port)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_nat44_ses(data)
-
- def test_ipfix_addr_exhausted(self):
- """ IPFIX logging NAT addresses exhausted """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=3025))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_addr_exhausted(data)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_ipfix_max_sessions(self):
- """ IPFIX logging maximum session entries exceeded """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- nat44_config = self.vapi.nat_show_config()
- max_sessions = 10 * nat44_config.translation_buckets
-
- pkts = []
- for i in range(0, max_sessions):
- src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=src, dst=self.pg1.remote_ip4) /
- TCP(sport=1025))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- self.pg1.get_capture(max_sessions)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=1025))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_sessions(data, max_sessions)
-
- def test_syslog_apmap(self):
- """ Test syslog address and port mapping creation and deletion """
- self.vapi.syslog_set_filter(
- self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
- self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=20))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- self.tcp_port_out = capture[0][TCP].sport
- capture = self.pg3.get_capture(1)
- self.verify_syslog_apmap(capture[0][Raw].load)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.nat44_add_address(self.nat_addr, is_add=0)
- capture = self.pg3.get_capture(1)
- self.verify_syslog_apmap(capture[0][Raw].load, False)
-
- def test_pool_addr_fib(self):
- """ NAT44 add pool addresses to FIB """
- static_addr = '10.0.0.10'
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
-
- # NAT44 address
- p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
- ARP(op=ARP.who_has, pdst=self.nat_addr,
- psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- self.assertTrue(capture[0].haslayer(ARP))
- self.assertTrue(capture[0][ARP].op, ARP.is_at)
-
- # 1:1 NAT address
- p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
- ARP(op=ARP.who_has, pdst=static_addr,
- psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- self.assertTrue(capture[0].haslayer(ARP))
- self.assertTrue(capture[0][ARP].op, ARP.is_at)
-
- # send ARP to non-NAT44 interface
- p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
- ARP(op=ARP.who_has, pdst=self.nat_addr,
- psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
- self.pg2.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
-
- # remove addresses and verify
- self.nat44_add_address(self.nat_addr, is_add=0)
- self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
- is_add=0)
-
- p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
- ARP(op=ARP.who_has, pdst=self.nat_addr,
- psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
-
- p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
- ARP(op=ARP.who_has, pdst=static_addr,
- psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
-
- def test_vrf_mode(self):
- """ NAT44 tenant VRF aware address pool mode """
-
- vrf_id1 = 1
- vrf_id2 = 2
- nat_ip1 = "10.0.0.10"
- nat_ip2 = "10.0.0.11"
-
- self.pg0.unconfig_ip4()
- self.pg1.unconfig_ip4()
- self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
- self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
- self.pg0.set_table_ip4(vrf_id1)
- self.pg1.set_table_ip4(vrf_id2)
- self.pg0.config_ip4()
- self.pg1.config_ip4()
- self.pg0.resolve_arp()
- self.pg1.resolve_arp()
-
- self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
- self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg2.sw_if_index,
- is_add=1)
-
- try:
- # first VRF
- pkts = self.create_stream_in(self.pg0, self.pg2)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip1)
-
- # second VRF
- pkts = self.create_stream_in(self.pg1, self.pg2)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip2)
-
- finally:
- self.pg0.unconfig_ip4()
- self.pg1.unconfig_ip4()
- self.pg0.set_table_ip4(0)
- self.pg1.set_table_ip4(0)
- self.pg0.config_ip4()
- self.pg1.config_ip4()
- self.pg0.resolve_arp()
- self.pg1.resolve_arp()
- self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
- self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
-
- def test_vrf_feature_independent(self):
- """ NAT44 tenant VRF independent address pool mode """
-
- nat_ip1 = "10.0.0.10"
- nat_ip2 = "10.0.0.11"
-
- self.nat44_add_address(nat_ip1)
- self.nat44_add_address(nat_ip2, vrf_id=99)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg2.sw_if_index,
- is_add=1)
-
- # first VRF
- pkts = self.create_stream_in(self.pg0, self.pg2)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip1)
-
- # second VRF
- pkts = self.create_stream_in(self.pg1, self.pg2)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip1)
-
- def create_routes_and_neigbors(self):
- r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
- [VppRoutePath(self.pg7.remote_ip4,
- self.pg7.sw_if_index)])
- r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
- [VppRoutePath(self.pg8.remote_ip4,
- self.pg8.sw_if_index)])
- r1.add_vpp_config()
- r2.add_vpp_config()
-
- n1 = VppNeighbor(self,
- self.pg7.sw_if_index,
- self.pg7.remote_mac,
- self.pg7.remote_ip4,
- is_static=1)
- n2 = VppNeighbor(self,
- self.pg8.sw_if_index,
- self.pg8.remote_mac,
- self.pg8.remote_ip4,
- is_static=1)
- n1.add_vpp_config()
- n2.add_vpp_config()
-
- def test_dynamic_ipless_interfaces(self):
- """ NAT44 interfaces without configured IP address """
- self.create_routes_and_neigbors()
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg7.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg8.sw_if_index,
- is_add=1)
-
- # in2out
- pkts = self.create_stream_in(self.pg7, self.pg8)
- self.pg7.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg8.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in
- pkts = self.create_stream_out(self.pg8, self.nat_addr)
- self.pg8.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg7.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg7)
-
- def test_static_ipless_interfaces(self):
- """ NAT44 interfaces without configured IP address - 1:1 NAT """
-
- self.create_routes_and_neigbors()
- self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg7.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg8.sw_if_index,
- is_add=1)
-
- # out2in
- pkts = self.create_stream_out(self.pg8)
- self.pg8.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg7.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg7)
-
- # in2out
- pkts = self.create_stream_in(self.pg7, self.pg8)
- self.pg7.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg8.get_capture(len(pkts))
- self.verify_capture_out(capture, self.nat_addr, True)
-
- def test_static_with_port_ipless_interfaces(self):
- """ NAT44 interfaces without configured IP address - 1:1 NAPT """
-
- self.tcp_port_out = 30606
- self.udp_port_out = 30607
- self.icmp_id_out = 30608
-
- self.create_routes_and_neigbors()
- self.nat44_add_address(self.nat_addr)
- self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
- self.tcp_port_in, self.tcp_port_out,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
- self.udp_port_in, self.udp_port_out,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
- self.icmp_id_in, self.icmp_id_out,
- proto=IP_PROTOS.icmp)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg7.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg8.sw_if_index,
- is_add=1)
-
- # out2in
- pkts = self.create_stream_out(self.pg8)
- self.pg8.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg7.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg7)
-
- # in2out
- pkts = self.create_stream_in(self.pg7, self.pg8)
- self.pg7.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg8.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- def test_static_unknown_proto(self):
- """ 1:1 NAT translate packet with unknown protocol """
- nat_ip = "10.0.0.10"
- self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # in2out
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, nat_ip)
- self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # out2in
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=nat_ip) /
- GRE() /
- IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
- self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_hairpinning_static_unknown_proto(self):
- """ 1:1 NAT translate packet with unknown protocol - hairpinning """
-
- host = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
-
- host_nat_ip = "10.0.0.10"
- server_nat_ip = "10.0.0.11"
-
- self.nat44_add_static_mapping(host.ip4, host_nat_ip)
- self.nat44_add_static_mapping(server.ip4, server_nat_ip)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # host to server
- p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
- IP(src=host.ip4, dst=server_nat_ip) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, host_nat_ip)
- self.assertEqual(packet[IP].dst, server.ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server to host
- p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
- IP(src=server.ip4, dst=host_nat_ip) /
- GRE() /
- IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, server_nat_ip)
- self.assertEqual(packet[IP].dst, host.ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_output_feature(self):
- """ NAT44 interface output feature (in2out postrouting) """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1, flags=flags,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg3.sw_if_index)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg3)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in
- pkts = self.create_stream_out(self.pg3)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # from non-NAT interface to NAT inside interface
- pkts = self.create_stream_in(self.pg2, self.pg0)
- self.pg2.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_no_translation(capture, self.pg2, self.pg0)
-
- def test_output_feature_vrf_aware(self):
- """ NAT44 interface output feature VRF aware (in2out postrouting) """
- nat_ip_vrf10 = "10.0.0.10"
- nat_ip_vrf20 = "10.0.0.20"
-
- r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
- [VppRoutePath(self.pg3.remote_ip4,
- self.pg3.sw_if_index)],
- table_id=10)
- r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
- [VppRoutePath(self.pg3.remote_ip4,
- self.pg3.sw_if_index)],
- table_id=20)
- r1.add_vpp_config()
- r2.add_vpp_config()
-
- self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
- self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1, flags=flags,
- sw_if_index=self.pg4.sw_if_index)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1, flags=flags,
- sw_if_index=self.pg6.sw_if_index)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg3.sw_if_index)
-
- # in2out VRF 10
- pkts = self.create_stream_in(self.pg4, self.pg3)
- self.pg4.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
-
- # out2in VRF 10
- pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg4.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg4)
-
- # in2out VRF 20
- pkts = self.create_stream_in(self.pg6, self.pg3)
- self.pg6.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
-
- # out2in VRF 20
- pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
- self.pg3.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg6)
-
- def test_output_feature_hairpinning(self):
- """ NAT44 interface output feature hairpinning (in2out postrouting) """
- host = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
- host_in_port = 1234
- host_out_port = 0
- server_in_port = 5678
- server_out_port = 8765
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
-
- # add static mapping for server
- self.nat44_add_static_mapping(server.ip4, self.nat_addr,
- server_in_port, server_out_port,
- proto=IP_PROTOS.tcp)
-
- # send packet from host to server
- p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
- IP(src=host.ip4, dst=self.nat_addr) /
- TCP(sport=host_in_port, dport=server_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, server.ip4)
- self.assertNotEqual(tcp.sport, host_in_port)
- self.assertEqual(tcp.dport, server_in_port)
- self.assert_packet_checksums_valid(p)
- host_out_port = tcp.sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # send reply from server to host
- p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
- IP(src=server.ip4, dst=self.nat_addr) /
- TCP(sport=server_in_port, dport=host_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, host.ip4)
- self.assertEqual(tcp.sport, server_out_port)
- self.assertEqual(tcp.dport, host_in_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_one_armed_nat44(self):
- """ One armed NAT44 """
- remote_host = self.pg9.remote_hosts[0]
- local_host = self.pg9.remote_hosts[1]
- external_port = 0
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg9.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg9.sw_if_index,
- flags=flags, is_add=1)
-
- # in2out
- p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
- IP(src=local_host.ip4, dst=remote_host.ip4) /
- TCP(sport=12345, dport=80))
- self.pg9.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg9.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, remote_host.ip4)
- self.assertNotEqual(tcp.sport, 12345)
- external_port = tcp.sport
- self.assertEqual(tcp.dport, 80)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # out2in
- p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
- IP(src=remote_host.ip4, dst=self.nat_addr) /
- TCP(sport=80, dport=external_port))
- self.pg9.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg9.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, remote_host.ip4)
- self.assertEqual(ip.dst, local_host.ip4)
- self.assertEqual(tcp.sport, 80)
- self.assertEqual(tcp.dport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- err = self.statistics.get_err_counter(
- '/err/nat44-classify/next in2out')
- self.assertEqual(err, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-classify/next out2in')
- self.assertEqual(err, 1)
-
- def test_del_session(self):
- """ Delete NAT44 session """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(len(pkts))
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- nsessions = len(sessions)
-
- self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=self.config_flags.NAT_IS_INSIDE)
- self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
- port=sessions[1].outside_port,
- protocol=sessions[1].protocol)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- self.assertEqual(nsessions - len(sessions), 2)
-
- self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=self.config_flags.NAT_IS_INSIDE)
-
- self.verify_no_nat44_user()
-
- def test_set_get_reass(self):
- """ NAT44 set/get virtual fragmentation reassembly """
- reas_cfg1 = self.vapi.nat_get_reass()
-
- self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
- max_reass=reas_cfg1.ip4_max_reass * 2,
- max_frag=reas_cfg1.ip4_max_frag * 2,
- drop_frag=0)
-
- reas_cfg2 = self.vapi.nat_get_reass()
-
- self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
- self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
- self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
-
- self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
- drop_frag=1)
- self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
-
- def test_frag_in_order(self):
- """ NAT44 translate fragments arriving in order """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- reas_cfg1 = self.vapi.nat_get_reass()
- # this test was intermittently failing in some cases
- # until we temporarily bump the reassembly timeouts
- self.vapi.nat_set_reass(timeout=20, max_reass=1024, max_frag=5,
- drop_frag=0)
-
- self.frag_in_order(proto=IP_PROTOS.tcp)
- self.frag_in_order(proto=IP_PROTOS.udp)
- self.frag_in_order(proto=IP_PROTOS.icmp)
-
- # restore the reassembly timeouts
- self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout,
- max_reass=reas_cfg1.ip4_max_reass,
- max_frag=reas_cfg1.ip4_max_frag,
- drop_frag=reas_cfg1.ip4_drop_frag)
-
- def test_frag_forwarding(self):
- """ NAT44 forwarding fragment test """
- self.vapi.nat44_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_forwarding_enable_disable(enable=1)
-
- data = b"A" * 16 + b"B" * 16 + b"C" * 3
- pkts = self.create_stream_frag(self.pg1,
- self.pg0.remote_ip4,
- 4789,
- 4789,
- data,
- proto=IP_PROTOS.udp)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.pg1.remote_ip4,
- self.pg0.remote_ip4)
- self.assertEqual(p[UDP].sport, 4789)
- self.assertEqual(p[UDP].dport, 4789)
- self.assertEqual(data, p[Raw].load)
-
- def test_reass_hairpinning(self):
- """ NAT44 fragments hairpinning """
-
- self.server = self.pg0.remote_hosts[1]
- self.host_in_port = random.randint(1025, 65535)
- self.server_in_port = random.randint(1025, 65535)
- self.server_out_port = random.randint(1025, 65535)
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- # add static mapping for server
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
-
- self.reass_hairpinning(proto=IP_PROTOS.tcp)
- self.reass_hairpinning(proto=IP_PROTOS.udp)
- self.reass_hairpinning(proto=IP_PROTOS.icmp)
-
- def test_frag_out_of_order(self):
- """ NAT44 translate fragments arriving out of order """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- self.frag_out_of_order(proto=IP_PROTOS.tcp)
- self.frag_out_of_order(proto=IP_PROTOS.udp)
- self.frag_out_of_order(proto=IP_PROTOS.icmp)
-
- def test_port_restricted(self):
- """ Port restricted NAT44 (MAP-E CE) """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
- psid_offset=6,
- psid_length=6,
- psid=10)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=4567, dport=22))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg1.remote_ip4)
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.dport, 22)
- self.assertNotEqual(tcp.sport, 4567)
- self.assertEqual((tcp.sport >> 6) & 63, 10)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_port_range(self):
- """ External address port range """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
- start_port=1025,
- end_port=1027)
-
- pkts = []
- for port in range(0, 5):
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=1125 + port))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(3)
- for p in capture:
- tcp = p[TCP]
- self.assertGreaterEqual(tcp.sport, 1025)
- self.assertLessEqual(tcp.sport, 1027)
-
- def test_ipfix_max_frags(self):
- """ IPFIX logging maximum fragments pending reassembly exceeded """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
- drop_frag=0)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- self.tcp_port_in = random.randint(1025, 65535)
- pkts = self.create_stream_frag(self.pg0,
- self.pg1.remote_ip4,
- self.tcp_port_in,
- 20,
- data)
- pkts.reverse()
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_fragments_ip4(data, 1,
- self.pg0.remote_ip4n)
-
- def test_multiple_outside_vrf(self):
- """ Multiple outside VRF """
- vrf_id1 = 1
- vrf_id2 = 2
-
- self.pg1.unconfig_ip4()
- self.pg2.unconfig_ip4()
- self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
- self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
- self.pg1.set_table_ip4(vrf_id1)
- self.pg2.set_table_ip4(vrf_id2)
- self.pg1.config_ip4()
- self.pg2.config_ip4()
- self.pg1.resolve_arp()
- self.pg2.resolve_arp()
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg2.sw_if_index,
- is_add=1)
-
- try:
- # first VRF
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, self.nat_addr)
-
- pkts = self.create_stream_out(self.pg1, self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- self.tcp_port_in = 60303
- self.udp_port_in = 60304
- self.icmp_id_in = 60305
-
- # second VRF
- pkts = self.create_stream_in(self.pg0, self.pg2)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_out(capture, self.nat_addr)
-
- pkts = self.create_stream_out(self.pg2, self.nat_addr)
- self.pg2.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- finally:
- self.nat44_add_address(self.nat_addr, is_add=0)
- self.pg1.unconfig_ip4()
- self.pg2.unconfig_ip4()
- self.pg1.set_table_ip4(0)
- self.pg2.set_table_ip4(0)
- self.pg1.config_ip4()
- self.pg2.config_ip4()
- self.pg1.resolve_arp()
- self.pg2.resolve_arp()
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_timeout(self):
- """ NAT44 session timeouts """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
- tcp_transitory=240, icmp=60)
-
- max_sessions = 1000
- pkts = []
- for i in range(0, max_sessions):
- src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=src, dst=self.pg1.remote_ip4) /
- UDP(sport=1025, dport=53))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(max_sessions)
-
- sleep(6)
-
- pkts = []
- for i in range(0, max_sessions):
- src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=src, dst=self.pg1.remote_ip4) /
- UDP(sport=1026, dport=53))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(max_sessions)
-
- nsessions = 0
- users = self.vapi.nat44_user_dump()
- for user in users:
- nsessions = nsessions + user.nsessions
- self.assertLess(nsessions, 2 * max_sessions)
-
- def test_mss_clamping(self):
- """ TCP MSS clamping """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="S", options=[('MSS', 1400)]))
-
- self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- # Negotiated MSS value greater than configured - changed
- self.verify_mss_value(capture[0], 1000)
-
- self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- # MSS clamping disabled - negotiated MSS unchanged
- self.verify_mss_value(capture[0], 1400)
-
- self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- # Negotiated MSS value smaller than configured - unchanged
- self.verify_mss_value(capture[0], 1400)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_ha_send(self):
- """ Send HA session synchronization events (active) """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
- port=12345,
- path_mtu=512)
- self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
- port=12346, session_refresh_interval=10)
- bind_layers(UDP, HANATStateSync, sport=12345)
-
- # create sessions
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
- # active send HA events
- self.vapi.nat_ha_flush()
- stats = self.statistics.get_counter('/nat44/ha/add-event-send')
- self.assertEqual(stats[0][0], 3)
- capture = self.pg3.get_capture(1)
- p = capture[0]
- self.assert_packet_checksums_valid(p)
- try:
- ip = p[IP]
- udp = p[UDP]
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(ip.src, self.pg3.local_ip4)
- self.assertEqual(ip.dst, self.pg3.remote_ip4)
- self.assertEqual(udp.sport, 12345)
- self.assertEqual(udp.dport, 12346)
- self.assertEqual(hanat.version, 1)
- self.assertEqual(hanat.thread_index, 0)
- self.assertEqual(hanat.count, 3)
- seq = hanat.sequence_number
- for event in hanat.events:
- self.assertEqual(event.event_type, 1)
- self.assertEqual(event.in_addr, self.pg0.remote_ip4)
- self.assertEqual(event.out_addr, self.nat_addr)
- self.assertEqual(event.fib_index, 0)
-
- # ACK received events
- ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
- UDP(sport=12346, dport=12345) /
- HANATStateSync(sequence_number=seq, flags='ACK'))
- self.pg3.add_stream(ack)
- self.pg_start()
- stats = self.statistics.get_counter('/nat44/ha/ack-recv')
- self.assertEqual(stats[0][0], 1)
-
- # delete one session
- self.pg_enable_capture(self.pg_interfaces)
- self.vapi.nat44_del_session(address=self.pg0.remote_ip4n,
- port=self.tcp_port_in,
- protocol=IP_PROTOS.tcp,
- flags=self.config_flags.NAT_IS_INSIDE)
- self.vapi.nat_ha_flush()
- stats = self.statistics.get_counter('/nat44/ha/del-event-send')
- self.assertEqual(stats[0][0], 1)
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertGreater(hanat.sequence_number, seq)
-
- # do not send ACK, active retry send HA event again
- self.pg_enable_capture(self.pg_interfaces)
- sleep(12)
- stats = self.statistics.get_counter('/nat44/ha/retry-count')
- self.assertEqual(stats[0][0], 3)
- stats = self.statistics.get_counter('/nat44/ha/missed-count')
- self.assertEqual(stats[0][0], 1)
- capture = self.pg3.get_capture(3)
- for packet in capture:
- self.assertEqual(packet, p)
-
- # session counters refresh
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(2)
- self.vapi.nat_ha_flush()
- stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
- self.assertEqual(stats[0][0], 2)
- capture = self.pg3.get_capture(1)
- p = capture[0]
- self.assert_packet_checksums_valid(p)
- try:
- ip = p[IP]
- udp = p[UDP]
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(ip.src, self.pg3.local_ip4)
- self.assertEqual(ip.dst, self.pg3.remote_ip4)
- self.assertEqual(udp.sport, 12345)
- self.assertEqual(udp.dport, 12346)
- self.assertEqual(hanat.version, 1)
- self.assertEqual(hanat.count, 2)
- seq = hanat.sequence_number
- for event in hanat.events:
- self.assertEqual(event.event_type, 3)
- self.assertEqual(event.out_addr, self.nat_addr)
- self.assertEqual(event.fib_index, 0)
- self.assertEqual(event.total_pkts, 2)
- self.assertGreater(event.total_bytes, 0)
-
- ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
- UDP(sport=12346, dport=12345) /
- HANATStateSync(sequence_number=seq, flags='ACK'))
- self.pg3.add_stream(ack)
- self.pg_start()
- stats = self.statistics.get_counter('/nat44/ha/ack-recv')
- self.assertEqual(stats[0][0], 2)
-
- def test_ha_recv(self):
- """ Receive HA session synchronization events (passive) """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
- port=12345,
- path_mtu=512)
- bind_layers(UDP, HANATStateSync, sport=12345)
-
- self.tcp_port_out = random.randint(1025, 65535)
- self.udp_port_out = random.randint(1025, 65535)
-
- # send HA session add events to failover/passive
- p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
- UDP(sport=12346, dport=12345) /
- HANATStateSync(sequence_number=1, events=[
- Event(event_type='add', protocol='tcp',
- in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
- in_port=self.tcp_port_in, out_port=self.tcp_port_out,
- eh_addr=self.pg1.remote_ip4,
- ehn_addr=self.pg1.remote_ip4,
- eh_port=self.tcp_external_port,
- ehn_port=self.tcp_external_port, fib_index=0),
- Event(event_type='add', protocol='udp',
- in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
- in_port=self.udp_port_in, out_port=self.udp_port_out,
- eh_addr=self.pg1.remote_ip4,
- ehn_addr=self.pg1.remote_ip4,
- eh_port=self.udp_external_port,
- ehn_port=self.udp_external_port, fib_index=0)]))
-
- self.pg3.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- # receive ACK
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(hanat.sequence_number, 1)
- self.assertEqual(hanat.flags, 'ACK')
- self.assertEqual(hanat.version, 1)
- self.assertEqual(hanat.thread_index, 0)
- stats = self.statistics.get_counter('/nat44/ha/ack-send')
- self.assertEqual(stats[0][0], 1)
- stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
- self.assertEqual(stats[0][0], 2)
- users = self.statistics.get_counter('/nat44/total-users')
- self.assertEqual(users[0][0], 1)
- sessions = self.statistics.get_counter('/nat44/total-sessions')
- self.assertEqual(sessions[0][0], 2)
- users = self.vapi.nat44_user_dump()
- self.assertEqual(len(users), 1)
- self.assertEqual(str(users[0].ip_address),
- self.pg0.remote_ip4)
- # there should be 2 sessions created by HA
- sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
- users[0].vrf_id)
- self.assertEqual(len(sessions), 2)
- for session in sessions:
- self.assertEqual(str(session.inside_ip_address),
- self.pg0.remote_ip4)
- self.assertEqual(str(session.outside_ip_address),
- self.nat_addr)
- self.assertIn(session.inside_port,
- [self.tcp_port_in, self.udp_port_in])
- self.assertIn(session.outside_port,
- [self.tcp_port_out, self.udp_port_out])
- self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
-
- # send HA session delete event to failover/passive
- p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
- UDP(sport=12346, dport=12345) /
- HANATStateSync(sequence_number=2, events=[
- Event(event_type='del', protocol='udp',
- in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
- in_port=self.udp_port_in, out_port=self.udp_port_out,
- eh_addr=self.pg1.remote_ip4,
- ehn_addr=self.pg1.remote_ip4,
- eh_port=self.udp_external_port,
- ehn_port=self.udp_external_port, fib_index=0)]))
-
- self.pg3.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- # receive ACK
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(hanat.sequence_number, 2)
- self.assertEqual(hanat.flags, 'ACK')
- self.assertEqual(hanat.version, 1)
- users = self.vapi.nat44_user_dump()
- self.assertEqual(len(users), 1)
- self.assertEqual(str(users[0].ip_address),
- self.pg0.remote_ip4)
- # now we should have only 1 session, 1 deleted by HA
- sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
- users[0].vrf_id)
- self.assertEqual(len(sessions), 1)
- stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
- self.assertEqual(stats[0][0], 1)
-
- stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
- self.assertEqual(stats, 2)
-
- # send HA session refresh event to failover/passive
- p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
- UDP(sport=12346, dport=12345) /
- HANATStateSync(sequence_number=3, events=[
- Event(event_type='refresh', protocol='tcp',
- in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
- in_port=self.tcp_port_in, out_port=self.tcp_port_out,
- eh_addr=self.pg1.remote_ip4,
- ehn_addr=self.pg1.remote_ip4,
- eh_port=self.tcp_external_port,
- ehn_port=self.tcp_external_port, fib_index=0,
- total_bytes=1024, total_pkts=2)]))
- self.pg3.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- # receive ACK
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- hanat = p[HANATStateSync]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(hanat.sequence_number, 3)
- self.assertEqual(hanat.flags, 'ACK')
- self.assertEqual(hanat.version, 1)
- users = self.vapi.nat44_user_dump()
- self.assertEqual(len(users), 1)
- self.assertEqual(str(users[0].ip_address),
- self.pg0.remote_ip4)
- sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
- users[0].vrf_id)
- self.assertEqual(len(sessions), 1)
- session = sessions[0]
- self.assertEqual(session.total_bytes, 1024)
- self.assertEqual(session.total_pkts, 2)
- stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
- self.assertEqual(stats[0][0], 1)
-
- stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
- self.assertEqual(stats, 3)
-
- # send packet to test session created by HA
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- except IndexError:
- self.logger.error(ppp("Invalid packet:", p))
- raise
- else:
- self.assertEqual(ip.src, self.pg1.remote_ip4)
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.sport, self.tcp_external_port)
- self.assertEqual(tcp.dport, self.tcp_port_in)
-
- def tearDown(self):
- super(TestNAT44, self).tearDown()
- self.clear_nat44()
- self.vapi.cli("clear logging")
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat44 addresses"))
- self.logger.info(self.vapi.cli("show nat44 interfaces"))
- self.logger.info(self.vapi.cli("show nat44 static mappings"))
- self.logger.info(self.vapi.cli("show nat44 interface address"))
- self.logger.info(self.vapi.cli("show nat44 sessions detail"))
- self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
- self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
- self.logger.info(self.vapi.cli("show nat timeouts"))
- self.logger.info(
- self.vapi.cli("show nat addr-port-assignment-alg"))
- self.logger.info(self.vapi.cli("show nat ha"))
-
-
-class TestNAT44EndpointDependent(MethodHolder):
- """ Endpoint-Dependent mapping and filtering test cases """
-
- @classmethod
- def setUpConstants(cls):
- super(TestNAT44EndpointDependent, cls).setUpConstants()
- cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
-
- @classmethod
- def setUpClass(cls):
- super(TestNAT44EndpointDependent, cls).setUpClass()
- cls.vapi.cli("set log class nat level debug")
- try:
- cls.tcp_port_in = 6303
- cls.tcp_port_out = 6303
- cls.udp_port_in = 6304
- cls.udp_port_out = 6304
- cls.icmp_id_in = 6305
- cls.icmp_id_out = 6305
- cls.nat_addr = '10.0.0.3'
- cls.ipfix_src_port = 4739
- cls.ipfix_domain_id = 1
- cls.tcp_external_port = 80
-
- cls.create_pg_interfaces(range(7))
- cls.interfaces = list(cls.pg_interfaces[0:3])
-
- for i in cls.interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
-
- cls.pg0.generate_remote_hosts(3)
- cls.pg0.configure_ipv4_neighbors()
-
- cls.pg3.admin_up()
-
- cls.pg4.generate_remote_hosts(2)
- cls.pg4.config_ip4()
- ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
- cls.vapi.sw_interface_add_del_address(
- sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
- address_length=24)
- cls.pg4.admin_up()
- cls.pg4.resolve_arp()
- cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
- cls.pg4.resolve_arp()
-
- zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
- cls.vapi.ip_table_add_del(is_add=1, table_id=1)
-
- cls.pg5._local_ip4 = "10.1.1.1"
- cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
- cls.pg5.local_ip4)
- cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
- cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
- socket.AF_INET, cls.pg5.remote_ip4)
- cls.pg5.set_table_ip4(1)
- cls.pg5.config_ip4()
- cls.pg5.admin_up()
- r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
- [VppRoutePath("0.0.0.0",
- cls.pg5.sw_if_index)],
- table_id=1,
- register=False)
- r1.add_vpp_config()
-
- cls.pg6._local_ip4 = "10.1.2.1"
- cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
- cls.pg6.local_ip4)
- cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
- cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
- socket.AF_INET, cls.pg6.remote_ip4)
- cls.pg6.set_table_ip4(1)
- cls.pg6.config_ip4()
- cls.pg6.admin_up()
-
- r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
- [VppRoutePath("0.0.0.0",
- cls.pg6.sw_if_index)],
- table_id=1,
- register=False)
- r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
- [VppRoutePath("0.0.0.0",
- 0xffffffff,
- nh_table_id=1)],
- table_id=0,
- register=False)
- r4 = VppIpRoute(cls, "0.0.0.0", 0,
- [VppRoutePath("0.0.0.0", 0xffffffff,
- nh_table_id=0)],
- table_id=1,
- register=False)
- r5 = VppIpRoute(cls, "0.0.0.0", 0,
- [VppRoutePath(cls.pg1.local_ip4,
- cls.pg1.sw_if_index)],
- register=False)
- r2.add_vpp_config()
- r3.add_vpp_config()
- r4.add_vpp_config()
- r5.add_vpp_config()
-
- cls.pg5.resolve_arp()
- cls.pg6.resolve_arp()
-
- except Exception:
- super(TestNAT44EndpointDependent, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestNAT44EndpointDependent, cls).tearDownClass()
-
- def test_frag_in_order(self):
- """ NAT44 translate fragments arriving in order """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.frag_in_order(proto=IP_PROTOS.tcp)
- self.frag_in_order(proto=IP_PROTOS.udp)
- self.frag_in_order(proto=IP_PROTOS.icmp)
-
- def test_frag_in_order_dont_translate(self):
- """ NAT44 don't translate fragments arriving in order """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_forwarding_enable_disable(enable=True)
- reas_cfg1 = self.vapi.nat_get_reass()
- # this test was intermittently failing in some cases
- # until we temporarily bump the reassembly timeouts
- self.vapi.nat_set_reass(timeout=20, max_reass=1024, max_frag=5,
- drop_frag=0)
- self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
- # restore the reassembly timeouts
- self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout,
- max_reass=reas_cfg1.ip4_max_reass,
- max_frag=reas_cfg1.ip4_max_frag,
- drop_frag=reas_cfg1.ip4_drop_frag)
-
- def test_frag_out_of_order(self):
- """ NAT44 translate fragments arriving out of order """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.frag_out_of_order(proto=IP_PROTOS.tcp)
- self.frag_out_of_order(proto=IP_PROTOS.udp)
- self.frag_out_of_order(proto=IP_PROTOS.icmp)
-
- def test_frag_out_of_order_dont_translate(self):
- """ NAT44 don't translate fragments arriving out of order """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_forwarding_enable_disable(enable=True)
- self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
-
- def test_frag_in_order_in_plus_out(self):
- """ in+out interface fragments in order """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- flags=flags, is_add=1)
-
- self.server = self.pg1.remote_hosts[0]
-
- self.server_in_addr = self.server.ip4
- self.server_out_addr = '11.11.11.11'
- self.server_in_port = random.randint(1025, 65535)
- self.server_out_port = random.randint(1025, 65535)
-
- self.nat44_add_address(self.server_out_addr)
-
- # add static mappings for server
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- proto=IP_PROTOS.icmp)
-
- self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
- drop_frag=0)
-
- self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
- self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
- self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
-
- def test_frag_out_of_order_in_plus_out(self):
- """ in+out interface fragments out of order """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- flags=flags, is_add=1)
-
- self.server = self.pg1.remote_hosts[0]
-
- self.server_in_addr = self.server.ip4
- self.server_out_addr = '11.11.11.11'
- self.server_in_port = random.randint(1025, 65535)
- self.server_out_port = random.randint(1025, 65535)
-
- self.nat44_add_address(self.server_out_addr)
-
- # add static mappings for server
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.server_in_addr,
- self.server_out_addr,
- proto=IP_PROTOS.icmp)
-
- self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
- drop_frag=0)
-
- self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
- self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
- self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
-
- def test_reass_hairpinning(self):
- """ NAT44 fragments hairpinning """
- self.server = self.pg0.remote_hosts[1]
- self.host_in_port = random.randint(1025, 65535)
- self.server_in_port = random.randint(1025, 65535)
- self.server_out_port = random.randint(1025, 65535)
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- # add static mapping for server
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.tcp)
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
- self.server_in_port,
- self.server_out_port,
- proto=IP_PROTOS.udp)
- self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
-
- self.reass_hairpinning(proto=IP_PROTOS.tcp)
- self.reass_hairpinning(proto=IP_PROTOS.udp)
- self.reass_hairpinning(proto=IP_PROTOS.icmp)
-
- def test_dynamic(self):
- """ NAT44 dynamic translation test """
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- nat_config = self.vapi.nat_show_config()
- self.assertEqual(1, nat_config.endpoint_dependent)
-
- # in2out
- tcpn = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/TCP packets')
- udpn = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
- self.assertEqual(err - totaln, 3)
-
- # out2in
- tcpn = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/TCP packets')
- udpn = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in-slowpath/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/good out2in packets processed')
-
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in-slowpath/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat44-ed-out2in/good out2in packets processed')
- self.assertEqual(err - totaln, 2)
-
- users = self.statistics.get_counter('/nat44/total-users')
- self.assertEqual(users[0][0], 1)
- sessions = self.statistics.get_counter('/nat44/total-sessions')
- self.assertEqual(sessions[0][0], 3)
-
- def test_forwarding(self):
- """ NAT44 forwarding test """
-
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat44_forwarding_enable_disable(enable=1)
-
- real_ip = self.pg0.remote_ip4
- alias_ip = self.nat_addr
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(is_add=1,
- local_ip_address=real_ip,
- external_ip_address=alias_ip,
- external_sw_if_index=0xFFFFFFFF,
- flags=flags)
-
- try:
- # in2out - static mapping match
-
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, same_port=True)
-
- # in2out - no static mapping match
-
- host0 = self.pg0.remote_hosts[0]
- self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
- try:
- pkts = self.create_stream_out(self.pg1,
- dst_ip=self.pg0.remote_ip4,
- use_inside_ports=True)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
- same_port=True)
- finally:
- self.pg0.remote_hosts[0] = host0
-
- user = self.pg0.remote_hosts[1]
- sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
- self.assertEqual(len(sessions), 3)
- self.assertTrue(sessions[0].flags &
- self.config_flags.NAT_IS_EXT_HOST_VALID)
- self.vapi.nat44_del_session(
- address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=(self.config_flags.NAT_IS_INSIDE |
- self.config_flags.NAT_IS_EXT_HOST_VALID),
- ext_host_address=sessions[0].ext_host_address,
- ext_host_port=sessions[0].ext_host_port)
- sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
- self.assertEqual(len(sessions), 2)
-
- finally:
- self.vapi.nat44_forwarding_enable_disable(enable=0)
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_static_mapping(
- is_add=0,
- local_ip_address=real_ip,
- external_ip_address=alias_ip,
- external_sw_if_index=0xFFFFFFFF,
- flags=flags)
-
- def test_static_lb(self):
- """ NAT44 local service load balancing """
- external_addr_n = self.nat_addr
- external_port = 80
- local_port = 8080
- server1 = self.pg0.remote_hosts[0]
- server2 = self.pg0.remote_hosts[1]
-
- locals = [{'addr': server1.ip4n,
- 'port': local_port,
- 'probability': 70,
- 'vrf_id': 0},
- {'addr': server2.ip4n,
- 'port': local_port,
- 'probability': 30,
- 'vrf_id': 0}]
-
- self.nat44_add_address(self.nat_addr)
- self.vapi.nat44_add_del_lb_static_mapping(
- is_add=1,
- external_addr=external_addr_n,
- external_port=external_port,
- protocol=IP_PROTOS.tcp,
- local_num=len(locals),
- locals=locals)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # from client to service
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- server = None
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertIn(ip.dst, [server1.ip4, server2.ip4])
- if ip.dst == server1.ip4:
- server = server1
- else:
- server = server2
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client
- p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
- IP(src=server.ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
- self.assertEqual(len(sessions), 1)
- self.assertTrue(sessions[0].flags &
- self.config_flags.NAT_IS_EXT_HOST_VALID)
- self.vapi.nat44_del_session(
- address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=(self.config_flags.NAT_IS_INSIDE |
- self.config_flags.NAT_IS_EXT_HOST_VALID),
- ext_host_address=sessions[0].ext_host_address,
- ext_host_port=sessions[0].ext_host_port)
- sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
- self.assertEqual(len(sessions), 0)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_static_lb_multi_clients(self):
- """ NAT44 local service load balancing - multiple clients"""
-
- external_addr = self.nat_addr
- external_port = 80
- local_port = 8080
- server1 = self.pg0.remote_hosts[0]
- server2 = self.pg0.remote_hosts[1]
- server3 = self.pg0.remote_hosts[2]
-
- locals = [{'addr': server1.ip4n,
- 'port': local_port,
- 'probability': 90,
- 'vrf_id': 0},
- {'addr': server2.ip4n,
- 'port': local_port,
- 'probability': 10,
- 'vrf_id': 0}]
-
- self.nat44_add_address(self.nat_addr)
- self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
- external_addr=external_addr,
- external_port=external_port,
- protocol=IP_PROTOS.tcp,
- local_num=len(locals),
- locals=locals)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- server1_n = 0
- server2_n = 0
- clients = ip4_range(self.pg1.remote_ip4, 10, 50)
- pkts = []
- for client in clients:
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=client, dst=self.nat_addr) /
- TCP(sport=12345, dport=external_port))
- pkts.append(p)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for p in capture:
- if p[IP].dst == server1.ip4:
- server1_n += 1
- else:
- server2_n += 1
- self.assertGreater(server1_n, server2_n)
-
- local = {
- 'addr': server3.ip4n,
- 'port': local_port,
- 'probability': 20,
- 'vrf_id': 0
- }
-
- # add new back-end
- self.vapi.nat44_lb_static_mapping_add_del_local(
- is_add=1,
- external_addr=external_addr,
- external_port=external_port,
- local=local,
- protocol=IP_PROTOS.tcp)
- server1_n = 0
- server2_n = 0
- server3_n = 0
- clients = ip4_range(self.pg1.remote_ip4, 60, 110)
- pkts = []
- for client in clients:
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=client, dst=self.nat_addr) /
- TCP(sport=12346, dport=external_port))
- pkts.append(p)
- self.assertGreater(len(pkts), 0)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for p in capture:
- if p[IP].dst == server1.ip4:
- server1_n += 1
- elif p[IP].dst == server2.ip4:
- server2_n += 1
- else:
- server3_n += 1
- self.assertGreater(server1_n, 0)
- self.assertGreater(server2_n, 0)
- self.assertGreater(server3_n, 0)
-
- local = {
- 'addr': server2.ip4n,
- 'port': local_port,
- 'probability': 10,
- 'vrf_id': 0
- }
-
- # remove one back-end
- self.vapi.nat44_lb_static_mapping_add_del_local(
- is_add=0,
- external_addr=external_addr,
- external_port=external_port,
- local=local,
- protocol=IP_PROTOS.tcp)
- server1_n = 0
- server2_n = 0
- server3_n = 0
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for p in capture:
- if p[IP].dst == server1.ip4:
- server1_n += 1
- elif p[IP].dst == server2.ip4:
- server2_n += 1
- else:
- server3_n += 1
- self.assertGreater(server1_n, 0)
- self.assertEqual(server2_n, 0)
- self.assertGreater(server3_n, 0)
-
- def test_static_lb_2(self):
- """ NAT44 local service load balancing (asymmetrical rule) """
- external_addr = self.nat_addr
- external_port = 80
- local_port = 8080
- server1 = self.pg0.remote_hosts[0]
- server2 = self.pg0.remote_hosts[1]
-
- locals = [{'addr': server1.ip4n,
- 'port': local_port,
- 'probability': 70,
- 'vrf_id': 0},
- {'addr': server2.ip4n,
- 'port': local_port,
- 'probability': 30,
- 'vrf_id': 0}]
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- flags = self.config_flags.NAT_IS_OUT2IN_ONLY
- self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
- external_addr=external_addr,
- external_port=external_port,
- protocol=IP_PROTOS.tcp,
- local_num=len(locals),
- locals=locals)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # from client to service
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- server = None
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertIn(ip.dst, [server1.ip4, server2.ip4])
- if ip.dst == server1.ip4:
- server = server1
- else:
- server = server2
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client
- p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
- IP(src=server.ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client to server (no translation)
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
- TCP(sport=12346, dport=local_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- server = None
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, server1.ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client (no translation)
- p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
- IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12346))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, server1.ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_lb_affinity(self):
- """ NAT44 local service load balancing affinity """
- external_addr = self.nat_addr
- external_port = 80
- local_port = 8080
- server1 = self.pg0.remote_hosts[0]
- server2 = self.pg0.remote_hosts[1]
-
- locals = [{'addr': server1.ip4n,
- 'port': local_port,
- 'probability': 50,
- 'vrf_id': 0},
- {'addr': server2.ip4n,
- 'port': local_port,
- 'probability': 50,
- 'vrf_id': 0}]
-
- self.nat44_add_address(self.nat_addr)
- self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
- external_addr=external_addr,
- external_port=external_port,
- protocol=IP_PROTOS.tcp,
- affinity=10800,
- local_num=len(locals),
- locals=locals)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=1025, dport=external_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- backend = capture[0][IP].dst
-
- sessions = self.vapi.nat44_user_session_dump(backend, 0)
- self.assertEqual(len(sessions), 1)
- self.assertTrue(sessions[0].flags &
- self.config_flags.NAT_IS_EXT_HOST_VALID)
- self.vapi.nat44_del_session(
- address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=(self.config_flags.NAT_IS_INSIDE |
- self.config_flags.NAT_IS_EXT_HOST_VALID),
- ext_host_address=sessions[0].ext_host_address,
- ext_host_port=sessions[0].ext_host_port)
-
- pkts = []
- for port in range(1030, 1100):
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=port, dport=external_port))
- pkts.append(p)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for p in capture:
- self.assertEqual(p[IP].dst, backend)
-
- def test_unknown_proto(self):
- """ NAT44 translate packet with unknown protocol """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # in2out
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=20))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, self.nat_addr)
- self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # out2in
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
- self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_hairpinning_unknown_proto(self):
- """ NAT44 translate packet with unknown protocol - hairpinning """
- host = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
- host_in_port = 1234
- server_out_port = 8765
- server_nat_ip = "10.0.0.11"
-
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # add static mapping for server
- self.nat44_add_static_mapping(server.ip4, server_nat_ip)
-
- # host to server
- p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
- IP(src=host.ip4, dst=server_nat_ip) /
- TCP(sport=host_in_port, dport=server_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
- IP(src=host.ip4, dst=server_nat_ip) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, self.nat_addr)
- self.assertEqual(packet[IP].dst, server.ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server to host
- p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
- IP(src=server.ip4, dst=self.nat_addr) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, server_nat_ip)
- self.assertEqual(packet[IP].dst, host.ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_output_feature_and_service(self):
- """ NAT44 interface output feature and services """
- external_addr = '1.2.3.4'
- external_port = 80
- local_port = 8080
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_ADDR_ONLY
- self.vapi.nat44_add_del_identity_mapping(
- ip_address=self.pg1.remote_ip4n, sw_if_index=0xFFFFFFFF,
- flags=flags, is_add=1)
- flags = self.config_flags.NAT_IS_OUT2IN_ONLY
- self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
- local_port, external_port,
- proto=IP_PROTOS.tcp, flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
-
- # from client to service
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=external_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, external_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from local network host to external network
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # from external network back to local network host
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- def test_output_feature_and_service2(self):
- """ NAT44 interface output feature and service host direct access """
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
-
- # session initiated from service host - translate
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # session initiated from remote host - do not translate
- self.tcp_port_in = 60303
- self.udp_port_in = 60304
- self.icmp_id_in = 60305
- pkts = self.create_stream_out(self.pg1,
- self.pg0.remote_ip4,
- use_inside_ports=True)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
- same_port=True)
-
- def test_output_feature_and_service3(self):
- """ NAT44 interface output feature and DST NAT """
- external_addr = '1.2.3.4'
- external_port = 80
- local_port = 8080
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_OUT2IN_ONLY
- self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
- local_port, external_port,
- proto=IP_PROTOS.tcp, flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=external_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg0.remote_ip4)
- self.assertEqual(tcp.sport, 12345)
- self.assertEqual(ip.dst, self.pg1.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, external_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.dport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_next_src_nat(self):
- """ On way back forward packet to nat44-in2out node. """
- twice_nat_addr = '10.0.1.3'
- external_port = 80
- local_port = 8080
- post_twice_nat_port = 0
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(twice_nat_addr, twice_nat=1)
- flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
- self.config_flags.NAT_IS_SELF_TWICE_NAT)
- self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
- local_port, external_port,
- proto=IP_PROTOS.tcp, vrf_id=1,
- flags=flags)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg6.sw_if_index,
- is_add=1)
-
- p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
- IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=12345, dport=external_port))
- self.pg6.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, twice_nat_addr)
- self.assertNotEqual(tcp.sport, 12345)
- post_twice_nat_port = tcp.sport
- self.assertEqual(ip.dst, self.pg6.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
- IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
- TCP(sport=local_port, dport=post_twice_nat_port))
- self.pg6.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg1.remote_ip4)
- self.assertEqual(tcp.sport, external_port)
- self.assertEqual(ip.dst, self.pg6.remote_ip4)
- self.assertEqual(tcp.dport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
- client_id=None):
- twice_nat_addr = '10.0.1.3'
-
- port_in = 8080
- if lb:
- if not same_pg:
- port_in1 = port_in
- port_in2 = port_in
- else:
- port_in1 = port_in + 1
- port_in2 = port_in + 2
-
- port_out = 80
- eh_port_out = 4567
-
- server1 = self.pg0.remote_hosts[0]
- server2 = self.pg0.remote_hosts[1]
- if lb and same_pg:
- server2 = server1
- if not lb:
- server = server1
-
- pg0 = self.pg0
- if same_pg:
- pg1 = self.pg0
- else:
- pg1 = self.pg1
-
- eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
- client_id == 1)
-
- self.nat44_add_address(self.nat_addr)
- self.nat44_add_address(twice_nat_addr, twice_nat=1)
-
- flags = 0
- if self_twice_nat:
- flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
- else:
- flags |= self.config_flags.NAT_IS_TWICE_NAT
-
- if not lb:
- self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
- port_in, port_out,
- proto=IP_PROTOS.tcp,
- flags=flags)
- else:
- locals = [{'addr': server1.ip4n,
- 'port': port_in1,
- 'probability': 50,
- 'vrf_id': 0},
- {'addr': server2.ip4n,
- 'port': port_in2,
- 'probability': 50,
- 'vrf_id': 0}]
- out_addr = self.nat_addr
-
- self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
- external_addr=out_addr,
- external_port=port_out,
- protocol=IP_PROTOS.tcp,
- local_num=len(locals),
- locals=locals)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=pg1.sw_if_index,
- is_add=1)
-
- if same_pg:
- if not lb:
- client = server
- else:
- assert client_id is not None
- if client_id == 1:
- client = self.pg0.remote_hosts[0]
- elif client_id == 2:
- client = self.pg0.remote_hosts[1]
- else:
- client = pg1.remote_hosts[0]
- p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
- IP(src=client.ip4, dst=self.nat_addr) /
- TCP(sport=eh_port_out, dport=port_out))
- pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- if lb:
- if ip.dst == server1.ip4:
- server = server1
- port_in = port_in1
- else:
- server = server2
- port_in = port_in2
- self.assertEqual(ip.dst, server.ip4)
- if lb and same_pg:
- self.assertIn(tcp.dport, [port_in1, port_in2])
- else:
- self.assertEqual(tcp.dport, port_in)
- if eh_translate:
- self.assertEqual(ip.src, twice_nat_addr)
- self.assertNotEqual(tcp.sport, eh_port_out)
- else:
- self.assertEqual(ip.src, client.ip4)
- self.assertEqual(tcp.sport, eh_port_out)
- eh_addr_in = ip.src
- eh_port_in = tcp.sport
- saved_port_in = tcp.dport
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- p = (Ether(src=server.mac, dst=pg0.local_mac) /
- IP(src=server.ip4, dst=eh_addr_in) /
- TCP(sport=saved_port_in, dport=eh_port_in))
- pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, client.ip4)
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.dport, eh_port_out)
- self.assertEqual(tcp.sport, port_out)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- if eh_translate:
- sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
- self.assertEqual(len(sessions), 1)
- self.assertTrue(sessions[0].flags &
- self.config_flags.NAT_IS_EXT_HOST_VALID)
- self.assertTrue(sessions[0].flags &
- self.config_flags.NAT_IS_TWICE_NAT)
- self.logger.info(self.vapi.cli("show nat44 sessions detail"))
- self.vapi.nat44_del_session(
- address=sessions[0].inside_ip_address,
- port=sessions[0].inside_port,
- protocol=sessions[0].protocol,
- flags=(self.config_flags.NAT_IS_INSIDE |
- self.config_flags.NAT_IS_EXT_HOST_VALID),
- ext_host_address=sessions[0].ext_host_nat_address,
- ext_host_port=sessions[0].ext_host_nat_port)
- sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
- self.assertEqual(len(sessions), 0)
-
- def test_twice_nat(self):
- """ Twice NAT44 """
- self.twice_nat_common()
-
- def test_self_twice_nat_positive(self):
- """ Self Twice NAT44 (positive test) """
- self.twice_nat_common(self_twice_nat=True, same_pg=True)
-
- def test_self_twice_nat_negative(self):
- """ Self Twice NAT44 (negative test) """
- self.twice_nat_common(self_twice_nat=True)
-
- def test_twice_nat_lb(self):
- """ Twice NAT44 local service load balancing """
- self.twice_nat_common(lb=True)
-
- def test_self_twice_nat_lb_positive(self):
- """ Self Twice NAT44 local service load balancing (positive test) """
- self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
- client_id=1)
-
- def test_self_twice_nat_lb_negative(self):
- """ Self Twice NAT44 local service load balancing (negative test) """
- self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
- client_id=2)
-
- def test_twice_nat_interface_addr(self):
- """ Acquire twice NAT44 addresses from interface """
- flags = self.config_flags.NAT_IS_TWICE_NAT
- self.vapi.nat44_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg3.sw_if_index,
- flags=flags)
-
- # no address in NAT pool
- adresses = self.vapi.nat44_address_dump()
- self.assertEqual(0, len(adresses))
-
- # configure interface address and check NAT address pool
- self.pg3.config_ip4()
- adresses = self.vapi.nat44_address_dump()
- self.assertEqual(1, len(adresses))
- self.assertEqual(str(adresses[0].ip_address),
- self.pg3.local_ip4)
- self.assertEqual(adresses[0].flags, flags)
-
- # remove interface address and check NAT address pool
- self.pg3.unconfig_ip4()
- adresses = self.vapi.nat44_address_dump()
- self.assertEqual(0, len(adresses))
-
- def test_tcp_close(self):
- """ Close TCP session from inside network - output feature """
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.pg1.local_ip4)
- twice_nat_addr = '10.0.1.3'
- service_ip = '192.168.16.150'
- self.nat44_add_address(twice_nat_addr, twice_nat=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
- flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
- self.config_flags.NAT_IS_TWICE_NAT)
- self.nat44_add_static_mapping(self.pg0.remote_ip4,
- service_ip,
- 80,
- 80,
- proto=IP_PROTOS.tcp,
- flags=flags)
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- start_sessnum = len(sessions)
-
- # SYN packet out->in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=service_ip) /
- TCP(sport=33898, dport=80, flags="S"))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- tcp_port = p[TCP].sport
-
- # SYN + ACK packet in->out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
- TCP(sport=80, dport=tcp_port, flags="SA"))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # ACK packet out->in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=service_ip) /
- TCP(sport=33898, dport=80, flags="A"))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
- TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # FIN+ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=service_ip) /
- TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
- TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 0)
-
- def test_tcp_session_close_in(self):
- """ Close TCP session from inside network """
- self.tcp_port_out = 10505
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_TWICE_NAT
- self.nat44_add_static_mapping(self.pg0.remote_ip4,
- self.nat_addr,
- self.tcp_port_in,
- self.tcp_port_out,
- proto=IP_PROTOS.tcp,
- flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- start_sessnum = len(sessions)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
-
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=100, ack=300))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- pkts = []
-
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=300, ack=101))
- pkts.append(p)
-
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=300, ack=101))
- pkts.append(p)
-
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(2)
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A", seq=101, ack=301))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 0)
-
- def test_tcp_session_close_out(self):
- """ Close TCP session from outside network """
- self.tcp_port_out = 10505
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_TWICE_NAT
- self.nat44_add_static_mapping(self.pg0.remote_ip4,
- self.nat_addr,
- self.tcp_port_in,
- self.tcp_port_out,
- proto=IP_PROTOS.tcp,
- flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- start_sessnum = len(sessions)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
-
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=100, ack=300))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- # FIN+ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=300, ack=101))
-
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=101, ack=301))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 0)
-
- def test_tcp_session_close_simultaneous(self):
- """ Close TCP session from inside network """
- self.tcp_port_out = 10505
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_TWICE_NAT
- self.nat44_add_static_mapping(self.pg0.remote_ip4,
- self.nat_addr,
- self.tcp_port_in,
- self.tcp_port_out,
- proto=IP_PROTOS.tcp,
- flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
- start_sessnum = len(sessions)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
-
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=100, ack=300))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=300, ack=100))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A", seq=101, ack=301))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=301, ack=101))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 0)
-
- def test_one_armed_nat44_static(self):
- """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
- remote_host = self.pg4.remote_hosts[0]
- local_host = self.pg4.remote_hosts[1]
- external_port = 80
- local_port = 8080
- eh_port_in = 0
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr, twice_nat=1)
- flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
- self.config_flags.NAT_IS_TWICE_NAT)
- self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
- local_port, external_port,
- proto=IP_PROTOS.tcp, flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg4.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg4.sw_if_index,
- flags=flags, is_add=1)
-
- # from client to service
- p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
- IP(src=remote_host.ip4, dst=self.nat_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg4.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg4.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, local_host.ip4)
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.dport, local_port)
- self.assertNotEqual(tcp.sport, 12345)
- eh_port_in = tcp.sport
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client
- p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
- IP(src=local_host.ip4, dst=self.nat_addr) /
- TCP(sport=local_port, dport=eh_port_in))
- self.pg4.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg4.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, remote_host.ip4)
- self.assertEqual(tcp.sport, external_port)
- self.assertEqual(tcp.dport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_static_with_port_out2(self):
- """ 1:1 NAPT asymmetrical rule """
-
- external_port = 80
- local_port = 8080
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- flags = self.config_flags.NAT_IS_OUT2IN_ONLY
- self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
- local_port, external_port,
- proto=IP_PROTOS.tcp, flags=flags)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # from client to service
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # ICMP error
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- ICMP(type=11) / capture[0][IP])
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- self.assertEqual(p[IP].src, self.nat_addr)
- inner = p[IPerror]
- self.assertEqual(inner.dst, self.nat_addr)
- self.assertEqual(inner[TCPerror].dport, external_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # ICMP error
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- ICMP(type=11) / capture[0][IP])
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
- inner = p[IPerror]
- self.assertEqual(inner.src, self.pg0.remote_ip4)
- self.assertEqual(inner[TCPerror].sport, local_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client to server (no translation)
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
- TCP(sport=12346, dport=local_port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client (no translation)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=local_port, dport=12346))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg0.remote_ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_output_feature(self):
- """ NAT44 interface output feature (in2out postrouting) """
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture)
-
- # out2in
- pkts = self.create_stream_out(self.pg1)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- def test_multiple_vrf(self):
- """ Multiple VRF setup """
- external_addr = '1.2.3.4'
- external_port = 80
- local_port = 8080
- port = 0
-
- self.vapi.nat44_forwarding_enable_disable(enable=1)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_output_feature(
- is_add=1,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg5.sw_if_index,
- is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg5.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg6.sw_if_index,
- is_add=1)
- flags = self.config_flags.NAT_IS_OUT2IN_ONLY
- self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
- local_port, external_port, vrf_id=1,
- proto=IP_PROTOS.tcp, flags=flags)
- self.nat44_add_static_mapping(
- self.pg0.remote_ip4,
- external_sw_if_index=self.pg0.sw_if_index,
- local_port=local_port,
- vrf_id=0,
- external_port=external_port,
- proto=IP_PROTOS.tcp,
- flags=flags
- )
-
- # from client to service (both VRF1)
- p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
- IP(src=self.pg6.remote_ip4, dst=external_addr) /
- TCP(sport=12345, dport=external_port))
- self.pg6.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg5.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service back to client (both VRF1)
- p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
- IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
- TCP(sport=local_port, dport=12345))
- self.pg5.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, external_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # dynamic NAT from VRF1 to VRF0 (output-feature)
- p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
- IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=2345, dport=22))
- self.pg5.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertNotEqual(tcp.sport, 2345)
- self.assert_packet_checksums_valid(p)
- port = tcp.sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=22, dport=port))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg5.remote_ip4)
- self.assertEqual(tcp.dport, 2345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client VRF1 to service VRF0
- p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
- IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
- TCP(sport=12346, dport=external_port))
- self.pg6.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg0.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service VRF0 back to client VRF1
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
- TCP(sport=local_port, dport=12346))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg0.local_ip4)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client VRF0 to service VRF1
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=external_addr) /
- TCP(sport=12347, dport=external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg5.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from service VRF1 back to client VRF0
- p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
- IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
- TCP(sport=local_port, dport=12347))
- self.pg5.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, external_addr)
- self.assertEqual(tcp.sport, external_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client to server (both VRF1, no translation)
- p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
- IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
- TCP(sport=12348, dport=local_port))
- self.pg6.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg5.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from server back to client (both VRF1, no translation)
- p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
- IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
- TCP(sport=local_port, dport=12348))
- self.pg5.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg5.remote_ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client VRF1 to server VRF0 (no translation)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
- TCP(sport=local_port, dport=12349))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg0.remote_ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from server VRF0 back to client VRF1 (no translation)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
- TCP(sport=local_port, dport=12349))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg6.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg0.remote_ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from client VRF0 to server VRF1 (no translation)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
- TCP(sport=12344, dport=local_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg5.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.dst, self.pg5.remote_ip4)
- self.assertEqual(tcp.dport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # from server VRF1 back to client VRF0 (no translation)
- p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
- IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
- TCP(sport=local_port, dport=12344))
- self.pg5.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg5.remote_ip4)
- self.assertEqual(tcp.sport, local_port)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_timeout(self):
- """ NAT44 session timeouts """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
- tcp_transitory=240, icmp=5)
-
- max_sessions = 1000
- pkts = []
- for i in range(0, max_sessions):
- src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=src, dst=self.pg1.remote_ip4) /
- ICMP(id=1025, type='echo-request'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(max_sessions)
-
- sleep(10)
-
- pkts = []
- for i in range(0, max_sessions):
- src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=src, dst=self.pg1.remote_ip4) /
- ICMP(id=1026, type='echo-request'))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(max_sessions)
-
- nsessions = 0
- users = self.vapi.nat44_user_dump()
- for user in users:
- nsessions = nsessions + user.nsessions
- self.assertLess(nsessions, 2 * max_sessions)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_rst_timeout(self):
- """ NAT44 session RST timeouts """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
- tcp_transitory=5, icmp=60)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="R"))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- sleep(6)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
- flags="S"))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- nsessions = 0
- users = self.vapi.nat44_user_dump()
- self.assertEqual(len(users), 1)
- self.assertEqual(str(users[0].ip_address),
- self.pg0.remote_ip4)
- self.assertEqual(users[0].nsessions, 1)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_limit_per_user(self):
- """ Maximum sessions per user limit """
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
- src_address=self.pg2.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
- tcp_transitory=240, icmp=60)
-
- # get maximum number of translations per user
- nat44_config = self.vapi.nat_show_config()
-
- pkts = []
- for port in range(0, nat44_config.max_translations_per_user):
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=1025 + port, dport=1025 + port))
- pkts.append(p)
-
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
-
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=3001, dport=3002))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.assert_nothing_captured()
-
- # verify IPFIX logging
- self.vapi.ipfix_flush()
- sleep(1)
- capture = self.pg2.get_capture(10)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_entries_per_user(
- data,
- nat44_config.max_translations_per_user,
- self.pg0.remote_ip4n)
-
- sleep(6)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=3001, dport=3002))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- def test_syslog_sess(self):
- """ Test syslog session creation and deletion """
- self.vapi.syslog_set_filter(
- self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
- self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
- self.nat44_add_address(self.nat_addr)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- self.tcp_port_out = capture[0][TCP].sport
- capture = self.pg2.get_capture(1)
- self.verify_syslog_sess(capture[0][Raw].load)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.nat44_add_address(self.nat_addr, is_add=0)
- capture = self.pg2.get_capture(1)
- self.verify_syslog_sess(capture[0][Raw].load, False)
-
- def tearDown(self):
- super(TestNAT44EndpointDependent, self).tearDown()
- if not self.vpp_dead:
- self.clear_nat44()
- self.vapi.cli("clear logging")
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat44 addresses"))
- self.logger.info(self.vapi.cli("show nat44 interfaces"))
- self.logger.info(self.vapi.cli("show nat44 static mappings"))
- self.logger.info(self.vapi.cli("show nat44 interface address"))
- self.logger.info(self.vapi.cli("show nat44 sessions detail"))
- self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
- self.logger.info(self.vapi.cli("show nat timeouts"))
-
-
-class TestNAT44Out2InDPO(MethodHolder):
- """ NAT44 Test Cases using out2in DPO """
-
- @classmethod
- def setUpConstants(cls):
- super(TestNAT44Out2InDPO, cls).setUpConstants()
- cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
-
- @classmethod
- def setUpClass(cls):
- super(TestNAT44Out2InDPO, cls).setUpClass()
- cls.vapi.cli("set log class nat level debug")
-
- try:
- cls.tcp_port_in = 6303
- cls.tcp_port_out = 6303
- cls.udp_port_in = 6304
- cls.udp_port_out = 6304
- cls.icmp_id_in = 6305
- cls.icmp_id_out = 6305
- cls.nat_addr = '10.0.0.3'
- cls.dst_ip4 = '192.168.70.1'
-
- cls.create_pg_interfaces(range(2))
-
- cls.pg0.admin_up()
- cls.pg0.config_ip4()
- cls.pg0.resolve_arp()
-
- cls.pg1.admin_up()
- cls.pg1.config_ip6()
- cls.pg1.resolve_ndp()
-
- r1 = VppIpRoute(cls, "::", 0,
- [VppRoutePath(cls.pg1.remote_ip6,
- cls.pg1.sw_if_index)],
- register=False)
- r1.add_vpp_config()
-
- except Exception:
- super(TestNAT44Out2InDPO, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestNAT44Out2InDPO, cls).tearDownClass()
-
- def configure_xlat(self):
- self.dst_ip6_pfx = '1:2:3::'
- self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
- self.dst_ip6_pfx)
- self.dst_ip6_pfx_len = 96
- self.src_ip6_pfx = '4:5:6::'
- self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
- self.src_ip6_pfx)
- self.src_ip6_pfx_len = 96
- self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
- self.src_ip6_pfx_n, self.src_ip6_pfx_len,
- '\x00\x00\x00\x00', 0)
-
- @unittest.skip('Temporary disabled')
- def test_464xlat_ce(self):
- """ Test 464XLAT CE with NAT44 """
-
- nat_config = self.vapi.nat_show_config()
- self.assertEqual(1, nat_config.out2in_dpo)
-
- self.configure_xlat()
-
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
- last_ip_address=self.nat_addr_n,
- vrf_id=0xFFFFFFFF, is_add=1)
-
- out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
- self.dst_ip6_pfx_len)
- out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
- self.src_ip6_pfx_len)
-
- try:
- pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
- dst_ip=out_src_ip6)
-
- pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
- out_dst_ip6)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
- finally:
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags)
- self.vapi.nat44_add_del_address_range(
- first_ip_address=self.nat_addr_n,
- last_ip_address=self.nat_addr_n,
- vrf_id=0xFFFFFFFF)
-
- @unittest.skip('Temporary disabled')
- def test_464xlat_ce_no_nat(self):
- """ Test 464XLAT CE without NAT44 """
-
- self.configure_xlat()
-
- out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
- self.dst_ip6_pfx_len)
- out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
- self.src_ip6_pfx_len)
-
- pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
- nat_ip=out_dst_ip6, same_port=True)
-
- pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
-
-class TestDeterministicNAT(MethodHolder):
- """ Deterministic NAT Test Cases """
-
- @classmethod
- def setUpConstants(cls):
- super(TestDeterministicNAT, cls).setUpConstants()
- cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
-
- @classmethod
- def setUpClass(cls):
- super(TestDeterministicNAT, cls).setUpClass()
- cls.vapi.cli("set log class nat level debug")
-
- try:
- cls.tcp_port_in = 6303
- cls.tcp_external_port = 6303
- cls.udp_port_in = 6304
- cls.udp_external_port = 6304
- cls.icmp_id_in = 6305
- cls.nat_addr = '10.0.0.3'
-
- cls.create_pg_interfaces(range(3))
- cls.interfaces = list(cls.pg_interfaces)
-
- for i in cls.interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
-
- cls.pg0.generate_remote_hosts(2)
- cls.pg0.configure_ipv4_neighbors()
-
- except Exception:
- super(TestDeterministicNAT, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestDeterministicNAT, cls).tearDownClass()
-
- def create_stream_in(self, in_if, out_if, ttl=64):
- """
- Create packet stream for inside network
-
- :param in_if: Inside interface
- :param out_if: Outside interface
- :param ttl: TTL of generated packets
- """
- pkts = []
- # TCP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
- UDP(sport=self.udp_port_in, dport=self.udp_external_port))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
- IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
- ICMP(id=self.icmp_id_in, type='echo-request'))
- pkts.append(p)
-
- return pkts
-
- def create_stream_out(self, out_if, dst_ip=None, ttl=64):
- """
- Create packet stream for outside network
-
- :param out_if: Outside interface
- :param dst_ip: Destination IP address (Default use global NAT address)
- :param ttl: TTL of generated packets
- """
- if dst_ip is None:
- dst_ip = self.nat_addr
- pkts = []
- # TCP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
- pkts.append(p)
-
- # UDP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- UDP(dport=self.udp_port_out, sport=self.udp_external_port))
- pkts.append(p)
-
- # ICMP
- p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
- IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
- ICMP(id=self.icmp_external_id, type='echo-reply'))
- pkts.append(p)
-
- return pkts
-
- def verify_capture_out(self, capture, nat_ip=None):
- """
- Verify captured packets on outside network
-
- :param capture: Captured packets
- :param nat_ip: Translated IP address (Default use global NAT address)
- :param same_port: Source port number is not translated (Default False)
- """
- if nat_ip is None:
- nat_ip = self.nat_addr
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, nat_ip)
- if packet.haslayer(TCP):
- self.tcp_port_out = packet[TCP].sport
- elif packet.haslayer(UDP):
- self.udp_port_out = packet[UDP].sport
- else:
- self.icmp_external_id = packet[ICMP].id
- except:
- self.logger.error(ppp("Unexpected or invalid packet "
- "(outside network):", packet))
- raise
-
- def test_deterministic_mode(self):
- """ NAT plugin run deterministic mode """
- in_addr = '172.16.255.0'
- out_addr = '172.17.255.50'
- in_addr_t = '172.16.255.20'
- in_plen = 24
- out_plen = 32
-
- nat_config = self.vapi.nat_show_config()
- self.assertEqual(1, nat_config.deterministic)
-
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
- in_plen=in_plen, out_addr=out_addr,
- out_plen=out_plen)
-
- rep1 = self.vapi.nat_det_forward(in_addr_t)
- self.assertEqual(str(rep1.out_addr), out_addr)
- rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
-
- self.assertEqual(str(rep2.in_addr), in_addr_t)
-
- deterministic_mappings = self.vapi.nat_det_map_dump()
- self.assertEqual(len(deterministic_mappings), 1)
- dsm = deterministic_mappings[0]
- self.assertEqual(in_addr, str(dsm.in_addr))
- self.assertEqual(in_plen, dsm.in_plen)
- self.assertEqual(out_addr, str(dsm.out_addr))
- self.assertEqual(out_plen, dsm.out_plen)
-
- self.clear_nat_det()
- deterministic_mappings = self.vapi.nat_det_map_dump()
- self.assertEqual(len(deterministic_mappings), 0)
-
- def test_set_timeouts(self):
- """ Set deterministic NAT timeouts """
- timeouts_before = self.vapi.nat_get_timeouts()
-
- self.vapi.nat_set_timeouts(
- udp=timeouts_before.udp + 10,
- tcp_established=timeouts_before.tcp_established + 10,
- tcp_transitory=timeouts_before.tcp_transitory + 10,
- icmp=timeouts_before.icmp + 10)
-
- timeouts_after = self.vapi.nat_get_timeouts()
-
- self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
- self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
- self.assertNotEqual(timeouts_before.tcp_established,
- timeouts_after.tcp_established)
- self.assertNotEqual(timeouts_before.tcp_transitory,
- timeouts_after.tcp_transitory)
-
- def test_det_in(self):
- """ Deterministic NAT translation test (TCP, UDP, ICMP) """
-
- nat_ip = "10.0.0.10"
-
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
- in_plen=32,
- out_addr=socket.inet_aton(nat_ip),
- out_plen=32)
-
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # in2out
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip)
-
- # out2in
- pkts = self.create_stream_out(self.pg1, nat_ip)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in(capture, self.pg0)
-
- # session dump test
- sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
- self.assertEqual(len(sessions), 3)
-
- # TCP session
- s = sessions[0]
- self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
- self.assertEqual(s.in_port, self.tcp_port_in)
- self.assertEqual(s.out_port, self.tcp_port_out)
- self.assertEqual(s.ext_port, self.tcp_external_port)
-
- # UDP session
- s = sessions[1]
- self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
- self.assertEqual(s.in_port, self.udp_port_in)
- self.assertEqual(s.out_port, self.udp_port_out)
- self.assertEqual(s.ext_port, self.udp_external_port)
-
- # ICMP session
- s = sessions[2]
- self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
- self.assertEqual(s.in_port, self.icmp_id_in)
- self.assertEqual(s.out_port, self.icmp_external_id)
-
- def test_multiple_users(self):
- """ Deterministic NAT multiple users """
-
- nat_ip = "10.0.0.10"
- port_in = 80
- external_port = 6303
-
- host0 = self.pg0.remote_hosts[0]
- host1 = self.pg0.remote_hosts[1]
-
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4n, in_plen=24,
- out_addr=socket.inet_aton(nat_ip),
- out_plen=32)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- # host0 to out
- p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
- IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=port_in, dport=external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, nat_ip)
- self.assertEqual(ip.dst, self.pg1.remote_ip4)
- self.assertEqual(tcp.dport, external_port)
- port_out0 = tcp.sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # host1 to out
- p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
- IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=port_in, dport=external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, nat_ip)
- self.assertEqual(ip.dst, self.pg1.remote_ip4)
- self.assertEqual(tcp.dport, external_port)
- port_out1 = tcp.sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(1, len(dms))
- self.assertEqual(2, dms[0].ses_num)
-
- # out to host0
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=nat_ip) /
- TCP(sport=external_port, dport=port_out0))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg1.remote_ip4)
- self.assertEqual(ip.dst, host0.ip4)
- self.assertEqual(tcp.dport, port_in)
- self.assertEqual(tcp.sport, external_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # out to host1
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=nat_ip) /
- TCP(sport=external_port, dport=port_out1))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.pg1.remote_ip4)
- self.assertEqual(ip.dst, host1.ip4)
- self.assertEqual(tcp.dport, port_in)
- self.assertEqual(tcp.sport, external_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet", p))
- raise
-
- # session close api test
- self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
- port_out1,
- self.pg1.remote_ip4n,
- external_port)
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(dms[0].ses_num, 1)
-
- self.vapi.nat_det_close_session_in(host0.ip4n,
- port_in,
- self.pg1.remote_ip4n,
- external_port)
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(dms[0].ses_num, 0)
-
- def test_tcp_session_close_detection_in(self):
- """ Deterministic NAT TCP session close from inside network """
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
- in_plen=32,
- out_addr=socket.inet_aton(self.nat_addr),
- out_plen=32)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
-
- # close the session from inside
- try:
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="F"))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- pkts = []
-
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A"))
- pkts.append(p)
-
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="F"))
- pkts.append(p)
-
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(2)
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A"))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
-
- # Check if deterministic NAT44 closed the session
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(0, dms[0].ses_num)
- except:
- self.logger.error("TCP session termination failed")
- raise
-
- def test_tcp_session_close_detection_out(self):
- """ Deterministic NAT TCP session close from outside network """
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
- in_plen=32,
- out_addr=socket.inet_aton(self.nat_addr),
- out_plen=32)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
-
- # close the session from outside
- try:
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="F"))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- pkts = []
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A"))
- pkts.append(p)
-
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="F"))
- pkts.append(p)
-
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(2)
-
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A"))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
-
- # Check if deterministic NAT44 closed the session
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(0, dms[0].ses_num)
- except:
- self.logger.error("TCP session termination failed")
- raise
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_timeout(self):
- """ Deterministic NAT session timeouts """
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
- in_plen=32,
- out_addr=socket.inet_aton(self.nat_addr),
- out_plen=32)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
-
- self.initiate_tcp_session(self.pg0, self.pg1)
- self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
- icmp=5)
- pkts = self.create_stream_in(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- sleep(15)
-
- dms = self.vapi.nat_det_map_dump()
- self.assertEqual(0, dms[0].ses_num)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_limit_per_user(self):
- """ Deterministic NAT maximum sessions per user limit """
- self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4n,
- in_plen=32,
- out_addr=socket.inet_aton(self.nat_addr),
- out_plen=32)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg0.sw_if_index,
- flags=flags, is_add=1)
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=self.pg1.sw_if_index,
- is_add=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
- src_address=self.pg2.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
- enable=1)
-
- pkts = []
- for port in range(1025, 2025):
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=port, dport=port))
- pkts.append(p)
-
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=3001, dport=3002))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.assert_nothing_captured()
-
- # verify ICMP error packet
- capture = self.pg0.get_capture(1)
- p = capture[0]
- self.assertTrue(p.haslayer(ICMP))
- icmp = p[ICMP]
- self.assertEqual(icmp.type, 3)
- self.assertEqual(icmp.code, 1)
- self.assertTrue(icmp.haslayer(IPerror))
- inner_ip = icmp[IPerror]
- self.assertEqual(inner_ip[UDPerror].sport, 3001)
- self.assertEqual(inner_ip[UDPerror].dport, 3002)
-
- dms = self.vapi.nat_det_map_dump()
-
- self.assertEqual(1000, dms[0].ses_num)
-
- # verify IPFIX logging
- self.vapi.ipfix_flush()
- sleep(1)
- capture = self.pg2.get_capture(2)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_entries_per_user(data,
- 1000,
- self.pg0.remote_ip4n)
-
- def clear_nat_det(self):
- """
- Clear deterministic NAT configuration.
- """
- self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
- enable=0)
- self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
- tcp_transitory=240, icmp=60)
- deterministic_mappings = self.vapi.nat_det_map_dump()
- for dsm in deterministic_mappings:
- self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
- in_plen=dsm.in_plen,
- out_addr=dsm.out_addr,
- out_plen=dsm.out_plen)
-
- interfaces = self.vapi.nat44_interface_dump()
- for intf in interfaces:
- self.vapi.nat44_interface_add_del_feature(
- sw_if_index=intf.sw_if_index,
- flags=intf.flags)
-
- def tearDown(self):
- super(TestDeterministicNAT, self).tearDown()
- if not self.vpp_dead:
- self.clear_nat_det()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat44 interfaces"))
- self.logger.info(self.vapi.cli("show nat timeouts"))
- self.logger.info(
- self.vapi.cli("show nat44 deterministic mappings"))
- self.logger.info(
- self.vapi.cli("show nat44 deterministic sessions"))
-
-
-class TestNAT64(MethodHolder):
- """ NAT64 Test Cases """
-
- @classmethod
- def setUpConstants(cls):
- super(TestNAT64, cls).setUpConstants()
- cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
- "nat64 st hash buckets 256", "}"])
-
- @classmethod
- def setUpClass(cls):
- super(TestNAT64, cls).setUpClass()
-
- try:
- cls.tcp_port_in = 6303
- cls.tcp_port_out = 6303
- cls.udp_port_in = 6304
- cls.udp_port_out = 6304
- cls.icmp_id_in = 6305
- cls.icmp_id_out = 6305
- cls.tcp_external_port = 80
- cls.nat_addr = '10.0.0.3'
- cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
- cls.vrf1_id = 10
- cls.vrf1_nat_addr = '10.0.10.3'
- cls.ipfix_src_port = 4739
- cls.ipfix_domain_id = 1
-
- cls.create_pg_interfaces(range(6))
- cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
- cls.ip6_interfaces.append(cls.pg_interfaces[2])
- cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
-
- cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
- table_id=cls.vrf1_id)
-
- cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
-
- cls.pg0.generate_remote_hosts(2)
-
- for i in cls.ip6_interfaces:
- i.admin_up()
- i.config_ip6()
- i.configure_ipv6_neighbors()
-
- for i in cls.ip4_interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
-
- cls.pg3.admin_up()
- cls.pg3.config_ip4()
- cls.pg3.resolve_arp()
- cls.pg3.config_ip6()
- cls.pg3.configure_ipv6_neighbors()
-
- cls.pg5.admin_up()
- cls.pg5.config_ip6()
-
- except Exception:
- super(TestNAT64, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestNAT64, cls).tearDownClass()
-
- def test_nat64_inside_interface_handles_neighbor_advertisement(self):
- """ NAT64 inside interface handles Neighbor Advertisement """
-
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg5.sw_if_index)
-
- # Try to send ping
- ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
- IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
- ICMPv6EchoRequest())
- pkts = [ping]
- self.pg5.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Wait for Neighbor Solicitation
- capture = self.pg5.get_capture(len(pkts))
- packet = capture[0]
- try:
- self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
- self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
- tgt = packet[ICMPv6ND_NS].tgt
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # Send Neighbor Advertisement
- p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
- IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
- ICMPv6ND_NA(tgt=tgt) /
- ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
- pkts = [p]
- self.pg5.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Try to send ping again
- pkts = [ping]
- self.pg5.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- # Wait for ping reply
- capture = self.pg5.get_capture(len(pkts))
- packet = capture[0]
- try:
- self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
- self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
- self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_pool(self):
- """ Add/delete address to NAT64 pool """
- nat_addr = '1.2.3.4'
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
- end_addr=nat_addr,
- vrf_id=0xFFFFFFFF, is_add=1)
-
- addresses = self.vapi.nat64_pool_addr_dump()
- self.assertEqual(len(addresses), 1)
- self.assertEqual(str(addresses[0].address), nat_addr)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
- end_addr=nat_addr,
- vrf_id=0xFFFFFFFF, is_add=0)
-
- addresses = self.vapi.nat64_pool_addr_dump()
- self.assertEqual(len(addresses), 0)
-
- def test_interface(self):
- """ Enable/disable NAT64 feature on the interface """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- interfaces = self.vapi.nat64_interface_dump()
- self.assertEqual(len(interfaces), 2)
- pg0_found = False
- pg1_found = False
- for intf in interfaces:
- if intf.sw_if_index == self.pg0.sw_if_index:
- self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
- pg0_found = True
- elif intf.sw_if_index == self.pg1.sw_if_index:
- self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
- pg1_found = True
- self.assertTrue(pg0_found)
- self.assertTrue(pg1_found)
-
- features = self.vapi.cli("show interface features pg0")
- self.assertIn('nat64-in2out', features)
- features = self.vapi.cli("show interface features pg1")
- self.assertIn('nat64-out2in', features)
-
- self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
- sw_if_index=self.pg1.sw_if_index)
-
- interfaces = self.vapi.nat64_interface_dump()
- self.assertEqual(len(interfaces), 0)
-
- def test_static_bib(self):
- """ Add/delete static BIB entry """
- in_addr = '2001:db8:85a3::8a2e:370:7334'
- out_addr = '10.1.1.3'
- in_port = 1234
- out_port = 5678
- proto = IP_PROTOS.tcp
-
- self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
- i_port=in_port, o_port=out_port,
- proto=proto, vrf_id=0, is_add=1)
- bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
- static_bib_num = 0
- for bibe in bib:
- if bibe.flags & self.config_flags.NAT_IS_STATIC:
- static_bib_num += 1
- self.assertEqual(str(bibe.i_addr), in_addr)
- self.assertEqual(str(bibe.o_addr), out_addr)
- self.assertEqual(bibe.i_port, in_port)
- self.assertEqual(bibe.o_port, out_port)
- self.assertEqual(static_bib_num, 1)
- bibs = self.statistics.get_counter('/nat64/total-bibs')
- self.assertEqual(bibs[0][0], 1)
-
- self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
- i_port=in_port, o_port=out_port,
- proto=proto, vrf_id=0, is_add=0)
- bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
- static_bib_num = 0
- for bibe in bib:
- if bibe.flags & self.config_flags.NAT_IS_STATIC:
- static_bib_num += 1
- self.assertEqual(static_bib_num, 0)
- bibs = self.statistics.get_counter('/nat64/total-bibs')
- self.assertEqual(bibs[0][0], 0)
-
- def test_set_timeouts(self):
- """ Set NAT64 timeouts """
- # verify default values
- timeouts = self.vapi.nat_get_timeouts()
- self.assertEqual(timeouts.udp, 300)
- self.assertEqual(timeouts.icmp, 60)
- self.assertEqual(timeouts.tcp_transitory, 240)
- self.assertEqual(timeouts.tcp_established, 7440)
-
- # set and verify custom values
- self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
- tcp_transitory=250, icmp=30)
- timeouts = self.vapi.nat_get_timeouts()
- self.assertEqual(timeouts.udp, 200)
- self.assertEqual(timeouts.icmp, 30)
- self.assertEqual(timeouts.tcp_transitory, 250)
- self.assertEqual(timeouts.tcp_established, 7450)
-
- def test_dynamic(self):
- """ NAT64 dynamic translation test """
- self.tcp_port_in = 6303
- self.udp_port_in = 6304
- self.icmp_id_in = 6305
-
- ses_num_start = self.nat64_get_ses_num()
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- # in2out
- tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
- udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat64-in2out/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat64-in2out/good in2out packets processed')
-
- pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat64-in2out/good in2out packets processed')
- self.assertEqual(err - totaln, 3)
-
- # out2in
- tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
- udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
- icmpn = self.statistics.get_err_counter(
- '/err/nat64-out2in/ICMP packets')
- totaln = self.statistics.get_err_counter(
- '/err/nat64-out2in/good out2in packets processed')
-
- pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
- self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
-
- err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
- self.assertEqual(err - tcpn, 1)
- err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
- self.assertEqual(err - udpn, 1)
- err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
- self.assertEqual(err - icmpn, 1)
- err = self.statistics.get_err_counter(
- '/err/nat64-out2in/good out2in packets processed')
- self.assertEqual(err - totaln, 3)
-
- bibs = self.statistics.get_counter('/nat64/total-bibs')
- self.assertEqual(bibs[0][0], 3)
- sessions = self.statistics.get_counter('/nat64/total-sessions')
- self.assertEqual(sessions[0][0], 3)
-
- # in2out
- pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- # out2in
- pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
-
- ses_num_end = self.nat64_get_ses_num()
-
- self.assertEqual(ses_num_end - ses_num_start, 3)
-
- # tenant with specific VRF
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
- end_addr=self.vrf1_nat_addr,
- vrf_id=self.vrf1_id, is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg2.sw_if_index)
-
- pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
- self.pg2.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
-
- def test_static(self):
- """ NAT64 static translation test """
- self.tcp_port_in = 60303
- self.udp_port_in = 60304
- self.icmp_id_in = 60305
- self.tcp_port_out = 60303
- self.udp_port_out = 60304
- self.icmp_id_out = 60305
-
- ses_num_start = self.nat64_get_ses_num()
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
- o_addr=self.nat_addr,
- i_port=self.tcp_port_in,
- o_port=self.tcp_port_out,
- proto=IP_PROTOS.tcp, vrf_id=0,
- is_add=1)
- self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
- o_addr=self.nat_addr,
- i_port=self.udp_port_in,
- o_port=self.udp_port_out,
- proto=IP_PROTOS.udp, vrf_id=0,
- is_add=1)
- self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
- o_addr=self.nat_addr,
- i_port=self.icmp_id_in,
- o_port=self.icmp_id_out,
- proto=IP_PROTOS.icmp, vrf_id=0,
- is_add=1)
-
- # in2out
- pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.nat_addr,
- dst_ip=self.pg1.remote_ip4, same_port=True)
-
- # out2in
- pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
- self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
-
- ses_num_end = self.nat64_get_ses_num()
-
- self.assertEqual(ses_num_end - ses_num_start, 3)
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_session_timeout(self):
- """ NAT64 session timeout """
- self.icmp_id_in = 1234
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
- tcp_transitory=5,
- icmp=5)
-
- pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
-
- ses_num_before_timeout = self.nat64_get_ses_num()
-
- sleep(15)
-
- # ICMP and TCP session after timeout
- ses_num_after_timeout = self.nat64_get_ses_num()
- self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
-
- def test_icmp_error(self):
- """ NAT64 ICMP Error message translation """
- self.tcp_port_in = 6303
- self.udp_port_in = 6304
- self.icmp_id_in = 6305
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- # send some packets to create sessions
- pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture_ip4 = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture_ip4,
- nat_ip=self.nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture_ip6 = self.pg0.get_capture(len(pkts))
- ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
- self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
- self.pg0.remote_ip6)
-
- # in2out
- pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
- ICMPv6DestUnreach(code=1) /
- packet[IPv6] for packet in capture_ip6]
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IP].src, self.nat_addr)
- self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(packet[ICMP].type, 3)
- self.assertEqual(packet[ICMP].code, 13)
- inner = packet[IPerror]
- self.assertEqual(inner.src, self.pg1.remote_ip4)
- self.assertEqual(inner.dst, self.nat_addr)
- self.assert_packet_checksums_valid(packet)
- if inner.haslayer(TCPerror):
- self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
- elif inner.haslayer(UDPerror):
- self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
- else:
- self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # out2in
- pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- ICMP(type=3, code=13) /
- packet[IP] for packet in capture_ip4]
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, ip.src)
- self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
- icmp = packet[ICMPv6DestUnreach]
- self.assertEqual(icmp.code, 1)
- inner = icmp[IPerror6]
- self.assertEqual(inner.src, self.pg0.remote_ip6)
- self.assertEqual(inner.dst, ip.src)
- self.assert_icmpv6_checksum_valid(packet)
- if inner.haslayer(TCPerror):
- self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
- elif inner.haslayer(UDPerror):
- self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
- else:
- self.assertEqual(inner[ICMPv6EchoRequest].id,
- self.icmp_id_in)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_hairpinning(self):
- """ NAT64 hairpinning """
-
- client = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
- server_tcp_in_port = 22
- server_tcp_out_port = 4022
- server_udp_in_port = 23
- server_udp_out_port = 4023
- client_tcp_in_port = 1234
- client_udp_in_port = 1235
- client_tcp_out_port = 0
- client_udp_out_port = 0
- ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
- nat_addr_ip6 = ip.src
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
- o_addr=self.nat_addr,
- i_port=server_tcp_in_port,
- o_port=server_tcp_out_port,
- proto=IP_PROTOS.tcp, vrf_id=0,
- is_add=1)
- self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
- o_addr=self.nat_addr,
- i_port=server_udp_in_port,
- o_port=server_udp_out_port,
- proto=IP_PROTOS.udp, vrf_id=0,
- is_add=1)
-
- # client to server
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=client.ip6, dst=nat_addr_ip6) /
- TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=client.ip6, dst=nat_addr_ip6) /
- UDP(sport=client_udp_in_port, dport=server_udp_out_port))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, nat_addr_ip6)
- self.assertEqual(packet[IPv6].dst, server.ip6)
- self.assert_packet_checksums_valid(packet)
- if packet.haslayer(TCP):
- self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
- self.assertEqual(packet[TCP].dport, server_tcp_in_port)
- client_tcp_out_port = packet[TCP].sport
- else:
- self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
- self.assertEqual(packet[UDP].dport, server_udp_in_port)
- client_udp_out_port = packet[UDP].sport
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server to client
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=server.ip6, dst=nat_addr_ip6) /
- TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=server.ip6, dst=nat_addr_ip6) /
- UDP(sport=server_udp_in_port, dport=client_udp_out_port))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, nat_addr_ip6)
- self.assertEqual(packet[IPv6].dst, client.ip6)
- self.assert_packet_checksums_valid(packet)
- if packet.haslayer(TCP):
- self.assertEqual(packet[TCP].sport, server_tcp_out_port)
- self.assertEqual(packet[TCP].dport, client_tcp_in_port)
- else:
- self.assertEqual(packet[UDP].sport, server_udp_out_port)
- self.assertEqual(packet[UDP].dport, client_udp_in_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # ICMP error
- pkts = []
- pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=client.ip6, dst=nat_addr_ip6) /
- ICMPv6DestUnreach(code=1) /
- packet[IPv6] for packet in capture]
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, nat_addr_ip6)
- self.assertEqual(packet[IPv6].dst, server.ip6)
- icmp = packet[ICMPv6DestUnreach]
- self.assertEqual(icmp.code, 1)
- inner = icmp[IPerror6]
- self.assertEqual(inner.src, server.ip6)
- self.assertEqual(inner.dst, nat_addr_ip6)
- self.assert_packet_checksums_valid(packet)
- if inner.haslayer(TCPerror):
- self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
- self.assertEqual(inner[TCPerror].dport,
- client_tcp_out_port)
- else:
- self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
- self.assertEqual(inner[UDPerror].dport,
- client_udp_out_port)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_prefix(self):
- """ NAT64 Network-Specific Prefix """
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
- end_addr=self.vrf1_nat_addr,
- vrf_id=self.vrf1_id, is_add=1)
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg2.sw_if_index)
-
- # Add global prefix
- global_pref64 = "2001:db8::"
- global_pref64_len = 32
- global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
- self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
- is_add=1)
-
- prefix = self.vapi.nat64_prefix_dump()
- self.assertEqual(len(prefix), 1)
- self.assertEqual(prefix[0].prefix,
- IPv6Network(unicode(global_pref64_str)))
- self.assertEqual(prefix[0].vrf_id, 0)
-
- # Add tenant specific prefix
- vrf1_pref64 = "2001:db8:122:300::"
- vrf1_pref64_len = 56
- vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
- self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
- vrf_id=self.vrf1_id, is_add=1)
-
- prefix = self.vapi.nat64_prefix_dump()
- self.assertEqual(len(prefix), 2)
-
- # Global prefix
- pkts = self.create_stream_in_ip6(self.pg0,
- self.pg1,
- pref=global_pref64,
- plen=global_pref64_len)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- dst_ip = self.compose_ip6(self.pg1.remote_ip4,
- global_pref64,
- global_pref64_len)
- self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
-
- # Tenant specific prefix
- pkts = self.create_stream_in_ip6(self.pg2,
- self.pg1,
- pref=vrf1_pref64,
- plen=vrf1_pref64_len)
- self.pg2.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
- dst_ip=self.pg1.remote_ip4)
-
- pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg2.get_capture(len(pkts))
- dst_ip = self.compose_ip6(self.pg1.remote_ip4,
- vrf1_pref64,
- vrf1_pref64_len)
- self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
-
- def test_unknown_proto(self):
- """ NAT64 translate packet with unknown protocol """
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
-
- # in2out
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
- TCP(sport=self.tcp_port_in, dport=20))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
- GRE() /
- IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IP].src, self.nat_addr)
- self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(packet.haslayer(GRE), 1)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # out2in
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IPv6].src, remote_ip6)
- self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
- self.assertEqual(packet[IPv6].nh, 47)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_hairpinning_unknown_proto(self):
- """ NAT64 translate packet with unknown protocol - hairpinning """
-
- client = self.pg0.remote_hosts[0]
- server = self.pg0.remote_hosts[1]
- server_tcp_in_port = 22
- server_tcp_out_port = 4022
- client_tcp_in_port = 1234
- client_tcp_out_port = 1235
- server_nat_ip = "10.0.0.100"
- client_nat_ip = "10.0.0.110"
- server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
- client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
- end_addr=client_nat_ip,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
- o_addr=server_nat_ip,
- i_port=server_tcp_in_port,
- o_port=server_tcp_out_port,
- proto=IP_PROTOS.tcp, vrf_id=0,
- is_add=1)
-
- self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
- o_addr=server_nat_ip, i_port=0,
- o_port=0,
- proto=IP_PROTOS.gre, vrf_id=0,
- is_add=1)
-
- self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
- o_addr=client_nat_ip,
- i_port=client_tcp_in_port,
- o_port=client_tcp_out_port,
- proto=IP_PROTOS.tcp, vrf_id=0,
- is_add=1)
-
- # client to server
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=client.ip6, dst=server_nat_ip6) /
- TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
- GRE() /
- IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IPv6].src, client_nat_ip6)
- self.assertEqual(packet[IPv6].dst, server.ip6)
- self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # server to client
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
- GRE() /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
- TCP(sport=1234, dport=1234))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg0.get_capture(1)
- packet = p[0]
- try:
- self.assertEqual(packet[IPv6].src, server_nat_ip6)
- self.assertEqual(packet[IPv6].dst, client.ip6)
- self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def test_one_armed_nat64(self):
- """ One armed NAT64 """
- external_port = 0
- remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
- '64:ff9b::',
- 96)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg3.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg3.sw_if_index)
-
- # in2out
- p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
- IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
- TCP(sport=12345, dport=80))
- self.pg3.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- ip = p[IP]
- tcp = p[TCP]
- self.assertEqual(ip.src, self.nat_addr)
- self.assertEqual(ip.dst, self.pg3.remote_ip4)
- self.assertNotEqual(tcp.sport, 12345)
- external_port = tcp.sport
- self.assertEqual(tcp.dport, 80)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- # out2in
- p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
- IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
- TCP(sport=80, dport=external_port))
- self.pg3.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg3.get_capture(1)
- p = capture[0]
- try:
- ip = p[IPv6]
- tcp = p[TCP]
- self.assertEqual(ip.src, remote_host_ip6)
- self.assertEqual(ip.dst, self.pg3.remote_ip6)
- self.assertEqual(tcp.sport, 80)
- self.assertEqual(tcp.dport, 12345)
- self.assert_packet_checksums_valid(p)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", p))
- raise
-
- def test_frag_in_order(self):
- """ NAT64 translate fragments arriving in order """
- self.tcp_port_in = random.randint(1025, 65535)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- reass = self.vapi.nat_reass_dump()
- reass_n_start = len(reass)
-
- # in2out
- data = b'a' * 200
- pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
- self.tcp_port_in, 20, data)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.nat_addr,
- self.pg1.remote_ip4)
- self.assertEqual(p[TCP].dport, 20)
- self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
- self.tcp_port_out = p[TCP].sport
- self.assertEqual(data, p[Raw].load)
-
- # out2in
- data = b"A" * 4 + b"b" * 16 + b"C" * 3
- pkts = self.create_stream_frag(self.pg1,
- self.nat_addr,
- 20,
- self.tcp_port_out,
- data)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
- p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
- self.assertEqual(p[TCP].sport, 20)
- self.assertEqual(p[TCP].dport, self.tcp_port_in)
- self.assertEqual(data, p[Raw].load)
-
- reass = self.vapi.nat_reass_dump()
- reass_n_end = len(reass)
-
- self.assertEqual(reass_n_end - reass_n_start, 2)
-
- def test_reass_hairpinning(self):
- """ NAT64 fragments hairpinning """
- data = 'a' * 200
- server = self.pg0.remote_hosts[1]
- server_in_port = random.randint(1025, 65535)
- server_out_port = random.randint(1025, 65535)
- client_in_port = random.randint(1025, 65535)
- ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
- nat_addr_ip6 = ip.src
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- # add static BIB entry for server
- self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
- o_addr=self.nat_addr,
- i_port=server_in_port,
- o_port=server_out_port,
- proto=IP_PROTOS.tcp, vrf_id=0,
- is_add=1)
-
- # send packet from host to server
- pkts = self.create_stream_frag_ip6(self.pg0,
- self.nat_addr,
- client_in_port,
- server_out_port,
- data)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
- self.assertNotEqual(p[TCP].sport, client_in_port)
- self.assertEqual(p[TCP].dport, server_in_port)
- self.assertEqual(data, p[Raw].load)
-
- def test_frag_out_of_order(self):
- """ NAT64 translate fragments arriving out of order """
- self.tcp_port_in = random.randint(1025, 65535)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- # in2out
- data = b'a' * 200
- pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
- self.tcp_port_in, 20, data)
- pkts.reverse()
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg1.get_capture(len(pkts))
- p = self.reass_frags_and_verify(frags,
- self.nat_addr,
- self.pg1.remote_ip4)
- self.assertEqual(p[TCP].dport, 20)
- self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
- self.tcp_port_out = p[TCP].sport
- self.assertEqual(data, p[Raw].load)
-
- # out2in
- data = b"A" * 4 + b"B" * 16 + b"C" * 3
- pkts = self.create_stream_frag(self.pg1,
- self.nat_addr,
- 20,
- self.tcp_port_out,
- data)
- pkts.reverse()
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- frags = self.pg0.get_capture(len(pkts))
- src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
- p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
- self.assertEqual(p[TCP].sport, 20)
- self.assertEqual(p[TCP].dport, self.tcp_port_in)
- self.assertEqual(data, p[Raw].load)
-
- def test_interface_addr(self):
- """ Acquire NAT64 pool addresses from interface """
- self.vapi.nat64_add_del_interface_addr(
- is_add=1,
- sw_if_index=self.pg4.sw_if_index)
-
- # no address in NAT64 pool
- addresses = self.vapi.nat44_address_dump()
- self.assertEqual(0, len(addresses))
-
- # configure interface address and check NAT64 address pool
- self.pg4.config_ip4()
- addresses = self.vapi.nat64_pool_addr_dump()
- self.assertEqual(len(addresses), 1)
-
- self.assertEqual(str(addresses[0].address),
- self.pg4.local_ip4)
-
- # remove interface address and check NAT64 address pool
- self.pg4.unconfig_ip4()
- addresses = self.vapi.nat64_pool_addr_dump()
- self.assertEqual(0, len(addresses))
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_ipfix_max_bibs_sessions(self):
- """ IPFIX logging maximum session and BIB entries exceeded """
- max_bibs = 1280
- max_sessions = 2560
- remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
- '64:ff9b::',
- 96)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
-
- pkts = []
- src = ""
- for i in range(0, max_bibs):
- src = "fd01:aa::%x" % (i)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=src, dst=remote_host_ip6) /
- TCP(sport=12345, dport=80))
- pkts.append(p)
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=src, dst=remote_host_ip6) /
- TCP(sport=12345, dport=22))
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(max_sessions)
-
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=src, dst=remote_host_ip6) /
- TCP(sport=12345, dport=25))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_sessions(data, max_sessions)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
- TCP(sport=12345, dport=80))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(1)
- # verify events in data set
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_bibs(data, max_bibs)
-
- def test_ipfix_max_frags(self):
- """ IPFIX logging maximum fragments pending reassembly exceeded """
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
- drop_frag=0, is_ip6=1)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- data = b'a' * 200
- pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
- self.tcp_port_in, 20, data)
- pkts.reverse()
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.assert_nothing_captured()
- sleep(1)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(9)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_fragments_ip6(data, 1,
- self.pg0.remote_ip6n)
-
- def test_ipfix_bib_ses(self):
- """ IPFIX logging NAT64 BIB/session create and delete events """
- self.tcp_port_in = random.randint(1025, 65535)
- remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
- '64:ff9b::',
- 96)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
- src_address=self.pg3.local_ip4n,
- path_mtu=512,
- template_interval=10)
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=1)
-
- # Create
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
- TCP(sport=self.tcp_port_in, dport=25))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
- self.tcp_port_out = p[0][TCP].sport
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(10)
- ipfix = IPFIXDecoder()
- # first load template
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Template):
- ipfix.add_template(p.getlayer(Template))
- # verify events in data set
- for p in capture:
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- if scapy.compat.orb(data[0][230]) == 10:
- self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
- elif scapy.compat.orb(data[0][230]) == 6:
- self.verify_ipfix_nat64_ses(data,
- 1,
- self.pg0.remote_ip6n,
- self.pg1.remote_ip4,
- 25)
- else:
- self.logger.error(ppp("Unexpected or invalid packet: ", p))
-
- # Delete
- self.pg_enable_capture(self.pg_interfaces)
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=0)
- self.vapi.ipfix_flush()
- capture = self.pg3.get_capture(2)
- # verify events in data set
- for p in capture:
- self.assertTrue(p.haslayer(IPFIX))
- self.assertEqual(p[IP].src, self.pg3.local_ip4)
- self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
- self.assertEqual(p[UDP].sport, self.ipfix_src_port)
- self.assertEqual(p[UDP].dport, 4739)
- self.assertEqual(p[IPFIX].observationDomainID,
- self.ipfix_domain_id)
- if p.haslayer(Data):
- data = ipfix.decode_data_set(p.getlayer(Set))
- if scapy.compat.orb(data[0][230]) == 11:
- self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
- elif scapy.compat.orb(data[0][230]) == 7:
- self.verify_ipfix_nat64_ses(data,
- 0,
- self.pg0.remote_ip6n,
- self.pg1.remote_ip4,
- 25)
- else:
- self.logger.error(ppp("Unexpected or invalid packet: ", p))
-
- def test_syslog_sess(self):
- """ Test syslog session creation and deletion """
- self.tcp_port_in = random.randint(1025, 65535)
- remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
- '64:ff9b::',
- 96)
-
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=1)
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat64_add_del_interface(is_add=1, flags=0,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.syslog_set_filter(
- self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
- self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
-
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- p = self.pg1.get_capture(1)
- self.tcp_port_out = p[0][TCP].sport
- capture = self.pg3.get_capture(1)
- self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- vrf_id=0xFFFFFFFF,
- is_add=0)
- capture = self.pg3.get_capture(1)
- self.verify_syslog_sess(capture[0][Raw].load, False, True)
-
- def nat64_get_ses_num(self):
- """
- Return number of active NAT64 sessions.
- """
- st = self.vapi.nat64_st_dump(proto=255)
- return len(st)
-
- def clear_nat64(self):
- """
- Clear NAT64 configuration.
- """
- self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
- src_port=self.ipfix_src_port,
- enable=0)
- self.ipfix_src_port = 4739
- self.ipfix_domain_id = 1
-
- self.vapi.syslog_set_filter(
- self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
-
- self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
- tcp_transitory=240, icmp=60)
-
- interfaces = self.vapi.nat64_interface_dump()
- for intf in interfaces:
- self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
- sw_if_index=intf.sw_if_index)
-
- bib = self.vapi.nat64_bib_dump(proto=255)
- for bibe in bib:
- if bibe.flags & self.config_flags.NAT_IS_STATIC:
- self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
- o_addr=bibe.o_addr,
- i_port=bibe.i_port,
- o_port=bibe.o_port,
- proto=bibe.proto,
- vrf_id=bibe.vrf_id,
- is_add=0)
-
- adresses = self.vapi.nat64_pool_addr_dump()
- for addr in adresses:
- self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
- end_addr=addr.address,
- vrf_id=addr.vrf_id,
- is_add=0)
-
- prefixes = self.vapi.nat64_prefix_dump()
- for prefix in prefixes:
- self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
- vrf_id=prefix.vrf_id, is_add=0)
-
- bibs = self.statistics.get_counter('/nat64/total-bibs')
- self.assertEqual(bibs[0][0], 0)
- sessions = self.statistics.get_counter('/nat64/total-sessions')
- self.assertEqual(sessions[0][0], 0)
-
- def tearDown(self):
- super(TestNAT64, self).tearDown()
- if not self.vpp_dead:
- self.clear_nat64()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat64 pool"))
- self.logger.info(self.vapi.cli("show nat64 interfaces"))
- self.logger.info(self.vapi.cli("show nat64 prefix"))
- self.logger.info(self.vapi.cli("show nat64 bib all"))
- self.logger.info(self.vapi.cli("show nat64 session table all"))
- self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
-
-
-class TestDSlite(MethodHolder):
- """ DS-Lite Test Cases """
-
- @classmethod
- def setUpClass(cls):
- super(TestDSlite, cls).setUpClass()
-
- try:
- cls.nat_addr = '10.0.0.3'
-
- cls.create_pg_interfaces(range(3))
- cls.pg0.admin_up()
- cls.pg0.config_ip4()
- cls.pg0.resolve_arp()
- cls.pg1.admin_up()
- cls.pg1.config_ip6()
- cls.pg1.generate_remote_hosts(2)
- cls.pg1.configure_ipv6_neighbors()
- cls.pg2.admin_up()
- cls.pg2.config_ip4()
- cls.pg2.resolve_arp()
-
- except Exception:
- super(TestDSlite, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestDSlite, cls).tearDownClass()
-
- def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
- sv6enc, proto):
- message = data.decode('utf-8')
- try:
- message = SyslogMessage.parse(message)
- except ParseError as e:
- self.logger.error(e)
- else:
- self.assertEqual(message.severity, SyslogSeverity.info)
- self.assertEqual(message.appname, 'NAT')
- self.assertEqual(message.msgid, 'APMADD')
- sd_params = message.sd.get('napmap')
- self.assertTrue(sd_params is not None)
- self.assertEqual(sd_params.get('IATYP'), 'IPv4')
- self.assertEqual(sd_params.get('ISADDR'), isaddr)
- self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
- self.assertEqual(sd_params.get('XATYP'), 'IPv4')
- self.assertEqual(sd_params.get('XSADDR'), xsaddr)
- self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
- self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
- self.assertTrue(sd_params.get('SSUBIX') is not None)
- self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
-
- def test_dslite(self):
- """ Test DS-Lite """
- nat_config = self.vapi.nat_show_config()
- self.assertEqual(0, nat_config.dslite_ce)
-
- self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr,
- end_addr=self.nat_addr,
- is_add=1)
- aftr_ip4 = '192.0.0.1'
- aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
- self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
- self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
-
- # UDP
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
- IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
- UDP(sport=20000, dport=10000))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- capture = capture[0]
- self.assertFalse(capture.haslayer(IPv6))
- self.assertEqual(capture[IP].src, self.nat_addr)
- self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
- self.assertNotEqual(capture[UDP].sport, 20000)
- self.assertEqual(capture[UDP].dport, 10000)
- self.assert_packet_checksums_valid(capture)
- out_port = capture[UDP].sport
- capture = self.pg2.get_capture(1)
- self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
- 20000, self.nat_addr, out_port,
- self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
- UDP(sport=10000, dport=out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, aftr_ip6)
- self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
- self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
- self.assertEqual(capture[IP].dst, '192.168.1.1')
- self.assertEqual(capture[UDP].sport, 10000)
- self.assertEqual(capture[UDP].dport, 20000)
- self.assert_packet_checksums_valid(capture)
-
- # TCP
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
- IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
- TCP(sport=20001, dport=10001))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- capture = capture[0]
- self.assertFalse(capture.haslayer(IPv6))
- self.assertEqual(capture[IP].src, self.nat_addr)
- self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
- self.assertNotEqual(capture[TCP].sport, 20001)
- self.assertEqual(capture[TCP].dport, 10001)
- self.assert_packet_checksums_valid(capture)
- out_port = capture[TCP].sport
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
- TCP(sport=10001, dport=out_port))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, aftr_ip6)
- self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
- self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
- self.assertEqual(capture[IP].dst, '192.168.1.1')
- self.assertEqual(capture[TCP].sport, 10001)
- self.assertEqual(capture[TCP].dport, 20001)
- self.assert_packet_checksums_valid(capture)
-
- # ICMP
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
- IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
- ICMP(id=4000, type='echo-request'))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- capture = capture[0]
- self.assertFalse(capture.haslayer(IPv6))
- self.assertEqual(capture[IP].src, self.nat_addr)
- self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
- self.assertNotEqual(capture[ICMP].id, 4000)
- self.assert_packet_checksums_valid(capture)
- out_id = capture[ICMP].id
-
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
- ICMP(id=out_id, type='echo-reply'))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, aftr_ip6)
- self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
- self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
- self.assertEqual(capture[IP].dst, '192.168.1.1')
- self.assertEqual(capture[ICMP].id, 4000)
- self.assert_packet_checksums_valid(capture)
-
- # ping DS-Lite AFTR tunnel endpoint address
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
- ICMPv6EchoRequest())
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, aftr_ip6)
- self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
- self.assertTrue(capture.haslayer(ICMPv6EchoReply))
-
- b4s = self.statistics.get_counter('/dslite/total-b4s')
- self.assertEqual(b4s[0][0], 2)
- sessions = self.statistics.get_counter('/dslite/total-sessions')
- self.assertEqual(sessions[0][0], 3)
-
- def tearDown(self):
- super(TestDSlite, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show dslite pool"))
- self.logger.info(
- self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
- self.logger.info(self.vapi.cli("show dslite sessions"))
-
-
-class TestDSliteCE(MethodHolder):
- """ DS-Lite CE Test Cases """
-
- @classmethod
- def setUpConstants(cls):
- super(TestDSliteCE, cls).setUpConstants()
- cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
-
- @classmethod
- def setUpClass(cls):
- super(TestDSliteCE, cls).setUpClass()
-
- try:
- cls.create_pg_interfaces(range(2))
- cls.pg0.admin_up()
- cls.pg0.config_ip4()
- cls.pg0.resolve_arp()
- cls.pg1.admin_up()
- cls.pg1.config_ip6()
- cls.pg1.generate_remote_hosts(1)
- cls.pg1.configure_ipv6_neighbors()
-
- except Exception:
- super(TestDSliteCE, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestDSliteCE, cls).tearDownClass()
-
- def test_dslite_ce(self):
- """ Test DS-Lite CE """
-
- nat_config = self.vapi.nat_show_config()
- self.assertEqual(1, nat_config.dslite_ce)
-
- b4_ip4 = '192.0.0.2'
- b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
- self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6)
-
- aftr_ip4 = '192.0.0.1'
- aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
- aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
- self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
-
- r1 = VppIpRoute(self, aftr_ip6, 128,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- r1.add_vpp_config()
-
- # UDP encapsulation
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
- UDP(sport=10000, dport=20000))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, b4_ip6)
- self.assertEqual(capture[IPv6].dst, aftr_ip6)
- self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
- self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
- self.assertEqual(capture[UDP].sport, 10000)
- self.assertEqual(capture[UDP].dport, 20000)
- self.assert_packet_checksums_valid(capture)
-
- # UDP decapsulation
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(dst=b4_ip6, src=aftr_ip6) /
- IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
- UDP(sport=20000, dport=10000))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(1)
- capture = capture[0]
- self.assertFalse(capture.haslayer(IPv6))
- self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
- self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
- self.assertEqual(capture[UDP].sport, 20000)
- self.assertEqual(capture[UDP].dport, 10000)
- self.assert_packet_checksums_valid(capture)
-
- # ping DS-Lite B4 tunnel endpoint address
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
- ICMPv6EchoRequest())
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- capture = capture[0]
- self.assertEqual(capture[IPv6].src, b4_ip6)
- self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
- self.assertTrue(capture.haslayer(ICMPv6EchoReply))
-
- def tearDown(self):
- super(TestDSliteCE, self).tearDown()
-
- def show_commands_at_teardown(self):
- self.logger.info(
- self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
- self.logger.info(
- self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
-
-
-class TestNAT66(MethodHolder):
- """ NAT66 Test Cases """
-
- @classmethod
- def setUpClass(cls):
- super(TestNAT66, cls).setUpClass()
-
- try:
- cls.nat_addr = 'fd01:ff::2'
-
- cls.create_pg_interfaces(range(2))
- cls.interfaces = list(cls.pg_interfaces)
-
- for i in cls.interfaces:
- i.admin_up()
- i.config_ip6()
- i.configure_ipv6_neighbors()
-
- except Exception:
- super(TestNAT66, cls).tearDownClass()
- raise
-
- @classmethod
- def tearDownClass(cls):
- super(TestNAT66, cls).tearDownClass()
-
- def test_static(self):
- """ 1:1 NAT66 test """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat66_add_del_interface(is_add=1,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=self.pg0.remote_ip6n,
- external_ip_address=self.nat_addr,
- is_add=1)
-
- # in2out
- pkts = []
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
- TCP())
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
- UDP())
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
- ICMPv6EchoRequest())
- pkts.append(p)
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
- GRE() / IP() / TCP())
- pkts.append(p)
- self.pg0.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, self.nat_addr)
- self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # out2in
- pkts = []
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
- TCP())
- pkts.append(p)
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
- UDP())
- pkts.append(p)
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
- ICMPv6EchoReply())
- pkts.append(p)
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
- GRE() / IP() / TCP())
- pkts.append(p)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg0.get_capture(len(pkts))
- for packet in capture:
- try:
- self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
- self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
- self.assert_packet_checksums_valid(packet)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- sm = self.vapi.nat66_static_mapping_dump()
- self.assertEqual(len(sm), 1)
- self.assertEqual(sm[0].total_pkts, 8)
-
- def test_check_no_translate(self):
- """ NAT66 translate only when egress interface is outside interface """
- flags = self.config_flags.NAT_IS_INSIDE
- self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg0.sw_if_index)
- self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
- sw_if_index=self.pg1.sw_if_index)
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=self.pg0.remote_ip6n,
- external_ip_address=self.nat_addr,
- is_add=1)
-
- # in2out
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
- UDP())
- self.pg0.add_stream([p])
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- capture = self.pg1.get_capture(1)
- packet = capture[0]
- try:
- self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
- self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- def clear_nat66(self):
- """
- Clear NAT66 configuration.
- """
- interfaces = self.vapi.nat66_interface_dump()
- for intf in interfaces:
- self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
- sw_if_index=intf.sw_if_index)
-
- static_mappings = self.vapi.nat66_static_mapping_dump()
- for sm in static_mappings:
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=sm.local_ip_address,
- external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
- is_add=0)
-
- def tearDown(self):
- super(TestNAT66, self).tearDown()
- self.clear_nat66()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat66 interfaces"))
- self.logger.info(self.vapi.cli("show nat66 static mappings"))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_pppoe.py b/test/test_pppoe.py
deleted file mode 100644
index 54378673eb4..00000000000
--- a/test/test_pppoe.py
+++ /dev/null
@@ -1,606 +0,0 @@
-#!/usr/bin/env python
-
-import socket
-import unittest
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether
-from scapy.layers.ppp import PPPoE, PPPoED, PPP
-from scapy.layers.inet import IP
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip_route import VppIpRoute, VppRoutePath
-from vpp_pppoe_interface import VppPppoeInterface
-from util import ppp, ppc
-
-
-class TestPPPoE(VppTestCase):
- """ PPPoE Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestPPPoE, cls).setUpClass()
-
- cls.session_id = 1
- cls.dst_ip = "100.1.1.100"
- cls.dst_ipn = socket.inet_pton(socket.AF_INET, cls.dst_ip)
-
- @classmethod
- def tearDownClass(cls):
- super(TestPPPoE, cls).tearDownClass()
-
- def setUp(self):
- super(TestPPPoE, self).setUp()
-
- # create 2 pg interfaces
- self.create_pg_interfaces(range(3))
-
- for i in self.pg_interfaces:
- i.admin_up()
- i.config_ip4()
- i.resolve_arp()
-
- def tearDown(self):
- super(TestPPPoE, self).tearDown()
-
- for i in self.pg_interfaces:
- i.unconfig_ip4()
- i.admin_down()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show int"))
- self.logger.info(self.vapi.cli("show pppoe fib"))
- self.logger.info(self.vapi.cli("show pppoe session"))
- self.logger.info(self.vapi.cli("show ip fib"))
- self.logger.info(self.vapi.cli("show trace"))
-
- def create_stream_pppoe_discovery(self, src_if, dst_if,
- client_mac, count=1):
- packets = []
- for i in range(count):
- # create packet info stored in the test case instance
- info = self.create_packet_info(src_if, dst_if)
- # convert the info into packet payload
- payload = self.info_to_payload(info)
- # create the packet itself
- p = (Ether(dst=src_if.local_mac, src=client_mac) /
- PPPoED(sessionid=0) /
- Raw(payload))
- # store a copy of the packet in the packet info
- info.data = p.copy()
- # append the packet to the list
- packets.append(p)
-
- # return the created packet list
- return packets
-
- def create_stream_pppoe_lcp(self, src_if, dst_if,
- client_mac, session_id, count=1):
- packets = []
- for i in range(count):
- # create packet info stored in the test case instance
- info = self.create_packet_info(src_if, dst_if)
- # convert the info into packet payload
- payload = self.info_to_payload(info)
- # create the packet itself
- p = (Ether(dst=src_if.local_mac, src=client_mac) /
- PPPoE(sessionid=session_id) /
- PPP(proto=0xc021) /
- Raw(payload))
- # store a copy of the packet in the packet info
- info.data = p.copy()
- # append the packet to the list
- packets.append(p)
-
- # return the created packet list
- return packets
-
- def create_stream_pppoe_ip4(self, src_if, dst_if,
- client_mac, session_id, client_ip, count=1):
- packets = []
- for i in range(count):
- # create packet info stored in the test case instance
- info = self.create_packet_info(src_if, dst_if)
- # convert the info into packet payload
- payload = self.info_to_payload(info)
- # create the packet itself
- p = (Ether(dst=src_if.local_mac, src=client_mac) /
- PPPoE(sessionid=session_id) /
- PPP(proto=0x0021) /
- IP(src=client_ip, dst=self.dst_ip) /
- Raw(payload))
- # store a copy of the packet in the packet info
- info.data = p.copy()
- # append the packet to the list
- packets.append(p)
-
- # return the created packet list
- return packets
-
- def create_stream_ip4(self, src_if, dst_if, client_ip, dst_ip, count=1):
- pkts = []
- for i in range(count):
- # create packet info stored in the test case instance
- info = self.create_packet_info(src_if, dst_if)
- # convert the info into packet payload
- payload = self.info_to_payload(info)
- # create the packet itself
- p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
- IP(src=dst_ip, dst=client_ip) /
- Raw(payload))
- # store a copy of the packet in the packet info
- info.data = p.copy()
- # append the packet to the list
- pkts.append(p)
-
- # return the created packet list
- return pkts
-
- def verify_decapped_pppoe(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]
-
- 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_encaped_pppoe(self, src_if, capture, sent, session_id):
-
- 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, tx_ip.src)
- self.assertEqual(rx_ip.dst, tx_ip.dst)
-
- rx_pppoe = rx[PPPoE]
-
- self.assertEqual(rx_pppoe.sessionid, session_id)
-
- except:
- self.logger.error(ppp("Rx:", rx))
- self.logger.error(ppp("Tx:", tx))
- raise
-
- def test_PPPoE_Decap(self):
- """ PPPoE Decap Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session
- pppoe_if = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if.add_vpp_config()
-
- #
- # Send tunneled packets that match the created tunnel and
- # are decapped and forwarded
- #
- tx2 = self.create_stream_pppoe_ip4(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id,
- self.pg0.remote_ip4)
- self.pg0.add_stream(tx2)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx2 = self.pg1.get_capture(len(tx2))
- self.verify_decapped_pppoe(self.pg0, rx2, tx2)
-
- self.logger.info(self.vapi.cli("show pppoe fib"))
- self.logger.info(self.vapi.cli("show pppoe session"))
- self.logger.info(self.vapi.cli("show ip fib"))
-
- #
- # test case cleanup
- #
-
- # Delete PPPoE session
- pppoe_if.remove_vpp_config()
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
- def test_PPPoE_Encap(self):
- """ PPPoE Encap Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session
- pppoe_if = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if.add_vpp_config()
-
- #
- # Send a packet stream that is routed into the session
- # - packets are PPPoE encapped
- #
- self.vapi.cli("clear trace")
- tx2 = self.create_stream_ip4(self.pg1, self.pg0,
- self.pg0.remote_ip4, self.dst_ip, 65)
- self.pg1.add_stream(tx2)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx2 = self.pg0.get_capture(len(tx2))
- self.verify_encaped_pppoe(self.pg1, rx2, tx2, self.session_id)
-
- self.logger.info(self.vapi.cli("show pppoe fib"))
- self.logger.info(self.vapi.cli("show pppoe session"))
- self.logger.info(self.vapi.cli("show ip fib"))
- self.logger.info(self.vapi.cli("show adj"))
-
- #
- # test case cleanup
- #
-
- # Delete PPPoE session
- pppoe_if.remove_vpp_config()
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
- def test_PPPoE_Add_Twice(self):
- """ PPPoE Add Same Session Twice Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session
- pppoe_if = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if.add_vpp_config()
-
- #
- # The double create (create the same session twice) should fail,
- # and we should still be able to use the original
- #
- try:
- pppoe_if.add_vpp_config()
- except Exception:
- pass
- else:
- self.fail("Double GRE tunnel add does not fail")
-
- #
- # test case cleanup
- #
-
- # Delete PPPoE session
- pppoe_if.remove_vpp_config()
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
- def test_PPPoE_Del_Twice(self):
- """ PPPoE Delete Same Session Twice Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session
- pppoe_if = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if.add_vpp_config()
-
- # Delete PPPoE session
- pppoe_if.remove_vpp_config()
-
- #
- # The double del (del the same session twice) should fail,
- # and we should still be able to use the original
- #
- try:
- pppoe_if.remove_vpp_config()
- except Exception:
- pass
- else:
- self.fail("Double GRE tunnel del does not fail")
-
- #
- # test case cleanup
- #
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
- def test_PPPoE_Decap_Multiple(self):
- """ PPPoE Decap Multiple Sessions Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery 1
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP 1
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session 1
- pppoe_if1 = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if1.add_vpp_config()
-
- # Send PPPoE Discovery 2
- tx3 = self.create_stream_pppoe_discovery(self.pg2, self.pg1,
- self.pg2.remote_mac)
- self.pg2.add_stream(tx3)
- self.pg_start()
-
- # Send PPPoE PPP LCP 2
- tx4 = self.create_stream_pppoe_lcp(self.pg2, self.pg1,
- self.pg2.remote_mac,
- self.session_id + 1)
- self.pg2.add_stream(tx4)
- self.pg_start()
-
- # Create PPPoE session 2
- pppoe_if2 = VppPppoeInterface(self,
- self.pg2.remote_ip4,
- self.pg2.remote_mac,
- self.session_id + 1)
- pppoe_if2.add_vpp_config()
-
- #
- # Send tunneled packets that match the created tunnel and
- # are decapped and forwarded
- #
- tx2 = self.create_stream_pppoe_ip4(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id,
- self.pg0.remote_ip4)
- self.pg0.add_stream(tx2)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx2 = self.pg1.get_capture(len(tx2))
- self.verify_decapped_pppoe(self.pg0, rx2, tx2)
-
- tx5 = self.create_stream_pppoe_ip4(self.pg2, self.pg1,
- self.pg2.remote_mac,
- self.session_id + 1,
- self.pg2.remote_ip4)
- self.pg2.add_stream(tx5)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx5 = self.pg1.get_capture(len(tx5))
- self.verify_decapped_pppoe(self.pg2, rx5, tx5)
-
- self.logger.info(self.vapi.cli("show pppoe fib"))
- self.logger.info(self.vapi.cli("show pppoe session"))
- self.logger.info(self.vapi.cli("show ip fib"))
-
- #
- # test case cleanup
- #
-
- # Delete PPPoE session
- pppoe_if1.remove_vpp_config()
- pppoe_if2.remove_vpp_config()
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
- def test_PPPoE_Encap_Multiple(self):
- """ PPPoE Encap Multiple Sessions Test """
-
- self.vapi.cli("clear trace")
-
- #
- # Add a route that resolves the server's destination
- #
- route_sever_dst = VppIpRoute(self, "100.1.1.100", 32,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index)])
- route_sever_dst.add_vpp_config()
-
- # Send PPPoE Discovery 1
- tx0 = self.create_stream_pppoe_discovery(self.pg0, self.pg1,
- self.pg0.remote_mac)
- self.pg0.add_stream(tx0)
- self.pg_start()
-
- # Send PPPoE PPP LCP 1
- tx1 = self.create_stream_pppoe_lcp(self.pg0, self.pg1,
- self.pg0.remote_mac,
- self.session_id)
- self.pg0.add_stream(tx1)
- self.pg_start()
-
- # Create PPPoE session 1
- pppoe_if1 = VppPppoeInterface(self,
- self.pg0.remote_ip4,
- self.pg0.remote_mac,
- self.session_id)
- pppoe_if1.add_vpp_config()
-
- # Send PPPoE Discovery 2
- tx3 = self.create_stream_pppoe_discovery(self.pg2, self.pg1,
- self.pg2.remote_mac)
- self.pg2.add_stream(tx3)
- self.pg_start()
-
- # Send PPPoE PPP LCP 2
- tx4 = self.create_stream_pppoe_lcp(self.pg2, self.pg1,
- self.pg2.remote_mac,
- self.session_id + 1)
- self.pg2.add_stream(tx4)
- self.pg_start()
-
- # Create PPPoE session 2
- pppoe_if2 = VppPppoeInterface(self,
- self.pg2.remote_ip4,
- self.pg2.remote_mac,
- self.session_id + 1)
- pppoe_if2.add_vpp_config()
-
- #
- # Send a packet stream that is routed into the session
- # - packets are PPPoE encapped
- #
- self.vapi.cli("clear trace")
- tx2 = self.create_stream_ip4(self.pg1, self.pg0,
- self.pg0.remote_ip4, self.dst_ip)
- self.pg1.add_stream(tx2)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx2 = self.pg0.get_capture(len(tx2))
- self.verify_encaped_pppoe(self.pg1, rx2, tx2, self.session_id)
-
- tx5 = self.create_stream_ip4(self.pg1, self.pg2,
- self.pg2.remote_ip4, self.dst_ip)
- self.pg1.add_stream(tx5)
-
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
-
- rx5 = self.pg2.get_capture(len(tx5))
- self.verify_encaped_pppoe(self.pg1, rx5, tx5, self.session_id + 1)
-
- self.logger.info(self.vapi.cli("show pppoe fib"))
- self.logger.info(self.vapi.cli("show pppoe session"))
- self.logger.info(self.vapi.cli("show ip fib"))
-
- #
- # test case cleanup
- #
-
- # Delete PPPoE session
- pppoe_if1.remove_vpp_config()
- pppoe_if2.remove_vpp_config()
-
- # Delete a route that resolves the server's destination
- route_sever_dst.remove_vpp_config()
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_quic.py b/test/test_quic.py
deleted file mode 100644
index ed15cdcd8ed..00000000000
--- a/test/test_quic.py
+++ /dev/null
@@ -1,248 +0,0 @@
-#!/usr/bin/env python
-""" Vpp QUIC tests """
-
-import unittest
-import os
-import subprocess
-import signal
-from framework import VppTestCase, VppTestRunner, running_extended_tests, \
- Worker
-from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
-
-
-class QUICAppWorker(Worker):
- """ QUIC Test Application Worker """
- process = None
-
- def __init__(self, build_dir, appname, args, logger, env={}):
- app = "%s/vpp/bin/%s" % (build_dir, appname)
- self.args = [app] + args
- super(QUICAppWorker, self).__init__(self.args, logger, env)
-
- def run(self):
- super(QUICAppWorker, self).run()
-
- def teardown(self, logger, timeout):
- if self.process is None:
- return False
- try:
- logger.debug("Killing worker process (pid %d)" % self.process.pid)
- os.killpg(os.getpgid(self.process.pid), signal.SIGKILL)
- self.join(timeout)
- except OSError as e:
- logger.debug("Couldn't kill worker process")
- return True
- return False
-
-
-class QUICTestCase(VppTestCase):
- """ QUIC Test Case """
-
- def setUp(self):
- super(QUICTestCase, self).setUp()
- var = "VPP_BUILD_DIR"
- self.build_dir = os.getenv(var, None)
- if self.build_dir is None:
- raise Exception("Environment variable `%s' not set" % var)
- self.vppDebug = 'vpp_debug' in self.build_dir
- self.timeout = 20
- self.vapi.session_enable_disable(is_enabled=1)
- self.pre_test_sleep = 0.3
- self.post_test_sleep = 0.2
-
- self.create_loopback_interfaces(2)
- self.uri = "quic://%s/1234" % self.loop0.local_ip4
- table_id = 1
- for i in self.lo_interfaces:
- i.admin_up()
-
- if table_id != 0:
- tbl = VppIpTable(self, table_id)
- tbl.add_vpp_config()
-
- i.set_table_ip4(table_id)
- i.config_ip4()
- table_id += 1
-
- # Configure namespaces
- self.vapi.app_namespace_add_del(namespace_id=b"server",
- sw_if_index=self.loop0.sw_if_index)
- self.vapi.app_namespace_add_del(namespace_id=b"client",
- sw_if_index=self.loop1.sw_if_index)
-
- # Add inter-table routes
- self.ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
- [VppRoutePath("0.0.0.0",
- 0xffffffff,
- nh_table_id=2)], table_id=1)
- self.ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
- [VppRoutePath("0.0.0.0",
- 0xffffffff,
- nh_table_id=1)], table_id=2)
- self.ip_t01.add_vpp_config()
- self.ip_t10.add_vpp_config()
- self.logger.debug(self.vapi.cli("show ip fib"))
-
- def tearDown(self):
- self.vapi.session_enable_disable(is_enabled=0)
- # Delete inter-table routes
- self.ip_t01.remove_vpp_config()
- self.ip_t10.remove_vpp_config()
-
- for i in self.lo_interfaces:
- i.unconfig_ip4()
- i.set_table_ip4(0)
- i.admin_down()
- super(QUICTestCase, self).tearDown()
-
-
-class QUICEchoInternalTestCase(QUICTestCase):
- """QUIC Echo Internal Test Case"""
-
- def setUp(self):
- super(QUICEchoInternalTestCase, self).setUp()
- self.client_args = "uri %s fifo-size 64 test-bytes appns client" \
- % self.uri
- self.server_args = "uri %s fifo-size 64 appns server" % self.uri
-
- def server(self, *args):
- error = self.vapi.cli(
- "test echo server %s %s" %
- (self.server_args, ' '.join(args)))
- if error:
- self.logger.critical(error)
- self.assertNotIn("failed", error)
-
- def client(self, *args):
- error = self.vapi.cli(
- "test echo client %s %s" %
- (self.client_args, ' '.join(args)))
- if error:
- self.logger.critical(error)
- self.assertNotIn("failed", error)
-
-
-class QUICEchoInternalTransferTestCase(QUICEchoInternalTestCase):
- """QUIC Echo Internal Transfer Test Case"""
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_internal_transfer(self):
- self.server()
- self.client("no-output", "mbytes", "2")
-
-
-class QUICEchoInternalSerialTestCase(QUICEchoInternalTestCase):
- """QUIC Echo Internal Serial Transfer Test Case"""
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_serial_internal_transfer(self):
- self.server()
- self.client("no-output", "mbytes", "2")
- self.client("no-output", "mbytes", "2")
- self.client("no-output", "mbytes", "2")
- self.client("no-output", "mbytes", "2")
- self.client("no-output", "mbytes", "2")
-
-
-class QUICEchoInternalMStreamTestCase(QUICEchoInternalTestCase):
- """QUIC Echo Internal MultiStream Test Case"""
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_internal_multistream_transfer(self):
- self.server()
- self.client("nclients", "10", "mbytes", "1", "no-output")
-
-
-class QUICEchoExternalTestCase(QUICTestCase):
- extra_vpp_punt_config = ["session", "{", "evt_qs_memfd_seg", "}"]
- quic_setup = "default"
-
- def setUp(self):
- super(QUICEchoExternalTestCase, self).setUp()
- common_args = [
- "uri",
- self.uri,
- "fifo-size",
- "64",
- "test-bytes:assert",
- "socket-name",
- self.api_sock]
- self.server_echo_test_args = common_args + \
- ["server", "appns", "server", "quic-setup", self.quic_setup]
- self.client_echo_test_args = common_args + \
- ["client", "appns", "client", "quic-setup", self.quic_setup]
-
- def server(self, *args):
- _args = self.server_echo_test_args + list(args)
- self.worker_server = QUICAppWorker(
- self.build_dir,
- "quic_echo",
- _args,
- self.logger)
- self.worker_server.start()
- self.sleep(self.pre_test_sleep)
-
- def client(self, *args):
- _args = self.client_echo_test_args + list(args)
- # self.client_echo_test_args += "use-svm-api"
- self.worker_client = QUICAppWorker(
- self.build_dir,
- "quic_echo",
- _args,
- self.logger)
- self.worker_client.start()
- self.worker_client.join(self.timeout)
- self.worker_server.join(self.timeout)
- self.sleep(self.post_test_sleep)
-
- def validate_external_test_results(self):
- self.logger.info(
- "Client worker result is `%s'" %
- self.worker_client.result)
- server_result = self.worker_server.result
- client_result = self.worker_client.result
- server_kill_error = False
- if self.worker_server.result is None:
- server_kill_error = self.worker_server.teardown(
- self.logger, self.timeout)
- if self.worker_client.result is None:
- self.worker_client.teardown(self.logger, self.timeout)
- self.assertEqual(server_result, 0, "Wrong server worker return code")
- self.assertIsNotNone(
- client_result,
- "Timeout! Client worker did not finish in %ss" %
- self.timeout)
- self.assertEqual(client_result, 0, "Wrong client worker return code")
- self.assertFalse(server_kill_error, "Server kill errored")
-
-
-class QUICEchoExternalTransferTestCase(QUICEchoExternalTestCase):
- """QUIC Echo External Transfer Test Case"""
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_external_transfer(self):
- self.server()
- self.client()
- self.validate_external_test_results()
-
-
-class QUICEchoExternalServerStreamTestCase(QUICEchoExternalTestCase):
- """QUIC Echo External Transfer Server Stream Test Case"""
- quic_setup = "serverstream"
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_external_transfer_server_stream(self):
- self.server("TX=1Kb", "RX=0")
- self.client("TX=0", "RX=1Kb")
- self.validate_external_test_results()
-
-
-class QUICEchoExternalServerStreamWorkersTestCase(QUICEchoExternalTestCase):
- """QUIC Echo External Transfer Server Stream MultiWorker Test Case"""
- quic_setup = "serverstream"
-
- @unittest.skipUnless(running_extended_tests, "part of extended tests")
- def test_quic_external_transfer_server_stream_multi_workers(self):
- self.server("nclients", "4/4", "TX=1Kb", "RX=0")
- self.client("nclients", "4/4", "TX=0", "RX=1Kb")
- self.validate_external_test_results()
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_sctp.py b/test/test_sctp.py
deleted file mode 100644
index 75bbb23f31f..00000000000
--- a/test/test_sctp.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
-
-
-class TestSCTP(VppTestCase):
- """ SCTP Test Case """
-
- @classmethod
- def setUpClass(cls):
- cls.extra_vpp_plugin_config.append("plugin sctp_plugin.so { enable }")
- super(TestSCTP, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestSCTP, cls).tearDownClass()
-
- def setUp(self):
- super(TestSCTP, self).setUp()
- self.vapi.session_enable_disable(is_enabled=1)
- self.vapi.cli("sctp enable")
- self.create_loopback_interfaces(2)
-
- table_id = 0
-
- for i in self.lo_interfaces:
- i.admin_up()
-
- if table_id != 0:
- tbl = VppIpTable(self, table_id)
- tbl.add_vpp_config()
-
- i.set_table_ip4(table_id)
- i.config_ip4()
- table_id += 1
-
- # Configure namespaces
- self.vapi.app_namespace_add_del(namespace_id=b"0",
- sw_if_index=self.loop0.sw_if_index)
- self.vapi.app_namespace_add_del(namespace_id=b"1",
- sw_if_index=self.loop1.sw_if_index)
-
- def tearDown(self):
- for i in self.lo_interfaces:
- i.unconfig_ip4()
- i.set_table_ip4(0)
- i.admin_down()
- self.vapi.session_enable_disable(is_enabled=0)
- super(TestSCTP, self).tearDown()
-
- def test_sctp_transfer(self):
- """ SCTP echo client/server transfer """
-
- # Add inter-table routes
- ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32,
- [VppRoutePath("0.0.0.0",
- 0xffffffff,
- nh_table_id=1)])
- ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32,
- [VppRoutePath("0.0.0.0",
- 0xffffffff,
- nh_table_id=0)], table_id=1)
- ip_t01.add_vpp_config()
- ip_t10.add_vpp_config()
-
- # Start builtin server and client
- uri = "sctp://" + self.loop0.local_ip4 + "/1234"
- error = self.vapi.cli("test echo server appns 0 fifo-size 4 " +
- "no-echo uri " + uri)
- if error:
- self.logger.critical(error)
- self.assertNotIn("failed", error)
-
- error = self.vapi.cli("test echo client mbytes 10 no-return " +
- " appns 1" +
- " fifo-size 4" +
- " no-output test-bytes syn-timeout 3" +
- " test-timeout 30" +
- " uri " + uri)
- if error:
- self.logger.critical(error)
- self.assertNotIn("failed", error)
-
- # Delete inter-table routes
- ip_t01.remove_vpp_config()
- ip_t10.remove_vpp_config()
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_srv6.py b/test/test_srv6.py
deleted file mode 100644
index b3e69724028..00000000000
--- a/test/test_srv6.py
+++ /dev/null
@@ -1,2141 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-import binascii
-from socket import AF_INET6
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto, VppIpTable
-from vpp_srv6 import SRv6LocalSIDBehaviors, VppSRv6LocalSID, VppSRv6Policy, \
- SRv6PolicyType, VppSRv6Steering, SRv6PolicySteeringTypes
-
-import scapy.compat
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet6 import IPv6, UDP, IPv6ExtHdrSegmentRouting
-from scapy.layers.inet import IP, UDP
-
-from scapy.utils import inet_pton, inet_ntop
-
-from util import ppp
-
-
-class TestSRv6(VppTestCase):
- """ SRv6 Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestSRv6, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestSRv6, cls).tearDownClass()
-
- def setUp(self):
- """ Perform test setup before each test case.
- """
- super(TestSRv6, self).setUp()
-
- # packet sizes, inclusive L2 overhead
- self.pg_packet_sizes = [64, 512, 1518, 9018]
-
- # reset packet_infos
- self.reset_packet_infos()
-
- def tearDown(self):
- """ Clean up test setup after each test case.
- """
- self.teardown_interfaces()
-
- super(TestSRv6, self).tearDown()
-
- def configure_interface(self,
- interface,
- ipv6=False, ipv4=False,
- ipv6_table_id=0, ipv4_table_id=0):
- """ Configure interface.
- :param ipv6: configure IPv6 on interface
- :param ipv4: configure IPv4 on interface
- :param ipv6_table_id: FIB table_id for IPv6
- :param ipv4_table_id: FIB table_id for IPv4
- """
- self.logger.debug("Configuring interface %s" % (interface.name))
- if ipv6:
- self.logger.debug("Configuring IPv6")
- interface.set_table_ip6(ipv6_table_id)
- interface.config_ip6()
- interface.resolve_ndp(timeout=5)
- if ipv4:
- self.logger.debug("Configuring IPv4")
- interface.set_table_ip4(ipv4_table_id)
- interface.config_ip4()
- interface.resolve_arp()
- interface.admin_up()
-
- def setup_interfaces(self, ipv6=[], ipv4=[],
- ipv6_table_id=[], ipv4_table_id=[]):
- """ Create and configure interfaces.
-
- :param ipv6: list of interface IPv6 capabilities
- :param ipv4: list of interface IPv4 capabilities
- :param ipv6_table_id: list of intf IPv6 FIB table_ids
- :param ipv4_table_id: list of intf IPv4 FIB table_ids
- :returns: List of created interfaces.
- """
- # how many interfaces?
- if len(ipv6):
- count = len(ipv6)
- else:
- count = len(ipv4)
- self.logger.debug("Creating and configuring %d interfaces" % (count))
-
- # fill up ipv6 and ipv4 lists if needed
- # not enabled (False) is the default
- if len(ipv6) < count:
- ipv6 += (count - len(ipv6)) * [False]
- if len(ipv4) < count:
- ipv4 += (count - len(ipv4)) * [False]
-
- # fill up table_id lists if needed
- # table_id 0 (global) is the default
- if len(ipv6_table_id) < count:
- ipv6_table_id += (count - len(ipv6_table_id)) * [0]
- if len(ipv4_table_id) < count:
- ipv4_table_id += (count - len(ipv4_table_id)) * [0]
-
- # create 'count' pg interfaces
- self.create_pg_interfaces(range(count))
-
- # setup all interfaces
- for i in range(count):
- intf = self.pg_interfaces[i]
- self.configure_interface(intf,
- ipv6[i], ipv4[i],
- ipv6_table_id[i], ipv4_table_id[i])
-
- if any(ipv6):
- self.logger.debug(self.vapi.cli("show ip6 neighbors"))
- if any(ipv4):
- self.logger.debug(self.vapi.cli("show ip arp"))
- self.logger.debug(self.vapi.cli("show interface"))
- self.logger.debug(self.vapi.cli("show hardware"))
-
- return self.pg_interfaces
-
- def teardown_interfaces(self):
- """ Unconfigure and bring down interface.
- """
- self.logger.debug("Tearing down interfaces")
- # tear down all interfaces
- # AFAIK they cannot be deleted
- for i in self.pg_interfaces:
- self.logger.debug("Tear down interface %s" % (i.name))
- i.admin_down()
- i.unconfig()
- i.set_table_ip4(0)
- i.set_table_ip6(0)
-
- @unittest.skipUnless(0, "PC to fix")
- def test_SRv6_T_Encaps(self):
- """ Test SRv6 Transit.Encaps behavior for IPv6.
- """
- # send traffic to one destination interface
- # source and destination are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure encaps IPv6 source address
- # needs to be done before SR Policy config
- # TODO: API?
- self.vapi.cli("set sr encaps source addr a3::")
-
- bsid = 'a3::9999:1'
- # configure SRv6 Policy
- # Note: segment list order: first -> last
- sr_policy = VppSRv6Policy(
- self, bsid=bsid,
- is_encap=1,
- sr_type=SRv6PolicyType.SR_POLICY_TYPE_DEFAULT,
- weight=1, fib_table=0,
- segments=['a4::', 'a5::', 'a6::c7'],
- source='a3::')
- sr_policy.add_vpp_config()
- self.sr_policy = sr_policy
-
- # log the sr policies
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # steer IPv6 traffic to a7::/64 into SRv6 Policy
- # use the bsid of the above self.sr_policy
- pol_steering = VppSRv6Steering(
- self,
- bsid=self.sr_policy.bsid,
- prefix="a7::", mask_width=64,
- traffic_type=SRv6PolicySteeringTypes.SR_STEER_IPV6,
- sr_policy_index=0, table_id=0,
- sw_if_index=0)
- pol_steering.add_vpp_config()
-
- # log the sr steering policies
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # create packets
- count = len(self.pg_packet_sizes)
- dst_inner = 'a7::1234'
- pkts = []
-
- # create IPv6 packets without SRH
- packet_header = self.create_packet_header_IPv6(dst_inner)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # create IPv6 packets with SRH
- # packets with segments-left 1, active segment a7::
- packet_header = self.create_packet_header_IPv6_SRH(
- sidlist=['a8::', 'a7::', 'a6::'],
- segleft=1)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # create IPv6 packets with SRH and IPv6
- # packets with segments-left 1, active segment a7::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a8::', 'a7::', 'a6::'],
- segleft=1)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_T_Encaps)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SR steering
- pol_steering.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # remove SR Policies
- self.sr_policy.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- @unittest.skipUnless(0, "PC to fix")
- def test_SRv6_T_Insert(self):
- """ Test SRv6 Transit.Insert behavior (IPv6 only).
- """
- # send traffic to one destination interface
- # source and destination are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure encaps IPv6 source address
- # needs to be done before SR Policy config
- # TODO: API?
- self.vapi.cli("set sr encaps source addr a3::")
-
- bsid = 'a3::9999:1'
- # configure SRv6 Policy
- # Note: segment list order: first -> last
- sr_policy = VppSRv6Policy(
- self, bsid=bsid,
- is_encap=0,
- sr_type=SRv6PolicyType.SR_POLICY_TYPE_DEFAULT,
- weight=1, fib_table=0,
- segments=['a4::', 'a5::', 'a6::c7'],
- source='a3::')
- sr_policy.add_vpp_config()
- self.sr_policy = sr_policy
-
- # log the sr policies
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # steer IPv6 traffic to a7::/64 into SRv6 Policy
- # use the bsid of the above self.sr_policy
- pol_steering = VppSRv6Steering(
- self,
- bsid=self.sr_policy.bsid,
- prefix="a7::", mask_width=64,
- traffic_type=SRv6PolicySteeringTypes.SR_STEER_IPV6,
- sr_policy_index=0, table_id=0,
- sw_if_index=0)
- pol_steering.add_vpp_config()
-
- # log the sr steering policies
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # create packets
- count = len(self.pg_packet_sizes)
- dst_inner = 'a7::1234'
- pkts = []
-
- # create IPv6 packets without SRH
- packet_header = self.create_packet_header_IPv6(dst_inner)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # create IPv6 packets with SRH
- # packets with segments-left 1, active segment a7::
- packet_header = self.create_packet_header_IPv6_SRH(
- sidlist=['a8::', 'a7::', 'a6::'],
- segleft=1)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_T_Insert)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SR steering
- pol_steering.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # remove SR Policies
- self.sr_policy.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- @unittest.skipUnless(0, "PC to fix")
- def test_SRv6_T_Encaps_IPv4(self):
- """ Test SRv6 Transit.Encaps behavior for IPv4.
- """
- # send traffic to one destination interface
- # source interface is IPv4 only
- # destination interface is IPv6 only
- self.setup_interfaces(ipv6=[False, True], ipv4=[True, False])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure encaps IPv6 source address
- # needs to be done before SR Policy config
- # TODO: API?
- self.vapi.cli("set sr encaps source addr a3::")
-
- bsid = 'a3::9999:1'
- # configure SRv6 Policy
- # Note: segment list order: first -> last
- sr_policy = VppSRv6Policy(
- self, bsid=bsid,
- is_encap=1,
- sr_type=SRv6PolicyType.SR_POLICY_TYPE_DEFAULT,
- weight=1, fib_table=0,
- segments=['a4::', 'a5::', 'a6::c7'],
- source='a3::')
- sr_policy.add_vpp_config()
- self.sr_policy = sr_policy
-
- # log the sr policies
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # steer IPv4 traffic to 7.1.1.0/24 into SRv6 Policy
- # use the bsid of the above self.sr_policy
- pol_steering = VppSRv6Steering(
- self,
- bsid=self.sr_policy.bsid,
- prefix="7.1.1.0", mask_width=24,
- traffic_type=SRv6PolicySteeringTypes.SR_STEER_IPV4,
- sr_policy_index=0, table_id=0,
- sw_if_index=0)
- pol_steering.add_vpp_config()
-
- # log the sr steering policies
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # create packets
- count = len(self.pg_packet_sizes)
- dst_inner = '7.1.1.123'
- pkts = []
-
- # create IPv4 packets
- packet_header = self.create_packet_header_IPv4(dst_inner)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_T_Encaps_IPv4)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SR steering
- pol_steering.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # remove SR Policies
- self.sr_policy.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- @unittest.skip("VPP crashes after running this test")
- def test_SRv6_T_Encaps_L2(self):
- """ Test SRv6 Transit.Encaps behavior for L2.
- """
- # send traffic to one destination interface
- # source interface is IPv4 only TODO?
- # destination interface is IPv6 only
- self.setup_interfaces(ipv6=[False, True], ipv4=[False, False])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure encaps IPv6 source address
- # needs to be done before SR Policy config
- # TODO: API?
- self.vapi.cli("set sr encaps source addr a3::")
-
- bsid = 'a3::9999:1'
- # configure SRv6 Policy
- # Note: segment list order: first -> last
- sr_policy = VppSRv6Policy(
- self, bsid=bsid,
- is_encap=1,
- sr_type=SRv6PolicyType.SR_POLICY_TYPE_DEFAULT,
- weight=1, fib_table=0,
- segments=['a4::', 'a5::', 'a6::c7'],
- source='a3::')
- sr_policy.add_vpp_config()
- self.sr_policy = sr_policy
-
- # log the sr policies
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # steer L2 traffic into SRv6 Policy
- # use the bsid of the above self.sr_policy
- pol_steering = VppSRv6Steering(
- self,
- bsid=self.sr_policy.bsid,
- prefix="::", mask_width=0,
- traffic_type=SRv6PolicySteeringTypes.SR_STEER_L2,
- sr_policy_index=0, table_id=0,
- sw_if_index=self.pg0.sw_if_index)
- pol_steering.add_vpp_config()
-
- # log the sr steering policies
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # create packets
- count = len(self.pg_packet_sizes)
- pkts = []
-
- # create L2 packets without dot1q header
- packet_header = self.create_packet_header_L2()
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # create L2 packets with dot1q header
- packet_header = self.create_packet_header_L2(vlan=123)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_T_Encaps_L2)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SR steering
- pol_steering.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # remove SR Policies
- self.sr_policy.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End(self):
- """ Test SRv6 End (without PSP) behavior.
- """
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID End without PSP behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::0'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_END,
- nh_addr4='0.0.0.0',
- nh_addr6='::',
- end_psp=0,
- sw_if_index=0,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=2, SL=1, SL=0)
- # send one packet per SL value per packet size
- # SL=0 packet with localSID End with USP needs 2nd SRH
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234'
- pkts = []
-
- # packets with segments-left 2, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a5::', 'a4::', 'a3::'],
- segleft=2)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets with segments-left 1, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a4::', 'a3::', 'a2::'],
- segleft=1)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # TODO: test behavior with SL=0 packet (needs 2*SRH?)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_with_PSP(self):
- """ Test SRv6 End with PSP behavior.
- """
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID End with PSP behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::0'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_END,
- nh_addr4='0.0.0.0',
- nh_addr6='::',
- end_psp=1,
- sw_if_index=0,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=2, SL=1)
- # send one packet per SL value per packet size
- # SL=0 packet with localSID End with PSP is dropped
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234'
- pkts = []
-
- # packets with segments-left 2, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a5::', 'a4::', 'a3::'],
- segleft=2)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets with segments-left 1, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a4::', 'a3::', 'a2::'],
- segleft=1)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End_PSP)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_X(self):
- """ Test SRv6 End.X (without PSP) behavior.
- """
- # create three interfaces (1 source, 2 destinations)
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True, True])
-
- # configure FIB entries
- # a4::/64 via pg1 and pg2
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index),
- VppRoutePath(self.pg2.remote_ip6,
- self.pg2.sw_if_index)])
- route.add_vpp_config()
- self.logger.debug(self.vapi.cli("show ip6 fib"))
-
- # configure SRv6 localSID End.X without PSP behavior
- # End.X points to interface pg1
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_X,
- nh_addr4='0.0.0.0',
- nh_addr6=self.pg1.remote_ip6,
- end_psp=0,
- sw_if_index=self.pg1.sw_if_index,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=2, SL=1)
- # send one packet per SL value per packet size
- # SL=0 packet with localSID End with PSP is dropped
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234'
- pkts = []
-
- # packets with segments-left 2, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a5::', 'a4::', 'a3::c4'],
- segleft=2)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets with segments-left 1, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a4::', 'a3::c4', 'a2::'],
- segleft=1)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- # using same comparison function as End (no PSP)
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End)
-
- # assert nothing was received on the other interface (pg2)
- self.pg2.assert_nothing_captured("mis-directed packet(s)")
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_X_with_PSP(self):
- """ Test SRv6 End.X with PSP behavior.
- """
- # create three interfaces (1 source, 2 destinations)
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True, True])
-
- # configure FIB entries
- # a4::/64 via pg1 and pg2
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(
- self.pg1.remote_ip6,
- self.pg1.sw_if_index),
- VppRoutePath(self.pg2.remote_ip6,
- self.pg2.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID End with PSP behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_X,
- nh_addr4='0.0.0.0',
- nh_addr6=self.pg1.remote_ip6,
- end_psp=1,
- sw_if_index=self.pg1.sw_if_index,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=2, SL=1)
- # send one packet per SL value per packet size
- # SL=0 packet with localSID End with PSP is dropped
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234'
- pkts = []
-
- # packets with segments-left 2, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a5::', 'a4::', 'a3::c4'],
- segleft=2)
- # create traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets with segments-left 1, active segment a3::
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a4::', 'a3::c4', 'a2::'],
- segleft=1)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- # using same comparison function as End with PSP
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End_PSP)
-
- # assert nothing was received on the other interface (pg2)
- self.pg2.assert_nothing_captured("mis-directed packet(s)")
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_DX6(self):
- """ Test SRv6 End.DX6 behavior.
- """
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure SRv6 localSID End.DX6 behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_DX6,
- nh_addr4='0.0.0.0',
- nh_addr6=self.pg1.remote_ip6,
- end_psp=0,
- sw_if_index=self.pg1.sw_if_index,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=0)
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234' # inner header destination address
- pkts = []
-
- # packets with SRH, segments-left 0, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, IPv6 in IPv6
- # outer IPv6 dest addr is the localsid End.DX6
- packet_header = self.create_packet_header_IPv6_IPv6(
- dst_inner,
- dst_outer='a3::c4')
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End_DX6)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_DT6(self):
- """ Test SRv6 End.DT6 behavior.
- """
- # create three interfaces (1 source, 2 destinations)
- # all interfaces are IPv6 only
- # source interface in global FIB (0)
- # destination interfaces in global and vrf
- vrf_1 = 1
- ipt = VppIpTable(self, vrf_1, is_ip6=True)
- ipt.add_vpp_config()
- self.setup_interfaces(ipv6=[True, True, True],
- ipv6_table_id=[0, 0, vrf_1])
-
- # configure FIB entries
- # a4::/64 is reachable
- # via pg1 in table 0 (global)
- # and via pg2 in table vrf_1
- route0 = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg1.remote_ip6,
- self.pg1.sw_if_index,
- nh_table_id=0)],
- table_id=0)
- route0.add_vpp_config()
- route1 = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(self.pg2.remote_ip6,
- self.pg2.sw_if_index,
- nh_table_id=vrf_1)],
- table_id=vrf_1)
- route1.add_vpp_config()
- self.logger.debug(self.vapi.cli("show ip6 fib"))
-
- # configure SRv6 localSID End.DT6 behavior
- # Note:
- # fib_table: where the localsid is installed
- # sw_if_index: in T-variants of localsid this is the vrf table_id
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_DT6,
- nh_addr4='0.0.0.0',
- nh_addr6='::',
- end_psp=0,
- sw_if_index=vrf_1,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=0)
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
- dst_inner = 'a4::1234' # inner header destination address
- pkts = []
-
- # packets with SRH, segments-left 0, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv6(
- dst_inner,
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg2, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, IPv6 in IPv6
- # outer IPv6 dest addr is the localsid End.DT6
- packet_header = self.create_packet_header_IPv6_IPv6(
- dst_inner,
- dst_outer='a3::c4')
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg2, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- # using same comparison function as End.DX6
- self.send_and_verify_pkts(self.pg0, pkts, self.pg2,
- self.compare_rx_tx_packet_End_DX6)
-
- # assert nothing was received on the other interface (pg2)
- self.pg1.assert_nothing_captured("mis-directed packet(s)")
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_DX4(self):
- """ Test SRv6 End.DX4 behavior.
- """
- # send traffic to one destination interface
- # source interface is IPv6 only
- # destination interface is IPv4 only
- self.setup_interfaces(ipv6=[True, False], ipv4=[False, True])
-
- # configure SRv6 localSID End.DX4 behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_DX4,
- nh_addr4=self.pg1.remote_ip4,
- nh_addr6='::',
- end_psp=0,
- sw_if_index=self.pg1.sw_if_index,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
- dst_inner = '4.1.1.123' # inner header destination address
- pkts = []
-
- # packets with SRH, segments-left 0, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv4(
- dst_inner,
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, IPv4 in IPv6
- # outer IPv6 dest addr is the localsid End.DX4
- packet_header = self.create_packet_header_IPv6_IPv4(
- dst_inner,
- dst_outer='a3::c4')
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End_DX4)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_DT4(self):
- """ Test SRv6 End.DT4 behavior.
- """
- # create three interfaces (1 source, 2 destinations)
- # source interface is IPv6-only
- # destination interfaces are IPv4 only
- # source interface in global FIB (0)
- # destination interfaces in global and vrf
- vrf_1 = 1
- ipt = VppIpTable(self, vrf_1)
- ipt.add_vpp_config()
- self.setup_interfaces(ipv6=[True, False, False],
- ipv4=[False, True, True],
- ipv6_table_id=[0, 0, 0],
- ipv4_table_id=[0, 0, vrf_1])
-
- # configure FIB entries
- # 4.1.1.0/24 is reachable
- # via pg1 in table 0 (global)
- # and via pg2 in table vrf_1
- route0 = VppIpRoute(self, "4.1.1.0", 24,
- [VppRoutePath(self.pg1.remote_ip4,
- self.pg1.sw_if_index,
- nh_table_id=0)],
- table_id=0)
- route0.add_vpp_config()
- route1 = VppIpRoute(self, "4.1.1.0", 24,
- [VppRoutePath(self.pg2.remote_ip4,
- self.pg2.sw_if_index,
- nh_table_id=vrf_1)],
- table_id=vrf_1)
- route1.add_vpp_config()
- self.logger.debug(self.vapi.cli("show ip fib"))
-
- # configure SRv6 localSID End.DT6 behavior
- # Note:
- # fib_table: where the localsid is installed
- # sw_if_index: in T-variants of localsid: vrf table_id
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_DT4,
- nh_addr4='0.0.0.0',
- nh_addr6='::',
- end_psp=0,
- sw_if_index=vrf_1,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # create IPv6 packets with SRH (SL=0)
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
- dst_inner = '4.1.1.123' # inner header destination address
- pkts = []
-
- # packets with SRH, segments-left 0, active segment a3::c4
- packet_header = self.create_packet_header_IPv6_SRH_IPv4(
- dst_inner,
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg2, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, IPv6 in IPv6
- # outer IPv6 dest addr is the localsid End.DX4
- packet_header = self.create_packet_header_IPv6_IPv4(
- dst_inner,
- dst_outer='a3::c4')
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg2, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- # using same comparison function as End.DX4
- self.send_and_verify_pkts(self.pg0, pkts, self.pg2,
- self.compare_rx_tx_packet_End_DX4)
-
- # assert nothing was received on the other interface (pg2)
- self.pg1.assert_nothing_captured("mis-directed packet(s)")
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def test_SRv6_End_DX2(self):
- """ Test SRv6 End.DX2 behavior.
- """
- # send traffic to one destination interface
- # source interface is IPv6 only
- self.setup_interfaces(ipv6=[True, False], ipv4=[False, False])
-
- # configure SRv6 localSID End.DX2 behavior
- localsid = VppSRv6LocalSID(
- self, localsid={'addr': 'A3::C4'},
- behavior=SRv6LocalSIDBehaviors.SR_BEHAVIOR_DX2,
- nh_addr4='0.0.0.0',
- nh_addr6='::',
- end_psp=0,
- sw_if_index=self.pg1.sw_if_index,
- vlan_index=0,
- fib_table=0)
- localsid.add_vpp_config()
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
- pkts = []
-
- # packets with SRH, segments-left 0, active segment a3::c4
- # L2 has no dot1q header
- packet_header = self.create_packet_header_IPv6_SRH_L2(
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0,
- vlan=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets with SRH, segments-left 0, active segment a3::c4
- # L2 has dot1q header
- packet_header = self.create_packet_header_IPv6_SRH_L2(
- sidlist=['a3::c4', 'a2::', 'a1::'],
- segleft=0,
- vlan=123)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, L2 in IPv6
- # outer IPv6 dest addr is the localsid End.DX2
- # L2 has no dot1q header
- packet_header = self.create_packet_header_IPv6_L2(
- dst_outer='a3::c4',
- vlan=0)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # packets without SRH, L2 in IPv6
- # outer IPv6 dest addr is the localsid End.DX2
- # L2 has dot1q header
- packet_header = self.create_packet_header_IPv6_L2(
- dst_outer='a3::c4',
- vlan=123)
- # add to traffic stream pg0->pg1
- pkts.extend(self.create_stream(self.pg0, self.pg1, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts, self.pg1,
- self.compare_rx_tx_packet_End_DX2)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- localsid.remove_vpp_config()
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- @unittest.skipUnless(0, "PC to fix")
- def test_SRv6_T_Insert_Classifier(self):
- """ Test SRv6 Transit.Insert behavior (IPv6 only).
- steer packets using the classifier
- """
- # send traffic to one destination interface
- # source and destination are IPv6 only
- self.setup_interfaces(ipv6=[False, False, False, True, True])
-
- # configure FIB entries
- route = VppIpRoute(self, "a4::", 64,
- [VppRoutePath(
- self.pg4.remote_ip6,
- self.pg4.sw_if_index)])
- route.add_vpp_config()
-
- # configure encaps IPv6 source address
- # needs to be done before SR Policy config
- # TODO: API?
- self.vapi.cli("set sr encaps source addr a3::")
-
- bsid = 'a3::9999:1'
- # configure SRv6 Policy
- # Note: segment list order: first -> last
- sr_policy = VppSRv6Policy(
- self, bsid=bsid,
- is_encap=0,
- sr_type=SRv6PolicyType.SR_POLICY_TYPE_DEFAULT,
- weight=1, fib_table=0,
- segments=['a4::', 'a5::', 'a6::c7'],
- source='a3::')
- sr_policy.add_vpp_config()
- self.sr_policy = sr_policy
-
- # log the sr policies
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # add classify table
- # mask on dst ip address prefix a7::/8
- mask = '{!s:0<16}'.format('ff')
- r = self.vapi.classify_add_del_table(
- 1,
- binascii.unhexlify(mask),
- match_n_vectors=(len(mask) - 1) // 32 + 1,
- current_data_flag=1,
- skip_n_vectors=2) # data offset
- self.assertIsNotNone(r, 'No response msg for add_del_table')
- table_index = r.new_table_index
-
- # add the source routing node as a ip6 inacl netxt node
- r = self.vapi.add_node_next('ip6-inacl',
- 'sr-pl-rewrite-insert')
- inacl_next_node_index = r.node_index
-
- match = '{!s:0<16}'.format('a7')
- r = self.vapi.classify_add_del_session(
- 1,
- table_index,
- binascii.unhexlify(match),
- hit_next_index=inacl_next_node_index,
- action=3,
- metadata=0) # sr policy index
- self.assertIsNotNone(r, 'No response msg for add_del_session')
-
- # log the classify table used in the steering policy
- self.logger.info(self.vapi.cli("show classify table"))
-
- r = self.vapi.input_acl_set_interface(
- is_add=1,
- sw_if_index=self.pg3.sw_if_index,
- ip6_table_index=table_index)
- self.assertIsNotNone(r,
- 'No response msg for input_acl_set_interface')
-
- # log the ip6 inacl
- self.logger.info(self.vapi.cli("show inacl type ip6"))
-
- # create packets
- count = len(self.pg_packet_sizes)
- dst_inner = 'a7::1234'
- pkts = []
-
- # create IPv6 packets without SRH
- packet_header = self.create_packet_header_IPv6(dst_inner)
- # create traffic stream pg3->pg4
- pkts.extend(self.create_stream(self.pg3, self.pg4, packet_header,
- self.pg_packet_sizes, count))
-
- # create IPv6 packets with SRH
- # packets with segments-left 1, active segment a7::
- packet_header = self.create_packet_header_IPv6_SRH(
- sidlist=['a8::', 'a7::', 'a6::'],
- segleft=1)
- # create traffic stream pg3->pg4
- pkts.extend(self.create_stream(self.pg3, self.pg4, packet_header,
- self.pg_packet_sizes, count))
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg3, pkts, self.pg4,
- self.compare_rx_tx_packet_T_Insert)
-
- # remove the interface l2 input feature
- r = self.vapi.input_acl_set_interface(
- is_add=0,
- sw_if_index=self.pg3.sw_if_index,
- ip6_table_index=table_index)
- self.assertIsNotNone(r,
- 'No response msg for input_acl_set_interface')
-
- # log the ip6 inacl after cleaning
- self.logger.info(self.vapi.cli("show inacl type ip6"))
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove classifier SR steering
- # classifier_steering.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr steering policies"))
-
- # remove SR Policies
- self.sr_policy.remove_vpp_config()
- self.logger.info(self.vapi.cli("show sr policies"))
-
- # remove classify session and table
- r = self.vapi.classify_add_del_session(
- 0,
- table_index,
- binascii.unhexlify(match))
- self.assertIsNotNone(r, 'No response msg for add_del_session')
-
- r = self.vapi.classify_add_del_table(
- 0,
- binascii.unhexlify(mask),
- table_index=table_index)
- self.assertIsNotNone(r, 'No response msg for add_del_table')
-
- self.logger.info(self.vapi.cli("show classify table"))
-
- # remove FIB entries
- # done by tearDown
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def compare_rx_tx_packet_T_Encaps(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing T.Encaps
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # T.Encaps updates the headers as follows:
- # SR Policy seglist (S3, S2, S1)
- # SR Policy source C
- # IPv6:
- # in: IPv6(A, B2)
- # out: IPv6(C, S1)SRH(S3, S2, S1; SL=2)IPv6(A, B2)
- # IPv6 + SRH:
- # in: IPv6(A, B2)SRH(B3, B2, B1; SL=1)
- # out: IPv6(C, S1)SRH(S3, S2, S1; SL=2)IPv6(a, B2)SRH(B3, B2, B1; SL=1)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ip = tx_pkt.getlayer(IPv6)
-
- # expected segment-list
- seglist = self.sr_policy.segments
- # reverse list to get order as in SRH
- tx_seglist = seglist[::-1]
-
- # get source address of SR Policy
- sr_policy_source = self.sr_policy.source
-
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, sr_policy_source)
- # received ip.dst should be equal to expected sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
- # rx'ed seglist should be equal to expected seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size expected seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the hop-limit field
- # -> update tx'ed hlim to the expected hlim
- tx_ip.hlim = tx_ip.hlim - 1
-
- self.assertEqual(rx_srh.payload, tx_ip)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_T_Encaps_IPv4(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing T.Encaps for IPv4
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # T.Encaps for IPv4 updates the headers as follows:
- # SR Policy seglist (S3, S2, S1)
- # SR Policy source C
- # IPv4:
- # in: IPv4(A, B2)
- # out: IPv6(C, S1)SRH(S3, S2, S1; SL=2)IPv4(A, B2)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ip = tx_pkt.getlayer(IP)
-
- # expected segment-list
- seglist = self.sr_policy.segments
- # reverse list to get order as in SRH
- tx_seglist = seglist[::-1]
-
- # get source address of SR Policy
- sr_policy_source = self.sr_policy.source
-
- # checks common to cases tx with and without SRH
- # rx'ed packet should have SRH and IPv4 header
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- self.assertTrue(rx_ip.payload.haslayer(IP))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, sr_policy_source)
- # received ip.dst should be equal to sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
- # rx'ed seglist should be equal to seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the ttl field and ip checksum
- # -> adjust tx'ed ttl to expected ttl
- tx_ip.ttl = tx_ip.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip.chksum = None
- # read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- tx_ip = IP(scapy.compat.raw(tx_ip))
-
- self.assertEqual(rx_srh.payload, tx_ip)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_T_Encaps_L2(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing T.Encaps for L2
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # T.Encaps for L2 updates the headers as follows:
- # SR Policy seglist (S3, S2, S1)
- # SR Policy source C
- # L2:
- # in: L2
- # out: IPv6(C, S1)SRH(S3, S2, S1; SL=2)L2
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ether = tx_pkt.getlayer(Ether)
-
- # expected segment-list
- seglist = self.sr_policy.segments
- # reverse list to get order as in SRH
- tx_seglist = seglist[::-1]
-
- # get source address of SR Policy
- sr_policy_source = self.sr_policy.source
-
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, sr_policy_source)
- # received ip.dst should be equal to sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
- # rx'ed seglist should be equal to seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
- # nh should be "No Next Header" (59)
- self.assertEqual(rx_srh.nh, 59)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- self.assertEqual(Ether(scapy.compat.raw(rx_srh.payload)), tx_ether)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_T_Insert(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing T.Insert
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # T.Insert updates the headers as follows:
- # IPv6:
- # in: IPv6(A, B2)
- # out: IPv6(A, S1)SRH(B2, S3, S2, S1; SL=3)
- # IPv6 + SRH:
- # in: IPv6(A, B2)SRH(B3, B2, B1; SL=1)
- # out: IPv6(A, S1)SRH(B2, S3, S2, S1; SL=3)SRH(B3, B2, B1; SL=1)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
- rx_ip2 = None
- rx_srh2 = None
- rx_ip3 = None
- rx_udp = rx_pkt[UDP]
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_srh = None
- tx_ip2 = None
- # some packets have been tx'ed with an SRH, some without it
- # get SRH if tx'ed packet has it
- if tx_pkt.haslayer(IPv6ExtHdrSegmentRouting):
- tx_srh = tx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
- tx_udp = tx_pkt[UDP]
-
- # expected segment-list (make copy of SR Policy segment list)
- seglist = self.sr_policy.segments[:]
- # expected seglist has initial dest addr as last segment
- seglist.append(tx_ip.dst)
- # reverse list to get order as in SRH
- tx_seglist = seglist[::-1]
-
- # get source address of SR Policy
- sr_policy_source = self.sr_policy.source
-
- # checks common to cases tx with and without SRH
- # rx'ed packet should have SRH and only one IPv6 header
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- self.assertFalse(rx_ip.payload.haslayer(IPv6))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # rx'ed ip.src should be equal to tx'ed ip.src
- self.assertEqual(rx_ip.src, tx_ip.src)
- # rx'ed ip.dst should be equal to sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
-
- # rx'ed seglist should be equal to expected seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size(expected seglist)-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
-
- if tx_srh: # packet was tx'ed with SRH
- # packet should have 2nd SRH
- self.assertTrue(rx_srh.payload.haslayer(IPv6ExtHdrSegmentRouting))
- # get 2nd SRH
- rx_srh2 = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting, 2)
-
- # rx'ed srh2.addresses should be equal to tx'ed srh.addresses
- self.assertEqual(rx_srh2.addresses, tx_srh.addresses)
- # rx'ed srh2.segleft should be equal to tx'ed srh.segleft
- self.assertEqual(rx_srh2.segleft, tx_srh.segleft)
- # rx'ed srh2.lastentry should be equal to tx'ed srh.lastentry
- self.assertEqual(rx_srh2.lastentry, tx_srh.lastentry)
-
- else: # packet was tx'ed without SRH
- # rx packet should have no other SRH
- self.assertFalse(rx_srh.payload.haslayer(IPv6ExtHdrSegmentRouting))
-
- # UDP layer should be unchanged
- self.assertEqual(rx_udp, tx_udp)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End (without PSP)
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # End (no PSP) updates the headers as follows:
- # IPv6 + SRH:
- # in: IPv6(A, S1)SRH(S3, S2, S1; SL=2)
- # out: IPv6(A, S2)SRH(S3, S2, S1; SL=1)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
- rx_ip2 = None
- rx_udp = rx_pkt[UDP]
-
- tx_ip = tx_pkt.getlayer(IPv6)
- # we know the packet has been tx'ed
- # with an inner IPv6 header and an SRH
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
- tx_srh = tx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- tx_udp = tx_pkt[UDP]
-
- # common checks, regardless of tx segleft value
- # rx'ed packet should have 2nd IPv6 header
- self.assertTrue(rx_ip.payload.haslayer(IPv6))
- # get second (inner) IPv6 header
- rx_ip2 = rx_pkt.getlayer(IPv6, 2)
-
- if tx_ip.segleft > 0:
- # SRH should NOT have been popped:
- # End SID without PSP does not pop SRH if segleft>0
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # received ip.src should be equal to expected ip.src
- self.assertEqual(rx_ip.src, tx_ip.src)
- # sidlist should be unchanged
- self.assertEqual(rx_srh.addresses, tx_srh.addresses)
- # segleft should have been decremented
- self.assertEqual(rx_srh.segleft, tx_srh.segleft-1)
- # received ip.dst should be equal to sidlist[segleft]
- self.assertEqual(rx_ip.dst, rx_srh.addresses[rx_srh.segleft])
- # lastentry should be unchanged
- self.assertEqual(rx_srh.lastentry, tx_srh.lastentry)
- # inner IPv6 packet (ip2) should be unchanged
- self.assertEqual(rx_ip2.src, tx_ip2.src)
- self.assertEqual(rx_ip2.dst, tx_ip2.dst)
- # else: # tx_ip.segleft == 0
- # TODO: Does this work with 2 SRHs in ingress packet?
-
- # UDP layer should be unchanged
- self.assertEqual(rx_udp, tx_udp)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_PSP(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End with PSP
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # End (PSP) updates the headers as follows:
- # IPv6 + SRH (SL>1):
- # in: IPv6(A, S1)SRH(S3, S2, S1; SL=2)
- # out: IPv6(A, S2)SRH(S3, S2, S1; SL=1)
- # IPv6 + SRH (SL=1):
- # in: IPv6(A, S2)SRH(S3, S2, S1; SL=1)
- # out: IPv6(A, S3)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
- rx_ip2 = None
- rx_udp = rx_pkt[UDP]
-
- tx_ip = tx_pkt.getlayer(IPv6)
- # we know the packet has been tx'ed
- # with an inner IPv6 header and an SRH
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
- tx_srh = tx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- tx_udp = tx_pkt[UDP]
-
- # common checks, regardless of tx segleft value
- self.assertTrue(rx_ip.payload.haslayer(IPv6))
- rx_ip2 = rx_pkt.getlayer(IPv6, 2)
- # inner IPv6 packet (ip2) should be unchanged
- self.assertEqual(rx_ip2.src, tx_ip2.src)
- self.assertEqual(rx_ip2.dst, tx_ip2.dst)
-
- if tx_ip.segleft > 1:
- # SRH should NOT have been popped:
- # End SID with PSP does not pop SRH if segleft>1
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
-
- # received ip.src should be equal to expected ip.src
- self.assertEqual(rx_ip.src, tx_ip.src)
- # sidlist should be unchanged
- self.assertEqual(rx_srh.addresses, tx_srh.addresses)
- # segleft should have been decremented
- self.assertEqual(rx_srh.segleft, tx_srh.segleft-1)
- # received ip.dst should be equal to sidlist[segleft]
- self.assertEqual(rx_ip.dst, rx_srh.addresses[rx_srh.segleft])
- # lastentry should be unchanged
- self.assertEqual(rx_srh.lastentry, tx_srh.lastentry)
-
- else: # tx_ip.segleft <= 1
- # SRH should have been popped:
- # End SID with PSP and segleft=1 pops SRH
- # the two IPv6 headers are still present
- # outer IPv6 header has DA == last segment of popped SRH
- # SRH should not be present
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # outer IPv6 header ip.src should be equal to tx'ed ip.src
- self.assertEqual(rx_ip.src, tx_ip.src)
- # outer IPv6 header ip.dst should be = to tx'ed sidlist[segleft-1]
- self.assertEqual(rx_ip.dst, tx_srh.addresses[tx_srh.segleft-1])
-
- # UDP layer should be unchanged
- self.assertEqual(rx_udp, tx_udp)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_DX6(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.DX6
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # End.DX6 updates the headers as follows:
- # IPv6 + SRH (SL=0):
- # in: IPv6(A, S3)SRH(S3, S2, S1; SL=0)IPv6(B, D)
- # out: IPv6(B, D)
- # IPv6:
- # in: IPv6(A, S3)IPv6(B, D)
- # out: IPv6(B, D)
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the hlim field
- # -> adjust tx'ed hlim to expected hlim
- tx_ip2.hlim = tx_ip2.hlim - 1
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_DX4(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.DX4
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # End.DX4 updates the headers as follows:
- # IPv6 + SRH (SL=0):
- # in: IPv6(A, S3)SRH(S3, S2, S1; SL=0)IPv4(B, D)
- # out: IPv4(B, D)
- # IPv6:
- # in: IPv6(A, S3)IPv4(B, D)
- # out: IPv4(B, D)
-
- # get IPv4 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IP)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IP)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the ttl field and ip checksum
- # -> adjust tx'ed ttl to expected ttl
- tx_ip2.ttl = tx_ip2.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip2.chksum = None
- # read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- tx_ip2 = IP(scapy.compat.raw(tx_ip2))
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_DX2(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.DX2
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
- # End.DX2 updates the headers as follows:
- # IPv6 + SRH (SL=0):
- # in: IPv6(A, S3)SRH(S3, S2, S1; SL=0)L2
- # out: L2
- # IPv6:
- # in: IPv6(A, S3)L2
- # out: L2
-
- # get IPv4 header of rx'ed packet
- rx_eth = rx_pkt.getlayer(Ether)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- # we can't just get the 2nd Ether layer
- # get the Raw content and dissect it as Ether
- tx_eth1 = Ether(scapy.compat.raw(tx_pkt[Raw]))
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_eth pkt should be equal to tx_eth1
- self.assertEqual(rx_eth, tx_eth1)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def create_stream(self, src_if, dst_if, packet_header, packet_sizes,
- count):
- """Create SRv6 input packet stream for defined interface.
-
- :param VppInterface src_if: Interface to create packet stream for
- :param VppInterface dst_if: destination interface of packet stream
- :param packet_header: Layer3 scapy packet headers,
- L2 is added when not provided,
- Raw(payload) with packet_info is added
- :param list packet_sizes: packet stream pckt sizes,sequentially applied
- to packets in stream have
- :param int count: number of packets in packet stream
- :return: list of packets
- """
- self.logger.info("Creating packets")
- pkts = []
- for i in range(0, count-1):
- payload_info = self.create_packet_info(src_if, dst_if)
- self.logger.debug(
- "Creating packet with index %d" % (payload_info.index))
- payload = self.info_to_payload(payload_info)
- # add L2 header if not yet provided in packet_header
- if packet_header.getlayer(0).name == 'Ethernet':
- p = (packet_header /
- Raw(payload))
- else:
- p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
- packet_header /
- Raw(payload))
- size = packet_sizes[i % len(packet_sizes)]
- self.logger.debug("Packet size %d" % (size))
- self.extend_packet(p, size)
- # we need to store the packet with the automatic fields computed
- # read back the dumped packet (with str())
- # to force computing these fields
- # probably other ways are possible
- p = Ether(scapy.compat.raw(p))
- payload_info.data = p.copy()
- self.logger.debug(ppp("Created packet:", p))
- pkts.append(p)
- self.logger.info("Done creating packets")
- return pkts
-
- def send_and_verify_pkts(self, input, pkts, output, compare_func):
- """Send packets and verify received packets using compare_func
-
- :param input: ingress interface of DUT
- :param pkts: list of packets to transmit
- :param output: egress interface of DUT
- :param compare_func: function to compare in and out packets
- """
- # add traffic stream to input interface
- input.add_stream(pkts)
-
- # enable capture on all interfaces
- self.pg_enable_capture(self.pg_interfaces)
-
- # start traffic
- self.logger.info("Starting traffic")
- self.pg_start()
-
- # get output capture
- self.logger.info("Getting packet capture")
- capture = output.get_capture()
-
- # assert nothing was captured on input interface
- input.assert_nothing_captured()
-
- # verify captured packets
- self.verify_captured_pkts(output, capture, compare_func)
-
- def create_packet_header_IPv6(self, dst):
- """Create packet header: IPv6 header, UDP header
-
- :param dst: IPv6 destination address
-
- IPv6 source address is 1234::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=dst) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH(self, sidlist, segleft):
- """Create packet header: IPv6 header with SRH, UDP header
-
- :param list sidlist: segment list
- :param int segleft: segments-left field value
-
- IPv6 destination address is set to sidlist[segleft]
- IPv6 source addresses are 1234::1 and 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH_IPv6(self, dst, sidlist, segleft):
- """Create packet header: IPv6 encapsulated in SRv6:
- IPv6 header with SRH, IPv6 header, UDP header
-
- :param ipv6address dst: inner IPv6 destination address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source addresses are 1234::1 and 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=41) /
- IPv6(src='4321::1', dst=dst) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_IPv6(self, dst_inner, dst_outer):
- """Create packet header: IPv6 encapsulated in IPv6:
- IPv6 header, IPv6 header, UDP header
-
- :param ipv6address dst_inner: inner IPv6 destination address
- :param ipv6address dst_outer: outer IPv6 destination address
-
- IPv6 source addresses are 1234::1 and 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=dst_outer) /
- IPv6(src='4321::1', dst=dst_inner) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH_SRH_IPv6(self, dst, sidlist1, segleft1,
- sidlist2, segleft2):
- """Create packet header: IPv6 encapsulated in SRv6 with 2 SRH:
- IPv6 header with SRH, 2nd SRH, IPv6 header, UDP header
-
- :param ipv6address dst: inner IPv6 destination address
- :param list sidlist1: segment list of outer IPv6 SRH
- :param int segleft1: segments-left field of outer IPv6 SRH
- :param list sidlist2: segment list of inner IPv6 SRH
- :param int segleft2: segments-left field of inner IPv6 SRH
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source addresses are 1234::1 and 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=sidlist1[segleft1]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist1,
- segleft=segleft1, nh=43) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist2,
- segleft=segleft2, nh=41) /
- IPv6(src='4321::1', dst=dst) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv4(self, dst):
- """Create packet header: IPv4 header, UDP header
-
- :param dst: IPv4 destination address
-
- IPv4 source address is 123.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = (IP(src='123.1.1.1', dst=dst) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_IPv4(self, dst_inner, dst_outer):
- """Create packet header: IPv4 encapsulated in IPv6:
- IPv6 header, IPv4 header, UDP header
-
- :param ipv4address dst_inner: inner IPv4 destination address
- :param ipv6address dst_outer: outer IPv6 destination address
-
- IPv6 source address is 1234::1
- IPv4 source address is 123.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=dst_outer) /
- IP(src='123.1.1.1', dst=dst_inner) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH_IPv4(self, dst, sidlist, segleft):
- """Create packet header: IPv4 encapsulated in SRv6:
- IPv6 header with SRH, IPv4 header, UDP header
-
- :param ipv4address dst: inner IPv4 destination address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source address is 1234::1
- IPv4 source address is 123.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=4) /
- IP(src='123.1.1.1', dst=dst) /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_L2(self, vlan=0):
- """Create packet header: L2 header
-
- :param vlan: if vlan!=0 then add 802.1q header
- """
- # Note: the dst addr ('00:55:44:33:22:11') is used in
- # the compare function compare_rx_tx_packet_T_Encaps_L2
- # to detect presence of L2 in SRH payload
- p = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- p /= Dot1Q(vlan=vlan, type=etype)
- else:
- p.type = etype
- return p
-
- def create_packet_header_IPv6_SRH_L2(self, sidlist, segleft, vlan=0):
- """Create packet header: L2 encapsulated in SRv6:
- IPv6 header with SRH, L2
-
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
- :param vlan: L2 vlan; if vlan!=0 then add 802.1q header
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source address is 1234::1
- """
- eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- eth /= Dot1Q(vlan=vlan, type=etype)
- else:
- eth.type = etype
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=59) /
- eth)
- return p
-
- def create_packet_header_IPv6_L2(self, dst_outer, vlan=0):
- """Create packet header: L2 encapsulated in IPv6:
- IPv6 header, L2
-
- :param ipv6address dst_outer: outer IPv6 destination address
- :param vlan: L2 vlan; if vlan!=0 then add 802.1q header
- """
- eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- eth /= Dot1Q(vlan=vlan, type=etype)
- else:
- eth.type = etype
-
- p = (IPv6(src='1234::1', dst=dst_outer, nh=59) / eth)
- return p
-
- def get_payload_info(self, packet):
- """ Extract the payload_info from the packet
- """
- # in most cases, payload_info is in packet[Raw]
- # but packet[Raw] gives the complete payload
- # (incl L2 header) for the T.Encaps L2 case
- try:
- payload_info = self.payload_to_info(packet[Raw])
-
- except:
- # remote L2 header from packet[Raw]:
- # take packet[Raw], convert it to an Ether layer
- # and then extract Raw from it
- payload_info = self.payload_to_info(
- Ether(scapy.compat.r(packet[Raw]))[Raw])
-
- return payload_info
-
- def verify_captured_pkts(self, dst_if, capture, compare_func):
- """
- Verify captured packet stream for specified interface.
- Compare ingress with egress packets using the specified compare fn
-
- :param dst_if: egress interface of DUT
- :param capture: captured packets
- :param compare_func: function to compare in and out packet
- """
- self.logger.info("Verifying capture on interface %s using function %s"
- % (dst_if.name, compare_func.__name__))
-
- last_info = dict()
- for i in self.pg_interfaces:
- last_info[i.sw_if_index] = None
- dst_sw_if_index = dst_if.sw_if_index
-
- for packet in capture:
- try:
- # extract payload_info from packet's payload
- payload_info = self.get_payload_info(packet)
- packet_index = payload_info.index
-
- self.logger.debug("Verifying packet with index %d"
- % (packet_index))
- # packet should have arrived on the expected interface
- self.assertEqual(payload_info.dst, dst_sw_if_index)
- self.logger.debug(
- "Got packet on interface %s: src=%u (idx=%u)" %
- (dst_if.name, payload_info.src, packet_index))
-
- # search for payload_info with same src and dst if_index
- # this will give us the transmitted packet
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- # next_info should not be None
- self.assertTrue(next_info is not None)
- # index of tx and rx packets should be equal
- self.assertEqual(packet_index, next_info.index)
- # data field of next_info contains the tx packet
- txed_packet = next_info.data
-
- self.logger.debug(ppp("Transmitted packet:",
- txed_packet)) # ppp=Pretty Print Packet
-
- self.logger.debug(ppp("Received packet:", packet))
-
- # compare rcvd packet with expected packet using compare_func
- compare_func(txed_packet, packet)
-
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # have all expected packets arrived?
- for i in self.pg_interfaces:
- remaining_packet = self.get_next_packet_info_for_interface2(
- i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
- self.assertTrue(remaining_packet is None,
- "Interface %s: Packet expected from interface %s "
- "didn't arrive" % (dst_if.name, i.name))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_srv6_ad.py b/test/test_srv6_ad.py
deleted file mode 100644
index aa4b8d3c088..00000000000
--- a/test/test_srv6_ad.py
+++ /dev/null
@@ -1,811 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-import binascii
-from socket import AF_INET6
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip import DpoProto
-from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
-from vpp_srv6 import SRv6LocalSIDBehaviors, VppSRv6LocalSID, VppSRv6Policy, \
- SRv6PolicyType, VppSRv6Steering, SRv6PolicySteeringTypes
-
-import scapy.compat
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet6 import IPv6, UDP, IPv6ExtHdrSegmentRouting
-from scapy.layers.inet import IP, UDP
-
-from scapy.utils import inet_pton, inet_ntop
-
-from util import ppp
-
-
-class TestSRv6(VppTestCase):
- """ SRv6 Dynamic Proxy plugin Test Case """
-
- @classmethod
- def setUpClass(self):
- super(TestSRv6, self).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestSRv6, cls).tearDownClass()
-
- def setUp(self):
- """ Perform test setup before each test case.
- """
- super(TestSRv6, self).setUp()
-
- # packet sizes, inclusive L2 overhead
- self.pg_packet_sizes = [64, 512, 1518, 9018]
-
- # reset packet_infos
- self.reset_packet_infos()
-
- def tearDown(self):
- """ Clean up test setup after each test case.
- """
- self.teardown_interfaces()
-
- super(TestSRv6, self).tearDown()
-
- def configure_interface(self,
- interface,
- ipv6=False, ipv4=False,
- ipv6_table_id=0, ipv4_table_id=0):
- """ Configure interface.
- :param ipv6: configure IPv6 on interface
- :param ipv4: configure IPv4 on interface
- :param ipv6_table_id: FIB table_id for IPv6
- :param ipv4_table_id: FIB table_id for IPv4
- """
- self.logger.debug("Configuring interface %s" % (interface.name))
- if ipv6:
- self.logger.debug("Configuring IPv6")
- interface.set_table_ip6(ipv6_table_id)
- interface.config_ip6()
- interface.resolve_ndp(timeout=5)
- if ipv4:
- self.logger.debug("Configuring IPv4")
- interface.set_table_ip4(ipv4_table_id)
- interface.config_ip4()
- interface.resolve_arp()
- interface.admin_up()
-
- def setup_interfaces(self, ipv6=[], ipv4=[],
- ipv6_table_id=[], ipv4_table_id=[]):
- """ Create and configure interfaces.
-
- :param ipv6: list of interface IPv6 capabilities
- :param ipv4: list of interface IPv4 capabilities
- :param ipv6_table_id: list of intf IPv6 FIB table_ids
- :param ipv4_table_id: list of intf IPv4 FIB table_ids
- :returns: List of created interfaces.
- """
- # how many interfaces?
- if len(ipv6):
- count = len(ipv6)
- else:
- count = len(ipv4)
- self.logger.debug("Creating and configuring %d interfaces" % (count))
-
- # fill up ipv6 and ipv4 lists if needed
- # not enabled (False) is the default
- if len(ipv6) < count:
- ipv6 += (count - len(ipv6)) * [False]
- if len(ipv4) < count:
- ipv4 += (count - len(ipv4)) * [False]
-
- # fill up table_id lists if needed
- # table_id 0 (global) is the default
- if len(ipv6_table_id) < count:
- ipv6_table_id += (count - len(ipv6_table_id)) * [0]
- if len(ipv4_table_id) < count:
- ipv4_table_id += (count - len(ipv4_table_id)) * [0]
-
- # create 'count' pg interfaces
- self.create_pg_interfaces(range(count))
-
- # setup all interfaces
- for i in range(count):
- intf = self.pg_interfaces[i]
- self.configure_interface(intf,
- ipv6[i], ipv4[i],
- ipv6_table_id[i], ipv4_table_id[i])
-
- if any(ipv6):
- self.logger.debug(self.vapi.cli("show ip6 neighbors"))
- if any(ipv4):
- self.logger.debug(self.vapi.cli("show ip arp"))
- self.logger.debug(self.vapi.cli("show interface"))
- self.logger.debug(self.vapi.cli("show hardware"))
-
- return self.pg_interfaces
-
- def teardown_interfaces(self):
- """ Unconfigure and bring down interface.
- """
- self.logger.debug("Tearing down interfaces")
- # tear down all interfaces
- # AFAIK they cannot be deleted
- for i in self.pg_interfaces:
- self.logger.debug("Tear down interface %s" % (i.name))
- i.admin_down()
- i.unconfig()
- i.set_table_ip4(0)
- i.set_table_ip6(0)
-
- def test_SRv6_End_AD_IPv6(self):
- """ Test SRv6 End.AD behavior with IPv6 traffic.
- """
- self.src_addr = 'a0::'
- self.sid_list = ['a1::', 'a2::a6', 'a3::']
- self.test_sid_index = 1
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure route to next segment
- route = VppIpRoute(self, self.sid_list[self.test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index,
- proto=DpoProto.DPO_PROTO_IP6)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + \
- self.sid_list[self.test_sid_index] + \
- " behavior end.ad" + \
- " nh " + self.pg1.remote_ip6 + \
- " oif " + self.pg1.name + \
- " iif " + self.pg1.name
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare IPv6 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_IPv6(
- srcaddr=self.src_addr,
- sidlist=self.sid_list[::-1],
- segleft=len(self.sid_list) - self.test_sid_index - 1)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AD_IPv6_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare IPv6 header for returning packets
- packet_header2 = self.create_packet_header_IPv6()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AD_IPv6_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- cli_str = "sr localsid del address " + \
- self.sid_list[self.test_sid_index]
- self.vapi.cli(cli_str)
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def compare_rx_tx_packet_End_AD_IPv6_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD with IPv6
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the hlim field
- # -> adjust tx'ed hlim to expected hlim
- tx_ip2.hlim = tx_ip2.hlim - 1
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AD_IPv6_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.src_addr)
- # received ip.dst should be equal to expected sidlist next segment
- self.assertEqual(rx_ip.dst, self.sid_list[self.test_sid_index + 1])
-
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to SID-list in reversed order
- self.assertEqual(rx_srh.addresses, self.sid_list[::-1])
- # segleft should be equal to previous segleft value minus 1
- self.assertEqual(rx_srh.segleft,
- len(self.sid_list) - self.test_sid_index - 2)
- # lastentry should be equal to the SID-list length minus 1
- self.assertEqual(rx_srh.lastentry, len(self.sid_list) - 1)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the hop-limit field
- tx_ip = tx_pkt.getlayer(IPv6)
- # -> update tx'ed hlim to the expected hlim
- tx_ip.hlim -= 1
- # -> check payload
- self.assertEqual(rx_srh.payload, tx_ip)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def test_SRv6_End_AD_IPv4(self):
- """ Test SRv6 End.AD behavior with IPv4 traffic.
- """
- self.src_addr = 'a0::'
- self.sid_list = ['a1::', 'a2::a4', 'a3::']
- self.test_sid_index = 1
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, False], ipv4=[False, True])
-
- # configure route to next segment
- route = VppIpRoute(self, self.sid_list[self.test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index,
- proto=DpoProto.DPO_PROTO_IP6)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + \
- self.sid_list[self.test_sid_index] + \
- " behavior end.ad" + \
- " nh " + self.pg1.remote_ip4 + \
- " oif " + self.pg1.name + \
- " iif " + self.pg1.name
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare IPv4 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_IPv4(
- srcaddr=self.src_addr,
- sidlist=self.sid_list[::-1],
- segleft=len(self.sid_list) - self.test_sid_index - 1)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AD_IPv4_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare IPv6 header for returning packets
- packet_header2 = self.create_packet_header_IPv4()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AD_IPv4_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- cli_str = "sr localsid del address " + \
- self.sid_list[self.test_sid_index]
- self.vapi.cli(cli_str)
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def compare_rx_tx_packet_End_AD_IPv4_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD with IPv4
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get IPv4 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IP)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IP)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the ttl field and ip checksum
- # -> adjust tx'ed ttl to expected ttl
- tx_ip2.ttl = tx_ip2.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip2.chksum = None
- # read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- tx_ip2 = IP(scapy.compat.raw(tx_ip2))
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AD_IPv4_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.src_addr)
- # received ip.dst should be equal to expected sidlist next segment
- self.assertEqual(rx_ip.dst, self.sid_list[self.test_sid_index + 1])
-
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to SID-list in reversed order
- self.assertEqual(rx_srh.addresses, self.sid_list[::-1])
- # segleft should be equal to previous segleft value minus 1
- self.assertEqual(rx_srh.segleft,
- len(self.sid_list) - self.test_sid_index - 2)
- # lastentry should be equal to the SID-list length minus 1
- self.assertEqual(rx_srh.lastentry, len(self.sid_list) - 1)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the ttl field and ip checksum
- tx_ip = tx_pkt.getlayer(IP)
- # -> adjust tx'ed ttl to expected ttl
- tx_ip.ttl = tx_ip.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip.chksum = None
- # -> read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- self.assertEqual(rx_srh.payload, IP(scapy.compat.raw(tx_ip)))
-
- self.logger.debug("packet verification: SUCCESS")
-
- def test_SRv6_End_AD_L2(self):
- """ Test SRv6 End.AD behavior with L2 traffic.
- """
- self.src_addr = 'a0::'
- self.sid_list = ['a1::', 'a2::a4', 'a3::']
- self.test_sid_index = 1
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, False])
-
- # configure route to next segment
- route = VppIpRoute(self, self.sid_list[self.test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index,
- proto=DpoProto.DPO_PROTO_IP6)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + \
- self.sid_list[self.test_sid_index] + \
- " behavior end.ad" + \
- " oif " + self.pg1.name + \
- " iif " + self.pg1.name
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare L2 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_L2(
- srcaddr=self.src_addr,
- sidlist=self.sid_list[::-1],
- segleft=len(self.sid_list) - self.test_sid_index - 1,
- vlan=0)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AD_L2_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare L2 header for returning packets
- packet_header2 = self.create_packet_header_L2()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AD_L2_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- cli_str = "sr localsid del address " + \
- self.sid_list[self.test_sid_index]
- self.vapi.cli(cli_str)
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def compare_rx_tx_packet_End_AD_L2_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD with L2
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get IPv4 header of rx'ed packet
- rx_eth = rx_pkt.getlayer(Ether)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- # we can't just get the 2nd Ether layer
- # get the Raw content and dissect it as Ether
- tx_eth1 = Ether(scapy.compat.raw(tx_pkt[Raw]))
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_eth pkt should be equal to tx_eth1
- self.assertEqual(rx_eth, tx_eth1)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AD_L2_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AD
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- ####
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.src_addr)
- # received ip.dst should be equal to expected sidlist next segment
- self.assertEqual(rx_ip.dst, self.sid_list[self.test_sid_index + 1])
-
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to SID-list in reversed order
- self.assertEqual(rx_srh.addresses, self.sid_list[::-1])
- # segleft should be equal to previous segleft value minus 1
- self.assertEqual(rx_srh.segleft,
- len(self.sid_list) - self.test_sid_index - 2)
- # lastentry should be equal to the SID-list length minus 1
- self.assertEqual(rx_srh.lastentry, len(self.sid_list) - 1)
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- tx_ether = tx_pkt.getlayer(Ether)
- self.assertEqual(Ether(scapy.compat.raw(rx_srh.payload)), tx_ether)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def create_stream(self, src_if, dst_if, packet_header, packet_sizes,
- count):
- """Create SRv6 input packet stream for defined interface.
-
- :param VppInterface src_if: Interface to create packet stream for
- :param VppInterface dst_if: destination interface of packet stream
- :param packet_header: Layer3 scapy packet headers,
- L2 is added when not provided,
- Raw(payload) with packet_info is added
- :param list packet_sizes: packet stream pckt sizes,sequentially applied
- to packets in stream have
- :param int count: number of packets in packet stream
- :return: list of packets
- """
- self.logger.info("Creating packets")
- pkts = []
- for i in range(0, count - 1):
- payload_info = self.create_packet_info(src_if, dst_if)
- self.logger.debug(
- "Creating packet with index %d" % (payload_info.index))
- payload = self.info_to_payload(payload_info)
- # add L2 header if not yet provided in packet_header
- if packet_header.getlayer(0).name == 'Ethernet':
- p = packet_header / Raw(payload)
- else:
- p = Ether(dst=src_if.local_mac, src=src_if.remote_mac) / \
- packet_header / Raw(payload)
- size = packet_sizes[i % len(packet_sizes)]
- self.logger.debug("Packet size %d" % (size))
- self.extend_packet(p, size)
- # we need to store the packet with the automatic fields computed
- # read back the dumped packet (with str())
- # to force computing these fields
- # probably other ways are possible
- p = Ether(scapy.compat.raw(p))
- payload_info.data = p.copy()
- self.logger.debug(ppp("Created packet:", p))
- pkts.append(p)
- self.logger.info("Done creating packets")
- return pkts
-
- def send_and_verify_pkts(self, input, pkts, output, compare_func):
- """Send packets and verify received packets using compare_func
-
- :param input: ingress interface of DUT
- :param pkts: list of packets to transmit
- :param output: egress interface of DUT
- :param compare_func: function to compare in and out packets
- """
- # add traffic stream to input interface
- input.add_stream(pkts)
-
- # enable capture on all interfaces
- self.pg_enable_capture(self.pg_interfaces)
-
- # start traffic
- self.logger.info("Starting traffic")
- self.pg_start()
-
- # get output capture
- self.logger.info("Getting packet capture")
- capture = output.get_capture()
-
- # assert nothing was captured on input interface
- # input.assert_nothing_captured()
-
- # verify captured packets
- self.verify_captured_pkts(output, capture, compare_func)
-
- def create_packet_header_IPv6(self):
- """Create packet header: IPv6 header, UDP header
-
- :param dst: IPv6 destination address
-
- IPv6 source address is 1234::1
- IPv6 destination address is 4321::1
- UDP source port and destination port are 1234
- """
-
- p = IPv6(src='1234::1', dst='4321::1') / UDP(sport=1234, dport=1234)
- return p
-
- def create_packet_header_IPv6_SRH_IPv6(self, srcaddr, sidlist, segleft):
- """Create packet header: IPv6 encapsulated in SRv6:
- IPv6 header with SRH, IPv6 header, UDP header
-
- :param int srcaddr: outer source address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 source address is set to srcaddr
- Outer IPv6 destination address is set to sidlist[segleft]
- Inner IPv6 source addresses is 1234::1
- Inner IPv6 destination address is 4321::1
- UDP source port and destination port are 1234
- """
-
- p = IPv6(src=srcaddr, dst=sidlist[segleft]) / \
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=41) / \
- IPv6(src='1234::1', dst='4321::1') / \
- UDP(sport=1234, dport=1234)
- return p
-
- def create_packet_header_IPv4(self):
- """Create packet header: IPv4 header, UDP header
-
- :param dst: IPv4 destination address
-
- IPv4 source address is 123.1.1.1
- IPv4 destination address is 124.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = IP(src='123.1.1.1', dst='124.1.1.1') / UDP(sport=1234, dport=1234)
- return p
-
- def create_packet_header_IPv6_SRH_IPv4(self, srcaddr, sidlist, segleft):
- """Create packet header: IPv4 encapsulated in SRv6:
- IPv6 header with SRH, IPv4 header, UDP header
-
- :param int srcaddr: outer source address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 source address is set to srcaddr
- Outer IPv6 destination address is set to sidlist[segleft]
- Inner IPv4 source address is 123.1.1.1
- Inner IPv4 destination address is 124.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = IPv6(src=srcaddr, dst=sidlist[segleft]) / \
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=4) / \
- IP(src='123.1.1.1', dst='124.1.1.1') / \
- UDP(sport=1234, dport=1234)
- return p
-
- def create_packet_header_L2(self, vlan=0):
- """Create packet header: L2 header
-
- :param vlan: if vlan!=0 then add 802.1q header
- """
- # Note: the dst addr ('00:55:44:33:22:11') is used in
- # the compare function compare_rx_tx_packet_T_Encaps_L2
- # to detect presence of L2 in SRH payload
- p = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- p /= Dot1Q(vlan=vlan, type=etype)
- else:
- p.type = etype
- return p
-
- def create_packet_header_IPv6_SRH_L2(self, srcaddr, sidlist, segleft,
- vlan=0):
- """Create packet header: L2 encapsulated in SRv6:
- IPv6 header with SRH, L2
-
- :param int srcaddr: IPv6 source address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
- :param vlan: L2 vlan; if vlan!=0 then add 802.1q header
-
- IPv6 source address is set to srcaddr
- IPv6 destination address is set to sidlist[segleft]
- """
- eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- eth /= Dot1Q(vlan=vlan, type=etype)
- else:
- eth.type = etype
-
- p = IPv6(src=srcaddr, dst=sidlist[segleft]) / \
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=59) / \
- eth
- return p
-
- def get_payload_info(self, packet):
- """ Extract the payload_info from the packet
- """
- # in most cases, payload_info is in packet[Raw]
- # but packet[Raw] gives the complete payload
- # (incl L2 header) for the T.Encaps L2 case
- try:
- payload_info = self.payload_to_info(packet[Raw])
-
- except:
- # remote L2 header from packet[Raw]:
- # take packet[Raw], convert it to an Ether layer
- # and then extract Raw from it
- payload_info = self.payload_to_info(
- Ether(scapy.compat.raw(packet[Raw]))[Raw])
-
- return payload_info
-
- def verify_captured_pkts(self, dst_if, capture, compare_func):
- """
- Verify captured packet stream for specified interface.
- Compare ingress with egress packets using the specified compare fn
-
- :param dst_if: egress interface of DUT
- :param capture: captured packets
- :param compare_func: function to compare in and out packet
- """
- self.logger.info("Verifying capture on interface %s using function %s"
- % (dst_if.name, compare_func.__name__))
-
- last_info = dict()
- for i in self.pg_interfaces:
- last_info[i.sw_if_index] = None
- dst_sw_if_index = dst_if.sw_if_index
-
- for packet in capture:
- try:
- # extract payload_info from packet's payload
- payload_info = self.get_payload_info(packet)
- packet_index = payload_info.index
-
- self.logger.debug("Verifying packet with index %d"
- % (packet_index))
- # packet should have arrived on the expected interface
- self.assertEqual(payload_info.dst, dst_sw_if_index)
- self.logger.debug(
- "Got packet on interface %s: src=%u (idx=%u)" %
- (dst_if.name, payload_info.src, packet_index))
-
- # search for payload_info with same src and dst if_index
- # this will give us the transmitted packet
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- # next_info should not be None
- self.assertTrue(next_info is not None)
- # index of tx and rx packets should be equal
- self.assertEqual(packet_index, next_info.index)
- # data field of next_info contains the tx packet
- txed_packet = next_info.data
-
- self.logger.debug(ppp("Transmitted packet:",
- txed_packet)) # ppp=Pretty Print Packet
-
- self.logger.debug(ppp("Received packet:", packet))
-
- # compare rcvd packet with expected packet using compare_func
- compare_func(txed_packet, packet)
-
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # have all expected packets arrived?
- for i in self.pg_interfaces:
- remaining_packet = self.get_next_packet_info_for_interface2(
- i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
- self.assertTrue(remaining_packet is None,
- "Interface %s: Packet expected from interface %s "
- "didn't arrive" % (dst_if.name, i.name))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_srv6_as.py b/test/test_srv6_as.py
deleted file mode 100755
index 2be7865d5bd..00000000000
--- a/test/test_srv6_as.py
+++ /dev/null
@@ -1,889 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-import binascii
-from socket import AF_INET6
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto, VppIpTable
-from vpp_srv6 import SRv6LocalSIDBehaviors, VppSRv6LocalSID, VppSRv6Policy, \
- SRv6PolicyType, VppSRv6Steering, SRv6PolicySteeringTypes
-
-import scapy.compat
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet6 import IPv6, UDP, IPv6ExtHdrSegmentRouting
-from scapy.layers.inet import IP, UDP
-
-from scapy.utils import inet_pton, inet_ntop
-
-from util import ppp
-
-
-class TestSRv6(VppTestCase):
- """ SRv6 Static Proxy plugin Test Case """
-
- @classmethod
- def setUpClass(self):
- super(TestSRv6, self).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestSRv6, cls).tearDownClass()
-
- def setUp(self):
- """ Perform test setup before each test case.
- """
- super(TestSRv6, self).setUp()
-
- # packet sizes, inclusive L2 overhead
- self.pg_packet_sizes = [64, 512, 1518, 9018]
-
- # reset packet_infos
- self.reset_packet_infos()
-
- def tearDown(self):
- """ Clean up test setup after each test case.
- """
- self.teardown_interfaces()
-
- super(TestSRv6, self).tearDown()
-
- def configure_interface(self,
- interface,
- ipv6=False, ipv4=False,
- ipv6_table_id=0, ipv4_table_id=0):
- """ Configure interface.
- :param ipv6: configure IPv6 on interface
- :param ipv4: configure IPv4 on interface
- :param ipv6_table_id: FIB table_id for IPv6
- :param ipv4_table_id: FIB table_id for IPv4
- """
- self.logger.debug("Configuring interface %s" % (interface.name))
- if ipv6:
- self.logger.debug("Configuring IPv6")
- interface.set_table_ip6(ipv6_table_id)
- interface.config_ip6()
- interface.resolve_ndp(timeout=5)
- if ipv4:
- self.logger.debug("Configuring IPv4")
- interface.set_table_ip4(ipv4_table_id)
- interface.config_ip4()
- interface.resolve_arp()
- interface.admin_up()
-
- def setup_interfaces(self, ipv6=[], ipv4=[],
- ipv6_table_id=[], ipv4_table_id=[]):
- """ Create and configure interfaces.
-
- :param ipv6: list of interface IPv6 capabilities
- :param ipv4: list of interface IPv4 capabilities
- :param ipv6_table_id: list of intf IPv6 FIB table_ids
- :param ipv4_table_id: list of intf IPv4 FIB table_ids
- :returns: List of created interfaces.
- """
- # how many interfaces?
- if len(ipv6):
- count = len(ipv6)
- else:
- count = len(ipv4)
- self.logger.debug("Creating and configuring %d interfaces" % (count))
-
- # fill up ipv6 and ipv4 lists if needed
- # not enabled (False) is the default
- if len(ipv6) < count:
- ipv6 += (count - len(ipv6)) * [False]
- if len(ipv4) < count:
- ipv4 += (count - len(ipv4)) * [False]
-
- # fill up table_id lists if needed
- # table_id 0 (global) is the default
- if len(ipv6_table_id) < count:
- ipv6_table_id += (count - len(ipv6_table_id)) * [0]
- if len(ipv4_table_id) < count:
- ipv4_table_id += (count - len(ipv4_table_id)) * [0]
-
- # create 'count' pg interfaces
- self.create_pg_interfaces(range(count))
-
- # setup all interfaces
- for i in range(count):
- intf = self.pg_interfaces[i]
- self.configure_interface(intf,
- ipv6[i], ipv4[i],
- ipv6_table_id[i], ipv4_table_id[i])
-
- if any(ipv6):
- self.logger.debug(self.vapi.cli("show ip6 neighbors"))
- if any(ipv4):
- self.logger.debug(self.vapi.cli("show ip arp"))
- self.logger.debug(self.vapi.cli("show interface"))
- self.logger.debug(self.vapi.cli("show hardware"))
-
- return self.pg_interfaces
-
- def teardown_interfaces(self):
- """ Unconfigure and bring down interface.
- """
- self.logger.debug("Tearing down interfaces")
- # tear down all interfaces
- # AFAIK they cannot be deleted
- for i in self.pg_interfaces:
- self.logger.debug("Tear down interface %s" % (i.name))
- i.admin_down()
- i.unconfig()
- i.set_table_ip4(0)
- i.set_table_ip6(0)
-
- def test_SRv6_End_AS_IPv6_noSRH(self):
- """ Test SRv6 End.AS behavior with IPv6 traffic and no SRH rewrite.
- """
- self.run_SRv6_End_AS_IPv6(
- sid_list=['a1::', 'a2::a6', 'a3::'],
- test_sid_index=1,
- rewrite_src_addr='a2::')
-
- def test_SRv6_End_AS_IPv6_SRH(self):
- """ Test SRv6 End.AS behavior with IPv6 traffic and SRH rewrite.
- """
- self.run_SRv6_End_AS_IPv6(
- sid_list=['a1::a6', 'a2::', 'a3::'],
- test_sid_index=0,
- rewrite_src_addr='a1::')
-
- def test_SRv6_End_AS_IPv4_noSRH(self):
- """ Test SRv6 End.AS behavior with IPv4 traffic and no SRH rewrite.
- """
- self.run_SRv6_End_AS_IPv4(
- sid_list=['a1::', 'a2::a6', 'a3::'],
- test_sid_index=1,
- rewrite_src_addr='a2::')
-
- def test_SRv6_End_AS_IPv4_SRH(self):
- """ Test SRv6 End.AS behavior with IPv4 traffic and SRH rewrite.
- """
- self.run_SRv6_End_AS_IPv4(
- sid_list=['a1::a6', 'a2::', 'a3::'],
- test_sid_index=0,
- rewrite_src_addr='a1::')
-
- def test_SRv6_End_AS_L2_noSRH(self):
- """ Test SRv6 End.AS behavior with L2 traffic and no SRH rewrite.
- """
- self.run_SRv6_End_AS_L2(
- sid_list=['a1::', 'a2::a6', 'a3::'],
- test_sid_index=1,
- rewrite_src_addr='a2::')
-
- def test_SRv6_End_AS_L2_SRH(self):
- """ Test SRv6 End.AS behavior with L2 traffic and SRH rewrite.
- """
- self.run_SRv6_End_AS_L2(
- sid_list=['a1::a6', 'a2::', 'a3::'],
- test_sid_index=0,
- rewrite_src_addr='a1::')
-
- def run_SRv6_End_AS_L2(self, sid_list, test_sid_index, rewrite_src_addr):
- """ Run SRv6 End.AS test with L2 traffic.
- """
- self.rewrite_src_addr = rewrite_src_addr
- self.rewrite_sid_list = sid_list[test_sid_index + 1::]
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, False])
-
- # configure route to next segment
- route = VppIpRoute(self, sid_list[test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + sid_list[test_sid_index] \
- + " behavior end.as" \
- + " oif " + self.pg1.name \
- + " iif " + self.pg1.name \
- + " src " + self.rewrite_src_addr
- for s in self.rewrite_sid_list:
- cli_str += " next " + s
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare L2 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_L2(
- sidlist=sid_list[::-1],
- segleft=len(sid_list) - test_sid_index - 1,
- vlan=0)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AS_L2_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare L2 header for returning packets
- packet_header2 = self.create_packet_header_L2()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AS_L2_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- self.vapi.cli("sr localsid del address " + sid_list[test_sid_index])
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def run_SRv6_End_AS_IPv6(self, sid_list, test_sid_index, rewrite_src_addr):
- """ Run SRv6 End.AS test with IPv6 traffic.
- """
- self.rewrite_src_addr = rewrite_src_addr
- self.rewrite_sid_list = sid_list[test_sid_index + 1::]
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, True])
-
- # configure route to next segment
- route = VppIpRoute(self, sid_list[test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + sid_list[test_sid_index] \
- + " behavior end.as" \
- + " nh " + self.pg1.remote_ip6 \
- + " oif " + self.pg1.name \
- + " iif " + self.pg1.name \
- + " src " + self.rewrite_src_addr
- for s in self.rewrite_sid_list:
- cli_str += " next " + s
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare IPv6 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_IPv6(
- sidlist=sid_list[::-1],
- segleft=len(sid_list) - test_sid_index - 1)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AS_IPv6_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare IPv6 header for returning packets
- packet_header2 = self.create_packet_header_IPv6()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AS_IPv6_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- self.vapi.cli("sr localsid del address " + sid_list[test_sid_index])
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def run_SRv6_End_AS_IPv4(self, sid_list, test_sid_index, rewrite_src_addr):
- """ Run SRv6 End.AS test with IPv4 traffic.
- """
- self.rewrite_src_addr = rewrite_src_addr
- self.rewrite_sid_list = sid_list[test_sid_index + 1::]
-
- # send traffic to one destination interface
- # source and destination interfaces are IPv6 only
- self.setup_interfaces(ipv6=[True, False], ipv4=[True, True])
-
- # configure route to next segment
- route = VppIpRoute(self, sid_list[test_sid_index + 1], 128,
- [VppRoutePath(self.pg0.remote_ip6,
- self.pg0.sw_if_index)])
- route.add_vpp_config()
-
- # configure SRv6 localSID behavior
- cli_str = "sr localsid address " + sid_list[test_sid_index] \
- + " behavior end.as" \
- + " nh " + self.pg1.remote_ip4 \
- + " oif " + self.pg1.name \
- + " iif " + self.pg1.name \
- + " src " + self.rewrite_src_addr
- for s in self.rewrite_sid_list:
- cli_str += " next " + s
- self.vapi.cli(cli_str)
-
- # log the localsids
- self.logger.debug(self.vapi.cli("show sr localsid"))
-
- # send one packet per packet size
- count = len(self.pg_packet_sizes)
-
- # prepare IPv4 in SRv6 headers
- packet_header1 = self.create_packet_header_IPv6_SRH_IPv4(
- sidlist=sid_list[::-1],
- segleft=len(sid_list) - test_sid_index - 1)
-
- # generate packets (pg0->pg1)
- pkts1 = self.create_stream(self.pg0, self.pg1, packet_header1,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg0, pkts1, self.pg1,
- self.compare_rx_tx_packet_End_AS_IPv4_out)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # prepare IPv6 header for returning packets
- packet_header2 = self.create_packet_header_IPv4()
-
- # generate returning packets (pg1->pg0)
- pkts2 = self.create_stream(self.pg1, self.pg0, packet_header2,
- self.pg_packet_sizes, count)
-
- # send packets and verify received packets
- self.send_and_verify_pkts(self.pg1, pkts2, self.pg0,
- self.compare_rx_tx_packet_End_AS_IPv4_in)
-
- # log the localsid counters
- self.logger.info(self.vapi.cli("show sr localsid"))
-
- # remove SRv6 localSIDs
- self.vapi.cli("sr localsid del address " + sid_list[test_sid_index])
-
- # cleanup interfaces
- self.teardown_interfaces()
-
- def compare_rx_tx_packet_End_AS_IPv6_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ip = tx_pkt.getlayer(IPv6)
-
- # expected segment-list (SRH order)
- tx_seglist = self.rewrite_sid_list[::-1]
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.rewrite_src_addr)
- # received ip.dst should be equal to expected sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
-
- if len(tx_seglist) > 1:
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to expected seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size expected seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
- # get payload
- payload = rx_srh.payload
- else:
- # rx'ed packet should NOT have SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get payload
- payload = rx_ip.payload
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the hop-limit field
- # -> update tx'ed hlim to the expected hlim
- tx_ip.hlim = tx_ip.hlim - 1
-
- self.assertEqual(payload, tx_ip)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AS_IPv4_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ip = tx_pkt.getlayer(IP)
-
- # expected segment-list (SRH order)
- tx_seglist = self.rewrite_sid_list[::-1]
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.rewrite_src_addr)
- # received ip.dst should be equal to expected sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
-
- if len(tx_seglist) > 1:
- # rx'ed packet should have SRH and IPv4 header
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- self.assertTrue(rx_ip.payload.haslayer(IP))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
- payload = rx_srh.payload
- else:
- # rx'ed packet should NOT have SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get payload
- payload = rx_ip.payload
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- # except for the ttl field and ip checksum
- # -> adjust tx'ed ttl to expected ttl
- tx_ip.ttl = tx_ip.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip.chksum = None
- # read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- tx_ip = IP(scapy.compat.raw(tx_ip))
-
- self.assertEqual(payload, tx_ip)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AS_L2_in(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
- rx_srh = None
-
- tx_ether = tx_pkt.getlayer(Ether)
-
- # expected segment-list (SRH order)
- tx_seglist = self.rewrite_sid_list[::-1]
-
- # received ip.src should be equal to SR Policy source
- self.assertEqual(rx_ip.src, self.rewrite_src_addr)
- # received ip.dst should be equal to expected sidlist[lastentry]
- self.assertEqual(rx_ip.dst, tx_seglist[-1])
-
- if len(tx_seglist) > 1:
- # rx'ed packet should have SRH
- self.assertTrue(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get SRH
- rx_srh = rx_pkt.getlayer(IPv6ExtHdrSegmentRouting)
- # rx'ed seglist should be equal to seglist
- self.assertEqual(rx_srh.addresses, tx_seglist)
- # segleft should be equal to size seglist-1
- self.assertEqual(rx_srh.segleft, len(tx_seglist)-1)
- # segleft should be equal to lastentry
- self.assertEqual(rx_srh.segleft, rx_srh.lastentry)
- # nh should be "No Next Header" (59)
- self.assertEqual(rx_srh.nh, 59)
- # get payload
- payload = rx_srh.payload
- else:
- # rx'ed packet should NOT have SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
- # get payload
- payload = rx_ip.payload
-
- # the whole rx'ed pkt beyond SRH should be equal to tx'ed pkt
- self.assertEqual(Ether(scapy.compat.raw(payload)), tx_ether)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AS_IPv6_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS with IPv6
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get first (outer) IPv6 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IPv6)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IPv6, 2)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the hlim field
- # -> adjust tx'ed hlim to expected hlim
- tx_ip2.hlim = tx_ip2.hlim - 1
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AS_IPv4_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS with IPv4
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get IPv4 header of rx'ed packet
- rx_ip = rx_pkt.getlayer(IP)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- tx_ip2 = tx_pkt.getlayer(IP)
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_ip pkt should be equal to tx_ip2
- # except for the ttl field and ip checksum
- # -> adjust tx'ed ttl to expected ttl
- tx_ip2.ttl = tx_ip2.ttl - 1
- # -> set tx'ed ip checksum to None and let scapy recompute
- tx_ip2.chksum = None
- # read back the pkt (with str()) to force computing these fields
- # probably other ways to accomplish this are possible
- tx_ip2 = IP(scapy.compat.raw(tx_ip2))
-
- self.assertEqual(rx_ip, tx_ip2)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def compare_rx_tx_packet_End_AS_L2_out(self, tx_pkt, rx_pkt):
- """ Compare input and output packet after passing End.AS with L2
-
- :param tx_pkt: transmitted packet
- :param rx_pkt: received packet
- """
-
- # get IPv4 header of rx'ed packet
- rx_eth = rx_pkt.getlayer(Ether)
-
- tx_ip = tx_pkt.getlayer(IPv6)
- # we can't just get the 2nd Ether layer
- # get the Raw content and dissect it as Ether
- tx_eth1 = Ether(scapy.compat.raw(tx_pkt[Raw]))
-
- # verify if rx'ed packet has no SRH
- self.assertFalse(rx_pkt.haslayer(IPv6ExtHdrSegmentRouting))
-
- # the whole rx_eth pkt should be equal to tx_eth1
- self.assertEqual(rx_eth, tx_eth1)
-
- self.logger.debug("packet verification: SUCCESS")
-
- def create_stream(self, src_if, dst_if, packet_header, packet_sizes,
- count):
- """Create SRv6 input packet stream for defined interface.
-
- :param VppInterface src_if: Interface to create packet stream for
- :param VppInterface dst_if: destination interface of packet stream
- :param packet_header: Layer3 scapy packet headers,
- L2 is added when not provided,
- Raw(payload) with packet_info is added
- :param list packet_sizes: packet stream pckt sizes,sequentially applied
- to packets in stream have
- :param int count: number of packets in packet stream
- :return: list of packets
- """
- self.logger.info("Creating packets")
- pkts = []
- for i in range(0, count-1):
- payload_info = self.create_packet_info(src_if, dst_if)
- self.logger.debug(
- "Creating packet with index %d" % (payload_info.index))
- payload = self.info_to_payload(payload_info)
- # add L2 header if not yet provided in packet_header
- if packet_header.getlayer(0).name == 'Ethernet':
- p = (packet_header /
- Raw(payload))
- else:
- p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
- packet_header /
- Raw(payload))
- size = packet_sizes[i % len(packet_sizes)]
- self.logger.debug("Packet size %d" % (size))
- self.extend_packet(p, size)
- # we need to store the packet with the automatic fields computed
- # read back the dumped packet (with str())
- # to force computing these fields
- # probably other ways are possible
- p = Ether(scapy.compat.raw(p))
- payload_info.data = p.copy()
- self.logger.debug(ppp("Created packet:", p))
- pkts.append(p)
- self.logger.info("Done creating packets")
- return pkts
-
- def send_and_verify_pkts(self, input, pkts, output, compare_func):
- """Send packets and verify received packets using compare_func
-
- :param input: ingress interface of DUT
- :param pkts: list of packets to transmit
- :param output: egress interface of DUT
- :param compare_func: function to compare in and out packets
- """
- # add traffic stream to input interface
- input.add_stream(pkts)
-
- # enable capture on all interfaces
- self.pg_enable_capture(self.pg_interfaces)
-
- # start traffic
- self.logger.info("Starting traffic")
- self.pg_start()
-
- # get output capture
- self.logger.info("Getting packet capture")
- capture = output.get_capture()
-
- # assert nothing was captured on input interface
- # input.assert_nothing_captured()
-
- # verify captured packets
- self.verify_captured_pkts(output, capture, compare_func)
-
- def create_packet_header_IPv6(self):
- """Create packet header: IPv6 header, UDP header
-
- :param dst: IPv6 destination address
-
- IPv6 source address is 1234::1
- IPv6 destination address is 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst='4321::1') /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH_IPv6(self, sidlist, segleft):
- """Create packet header: IPv6 encapsulated in SRv6:
- IPv6 header with SRH, IPv6 header, UDP header
-
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 source address is set to 5678::1
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source addresses is 1234::1
- IPv6 destination address is 4321::1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='5678::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=41) /
- IPv6(src='1234::1', dst='4321::1') /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv4(self):
- """Create packet header: IPv4 header, UDP header
-
- :param dst: IPv4 destination address
-
- IPv4 source address is 123.1.1.1
- IPv4 destination address is 124.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = (IP(src='123.1.1.1', dst='124.1.1.1') /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_IPv6_SRH_IPv4(self, sidlist, segleft):
- """Create packet header: IPv4 encapsulated in SRv6:
- IPv6 header with SRH, IPv4 header, UDP header
-
- :param ipv4address dst: inner IPv4 destination address
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source address is 1234::1
- IPv4 source address is 123.1.1.1
- IPv4 destination address is 124.1.1.1
- UDP source port and destination port are 1234
- """
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=4) /
- IP(src='123.1.1.1', dst='124.1.1.1') /
- UDP(sport=1234, dport=1234))
- return p
-
- def create_packet_header_L2(self, vlan=0):
- """Create packet header: L2 header
-
- :param vlan: if vlan!=0 then add 802.1q header
- """
- # Note: the dst addr ('00:55:44:33:22:11') is used in
- # the compare function compare_rx_tx_packet_T_Encaps_L2
- # to detect presence of L2 in SRH payload
- p = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- p /= Dot1Q(vlan=vlan, type=etype)
- else:
- p.type = etype
- return p
-
- def create_packet_header_IPv6_SRH_L2(self, sidlist, segleft, vlan=0):
- """Create packet header: L2 encapsulated in SRv6:
- IPv6 header with SRH, L2
-
- :param list sidlist: segment list of outer IPv6 SRH
- :param int segleft: segments-left field of outer IPv6 SRH
- :param vlan: L2 vlan; if vlan!=0 then add 802.1q header
-
- Outer IPv6 destination address is set to sidlist[segleft]
- IPv6 source address is 1234::1
- """
- eth = Ether(src='00:11:22:33:44:55', dst='00:55:44:33:22:11')
- etype = 0x8137 # IPX
- if vlan:
- # add 802.1q layer
- eth /= Dot1Q(vlan=vlan, type=etype)
- else:
- eth.type = etype
-
- p = (IPv6(src='1234::1', dst=sidlist[segleft]) /
- IPv6ExtHdrSegmentRouting(addresses=sidlist,
- segleft=segleft, nh=59) /
- eth)
- return p
-
- def get_payload_info(self, packet):
- """ Extract the payload_info from the packet
- """
- # in most cases, payload_info is in packet[Raw]
- # but packet[Raw] gives the complete payload
- # (incl L2 header) for the T.Encaps L2 case
- try:
- payload_info = self.payload_to_info(packet[Raw])
-
- except:
- # remote L2 header from packet[Raw]:
- # take packet[Raw], convert it to an Ether layer
- # and then extract Raw from it
- payload_info = self.payload_to_info(
- Ether(scapy.compat.raw(packet[Raw]))[Raw])
-
- return payload_info
-
- def verify_captured_pkts(self, dst_if, capture, compare_func):
- """
- Verify captured packet stream for specified interface.
- Compare ingress with egress packets using the specified compare fn
-
- :param dst_if: egress interface of DUT
- :param capture: captured packets
- :param compare_func: function to compare in and out packet
- """
- self.logger.info("Verifying capture on interface %s using function %s"
- % (dst_if.name, compare_func.__name__))
-
- last_info = dict()
- for i in self.pg_interfaces:
- last_info[i.sw_if_index] = None
- dst_sw_if_index = dst_if.sw_if_index
-
- for packet in capture:
- try:
- # extract payload_info from packet's payload
- payload_info = self.get_payload_info(packet)
- packet_index = payload_info.index
-
- self.logger.debug("Verifying packet with index %d"
- % (packet_index))
- # packet should have arrived on the expected interface
- self.assertEqual(payload_info.dst, dst_sw_if_index)
- self.logger.debug(
- "Got packet on interface %s: src=%u (idx=%u)" %
- (dst_if.name, payload_info.src, packet_index))
-
- # search for payload_info with same src and dst if_index
- # this will give us the transmitted packet
- next_info = self.get_next_packet_info_for_interface2(
- payload_info.src, dst_sw_if_index,
- last_info[payload_info.src])
- last_info[payload_info.src] = next_info
- # next_info should not be None
- self.assertTrue(next_info is not None)
- # index of tx and rx packets should be equal
- self.assertEqual(packet_index, next_info.index)
- # data field of next_info contains the tx packet
- txed_packet = next_info.data
-
- self.logger.debug(ppp("Transmitted packet:",
- txed_packet)) # ppp=Pretty Print Packet
-
- self.logger.debug(ppp("Received packet:", packet))
-
- # compare rcvd packet with expected packet using compare_func
- compare_func(txed_packet, packet)
-
- except:
- self.logger.error(ppp("Unexpected or invalid packet:", packet))
- raise
-
- # have all expected packets arrived?
- for i in self.pg_interfaces:
- remaining_packet = self.get_next_packet_info_for_interface2(
- i.sw_if_index, dst_sw_if_index, last_info[i.sw_if_index])
- self.assertTrue(remaining_packet is None,
- "Interface %s: Packet expected from interface %s "
- "didn't arrive" % (dst_if.name, i.name))
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/test_svs.py b/test/test_svs.py
deleted file mode 100644
index 9a9ac57016b..00000000000
--- a/test/test_svs.py
+++ /dev/null
@@ -1,322 +0,0 @@
-#!/usr/bin/env python
-
-import unittest
-
-from framework import VppTestCase, VppTestRunner
-from vpp_ip_route import VppIpTable
-
-from scapy.packet import Raw
-from scapy.layers.l2 import Ether
-from scapy.layers.inet import IP, UDP, ICMP
-from scapy.layers.inet6 import IPv6
-
-from vpp_papi import VppEnum
-
-NUM_PKTS = 67
-
-
-class TestSVS(VppTestCase):
- """ SVS Test Case """
-
- @classmethod
- def setUpClass(cls):
- super(TestSVS, cls).setUpClass()
-
- @classmethod
- def tearDownClass(cls):
- super(TestSVS, cls).tearDownClass()
-
- def setUp(self):
- super(TestSVS, self).setUp()
-
- # create 2 pg interfaces
- self.create_pg_interfaces(range(4))
-
- table_id = 0
-
- for i in self.pg_interfaces:
- i.admin_up()
-
- if table_id != 0:
- tbl = VppIpTable(self, table_id)
- tbl.add_vpp_config()
- tbl = VppIpTable(self, table_id, is_ip6=1)
- tbl.add_vpp_config()
-
- i.set_table_ip4(table_id)
- i.set_table_ip6(table_id)
- i.config_ip4()
- i.resolve_arp()
- i.config_ip6()
- i.resolve_ndp()
- table_id += 1
-
- def tearDown(self):
- for i in self.pg_interfaces:
- i.unconfig_ip4()
- i.unconfig_ip6()
- i.ip6_disable()
- i.set_table_ip4(0)
- i.set_table_ip6(0)
- i.admin_down()
- super(TestSVS, self).tearDown()
-
- def test_svs4(self):
- """ Source VRF Select IP4 """
-
- #
- # packets destined out of the 3 non-default table interfaces
- #
- pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
- pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src="1.1.1.1", dst=self.pg1.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src="2.2.2.2", dst=self.pg2.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src="3.3.3.3", dst=self.pg3.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
-
- #
- # before adding the SVS config all these packets are dropped when
- # ingressing on pg0 since pg0 is in the default table
- #
- for p in pkts_0:
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add table 1001 & 1002 into which we'll add the routes
- # determining the source VRF selection
- #
- table_ids = [101, 102]
-
- for table_id in table_ids:
- self.vapi.svs_table_add_del(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_id)
-
- #
- # map X.0.0.0/8 to each SVS table for lookup in table X
- #
- for i in range(1, 4):
- self.vapi.svs_route_add_del(
- table_id, "%d.0.0.0/8" % i, i)
-
- #
- # Enable SVS on pg0/pg1 using table 1001/1002
- #
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[0],
- self.pg0.sw_if_index)
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4, table_ids[1],
- self.pg1.sw_if_index)
-
- #
- # now all the packets should be delivered out the respective interface
- #
- self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
- self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
- self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
- self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
- self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
- self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
-
- #
- # check that if the SVS lookup does not match a route the packet
- # is forwarded using the interface's routing table
- #
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
-
- #
- # dump the SVS configs
- #
- ss = self.vapi.svs_dump()
-
- self.assertEqual(ss[0].table_id, table_ids[0])
- self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
- self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
- self.assertEqual(ss[1].table_id, table_ids[1])
- self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
- self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
-
- #
- # cleanup
- #
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4,
- table_ids[0],
- self.pg0.sw_if_index,
- is_enable=0)
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4,
- table_ids[1],
- self.pg1.sw_if_index,
- is_enable=0)
-
- for table_id in table_ids:
- for i in range(1, 4):
- self.vapi.svs_route_add_del(
- table_id, "%d.0.0.0/8" % i,
- 0, is_add=0)
- self.vapi.svs_table_add_del(
- VppEnum.vl_api_address_family_t.ADDRESS_IP4,
- table_id,
- is_add=0)
-
- def test_svs6(self):
- """ Source VRF Select IP6 """
-
- #
- # packets destined out of the 3 non-default table interfaces
- #
- pkts_0 = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
- pkts_1 = [(Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src="2001:1::1", dst=self.pg1.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src="2001:2::1", dst=self.pg2.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100)),
- (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src="2001:3::1", dst=self.pg3.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))]
-
- #
- # before adding the SVS config all these packets are dropped when
- # ingressing on pg0 since pg0 is in the default table
- #
- for p in pkts_0:
- self.send_and_assert_no_replies(self.pg0, p * 1)
-
- #
- # Add table 1001 & 1002 into which we'll add the routes
- # determining the source VRF selection
- #
- table_ids = [101, 102]
-
- for table_id in table_ids:
- self.vapi.svs_table_add_del(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6, table_id)
-
- #
- # map X.0.0.0/8 to each SVS table for lookup in table X
- #
- for i in range(1, 4):
- self.vapi.svs_route_add_del(
- table_id, "2001:%d::/32" % i,
- i)
-
- #
- # Enable SVS on pg0/pg1 using table 1001/1002
- #
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6,
- table_ids[0],
- self.pg0.sw_if_index)
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6,
- table_ids[1],
- self.pg1.sw_if_index)
-
- #
- # now all the packets should be delivered out the respective interface
- #
- self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
- self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
- self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
- self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
- self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
- self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
-
- #
- # check that if the SVS lookup does not match a route the packet
- # is forwarded using the interface's routing table
- #
- p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
- IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
-
- p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
- IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) /
- UDP(sport=1234, dport=1234) /
- Raw('\xa5' * 100))
- self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
-
- #
- # dump the SVS configs
- #
- ss = self.vapi.svs_dump()
-
- self.assertEqual(ss[0].table_id, table_ids[0])
- self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
- self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
- self.assertEqual(ss[1].table_id, table_ids[1])
- self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
- self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
-
- #
- # cleanup
- #
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6,
- table_ids[0],
- self.pg0.sw_if_index,
- is_enable=0)
- self.vapi.svs_enable_disable(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6,
- table_ids[1],
- self.pg1.sw_if_index,
- is_enable=0)
- for table_id in table_ids:
- for i in range(1, 4):
- self.vapi.svs_route_add_del(
- table_id, "2001:%d::/32" % i,
- 0, is_add=0)
- self.vapi.svs_table_add_del(
- VppEnum.vl_api_address_family_t.ADDRESS_IP6,
- table_id,
- is_add=0)
-
-
-if __name__ == '__main__':
- unittest.main(testRunner=VppTestRunner)
diff --git a/test/vpp_igmp.py b/test/vpp_igmp.py
deleted file mode 100644
index 8f78a9b909a..00000000000
--- a/test/vpp_igmp.py
+++ /dev/null
@@ -1,75 +0,0 @@
-
-from vpp_object import VppObject
-import socket
-
-
-class IGMP_MODE:
- ROUTER = 0
- HOST = 1
-
-
-class IGMP_FILTER:
- INCLUDE = 1
- EXCLUDE = 0
-
-
-def find_igmp_state(states, itf, gaddr, saddr):
- for s in states:
- if s.sw_if_index == itf.sw_if_index and \
- str(s.gaddr) == gaddr and str(s.saddr) == saddr:
- return True
- return False
-
-
-def wait_for_igmp_event(test, timeout, itf, gaddr, saddr, ff):
- ev = test.vapi.wait_for_event(timeout, "igmp_event")
- if ev.sw_if_index == itf.sw_if_index and \
- str(ev.gaddr) == gaddr and str(ev.saddr) == saddr and \
- ev.filter == ff:
- return True
- return False
-
-
-class IgmpSG():
- def __init__(self, gaddr, saddrs):
- self.gaddr = gaddr
- self.gaddr_p = socket.inet_pton(socket.AF_INET, gaddr)
- self.saddrs = saddrs
- self.saddrs_p = []
- self.saddrs_encoded = []
- for s in saddrs:
- ss = socket.inet_pton(socket.AF_INET, s)
- self.saddrs_p.append(ss)
- self.saddrs_encoded.append(ss)
-
-
-class IgmpRecord():
- def __init__(self, sg, type):
- self.sg = sg
- self.type = type
-
-
-class VppHostState(VppObject):
- def __init__(self, test, filter, sw_if_index, sg):
- self._test = test
- self.sw_if_index = sw_if_index
- self.filter = filter
- self.sg = sg
-
- def add_vpp_config(self):
- self._test.vapi.igmp_listen(
- self.filter, self.sw_if_index,
- self.sg.saddrs_encoded, self.sg.gaddr_p)
-
- def remove_vpp_config(self):
- self._test.vapi.igmp_listen(
- self.filter,
- self.sw_if_index,
- [],
- self.sg.gaddr_p)
-
- def object_id(self):
- return "%s:%d" % (self.sg, self.sw_if_index)
-
- def query_vpp_config(self):
- return self._test.vapi.igmp_dump()
diff --git a/test/vpp_lb.py b/test/vpp_lb.py
deleted file mode 100644
index d755cef70e5..00000000000
--- a/test/vpp_lb.py
+++ /dev/null
@@ -1,84 +0,0 @@
-# Copyright (c) 2019. Vinci Consulting Corp. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import vpp_object
-
-
-class VppLbVip(vpp_object.VppObject):
-
- def __init__(self, test, pfx, sfx, port, protocol):
- self._test = test
- self.pfx = pfx
- self.sfx = sfx
- self.port = port
- self.protocol = protocol
-
- def add_vpp_config(self):
- self._test_vapi.lb_add_del_vip(pfx=self.pfx,
- sfx=self.pfx,
- port=self.port,
- protocol=self.protocol)
-
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.lb_add_del_vip(pfx=self.pfx,
- sfx=self.pfx,
- port=self.port,
- protocol=self.protocol,
- is_del=1)
-
- def query_vpp_config(self):
- details = self._test.vapi.lb_add_del_vip(fx=self.pfx,
- sfx=self.pfx,
- port=self.port,
- protocol=self.protocol)
- return True if self == details else False
-
-
-class VppLbAs(vpp_object.VppObject):
- def __init__(self, test, pfx, port, protocol, app_srv, is_del, is_flush):
- self._test = test
- # this is the vip
- self.pfx = pfx
- self.port = port
- self.protocol = protocol
-
- self.app_srv = app_srv
- self.is_del = is_del
- self.is_flush = is_flush
-
- def add_vpp_config(self):
- self._test_vapi.lb_add_del_as(pfx=self.pfx,
- port=self.port,
- protocol=self.protocol,
- app_srv=self.app_srv,
- is_flush=self.is_flush,
- )
-
- self._test.registry.register(self, self._test.logger)
-
- def remove_vpp_config(self):
- self._test.vapi.lb_add_del_as(pfx=self.pfx,
- port=self.port,
- protocol=self.protocol,
- app_srv=self.app_srv,
- is_flush=self.is_flush,
- is_del=1)
-
- def query_vpp_config(self):
- details = self._test.vapi.lb_as_dump(pfx=self.pfx,
- port=self.port,
- protocol=self.protocol)
- return True if self == details else False
diff --git a/test/vpp_memif.py b/test/vpp_memif.py
deleted file mode 100644
index 7fa45092740..00000000000
--- a/test/vpp_memif.py
+++ /dev/null
@@ -1,153 +0,0 @@
-import socket
-
-import six
-
-from vpp_object import VppObject
-
-
-class MEMIF_ROLE:
- MASTER = 0
- SLAVE = 1
-
-
-class MEMIF_MODE:
- ETHERNET = 0
- IP = 1
- PUNT_INJECT = 2
-
-
-def get_if_dump(dump, sw_if_index):
- for d in dump:
- if (d.sw_if_index == sw_if_index):
- return d
-
-
-def query_all_memif_vpp_config(_test):
- return _test.vapi.memif_dump()
-
-
-def remove_all_memif_vpp_config(_test):
- dump = _test.vapi.memif_dump()
- for d in dump:
- _test.vapi.memif_delete(d.sw_if_index)
- dump = _test.vapi.memif_socket_filename_dump()
- for d in dump:
- if d.socket_id != 0:
- _test.vapi.memif_socket_filename_add_del(
- 0, d.socket_id, d.socket_filename)
-
-
-class VppSocketFilename(VppObject):
- def __init__(self, test, socket_id, socket_filename,
- add_default_folder=False):
- self._test = test
- self.socket_id = socket_id
- self.socket_filename = socket_filename
-
- # if True insert default socket folder before socket filename,
- # after adding vpp config
- self.add_default_folder = add_default_folder
-
- def add_vpp_config(self):
- rv = self._test.vapi.memif_socket_filename_add_del(
- 1, self.socket_id, self.socket_filename)
- if self.add_default_folder:
- self.socket_filename = b"%s/%s" % (
- six.ensure_binary(self._test.tempdir, encoding='utf-8'),
- self.socket_filename)
- return rv
-
- def remove_vpp_config(self):
- return self._test.vapi.memif_socket_filename_add_del(
- 0, self.socket_id, self.socket_filename)
-
- def query_vpp_config(self):
- return self._test.vapi.memif_socket_filename_dump()
-
- def object_id(self):
- return "socket-filename-%d-%s" % (self.socket_id, self.socket_filename)
-
-
-class VppMemif(VppObject):
- def __init__(self, test, role, mode, rx_queues=0, tx_queues=0, if_id=0,
- socket_id=0, secret="", ring_size=0, buffer_size=0,
- hw_addr=""):
- self._test = test
- self.role = role
- self.mode = mode
- self.rx_queues = rx_queues
- self.tx_queues = tx_queues
- self.if_id = if_id
- self.socket_id = socket_id
- self.secret = secret
- self.ring_size = ring_size
- self.buffer_size = buffer_size
- self.hw_addr = hw_addr
- self.sw_if_index = None
- self.ip4_addr = "192.168.%d.%d" % (self.if_id + 1, self.role + 1)
- self.ip4_addr_len = 24
-
- def add_vpp_config(self):
- rv = self._test.vapi.memif_create(
- role=self.role,
- mode=self.mode,
- rx_queues=self.rx_queues,
- tx_queues=self.tx_queues,
- id=self.if_id,
- socket_id=self.socket_id,
- secret=self.secret,
- ring_size=self.ring_size,
- buffer_size=self.buffer_size,
- hw_addr=self.hw_addr)
- try:
- self.sw_if_index = 0
- except AttributeError:
- raise AttributeError('self: %s' % self.__dict__)
- try:
- self.sw_if_index = rv.sw_if_index
- except AttributeError:
- raise AttributeError("%s %s", self, rv)
-
- return self.sw_if_index
-
- def admin_up(self):
- if self.sw_if_index:
- return self._test.vapi.sw_interface_set_flags(self.sw_if_index, 1)
-
- def admin_down(self):
- if self.sw_if_index:
- return self._test.vapi.sw_interface_set_flags(self.sw_if_index, 0)
-
- def wait_for_link_up(self, timeout, step=1):
- if not self.sw_if_index:
- return False
- while True:
- dump = self.query_vpp_config()
- if dump.link_up_down == 1:
- return True
- self._test.sleep(step)
- timeout -= step
- if timeout <= 0:
- return False
-
- def config_ip4(self):
- return self._test.vapi.sw_interface_add_del_address(
- sw_if_index=self.sw_if_index, address=socket.inet_pton(
- socket.AF_INET, self.ip4_addr),
- address_length=self.ip4_addr_len)
-
- def remove_vpp_config(self):
- self._test.vapi.memif_delete(self.sw_if_index)
- self.sw_if_index = None
-
- def query_vpp_config(self):
- if not self.sw_if_index:
- return None
- dump = self._test.vapi.memif_dump()
- return get_if_dump(dump, self.sw_if_index)
-
- def object_id(self):
- if self.sw_if_index:
- return "%d:%d:%d" % (self.role, self.if_id, self.sw_if_index)
- else:
- return "%d:%d:None" % (self.role, self.if_id)
diff --git a/test/vpp_pppoe_interface.py b/test/vpp_pppoe_interface.py
deleted file mode 100644
index 9be92327dcf..00000000000
--- a/test/vpp_pppoe_interface.py
+++ /dev/null
@@ -1,39 +0,0 @@
-
-from vpp_interface import VppInterface
-import socket
-from vpp_papi import mac_pton
-
-
-class VppPppoeInterface(VppInterface):
- """
- VPP Pppoe interface
- """
-
- def __init__(self, test, client_ip, client_mac,
- session_id, decap_vrf_id=0):
- """ Create VPP PPPoE4 interface """
- super(VppPppoeInterface, self).__init__(test)
- self.client_ip = client_ip
- self.client_mac = client_mac
- self.session_id = session_id
- self.decap_vrf_id = decap_vrf_id
-
- def add_vpp_config(self):
- cip = socket.inet_pton(socket.AF_INET, self.client_ip)
- cmac = mac_pton(self.client_mac)
- r = self.test.vapi.pppoe_add_del_session(
- cip, cmac,
- session_id=self.session_id,
- decap_vrf_id=self.decap_vrf_id)
- self.set_sw_if_index(r.sw_if_index)
- self.generate_remote_hosts()
-
- def remove_vpp_config(self):
- cip = socket.inet_pton(socket.AF_INET, self.client_ip)
- cmac = mac_pton(self.client_mac)
- self.unconfig()
- self.test.vapi.pppoe_add_del_session(
- cip, cmac,
- session_id=self.session_id,
- decap_vrf_id=self.decap_vrf_id,
- is_add=0)
diff --git a/test/vpp_srv6.py b/test/vpp_srv6.py
deleted file mode 100644
index b6dbc014207..00000000000
--- a/test/vpp_srv6.py
+++ /dev/null
@@ -1,222 +0,0 @@
-"""
- SRv6 LocalSIDs
-
- object abstractions for representing SRv6 localSIDs in VPP
-"""
-
-from vpp_object import VppObject
-from socket import inet_pton, inet_ntop, AF_INET, AF_INET6
-
-
-class SRv6LocalSIDBehaviors():
- # from src/vnet/srv6/sr.h
- SR_BEHAVIOR_END = 1
- SR_BEHAVIOR_X = 2
- SR_BEHAVIOR_T = 3
- SR_BEHAVIOR_D_FIRST = 4 # Unused. Separator in between regular and D
- SR_BEHAVIOR_DX2 = 5
- SR_BEHAVIOR_DX6 = 6
- SR_BEHAVIOR_DX4 = 7
- SR_BEHAVIOR_DT6 = 8
- SR_BEHAVIOR_DT4 = 9
- SR_BEHAVIOR_LAST = 10 # Must always be the last one
-
-
-class SRv6PolicyType():
- # from src/vnet/srv6/sr.h
- SR_POLICY_TYPE_DEFAULT = 0
- SR_POLICY_TYPE_SPRAY = 1
-
-
-class SRv6PolicySteeringTypes():
- # from src/vnet/srv6/sr.h
- SR_STEER_L2 = 2
- SR_STEER_IPV4 = 4
- SR_STEER_IPV6 = 6
-
-
-class VppSRv6LocalSID(VppObject):
- """
- SRv6 LocalSID
- """
-
- def __init__(self, test, localsid, behavior, nh_addr4, nh_addr6,
- end_psp, sw_if_index, vlan_index, fib_table):
- self._test = test
- self.localsid = localsid
- # keep binary format in _localsid
- self.localsid["addr"] = inet_pton(AF_INET6, self.localsid["addr"])
- self.behavior = behavior
- self.nh_addr4 = inet_pton(AF_INET, nh_addr4)
- self.nh_addr6 = inet_pton(AF_INET6, nh_addr6)
- self.end_psp = end_psp
- self.sw_if_index = sw_if_index
- self.vlan_index = vlan_index
- self.fib_table = fib_table
- self._configured = False
-
- def add_vpp_config(self):
- self._test.vapi.sr_localsid_add_del(
- self.localsid,
- self.behavior,
- self.nh_addr4,
- self.nh_addr6,
- is_del=0,
- end_psp=self.end_psp,
- sw_if_index=self.sw_if_index,
- vlan_index=self.vlan_index,
- fib_table=self.fib_table)
- self._configured = True
-
- def remove_vpp_config(self):
- self._test.vapi.sr_localsid_add_del(
- self.localsid,
- self.behavior,
- self.nh_addr4,
- self.nh_addr6,
- is_del=1,
- end_psp=self.end_psp,
- sw_if_index=self.sw_if_index,
- vlan_index=self.vlan_index,
- fib_table=self.fib_table)
- self._configured = False
-
- def query_vpp_config(self):
- # sr_localsids_dump API is disabled
- # use _configured flag for now
- return self._configured
-
- def object_id(self):
- return ("%d;%s,%d"
- % (self.fib_table,
- self.localsid,
- self.behavior))
-
-
-class VppSRv6Policy(VppObject):
- """
- SRv6 Policy
- """
-
- def __init__(self, test, bsid,
- is_encap, sr_type, weight, fib_table,
- segments, source):
- self._test = test
- self.bsid = bsid
- # keep binary format in _bsid
- self._bsid = inet_pton(AF_INET6, bsid)
- self.is_encap = is_encap
- self.sr_type = sr_type
- self.weight = weight
- self.fib_table = fib_table
- self.segments = segments
- # keep binary format in _segments
- self._segments = []
- for seg in segments:
- self._segments.extend(inet_pton(AF_INET6, seg))
- self.n_segments = len(segments)
- # source not passed to API
- # self.source = inet_pton(AF_INET6, source)
- self.source = source
- self._configured = False
-
- def add_vpp_config(self):
- self._test.vapi.sr_policy_add(
- self._bsid,
- self.weight,
- self.is_encap,
- self.sr_type,
- self.fib_table,
- self.n_segments,
- self._segments)
- self._configured = True
-
- def remove_vpp_config(self):
- self._test.vapi.sr_policy_del(
- self._bsid)
- self._configured = False
-
- def query_vpp_config(self):
- # no API to query SR Policies
- # use _configured flag for now
- return self._configured
-
- def object_id(self):
- return ("%d;%s-><%s>;%d"
- % (self.sr_type,
- self.bsid,
- ','.join(self.segments),
- self.is_encap))
-
-
-class VppSRv6Steering(VppObject):
- """
- SRv6 Steering
- """
-
- def __init__(self, test,
- bsid,
- prefix,
- mask_width,
- traffic_type,
- sr_policy_index,
- table_id,
- sw_if_index):
- self._test = test
- self.bsid = bsid
- # keep binary format in _bsid
- self._bsid = inet_pton(AF_INET6, bsid)
- self.prefix = prefix
- # keep binary format in _prefix
- if ':' in prefix:
- # IPv6
- self._prefix = inet_pton(AF_INET6, prefix)
- else:
- # IPv4
- # API expects 16 octets (128 bits)
- # last 4 octets are used for IPv4
- # --> prepend 12 octets
- self._prefix = ('\x00' * 12) + inet_pton(AF_INET, prefix)
- self.mask_width = mask_width
- self.traffic_type = traffic_type
- self.sr_policy_index = sr_policy_index
- self.sw_if_index = sw_if_index
- self.table_id = table_id
- self._configured = False
-
- def add_vpp_config(self):
- self._test.vapi.sr_steering_add_del(
- 0,
- self._bsid,
- self.sr_policy_index,
- self.table_id,
- self._prefix,
- self.mask_width,
- self.sw_if_index,
- self.traffic_type)
- self._configured = True
-
- def remove_vpp_config(self):
- self._test.vapi.sr_steering_add_del(
- 1,
- self._bsid,
- self.sr_policy_index,
- self.table_id,
- self._prefix,
- self.mask_width,
- self.sw_if_index,
- self.traffic_type)
- self._configured = False
-
- def query_vpp_config(self):
- # no API to query steering entries
- # use _configured flag for now
- return self._configured
-
- def object_id(self):
- return ("%d;%d;%s/%d->%s"
- % (self.table_id,
- self.traffic_type,
- self.prefix,
- self.mask_width,
- self.bsid))