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