blob: 18a2e3a36c210b75f9ef696c5d4bd856409d0547 [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,
Dave Wallace8800f732023-08-31 00:47:44 -040019 tag_fixme_debian11,
20 tag_run_solo,
21 is_distro_ubuntu2204,
22 is_distro_debian11,
23 VppTestRunner,
24)
Ole Troan5c749732017-03-13 13:39:52 +010025from vpp_object import VppObject
Ole Troan5c749732017-03-13 13:39:52 +010026from util import ppp
27from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Ole Troaned929252017-06-13 21:15:40 +020028from vpp_ip_route import VppIpRoute, VppRoutePath
Ole Troanb0d83f12019-10-21 23:13:46 +020029from vpp_papi.macaddress import mac_ntop
30from socket import inet_ntop
Ole Troan3013e692019-12-09 15:51:44 +010031from vpp_papi import VppEnum
Alexander Chernavin64d64632023-11-07 11:25:21 +000032from vpp_sub_interface import VppDot1ADSubint
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000033from config import config
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()
Andrew Yourtchenko9987d472024-07-02 18:02:09 +0200186 if (is_distro_debian11 == True) and not hasattr(cls, "vpp"):
Dave Wallace670724c2022-09-20 21:52:18 -0400187 return
Ole Troan5c749732017-03-13 13:39:52 +0100188 try:
189 # Create pg interfaces
Ole Troaned929252017-06-13 21:15:40 +0200190 cls.create_pg_interfaces(range(9))
Ole Troan5c749732017-03-13 13:39:52 +0100191
192 # Packet sizes
193 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
194
195 # Create BD with MAC learning and unknown unicast flooding disabled
196 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200197 cls.vapi.bridge_domain_add_del_v2(
198 bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
199 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100200 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200201 rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1
202 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100203 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200204 rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1
205 )
Ole Troan5c749732017-03-13 13:39:52 +0100206
207 # Set up all interfaces
208 for i in cls.pg_interfaces:
209 i.admin_up()
210
211 cls.pg0.config_ip4()
212 cls.pg0.configure_ipv4_neighbors()
213 cls.collector = cls.pg0
214
215 cls.pg1.config_ip4()
216 cls.pg1.resolve_arp()
217 cls.pg2.config_ip4()
218 cls.pg2.resolve_arp()
219 cls.pg3.config_ip4()
220 cls.pg3.resolve_arp()
221 cls.pg4.config_ip4()
222 cls.pg4.resolve_arp()
Ole Troaned929252017-06-13 21:15:40 +0200223 cls.pg7.config_ip4()
224 cls.pg8.config_ip4()
225 cls.pg8.configure_ipv4_neighbors()
Ole Troan5c749732017-03-13 13:39:52 +0100226
227 cls.pg5.config_ip6()
228 cls.pg5.resolve_ndp()
229 cls.pg5.disable_ipv6_ra()
230 cls.pg6.config_ip6()
231 cls.pg6.resolve_ndp()
232 cls.pg6.disable_ipv6_ra()
233 except Exception:
234 super(MethodHolder, cls).tearDownClass()
235 raise
236
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800237 @classmethod
238 def tearDownClass(cls):
239 super(MethodHolder, cls).tearDownClass()
240
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200241 def create_stream(
242 self, src_if=None, dst_if=None, packets=None, size=None, ip_ver="v4"
243 ):
Ole Troan5c749732017-03-13 13:39:52 +0100244 """Create a packet stream to tickle the plugin
245
246 :param VppInterface src_if: Source interface for packet stream
247 :param VppInterface src_if: Dst interface for packet stream
248 """
249 if src_if is None:
250 src_if = self.pg1
251 if dst_if is None:
252 dst_if = self.pg2
253 self.pkts = []
254 if packets is None:
255 packets = random.randint(1, self.max_number_of_packets)
256 pkt_size = size
257 for p in range(0, packets):
258 if size is None:
259 pkt_size = random.choice(self.pg_if_packet_sizes)
260 info = self.create_packet_info(src_if, dst_if)
261 payload = self.info_to_payload(info)
262 p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200263 if ip_ver == "v4":
Ole Troan5c749732017-03-13 13:39:52 +0100264 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
265 else:
266 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
Ole Troaned929252017-06-13 21:15:40 +0200267 p /= UDP(sport=1234, dport=4321)
268 p /= Raw(payload)
Ole Troan5c749732017-03-13 13:39:52 +0100269 info.data = p.copy()
270 self.extend_packet(p, pkt_size)
271 self.pkts.append(p)
272
273 def verify_cflow_data(self, decoder, capture, cflow):
274 octets = 0
275 packets = 0
276 for p in capture:
277 octets += p[IP].len
278 packets += 1
279 if cflow.haslayer(Data):
280 data = decoder.decode_data_set(cflow.getlayer(Set))
281 for record in data:
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800282 self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
283 self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
Ole Troan5c749732017-03-13 13:39:52 +0100284
Pavel Kotucek89111d02017-06-12 08:26:13 +0200285 def send_packets(self, src_if=None, dst_if=None):
286 if src_if is None:
287 src_if = self.pg1
288 if dst_if is None:
289 dst_if = self.pg2
290 self.pg_enable_capture([dst_if])
291 src_if.add_stream(self.pkts)
292 self.pg_start()
293 return dst_if.get_capture(len(self.pkts))
294
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 def verify_cflow_data_detail(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000296 self,
297 decoder,
298 capture,
299 cflow,
300 data_set={1: "octets", 2: "packets"},
301 ip_ver="v4",
302 field_count=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200303 ):
Ole Troan5c749732017-03-13 13:39:52 +0100304 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800305 print(capture[0].show())
Ole Troan5c749732017-03-13 13:39:52 +0100306 if cflow.haslayer(Data):
307 data = decoder.decode_data_set(cflow.getlayer(Set))
308 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800309 print(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200310 if ip_ver == "v4":
Alexander Chernavin120095d2023-10-11 12:15:55 +0000311 ip_layer = capture[0][IP] if capture[0].haslayer(IP) else None
Ole Troan5c749732017-03-13 13:39:52 +0100312 else:
Alexander Chernavin120095d2023-10-11 12:15:55 +0000313 ip_layer = capture[0][IPv6] if capture[0].haslayer(IPv6) else None
Ole Troan5c749732017-03-13 13:39:52 +0100314 if data_set is not None:
315 for record in data:
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700316 # skip flow if ingress/egress interface is 0
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800317 if int(binascii.hexlify(record[10]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100318 continue
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800319 if int(binascii.hexlify(record[14]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100320 continue
321
322 for field in data_set:
Ole Troan5c749732017-03-13 13:39:52 +0100323 value = data_set[field]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200324 if value == "octets":
Ole Troan5c749732017-03-13 13:39:52 +0100325 value = ip_layer.len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 if ip_ver == "v6":
327 value += 40 # ??? is this correct
328 elif value == "packets":
Ole Troan5c749732017-03-13 13:39:52 +0100329 value = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200330 elif value == "src_ip":
331 if ip_ver == "v4":
332 ip = socket.inet_pton(socket.AF_INET, ip_layer.src)
Ole Troan5c749732017-03-13 13:39:52 +0100333 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200334 ip = socket.inet_pton(socket.AF_INET6, ip_layer.src)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800335 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200336 elif value == "dst_ip":
337 if ip_ver == "v4":
338 ip = socket.inet_pton(socket.AF_INET, ip_layer.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100339 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200340 ip = socket.inet_pton(socket.AF_INET6, ip_layer.dst)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800341 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 elif value == "sport":
Ole Troan5c749732017-03-13 13:39:52 +0100343 value = int(capture[0][UDP].sport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 elif value == "dport":
Ole Troan5c749732017-03-13 13:39:52 +0100345 value = int(capture[0][UDP].dport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 self.assertEqual(
347 int(binascii.hexlify(record[field]), 16), value
348 )
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000349 if field_count is not None:
350 for record in data:
351 self.assertEqual(len(record), field_count)
Ole Troan5c749732017-03-13 13:39:52 +0100352
353 def verify_cflow_data_notimer(self, decoder, capture, cflows):
354 idx = 0
355 for cflow in cflows:
356 if cflow.haslayer(Data):
357 data = decoder.decode_data_set(cflow.getlayer(Set))
358 else:
359 raise Exception("No CFLOW data")
360
361 for rec in data:
362 p = capture[idx]
363 idx += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200364 self.assertEqual(p[IP].len, int(binascii.hexlify(rec[1]), 16))
365 self.assertEqual(1, int(binascii.hexlify(rec[2]), 16))
Ole Troan5c749732017-03-13 13:39:52 +0100366 self.assertEqual(len(capture), idx)
367
Klement Sekerac4794572021-09-08 15:15:59 +0200368 def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200369 """wait for CFLOW packet and verify its correctness
Ole Troan5c749732017-03-13 13:39:52 +0100370
371 :param timeout: how long to wait
372
Ole Troan5c749732017-03-13 13:39:52 +0100373 """
374 self.logger.info("IPFIX: Waiting for CFLOW packet")
Ole Troan5c749732017-03-13 13:39:52 +0100375 # self.logger.debug(self.vapi.ppcli("show flow table"))
Klement Sekerac4794572021-09-08 15:15:59 +0200376 p = collector_intf.wait_for_packet(timeout=timeout)
377 self.assertEqual(p[Set].setID, set_id)
378 # self.logger.debug(self.vapi.ppcli("show flow table"))
379 self.logger.debug(ppp("IPFIX: Got packet:", p))
Ole Troan5c749732017-03-13 13:39:52 +0100380 return p
381
Ole Troan5c749732017-03-13 13:39:52 +0100382
Andrew Yourtchenko06f32812021-01-14 10:19:08 +0000383@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000384@tag_fixme_vpp_workers
Dave Wallace670724c2022-09-20 21:52:18 -0400385@tag_fixme_debian11
Dmitry Valter34fa0ce2024-03-11 10:38:46 +0000386@unittest.skipIf(
387 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
388)
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
adrianvillina77d4ca2023-12-22 16:52:56 +0100424 @unittest.skipUnless(
425 config.extended, "Test is unstable (assertion error, needs to be fixed"
426 )
Pavel Kotucek89111d02017-06-12 08:26:13 +0200427 def test_0002(self):
adrianvillina77d4ca2023-12-22 16:52:56 +0100428 """timer greater than template timeout [UNSTABLE, FIX ME]"""
Ole Troaned929252017-06-13 21:15:40 +0200429 self.logger.info("FFP_TEST_START_0002")
Ole Troan5c749732017-03-13 13:39:52 +0100430 self.pg_enable_capture(self.pg_interfaces)
431 self.pkts = []
432
Pavel Kotucek89111d02017-06-12 08:26:13 +0200433 ipfix = VppCFLOW(test=self, timeout=3, active=4)
Ole Troan5c749732017-03-13 13:39:52 +0100434 ipfix.add_vpp_config()
435
436 ipfix_decoder = IPFIXDecoder()
437 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200438 ipfix.verify_templates()
Ole Troan5c749732017-03-13 13:39:52 +0100439
Pavel Kotucek89111d02017-06-12 08:26:13 +0200440 self.create_stream(packets=2)
441 self.send_packets()
442 capture = self.pg2.get_capture(2)
Ole Troan5c749732017-03-13 13:39:52 +0100443
444 # next set of template packet should arrive after 20 seconds
445 # template packet should arrive within 20 s
Pavel Kotucek89111d02017-06-12 08:26:13 +0200446 templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
Ole Troan5c749732017-03-13 13:39:52 +0100447
448 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200449 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100450 self.verify_cflow_data(ipfix_decoder, capture, cflow)
451
452 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200453 self.logger.info("FFP_TEST_FINISH_0002")
454
455 def test_cflow_packet(self):
456 """verify cflow packet fields"""
457 self.logger.info("FFP_TEST_START_0000")
458 self.pg_enable_capture(self.pg_interfaces)
459 self.pkts = []
460
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200461 ipfix = VppCFLOW(
462 test=self, intf="pg8", datapath="ip4", layer="l2 l3 l4", active=2
463 )
Ole Troaned929252017-06-13 21:15:40 +0200464 ipfix.add_vpp_config()
465
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200466 route_9001 = VppIpRoute(
467 self,
468 "9.0.0.0",
469 24,
470 [VppRoutePath(self.pg8._remote_hosts[0].ip4, self.pg8.sw_if_index)],
471 )
Ole Troaned929252017-06-13 21:15:40 +0200472 route_9001.add_vpp_config()
473
474 ipfix_decoder = IPFIXDecoder()
475 templates = ipfix.verify_templates(ipfix_decoder, count=1)
476
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200477 self.pkts = [
478 (
479 Ether(dst=self.pg7.local_mac, src=self.pg7.remote_mac)
480 / IP(src=self.pg7.remote_ip4, dst="9.0.0.100")
481 / TCP(sport=1234, dport=4321, flags=80)
482 / Raw(b"\xa5" * 100)
483 )
484 ]
Ole Troaned929252017-06-13 21:15:40 +0200485
486 nowUTC = int(time.time())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200487 nowUNIX = nowUTC + 2208988800
Ole Troaned929252017-06-13 21:15:40 +0200488 self.send_packets(src_if=self.pg7, dst_if=self.pg8)
489
490 cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
491 self.collector.get_capture(2)
492
493 if cflow[0].haslayer(IPFIX):
494 self.assertEqual(cflow[IPFIX].version, 10)
495 self.assertEqual(cflow[IPFIX].observationDomainID, 1)
496 self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
497 self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
498 if cflow.haslayer(Data):
499 record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
500 # ingress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800501 self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200502 # egress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800503 self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000504 # direction
505 self.assertEqual(int(binascii.hexlify(record[61]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200506 # packets
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800507 self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200508 # src mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200509 self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
Ole Troaned929252017-06-13 21:15:40 +0200510 # dst mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200511 self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800512 flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200513 # flow start timestamp
514 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800515 flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200516 # flow end timestamp
517 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
518 # ethernet type
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800519 self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200520 # src ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200521 self.assertEqual(inet_ntop(socket.AF_INET, record[8]), self.pg7.remote_ip4)
Ole Troaned929252017-06-13 21:15:40 +0200522 # dst ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200523 self.assertEqual(inet_ntop(socket.AF_INET, record[12]), "9.0.0.100")
Ole Troaned929252017-06-13 21:15:40 +0200524 # protocol (TCP)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800525 self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
Ole Troaned929252017-06-13 21:15:40 +0200526 # src port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800527 self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
Ole Troaned929252017-06-13 21:15:40 +0200528 # dst port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800529 self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
Ole Troaned929252017-06-13 21:15:40 +0200530 # tcp flags
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800531 self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
Ole Troaned929252017-06-13 21:15:40 +0200532
533 ipfix.remove_vpp_config()
534 self.logger.info("FFP_TEST_FINISH_0000")
Ole Troan5c749732017-03-13 13:39:52 +0100535
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000536 def test_flow_entry_reuse(self):
537 """Verify flow entry reuse doesn't accumulate meta info"""
538 self.pg_enable_capture(self.pg_interfaces)
539 self.pkts = []
540
541 # enable ip4 datapath for an interface
542 # set active and passive timers
543 ipfix = VppCFLOW(
544 test=self,
545 active=2,
546 passive=3,
547 intf="pg3",
548 layer="l3 l4",
549 datapath="ip4",
550 direction="rx",
551 mtu=100,
552 )
553 ipfix.add_vpp_config()
554
555 # template packet should arrive immediately
556 ipfix_decoder = IPFIXDecoder()
557 templates = ipfix.verify_templates(ipfix_decoder, count=1)
558
559 # make a tcp packet
560 self.pkts = [
561 (
Steven Luonge4238aa2024-04-19 09:49:20 -0700562 Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000563 / IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
564 / TCP(sport=1234, dport=4321)
565 / Raw(b"\xa5" * 50)
566 )
567 ]
568
569 # send the tcp packet two times, each time with new set of flags
570 tcp_flags = (
571 TCP_F_SYN | TCP_F_ACK,
572 TCP_F_RST | TCP_F_PSH,
573 )
574 for f in tcp_flags:
575 self.pkts[0][TCP].flags = f
576 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
577
578 # verify meta info - packet/octet delta and tcp flags
579 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=6)
580 self.verify_cflow_data(ipfix_decoder, capture, cflow)
581 self.verify_cflow_data_detail(
582 ipfix_decoder,
583 capture,
584 cflow,
585 {
586 IPFIX_TCP_FLAGS_ID: f,
587 IPFIX_SRC_TRANS_PORT_ID: 1234,
588 IPFIX_DST_TRANS_PORT_ID: 4321,
589 },
590 )
591
592 self.collector.get_capture(3)
593
594 # cleanup
595 ipfix.remove_vpp_config()
596
Alexander Chernavin86c78562022-05-12 14:56:24 +0000597 def test_interface_dump(self):
598 """Dump interfaces with IPFIX flow record generation enabled"""
599 self.logger.info("FFP_TEST_START_0003")
600
601 # Enable feature for 3 interfaces
602 ipfix1 = VppCFLOW(test=self, intf="pg1", datapath="l2", direction="rx")
603 ipfix1.add_vpp_config()
604
605 ipfix2 = VppCFLOW(test=self, intf="pg2", datapath="ip4", direction="tx")
606 ipfix2.enable_flowprobe_feature()
607
608 ipfix3 = VppCFLOW(test=self, intf="pg3", datapath="ip6", direction="both")
609 ipfix3.enable_flowprobe_feature()
610
611 # When request "all", dump should contain all enabled interfaces
612 dump = self.vapi.flowprobe_interface_dump()
613 self.assertEqual(len(dump), 3)
614
615 # Verify 1st interface
616 self.assertEqual(dump[0].sw_if_index, self.pg1.sw_if_index)
617 self.assertEqual(
618 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2
619 )
620 self.assertEqual(
621 dump[0].direction,
622 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
623 )
624
625 # Verify 2nd interface
626 self.assertEqual(dump[1].sw_if_index, self.pg2.sw_if_index)
627 self.assertEqual(
628 dump[1].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
629 )
630 self.assertEqual(
631 dump[1].direction,
632 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
633 )
634
635 # Verify 3rd interface
636 self.assertEqual(dump[2].sw_if_index, self.pg3.sw_if_index)
637 self.assertEqual(
638 dump[2].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6
639 )
640 self.assertEqual(
641 dump[2].direction,
642 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
643 )
644
645 # When request 2nd interface, dump should contain only the specified interface
646 dump = self.vapi.flowprobe_interface_dump(sw_if_index=self.pg2.sw_if_index)
647 self.assertEqual(len(dump), 1)
648
649 # Verify 2nd interface
650 self.assertEqual(dump[0].sw_if_index, self.pg2.sw_if_index)
651 self.assertEqual(
652 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
653 )
654 self.assertEqual(
655 dump[0].direction,
656 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
657 )
658
659 # When request 99th interface, dump should be empty
660 dump = self.vapi.flowprobe_interface_dump(sw_if_index=99)
661 self.assertEqual(len(dump), 0)
662
663 ipfix1.remove_vpp_config()
664 ipfix2.remove_vpp_config()
665 ipfix3.remove_vpp_config()
666 self.logger.info("FFP_TEST_FINISH_0003")
667
668 def test_get_params(self):
669 """Get IPFIX flow record generation parameters"""
670 self.logger.info("FFP_TEST_START_0004")
671
672 # Enable feature for an interface with custom parameters
673 ipfix = VppCFLOW(test=self, active=20, passive=40, layer="l2 l3 l4")
674 ipfix.add_vpp_config()
675
676 # Get and verify parameters
677 params = self.vapi.flowprobe_get_params()
678 self.assertEqual(params.active_timer, 20)
679 self.assertEqual(params.passive_timer, 40)
680 record_flags = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
681 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
682 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
683 self.assertEqual(params.record_flags, record_flags)
684
685 ipfix.remove_vpp_config()
686 self.logger.info("FFP_TEST_FINISH_0004")
687
Ole Troan5c749732017-03-13 13:39:52 +0100688
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000689class DatapathTestsHolder(object):
Pavel Kotucek89111d02017-06-12 08:26:13 +0200690 """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
Ole Troan5c749732017-03-13 13:39:52 +0100691
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800692 @classmethod
693 def setUpClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000694 super(DatapathTestsHolder, cls).setUpClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800695
696 @classmethod
697 def tearDownClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000698 super(DatapathTestsHolder, cls).tearDownClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800699
Pavel Kotucek89111d02017-06-12 08:26:13 +0200700 def test_templatesL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200701 """verify template on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100702 self.logger.info("FFP_TEST_START_0000")
703 self.pg_enable_capture(self.pg_interfaces)
704
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000705 ipfix = VppCFLOW(
706 test=self, intf=self.intf1, layer="l2", direction=self.direction
707 )
Ole Troan5c749732017-03-13 13:39:52 +0100708 ipfix.add_vpp_config()
709
710 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400711 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200712 ipfix.verify_templates(timeout=3, count=1)
713 self.collector.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100714
715 ipfix.remove_vpp_config()
716 self.logger.info("FFP_TEST_FINISH_0000")
717
Pavel Kotucek89111d02017-06-12 08:26:13 +0200718 def test_L2onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200719 """L2 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100720 self.logger.info("FFP_TEST_START_0001")
721 self.pg_enable_capture(self.pg_interfaces)
722 self.pkts = []
723
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000724 ipfix = VppCFLOW(
725 test=self, intf=self.intf1, layer="l2", direction=self.direction
726 )
Ole Troan5c749732017-03-13 13:39:52 +0100727 ipfix.add_vpp_config()
728
729 ipfix_decoder = IPFIXDecoder()
730 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200731 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100732
733 self.create_stream(packets=1)
734 capture = self.send_packets()
735
736 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400737 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200738 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200739 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000740 ipfix_decoder,
741 capture,
742 cflow,
743 {2: "packets", 256: 8, 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200744 )
Ole Troan5c749732017-03-13 13:39:52 +0100745 self.collector.get_capture(2)
746
747 ipfix.remove_vpp_config()
748 self.logger.info("FFP_TEST_FINISH_0001")
749
Pavel Kotucek89111d02017-06-12 08:26:13 +0200750 def test_L3onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200751 """L3 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100752 self.logger.info("FFP_TEST_START_0002")
753 self.pg_enable_capture(self.pg_interfaces)
754 self.pkts = []
755
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000756 ipfix = VppCFLOW(
757 test=self, intf=self.intf1, layer="l3", direction=self.direction
758 )
Ole Troan5c749732017-03-13 13:39:52 +0100759 ipfix.add_vpp_config()
760
761 ipfix_decoder = IPFIXDecoder()
762 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200763 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100764
765 self.create_stream(packets=1)
766 capture = self.send_packets()
767
768 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400769 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200770 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200771 self.verify_cflow_data_detail(
772 ipfix_decoder,
773 capture,
774 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000775 {
776 2: "packets",
777 4: 17,
778 8: "src_ip",
779 12: "dst_ip",
780 61: (self.direction == "tx"),
781 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 )
Ole Troan5c749732017-03-13 13:39:52 +0100783
Ole Troan5c749732017-03-13 13:39:52 +0100784 self.collector.get_capture(3)
785
786 ipfix.remove_vpp_config()
787 self.logger.info("FFP_TEST_FINISH_0002")
788
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000789 def test_L234onL2(self):
790 """L2/3/4 data on L2 datapath"""
Alexander Chernavin120095d2023-10-11 12:15:55 +0000791 self.pg_enable_capture(self.pg_interfaces)
792 self.pkts = []
793
794 ipfix = VppCFLOW(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000795 test=self, intf=self.intf1, layer="l2 l3 l4", direction=self.direction
Alexander Chernavin120095d2023-10-11 12:15:55 +0000796 )
797 ipfix.add_vpp_config()
798
799 ipfix_decoder = IPFIXDecoder()
800 # template packet should arrive immediately
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000801 tmpl_l2_field_count = TMPL_COMMON_FIELD_COUNT + TMPL_L2_FIELD_COUNT
802 tmpl_ip_field_count = (
803 TMPL_COMMON_FIELD_COUNT
804 + TMPL_L2_FIELD_COUNT
805 + TMPL_L3_FIELD_COUNT
806 + TMPL_L4_FIELD_COUNT
807 )
808 templates = ipfix.verify_templates(
809 ipfix_decoder,
810 count=3,
811 field_count_in=(tmpl_l2_field_count, tmpl_ip_field_count),
812 )
Alexander Chernavin120095d2023-10-11 12:15:55 +0000813
814 # verify IPv4 and IPv6 flows
815 for ip_ver in ("v4", "v6"):
816 self.create_stream(packets=1, ip_ver=ip_ver)
817 capture = self.send_packets()
818
819 # make sure the one packet we expect actually showed up
820 self.vapi.ipfix_flush()
821 cflow = self.wait_for_cflow_packet(
822 self.collector, templates[1 if ip_ver == "v4" else 2]
823 )
824 src_ip_id = 8 if ip_ver == "v4" else 27
825 dst_ip_id = 12 if ip_ver == "v4" else 28
826 self.verify_cflow_data_detail(
827 ipfix_decoder,
828 capture,
829 cflow,
830 {
831 2: "packets",
832 256: 8 if ip_ver == "v4" else 56710,
833 4: 17,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000834 7: "sport",
835 11: "dport",
Alexander Chernavin120095d2023-10-11 12:15:55 +0000836 src_ip_id: "src_ip",
837 dst_ip_id: "dst_ip",
838 61: (self.direction == "tx"),
839 },
840 ip_ver=ip_ver,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000841 field_count=tmpl_ip_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000842 )
843
844 # verify non-IP flow
845 self.pkts = [
846 (
847 Ether(dst=self.pg2.local_mac, src=self.pg1.remote_mac)
848 / SlowProtocol()
849 / LACP()
850 )
851 ]
852 capture = self.send_packets()
853
854 # make sure the one packet we expect actually showed up
855 self.vapi.ipfix_flush()
856 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
857 self.verify_cflow_data_detail(
858 ipfix_decoder,
859 capture,
860 cflow,
861 {2: "packets", 256: 2440, 61: (self.direction == "tx")},
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000862 field_count=tmpl_l2_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000863 )
864
865 self.collector.get_capture(6)
866
867 ipfix.remove_vpp_config()
868
Pavel Kotucek89111d02017-06-12 08:26:13 +0200869 def test_L4onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200870 """L4 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100871 self.logger.info("FFP_TEST_START_0003")
872 self.pg_enable_capture(self.pg_interfaces)
873 self.pkts = []
874
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000875 ipfix = VppCFLOW(
876 test=self, intf=self.intf1, layer="l4", direction=self.direction
877 )
Ole Troan5c749732017-03-13 13:39:52 +0100878 ipfix.add_vpp_config()
879
880 ipfix_decoder = IPFIXDecoder()
881 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200882 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100883
884 self.create_stream(packets=1)
885 capture = self.send_packets()
886
887 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400888 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200889 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200890 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000891 ipfix_decoder,
892 capture,
893 cflow,
894 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200895 )
Ole Troan5c749732017-03-13 13:39:52 +0100896
Ole Troan5c749732017-03-13 13:39:52 +0100897 self.collector.get_capture(3)
898
899 ipfix.remove_vpp_config()
900 self.logger.info("FFP_TEST_FINISH_0003")
901
Pavel Kotucek89111d02017-06-12 08:26:13 +0200902 def test_templatesIp4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200903 """verify templates on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100904 self.logger.info("FFP_TEST_START_0000")
905
906 self.pg_enable_capture(self.pg_interfaces)
907
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000908 ipfix = VppCFLOW(
909 test=self, intf=self.intf1, datapath="ip4", direction=self.direction
910 )
Ole Troan5c749732017-03-13 13:39:52 +0100911 ipfix.add_vpp_config()
912
913 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400914 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +0100915 ipfix.verify_templates(timeout=3, count=1)
916 self.collector.get_capture(1)
917
918 ipfix.remove_vpp_config()
919
920 self.logger.info("FFP_TEST_FINISH_0000")
921
Pavel Kotucek89111d02017-06-12 08:26:13 +0200922 def test_L2onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200923 """L2 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100924 self.logger.info("FFP_TEST_START_0001")
925 self.pg_enable_capture(self.pg_interfaces)
926 self.pkts = []
927
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000928 ipfix = VppCFLOW(
929 test=self,
930 intf=self.intf2,
931 layer="l2",
932 datapath="ip4",
933 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200934 )
Ole Troan5c749732017-03-13 13:39:52 +0100935 ipfix.add_vpp_config()
936
937 ipfix_decoder = IPFIXDecoder()
938 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200939 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100940
941 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
942 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
943
944 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400945 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200946 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200947 self.verify_cflow_data_detail(
948 ipfix_decoder,
949 capture,
950 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000951 {2: "packets", 256: 8, 61: (self.direction == "tx")},
952 )
953
954 # expected two templates and one cflow packet
955 self.collector.get_capture(2)
956
957 ipfix.remove_vpp_config()
958 self.logger.info("FFP_TEST_FINISH_0001")
959
960 def test_L3onIP4(self):
961 """L3 data on IP4 datapath"""
962 self.logger.info("FFP_TEST_START_0002")
963 self.pg_enable_capture(self.pg_interfaces)
964 self.pkts = []
965
966 ipfix = VppCFLOW(
967 test=self,
968 intf=self.intf2,
969 layer="l3",
970 datapath="ip4",
971 direction=self.direction,
972 )
973 ipfix.add_vpp_config()
974
975 ipfix_decoder = IPFIXDecoder()
976 # template packet should arrive immediately
977 templates = ipfix.verify_templates(ipfix_decoder, count=1)
978
979 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
980 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
981
982 # make sure the one packet we expect actually showed up
983 self.vapi.ipfix_flush()
984 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
985 self.verify_cflow_data_detail(
986 ipfix_decoder,
987 capture,
988 cflow,
989 {
990 1: "octets",
991 2: "packets",
992 8: "src_ip",
993 12: "dst_ip",
994 61: (self.direction == "tx"),
995 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200996 )
Ole Troan5c749732017-03-13 13:39:52 +0100997
998 # expected two templates and one cflow packet
999 self.collector.get_capture(2)
1000
1001 ipfix.remove_vpp_config()
1002 self.logger.info("FFP_TEST_FINISH_0002")
1003
Pavel Kotucek89111d02017-06-12 08:26:13 +02001004 def test_L4onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001005 """L4 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001006 self.logger.info("FFP_TEST_START_0003")
1007 self.pg_enable_capture(self.pg_interfaces)
1008 self.pkts = []
1009
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001010 ipfix = VppCFLOW(
1011 test=self,
1012 intf=self.intf2,
1013 layer="l4",
1014 datapath="ip4",
1015 direction=self.direction,
1016 )
Ole Troan5c749732017-03-13 13:39:52 +01001017 ipfix.add_vpp_config()
1018
1019 ipfix_decoder = IPFIXDecoder()
1020 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001021 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001022
1023 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
1024 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1025
1026 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001027 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001028 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001029 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001030 ipfix_decoder,
1031 capture,
1032 cflow,
1033 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001034 )
Ole Troan5c749732017-03-13 13:39:52 +01001035
1036 # expected two templates and one cflow packet
1037 self.collector.get_capture(2)
1038
1039 ipfix.remove_vpp_config()
1040 self.logger.info("FFP_TEST_FINISH_0003")
1041
Pavel Kotucek89111d02017-06-12 08:26:13 +02001042 def test_templatesIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001043 """verify templates on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001044 self.logger.info("FFP_TEST_START_0000")
1045 self.pg_enable_capture(self.pg_interfaces)
1046
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001047 ipfix = VppCFLOW(
1048 test=self, intf=self.intf1, datapath="ip6", direction=self.direction
1049 )
Ole Troan5c749732017-03-13 13:39:52 +01001050 ipfix.add_vpp_config()
1051
1052 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001053 ipfix.verify_templates(count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001054 self.collector.get_capture(1)
1055
1056 ipfix.remove_vpp_config()
1057
1058 self.logger.info("FFP_TEST_FINISH_0000")
1059
Pavel Kotucek89111d02017-06-12 08:26:13 +02001060 def test_L2onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001061 """L2 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001062 self.logger.info("FFP_TEST_START_0001")
1063 self.pg_enable_capture(self.pg_interfaces)
1064 self.pkts = []
1065
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001066 ipfix = VppCFLOW(
1067 test=self,
1068 intf=self.intf3,
1069 layer="l2",
1070 datapath="ip6",
1071 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001072 )
Ole Troan5c749732017-03-13 13:39:52 +01001073 ipfix.add_vpp_config()
1074
1075 ipfix_decoder = IPFIXDecoder()
1076 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001077 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001078
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001079 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001080 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1081
1082 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001083 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001084 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001085 self.verify_cflow_data_detail(
1086 ipfix_decoder,
1087 capture,
1088 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001089 {2: "packets", 256: 56710, 61: (self.direction == "tx")},
1090 ip_ver="v6",
1091 )
1092
1093 # expected two templates and one cflow packet
1094 self.collector.get_capture(2)
1095
1096 ipfix.remove_vpp_config()
1097 self.logger.info("FFP_TEST_FINISH_0001")
1098
1099 def test_L3onIP6(self):
1100 """L3 data on IP6 datapath"""
1101 self.logger.info("FFP_TEST_START_0002")
1102 self.pg_enable_capture(self.pg_interfaces)
1103 self.pkts = []
1104
1105 ipfix = VppCFLOW(
1106 test=self,
1107 intf=self.intf3,
1108 layer="l3",
1109 datapath="ip6",
1110 direction=self.direction,
1111 )
1112 ipfix.add_vpp_config()
1113
1114 ipfix_decoder = IPFIXDecoder()
1115 # template packet should arrive immediately
1116 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1117
1118 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
1119 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1120
1121 # make sure the one packet we expect actually showed up
1122 self.vapi.ipfix_flush()
1123 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1124 self.verify_cflow_data_detail(
1125 ipfix_decoder,
1126 capture,
1127 cflow,
1128 {2: "packets", 27: "src_ip", 28: "dst_ip", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001129 ip_ver="v6",
1130 )
Ole Troan5c749732017-03-13 13:39:52 +01001131
1132 # expected two templates and one cflow packet
1133 self.collector.get_capture(2)
1134
1135 ipfix.remove_vpp_config()
1136 self.logger.info("FFP_TEST_FINISH_0002")
1137
Pavel Kotucek89111d02017-06-12 08:26:13 +02001138 def test_L4onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001139 """L4 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001140 self.logger.info("FFP_TEST_START_0003")
1141 self.pg_enable_capture(self.pg_interfaces)
1142 self.pkts = []
1143
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001144 ipfix = VppCFLOW(
1145 test=self,
1146 intf=self.intf3,
1147 layer="l4",
1148 datapath="ip6",
1149 direction=self.direction,
1150 )
Ole Troan5c749732017-03-13 13:39:52 +01001151 ipfix.add_vpp_config()
1152
1153 ipfix_decoder = IPFIXDecoder()
1154 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001155 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001156
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001157 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001158 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1159
1160 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001161 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001162 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001163 self.verify_cflow_data_detail(
1164 ipfix_decoder,
1165 capture,
1166 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001167 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001168 ip_ver="v6",
1169 )
Ole Troan5c749732017-03-13 13:39:52 +01001170
1171 # expected two templates and one cflow packet
1172 self.collector.get_capture(2)
1173
1174 ipfix.remove_vpp_config()
1175 self.logger.info("FFP_TEST_FINISH_0003")
1176
Ole Troan5c749732017-03-13 13:39:52 +01001177 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001178 """no timers, one CFLOW packet, 9 Flows inside"""
Ole Troan5c749732017-03-13 13:39:52 +01001179 self.logger.info("FFP_TEST_START_0001")
1180 self.pg_enable_capture(self.pg_interfaces)
1181 self.pkts = []
1182
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001183 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction)
Ole Troan5c749732017-03-13 13:39:52 +01001184 ipfix.add_vpp_config()
1185
1186 ipfix_decoder = IPFIXDecoder()
1187 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001188 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001189
1190 self.create_stream(packets=9)
1191 capture = self.send_packets()
1192
1193 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001194 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001195 cflow = self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001196 self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
Ole Troan5c749732017-03-13 13:39:52 +01001197 self.collector.get_capture(4)
1198
1199 ipfix.remove_vpp_config()
1200 self.logger.info("FFP_TEST_FINISH_0001")
1201
1202 def test_0002(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001203 """no timers, two CFLOW packets (mtu=260), 3 Flows in each"""
Ole Troan5c749732017-03-13 13:39:52 +01001204 self.logger.info("FFP_TEST_START_0002")
1205 self.pg_enable_capture(self.pg_interfaces)
1206 self.pkts = []
1207
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001208 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction, mtu=260)
Ole Troan5c749732017-03-13 13:39:52 +01001209 ipfix.add_vpp_config()
1210
1211 ipfix_decoder = IPFIXDecoder()
1212 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001213 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001214 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001215
1216 self.create_stream(packets=6)
1217 capture = self.send_packets()
1218
1219 # make sure the one packet we expect actually showed up
1220 cflows = []
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001221 self.vapi.ipfix_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001222 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
1223 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
Ole Troan5c749732017-03-13 13:39:52 +01001224 self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
1225 self.collector.get_capture(5)
1226
1227 ipfix.remove_vpp_config()
1228 self.logger.info("FFP_TEST_FINISH_0002")
1229
1230
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001231@unittest.skipIf(
1232 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1233)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001234class DatapathTx(MethodHolder, DatapathTestsHolder):
1235 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1236
1237 intf1 = "pg2"
1238 intf2 = "pg4"
1239 intf3 = "pg6"
1240 direction = "tx"
1241
Alexander Chernavin64d64632023-11-07 11:25:21 +00001242 def test_rewritten_traffic(self):
1243 """Rewritten traffic (from subif to ipfix if)"""
1244 self.pg_enable_capture(self.pg_interfaces)
1245 self.pkts = []
1246
1247 # prepare a sub-interface
1248 subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400)
1249 subif.admin_up()
1250 subif.config_ip4()
1251
1252 # enable ip4 datapath for an interface
1253 ipfix = VppCFLOW(
1254 test=self,
1255 intf="pg8",
1256 datapath="ip4",
1257 layer="l2 l3 l4",
1258 direction=self.direction,
1259 )
1260 ipfix.add_vpp_config()
1261
1262 # template packet should arrive immediately
1263 ipfix_decoder = IPFIXDecoder()
1264 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1265
1266 # forward some traffic through the ipfix interface
1267 route = VppIpRoute(
1268 self,
1269 "9.0.0.0",
1270 24,
1271 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
1272 )
1273 route.add_vpp_config()
1274
1275 # prepare an IPv4 packet (subif => ipfix interface)
1276 pkt = (
1277 Ether(src=subif.remote_mac, dst=self.pg7.local_mac)
1278 / IP(src=subif.remote_ip4, dst="9.0.0.1")
1279 / UDP(sport=1234, dport=4321)
1280 / Raw(b"\xa5" * 123)
1281 )
1282 self.pkts = [
1283 subif.add_dot1ad_layer(pkt, 300, 400),
1284 ]
1285
1286 # send the packet
1287 capture = self.send_packets(self.pg7, self.pg8)
1288
1289 # wait for a flow and verify it
1290 self.vapi.ipfix_flush()
1291 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1292 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1293 self.verify_cflow_data_detail(
1294 ipfix_decoder,
1295 capture,
1296 cflow,
1297 {
1298 IPFIX_SRC_IP4_ADDR_ID: "src_ip",
1299 IPFIX_DST_IP4_ADDR_ID: "dst_ip",
1300 IPFIX_SRC_TRANS_PORT_ID: "sport",
1301 IPFIX_DST_TRANS_PORT_ID: "dport",
1302 IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"),
1303 },
1304 )
1305
1306 self.collector.get_capture(2)
1307
1308 # cleanup
1309 route.remove_vpp_config()
1310 subif.remove_vpp_config()
1311 ipfix.remove_vpp_config()
1312
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001313
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001314@unittest.skipIf(
1315 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1316)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001317class DatapathRx(MethodHolder, DatapathTestsHolder):
1318 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1319
1320 intf1 = "pg1"
1321 intf2 = "pg3"
1322 intf3 = "pg5"
1323 direction = "rx"
1324
1325
Klement Sekerab23ffd72021-05-31 16:08:53 +02001326@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001327@unittest.skipIf(
1328 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1329)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001330class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001331 """Disable IPFIX"""
1332
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001333 @classmethod
1334 def setUpClass(cls):
1335 super(DisableIPFIX, cls).setUpClass()
1336
1337 @classmethod
1338 def tearDownClass(cls):
1339 super(DisableIPFIX, cls).tearDownClass()
1340
Ole Troan5c749732017-03-13 13:39:52 +01001341 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001343 self.logger.info("FFP_TEST_START_0001")
1344 self.pg_enable_capture(self.pg_interfaces)
1345 self.pkts = []
1346
Pavel Kotucek89111d02017-06-12 08:26:13 +02001347 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001348 ipfix.add_vpp_config()
1349
1350 ipfix_decoder = IPFIXDecoder()
1351 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001352 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001353
1354 self.create_stream()
1355 self.send_packets()
1356
1357 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001358 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001359 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001360 self.collector.get_capture(4)
1361
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001362 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001363 ipfix.disable_exporter()
1364 self.pg_enable_capture([self.collector])
1365
1366 self.send_packets()
1367
1368 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001369 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001370 self.sleep(1, "wait before verifying no packets sent")
1371 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001372
1373 ipfix.remove_vpp_config()
1374 self.logger.info("FFP_TEST_FINISH_0001")
1375
1376
Klement Sekerab23ffd72021-05-31 16:08:53 +02001377@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001378@unittest.skipIf(
1379 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1380)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001381class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001382 """Re-enable IPFIX"""
1383
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001384 @classmethod
1385 def setUpClass(cls):
1386 super(ReenableIPFIX, cls).setUpClass()
1387
1388 @classmethod
1389 def tearDownClass(cls):
1390 super(ReenableIPFIX, cls).tearDownClass()
1391
Pavel Kotucek89111d02017-06-12 08:26:13 +02001392 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001393 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001394 self.logger.info("FFP_TEST_START_0001")
1395 self.pg_enable_capture(self.pg_interfaces)
1396 self.pkts = []
1397
Pavel Kotucek89111d02017-06-12 08:26:13 +02001398 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001399 ipfix.add_vpp_config()
1400
1401 ipfix_decoder = IPFIXDecoder()
1402 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001403 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001404
Pavel Kotucek89111d02017-06-12 08:26:13 +02001405 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001406 self.send_packets()
1407
1408 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001409 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001410 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001411 self.collector.get_capture(4)
1412
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001413 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001414 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001415 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001416 self.pg_enable_capture([self.collector])
1417
1418 self.send_packets()
1419
1420 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001421 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001422 self.sleep(1, "wait before verifying no packets sent")
1423 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001424 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001425
1426 # enable IPFIX
1427 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001428
Pavel Kotucek89111d02017-06-12 08:26:13 +02001429 capture = self.collector.get_capture(4)
1430 nr_templates = 0
1431 nr_data = 0
1432 for p in capture:
1433 self.assertTrue(p.haslayer(IPFIX))
1434 if p.haslayer(Template):
1435 nr_templates += 1
1436 self.assertTrue(nr_templates, 3)
1437 for p in capture:
1438 self.assertTrue(p.haslayer(IPFIX))
1439 if p.haslayer(Data):
1440 nr_data += 1
1441 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001442
1443 ipfix.remove_vpp_config()
1444 self.logger.info("FFP_TEST_FINISH_0001")
1445
1446
Klement Sekerab23ffd72021-05-31 16:08:53 +02001447@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001448@unittest.skipIf(
1449 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1450)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001451class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001452 """Disable Flowprobe feature"""
1453
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001454 @classmethod
1455 def setUpClass(cls):
1456 super(DisableFP, cls).setUpClass()
1457
1458 @classmethod
1459 def tearDownClass(cls):
1460 super(DisableFP, cls).tearDownClass()
1461
Ole Troan5c749732017-03-13 13:39:52 +01001462 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001463 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001464 self.logger.info("FFP_TEST_START_0001")
1465 self.pg_enable_capture(self.pg_interfaces)
1466 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001467 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001468 ipfix.add_vpp_config()
1469
1470 ipfix_decoder = IPFIXDecoder()
1471 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001472 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001473
1474 self.create_stream()
1475 self.send_packets()
1476
1477 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001478 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001479 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001480 self.collector.get_capture(4)
1481
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001482 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001483 ipfix.disable_flowprobe_feature()
1484 self.pg_enable_capture([self.collector])
1485
1486 self.send_packets()
1487
1488 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001489 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001490 self.sleep(1, "wait before verifying no packets sent")
1491 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001492
Dave Wallace8800f732023-08-31 00:47:44 -04001493 # enable FPP feature so the remove_vpp_config() doesn't fail
1494 # due to missing feature on interface.
1495 ipfix.enable_flowprobe_feature()
1496
Ole Troan5c749732017-03-13 13:39:52 +01001497 ipfix.remove_vpp_config()
1498 self.logger.info("FFP_TEST_FINISH_0001")
1499
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001500 def test_no_leftover_flows_after_disabling(self):
1501 """disable flowprobe feature and expect no leftover flows"""
1502 self.pg_enable_capture(self.pg_interfaces)
1503 self.pkts = []
1504
1505 # enable ip4 datapath for an interface
1506 # set active and passive timers
1507 ipfix = VppCFLOW(
1508 test=self,
1509 active=3,
1510 passive=4,
1511 intf="pg3",
1512 layer="l3",
1513 datapath="ip4",
1514 direction="rx",
1515 mtu=100,
1516 )
1517 ipfix.add_vpp_config()
1518
1519 # template packet should arrive immediately
1520 ipfix.verify_templates(count=1)
1521
1522 # send some ip4 packets
1523 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1524 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1525
1526 # disable feature for the interface
1527 # currently stored ip4 flows should be removed
1528 ipfix.disable_flowprobe_feature()
1529
1530 # no leftover ip4 flows are expected
1531 self.pg_enable_capture([self.collector])
1532 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1533 self.collector.assert_nothing_captured()
1534
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001535 # re-enable feature for the interface
1536 ipfix.enable_flowprobe_feature()
1537
1538 # template packet should arrive immediately
1539 ipfix_decoder = IPFIXDecoder()
1540 self.vapi.ipfix_flush()
1541 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1542
1543 # send some ip4 packets
1544 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1545 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1546
1547 # verify meta info - packet/octet delta
1548 self.vapi.ipfix_flush()
1549 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1550 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1551
1552 self.collector.get_capture(2)
1553
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001554 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001555 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001556
Ole Troan5c749732017-03-13 13:39:52 +01001557
Klement Sekerab23ffd72021-05-31 16:08:53 +02001558@unittest.skipUnless(config.extended, "part of extended tests")
Dmitry Valter34fa0ce2024-03-11 10:38:46 +00001559@unittest.skipIf(
1560 "flowprobe" in config.excluded_plugins, "Exclude Flowprobe plugin tests"
1561)
Pavel Kotucek89111d02017-06-12 08:26:13 +02001562class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001563 """Re-enable Flowprobe feature"""
1564
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001565 @classmethod
1566 def setUpClass(cls):
1567 super(ReenableFP, cls).setUpClass()
1568
1569 @classmethod
1570 def tearDownClass(cls):
1571 super(ReenableFP, cls).tearDownClass()
1572
Ole Troan5c749732017-03-13 13:39:52 +01001573 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001574 """disable flowprobe feature after first packets and re-enable
1575 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001576 self.logger.info("FFP_TEST_START_0001")
1577 self.pg_enable_capture(self.pg_interfaces)
1578 self.pkts = []
1579
Pavel Kotucek89111d02017-06-12 08:26:13 +02001580 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001581 ipfix.add_vpp_config()
1582
1583 ipfix_decoder = IPFIXDecoder()
1584 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001585 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001586 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1587
1588 self.create_stream()
1589 self.send_packets()
1590
1591 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001592 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001593 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001594 self.collector.get_capture(4)
1595
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001596 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001597 ipfix.disable_flowprobe_feature()
1598 self.pg_enable_capture([self.collector])
1599
1600 self.send_packets()
1601
1602 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001603 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001604 self.sleep(5, "wait before verifying no packets sent")
1605 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001606
1607 # enable FPP feature
1608 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001609 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001610 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1611
1612 self.send_packets()
1613
1614 # make sure the next packets (templates and data) we expect actually
1615 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001616 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001617 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001618 self.collector.get_capture(4)
1619
1620 ipfix.remove_vpp_config()
1621 self.logger.info("FFP_TEST_FINISH_0001")
1622
1623
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001624if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001625 unittest.main(testRunner=VppTestRunner)