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