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