tests: replace pycodestyle with black
[vpp.git] / test / test_svs.py
1 #!/usr/bin/env python3
2
3 import unittest
4
5 from framework import VppTestCase, VppTestRunner
6 from vpp_ip_route import VppIpTable
7
8 from scapy.packet import Raw
9 from scapy.layers.l2 import Ether
10 from scapy.layers.inet import IP, UDP, ICMP
11 from scapy.layers.inet6 import IPv6
12
13 from vpp_papi import VppEnum
14
15 NUM_PKTS = 67
16
17
18 class TestSVS(VppTestCase):
19     """SVS Test Case"""
20
21     @classmethod
22     def setUpClass(cls):
23         super(TestSVS, cls).setUpClass()
24
25     @classmethod
26     def tearDownClass(cls):
27         super(TestSVS, cls).tearDownClass()
28
29     def setUp(self):
30         super(TestSVS, self).setUp()
31
32         # create 2 pg interfaces
33         self.create_pg_interfaces(range(4))
34
35         table_id = 0
36
37         for i in self.pg_interfaces:
38             i.admin_up()
39
40             if table_id != 0:
41                 tbl = VppIpTable(self, table_id)
42                 tbl.add_vpp_config()
43                 tbl = VppIpTable(self, table_id, is_ip6=1)
44                 tbl.add_vpp_config()
45
46             i.set_table_ip4(table_id)
47             i.set_table_ip6(table_id)
48             i.config_ip4()
49             i.resolve_arp()
50             i.config_ip6()
51             i.resolve_ndp()
52             table_id += 1
53
54     def tearDown(self):
55         for i in self.pg_interfaces:
56             i.unconfig_ip4()
57             i.unconfig_ip6()
58             i.set_table_ip4(0)
59             i.set_table_ip6(0)
60             i.admin_down()
61         super(TestSVS, self).tearDown()
62
63     def test_svs4(self):
64         """Source VRF Select IP4"""
65
66         #
67         # packets destined out of the 3 non-default table interfaces
68         #
69         pkts_0 = [
70             (
71                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
72                 / IP(src="1.1.1.1", dst=self.pg1.remote_ip4)
73                 / UDP(sport=1234, dport=1234)
74                 / Raw(b"\xa5" * 100)
75             ),
76             (
77                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
78                 / IP(src="2.2.2.2", dst=self.pg2.remote_ip4)
79                 / UDP(sport=1234, dport=1234)
80                 / Raw(b"\xa5" * 100)
81             ),
82             (
83                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
84                 / IP(src="3.3.3.3", dst=self.pg3.remote_ip4)
85                 / UDP(sport=1234, dport=1234)
86                 / Raw(b"\xa5" * 100)
87             ),
88         ]
89         pkts_1 = [
90             (
91                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
92                 / IP(src="1.1.1.1", dst=self.pg1.remote_ip4)
93                 / UDP(sport=1234, dport=1234)
94                 / Raw(b"\xa5" * 100)
95             ),
96             (
97                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
98                 / IP(src="2.2.2.2", dst=self.pg2.remote_ip4)
99                 / UDP(sport=1234, dport=1234)
100                 / Raw(b"\xa5" * 100)
101             ),
102             (
103                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
104                 / IP(src="3.3.3.3", dst=self.pg3.remote_ip4)
105                 / UDP(sport=1234, dport=1234)
106                 / Raw(b"\xa5" * 100)
107             ),
108         ]
109
110         #
111         # before adding the SVS config all these packets are dropped when
112         # ingressing on pg0 since pg0 is in the default table
113         #
114         for p in pkts_0:
115             self.send_and_assert_no_replies(self.pg0, p * 1)
116
117         #
118         # Add table 1001 & 1002 into which we'll add the routes
119         # determining the source VRF selection
120         #
121         table_ids = [101, 102]
122
123         for table_id in table_ids:
124             self.vapi.svs_table_add_del(
125                 is_add=1,
126                 af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
127                 table_id=table_id,
128             )
129
130             #
131             # map X.0.0.0/8 to each SVS table for lookup in table X
132             #
133             for i in range(1, 4):
134                 self.vapi.svs_route_add_del(
135                     is_add=1,
136                     prefix="%d.0.0.0/8" % i,
137                     table_id=table_id,
138                     source_table_id=i,
139                 )
140
141         #
142         # Enable SVS on pg0/pg1 using table 1001/1002
143         #
144         self.vapi.svs_enable_disable(
145             is_enable=1,
146             af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
147             table_id=table_ids[0],
148             sw_if_index=self.pg0.sw_if_index,
149         )
150         self.vapi.svs_enable_disable(
151             is_enable=1,
152             af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
153             table_id=table_ids[1],
154             sw_if_index=self.pg1.sw_if_index,
155         )
156
157         #
158         # now all the packets should be delivered out the respective interface
159         #
160         self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
161         self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
162         self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
163         self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
164         self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
165         self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
166
167         #
168         # check that if the SVS lookup does not match a route the packet
169         # is forwarded using the interface's routing table
170         #
171         p = (
172             Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
173             / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
174             / UDP(sport=1234, dport=1234)
175             / Raw(b"\xa5" * 100)
176         )
177         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
178
179         p = (
180             Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
181             / IP(src=self.pg1.remote_ip4, dst=self.pg1.remote_ip4)
182             / UDP(sport=1234, dport=1234)
183             / Raw(b"\xa5" * 100)
184         )
185         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
186
187         #
188         # dump the SVS configs
189         #
190         ss = self.vapi.svs_dump()
191
192         self.assertEqual(ss[0].table_id, table_ids[0])
193         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
194         self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
195         self.assertEqual(ss[1].table_id, table_ids[1])
196         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
197         self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP4)
198
199         #
200         # cleanup
201         #
202         self.vapi.svs_enable_disable(
203             is_enable=0,
204             af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
205             table_id=table_ids[0],
206             sw_if_index=self.pg0.sw_if_index,
207         )
208         self.vapi.svs_enable_disable(
209             is_enable=0,
210             af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
211             table_id=table_ids[1],
212             sw_if_index=self.pg1.sw_if_index,
213         )
214
215         for table_id in table_ids:
216             for i in range(1, 4):
217                 self.vapi.svs_route_add_del(
218                     is_add=0,
219                     prefix="%d.0.0.0/8" % i,
220                     table_id=table_id,
221                     source_table_id=0,
222                 )
223
224             self.vapi.svs_table_add_del(
225                 is_add=0,
226                 af=VppEnum.vl_api_address_family_t.ADDRESS_IP4,
227                 table_id=table_id,
228             )
229
230     def test_svs6(self):
231         """Source VRF Select IP6"""
232
233         #
234         # packets destined out of the 3 non-default table interfaces
235         #
236         pkts_0 = [
237             (
238                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
239                 / IPv6(src="2001:1::1", dst=self.pg1.remote_ip6)
240                 / UDP(sport=1234, dport=1234)
241                 / Raw(b"\xa5" * 100)
242             ),
243             (
244                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
245                 / IPv6(src="2001:2::1", dst=self.pg2.remote_ip6)
246                 / UDP(sport=1234, dport=1234)
247                 / Raw(b"\xa5" * 100)
248             ),
249             (
250                 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
251                 / IPv6(src="2001:3::1", dst=self.pg3.remote_ip6)
252                 / UDP(sport=1234, dport=1234)
253                 / Raw(b"\xa5" * 100)
254             ),
255         ]
256         pkts_1 = [
257             (
258                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
259                 / IPv6(src="2001:1::1", dst=self.pg1.remote_ip6)
260                 / UDP(sport=1234, dport=1234)
261                 / Raw(b"\xa5" * 100)
262             ),
263             (
264                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
265                 / IPv6(src="2001:2::1", dst=self.pg2.remote_ip6)
266                 / UDP(sport=1234, dport=1234)
267                 / Raw(b"\xa5" * 100)
268             ),
269             (
270                 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
271                 / IPv6(src="2001:3::1", dst=self.pg3.remote_ip6)
272                 / UDP(sport=1234, dport=1234)
273                 / Raw(b"\xa5" * 100)
274             ),
275         ]
276
277         #
278         # before adding the SVS config all these packets are dropped when
279         # ingressing on pg0 since pg0 is in the default table
280         #
281         for p in pkts_0:
282             self.send_and_assert_no_replies(self.pg0, p * 1)
283
284         #
285         # Add table 1001 & 1002 into which we'll add the routes
286         # determining the source VRF selection
287         #
288         table_ids = [101, 102]
289
290         for table_id in table_ids:
291             self.vapi.svs_table_add_del(
292                 is_add=1,
293                 af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
294                 table_id=table_id,
295             )
296
297             #
298             # map X.0.0.0/8 to each SVS table for lookup in table X
299             #
300             for i in range(1, 4):
301                 self.vapi.svs_route_add_del(
302                     is_add=1,
303                     prefix="2001:%d::/32" % i,
304                     table_id=table_id,
305                     source_table_id=i,
306                 )
307
308         #
309         # Enable SVS on pg0/pg1 using table 1001/1002
310         #
311         self.vapi.svs_enable_disable(
312             is_enable=1,
313             af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
314             table_id=table_ids[0],
315             sw_if_index=self.pg0.sw_if_index,
316         )
317         self.vapi.svs_enable_disable(
318             is_enable=1,
319             af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
320             table_id=table_ids[1],
321             sw_if_index=self.pg1.sw_if_index,
322         )
323
324         #
325         # now all the packets should be delivered out the respective interface
326         #
327         self.send_and_expect(self.pg0, pkts_0[0] * NUM_PKTS, self.pg1)
328         self.send_and_expect(self.pg0, pkts_0[1] * NUM_PKTS, self.pg2)
329         self.send_and_expect(self.pg0, pkts_0[2] * NUM_PKTS, self.pg3)
330         self.send_and_expect(self.pg1, pkts_1[0] * NUM_PKTS, self.pg1)
331         self.send_and_expect(self.pg1, pkts_1[1] * NUM_PKTS, self.pg2)
332         self.send_and_expect(self.pg1, pkts_1[2] * NUM_PKTS, self.pg3)
333
334         #
335         # check that if the SVS lookup does not match a route the packet
336         # is forwarded using the interface's routing table
337         #
338         p = (
339             Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
340             / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
341             / UDP(sport=1234, dport=1234)
342             / Raw(b"\xa5" * 100)
343         )
344         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg0)
345
346         p = (
347             Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
348             / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6)
349             / UDP(sport=1234, dport=1234)
350             / Raw(b"\xa5" * 100)
351         )
352         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg1)
353
354         #
355         # dump the SVS configs
356         #
357         ss = self.vapi.svs_dump()
358
359         self.assertEqual(ss[0].table_id, table_ids[0])
360         self.assertEqual(ss[0].sw_if_index, self.pg0.sw_if_index)
361         self.assertEqual(ss[0].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
362         self.assertEqual(ss[1].table_id, table_ids[1])
363         self.assertEqual(ss[1].sw_if_index, self.pg1.sw_if_index)
364         self.assertEqual(ss[1].af, VppEnum.vl_api_address_family_t.ADDRESS_IP6)
365
366         #
367         # cleanup
368         #
369         self.vapi.svs_enable_disable(
370             is_enable=0,
371             af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
372             table_id=table_ids[0],
373             sw_if_index=self.pg0.sw_if_index,
374         )
375         self.vapi.svs_enable_disable(
376             is_enable=0,
377             af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
378             table_id=table_ids[1],
379             sw_if_index=self.pg1.sw_if_index,
380         )
381
382         for table_id in table_ids:
383             for i in range(1, 4):
384                 self.vapi.svs_route_add_del(
385                     is_add=0,
386                     prefix="2001:%d::/32" % i,
387                     table_id=table_id,
388                     source_table_id=0,
389                 )
390
391             self.vapi.svs_table_add_del(
392                 is_add=0,
393                 af=VppEnum.vl_api_address_family_t.ADDRESS_IP6,
394                 table_id=table_id,
395             )
396
397
398 if __name__ == "__main__":
399     unittest.main(testRunner=VppTestRunner)