summaryrefslogtreecommitdiffstats
path: root/test/test_pipe.py
diff options
context:
space:
mode:
authorNeale Ranns <neale.ranns@cisco.com>2018-07-04 10:24:24 -0700
committerDave Barach <openvpp@barachs.net>2018-07-07 16:06:34 +0000
commit17ff3c1fa5687255a118c53223fa2cd49132d929 (patch)
tree874a3fbf5bed5408f9f9c84546a3b95df62ead79 /test/test_pipe.py
parent65784c1602c7c8171effd00384f65f546d93a13b (diff)
Pipes
A pipe resembles a unix pipe. Each end of the pipe is a full VPP interface. pipes can be used for e.g. packet recirculation, inter-BD, etc. Change-Id: I185bb9fb43dd233ff45da63ac1b85ae2e1ceca16 Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Diffstat (limited to 'test/test_pipe.py')
-rw-r--r--test/test_pipe.py255
1 files changed, 255 insertions, 0 deletions
diff --git a/test/test_pipe.py b/test/test_pipe.py
new file mode 100644
index 00000000000..a89c1e90236
--- /dev/null
+++ b/test/test_pipe.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python
+from socket import AF_INET, AF_INET6, inet_pton
+
+from framework import VppTestCase, VppTestRunner
+from vpp_interface import VppInterface
+from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
+
+from scapy.packet import Raw
+from scapy.layers.l2 import Ether
+from scapy.layers.inet import IP, UDP
+
+
+class VppPipe(VppInterface):
+ """
+ VPP Pipe
+ """
+
+ @property
+ def east(self):
+ return self.result.pipe_sw_if_index[1]
+
+ @property
+ def west(self):
+ return self.result.pipe_sw_if_index[0]
+
+ def __init__(self, test, instance=0xffffffff):
+ super(VppPipe, self).__init__(test)
+ self._test = test
+ self.instance = instance
+
+ def add_vpp_config(self):
+ self.result = self._test.vapi.pipe_create(
+ 0 if self.instance == 0xffffffff else 1,
+ self.instance)
+ self.set_sw_if_index(self.result.parent_sw_if_index)
+
+ def remove_vpp_config(self):
+ self._test.vapi.pipe_delete(
+ self.result.parent_sw_if_index)
+
+ def __str__(self):
+ return self.object_id()
+
+ def object_id(self):
+ return "pipe-%d" % (self._sw_if_index)
+
+ def query_vpp_config(self):
+ pipes = self._test.vapi.pipe_dump()
+ for p in pipes:
+ if p.parent_sw_if_index == self.result.parent_sw_if_index:
+ return True
+ return False
+
+ def set_unnumbered(self, ip_sw_if_index, is_add=True):
+ res = self._test.vapi.sw_interface_set_unnumbered(
+ self.east, ip_sw_if_index, is_add)
+ res = self._test.vapi.sw_interface_set_unnumbered(
+ self.west, ip_sw_if_index, is_add)
+
+
+class TestPipe(VppTestCase):
+ """ Pipes """
+
+ def setUp(self):
+ super(TestPipe, self).setUp()
+
+ self.create_pg_interfaces(range(4))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+
+ def tearDown(self):
+ for i in self.pg_interfaces:
+ i.admin_down()
+
+ super(TestPipe, self).tearDown()
+
+ def test_pipe(self):
+ """ Pipes """
+
+ pipes = []
+ pipes.append(VppPipe(self))
+ pipes.append(VppPipe(self, 10))
+
+ for p in pipes:
+ p.add_vpp_config()
+ p.admin_up()
+
+ #
+ # L2 cross-connect pipe0 east with pg0 and west with pg1
+ #
+ self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
+ pipes[0].east,
+ enable=1)
+ self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
+ self.pg0.sw_if_index,
+ enable=1)
+ self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
+ pipes[0].west,
+ enable=1)
+ self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
+ self.pg1.sw_if_index,
+ enable=1)
+
+ # test bi-drectional L2 flow pg0<->pg1
+ p = (Ether(src=self.pg0.remote_mac,
+ dst=self.pg1.remote_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 * 65, self.pg1)
+ self.send_and_expect(self.pg1, p * 65, self.pg0)
+
+ #
+ # Attach ACL to ensure features are run on the pipe
+ #
+ rule_1 = ({'is_permit': 0,
+ '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 = self.vapi.acl_add_replace(acl_index=4294967295,
+ r=[rule_1])
+
+ # Apply the ACL on the pipe on output
+ self.vapi.acl_interface_set_acl_list(pipes[0].east,
+ 0,
+ [acl.acl_index])
+ self.send_and_assert_no_replies(self.pg0, p * 65)
+ self.send_and_expect(self.pg1, p * 65, self.pg0)
+
+ # remove from output and apply on input
+ self.vapi.acl_interface_set_acl_list(pipes[0].east,
+ 0,
+ [])
+ self.vapi.acl_interface_set_acl_list(pipes[0].west,
+ 1,
+ [acl.acl_index])
+ self.send_and_assert_no_replies(self.pg0, p * 65)
+ self.send_and_expect(self.pg1, p * 65, self.pg0)
+ self.vapi.acl_interface_set_acl_list(pipes[0].west,
+ 0,
+ [])
+ self.send_and_expect(self.pg0, p * 65, self.pg1)
+ self.send_and_expect(self.pg1, p * 65, self.pg0)
+
+ #
+ # L3 routes in two separate tables so a pipe can be used to L3
+ # x-connect
+ #
+ tables = []
+ tables.append(VppIpTable(self, 1))
+ tables.append(VppIpTable(self, 2))
+
+ for t in tables:
+ t.add_vpp_config()
+
+ self.pg2.set_table_ip4(1)
+ self.pg2.config_ip4()
+ self.pg2.resolve_arp()
+ self.pg3.set_table_ip4(2)
+ self.pg3.config_ip4()
+ self.pg3.resolve_arp()
+
+ routes = []
+ routes.append(VppIpRoute(self, "1.1.1.1", 32,
+ [VppRoutePath(self.pg3.remote_ip4,
+ self.pg3.sw_if_index)],
+ table_id=2))
+ routes.append(VppIpRoute(self, "1.1.1.1", 32,
+ [VppRoutePath("0.0.0.0", pipes[1].east)],
+ table_id=1))
+ routes.append(VppIpRoute(self, "1.1.1.2", 32,
+ [VppRoutePath("0.0.0.0", pipes[1].west)],
+ table_id=2))
+ routes.append(VppIpRoute(self, "1.1.1.2", 32,
+ [VppRoutePath(self.pg2.remote_ip4,
+ self.pg2.sw_if_index)],
+ table_id=1))
+
+ for r in routes:
+ r.add_vpp_config()
+
+ p_east = (Ether(src=self.pg2.remote_mac,
+ dst=self.pg2.local_mac) /
+ IP(src="1.1.1.2",
+ dst="1.1.1.1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ # bind the pipe ends to the correct tables
+ self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
+ self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
+
+ # IP is not enabled on the pipes at this point
+ self.send_and_assert_no_replies(self.pg2, p_east * 65)
+
+ # IP enable the Pipes by making them unnumbered
+ pipes[0].set_unnumbered(self.pg2.sw_if_index)
+ pipes[1].set_unnumbered(self.pg3.sw_if_index)
+
+ self.send_and_expect(self.pg2, p_east * 65, self.pg3)
+
+ # and the return path
+ p_west = (Ether(src=self.pg3.remote_mac,
+ dst=self.pg3.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.pg3, p_west * 65, self.pg2)
+
+ #
+ # Use ACLs to test features run on the Pipes
+ #
+ self.vapi.acl_interface_set_acl_list(pipes[1].east,
+ 0,
+ [acl.acl_index])
+ self.send_and_assert_no_replies(self.pg2, p_east * 65)
+ self.send_and_expect(self.pg3, p_west * 65, self.pg2)
+
+ # remove from output and apply on input
+ self.vapi.acl_interface_set_acl_list(pipes[1].east,
+ 0,
+ [])
+ self.vapi.acl_interface_set_acl_list(pipes[1].west,
+ 1,
+ [acl.acl_index])
+ self.send_and_assert_no_replies(self.pg2, p_east * 65)
+ self.send_and_expect(self.pg3, p_west * 65, self.pg2)
+ self.vapi.acl_interface_set_acl_list(pipes[1].west,
+ 0,
+ [])
+ self.send_and_expect(self.pg2, p_east * 65, self.pg3)
+ self.send_and_expect(self.pg3, p_west * 65, self.pg2)
+
+ # cleanup (so the tables delete)
+ self.pg2.unconfig_ip4()
+ self.pg2.set_table_ip4(0)
+ self.pg3.unconfig_ip4()
+ self.pg3.set_table_ip4(0)
+ self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
+ self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
+
+
+if __name__ == '__main__':
+ unittest.main(testRunner=VppTestRunner)