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