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