blob: 01d2f30f494789115ff0db53dcf356facd998e0d [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Paul Vinciguerra38404db2019-05-14 13:35:19 -04002import unittest
Jakub Grajciar2f8cd912020-03-27 06:55:06 +01003from ipaddress import IPv4Network
Neale Ranns17ff3c12018-07-04 10:24:24 -07004
5from scapy.packet import Raw
6from scapy.layers.l2 import Ether
7from scapy.layers.inet import IP, UDP
8
Dave Wallace8800f732023-08-31 00:47:44 -04009from framework import VppTestCase
10from asfframework import VppTestRunner
Paul Vinciguerra38404db2019-05-14 13:35:19 -040011from 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
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000014from config import config
Paul Vinciguerra38404db2019-05-14 13:35:19 -040015
Paul Vinciguerra4271c972019-05-14 13:25:49 -040016NUM_PKTS = 67
17
Neale Ranns17ff3c12018-07-04 10:24:24 -070018
19class VppPipe(VppInterface):
20 """
21 VPP Pipe
22 """
23
24 @property
25 def east(self):
26 return self.result.pipe_sw_if_index[1]
27
28 @property
29 def west(self):
30 return self.result.pipe_sw_if_index[0]
31
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020032 def __init__(self, test, instance=0xFFFFFFFF):
Neale Ranns17ff3c12018-07-04 10:24:24 -070033 super(VppPipe, self).__init__(test)
34 self._test = test
35 self.instance = instance
36
37 def add_vpp_config(self):
38 self.result = self._test.vapi.pipe_create(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020039 0 if self.instance == 0xFFFFFFFF else 1, self.instance
40 )
Neale Ranns208c29a2018-04-11 08:08:30 -070041 self.set_sw_if_index(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070042
43 def remove_vpp_config(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020044 self._test.vapi.pipe_delete(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070045
Neale Ranns17ff3c12018-07-04 10:24:24 -070046 def object_id(self):
47 return "pipe-%d" % (self._sw_if_index)
48
49 def query_vpp_config(self):
50 pipes = self._test.vapi.pipe_dump()
51 for p in pipes:
Neale Ranns208c29a2018-04-11 08:08:30 -070052 if p.sw_if_index == self.result.sw_if_index:
Neale Ranns17ff3c12018-07-04 10:24:24 -070053 return True
54 return False
55
Stanislav Zaikin328b5da2021-07-15 16:27:29 +020056 def set_unnumbered(self, ip_sw_if_index, is_east, is_add=True):
57 if is_east:
58 res = self._test.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020059 ip_sw_if_index, self.east, is_add
60 )
Stanislav Zaikin328b5da2021-07-15 16:27:29 +020061 else:
62 res = self._test.vapi.sw_interface_set_unnumbered(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020063 ip_sw_if_index, self.west, is_add
64 )
Neale Ranns17ff3c12018-07-04 10:24:24 -070065
66
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000067@unittest.skipIf("acl" in config.excluded_plugins, "Exclude tests requiring ACL plugin")
Neale Ranns17ff3c12018-07-04 10:24:24 -070068class TestPipe(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020069 """Pipes"""
Neale Ranns17ff3c12018-07-04 10:24:24 -070070
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070071 @classmethod
72 def setUpClass(cls):
73 super(TestPipe, cls).setUpClass()
74
75 @classmethod
76 def tearDownClass(cls):
77 super(TestPipe, cls).tearDownClass()
78
Neale Ranns17ff3c12018-07-04 10:24:24 -070079 def setUp(self):
80 super(TestPipe, self).setUp()
81
82 self.create_pg_interfaces(range(4))
83
84 for i in self.pg_interfaces:
85 i.admin_up()
86
87 def tearDown(self):
88 for i in self.pg_interfaces:
89 i.admin_down()
90
91 super(TestPipe, self).tearDown()
92
93 def test_pipe(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020094 """Pipes"""
Neale Ranns17ff3c12018-07-04 10:24:24 -070095
Neale Ranns208c29a2018-04-11 08:08:30 -070096 pipes = [VppPipe(self), VppPipe(self, 10)]
Neale Ranns17ff3c12018-07-04 10:24:24 -070097
98 for p in pipes:
99 p.add_vpp_config()
100 p.admin_up()
101
102 #
103 # L2 cross-connect pipe0 east with pg0 and west with pg1
104 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200105 self.vapi.sw_interface_set_l2_xconnect(
106 self.pg0.sw_if_index, pipes[0].east, enable=1
107 )
108 self.vapi.sw_interface_set_l2_xconnect(
109 pipes[0].east, self.pg0.sw_if_index, enable=1
110 )
111 self.vapi.sw_interface_set_l2_xconnect(
112 self.pg1.sw_if_index, pipes[0].west, enable=1
113 )
114 self.vapi.sw_interface_set_l2_xconnect(
115 pipes[0].west, self.pg1.sw_if_index, enable=1
116 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700117
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700118 # test bi-directional L2 flow pg0<->pg1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 p = (
120 Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac)
121 / IP(src="1.1.1.1", dst="1.1.1.2")
122 / UDP(sport=1234, dport=1234)
123 / Raw(b"\xa5" * 100)
124 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700125
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400126 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
127 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700128
129 #
130 # Attach ACL to ensure features are run on the pipe
131 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200132 rule_1 = AclRule(
133 is_permit=0,
134 proto=17,
135 src_prefix=IPv4Network("1.1.1.1/32"),
136 dst_prefix=IPv4Network("1.1.1.2/32"),
137 ports=1234,
138 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100139 acl = VppAcl(self, rules=[rule_1])
140 acl.add_vpp_config()
Neale Ranns17ff3c12018-07-04 10:24:24 -0700141
142 # Apply the ACL on the pipe on output
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200143 acl_if_e = VppAclInterface(
144 self, sw_if_index=pipes[0].east, n_input=0, acls=[acl]
145 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100146 acl_if_e.add_vpp_config()
147
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400148 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
149 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700150
151 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100152 acl_if_e.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200153 acl_if_w = VppAclInterface(
154 self, sw_if_index=pipes[0].west, n_input=1, acls=[acl]
155 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100156 acl_if_w.add_vpp_config()
157
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400158 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
159 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100160
161 acl_if_w.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400162 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
163 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700164
165 #
166 # L3 routes in two separate tables so a pipe can be used to L3
167 # x-connect
168 #
169 tables = []
170 tables.append(VppIpTable(self, 1))
171 tables.append(VppIpTable(self, 2))
172
173 for t in tables:
174 t.add_vpp_config()
175
176 self.pg2.set_table_ip4(1)
177 self.pg2.config_ip4()
178 self.pg2.resolve_arp()
179 self.pg3.set_table_ip4(2)
180 self.pg3.config_ip4()
181 self.pg3.resolve_arp()
182
183 routes = []
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200184 routes.append(
185 VppIpRoute(
186 self,
187 "1.1.1.1",
188 32,
189 [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)],
190 table_id=2,
191 )
192 )
193 routes.append(
194 VppIpRoute(
195 self,
196 "1.1.1.1",
197 32,
198 [VppRoutePath("0.0.0.0", pipes[1].east)],
199 table_id=1,
200 )
201 )
202 routes.append(
203 VppIpRoute(
204 self,
205 "1.1.1.2",
206 32,
207 [VppRoutePath("0.0.0.0", pipes[1].west)],
208 table_id=2,
209 )
210 )
211 routes.append(
212 VppIpRoute(
213 self,
214 "1.1.1.2",
215 32,
216 [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)],
217 table_id=1,
218 )
219 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700220
221 for r in routes:
222 r.add_vpp_config()
223
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200224 p_east = (
225 Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
226 / IP(src="1.1.1.2", dst="1.1.1.1")
227 / UDP(sport=1234, dport=1234)
228 / Raw(b"\xa5" * 100)
229 )
Neale Ranns17ff3c12018-07-04 10:24:24 -0700230
231 # bind the pipe ends to the correct tables
232 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
233 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
234
235 # IP is not enabled on the pipes at this point
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400236 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700237
238 # IP enable the Pipes by making them unnumbered
Stanislav Zaikin328b5da2021-07-15 16:27:29 +0200239 pipes[1].set_unnumbered(self.pg2.sw_if_index, True)
240 pipes[1].set_unnumbered(self.pg3.sw_if_index, False)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700241
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400242 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700243
244 # and the return path
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200245 p_west = (
246 Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
247 / IP(src="1.1.1.1", dst="1.1.1.2")
248 / UDP(sport=1234, dport=1234)
249 / Raw(b"\xa5" * 100)
250 )
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400251 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700252
253 #
254 # Use ACLs to test features run on the Pipes
255 #
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200256 acl_if_e1 = VppAclInterface(
257 self, sw_if_index=pipes[1].east, n_input=0, acls=[acl]
258 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100259 acl_if_e1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400260 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
261 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700262
263 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100264 acl_if_e1.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 acl_if_w1 = VppAclInterface(
266 self, sw_if_index=pipes[1].west, n_input=1, acls=[acl]
267 )
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100268 acl_if_w1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400269 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
270 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100271 acl_if_w1.remove_vpp_config()
272
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400273 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
274 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700275
276 # cleanup (so the tables delete)
277 self.pg2.unconfig_ip4()
278 self.pg2.set_table_ip4(0)
279 self.pg3.unconfig_ip4()
280 self.pg3.set_table_ip4(0)
281 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
282 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
283
284
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200285if __name__ == "__main__":
Neale Ranns17ff3c12018-07-04 10:24:24 -0700286 unittest.main(testRunner=VppTestRunner)