udp: fix csum computation when offload disabled
[vpp.git] / test / test_sixrd.py
1 #!/usr/bin/env python3
2 """ 6RD RFC5969 functional tests """
3
4 import unittest
5 from scapy.layers.inet import IP, UDP, Ether
6 from scapy.layers.inet6 import IPv6
7 from scapy.packet import Raw
8 from framework import VppTestCase
9 from asfframework import VppTestRunner
10 from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
11
12 """ Test6rd is a subclass of  VPPTestCase classes.
13
14 6RD tests.
15
16 """
17
18
19 class Test6RD(VppTestCase):
20     """6RD Test Case"""
21
22     @classmethod
23     def setUpClass(cls):
24         super(Test6RD, cls).setUpClass()
25         cls.create_pg_interfaces(range(4))
26         cls.interfaces = list(cls.pg_interfaces)
27
28     @classmethod
29     def tearDownClass(cls):
30         super(Test6RD, cls).tearDownClass()
31
32     def setUp(self):
33         super(Test6RD, self).setUp()
34         t4 = VppIpTable(self, 10)
35         t6 = VppIpTable(self, 20, True)
36
37         t4.add_vpp_config()
38         t6.add_vpp_config()
39
40         for n in range(4):
41             i = self.pg_interfaces[n]
42             i.admin_up()
43             if n > 1:
44                 i.set_table_ip4(10)
45                 i.set_table_ip6(20)
46             i.config_ip4()
47             i.config_ip6()
48             i.disable_ipv6_ra()
49             i.resolve_arp()
50             i.resolve_ndp()
51
52     def tearDown(self):
53         for i in self.pg_interfaces:
54             i.unconfig_ip4()
55             i.unconfig_ip6()
56             i.set_table_ip4(0)
57             i.set_table_ip6(0)
58             i.admin_down()
59         super(Test6RD, self).tearDown()
60
61     def validate_6in4(self, rx, expected):
62         if IP not in rx:
63             self.fail()
64         if IPv6 not in rx:
65             self.fail()
66
67         self.assertEqual(rx[IP].src, expected[IP].src)
68         self.assertEqual(rx[IP].dst, expected[IP].dst)
69         self.assertEqual(rx[IP].proto, expected[IP].proto)
70         self.assertEqual(rx[IPv6].src, expected[IPv6].src)
71         self.assertEqual(rx[IPv6].dst, expected[IPv6].dst)
72
73     def validate_4in6(self, rx, expected):
74         if IPv6 not in rx:
75             self.fail()
76         if IP in rx:
77             self.fail()
78
79         self.assertEqual(rx[IPv6].src, expected[IPv6].src)
80         self.assertEqual(rx[IPv6].dst, expected[IPv6].dst)
81         self.assertEqual(rx[IPv6].nh, expected[IPv6].nh)
82
83     def payload(self, len):
84         return "x" * len
85
86     def test_6rd_ip6_to_ip4(self):
87         """ip6 -> ip4 (encap) 6rd test"""
88         p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
89         p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1", nh="UDP")
90
91         rv = self.vapi.ipip_6rd_add_tunnel(
92             ip6_table_id=0,
93             ip4_table_id=0,
94             ip6_prefix="2002::/16",
95             ip4_prefix="0.0.0.0/0",
96             ip4_src=self.pg0.local_ip4,
97             security_check=True,
98         )
99
100         self.tunnel_index = rv.sw_if_index
101
102         self.vapi.cli("show ip6 fib")
103         p_payload = UDP(sport=1234, dport=1234)
104         p = p_ether / p_ip6 / p_payload
105
106         p_reply = (
107             IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, proto="ipv6") / p_ip6
108         )
109
110         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
111         for p in rx:
112             self.validate_6in4(p, p_reply)
113
114         # MTU tests (default is 1480)
115         plen = 1481 - 40 - 8
116         p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1")
117         p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
118         p = p_ether / p_ip6 / p_payload
119
120         p_reply = (
121             IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, proto="ipv6") / p_ip6
122         )
123
124         rx = self.send_and_assert_no_replies(self.pg0, p * 10)
125         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
126
127     def test_6rd_ip6_to_ip4_vrf(self):
128         """ip6 -> ip4 (encap) 6rd VRF test"""
129         p_ether = Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
130         p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1", nh="UDP")
131
132         rv = self.vapi.ipip_6rd_add_tunnel(
133             ip6_table_id=20,
134             ip4_table_id=10,
135             ip6_prefix="2002::/16",
136             ip4_prefix="0.0.0.0/0",
137             ip4_src=self.pg2.local_ip4,
138             security_check=True,
139         )
140         self.tunnel_index = rv.sw_if_index
141
142         self.vapi.cli("show ip6 fib")
143         p_payload = UDP(sport=1234, dport=1234)
144         p = p_ether / p_ip6 / p_payload
145
146         p_reply = (
147             IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4, proto="ipv6") / p_ip6
148         )
149
150         rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
151         for p in rx:
152             self.validate_6in4(p, p_reply)
153
154         # MTU tests (default is 1480)
155         plen = 1481 - 40 - 8
156         p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1")
157         p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
158         p = p_ether / p_ip6 / p_payload
159
160         p_reply = (
161             IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4, proto="ipv6") / p_ip6
162         )
163
164         rx = self.send_and_assert_no_replies(self.pg0, p * 10)
165         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
166
167     def test_6rd_ip4_to_ip6(self):
168         """ip4 -> ip6 (decap) 6rd test"""
169
170         rv = self.vapi.ipip_6rd_add_tunnel(
171             ip6_table_id=0,
172             ip4_table_id=0,
173             ip6_prefix="2002::/16",
174             ip4_prefix="0.0.0.0/0",
175             ip4_src=self.pg0.local_ip4,
176             security_check=True,
177         )
178         self.tunnel_index = rv.sw_if_index
179         rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
180         rv = self.vapi.ipip_6rd_add_tunnel(
181             ip6_table_id=0,
182             ip4_table_id=0,
183             ip6_prefix="2002::/16",
184             ip4_prefix="0.0.0.0/0",
185             ip4_src=self.pg0.local_ip4,
186             security_check=True,
187         )
188         self.tunnel_index = rv.sw_if_index
189
190         p_ip6 = IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) / UDP(
191             sport=1234, dport=1234
192         )
193
194         p = (
195             Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
196             / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
197             / p_ip6
198         )
199
200         p_reply = p_ip6
201
202         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
203         for p in rx:
204             self.validate_4in6(p, p_reply)
205         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
206
207     def test_6rd_ip4_to_ip6_vrf(self):
208         """ip4 -> ip6 (decap) 6rd VRF test"""
209
210         rv = self.vapi.ipip_6rd_add_tunnel(
211             ip6_table_id=20,
212             ip4_table_id=10,
213             ip6_prefix="2002::/16",
214             ip4_prefix="0.0.0.0/0",
215             ip4_src=self.pg2.local_ip4,
216             security_check=True,
217         )
218         self.tunnel_index = rv.sw_if_index
219         rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
220         rv = self.vapi.ipip_6rd_add_tunnel(
221             ip6_table_id=20,
222             ip4_table_id=10,
223             ip6_prefix="2002::/16",
224             ip4_prefix="0.0.0.0/0",
225             ip4_src=self.pg2.local_ip4,
226             security_check=True,
227         )
228         self.tunnel_index = rv.sw_if_index
229         self.vapi.sw_interface_set_table(self.tunnel_index, 1, 20)
230
231         p_ip6 = IPv6(src="2002:AC10:0402::1", dst=self.pg3.remote_ip6) / UDP(
232             sport=1234, dport=1234
233         )
234
235         p = (
236             Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
237             / IP(src=self.pg3.remote_ip4, dst=self.pg2.local_ip4)
238             / p_ip6
239         )
240
241         p_reply = p_ip6
242
243         rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
244         for p in rx:
245             self.validate_4in6(p, p_reply)
246         self.vapi.sw_interface_set_table(self.tunnel_index, 1, 0)
247         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
248
249     def test_6rd_ip4_to_ip6_multiple(self):
250         """ip4 -> ip6 (decap) 6rd test"""
251
252         self.tunnel_index = []
253         rv = self.vapi.ipip_6rd_add_tunnel(
254             ip6_table_id=0,
255             ip4_table_id=0,
256             ip6_prefix="2002::/16",
257             ip4_prefix="0.0.0.0/0",
258             ip4_src=self.pg0.local_ip4,
259             security_check=True,
260         )
261         self.tunnel_index.append(rv.sw_if_index)
262         rv = self.vapi.ipip_6rd_add_tunnel(
263             ip6_table_id=0,
264             ip4_table_id=0,
265             ip6_prefix="2003::/16",
266             ip4_prefix="0.0.0.0/0",
267             ip4_src=self.pg1.local_ip4,
268             security_check=True,
269         )
270
271         self.tunnel_index.append(rv.sw_if_index)
272
273         self.vapi.cli("show ip6 fib")
274         p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
275         p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
276         p_ip6_1 = IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) / UDP(
277             sport=1234, dport=1234
278         )
279         p_ip6_2 = IPv6(src="2003:AC10:0202::1", dst=self.pg1.remote_ip6) / UDP(
280             sport=1234, dport=1234
281         )
282
283         p = p_ether / p_ip4 / p_ip6_1
284         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
285         for p in rx:
286             self.validate_4in6(p, p_ip6_1)
287
288         p = p_ether / p_ip4 / p_ip6_2
289         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
290         for p in rx:
291             self.validate_4in6(p, p_ip6_2)
292         for i in self.tunnel_index:
293             self.vapi.ipip_6rd_del_tunnel(i)
294
295     def test_6rd_ip4_to_ip6_suffix(self):
296         """ip4 -> ip6 (decap) 6rd test"""
297
298         rv = self.vapi.ipip_6rd_add_tunnel(
299             ip6_table_id=0,
300             ip4_table_id=0,
301             ip6_prefix="2002::/16",
302             ip4_prefix="172.0.0.0/8",
303             ip4_src=self.pg0.local_ip4,
304             security_check=True,
305         )
306         self.tunnel_index = rv.sw_if_index
307
308         self.vapi.cli("show ip6 fib")
309         p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
310         p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
311         p_ip6 = IPv6(src="2002:1002:0200::1", dst=self.pg1.remote_ip6) / UDP(
312             sport=1234, dport=1234
313         )
314
315         p = p_ether / p_ip4 / p_ip6
316         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
317         for p in rx:
318             self.validate_4in6(p, p_ip6)
319         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
320
321     def test_6rd_ip4_to_ip6_sec_check(self):
322         """ip4 -> ip6 (decap) security check 6rd test"""
323
324         rv = self.vapi.ipip_6rd_add_tunnel(
325             ip6_table_id=0,
326             ip4_table_id=0,
327             ip6_prefix="2002::/16",
328             ip4_prefix="0.0.0.0/0",
329             ip4_src=self.pg0.local_ip4,
330             security_check=True,
331         )
332         self.tunnel_index = rv.sw_if_index
333
334         self.vapi.cli("show ip6 fib")
335         p_ip6 = IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) / UDP(
336             sport=1234, dport=1234
337         )
338         p_ip6_fail = IPv6(src="2002:DEAD:0202::1", dst=self.pg1.remote_ip6) / UDP(
339             sport=1234, dport=1234
340         )
341
342         p = (
343             Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
344             / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
345             / p_ip6
346         )
347
348         p_reply = p_ip6
349
350         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
351         for p in rx:
352             self.validate_4in6(p, p_reply)
353
354         p = (
355             Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
356             / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
357             / p_ip6_fail
358         )
359         rx = self.send_and_assert_no_replies(self.pg0, p * 10)
360         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
361
362     def test_6rd_bgp_tunnel(self):
363         """6rd BGP tunnel"""
364
365         rv = self.vapi.ipip_6rd_add_tunnel(
366             ip6_table_id=0,
367             ip4_table_id=0,
368             ip6_prefix="2002::/16",
369             ip4_prefix="0.0.0.0/0",
370             ip4_src=self.pg0.local_ip4,
371             security_check=False,
372         )
373
374         self.tunnel_index = rv.sw_if_index
375
376         default_route = VppIpRoute(
377             self, "DEAD::", 16, [VppRoutePath("2002:0808:0808::", self.tunnel_index)]
378         )
379         default_route.add_vpp_config()
380
381         ip4_route = VppIpRoute(
382             self, "8.0.0.0", 8, [VppRoutePath(self.pg1.remote_ip4, 0xFFFFFFFF)]
383         )
384         ip4_route.add_vpp_config()
385
386         # Via recursive route 6 -> 4
387         p = (
388             Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
389             / IPv6(src="1::1", dst="DEAD:BEEF::1")
390             / UDP(sport=1234, dport=1234)
391         )
392
393         p_reply = IP(src=self.pg0.local_ip4, dst="8.8.8.8", proto="ipv6") / IPv6(
394             src="1::1", dst="DEAD:BEEF::1", nh="UDP"
395         )
396
397         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
398         for p in rx:
399             self.validate_6in4(p, p_reply)
400
401         # Via recursive route 4 -> 6 (Security check must be disabled)
402         p_ip6 = IPv6(src="DEAD:BEEF::1", dst=self.pg1.remote_ip6) / UDP(
403             sport=1234, dport=1234
404         )
405         p = (
406             Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
407             / IP(src="8.8.8.8", dst=self.pg0.local_ip4)
408             / p_ip6
409         )
410
411         p_reply = p_ip6
412
413         rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
414         for p in rx:
415             self.validate_4in6(p, p_reply)
416         ip4_route.remove_vpp_config()
417         default_route.remove_vpp_config()
418         self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
419
420
421 if __name__ == "__main__":
422     unittest.main(testRunner=VppTestRunner)