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,
40 self.set_sw_if_index(self.result.sw_if_index)
42 def remove_vpp_config(self):
43 self._test.vapi.pipe_delete(
44 self.result.sw_if_index)
47 return "pipe-%d" % (self._sw_if_index)
49 def query_vpp_config(self):
50 pipes = self._test.vapi.pipe_dump()
52 if p.sw_if_index == self.result.sw_if_index:
56 def set_unnumbered(self, ip_sw_if_index, is_add=True):
57 res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
59 res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
63 class TestPipe(VppTestCase):
68 super(TestPipe, cls).setUpClass()
71 def tearDownClass(cls):
72 super(TestPipe, cls).tearDownClass()
75 super(TestPipe, self).setUp()
77 self.create_pg_interfaces(range(4))
79 for i in self.pg_interfaces:
83 for i in self.pg_interfaces:
86 super(TestPipe, self).tearDown()
91 pipes = [VppPipe(self), VppPipe(self, 10)]
98 # L2 cross-connect pipe0 east with pg0 and west with pg1
100 self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
103 self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
104 self.pg0.sw_if_index,
106 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
109 self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
110 self.pg1.sw_if_index,
113 # test bi-directional L2 flow pg0<->pg1
114 p = (Ether(src=self.pg0.remote_mac,
115 dst=self.pg1.remote_mac) /
118 UDP(sport=1234, dport=1234) /
121 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
122 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
125 # Attach ACL to ensure features are run on the pipe
127 rule_1 = AclRule(is_permit=0, proto=17,
128 src_prefix=IPv4Network("1.1.1.1/32"),
129 dst_prefix=IPv4Network("1.1.1.2/32"), ports=1234)
130 acl = VppAcl(self, rules=[rule_1])
133 # Apply the ACL on the pipe on output
134 acl_if_e = VppAclInterface(self, sw_if_index=pipes[0].east, n_input=0,
136 acl_if_e.add_vpp_config()
138 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
139 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
141 # remove from output and apply on input
142 acl_if_e.remove_vpp_config()
143 acl_if_w = VppAclInterface(self, sw_if_index=pipes[0].west, n_input=1,
145 acl_if_w.add_vpp_config()
147 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
148 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
150 acl_if_w.remove_vpp_config()
151 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
152 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
155 # L3 routes in two separate tables so a pipe can be used to L3
159 tables.append(VppIpTable(self, 1))
160 tables.append(VppIpTable(self, 2))
165 self.pg2.set_table_ip4(1)
166 self.pg2.config_ip4()
167 self.pg2.resolve_arp()
168 self.pg3.set_table_ip4(2)
169 self.pg3.config_ip4()
170 self.pg3.resolve_arp()
173 routes.append(VppIpRoute(self, "1.1.1.1", 32,
174 [VppRoutePath(self.pg3.remote_ip4,
175 self.pg3.sw_if_index)],
177 routes.append(VppIpRoute(self, "1.1.1.1", 32,
178 [VppRoutePath("0.0.0.0", pipes[1].east)],
180 routes.append(VppIpRoute(self, "1.1.1.2", 32,
181 [VppRoutePath("0.0.0.0", pipes[1].west)],
183 routes.append(VppIpRoute(self, "1.1.1.2", 32,
184 [VppRoutePath(self.pg2.remote_ip4,
185 self.pg2.sw_if_index)],
191 p_east = (Ether(src=self.pg2.remote_mac,
192 dst=self.pg2.local_mac) /
195 UDP(sport=1234, dport=1234) /
198 # bind the pipe ends to the correct tables
199 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
200 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
202 # IP is not enabled on the pipes at this point
203 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
205 # IP enable the Pipes by making them unnumbered
206 pipes[0].set_unnumbered(self.pg2.sw_if_index)
207 pipes[1].set_unnumbered(self.pg3.sw_if_index)
209 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
211 # and the return path
212 p_west = (Ether(src=self.pg3.remote_mac,
213 dst=self.pg3.local_mac) /
216 UDP(sport=1234, dport=1234) /
218 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
221 # Use ACLs to test features run on the Pipes
223 acl_if_e1 = VppAclInterface(self, sw_if_index=pipes[1].east, n_input=0,
225 acl_if_e1.add_vpp_config()
226 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
227 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
229 # remove from output and apply on input
230 acl_if_e1.remove_vpp_config()
231 acl_if_w1 = VppAclInterface(self, sw_if_index=pipes[1].west, n_input=1,
233 acl_if_w1.add_vpp_config()
234 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
235 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
236 acl_if_w1.remove_vpp_config()
238 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
239 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
241 # cleanup (so the tables delete)
242 self.pg2.unconfig_ip4()
243 self.pg2.set_table_ip4(0)
244 self.pg3.unconfig_ip4()
245 self.pg3.set_table_ip4(0)
246 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
247 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
250 if __name__ == '__main__':
251 unittest.main(testRunner=VppTestRunner)