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