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