2 from socket import AF_INET, AF_INET6, inet_pton
5 from scapy.packet import Raw
6 from scapy.layers.l2 import Ether
7 from scapy.layers.inet import IP, UDP
9 from framework import VppTestCase, VppTestRunner
10 from vpp_interface import VppInterface
11 from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
16 class VppPipe(VppInterface):
23 return self.result.pipe_sw_if_index[1]
27 return self.result.pipe_sw_if_index[0]
29 def __init__(self, test, instance=0xffffffff):
30 super(VppPipe, self).__init__(test)
32 self.instance = instance
34 def add_vpp_config(self):
35 self.result = self._test.vapi.pipe_create(
36 0 if self.instance == 0xffffffff else 1,
38 self.set_sw_if_index(self.result.sw_if_index)
40 def remove_vpp_config(self):
41 self._test.vapi.pipe_delete(
42 self.result.sw_if_index)
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(ip_sw_if_index,
57 res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
61 class TestPipe(VppTestCase):
66 super(TestPipe, cls).setUpClass()
69 def tearDownClass(cls):
70 super(TestPipe, cls).tearDownClass()
73 super(TestPipe, self).setUp()
75 self.create_pg_interfaces(range(4))
77 for i in self.pg_interfaces:
81 for i in self.pg_interfaces:
84 super(TestPipe, self).tearDown()
89 pipes = [VppPipe(self), VppPipe(self, 10)]
96 # L2 cross-connect pipe0 east with pg0 and west with pg1
98 self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
101 self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
102 self.pg0.sw_if_index,
104 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
107 self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
108 self.pg1.sw_if_index,
111 # test bi-directional L2 flow pg0<->pg1
112 p = (Ether(src=self.pg0.remote_mac,
113 dst=self.pg1.remote_mac) /
116 UDP(sport=1234, dport=1234) /
119 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
120 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
123 # Attach ACL to ensure features are run on the pipe
125 rule_1 = ({'is_permit': 0,
128 'srcport_or_icmptype_first': 1234,
129 'srcport_or_icmptype_last': 1234,
130 'src_ip_prefix_len': 32,
131 'src_ip_addr': inet_pton(AF_INET, "1.1.1.1"),
132 'dstport_or_icmpcode_first': 1234,
133 'dstport_or_icmpcode_last': 1234,
134 'dst_ip_prefix_len': 32,
135 'dst_ip_addr': inet_pton(AF_INET, "1.1.1.2")})
136 acl = self.vapi.acl_add_replace(acl_index=4294967295,
139 # Apply the ACL on the pipe on output
140 self.vapi.acl_interface_set_acl_list(pipes[0].east,
143 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
144 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
146 # remove from output and apply on input
147 self.vapi.acl_interface_set_acl_list(pipes[0].east,
150 self.vapi.acl_interface_set_acl_list(pipes[0].west,
153 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
154 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
155 self.vapi.acl_interface_set_acl_list(pipes[0].west,
158 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
159 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
162 # L3 routes in two separate tables so a pipe can be used to L3
166 tables.append(VppIpTable(self, 1))
167 tables.append(VppIpTable(self, 2))
172 self.pg2.set_table_ip4(1)
173 self.pg2.config_ip4()
174 self.pg2.resolve_arp()
175 self.pg3.set_table_ip4(2)
176 self.pg3.config_ip4()
177 self.pg3.resolve_arp()
180 routes.append(VppIpRoute(self, "1.1.1.1", 32,
181 [VppRoutePath(self.pg3.remote_ip4,
182 self.pg3.sw_if_index)],
184 routes.append(VppIpRoute(self, "1.1.1.1", 32,
185 [VppRoutePath("0.0.0.0", pipes[1].east)],
187 routes.append(VppIpRoute(self, "1.1.1.2", 32,
188 [VppRoutePath("0.0.0.0", pipes[1].west)],
190 routes.append(VppIpRoute(self, "1.1.1.2", 32,
191 [VppRoutePath(self.pg2.remote_ip4,
192 self.pg2.sw_if_index)],
198 p_east = (Ether(src=self.pg2.remote_mac,
199 dst=self.pg2.local_mac) /
202 UDP(sport=1234, dport=1234) /
205 # bind the pipe ends to the correct tables
206 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
207 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
209 # IP is not enabled on the pipes at this point
210 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
212 # IP enable the Pipes by making them unnumbered
213 pipes[0].set_unnumbered(self.pg2.sw_if_index)
214 pipes[1].set_unnumbered(self.pg3.sw_if_index)
216 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
218 # and the return path
219 p_west = (Ether(src=self.pg3.remote_mac,
220 dst=self.pg3.local_mac) /
223 UDP(sport=1234, dport=1234) /
225 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
228 # Use ACLs to test features run on the Pipes
230 self.vapi.acl_interface_set_acl_list(pipes[1].east,
233 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
234 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
236 # remove from output and apply on input
237 self.vapi.acl_interface_set_acl_list(pipes[1].east,
240 self.vapi.acl_interface_set_acl_list(pipes[1].west,
243 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
244 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
245 self.vapi.acl_interface_set_acl_list(pipes[1].west,
248 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
249 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
251 # cleanup (so the tables delete)
252 self.pg2.unconfig_ip4()
253 self.pg2.set_table_ip4(0)
254 self.pg3.unconfig_ip4()
255 self.pg3.set_table_ip4(0)
256 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
257 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
260 if __name__ == '__main__':
261 unittest.main(testRunner=VppTestRunner)