c6b3c0885168afb48abb0d3fdeb344e9dcc1a382
[vpp.git] / test / test_sixrd.py
1 #!/usr/bin/env python
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_route import VppIpRoute, VppRoutePath, DpoProto
10 from socket import AF_INET, AF_INET6, inet_pton
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(2))
26         cls.interfaces = list(cls.pg_interfaces)
27
28     def setUp(cls):
29         super(Test6RD, cls).setUp()
30         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()
37
38     def tearDown(self):
39         super(Test6RD, self).tearDown()
40         if not self.vpp_dead:
41             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)
50
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
81         rv = self.vapi.ipip_6rd_add_tunnel(
82             0, inet_pton(AF_INET6, '2002::'), 16,
83             inet_pton(AF_INET, '0.0.0.0'), 0,
84             self.pg0.local_ip4n, True)
85         self.tunnel_index = rv.sw_if_index
86
87         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
112         rv = self.vapi.ipip_6rd_add_tunnel(
113             0, inet_pton(AF_INET6, '2002::'),
114             16, inet_pton(AF_INET, '0.0.0.0'),
115             0, self.pg0.local_ip4n, True)
116         self.tunnel_index = rv.sw_if_index
117         rv = self.vapi.ipip_6rd_del_tunnel(rv.sw_if_index)
118         rv = self.vapi.ipip_6rd_add_tunnel(
119             0, inet_pton(AF_INET6, '2002::'),
120             16, inet_pton(AF_INET, '0.0.0.0'),
121             0, self.pg0.local_ip4n, True)
122         self.tunnel_index = rv.sw_if_index
123
124         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 = []
142         rv = self.vapi.ipip_6rd_add_tunnel(
143             0, inet_pton(AF_INET6, '2002::'),
144             16, inet_pton(AF_INET, '0.0.0.0'),
145             0, self.pg0.local_ip4n, True)
146         self.tunnel_index.append(rv.sw_if_index)
147
148         rv = self.vapi.ipip_6rd_add_tunnel(
149             0, inet_pton(AF_INET6, '2003::'),
150             16, inet_pton(AF_INET, '0.0.0.0'),
151             0, self.pg1.local_ip4n, True)
152         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
175         rv = self.vapi.ipip_6rd_add_tunnel(
176             0, inet_pton(AF_INET6, '2002::'), 16,
177             inet_pton(AF_INET, '172.0.0.0'), 8,
178             self.pg0.local_ip4n, True)
179
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
196         rv = self.vapi.ipip_6rd_add_tunnel(
197             0, inet_pton(AF_INET6, '2002::'),
198             16, inet_pton(AF_INET, '0.0.0.0'),
199             0, self.pg0.local_ip4n, True)
200         self.tunnel_index = rv.sw_if_index
201
202         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
228         rv = self.vapi.ipip_6rd_add_tunnel(
229             0, inet_pton(AF_INET6, '2002::'),
230             16, inet_pton(AF_INET, '0.0.0.0'),
231             0, self.pg0.local_ip4n, False)
232         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
274 if __name__ == '__main__':
275     unittest.main(testRunner=VppTestRunner)