blob: ffd5864d5b3f35776a1e57b9dd8be19198178a67 [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
10from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
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
Neale Ranns61502112018-08-22 00:21:14 -070029 def setUp(self):
30 super(Test6RD, self).setUp()
31 t4 = VppIpTable(self, 10)
32 t6 = VppIpTable(self, 20, True)
33
34 t4.add_vpp_config()
35 t6.add_vpp_config()
36
37 for n in range(4):
38 i = self.pg_interfaces[n]
Ole Troan46c1c112018-03-14 20:39:40 +010039 i.admin_up()
Neale Ranns61502112018-08-22 00:21:14 -070040 if (n > 1):
41 i.set_table_ip4(10)
42 i.set_table_ip6(20)
Ole Troan46c1c112018-03-14 20:39:40 +010043 i.config_ip4()
44 i.config_ip6()
45 i.disable_ipv6_ra()
46 i.resolve_arp()
47 i.resolve_ndp()
Ole Troan6ee40512018-02-12 18:14:39 +010048
49 def tearDown(self):
Neale Ranns61502112018-08-22 00:21:14 -070050 for i in self.pg_interfaces:
51 i.unconfig_ip4()
52 i.unconfig_ip6()
53 i.set_table_ip4(0)
54 i.set_table_ip6(0)
Ole Troan6ee40512018-02-12 18:14:39 +010055 super(Test6RD, self).tearDown()
Ole Troan6ee40512018-02-12 18:14:39 +010056
57 def validate_6in4(self, rx, expected):
58 if IP not in rx:
59 self.fail()
60 if IPv6 not in rx:
61 self.fail()
62
63 self.assertEqual(rx[IP].src, expected[IP].src)
64 self.assertEqual(rx[IP].dst, expected[IP].dst)
65 self.assertEqual(rx[IP].proto, expected[IP].proto)
66 self.assertEqual(rx[IPv6].src, expected[IPv6].src)
67 self.assertEqual(rx[IPv6].dst, expected[IPv6].dst)
68
69 def validate_4in6(self, rx, expected):
70 if IPv6 not in rx:
71 self.fail()
72 if IP in rx:
73 self.fail()
74
Paul Vinciguerra3d2df212018-11-24 23:19:53 -080075 self.assertEqual(rx[IPv6].src, expected[IPv6].src)
76 self.assertEqual(rx[IPv6].dst, expected[IPv6].dst)
77 self.assertEqual(rx[IPv6].nh, expected[IPv6].nh)
Ole Troan6ee40512018-02-12 18:14:39 +010078
79 def payload(self, len):
80 return 'x' * len
81
82 def test_6rd_ip6_to_ip4(self):
83 """ ip6 -> ip4 (encap) 6rd test """
84 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
85 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1", nh='UDP')
86
Ole Troan9a475372019-03-05 16:58:24 +010087 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
88 inet_pton(AF_INET, '0.0.0.0'),
89 self.pg0.local_ip4n, 16, 0, True)
Ole Troan6ee40512018-02-12 18:14:39 +010090 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +010091
Ole Troan6ee40512018-02-12 18:14:39 +010092 self.vapi.cli("show ip6 fib")
93 p_payload = UDP(sport=1234, dport=1234)
94 p = (p_ether / p_ip6 / p_payload)
95
96 p_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
97 proto='ipv6') / p_ip6)
98
Ole Troan9a475372019-03-05 16:58:24 +010099 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100100 for p in rx:
101 self.validate_6in4(p, p_reply)
102
103 # MTU tests (default is 1480)
104 plen = 1481 - 40 - 8
105 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1")
106 p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
107 p = (p_ether / p_ip6 / p_payload)
108
109 p_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
110 proto='ipv6') / p_ip6)
111
Ole Troan9a475372019-03-05 16:58:24 +0100112 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700113 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
114
115 def test_6rd_ip6_to_ip4_vrf(self):
116 """ ip6 -> ip4 (encap) 6rd VRF test """
117 p_ether = Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac)
118 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1", nh='UDP')
119
Ole Troan9a475372019-03-05 16:58:24 +0100120 rv = self.vapi.ipip_6rd_add_tunnel(20, 10,
121 inet_pton(AF_INET6, '2002::'),
122 inet_pton(AF_INET, '0.0.0.0'),
123 self.pg2.local_ip4n, 16, 0, True)
Neale Ranns61502112018-08-22 00:21:14 -0700124 self.tunnel_index = rv.sw_if_index
125
126 self.vapi.cli("show ip6 fib")
127 p_payload = UDP(sport=1234, dport=1234)
128 p = (p_ether / p_ip6 / p_payload)
129
130 p_reply = (IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4,
131 proto='ipv6') / p_ip6)
132
Ole Troan9a475372019-03-05 16:58:24 +0100133 rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
Neale Ranns61502112018-08-22 00:21:14 -0700134 for p in rx:
135 self.validate_6in4(p, p_reply)
136
137 # MTU tests (default is 1480)
138 plen = 1481 - 40 - 8
139 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0402::1")
140 p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
141 p = (p_ether / p_ip6 / p_payload)
142
143 p_reply = (IP(src=self.pg2.local_ip4, dst=self.pg3.remote_ip4,
144 proto='ipv6') / p_ip6)
145
Ole Troan9a475372019-03-05 16:58:24 +0100146 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700147 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100148
149 def test_6rd_ip4_to_ip6(self):
150 """ ip4 -> ip6 (decap) 6rd test """
151
Ole Troan9a475372019-03-05 16:58:24 +0100152 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
153 inet_pton(AF_INET, '0.0.0.0'),
154 self.pg0.local_ip4n, 16, 0, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100155 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100156 rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
Ole Troan9a475372019-03-05 16:58:24 +0100157 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
158 inet_pton(AF_INET, '0.0.0.0'),
159 self.pg0.local_ip4n, 16, 0, True)
Ole Troan298c6952018-03-08 12:30:43 +0100160 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100161
Ole Troan6ee40512018-02-12 18:14:39 +0100162 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
163 UDP(sport=1234, dport=1234))
164
165 p = (Ether(src=self.pg0.remote_mac,
166 dst=self.pg0.local_mac) /
167 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
168 p_ip6)
169
170 p_reply = p_ip6
171
Ole Troan9a475372019-03-05 16:58:24 +0100172 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100173 for p in rx:
174 self.validate_4in6(p, p_reply)
Neale Ranns61502112018-08-22 00:21:14 -0700175 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
176
177 def test_6rd_ip4_to_ip6_vrf(self):
178 """ ip4 -> ip6 (decap) 6rd VRF test """
179
Ole Troan9a475372019-03-05 16:58:24 +0100180 rv = self.vapi.ipip_6rd_add_tunnel(20, 10,
181 inet_pton(AF_INET6, '2002::'),
182 inet_pton(AF_INET, '0.0.0.0'),
183 self.pg2.local_ip4n, 16, 0, True)
Neale Ranns61502112018-08-22 00:21:14 -0700184 self.tunnel_index = rv.sw_if_index
185 rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
Ole Troan9a475372019-03-05 16:58:24 +0100186 rv = self.vapi.ipip_6rd_add_tunnel(20, 10,
187 inet_pton(AF_INET6, '2002::'),
188 inet_pton(AF_INET, '0.0.0.0'),
189 self.pg2.local_ip4n, 16, 0, True)
Neale Ranns61502112018-08-22 00:21:14 -0700190 self.tunnel_index = rv.sw_if_index
191 self.vapi.sw_interface_set_table(self.tunnel_index, 1, 20)
192
193 p_ip6 = (IPv6(src="2002:AC10:0402::1", dst=self.pg3.remote_ip6) /
194 UDP(sport=1234, dport=1234))
195
196 p = (Ether(src=self.pg2.remote_mac,
197 dst=self.pg2.local_mac) /
198 IP(src=self.pg3.remote_ip4, dst=self.pg2.local_ip4) /
199 p_ip6)
200
201 p_reply = p_ip6
202
Ole Troan9a475372019-03-05 16:58:24 +0100203 rx = self.send_and_expect(self.pg2, p * 10, self.pg3)
Neale Ranns61502112018-08-22 00:21:14 -0700204 for p in rx:
205 self.validate_4in6(p, p_reply)
206 self.vapi.sw_interface_set_table(self.tunnel_index, 1, 0)
207 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100208
209 def test_6rd_ip4_to_ip6_multiple(self):
210 """ ip4 -> ip6 (decap) 6rd test """
211
212 self.tunnel_index = []
Ole Troan9a475372019-03-05 16:58:24 +0100213 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
214 inet_pton(AF_INET, '0.0.0.0'),
215 self.pg0.local_ip4n, 16, 0, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100216 self.tunnel_index.append(rv.sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100217
Ole Troan9a475372019-03-05 16:58:24 +0100218 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2003::'),
219 inet_pton(AF_INET, '0.0.0.0'),
220 self.pg1.local_ip4n, 16, 0, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100221 self.tunnel_index.append(rv.sw_if_index)
222
223 self.vapi.cli("show ip6 fib")
224 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
225 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
226 p_ip6_1 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
227 UDP(sport=1234, dport=1234))
228 p_ip6_2 = (IPv6(src="2003:AC10:0202::1", dst=self.pg1.remote_ip6) /
229 UDP(sport=1234, dport=1234))
230
231 p = (p_ether / p_ip4 / p_ip6_1)
Ole Troan9a475372019-03-05 16:58:24 +0100232 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100233 for p in rx:
234 self.validate_4in6(p, p_ip6_1)
235
236 p = (p_ether / p_ip4 / p_ip6_2)
Ole Troan9a475372019-03-05 16:58:24 +0100237 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100238 for p in rx:
239 self.validate_4in6(p, p_ip6_2)
Neale Ranns61502112018-08-22 00:21:14 -0700240 for i in self.tunnel_index:
241 self.vapi.ipip_6rd_del_tunnel(i)
Ole Troan6ee40512018-02-12 18:14:39 +0100242
243 def test_6rd_ip4_to_ip6_suffix(self):
244 """ ip4 -> ip6 (decap) 6rd test """
245
Ole Troan9a475372019-03-05 16:58:24 +0100246 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
247 inet_pton(AF_INET, '172.0.0.0'),
248 self.pg0.local_ip4n, 16, 8, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100249
250 self.tunnel_index = rv.sw_if_index
251
252 self.vapi.cli("show ip6 fib")
253 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
254 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
255 p_ip6 = (IPv6(src="2002:1002:0200::1", dst=self.pg1.remote_ip6) /
256 UDP(sport=1234, dport=1234))
257
258 p = (p_ether / p_ip4 / p_ip6)
Ole Troan9a475372019-03-05 16:58:24 +0100259 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100260 for p in rx:
261 self.validate_4in6(p, p_ip6)
Neale Ranns61502112018-08-22 00:21:14 -0700262 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100263
264 def test_6rd_ip4_to_ip6_sec_check(self):
265 """ ip4 -> ip6 (decap) security check 6rd test """
266
Ole Troan9a475372019-03-05 16:58:24 +0100267 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
268 inet_pton(AF_INET, '0.0.0.0'),
269 self.pg0.local_ip4n, 16, 0, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100270 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100271
Ole Troan6ee40512018-02-12 18:14:39 +0100272 self.vapi.cli("show ip6 fib")
273 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
274 UDP(sport=1234, dport=1234))
275 p_ip6_fail = (IPv6(src="2002:DEAD:0202::1", dst=self.pg1.remote_ip6) /
276 UDP(sport=1234, dport=1234))
277
278 p = (Ether(src=self.pg0.remote_mac,
279 dst=self.pg0.local_mac) /
280 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
281 p_ip6)
282
283 p_reply = p_ip6
284
Ole Troan9a475372019-03-05 16:58:24 +0100285 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100286 for p in rx:
287 self.validate_4in6(p, p_reply)
288
289 p = (Ether(src=self.pg0.remote_mac,
290 dst=self.pg0.local_mac) /
291 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
292 p_ip6_fail)
Ole Troan9a475372019-03-05 16:58:24 +0100293 rx = self.send_and_assert_no_replies(self.pg0, p * 10)
Neale Ranns61502112018-08-22 00:21:14 -0700294 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100295
296 def test_6rd_bgp_tunnel(self):
297 """ 6rd BGP tunnel """
298
Ole Troan9a475372019-03-05 16:58:24 +0100299 rv = self.vapi.ipip_6rd_add_tunnel(0, 0, inet_pton(AF_INET6, '2002::'),
300 inet_pton(AF_INET, '0.0.0.0'),
301 self.pg0.local_ip4n, 16, 0, False)
Ole Troan6ee40512018-02-12 18:14:39 +0100302 self.tunnel_index = rv.sw_if_index
303
304 default_route = VppIpRoute(
305 self, "DEAD::", 16, [VppRoutePath("2002:0808:0808::",
306 self.tunnel_index,
307 proto=DpoProto.DPO_PROTO_IP6)],
308 is_ip6=1)
309 default_route.add_vpp_config()
310
311 ip4_route = VppIpRoute(self, "8.0.0.0", 8,
312 [VppRoutePath(self.pg1.remote_ip4, 0xFFFFFFFF)])
313 ip4_route.add_vpp_config()
314
315 # Via recursive route 6 -> 4
316 p = (Ether(src=self.pg0.remote_mac,
317 dst=self.pg0.local_mac) /
318 IPv6(src="1::1", dst="DEAD:BEEF::1") /
319 UDP(sport=1234, dport=1234))
320
321 p_reply = (IP(src=self.pg0.local_ip4, dst="8.8.8.8",
322 proto='ipv6') /
323 IPv6(src='1::1', dst='DEAD:BEEF::1', nh='UDP'))
324
Ole Troan9a475372019-03-05 16:58:24 +0100325 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100326 for p in rx:
327 self.validate_6in4(p, p_reply)
328
329 # Via recursive route 4 -> 6 (Security check must be disabled)
330 p_ip6 = (IPv6(src="DEAD:BEEF::1", dst=self.pg1.remote_ip6) /
331 UDP(sport=1234, dport=1234))
332 p = (Ether(src=self.pg0.remote_mac,
333 dst=self.pg0.local_mac) /
334 IP(src="8.8.8.8", dst=self.pg0.local_ip4) /
335 p_ip6)
336
337 p_reply = p_ip6
338
Ole Troan9a475372019-03-05 16:58:24 +0100339 rx = self.send_and_expect(self.pg0, p * 10, self.pg1)
Ole Troan6ee40512018-02-12 18:14:39 +0100340 for p in rx:
341 self.validate_4in6(p, p_reply)
Neale Ranns61502112018-08-22 00:21:14 -0700342 ip4_route.remove_vpp_config()
343 default_route.remove_vpp_config()
344 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +0100345
346
347if __name__ == '__main__':
348 unittest.main(testRunner=VppTestRunner)