blob: 30540997ff62b703b2b306ca5c94a36691073a86 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns17ff3c12018-07-04 10:24:24 -07002from socket import AF_INET, AF_INET6, inet_pton
Paul Vinciguerra38404db2019-05-14 13:35:19 -04003import unittest
Jakub Grajciar2f8cd912020-03-27 06:55:06 +01004from ipaddress import IPv4Network
Neale Ranns17ff3c12018-07-04 10:24:24 -07005
6from scapy.packet import Raw
7from scapy.layers.l2 import Ether
8from scapy.layers.inet import IP, UDP
9
Paul Vinciguerra38404db2019-05-14 13:35:19 -040010from framework import VppTestCase, VppTestRunner
11from vpp_interface import VppInterface
12from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
Jakub Grajciar2f8cd912020-03-27 06:55:06 +010013from vpp_acl import AclRule, VppAcl, VppAclInterface
Paul Vinciguerra38404db2019-05-14 13:35:19 -040014
Paul Vinciguerra4271c972019-05-14 13:25:49 -040015NUM_PKTS = 67
16
Neale Ranns17ff3c12018-07-04 10:24:24 -070017
18class VppPipe(VppInterface):
19 """
20 VPP Pipe
21 """
22
23 @property
24 def east(self):
25 return self.result.pipe_sw_if_index[1]
26
27 @property
28 def west(self):
29 return self.result.pipe_sw_if_index[0]
30
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020031 def __init__(self, test, instance=0xFFFFFFFF):
Neale Ranns17ff3c12018-07-04 10:24:24 -070032 super(VppPipe, self).__init__(test)
33 self._test = test
34 self.instance = instance
35
36 def add_vpp_config(self):
37 self.result = self._test.vapi.pipe_create(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020038 0 if self.instance == 0xFFFFFFFF else 1, self.instance
39 )
Neale Ranns208c29a2018-04-11 08:08:30 -070040 self.set_sw_if_index(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070041
42 def remove_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020043 self._test.vapi.pipe_delete(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070044
Neale Ranns17ff3c12018-07-04 10:24:24 -070045 def object_id(self):
46 return "pipe-%d" % (self._sw_if_index)
47
48 def query_vpp_config(self):
49 pipes = self._test.vapi.pipe_dump()
50 for p in pipes:
Neale Ranns208c29a2018-04-11 08:08:30 -070051 if p.sw_if_index == self.result.sw_if_index:
Neale Ranns17ff3c12018-07-04 10:24:24 -070052 return True
53 return False
54
Stanislav Zaikin328b5da2021-07-15 16:27:29 +020055 def set_unnumbered(self, ip_sw_if_index, is_east, is_add=True):
56 if is_east:
57 res = self._test.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020058 ip_sw_if_index, self.east, is_add
59 )
Stanislav Zaikin328b5da2021-07-15 16:27:29 +020060 else:
61 res = self._test.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020062 ip_sw_if_index, self.west, is_add
63 )
Neale Ranns17ff3c12018-07-04 10:24:24 -070064
65
66class TestPipe(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020067 """Pipes"""
Neale Ranns17ff3c12018-07-04 10:24:24 -070068
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070069 @classmethod
70 def setUpClass(cls):
71 super(TestPipe, cls).setUpClass()
72
73 @classmethod
74 def tearDownClass(cls):
75 super(TestPipe, cls).tearDownClass()
76
Neale Ranns17ff3c12018-07-04 10:24:24 -070077 def setUp(self):
78 super(TestPipe, self).setUp()
79
80 self.create_pg_interfaces(range(4))
81
82 for i in self.pg_interfaces:
83 i.admin_up()
84
85 def tearDown(self):
86 for i in self.pg_interfaces:
87 i.admin_down()
88
89 super(TestPipe, self).tearDown()
90
91 def test_pipe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020092 """Pipes"""
Neale Ranns17ff3c12018-07-04 10:24:24 -070093
Neale Ranns208c29a2018-04-11 08:08:30 -070094 pipes = [VppPipe(self), VppPipe(self, 10)]
Neale Ranns17ff3c12018-07-04 10:24:24 -070095
96 for p in pipes:
97 p.add_vpp_config()
98 p.admin_up()
99
100 #
101 # L2 cross-connect pipe0 east with pg0 and west with pg1
102 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200103 self.vapi.sw_interface_set_l2_xconnect(
104 self.pg0.sw_if_index, pipes[0].east, enable=1
105 )
106 self.vapi.sw_interface_set_l2_xconnect(
107 pipes[0].east, self.pg0.sw_if_index, enable=1
108 )
109 self.vapi.sw_interface_set_l2_xconnect(
110 self.pg1.sw_if_index, pipes[0].west, enable=1
111 )
112 self.vapi.sw_interface_set_l2_xconnect(
113 pipes[0].west, self.pg1.sw_if_index, enable=1
114 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700115
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700116 # test bi-directional L2 flow pg0<->pg1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200117 p = (
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)
121 / Raw(b"\xa5" * 100)
122 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700123
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400124 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
125 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700126
127 #
128 # Attach ACL to ensure features are run on the pipe
129 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200130 rule_1 = AclRule(
131 is_permit=0,
132 proto=17,
133 src_prefix=IPv4Network("1.1.1.1/32"),
134 dst_prefix=IPv4Network("1.1.1.2/32"),
135 ports=1234,
136 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100137 acl = VppAcl(self, rules=[rule_1])
138 acl.add_vpp_config()
Neale Ranns17ff3c12018-07-04 10:24:24 -0700139
140 # Apply the ACL on the pipe on output
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200141 acl_if_e = VppAclInterface(
142 self, sw_if_index=pipes[0].east, n_input=0, acls=[acl]
143 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100144 acl_if_e.add_vpp_config()
145
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400146 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
147 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700148
149 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100150 acl_if_e.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200151 acl_if_w = VppAclInterface(
152 self, sw_if_index=pipes[0].west, n_input=1, acls=[acl]
153 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100154 acl_if_w.add_vpp_config()
155
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400156 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
157 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100158
159 acl_if_w.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400160 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
161 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700162
163 #
164 # L3 routes in two separate tables so a pipe can be used to L3
165 # x-connect
166 #
167 tables = []
168 tables.append(VppIpTable(self, 1))
169 tables.append(VppIpTable(self, 2))
170
171 for t in tables:
172 t.add_vpp_config()
173
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()
180
181 routes = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200182 routes.append(
183 VppIpRoute(
184 self,
185 "1.1.1.1",
186 32,
187 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
188 table_id=2,
189 )
190 )
191 routes.append(
192 VppIpRoute(
193 self,
194 "1.1.1.1",
195 32,
196 [VppRoutePath("0.0.0.0", pipes[1].east)],
197 table_id=1,
198 )
199 )
200 routes.append(
201 VppIpRoute(
202 self,
203 "1.1.1.2",
204 32,
205 [VppRoutePath("0.0.0.0", pipes[1].west)],
206 table_id=2,
207 )
208 )
209 routes.append(
210 VppIpRoute(
211 self,
212 "1.1.1.2",
213 32,
214 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
215 table_id=1,
216 )
217 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700218
219 for r in routes:
220 r.add_vpp_config()
221
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200222 p_east = (
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)
226 / Raw(b"\xa5" * 100)
227 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700228
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)
232
233 # IP is not enabled on the pipes at this point
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400234 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700235
236 # IP enable the Pipes by making them unnumbered
Stanislav Zaikin328b5da2021-07-15 16:27:29 +0200237 pipes[1].set_unnumbered(self.pg2.sw_if_index, True)
238 pipes[1].set_unnumbered(self.pg3.sw_if_index, False)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700239
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400240 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700241
242 # and the return path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 p_west = (
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)
247 / Raw(b"\xa5" * 100)
248 )
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400249 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700250
251 #
252 # Use ACLs to test features run on the Pipes
253 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200254 acl_if_e1 = VppAclInterface(
255 self, sw_if_index=pipes[1].east, n_input=0, acls=[acl]
256 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100257 acl_if_e1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400258 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700260
261 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100262 acl_if_e1.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200263 acl_if_w1 = VppAclInterface(
264 self, sw_if_index=pipes[1].west, n_input=1, acls=[acl]
265 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100266 acl_if_w1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400267 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)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100269 acl_if_w1.remove_vpp_config()
270
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400271 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700273
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)
281
282
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200283if __name__ == "__main__":
Neale Ranns17ff3c12018-07-04 10:24:24 -0700284 unittest.main(testRunner=VppTestRunner)