blob: ca2bbb53cbcb319ba9425f694b4b0d2b78bf0f5f [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
Alexander Chernavin64d64632023-11-07 11:25:21 +000033from vpp_sub_interface import VppDot1ADSubint
Ole Troan5c749732017-03-13 13:39:52 +010034
35
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000036TMPL_COMMON_FIELD_COUNT = 6
37TMPL_L2_FIELD_COUNT = 3
38TMPL_L3_FIELD_COUNT = 4
39TMPL_L4_FIELD_COUNT = 3
40
Alexander Chernavin21922ce2023-10-26 11:18:19 +000041IPFIX_TCP_FLAGS_ID = 6
42IPFIX_SRC_TRANS_PORT_ID = 7
43IPFIX_DST_TRANS_PORT_ID = 11
Alexander Chernavin64d64632023-11-07 11:25:21 +000044IPFIX_SRC_IP4_ADDR_ID = 8
45IPFIX_DST_IP4_ADDR_ID = 12
46IPFIX_FLOW_DIRECTION_ID = 61
Alexander Chernavin21922ce2023-10-26 11:18:19 +000047
48TCP_F_FIN = 0x01
49TCP_F_SYN = 0x02
50TCP_F_RST = 0x04
51TCP_F_PSH = 0x08
52TCP_F_ACK = 0x10
53TCP_F_URG = 0x20
54TCP_F_ECE = 0x40
55TCP_F_CWR = 0x80
56
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000057
Ole Troan5c749732017-03-13 13:39:52 +010058class VppCFLOW(VppObject):
59 """CFLOW object for IPFIX exporter and Flowprobe feature"""
60
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020061 def __init__(
62 self,
63 test,
64 intf="pg2",
65 active=0,
66 passive=0,
67 timeout=100,
68 mtu=1024,
69 datapath="l2",
70 layer="l2 l3 l4",
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000071 direction="tx",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020072 ):
Ole Troan5c749732017-03-13 13:39:52 +010073 self._test = test
74 self._intf = intf
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000075 self._intf_obj = getattr(self._test, intf)
Ole Troan5c749732017-03-13 13:39:52 +010076 self._active = active
77 if passive == 0 or passive < active:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078 self._passive = active + 1
Ole Troan5c749732017-03-13 13:39:52 +010079 else:
80 self._passive = passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020081 self._datapath = datapath # l2 ip4 ip6
82 self._collect = layer # l2 l3 l4
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000083 self._direction = direction # rx tx both
Ole Troan5c749732017-03-13 13:39:52 +010084 self._timeout = timeout
85 self._mtu = mtu
86 self._configured = False
87
88 def add_vpp_config(self):
89 self.enable_exporter()
Ole Troan3013e692019-12-09 15:51:44 +010090 l2_flag = 0
91 l3_flag = 0
92 l4_flag = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020093 if "l2" in self._collect.lower():
94 l2_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
95 if "l3" in self._collect.lower():
96 l3_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
97 if "l4" in self._collect.lower():
98 l4_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
Alexander Chernavin86c78562022-05-12 14:56:24 +000099 self._test.vapi.flowprobe_set_params(
Ole Troan3013e692019-12-09 15:51:44 +0100100 record_flags=(l2_flag | l3_flag | l4_flag),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 active_timer=self._active,
102 passive_timer=self._passive,
103 )
Ole Troan5c749732017-03-13 13:39:52 +0100104 self.enable_flowprobe_feature()
105 self._test.vapi.cli("ipfix flush")
106 self._configured = True
107
108 def remove_vpp_config(self):
109 self.disable_exporter()
110 self.disable_flowprobe_feature()
111 self._test.vapi.cli("ipfix flush")
112 self._configured = False
113
114 def enable_exporter(self):
115 self._test.vapi.set_ipfix_exporter(
Jakub Grajciar2f71a882019-10-10 14:21:22 +0200116 collector_address=self._test.pg0.remote_ip4,
117 src_address=self._test.pg0.local_ip4,
Ole Troan5c749732017-03-13 13:39:52 +0100118 path_mtu=self._mtu,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 template_interval=self._timeout,
120 )
Ole Troan5c749732017-03-13 13:39:52 +0100121
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000122 def _enable_disable_flowprobe_feature(self, is_add):
123 which_map = {
124 "l2": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2,
125 "ip4": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4,
126 "ip6": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6,
127 }
128 direction_map = {
129 "rx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
130 "tx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
131 "both": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
132 }
133 self._test.vapi.flowprobe_interface_add_del(
134 is_add=is_add,
135 which=which_map[self._datapath],
136 direction=direction_map[self._direction],
137 sw_if_index=self._intf_obj.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200138 )
Ole Troan5c749732017-03-13 13:39:52 +0100139
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000140 def enable_flowprobe_feature(self):
141 self._enable_disable_flowprobe_feature(is_add=True)
142
Ole Troan5c749732017-03-13 13:39:52 +0100143 def disable_exporter(self):
144 self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
145
146 def disable_flowprobe_feature(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000147 self._enable_disable_flowprobe_feature(is_add=False)
Ole Troan5c749732017-03-13 13:39:52 +0100148
149 def object_id(self):
Paul Vinciguerrae3a0e6e2019-03-14 08:46:52 -0700150 return "ipfix-collector-%s-%s" % (self._src, self.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100151
152 def query_vpp_config(self):
153 return self._configured
154
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000155 def verify_templates(self, decoder=None, timeout=1, count=3, field_count_in=None):
Ole Troan5c749732017-03-13 13:39:52 +0100156 templates = []
Klement Sekerac4794572021-09-08 15:15:59 +0200157 self._test.assertIn(count, (1, 2, 3))
158 for _ in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200159 p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
Ole Troan5c749732017-03-13 13:39:52 +0100160 self._test.assertTrue(p.haslayer(IPFIX))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000161 self._test.assertTrue(p.haslayer(Template))
162 if decoder is not None:
Ole Troan5c749732017-03-13 13:39:52 +0100163 templates.append(p[Template].templateID)
164 decoder.add_template(p.getlayer(Template))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000165 if field_count_in is not None:
166 self._test.assertIn(p[Template].fieldCount, field_count_in)
Ole Troan5c749732017-03-13 13:39:52 +0100167 return templates
168
169
170class MethodHolder(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 """Flow-per-packet plugin: test L2, IP4, IP6 reporting"""
Ole Troan5c749732017-03-13 13:39:52 +0100172
173 # Test variables
174 debug_print = False
Pavel Kotucek89111d02017-06-12 08:26:13 +0200175 max_number_of_packets = 10
Ole Troan5c749732017-03-13 13:39:52 +0100176 pkts = []
177
178 @classmethod
179 def setUpClass(cls):
180 """
181 Perform standard class setup (defined by class method setUpClass in
182 class VppTestCase) before running the test case, set test case related
183 variables and configure VPP.
184 """
185 super(MethodHolder, cls).setUpClass()
Dave Wallace670724c2022-09-20 21:52:18 -0400186 if (is_distro_ubuntu2204 == True or is_distro_debian11 == True) and not hasattr(
187 cls, "vpp"
188 ):
189 return
Ole Troan5c749732017-03-13 13:39:52 +0100190 try:
191 # Create pg interfaces
Ole Troaned929252017-06-13 21:15:40 +0200192 cls.create_pg_interfaces(range(9))
Ole Troan5c749732017-03-13 13:39:52 +0100193
194 # Packet sizes
195 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
196
197 # Create BD with MAC learning and unknown unicast flooding disabled
198 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200199 cls.vapi.bridge_domain_add_del_v2(
200 bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
201 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100202 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200203 rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1
204 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100205 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1
207 )
Ole Troan5c749732017-03-13 13:39:52 +0100208
209 # Set up all interfaces
210 for i in cls.pg_interfaces:
211 i.admin_up()
212
213 cls.pg0.config_ip4()
214 cls.pg0.configure_ipv4_neighbors()
215 cls.collector = cls.pg0
216
217 cls.pg1.config_ip4()
218 cls.pg1.resolve_arp()
219 cls.pg2.config_ip4()
220 cls.pg2.resolve_arp()
221 cls.pg3.config_ip4()
222 cls.pg3.resolve_arp()
223 cls.pg4.config_ip4()
224 cls.pg4.resolve_arp()
Ole Troaned929252017-06-13 21:15:40 +0200225 cls.pg7.config_ip4()
226 cls.pg8.config_ip4()
227 cls.pg8.configure_ipv4_neighbors()
Ole Troan5c749732017-03-13 13:39:52 +0100228
229 cls.pg5.config_ip6()
230 cls.pg5.resolve_ndp()
231 cls.pg5.disable_ipv6_ra()
232 cls.pg6.config_ip6()
233 cls.pg6.resolve_ndp()
234 cls.pg6.disable_ipv6_ra()
235 except Exception:
236 super(MethodHolder, cls).tearDownClass()
237 raise
238
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800239 @classmethod
240 def tearDownClass(cls):
241 super(MethodHolder, cls).tearDownClass()
242
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 def create_stream(
244 self, src_if=None, dst_if=None, packets=None, size=None, ip_ver="v4"
245 ):
Ole Troan5c749732017-03-13 13:39:52 +0100246 """Create a packet stream to tickle the plugin
247
248 :param VppInterface src_if: Source interface for packet stream
249 :param VppInterface src_if: Dst interface for packet stream
250 """
251 if src_if is None:
252 src_if = self.pg1
253 if dst_if is None:
254 dst_if = self.pg2
255 self.pkts = []
256 if packets is None:
257 packets = random.randint(1, self.max_number_of_packets)
258 pkt_size = size
259 for p in range(0, packets):
260 if size is None:
261 pkt_size = random.choice(self.pg_if_packet_sizes)
262 info = self.create_packet_info(src_if, dst_if)
263 payload = self.info_to_payload(info)
264 p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 if ip_ver == "v4":
Ole Troan5c749732017-03-13 13:39:52 +0100266 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
267 else:
268 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
Ole Troaned929252017-06-13 21:15:40 +0200269 p /= UDP(sport=1234, dport=4321)
270 p /= Raw(payload)
Ole Troan5c749732017-03-13 13:39:52 +0100271 info.data = p.copy()
272 self.extend_packet(p, pkt_size)
273 self.pkts.append(p)
274
275 def verify_cflow_data(self, decoder, capture, cflow):
276 octets = 0
277 packets = 0
278 for p in capture:
279 octets += p[IP].len
280 packets += 1
281 if cflow.haslayer(Data):
282 data = decoder.decode_data_set(cflow.getlayer(Set))
283 for record in data:
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800284 self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
285 self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
Ole Troan5c749732017-03-13 13:39:52 +0100286
Pavel Kotucek89111d02017-06-12 08:26:13 +0200287 def send_packets(self, src_if=None, dst_if=None):
288 if src_if is None:
289 src_if = self.pg1
290 if dst_if is None:
291 dst_if = self.pg2
292 self.pg_enable_capture([dst_if])
293 src_if.add_stream(self.pkts)
294 self.pg_start()
295 return dst_if.get_capture(len(self.pkts))
296
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 def verify_cflow_data_detail(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000298 self,
299 decoder,
300 capture,
301 cflow,
302 data_set={1: "octets", 2: "packets"},
303 ip_ver="v4",
304 field_count=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200305 ):
Ole Troan5c749732017-03-13 13:39:52 +0100306 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800307 print(capture[0].show())
Ole Troan5c749732017-03-13 13:39:52 +0100308 if cflow.haslayer(Data):
309 data = decoder.decode_data_set(cflow.getlayer(Set))
310 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800311 print(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200312 if ip_ver == "v4":
Alexander Chernavin120095d2023-10-11 12:15:55 +0000313 ip_layer = capture[0][IP] if capture[0].haslayer(IP) else None
Ole Troan5c749732017-03-13 13:39:52 +0100314 else:
Alexander Chernavin120095d2023-10-11 12:15:55 +0000315 ip_layer = capture[0][IPv6] if capture[0].haslayer(IPv6) else None
Ole Troan5c749732017-03-13 13:39:52 +0100316 if data_set is not None:
317 for record in data:
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700318 # skip flow if ingress/egress interface is 0
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800319 if int(binascii.hexlify(record[10]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100320 continue
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800321 if int(binascii.hexlify(record[14]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100322 continue
323
324 for field in data_set:
Ole Troan5c749732017-03-13 13:39:52 +0100325 value = data_set[field]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 if value == "octets":
Ole Troan5c749732017-03-13 13:39:52 +0100327 value = ip_layer.len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 if ip_ver == "v6":
329 value += 40 # ??? is this correct
330 elif value == "packets":
Ole Troan5c749732017-03-13 13:39:52 +0100331 value = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 elif value == "src_ip":
333 if ip_ver == "v4":
334 ip = socket.inet_pton(socket.AF_INET, ip_layer.src)
Ole Troan5c749732017-03-13 13:39:52 +0100335 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200336 ip = socket.inet_pton(socket.AF_INET6, ip_layer.src)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800337 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200338 elif value == "dst_ip":
339 if ip_ver == "v4":
340 ip = socket.inet_pton(socket.AF_INET, ip_layer.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100341 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 ip = socket.inet_pton(socket.AF_INET6, ip_layer.dst)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800343 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 elif value == "sport":
Ole Troan5c749732017-03-13 13:39:52 +0100345 value = int(capture[0][UDP].sport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 elif value == "dport":
Ole Troan5c749732017-03-13 13:39:52 +0100347 value = int(capture[0][UDP].dport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200348 self.assertEqual(
349 int(binascii.hexlify(record[field]), 16), value
350 )
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000351 if field_count is not None:
352 for record in data:
353 self.assertEqual(len(record), field_count)
Ole Troan5c749732017-03-13 13:39:52 +0100354
355 def verify_cflow_data_notimer(self, decoder, capture, cflows):
356 idx = 0
357 for cflow in cflows:
358 if cflow.haslayer(Data):
359 data = decoder.decode_data_set(cflow.getlayer(Set))
360 else:
361 raise Exception("No CFLOW data")
362
363 for rec in data:
364 p = capture[idx]
365 idx += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366 self.assertEqual(p[IP].len, int(binascii.hexlify(rec[1]), 16))
367 self.assertEqual(1, int(binascii.hexlify(rec[2]), 16))
Ole Troan5c749732017-03-13 13:39:52 +0100368 self.assertEqual(len(capture), idx)
369
Klement Sekerac4794572021-09-08 15:15:59 +0200370 def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200371 """wait for CFLOW packet and verify its correctness
Ole Troan5c749732017-03-13 13:39:52 +0100372
373 :param timeout: how long to wait
374
Ole Troan5c749732017-03-13 13:39:52 +0100375 """
376 self.logger.info("IPFIX: Waiting for CFLOW packet")
Ole Troan5c749732017-03-13 13:39:52 +0100377 # self.logger.debug(self.vapi.ppcli("show flow table"))
Klement Sekerac4794572021-09-08 15:15:59 +0200378 p = collector_intf.wait_for_packet(timeout=timeout)
379 self.assertEqual(p[Set].setID, set_id)
380 # self.logger.debug(self.vapi.ppcli("show flow table"))
381 self.logger.debug(ppp("IPFIX: Got packet:", p))
Ole Troan5c749732017-03-13 13:39:52 +0100382 return p
383
Ole Troan5c749732017-03-13 13:39:52 +0100384
Andrew Yourtchenko06f32812021-01-14 10:19:08 +0000385@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000386@tag_fixme_vpp_workers
Dave Wallace670724c2022-09-20 21:52:18 -0400387@tag_fixme_ubuntu2204
388@tag_fixme_debian11
Ole Troaned929252017-06-13 21:15:40 +0200389class Flowprobe(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +0100390 """Template verification, timer tests"""
391
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800392 @classmethod
393 def setUpClass(cls):
394 super(Flowprobe, cls).setUpClass()
395
396 @classmethod
397 def tearDownClass(cls):
398 super(Flowprobe, cls).tearDownClass()
399
Ole Troan5c749732017-03-13 13:39:52 +0100400 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 """timer less than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200402 self.logger.info("FFP_TEST_START_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100403 self.pg_enable_capture(self.pg_interfaces)
404 self.pkts = []
405
Pavel Kotucek89111d02017-06-12 08:26:13 +0200406 ipfix = VppCFLOW(test=self, active=2)
Ole Troan5c749732017-03-13 13:39:52 +0100407 ipfix.add_vpp_config()
408
409 ipfix_decoder = IPFIXDecoder()
410 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200411 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +0100412
Ole Troaned929252017-06-13 21:15:40 +0200413 self.create_stream(packets=1)
Pavel Kotucek89111d02017-06-12 08:26:13 +0200414 self.send_packets()
Ole Troaned929252017-06-13 21:15:40 +0200415 capture = self.pg2.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100416
417 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200418 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100419 self.verify_cflow_data(ipfix_decoder, capture, cflow)
420
421 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200422 self.logger.info("FFP_TEST_FINISH_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100423
Pavel Kotucek89111d02017-06-12 08:26:13 +0200424 def test_0002(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200425 """timer greater than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200426 self.logger.info("FFP_TEST_START_0002")
Ole Troan5c749732017-03-13 13:39:52 +0100427 self.pg_enable_capture(self.pg_interfaces)
428 self.pkts = []
429
Pavel Kotucek89111d02017-06-12 08:26:13 +0200430 ipfix = VppCFLOW(test=self, timeout=3, active=4)
Ole Troan5c749732017-03-13 13:39:52 +0100431 ipfix.add_vpp_config()
432
433 ipfix_decoder = IPFIXDecoder()
434 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200435 ipfix.verify_templates()
Ole Troan5c749732017-03-13 13:39:52 +0100436
Pavel Kotucek89111d02017-06-12 08:26:13 +0200437 self.create_stream(packets=2)
438 self.send_packets()
439 capture = self.pg2.get_capture(2)
Ole Troan5c749732017-03-13 13:39:52 +0100440
441 # next set of template packet should arrive after 20 seconds
442 # template packet should arrive within 20 s
Pavel Kotucek89111d02017-06-12 08:26:13 +0200443 templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
Ole Troan5c749732017-03-13 13:39:52 +0100444
445 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200446 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100447 self.verify_cflow_data(ipfix_decoder, capture, cflow)
448
449 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200450 self.logger.info("FFP_TEST_FINISH_0002")
451
452 def test_cflow_packet(self):
453 """verify cflow packet fields"""
454 self.logger.info("FFP_TEST_START_0000")
455 self.pg_enable_capture(self.pg_interfaces)
456 self.pkts = []
457
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200458 ipfix = VppCFLOW(
459 test=self, intf="pg8", datapath="ip4", layer="l2 l3 l4", active=2
460 )
Ole Troaned929252017-06-13 21:15:40 +0200461 ipfix.add_vpp_config()
462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200463 route_9001 = VppIpRoute(
464 self,
465 "9.0.0.0",
466 24,
467 [VppRoutePath(self.pg8._remote_hosts[0].ip4, self.pg8.sw_if_index)],
468 )
Ole Troaned929252017-06-13 21:15:40 +0200469 route_9001.add_vpp_config()
470
471 ipfix_decoder = IPFIXDecoder()
472 templates = ipfix.verify_templates(ipfix_decoder, count=1)
473
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200474 self.pkts = [
475 (
476 Ether(dst=self.pg7.local_mac, src=self.pg7.remote_mac)
477 / IP(src=self.pg7.remote_ip4, dst="9.0.0.100")
478 / TCP(sport=1234, dport=4321, flags=80)
479 / Raw(b"\xa5" * 100)
480 )
481 ]
Ole Troaned929252017-06-13 21:15:40 +0200482
483 nowUTC = int(time.time())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200484 nowUNIX = nowUTC + 2208988800
Ole Troaned929252017-06-13 21:15:40 +0200485 self.send_packets(src_if=self.pg7, dst_if=self.pg8)
486
487 cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
488 self.collector.get_capture(2)
489
490 if cflow[0].haslayer(IPFIX):
491 self.assertEqual(cflow[IPFIX].version, 10)
492 self.assertEqual(cflow[IPFIX].observationDomainID, 1)
493 self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
494 self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
495 if cflow.haslayer(Data):
496 record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
497 # ingress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800498 self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200499 # egress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800500 self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000501 # direction
502 self.assertEqual(int(binascii.hexlify(record[61]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200503 # packets
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800504 self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200505 # src mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200506 self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
Ole Troaned929252017-06-13 21:15:40 +0200507 # dst mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200508 self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800509 flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200510 # flow start timestamp
511 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800512 flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200513 # flow end timestamp
514 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
515 # ethernet type
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800516 self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200517 # src ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200518 self.assertEqual(inet_ntop(socket.AF_INET, record[8]), self.pg7.remote_ip4)
Ole Troaned929252017-06-13 21:15:40 +0200519 # dst ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200520 self.assertEqual(inet_ntop(socket.AF_INET, record[12]), "9.0.0.100")
Ole Troaned929252017-06-13 21:15:40 +0200521 # protocol (TCP)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800522 self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
Ole Troaned929252017-06-13 21:15:40 +0200523 # src port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800524 self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
Ole Troaned929252017-06-13 21:15:40 +0200525 # dst port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800526 self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
Ole Troaned929252017-06-13 21:15:40 +0200527 # tcp flags
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800528 self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
Ole Troaned929252017-06-13 21:15:40 +0200529
530 ipfix.remove_vpp_config()
531 self.logger.info("FFP_TEST_FINISH_0000")
Ole Troan5c749732017-03-13 13:39:52 +0100532
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000533 def test_flow_entry_reuse(self):
534 """Verify flow entry reuse doesn't accumulate meta info"""
535 self.pg_enable_capture(self.pg_interfaces)
536 self.pkts = []
537
538 # enable ip4 datapath for an interface
539 # set active and passive timers
540 ipfix = VppCFLOW(
541 test=self,
542 active=2,
543 passive=3,
544 intf="pg3",
545 layer="l3 l4",
546 datapath="ip4",
547 direction="rx",
548 mtu=100,
549 )
550 ipfix.add_vpp_config()
551
552 # template packet should arrive immediately
553 ipfix_decoder = IPFIXDecoder()
554 templates = ipfix.verify_templates(ipfix_decoder, count=1)
555
556 # make a tcp packet
557 self.pkts = [
558 (
559 Ether(src=self.pg3.remote_mac, dst=self.pg4.local_mac)
560 / IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
561 / TCP(sport=1234, dport=4321)
562 / Raw(b"\xa5" * 50)
563 )
564 ]
565
566 # send the tcp packet two times, each time with new set of flags
567 tcp_flags = (
568 TCP_F_SYN | TCP_F_ACK,
569 TCP_F_RST | TCP_F_PSH,
570 )
571 for f in tcp_flags:
572 self.pkts[0][TCP].flags = f
573 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
574
575 # verify meta info - packet/octet delta and tcp flags
576 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=6)
577 self.verify_cflow_data(ipfix_decoder, capture, cflow)
578 self.verify_cflow_data_detail(
579 ipfix_decoder,
580 capture,
581 cflow,
582 {
583 IPFIX_TCP_FLAGS_ID: f,
584 IPFIX_SRC_TRANS_PORT_ID: 1234,
585 IPFIX_DST_TRANS_PORT_ID: 4321,
586 },
587 )
588
589 self.collector.get_capture(3)
590
591 # cleanup
592 ipfix.remove_vpp_config()
593
Alexander Chernavin86c78562022-05-12 14:56:24 +0000594 def test_interface_dump(self):
595 """Dump interfaces with IPFIX flow record generation enabled"""
596 self.logger.info("FFP_TEST_START_0003")
597
598 # Enable feature for 3 interfaces
599 ipfix1 = VppCFLOW(test=self, intf="pg1", datapath="l2", direction="rx")
600 ipfix1.add_vpp_config()
601
602 ipfix2 = VppCFLOW(test=self, intf="pg2", datapath="ip4", direction="tx")
603 ipfix2.enable_flowprobe_feature()
604
605 ipfix3 = VppCFLOW(test=self, intf="pg3", datapath="ip6", direction="both")
606 ipfix3.enable_flowprobe_feature()
607
608 # When request "all", dump should contain all enabled interfaces
609 dump = self.vapi.flowprobe_interface_dump()
610 self.assertEqual(len(dump), 3)
611
612 # Verify 1st interface
613 self.assertEqual(dump[0].sw_if_index, self.pg1.sw_if_index)
614 self.assertEqual(
615 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2
616 )
617 self.assertEqual(
618 dump[0].direction,
619 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
620 )
621
622 # Verify 2nd interface
623 self.assertEqual(dump[1].sw_if_index, self.pg2.sw_if_index)
624 self.assertEqual(
625 dump[1].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
626 )
627 self.assertEqual(
628 dump[1].direction,
629 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
630 )
631
632 # Verify 3rd interface
633 self.assertEqual(dump[2].sw_if_index, self.pg3.sw_if_index)
634 self.assertEqual(
635 dump[2].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6
636 )
637 self.assertEqual(
638 dump[2].direction,
639 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
640 )
641
642 # When request 2nd interface, dump should contain only the specified interface
643 dump = self.vapi.flowprobe_interface_dump(sw_if_index=self.pg2.sw_if_index)
644 self.assertEqual(len(dump), 1)
645
646 # Verify 2nd interface
647 self.assertEqual(dump[0].sw_if_index, self.pg2.sw_if_index)
648 self.assertEqual(
649 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
650 )
651 self.assertEqual(
652 dump[0].direction,
653 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
654 )
655
656 # When request 99th interface, dump should be empty
657 dump = self.vapi.flowprobe_interface_dump(sw_if_index=99)
658 self.assertEqual(len(dump), 0)
659
660 ipfix1.remove_vpp_config()
661 ipfix2.remove_vpp_config()
662 ipfix3.remove_vpp_config()
663 self.logger.info("FFP_TEST_FINISH_0003")
664
665 def test_get_params(self):
666 """Get IPFIX flow record generation parameters"""
667 self.logger.info("FFP_TEST_START_0004")
668
669 # Enable feature for an interface with custom parameters
670 ipfix = VppCFLOW(test=self, active=20, passive=40, layer="l2 l3 l4")
671 ipfix.add_vpp_config()
672
673 # Get and verify parameters
674 params = self.vapi.flowprobe_get_params()
675 self.assertEqual(params.active_timer, 20)
676 self.assertEqual(params.passive_timer, 40)
677 record_flags = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
678 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
679 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
680 self.assertEqual(params.record_flags, record_flags)
681
682 ipfix.remove_vpp_config()
683 self.logger.info("FFP_TEST_FINISH_0004")
684
Ole Troan5c749732017-03-13 13:39:52 +0100685
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000686class DatapathTestsHolder(object):
Pavel Kotucek89111d02017-06-12 08:26:13 +0200687 """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
Ole Troan5c749732017-03-13 13:39:52 +0100688
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800689 @classmethod
690 def setUpClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000691 super(DatapathTestsHolder, cls).setUpClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800692
693 @classmethod
694 def tearDownClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000695 super(DatapathTestsHolder, cls).tearDownClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800696
Pavel Kotucek89111d02017-06-12 08:26:13 +0200697 def test_templatesL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200698 """verify template on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100699 self.logger.info("FFP_TEST_START_0000")
700 self.pg_enable_capture(self.pg_interfaces)
701
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000702 ipfix = VppCFLOW(
703 test=self, intf=self.intf1, layer="l2", direction=self.direction
704 )
Ole Troan5c749732017-03-13 13:39:52 +0100705 ipfix.add_vpp_config()
706
707 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400708 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200709 ipfix.verify_templates(timeout=3, count=1)
710 self.collector.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100711
712 ipfix.remove_vpp_config()
713 self.logger.info("FFP_TEST_FINISH_0000")
714
Pavel Kotucek89111d02017-06-12 08:26:13 +0200715 def test_L2onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200716 """L2 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100717 self.logger.info("FFP_TEST_START_0001")
718 self.pg_enable_capture(self.pg_interfaces)
719 self.pkts = []
720
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000721 ipfix = VppCFLOW(
722 test=self, intf=self.intf1, layer="l2", direction=self.direction
723 )
Ole Troan5c749732017-03-13 13:39:52 +0100724 ipfix.add_vpp_config()
725
726 ipfix_decoder = IPFIXDecoder()
727 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200728 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100729
730 self.create_stream(packets=1)
731 capture = self.send_packets()
732
733 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400734 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200735 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200736 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000737 ipfix_decoder,
738 capture,
739 cflow,
740 {2: "packets", 256: 8, 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200741 )
Ole Troan5c749732017-03-13 13:39:52 +0100742 self.collector.get_capture(2)
743
744 ipfix.remove_vpp_config()
745 self.logger.info("FFP_TEST_FINISH_0001")
746
Pavel Kotucek89111d02017-06-12 08:26:13 +0200747 def test_L3onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200748 """L3 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100749 self.logger.info("FFP_TEST_START_0002")
750 self.pg_enable_capture(self.pg_interfaces)
751 self.pkts = []
752
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000753 ipfix = VppCFLOW(
754 test=self, intf=self.intf1, layer="l3", direction=self.direction
755 )
Ole Troan5c749732017-03-13 13:39:52 +0100756 ipfix.add_vpp_config()
757
758 ipfix_decoder = IPFIXDecoder()
759 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200760 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100761
762 self.create_stream(packets=1)
763 capture = self.send_packets()
764
765 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400766 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200767 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200768 self.verify_cflow_data_detail(
769 ipfix_decoder,
770 capture,
771 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000772 {
773 2: "packets",
774 4: 17,
775 8: "src_ip",
776 12: "dst_ip",
777 61: (self.direction == "tx"),
778 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200779 )
Ole Troan5c749732017-03-13 13:39:52 +0100780
Ole Troan5c749732017-03-13 13:39:52 +0100781 self.collector.get_capture(3)
782
783 ipfix.remove_vpp_config()
784 self.logger.info("FFP_TEST_FINISH_0002")
785
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000786 def test_L234onL2(self):
787 """L2/3/4 data on L2 datapath"""
Alexander Chernavin120095d2023-10-11 12:15:55 +0000788 self.pg_enable_capture(self.pg_interfaces)
789 self.pkts = []
790
791 ipfix = VppCFLOW(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000792 test=self, intf=self.intf1, layer="l2 l3 l4", direction=self.direction
Alexander Chernavin120095d2023-10-11 12:15:55 +0000793 )
794 ipfix.add_vpp_config()
795
796 ipfix_decoder = IPFIXDecoder()
797 # template packet should arrive immediately
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000798 tmpl_l2_field_count = TMPL_COMMON_FIELD_COUNT + TMPL_L2_FIELD_COUNT
799 tmpl_ip_field_count = (
800 TMPL_COMMON_FIELD_COUNT
801 + TMPL_L2_FIELD_COUNT
802 + TMPL_L3_FIELD_COUNT
803 + TMPL_L4_FIELD_COUNT
804 )
805 templates = ipfix.verify_templates(
806 ipfix_decoder,
807 count=3,
808 field_count_in=(tmpl_l2_field_count, tmpl_ip_field_count),
809 )
Alexander Chernavin120095d2023-10-11 12:15:55 +0000810
811 # verify IPv4 and IPv6 flows
812 for ip_ver in ("v4", "v6"):
813 self.create_stream(packets=1, ip_ver=ip_ver)
814 capture = self.send_packets()
815
816 # make sure the one packet we expect actually showed up
817 self.vapi.ipfix_flush()
818 cflow = self.wait_for_cflow_packet(
819 self.collector, templates[1 if ip_ver == "v4" else 2]
820 )
821 src_ip_id = 8 if ip_ver == "v4" else 27
822 dst_ip_id = 12 if ip_ver == "v4" else 28
823 self.verify_cflow_data_detail(
824 ipfix_decoder,
825 capture,
826 cflow,
827 {
828 2: "packets",
829 256: 8 if ip_ver == "v4" else 56710,
830 4: 17,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000831 7: "sport",
832 11: "dport",
Alexander Chernavin120095d2023-10-11 12:15:55 +0000833 src_ip_id: "src_ip",
834 dst_ip_id: "dst_ip",
835 61: (self.direction == "tx"),
836 },
837 ip_ver=ip_ver,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000838 field_count=tmpl_ip_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000839 )
840
841 # verify non-IP flow
842 self.pkts = [
843 (
844 Ether(dst=self.pg2.local_mac, src=self.pg1.remote_mac)
845 / SlowProtocol()
846 / LACP()
847 )
848 ]
849 capture = self.send_packets()
850
851 # make sure the one packet we expect actually showed up
852 self.vapi.ipfix_flush()
853 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
854 self.verify_cflow_data_detail(
855 ipfix_decoder,
856 capture,
857 cflow,
858 {2: "packets", 256: 2440, 61: (self.direction == "tx")},
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000859 field_count=tmpl_l2_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000860 )
861
862 self.collector.get_capture(6)
863
864 ipfix.remove_vpp_config()
865
Pavel Kotucek89111d02017-06-12 08:26:13 +0200866 def test_L4onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200867 """L4 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100868 self.logger.info("FFP_TEST_START_0003")
869 self.pg_enable_capture(self.pg_interfaces)
870 self.pkts = []
871
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000872 ipfix = VppCFLOW(
873 test=self, intf=self.intf1, layer="l4", direction=self.direction
874 )
Ole Troan5c749732017-03-13 13:39:52 +0100875 ipfix.add_vpp_config()
876
877 ipfix_decoder = IPFIXDecoder()
878 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200879 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100880
881 self.create_stream(packets=1)
882 capture = self.send_packets()
883
884 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400885 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200886 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200887 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000888 ipfix_decoder,
889 capture,
890 cflow,
891 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200892 )
Ole Troan5c749732017-03-13 13:39:52 +0100893
Ole Troan5c749732017-03-13 13:39:52 +0100894 self.collector.get_capture(3)
895
896 ipfix.remove_vpp_config()
897 self.logger.info("FFP_TEST_FINISH_0003")
898
Pavel Kotucek89111d02017-06-12 08:26:13 +0200899 def test_templatesIp4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200900 """verify templates on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100901 self.logger.info("FFP_TEST_START_0000")
902
903 self.pg_enable_capture(self.pg_interfaces)
904
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000905 ipfix = VppCFLOW(
906 test=self, intf=self.intf1, datapath="ip4", direction=self.direction
907 )
Ole Troan5c749732017-03-13 13:39:52 +0100908 ipfix.add_vpp_config()
909
910 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400911 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +0100912 ipfix.verify_templates(timeout=3, count=1)
913 self.collector.get_capture(1)
914
915 ipfix.remove_vpp_config()
916
917 self.logger.info("FFP_TEST_FINISH_0000")
918
Pavel Kotucek89111d02017-06-12 08:26:13 +0200919 def test_L2onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200920 """L2 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100921 self.logger.info("FFP_TEST_START_0001")
922 self.pg_enable_capture(self.pg_interfaces)
923 self.pkts = []
924
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000925 ipfix = VppCFLOW(
926 test=self,
927 intf=self.intf2,
928 layer="l2",
929 datapath="ip4",
930 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200931 )
Ole Troan5c749732017-03-13 13:39:52 +0100932 ipfix.add_vpp_config()
933
934 ipfix_decoder = IPFIXDecoder()
935 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200936 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100937
938 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
939 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
940
941 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400942 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200943 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200944 self.verify_cflow_data_detail(
945 ipfix_decoder,
946 capture,
947 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000948 {2: "packets", 256: 8, 61: (self.direction == "tx")},
949 )
950
951 # expected two templates and one cflow packet
952 self.collector.get_capture(2)
953
954 ipfix.remove_vpp_config()
955 self.logger.info("FFP_TEST_FINISH_0001")
956
957 def test_L3onIP4(self):
958 """L3 data on IP4 datapath"""
959 self.logger.info("FFP_TEST_START_0002")
960 self.pg_enable_capture(self.pg_interfaces)
961 self.pkts = []
962
963 ipfix = VppCFLOW(
964 test=self,
965 intf=self.intf2,
966 layer="l3",
967 datapath="ip4",
968 direction=self.direction,
969 )
970 ipfix.add_vpp_config()
971
972 ipfix_decoder = IPFIXDecoder()
973 # template packet should arrive immediately
974 templates = ipfix.verify_templates(ipfix_decoder, count=1)
975
976 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
977 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
978
979 # make sure the one packet we expect actually showed up
980 self.vapi.ipfix_flush()
981 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
982 self.verify_cflow_data_detail(
983 ipfix_decoder,
984 capture,
985 cflow,
986 {
987 1: "octets",
988 2: "packets",
989 8: "src_ip",
990 12: "dst_ip",
991 61: (self.direction == "tx"),
992 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200993 )
Ole Troan5c749732017-03-13 13:39:52 +0100994
995 # expected two templates and one cflow packet
996 self.collector.get_capture(2)
997
998 ipfix.remove_vpp_config()
999 self.logger.info("FFP_TEST_FINISH_0002")
1000
Pavel Kotucek89111d02017-06-12 08:26:13 +02001001 def test_L4onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001002 """L4 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001003 self.logger.info("FFP_TEST_START_0003")
1004 self.pg_enable_capture(self.pg_interfaces)
1005 self.pkts = []
1006
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001007 ipfix = VppCFLOW(
1008 test=self,
1009 intf=self.intf2,
1010 layer="l4",
1011 datapath="ip4",
1012 direction=self.direction,
1013 )
Ole Troan5c749732017-03-13 13:39:52 +01001014 ipfix.add_vpp_config()
1015
1016 ipfix_decoder = IPFIXDecoder()
1017 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001018 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001019
1020 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
1021 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1022
1023 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001024 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001025 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001026 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001027 ipfix_decoder,
1028 capture,
1029 cflow,
1030 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 )
Ole Troan5c749732017-03-13 13:39:52 +01001032
1033 # expected two templates and one cflow packet
1034 self.collector.get_capture(2)
1035
1036 ipfix.remove_vpp_config()
1037 self.logger.info("FFP_TEST_FINISH_0003")
1038
Pavel Kotucek89111d02017-06-12 08:26:13 +02001039 def test_templatesIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001040 """verify templates on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001041 self.logger.info("FFP_TEST_START_0000")
1042 self.pg_enable_capture(self.pg_interfaces)
1043
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001044 ipfix = VppCFLOW(
1045 test=self, intf=self.intf1, datapath="ip6", direction=self.direction
1046 )
Ole Troan5c749732017-03-13 13:39:52 +01001047 ipfix.add_vpp_config()
1048
1049 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001050 ipfix.verify_templates(count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001051 self.collector.get_capture(1)
1052
1053 ipfix.remove_vpp_config()
1054
1055 self.logger.info("FFP_TEST_FINISH_0000")
1056
Pavel Kotucek89111d02017-06-12 08:26:13 +02001057 def test_L2onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001058 """L2 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001059 self.logger.info("FFP_TEST_START_0001")
1060 self.pg_enable_capture(self.pg_interfaces)
1061 self.pkts = []
1062
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001063 ipfix = VppCFLOW(
1064 test=self,
1065 intf=self.intf3,
1066 layer="l2",
1067 datapath="ip6",
1068 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 )
Ole Troan5c749732017-03-13 13:39:52 +01001070 ipfix.add_vpp_config()
1071
1072 ipfix_decoder = IPFIXDecoder()
1073 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001074 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001075
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001076 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001077 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1078
1079 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001080 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001081 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 self.verify_cflow_data_detail(
1083 ipfix_decoder,
1084 capture,
1085 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001086 {2: "packets", 256: 56710, 61: (self.direction == "tx")},
1087 ip_ver="v6",
1088 )
1089
1090 # expected two templates and one cflow packet
1091 self.collector.get_capture(2)
1092
1093 ipfix.remove_vpp_config()
1094 self.logger.info("FFP_TEST_FINISH_0001")
1095
1096 def test_L3onIP6(self):
1097 """L3 data on IP6 datapath"""
1098 self.logger.info("FFP_TEST_START_0002")
1099 self.pg_enable_capture(self.pg_interfaces)
1100 self.pkts = []
1101
1102 ipfix = VppCFLOW(
1103 test=self,
1104 intf=self.intf3,
1105 layer="l3",
1106 datapath="ip6",
1107 direction=self.direction,
1108 )
1109 ipfix.add_vpp_config()
1110
1111 ipfix_decoder = IPFIXDecoder()
1112 # template packet should arrive immediately
1113 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1114
1115 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
1116 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1117
1118 # make sure the one packet we expect actually showed up
1119 self.vapi.ipfix_flush()
1120 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1121 self.verify_cflow_data_detail(
1122 ipfix_decoder,
1123 capture,
1124 cflow,
1125 {2: "packets", 27: "src_ip", 28: "dst_ip", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001126 ip_ver="v6",
1127 )
Ole Troan5c749732017-03-13 13:39:52 +01001128
1129 # expected two templates and one cflow packet
1130 self.collector.get_capture(2)
1131
1132 ipfix.remove_vpp_config()
1133 self.logger.info("FFP_TEST_FINISH_0002")
1134
Pavel Kotucek89111d02017-06-12 08:26:13 +02001135 def test_L4onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001136 """L4 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001137 self.logger.info("FFP_TEST_START_0003")
1138 self.pg_enable_capture(self.pg_interfaces)
1139 self.pkts = []
1140
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001141 ipfix = VppCFLOW(
1142 test=self,
1143 intf=self.intf3,
1144 layer="l4",
1145 datapath="ip6",
1146 direction=self.direction,
1147 )
Ole Troan5c749732017-03-13 13:39:52 +01001148 ipfix.add_vpp_config()
1149
1150 ipfix_decoder = IPFIXDecoder()
1151 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001152 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001153
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001154 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001155 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1156
1157 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001158 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001159 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001160 self.verify_cflow_data_detail(
1161 ipfix_decoder,
1162 capture,
1163 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001164 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001165 ip_ver="v6",
1166 )
Ole Troan5c749732017-03-13 13:39:52 +01001167
1168 # expected two templates and one cflow packet
1169 self.collector.get_capture(2)
1170
1171 ipfix.remove_vpp_config()
1172 self.logger.info("FFP_TEST_FINISH_0003")
1173
Ole Troan5c749732017-03-13 13:39:52 +01001174 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001175 """no timers, one CFLOW packet, 9 Flows inside"""
Ole Troan5c749732017-03-13 13:39:52 +01001176 self.logger.info("FFP_TEST_START_0001")
1177 self.pg_enable_capture(self.pg_interfaces)
1178 self.pkts = []
1179
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001180 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction)
Ole Troan5c749732017-03-13 13:39:52 +01001181 ipfix.add_vpp_config()
1182
1183 ipfix_decoder = IPFIXDecoder()
1184 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001185 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001186
1187 self.create_stream(packets=9)
1188 capture = self.send_packets()
1189
1190 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001191 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001192 cflow = self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001193 self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
Ole Troan5c749732017-03-13 13:39:52 +01001194 self.collector.get_capture(4)
1195
1196 ipfix.remove_vpp_config()
1197 self.logger.info("FFP_TEST_FINISH_0001")
1198
1199 def test_0002(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001200 """no timers, two CFLOW packets (mtu=260), 3 Flows in each"""
Ole Troan5c749732017-03-13 13:39:52 +01001201 self.logger.info("FFP_TEST_START_0002")
1202 self.pg_enable_capture(self.pg_interfaces)
1203 self.pkts = []
1204
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001205 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction, mtu=260)
Ole Troan5c749732017-03-13 13:39:52 +01001206 ipfix.add_vpp_config()
1207
1208 ipfix_decoder = IPFIXDecoder()
1209 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001210 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001211 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001212
1213 self.create_stream(packets=6)
1214 capture = self.send_packets()
1215
1216 # make sure the one packet we expect actually showed up
1217 cflows = []
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001218 self.vapi.ipfix_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001219 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
1220 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
Ole Troan5c749732017-03-13 13:39:52 +01001221 self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
1222 self.collector.get_capture(5)
1223
1224 ipfix.remove_vpp_config()
1225 self.logger.info("FFP_TEST_FINISH_0002")
1226
1227
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001228@tag_fixme_vpp_workers
1229class DatapathTx(MethodHolder, DatapathTestsHolder):
1230 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1231
1232 intf1 = "pg2"
1233 intf2 = "pg4"
1234 intf3 = "pg6"
1235 direction = "tx"
1236
Alexander Chernavin64d64632023-11-07 11:25:21 +00001237 def test_rewritten_traffic(self):
1238 """Rewritten traffic (from subif to ipfix if)"""
1239 self.pg_enable_capture(self.pg_interfaces)
1240 self.pkts = []
1241
1242 # prepare a sub-interface
1243 subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400)
1244 subif.admin_up()
1245 subif.config_ip4()
1246
1247 # enable ip4 datapath for an interface
1248 ipfix = VppCFLOW(
1249 test=self,
1250 intf="pg8",
1251 datapath="ip4",
1252 layer="l2 l3 l4",
1253 direction=self.direction,
1254 )
1255 ipfix.add_vpp_config()
1256
1257 # template packet should arrive immediately
1258 ipfix_decoder = IPFIXDecoder()
1259 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1260
1261 # forward some traffic through the ipfix interface
1262 route = VppIpRoute(
1263 self,
1264 "9.0.0.0",
1265 24,
1266 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
1267 )
1268 route.add_vpp_config()
1269
1270 # prepare an IPv4 packet (subif => ipfix interface)
1271 pkt = (
1272 Ether(src=subif.remote_mac, dst=self.pg7.local_mac)
1273 / IP(src=subif.remote_ip4, dst="9.0.0.1")
1274 / UDP(sport=1234, dport=4321)
1275 / Raw(b"\xa5" * 123)
1276 )
1277 self.pkts = [
1278 subif.add_dot1ad_layer(pkt, 300, 400),
1279 ]
1280
1281 # send the packet
1282 capture = self.send_packets(self.pg7, self.pg8)
1283
1284 # wait for a flow and verify it
1285 self.vapi.ipfix_flush()
1286 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1287 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1288 self.verify_cflow_data_detail(
1289 ipfix_decoder,
1290 capture,
1291 cflow,
1292 {
1293 IPFIX_SRC_IP4_ADDR_ID: "src_ip",
1294 IPFIX_DST_IP4_ADDR_ID: "dst_ip",
1295 IPFIX_SRC_TRANS_PORT_ID: "sport",
1296 IPFIX_DST_TRANS_PORT_ID: "dport",
1297 IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"),
1298 },
1299 )
1300
1301 self.collector.get_capture(2)
1302
1303 # cleanup
1304 route.remove_vpp_config()
1305 subif.remove_vpp_config()
1306 ipfix.remove_vpp_config()
1307
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001308
1309@tag_fixme_vpp_workers
1310class DatapathRx(MethodHolder, DatapathTestsHolder):
1311 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1312
1313 intf1 = "pg1"
1314 intf2 = "pg3"
1315 intf3 = "pg5"
1316 direction = "rx"
1317
1318
Klement Sekerab23ffd72021-05-31 16:08:53 +02001319@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001320class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001321 """Disable IPFIX"""
1322
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001323 @classmethod
1324 def setUpClass(cls):
1325 super(DisableIPFIX, cls).setUpClass()
1326
1327 @classmethod
1328 def tearDownClass(cls):
1329 super(DisableIPFIX, cls).tearDownClass()
1330
Ole Troan5c749732017-03-13 13:39:52 +01001331 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001332 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001333 self.logger.info("FFP_TEST_START_0001")
1334 self.pg_enable_capture(self.pg_interfaces)
1335 self.pkts = []
1336
Pavel Kotucek89111d02017-06-12 08:26:13 +02001337 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001338 ipfix.add_vpp_config()
1339
1340 ipfix_decoder = IPFIXDecoder()
1341 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001342 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001343
1344 self.create_stream()
1345 self.send_packets()
1346
1347 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001348 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001349 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001350 self.collector.get_capture(4)
1351
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001352 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001353 ipfix.disable_exporter()
1354 self.pg_enable_capture([self.collector])
1355
1356 self.send_packets()
1357
1358 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001359 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001360 self.sleep(1, "wait before verifying no packets sent")
1361 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001362
1363 ipfix.remove_vpp_config()
1364 self.logger.info("FFP_TEST_FINISH_0001")
1365
1366
Klement Sekerab23ffd72021-05-31 16:08:53 +02001367@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001368class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001369 """Re-enable IPFIX"""
1370
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001371 @classmethod
1372 def setUpClass(cls):
1373 super(ReenableIPFIX, cls).setUpClass()
1374
1375 @classmethod
1376 def tearDownClass(cls):
1377 super(ReenableIPFIX, cls).tearDownClass()
1378
Pavel Kotucek89111d02017-06-12 08:26:13 +02001379 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001380 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001381 self.logger.info("FFP_TEST_START_0001")
1382 self.pg_enable_capture(self.pg_interfaces)
1383 self.pkts = []
1384
Pavel Kotucek89111d02017-06-12 08:26:13 +02001385 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001386 ipfix.add_vpp_config()
1387
1388 ipfix_decoder = IPFIXDecoder()
1389 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001390 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001391
Pavel Kotucek89111d02017-06-12 08:26:13 +02001392 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001393 self.send_packets()
1394
1395 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001396 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001397 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001398 self.collector.get_capture(4)
1399
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001400 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001401 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001402 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001403 self.pg_enable_capture([self.collector])
1404
1405 self.send_packets()
1406
1407 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001408 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001409 self.sleep(1, "wait before verifying no packets sent")
1410 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001411 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001412
1413 # enable IPFIX
1414 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001415
Pavel Kotucek89111d02017-06-12 08:26:13 +02001416 capture = self.collector.get_capture(4)
1417 nr_templates = 0
1418 nr_data = 0
1419 for p in capture:
1420 self.assertTrue(p.haslayer(IPFIX))
1421 if p.haslayer(Template):
1422 nr_templates += 1
1423 self.assertTrue(nr_templates, 3)
1424 for p in capture:
1425 self.assertTrue(p.haslayer(IPFIX))
1426 if p.haslayer(Data):
1427 nr_data += 1
1428 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001429
1430 ipfix.remove_vpp_config()
1431 self.logger.info("FFP_TEST_FINISH_0001")
1432
1433
Klement Sekerab23ffd72021-05-31 16:08:53 +02001434@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001435class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001436 """Disable Flowprobe feature"""
1437
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001438 @classmethod
1439 def setUpClass(cls):
1440 super(DisableFP, cls).setUpClass()
1441
1442 @classmethod
1443 def tearDownClass(cls):
1444 super(DisableFP, cls).tearDownClass()
1445
Ole Troan5c749732017-03-13 13:39:52 +01001446 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001447 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001448 self.logger.info("FFP_TEST_START_0001")
1449 self.pg_enable_capture(self.pg_interfaces)
1450 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001451 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001452 ipfix.add_vpp_config()
1453
1454 ipfix_decoder = IPFIXDecoder()
1455 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001456 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001457
1458 self.create_stream()
1459 self.send_packets()
1460
1461 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001462 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001463 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001464 self.collector.get_capture(4)
1465
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001466 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001467 ipfix.disable_flowprobe_feature()
1468 self.pg_enable_capture([self.collector])
1469
1470 self.send_packets()
1471
1472 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001473 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001474 self.sleep(1, "wait before verifying no packets sent")
1475 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001476
Dave Wallace8800f732023-08-31 00:47:44 -04001477 # enable FPP feature so the remove_vpp_config() doesn't fail
1478 # due to missing feature on interface.
1479 ipfix.enable_flowprobe_feature()
1480
Ole Troan5c749732017-03-13 13:39:52 +01001481 ipfix.remove_vpp_config()
1482 self.logger.info("FFP_TEST_FINISH_0001")
1483
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001484 def test_no_leftover_flows_after_disabling(self):
1485 """disable flowprobe feature and expect no leftover flows"""
1486 self.pg_enable_capture(self.pg_interfaces)
1487 self.pkts = []
1488
1489 # enable ip4 datapath for an interface
1490 # set active and passive timers
1491 ipfix = VppCFLOW(
1492 test=self,
1493 active=3,
1494 passive=4,
1495 intf="pg3",
1496 layer="l3",
1497 datapath="ip4",
1498 direction="rx",
1499 mtu=100,
1500 )
1501 ipfix.add_vpp_config()
1502
1503 # template packet should arrive immediately
1504 ipfix.verify_templates(count=1)
1505
1506 # send some ip4 packets
1507 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1508 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1509
1510 # disable feature for the interface
1511 # currently stored ip4 flows should be removed
1512 ipfix.disable_flowprobe_feature()
1513
1514 # no leftover ip4 flows are expected
1515 self.pg_enable_capture([self.collector])
1516 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1517 self.collector.assert_nothing_captured()
1518
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001519 # re-enable feature for the interface
1520 ipfix.enable_flowprobe_feature()
1521
1522 # template packet should arrive immediately
1523 ipfix_decoder = IPFIXDecoder()
1524 self.vapi.ipfix_flush()
1525 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1526
1527 # send some ip4 packets
1528 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1529 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1530
1531 # verify meta info - packet/octet delta
1532 self.vapi.ipfix_flush()
1533 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1534 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1535
1536 self.collector.get_capture(2)
1537
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001538 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001539 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001540
Ole Troan5c749732017-03-13 13:39:52 +01001541
Klement Sekerab23ffd72021-05-31 16:08:53 +02001542@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001543class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001544 """Re-enable Flowprobe feature"""
1545
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001546 @classmethod
1547 def setUpClass(cls):
1548 super(ReenableFP, cls).setUpClass()
1549
1550 @classmethod
1551 def tearDownClass(cls):
1552 super(ReenableFP, cls).tearDownClass()
1553
Ole Troan5c749732017-03-13 13:39:52 +01001554 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 """disable flowprobe feature after first packets and re-enable
1556 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001557 self.logger.info("FFP_TEST_START_0001")
1558 self.pg_enable_capture(self.pg_interfaces)
1559 self.pkts = []
1560
Pavel Kotucek89111d02017-06-12 08:26:13 +02001561 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001562 ipfix.add_vpp_config()
1563
1564 ipfix_decoder = IPFIXDecoder()
1565 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001566 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001567 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1568
1569 self.create_stream()
1570 self.send_packets()
1571
1572 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001573 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001574 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001575 self.collector.get_capture(4)
1576
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001577 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001578 ipfix.disable_flowprobe_feature()
1579 self.pg_enable_capture([self.collector])
1580
1581 self.send_packets()
1582
1583 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001584 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001585 self.sleep(5, "wait before verifying no packets sent")
1586 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001587
1588 # enable FPP feature
1589 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001590 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001591 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1592
1593 self.send_packets()
1594
1595 # make sure the next packets (templates and data) we expect actually
1596 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001597 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001598 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001599 self.collector.get_capture(4)
1600
1601 ipfix.remove_vpp_config()
1602 self.logger.info("FFP_TEST_FINISH_0001")
1603
1604
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001605if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001606 unittest.main(testRunner=VppTestRunner)