blob: 28ddff8a65e15c50a730de8e71e05a66c87d7567 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Paul Vinciguerra661f91f2018-11-28 19:06:41 -08002from __future__ import print_function
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08003import binascii
Ole Troan5c749732017-03-13 13:39:52 +01004import random
5import socket
6import unittest
7import time
8
9from scapy.packet import Raw
10from scapy.layers.l2 import Ether
Ole Troaned929252017-06-13 21:15:40 +020011from scapy.layers.inet import IP, TCP, UDP
Ole Troan5c749732017-03-13 13:39:52 +010012from scapy.layers.inet6 import IPv6
Alexander Chernavin120095d2023-10-11 12:15:55 +000013from scapy.contrib.lacp import SlowProtocol, LACP
Ole Troan5c749732017-03-13 13:39:52 +010014
Klement Sekerab23ffd72021-05-31 16:08:53 +020015from config import config
Dave Wallace8800f732023-08-31 00:47:44 -040016from framework import VppTestCase
17from asfframework import (
18 tag_fixme_vpp_workers,
19 tag_fixme_ubuntu2204,
20 tag_fixme_debian11,
21 tag_run_solo,
22 is_distro_ubuntu2204,
23 is_distro_debian11,
24 VppTestRunner,
25)
Ole Troan5c749732017-03-13 13:39:52 +010026from vpp_object import VppObject
Ole Troan5c749732017-03-13 13:39:52 +010027from util import ppp
28from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Ole Troaned929252017-06-13 21:15:40 +020029from vpp_ip_route import VppIpRoute, VppRoutePath
Ole Troanb0d83f12019-10-21 23:13:46 +020030from vpp_papi.macaddress import mac_ntop
31from socket import inet_ntop
Ole Troan3013e692019-12-09 15:51:44 +010032from vpp_papi import VppEnum
Ole Troan5c749732017-03-13 13:39:52 +010033
34
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000035TMPL_COMMON_FIELD_COUNT = 6
36TMPL_L2_FIELD_COUNT = 3
37TMPL_L3_FIELD_COUNT = 4
38TMPL_L4_FIELD_COUNT = 3
39
Alexander Chernavin21922ce2023-10-26 11:18:19 +000040IPFIX_TCP_FLAGS_ID = 6
41IPFIX_SRC_TRANS_PORT_ID = 7
42IPFIX_DST_TRANS_PORT_ID = 11
43
44TCP_F_FIN = 0x01
45TCP_F_SYN = 0x02
46TCP_F_RST = 0x04
47TCP_F_PSH = 0x08
48TCP_F_ACK = 0x10
49TCP_F_URG = 0x20
50TCP_F_ECE = 0x40
51TCP_F_CWR = 0x80
52
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000053
Ole Troan5c749732017-03-13 13:39:52 +010054class VppCFLOW(VppObject):
55 """CFLOW object for IPFIX exporter and Flowprobe feature"""
56
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020057 def __init__(
58 self,
59 test,
60 intf="pg2",
61 active=0,
62 passive=0,
63 timeout=100,
64 mtu=1024,
65 datapath="l2",
66 layer="l2 l3 l4",
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000067 direction="tx",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020068 ):
Ole Troan5c749732017-03-13 13:39:52 +010069 self._test = test
70 self._intf = intf
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000071 self._intf_obj = getattr(self._test, intf)
Ole Troan5c749732017-03-13 13:39:52 +010072 self._active = active
73 if passive == 0 or passive < active:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020074 self._passive = active + 1
Ole Troan5c749732017-03-13 13:39:52 +010075 else:
76 self._passive = passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020077 self._datapath = datapath # l2 ip4 ip6
78 self._collect = layer # l2 l3 l4
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000079 self._direction = direction # rx tx both
Ole Troan5c749732017-03-13 13:39:52 +010080 self._timeout = timeout
81 self._mtu = mtu
82 self._configured = False
83
84 def add_vpp_config(self):
85 self.enable_exporter()
Ole Troan3013e692019-12-09 15:51:44 +010086 l2_flag = 0
87 l3_flag = 0
88 l4_flag = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020089 if "l2" in self._collect.lower():
90 l2_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
91 if "l3" in self._collect.lower():
92 l3_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
93 if "l4" in self._collect.lower():
94 l4_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
Alexander Chernavin86c78562022-05-12 14:56:24 +000095 self._test.vapi.flowprobe_set_params(
Ole Troan3013e692019-12-09 15:51:44 +010096 record_flags=(l2_flag | l3_flag | l4_flag),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020097 active_timer=self._active,
98 passive_timer=self._passive,
99 )
Ole Troan5c749732017-03-13 13:39:52 +0100100 self.enable_flowprobe_feature()
101 self._test.vapi.cli("ipfix flush")
102 self._configured = True
103
104 def remove_vpp_config(self):
105 self.disable_exporter()
106 self.disable_flowprobe_feature()
107 self._test.vapi.cli("ipfix flush")
108 self._configured = False
109
110 def enable_exporter(self):
111 self._test.vapi.set_ipfix_exporter(
Jakub Grajciar2f71a882019-10-10 14:21:22 +0200112 collector_address=self._test.pg0.remote_ip4,
113 src_address=self._test.pg0.local_ip4,
Ole Troan5c749732017-03-13 13:39:52 +0100114 path_mtu=self._mtu,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200115 template_interval=self._timeout,
116 )
Ole Troan5c749732017-03-13 13:39:52 +0100117
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000118 def _enable_disable_flowprobe_feature(self, is_add):
119 which_map = {
120 "l2": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2,
121 "ip4": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4,
122 "ip6": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6,
123 }
124 direction_map = {
125 "rx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
126 "tx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
127 "both": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
128 }
129 self._test.vapi.flowprobe_interface_add_del(
130 is_add=is_add,
131 which=which_map[self._datapath],
132 direction=direction_map[self._direction],
133 sw_if_index=self._intf_obj.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200134 )
Ole Troan5c749732017-03-13 13:39:52 +0100135
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000136 def enable_flowprobe_feature(self):
137 self._enable_disable_flowprobe_feature(is_add=True)
138
Ole Troan5c749732017-03-13 13:39:52 +0100139 def disable_exporter(self):
140 self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
141
142 def disable_flowprobe_feature(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000143 self._enable_disable_flowprobe_feature(is_add=False)
Ole Troan5c749732017-03-13 13:39:52 +0100144
145 def object_id(self):
Paul Vinciguerrae3a0e6e2019-03-14 08:46:52 -0700146 return "ipfix-collector-%s-%s" % (self._src, self.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100147
148 def query_vpp_config(self):
149 return self._configured
150
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000151 def verify_templates(self, decoder=None, timeout=1, count=3, field_count_in=None):
Ole Troan5c749732017-03-13 13:39:52 +0100152 templates = []
Klement Sekerac4794572021-09-08 15:15:59 +0200153 self._test.assertIn(count, (1, 2, 3))
154 for _ in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200155 p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
Ole Troan5c749732017-03-13 13:39:52 +0100156 self._test.assertTrue(p.haslayer(IPFIX))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000157 self._test.assertTrue(p.haslayer(Template))
158 if decoder is not None:
Ole Troan5c749732017-03-13 13:39:52 +0100159 templates.append(p[Template].templateID)
160 decoder.add_template(p.getlayer(Template))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000161 if field_count_in is not None:
162 self._test.assertIn(p[Template].fieldCount, field_count_in)
Ole Troan5c749732017-03-13 13:39:52 +0100163 return templates
164
165
166class MethodHolder(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200167 """Flow-per-packet plugin: test L2, IP4, IP6 reporting"""
Ole Troan5c749732017-03-13 13:39:52 +0100168
169 # Test variables
170 debug_print = False
Pavel Kotucek89111d02017-06-12 08:26:13 +0200171 max_number_of_packets = 10
Ole Troan5c749732017-03-13 13:39:52 +0100172 pkts = []
173
174 @classmethod
175 def setUpClass(cls):
176 """
177 Perform standard class setup (defined by class method setUpClass in
178 class VppTestCase) before running the test case, set test case related
179 variables and configure VPP.
180 """
181 super(MethodHolder, cls).setUpClass()
Dave Wallace670724c2022-09-20 21:52:18 -0400182 if (is_distro_ubuntu2204 == True or is_distro_debian11 == True) and not hasattr(
183 cls, "vpp"
184 ):
185 return
Ole Troan5c749732017-03-13 13:39:52 +0100186 try:
187 # Create pg interfaces
Ole Troaned929252017-06-13 21:15:40 +0200188 cls.create_pg_interfaces(range(9))
Ole Troan5c749732017-03-13 13:39:52 +0100189
190 # Packet sizes
191 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
192
193 # Create BD with MAC learning and unknown unicast flooding disabled
194 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200195 cls.vapi.bridge_domain_add_del_v2(
196 bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
197 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100198 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200199 rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1
200 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100201 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200202 rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1
203 )
Ole Troan5c749732017-03-13 13:39:52 +0100204
205 # Set up all interfaces
206 for i in cls.pg_interfaces:
207 i.admin_up()
208
209 cls.pg0.config_ip4()
210 cls.pg0.configure_ipv4_neighbors()
211 cls.collector = cls.pg0
212
213 cls.pg1.config_ip4()
214 cls.pg1.resolve_arp()
215 cls.pg2.config_ip4()
216 cls.pg2.resolve_arp()
217 cls.pg3.config_ip4()
218 cls.pg3.resolve_arp()
219 cls.pg4.config_ip4()
220 cls.pg4.resolve_arp()
Ole Troaned929252017-06-13 21:15:40 +0200221 cls.pg7.config_ip4()
222 cls.pg8.config_ip4()
223 cls.pg8.configure_ipv4_neighbors()
Ole Troan5c749732017-03-13 13:39:52 +0100224
225 cls.pg5.config_ip6()
226 cls.pg5.resolve_ndp()
227 cls.pg5.disable_ipv6_ra()
228 cls.pg6.config_ip6()
229 cls.pg6.resolve_ndp()
230 cls.pg6.disable_ipv6_ra()
231 except Exception:
232 super(MethodHolder, cls).tearDownClass()
233 raise
234
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800235 @classmethod
236 def tearDownClass(cls):
237 super(MethodHolder, cls).tearDownClass()
238
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200239 def create_stream(
240 self, src_if=None, dst_if=None, packets=None, size=None, ip_ver="v4"
241 ):
Ole Troan5c749732017-03-13 13:39:52 +0100242 """Create a packet stream to tickle the plugin
243
244 :param VppInterface src_if: Source interface for packet stream
245 :param VppInterface src_if: Dst interface for packet stream
246 """
247 if src_if is None:
248 src_if = self.pg1
249 if dst_if is None:
250 dst_if = self.pg2
251 self.pkts = []
252 if packets is None:
253 packets = random.randint(1, self.max_number_of_packets)
254 pkt_size = size
255 for p in range(0, packets):
256 if size is None:
257 pkt_size = random.choice(self.pg_if_packet_sizes)
258 info = self.create_packet_info(src_if, dst_if)
259 payload = self.info_to_payload(info)
260 p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200261 if ip_ver == "v4":
Ole Troan5c749732017-03-13 13:39:52 +0100262 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
263 else:
264 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
Ole Troaned929252017-06-13 21:15:40 +0200265 p /= UDP(sport=1234, dport=4321)
266 p /= Raw(payload)
Ole Troan5c749732017-03-13 13:39:52 +0100267 info.data = p.copy()
268 self.extend_packet(p, pkt_size)
269 self.pkts.append(p)
270
271 def verify_cflow_data(self, decoder, capture, cflow):
272 octets = 0
273 packets = 0
274 for p in capture:
275 octets += p[IP].len
276 packets += 1
277 if cflow.haslayer(Data):
278 data = decoder.decode_data_set(cflow.getlayer(Set))
279 for record in data:
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800280 self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
281 self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
Ole Troan5c749732017-03-13 13:39:52 +0100282
Pavel Kotucek89111d02017-06-12 08:26:13 +0200283 def send_packets(self, src_if=None, dst_if=None):
284 if src_if is None:
285 src_if = self.pg1
286 if dst_if is None:
287 dst_if = self.pg2
288 self.pg_enable_capture([dst_if])
289 src_if.add_stream(self.pkts)
290 self.pg_start()
291 return dst_if.get_capture(len(self.pkts))
292
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 def verify_cflow_data_detail(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000294 self,
295 decoder,
296 capture,
297 cflow,
298 data_set={1: "octets", 2: "packets"},
299 ip_ver="v4",
300 field_count=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 ):
Ole Troan5c749732017-03-13 13:39:52 +0100302 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800303 print(capture[0].show())
Ole Troan5c749732017-03-13 13:39:52 +0100304 if cflow.haslayer(Data):
305 data = decoder.decode_data_set(cflow.getlayer(Set))
306 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800307 print(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200308 if ip_ver == "v4":
Alexander Chernavin120095d2023-10-11 12:15:55 +0000309 ip_layer = capture[0][IP] if capture[0].haslayer(IP) else None
Ole Troan5c749732017-03-13 13:39:52 +0100310 else:
Alexander Chernavin120095d2023-10-11 12:15:55 +0000311 ip_layer = capture[0][IPv6] if capture[0].haslayer(IPv6) else None
Ole Troan5c749732017-03-13 13:39:52 +0100312 if data_set is not None:
313 for record in data:
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700314 # skip flow if ingress/egress interface is 0
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800315 if int(binascii.hexlify(record[10]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100316 continue
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800317 if int(binascii.hexlify(record[14]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100318 continue
319
320 for field in data_set:
Ole Troan5c749732017-03-13 13:39:52 +0100321 value = data_set[field]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322 if value == "octets":
Ole Troan5c749732017-03-13 13:39:52 +0100323 value = ip_layer.len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200324 if ip_ver == "v6":
325 value += 40 # ??? is this correct
326 elif value == "packets":
Ole Troan5c749732017-03-13 13:39:52 +0100327 value = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 elif value == "src_ip":
329 if ip_ver == "v4":
330 ip = socket.inet_pton(socket.AF_INET, ip_layer.src)
Ole Troan5c749732017-03-13 13:39:52 +0100331 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 ip = socket.inet_pton(socket.AF_INET6, ip_layer.src)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800333 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200334 elif value == "dst_ip":
335 if ip_ver == "v4":
336 ip = socket.inet_pton(socket.AF_INET, ip_layer.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100337 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200338 ip = socket.inet_pton(socket.AF_INET6, ip_layer.dst)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800339 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200340 elif value == "sport":
Ole Troan5c749732017-03-13 13:39:52 +0100341 value = int(capture[0][UDP].sport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 elif value == "dport":
Ole Troan5c749732017-03-13 13:39:52 +0100343 value = int(capture[0][UDP].dport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 self.assertEqual(
345 int(binascii.hexlify(record[field]), 16), value
346 )
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000347 if field_count is not None:
348 for record in data:
349 self.assertEqual(len(record), field_count)
Ole Troan5c749732017-03-13 13:39:52 +0100350
351 def verify_cflow_data_notimer(self, decoder, capture, cflows):
352 idx = 0
353 for cflow in cflows:
354 if cflow.haslayer(Data):
355 data = decoder.decode_data_set(cflow.getlayer(Set))
356 else:
357 raise Exception("No CFLOW data")
358
359 for rec in data:
360 p = capture[idx]
361 idx += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200362 self.assertEqual(p[IP].len, int(binascii.hexlify(rec[1]), 16))
363 self.assertEqual(1, int(binascii.hexlify(rec[2]), 16))
Ole Troan5c749732017-03-13 13:39:52 +0100364 self.assertEqual(len(capture), idx)
365
Klement Sekerac4794572021-09-08 15:15:59 +0200366 def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 """wait for CFLOW packet and verify its correctness
Ole Troan5c749732017-03-13 13:39:52 +0100368
369 :param timeout: how long to wait
370
Ole Troan5c749732017-03-13 13:39:52 +0100371 """
372 self.logger.info("IPFIX: Waiting for CFLOW packet")
Ole Troan5c749732017-03-13 13:39:52 +0100373 # self.logger.debug(self.vapi.ppcli("show flow table"))
Klement Sekerac4794572021-09-08 15:15:59 +0200374 p = collector_intf.wait_for_packet(timeout=timeout)
375 self.assertEqual(p[Set].setID, set_id)
376 # self.logger.debug(self.vapi.ppcli("show flow table"))
377 self.logger.debug(ppp("IPFIX: Got packet:", p))
Ole Troan5c749732017-03-13 13:39:52 +0100378 return p
379
Ole Troan5c749732017-03-13 13:39:52 +0100380
Andrew Yourtchenko06f32812021-01-14 10:19:08 +0000381@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000382@tag_fixme_vpp_workers
Dave Wallace670724c2022-09-20 21:52:18 -0400383@tag_fixme_ubuntu2204
384@tag_fixme_debian11
Ole Troaned929252017-06-13 21:15:40 +0200385class Flowprobe(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +0100386 """Template verification, timer tests"""
387
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800388 @classmethod
389 def setUpClass(cls):
390 super(Flowprobe, cls).setUpClass()
391
392 @classmethod
393 def tearDownClass(cls):
394 super(Flowprobe, cls).tearDownClass()
395
Ole Troan5c749732017-03-13 13:39:52 +0100396 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200397 """timer less than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200398 self.logger.info("FFP_TEST_START_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100399 self.pg_enable_capture(self.pg_interfaces)
400 self.pkts = []
401
Pavel Kotucek89111d02017-06-12 08:26:13 +0200402 ipfix = VppCFLOW(test=self, active=2)
Ole Troan5c749732017-03-13 13:39:52 +0100403 ipfix.add_vpp_config()
404
405 ipfix_decoder = IPFIXDecoder()
406 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200407 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +0100408
Ole Troaned929252017-06-13 21:15:40 +0200409 self.create_stream(packets=1)
Pavel Kotucek89111d02017-06-12 08:26:13 +0200410 self.send_packets()
Ole Troaned929252017-06-13 21:15:40 +0200411 capture = self.pg2.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100412
413 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200414 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100415 self.verify_cflow_data(ipfix_decoder, capture, cflow)
416
417 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200418 self.logger.info("FFP_TEST_FINISH_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100419
Pavel Kotucek89111d02017-06-12 08:26:13 +0200420 def test_0002(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200421 """timer greater than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200422 self.logger.info("FFP_TEST_START_0002")
Ole Troan5c749732017-03-13 13:39:52 +0100423 self.pg_enable_capture(self.pg_interfaces)
424 self.pkts = []
425
Pavel Kotucek89111d02017-06-12 08:26:13 +0200426 ipfix = VppCFLOW(test=self, timeout=3, active=4)
Ole Troan5c749732017-03-13 13:39:52 +0100427 ipfix.add_vpp_config()
428
429 ipfix_decoder = IPFIXDecoder()
430 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200431 ipfix.verify_templates()
Ole Troan5c749732017-03-13 13:39:52 +0100432
Pavel Kotucek89111d02017-06-12 08:26:13 +0200433 self.create_stream(packets=2)
434 self.send_packets()
435 capture = self.pg2.get_capture(2)
Ole Troan5c749732017-03-13 13:39:52 +0100436
437 # next set of template packet should arrive after 20 seconds
438 # template packet should arrive within 20 s
Pavel Kotucek89111d02017-06-12 08:26:13 +0200439 templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
Ole Troan5c749732017-03-13 13:39:52 +0100440
441 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200442 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100443 self.verify_cflow_data(ipfix_decoder, capture, cflow)
444
445 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200446 self.logger.info("FFP_TEST_FINISH_0002")
447
448 def test_cflow_packet(self):
449 """verify cflow packet fields"""
450 self.logger.info("FFP_TEST_START_0000")
451 self.pg_enable_capture(self.pg_interfaces)
452 self.pkts = []
453
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200454 ipfix = VppCFLOW(
455 test=self, intf="pg8", datapath="ip4", layer="l2 l3 l4", active=2
456 )
Ole Troaned929252017-06-13 21:15:40 +0200457 ipfix.add_vpp_config()
458
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 route_9001 = VppIpRoute(
460 self,
461 "9.0.0.0",
462 24,
463 [VppRoutePath(self.pg8._remote_hosts[0].ip4, self.pg8.sw_if_index)],
464 )
Ole Troaned929252017-06-13 21:15:40 +0200465 route_9001.add_vpp_config()
466
467 ipfix_decoder = IPFIXDecoder()
468 templates = ipfix.verify_templates(ipfix_decoder, count=1)
469
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200470 self.pkts = [
471 (
472 Ether(dst=self.pg7.local_mac, src=self.pg7.remote_mac)
473 / IP(src=self.pg7.remote_ip4, dst="9.0.0.100")
474 / TCP(sport=1234, dport=4321, flags=80)
475 / Raw(b"\xa5" * 100)
476 )
477 ]
Ole Troaned929252017-06-13 21:15:40 +0200478
479 nowUTC = int(time.time())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200480 nowUNIX = nowUTC + 2208988800
Ole Troaned929252017-06-13 21:15:40 +0200481 self.send_packets(src_if=self.pg7, dst_if=self.pg8)
482
483 cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
484 self.collector.get_capture(2)
485
486 if cflow[0].haslayer(IPFIX):
487 self.assertEqual(cflow[IPFIX].version, 10)
488 self.assertEqual(cflow[IPFIX].observationDomainID, 1)
489 self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
490 self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
491 if cflow.haslayer(Data):
492 record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
493 # ingress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800494 self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200495 # egress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800496 self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000497 # direction
498 self.assertEqual(int(binascii.hexlify(record[61]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200499 # packets
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800500 self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200501 # src mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200502 self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
Ole Troaned929252017-06-13 21:15:40 +0200503 # dst mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200504 self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800505 flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200506 # flow start timestamp
507 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800508 flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200509 # flow end timestamp
510 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
511 # ethernet type
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800512 self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200513 # src ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200514 self.assertEqual(inet_ntop(socket.AF_INET, record[8]), self.pg7.remote_ip4)
Ole Troaned929252017-06-13 21:15:40 +0200515 # dst ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200516 self.assertEqual(inet_ntop(socket.AF_INET, record[12]), "9.0.0.100")
Ole Troaned929252017-06-13 21:15:40 +0200517 # protocol (TCP)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800518 self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
Ole Troaned929252017-06-13 21:15:40 +0200519 # src port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800520 self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
Ole Troaned929252017-06-13 21:15:40 +0200521 # dst port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800522 self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
Ole Troaned929252017-06-13 21:15:40 +0200523 # tcp flags
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800524 self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
Ole Troaned929252017-06-13 21:15:40 +0200525
526 ipfix.remove_vpp_config()
527 self.logger.info("FFP_TEST_FINISH_0000")
Ole Troan5c749732017-03-13 13:39:52 +0100528
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000529 def test_flow_entry_reuse(self):
530 """Verify flow entry reuse doesn't accumulate meta info"""
531 self.pg_enable_capture(self.pg_interfaces)
532 self.pkts = []
533
534 # enable ip4 datapath for an interface
535 # set active and passive timers
536 ipfix = VppCFLOW(
537 test=self,
538 active=2,
539 passive=3,
540 intf="pg3",
541 layer="l3 l4",
542 datapath="ip4",
543 direction="rx",
544 mtu=100,
545 )
546 ipfix.add_vpp_config()
547
548 # template packet should arrive immediately
549 ipfix_decoder = IPFIXDecoder()
550 templates = ipfix.verify_templates(ipfix_decoder, count=1)
551
552 # make a tcp packet
553 self.pkts = [
554 (
555 Ether(src=self.pg3.remote_mac, dst=self.pg4.local_mac)
556 / IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
557 / TCP(sport=1234, dport=4321)
558 / Raw(b"\xa5" * 50)
559 )
560 ]
561
562 # send the tcp packet two times, each time with new set of flags
563 tcp_flags = (
564 TCP_F_SYN | TCP_F_ACK,
565 TCP_F_RST | TCP_F_PSH,
566 )
567 for f in tcp_flags:
568 self.pkts[0][TCP].flags = f
569 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
570
571 # verify meta info - packet/octet delta and tcp flags
572 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=6)
573 self.verify_cflow_data(ipfix_decoder, capture, cflow)
574 self.verify_cflow_data_detail(
575 ipfix_decoder,
576 capture,
577 cflow,
578 {
579 IPFIX_TCP_FLAGS_ID: f,
580 IPFIX_SRC_TRANS_PORT_ID: 1234,
581 IPFIX_DST_TRANS_PORT_ID: 4321,
582 },
583 )
584
585 self.collector.get_capture(3)
586
587 # cleanup
588 ipfix.remove_vpp_config()
589
Alexander Chernavin86c78562022-05-12 14:56:24 +0000590 def test_interface_dump(self):
591 """Dump interfaces with IPFIX flow record generation enabled"""
592 self.logger.info("FFP_TEST_START_0003")
593
594 # Enable feature for 3 interfaces
595 ipfix1 = VppCFLOW(test=self, intf="pg1", datapath="l2", direction="rx")
596 ipfix1.add_vpp_config()
597
598 ipfix2 = VppCFLOW(test=self, intf="pg2", datapath="ip4", direction="tx")
599 ipfix2.enable_flowprobe_feature()
600
601 ipfix3 = VppCFLOW(test=self, intf="pg3", datapath="ip6", direction="both")
602 ipfix3.enable_flowprobe_feature()
603
604 # When request "all", dump should contain all enabled interfaces
605 dump = self.vapi.flowprobe_interface_dump()
606 self.assertEqual(len(dump), 3)
607
608 # Verify 1st interface
609 self.assertEqual(dump[0].sw_if_index, self.pg1.sw_if_index)
610 self.assertEqual(
611 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2
612 )
613 self.assertEqual(
614 dump[0].direction,
615 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
616 )
617
618 # Verify 2nd interface
619 self.assertEqual(dump[1].sw_if_index, self.pg2.sw_if_index)
620 self.assertEqual(
621 dump[1].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
622 )
623 self.assertEqual(
624 dump[1].direction,
625 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
626 )
627
628 # Verify 3rd interface
629 self.assertEqual(dump[2].sw_if_index, self.pg3.sw_if_index)
630 self.assertEqual(
631 dump[2].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6
632 )
633 self.assertEqual(
634 dump[2].direction,
635 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
636 )
637
638 # When request 2nd interface, dump should contain only the specified interface
639 dump = self.vapi.flowprobe_interface_dump(sw_if_index=self.pg2.sw_if_index)
640 self.assertEqual(len(dump), 1)
641
642 # Verify 2nd interface
643 self.assertEqual(dump[0].sw_if_index, self.pg2.sw_if_index)
644 self.assertEqual(
645 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
646 )
647 self.assertEqual(
648 dump[0].direction,
649 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
650 )
651
652 # When request 99th interface, dump should be empty
653 dump = self.vapi.flowprobe_interface_dump(sw_if_index=99)
654 self.assertEqual(len(dump), 0)
655
656 ipfix1.remove_vpp_config()
657 ipfix2.remove_vpp_config()
658 ipfix3.remove_vpp_config()
659 self.logger.info("FFP_TEST_FINISH_0003")
660
661 def test_get_params(self):
662 """Get IPFIX flow record generation parameters"""
663 self.logger.info("FFP_TEST_START_0004")
664
665 # Enable feature for an interface with custom parameters
666 ipfix = VppCFLOW(test=self, active=20, passive=40, layer="l2 l3 l4")
667 ipfix.add_vpp_config()
668
669 # Get and verify parameters
670 params = self.vapi.flowprobe_get_params()
671 self.assertEqual(params.active_timer, 20)
672 self.assertEqual(params.passive_timer, 40)
673 record_flags = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
674 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
675 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
676 self.assertEqual(params.record_flags, record_flags)
677
678 ipfix.remove_vpp_config()
679 self.logger.info("FFP_TEST_FINISH_0004")
680
Ole Troan5c749732017-03-13 13:39:52 +0100681
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000682class DatapathTestsHolder(object):
Pavel Kotucek89111d02017-06-12 08:26:13 +0200683 """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
Ole Troan5c749732017-03-13 13:39:52 +0100684
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800685 @classmethod
686 def setUpClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000687 super(DatapathTestsHolder, cls).setUpClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800688
689 @classmethod
690 def tearDownClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000691 super(DatapathTestsHolder, cls).tearDownClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800692
Pavel Kotucek89111d02017-06-12 08:26:13 +0200693 def test_templatesL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200694 """verify template on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100695 self.logger.info("FFP_TEST_START_0000")
696 self.pg_enable_capture(self.pg_interfaces)
697
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000698 ipfix = VppCFLOW(
699 test=self, intf=self.intf1, layer="l2", direction=self.direction
700 )
Ole Troan5c749732017-03-13 13:39:52 +0100701 ipfix.add_vpp_config()
702
703 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400704 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200705 ipfix.verify_templates(timeout=3, count=1)
706 self.collector.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100707
708 ipfix.remove_vpp_config()
709 self.logger.info("FFP_TEST_FINISH_0000")
710
Pavel Kotucek89111d02017-06-12 08:26:13 +0200711 def test_L2onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200712 """L2 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100713 self.logger.info("FFP_TEST_START_0001")
714 self.pg_enable_capture(self.pg_interfaces)
715 self.pkts = []
716
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000717 ipfix = VppCFLOW(
718 test=self, intf=self.intf1, layer="l2", direction=self.direction
719 )
Ole Troan5c749732017-03-13 13:39:52 +0100720 ipfix.add_vpp_config()
721
722 ipfix_decoder = IPFIXDecoder()
723 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200724 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100725
726 self.create_stream(packets=1)
727 capture = self.send_packets()
728
729 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400730 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200731 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200732 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000733 ipfix_decoder,
734 capture,
735 cflow,
736 {2: "packets", 256: 8, 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200737 )
Ole Troan5c749732017-03-13 13:39:52 +0100738 self.collector.get_capture(2)
739
740 ipfix.remove_vpp_config()
741 self.logger.info("FFP_TEST_FINISH_0001")
742
Pavel Kotucek89111d02017-06-12 08:26:13 +0200743 def test_L3onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 """L3 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100745 self.logger.info("FFP_TEST_START_0002")
746 self.pg_enable_capture(self.pg_interfaces)
747 self.pkts = []
748
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000749 ipfix = VppCFLOW(
750 test=self, intf=self.intf1, layer="l3", direction=self.direction
751 )
Ole Troan5c749732017-03-13 13:39:52 +0100752 ipfix.add_vpp_config()
753
754 ipfix_decoder = IPFIXDecoder()
755 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200756 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100757
758 self.create_stream(packets=1)
759 capture = self.send_packets()
760
761 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400762 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200763 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200764 self.verify_cflow_data_detail(
765 ipfix_decoder,
766 capture,
767 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000768 {
769 2: "packets",
770 4: 17,
771 8: "src_ip",
772 12: "dst_ip",
773 61: (self.direction == "tx"),
774 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200775 )
Ole Troan5c749732017-03-13 13:39:52 +0100776
Ole Troan5c749732017-03-13 13:39:52 +0100777 self.collector.get_capture(3)
778
779 ipfix.remove_vpp_config()
780 self.logger.info("FFP_TEST_FINISH_0002")
781
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000782 def test_L234onL2(self):
783 """L2/3/4 data on L2 datapath"""
Alexander Chernavin120095d2023-10-11 12:15:55 +0000784 self.pg_enable_capture(self.pg_interfaces)
785 self.pkts = []
786
787 ipfix = VppCFLOW(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000788 test=self, intf=self.intf1, layer="l2 l3 l4", direction=self.direction
Alexander Chernavin120095d2023-10-11 12:15:55 +0000789 )
790 ipfix.add_vpp_config()
791
792 ipfix_decoder = IPFIXDecoder()
793 # template packet should arrive immediately
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000794 tmpl_l2_field_count = TMPL_COMMON_FIELD_COUNT + TMPL_L2_FIELD_COUNT
795 tmpl_ip_field_count = (
796 TMPL_COMMON_FIELD_COUNT
797 + TMPL_L2_FIELD_COUNT
798 + TMPL_L3_FIELD_COUNT
799 + TMPL_L4_FIELD_COUNT
800 )
801 templates = ipfix.verify_templates(
802 ipfix_decoder,
803 count=3,
804 field_count_in=(tmpl_l2_field_count, tmpl_ip_field_count),
805 )
Alexander Chernavin120095d2023-10-11 12:15:55 +0000806
807 # verify IPv4 and IPv6 flows
808 for ip_ver in ("v4", "v6"):
809 self.create_stream(packets=1, ip_ver=ip_ver)
810 capture = self.send_packets()
811
812 # make sure the one packet we expect actually showed up
813 self.vapi.ipfix_flush()
814 cflow = self.wait_for_cflow_packet(
815 self.collector, templates[1 if ip_ver == "v4" else 2]
816 )
817 src_ip_id = 8 if ip_ver == "v4" else 27
818 dst_ip_id = 12 if ip_ver == "v4" else 28
819 self.verify_cflow_data_detail(
820 ipfix_decoder,
821 capture,
822 cflow,
823 {
824 2: "packets",
825 256: 8 if ip_ver == "v4" else 56710,
826 4: 17,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000827 7: "sport",
828 11: "dport",
Alexander Chernavin120095d2023-10-11 12:15:55 +0000829 src_ip_id: "src_ip",
830 dst_ip_id: "dst_ip",
831 61: (self.direction == "tx"),
832 },
833 ip_ver=ip_ver,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000834 field_count=tmpl_ip_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000835 )
836
837 # verify non-IP flow
838 self.pkts = [
839 (
840 Ether(dst=self.pg2.local_mac, src=self.pg1.remote_mac)
841 / SlowProtocol()
842 / LACP()
843 )
844 ]
845 capture = self.send_packets()
846
847 # make sure the one packet we expect actually showed up
848 self.vapi.ipfix_flush()
849 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
850 self.verify_cflow_data_detail(
851 ipfix_decoder,
852 capture,
853 cflow,
854 {2: "packets", 256: 2440, 61: (self.direction == "tx")},
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000855 field_count=tmpl_l2_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000856 )
857
858 self.collector.get_capture(6)
859
860 ipfix.remove_vpp_config()
861
Pavel Kotucek89111d02017-06-12 08:26:13 +0200862 def test_L4onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 """L4 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100864 self.logger.info("FFP_TEST_START_0003")
865 self.pg_enable_capture(self.pg_interfaces)
866 self.pkts = []
867
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000868 ipfix = VppCFLOW(
869 test=self, intf=self.intf1, layer="l4", direction=self.direction
870 )
Ole Troan5c749732017-03-13 13:39:52 +0100871 ipfix.add_vpp_config()
872
873 ipfix_decoder = IPFIXDecoder()
874 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200875 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100876
877 self.create_stream(packets=1)
878 capture = self.send_packets()
879
880 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400881 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200882 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200883 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000884 ipfix_decoder,
885 capture,
886 cflow,
887 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200888 )
Ole Troan5c749732017-03-13 13:39:52 +0100889
Ole Troan5c749732017-03-13 13:39:52 +0100890 self.collector.get_capture(3)
891
892 ipfix.remove_vpp_config()
893 self.logger.info("FFP_TEST_FINISH_0003")
894
Pavel Kotucek89111d02017-06-12 08:26:13 +0200895 def test_templatesIp4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200896 """verify templates on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100897 self.logger.info("FFP_TEST_START_0000")
898
899 self.pg_enable_capture(self.pg_interfaces)
900
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000901 ipfix = VppCFLOW(
902 test=self, intf=self.intf1, datapath="ip4", direction=self.direction
903 )
Ole Troan5c749732017-03-13 13:39:52 +0100904 ipfix.add_vpp_config()
905
906 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400907 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +0100908 ipfix.verify_templates(timeout=3, count=1)
909 self.collector.get_capture(1)
910
911 ipfix.remove_vpp_config()
912
913 self.logger.info("FFP_TEST_FINISH_0000")
914
Pavel Kotucek89111d02017-06-12 08:26:13 +0200915 def test_L2onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200916 """L2 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100917 self.logger.info("FFP_TEST_START_0001")
918 self.pg_enable_capture(self.pg_interfaces)
919 self.pkts = []
920
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000921 ipfix = VppCFLOW(
922 test=self,
923 intf=self.intf2,
924 layer="l2",
925 datapath="ip4",
926 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200927 )
Ole Troan5c749732017-03-13 13:39:52 +0100928 ipfix.add_vpp_config()
929
930 ipfix_decoder = IPFIXDecoder()
931 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200932 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100933
934 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
935 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
936
937 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400938 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200939 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200940 self.verify_cflow_data_detail(
941 ipfix_decoder,
942 capture,
943 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000944 {2: "packets", 256: 8, 61: (self.direction == "tx")},
945 )
946
947 # expected two templates and one cflow packet
948 self.collector.get_capture(2)
949
950 ipfix.remove_vpp_config()
951 self.logger.info("FFP_TEST_FINISH_0001")
952
953 def test_L3onIP4(self):
954 """L3 data on IP4 datapath"""
955 self.logger.info("FFP_TEST_START_0002")
956 self.pg_enable_capture(self.pg_interfaces)
957 self.pkts = []
958
959 ipfix = VppCFLOW(
960 test=self,
961 intf=self.intf2,
962 layer="l3",
963 datapath="ip4",
964 direction=self.direction,
965 )
966 ipfix.add_vpp_config()
967
968 ipfix_decoder = IPFIXDecoder()
969 # template packet should arrive immediately
970 templates = ipfix.verify_templates(ipfix_decoder, count=1)
971
972 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
973 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
974
975 # make sure the one packet we expect actually showed up
976 self.vapi.ipfix_flush()
977 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
978 self.verify_cflow_data_detail(
979 ipfix_decoder,
980 capture,
981 cflow,
982 {
983 1: "octets",
984 2: "packets",
985 8: "src_ip",
986 12: "dst_ip",
987 61: (self.direction == "tx"),
988 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200989 )
Ole Troan5c749732017-03-13 13:39:52 +0100990
991 # expected two templates and one cflow packet
992 self.collector.get_capture(2)
993
994 ipfix.remove_vpp_config()
995 self.logger.info("FFP_TEST_FINISH_0002")
996
Pavel Kotucek89111d02017-06-12 08:26:13 +0200997 def test_L4onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200998 """L4 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100999 self.logger.info("FFP_TEST_START_0003")
1000 self.pg_enable_capture(self.pg_interfaces)
1001 self.pkts = []
1002
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001003 ipfix = VppCFLOW(
1004 test=self,
1005 intf=self.intf2,
1006 layer="l4",
1007 datapath="ip4",
1008 direction=self.direction,
1009 )
Ole Troan5c749732017-03-13 13:39:52 +01001010 ipfix.add_vpp_config()
1011
1012 ipfix_decoder = IPFIXDecoder()
1013 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001014 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001015
1016 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
1017 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1018
1019 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001020 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001021 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001022 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001023 ipfix_decoder,
1024 capture,
1025 cflow,
1026 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 )
Ole Troan5c749732017-03-13 13:39:52 +01001028
1029 # expected two templates and one cflow packet
1030 self.collector.get_capture(2)
1031
1032 ipfix.remove_vpp_config()
1033 self.logger.info("FFP_TEST_FINISH_0003")
1034
Pavel Kotucek89111d02017-06-12 08:26:13 +02001035 def test_templatesIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 """verify templates on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001037 self.logger.info("FFP_TEST_START_0000")
1038 self.pg_enable_capture(self.pg_interfaces)
1039
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001040 ipfix = VppCFLOW(
1041 test=self, intf=self.intf1, datapath="ip6", direction=self.direction
1042 )
Ole Troan5c749732017-03-13 13:39:52 +01001043 ipfix.add_vpp_config()
1044
1045 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001046 ipfix.verify_templates(count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001047 self.collector.get_capture(1)
1048
1049 ipfix.remove_vpp_config()
1050
1051 self.logger.info("FFP_TEST_FINISH_0000")
1052
Pavel Kotucek89111d02017-06-12 08:26:13 +02001053 def test_L2onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001054 """L2 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001055 self.logger.info("FFP_TEST_START_0001")
1056 self.pg_enable_capture(self.pg_interfaces)
1057 self.pkts = []
1058
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001059 ipfix = VppCFLOW(
1060 test=self,
1061 intf=self.intf3,
1062 layer="l2",
1063 datapath="ip6",
1064 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001065 )
Ole Troan5c749732017-03-13 13:39:52 +01001066 ipfix.add_vpp_config()
1067
1068 ipfix_decoder = IPFIXDecoder()
1069 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001070 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001071
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001072 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001073 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1074
1075 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001076 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001077 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001078 self.verify_cflow_data_detail(
1079 ipfix_decoder,
1080 capture,
1081 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001082 {2: "packets", 256: 56710, 61: (self.direction == "tx")},
1083 ip_ver="v6",
1084 )
1085
1086 # expected two templates and one cflow packet
1087 self.collector.get_capture(2)
1088
1089 ipfix.remove_vpp_config()
1090 self.logger.info("FFP_TEST_FINISH_0001")
1091
1092 def test_L3onIP6(self):
1093 """L3 data on IP6 datapath"""
1094 self.logger.info("FFP_TEST_START_0002")
1095 self.pg_enable_capture(self.pg_interfaces)
1096 self.pkts = []
1097
1098 ipfix = VppCFLOW(
1099 test=self,
1100 intf=self.intf3,
1101 layer="l3",
1102 datapath="ip6",
1103 direction=self.direction,
1104 )
1105 ipfix.add_vpp_config()
1106
1107 ipfix_decoder = IPFIXDecoder()
1108 # template packet should arrive immediately
1109 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1110
1111 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
1112 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1113
1114 # make sure the one packet we expect actually showed up
1115 self.vapi.ipfix_flush()
1116 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1117 self.verify_cflow_data_detail(
1118 ipfix_decoder,
1119 capture,
1120 cflow,
1121 {2: "packets", 27: "src_ip", 28: "dst_ip", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001122 ip_ver="v6",
1123 )
Ole Troan5c749732017-03-13 13:39:52 +01001124
1125 # expected two templates and one cflow packet
1126 self.collector.get_capture(2)
1127
1128 ipfix.remove_vpp_config()
1129 self.logger.info("FFP_TEST_FINISH_0002")
1130
Pavel Kotucek89111d02017-06-12 08:26:13 +02001131 def test_L4onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001132 """L4 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001133 self.logger.info("FFP_TEST_START_0003")
1134 self.pg_enable_capture(self.pg_interfaces)
1135 self.pkts = []
1136
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001137 ipfix = VppCFLOW(
1138 test=self,
1139 intf=self.intf3,
1140 layer="l4",
1141 datapath="ip6",
1142 direction=self.direction,
1143 )
Ole Troan5c749732017-03-13 13:39:52 +01001144 ipfix.add_vpp_config()
1145
1146 ipfix_decoder = IPFIXDecoder()
1147 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001148 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001149
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001150 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001151 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1152
1153 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001154 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001155 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 self.verify_cflow_data_detail(
1157 ipfix_decoder,
1158 capture,
1159 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001160 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001161 ip_ver="v6",
1162 )
Ole Troan5c749732017-03-13 13:39:52 +01001163
1164 # expected two templates and one cflow packet
1165 self.collector.get_capture(2)
1166
1167 ipfix.remove_vpp_config()
1168 self.logger.info("FFP_TEST_FINISH_0003")
1169
Ole Troan5c749732017-03-13 13:39:52 +01001170 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001171 """no timers, one CFLOW packet, 9 Flows inside"""
Ole Troan5c749732017-03-13 13:39:52 +01001172 self.logger.info("FFP_TEST_START_0001")
1173 self.pg_enable_capture(self.pg_interfaces)
1174 self.pkts = []
1175
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001176 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction)
Ole Troan5c749732017-03-13 13:39:52 +01001177 ipfix.add_vpp_config()
1178
1179 ipfix_decoder = IPFIXDecoder()
1180 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001181 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001182
1183 self.create_stream(packets=9)
1184 capture = self.send_packets()
1185
1186 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001187 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001188 cflow = self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001189 self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
Ole Troan5c749732017-03-13 13:39:52 +01001190 self.collector.get_capture(4)
1191
1192 ipfix.remove_vpp_config()
1193 self.logger.info("FFP_TEST_FINISH_0001")
1194
1195 def test_0002(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001196 """no timers, two CFLOW packets (mtu=260), 3 Flows in each"""
Ole Troan5c749732017-03-13 13:39:52 +01001197 self.logger.info("FFP_TEST_START_0002")
1198 self.pg_enable_capture(self.pg_interfaces)
1199 self.pkts = []
1200
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001201 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction, mtu=260)
Ole Troan5c749732017-03-13 13:39:52 +01001202 ipfix.add_vpp_config()
1203
1204 ipfix_decoder = IPFIXDecoder()
1205 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001206 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001207 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001208
1209 self.create_stream(packets=6)
1210 capture = self.send_packets()
1211
1212 # make sure the one packet we expect actually showed up
1213 cflows = []
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001214 self.vapi.ipfix_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001215 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
1216 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
Ole Troan5c749732017-03-13 13:39:52 +01001217 self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
1218 self.collector.get_capture(5)
1219
1220 ipfix.remove_vpp_config()
1221 self.logger.info("FFP_TEST_FINISH_0002")
1222
1223
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001224@tag_fixme_vpp_workers
1225class DatapathTx(MethodHolder, DatapathTestsHolder):
1226 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1227
1228 intf1 = "pg2"
1229 intf2 = "pg4"
1230 intf3 = "pg6"
1231 direction = "tx"
1232
1233
1234@tag_fixme_vpp_workers
1235class DatapathRx(MethodHolder, DatapathTestsHolder):
1236 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1237
1238 intf1 = "pg1"
1239 intf2 = "pg3"
1240 intf3 = "pg5"
1241 direction = "rx"
1242
1243
Klement Sekerab23ffd72021-05-31 16:08:53 +02001244@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001245class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001246 """Disable IPFIX"""
1247
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001248 @classmethod
1249 def setUpClass(cls):
1250 super(DisableIPFIX, cls).setUpClass()
1251
1252 @classmethod
1253 def tearDownClass(cls):
1254 super(DisableIPFIX, cls).tearDownClass()
1255
Ole Troan5c749732017-03-13 13:39:52 +01001256 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001257 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001258 self.logger.info("FFP_TEST_START_0001")
1259 self.pg_enable_capture(self.pg_interfaces)
1260 self.pkts = []
1261
Pavel Kotucek89111d02017-06-12 08:26:13 +02001262 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001263 ipfix.add_vpp_config()
1264
1265 ipfix_decoder = IPFIXDecoder()
1266 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001267 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001268
1269 self.create_stream()
1270 self.send_packets()
1271
1272 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001273 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001274 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001275 self.collector.get_capture(4)
1276
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001277 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001278 ipfix.disable_exporter()
1279 self.pg_enable_capture([self.collector])
1280
1281 self.send_packets()
1282
1283 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001284 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001285 self.sleep(1, "wait before verifying no packets sent")
1286 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001287
1288 ipfix.remove_vpp_config()
1289 self.logger.info("FFP_TEST_FINISH_0001")
1290
1291
Klement Sekerab23ffd72021-05-31 16:08:53 +02001292@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001293class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001294 """Re-enable IPFIX"""
1295
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001296 @classmethod
1297 def setUpClass(cls):
1298 super(ReenableIPFIX, cls).setUpClass()
1299
1300 @classmethod
1301 def tearDownClass(cls):
1302 super(ReenableIPFIX, cls).tearDownClass()
1303
Pavel Kotucek89111d02017-06-12 08:26:13 +02001304 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001305 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001306 self.logger.info("FFP_TEST_START_0001")
1307 self.pg_enable_capture(self.pg_interfaces)
1308 self.pkts = []
1309
Pavel Kotucek89111d02017-06-12 08:26:13 +02001310 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001311 ipfix.add_vpp_config()
1312
1313 ipfix_decoder = IPFIXDecoder()
1314 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001315 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001316
Pavel Kotucek89111d02017-06-12 08:26:13 +02001317 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001318 self.send_packets()
1319
1320 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001321 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001322 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001323 self.collector.get_capture(4)
1324
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001325 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001326 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001327 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001328 self.pg_enable_capture([self.collector])
1329
1330 self.send_packets()
1331
1332 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001333 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001334 self.sleep(1, "wait before verifying no packets sent")
1335 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001336 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001337
1338 # enable IPFIX
1339 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001340
Pavel Kotucek89111d02017-06-12 08:26:13 +02001341 capture = self.collector.get_capture(4)
1342 nr_templates = 0
1343 nr_data = 0
1344 for p in capture:
1345 self.assertTrue(p.haslayer(IPFIX))
1346 if p.haslayer(Template):
1347 nr_templates += 1
1348 self.assertTrue(nr_templates, 3)
1349 for p in capture:
1350 self.assertTrue(p.haslayer(IPFIX))
1351 if p.haslayer(Data):
1352 nr_data += 1
1353 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001354
1355 ipfix.remove_vpp_config()
1356 self.logger.info("FFP_TEST_FINISH_0001")
1357
1358
Klement Sekerab23ffd72021-05-31 16:08:53 +02001359@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001360class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001361 """Disable Flowprobe feature"""
1362
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001363 @classmethod
1364 def setUpClass(cls):
1365 super(DisableFP, cls).setUpClass()
1366
1367 @classmethod
1368 def tearDownClass(cls):
1369 super(DisableFP, cls).tearDownClass()
1370
Ole Troan5c749732017-03-13 13:39:52 +01001371 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001372 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001373 self.logger.info("FFP_TEST_START_0001")
1374 self.pg_enable_capture(self.pg_interfaces)
1375 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001376 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001377 ipfix.add_vpp_config()
1378
1379 ipfix_decoder = IPFIXDecoder()
1380 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001381 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001382
1383 self.create_stream()
1384 self.send_packets()
1385
1386 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001387 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001388 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001389 self.collector.get_capture(4)
1390
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001391 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001392 ipfix.disable_flowprobe_feature()
1393 self.pg_enable_capture([self.collector])
1394
1395 self.send_packets()
1396
1397 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001398 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001399 self.sleep(1, "wait before verifying no packets sent")
1400 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001401
Dave Wallace8800f732023-08-31 00:47:44 -04001402 # enable FPP feature so the remove_vpp_config() doesn't fail
1403 # due to missing feature on interface.
1404 ipfix.enable_flowprobe_feature()
1405
Ole Troan5c749732017-03-13 13:39:52 +01001406 ipfix.remove_vpp_config()
1407 self.logger.info("FFP_TEST_FINISH_0001")
1408
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001409 def test_no_leftover_flows_after_disabling(self):
1410 """disable flowprobe feature and expect no leftover flows"""
1411 self.pg_enable_capture(self.pg_interfaces)
1412 self.pkts = []
1413
1414 # enable ip4 datapath for an interface
1415 # set active and passive timers
1416 ipfix = VppCFLOW(
1417 test=self,
1418 active=3,
1419 passive=4,
1420 intf="pg3",
1421 layer="l3",
1422 datapath="ip4",
1423 direction="rx",
1424 mtu=100,
1425 )
1426 ipfix.add_vpp_config()
1427
1428 # template packet should arrive immediately
1429 ipfix.verify_templates(count=1)
1430
1431 # send some ip4 packets
1432 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1433 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1434
1435 # disable feature for the interface
1436 # currently stored ip4 flows should be removed
1437 ipfix.disable_flowprobe_feature()
1438
1439 # no leftover ip4 flows are expected
1440 self.pg_enable_capture([self.collector])
1441 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1442 self.collector.assert_nothing_captured()
1443
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001444 # re-enable feature for the interface
1445 ipfix.enable_flowprobe_feature()
1446
1447 # template packet should arrive immediately
1448 ipfix_decoder = IPFIXDecoder()
1449 self.vapi.ipfix_flush()
1450 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1451
1452 # send some ip4 packets
1453 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1454 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1455
1456 # verify meta info - packet/octet delta
1457 self.vapi.ipfix_flush()
1458 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1459 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1460
1461 self.collector.get_capture(2)
1462
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001463 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001464 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001465
Ole Troan5c749732017-03-13 13:39:52 +01001466
Klement Sekerab23ffd72021-05-31 16:08:53 +02001467@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001468class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001469 """Re-enable Flowprobe feature"""
1470
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001471 @classmethod
1472 def setUpClass(cls):
1473 super(ReenableFP, cls).setUpClass()
1474
1475 @classmethod
1476 def tearDownClass(cls):
1477 super(ReenableFP, cls).tearDownClass()
1478
Ole Troan5c749732017-03-13 13:39:52 +01001479 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001480 """disable flowprobe feature after first packets and re-enable
1481 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001482 self.logger.info("FFP_TEST_START_0001")
1483 self.pg_enable_capture(self.pg_interfaces)
1484 self.pkts = []
1485
Pavel Kotucek89111d02017-06-12 08:26:13 +02001486 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001487 ipfix.add_vpp_config()
1488
1489 ipfix_decoder = IPFIXDecoder()
1490 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001491 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001492 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1493
1494 self.create_stream()
1495 self.send_packets()
1496
1497 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001498 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001499 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001500 self.collector.get_capture(4)
1501
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001502 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001503 ipfix.disable_flowprobe_feature()
1504 self.pg_enable_capture([self.collector])
1505
1506 self.send_packets()
1507
1508 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001509 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001510 self.sleep(5, "wait before verifying no packets sent")
1511 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001512
1513 # enable FPP feature
1514 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001515 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001516 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1517
1518 self.send_packets()
1519
1520 # make sure the next packets (templates and data) we expect actually
1521 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001522 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001523 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001524 self.collector.get_capture(4)
1525
1526 ipfix.remove_vpp_config()
1527 self.logger.info("FFP_TEST_FINISH_0001")
1528
1529
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001530if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001531 unittest.main(testRunner=VppTestRunner)