blob: 6a356a00b0c2a885aa26ad5ac964424652dc261c [file] [log] [blame]
Klement Sekera75e7d132017-09-20 08:26:30 +02001#!/usr/bin/env python
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -08002
Paul Vinciguerra69555952019-03-01 08:46:29 -08003from random import shuffle
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -08004import six
Klement Sekera75e7d132017-09-20 08:26:30 +02005import unittest
Klement Sekera75e7d132017-09-20 08:26:30 +02006
Paul Vinciguerra69555952019-03-01 08:46:29 -08007from parameterized import parameterized
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07008import scapy.compat
Klement Sekera75e7d132017-09-20 08:26:30 +02009from scapy.packet import Raw
10from scapy.layers.l2 import Ether, GRE
Juraj Sloboda3048b632018-10-02 11:13:53 +020011from scapy.layers.inet import IP, UDP, ICMP
Paul Vinciguerra69555952019-03-01 08:46:29 -080012
Klement Sekera75e7d132017-09-20 08:26:30 +020013from scapy.layers.inet6 import IPv6, IPv6ExtHdrFragment, ICMPv6ParamProblem,\
14 ICMPv6TimeExceeded
Paul Vinciguerra69555952019-03-01 08:46:29 -080015
16from framework import VppTestCase, VppTestRunner
17from util import ppp, fragment_rfc791, fragment_rfc8200
Neale Ranns5a8844b2019-04-16 07:15:35 +000018from vpp_gre_interface import VppGreInterface
Neale Rannsc0a93142018-09-05 15:42:26 -070019from vpp_ip import DpoProto
Neale Ranns097fa662018-05-01 05:17:55 -070020from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathProto
Klement Sekera75e7d132017-09-20 08:26:30 +020021
Klement Sekerad0f70a32018-12-14 17:24:13 +010022# 35 is enough to have >257 400-byte fragments
23test_packet_count = 35
Klement Sekera75e7d132017-09-20 08:26:30 +020024
Paul Vinciguerra69555952019-03-01 08:46:29 -080025# <class 'scapy.layers.inet.IP'>
26# <class 'scapy.layers.inet6.IPv6'>
27_scapy_ip_family_types = (IP, IPv6)
Klement Sekera75e7d132017-09-20 08:26:30 +020028
Paul Vinciguerra69555952019-03-01 08:46:29 -080029
30def validate_scapy_ip_family(scapy_ip_family):
31
32 if scapy_ip_family not in _scapy_ip_family_types:
33 raise ValueError("'scapy_ip_family' must be of type: %s. Got %s" %
34 (_scapy_ip_family_types, scapy_ip_family))
35
36
37class TestIPReassemblyMixin(object):
38
39 def verify_capture(self, scapy_ip_family, capture,
40 dropped_packet_indexes=None):
41 """Verify captured packet stream.
42
43 :param list capture: Captured packet stream.
44 """
45 validate_scapy_ip_family(scapy_ip_family)
46
47 if dropped_packet_indexes is None:
48 dropped_packet_indexes = []
49 info = None
50 seen = set()
51 for packet in capture:
52 try:
53 self.logger.debug(ppp("Got packet:", packet))
54 ip = packet[scapy_ip_family]
55 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -080056 payload_info = self.payload_to_info(packet[Raw])
Paul Vinciguerra69555952019-03-01 08:46:29 -080057 packet_index = payload_info.index
58 self.assertTrue(
59 packet_index not in dropped_packet_indexes,
60 ppp("Packet received, but should be dropped:", packet))
61 if packet_index in seen:
62 raise Exception(ppp("Duplicate packet received", packet))
63 seen.add(packet_index)
64 self.assertEqual(payload_info.dst, self.src_if.sw_if_index)
65 info = self._packet_infos[packet_index]
66 self.assertTrue(info is not None)
67 self.assertEqual(packet_index, info.index)
68 saved_packet = info.data
69 self.assertEqual(ip.src, saved_packet[scapy_ip_family].src)
70 self.assertEqual(ip.dst, saved_packet[scapy_ip_family].dst)
71 self.assertEqual(udp.payload, saved_packet[UDP].payload)
72 except Exception:
73 self.logger.error(ppp("Unexpected or invalid packet:", packet))
74 raise
75 for index in self._packet_infos:
76 self.assertTrue(index in seen or index in dropped_packet_indexes,
77 "Packet with packet_index %d not received" % index)
78
79 def test_disabled(self, scapy_ip_family, stream,
80 dropped_packet_indexes):
81 """ reassembly disabled """
82 validate_scapy_ip_family(scapy_ip_family)
83 is_ip6 = 1 if scapy_ip_family == IPv6 else 0
84
85 self.vapi.ip_reassembly_set(timeout_ms=1000, max_reassemblies=0,
Klement Sekera3a343d42019-05-16 14:35:46 +020086 max_reassembly_length=1000,
Paul Vinciguerra69555952019-03-01 08:46:29 -080087 expire_walk_interval_ms=10000,
88 is_ip6=is_ip6)
89
90 self.pg_enable_capture()
91 self.src_if.add_stream(stream)
92 self.pg_start()
93
94 packets = self.dst_if.get_capture(
95 len(self.pkt_infos) - len(dropped_packet_indexes))
96 self.verify_capture(scapy_ip_family, packets, dropped_packet_indexes)
97 self.src_if.assert_nothing_captured()
98
99 def test_duplicates(self, scapy_ip_family, stream):
100 """ duplicate fragments """
101 validate_scapy_ip_family(scapy_ip_family)
102
103 self.pg_enable_capture()
104 self.src_if.add_stream(stream)
105 self.pg_start()
106
107 packets = self.dst_if.get_capture(len(self.pkt_infos))
108 self.verify_capture(scapy_ip_family, packets)
109 self.src_if.assert_nothing_captured()
110
111 def test_random(self, scapy_ip_family, stream):
112 """ random order reassembly """
113 validate_scapy_ip_family(scapy_ip_family)
114
115 fragments = list(stream)
116 shuffle(fragments)
117
118 self.pg_enable_capture()
119 self.src_if.add_stream(fragments)
120 self.pg_start()
121
122 packets = self.dst_if.get_capture(len(self.packet_infos))
123 self.verify_capture(scapy_ip_family, packets)
124 self.src_if.assert_nothing_captured()
125
126 # run it all again to verify correctness
127 self.pg_enable_capture()
128 self.src_if.add_stream(fragments)
129 self.pg_start()
130
131 packets = self.dst_if.get_capture(len(self.packet_infos))
132 self.verify_capture(scapy_ip_family, packets)
133 self.src_if.assert_nothing_captured()
134
135 def test_reassembly(self, scapy_ip_family, stream):
136 """ basic reassembly """
137 validate_scapy_ip_family(scapy_ip_family)
138
139 self.pg_enable_capture()
140 self.src_if.add_stream(stream)
141 self.pg_start()
142
143 packets = self.dst_if.get_capture(len(self.pkt_infos))
144 self.verify_capture(scapy_ip_family, packets)
145 self.src_if.assert_nothing_captured()
146
147 # run it all again to verify correctness
148 self.pg_enable_capture()
149 self.src_if.add_stream(stream)
150 self.pg_start()
151
152 packets = self.dst_if.get_capture(len(self.pkt_infos))
153 self.verify_capture(scapy_ip_family, packets)
154 self.src_if.assert_nothing_captured()
155
156 def test_reversed(self, scapy_ip_family, stream):
157 """ reverse order reassembly """
158 validate_scapy_ip_family(scapy_ip_family)
159
160 fragments = list(stream)
161 fragments.reverse()
162
163 self.pg_enable_capture()
164 self.src_if.add_stream(fragments)
165 self.pg_start()
166
167 packets = self.dst_if.get_capture(len(self.packet_infos))
168 self.verify_capture(scapy_ip_family, packets)
169 self.src_if.assert_nothing_captured()
170
171 # run it all again to verify correctness
172 self.pg_enable_capture()
173 self.src_if.add_stream(fragments)
174 self.pg_start()
175
176 packets = self.dst_if.get_capture(len(self.packet_infos))
177 self.verify_capture(scapy_ip_family, packets)
178 self.src_if.assert_nothing_captured()
179
180 def test_timeout_inline(self, scapy_ip_family, stream,
181 dropped_packet_indexes):
182 """ timeout (inline) """
183 validate_scapy_ip_family(scapy_ip_family)
184 is_ip6 = 1 if scapy_ip_family == IPv6 else 0
185
186 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200187 max_reassembly_length=1000,
Paul Vinciguerra69555952019-03-01 08:46:29 -0800188 expire_walk_interval_ms=10000,
189 is_ip6=is_ip6)
190
191 self.pg_enable_capture()
192 self.src_if.add_stream(stream)
193 self.pg_start()
194
195 packets = self.dst_if.get_capture(
196 len(self.pkt_infos) - len(dropped_packet_indexes))
197 self.verify_capture(scapy_ip_family, packets,
198 dropped_packet_indexes)
199
200
201class TestIPv4Reassembly(TestIPReassemblyMixin, VppTestCase):
Klement Sekera75e7d132017-09-20 08:26:30 +0200202 """ IPv4 Reassembly """
203
204 @classmethod
205 def setUpClass(cls):
206 super(TestIPv4Reassembly, cls).setUpClass()
207
Klement Sekera4c533132018-02-22 11:41:12 +0100208 cls.create_pg_interfaces([0, 1])
209 cls.src_if = cls.pg0
210 cls.dst_if = cls.pg1
Klement Sekera75e7d132017-09-20 08:26:30 +0200211
212 # setup all interfaces
213 for i in cls.pg_interfaces:
214 i.admin_up()
215 i.config_ip4()
216 i.resolve_arp()
217
Klement Sekera75e7d132017-09-20 08:26:30 +0200218 # packet sizes
219 cls.packet_sizes = [64, 512, 1518, 9018]
220 cls.padding = " abcdefghijklmn"
221 cls.create_stream(cls.packet_sizes)
222 cls.create_fragments()
223
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700224 @classmethod
225 def tearDownClass(cls):
226 super(TestIPv4Reassembly, cls).tearDownClass()
227
Klement Sekera75e7d132017-09-20 08:26:30 +0200228 def setUp(self):
229 """ Test setup - force timeout on existing reassemblies """
230 super(TestIPv4Reassembly, self).setUp()
Klement Sekera4c533132018-02-22 11:41:12 +0100231 self.vapi.ip_reassembly_enable_disable(
232 sw_if_index=self.src_if.sw_if_index, enable_ip4=True)
Klement Sekera75e7d132017-09-20 08:26:30 +0200233 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200234 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200235 expire_walk_interval_ms=10)
236 self.sleep(.25)
237 self.vapi.ip_reassembly_set(timeout_ms=1000000, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200238 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200239 expire_walk_interval_ms=10000)
240
241 def tearDown(self):
242 super(TestIPv4Reassembly, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700243
244 def show_commands_at_teardown(self):
Klement Sekera75e7d132017-09-20 08:26:30 +0200245 self.logger.debug(self.vapi.ppcli("show ip4-reassembly details"))
Klement Sekeracae98b72019-02-19 13:53:43 +0100246 self.logger.debug(self.vapi.ppcli("show buffers"))
Klement Sekera75e7d132017-09-20 08:26:30 +0200247
248 @classmethod
249 def create_stream(cls, packet_sizes, packet_count=test_packet_count):
Klement Sekerad0f70a32018-12-14 17:24:13 +0100250 """Create input packet stream
Klement Sekera75e7d132017-09-20 08:26:30 +0200251
252 :param list packet_sizes: Required packet sizes.
253 """
254 for i in range(0, packet_count):
Klement Sekera4c533132018-02-22 11:41:12 +0100255 info = cls.create_packet_info(cls.src_if, cls.src_if)
Klement Sekera75e7d132017-09-20 08:26:30 +0200256 payload = cls.info_to_payload(info)
Klement Sekera4c533132018-02-22 11:41:12 +0100257 p = (Ether(dst=cls.src_if.local_mac, src=cls.src_if.remote_mac) /
258 IP(id=info.index, src=cls.src_if.remote_ip4,
259 dst=cls.dst_if.remote_ip4) /
260 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +0200261 Raw(payload))
262 size = packet_sizes[(i // 2) % len(packet_sizes)]
263 cls.extend_packet(p, size, cls.padding)
264 info.data = p
265
266 @classmethod
267 def create_fragments(cls):
268 infos = cls._packet_infos
269 cls.pkt_infos = []
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -0800270 for index, info in six.iteritems(infos):
Klement Sekera75e7d132017-09-20 08:26:30 +0200271 p = info.data
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700272 # cls.logger.debug(ppp("Packet:",
273 # p.__class__(scapy.compat.raw(p))))
Klement Sekera75e7d132017-09-20 08:26:30 +0200274 fragments_400 = fragment_rfc791(p, 400)
275 fragments_300 = fragment_rfc791(p, 300)
276 fragments_200 = [
277 x for f in fragments_400 for x in fragment_rfc791(f, 200)]
278 cls.pkt_infos.append(
279 (index, fragments_400, fragments_300, fragments_200))
280 cls.fragments_400 = [
281 x for (_, frags, _, _) in cls.pkt_infos for x in frags]
282 cls.fragments_300 = [
283 x for (_, _, frags, _) in cls.pkt_infos for x in frags]
284 cls.fragments_200 = [
285 x for (_, _, _, frags) in cls.pkt_infos for x in frags]
286 cls.logger.debug("Fragmented %s packets into %s 400-byte fragments, "
287 "%s 300-byte fragments and %s 200-byte fragments" %
288 (len(infos), len(cls.fragments_400),
289 len(cls.fragments_300), len(cls.fragments_200)))
290
Paul Vinciguerra69555952019-03-01 08:46:29 -0800291 @parameterized.expand([(IP, None)])
292 def test_reassembly(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200293 """ basic reassembly """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800294 stream = self.__class__.fragments_200
295 super(TestIPv4Reassembly, self).test_reassembly(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200296
Paul Vinciguerra69555952019-03-01 08:46:29 -0800297 @parameterized.expand([(IP, None)])
298 def test_reversed(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200299 """ reverse order reassembly """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800300 stream = self.__class__.fragments_200
301 super(TestIPv4Reassembly, self).test_reversed(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200302
Paul Vinciguerra69555952019-03-01 08:46:29 -0800303 @parameterized.expand([(IP, None)])
304 def test_random(self, family, stream):
305 stream = self.__class__.fragments_200
306 super(TestIPv4Reassembly, self).test_random(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200307
Klement Sekera3a343d42019-05-16 14:35:46 +0200308 def test_long_fragment_chain(self):
309 """ long fragment chain """
310
311 error_cnt_str = \
312 "/err/ip4-reassembly-feature/fragment chain too long (drop)"
313
Klement Sekera34641f22019-05-22 20:18:26 +0200314 error_cnt = self.statistics.get_err_counter(error_cnt_str)
Klement Sekera3a343d42019-05-16 14:35:46 +0200315
316 self.vapi.ip_reassembly_set(timeout_ms=100, max_reassemblies=1000,
317 max_reassembly_length=3,
318 expire_walk_interval_ms=50)
319
320 p1 = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
321 IP(id=1000, src=self.src_if.remote_ip4,
322 dst=self.dst_if.remote_ip4) /
323 UDP(sport=1234, dport=5678) /
324 Raw("X" * 1000))
325 p2 = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
326 IP(id=1001, src=self.src_if.remote_ip4,
327 dst=self.dst_if.remote_ip4) /
328 UDP(sport=1234, dport=5678) /
329 Raw("X" * 1000))
330 frags = fragment_rfc791(p1, 200) + fragment_rfc791(p2, 500)
331
332 self.pg_enable_capture()
333 self.src_if.add_stream(frags)
334 self.pg_start()
335
336 self.dst_if.get_capture(1)
Klement Sekera34641f22019-05-22 20:18:26 +0200337 self.assert_error_counter_equal(error_cnt_str, error_cnt + 1)
Klement Sekera3a343d42019-05-16 14:35:46 +0200338
Klement Sekera14d7e902018-12-10 13:46:09 +0100339 def test_5737(self):
340 """ fragment length + ip header size > 65535 """
Klement Sekera4ee633e2018-12-14 12:00:44 +0100341 self.vapi.cli("clear errors")
Klement Sekera14d7e902018-12-10 13:46:09 +0100342 raw = ('E\x00\x00\x88,\xf8\x1f\xfe@\x01\x98\x00\xc0\xa8\n-\xc0\xa8\n'
343 '\x01\x08\x00\xf0J\xed\xcb\xf1\xf5Test-group: IPv4.IPv4.ipv4-'
344 'message.Ethernet-Payload.IPv4-Packet.IPv4-Header.Fragment-Of'
345 'fset; Test-case: 5737')
346
347 malformed_packet = (Ether(dst=self.src_if.local_mac,
348 src=self.src_if.remote_mac) /
349 IP(raw))
350 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
351 IP(id=1000, src=self.src_if.remote_ip4,
352 dst=self.dst_if.remote_ip4) /
353 UDP(sport=1234, dport=5678) /
354 Raw("X" * 1000))
355 valid_fragments = fragment_rfc791(p, 400)
356
357 self.pg_enable_capture()
358 self.src_if.add_stream([malformed_packet] + valid_fragments)
359 self.pg_start()
360
361 self.dst_if.get_capture(1)
Klement Sekera4ee633e2018-12-14 12:00:44 +0100362 self.assert_packet_counter_equal("ip4-reassembly-feature", 1)
363 # TODO remove above, uncomment below once clearing of counters
364 # is supported
365 # self.assert_packet_counter_equal(
366 # "/err/ip4-reassembly-feature/malformed packets", 1)
Klement Sekera14d7e902018-12-10 13:46:09 +0100367
Klement Sekera400f6d82018-12-13 14:35:48 +0100368 def test_44924(self):
369 """ compress tiny fragments """
370 packets = [(Ether(dst=self.src_if.local_mac,
371 src=self.src_if.remote_mac) /
372 IP(id=24339, flags="MF", frag=0, ttl=64,
373 src=self.src_if.remote_ip4,
374 dst=self.dst_if.remote_ip4) /
375 ICMP(type="echo-request", code=0, id=0x1fe6, seq=0x2407) /
376 Raw(load='Test-group: IPv4')),
377 (Ether(dst=self.src_if.local_mac,
378 src=self.src_if.remote_mac) /
379 IP(id=24339, flags="MF", frag=3, ttl=64,
380 src=self.src_if.remote_ip4,
381 dst=self.dst_if.remote_ip4) /
382 ICMP(type="echo-request", code=0, id=0x1fe6, seq=0x2407) /
383 Raw(load='.IPv4.Fragmentation.vali')),
384 (Ether(dst=self.src_if.local_mac,
385 src=self.src_if.remote_mac) /
386 IP(id=24339, frag=6, ttl=64,
387 src=self.src_if.remote_ip4,
388 dst=self.dst_if.remote_ip4) /
389 ICMP(type="echo-request", code=0, id=0x1fe6, seq=0x2407) /
390 Raw(load='d; Test-case: 44924'))
391 ]
392
393 self.pg_enable_capture()
394 self.src_if.add_stream(packets)
395 self.pg_start()
396
397 self.dst_if.get_capture(1)
398
Klement Sekera4ee633e2018-12-14 12:00:44 +0100399 def test_frag_1(self):
400 """ fragment of size 1 """
401 self.vapi.cli("clear errors")
402 malformed_packets = [(Ether(dst=self.src_if.local_mac,
403 src=self.src_if.remote_mac) /
404 IP(id=7, len=21, flags="MF", frag=0, ttl=64,
405 src=self.src_if.remote_ip4,
406 dst=self.dst_if.remote_ip4) /
407 ICMP(type="echo-request")),
408 (Ether(dst=self.src_if.local_mac,
409 src=self.src_if.remote_mac) /
410 IP(id=7, len=21, frag=1, ttl=64,
411 src=self.src_if.remote_ip4,
412 dst=self.dst_if.remote_ip4) /
413 Raw(load='\x08')),
414 ]
415
416 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
417 IP(id=1000, src=self.src_if.remote_ip4,
418 dst=self.dst_if.remote_ip4) /
419 UDP(sport=1234, dport=5678) /
420 Raw("X" * 1000))
421 valid_fragments = fragment_rfc791(p, 400)
422
423 self.pg_enable_capture()
424 self.src_if.add_stream(malformed_packets + valid_fragments)
425 self.pg_start()
426
427 self.dst_if.get_capture(1)
428
429 self.assert_packet_counter_equal("ip4-reassembly-feature", 1)
430 # TODO remove above, uncomment below once clearing of counters
431 # is supported
432 # self.assert_packet_counter_equal(
433 # "/err/ip4-reassembly-feature/malformed packets", 1)
434
Paul Vinciguerra69555952019-03-01 08:46:29 -0800435 @parameterized.expand([(IP, None)])
436 def test_duplicates(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200437 """ duplicate fragments """
Klement Sekera75e7d132017-09-20 08:26:30 +0200438 fragments = [
Paul Vinciguerra69555952019-03-01 08:46:29 -0800439 # IPv4 uses 4 fields in pkt_infos, IPv6 uses 3.
Klement Sekera75e7d132017-09-20 08:26:30 +0200440 x for (_, frags, _, _) in self.pkt_infos
441 for x in frags
442 for _ in range(0, min(2, len(frags)))
443 ]
Paul Vinciguerra69555952019-03-01 08:46:29 -0800444 super(TestIPv4Reassembly, self).test_duplicates(family, fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200445
446 def test_overlap1(self):
447 """ overlapping fragments case #1 """
448
449 fragments = []
450 for _, _, frags_300, frags_200 in self.pkt_infos:
451 if len(frags_300) == 1:
452 fragments.extend(frags_300)
453 else:
454 for i, j in zip(frags_200, frags_300):
455 fragments.extend(i)
456 fragments.extend(j)
457
458 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100459 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200460 self.pg_start()
461
Klement Sekera4c533132018-02-22 11:41:12 +0100462 packets = self.dst_if.get_capture(len(self.pkt_infos))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800463 self.verify_capture(IP, packets)
Klement Sekera4c533132018-02-22 11:41:12 +0100464 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200465
466 # run it all to verify correctness
467 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100468 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200469 self.pg_start()
470
Klement Sekera4c533132018-02-22 11:41:12 +0100471 packets = self.dst_if.get_capture(len(self.pkt_infos))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800472 self.verify_capture(IP, packets)
Klement Sekera4c533132018-02-22 11:41:12 +0100473 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200474
475 def test_overlap2(self):
476 """ overlapping fragments case #2 """
477
478 fragments = []
479 for _, _, frags_300, frags_200 in self.pkt_infos:
480 if len(frags_300) == 1:
481 fragments.extend(frags_300)
482 else:
483 # care must be taken here so that there are no fragments
484 # received by vpp after reassembly is finished, otherwise
485 # new reassemblies will be started and packet generator will
486 # freak out when it detects unfreed buffers
487 zipped = zip(frags_300, frags_200)
Paul Vinciguerrac7834e02019-03-02 10:43:05 -0800488 for i, j in zipped:
Klement Sekera75e7d132017-09-20 08:26:30 +0200489 fragments.extend(i)
490 fragments.extend(j)
Paul Vinciguerrac7834e02019-03-02 10:43:05 -0800491 fragments.pop()
Klement Sekera75e7d132017-09-20 08:26:30 +0200492
493 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100494 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200495 self.pg_start()
496
Klement Sekera4c533132018-02-22 11:41:12 +0100497 packets = self.dst_if.get_capture(len(self.pkt_infos))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800498 self.verify_capture(IP, packets)
Klement Sekera4c533132018-02-22 11:41:12 +0100499 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200500
501 # run it all to verify correctness
502 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100503 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200504 self.pg_start()
505
Klement Sekera4c533132018-02-22 11:41:12 +0100506 packets = self.dst_if.get_capture(len(self.pkt_infos))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800507 self.verify_capture(IP, packets)
Klement Sekera4c533132018-02-22 11:41:12 +0100508 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200509
Paul Vinciguerra69555952019-03-01 08:46:29 -0800510 @parameterized.expand([(IP, None, None)])
511 def test_timeout_inline(self, family, stream, dropped_packet_indexes):
Klement Sekera75e7d132017-09-20 08:26:30 +0200512 """ timeout (inline) """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800513 stream = self.fragments_400
Klement Sekera75e7d132017-09-20 08:26:30 +0200514
515 dropped_packet_indexes = set(
516 index for (index, frags, _, _) in self.pkt_infos if len(frags) > 1
517 )
Paul Vinciguerra69555952019-03-01 08:46:29 -0800518 super(TestIPv4Reassembly, self).test_timeout_inline(
519 family, stream, dropped_packet_indexes)
Klement Sekera75e7d132017-09-20 08:26:30 +0200520
Klement Sekera4c533132018-02-22 11:41:12 +0100521 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200522
523 def test_timeout_cleanup(self):
524 """ timeout (cleanup) """
525
526 # whole packets + fragmented packets sans last fragment
527 fragments = [
528 x for (_, frags_400, _, _) in self.pkt_infos
529 for x in frags_400[:-1 if len(frags_400) > 1 else None]
530 ]
531
532 # last fragments for fragmented packets
533 fragments2 = [frags_400[-1]
534 for (_, frags_400, _, _) in self.pkt_infos
535 if len(frags_400) > 1]
536
537 dropped_packet_indexes = set(
538 index for (index, frags_400, _, _) in self.pkt_infos
539 if len(frags_400) > 1)
540
541 self.vapi.ip_reassembly_set(timeout_ms=100, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200542 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200543 expire_walk_interval_ms=50)
544
545 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100546 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200547 self.pg_start()
548
549 self.sleep(.25, "wait before sending rest of fragments")
550
Klement Sekera4c533132018-02-22 11:41:12 +0100551 self.src_if.add_stream(fragments2)
Klement Sekera75e7d132017-09-20 08:26:30 +0200552 self.pg_start()
Klement Sekera75e7d132017-09-20 08:26:30 +0200553
Klement Sekera4c533132018-02-22 11:41:12 +0100554 packets = self.dst_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200555 len(self.pkt_infos) - len(dropped_packet_indexes))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800556 self.verify_capture(IP, packets, dropped_packet_indexes)
Klement Sekera4c533132018-02-22 11:41:12 +0100557 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200558
Paul Vinciguerra69555952019-03-01 08:46:29 -0800559 @parameterized.expand([(IP, None, None)])
560 def test_disabled(self, family, stream, dropped_packet_indexes):
Klement Sekera75e7d132017-09-20 08:26:30 +0200561 """ reassembly disabled """
562
Paul Vinciguerra69555952019-03-01 08:46:29 -0800563 stream = self.__class__.fragments_400
Klement Sekera75e7d132017-09-20 08:26:30 +0200564 dropped_packet_indexes = set(
565 index for (index, frags_400, _, _) in self.pkt_infos
566 if len(frags_400) > 1)
Paul Vinciguerra69555952019-03-01 08:46:29 -0800567 super(TestIPv4Reassembly, self).test_disabled(
568 family, stream, dropped_packet_indexes)
Klement Sekera75e7d132017-09-20 08:26:30 +0200569
570
Paul Vinciguerra69555952019-03-01 08:46:29 -0800571class TestIPv6Reassembly(TestIPReassemblyMixin, VppTestCase):
Klement Sekera75e7d132017-09-20 08:26:30 +0200572 """ IPv6 Reassembly """
573
574 @classmethod
575 def setUpClass(cls):
576 super(TestIPv6Reassembly, cls).setUpClass()
577
Klement Sekera4c533132018-02-22 11:41:12 +0100578 cls.create_pg_interfaces([0, 1])
579 cls.src_if = cls.pg0
580 cls.dst_if = cls.pg1
Klement Sekera75e7d132017-09-20 08:26:30 +0200581
582 # setup all interfaces
583 for i in cls.pg_interfaces:
584 i.admin_up()
585 i.config_ip6()
586 i.resolve_ndp()
587
Klement Sekera75e7d132017-09-20 08:26:30 +0200588 # packet sizes
589 cls.packet_sizes = [64, 512, 1518, 9018]
590 cls.padding = " abcdefghijklmn"
591 cls.create_stream(cls.packet_sizes)
592 cls.create_fragments()
593
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700594 @classmethod
595 def tearDownClass(cls):
596 super(TestIPv6Reassembly, cls).tearDownClass()
597
Klement Sekera75e7d132017-09-20 08:26:30 +0200598 def setUp(self):
599 """ Test setup - force timeout on existing reassemblies """
600 super(TestIPv6Reassembly, self).setUp()
Klement Sekera4c533132018-02-22 11:41:12 +0100601 self.vapi.ip_reassembly_enable_disable(
602 sw_if_index=self.src_if.sw_if_index, enable_ip6=True)
Klement Sekera75e7d132017-09-20 08:26:30 +0200603 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200604 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200605 expire_walk_interval_ms=10, is_ip6=1)
606 self.sleep(.25)
607 self.vapi.ip_reassembly_set(timeout_ms=1000000, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200608 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200609 expire_walk_interval_ms=10000, is_ip6=1)
Klement Sekera4c533132018-02-22 11:41:12 +0100610 self.logger.debug(self.vapi.ppcli("show ip6-reassembly details"))
Klement Sekeracae98b72019-02-19 13:53:43 +0100611 self.logger.debug(self.vapi.ppcli("show buffers"))
Klement Sekera75e7d132017-09-20 08:26:30 +0200612
613 def tearDown(self):
614 super(TestIPv6Reassembly, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700615
616 def show_commands_at_teardown(self):
Klement Sekera75e7d132017-09-20 08:26:30 +0200617 self.logger.debug(self.vapi.ppcli("show ip6-reassembly details"))
Klement Sekeracae98b72019-02-19 13:53:43 +0100618 self.logger.debug(self.vapi.ppcli("show buffers"))
Klement Sekera75e7d132017-09-20 08:26:30 +0200619
620 @classmethod
621 def create_stream(cls, packet_sizes, packet_count=test_packet_count):
622 """Create input packet stream for defined interface.
623
624 :param list packet_sizes: Required packet sizes.
625 """
626 for i in range(0, packet_count):
Klement Sekera4c533132018-02-22 11:41:12 +0100627 info = cls.create_packet_info(cls.src_if, cls.src_if)
Klement Sekera75e7d132017-09-20 08:26:30 +0200628 payload = cls.info_to_payload(info)
Klement Sekera4c533132018-02-22 11:41:12 +0100629 p = (Ether(dst=cls.src_if.local_mac, src=cls.src_if.remote_mac) /
630 IPv6(src=cls.src_if.remote_ip6,
631 dst=cls.dst_if.remote_ip6) /
632 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +0200633 Raw(payload))
634 size = packet_sizes[(i // 2) % len(packet_sizes)]
635 cls.extend_packet(p, size, cls.padding)
636 info.data = p
637
638 @classmethod
639 def create_fragments(cls):
640 infos = cls._packet_infos
641 cls.pkt_infos = []
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -0800642 for index, info in six.iteritems(infos):
Klement Sekera75e7d132017-09-20 08:26:30 +0200643 p = info.data
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700644 # cls.logger.debug(ppp("Packet:",
645 # p.__class__(scapy.compat.raw(p))))
Klement Sekera75e7d132017-09-20 08:26:30 +0200646 fragments_400 = fragment_rfc8200(p, info.index, 400)
647 fragments_300 = fragment_rfc8200(p, info.index, 300)
648 cls.pkt_infos.append((index, fragments_400, fragments_300))
649 cls.fragments_400 = [
650 x for _, frags, _ in cls.pkt_infos for x in frags]
651 cls.fragments_300 = [
652 x for _, _, frags in cls.pkt_infos for x in frags]
653 cls.logger.debug("Fragmented %s packets into %s 400-byte fragments, "
654 "and %s 300-byte fragments" %
655 (len(infos), len(cls.fragments_400),
656 len(cls.fragments_300)))
657
Paul Vinciguerra69555952019-03-01 08:46:29 -0800658 @parameterized.expand([(IPv6, None)])
659 def test_reassembly(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200660 """ basic reassembly """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800661 stream = self.__class__.fragments_400
662 super(TestIPv6Reassembly, self).test_reassembly(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200663
Paul Vinciguerra69555952019-03-01 08:46:29 -0800664 @parameterized.expand([(IPv6, None)])
665 def test_reversed(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200666 """ reverse order reassembly """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800667 stream = self.__class__.fragments_400
668 super(TestIPv6Reassembly, self).test_reversed(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200669
Paul Vinciguerra69555952019-03-01 08:46:29 -0800670 @parameterized.expand([(IPv6, None)])
671 def test_random(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200672 """ random order reassembly """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800673 stream = self.__class__.fragments_400
674 super(TestIPv6Reassembly, self).test_random(family, stream)
Klement Sekera75e7d132017-09-20 08:26:30 +0200675
Paul Vinciguerra69555952019-03-01 08:46:29 -0800676 @parameterized.expand([(IPv6, None)])
677 def test_duplicates(self, family, stream):
Klement Sekera75e7d132017-09-20 08:26:30 +0200678 """ duplicate fragments """
679
680 fragments = [
Paul Vinciguerra69555952019-03-01 08:46:29 -0800681 # IPv4 uses 4 fields in pkt_infos, IPv6 uses 3.
Klement Sekera75e7d132017-09-20 08:26:30 +0200682 x for (_, frags, _) in self.pkt_infos
683 for x in frags
684 for _ in range(0, min(2, len(frags)))
685 ]
Paul Vinciguerra69555952019-03-01 08:46:29 -0800686 super(TestIPv6Reassembly, self).test_duplicates(family, fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200687
Klement Sekera3a343d42019-05-16 14:35:46 +0200688 def test_long_fragment_chain(self):
689 """ long fragment chain """
690
691 error_cnt_str = \
692 "/err/ip6-reassembly-feature/fragment chain too long (drop)"
693
Klement Sekera34641f22019-05-22 20:18:26 +0200694 error_cnt = self.statistics.get_err_counter(error_cnt_str)
Klement Sekera3a343d42019-05-16 14:35:46 +0200695
696 self.vapi.ip_reassembly_set(timeout_ms=100, max_reassemblies=1000,
697 max_reassembly_length=3,
698 expire_walk_interval_ms=50, is_ip6=1)
699
700 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
701 IPv6(src=self.src_if.remote_ip6,
702 dst=self.dst_if.remote_ip6) /
703 UDP(sport=1234, dport=5678) /
704 Raw("X" * 1000))
705 frags = fragment_rfc8200(p, 1, 300) + fragment_rfc8200(p, 2, 500)
706
707 self.pg_enable_capture()
708 self.src_if.add_stream(frags)
709 self.pg_start()
710
711 self.dst_if.get_capture(1)
Klement Sekera34641f22019-05-22 20:18:26 +0200712 self.assert_error_counter_equal(error_cnt_str, error_cnt + 1)
Klement Sekera3a343d42019-05-16 14:35:46 +0200713
Klement Sekera75e7d132017-09-20 08:26:30 +0200714 def test_overlap1(self):
Paul Vinciguerra69555952019-03-01 08:46:29 -0800715 """ overlapping fragments case #1 (differs from IP test case)"""
Klement Sekera75e7d132017-09-20 08:26:30 +0200716
717 fragments = []
718 for _, frags_400, frags_300 in self.pkt_infos:
719 if len(frags_300) == 1:
720 fragments.extend(frags_400)
721 else:
722 for i, j in zip(frags_300, frags_400):
723 fragments.extend(i)
724 fragments.extend(j)
725
726 dropped_packet_indexes = set(
727 index for (index, _, frags) in self.pkt_infos if len(frags) > 1
728 )
729
730 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100731 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200732 self.pg_start()
733
Klement Sekera4c533132018-02-22 11:41:12 +0100734 packets = self.dst_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200735 len(self.pkt_infos) - len(dropped_packet_indexes))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800736 self.verify_capture(IPv6, packets, dropped_packet_indexes)
Klement Sekera4c533132018-02-22 11:41:12 +0100737 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200738
739 def test_overlap2(self):
Paul Vinciguerra69555952019-03-01 08:46:29 -0800740 """ overlapping fragments case #2 (differs from IP test case)"""
Klement Sekera75e7d132017-09-20 08:26:30 +0200741
742 fragments = []
Klement Sekera4c533132018-02-22 11:41:12 +0100743 for _, frags_400, frags_300 in self.pkt_infos:
Klement Sekera75e7d132017-09-20 08:26:30 +0200744 if len(frags_400) == 1:
745 fragments.extend(frags_400)
746 else:
747 # care must be taken here so that there are no fragments
748 # received by vpp after reassembly is finished, otherwise
749 # new reassemblies will be started and packet generator will
750 # freak out when it detects unfreed buffers
Klement Sekera4c533132018-02-22 11:41:12 +0100751 zipped = zip(frags_400, frags_300)
Paul Vinciguerrac7834e02019-03-02 10:43:05 -0800752 for i, j in zipped:
Klement Sekera75e7d132017-09-20 08:26:30 +0200753 fragments.extend(i)
754 fragments.extend(j)
Paul Vinciguerrac7834e02019-03-02 10:43:05 -0800755 fragments.pop()
Klement Sekera75e7d132017-09-20 08:26:30 +0200756
757 dropped_packet_indexes = set(
758 index for (index, _, frags) in self.pkt_infos if len(frags) > 1
759 )
760
761 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100762 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200763 self.pg_start()
764
Klement Sekera4c533132018-02-22 11:41:12 +0100765 packets = self.dst_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200766 len(self.pkt_infos) - len(dropped_packet_indexes))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800767 self.verify_capture(IPv6, packets, dropped_packet_indexes)
Klement Sekera4c533132018-02-22 11:41:12 +0100768 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200769
Paul Vinciguerra69555952019-03-01 08:46:29 -0800770 @parameterized.expand([(IPv6, None, None)])
771 def test_timeout_inline(self, family, stream, dropped_packets_index):
Klement Sekera75e7d132017-09-20 08:26:30 +0200772 """ timeout (inline) """
Paul Vinciguerra69555952019-03-01 08:46:29 -0800773 stream = self.__class__.fragments_400
Klement Sekera75e7d132017-09-20 08:26:30 +0200774
775 dropped_packet_indexes = set(
776 index for (index, frags, _) in self.pkt_infos if len(frags) > 1
777 )
Paul Vinciguerra69555952019-03-01 08:46:29 -0800778 super(TestIPv6Reassembly, self).test_timeout_inline(
779 family, stream, dropped_packet_indexes)
Klement Sekera75e7d132017-09-20 08:26:30 +0200780
Klement Sekera4c533132018-02-22 11:41:12 +0100781 pkts = self.src_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200782 expected_count=len(dropped_packet_indexes))
783 for icmp in pkts:
784 self.assertIn(ICMPv6TimeExceeded, icmp)
785 self.assertIn(IPv6ExtHdrFragment, icmp)
786 self.assertIn(icmp[IPv6ExtHdrFragment].id, dropped_packet_indexes)
787 dropped_packet_indexes.remove(icmp[IPv6ExtHdrFragment].id)
788
789 def test_timeout_cleanup(self):
790 """ timeout (cleanup) """
791
792 # whole packets + fragmented packets sans last fragment
793 fragments = [
794 x for (_, frags_400, _) in self.pkt_infos
795 for x in frags_400[:-1 if len(frags_400) > 1 else None]
796 ]
797
798 # last fragments for fragmented packets
799 fragments2 = [frags_400[-1]
800 for (_, frags_400, _) in self.pkt_infos
801 if len(frags_400) > 1]
802
803 dropped_packet_indexes = set(
804 index for (index, frags_400, _) in self.pkt_infos
805 if len(frags_400) > 1)
806
807 self.vapi.ip_reassembly_set(timeout_ms=100, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200808 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200809 expire_walk_interval_ms=50)
810
811 self.vapi.ip_reassembly_set(timeout_ms=100, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200812 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +0200813 expire_walk_interval_ms=50, is_ip6=1)
814
815 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100816 self.src_if.add_stream(fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +0200817 self.pg_start()
818
819 self.sleep(.25, "wait before sending rest of fragments")
820
Klement Sekera4c533132018-02-22 11:41:12 +0100821 self.src_if.add_stream(fragments2)
Klement Sekera75e7d132017-09-20 08:26:30 +0200822 self.pg_start()
Klement Sekera75e7d132017-09-20 08:26:30 +0200823
Klement Sekera4c533132018-02-22 11:41:12 +0100824 packets = self.dst_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200825 len(self.pkt_infos) - len(dropped_packet_indexes))
Paul Vinciguerra69555952019-03-01 08:46:29 -0800826 self.verify_capture(IPv6, packets, dropped_packet_indexes)
Klement Sekera4c533132018-02-22 11:41:12 +0100827 pkts = self.src_if.get_capture(
Klement Sekera75e7d132017-09-20 08:26:30 +0200828 expected_count=len(dropped_packet_indexes))
829 for icmp in pkts:
830 self.assertIn(ICMPv6TimeExceeded, icmp)
831 self.assertIn(IPv6ExtHdrFragment, icmp)
832 self.assertIn(icmp[IPv6ExtHdrFragment].id, dropped_packet_indexes)
833 dropped_packet_indexes.remove(icmp[IPv6ExtHdrFragment].id)
834
Paul Vinciguerra69555952019-03-01 08:46:29 -0800835 @parameterized.expand([(IPv6, None, None)])
836 def test_disabled(self, family, stream, dropped_packet_indexes):
Klement Sekera75e7d132017-09-20 08:26:30 +0200837 """ reassembly disabled """
838
Paul Vinciguerra69555952019-03-01 08:46:29 -0800839 stream = self.__class__.fragments_400
Klement Sekera75e7d132017-09-20 08:26:30 +0200840 dropped_packet_indexes = set(
841 index for (index, frags_400, _) in self.pkt_infos
842 if len(frags_400) > 1)
Paul Vinciguerra69555952019-03-01 08:46:29 -0800843 super(TestIPv6Reassembly, self).test_disabled(
844 family, stream, dropped_packet_indexes)
Klement Sekera4c533132018-02-22 11:41:12 +0100845 self.src_if.assert_nothing_captured()
Klement Sekera75e7d132017-09-20 08:26:30 +0200846
847 def test_missing_upper(self):
848 """ missing upper layer """
Klement Sekera4c533132018-02-22 11:41:12 +0100849 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
850 IPv6(src=self.src_if.remote_ip6,
851 dst=self.src_if.local_ip6) /
852 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +0200853 Raw())
854 self.extend_packet(p, 1000, self.padding)
855 fragments = fragment_rfc8200(p, 1, 500)
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700856 bad_fragment = p.__class__(scapy.compat.raw(fragments[1]))
Klement Sekera75e7d132017-09-20 08:26:30 +0200857 bad_fragment[IPv6ExtHdrFragment].nh = 59
858 bad_fragment[IPv6ExtHdrFragment].offset = 0
859 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100860 self.src_if.add_stream([bad_fragment])
Klement Sekera75e7d132017-09-20 08:26:30 +0200861 self.pg_start()
Klement Sekera4c533132018-02-22 11:41:12 +0100862 pkts = self.src_if.get_capture(expected_count=1)
Klement Sekera75e7d132017-09-20 08:26:30 +0200863 icmp = pkts[0]
864 self.assertIn(ICMPv6ParamProblem, icmp)
865 self.assert_equal(icmp[ICMPv6ParamProblem].code, 3, "ICMP code")
866
867 def test_invalid_frag_size(self):
868 """ fragment size not a multiple of 8 """
Klement Sekera4c533132018-02-22 11:41:12 +0100869 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
870 IPv6(src=self.src_if.remote_ip6,
871 dst=self.src_if.local_ip6) /
872 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +0200873 Raw())
874 self.extend_packet(p, 1000, self.padding)
875 fragments = fragment_rfc8200(p, 1, 500)
876 bad_fragment = fragments[0]
877 self.extend_packet(bad_fragment, len(bad_fragment) + 5)
878 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100879 self.src_if.add_stream([bad_fragment])
Klement Sekera75e7d132017-09-20 08:26:30 +0200880 self.pg_start()
Klement Sekera4c533132018-02-22 11:41:12 +0100881 pkts = self.src_if.get_capture(expected_count=1)
Klement Sekera75e7d132017-09-20 08:26:30 +0200882 icmp = pkts[0]
883 self.assertIn(ICMPv6ParamProblem, icmp)
884 self.assert_equal(icmp[ICMPv6ParamProblem].code, 0, "ICMP code")
885
886 def test_invalid_packet_size(self):
887 """ total packet size > 65535 """
Klement Sekera4c533132018-02-22 11:41:12 +0100888 p = (Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
889 IPv6(src=self.src_if.remote_ip6,
890 dst=self.src_if.local_ip6) /
891 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +0200892 Raw())
893 self.extend_packet(p, 1000, self.padding)
894 fragments = fragment_rfc8200(p, 1, 500)
895 bad_fragment = fragments[1]
896 bad_fragment[IPv6ExtHdrFragment].offset = 65500
897 self.pg_enable_capture()
Klement Sekera4c533132018-02-22 11:41:12 +0100898 self.src_if.add_stream([bad_fragment])
Klement Sekera75e7d132017-09-20 08:26:30 +0200899 self.pg_start()
Klement Sekera4c533132018-02-22 11:41:12 +0100900 pkts = self.src_if.get_capture(expected_count=1)
Klement Sekera75e7d132017-09-20 08:26:30 +0200901 icmp = pkts[0]
902 self.assertIn(ICMPv6ParamProblem, icmp)
903 self.assert_equal(icmp[ICMPv6ParamProblem].code, 0, "ICMP code")
904
905
Juraj Sloboda3048b632018-10-02 11:13:53 +0200906class TestIPv4ReassemblyLocalNode(VppTestCase):
907 """ IPv4 Reassembly for packets coming to ip4-local node """
908
909 @classmethod
910 def setUpClass(cls):
911 super(TestIPv4ReassemblyLocalNode, cls).setUpClass()
912
913 cls.create_pg_interfaces([0])
914 cls.src_dst_if = cls.pg0
915
916 # setup all interfaces
917 for i in cls.pg_interfaces:
918 i.admin_up()
919 i.config_ip4()
920 i.resolve_arp()
921
922 cls.padding = " abcdefghijklmn"
923 cls.create_stream()
924 cls.create_fragments()
925
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -0700926 @classmethod
927 def tearDownClass(cls):
928 super(TestIPv4ReassemblyLocalNode, cls).tearDownClass()
929
Juraj Sloboda3048b632018-10-02 11:13:53 +0200930 def setUp(self):
931 """ Test setup - force timeout on existing reassemblies """
932 super(TestIPv4ReassemblyLocalNode, self).setUp()
933 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200934 max_reassembly_length=1000,
Juraj Sloboda3048b632018-10-02 11:13:53 +0200935 expire_walk_interval_ms=10)
936 self.sleep(.25)
937 self.vapi.ip_reassembly_set(timeout_ms=1000000, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +0200938 max_reassembly_length=1000,
Juraj Sloboda3048b632018-10-02 11:13:53 +0200939 expire_walk_interval_ms=10000)
940
941 def tearDown(self):
942 super(TestIPv4ReassemblyLocalNode, self).tearDown()
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -0700943
944 def show_commands_at_teardown(self):
Juraj Sloboda3048b632018-10-02 11:13:53 +0200945 self.logger.debug(self.vapi.ppcli("show ip4-reassembly details"))
Klement Sekeracae98b72019-02-19 13:53:43 +0100946 self.logger.debug(self.vapi.ppcli("show buffers"))
Juraj Sloboda3048b632018-10-02 11:13:53 +0200947
948 @classmethod
949 def create_stream(cls, packet_count=test_packet_count):
950 """Create input packet stream for defined interface.
951
952 :param list packet_sizes: Required packet sizes.
953 """
954 for i in range(0, packet_count):
955 info = cls.create_packet_info(cls.src_dst_if, cls.src_dst_if)
956 payload = cls.info_to_payload(info)
957 p = (Ether(dst=cls.src_dst_if.local_mac,
958 src=cls.src_dst_if.remote_mac) /
959 IP(id=info.index, src=cls.src_dst_if.remote_ip4,
960 dst=cls.src_dst_if.local_ip4) /
961 ICMP(type='echo-request', id=1234) /
962 Raw(payload))
963 cls.extend_packet(p, 1518, cls.padding)
964 info.data = p
965
966 @classmethod
967 def create_fragments(cls):
968 infos = cls._packet_infos
969 cls.pkt_infos = []
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -0800970 for index, info in six.iteritems(infos):
Juraj Sloboda3048b632018-10-02 11:13:53 +0200971 p = info.data
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700972 # cls.logger.debug(ppp("Packet:",
973 # p.__class__(scapy.compat.raw(p))))
Juraj Sloboda3048b632018-10-02 11:13:53 +0200974 fragments_300 = fragment_rfc791(p, 300)
975 cls.pkt_infos.append((index, fragments_300))
976 cls.fragments_300 = [x for (_, frags) in cls.pkt_infos for x in frags]
977 cls.logger.debug("Fragmented %s packets into %s 300-byte fragments" %
978 (len(infos), len(cls.fragments_300)))
979
980 def verify_capture(self, capture):
981 """Verify captured packet stream.
982
983 :param list capture: Captured packet stream.
984 """
985 info = None
986 seen = set()
987 for packet in capture:
988 try:
989 self.logger.debug(ppp("Got packet:", packet))
990 ip = packet[IP]
991 icmp = packet[ICMP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -0800992 payload_info = self.payload_to_info(packet[Raw])
Juraj Sloboda3048b632018-10-02 11:13:53 +0200993 packet_index = payload_info.index
994 if packet_index in seen:
995 raise Exception(ppp("Duplicate packet received", packet))
996 seen.add(packet_index)
997 self.assertEqual(payload_info.dst, self.src_dst_if.sw_if_index)
998 info = self._packet_infos[packet_index]
Klement Sekera14d7e902018-12-10 13:46:09 +0100999 self.assertIsNotNone(info)
Juraj Sloboda3048b632018-10-02 11:13:53 +02001000 self.assertEqual(packet_index, info.index)
1001 saved_packet = info.data
1002 self.assertEqual(ip.src, saved_packet[IP].dst)
1003 self.assertEqual(ip.dst, saved_packet[IP].src)
1004 self.assertEqual(icmp.type, 0) # echo reply
1005 self.assertEqual(icmp.id, saved_packet[ICMP].id)
1006 self.assertEqual(icmp.payload, saved_packet[ICMP].payload)
1007 except Exception:
1008 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1009 raise
1010 for index in self._packet_infos:
Klement Sekera14d7e902018-12-10 13:46:09 +01001011 self.assertIn(index, seen,
1012 "Packet with packet_index %d not received" % index)
Juraj Sloboda3048b632018-10-02 11:13:53 +02001013
1014 def test_reassembly(self):
1015 """ basic reassembly """
1016
1017 self.pg_enable_capture()
1018 self.src_dst_if.add_stream(self.fragments_300)
1019 self.pg_start()
1020
1021 packets = self.src_dst_if.get_capture(len(self.pkt_infos))
1022 self.verify_capture(packets)
1023
1024 # run it all again to verify correctness
1025 self.pg_enable_capture()
1026 self.src_dst_if.add_stream(self.fragments_300)
1027 self.pg_start()
1028
1029 packets = self.src_dst_if.get_capture(len(self.pkt_infos))
1030 self.verify_capture(packets)
1031
1032
Klement Sekera75e7d132017-09-20 08:26:30 +02001033class TestFIFReassembly(VppTestCase):
1034 """ Fragments in fragments reassembly """
1035
1036 @classmethod
1037 def setUpClass(cls):
1038 super(TestFIFReassembly, cls).setUpClass()
1039
Klement Sekera4c533132018-02-22 11:41:12 +01001040 cls.create_pg_interfaces([0, 1])
1041 cls.src_if = cls.pg0
1042 cls.dst_if = cls.pg1
1043 for i in cls.pg_interfaces:
1044 i.admin_up()
1045 i.config_ip4()
1046 i.resolve_arp()
1047 i.config_ip6()
1048 i.resolve_ndp()
Klement Sekera75e7d132017-09-20 08:26:30 +02001049
Klement Sekera75e7d132017-09-20 08:26:30 +02001050 cls.packet_sizes = [64, 512, 1518, 9018]
1051 cls.padding = " abcdefghijklmn"
1052
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001053 @classmethod
1054 def tearDownClass(cls):
1055 super(TestFIFReassembly, cls).tearDownClass()
1056
Klement Sekera75e7d132017-09-20 08:26:30 +02001057 def setUp(self):
1058 """ Test setup - force timeout on existing reassemblies """
1059 super(TestFIFReassembly, self).setUp()
Klement Sekera4c533132018-02-22 11:41:12 +01001060 self.vapi.ip_reassembly_enable_disable(
1061 sw_if_index=self.src_if.sw_if_index, enable_ip4=True,
1062 enable_ip6=True)
1063 self.vapi.ip_reassembly_enable_disable(
1064 sw_if_index=self.dst_if.sw_if_index, enable_ip4=True,
1065 enable_ip6=True)
Klement Sekera75e7d132017-09-20 08:26:30 +02001066 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +02001067 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +02001068 expire_walk_interval_ms=10)
1069 self.vapi.ip_reassembly_set(timeout_ms=0, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +02001070 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +02001071 expire_walk_interval_ms=10, is_ip6=1)
1072 self.sleep(.25)
1073 self.vapi.ip_reassembly_set(timeout_ms=1000000, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +02001074 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +02001075 expire_walk_interval_ms=10000)
1076 self.vapi.ip_reassembly_set(timeout_ms=1000000, max_reassemblies=1000,
Klement Sekera3a343d42019-05-16 14:35:46 +02001077 max_reassembly_length=1000,
Klement Sekera75e7d132017-09-20 08:26:30 +02001078 expire_walk_interval_ms=10000, is_ip6=1)
1079
1080 def tearDown(self):
Paul Vinciguerra90cf21b2019-03-13 09:23:05 -07001081 super(TestFIFReassembly, self).tearDown()
1082
1083 def show_commands_at_teardown(self):
Klement Sekera75e7d132017-09-20 08:26:30 +02001084 self.logger.debug(self.vapi.ppcli("show ip4-reassembly details"))
1085 self.logger.debug(self.vapi.ppcli("show ip6-reassembly details"))
Klement Sekeracae98b72019-02-19 13:53:43 +01001086 self.logger.debug(self.vapi.ppcli("show buffers"))
Klement Sekera75e7d132017-09-20 08:26:30 +02001087
1088 def verify_capture(self, capture, ip_class, dropped_packet_indexes=[]):
1089 """Verify captured packet stream.
1090
1091 :param list capture: Captured packet stream.
1092 """
1093 info = None
1094 seen = set()
1095 for packet in capture:
1096 try:
Klement Sekera4c533132018-02-22 11:41:12 +01001097 self.logger.debug(ppp("Got packet:", packet))
Klement Sekera75e7d132017-09-20 08:26:30 +02001098 ip = packet[ip_class]
1099 udp = packet[UDP]
Paul Vinciguerraeaea4212019-03-06 11:58:06 -08001100 payload_info = self.payload_to_info(packet[Raw])
Klement Sekera75e7d132017-09-20 08:26:30 +02001101 packet_index = payload_info.index
1102 self.assertTrue(
1103 packet_index not in dropped_packet_indexes,
1104 ppp("Packet received, but should be dropped:", packet))
1105 if packet_index in seen:
1106 raise Exception(ppp("Duplicate packet received", packet))
1107 seen.add(packet_index)
Klement Sekera4c533132018-02-22 11:41:12 +01001108 self.assertEqual(payload_info.dst, self.dst_if.sw_if_index)
Klement Sekera75e7d132017-09-20 08:26:30 +02001109 info = self._packet_infos[packet_index]
1110 self.assertTrue(info is not None)
1111 self.assertEqual(packet_index, info.index)
1112 saved_packet = info.data
1113 self.assertEqual(ip.src, saved_packet[ip_class].src)
1114 self.assertEqual(ip.dst, saved_packet[ip_class].dst)
1115 self.assertEqual(udp.payload, saved_packet[UDP].payload)
Klement Sekera4c533132018-02-22 11:41:12 +01001116 except Exception:
Klement Sekera75e7d132017-09-20 08:26:30 +02001117 self.logger.error(ppp("Unexpected or invalid packet:", packet))
1118 raise
1119 for index in self._packet_infos:
1120 self.assertTrue(index in seen or index in dropped_packet_indexes,
1121 "Packet with packet_index %d not received" % index)
1122
1123 def test_fif4(self):
1124 """ Fragments in fragments (4o4) """
1125
1126 # TODO this should be ideally in setUpClass, but then we hit a bug
1127 # with VppIpRoute incorrectly reporting it's present when it's not
1128 # so we need to manually remove the vpp config, thus we cannot have
1129 # it shared for multiple test cases
1130 self.tun_ip4 = "1.1.1.2"
1131
Klement Sekera4c533132018-02-22 11:41:12 +01001132 self.gre4 = VppGreInterface(self, self.src_if.local_ip4, self.tun_ip4)
Klement Sekera75e7d132017-09-20 08:26:30 +02001133 self.gre4.add_vpp_config()
1134 self.gre4.admin_up()
1135 self.gre4.config_ip4()
1136
Klement Sekera4c533132018-02-22 11:41:12 +01001137 self.vapi.ip_reassembly_enable_disable(
1138 sw_if_index=self.gre4.sw_if_index, enable_ip4=True)
1139
Klement Sekera75e7d132017-09-20 08:26:30 +02001140 self.route4 = VppIpRoute(self, self.tun_ip4, 32,
Klement Sekera4c533132018-02-22 11:41:12 +01001141 [VppRoutePath(self.src_if.remote_ip4,
1142 self.src_if.sw_if_index)])
Klement Sekera75e7d132017-09-20 08:26:30 +02001143 self.route4.add_vpp_config()
1144
1145 self.reset_packet_infos()
1146 for i in range(test_packet_count):
Klement Sekera4c533132018-02-22 11:41:12 +01001147 info = self.create_packet_info(self.src_if, self.dst_if)
Klement Sekera75e7d132017-09-20 08:26:30 +02001148 payload = self.info_to_payload(info)
Klement Sekera4c533132018-02-22 11:41:12 +01001149 # Ethernet header here is only for size calculation, thus it
1150 # doesn't matter how it's initialized. This is to ensure that
1151 # reassembled packet is not > 9000 bytes, so that it's not dropped
1152 p = (Ether() /
1153 IP(id=i, src=self.src_if.remote_ip4,
1154 dst=self.dst_if.remote_ip4) /
1155 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +02001156 Raw(payload))
1157 size = self.packet_sizes[(i // 2) % len(self.packet_sizes)]
1158 self.extend_packet(p, size, self.padding)
Klement Sekera4c533132018-02-22 11:41:12 +01001159 info.data = p[IP] # use only IP part, without ethernet header
Klement Sekera75e7d132017-09-20 08:26:30 +02001160
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -08001161 fragments = [x for _, p in six.iteritems(self._packet_infos)
Klement Sekera75e7d132017-09-20 08:26:30 +02001162 for x in fragment_rfc791(p.data, 400)]
1163
1164 encapped_fragments = \
Klement Sekera4c533132018-02-22 11:41:12 +01001165 [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1166 IP(src=self.tun_ip4, dst=self.src_if.local_ip4) /
Klement Sekera75e7d132017-09-20 08:26:30 +02001167 GRE() /
1168 p
1169 for p in fragments]
1170
1171 fragmented_encapped_fragments = \
1172 [x for p in encapped_fragments
1173 for x in fragment_rfc791(p, 200)]
1174
Klement Sekera4c533132018-02-22 11:41:12 +01001175 self.src_if.add_stream(fragmented_encapped_fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +02001176
1177 self.pg_enable_capture(self.pg_interfaces)
1178 self.pg_start()
1179
Klement Sekera4c533132018-02-22 11:41:12 +01001180 self.src_if.assert_nothing_captured()
1181 packets = self.dst_if.get_capture(len(self._packet_infos))
Klement Sekera75e7d132017-09-20 08:26:30 +02001182 self.verify_capture(packets, IP)
1183
1184 # TODO remove gre vpp config by hand until VppIpRoute gets fixed
1185 # so that it's query_vpp_config() works as it should
1186 self.gre4.remove_vpp_config()
Klement Sekera4c533132018-02-22 11:41:12 +01001187 self.logger.debug(self.vapi.ppcli("show interface"))
Klement Sekera75e7d132017-09-20 08:26:30 +02001188
1189 def test_fif6(self):
1190 """ Fragments in fragments (6o6) """
1191 # TODO this should be ideally in setUpClass, but then we hit a bug
1192 # with VppIpRoute incorrectly reporting it's present when it's not
1193 # so we need to manually remove the vpp config, thus we cannot have
1194 # it shared for multiple test cases
1195 self.tun_ip6 = "1002::1"
1196
Neale Ranns5a8844b2019-04-16 07:15:35 +00001197 self.gre6 = VppGreInterface(self, self.src_if.local_ip6, self.tun_ip6)
Klement Sekera75e7d132017-09-20 08:26:30 +02001198 self.gre6.add_vpp_config()
1199 self.gre6.admin_up()
1200 self.gre6.config_ip6()
1201
Klement Sekera4c533132018-02-22 11:41:12 +01001202 self.vapi.ip_reassembly_enable_disable(
1203 sw_if_index=self.gre6.sw_if_index, enable_ip6=True)
1204
Klement Sekera75e7d132017-09-20 08:26:30 +02001205 self.route6 = VppIpRoute(self, self.tun_ip6, 128,
Neale Ranns097fa662018-05-01 05:17:55 -07001206 [VppRoutePath(
1207 self.src_if.remote_ip6,
1208 self.src_if.sw_if_index)])
Klement Sekera75e7d132017-09-20 08:26:30 +02001209 self.route6.add_vpp_config()
1210
1211 self.reset_packet_infos()
1212 for i in range(test_packet_count):
Klement Sekera4c533132018-02-22 11:41:12 +01001213 info = self.create_packet_info(self.src_if, self.dst_if)
Klement Sekera75e7d132017-09-20 08:26:30 +02001214 payload = self.info_to_payload(info)
Klement Sekera4c533132018-02-22 11:41:12 +01001215 # Ethernet header here is only for size calculation, thus it
1216 # doesn't matter how it's initialized. This is to ensure that
1217 # reassembled packet is not > 9000 bytes, so that it's not dropped
1218 p = (Ether() /
1219 IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6) /
1220 UDP(sport=1234, dport=5678) /
Klement Sekera75e7d132017-09-20 08:26:30 +02001221 Raw(payload))
1222 size = self.packet_sizes[(i // 2) % len(self.packet_sizes)]
1223 self.extend_packet(p, size, self.padding)
Klement Sekera4c533132018-02-22 11:41:12 +01001224 info.data = p[IPv6] # use only IPv6 part, without ethernet header
Klement Sekera75e7d132017-09-20 08:26:30 +02001225
Paul Vinciguerraf1f2aa62018-11-25 08:36:47 -08001226 fragments = [x for _, i in six.iteritems(self._packet_infos)
Klement Sekera75e7d132017-09-20 08:26:30 +02001227 for x in fragment_rfc8200(
1228 i.data, i.index, 400)]
1229
1230 encapped_fragments = \
Klement Sekera4c533132018-02-22 11:41:12 +01001231 [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) /
1232 IPv6(src=self.tun_ip6, dst=self.src_if.local_ip6) /
Klement Sekera75e7d132017-09-20 08:26:30 +02001233 GRE() /
1234 p
1235 for p in fragments]
1236
1237 fragmented_encapped_fragments = \
1238 [x for p in encapped_fragments for x in (
1239 fragment_rfc8200(
1240 p,
1241 2 * len(self._packet_infos) + p[IPv6ExtHdrFragment].id,
1242 200)
1243 if IPv6ExtHdrFragment in p else [p]
1244 )
1245 ]
1246
Klement Sekera4c533132018-02-22 11:41:12 +01001247 self.src_if.add_stream(fragmented_encapped_fragments)
Klement Sekera75e7d132017-09-20 08:26:30 +02001248
1249 self.pg_enable_capture(self.pg_interfaces)
1250 self.pg_start()
1251
Klement Sekera4c533132018-02-22 11:41:12 +01001252 self.src_if.assert_nothing_captured()
1253 packets = self.dst_if.get_capture(len(self._packet_infos))
Klement Sekera75e7d132017-09-20 08:26:30 +02001254 self.verify_capture(packets, IPv6)
1255
1256 # TODO remove gre vpp config by hand until VppIpRoute gets fixed
1257 # so that it's query_vpp_config() works as it should
Klement Sekera3ecc2212018-03-27 10:34:43 +02001258 self.gre6.remove_vpp_config()
Klement Sekera75e7d132017-09-20 08:26:30 +02001259
1260
1261if __name__ == '__main__':
1262 unittest.main(testRunner=VppTestRunner)