2 from socket import AF_INET, AF_INET6, inet_pton
4 from ipaddress import IPv4Network
6 from scapy.packet import Raw
7 from scapy.layers.l2 import Ether
8 from scapy.layers.inet import IP, UDP
10 from framework import VppTestCase, VppTestRunner
11 from vpp_interface import VppInterface
12 from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
13 from vpp_acl import AclRule, VppAcl, VppAclInterface
18 class VppPipe(VppInterface):
25 return self.result.pipe_sw_if_index[1]
29 return self.result.pipe_sw_if_index[0]
31 def __init__(self, test, instance=0xFFFFFFFF):
32 super(VppPipe, self).__init__(test)
34 self.instance = instance
36 def add_vpp_config(self):
37 self.result = self._test.vapi.pipe_create(
38 0 if self.instance == 0xFFFFFFFF else 1, self.instance
40 self.set_sw_if_index(self.result.sw_if_index)
42 def remove_vpp_config(self):
43 self._test.vapi.pipe_delete(self.result.sw_if_index)
46 return "pipe-%d" % (self._sw_if_index)
48 def query_vpp_config(self):
49 pipes = self._test.vapi.pipe_dump()
51 if p.sw_if_index == self.result.sw_if_index:
55 def set_unnumbered(self, ip_sw_if_index, is_east, is_add=True):
57 res = self._test.vapi.sw_interface_set_unnumbered(
58 ip_sw_if_index, self.east, is_add
61 res = self._test.vapi.sw_interface_set_unnumbered(
62 ip_sw_if_index, self.west, is_add
66 class TestPipe(VppTestCase):
71 super(TestPipe, cls).setUpClass()
74 def tearDownClass(cls):
75 super(TestPipe, cls).tearDownClass()
78 super(TestPipe, self).setUp()
80 self.create_pg_interfaces(range(4))
82 for i in self.pg_interfaces:
86 for i in self.pg_interfaces:
89 super(TestPipe, self).tearDown()
94 pipes = [VppPipe(self), VppPipe(self, 10)]
101 # L2 cross-connect pipe0 east with pg0 and west with pg1
103 self.vapi.sw_interface_set_l2_xconnect(
104 self.pg0.sw_if_index, pipes[0].east, enable=1
106 self.vapi.sw_interface_set_l2_xconnect(
107 pipes[0].east, self.pg0.sw_if_index, enable=1
109 self.vapi.sw_interface_set_l2_xconnect(
110 self.pg1.sw_if_index, pipes[0].west, enable=1
112 self.vapi.sw_interface_set_l2_xconnect(
113 pipes[0].west, self.pg1.sw_if_index, enable=1
116 # test bi-directional L2 flow pg0<->pg1
118 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
119 / IP(src="1.1.1.1", dst="1.1.1.2")
120 / UDP(sport=1234, dport=1234)
124 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
125 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
128 # Attach ACL to ensure features are run on the pipe
133 src_prefix=IPv4Network("1.1.1.1/32"),
134 dst_prefix=IPv4Network("1.1.1.2/32"),
137 acl = VppAcl(self, rules=[rule_1])
140 # Apply the ACL on the pipe on output
141 acl_if_e = VppAclInterface(
142 self, sw_if_index=pipes[0].east, n_input=0, acls=[acl]
144 acl_if_e.add_vpp_config()
146 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
147 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
149 # remove from output and apply on input
150 acl_if_e.remove_vpp_config()
151 acl_if_w = VppAclInterface(
152 self, sw_if_index=pipes[0].west, n_input=1, acls=[acl]
154 acl_if_w.add_vpp_config()
156 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
157 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
159 acl_if_w.remove_vpp_config()
160 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
161 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
164 # L3 routes in two separate tables so a pipe can be used to L3
168 tables.append(VppIpTable(self, 1))
169 tables.append(VppIpTable(self, 2))
174 self.pg2.set_table_ip4(1)
175 self.pg2.config_ip4()
176 self.pg2.resolve_arp()
177 self.pg3.set_table_ip4(2)
178 self.pg3.config_ip4()
179 self.pg3.resolve_arp()
187 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
196 [VppRoutePath("0.0.0.0", pipes[1].east)],
205 [VppRoutePath("0.0.0.0", pipes[1].west)],
214 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
223 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
224 / IP(src="1.1.1.2", dst="1.1.1.1")
225 / UDP(sport=1234, dport=1234)
229 # bind the pipe ends to the correct tables
230 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
231 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
233 # IP is not enabled on the pipes at this point
234 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
236 # IP enable the Pipes by making them unnumbered
237 pipes[1].set_unnumbered(self.pg2.sw_if_index, True)
238 pipes[1].set_unnumbered(self.pg3.sw_if_index, False)
240 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
242 # and the return path
244 Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
245 / IP(src="1.1.1.1", dst="1.1.1.2")
246 / UDP(sport=1234, dport=1234)
249 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
252 # Use ACLs to test features run on the Pipes
254 acl_if_e1 = VppAclInterface(
255 self, sw_if_index=pipes[1].east, n_input=0, acls=[acl]
257 acl_if_e1.add_vpp_config()
258 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
259 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
261 # remove from output and apply on input
262 acl_if_e1.remove_vpp_config()
263 acl_if_w1 = VppAclInterface(
264 self, sw_if_index=pipes[1].west, n_input=1, acls=[acl]
266 acl_if_w1.add_vpp_config()
267 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
268 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
269 acl_if_w1.remove_vpp_config()
271 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
272 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
274 # cleanup (so the tables delete)
275 self.pg2.unconfig_ip4()
276 self.pg2.set_table_ip4(0)
277 self.pg3.unconfig_ip4()
278 self.pg3.set_table_ip4(0)
279 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
280 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
283 if __name__ == "__main__":
284 unittest.main(testRunner=VppTestRunner)