blob: 609099980fcf8836b86b569f853a0e24540d9cc7 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Paul Vinciguerra661f91f2018-11-28 19:06:41 -08002from __future__ import print_function
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -08003import binascii
Ole Troan5c749732017-03-13 13:39:52 +01004import random
5import socket
6import unittest
7import time
8
9from scapy.packet import Raw
10from scapy.layers.l2 import Ether
Ole Troaned929252017-06-13 21:15:40 +020011from scapy.layers.inet import IP, TCP, UDP
Ole Troan5c749732017-03-13 13:39:52 +010012from scapy.layers.inet6 import IPv6
Alexander Chernavin120095d2023-10-11 12:15:55 +000013from scapy.contrib.lacp import SlowProtocol, LACP
Ole Troan5c749732017-03-13 13:39:52 +010014
Klement Sekerab23ffd72021-05-31 16:08:53 +020015from config import config
Dave Wallace8800f732023-08-31 00:47:44 -040016from framework import VppTestCase
17from asfframework import (
18 tag_fixme_vpp_workers,
19 tag_fixme_ubuntu2204,
20 tag_fixme_debian11,
21 tag_run_solo,
22 is_distro_ubuntu2204,
23 is_distro_debian11,
24 VppTestRunner,
25)
Ole Troan5c749732017-03-13 13:39:52 +010026from vpp_object import VppObject
Ole Troan5c749732017-03-13 13:39:52 +010027from util import ppp
28from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
Ole Troaned929252017-06-13 21:15:40 +020029from vpp_ip_route import VppIpRoute, VppRoutePath
Ole Troanb0d83f12019-10-21 23:13:46 +020030from vpp_papi.macaddress import mac_ntop
31from socket import inet_ntop
Ole Troan3013e692019-12-09 15:51:44 +010032from vpp_papi import VppEnum
Alexander Chernavin64d64632023-11-07 11:25:21 +000033from vpp_sub_interface import VppDot1ADSubint
Ole Troan5c749732017-03-13 13:39:52 +010034
35
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000036TMPL_COMMON_FIELD_COUNT = 6
37TMPL_L2_FIELD_COUNT = 3
38TMPL_L3_FIELD_COUNT = 4
39TMPL_L4_FIELD_COUNT = 3
40
Alexander Chernavin21922ce2023-10-26 11:18:19 +000041IPFIX_TCP_FLAGS_ID = 6
42IPFIX_SRC_TRANS_PORT_ID = 7
43IPFIX_DST_TRANS_PORT_ID = 11
Alexander Chernavin64d64632023-11-07 11:25:21 +000044IPFIX_SRC_IP4_ADDR_ID = 8
45IPFIX_DST_IP4_ADDR_ID = 12
46IPFIX_FLOW_DIRECTION_ID = 61
Alexander Chernavin21922ce2023-10-26 11:18:19 +000047
48TCP_F_FIN = 0x01
49TCP_F_SYN = 0x02
50TCP_F_RST = 0x04
51TCP_F_PSH = 0x08
52TCP_F_ACK = 0x10
53TCP_F_URG = 0x20
54TCP_F_ECE = 0x40
55TCP_F_CWR = 0x80
56
Alexander Chernavin6b027cf2023-10-17 08:54:33 +000057
Ole Troan5c749732017-03-13 13:39:52 +010058class VppCFLOW(VppObject):
59 """CFLOW object for IPFIX exporter and Flowprobe feature"""
60
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020061 def __init__(
62 self,
63 test,
64 intf="pg2",
65 active=0,
66 passive=0,
67 timeout=100,
68 mtu=1024,
69 datapath="l2",
70 layer="l2 l3 l4",
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000071 direction="tx",
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020072 ):
Ole Troan5c749732017-03-13 13:39:52 +010073 self._test = test
74 self._intf = intf
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000075 self._intf_obj = getattr(self._test, intf)
Ole Troan5c749732017-03-13 13:39:52 +010076 self._active = active
77 if passive == 0 or passive < active:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078 self._passive = active + 1
Ole Troan5c749732017-03-13 13:39:52 +010079 else:
80 self._passive = passive
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020081 self._datapath = datapath # l2 ip4 ip6
82 self._collect = layer # l2 l3 l4
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +000083 self._direction = direction # rx tx both
Ole Troan5c749732017-03-13 13:39:52 +010084 self._timeout = timeout
85 self._mtu = mtu
86 self._configured = False
87
88 def add_vpp_config(self):
89 self.enable_exporter()
Ole Troan3013e692019-12-09 15:51:44 +010090 l2_flag = 0
91 l3_flag = 0
92 l4_flag = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020093 if "l2" in self._collect.lower():
94 l2_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
95 if "l3" in self._collect.lower():
96 l3_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
97 if "l4" in self._collect.lower():
98 l4_flag = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
Alexander Chernavin86c78562022-05-12 14:56:24 +000099 self._test.vapi.flowprobe_set_params(
Ole Troan3013e692019-12-09 15:51:44 +0100100 record_flags=(l2_flag | l3_flag | l4_flag),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 active_timer=self._active,
102 passive_timer=self._passive,
103 )
Ole Troan5c749732017-03-13 13:39:52 +0100104 self.enable_flowprobe_feature()
105 self._test.vapi.cli("ipfix flush")
106 self._configured = True
107
108 def remove_vpp_config(self):
109 self.disable_exporter()
110 self.disable_flowprobe_feature()
111 self._test.vapi.cli("ipfix flush")
112 self._configured = False
113
114 def enable_exporter(self):
115 self._test.vapi.set_ipfix_exporter(
Jakub Grajciar2f71a882019-10-10 14:21:22 +0200116 collector_address=self._test.pg0.remote_ip4,
117 src_address=self._test.pg0.local_ip4,
Ole Troan5c749732017-03-13 13:39:52 +0100118 path_mtu=self._mtu,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 template_interval=self._timeout,
120 )
Ole Troan5c749732017-03-13 13:39:52 +0100121
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000122 def _enable_disable_flowprobe_feature(self, is_add):
123 which_map = {
124 "l2": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2,
125 "ip4": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4,
126 "ip6": VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6,
127 }
128 direction_map = {
129 "rx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
130 "tx": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
131 "both": VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
132 }
133 self._test.vapi.flowprobe_interface_add_del(
134 is_add=is_add,
135 which=which_map[self._datapath],
136 direction=direction_map[self._direction],
137 sw_if_index=self._intf_obj.sw_if_index,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200138 )
Ole Troan5c749732017-03-13 13:39:52 +0100139
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000140 def enable_flowprobe_feature(self):
141 self._enable_disable_flowprobe_feature(is_add=True)
142
Ole Troan5c749732017-03-13 13:39:52 +0100143 def disable_exporter(self):
144 self._test.vapi.cli("set ipfix exporter collector 0.0.0.0")
145
146 def disable_flowprobe_feature(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000147 self._enable_disable_flowprobe_feature(is_add=False)
Ole Troan5c749732017-03-13 13:39:52 +0100148
149 def object_id(self):
Paul Vinciguerrae3a0e6e2019-03-14 08:46:52 -0700150 return "ipfix-collector-%s-%s" % (self._src, self.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100151
152 def query_vpp_config(self):
153 return self._configured
154
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000155 def verify_templates(self, decoder=None, timeout=1, count=3, field_count_in=None):
Ole Troan5c749732017-03-13 13:39:52 +0100156 templates = []
Klement Sekerac4794572021-09-08 15:15:59 +0200157 self._test.assertIn(count, (1, 2, 3))
158 for _ in range(count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200159 p = self._test.wait_for_cflow_packet(self._test.collector, 2, timeout)
Ole Troan5c749732017-03-13 13:39:52 +0100160 self._test.assertTrue(p.haslayer(IPFIX))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000161 self._test.assertTrue(p.haslayer(Template))
162 if decoder is not None:
Ole Troan5c749732017-03-13 13:39:52 +0100163 templates.append(p[Template].templateID)
164 decoder.add_template(p.getlayer(Template))
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000165 if field_count_in is not None:
166 self._test.assertIn(p[Template].fieldCount, field_count_in)
Ole Troan5c749732017-03-13 13:39:52 +0100167 return templates
168
169
170class MethodHolder(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 """Flow-per-packet plugin: test L2, IP4, IP6 reporting"""
Ole Troan5c749732017-03-13 13:39:52 +0100172
173 # Test variables
174 debug_print = False
Pavel Kotucek89111d02017-06-12 08:26:13 +0200175 max_number_of_packets = 10
Ole Troan5c749732017-03-13 13:39:52 +0100176 pkts = []
177
178 @classmethod
179 def setUpClass(cls):
180 """
181 Perform standard class setup (defined by class method setUpClass in
182 class VppTestCase) before running the test case, set test case related
183 variables and configure VPP.
184 """
185 super(MethodHolder, cls).setUpClass()
Dave Wallace670724c2022-09-20 21:52:18 -0400186 if (is_distro_ubuntu2204 == True or is_distro_debian11 == True) and not hasattr(
187 cls, "vpp"
188 ):
189 return
Ole Troan5c749732017-03-13 13:39:52 +0100190 try:
191 # Create pg interfaces
Ole Troaned929252017-06-13 21:15:40 +0200192 cls.create_pg_interfaces(range(9))
Ole Troan5c749732017-03-13 13:39:52 +0100193
194 # Packet sizes
195 cls.pg_if_packet_sizes = [64, 512, 1518, 9018]
196
197 # Create BD with MAC learning and unknown unicast flooding disabled
198 # and put interfaces to this BD
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200199 cls.vapi.bridge_domain_add_del_v2(
200 bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
201 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100202 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200203 rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1
204 )
Ole Troana5b2eec2019-03-11 19:23:25 +0100205 cls.vapi.sw_interface_set_l2_bridge(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200206 rx_sw_if_index=cls.pg2._sw_if_index, bd_id=1
207 )
Ole Troan5c749732017-03-13 13:39:52 +0100208
209 # Set up all interfaces
210 for i in cls.pg_interfaces:
211 i.admin_up()
212
213 cls.pg0.config_ip4()
214 cls.pg0.configure_ipv4_neighbors()
215 cls.collector = cls.pg0
216
217 cls.pg1.config_ip4()
218 cls.pg1.resolve_arp()
219 cls.pg2.config_ip4()
220 cls.pg2.resolve_arp()
221 cls.pg3.config_ip4()
222 cls.pg3.resolve_arp()
223 cls.pg4.config_ip4()
224 cls.pg4.resolve_arp()
Ole Troaned929252017-06-13 21:15:40 +0200225 cls.pg7.config_ip4()
226 cls.pg8.config_ip4()
227 cls.pg8.configure_ipv4_neighbors()
Ole Troan5c749732017-03-13 13:39:52 +0100228
229 cls.pg5.config_ip6()
230 cls.pg5.resolve_ndp()
231 cls.pg5.disable_ipv6_ra()
232 cls.pg6.config_ip6()
233 cls.pg6.resolve_ndp()
234 cls.pg6.disable_ipv6_ra()
235 except Exception:
236 super(MethodHolder, cls).tearDownClass()
237 raise
238
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800239 @classmethod
240 def tearDownClass(cls):
241 super(MethodHolder, cls).tearDownClass()
242
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200243 def create_stream(
244 self, src_if=None, dst_if=None, packets=None, size=None, ip_ver="v4"
245 ):
Ole Troan5c749732017-03-13 13:39:52 +0100246 """Create a packet stream to tickle the plugin
247
248 :param VppInterface src_if: Source interface for packet stream
249 :param VppInterface src_if: Dst interface for packet stream
250 """
251 if src_if is None:
252 src_if = self.pg1
253 if dst_if is None:
254 dst_if = self.pg2
255 self.pkts = []
256 if packets is None:
257 packets = random.randint(1, self.max_number_of_packets)
258 pkt_size = size
259 for p in range(0, packets):
260 if size is None:
261 pkt_size = random.choice(self.pg_if_packet_sizes)
262 info = self.create_packet_info(src_if, dst_if)
263 payload = self.info_to_payload(info)
264 p = Ether(src=src_if.remote_mac, dst=src_if.local_mac)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200265 if ip_ver == "v4":
Ole Troan5c749732017-03-13 13:39:52 +0100266 p /= IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4)
267 else:
268 p /= IPv6(src=src_if.remote_ip6, dst=dst_if.remote_ip6)
Ole Troaned929252017-06-13 21:15:40 +0200269 p /= UDP(sport=1234, dport=4321)
270 p /= Raw(payload)
Ole Troan5c749732017-03-13 13:39:52 +0100271 info.data = p.copy()
272 self.extend_packet(p, pkt_size)
273 self.pkts.append(p)
274
275 def verify_cflow_data(self, decoder, capture, cflow):
276 octets = 0
277 packets = 0
278 for p in capture:
279 octets += p[IP].len
280 packets += 1
281 if cflow.haslayer(Data):
282 data = decoder.decode_data_set(cflow.getlayer(Set))
283 for record in data:
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800284 self.assertEqual(int(binascii.hexlify(record[1]), 16), octets)
285 self.assertEqual(int(binascii.hexlify(record[2]), 16), packets)
Ole Troan5c749732017-03-13 13:39:52 +0100286
Pavel Kotucek89111d02017-06-12 08:26:13 +0200287 def send_packets(self, src_if=None, dst_if=None):
288 if src_if is None:
289 src_if = self.pg1
290 if dst_if is None:
291 dst_if = self.pg2
292 self.pg_enable_capture([dst_if])
293 src_if.add_stream(self.pkts)
294 self.pg_start()
295 return dst_if.get_capture(len(self.pkts))
296
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200297 def verify_cflow_data_detail(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000298 self,
299 decoder,
300 capture,
301 cflow,
302 data_set={1: "octets", 2: "packets"},
303 ip_ver="v4",
304 field_count=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200305 ):
Ole Troan5c749732017-03-13 13:39:52 +0100306 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800307 print(capture[0].show())
Ole Troan5c749732017-03-13 13:39:52 +0100308 if cflow.haslayer(Data):
309 data = decoder.decode_data_set(cflow.getlayer(Set))
310 if self.debug_print:
Paul Vinciguerra661f91f2018-11-28 19:06:41 -0800311 print(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200312 if ip_ver == "v4":
Alexander Chernavin120095d2023-10-11 12:15:55 +0000313 ip_layer = capture[0][IP] if capture[0].haslayer(IP) else None
Ole Troan5c749732017-03-13 13:39:52 +0100314 else:
Alexander Chernavin120095d2023-10-11 12:15:55 +0000315 ip_layer = capture[0][IPv6] if capture[0].haslayer(IPv6) else None
Ole Troan5c749732017-03-13 13:39:52 +0100316 if data_set is not None:
317 for record in data:
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700318 # skip flow if ingress/egress interface is 0
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800319 if int(binascii.hexlify(record[10]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100320 continue
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800321 if int(binascii.hexlify(record[14]), 16) == 0:
Ole Troan5c749732017-03-13 13:39:52 +0100322 continue
323
324 for field in data_set:
Ole Troan5c749732017-03-13 13:39:52 +0100325 value = data_set[field]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 if value == "octets":
Ole Troan5c749732017-03-13 13:39:52 +0100327 value = ip_layer.len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200328 if ip_ver == "v6":
329 value += 40 # ??? is this correct
330 elif value == "packets":
Ole Troan5c749732017-03-13 13:39:52 +0100331 value = 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 elif value == "src_ip":
333 if ip_ver == "v4":
334 ip = socket.inet_pton(socket.AF_INET, ip_layer.src)
Ole Troan5c749732017-03-13 13:39:52 +0100335 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200336 ip = socket.inet_pton(socket.AF_INET6, ip_layer.src)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800337 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200338 elif value == "dst_ip":
339 if ip_ver == "v4":
340 ip = socket.inet_pton(socket.AF_INET, ip_layer.dst)
Ole Troan5c749732017-03-13 13:39:52 +0100341 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200342 ip = socket.inet_pton(socket.AF_INET6, ip_layer.dst)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800343 value = int(binascii.hexlify(ip), 16)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200344 elif value == "sport":
Ole Troan5c749732017-03-13 13:39:52 +0100345 value = int(capture[0][UDP].sport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200346 elif value == "dport":
Ole Troan5c749732017-03-13 13:39:52 +0100347 value = int(capture[0][UDP].dport)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200348 self.assertEqual(
349 int(binascii.hexlify(record[field]), 16), value
350 )
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000351 if field_count is not None:
352 for record in data:
353 self.assertEqual(len(record), field_count)
Ole Troan5c749732017-03-13 13:39:52 +0100354
355 def verify_cflow_data_notimer(self, decoder, capture, cflows):
356 idx = 0
357 for cflow in cflows:
358 if cflow.haslayer(Data):
359 data = decoder.decode_data_set(cflow.getlayer(Set))
360 else:
361 raise Exception("No CFLOW data")
362
363 for rec in data:
364 p = capture[idx]
365 idx += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200366 self.assertEqual(p[IP].len, int(binascii.hexlify(rec[1]), 16))
367 self.assertEqual(1, int(binascii.hexlify(rec[2]), 16))
Ole Troan5c749732017-03-13 13:39:52 +0100368 self.assertEqual(len(capture), idx)
369
Klement Sekerac4794572021-09-08 15:15:59 +0200370 def wait_for_cflow_packet(self, collector_intf, set_id=2, timeout=1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200371 """wait for CFLOW packet and verify its correctness
Ole Troan5c749732017-03-13 13:39:52 +0100372
373 :param timeout: how long to wait
374
Ole Troan5c749732017-03-13 13:39:52 +0100375 """
376 self.logger.info("IPFIX: Waiting for CFLOW packet")
Ole Troan5c749732017-03-13 13:39:52 +0100377 # self.logger.debug(self.vapi.ppcli("show flow table"))
Klement Sekerac4794572021-09-08 15:15:59 +0200378 p = collector_intf.wait_for_packet(timeout=timeout)
379 self.assertEqual(p[Set].setID, set_id)
380 # self.logger.debug(self.vapi.ppcli("show flow table"))
381 self.logger.debug(ppp("IPFIX: Got packet:", p))
Ole Troan5c749732017-03-13 13:39:52 +0100382 return p
383
Ole Troan5c749732017-03-13 13:39:52 +0100384
Andrew Yourtchenko06f32812021-01-14 10:19:08 +0000385@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +0000386@tag_fixme_vpp_workers
Dave Wallace670724c2022-09-20 21:52:18 -0400387@tag_fixme_ubuntu2204
388@tag_fixme_debian11
Ole Troaned929252017-06-13 21:15:40 +0200389class Flowprobe(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +0100390 """Template verification, timer tests"""
391
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800392 @classmethod
393 def setUpClass(cls):
394 super(Flowprobe, cls).setUpClass()
395
396 @classmethod
397 def tearDownClass(cls):
398 super(Flowprobe, cls).tearDownClass()
399
Ole Troan5c749732017-03-13 13:39:52 +0100400 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 """timer less than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200402 self.logger.info("FFP_TEST_START_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100403 self.pg_enable_capture(self.pg_interfaces)
404 self.pkts = []
405
Pavel Kotucek89111d02017-06-12 08:26:13 +0200406 ipfix = VppCFLOW(test=self, active=2)
Ole Troan5c749732017-03-13 13:39:52 +0100407 ipfix.add_vpp_config()
408
409 ipfix_decoder = IPFIXDecoder()
410 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200411 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +0100412
Ole Troaned929252017-06-13 21:15:40 +0200413 self.create_stream(packets=1)
Pavel Kotucek89111d02017-06-12 08:26:13 +0200414 self.send_packets()
Ole Troaned929252017-06-13 21:15:40 +0200415 capture = self.pg2.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100416
417 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200418 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100419 self.verify_cflow_data(ipfix_decoder, capture, cflow)
420
421 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200422 self.logger.info("FFP_TEST_FINISH_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100423
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 (
562 Ether(src=self.pg3.remote_mac, dst=self.pg4.local_mac)
563 / 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
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001231@tag_fixme_vpp_workers
1232class DatapathTx(MethodHolder, DatapathTestsHolder):
1233 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1234
1235 intf1 = "pg2"
1236 intf2 = "pg4"
1237 intf3 = "pg6"
1238 direction = "tx"
1239
Alexander Chernavin64d64632023-11-07 11:25:21 +00001240 def test_rewritten_traffic(self):
1241 """Rewritten traffic (from subif to ipfix if)"""
1242 self.pg_enable_capture(self.pg_interfaces)
1243 self.pkts = []
1244
1245 # prepare a sub-interface
1246 subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400)
1247 subif.admin_up()
1248 subif.config_ip4()
1249
1250 # enable ip4 datapath for an interface
1251 ipfix = VppCFLOW(
1252 test=self,
1253 intf="pg8",
1254 datapath="ip4",
1255 layer="l2 l3 l4",
1256 direction=self.direction,
1257 )
1258 ipfix.add_vpp_config()
1259
1260 # template packet should arrive immediately
1261 ipfix_decoder = IPFIXDecoder()
1262 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1263
1264 # forward some traffic through the ipfix interface
1265 route = VppIpRoute(
1266 self,
1267 "9.0.0.0",
1268 24,
1269 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
1270 )
1271 route.add_vpp_config()
1272
1273 # prepare an IPv4 packet (subif => ipfix interface)
1274 pkt = (
1275 Ether(src=subif.remote_mac, dst=self.pg7.local_mac)
1276 / IP(src=subif.remote_ip4, dst="9.0.0.1")
1277 / UDP(sport=1234, dport=4321)
1278 / Raw(b"\xa5" * 123)
1279 )
1280 self.pkts = [
1281 subif.add_dot1ad_layer(pkt, 300, 400),
1282 ]
1283
1284 # send the packet
1285 capture = self.send_packets(self.pg7, self.pg8)
1286
1287 # wait for a flow and verify it
1288 self.vapi.ipfix_flush()
1289 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1290 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1291 self.verify_cflow_data_detail(
1292 ipfix_decoder,
1293 capture,
1294 cflow,
1295 {
1296 IPFIX_SRC_IP4_ADDR_ID: "src_ip",
1297 IPFIX_DST_IP4_ADDR_ID: "dst_ip",
1298 IPFIX_SRC_TRANS_PORT_ID: "sport",
1299 IPFIX_DST_TRANS_PORT_ID: "dport",
1300 IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"),
1301 },
1302 )
1303
1304 self.collector.get_capture(2)
1305
1306 # cleanup
1307 route.remove_vpp_config()
1308 subif.remove_vpp_config()
1309 ipfix.remove_vpp_config()
1310
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001311
1312@tag_fixme_vpp_workers
1313class DatapathRx(MethodHolder, DatapathTestsHolder):
1314 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1315
1316 intf1 = "pg1"
1317 intf2 = "pg3"
1318 intf3 = "pg5"
1319 direction = "rx"
1320
1321
Klement Sekerab23ffd72021-05-31 16:08:53 +02001322@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001323class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001324 """Disable IPFIX"""
1325
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001326 @classmethod
1327 def setUpClass(cls):
1328 super(DisableIPFIX, cls).setUpClass()
1329
1330 @classmethod
1331 def tearDownClass(cls):
1332 super(DisableIPFIX, cls).tearDownClass()
1333
Ole Troan5c749732017-03-13 13:39:52 +01001334 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001335 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001336 self.logger.info("FFP_TEST_START_0001")
1337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pkts = []
1339
Pavel Kotucek89111d02017-06-12 08:26:13 +02001340 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001341 ipfix.add_vpp_config()
1342
1343 ipfix_decoder = IPFIXDecoder()
1344 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001345 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001346
1347 self.create_stream()
1348 self.send_packets()
1349
1350 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001351 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001352 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001353 self.collector.get_capture(4)
1354
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001355 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001356 ipfix.disable_exporter()
1357 self.pg_enable_capture([self.collector])
1358
1359 self.send_packets()
1360
1361 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001362 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001363 self.sleep(1, "wait before verifying no packets sent")
1364 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001365
1366 ipfix.remove_vpp_config()
1367 self.logger.info("FFP_TEST_FINISH_0001")
1368
1369
Klement Sekerab23ffd72021-05-31 16:08:53 +02001370@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001371class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001372 """Re-enable IPFIX"""
1373
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001374 @classmethod
1375 def setUpClass(cls):
1376 super(ReenableIPFIX, cls).setUpClass()
1377
1378 @classmethod
1379 def tearDownClass(cls):
1380 super(ReenableIPFIX, cls).tearDownClass()
1381
Pavel Kotucek89111d02017-06-12 08:26:13 +02001382 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001383 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001384 self.logger.info("FFP_TEST_START_0001")
1385 self.pg_enable_capture(self.pg_interfaces)
1386 self.pkts = []
1387
Pavel Kotucek89111d02017-06-12 08:26:13 +02001388 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001389 ipfix.add_vpp_config()
1390
1391 ipfix_decoder = IPFIXDecoder()
1392 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001393 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001394
Pavel Kotucek89111d02017-06-12 08:26:13 +02001395 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001396 self.send_packets()
1397
1398 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001399 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001400 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001401 self.collector.get_capture(4)
1402
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001403 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001404 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001405 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001406 self.pg_enable_capture([self.collector])
1407
1408 self.send_packets()
1409
1410 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001411 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001412 self.sleep(1, "wait before verifying no packets sent")
1413 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001414 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001415
1416 # enable IPFIX
1417 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001418
Pavel Kotucek89111d02017-06-12 08:26:13 +02001419 capture = self.collector.get_capture(4)
1420 nr_templates = 0
1421 nr_data = 0
1422 for p in capture:
1423 self.assertTrue(p.haslayer(IPFIX))
1424 if p.haslayer(Template):
1425 nr_templates += 1
1426 self.assertTrue(nr_templates, 3)
1427 for p in capture:
1428 self.assertTrue(p.haslayer(IPFIX))
1429 if p.haslayer(Data):
1430 nr_data += 1
1431 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001432
1433 ipfix.remove_vpp_config()
1434 self.logger.info("FFP_TEST_FINISH_0001")
1435
1436
Klement Sekerab23ffd72021-05-31 16:08:53 +02001437@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001438class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001439 """Disable Flowprobe feature"""
1440
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001441 @classmethod
1442 def setUpClass(cls):
1443 super(DisableFP, cls).setUpClass()
1444
1445 @classmethod
1446 def tearDownClass(cls):
1447 super(DisableFP, cls).tearDownClass()
1448
Ole Troan5c749732017-03-13 13:39:52 +01001449 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001450 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001451 self.logger.info("FFP_TEST_START_0001")
1452 self.pg_enable_capture(self.pg_interfaces)
1453 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001454 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001455 ipfix.add_vpp_config()
1456
1457 ipfix_decoder = IPFIXDecoder()
1458 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001459 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001460
1461 self.create_stream()
1462 self.send_packets()
1463
1464 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001465 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001466 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001467 self.collector.get_capture(4)
1468
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001469 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001470 ipfix.disable_flowprobe_feature()
1471 self.pg_enable_capture([self.collector])
1472
1473 self.send_packets()
1474
1475 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001476 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001477 self.sleep(1, "wait before verifying no packets sent")
1478 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001479
Dave Wallace8800f732023-08-31 00:47:44 -04001480 # enable FPP feature so the remove_vpp_config() doesn't fail
1481 # due to missing feature on interface.
1482 ipfix.enable_flowprobe_feature()
1483
Ole Troan5c749732017-03-13 13:39:52 +01001484 ipfix.remove_vpp_config()
1485 self.logger.info("FFP_TEST_FINISH_0001")
1486
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001487 def test_no_leftover_flows_after_disabling(self):
1488 """disable flowprobe feature and expect no leftover flows"""
1489 self.pg_enable_capture(self.pg_interfaces)
1490 self.pkts = []
1491
1492 # enable ip4 datapath for an interface
1493 # set active and passive timers
1494 ipfix = VppCFLOW(
1495 test=self,
1496 active=3,
1497 passive=4,
1498 intf="pg3",
1499 layer="l3",
1500 datapath="ip4",
1501 direction="rx",
1502 mtu=100,
1503 )
1504 ipfix.add_vpp_config()
1505
1506 # template packet should arrive immediately
1507 ipfix.verify_templates(count=1)
1508
1509 # send some ip4 packets
1510 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1511 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1512
1513 # disable feature for the interface
1514 # currently stored ip4 flows should be removed
1515 ipfix.disable_flowprobe_feature()
1516
1517 # no leftover ip4 flows are expected
1518 self.pg_enable_capture([self.collector])
1519 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1520 self.collector.assert_nothing_captured()
1521
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001522 # re-enable feature for the interface
1523 ipfix.enable_flowprobe_feature()
1524
1525 # template packet should arrive immediately
1526 ipfix_decoder = IPFIXDecoder()
1527 self.vapi.ipfix_flush()
1528 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1529
1530 # send some ip4 packets
1531 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1532 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1533
1534 # verify meta info - packet/octet delta
1535 self.vapi.ipfix_flush()
1536 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1537 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1538
1539 self.collector.get_capture(2)
1540
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001541 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001542 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001543
Ole Troan5c749732017-03-13 13:39:52 +01001544
Klement Sekerab23ffd72021-05-31 16:08:53 +02001545@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001546class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001547 """Re-enable Flowprobe feature"""
1548
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001549 @classmethod
1550 def setUpClass(cls):
1551 super(ReenableFP, cls).setUpClass()
1552
1553 @classmethod
1554 def tearDownClass(cls):
1555 super(ReenableFP, cls).tearDownClass()
1556
Ole Troan5c749732017-03-13 13:39:52 +01001557 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001558 """disable flowprobe feature after first packets and re-enable
1559 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001560 self.logger.info("FFP_TEST_START_0001")
1561 self.pg_enable_capture(self.pg_interfaces)
1562 self.pkts = []
1563
Pavel Kotucek89111d02017-06-12 08:26:13 +02001564 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001565 ipfix.add_vpp_config()
1566
1567 ipfix_decoder = IPFIXDecoder()
1568 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001569 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001570 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1571
1572 self.create_stream()
1573 self.send_packets()
1574
1575 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001576 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001577 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001578 self.collector.get_capture(4)
1579
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001580 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001581 ipfix.disable_flowprobe_feature()
1582 self.pg_enable_capture([self.collector])
1583
1584 self.send_packets()
1585
1586 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001587 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001588 self.sleep(5, "wait before verifying no packets sent")
1589 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001590
1591 # enable FPP feature
1592 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001593 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001594 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1595
1596 self.send_packets()
1597
1598 # make sure the next packets (templates and data) we expect actually
1599 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001600 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001601 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001602 self.collector.get_capture(4)
1603
1604 ipfix.remove_vpp_config()
1605 self.logger.info("FFP_TEST_FINISH_0001")
1606
1607
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001608if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001609 unittest.main(testRunner=VppTestRunner)