flowprobe: use explicit types in api
[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 setUpClass(cls):
351         super(Flowprobe, cls).setUpClass()
352
353     @classmethod
354     def tearDownClass(cls):
355         super(Flowprobe, cls).tearDownClass()
356
357     def test_0001(self):
358         """ timer less than template timeout"""
359         self.logger.info("FFP_TEST_START_0001")
360         self.pg_enable_capture(self.pg_interfaces)
361         self.pkts = []
362
363         ipfix = VppCFLOW(test=self, active=2)
364         ipfix.add_vpp_config()
365
366         ipfix_decoder = IPFIXDecoder()
367         # template packet should arrive immediately
368         templates = ipfix.verify_templates(ipfix_decoder)
369
370         self.create_stream(packets=1)
371         self.send_packets()
372         capture = self.pg2.get_capture(1)
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_0001")
380
381     def test_0002(self):
382         """ timer greater than template timeout"""
383         self.logger.info("FFP_TEST_START_0002")
384         self.pg_enable_capture(self.pg_interfaces)
385         self.pkts = []
386
387         ipfix = VppCFLOW(test=self, timeout=3, active=4)
388         ipfix.add_vpp_config()
389
390         ipfix_decoder = IPFIXDecoder()
391         # template packet should arrive immediately
392         ipfix.verify_templates()
393
394         self.create_stream(packets=2)
395         self.send_packets()
396         capture = self.pg2.get_capture(2)
397
398         # next set of template packet should arrive after 20 seconds
399         # template packet should arrive within 20 s
400         templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
401
402         # make sure the one packet we expect actually showed up
403         cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
404         self.verify_cflow_data(ipfix_decoder, capture, cflow)
405
406         ipfix.remove_vpp_config()
407         self.logger.info("FFP_TEST_FINISH_0002")
408
409     def test_cflow_packet(self):
410         """verify cflow packet fields"""
411         self.logger.info("FFP_TEST_START_0000")
412         self.pg_enable_capture(self.pg_interfaces)
413         self.pkts = []
414
415         ipfix = VppCFLOW(test=self, intf='pg8', datapath="ip4",
416                          layer='l2 l3 l4', active=2)
417         ipfix.add_vpp_config()
418
419         route_9001 = VppIpRoute(self, "9.0.0.0", 24,
420                                 [VppRoutePath(self.pg8._remote_hosts[0].ip4,
421                                               self.pg8.sw_if_index)])
422         route_9001.add_vpp_config()
423
424         ipfix_decoder = IPFIXDecoder()
425         templates = ipfix.verify_templates(ipfix_decoder, count=1)
426
427         self.pkts = [(Ether(dst=self.pg7.local_mac,
428                             src=self.pg7.remote_mac) /
429                       IP(src=self.pg7.remote_ip4, dst="9.0.0.100") /
430                       TCP(sport=1234, dport=4321, flags=80) /
431                       Raw(b'\xa5' * 100))]
432
433         nowUTC = int(time.time())
434         nowUNIX = nowUTC+2208988800
435         self.send_packets(src_if=self.pg7, dst_if=self.pg8)
436
437         cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
438         self.collector.get_capture(2)
439
440         if cflow[0].haslayer(IPFIX):
441             self.assertEqual(cflow[IPFIX].version, 10)
442             self.assertEqual(cflow[IPFIX].observationDomainID, 1)
443             self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
444             self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
445         if cflow.haslayer(Data):
446             record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
447             # ingress interface
448             self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
449             # egress interface
450             self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
451             # packets
452             self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
453             # src mac
454             self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
455             # dst mac
456             self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
457             flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
458             # flow start timestamp
459             self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
460             flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
461             # flow end timestamp
462             self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
463             # ethernet type
464             self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
465             # src ip
466             self.assertEqual(inet_ntop(socket.AF_INET, record[8]),
467                              self.pg7.remote_ip4)
468             # dst ip
469             self.assertEqual(inet_ntop(socket.AF_INET, record[12]),
470                              "9.0.0.100")
471             # protocol (TCP)
472             self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
473             # src port
474             self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
475             # dst port
476             self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
477             # tcp flags
478             self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
479
480         ipfix.remove_vpp_config()
481         self.logger.info("FFP_TEST_FINISH_0000")
482
483
484 class Datapath(MethodHolder):
485     """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
486
487     @classmethod
488     def setUpClass(cls):
489         super(Datapath, cls).setUpClass()
490
491     @classmethod
492     def tearDownClass(cls):
493         super(Datapath, cls).tearDownClass()
494
495     def test_templatesL2(self):
496         """ verify template on L2 datapath"""
497         self.logger.info("FFP_TEST_START_0000")
498         self.pg_enable_capture(self.pg_interfaces)
499
500         ipfix = VppCFLOW(test=self, layer='l2')
501         ipfix.add_vpp_config()
502
503         # template packet should arrive immediately
504         self.vapi.ipfix_flush()
505         ipfix.verify_templates(timeout=3, count=1)
506         self.collector.get_capture(1)
507
508         ipfix.remove_vpp_config()
509         self.logger.info("FFP_TEST_FINISH_0000")
510
511     def test_L2onL2(self):
512         """ L2 data on L2 datapath"""
513         self.logger.info("FFP_TEST_START_0001")
514         self.pg_enable_capture(self.pg_interfaces)
515         self.pkts = []
516
517         ipfix = VppCFLOW(test=self, layer='l2')
518         ipfix.add_vpp_config()
519
520         ipfix_decoder = IPFIXDecoder()
521         # template packet should arrive immediately
522         templates = ipfix.verify_templates(ipfix_decoder, count=1)
523
524         self.create_stream(packets=1)
525         capture = self.send_packets()
526
527         # make sure the one packet we expect actually showed up
528         self.vapi.ipfix_flush()
529         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
530         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
531                                       {2: 'packets', 256: 8})
532         self.collector.get_capture(2)
533
534         ipfix.remove_vpp_config()
535         self.logger.info("FFP_TEST_FINISH_0001")
536
537     def test_L3onL2(self):
538         """ L3 data on L2 datapath"""
539         self.logger.info("FFP_TEST_START_0002")
540         self.pg_enable_capture(self.pg_interfaces)
541         self.pkts = []
542
543         ipfix = VppCFLOW(test=self, layer='l3')
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', 4: 17,
558                                        8: 'src_ip', 12: 'dst_ip'})
559
560         self.collector.get_capture(3)
561
562         ipfix.remove_vpp_config()
563         self.logger.info("FFP_TEST_FINISH_0002")
564
565     def test_L4onL2(self):
566         """ L4 data on L2 datapath"""
567         self.logger.info("FFP_TEST_START_0003")
568         self.pg_enable_capture(self.pg_interfaces)
569         self.pkts = []
570
571         ipfix = VppCFLOW(test=self, layer='l4')
572         ipfix.add_vpp_config()
573
574         ipfix_decoder = IPFIXDecoder()
575         # template packet should arrive immediately
576         templates = ipfix.verify_templates(ipfix_decoder, count=2)
577
578         self.create_stream(packets=1)
579         capture = self.send_packets()
580
581         # make sure the one packet we expect actually showed up
582         self.vapi.ipfix_flush()
583         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
584         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
585                                       {2: 'packets', 7: 'sport', 11: 'dport'})
586
587         self.collector.get_capture(3)
588
589         ipfix.remove_vpp_config()
590         self.logger.info("FFP_TEST_FINISH_0003")
591
592     def test_templatesIp4(self):
593         """ verify templates on IP4 datapath"""
594         self.logger.info("FFP_TEST_START_0000")
595
596         self.pg_enable_capture(self.pg_interfaces)
597
598         ipfix = VppCFLOW(test=self, datapath='ip4')
599         ipfix.add_vpp_config()
600
601         # template packet should arrive immediately
602         self.vapi.ipfix_flush()
603         ipfix.verify_templates(timeout=3, count=1)
604         self.collector.get_capture(1)
605
606         ipfix.remove_vpp_config()
607
608         self.logger.info("FFP_TEST_FINISH_0000")
609
610     def test_L2onIP4(self):
611         """ L2 data on IP4 datapath"""
612         self.logger.info("FFP_TEST_START_0001")
613         self.pg_enable_capture(self.pg_interfaces)
614         self.pkts = []
615
616         ipfix = VppCFLOW(test=self, intf='pg4', layer='l2', 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                                       {2: 'packets', 256: 8})
631
632         # expected two templates and one cflow packet
633         self.collector.get_capture(2)
634
635         ipfix.remove_vpp_config()
636         self.logger.info("FFP_TEST_FINISH_0001")
637
638     def test_L3onIP4(self):
639         """ L3 data on IP4 datapath"""
640         self.logger.info("FFP_TEST_START_0002")
641         self.pg_enable_capture(self.pg_interfaces)
642         self.pkts = []
643
644         ipfix = VppCFLOW(test=self, intf='pg4', layer='l3', datapath='ip4')
645         ipfix.add_vpp_config()
646
647         ipfix_decoder = IPFIXDecoder()
648         # template packet should arrive immediately
649         templates = ipfix.verify_templates(ipfix_decoder, count=1)
650
651         self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
652         capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
653
654         # make sure the one packet we expect actually showed up
655         self.vapi.ipfix_flush()
656         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
657         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
658                                       {1: 'octets', 2: 'packets',
659                                        8: 'src_ip', 12: 'dst_ip'})
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_0002")
666
667     def test_L4onIP4(self):
668         """ L4 data on IP4 datapath"""
669         self.logger.info("FFP_TEST_START_0003")
670         self.pg_enable_capture(self.pg_interfaces)
671         self.pkts = []
672
673         ipfix = VppCFLOW(test=self, intf='pg4', layer='l4', datapath='ip4')
674         ipfix.add_vpp_config()
675
676         ipfix_decoder = IPFIXDecoder()
677         # template packet should arrive immediately
678         templates = ipfix.verify_templates(ipfix_decoder, count=1)
679
680         self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
681         capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
682
683         # make sure the one packet we expect actually showed up
684         self.vapi.ipfix_flush()
685         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
686         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
687                                       {2: 'packets', 7: 'sport', 11: 'dport'})
688
689         # expected two templates and one cflow packet
690         self.collector.get_capture(2)
691
692         ipfix.remove_vpp_config()
693         self.logger.info("FFP_TEST_FINISH_0003")
694
695     def test_templatesIP6(self):
696         """ verify templates on IP6 datapath"""
697         self.logger.info("FFP_TEST_START_0000")
698         self.pg_enable_capture(self.pg_interfaces)
699
700         ipfix = VppCFLOW(test=self, datapath='ip6')
701         ipfix.add_vpp_config()
702
703         # template packet should arrive immediately
704         ipfix.verify_templates(count=1)
705         self.collector.get_capture(1)
706
707         ipfix.remove_vpp_config()
708
709         self.logger.info("FFP_TEST_FINISH_0000")
710
711     def test_L2onIP6(self):
712         """ L2 data on IP6 datapath"""
713         self.logger.info("FFP_TEST_START_0001")
714         self.pg_enable_capture(self.pg_interfaces)
715         self.pkts = []
716
717         ipfix = VppCFLOW(test=self, intf='pg6', layer='l2', datapath='ip6')
718         ipfix.add_vpp_config()
719
720         ipfix_decoder = IPFIXDecoder()
721         # template packet should arrive immediately
722         templates = ipfix.verify_templates(ipfix_decoder, count=1)
723
724         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
725                            ip_ver='IPv6')
726         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
727
728         # make sure the one packet we expect actually showed up
729         self.vapi.ipfix_flush()
730         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
731         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
732                                       {2: 'packets', 256: 56710},
733                                       ip_ver='v6')
734
735         # expected two templates and one cflow packet
736         self.collector.get_capture(2)
737
738         ipfix.remove_vpp_config()
739         self.logger.info("FFP_TEST_FINISH_0001")
740
741     def test_L3onIP6(self):
742         """ L3 data on IP6 datapath"""
743         self.logger.info("FFP_TEST_START_0002")
744         self.pg_enable_capture(self.pg_interfaces)
745         self.pkts = []
746
747         ipfix = VppCFLOW(test=self, intf='pg6', layer='l3', datapath='ip6')
748         ipfix.add_vpp_config()
749
750         ipfix_decoder = IPFIXDecoder()
751         # template packet should arrive immediately
752         templates = ipfix.verify_templates(ipfix_decoder, count=1)
753
754         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
755                            ip_ver='IPv6')
756         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
757
758         # make sure the one packet we expect actually showed up
759         self.vapi.ipfix_flush()
760         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
761         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
762                                       {2: 'packets',
763                                        27: 'src_ip', 28: 'dst_ip'},
764                                       ip_ver='v6')
765
766         # expected two templates and one cflow packet
767         self.collector.get_capture(2)
768
769         ipfix.remove_vpp_config()
770         self.logger.info("FFP_TEST_FINISH_0002")
771
772     def test_L4onIP6(self):
773         """ L4 data on IP6 datapath"""
774         self.logger.info("FFP_TEST_START_0003")
775         self.pg_enable_capture(self.pg_interfaces)
776         self.pkts = []
777
778         ipfix = VppCFLOW(test=self, intf='pg6', layer='l4', datapath='ip6')
779         ipfix.add_vpp_config()
780
781         ipfix_decoder = IPFIXDecoder()
782         # template packet should arrive immediately
783         templates = ipfix.verify_templates(ipfix_decoder, count=1)
784
785         self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1,
786                            ip_ver='IPv6')
787         capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
788
789         # make sure the one packet we expect actually showed up
790         self.vapi.ipfix_flush()
791         cflow = self.wait_for_cflow_packet(self.collector, templates[0])
792         self.verify_cflow_data_detail(ipfix_decoder, capture, cflow,
793                                       {2: 'packets', 7: 'sport', 11: 'dport'},
794                                       ip_ver='v6')
795
796         # expected two templates and one cflow packet
797         self.collector.get_capture(2)
798
799         ipfix.remove_vpp_config()
800         self.logger.info("FFP_TEST_FINISH_0003")
801
802     def test_0001(self):
803         """ no timers, one CFLOW packet, 9 Flows inside"""
804         self.logger.info("FFP_TEST_START_0001")
805         self.pg_enable_capture(self.pg_interfaces)
806         self.pkts = []
807
808         ipfix = VppCFLOW(test=self)
809         ipfix.add_vpp_config()
810
811         ipfix_decoder = IPFIXDecoder()
812         # template packet should arrive immediately
813         templates = ipfix.verify_templates(ipfix_decoder)
814
815         self.create_stream(packets=9)
816         capture = self.send_packets()
817
818         # make sure the one packet we expect actually showed up
819         self.vapi.ipfix_flush()
820         cflow = self.wait_for_cflow_packet(self.collector, templates[1])
821         self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
822         self.collector.get_capture(4)
823
824         ipfix.remove_vpp_config()
825         self.logger.info("FFP_TEST_FINISH_0001")
826
827     def test_0002(self):
828         """ no timers, two CFLOW packets (mtu=256), 3 Flows in each"""
829         self.logger.info("FFP_TEST_START_0002")
830         self.pg_enable_capture(self.pg_interfaces)
831         self.pkts = []
832
833         ipfix = VppCFLOW(test=self, mtu=256)
834         ipfix.add_vpp_config()
835
836         ipfix_decoder = IPFIXDecoder()
837         # template packet should arrive immediately
838         self.vapi.ipfix_flush()
839         templates = ipfix.verify_templates(ipfix_decoder)
840
841         self.create_stream(packets=6)
842         capture = self.send_packets()
843
844         # make sure the one packet we expect actually showed up
845         cflows = []
846         self.vapi.ipfix_flush()
847         cflows.append(self.wait_for_cflow_packet(self.collector,
848                                                  templates[1]))
849         cflows.append(self.wait_for_cflow_packet(self.collector,
850                                                  templates[1]))
851         self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
852         self.collector.get_capture(5)
853
854         ipfix.remove_vpp_config()
855         self.logger.info("FFP_TEST_FINISH_0002")
856
857
858 @unittest.skipUnless(running_extended_tests, "part of extended tests")
859 class DisableIPFIX(MethodHolder):
860     """Disable IPFIX"""
861
862     @classmethod
863     def setUpClass(cls):
864         super(DisableIPFIX, cls).setUpClass()
865
866     @classmethod
867     def tearDownClass(cls):
868         super(DisableIPFIX, cls).tearDownClass()
869
870     def test_0001(self):
871         """ disable IPFIX after first packets"""
872         self.logger.info("FFP_TEST_START_0001")
873         self.pg_enable_capture(self.pg_interfaces)
874         self.pkts = []
875
876         ipfix = VppCFLOW(test=self)
877         ipfix.add_vpp_config()
878
879         ipfix_decoder = IPFIXDecoder()
880         # template packet should arrive immediately
881         templates = ipfix.verify_templates(ipfix_decoder)
882
883         self.create_stream()
884         self.send_packets()
885
886         # make sure the one packet we expect actually showed up
887         self.vapi.ipfix_flush()
888         self.wait_for_cflow_packet(self.collector, templates[1])
889         self.collector.get_capture(4)
890
891         # disable IPFIX
892         ipfix.disable_exporter()
893         self.pg_enable_capture([self.collector])
894
895         self.send_packets()
896
897         # make sure no one packet arrived in 1 minute
898         self.vapi.ipfix_flush()
899         self.wait_for_cflow_packet(self.collector, templates[1],
900                                    expected=False)
901         self.collector.get_capture(0)
902
903         ipfix.remove_vpp_config()
904         self.logger.info("FFP_TEST_FINISH_0001")
905
906
907 @unittest.skipUnless(running_extended_tests, "part of extended tests")
908 class ReenableIPFIX(MethodHolder):
909     """Re-enable IPFIX"""
910
911     @classmethod
912     def setUpClass(cls):
913         super(ReenableIPFIX, cls).setUpClass()
914
915     @classmethod
916     def tearDownClass(cls):
917         super(ReenableIPFIX, cls).tearDownClass()
918
919     def test_0011(self):
920         """ disable IPFIX after first packets and re-enable after few packets
921         """
922         self.logger.info("FFP_TEST_START_0001")
923         self.pg_enable_capture(self.pg_interfaces)
924         self.pkts = []
925
926         ipfix = VppCFLOW(test=self)
927         ipfix.add_vpp_config()
928
929         ipfix_decoder = IPFIXDecoder()
930         # template packet should arrive immediately
931         templates = ipfix.verify_templates(ipfix_decoder)
932
933         self.create_stream(packets=5)
934         self.send_packets()
935
936         # make sure the one packet we expect actually showed up
937         self.vapi.ipfix_flush()
938         self.wait_for_cflow_packet(self.collector, templates[1])
939         self.collector.get_capture(4)
940
941         # disable IPFIX
942         ipfix.disable_exporter()
943         self.vapi.ipfix_flush()
944         self.pg_enable_capture([self.collector])
945
946         self.send_packets()
947
948         # make sure no one packet arrived in active timer span
949         self.vapi.ipfix_flush()
950         self.wait_for_cflow_packet(self.collector, templates[1],
951                                    expected=False)
952         self.collector.get_capture(0)
953         self.pg2.get_capture(5)
954
955         # enable IPFIX
956         ipfix.enable_exporter()
957
958         capture = self.collector.get_capture(4)
959         nr_templates = 0
960         nr_data = 0
961         for p in capture:
962             self.assertTrue(p.haslayer(IPFIX))
963             if p.haslayer(Template):
964                 nr_templates += 1
965         self.assertTrue(nr_templates, 3)
966         for p in capture:
967             self.assertTrue(p.haslayer(IPFIX))
968             if p.haslayer(Data):
969                 nr_data += 1
970         self.assertTrue(nr_templates, 1)
971
972         ipfix.remove_vpp_config()
973         self.logger.info("FFP_TEST_FINISH_0001")
974
975
976 @unittest.skipUnless(running_extended_tests, "part of extended tests")
977 class DisableFP(MethodHolder):
978     """Disable Flowprobe feature"""
979
980     @classmethod
981     def setUpClass(cls):
982         super(DisableFP, cls).setUpClass()
983
984     @classmethod
985     def tearDownClass(cls):
986         super(DisableFP, cls).tearDownClass()
987
988     def test_0001(self):
989         """ disable flowprobe feature after first packets"""
990         self.logger.info("FFP_TEST_START_0001")
991         self.pg_enable_capture(self.pg_interfaces)
992         self.pkts = []
993         ipfix = VppCFLOW(test=self)
994         ipfix.add_vpp_config()
995
996         ipfix_decoder = IPFIXDecoder()
997         # template packet should arrive immediately
998         templates = ipfix.verify_templates(ipfix_decoder)
999
1000         self.create_stream()
1001         self.send_packets()
1002
1003         # make sure the one packet we expect actually showed up
1004         self.vapi.ipfix_flush()
1005         self.wait_for_cflow_packet(self.collector, templates[1])
1006         self.collector.get_capture(4)
1007
1008         # disable IPFIX
1009         ipfix.disable_flowprobe_feature()
1010         self.pg_enable_capture([self.collector])
1011
1012         self.send_packets()
1013
1014         # make sure no one packet arrived in active timer span
1015         self.vapi.ipfix_flush()
1016         self.wait_for_cflow_packet(self.collector, templates[1],
1017                                    expected=False)
1018         self.collector.get_capture(0)
1019
1020         ipfix.remove_vpp_config()
1021         self.logger.info("FFP_TEST_FINISH_0001")
1022
1023
1024 @unittest.skipUnless(running_extended_tests, "part of extended tests")
1025 class ReenableFP(MethodHolder):
1026     """Re-enable Flowprobe feature"""
1027
1028     @classmethod
1029     def setUpClass(cls):
1030         super(ReenableFP, cls).setUpClass()
1031
1032     @classmethod
1033     def tearDownClass(cls):
1034         super(ReenableFP, cls).tearDownClass()
1035
1036     def test_0001(self):
1037         """ disable flowprobe feature after first packets and re-enable
1038         after few packets """
1039         self.logger.info("FFP_TEST_START_0001")
1040         self.pg_enable_capture(self.pg_interfaces)
1041         self.pkts = []
1042
1043         ipfix = VppCFLOW(test=self)
1044         ipfix.add_vpp_config()
1045
1046         ipfix_decoder = IPFIXDecoder()
1047         # template packet should arrive immediately
1048         self.vapi.ipfix_flush()
1049         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1050
1051         self.create_stream()
1052         self.send_packets()
1053
1054         # make sure the one packet we expect actually showed up
1055         self.vapi.ipfix_flush()
1056         self.wait_for_cflow_packet(self.collector, templates[1], 5)
1057         self.collector.get_capture(4)
1058
1059         # disable FPP feature
1060         ipfix.disable_flowprobe_feature()
1061         self.pg_enable_capture([self.collector])
1062
1063         self.send_packets()
1064
1065         # make sure no one packet arrived in active timer span
1066         self.vapi.ipfix_flush()
1067         self.wait_for_cflow_packet(self.collector, templates[1], 5,
1068                                    expected=False)
1069         self.collector.get_capture(0)
1070
1071         # enable FPP feature
1072         ipfix.enable_flowprobe_feature()
1073         self.vapi.ipfix_flush()
1074         templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1075
1076         self.send_packets()
1077
1078         # make sure the next packets (templates and data) we expect actually
1079         # showed up
1080         self.vapi.ipfix_flush()
1081         self.wait_for_cflow_packet(self.collector, templates[1], 5)
1082         self.collector.get_capture(4)
1083
1084         ipfix.remove_vpp_config()
1085         self.logger.info("FFP_TEST_FINISH_0001")
1086
1087
1088 if __name__ == '__main__':
1089     unittest.main(testRunner=VppTestRunner)