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