blob: 989330faa6f53f7cb016137f0663efffb4e4eb6f [file] [log] [blame]
Ole Troan46c1c112018-03-14 20:39:40 +01001#!/usr/bin/env python
2"""IP{4,6} over IP{v,6} tunnel functional tests"""
Ole Troan298c6952018-03-08 12:30:43 +01003
4import unittest
Ole Troan282093f2018-09-19 12:38:51 +02005from scapy.layers.inet6 import IPv6, Ether, IP, UDP, IPv6ExtHdrFragment
6from scapy.all import fragment, fragment6, RandShort, defragment6
Ole Troan46c1c112018-03-14 20:39:40 +01007from framework import VppTestCase, VppTestRunner
Neale Rannsc0a93142018-09-05 15:42:26 -07008from vpp_ip import DpoProto
9from vpp_ip_route import VppIpRoute, VppRoutePath, VppIpTable
Ole Troan46c1c112018-03-14 20:39:40 +010010from socket import AF_INET, AF_INET6, inet_pton
Ole Troan4146c652018-08-08 22:23:19 +020011import StringIO
Ole Troan298c6952018-03-08 12:30:43 +010012
13""" Testipip is a subclass of VPPTestCase classes.
14
15IPIP tests.
16
17"""
18
19
Ole Troan282093f2018-09-19 12:38:51 +020020# Replace by deframent from scapy.
Ole Troan4146c652018-08-08 22:23:19 +020021def reassemble(listoffragments):
22 buffer = StringIO.StringIO()
23 first = listoffragments[0]
24 buffer.seek(20)
25 for pkt in listoffragments:
26 buffer.seek(pkt[IP].frag*8)
27 buffer.write(pkt[IP].payload)
28 first.len = len(buffer.getvalue()) + 20
29 first.flags = 0
30 del(first.chksum)
31 header = str(first[IP])[:20]
32 return first[IP].__class__(header + buffer.getvalue())
33
34
Ole Troan298c6952018-03-08 12:30:43 +010035class TestIPIP(VppTestCase):
36 """ IPIP Test Case """
37
38 @classmethod
39 def setUpClass(cls):
40 super(TestIPIP, cls).setUpClass()
Ole Troan46c1c112018-03-14 20:39:40 +010041 cls.create_pg_interfaces(range(2))
42 cls.interfaces = list(cls.pg_interfaces)
Ole Troan298c6952018-03-08 12:30:43 +010043
Paul Vinciguerra741865b2018-11-27 06:01:22 -080044 def setUp(self):
45 super(TestIPIP, self).setUp()
46 for i in self.interfaces:
Ole Troan46c1c112018-03-14 20:39:40 +010047 i.admin_up()
48 i.config_ip4()
49 i.config_ip6()
50 i.disable_ipv6_ra()
51 i.resolve_arp()
52 i.resolve_ndp()
Ole Troan298c6952018-03-08 12:30:43 +010053
54 def tearDown(self):
55 super(TestIPIP, self).tearDown()
56 if not self.vpp_dead:
Ole Troan46c1c112018-03-14 20:39:40 +010057 for i in self.pg_interfaces:
58 i.unconfig_ip4()
59 i.unconfig_ip6()
60 i.admin_down()
Ole Troan298c6952018-03-08 12:30:43 +010061
62 def validate(self, rx, expected):
Ole Troan46c1c112018-03-14 20:39:40 +010063 self.assertEqual(rx, expected.__class__(str(expected)))
Ole Troan298c6952018-03-08 12:30:43 +010064
Ole Troan282093f2018-09-19 12:38:51 +020065 def generate_ip4_frags(self, payload_length, fragment_size):
Ole Troan7eb9d962018-08-10 14:39:48 +020066 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
67 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
68 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
69 outer_ip4 = (p_ether / IP(src=self.pg1.remote_ip4,
70 id=RandShort(),
71 dst=self.pg0.local_ip4) / p_ip4 / p_payload)
72 frags = fragment(outer_ip4, fragment_size)
73 p4_reply = (p_ip4 / p_payload)
74 p4_reply.ttl -= 1
75 return frags, p4_reply
76
Ole Troan298c6952018-03-08 12:30:43 +010077 def test_ipip4(self):
78 """ ip{v4,v6} over ip4 test """
79 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
Ole Troand57f6362018-05-24 13:21:43 +020080 p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42)
81 p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
Damjan Marionfe7d4a22018-04-13 19:43:39 +020082 p_payload = UDP(sport=1234, dport=1234)
Ole Troan298c6952018-03-08 12:30:43 +010083
84 # IPv4 transport
85 rv = self.vapi.ipip_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +010086 src_address=self.pg0.local_ip4n,
87 dst_address=self.pg1.remote_ip4n,
Ole Troand57f6362018-05-24 13:21:43 +020088 is_ipv6=0, tc_tos=0xFF)
Ole Troan298c6952018-03-08 12:30:43 +010089 sw_if_index = rv.sw_if_index
90
91 # Set interface up and enable IP on it
Ole Troan46c1c112018-03-14 20:39:40 +010092 self.vapi.sw_interface_set_flags(sw_if_index, 1)
93 self.vapi.sw_interface_set_unnumbered(
Ole Troan298c6952018-03-08 12:30:43 +010094 ip_sw_if_index=self.pg0.sw_if_index,
95 sw_if_index=sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +010096
97 # Add IPv4 and IPv6 routes via tunnel interface
98 ip4_via_tunnel = VppIpRoute(
99 self, "130.67.0.0", 16,
100 [VppRoutePath("0.0.0.0",
101 sw_if_index,
102 proto=DpoProto.DPO_PROTO_IP4)], is_ip6=0)
103 ip4_via_tunnel.add_vpp_config()
104
105 ip6_via_tunnel = VppIpRoute(
106 self, "dead::", 16,
107 [VppRoutePath("::",
108 sw_if_index,
109 proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1)
110 ip6_via_tunnel.add_vpp_config()
111
112 # IPv6 in to IPv4 tunnel
113 p6 = (p_ether / p_ip6 / p_payload)
114 p_inner_ip6 = p_ip6
115 p_inner_ip6.hlim -= 1
116 p6_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
Ole Troand57f6362018-05-24 13:21:43 +0200117 proto='ipv6', id=0, tos=42) / p_inner_ip6 / p_payload)
Ole Troan298c6952018-03-08 12:30:43 +0100118 p6_reply.ttl -= 1
119 rx = self.send_and_expect(self.pg0, p6*10, self.pg1)
120 for p in rx:
121 self.validate(p[1], p6_reply)
122
123 # IPv4 in to IPv4 tunnel
124 p4 = (p_ether / p_ip4 / p_payload)
125 p_ip4_inner = p_ip4
126 p_ip4_inner.ttl -= 1
Ole Troand57f6362018-05-24 13:21:43 +0200127 p4_reply = (IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4,
128 tos=42) /
129 p_ip4_inner / p_payload)
Ole Troan298c6952018-03-08 12:30:43 +0100130 p4_reply.ttl -= 1
131 p4_reply.id = 0
Damjan Marionfe7d4a22018-04-13 19:43:39 +0200132 rx = self.send_and_expect(self.pg0, p4*10, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100133 for p in rx:
134 self.validate(p[1], p4_reply)
135
136 # Decapsulation
137 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
138
139 # IPv4 tunnel to IPv4
140 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
141 p4 = (p_ether / IP(src=self.pg1.remote_ip4,
142 dst=self.pg0.local_ip4) / p_ip4 / p_payload)
143 p4_reply = (p_ip4 / p_payload)
144 p4_reply.ttl -= 1
145 rx = self.send_and_expect(self.pg1, p4*10, self.pg0)
146 for p in rx:
147 self.validate(p[1], p4_reply)
148
Ole Troan58492a82018-09-04 13:19:12 +0200149 err = self.statistics.get_counter(
150 '/err/ipip4-input/packets decapsulated')
151 self.assertEqual(err, 10)
Ole Troan73202102018-08-31 00:29:48 +0200152
Ole Troan298c6952018-03-08 12:30:43 +0100153 # IPv4 tunnel to IPv6
154 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
155 p6 = (p_ether / IP(src=self.pg1.remote_ip4,
156 dst=self.pg0.local_ip4) / p_ip6 / p_payload)
157 p6_reply = (p_ip6 / p_payload)
158 p6_reply.hlim = 63
159 rx = self.send_and_expect(self.pg1, p6*10, self.pg0)
160 for p in rx:
161 self.validate(p[1], p6_reply)
162
Ole Troan58492a82018-09-04 13:19:12 +0200163 err = self.statistics.get_counter(
164 '/err/ipip4-input/packets decapsulated')
165 self.assertEqual(err, 20)
Ole Troan73202102018-08-31 00:29:48 +0200166
Ole Troan7eb9d962018-08-10 14:39:48 +0200167 #
Ole Troan4146c652018-08-08 22:23:19 +0200168 # Fragmentation / Reassembly and Re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200169 #
Ole Troan4146c652018-08-08 22:23:19 +0200170 rv = self.vapi.ip_reassembly_enable_disable(
171 sw_if_index=self.pg1.sw_if_index,
172 enable_ip4=1)
Ole Troan4146c652018-08-08 22:23:19 +0200173
Ole Troan7eb9d962018-08-10 14:39:48 +0200174 # Send lots of fragments, verify reassembled packet
Ole Troan282093f2018-09-19 12:38:51 +0200175 frags, p4_reply = self.generate_ip4_frags(3131, 1400)
Ole Troan7eb9d962018-08-10 14:39:48 +0200176 f = []
177 for i in range(0, 1000):
178 f.extend(frags)
179 self.pg1.add_stream(f)
Ole Troan4146c652018-08-08 22:23:19 +0200180 self.pg_enable_capture()
Ole Troan4146c652018-08-08 22:23:19 +0200181 self.pg_start()
Ole Troan7eb9d962018-08-10 14:39:48 +0200182 rx = self.pg0.get_capture(1000)
183
Ole Troan4146c652018-08-08 22:23:19 +0200184 for p in rx:
185 self.validate(p[1], p4_reply)
186
Ole Troan58492a82018-09-04 13:19:12 +0200187 err = self.statistics.get_counter(
188 '/err/ipip4-input/packets decapsulated')
189 self.assertEqual(err, 1020)
Ole Troan73202102018-08-31 00:29:48 +0200190
Ole Troan7eb9d962018-08-10 14:39:48 +0200191 f = []
192 r = []
193 for i in range(1, 90):
Ole Troan282093f2018-09-19 12:38:51 +0200194 frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
Ole Troan7eb9d962018-08-10 14:39:48 +0200195 f.extend(frags)
196 r.extend(p4_reply)
197 self.pg_enable_capture()
198 self.pg1.add_stream(f)
199 self.pg_start()
200 rx = self.pg0.get_capture(89)
201 i = 0
202 for p in rx:
203 self.validate(p[1], r[i])
204 i += 1
205
Ole Troan4146c652018-08-08 22:23:19 +0200206 # Now try with re-fragmentation
Ole Troan7eb9d962018-08-10 14:39:48 +0200207 #
208 # Send fragments to tunnel head-end, for the tunnel head end
209 # to reassemble and then refragment
210 #
Ole Troan4146c652018-08-08 22:23:19 +0200211 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200212 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan4146c652018-08-08 22:23:19 +0200213 self.pg_enable_capture()
214 self.pg1.add_stream(frags)
215 self.pg_start()
216 rx = self.pg0.get_capture(6)
217 reass_pkt = reassemble(rx)
218 p4_reply.ttl -= 1
219 p4_reply.id = 256
220 self.validate(reass_pkt, p4_reply)
221
Ole Troan7eb9d962018-08-10 14:39:48 +0200222 self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
Ole Troan282093f2018-09-19 12:38:51 +0200223 frags, p4_reply = self.generate_ip4_frags(3123, 1200)
Ole Troan7eb9d962018-08-10 14:39:48 +0200224 self.pg_enable_capture()
225 self.pg1.add_stream(frags)
226 self.pg_start()
227 rx = self.pg0.get_capture(2)
228 reass_pkt = reassemble(rx)
229 p4_reply.ttl -= 1
230 p4_reply.id = 512
231 self.validate(reass_pkt, p4_reply)
232
Ole Troan282093f2018-09-19 12:38:51 +0200233 def test_ipip_create(self):
234 """ ipip create / delete interface test """
235 rv = self.vapi.ipip_add_tunnel(
236 src_address=inet_pton(AF_INET, '1.2.3.4'),
237 dst_address=inet_pton(AF_INET, '2.3.4.5'), is_ipv6=0)
238 sw_if_index = rv.sw_if_index
239 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100240
Ole Troan282093f2018-09-19 12:38:51 +0200241 def test_ipip_vrf_create(self):
242 """ ipip create / delete interface VRF test """
243
244 t = VppIpTable(self, 20)
245 t.add_vpp_config()
246 rv = self.vapi.ipip_add_tunnel(
247 src_address=inet_pton(AF_INET, '1.2.3.4'),
248 dst_address=inet_pton(AF_INET, '2.3.4.5'), is_ipv6=0,
249 table_id=20)
250 sw_if_index = rv.sw_if_index
251 self.vapi.ipip_del_tunnel(sw_if_index)
252
253 def payload(self, len):
254 return 'x' * len
255
256
257class TestIPIP6(VppTestCase):
258 """ IPIP6 Test Case """
259
260 @classmethod
261 def setUpClass(cls):
262 super(TestIPIP6, cls).setUpClass()
263 cls.create_pg_interfaces(range(2))
264 cls.interfaces = list(cls.pg_interfaces)
265
266 def setUp(self):
267 for i in self.interfaces:
268 i.admin_up()
269 i.config_ip4()
270 i.config_ip6()
271 i.disable_ipv6_ra()
272 i.resolve_arp()
273 i.resolve_ndp()
274 self.setup_tunnel()
275
276 def tearDown(self):
277 if not self.vpp_dead:
278 self.destroy_tunnel()
279 for i in self.pg_interfaces:
280 i.unconfig_ip4()
281 i.unconfig_ip6()
282 i.admin_down()
283 super(TestIPIP6, self).tearDown()
284
285 def setup_tunnel(self):
Ole Troan298c6952018-03-08 12:30:43 +0100286 # IPv6 transport
287 rv = self.vapi.ipip_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100288 src_address=self.pg0.local_ip6n,
Ole Troand57f6362018-05-24 13:21:43 +0200289 dst_address=self.pg1.remote_ip6n, tc_tos=255)
Ole Troan298c6952018-03-08 12:30:43 +0100290
291 sw_if_index = rv.sw_if_index
Ole Troan282093f2018-09-19 12:38:51 +0200292 self.tunnel_if_index = sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +0100293 self.vapi.sw_interface_set_flags(sw_if_index, 1)
294 self.vapi.sw_interface_set_unnumbered(
Ole Troan298c6952018-03-08 12:30:43 +0100295 ip_sw_if_index=self.pg0.sw_if_index, sw_if_index=sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100296
297 # Add IPv4 and IPv6 routes via tunnel interface
298 ip4_via_tunnel = VppIpRoute(
299 self, "130.67.0.0", 16,
300 [VppRoutePath("0.0.0.0",
301 sw_if_index,
302 proto=DpoProto.DPO_PROTO_IP4)], is_ip6=0)
303 ip4_via_tunnel.add_vpp_config()
304
305 ip6_via_tunnel = VppIpRoute(
306 self, "dead::", 16,
307 [VppRoutePath("::",
308 sw_if_index,
309 proto=DpoProto.DPO_PROTO_IP6)], is_ip6=1)
310 ip6_via_tunnel.add_vpp_config()
311
Ole Troan282093f2018-09-19 12:38:51 +0200312 self.tunnel_ip6_via_tunnel = ip6_via_tunnel
313 self.tunnel_ip4_via_tunnel = ip4_via_tunnel
Ole Troan298c6952018-03-08 12:30:43 +0100314
Ole Troan282093f2018-09-19 12:38:51 +0200315 def destroy_tunnel(self):
316 # IPv6 transport
317 self.tunnel_ip4_via_tunnel.remove_vpp_config()
318 self.tunnel_ip6_via_tunnel.remove_vpp_config()
319
320 rv = self.vapi.ipip_del_tunnel(sw_if_index=self.tunnel_if_index)
321
322 def validate(self, rx, expected):
323 self.assertEqual(rx, expected.__class__(str(expected)))
324
325 def generate_ip6_frags(self, payload_length, fragment_size):
326 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
327 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
328 p_ip6 = IPv6(src="1::1", dst=self.pg0.remote_ip6)
329 outer_ip6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
330 dst=self.pg0.local_ip6) /
331 IPv6ExtHdrFragment() / p_ip6 / p_payload)
332 frags = fragment6(outer_ip6, fragment_size)
333 p6_reply = (p_ip6 / p_payload)
334 p6_reply.hlim -= 1
335 return frags, p6_reply
336
337 def generate_ip6_hairpin_frags(self, payload_length, fragment_size):
338 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
339 p_payload = UDP(sport=1234, dport=1234) / self.payload(payload_length)
340 p_ip6 = IPv6(src="1::1", dst="dead::1")
341 outer_ip6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
342 dst=self.pg0.local_ip6) /
343 IPv6ExtHdrFragment() / p_ip6 / p_payload)
344 frags = fragment6(outer_ip6, fragment_size)
345 p_ip6.hlim -= 1
346 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
347 hlim=63) / p_ip6 / p_payload)
348
349 return frags, p6_reply
350
351 def test_encap(self):
352 """ ip{v4,v6} over ip6 test encap """
353 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
354 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
355 p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
356 p_payload = UDP(sport=1234, dport=1234)
357
358 # Encapsulation
Ole Troan298c6952018-03-08 12:30:43 +0100359 # IPv6 in to IPv6 tunnel
360 p6 = (p_ether / p_ip6 / p_payload)
Ole Troand57f6362018-05-24 13:21:43 +0200361 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
Ole Troan282093f2018-09-19 12:38:51 +0200362 hlim=64, tc=42) /
Ole Troand57f6362018-05-24 13:21:43 +0200363 p_ip6 / p_payload)
Ole Troan298c6952018-03-08 12:30:43 +0100364 p6_reply[1].hlim -= 1
Ole Troand57f6362018-05-24 13:21:43 +0200365 rx = self.send_and_expect(self.pg0, p6*11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100366 for p in rx:
367 self.validate(p[1], p6_reply)
368
369 # IPv4 in to IPv6 tunnel
370 p4 = (p_ether / p_ip4 / p_payload)
371 p4_reply = (IPv6(src=self.pg0.local_ip6,
Ole Troan282093f2018-09-19 12:38:51 +0200372 dst=self.pg1.remote_ip6, hlim=64, tc=42) /
Ole Troand57f6362018-05-24 13:21:43 +0200373 p_ip4 / p_payload)
Ole Troan298c6952018-03-08 12:30:43 +0100374 p4_reply[1].ttl -= 1
Ole Troand57f6362018-05-24 13:21:43 +0200375 rx = self.send_and_expect(self.pg0, p4*11, self.pg1)
Ole Troan298c6952018-03-08 12:30:43 +0100376 for p in rx:
377 self.validate(p[1], p4_reply)
378
Ole Troan282093f2018-09-19 12:38:51 +0200379 def test_decap(self):
380 """ ip{v4,v6} over ip6 test decap """
Ole Troan298c6952018-03-08 12:30:43 +0100381
382 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
Ole Troan282093f2018-09-19 12:38:51 +0200383 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
Ole Troan298c6952018-03-08 12:30:43 +0100384 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
Ole Troan282093f2018-09-19 12:38:51 +0200385 p_payload = UDP(sport=1234, dport=1234)
386
387 # Decapsulation
388 # IPv6 tunnel to IPv4
389
Ole Troan298c6952018-03-08 12:30:43 +0100390 p4 = (p_ether / IPv6(src=self.pg1.remote_ip6,
391 dst=self.pg0.local_ip6) / p_ip4 / p_payload)
392 p4_reply = (p_ip4 / p_payload)
393 p4_reply.ttl -= 1
Ole Troand57f6362018-05-24 13:21:43 +0200394 rx = self.send_and_expect(self.pg1, p4*11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100395 for p in rx:
396 self.validate(p[1], p4_reply)
397
398 # IPv6 tunnel to IPv6
399 p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
400 p6 = (p_ether / IPv6(src=self.pg1.remote_ip6,
401 dst=self.pg0.local_ip6) / p_ip6 / p_payload)
402 p6_reply = (p_ip6 / p_payload)
403 p6_reply.hlim = 63
Ole Troand57f6362018-05-24 13:21:43 +0200404 rx = self.send_and_expect(self.pg1, p6*11, self.pg0)
Ole Troan298c6952018-03-08 12:30:43 +0100405 for p in rx:
406 self.validate(p[1], p6_reply)
407
Ole Troan282093f2018-09-19 12:38:51 +0200408 def test_frag(self):
409 """ ip{v4,v6} over ip6 test frag """
410
411 p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
412 p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
413 p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
414 p_payload = UDP(sport=1234, dport=1234)
415
416 #
417 # Fragmentation / Reassembly and Re-fragmentation
418 #
419 rv = self.vapi.ip_reassembly_enable_disable(
420 sw_if_index=self.pg1.sw_if_index,
421 enable_ip6=1)
422
423 # Send lots of fragments, verify reassembled packet
424 before_cnt = self.statistics.get_counter(
425 '/err/ipip6-input/packets decapsulated')
426 frags, p6_reply = self.generate_ip6_frags(3131, 1400)
427 f = []
428 for i in range(0, 1000):
429 f.extend(frags)
430 self.pg1.add_stream(f)
431 self.pg_enable_capture()
432 self.pg_start()
433 rx = self.pg0.get_capture(1000)
434
435 for p in rx:
436 self.validate(p[1], p6_reply)
437
438 cnt = self.statistics.get_counter(
439 '/err/ipip6-input/packets decapsulated')
440 self.assertEqual(cnt, before_cnt + 1000)
441
442 f = []
443 r = []
444 # TODO: Check out why reassembly of atomic fragments don't work
445 for i in range(10, 90):
446 frags, p6_reply = self.generate_ip6_frags(i * 100, 1000)
447 f.extend(frags)
448 r.extend(p6_reply)
449 self.pg_enable_capture()
450 self.pg1.add_stream(f)
451 self.pg_start()
452 rx = self.pg0.get_capture(80)
453 i = 0
454 for p in rx:
455 self.validate(p[1], r[i])
456 i += 1
457
458 # Simple fragmentation
459 p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
460 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
461
462 # IPv6 in to IPv6 tunnel
463 p_payload = UDP(sport=1234, dport=1234) / self.payload(1300)
464
465 p6 = (p_ether / p_ip6 / p_payload)
466 p6_reply = (IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6,
467 hlim=63, tc=42) /
468 p_ip6 / p_payload)
469 p6_reply[1].hlim -= 1
470 self.pg_enable_capture()
471 self.pg0.add_stream(p6)
472 self.pg_start()
473 rx = self.pg1.get_capture(2)
474
475 # Scapy defragment doesn't deal well with multiple layers
476 # of samy type / Ethernet header first
477 f = [p[1] for p in rx]
478 reass_pkt = defragment6(f)
479 self.validate(reass_pkt, p6_reply)
480
481 # Now try with re-fragmentation
482 #
483 # Send large fragments to tunnel head-end, for the tunnel head end
484 # to reassemble and then refragment out the tunnel again.
485 # Hair-pinning
486 #
487 self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
488 frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200)
489 self.pg_enable_capture()
490 self.pg1.add_stream(frags)
491 self.pg_start()
492 rx = self.pg1.get_capture(7)
493 f = [p[1] for p in rx]
494 reass_pkt = defragment6(f)
495 p6_reply.id = 256
496 self.validate(reass_pkt, p6_reply)
497
Ole Troan298c6952018-03-08 12:30:43 +0100498 def test_ipip_create(self):
499 """ ipip create / delete interface test """
500 rv = self.vapi.ipip_add_tunnel(
Ole Troan46c1c112018-03-14 20:39:40 +0100501 src_address=inet_pton(AF_INET, '1.2.3.4'),
502 dst_address=inet_pton(AF_INET, '2.3.4.5'), is_ipv6=0)
Ole Troan298c6952018-03-08 12:30:43 +0100503 sw_if_index = rv.sw_if_index
Ole Troan46c1c112018-03-14 20:39:40 +0100504 self.vapi.ipip_del_tunnel(sw_if_index)
Ole Troan298c6952018-03-08 12:30:43 +0100505
Neale Ranns61502112018-08-22 00:21:14 -0700506 def test_ipip_vrf_create(self):
507 """ ipip create / delete interface VRF test """
508
509 t = VppIpTable(self, 20)
510 t.add_vpp_config()
511 rv = self.vapi.ipip_add_tunnel(
512 src_address=inet_pton(AF_INET, '1.2.3.4'),
513 dst_address=inet_pton(AF_INET, '2.3.4.5'), is_ipv6=0,
514 table_id=20)
515 sw_if_index = rv.sw_if_index
516 self.vapi.ipip_del_tunnel(sw_if_index)
517
Ole Troan4146c652018-08-08 22:23:19 +0200518 def payload(self, len):
519 return 'x' * len
520
Ole Troan298c6952018-03-08 12:30:43 +0100521
522if __name__ == '__main__':
523 unittest.main(testRunner=VppTestRunner)