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