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