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