blob: 9622e6158b5f7f9440db3f85b681d3155c54ab37 [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
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000034from config import config
Ole Troan5c749732017-03-13 13:39:52 +010035
36
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000037TMPL_COMMON_FIELD_COUNT = 6
38TMPL_L2_FIELD_COUNT = 3
39TMPL_L3_FIELD_COUNT = 4
40TMPL_L4_FIELD_COUNT = 3
41
Alexander Chernavin21922ce2023-10-26 11:18:19 +000042IPFIX_TCP_FLAGS_ID = 6
43IPFIX_SRC_TRANS_PORT_ID = 7
44IPFIX_DST_TRANS_PORT_ID = 11
Alexander Chernavin64d64632023-11-07 11:25:21 +000045IPFIX_SRC_IP4_ADDR_ID = 8
46IPFIX_DST_IP4_ADDR_ID = 12
47IPFIX_FLOW_DIRECTION_ID = 61
Alexander Chernavin21922ce2023-10-26 11:18:19 +000048
49TCP_F_FIN = 0x01
50TCP_F_SYN = 0x02
51TCP_F_RST = 0x04
52TCP_F_PSH = 0x08
53TCP_F_ACK = 0x10
54TCP_F_URG = 0x20
55TCP_F_ECE = 0x40
56TCP_F_CWR = 0x80
57
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000058
Ole Troan5c749732017-03-13 13:39:52 +010059class VppCFLOW(VppObject):
60 """CFLOW object for IPFIX exporter and Flowprobe feature"""
61
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020062 def __init__(
63 self,
64 test,
65 intf="pg2",
66 active=0,
67 passive=0,
68 timeout=100,
69 mtu=1024,
70 datapath="l2",
71 layer="l2 l3 l4",
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000072 direction="tx",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020073 ):
Ole Troan5c749732017-03-13 13:39:52 +010074 self._test = test
75 self._intf = intf
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000076 self._intf_obj = getattr(self._test, intf)
Ole Troan5c749732017-03-13 13:39:52 +010077 self._active = active
78 if passive == 0 or passive < active:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020079 self._passive = active + 1
Ole Troan5c749732017-03-13 13:39:52 +010080 else:
81 self._passive = passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020082 self._datapath = datapath # l2 ip4 ip6
83 self._collect = layer # l2 l3 l4
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000084 self._direction = direction # rx tx both
Ole Troan5c749732017-03-13 13:39:52 +010085 self._timeout = timeout
86 self._mtu = mtu
87 self._configured = False
88
89 def add_vpp_config(self):
90 self.enable_exporter()
Ole Troan3013e692019-12-09 15:51:44 +010091 l2_flag = 0
92 l3_flag = 0
93 l4_flag = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020094 if "l2" in self._collect.lower():
95 l2_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
96 if "l3" in self._collect.lower():
97 l3_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
98 if "l4" in self._collect.lower():
99 l4_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
Alexander Chernavin86c78562022-05-12 14:56:24 +0000100 self._test.vapi.flowprobe_set_params(
Ole Troan3013e692019-12-09 15:51:44 +0100101 record_flags=(l2_flag | l3_flag | l4_flag),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200102 active_timer=self._active,
103 passive_timer=self._passive,
104 )
Ole Troan5c749732017-03-13 13:39:52 +0100105 self.enable_flowprobe_feature()
106 self._test.vapi.cli("ipfix flush")
107 self._configured = True
108
109 def remove_vpp_config(self):
110 self.disable_exporter()
111 self.disable_flowprobe_feature()
112 self._test.vapi.cli("ipfix flush")
113 self._configured = False
114
115 def enable_exporter(self):
116 self._test.vapi.set_ipfix_exporter(
Jakub Grajciar2f71a882019-10-10 14:21:22 +0200117 collector_address=self._test.pg0.remote_ip4,
118 src_address=self._test.pg0.local_ip4,
Ole Troan5c749732017-03-13 13:39:52 +0100119 path_mtu=self._mtu,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200120 template_interval=self._timeout,
121 )
Ole Troan5c749732017-03-13 13:39:52 +0100122
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000123 def _enable_disable_flowprobe_feature(self, is_add):
124 which_map = {
125 "l2": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2,
126 "ip4": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4,
127 "ip6": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6,
128 }
129 direction_map = {
130 "rx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
131 "tx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
132 "both": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
133 }
134 self._test.vapi.flowprobe_interface_add_del(
135 is_add=is_add,
136 which=which_map[self._datapath],
137 direction=direction_map[self._direction],
138 sw_if_index=self._intf_obj.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200139 )
Ole Troan5c749732017-03-13 13:39:52 +0100140
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000141 def enable_flowprobe_feature(self):
142 self._enable_disable_flowprobe_feature(is_add=True)
143
Ole Troan5c749732017-03-13 13:39:52 +0100144 def disable_exporter(self):
145 self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
146
147 def disable_flowprobe_feature(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000148 self._enable_disable_flowprobe_feature(is_add=False)
Ole Troan5c749732017-03-13 13:39:52 +0100149
150 def object_id(self):
Paul Vinciguerrae3a0e6e2019-03-14 08:46:52 -0700151 return "ipfix-collector-%s-%s" % (self._src, self.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100152
153 def query_vpp_config(self):
154 return self._configured
155
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000156 def verify_templates(self, decoder=None, timeout=1, count=3, field_count_in=None):
Ole Troan5c749732017-03-13 13:39:52 +0100157 templates = []
Klement Sekerac4794572021-09-08 15:15:59 +0200158 self._test.assertIn(count, (1, 2, 3))
159 for _ in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200160 p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
Ole Troan5c749732017-03-13 13:39:52 +0100161 self._test.assertTrue(p.haslayer(IPFIX))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000162 self._test.assertTrue(p.haslayer(Template))
163 if decoder is not None:
Ole Troan5c749732017-03-13 13:39:52 +0100164 templates.append(p[Template].templateID)
165 decoder.add_template(p.getlayer(Template))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000166 if field_count_in is not None:
167 self._test.assertIn(p[Template].fieldCount, field_count_in)
Ole Troan5c749732017-03-13 13:39:52 +0100168 return templates
169
170
171class MethodHolder(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200172 """Flow-per-packet plugin: test L2, IP4, IP6 reporting"""
Ole Troan5c749732017-03-13 13:39:52 +0100173
174 # Test variables
175 debug_print = False
Pavel Kotucek89111d02017-06-12 08:26:13 +0200176 max_number_of_packets = 10
Ole Troan5c749732017-03-13 13:39:52 +0100177 pkts = []
178
179 @classmethod
180 def setUpClass(cls):
181 """
182 Perform standard class setup (defined by class method setUpClass in
183 class VppTestCase) before running the test case, set test case related
184 variables and configure VPP.
185 """
186 super(MethodHolder, cls).setUpClass()
Andrew Yourtchenko9987d472024-07-02 18:02:09 +0200187 if (is_distro_debian11 == True) and not hasattr(cls, "vpp"):
Dave Wallace670724c2022-09-20 21:52:18 -0400188 return
Ole Troan5c749732017-03-13 13:39:52 +0100189 try:
190 # Create pg interfaces
Ole Troaned929252017-06-13 21:15:40 +0200191 cls.create_pg_interfaces(range(9))
Ole Troan5c749732017-03-13 13:39:52 +0100192
193 # Packet sizes
194 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
195
196 # Create BD with MAC learning and unknown unicast flooding disabled
197 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200198 cls.vapi.bridge_domain_add_del_v2(
199 bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=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.pg1._sw_if_index, bd_id=1
203 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100204 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200205 rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1
206 )
Ole Troan5c749732017-03-13 13:39:52 +0100207
208 # Set up all interfaces
209 for i in cls.pg_interfaces:
210 i.admin_up()
211
212 cls.pg0.config_ip4()
213 cls.pg0.configure_ipv4_neighbors()
214 cls.collector = cls.pg0
215
216 cls.pg1.config_ip4()
217 cls.pg1.resolve_arp()
218 cls.pg2.config_ip4()
219 cls.pg2.resolve_arp()
220 cls.pg3.config_ip4()
221 cls.pg3.resolve_arp()
222 cls.pg4.config_ip4()
223 cls.pg4.resolve_arp()
Ole Troaned929252017-06-13 21:15:40 +0200224 cls.pg7.config_ip4()
225 cls.pg8.config_ip4()
226 cls.pg8.configure_ipv4_neighbors()
Ole Troan5c749732017-03-13 13:39:52 +0100227
228 cls.pg5.config_ip6()
229 cls.pg5.resolve_ndp()
230 cls.pg5.disable_ipv6_ra()
231 cls.pg6.config_ip6()
232 cls.pg6.resolve_ndp()
233 cls.pg6.disable_ipv6_ra()
234 except Exception:
235 super(MethodHolder, cls).tearDownClass()
236 raise
237
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800238 @classmethod
239 def tearDownClass(cls):
240 super(MethodHolder, cls).tearDownClass()
241
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 def create_stream(
243 self, src_if=None, dst_if=None, packets=None, size=None, ip_ver="v4"
244 ):
Ole Troan5c749732017-03-13 13:39:52 +0100245 """Create a packet stream to tickle the plugin
246
247 :param VppInterface src_if: Source interface for packet stream
248 :param VppInterface src_if: Dst interface for packet stream
249 """
250 if src_if is None:
251 src_if = self.pg1
252 if dst_if is None:
253 dst_if = self.pg2
254 self.pkts = []
255 if packets is None:
256 packets = random.randint(1, self.max_number_of_packets)
257 pkt_size = size
258 for p in range(0, packets):
259 if size is None:
260 pkt_size = random.choice(self.pg_if_packet_sizes)
261 info = self.create_packet_info(src_if, dst_if)
262 payload = self.info_to_payload(info)
263 p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200264 if ip_ver == "v4":
Ole Troan5c749732017-03-13 13:39:52 +0100265 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
266 else:
267 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
Ole Troaned929252017-06-13 21:15:40 +0200268 p /= UDP(sport=1234, dport=4321)
269 p /= Raw(payload)
Ole Troan5c749732017-03-13 13:39:52 +0100270 info.data = p.copy()
271 self.extend_packet(p, pkt_size)
272 self.pkts.append(p)
273
274 def verify_cflow_data(self, decoder, capture, cflow):
275 octets = 0
276 packets = 0
277 for p in capture:
278 octets += p[IP].len
279 packets += 1
280 if cflow.haslayer(Data):
281 data = decoder.decode_data_set(cflow.getlayer(Set))
282 for record in data:
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800283 self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
284 self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
Ole Troan5c749732017-03-13 13:39:52 +0100285
Pavel Kotucek89111d02017-06-12 08:26:13 +0200286 def send_packets(self, src_if=None, dst_if=None):
287 if src_if is None:
288 src_if = self.pg1
289 if dst_if is None:
290 dst_if = self.pg2
291 self.pg_enable_capture([dst_if])
292 src_if.add_stream(self.pkts)
293 self.pg_start()
294 return dst_if.get_capture(len(self.pkts))
295
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200296 def verify_cflow_data_detail(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000297 self,
298 decoder,
299 capture,
300 cflow,
301 data_set={1: "octets", 2: "packets"},
302 ip_ver="v4",
303 field_count=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200304 ):
Ole Troan5c749732017-03-13 13:39:52 +0100305 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800306 print(capture[0].show())
Ole Troan5c749732017-03-13 13:39:52 +0100307 if cflow.haslayer(Data):
308 data = decoder.decode_data_set(cflow.getlayer(Set))
309 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800310 print(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200311 if ip_ver == "v4":
Alexander Chernavin120095d2023-10-11 12:15:55 +0000312 ip_layer = capture[0][IP] if capture[0].haslayer(IP) else None
Ole Troan5c749732017-03-13 13:39:52 +0100313 else:
Alexander Chernavin120095d2023-10-11 12:15:55 +0000314 ip_layer = capture[0][IPv6] if capture[0].haslayer(IPv6) else None
Ole Troan5c749732017-03-13 13:39:52 +0100315 if data_set is not None:
316 for record in data:
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700317 # skip flow if ingress/egress interface is 0
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800318 if int(binascii.hexlify(record[10]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100319 continue
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800320 if int(binascii.hexlify(record[14]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100321 continue
322
323 for field in data_set:
Ole Troan5c749732017-03-13 13:39:52 +0100324 value = data_set[field]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200325 if value == "octets":
Ole Troan5c749732017-03-13 13:39:52 +0100326 value = ip_layer.len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200327 if ip_ver == "v6":
328 value += 40 # ??? is this correct
329 elif value == "packets":
Ole Troan5c749732017-03-13 13:39:52 +0100330 value = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200331 elif value == "src_ip":
332 if ip_ver == "v4":
333 ip = socket.inet_pton(socket.AF_INET, ip_layer.src)
Ole Troan5c749732017-03-13 13:39:52 +0100334 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200335 ip = socket.inet_pton(socket.AF_INET6, ip_layer.src)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800336 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200337 elif value == "dst_ip":
338 if ip_ver == "v4":
339 ip = socket.inet_pton(socket.AF_INET, ip_layer.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100340 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200341 ip = socket.inet_pton(socket.AF_INET6, ip_layer.dst)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800342 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 elif value == "sport":
Ole Troan5c749732017-03-13 13:39:52 +0100344 value = int(capture[0][UDP].sport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200345 elif value == "dport":
Ole Troan5c749732017-03-13 13:39:52 +0100346 value = int(capture[0][UDP].dport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200347 self.assertEqual(
348 int(binascii.hexlify(record[field]), 16), value
349 )
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000350 if field_count is not None:
351 for record in data:
352 self.assertEqual(len(record), field_count)
Ole Troan5c749732017-03-13 13:39:52 +0100353
354 def verify_cflow_data_notimer(self, decoder, capture, cflows):
355 idx = 0
356 for cflow in cflows:
357 if cflow.haslayer(Data):
358 data = decoder.decode_data_set(cflow.getlayer(Set))
359 else:
360 raise Exception("No CFLOW data")
361
362 for rec in data:
363 p = capture[idx]
364 idx += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200365 self.assertEqual(p[IP].len, int(binascii.hexlify(rec[1]), 16))
366 self.assertEqual(1, int(binascii.hexlify(rec[2]), 16))
Ole Troan5c749732017-03-13 13:39:52 +0100367 self.assertEqual(len(capture), idx)
368
Klement Sekerac4794572021-09-08 15:15:59 +0200369 def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200370 """wait for CFLOW packet and verify its correctness
Ole Troan5c749732017-03-13 13:39:52 +0100371
372 :param timeout: how long to wait
373
Ole Troan5c749732017-03-13 13:39:52 +0100374 """
375 self.logger.info("IPFIX: Waiting for CFLOW packet")
Ole Troan5c749732017-03-13 13:39:52 +0100376 # self.logger.debug(self.vapi.ppcli("show flow table"))
Klement Sekerac4794572021-09-08 15:15:59 +0200377 p = collector_intf.wait_for_packet(timeout=timeout)
378 self.assertEqual(p[Set].setID, set_id)
379 # self.logger.debug(self.vapi.ppcli("show flow table"))
380 self.logger.debug(ppp("IPFIX: Got packet:", p))
Ole Troan5c749732017-03-13 13:39:52 +0100381 return p
382
Ole Troan5c749732017-03-13 13:39:52 +0100383
Andrew Yourtchenko06f32812021-01-14 10:19:08 +0000384@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000385@tag_fixme_vpp_workers
Dave Wallace670724c2022-09-20 21:52:18 -0400386@tag_fixme_ubuntu2204
387@tag_fixme_debian11
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000388@unittest.skipIf(
389 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
390)
Ole Troaned929252017-06-13 21:15:40 +0200391class Flowprobe(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +0100392 """Template verification, timer tests"""
393
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800394 @classmethod
395 def setUpClass(cls):
396 super(Flowprobe, cls).setUpClass()
397
398 @classmethod
399 def tearDownClass(cls):
400 super(Flowprobe, cls).tearDownClass()
401
Ole Troan5c749732017-03-13 13:39:52 +0100402 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200403 """timer less than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200404 self.logger.info("FFP_TEST_START_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100405 self.pg_enable_capture(self.pg_interfaces)
406 self.pkts = []
407
Pavel Kotucek89111d02017-06-12 08:26:13 +0200408 ipfix = VppCFLOW(test=self, active=2)
Ole Troan5c749732017-03-13 13:39:52 +0100409 ipfix.add_vpp_config()
410
411 ipfix_decoder = IPFIXDecoder()
412 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200413 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +0100414
Ole Troaned929252017-06-13 21:15:40 +0200415 self.create_stream(packets=1)
Pavel Kotucek89111d02017-06-12 08:26:13 +0200416 self.send_packets()
Ole Troaned929252017-06-13 21:15:40 +0200417 capture = self.pg2.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100418
419 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200420 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100421 self.verify_cflow_data(ipfix_decoder, capture, cflow)
422
423 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200424 self.logger.info("FFP_TEST_FINISH_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100425
adrianvillina77d4ca2023-12-22 16:52:56 +0100426 @unittest.skipUnless(
427 config.extended, "Test is unstable (assertion error, needs to be fixed"
428 )
Pavel Kotucek89111d02017-06-12 08:26:13 +0200429 def test_0002(self):
adrianvillina77d4ca2023-12-22 16:52:56 +0100430 """timer greater than template timeout [UNSTABLE, FIX ME]"""
Ole Troaned929252017-06-13 21:15:40 +0200431 self.logger.info("FFP_TEST_START_0002")
Ole Troan5c749732017-03-13 13:39:52 +0100432 self.pg_enable_capture(self.pg_interfaces)
433 self.pkts = []
434
Pavel Kotucek89111d02017-06-12 08:26:13 +0200435 ipfix = VppCFLOW(test=self, timeout=3, active=4)
Ole Troan5c749732017-03-13 13:39:52 +0100436 ipfix.add_vpp_config()
437
438 ipfix_decoder = IPFIXDecoder()
439 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200440 ipfix.verify_templates()
Ole Troan5c749732017-03-13 13:39:52 +0100441
Pavel Kotucek89111d02017-06-12 08:26:13 +0200442 self.create_stream(packets=2)
443 self.send_packets()
444 capture = self.pg2.get_capture(2)
Ole Troan5c749732017-03-13 13:39:52 +0100445
446 # next set of template packet should arrive after 20 seconds
447 # template packet should arrive within 20 s
Pavel Kotucek89111d02017-06-12 08:26:13 +0200448 templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
Ole Troan5c749732017-03-13 13:39:52 +0100449
450 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200451 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100452 self.verify_cflow_data(ipfix_decoder, capture, cflow)
453
454 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200455 self.logger.info("FFP_TEST_FINISH_0002")
456
457 def test_cflow_packet(self):
458 """verify cflow packet fields"""
459 self.logger.info("FFP_TEST_START_0000")
460 self.pg_enable_capture(self.pg_interfaces)
461 self.pkts = []
462
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200463 ipfix = VppCFLOW(
464 test=self, intf="pg8", datapath="ip4", layer="l2 l3 l4", active=2
465 )
Ole Troaned929252017-06-13 21:15:40 +0200466 ipfix.add_vpp_config()
467
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200468 route_9001 = VppIpRoute(
469 self,
470 "9.0.0.0",
471 24,
472 [VppRoutePath(self.pg8._remote_hosts[0].ip4, self.pg8.sw_if_index)],
473 )
Ole Troaned929252017-06-13 21:15:40 +0200474 route_9001.add_vpp_config()
475
476 ipfix_decoder = IPFIXDecoder()
477 templates = ipfix.verify_templates(ipfix_decoder, count=1)
478
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200479 self.pkts = [
480 (
481 Ether(dst=self.pg7.local_mac, src=self.pg7.remote_mac)
482 / IP(src=self.pg7.remote_ip4, dst="9.0.0.100")
483 / TCP(sport=1234, dport=4321, flags=80)
484 / Raw(b"\xa5" * 100)
485 )
486 ]
Ole Troaned929252017-06-13 21:15:40 +0200487
488 nowUTC = int(time.time())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200489 nowUNIX = nowUTC + 2208988800
Ole Troaned929252017-06-13 21:15:40 +0200490 self.send_packets(src_if=self.pg7, dst_if=self.pg8)
491
492 cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
493 self.collector.get_capture(2)
494
495 if cflow[0].haslayer(IPFIX):
496 self.assertEqual(cflow[IPFIX].version, 10)
497 self.assertEqual(cflow[IPFIX].observationDomainID, 1)
498 self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
499 self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
500 if cflow.haslayer(Data):
501 record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
502 # ingress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800503 self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200504 # egress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800505 self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000506 # direction
507 self.assertEqual(int(binascii.hexlify(record[61]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200508 # packets
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800509 self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200510 # src mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200511 self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
Ole Troaned929252017-06-13 21:15:40 +0200512 # dst mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200513 self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800514 flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200515 # flow start timestamp
516 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800517 flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200518 # flow end timestamp
519 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
520 # ethernet type
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800521 self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200522 # src ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 self.assertEqual(inet_ntop(socket.AF_INET, record[8]), self.pg7.remote_ip4)
Ole Troaned929252017-06-13 21:15:40 +0200524 # dst ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 self.assertEqual(inet_ntop(socket.AF_INET, record[12]), "9.0.0.100")
Ole Troaned929252017-06-13 21:15:40 +0200526 # protocol (TCP)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800527 self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
Ole Troaned929252017-06-13 21:15:40 +0200528 # src port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800529 self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
Ole Troaned929252017-06-13 21:15:40 +0200530 # dst port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800531 self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
Ole Troaned929252017-06-13 21:15:40 +0200532 # tcp flags
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800533 self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
Ole Troaned929252017-06-13 21:15:40 +0200534
535 ipfix.remove_vpp_config()
536 self.logger.info("FFP_TEST_FINISH_0000")
Ole Troan5c749732017-03-13 13:39:52 +0100537
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000538 def test_flow_entry_reuse(self):
539 """Verify flow entry reuse doesn't accumulate meta info"""
540 self.pg_enable_capture(self.pg_interfaces)
541 self.pkts = []
542
543 # enable ip4 datapath for an interface
544 # set active and passive timers
545 ipfix = VppCFLOW(
546 test=self,
547 active=2,
548 passive=3,
549 intf="pg3",
550 layer="l3 l4",
551 datapath="ip4",
552 direction="rx",
553 mtu=100,
554 )
555 ipfix.add_vpp_config()
556
557 # template packet should arrive immediately
558 ipfix_decoder = IPFIXDecoder()
559 templates = ipfix.verify_templates(ipfix_decoder, count=1)
560
561 # make a tcp packet
562 self.pkts = [
563 (
Steven Luonge4238aa2024-04-19 09:49:20 -0700564 Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000565 / IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
566 / TCP(sport=1234, dport=4321)
567 / Raw(b"\xa5" * 50)
568 )
569 ]
570
571 # send the tcp packet two times, each time with new set of flags
572 tcp_flags = (
573 TCP_F_SYN | TCP_F_ACK,
574 TCP_F_RST | TCP_F_PSH,
575 )
576 for f in tcp_flags:
577 self.pkts[0][TCP].flags = f
578 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
579
580 # verify meta info - packet/octet delta and tcp flags
581 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=6)
582 self.verify_cflow_data(ipfix_decoder, capture, cflow)
583 self.verify_cflow_data_detail(
584 ipfix_decoder,
585 capture,
586 cflow,
587 {
588 IPFIX_TCP_FLAGS_ID: f,
589 IPFIX_SRC_TRANS_PORT_ID: 1234,
590 IPFIX_DST_TRANS_PORT_ID: 4321,
591 },
592 )
593
594 self.collector.get_capture(3)
595
596 # cleanup
597 ipfix.remove_vpp_config()
598
Alexander Chernavin86c78562022-05-12 14:56:24 +0000599 def test_interface_dump(self):
600 """Dump interfaces with IPFIX flow record generation enabled"""
601 self.logger.info("FFP_TEST_START_0003")
602
603 # Enable feature for 3 interfaces
604 ipfix1 = VppCFLOW(test=self, intf="pg1", datapath="l2", direction="rx")
605 ipfix1.add_vpp_config()
606
607 ipfix2 = VppCFLOW(test=self, intf="pg2", datapath="ip4", direction="tx")
608 ipfix2.enable_flowprobe_feature()
609
610 ipfix3 = VppCFLOW(test=self, intf="pg3", datapath="ip6", direction="both")
611 ipfix3.enable_flowprobe_feature()
612
613 # When request "all", dump should contain all enabled interfaces
614 dump = self.vapi.flowprobe_interface_dump()
615 self.assertEqual(len(dump), 3)
616
617 # Verify 1st interface
618 self.assertEqual(dump[0].sw_if_index, self.pg1.sw_if_index)
619 self.assertEqual(
620 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2
621 )
622 self.assertEqual(
623 dump[0].direction,
624 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
625 )
626
627 # Verify 2nd interface
628 self.assertEqual(dump[1].sw_if_index, self.pg2.sw_if_index)
629 self.assertEqual(
630 dump[1].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
631 )
632 self.assertEqual(
633 dump[1].direction,
634 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
635 )
636
637 # Verify 3rd interface
638 self.assertEqual(dump[2].sw_if_index, self.pg3.sw_if_index)
639 self.assertEqual(
640 dump[2].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6
641 )
642 self.assertEqual(
643 dump[2].direction,
644 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
645 )
646
647 # When request 2nd interface, dump should contain only the specified interface
648 dump = self.vapi.flowprobe_interface_dump(sw_if_index=self.pg2.sw_if_index)
649 self.assertEqual(len(dump), 1)
650
651 # Verify 2nd interface
652 self.assertEqual(dump[0].sw_if_index, self.pg2.sw_if_index)
653 self.assertEqual(
654 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
655 )
656 self.assertEqual(
657 dump[0].direction,
658 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
659 )
660
661 # When request 99th interface, dump should be empty
662 dump = self.vapi.flowprobe_interface_dump(sw_if_index=99)
663 self.assertEqual(len(dump), 0)
664
665 ipfix1.remove_vpp_config()
666 ipfix2.remove_vpp_config()
667 ipfix3.remove_vpp_config()
668 self.logger.info("FFP_TEST_FINISH_0003")
669
670 def test_get_params(self):
671 """Get IPFIX flow record generation parameters"""
672 self.logger.info("FFP_TEST_START_0004")
673
674 # Enable feature for an interface with custom parameters
675 ipfix = VppCFLOW(test=self, active=20, passive=40, layer="l2 l3 l4")
676 ipfix.add_vpp_config()
677
678 # Get and verify parameters
679 params = self.vapi.flowprobe_get_params()
680 self.assertEqual(params.active_timer, 20)
681 self.assertEqual(params.passive_timer, 40)
682 record_flags = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
683 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
684 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
685 self.assertEqual(params.record_flags, record_flags)
686
687 ipfix.remove_vpp_config()
688 self.logger.info("FFP_TEST_FINISH_0004")
689
Ole Troan5c749732017-03-13 13:39:52 +0100690
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000691class DatapathTestsHolder(object):
Pavel Kotucek89111d02017-06-12 08:26:13 +0200692 """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
Ole Troan5c749732017-03-13 13:39:52 +0100693
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800694 @classmethod
695 def setUpClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000696 super(DatapathTestsHolder, cls).setUpClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800697
698 @classmethod
699 def tearDownClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000700 super(DatapathTestsHolder, cls).tearDownClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800701
Pavel Kotucek89111d02017-06-12 08:26:13 +0200702 def test_templatesL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200703 """verify template on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100704 self.logger.info("FFP_TEST_START_0000")
705 self.pg_enable_capture(self.pg_interfaces)
706
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000707 ipfix = VppCFLOW(
708 test=self, intf=self.intf1, layer="l2", direction=self.direction
709 )
Ole Troan5c749732017-03-13 13:39:52 +0100710 ipfix.add_vpp_config()
711
712 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400713 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200714 ipfix.verify_templates(timeout=3, count=1)
715 self.collector.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100716
717 ipfix.remove_vpp_config()
718 self.logger.info("FFP_TEST_FINISH_0000")
719
Pavel Kotucek89111d02017-06-12 08:26:13 +0200720 def test_L2onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200721 """L2 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100722 self.logger.info("FFP_TEST_START_0001")
723 self.pg_enable_capture(self.pg_interfaces)
724 self.pkts = []
725
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000726 ipfix = VppCFLOW(
727 test=self, intf=self.intf1, layer="l2", direction=self.direction
728 )
Ole Troan5c749732017-03-13 13:39:52 +0100729 ipfix.add_vpp_config()
730
731 ipfix_decoder = IPFIXDecoder()
732 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200733 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100734
735 self.create_stream(packets=1)
736 capture = self.send_packets()
737
738 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400739 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200740 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200741 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000742 ipfix_decoder,
743 capture,
744 cflow,
745 {2: "packets", 256: 8, 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200746 )
Ole Troan5c749732017-03-13 13:39:52 +0100747 self.collector.get_capture(2)
748
749 ipfix.remove_vpp_config()
750 self.logger.info("FFP_TEST_FINISH_0001")
751
Pavel Kotucek89111d02017-06-12 08:26:13 +0200752 def test_L3onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200753 """L3 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100754 self.logger.info("FFP_TEST_START_0002")
755 self.pg_enable_capture(self.pg_interfaces)
756 self.pkts = []
757
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000758 ipfix = VppCFLOW(
759 test=self, intf=self.intf1, layer="l3", direction=self.direction
760 )
Ole Troan5c749732017-03-13 13:39:52 +0100761 ipfix.add_vpp_config()
762
763 ipfix_decoder = IPFIXDecoder()
764 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200765 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100766
767 self.create_stream(packets=1)
768 capture = self.send_packets()
769
770 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400771 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200772 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200773 self.verify_cflow_data_detail(
774 ipfix_decoder,
775 capture,
776 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000777 {
778 2: "packets",
779 4: 17,
780 8: "src_ip",
781 12: "dst_ip",
782 61: (self.direction == "tx"),
783 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200784 )
Ole Troan5c749732017-03-13 13:39:52 +0100785
Ole Troan5c749732017-03-13 13:39:52 +0100786 self.collector.get_capture(3)
787
788 ipfix.remove_vpp_config()
789 self.logger.info("FFP_TEST_FINISH_0002")
790
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000791 def test_L234onL2(self):
792 """L2/3/4 data on L2 datapath"""
Alexander Chernavin120095d2023-10-11 12:15:55 +0000793 self.pg_enable_capture(self.pg_interfaces)
794 self.pkts = []
795
796 ipfix = VppCFLOW(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000797 test=self, intf=self.intf1, layer="l2 l3 l4", direction=self.direction
Alexander Chernavin120095d2023-10-11 12:15:55 +0000798 )
799 ipfix.add_vpp_config()
800
801 ipfix_decoder = IPFIXDecoder()
802 # template packet should arrive immediately
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000803 tmpl_l2_field_count = TMPL_COMMON_FIELD_COUNT + TMPL_L2_FIELD_COUNT
804 tmpl_ip_field_count = (
805 TMPL_COMMON_FIELD_COUNT
806 + TMPL_L2_FIELD_COUNT
807 + TMPL_L3_FIELD_COUNT
808 + TMPL_L4_FIELD_COUNT
809 )
810 templates = ipfix.verify_templates(
811 ipfix_decoder,
812 count=3,
813 field_count_in=(tmpl_l2_field_count, tmpl_ip_field_count),
814 )
Alexander Chernavin120095d2023-10-11 12:15:55 +0000815
816 # verify IPv4 and IPv6 flows
817 for ip_ver in ("v4", "v6"):
818 self.create_stream(packets=1, ip_ver=ip_ver)
819 capture = self.send_packets()
820
821 # make sure the one packet we expect actually showed up
822 self.vapi.ipfix_flush()
823 cflow = self.wait_for_cflow_packet(
824 self.collector, templates[1 if ip_ver == "v4" else 2]
825 )
826 src_ip_id = 8 if ip_ver == "v4" else 27
827 dst_ip_id = 12 if ip_ver == "v4" else 28
828 self.verify_cflow_data_detail(
829 ipfix_decoder,
830 capture,
831 cflow,
832 {
833 2: "packets",
834 256: 8 if ip_ver == "v4" else 56710,
835 4: 17,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000836 7: "sport",
837 11: "dport",
Alexander Chernavin120095d2023-10-11 12:15:55 +0000838 src_ip_id: "src_ip",
839 dst_ip_id: "dst_ip",
840 61: (self.direction == "tx"),
841 },
842 ip_ver=ip_ver,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000843 field_count=tmpl_ip_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000844 )
845
846 # verify non-IP flow
847 self.pkts = [
848 (
849 Ether(dst=self.pg2.local_mac, src=self.pg1.remote_mac)
850 / SlowProtocol()
851 / LACP()
852 )
853 ]
854 capture = self.send_packets()
855
856 # make sure the one packet we expect actually showed up
857 self.vapi.ipfix_flush()
858 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
859 self.verify_cflow_data_detail(
860 ipfix_decoder,
861 capture,
862 cflow,
863 {2: "packets", 256: 2440, 61: (self.direction == "tx")},
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000864 field_count=tmpl_l2_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000865 )
866
867 self.collector.get_capture(6)
868
869 ipfix.remove_vpp_config()
870
Pavel Kotucek89111d02017-06-12 08:26:13 +0200871 def test_L4onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200872 """L4 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100873 self.logger.info("FFP_TEST_START_0003")
874 self.pg_enable_capture(self.pg_interfaces)
875 self.pkts = []
876
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000877 ipfix = VppCFLOW(
878 test=self, intf=self.intf1, layer="l4", direction=self.direction
879 )
Ole Troan5c749732017-03-13 13:39:52 +0100880 ipfix.add_vpp_config()
881
882 ipfix_decoder = IPFIXDecoder()
883 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200884 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100885
886 self.create_stream(packets=1)
887 capture = self.send_packets()
888
889 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400890 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200891 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200892 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000893 ipfix_decoder,
894 capture,
895 cflow,
896 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200897 )
Ole Troan5c749732017-03-13 13:39:52 +0100898
Ole Troan5c749732017-03-13 13:39:52 +0100899 self.collector.get_capture(3)
900
901 ipfix.remove_vpp_config()
902 self.logger.info("FFP_TEST_FINISH_0003")
903
Pavel Kotucek89111d02017-06-12 08:26:13 +0200904 def test_templatesIp4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200905 """verify templates on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100906 self.logger.info("FFP_TEST_START_0000")
907
908 self.pg_enable_capture(self.pg_interfaces)
909
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000910 ipfix = VppCFLOW(
911 test=self, intf=self.intf1, datapath="ip4", direction=self.direction
912 )
Ole Troan5c749732017-03-13 13:39:52 +0100913 ipfix.add_vpp_config()
914
915 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400916 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +0100917 ipfix.verify_templates(timeout=3, count=1)
918 self.collector.get_capture(1)
919
920 ipfix.remove_vpp_config()
921
922 self.logger.info("FFP_TEST_FINISH_0000")
923
Pavel Kotucek89111d02017-06-12 08:26:13 +0200924 def test_L2onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200925 """L2 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100926 self.logger.info("FFP_TEST_START_0001")
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pkts = []
929
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000930 ipfix = VppCFLOW(
931 test=self,
932 intf=self.intf2,
933 layer="l2",
934 datapath="ip4",
935 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200936 )
Ole Troan5c749732017-03-13 13:39:52 +0100937 ipfix.add_vpp_config()
938
939 ipfix_decoder = IPFIXDecoder()
940 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200941 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100942
943 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
944 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
945
946 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400947 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200948 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200949 self.verify_cflow_data_detail(
950 ipfix_decoder,
951 capture,
952 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000953 {2: "packets", 256: 8, 61: (self.direction == "tx")},
954 )
955
956 # expected two templates and one cflow packet
957 self.collector.get_capture(2)
958
959 ipfix.remove_vpp_config()
960 self.logger.info("FFP_TEST_FINISH_0001")
961
962 def test_L3onIP4(self):
963 """L3 data on IP4 datapath"""
964 self.logger.info("FFP_TEST_START_0002")
965 self.pg_enable_capture(self.pg_interfaces)
966 self.pkts = []
967
968 ipfix = VppCFLOW(
969 test=self,
970 intf=self.intf2,
971 layer="l3",
972 datapath="ip4",
973 direction=self.direction,
974 )
975 ipfix.add_vpp_config()
976
977 ipfix_decoder = IPFIXDecoder()
978 # template packet should arrive immediately
979 templates = ipfix.verify_templates(ipfix_decoder, count=1)
980
981 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
982 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
983
984 # make sure the one packet we expect actually showed up
985 self.vapi.ipfix_flush()
986 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
987 self.verify_cflow_data_detail(
988 ipfix_decoder,
989 capture,
990 cflow,
991 {
992 1: "octets",
993 2: "packets",
994 8: "src_ip",
995 12: "dst_ip",
996 61: (self.direction == "tx"),
997 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200998 )
Ole Troan5c749732017-03-13 13:39:52 +0100999
1000 # expected two templates and one cflow packet
1001 self.collector.get_capture(2)
1002
1003 ipfix.remove_vpp_config()
1004 self.logger.info("FFP_TEST_FINISH_0002")
1005
Pavel Kotucek89111d02017-06-12 08:26:13 +02001006 def test_L4onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001007 """L4 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001008 self.logger.info("FFP_TEST_START_0003")
1009 self.pg_enable_capture(self.pg_interfaces)
1010 self.pkts = []
1011
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001012 ipfix = VppCFLOW(
1013 test=self,
1014 intf=self.intf2,
1015 layer="l4",
1016 datapath="ip4",
1017 direction=self.direction,
1018 )
Ole Troan5c749732017-03-13 13:39:52 +01001019 ipfix.add_vpp_config()
1020
1021 ipfix_decoder = IPFIXDecoder()
1022 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001023 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001024
1025 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
1026 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1027
1028 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001029 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001030 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001032 ipfix_decoder,
1033 capture,
1034 cflow,
1035 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001036 )
Ole Troan5c749732017-03-13 13:39:52 +01001037
1038 # expected two templates and one cflow packet
1039 self.collector.get_capture(2)
1040
1041 ipfix.remove_vpp_config()
1042 self.logger.info("FFP_TEST_FINISH_0003")
1043
Pavel Kotucek89111d02017-06-12 08:26:13 +02001044 def test_templatesIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001045 """verify templates on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001046 self.logger.info("FFP_TEST_START_0000")
1047 self.pg_enable_capture(self.pg_interfaces)
1048
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001049 ipfix = VppCFLOW(
1050 test=self, intf=self.intf1, datapath="ip6", direction=self.direction
1051 )
Ole Troan5c749732017-03-13 13:39:52 +01001052 ipfix.add_vpp_config()
1053
1054 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001055 ipfix.verify_templates(count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001056 self.collector.get_capture(1)
1057
1058 ipfix.remove_vpp_config()
1059
1060 self.logger.info("FFP_TEST_FINISH_0000")
1061
Pavel Kotucek89111d02017-06-12 08:26:13 +02001062 def test_L2onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001063 """L2 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001064 self.logger.info("FFP_TEST_START_0001")
1065 self.pg_enable_capture(self.pg_interfaces)
1066 self.pkts = []
1067
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001068 ipfix = VppCFLOW(
1069 test=self,
1070 intf=self.intf3,
1071 layer="l2",
1072 datapath="ip6",
1073 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001074 )
Ole Troan5c749732017-03-13 13:39:52 +01001075 ipfix.add_vpp_config()
1076
1077 ipfix_decoder = IPFIXDecoder()
1078 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001079 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001080
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001081 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001082 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1083
1084 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001085 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001086 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001087 self.verify_cflow_data_detail(
1088 ipfix_decoder,
1089 capture,
1090 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001091 {2: "packets", 256: 56710, 61: (self.direction == "tx")},
1092 ip_ver="v6",
1093 )
1094
1095 # expected two templates and one cflow packet
1096 self.collector.get_capture(2)
1097
1098 ipfix.remove_vpp_config()
1099 self.logger.info("FFP_TEST_FINISH_0001")
1100
1101 def test_L3onIP6(self):
1102 """L3 data on IP6 datapath"""
1103 self.logger.info("FFP_TEST_START_0002")
1104 self.pg_enable_capture(self.pg_interfaces)
1105 self.pkts = []
1106
1107 ipfix = VppCFLOW(
1108 test=self,
1109 intf=self.intf3,
1110 layer="l3",
1111 datapath="ip6",
1112 direction=self.direction,
1113 )
1114 ipfix.add_vpp_config()
1115
1116 ipfix_decoder = IPFIXDecoder()
1117 # template packet should arrive immediately
1118 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1119
1120 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
1121 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1122
1123 # make sure the one packet we expect actually showed up
1124 self.vapi.ipfix_flush()
1125 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1126 self.verify_cflow_data_detail(
1127 ipfix_decoder,
1128 capture,
1129 cflow,
1130 {2: "packets", 27: "src_ip", 28: "dst_ip", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001131 ip_ver="v6",
1132 )
Ole Troan5c749732017-03-13 13:39:52 +01001133
1134 # expected two templates and one cflow packet
1135 self.collector.get_capture(2)
1136
1137 ipfix.remove_vpp_config()
1138 self.logger.info("FFP_TEST_FINISH_0002")
1139
Pavel Kotucek89111d02017-06-12 08:26:13 +02001140 def test_L4onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001141 """L4 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001142 self.logger.info("FFP_TEST_START_0003")
1143 self.pg_enable_capture(self.pg_interfaces)
1144 self.pkts = []
1145
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001146 ipfix = VppCFLOW(
1147 test=self,
1148 intf=self.intf3,
1149 layer="l4",
1150 datapath="ip6",
1151 direction=self.direction,
1152 )
Ole Troan5c749732017-03-13 13:39:52 +01001153 ipfix.add_vpp_config()
1154
1155 ipfix_decoder = IPFIXDecoder()
1156 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001157 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001158
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001159 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001160 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1161
1162 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001163 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001164 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001165 self.verify_cflow_data_detail(
1166 ipfix_decoder,
1167 capture,
1168 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001169 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001170 ip_ver="v6",
1171 )
Ole Troan5c749732017-03-13 13:39:52 +01001172
1173 # expected two templates and one cflow packet
1174 self.collector.get_capture(2)
1175
1176 ipfix.remove_vpp_config()
1177 self.logger.info("FFP_TEST_FINISH_0003")
1178
Ole Troan5c749732017-03-13 13:39:52 +01001179 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001180 """no timers, one CFLOW packet, 9 Flows inside"""
Ole Troan5c749732017-03-13 13:39:52 +01001181 self.logger.info("FFP_TEST_START_0001")
1182 self.pg_enable_capture(self.pg_interfaces)
1183 self.pkts = []
1184
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001185 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction)
Ole Troan5c749732017-03-13 13:39:52 +01001186 ipfix.add_vpp_config()
1187
1188 ipfix_decoder = IPFIXDecoder()
1189 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001190 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001191
1192 self.create_stream(packets=9)
1193 capture = self.send_packets()
1194
1195 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001196 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001197 cflow = self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001198 self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
Ole Troan5c749732017-03-13 13:39:52 +01001199 self.collector.get_capture(4)
1200
1201 ipfix.remove_vpp_config()
1202 self.logger.info("FFP_TEST_FINISH_0001")
1203
1204 def test_0002(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001205 """no timers, two CFLOW packets (mtu=260), 3 Flows in each"""
Ole Troan5c749732017-03-13 13:39:52 +01001206 self.logger.info("FFP_TEST_START_0002")
1207 self.pg_enable_capture(self.pg_interfaces)
1208 self.pkts = []
1209
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001210 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction, mtu=260)
Ole Troan5c749732017-03-13 13:39:52 +01001211 ipfix.add_vpp_config()
1212
1213 ipfix_decoder = IPFIXDecoder()
1214 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001215 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001216 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001217
1218 self.create_stream(packets=6)
1219 capture = self.send_packets()
1220
1221 # make sure the one packet we expect actually showed up
1222 cflows = []
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001223 self.vapi.ipfix_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001224 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
1225 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
Ole Troan5c749732017-03-13 13:39:52 +01001226 self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
1227 self.collector.get_capture(5)
1228
1229 ipfix.remove_vpp_config()
1230 self.logger.info("FFP_TEST_FINISH_0002")
1231
1232
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001233@unittest.skipIf(
1234 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1235)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001236class DatapathTx(MethodHolder, DatapathTestsHolder):
1237 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1238
1239 intf1 = "pg2"
1240 intf2 = "pg4"
1241 intf3 = "pg6"
1242 direction = "tx"
1243
Alexander Chernavin64d64632023-11-07 11:25:21 +00001244 def test_rewritten_traffic(self):
1245 """Rewritten traffic (from subif to ipfix if)"""
1246 self.pg_enable_capture(self.pg_interfaces)
1247 self.pkts = []
1248
1249 # prepare a sub-interface
1250 subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400)
1251 subif.admin_up()
1252 subif.config_ip4()
1253
1254 # enable ip4 datapath for an interface
1255 ipfix = VppCFLOW(
1256 test=self,
1257 intf="pg8",
1258 datapath="ip4",
1259 layer="l2 l3 l4",
1260 direction=self.direction,
1261 )
1262 ipfix.add_vpp_config()
1263
1264 # template packet should arrive immediately
1265 ipfix_decoder = IPFIXDecoder()
1266 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1267
1268 # forward some traffic through the ipfix interface
1269 route = VppIpRoute(
1270 self,
1271 "9.0.0.0",
1272 24,
1273 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
1274 )
1275 route.add_vpp_config()
1276
1277 # prepare an IPv4 packet (subif => ipfix interface)
1278 pkt = (
1279 Ether(src=subif.remote_mac, dst=self.pg7.local_mac)
1280 / IP(src=subif.remote_ip4, dst="9.0.0.1")
1281 / UDP(sport=1234, dport=4321)
1282 / Raw(b"\xa5" * 123)
1283 )
1284 self.pkts = [
1285 subif.add_dot1ad_layer(pkt, 300, 400),
1286 ]
1287
1288 # send the packet
1289 capture = self.send_packets(self.pg7, self.pg8)
1290
1291 # wait for a flow and verify it
1292 self.vapi.ipfix_flush()
1293 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1294 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1295 self.verify_cflow_data_detail(
1296 ipfix_decoder,
1297 capture,
1298 cflow,
1299 {
1300 IPFIX_SRC_IP4_ADDR_ID: "src_ip",
1301 IPFIX_DST_IP4_ADDR_ID: "dst_ip",
1302 IPFIX_SRC_TRANS_PORT_ID: "sport",
1303 IPFIX_DST_TRANS_PORT_ID: "dport",
1304 IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"),
1305 },
1306 )
1307
1308 self.collector.get_capture(2)
1309
1310 # cleanup
1311 route.remove_vpp_config()
1312 subif.remove_vpp_config()
1313 ipfix.remove_vpp_config()
1314
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001315
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001316@unittest.skipIf(
1317 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1318)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001319class DatapathRx(MethodHolder, DatapathTestsHolder):
1320 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1321
1322 intf1 = "pg1"
1323 intf2 = "pg3"
1324 intf3 = "pg5"
1325 direction = "rx"
1326
1327
Klement Sekerab23ffd72021-05-31 16:08:53 +02001328@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001329@unittest.skipIf(
1330 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1331)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001332class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001333 """Disable IPFIX"""
1334
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001335 @classmethod
1336 def setUpClass(cls):
1337 super(DisableIPFIX, cls).setUpClass()
1338
1339 @classmethod
1340 def tearDownClass(cls):
1341 super(DisableIPFIX, cls).tearDownClass()
1342
Ole Troan5c749732017-03-13 13:39:52 +01001343 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001344 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001345 self.logger.info("FFP_TEST_START_0001")
1346 self.pg_enable_capture(self.pg_interfaces)
1347 self.pkts = []
1348
Pavel Kotucek89111d02017-06-12 08:26:13 +02001349 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001350 ipfix.add_vpp_config()
1351
1352 ipfix_decoder = IPFIXDecoder()
1353 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001354 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001355
1356 self.create_stream()
1357 self.send_packets()
1358
1359 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001360 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001361 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001362 self.collector.get_capture(4)
1363
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001364 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001365 ipfix.disable_exporter()
1366 self.pg_enable_capture([self.collector])
1367
1368 self.send_packets()
1369
1370 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001371 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001372 self.sleep(1, "wait before verifying no packets sent")
1373 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001374
1375 ipfix.remove_vpp_config()
1376 self.logger.info("FFP_TEST_FINISH_0001")
1377
1378
Klement Sekerab23ffd72021-05-31 16:08:53 +02001379@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001380@unittest.skipIf(
1381 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1382)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001383class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001384 """Re-enable IPFIX"""
1385
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001386 @classmethod
1387 def setUpClass(cls):
1388 super(ReenableIPFIX, cls).setUpClass()
1389
1390 @classmethod
1391 def tearDownClass(cls):
1392 super(ReenableIPFIX, cls).tearDownClass()
1393
Pavel Kotucek89111d02017-06-12 08:26:13 +02001394 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001395 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001396 self.logger.info("FFP_TEST_START_0001")
1397 self.pg_enable_capture(self.pg_interfaces)
1398 self.pkts = []
1399
Pavel Kotucek89111d02017-06-12 08:26:13 +02001400 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001401 ipfix.add_vpp_config()
1402
1403 ipfix_decoder = IPFIXDecoder()
1404 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001405 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001406
Pavel Kotucek89111d02017-06-12 08:26:13 +02001407 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001408 self.send_packets()
1409
1410 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001411 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001412 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001413 self.collector.get_capture(4)
1414
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001415 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001416 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001417 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001418 self.pg_enable_capture([self.collector])
1419
1420 self.send_packets()
1421
1422 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001423 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001424 self.sleep(1, "wait before verifying no packets sent")
1425 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001426 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001427
1428 # enable IPFIX
1429 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001430
Pavel Kotucek89111d02017-06-12 08:26:13 +02001431 capture = self.collector.get_capture(4)
1432 nr_templates = 0
1433 nr_data = 0
1434 for p in capture:
1435 self.assertTrue(p.haslayer(IPFIX))
1436 if p.haslayer(Template):
1437 nr_templates += 1
1438 self.assertTrue(nr_templates, 3)
1439 for p in capture:
1440 self.assertTrue(p.haslayer(IPFIX))
1441 if p.haslayer(Data):
1442 nr_data += 1
1443 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001444
1445 ipfix.remove_vpp_config()
1446 self.logger.info("FFP_TEST_FINISH_0001")
1447
1448
Klement Sekerab23ffd72021-05-31 16:08:53 +02001449@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001450@unittest.skipIf(
1451 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1452)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001453class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001454 """Disable Flowprobe feature"""
1455
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001456 @classmethod
1457 def setUpClass(cls):
1458 super(DisableFP, cls).setUpClass()
1459
1460 @classmethod
1461 def tearDownClass(cls):
1462 super(DisableFP, cls).tearDownClass()
1463
Ole Troan5c749732017-03-13 13:39:52 +01001464 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001465 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001466 self.logger.info("FFP_TEST_START_0001")
1467 self.pg_enable_capture(self.pg_interfaces)
1468 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001469 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001470 ipfix.add_vpp_config()
1471
1472 ipfix_decoder = IPFIXDecoder()
1473 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001474 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001475
1476 self.create_stream()
1477 self.send_packets()
1478
1479 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001480 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001481 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001482 self.collector.get_capture(4)
1483
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001484 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001485 ipfix.disable_flowprobe_feature()
1486 self.pg_enable_capture([self.collector])
1487
1488 self.send_packets()
1489
1490 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001491 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001492 self.sleep(1, "wait before verifying no packets sent")
1493 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001494
Dave Wallace8800f732023-08-31 00:47:44 -04001495 # enable FPP feature so the remove_vpp_config() doesn't fail
1496 # due to missing feature on interface.
1497 ipfix.enable_flowprobe_feature()
1498
Ole Troan5c749732017-03-13 13:39:52 +01001499 ipfix.remove_vpp_config()
1500 self.logger.info("FFP_TEST_FINISH_0001")
1501
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001502 def test_no_leftover_flows_after_disabling(self):
1503 """disable flowprobe feature and expect no leftover flows"""
1504 self.pg_enable_capture(self.pg_interfaces)
1505 self.pkts = []
1506
1507 # enable ip4 datapath for an interface
1508 # set active and passive timers
1509 ipfix = VppCFLOW(
1510 test=self,
1511 active=3,
1512 passive=4,
1513 intf="pg3",
1514 layer="l3",
1515 datapath="ip4",
1516 direction="rx",
1517 mtu=100,
1518 )
1519 ipfix.add_vpp_config()
1520
1521 # template packet should arrive immediately
1522 ipfix.verify_templates(count=1)
1523
1524 # send some ip4 packets
1525 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1526 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1527
1528 # disable feature for the interface
1529 # currently stored ip4 flows should be removed
1530 ipfix.disable_flowprobe_feature()
1531
1532 # no leftover ip4 flows are expected
1533 self.pg_enable_capture([self.collector])
1534 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1535 self.collector.assert_nothing_captured()
1536
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001537 # re-enable feature for the interface
1538 ipfix.enable_flowprobe_feature()
1539
1540 # template packet should arrive immediately
1541 ipfix_decoder = IPFIXDecoder()
1542 self.vapi.ipfix_flush()
1543 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1544
1545 # send some ip4 packets
1546 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1547 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1548
1549 # verify meta info - packet/octet delta
1550 self.vapi.ipfix_flush()
1551 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1552 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1553
1554 self.collector.get_capture(2)
1555
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001556 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001557 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001558
Ole Troan5c749732017-03-13 13:39:52 +01001559
Klement Sekerab23ffd72021-05-31 16:08:53 +02001560@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001561@unittest.skipIf(
1562 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1563)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001564class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001565 """Re-enable Flowprobe feature"""
1566
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001567 @classmethod
1568 def setUpClass(cls):
1569 super(ReenableFP, cls).setUpClass()
1570
1571 @classmethod
1572 def tearDownClass(cls):
1573 super(ReenableFP, cls).tearDownClass()
1574
Ole Troan5c749732017-03-13 13:39:52 +01001575 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001576 """disable flowprobe feature after first packets and re-enable
1577 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001578 self.logger.info("FFP_TEST_START_0001")
1579 self.pg_enable_capture(self.pg_interfaces)
1580 self.pkts = []
1581
Pavel Kotucek89111d02017-06-12 08:26:13 +02001582 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001583 ipfix.add_vpp_config()
1584
1585 ipfix_decoder = IPFIXDecoder()
1586 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001587 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001588 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1589
1590 self.create_stream()
1591 self.send_packets()
1592
1593 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001594 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001595 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001596 self.collector.get_capture(4)
1597
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001598 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001599 ipfix.disable_flowprobe_feature()
1600 self.pg_enable_capture([self.collector])
1601
1602 self.send_packets()
1603
1604 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001605 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001606 self.sleep(5, "wait before verifying no packets sent")
1607 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001608
1609 # enable FPP feature
1610 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001611 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001612 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1613
1614 self.send_packets()
1615
1616 # make sure the next packets (templates and data) we expect actually
1617 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001618 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001619 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001620 self.collector.get_capture(4)
1621
1622 ipfix.remove_vpp_config()
1623 self.logger.info("FFP_TEST_FINISH_0001")
1624
1625
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001626if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001627 unittest.main(testRunner=VppTestRunner)