blob: ae4af15c2e3d3d37d847230127de8a75f5392886 [file] [log] [blame]
Ole Troan46c1c112018-03-14 20:39:40 +01001#!/usr/bin/env python
2""" 6RD RFC5969 functional tests """
Ole Troan6ee40512018-02-12 18:14:39 +01003
4import unittest
Ole Troan46c1c112018-03-14 20:39:40 +01005from scapy.layers.inet import IP, UDP, Ether
Ole Troan6ee40512018-02-12 18:14:39 +01006from scapy.layers.inet6 import IPv6
Ole Troan6ee40512018-02-12 18:14:39 +01007from scapy.packet import Raw
Ole Troan46c1c112018-03-14 20:39:40 +01008from framework import VppTestCase, VppTestRunner
Neale Rannsc0a93142018-09-05 15:42:26 -07009from vpp_ip import DpoProto
Neale Ranns097fa662018-05-01 05:17:55 -070010from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable, FibPathProto
Ole Troan46c1c112018-03-14 20:39:40 +010011from socket import AF_INET, AF_INET6, inet_pton
Ole Troan6ee40512018-02-12 18:14:39 +010012
13""" Test6rd is a subclass of VPPTestCase classes.
14
156RD tests.
16
17"""
18
19
20class Test6RD(VppTestCase):
21 """ 6RD Test Case """
22
23 @classmethod
24 def setUpClass(cls):
25 super(Test6RD, cls).setUpClass()
Neale Ranns61502112018-08-22 00:21:14 -070026 cls.create_pg_interfaces(range(4))
Ole Troan46c1c112018-03-14 20:39:40 +010027 cls.interfaces = list(cls.pg_interfaces)
Ole Troan6ee40512018-02-12 18:14:39 +010028
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070029 @classmethod
30 def tearDownClass(cls):
31 super(Test6RD, cls).tearDownClass()
32
Neale Ranns61502112018-08-22 00:21:14 -070033 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]
Ole Troan46c1c112018-03-14 20:39:40 +010043 i.admin_up()
Neale Ranns61502112018-08-22 00:21:14 -070044 if (n > 1):
45 i.set_table_ip4(10)
46 i.set_table_ip6(20)
Ole Troan46c1c112018-03-14 20:39:40 +010047 i.config_ip4()
48 i.config_ip6()
49 i.disable_ipv6_ra()
50 i.resolve_arp()
51 i.resolve_ndp()
Ole Troan6ee40512018-02-12 18:14:39 +010052
53 def tearDown(self):
Neale Ranns61502112018-08-22 00:21:14 -070054 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)
Ole Troan6ee40512018-02-12 18:14:39 +010059 super(Test6RD, self).tearDown()
Ole Troan6ee40512018-02-12 18:14:39 +010060
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
Paul Vinciguerra3d2df212018-11-24 23:19:53 -080079 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)
Ole Troan6ee40512018-02-12 18:14:39 +010082
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
Ole Troan288e0932019-05-29 12:30:05 +020091 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
92 ip4_table_id=0,
93 ip6_prefix='2002::/16',
94 ip4_prefix='0.0.0.0/0',
95 ip4_src=self.pg0.local_ip4,
96 security_check=True)
97
Ole Troan6ee40512018-02-12 18:14:39 +010098 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +010099
Ole Troan6ee40512018-02-12 18:14:39 +0100100 self.vapi.cli("show ip6 fib")
101 p_payload = UDP(sport=1234, dport=1234)
102 p = (p_ether / p_ip6 / p_payload)
103
104 p_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
105 proto='ipv6') / p_ip6)
106
Ole Troan9a475372019-03-05 16:58:24 +0100107 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100108 for p in rx:
109 self.validate_6in4(p, p_reply)
110
111 # MTU tests (default is 1480)
112 plen = 1481 - 40 - 8
113 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1")
114 p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
115 p = (p_ether / p_ip6 / p_payload)
116
117 p_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
118 proto='ipv6') / p_ip6)
119
Ole Troan9a475372019-03-05 16:58:24 +0100120 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700121 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
122
123 def test_6rd_ip6_to_ip4_vrf(self):
124 """ ip6 -> ip4 (encap) 6rd VRF test """
125 p_ether = Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
126 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1", nh='UDP')
127
Ole Troan288e0932019-05-29 12:30:05 +0200128 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=20, ip4_table_id=10,
129 ip6_prefix='2002::/16',
130 ip4_prefix='0.0.0.0/0',
131 ip4_src=self.pg2.local_ip4,
132 security_check=True)
Neale Ranns61502112018-08-22 00:21:14 -0700133 self.tunnel_index = rv.sw_if_index
134
135 self.vapi.cli("show ip6 fib")
136 p_payload = UDP(sport=1234, dport=1234)
137 p = (p_ether / p_ip6 / p_payload)
138
139 p_reply = (IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4,
140 proto='ipv6') / p_ip6)
141
Ole Troan9a475372019-03-05 16:58:24 +0100142 rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
Neale Ranns61502112018-08-22 00:21:14 -0700143 for p in rx:
144 self.validate_6in4(p, p_reply)
145
146 # MTU tests (default is 1480)
147 plen = 1481 - 40 - 8
148 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1")
149 p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
150 p = (p_ether / p_ip6 / p_payload)
151
152 p_reply = (IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4,
153 proto='ipv6') / p_ip6)
154
Ole Troan9a475372019-03-05 16:58:24 +0100155 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700156 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100157
158 def test_6rd_ip4_to_ip6(self):
159 """ ip4 -> ip6 (decap) 6rd test """
160
Ole Troan288e0932019-05-29 12:30:05 +0200161 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
162 ip4_table_id=0,
163 ip6_prefix='2002::/16',
164 ip4_prefix='0.0.0.0/0',
165 ip4_src=self.pg0.local_ip4,
166 security_check=True)
Ole Troan6ee40512018-02-12 18:14:39 +0100167 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100168 rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
Ole Troan288e0932019-05-29 12:30:05 +0200169 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
170 ip4_table_id=0,
171 ip6_prefix='2002::/16',
172 ip4_prefix='0.0.0.0/0',
173 ip4_src=self.pg0.local_ip4,
174 security_check=True)
Ole Troan298c6952018-03-08 12:30:43 +0100175 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100176
Ole Troan6ee40512018-02-12 18:14:39 +0100177 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
178 UDP(sport=1234, dport=1234))
179
180 p = (Ether(src=self.pg0.remote_mac,
181 dst=self.pg0.local_mac) /
182 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
183 p_ip6)
184
185 p_reply = p_ip6
186
Ole Troan9a475372019-03-05 16:58:24 +0100187 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100188 for p in rx:
189 self.validate_4in6(p, p_reply)
Neale Ranns61502112018-08-22 00:21:14 -0700190 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
191
192 def test_6rd_ip4_to_ip6_vrf(self):
193 """ ip4 -> ip6 (decap) 6rd VRF test """
194
Ole Troan288e0932019-05-29 12:30:05 +0200195 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=20,
196 ip4_table_id=10,
197 ip6_prefix='2002::/16',
198 ip4_prefix='0.0.0.0/0',
199 ip4_src=self.pg2.local_ip4,
200 security_check=True)
Neale Ranns61502112018-08-22 00:21:14 -0700201 self.tunnel_index = rv.sw_if_index
202 rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
Ole Troan288e0932019-05-29 12:30:05 +0200203 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=20,
204 ip4_table_id=10,
205 ip6_prefix='2002::/16',
206 ip4_prefix='0.0.0.0/0',
207 ip4_src=self.pg2.local_ip4,
208 security_check=True)
Neale Ranns61502112018-08-22 00:21:14 -0700209 self.tunnel_index = rv.sw_if_index
210 self.vapi.sw_interface_set_table(self.tunnel_index, 1, 20)
211
212 p_ip6 = (IPv6(src="2002:AC10:0402::1", dst=self.pg3.remote_ip6) /
213 UDP(sport=1234, dport=1234))
214
215 p = (Ether(src=self.pg2.remote_mac,
216 dst=self.pg2.local_mac) /
217 IP(src=self.pg3.remote_ip4, dst=self.pg2.local_ip4) /
218 p_ip6)
219
220 p_reply = p_ip6
221
Ole Troan9a475372019-03-05 16:58:24 +0100222 rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
Neale Ranns61502112018-08-22 00:21:14 -0700223 for p in rx:
224 self.validate_4in6(p, p_reply)
225 self.vapi.sw_interface_set_table(self.tunnel_index, 1, 0)
226 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100227
228 def test_6rd_ip4_to_ip6_multiple(self):
229 """ ip4 -> ip6 (decap) 6rd test """
230
231 self.tunnel_index = []
Ole Troan288e0932019-05-29 12:30:05 +0200232 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
233 ip4_table_id=0,
234 ip6_prefix='2002::/16',
235 ip4_prefix='0.0.0.0/0',
236 ip4_src=self.pg0.local_ip4,
237 security_check=True)
Ole Troan6ee40512018-02-12 18:14:39 +0100238 self.tunnel_index.append(rv.sw_if_index)
Ole Troan288e0932019-05-29 12:30:05 +0200239 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
240 ip4_table_id=0,
241 ip6_prefix='2003::/16',
242 ip4_prefix='0.0.0.0/0',
243 ip4_src=self.pg1.local_ip4,
244 security_check=True)
Ole Troan298c6952018-03-08 12:30:43 +0100245
Ole Troan6ee40512018-02-12 18:14:39 +0100246 self.tunnel_index.append(rv.sw_if_index)
247
248 self.vapi.cli("show ip6 fib")
249 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
250 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
251 p_ip6_1 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
252 UDP(sport=1234, dport=1234))
253 p_ip6_2 = (IPv6(src="2003:AC10:0202::1", dst=self.pg1.remote_ip6) /
254 UDP(sport=1234, dport=1234))
255
256 p = (p_ether / p_ip4 / p_ip6_1)
Ole Troan9a475372019-03-05 16:58:24 +0100257 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100258 for p in rx:
259 self.validate_4in6(p, p_ip6_1)
260
261 p = (p_ether / p_ip4 / p_ip6_2)
Ole Troan9a475372019-03-05 16:58:24 +0100262 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100263 for p in rx:
264 self.validate_4in6(p, p_ip6_2)
Neale Ranns61502112018-08-22 00:21:14 -0700265 for i in self.tunnel_index:
266 self.vapi.ipip_6rd_del_tunnel(i)
Ole Troan6ee40512018-02-12 18:14:39 +0100267
268 def test_6rd_ip4_to_ip6_suffix(self):
269 """ ip4 -> ip6 (decap) 6rd test """
270
Ole Troan288e0932019-05-29 12:30:05 +0200271 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
272 ip4_table_id=0,
273 ip6_prefix='2002::/16',
274 ip4_prefix='172.0.0.0/8',
275 ip4_src=self.pg0.local_ip4,
276 security_check=True)
Ole Troan6ee40512018-02-12 18:14:39 +0100277 self.tunnel_index = rv.sw_if_index
278
279 self.vapi.cli("show ip6 fib")
280 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
281 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
282 p_ip6 = (IPv6(src="2002:1002:0200::1", dst=self.pg1.remote_ip6) /
283 UDP(sport=1234, dport=1234))
284
285 p = (p_ether / p_ip4 / p_ip6)
Ole Troan9a475372019-03-05 16:58:24 +0100286 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100287 for p in rx:
288 self.validate_4in6(p, p_ip6)
Neale Ranns61502112018-08-22 00:21:14 -0700289 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100290
291 def test_6rd_ip4_to_ip6_sec_check(self):
292 """ ip4 -> ip6 (decap) security check 6rd test """
293
Ole Troan288e0932019-05-29 12:30:05 +0200294 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
295 ip4_table_id=0,
296 ip6_prefix='2002::/16',
297 ip4_prefix='0.0.0.0/0',
298 ip4_src=self.pg0.local_ip4,
299 security_check=True)
Ole Troan6ee40512018-02-12 18:14:39 +0100300 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100301
Ole Troan6ee40512018-02-12 18:14:39 +0100302 self.vapi.cli("show ip6 fib")
303 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
304 UDP(sport=1234, dport=1234))
305 p_ip6_fail = (IPv6(src="2002:DEAD:0202::1", dst=self.pg1.remote_ip6) /
306 UDP(sport=1234, dport=1234))
307
308 p = (Ether(src=self.pg0.remote_mac,
309 dst=self.pg0.local_mac) /
310 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
311 p_ip6)
312
313 p_reply = p_ip6
314
Ole Troan9a475372019-03-05 16:58:24 +0100315 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100316 for p in rx:
317 self.validate_4in6(p, p_reply)
318
319 p = (Ether(src=self.pg0.remote_mac,
320 dst=self.pg0.local_mac) /
321 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
322 p_ip6_fail)
Ole Troan9a475372019-03-05 16:58:24 +0100323 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700324 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100325
326 def test_6rd_bgp_tunnel(self):
327 """ 6rd BGP tunnel """
328
Ole Troan288e0932019-05-29 12:30:05 +0200329 rv = self.vapi.ipip_6rd_add_tunnel(ip6_table_id=0,
330 ip4_table_id=0,
331 ip6_prefix='2002::/16',
332 ip4_prefix='0.0.0.0/0',
333 ip4_src=self.pg0.local_ip4,
334 security_check=False)
335
Ole Troan6ee40512018-02-12 18:14:39 +0100336 self.tunnel_index = rv.sw_if_index
337
Neale Ranns097fa662018-05-01 05:17:55 -0700338 default_route = VppIpRoute(self, "DEAD::", 16,
339 [VppRoutePath("2002:0808:0808::",
340 self.tunnel_index)])
Ole Troan6ee40512018-02-12 18:14:39 +0100341 default_route.add_vpp_config()
342
343 ip4_route = VppIpRoute(self, "8.0.0.0", 8,
344 [VppRoutePath(self.pg1.remote_ip4, 0xFFFFFFFF)])
345 ip4_route.add_vpp_config()
346
347 # Via recursive route 6 -> 4
348 p = (Ether(src=self.pg0.remote_mac,
349 dst=self.pg0.local_mac) /
350 IPv6(src="1::1", dst="DEAD:BEEF::1") /
351 UDP(sport=1234, dport=1234))
352
353 p_reply = (IP(src=self.pg0.local_ip4, dst="8.8.8.8",
354 proto='ipv6') /
355 IPv6(src='1::1', dst='DEAD:BEEF::1', nh='UDP'))
356
Ole Troan9a475372019-03-05 16:58:24 +0100357 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100358 for p in rx:
359 self.validate_6in4(p, p_reply)
360
361 # Via recursive route 4 -> 6 (Security check must be disabled)
362 p_ip6 = (IPv6(src="DEAD:BEEF::1", dst=self.pg1.remote_ip6) /
363 UDP(sport=1234, dport=1234))
364 p = (Ether(src=self.pg0.remote_mac,
365 dst=self.pg0.local_mac) /
366 IP(src="8.8.8.8", dst=self.pg0.local_ip4) /
367 p_ip6)
368
369 p_reply = p_ip6
370
Ole Troan9a475372019-03-05 16:58:24 +0100371 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100372 for p in rx:
373 self.validate_4in6(p, p_reply)
Neale Ranns61502112018-08-22 00:21:14 -0700374 ip4_route.remove_vpp_config()
375 default_route.remove_vpp_config()
376 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100377
378
379if __name__ == '__main__':
380 unittest.main(testRunner=VppTestRunner)