2 from socket import AF_INET, AF_INET6, inet_pton
4 from framework import VppTestCase, VppTestRunner
5 from vpp_interface import VppInterface
6 from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
8 from scapy.packet import Raw
9 from scapy.layers.l2 import Ether
10 from scapy.layers.inet import IP, UDP
13 class VppPipe(VppInterface):
20 return self.result.pipe_sw_if_index[1]
24 return self.result.pipe_sw_if_index[0]
26 def __init__(self, test, instance=0xffffffff):
27 super(VppPipe, self).__init__(test)
29 self.instance = instance
31 def add_vpp_config(self):
32 self.result = self._test.vapi.pipe_create(
33 0 if self.instance == 0xffffffff else 1,
35 self.set_sw_if_index(self.result.sw_if_index)
37 def remove_vpp_config(self):
38 self._test.vapi.pipe_delete(
39 self.result.sw_if_index)
42 return self.object_id()
45 return "pipe-%d" % (self._sw_if_index)
47 def query_vpp_config(self):
48 pipes = self._test.vapi.pipe_dump()
50 if p.sw_if_index == self.result.sw_if_index:
54 def set_unnumbered(self, ip_sw_if_index, is_add=True):
55 res = self._test.vapi.sw_interface_set_unnumbered(
56 self.east, ip_sw_if_index, is_add)
57 res = self._test.vapi.sw_interface_set_unnumbered(
58 self.west, ip_sw_if_index, is_add)
61 class TestPipe(VppTestCase):
65 super(TestPipe, self).setUp()
67 self.create_pg_interfaces(range(4))
69 for i in self.pg_interfaces:
73 for i in self.pg_interfaces:
76 super(TestPipe, self).tearDown()
81 pipes = [VppPipe(self), VppPipe(self, 10)]
88 # L2 cross-connect pipe0 east with pg0 and west with pg1
90 self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
93 self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
96 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
99 self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
100 self.pg1.sw_if_index,
103 # test bi-drectional L2 flow pg0<->pg1
104 p = (Ether(src=self.pg0.remote_mac,
105 dst=self.pg1.remote_mac) /
108 UDP(sport=1234, dport=1234) /
111 self.send_and_expect(self.pg0, p * 65, self.pg1)
112 self.send_and_expect(self.pg1, p * 65, self.pg0)
115 # Attach ACL to ensure features are run on the pipe
117 rule_1 = ({'is_permit': 0,
120 'srcport_or_icmptype_first': 1234,
121 'srcport_or_icmptype_last': 1234,
122 'src_ip_prefix_len': 32,
123 'src_ip_addr': inet_pton(AF_INET, "1.1.1.1"),
124 'dstport_or_icmpcode_first': 1234,
125 'dstport_or_icmpcode_last': 1234,
126 'dst_ip_prefix_len': 32,
127 'dst_ip_addr': inet_pton(AF_INET, "1.1.1.2")})
128 acl = self.vapi.acl_add_replace(acl_index=4294967295,
131 # Apply the ACL on the pipe on output
132 self.vapi.acl_interface_set_acl_list(pipes[0].east,
135 self.send_and_assert_no_replies(self.pg0, p * 65)
136 self.send_and_expect(self.pg1, p * 65, self.pg0)
138 # remove from output and apply on input
139 self.vapi.acl_interface_set_acl_list(pipes[0].east,
142 self.vapi.acl_interface_set_acl_list(pipes[0].west,
145 self.send_and_assert_no_replies(self.pg0, p * 65)
146 self.send_and_expect(self.pg1, p * 65, self.pg0)
147 self.vapi.acl_interface_set_acl_list(pipes[0].west,
150 self.send_and_expect(self.pg0, p * 65, self.pg1)
151 self.send_and_expect(self.pg1, p * 65, self.pg0)
154 # L3 routes in two separate tables so a pipe can be used to L3
158 tables.append(VppIpTable(self, 1))
159 tables.append(VppIpTable(self, 2))
164 self.pg2.set_table_ip4(1)
165 self.pg2.config_ip4()
166 self.pg2.resolve_arp()
167 self.pg3.set_table_ip4(2)
168 self.pg3.config_ip4()
169 self.pg3.resolve_arp()
172 routes.append(VppIpRoute(self, "1.1.1.1", 32,
173 [VppRoutePath(self.pg3.remote_ip4,
174 self.pg3.sw_if_index)],
176 routes.append(VppIpRoute(self, "1.1.1.1", 32,
177 [VppRoutePath("0.0.0.0", pipes[1].east)],
179 routes.append(VppIpRoute(self, "1.1.1.2", 32,
180 [VppRoutePath("0.0.0.0", pipes[1].west)],
182 routes.append(VppIpRoute(self, "1.1.1.2", 32,
183 [VppRoutePath(self.pg2.remote_ip4,
184 self.pg2.sw_if_index)],
190 p_east = (Ether(src=self.pg2.remote_mac,
191 dst=self.pg2.local_mac) /
194 UDP(sport=1234, dport=1234) /
197 # bind the pipe ends to the correct tables
198 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
199 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
201 # IP is not enabled on the pipes at this point
202 self.send_and_assert_no_replies(self.pg2, p_east * 65)
204 # IP enable the Pipes by making them unnumbered
205 pipes[0].set_unnumbered(self.pg2.sw_if_index)
206 pipes[1].set_unnumbered(self.pg3.sw_if_index)
208 self.send_and_expect(self.pg2, p_east * 65, self.pg3)
210 # and the return path
211 p_west = (Ether(src=self.pg3.remote_mac,
212 dst=self.pg3.local_mac) /
215 UDP(sport=1234, dport=1234) /
217 self.send_and_expect(self.pg3, p_west * 65, self.pg2)
220 # Use ACLs to test features run on the Pipes
222 self.vapi.acl_interface_set_acl_list(pipes[1].east,
225 self.send_and_assert_no_replies(self.pg2, p_east * 65)
226 self.send_and_expect(self.pg3, p_west * 65, self.pg2)
228 # remove from output and apply on input
229 self.vapi.acl_interface_set_acl_list(pipes[1].east,
232 self.vapi.acl_interface_set_acl_list(pipes[1].west,
235 self.send_and_assert_no_replies(self.pg2, p_east * 65)
236 self.send_and_expect(self.pg3, p_west * 65, self.pg2)
237 self.vapi.acl_interface_set_acl_list(pipes[1].west,
240 self.send_and_expect(self.pg2, p_east * 65, self.pg3)
241 self.send_and_expect(self.pg3, p_west * 65, self.pg2)
243 # cleanup (so the tables delete)
244 self.pg2.unconfig_ip4()
245 self.pg2.set_table_ip4(0)
246 self.pg3.unconfig_ip4()
247 self.pg3.set_table_ip4(0)
248 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
249 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
252 if __name__ == '__main__':
253 unittest.main(testRunner=VppTestRunner)