blob: c6b3c0885168afb48abb0d3fdeb344e9dcc1a382 [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
Ole Troan6ee40512018-02-12 18:14:39 +01009from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto
Ole Troan46c1c112018-03-14 20:39:40 +010010from socket import AF_INET, AF_INET6, inet_pton
Ole Troan6ee40512018-02-12 18:14:39 +010011
12""" Test6rd is a subclass of VPPTestCase classes.
13
146RD tests.
15
16"""
17
18
19class Test6RD(VppTestCase):
20 """ 6RD Test Case """
21
22 @classmethod
23 def setUpClass(cls):
24 super(Test6RD, cls).setUpClass()
Ole Troan46c1c112018-03-14 20:39:40 +010025 cls.create_pg_interfaces(range(2))
26 cls.interfaces = list(cls.pg_interfaces)
Ole Troan6ee40512018-02-12 18:14:39 +010027
28 def setUp(cls):
29 super(Test6RD, cls).setUp()
Ole Troan46c1c112018-03-14 20:39:40 +010030 for i in cls.interfaces:
31 i.admin_up()
32 i.config_ip4()
33 i.config_ip6()
34 i.disable_ipv6_ra()
35 i.resolve_arp()
36 i.resolve_ndp()
Ole Troan6ee40512018-02-12 18:14:39 +010037
38 def tearDown(self):
39 super(Test6RD, self).tearDown()
40 if not self.vpp_dead:
Ole Troan46c1c112018-03-14 20:39:40 +010041 for i in self.pg_interfaces:
42 i.unconfig_ip4()
43 i.unconfig_ip6()
44 i.admin_down()
45 if type(self.tunnel_index) is list:
46 for sw_if_index in self.tunnel_index:
47 self.vapi.ipip_6rd_del_tunnel(sw_if_index)
48 else:
49 self.vapi.ipip_6rd_del_tunnel(self.tunnel_index)
Ole Troan6ee40512018-02-12 18:14:39 +010050
51 def validate_6in4(self, rx, expected):
52 if IP not in rx:
53 self.fail()
54 if IPv6 not in rx:
55 self.fail()
56
57 self.assertEqual(rx[IP].src, expected[IP].src)
58 self.assertEqual(rx[IP].dst, expected[IP].dst)
59 self.assertEqual(rx[IP].proto, expected[IP].proto)
60 self.assertEqual(rx[IPv6].src, expected[IPv6].src)
61 self.assertEqual(rx[IPv6].dst, expected[IPv6].dst)
62
63 def validate_4in6(self, rx, expected):
64 if IPv6 not in rx:
65 self.fail()
66 if IP in rx:
67 self.fail()
68
69 self.assertTrue(rx[IPv6].src == expected[IPv6].src)
70 self.assertTrue(rx[IPv6].dst == expected[IPv6].dst)
71 self.assertTrue(rx[IPv6].nh == expected[IPv6].nh)
72
73 def payload(self, len):
74 return 'x' * len
75
76 def test_6rd_ip6_to_ip4(self):
77 """ ip6 -> ip4 (encap) 6rd test """
78 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
79 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1", nh='UDP')
80
Ole Troan298c6952018-03-08 12:30:43 +010081 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +010082 0, inet_pton(AF_INET6, '2002::'), 16,
83 inet_pton(AF_INET, '0.0.0.0'), 0,
84 self.pg0.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +010085 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +010086
Ole Troan6ee40512018-02-12 18:14:39 +010087 self.vapi.cli("show ip6 fib")
88 p_payload = UDP(sport=1234, dport=1234)
89 p = (p_ether / p_ip6 / p_payload)
90
91 p_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
92 proto='ipv6') / p_ip6)
93
94 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
95 for p in rx:
96 self.validate_6in4(p, p_reply)
97
98 # MTU tests (default is 1480)
99 plen = 1481 - 40 - 8
100 p_ip6 = IPv6(src="1::1", dst="2002:AC10:0202::1")
101 p_payload = UDP(sport=1234, dport=1234) / Raw(self.payload(plen))
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
107 rx = self.send_and_assert_no_replies(self.pg0, p*10)
108
109 def test_6rd_ip4_to_ip6(self):
110 """ ip4 -> ip6 (decap) 6rd test """
111
Ole Troan298c6952018-03-08 12:30:43 +0100112 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100113 0, inet_pton(AF_INET6, '2002::'),
114 16, inet_pton(AF_INET, '0.0.0.0'),
115 0, self.pg0.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100116 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100117 rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100118 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100119 0, inet_pton(AF_INET6, '2002::'),
120 16, inet_pton(AF_INET, '0.0.0.0'),
121 0, self.pg0.local_ip4n, True)
Ole Troan298c6952018-03-08 12:30:43 +0100122 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100123
Ole Troan6ee40512018-02-12 18:14:39 +0100124 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
125 UDP(sport=1234, dport=1234))
126
127 p = (Ether(src=self.pg0.remote_mac,
128 dst=self.pg0.local_mac) /
129 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
130 p_ip6)
131
132 p_reply = p_ip6
133
134 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
135 for p in rx:
136 self.validate_4in6(p, p_reply)
137
138 def test_6rd_ip4_to_ip6_multiple(self):
139 """ ip4 -> ip6 (decap) 6rd test """
140
141 self.tunnel_index = []
Ole Troan298c6952018-03-08 12:30:43 +0100142 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100143 0, inet_pton(AF_INET6, '2002::'),
144 16, inet_pton(AF_INET, '0.0.0.0'),
145 0, self.pg0.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100146 self.tunnel_index.append(rv.sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100147
148 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100149 0, inet_pton(AF_INET6, '2003::'),
150 16, inet_pton(AF_INET, '0.0.0.0'),
151 0, self.pg1.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100152 self.tunnel_index.append(rv.sw_if_index)
153
154 self.vapi.cli("show ip6 fib")
155 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
156 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
157 p_ip6_1 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
158 UDP(sport=1234, dport=1234))
159 p_ip6_2 = (IPv6(src="2003:AC10:0202::1", dst=self.pg1.remote_ip6) /
160 UDP(sport=1234, dport=1234))
161
162 p = (p_ether / p_ip4 / p_ip6_1)
163 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
164 for p in rx:
165 self.validate_4in6(p, p_ip6_1)
166
167 p = (p_ether / p_ip4 / p_ip6_2)
168 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
169 for p in rx:
170 self.validate_4in6(p, p_ip6_2)
171
172 def test_6rd_ip4_to_ip6_suffix(self):
173 """ ip4 -> ip6 (decap) 6rd test """
174
Ole Troan298c6952018-03-08 12:30:43 +0100175 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100176 0, inet_pton(AF_INET6, '2002::'), 16,
177 inet_pton(AF_INET, '172.0.0.0'), 8,
178 self.pg0.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100179
180 self.tunnel_index = rv.sw_if_index
181
182 self.vapi.cli("show ip6 fib")
183 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
184 p_ip4 = IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4)
185 p_ip6 = (IPv6(src="2002:1002:0200::1", dst=self.pg1.remote_ip6) /
186 UDP(sport=1234, dport=1234))
187
188 p = (p_ether / p_ip4 / p_ip6)
189 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
190 for p in rx:
191 self.validate_4in6(p, p_ip6)
192
193 def test_6rd_ip4_to_ip6_sec_check(self):
194 """ ip4 -> ip6 (decap) security check 6rd test """
195
Ole Troan298c6952018-03-08 12:30:43 +0100196 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100197 0, inet_pton(AF_INET6, '2002::'),
198 16, inet_pton(AF_INET, '0.0.0.0'),
199 0, self.pg0.local_ip4n, True)
Ole Troan6ee40512018-02-12 18:14:39 +0100200 self.tunnel_index = rv.sw_if_index
Ole Troan298c6952018-03-08 12:30:43 +0100201
Ole Troan6ee40512018-02-12 18:14:39 +0100202 self.vapi.cli("show ip6 fib")
203 p_ip6 = (IPv6(src="2002:AC10:0202::1", dst=self.pg1.remote_ip6) /
204 UDP(sport=1234, dport=1234))
205 p_ip6_fail = (IPv6(src="2002:DEAD:0202::1", dst=self.pg1.remote_ip6) /
206 UDP(sport=1234, dport=1234))
207
208 p = (Ether(src=self.pg0.remote_mac,
209 dst=self.pg0.local_mac) /
210 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
211 p_ip6)
212
213 p_reply = p_ip6
214
215 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
216 for p in rx:
217 self.validate_4in6(p, p_reply)
218
219 p = (Ether(src=self.pg0.remote_mac,
220 dst=self.pg0.local_mac) /
221 IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
222 p_ip6_fail)
223 rx = self.send_and_assert_no_replies(self.pg0, p*10)
224
225 def test_6rd_bgp_tunnel(self):
226 """ 6rd BGP tunnel """
227
Ole Troan298c6952018-03-08 12:30:43 +0100228 rv = self.vapi.ipip_6rd_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100229 0, inet_pton(AF_INET6, '2002::'),
230 16, inet_pton(AF_INET, '0.0.0.0'),
231 0, self.pg0.local_ip4n, False)
Ole Troan6ee40512018-02-12 18:14:39 +0100232 self.tunnel_index = rv.sw_if_index
233
234 default_route = VppIpRoute(
235 self, "DEAD::", 16, [VppRoutePath("2002:0808:0808::",
236 self.tunnel_index,
237 proto=DpoProto.DPO_PROTO_IP6)],
238 is_ip6=1)
239 default_route.add_vpp_config()
240
241 ip4_route = VppIpRoute(self, "8.0.0.0", 8,
242 [VppRoutePath(self.pg1.remote_ip4, 0xFFFFFFFF)])
243 ip4_route.add_vpp_config()
244
245 # Via recursive route 6 -> 4
246 p = (Ether(src=self.pg0.remote_mac,
247 dst=self.pg0.local_mac) /
248 IPv6(src="1::1", dst="DEAD:BEEF::1") /
249 UDP(sport=1234, dport=1234))
250
251 p_reply = (IP(src=self.pg0.local_ip4, dst="8.8.8.8",
252 proto='ipv6') /
253 IPv6(src='1::1', dst='DEAD:BEEF::1', nh='UDP'))
254
255 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
256 for p in rx:
257 self.validate_6in4(p, p_reply)
258
259 # Via recursive route 4 -> 6 (Security check must be disabled)
260 p_ip6 = (IPv6(src="DEAD:BEEF::1", dst=self.pg1.remote_ip6) /
261 UDP(sport=1234, dport=1234))
262 p = (Ether(src=self.pg0.remote_mac,
263 dst=self.pg0.local_mac) /
264 IP(src="8.8.8.8", dst=self.pg0.local_ip4) /
265 p_ip6)
266
267 p_reply = p_ip6
268
269 rx = self.send_and_expect(self.pg0, p*10, self.pg1)
270 for p in rx:
271 self.validate_4in6(p, p_reply)
272
273
274if __name__ == '__main__':
275 unittest.main(testRunner=VppTestRunner)