Flowprobe: Stateful flows and IPv6, L4 recording
[vpp.git] / test / test_flowprobe.py
1 #!/usr/bin/env python
2 import random
3 import socket
4 import unittest
5 import time
6
7 from scapy.packet import Raw
8 from scapy.layers.l2 import Ether
9 from scapy.layers.inet import IP, UDP
10 from scapy.layers.inet6 import IPv6
11
12 from framework import VppTestCase, VppTestRunner
13 from vpp_object import VppObject
14 from vpp_pg_interface import CaptureTimeoutError
15 from util import ppp
16 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
17
18
19 class VppCFLOW(VppObject):
20     """CFLOW object for IPFIX exporter and Flowprobe feature"""
21
22     def __init__(self, test, intf='pg2', active=0, passive=0, timeout=300,
23                  mtu=512, datapath='l2', layer='l2 l3 l4'):
24         self._test = test
25         self._intf = intf
26         self._active = active
27         if passive == 0 or passive < active:
28             self._passive = active+5
29         else:
30             self._passive = passive
31         self._datapath = datapath           # l2 ip4 ip6
32         self._collect = layer               # l2 l3 l4
33         self._timeout = timeout
34         self._mtu = mtu
35         self._configured = False
36
37     def add_vpp_config(self):
38         self.enable_exporter()
39         self._test.vapi.ppcli("flowprobe params record %s active %s "
40                               "passive %s" % (self._collect, self._active,
41                                               self._passive))
42         self.enable_flowprobe_feature()
43         self._test.vapi.cli("ipfix flush")
44         self._configured = True
45
46     def remove_vpp_config(self):
47         self.disable_exporter()
48         self.disable_flowprobe_feature()
49         self._test.vapi.cli("ipfix flush")
50         self._configured = False
51
52     def enable_exporter(self):
53         self._test.vapi.set_ipfix_exporter(
54             collector_address=self._test.pg0.remote_ip4n,
55             src_address=self._test.pg0.local_ip4n,
56             path_mtu=self._mtu,
57             template_interval=self._timeout)
58
59     def enable_flowprobe_feature(self):
60         self._test.vapi.ppcli("flowprobe feature add-del %s %s" %
61                               (self._intf, self._datapath))
62
63     def disable_exporter(self):
64         self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
65
66     def disable_flowprobe_feature(self):
67         self._test.vapi.cli("flowprobe feature add-del %s %s disable" %
68                             (self._intf, self._datapath))
69
70     def object_id(self):
71         return "ipfix-collector-%s" % (self._src, self.dst)
72
73     def query_vpp_config(self):
74         return self._configured
75
76     def verify_templates(self, decoder=None, timeout=1, count=3):
77         templates = []
78         p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
79         self._test.assertTrue(p.haslayer(IPFIX))
80         if decoder is not None and p.haslayer(Template):
81             templates.append(p[Template].templateID)
82             decoder.add_template(p.getlayer(Template))
83         if count > 1:
84             p = self._test.wait_for_cflow_packet(self._test.collector, 2)
85             self._test.assertTrue(p.haslayer(IPFIX))
86             if decoder is not None and p.haslayer(Template):
87                 templates.append(p[Template].templateID)
88                 decoder.add_template(p.getlayer(Template))
89         if count > 2:
90             p = self._test.wait_for_cflow_packet(self._test.collector, 2)
91             self._test.assertTrue(p.haslayer(IPFIX))
92             if decoder is not None and p.haslayer(Template):
93                 templates.append(p[Template].templateID)
94                 decoder.add_template(p.getlayer(Template))
95         return templates
96
97
98 class MethodHolder(VppTestCase):
99     """ Flow-per-packet plugin: test L2, IP4, IP6 reporting """
100
101     # Test variables
102     debug_print = False
103     max_number_of_packets = 16
104     pkts = []
105
106     @classmethod
107     def setUpClass(cls):
108         """
109         Perform standard class setup (defined by class method setUpClass in
110         class VppTestCase) before running the test case, set test case related
111         variables and configure VPP.
112         """
113         super(MethodHolder, cls).setUpClass()
114         try:
115             # Create pg interfaces
116             cls.create_pg_interfaces(range(7))
117
118             # Packet sizes
119             cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
120
121             # Create BD with MAC learning and unknown unicast flooding disabled
122             # and put interfaces to this BD
123             cls.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1, learn=1)
124             cls.vapi.sw_interface_set_l2_bridge(cls.pg1._sw_if_index, bd_id=1)
125             cls.vapi.sw_interface_set_l2_bridge(cls.pg2._sw_if_index, bd_id=1)
126
127             # Set up all interfaces
128             for i in cls.pg_interfaces:
129                 i.admin_up()
130
131             cls.pg0.config_ip4()
132             cls.pg0.configure_ipv4_neighbors()
133             cls.collector = cls.pg0
134
135             cls.pg1.config_ip4()
136             cls.pg1.resolve_arp()
137             cls.pg2.config_ip4()
138             cls.pg2.resolve_arp()
139             cls.pg3.config_ip4()
140             cls.pg3.resolve_arp()
141             cls.pg4.config_ip4()
142             cls.pg4.resolve_arp()
143
144             cls.pg5.config_ip6()
145             cls.pg5.resolve_ndp()
146             cls.pg5.disable_ipv6_ra()
147             cls.pg6.config_ip6()
148             cls.pg6.resolve_ndp()
149             cls.pg6.disable_ipv6_ra()
150         except Exception:
151             super(MethodHolder, cls).tearDownClass()
152             raise
153
154     def create_stream(self, src_if=None, dst_if=None, packets=None,
155                       size=None, ip_ver='v4'):
156         """Create a packet stream to tickle the plugin
157
158         :param VppInterface src_if: Source interface for packet stream
159         :param VppInterface src_if: Dst interface for packet stream
160         """
161         if src_if is None:
162             src_if = self.pg1
163         if dst_if is None:
164             dst_if = self.pg2
165         self.pkts = []
166         if packets is None:
167             packets = random.randint(1, self.max_number_of_packets)
168         pkt_size = size
169         for p in range(0, packets):
170             if size is None:
171                 pkt_size = random.choice(self.pg_if_packet_sizes)
172             info = self.create_packet_info(src_if, dst_if)
173             payload = self.info_to_payload(info)
174             p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
175             if ip_ver == 'v4':
176                 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
177             else:
178                 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
179             p /= (UDP(sport=1234, dport=4321) / Raw(payload))
180             info.data = p.copy()
181             self.extend_packet(p, pkt_size)
182             self.pkts.append(p)
183
184     def verify_cflow_data(self, decoder, capture, cflow):
185         octets = 0
186         packets = 0
187         for p in capture:
188             octets += p[IP].len
189             packets += 1
190         if cflow.haslayer(Data):
191             data = decoder.decode_data_set(cflow.getlayer(Set))
192             for record in data:
193                 self.assertEqual(int(record[1].encode('hex'), 16), octets)
194                 self.assertEqual(int(record[2].encode('hex'), 16), packets)
195
196     def verify_cflow_data_detail(self, decoder, capture, cflow,
197                                  data_set={1: 'octets', 2: 'packets'},
198                                  ip_ver='v4'):
199         if self.debug_print:
200             print capture[0].show()
201         if cflow.haslayer(Data):
202             data = decoder.decode_data_set(cflow.getlayer(Set))
203             if self.debug_print:
204                 print data
205             if ip_ver == 'v4':
206                 ip_layer = capture[0][IP]
207             else:
208                 ip_layer = capture[0][IPv6]
209             if data_set is not None:
210                 for record in data:
211                     # skip flow if in/out gress interface is 0
212                     if int(record[10].encode('hex'), 16) == 0:
213                         continue
214                     if int(record[14].encode('hex'), 16) == 0:
215                         continue
216
217                     for field in data_set:
218                         if field not in record.keys():
219                             continue
220                         value = data_set[field]
221                         if value == 'octets':
222                             value = ip_layer.len
223                             if ip_ver == 'v6':
224                                 value += 40        # ??? is this correct
225                         elif value == 'packets':
226                             value = 1
227                         elif value == 'src_ip':
228                             if ip_ver == 'v4':
229                                 ip = socket.inet_pton(socket.AF_INET,
230                                                       ip_layer.src)
231                             else:
232                                 ip = socket.inet_pton(socket.AF_INET6,
233                                                       ip_layer.src)
234                             value = int(ip.encode('hex'), 16)
235                         elif value == 'dst_ip':
236                             if ip_ver == 'v4':
237                                 ip = socket.inet_pton(socket.AF_INET,
238                                                       ip_layer.dst)
239                             else:
240                                 ip = socket.inet_pton(socket.AF_INET6,
241                                                       ip_layer.dst)
242                             value = int(ip.encode('hex'), 16)
243                         elif value == 'sport':
244                             value = int(capture[0][UDP].sport)
245                         elif value == 'dport':
246                             value = int(capture[0][UDP].dport)
247                         self.assertEqual(int(record[field].encode('hex'), 16),
248                                          value)
249
250     def verify_cflow_data_notimer(self, decoder, capture, cflows):
251         idx = 0
252         for cflow in cflows:
253             if cflow.haslayer(Data):
254                 data = decoder.decode_data_set(cflow.getlayer(Set))
255             else:
256                 raise Exception("No CFLOW data")
257
258             for rec in data:
259                 p = capture[idx]
260                 idx += 1
261                 self.assertEqual(p[IP].len, int(rec[1].encode('hex'), 16))
262                 self.assertEqual(1, int(rec[2].encode('hex'), 16))
263         self.assertEqual(len(capture), idx)
264
265     def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1,
266                               expected=True):
267         """ wait for CFLOW packet and verify its correctness
268
269         :param timeout: how long to wait
270
271         :returns: tuple (packet, time spent waiting for packet)
272         """
273         self.logger.info("IPFIX: Waiting for CFLOW packet")
274         deadline = time.time() + timeout
275         counter = 0
276         # self.logger.debug(self.vapi.ppcli("show flow table"))
277         while True:
278             counter += 1
279             # sanity check
280             self.assert_in_range(counter, 0, 100, "number of packets ignored")
281             time_left = deadline - time.time()
282             try:
283                 if time_left < 0 and expected:
284                     # self.logger.debug(self.vapi.ppcli("show flow table"))
285                     raise CaptureTimeoutError(
286                           "Packet did not arrive within timeout")
287                 p = collector_intf.wait_for_packet(timeout=time_left)
288             except CaptureTimeoutError:
289                 if expected:
290                     # self.logger.debug(self.vapi.ppcli("show flow table"))
291                     raise CaptureTimeoutError(
292                           "Packet did not arrive within timeout")
293                 else:
294                     return
295             if not expected:
296                 raise CaptureTimeoutError("Packet arrived even not expected")
297             self.assertEqual(p[Set].setID, set_id)
298             # self.logger.debug(self.vapi.ppcli("show flow table"))
299             self.logger.debug(ppp("IPFIX: Got packet:", p))
300             break
301         return p
302
303     def send_packets(self, src_if=None, dst_if=None):
304         self.sleep(3)
305         if src_if is None:
306             src_if = self.pg1
307         if dst_if is None:
308             dst_if = self.pg2
309         self.pg_enable_capture([dst_if])
310         src_if.add_stream(self.pkts)
311         self.pg_start()
312         return dst_if.get_capture(len(self.pkts))
313
314
315 class TestFFP_Timers(MethodHolder):
316     """Template verification, timer tests"""
317
318     def test_0001(self):
319         """ receive template data packets"""
320         self.logger.info("FFP_TEST_START_0001")
321         self.pg_enable_capture(self.pg_interfaces)
322
323         ipfix = VppCFLOW(test=self, active=10)
324         ipfix.add_vpp_config()
325
326         # template packet should arrive immediately
327         ipfix.verify_templates(timeout=3)
328
329         ipfix.remove_vpp_config()
330         self.logger.info("FFP_TEST_FINISH_0001")
331
332     def test_0002(self):
333         """ timer=10s, less than template timeout"""
334         self.logger.info("FFP_TEST_START_0002")
335         self.pg_enable_capture(self.pg_interfaces)
336         self.pkts = []
337
338         ipfix = VppCFLOW(test=self, active=20)
339         ipfix.add_vpp_config()
340
341         ipfix_decoder = IPFIXDecoder()
342         # template packet should arrive immediately
343         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
344
345         self.create_stream()
346         capture = self.send_packets()
347
348         # make sure the one packet we expect actually showed up
349         cflow = self.wait_for_cflow_packet(self.collector, templates[1], 39)
350         self.verify_cflow_data(ipfix_decoder, capture, cflow)
351
352         ipfix.remove_vpp_config()
353         self.logger.info("FFP_TEST_FINISH_0002")
354
355     def test_0003(self):
356         """ timer=30s, greater than template timeout"""
357         self.logger.info("FFP_TEST_START_0003")
358         self.pg_enable_capture(self.pg_interfaces)
359         self.pkts = []
360
361         ipfix = VppCFLOW(test=self, timeout=20, active=25)
362         ipfix.add_vpp_config()
363
364         ipfix_decoder = IPFIXDecoder()
365         # template packet should arrive immediately
366         ipfix.verify_templates(timeout=3)
367
368         self.create_stream()
369         capture = self.send_packets()
370
371         # next set of template packet should arrive after 20 seconds
372         # template packet should arrive within 20 s
373         templates = ipfix.verify_templates(ipfix_decoder, timeout=25)
374
375         # make sure the one packet we expect actually showed up
376         cflow = self.wait_for_cflow_packet(self.collector, templates[1], 55)
377         self.verify_cflow_data(ipfix_decoder, capture, cflow)
378
379         ipfix.remove_vpp_config()
380         self.logger.info("FFP_TEST_FINISH_0003")
381
382     def test_0004(self):
383         """ sent packet after first cflow packet arrived"""
384         self.logger.info("FFP_TEST_START_0004")
385         self.pg_enable_capture(self.pg_interfaces)
386         self.pkts = []
387
388         ipfix = VppCFLOW(test=self, active=20)
389         ipfix.add_vpp_config()
390
391         ipfix_decoder = IPFIXDecoder()
392         # template packet should arrive immediately
393         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
394
395         self.create_stream()
396         self.send_packets()
397
398         # make sure the one packet we expect actually showed up
399         self.wait_for_cflow_packet(self.collector, templates[1], 39)
400
401         self.pg_enable_capture([self.pg2])
402
403         capture = self.send_packets()
404
405         # make sure the one packet we expect actually showed up
406         cflow = self.wait_for_cflow_packet(self.collector, templates[1], 30)
407         self.verify_cflow_data(ipfix_decoder, capture, cflow)
408
409         ipfix.remove_vpp_config()
410         self.logger.info("FFP_TEST_FINISH_0004")
411
412
413 class TestFFP_DatapathL2(MethodHolder):
414     """collect information on Ethernet datapath"""
415
416     def test_0000(self):
417         """ verify template on L2 datapath"""
418         self.logger.info("FFP_TEST_START_0000")
419         self.pg_enable_capture(self.pg_interfaces)
420
421         ipfix = VppCFLOW(test=self, active=10)
422         ipfix.add_vpp_config()
423
424         # template packet should arrive immediately
425         ipfix.verify_templates(timeout=3, count=3)
426         self.collector.get_capture(3)
427
428         ipfix.remove_vpp_config()
429         self.logger.info("FFP_TEST_FINISH_0000")
430
431     def test_0001(self):
432         """ L2 data on L2 datapath"""
433         self.logger.info("FFP_TEST_START_0001")
434         self.pg_enable_capture(self.pg_interfaces)
435         self.pkts = []
436
437         ipfix = VppCFLOW(test=self, active=10, layer='l2')
438         ipfix.add_vpp_config()
439
440         ipfix_decoder = IPFIXDecoder()
441         # template packet should arrive immediately
442         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
443
444         self.create_stream(packets=1)
445         capture = self.send_packets()
446
447         # make sure the one packet we expect actually showed up
448         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
449         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
450                                       {2: 'packets', 256: 8})
451
452         # expected two templates and one cflow packet
453         self.collector.get_capture(2)
454
455         ipfix.remove_vpp_config()
456         self.logger.info("FFP_TEST_FINISH_0001")
457
458     def test_0002(self):
459         """ L3 data on L2 datapath"""
460         self.logger.info("FFP_TEST_START_0002")
461         self.pg_enable_capture(self.pg_interfaces)
462         self.pkts = []
463
464         ipfix = VppCFLOW(test=self, active=10, layer='l3')
465         ipfix.add_vpp_config()
466
467         ipfix_decoder = IPFIXDecoder()
468         # template packet should arrive immediately
469         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=2)
470
471         self.create_stream(packets=1)
472         capture = self.send_packets()
473
474         # make sure the one packet we expect actually showed up
475         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
476         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
477                                       {2: 'packets', 4: 17,
478                                        8: 'src_ip', 12: 'dst_ip'})
479
480         # expected one template and one cflow packet
481         self.collector.get_capture(3)
482
483         ipfix.remove_vpp_config()
484         self.logger.info("FFP_TEST_FINISH_0002")
485
486     def test_0003(self):
487         """ L4 data on L2 datapath"""
488         self.logger.info("FFP_TEST_START_0003")
489         self.pg_enable_capture(self.pg_interfaces)
490         self.pkts = []
491
492         ipfix = VppCFLOW(test=self, active=10, layer='l4')
493         ipfix.add_vpp_config()
494
495         ipfix_decoder = IPFIXDecoder()
496         # template packet should arrive immediately
497         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=2)
498
499         self.create_stream(packets=1)
500         capture = self.send_packets()
501
502         # make sure the one packet we expect actually showed up
503         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
504         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
505                                       {2: 'packets', 7: 'sport', 11: 'dport'})
506
507         # expected one template and one cflow packet
508         self.collector.get_capture(3)
509
510         ipfix.remove_vpp_config()
511         self.logger.info("FFP_TEST_FINISH_0003")
512
513
514 class TestFFP_DatapathIP4(MethodHolder):
515     """collect information on IP4 datapath"""
516
517     def test_0000(self):
518         """ verify templates on IP4 datapath"""
519         self.logger.info("FFP_TEST_START_0000")
520
521         self.pg_enable_capture(self.pg_interfaces)
522
523         ipfix = VppCFLOW(test=self, active=10, datapath='ip4')
524         ipfix.add_vpp_config()
525
526         # template packet should arrive immediately
527         ipfix.verify_templates(timeout=3, count=1)
528         self.collector.get_capture(1)
529
530         ipfix.remove_vpp_config()
531
532         self.logger.info("FFP_TEST_FINISH_0000")
533
534     def test_0001(self):
535         """ L2 data on IP4 datapath"""
536         self.logger.info("FFP_TEST_START_0001")
537         self.pg_enable_capture(self.pg_interfaces)
538         self.pkts = []
539
540         ipfix = VppCFLOW(test=self, intf='pg4', active=10,
541                          layer='l2', datapath='ip4')
542         ipfix.add_vpp_config()
543
544         ipfix_decoder = IPFIXDecoder()
545         # template packet should arrive immediately
546         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
547
548         self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
549         capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
550
551         # make sure the one packet we expect actually showed up
552         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
553         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
554                                       {2: 'packets', 256: 8})
555
556         # expected two templates and one cflow packet
557         self.collector.get_capture(2)
558
559         ipfix.remove_vpp_config()
560         self.logger.info("FFP_TEST_FINISH_0001")
561
562     def test_0002(self):
563         """ L3 data on IP4 datapath"""
564         self.logger.info("FFP_TEST_START_0002")
565         self.pg_enable_capture(self.pg_interfaces)
566         self.pkts = []
567
568         ipfix = VppCFLOW(test=self, intf='pg4', active=10,
569                          layer='l3', datapath='ip4')
570         ipfix.add_vpp_config()
571
572         ipfix_decoder = IPFIXDecoder()
573         # template packet should arrive immediately
574         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
575
576         self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
577         capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
578
579         # make sure the one packet we expect actually showed up
580         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
581         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
582                                       {1: 'octets', 2: 'packets',
583                                        8: 'src_ip', 12: 'dst_ip'})
584
585         # expected two templates and one cflow packet
586         self.collector.get_capture(2)
587
588         ipfix.remove_vpp_config()
589         self.logger.info("FFP_TEST_FINISH_0002")
590
591     def test_0003(self):
592         """ L4 data on IP4 datapath"""
593         self.logger.info("FFP_TEST_START_0003")
594         self.pg_enable_capture(self.pg_interfaces)
595         self.pkts = []
596
597         ipfix = VppCFLOW(test=self, intf='pg4', active=10,
598                          layer='l4', datapath='ip4')
599         ipfix.add_vpp_config()
600
601         ipfix_decoder = IPFIXDecoder()
602         # template packet should arrive immediately
603         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
604
605         self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
606         capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
607
608         # make sure the one packet we expect actually showed up
609         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
610         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
611                                       {2: 'packets', 7: 'sport', 11: 'dport'})
612
613         # expected two templates and one cflow packet
614         self.collector.get_capture(2)
615
616         ipfix.remove_vpp_config()
617         self.logger.info("FFP_TEST_FINISH_0003")
618
619
620 class TestFFP_DatapathIP6(MethodHolder):
621     """collect information on IP6 datapath"""
622
623     def test_0000(self):
624         """ verify templates on IP6 datapath"""
625         self.logger.info("FFP_TEST_START_0000")
626         self.pg_enable_capture(self.pg_interfaces)
627
628         ipfix = VppCFLOW(test=self, active=10, datapath='ip6')
629         ipfix.add_vpp_config()
630
631         # template packet should arrive immediately
632         ipfix.verify_templates(timeout=3, count=1)
633         self.collector.get_capture(1)
634
635         ipfix.remove_vpp_config()
636
637         self.logger.info("FFP_TEST_FINISH_0000")
638
639     def test_0001(self):
640         """ L2 data on IP6 datapath"""
641         self.logger.info("FFP_TEST_START_0001")
642         self.pg_enable_capture(self.pg_interfaces)
643         self.pkts = []
644
645         ipfix = VppCFLOW(test=self, intf='pg6', active=20,
646                          layer='l2', datapath='ip6')
647         ipfix.add_vpp_config()
648
649         ipfix_decoder = IPFIXDecoder()
650         # template packet should arrive immediately
651         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
652
653         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
654                            ip_ver='IPv6')
655         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
656
657         # make sure the one packet we expect actually showed up
658         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
659         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
660                                       {2: 'packets', 256: 56710},
661                                       ip_ver='v6')
662
663         # expected two templates and one cflow packet
664         self.collector.get_capture(2)
665
666         ipfix.remove_vpp_config()
667         self.logger.info("FFP_TEST_FINISH_0001")
668
669     def test_0002(self):
670         """ L3 data on IP6 datapath"""
671         self.logger.info("FFP_TEST_START_0002")
672         self.pg_enable_capture(self.pg_interfaces)
673         self.pkts = []
674
675         ipfix = VppCFLOW(test=self, intf='pg6', active=10,
676                          layer='l3', datapath='ip6')
677         ipfix.add_vpp_config()
678
679         ipfix_decoder = IPFIXDecoder()
680         # template packet should arrive immediately
681         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
682
683         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
684                            ip_ver='IPv6')
685         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
686
687         # make sure the one packet we expect actually showed up
688         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
689         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
690                                       {2: 'packets',
691                                        27: 'src_ip', 28: 'dst_ip'},
692                                       ip_ver='v6')
693
694         # expected two templates and one cflow packet
695         self.collector.get_capture(2)
696
697         ipfix.remove_vpp_config()
698         self.logger.info("FFP_TEST_FINISH_0002")
699
700     def test_0003(self):
701         """ L4 data on IP6 datapath"""
702         self.logger.info("FFP_TEST_START_0003")
703         self.pg_enable_capture(self.pg_interfaces)
704         self.pkts = []
705
706         ipfix = VppCFLOW(test=self, intf='pg6', active=10,
707                          layer='l4', datapath='ip6')
708         ipfix.add_vpp_config()
709
710         ipfix_decoder = IPFIXDecoder()
711         # template packet should arrive immediately
712         templates = ipfix.verify_templates(ipfix_decoder, timeout=3, count=1)
713
714         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
715                            ip_ver='IPv6')
716         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
717
718         # make sure the one packet we expect actually showed up
719         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 39)
720         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
721                                       {2: 'packets', 7: 'sport', 11: 'dport'},
722                                       ip_ver='v6')
723
724         # expected two templates and one cflow packet
725         self.collector.get_capture(2)
726
727         ipfix.remove_vpp_config()
728         self.logger.info("FFP_TEST_FINISH_0003")
729
730
731 class TestFFP_NoTimers(MethodHolder):
732     """No timers"""
733
734     def test_0001(self):
735         """ no timers, one CFLOW packet, 9 Flows inside"""
736         self.logger.info("FFP_TEST_START_0001")
737         self.pg_enable_capture(self.pg_interfaces)
738         self.pkts = []
739
740         ipfix = VppCFLOW(test=self, active=0)
741         ipfix.add_vpp_config()
742
743         ipfix_decoder = IPFIXDecoder()
744         # template packet should arrive immediately
745         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
746
747         self.create_stream(packets=9)
748         capture = self.send_packets()
749
750         # make sure the one packet we expect actually showed up
751         cflow = self.wait_for_cflow_packet(self.collector, templates[1], 10)
752         self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
753         self.wait_for_cflow_packet(self.collector, templates[1], 10,
754                                    expected=False)
755         self.collector.get_capture(4)
756
757         ipfix.remove_vpp_config()
758         self.logger.info("FFP_TEST_FINISH_0001")
759
760     def test_0002(self):
761         """ no timers, two CFLOW packets (mtu=256), 3 Flows in each"""
762         self.logger.info("FFP_TEST_START_0002")
763         self.pg_enable_capture(self.pg_interfaces)
764         self.pkts = []
765
766         ipfix = VppCFLOW(test=self, active=0, mtu=256)
767         ipfix.add_vpp_config()
768
769         ipfix_decoder = IPFIXDecoder()
770         # template packet should arrive immediately
771         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
772
773         self.create_stream(packets=6)
774         capture = self.send_packets()
775
776         # make sure the one packet we expect actually showed up
777         cflows = []
778         cflows.append(self.wait_for_cflow_packet(self.collector,
779                                                  templates[1], 10))
780         cflows.append(self.wait_for_cflow_packet(self.collector,
781                                                  templates[1], 10))
782         self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
783         self.collector.get_capture(5)
784
785         ipfix.remove_vpp_config()
786         self.logger.info("FFP_TEST_FINISH_0002")
787
788
789 class TestFFP_DisableIPFIX(MethodHolder):
790     """Disable IPFIX"""
791
792     def test_0001(self):
793         """ disable IPFIX after first packets"""
794         self.logger.info("FFP_TEST_START_0001")
795         self.pg_enable_capture(self.pg_interfaces)
796         self.pkts = []
797
798         ipfix = VppCFLOW(test=self, active=10)
799         ipfix.add_vpp_config()
800
801         ipfix_decoder = IPFIXDecoder()
802         # template packet should arrive immediately
803         templates = ipfix.verify_templates(ipfix_decoder, timeout=30)
804
805         self.create_stream()
806         self.send_packets()
807
808         # make sure the one packet we expect actually showed up
809         self.wait_for_cflow_packet(self.collector, templates[1], 30)
810         self.collector.get_capture(4)
811
812         # disble IPFIX
813         ipfix.disable_exporter()
814         self.pg_enable_capture([self.collector])
815
816         self.send_packets()
817
818         # make sure no one packet arrived in 1 minute
819         self.wait_for_cflow_packet(self.collector, templates[1], 30,
820                                    expected=False)
821         self.collector.get_capture(0)
822
823         ipfix.remove_vpp_config()
824         self.logger.info("FFP_TEST_FINISH_0001")
825
826
827 class TestFFP_ReenableIPFIX(MethodHolder):
828     """Re-enable IPFIX"""
829
830     def test_0001(self):
831         """ disable IPFIX after first packets and re-enable after few packets
832         """
833         self.logger.info("FFP_TEST_START_0001")
834         self.pg_enable_capture(self.pg_interfaces)
835         self.pkts = []
836
837         ipfix = VppCFLOW(test=self, active=10)
838         ipfix.add_vpp_config()
839
840         ipfix_decoder = IPFIXDecoder()
841         # template packet should arrive immediately
842         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
843
844         self.create_stream()
845         self.send_packets()
846
847         # make sure the one packet we expect actually showed up
848         self.wait_for_cflow_packet(self.collector, templates[1], 30)
849         self.collector.get_capture(4)
850
851         # disble IPFIX
852         ipfix.disable_exporter()
853         self.pg_enable_capture([self.collector])
854
855         self.send_packets()
856
857         # make sure no one packet arrived in active timer span
858         self.wait_for_cflow_packet(self.collector, templates[1], 30,
859                                    expected=False)
860         self.collector.get_capture(0)
861
862         # enable IPFIX
863         ipfix.enable_exporter()
864         self.vapi.cli("ipfix flush")
865         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
866
867         self.send_packets()
868
869         # make sure the next packets (templates and data) we expect actually
870         # showed up
871         self.wait_for_cflow_packet(self.collector, templates[1], 30)
872         self.collector.get_capture(4)
873
874         ipfix.remove_vpp_config()
875         self.logger.info("FFP_TEST_FINISH_0001")
876
877
878 class TestFFP_DisableFFP(MethodHolder):
879     """Disable Flowprobe feature"""
880
881     def test_0001(self):
882         """ disable flowprobe feature after first packets"""
883         self.logger.info("FFP_TEST_START_0001")
884         self.pg_enable_capture(self.pg_interfaces)
885         self.pkts = []
886         ipfix = VppCFLOW(test=self, active=10)
887         ipfix.add_vpp_config()
888
889         ipfix_decoder = IPFIXDecoder()
890         # template packet should arrive immediately
891         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
892
893         self.create_stream()
894         self.send_packets()
895
896         # make sure the one packet we expect actually showed up
897         self.wait_for_cflow_packet(self.collector, templates[1], 30)
898         self.collector.get_capture(4)
899
900         # disble IPFIX
901         ipfix.disable_flowprobe_feature()
902         self.pg_enable_capture([self.collector])
903
904         self.send_packets()
905
906         # make sure no one packet arrived in active timer span
907         self.wait_for_cflow_packet(self.collector, templates[1], 30,
908                                    expected=False)
909         self.collector.get_capture(0)
910
911         ipfix.remove_vpp_config()
912         self.logger.info("FFP_TEST_FINISH_0001")
913
914
915 class TestFFP_ReenableFFP(MethodHolder):
916     """Re-enable Flowprobe feature"""
917
918     def test_0001(self):
919         """ disable flowprobe feature after first packets and re-enable
920         after few packets """
921         self.logger.info("FFP_TEST_START_0001")
922         self.pg_enable_capture(self.pg_interfaces)
923         self.pkts = []
924
925         ipfix = VppCFLOW(test=self, active=10)
926         ipfix.add_vpp_config()
927
928         ipfix_decoder = IPFIXDecoder()
929         # template packet should arrive immediately
930         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
931
932         self.create_stream()
933         self.send_packets()
934
935         # make sure the one packet we expect actually showed up
936         self.wait_for_cflow_packet(self.collector, templates[1], 30)
937         self.collector.get_capture(4)
938
939         # disble FPP feature
940         ipfix.disable_flowprobe_feature()
941         self.pg_enable_capture([self.collector])
942
943         self.send_packets()
944
945         # make sure no one packet arrived in active timer span
946         self.wait_for_cflow_packet(self.collector, templates[1], 30,
947                                    expected=False)
948         self.collector.get_capture(0)
949
950         # enable FPP feature
951         ipfix.enable_flowprobe_feature()
952         self.vapi.cli("ipfix flush")
953         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
954
955         self.send_packets()
956
957         # make sure the next packets (templates and data) we expect actually
958         # showed up
959         self.wait_for_cflow_packet(self.collector, templates[1], 30)
960         self.collector.get_capture(4)
961
962         ipfix.remove_vpp_config()
963         self.logger.info("FFP_TEST_FINISH_0001")
964
965
966 if __name__ == '__main__':
967     unittest.main(testRunner=VppTestRunner)