blob: 89ac97ea88cf090602dc407ae97d7e765bfdd7a0 [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()
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_ubuntu2204
386@tag_fixme_debian11
Ole Troaned929252017-06-13 21:15:40 +0200387class Flowprobe(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +0100388 """Template verification, timer tests"""
389
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800390 @classmethod
391 def setUpClass(cls):
392 super(Flowprobe, cls).setUpClass()
393
394 @classmethod
395 def tearDownClass(cls):
396 super(Flowprobe, cls).tearDownClass()
397
Ole Troan5c749732017-03-13 13:39:52 +0100398 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 """timer less than template timeout"""
Ole Troaned929252017-06-13 21:15:40 +0200400 self.logger.info("FFP_TEST_START_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100401 self.pg_enable_capture(self.pg_interfaces)
402 self.pkts = []
403
Pavel Kotucek89111d02017-06-12 08:26:13 +0200404 ipfix = VppCFLOW(test=self, active=2)
Ole Troan5c749732017-03-13 13:39:52 +0100405 ipfix.add_vpp_config()
406
407 ipfix_decoder = IPFIXDecoder()
408 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200409 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +0100410
Ole Troaned929252017-06-13 21:15:40 +0200411 self.create_stream(packets=1)
Pavel Kotucek89111d02017-06-12 08:26:13 +0200412 self.send_packets()
Ole Troaned929252017-06-13 21:15:40 +0200413 capture = self.pg2.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100414
415 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200416 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100417 self.verify_cflow_data(ipfix_decoder, capture, cflow)
418
419 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200420 self.logger.info("FFP_TEST_FINISH_0001")
Ole Troan5c749732017-03-13 13:39:52 +0100421
adrianvillina77d4ca2023-12-22 16:52:56 +0100422 @unittest.skipUnless(
423 config.extended, "Test is unstable (assertion error, needs to be fixed"
424 )
Pavel Kotucek89111d02017-06-12 08:26:13 +0200425 def test_0002(self):
adrianvillina77d4ca2023-12-22 16:52:56 +0100426 """timer greater than template timeout [UNSTABLE, FIX ME]"""
Ole Troaned929252017-06-13 21:15:40 +0200427 self.logger.info("FFP_TEST_START_0002")
Ole Troan5c749732017-03-13 13:39:52 +0100428 self.pg_enable_capture(self.pg_interfaces)
429 self.pkts = []
430
Pavel Kotucek89111d02017-06-12 08:26:13 +0200431 ipfix = VppCFLOW(test=self, timeout=3, active=4)
Ole Troan5c749732017-03-13 13:39:52 +0100432 ipfix.add_vpp_config()
433
434 ipfix_decoder = IPFIXDecoder()
435 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200436 ipfix.verify_templates()
Ole Troan5c749732017-03-13 13:39:52 +0100437
Pavel Kotucek89111d02017-06-12 08:26:13 +0200438 self.create_stream(packets=2)
439 self.send_packets()
440 capture = self.pg2.get_capture(2)
Ole Troan5c749732017-03-13 13:39:52 +0100441
442 # next set of template packet should arrive after 20 seconds
443 # template packet should arrive within 20 s
Pavel Kotucek89111d02017-06-12 08:26:13 +0200444 templates = ipfix.verify_templates(ipfix_decoder, timeout=5)
Ole Troan5c749732017-03-13 13:39:52 +0100445
446 # make sure the one packet we expect actually showed up
Pavel Kotucek89111d02017-06-12 08:26:13 +0200447 cflow = self.wait_for_cflow_packet(self.collector, templates[1], 15)
Ole Troan5c749732017-03-13 13:39:52 +0100448 self.verify_cflow_data(ipfix_decoder, capture, cflow)
449
450 ipfix.remove_vpp_config()
Ole Troaned929252017-06-13 21:15:40 +0200451 self.logger.info("FFP_TEST_FINISH_0002")
452
453 def test_cflow_packet(self):
454 """verify cflow packet fields"""
455 self.logger.info("FFP_TEST_START_0000")
456 self.pg_enable_capture(self.pg_interfaces)
457 self.pkts = []
458
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 ipfix = VppCFLOW(
460 test=self, intf="pg8", datapath="ip4", layer="l2 l3 l4", active=2
461 )
Ole Troaned929252017-06-13 21:15:40 +0200462 ipfix.add_vpp_config()
463
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200464 route_9001 = VppIpRoute(
465 self,
466 "9.0.0.0",
467 24,
468 [VppRoutePath(self.pg8._remote_hosts[0].ip4, self.pg8.sw_if_index)],
469 )
Ole Troaned929252017-06-13 21:15:40 +0200470 route_9001.add_vpp_config()
471
472 ipfix_decoder = IPFIXDecoder()
473 templates = ipfix.verify_templates(ipfix_decoder, count=1)
474
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200475 self.pkts = [
476 (
477 Ether(dst=self.pg7.local_mac, src=self.pg7.remote_mac)
478 / IP(src=self.pg7.remote_ip4, dst="9.0.0.100")
479 / TCP(sport=1234, dport=4321, flags=80)
480 / Raw(b"\xa5" * 100)
481 )
482 ]
Ole Troaned929252017-06-13 21:15:40 +0200483
484 nowUTC = int(time.time())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200485 nowUNIX = nowUTC + 2208988800
Ole Troaned929252017-06-13 21:15:40 +0200486 self.send_packets(src_if=self.pg7, dst_if=self.pg8)
487
488 cflow = self.wait_for_cflow_packet(self.collector, templates[0], 10)
489 self.collector.get_capture(2)
490
491 if cflow[0].haslayer(IPFIX):
492 self.assertEqual(cflow[IPFIX].version, 10)
493 self.assertEqual(cflow[IPFIX].observationDomainID, 1)
494 self.assertEqual(cflow[IPFIX].sequenceNumber, 0)
495 self.assertAlmostEqual(cflow[IPFIX].exportTime, nowUTC, delta=5)
496 if cflow.haslayer(Data):
497 record = ipfix_decoder.decode_data_set(cflow[0].getlayer(Set))[0]
498 # ingress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800499 self.assertEqual(int(binascii.hexlify(record[10]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200500 # egress interface
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800501 self.assertEqual(int(binascii.hexlify(record[14]), 16), 9)
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000502 # direction
503 self.assertEqual(int(binascii.hexlify(record[61]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200504 # packets
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800505 self.assertEqual(int(binascii.hexlify(record[2]), 16), 1)
Ole Troaned929252017-06-13 21:15:40 +0200506 # src mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200507 self.assertEqual(mac_ntop(record[56]), self.pg8.local_mac)
Ole Troaned929252017-06-13 21:15:40 +0200508 # dst mac
Ole Troanb0d83f12019-10-21 23:13:46 +0200509 self.assertEqual(mac_ntop(record[80]), self.pg8.remote_mac)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800510 flowTimestamp = int(binascii.hexlify(record[156]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200511 # flow start timestamp
512 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800513 flowTimestamp = int(binascii.hexlify(record[157]), 16) >> 32
Ole Troaned929252017-06-13 21:15:40 +0200514 # flow end timestamp
515 self.assertAlmostEqual(flowTimestamp, nowUNIX, delta=1)
516 # ethernet type
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800517 self.assertEqual(int(binascii.hexlify(record[256]), 16), 8)
Ole Troaned929252017-06-13 21:15:40 +0200518 # src ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200519 self.assertEqual(inet_ntop(socket.AF_INET, record[8]), self.pg7.remote_ip4)
Ole Troaned929252017-06-13 21:15:40 +0200520 # dst ip
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200521 self.assertEqual(inet_ntop(socket.AF_INET, record[12]), "9.0.0.100")
Ole Troaned929252017-06-13 21:15:40 +0200522 # protocol (TCP)
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800523 self.assertEqual(int(binascii.hexlify(record[4]), 16), 6)
Ole Troaned929252017-06-13 21:15:40 +0200524 # src port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800525 self.assertEqual(int(binascii.hexlify(record[7]), 16), 1234)
Ole Troaned929252017-06-13 21:15:40 +0200526 # dst port
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800527 self.assertEqual(int(binascii.hexlify(record[11]), 16), 4321)
Ole Troaned929252017-06-13 21:15:40 +0200528 # tcp flags
Paul Vinciguerra6e4c6ad2018-11-25 10:35:29 -0800529 self.assertEqual(int(binascii.hexlify(record[6]), 16), 80)
Ole Troaned929252017-06-13 21:15:40 +0200530
531 ipfix.remove_vpp_config()
532 self.logger.info("FFP_TEST_FINISH_0000")
Ole Troan5c749732017-03-13 13:39:52 +0100533
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000534 def test_flow_entry_reuse(self):
535 """Verify flow entry reuse doesn't accumulate meta info"""
536 self.pg_enable_capture(self.pg_interfaces)
537 self.pkts = []
538
539 # enable ip4 datapath for an interface
540 # set active and passive timers
541 ipfix = VppCFLOW(
542 test=self,
543 active=2,
544 passive=3,
545 intf="pg3",
546 layer="l3 l4",
547 datapath="ip4",
548 direction="rx",
549 mtu=100,
550 )
551 ipfix.add_vpp_config()
552
553 # template packet should arrive immediately
554 ipfix_decoder = IPFIXDecoder()
555 templates = ipfix.verify_templates(ipfix_decoder, count=1)
556
557 # make a tcp packet
558 self.pkts = [
559 (
Steven Luonge4238aa2024-04-19 09:49:20 -0700560 Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac)
Alexander Chernavin21922ce2023-10-26 11:18:19 +0000561 / IP(src=self.pg3.remote_ip4, dst=self.pg4.remote_ip4)
562 / TCP(sport=1234, dport=4321)
563 / Raw(b"\xa5" * 50)
564 )
565 ]
566
567 # send the tcp packet two times, each time with new set of flags
568 tcp_flags = (
569 TCP_F_SYN | TCP_F_ACK,
570 TCP_F_RST | TCP_F_PSH,
571 )
572 for f in tcp_flags:
573 self.pkts[0][TCP].flags = f
574 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
575
576 # verify meta info - packet/octet delta and tcp flags
577 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=6)
578 self.verify_cflow_data(ipfix_decoder, capture, cflow)
579 self.verify_cflow_data_detail(
580 ipfix_decoder,
581 capture,
582 cflow,
583 {
584 IPFIX_TCP_FLAGS_ID: f,
585 IPFIX_SRC_TRANS_PORT_ID: 1234,
586 IPFIX_DST_TRANS_PORT_ID: 4321,
587 },
588 )
589
590 self.collector.get_capture(3)
591
592 # cleanup
593 ipfix.remove_vpp_config()
594
Alexander Chernavin86c78562022-05-12 14:56:24 +0000595 def test_interface_dump(self):
596 """Dump interfaces with IPFIX flow record generation enabled"""
597 self.logger.info("FFP_TEST_START_0003")
598
599 # Enable feature for 3 interfaces
600 ipfix1 = VppCFLOW(test=self, intf="pg1", datapath="l2", direction="rx")
601 ipfix1.add_vpp_config()
602
603 ipfix2 = VppCFLOW(test=self, intf="pg2", datapath="ip4", direction="tx")
604 ipfix2.enable_flowprobe_feature()
605
606 ipfix3 = VppCFLOW(test=self, intf="pg3", datapath="ip6", direction="both")
607 ipfix3.enable_flowprobe_feature()
608
609 # When request "all", dump should contain all enabled interfaces
610 dump = self.vapi.flowprobe_interface_dump()
611 self.assertEqual(len(dump), 3)
612
613 # Verify 1st interface
614 self.assertEqual(dump[0].sw_if_index, self.pg1.sw_if_index)
615 self.assertEqual(
616 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_L2
617 )
618 self.assertEqual(
619 dump[0].direction,
620 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_RX,
621 )
622
623 # Verify 2nd interface
624 self.assertEqual(dump[1].sw_if_index, self.pg2.sw_if_index)
625 self.assertEqual(
626 dump[1].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
627 )
628 self.assertEqual(
629 dump[1].direction,
630 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
631 )
632
633 # Verify 3rd interface
634 self.assertEqual(dump[2].sw_if_index, self.pg3.sw_if_index)
635 self.assertEqual(
636 dump[2].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP6
637 )
638 self.assertEqual(
639 dump[2].direction,
640 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_BOTH,
641 )
642
643 # When request 2nd interface, dump should contain only the specified interface
644 dump = self.vapi.flowprobe_interface_dump(sw_if_index=self.pg2.sw_if_index)
645 self.assertEqual(len(dump), 1)
646
647 # Verify 2nd interface
648 self.assertEqual(dump[0].sw_if_index, self.pg2.sw_if_index)
649 self.assertEqual(
650 dump[0].which, VppEnum.vl_api_flowprobe_which_t.FLOWPROBE_WHICH_IP4
651 )
652 self.assertEqual(
653 dump[0].direction,
654 VppEnum.vl_api_flowprobe_direction_t.FLOWPROBE_DIRECTION_TX,
655 )
656
657 # When request 99th interface, dump should be empty
658 dump = self.vapi.flowprobe_interface_dump(sw_if_index=99)
659 self.assertEqual(len(dump), 0)
660
661 ipfix1.remove_vpp_config()
662 ipfix2.remove_vpp_config()
663 ipfix3.remove_vpp_config()
664 self.logger.info("FFP_TEST_FINISH_0003")
665
666 def test_get_params(self):
667 """Get IPFIX flow record generation parameters"""
668 self.logger.info("FFP_TEST_START_0004")
669
670 # Enable feature for an interface with custom parameters
671 ipfix = VppCFLOW(test=self, active=20, passive=40, layer="l2 l3 l4")
672 ipfix.add_vpp_config()
673
674 # Get and verify parameters
675 params = self.vapi.flowprobe_get_params()
676 self.assertEqual(params.active_timer, 20)
677 self.assertEqual(params.passive_timer, 40)
678 record_flags = VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L2
679 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L3
680 record_flags |= VppEnum.vl_api_flowprobe_record_flags_t.FLOWPROBE_RECORD_FLAG_L4
681 self.assertEqual(params.record_flags, record_flags)
682
683 ipfix.remove_vpp_config()
684 self.logger.info("FFP_TEST_FINISH_0004")
685
Ole Troan5c749732017-03-13 13:39:52 +0100686
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000687class DatapathTestsHolder(object):
Pavel Kotucek89111d02017-06-12 08:26:13 +0200688 """collect information on Ethernet, IP4 and IP6 datapath (no timers)"""
Ole Troan5c749732017-03-13 13:39:52 +0100689
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800690 @classmethod
691 def setUpClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000692 super(DatapathTestsHolder, cls).setUpClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800693
694 @classmethod
695 def tearDownClass(cls):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000696 super(DatapathTestsHolder, cls).tearDownClass()
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800697
Pavel Kotucek89111d02017-06-12 08:26:13 +0200698 def test_templatesL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200699 """verify template on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100700 self.logger.info("FFP_TEST_START_0000")
701 self.pg_enable_capture(self.pg_interfaces)
702
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000703 ipfix = VppCFLOW(
704 test=self, intf=self.intf1, layer="l2", direction=self.direction
705 )
Ole Troan5c749732017-03-13 13:39:52 +0100706 ipfix.add_vpp_config()
707
708 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400709 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200710 ipfix.verify_templates(timeout=3, count=1)
711 self.collector.get_capture(1)
Ole Troan5c749732017-03-13 13:39:52 +0100712
713 ipfix.remove_vpp_config()
714 self.logger.info("FFP_TEST_FINISH_0000")
715
Pavel Kotucek89111d02017-06-12 08:26:13 +0200716 def test_L2onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200717 """L2 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100718 self.logger.info("FFP_TEST_START_0001")
719 self.pg_enable_capture(self.pg_interfaces)
720 self.pkts = []
721
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000722 ipfix = VppCFLOW(
723 test=self, intf=self.intf1, layer="l2", direction=self.direction
724 )
Ole Troan5c749732017-03-13 13:39:52 +0100725 ipfix.add_vpp_config()
726
727 ipfix_decoder = IPFIXDecoder()
728 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200729 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100730
731 self.create_stream(packets=1)
732 capture = self.send_packets()
733
734 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400735 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200736 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200737 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000738 ipfix_decoder,
739 capture,
740 cflow,
741 {2: "packets", 256: 8, 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200742 )
Ole Troan5c749732017-03-13 13:39:52 +0100743 self.collector.get_capture(2)
744
745 ipfix.remove_vpp_config()
746 self.logger.info("FFP_TEST_FINISH_0001")
747
Pavel Kotucek89111d02017-06-12 08:26:13 +0200748 def test_L3onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 """L3 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100750 self.logger.info("FFP_TEST_START_0002")
751 self.pg_enable_capture(self.pg_interfaces)
752 self.pkts = []
753
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000754 ipfix = VppCFLOW(
755 test=self, intf=self.intf1, layer="l3", direction=self.direction
756 )
Ole Troan5c749732017-03-13 13:39:52 +0100757 ipfix.add_vpp_config()
758
759 ipfix_decoder = IPFIXDecoder()
760 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200761 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100762
763 self.create_stream(packets=1)
764 capture = self.send_packets()
765
766 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400767 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200768 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200769 self.verify_cflow_data_detail(
770 ipfix_decoder,
771 capture,
772 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000773 {
774 2: "packets",
775 4: 17,
776 8: "src_ip",
777 12: "dst_ip",
778 61: (self.direction == "tx"),
779 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200780 )
Ole Troan5c749732017-03-13 13:39:52 +0100781
Ole Troan5c749732017-03-13 13:39:52 +0100782 self.collector.get_capture(3)
783
784 ipfix.remove_vpp_config()
785 self.logger.info("FFP_TEST_FINISH_0002")
786
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000787 def test_L234onL2(self):
788 """L2/3/4 data on L2 datapath"""
Alexander Chernavin120095d2023-10-11 12:15:55 +0000789 self.pg_enable_capture(self.pg_interfaces)
790 self.pkts = []
791
792 ipfix = VppCFLOW(
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000793 test=self, intf=self.intf1, layer="l2 l3 l4", direction=self.direction
Alexander Chernavin120095d2023-10-11 12:15:55 +0000794 )
795 ipfix.add_vpp_config()
796
797 ipfix_decoder = IPFIXDecoder()
798 # template packet should arrive immediately
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000799 tmpl_l2_field_count = TMPL_COMMON_FIELD_COUNT + TMPL_L2_FIELD_COUNT
800 tmpl_ip_field_count = (
801 TMPL_COMMON_FIELD_COUNT
802 + TMPL_L2_FIELD_COUNT
803 + TMPL_L3_FIELD_COUNT
804 + TMPL_L4_FIELD_COUNT
805 )
806 templates = ipfix.verify_templates(
807 ipfix_decoder,
808 count=3,
809 field_count_in=(tmpl_l2_field_count, tmpl_ip_field_count),
810 )
Alexander Chernavin120095d2023-10-11 12:15:55 +0000811
812 # verify IPv4 and IPv6 flows
813 for ip_ver in ("v4", "v6"):
814 self.create_stream(packets=1, ip_ver=ip_ver)
815 capture = self.send_packets()
816
817 # make sure the one packet we expect actually showed up
818 self.vapi.ipfix_flush()
819 cflow = self.wait_for_cflow_packet(
820 self.collector, templates[1 if ip_ver == "v4" else 2]
821 )
822 src_ip_id = 8 if ip_ver == "v4" else 27
823 dst_ip_id = 12 if ip_ver == "v4" else 28
824 self.verify_cflow_data_detail(
825 ipfix_decoder,
826 capture,
827 cflow,
828 {
829 2: "packets",
830 256: 8 if ip_ver == "v4" else 56710,
831 4: 17,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000832 7: "sport",
833 11: "dport",
Alexander Chernavin120095d2023-10-11 12:15:55 +0000834 src_ip_id: "src_ip",
835 dst_ip_id: "dst_ip",
836 61: (self.direction == "tx"),
837 },
838 ip_ver=ip_ver,
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000839 field_count=tmpl_ip_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000840 )
841
842 # verify non-IP flow
843 self.pkts = [
844 (
845 Ether(dst=self.pg2.local_mac, src=self.pg1.remote_mac)
846 / SlowProtocol()
847 / LACP()
848 )
849 ]
850 capture = self.send_packets()
851
852 # make sure the one packet we expect actually showed up
853 self.vapi.ipfix_flush()
854 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
855 self.verify_cflow_data_detail(
856 ipfix_decoder,
857 capture,
858 cflow,
859 {2: "packets", 256: 2440, 61: (self.direction == "tx")},
Alexander Chernavin6b027cf2023-10-17 08:54:33 +0000860 field_count=tmpl_l2_field_count,
Alexander Chernavin120095d2023-10-11 12:15:55 +0000861 )
862
863 self.collector.get_capture(6)
864
865 ipfix.remove_vpp_config()
866
Pavel Kotucek89111d02017-06-12 08:26:13 +0200867 def test_L4onL2(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200868 """L4 data on L2 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100869 self.logger.info("FFP_TEST_START_0003")
870 self.pg_enable_capture(self.pg_interfaces)
871 self.pkts = []
872
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000873 ipfix = VppCFLOW(
874 test=self, intf=self.intf1, layer="l4", direction=self.direction
875 )
Ole Troan5c749732017-03-13 13:39:52 +0100876 ipfix.add_vpp_config()
877
878 ipfix_decoder = IPFIXDecoder()
879 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200880 templates = ipfix.verify_templates(ipfix_decoder, count=2)
Ole Troan5c749732017-03-13 13:39:52 +0100881
882 self.create_stream(packets=1)
883 capture = self.send_packets()
884
885 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400886 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200887 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200888 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000889 ipfix_decoder,
890 capture,
891 cflow,
892 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 )
Ole Troan5c749732017-03-13 13:39:52 +0100894
Ole Troan5c749732017-03-13 13:39:52 +0100895 self.collector.get_capture(3)
896
897 ipfix.remove_vpp_config()
898 self.logger.info("FFP_TEST_FINISH_0003")
899
Pavel Kotucek89111d02017-06-12 08:26:13 +0200900 def test_templatesIp4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200901 """verify templates on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100902 self.logger.info("FFP_TEST_START_0000")
903
904 self.pg_enable_capture(self.pg_interfaces)
905
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000906 ipfix = VppCFLOW(
907 test=self, intf=self.intf1, datapath="ip4", direction=self.direction
908 )
Ole Troan5c749732017-03-13 13:39:52 +0100909 ipfix.add_vpp_config()
910
911 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400912 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +0100913 ipfix.verify_templates(timeout=3, count=1)
914 self.collector.get_capture(1)
915
916 ipfix.remove_vpp_config()
917
918 self.logger.info("FFP_TEST_FINISH_0000")
919
Pavel Kotucek89111d02017-06-12 08:26:13 +0200920 def test_L2onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200921 """L2 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +0100922 self.logger.info("FFP_TEST_START_0001")
923 self.pg_enable_capture(self.pg_interfaces)
924 self.pkts = []
925
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000926 ipfix = VppCFLOW(
927 test=self,
928 intf=self.intf2,
929 layer="l2",
930 datapath="ip4",
931 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200932 )
Ole Troan5c749732017-03-13 13:39:52 +0100933 ipfix.add_vpp_config()
934
935 ipfix_decoder = IPFIXDecoder()
936 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +0200937 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +0100938
939 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
940 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
941
942 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -0400943 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +0200944 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200945 self.verify_cflow_data_detail(
946 ipfix_decoder,
947 capture,
948 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +0000949 {2: "packets", 256: 8, 61: (self.direction == "tx")},
950 )
951
952 # expected two templates and one cflow packet
953 self.collector.get_capture(2)
954
955 ipfix.remove_vpp_config()
956 self.logger.info("FFP_TEST_FINISH_0001")
957
958 def test_L3onIP4(self):
959 """L3 data on IP4 datapath"""
960 self.logger.info("FFP_TEST_START_0002")
961 self.pg_enable_capture(self.pg_interfaces)
962 self.pkts = []
963
964 ipfix = VppCFLOW(
965 test=self,
966 intf=self.intf2,
967 layer="l3",
968 datapath="ip4",
969 direction=self.direction,
970 )
971 ipfix.add_vpp_config()
972
973 ipfix_decoder = IPFIXDecoder()
974 # template packet should arrive immediately
975 templates = ipfix.verify_templates(ipfix_decoder, count=1)
976
977 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
978 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
979
980 # make sure the one packet we expect actually showed up
981 self.vapi.ipfix_flush()
982 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
983 self.verify_cflow_data_detail(
984 ipfix_decoder,
985 capture,
986 cflow,
987 {
988 1: "octets",
989 2: "packets",
990 8: "src_ip",
991 12: "dst_ip",
992 61: (self.direction == "tx"),
993 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200994 )
Ole Troan5c749732017-03-13 13:39:52 +0100995
996 # expected two templates and one cflow packet
997 self.collector.get_capture(2)
998
999 ipfix.remove_vpp_config()
1000 self.logger.info("FFP_TEST_FINISH_0002")
1001
Pavel Kotucek89111d02017-06-12 08:26:13 +02001002 def test_L4onIP4(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001003 """L4 data on IP4 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001004 self.logger.info("FFP_TEST_START_0003")
1005 self.pg_enable_capture(self.pg_interfaces)
1006 self.pkts = []
1007
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001008 ipfix = VppCFLOW(
1009 test=self,
1010 intf=self.intf2,
1011 layer="l4",
1012 datapath="ip4",
1013 direction=self.direction,
1014 )
Ole Troan5c749732017-03-13 13:39:52 +01001015 ipfix.add_vpp_config()
1016
1017 ipfix_decoder = IPFIXDecoder()
1018 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001019 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001020
1021 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=1)
1022 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1023
1024 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001025 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001026 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 self.verify_cflow_data_detail(
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001028 ipfix_decoder,
1029 capture,
1030 cflow,
1031 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001032 )
Ole Troan5c749732017-03-13 13:39:52 +01001033
1034 # expected two templates and one cflow packet
1035 self.collector.get_capture(2)
1036
1037 ipfix.remove_vpp_config()
1038 self.logger.info("FFP_TEST_FINISH_0003")
1039
Pavel Kotucek89111d02017-06-12 08:26:13 +02001040 def test_templatesIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001041 """verify templates on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001042 self.logger.info("FFP_TEST_START_0000")
1043 self.pg_enable_capture(self.pg_interfaces)
1044
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001045 ipfix = VppCFLOW(
1046 test=self, intf=self.intf1, datapath="ip6", direction=self.direction
1047 )
Ole Troan5c749732017-03-13 13:39:52 +01001048 ipfix.add_vpp_config()
1049
1050 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001051 ipfix.verify_templates(count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001052 self.collector.get_capture(1)
1053
1054 ipfix.remove_vpp_config()
1055
1056 self.logger.info("FFP_TEST_FINISH_0000")
1057
Pavel Kotucek89111d02017-06-12 08:26:13 +02001058 def test_L2onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001059 """L2 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001060 self.logger.info("FFP_TEST_START_0001")
1061 self.pg_enable_capture(self.pg_interfaces)
1062 self.pkts = []
1063
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001064 ipfix = VppCFLOW(
1065 test=self,
1066 intf=self.intf3,
1067 layer="l2",
1068 datapath="ip6",
1069 direction=self.direction,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001070 )
Ole Troan5c749732017-03-13 13:39:52 +01001071 ipfix.add_vpp_config()
1072
1073 ipfix_decoder = IPFIXDecoder()
1074 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001075 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001076
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001077 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001078 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1079
1080 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001081 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001082 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001083 self.verify_cflow_data_detail(
1084 ipfix_decoder,
1085 capture,
1086 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001087 {2: "packets", 256: 56710, 61: (self.direction == "tx")},
1088 ip_ver="v6",
1089 )
1090
1091 # expected two templates and one cflow packet
1092 self.collector.get_capture(2)
1093
1094 ipfix.remove_vpp_config()
1095 self.logger.info("FFP_TEST_FINISH_0001")
1096
1097 def test_L3onIP6(self):
1098 """L3 data on IP6 datapath"""
1099 self.logger.info("FFP_TEST_START_0002")
1100 self.pg_enable_capture(self.pg_interfaces)
1101 self.pkts = []
1102
1103 ipfix = VppCFLOW(
1104 test=self,
1105 intf=self.intf3,
1106 layer="l3",
1107 datapath="ip6",
1108 direction=self.direction,
1109 )
1110 ipfix.add_vpp_config()
1111
1112 ipfix_decoder = IPFIXDecoder()
1113 # template packet should arrive immediately
1114 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1115
1116 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
1117 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1118
1119 # make sure the one packet we expect actually showed up
1120 self.vapi.ipfix_flush()
1121 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1122 self.verify_cflow_data_detail(
1123 ipfix_decoder,
1124 capture,
1125 cflow,
1126 {2: "packets", 27: "src_ip", 28: "dst_ip", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001127 ip_ver="v6",
1128 )
Ole Troan5c749732017-03-13 13:39:52 +01001129
1130 # expected two templates and one cflow packet
1131 self.collector.get_capture(2)
1132
1133 ipfix.remove_vpp_config()
1134 self.logger.info("FFP_TEST_FINISH_0002")
1135
Pavel Kotucek89111d02017-06-12 08:26:13 +02001136 def test_L4onIP6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001137 """L4 data on IP6 datapath"""
Ole Troan5c749732017-03-13 13:39:52 +01001138 self.logger.info("FFP_TEST_START_0003")
1139 self.pg_enable_capture(self.pg_interfaces)
1140 self.pkts = []
1141
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001142 ipfix = VppCFLOW(
1143 test=self,
1144 intf=self.intf3,
1145 layer="l4",
1146 datapath="ip6",
1147 direction=self.direction,
1148 )
Ole Troan5c749732017-03-13 13:39:52 +01001149 ipfix.add_vpp_config()
1150
1151 ipfix_decoder = IPFIXDecoder()
1152 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001153 templates = ipfix.verify_templates(ipfix_decoder, count=1)
Ole Troan5c749732017-03-13 13:39:52 +01001154
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001155 self.create_stream(src_if=self.pg5, dst_if=self.pg6, packets=1, ip_ver="IPv6")
Ole Troan5c749732017-03-13 13:39:52 +01001156 capture = self.send_packets(src_if=self.pg5, dst_if=self.pg6)
1157
1158 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001159 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001160 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001161 self.verify_cflow_data_detail(
1162 ipfix_decoder,
1163 capture,
1164 cflow,
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001165 {2: "packets", 7: "sport", 11: "dport", 61: (self.direction == "tx")},
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001166 ip_ver="v6",
1167 )
Ole Troan5c749732017-03-13 13:39:52 +01001168
1169 # expected two templates and one cflow packet
1170 self.collector.get_capture(2)
1171
1172 ipfix.remove_vpp_config()
1173 self.logger.info("FFP_TEST_FINISH_0003")
1174
Ole Troan5c749732017-03-13 13:39:52 +01001175 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001176 """no timers, one CFLOW packet, 9 Flows inside"""
Ole Troan5c749732017-03-13 13:39:52 +01001177 self.logger.info("FFP_TEST_START_0001")
1178 self.pg_enable_capture(self.pg_interfaces)
1179 self.pkts = []
1180
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001181 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction)
Ole Troan5c749732017-03-13 13:39:52 +01001182 ipfix.add_vpp_config()
1183
1184 ipfix_decoder = IPFIXDecoder()
1185 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001186 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001187
1188 self.create_stream(packets=9)
1189 capture = self.send_packets()
1190
1191 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001192 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001193 cflow = self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001194 self.verify_cflow_data_notimer(ipfix_decoder, capture, [cflow])
Ole Troan5c749732017-03-13 13:39:52 +01001195 self.collector.get_capture(4)
1196
1197 ipfix.remove_vpp_config()
1198 self.logger.info("FFP_TEST_FINISH_0001")
1199
1200 def test_0002(self):
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001201 """no timers, two CFLOW packets (mtu=260), 3 Flows in each"""
Ole Troan5c749732017-03-13 13:39:52 +01001202 self.logger.info("FFP_TEST_START_0002")
1203 self.pg_enable_capture(self.pg_interfaces)
1204 self.pkts = []
1205
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001206 ipfix = VppCFLOW(test=self, intf=self.intf1, direction=self.direction, mtu=260)
Ole Troan5c749732017-03-13 13:39:52 +01001207 ipfix.add_vpp_config()
1208
1209 ipfix_decoder = IPFIXDecoder()
1210 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001211 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001212 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001213
1214 self.create_stream(packets=6)
1215 capture = self.send_packets()
1216
1217 # make sure the one packet we expect actually showed up
1218 cflows = []
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001219 self.vapi.ipfix_flush()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001220 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
1221 cflows.append(self.wait_for_cflow_packet(self.collector, templates[1]))
Ole Troan5c749732017-03-13 13:39:52 +01001222 self.verify_cflow_data_notimer(ipfix_decoder, capture, cflows)
1223 self.collector.get_capture(5)
1224
1225 ipfix.remove_vpp_config()
1226 self.logger.info("FFP_TEST_FINISH_0002")
1227
1228
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001229class DatapathTx(MethodHolder, DatapathTestsHolder):
1230 """Collect info on Ethernet, IP4 and IP6 datapath (TX) (no timers)"""
1231
1232 intf1 = "pg2"
1233 intf2 = "pg4"
1234 intf3 = "pg6"
1235 direction = "tx"
1236
Alexander Chernavin64d64632023-11-07 11:25:21 +00001237 def test_rewritten_traffic(self):
1238 """Rewritten traffic (from subif to ipfix if)"""
1239 self.pg_enable_capture(self.pg_interfaces)
1240 self.pkts = []
1241
1242 # prepare a sub-interface
1243 subif = VppDot1ADSubint(self, self.pg7, 0, 300, 400)
1244 subif.admin_up()
1245 subif.config_ip4()
1246
1247 # enable ip4 datapath for an interface
1248 ipfix = VppCFLOW(
1249 test=self,
1250 intf="pg8",
1251 datapath="ip4",
1252 layer="l2 l3 l4",
1253 direction=self.direction,
1254 )
1255 ipfix.add_vpp_config()
1256
1257 # template packet should arrive immediately
1258 ipfix_decoder = IPFIXDecoder()
1259 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1260
1261 # forward some traffic through the ipfix interface
1262 route = VppIpRoute(
1263 self,
1264 "9.0.0.0",
1265 24,
1266 [VppRoutePath(self.pg8.remote_ip4, self.pg8.sw_if_index)],
1267 )
1268 route.add_vpp_config()
1269
1270 # prepare an IPv4 packet (subif => ipfix interface)
1271 pkt = (
1272 Ether(src=subif.remote_mac, dst=self.pg7.local_mac)
1273 / IP(src=subif.remote_ip4, dst="9.0.0.1")
1274 / UDP(sport=1234, dport=4321)
1275 / Raw(b"\xa5" * 123)
1276 )
1277 self.pkts = [
1278 subif.add_dot1ad_layer(pkt, 300, 400),
1279 ]
1280
1281 # send the packet
1282 capture = self.send_packets(self.pg7, self.pg8)
1283
1284 # wait for a flow and verify it
1285 self.vapi.ipfix_flush()
1286 cflow = self.wait_for_cflow_packet(self.collector, templates[0])
1287 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1288 self.verify_cflow_data_detail(
1289 ipfix_decoder,
1290 capture,
1291 cflow,
1292 {
1293 IPFIX_SRC_IP4_ADDR_ID: "src_ip",
1294 IPFIX_DST_IP4_ADDR_ID: "dst_ip",
1295 IPFIX_SRC_TRANS_PORT_ID: "sport",
1296 IPFIX_DST_TRANS_PORT_ID: "dport",
1297 IPFIX_FLOW_DIRECTION_ID: (self.direction == "tx"),
1298 },
1299 )
1300
1301 self.collector.get_capture(2)
1302
1303 # cleanup
1304 route.remove_vpp_config()
1305 subif.remove_vpp_config()
1306 ipfix.remove_vpp_config()
1307
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001308
Alexander Chernavin6f5ddf32022-05-06 11:35:59 +00001309class DatapathRx(MethodHolder, DatapathTestsHolder):
1310 """Collect info on Ethernet, IP4 and IP6 datapath (RX) (no timers)"""
1311
1312 intf1 = "pg1"
1313 intf2 = "pg3"
1314 intf3 = "pg5"
1315 direction = "rx"
1316
1317
Klement Sekerab23ffd72021-05-31 16:08:53 +02001318@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001319class DisableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001320 """Disable IPFIX"""
1321
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001322 @classmethod
1323 def setUpClass(cls):
1324 super(DisableIPFIX, cls).setUpClass()
1325
1326 @classmethod
1327 def tearDownClass(cls):
1328 super(DisableIPFIX, cls).tearDownClass()
1329
Ole Troan5c749732017-03-13 13:39:52 +01001330 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001331 """disable IPFIX after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001332 self.logger.info("FFP_TEST_START_0001")
1333 self.pg_enable_capture(self.pg_interfaces)
1334 self.pkts = []
1335
Pavel Kotucek89111d02017-06-12 08:26:13 +02001336 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001337 ipfix.add_vpp_config()
1338
1339 ipfix_decoder = IPFIXDecoder()
1340 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001341 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001342
1343 self.create_stream()
1344 self.send_packets()
1345
1346 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001347 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001348 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001349 self.collector.get_capture(4)
1350
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001351 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001352 ipfix.disable_exporter()
1353 self.pg_enable_capture([self.collector])
1354
1355 self.send_packets()
1356
1357 # make sure no one packet arrived in 1 minute
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001358 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001359 self.sleep(1, "wait before verifying no packets sent")
1360 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001361
1362 ipfix.remove_vpp_config()
1363 self.logger.info("FFP_TEST_FINISH_0001")
1364
1365
Klement Sekerab23ffd72021-05-31 16:08:53 +02001366@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001367class ReenableIPFIX(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001368 """Re-enable IPFIX"""
1369
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001370 @classmethod
1371 def setUpClass(cls):
1372 super(ReenableIPFIX, cls).setUpClass()
1373
1374 @classmethod
1375 def tearDownClass(cls):
1376 super(ReenableIPFIX, cls).tearDownClass()
1377
Pavel Kotucek89111d02017-06-12 08:26:13 +02001378 def test_0011(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001379 """disable IPFIX after first packets and re-enable after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001380 self.logger.info("FFP_TEST_START_0001")
1381 self.pg_enable_capture(self.pg_interfaces)
1382 self.pkts = []
1383
Pavel Kotucek89111d02017-06-12 08:26:13 +02001384 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001385 ipfix.add_vpp_config()
1386
1387 ipfix_decoder = IPFIXDecoder()
1388 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001389 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001390
Pavel Kotucek89111d02017-06-12 08:26:13 +02001391 self.create_stream(packets=5)
Ole Troan5c749732017-03-13 13:39:52 +01001392 self.send_packets()
1393
1394 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001395 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001396 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001397 self.collector.get_capture(4)
1398
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001399 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001400 ipfix.disable_exporter()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001401 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001402 self.pg_enable_capture([self.collector])
1403
1404 self.send_packets()
1405
1406 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001407 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001408 self.sleep(1, "wait before verifying no packets sent")
1409 self.collector.assert_nothing_captured()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001410 self.pg2.get_capture(5)
Ole Troan5c749732017-03-13 13:39:52 +01001411
1412 # enable IPFIX
1413 ipfix.enable_exporter()
Ole Troan5c749732017-03-13 13:39:52 +01001414
Pavel Kotucek89111d02017-06-12 08:26:13 +02001415 capture = self.collector.get_capture(4)
1416 nr_templates = 0
1417 nr_data = 0
1418 for p in capture:
1419 self.assertTrue(p.haslayer(IPFIX))
1420 if p.haslayer(Template):
1421 nr_templates += 1
1422 self.assertTrue(nr_templates, 3)
1423 for p in capture:
1424 self.assertTrue(p.haslayer(IPFIX))
1425 if p.haslayer(Data):
1426 nr_data += 1
1427 self.assertTrue(nr_templates, 1)
Ole Troan5c749732017-03-13 13:39:52 +01001428
1429 ipfix.remove_vpp_config()
1430 self.logger.info("FFP_TEST_FINISH_0001")
1431
1432
Klement Sekerab23ffd72021-05-31 16:08:53 +02001433@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001434class DisableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001435 """Disable Flowprobe feature"""
1436
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001437 @classmethod
1438 def setUpClass(cls):
1439 super(DisableFP, cls).setUpClass()
1440
1441 @classmethod
1442 def tearDownClass(cls):
1443 super(DisableFP, cls).tearDownClass()
1444
Ole Troan5c749732017-03-13 13:39:52 +01001445 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 """disable flowprobe feature after first packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001447 self.logger.info("FFP_TEST_START_0001")
1448 self.pg_enable_capture(self.pg_interfaces)
1449 self.pkts = []
Pavel Kotucek89111d02017-06-12 08:26:13 +02001450 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001451 ipfix.add_vpp_config()
1452
1453 ipfix_decoder = IPFIXDecoder()
1454 # template packet should arrive immediately
Pavel Kotucek89111d02017-06-12 08:26:13 +02001455 templates = ipfix.verify_templates(ipfix_decoder)
Ole Troan5c749732017-03-13 13:39:52 +01001456
1457 self.create_stream()
1458 self.send_packets()
1459
1460 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001461 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001462 self.wait_for_cflow_packet(self.collector, templates[1])
Ole Troan5c749732017-03-13 13:39:52 +01001463 self.collector.get_capture(4)
1464
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001465 # disable IPFIX
Ole Troan5c749732017-03-13 13:39:52 +01001466 ipfix.disable_flowprobe_feature()
1467 self.pg_enable_capture([self.collector])
1468
1469 self.send_packets()
1470
1471 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001472 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001473 self.sleep(1, "wait before verifying no packets sent")
1474 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001475
Dave Wallace8800f732023-08-31 00:47:44 -04001476 # enable FPP feature so the remove_vpp_config() doesn't fail
1477 # due to missing feature on interface.
1478 ipfix.enable_flowprobe_feature()
1479
Ole Troan5c749732017-03-13 13:39:52 +01001480 ipfix.remove_vpp_config()
1481 self.logger.info("FFP_TEST_FINISH_0001")
1482
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001483 def test_no_leftover_flows_after_disabling(self):
1484 """disable flowprobe feature and expect no leftover flows"""
1485 self.pg_enable_capture(self.pg_interfaces)
1486 self.pkts = []
1487
1488 # enable ip4 datapath for an interface
1489 # set active and passive timers
1490 ipfix = VppCFLOW(
1491 test=self,
1492 active=3,
1493 passive=4,
1494 intf="pg3",
1495 layer="l3",
1496 datapath="ip4",
1497 direction="rx",
1498 mtu=100,
1499 )
1500 ipfix.add_vpp_config()
1501
1502 # template packet should arrive immediately
1503 ipfix.verify_templates(count=1)
1504
1505 # send some ip4 packets
1506 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1507 self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1508
1509 # disable feature for the interface
1510 # currently stored ip4 flows should be removed
1511 ipfix.disable_flowprobe_feature()
1512
1513 # no leftover ip4 flows are expected
1514 self.pg_enable_capture([self.collector])
1515 self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
1516 self.collector.assert_nothing_captured()
1517
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001518 # re-enable feature for the interface
1519 ipfix.enable_flowprobe_feature()
1520
1521 # template packet should arrive immediately
1522 ipfix_decoder = IPFIXDecoder()
1523 self.vapi.ipfix_flush()
1524 templates = ipfix.verify_templates(ipfix_decoder, count=1)
1525
1526 # send some ip4 packets
1527 self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
1528 capture = self.send_packets(src_if=self.pg3, dst_if=self.pg4)
1529
1530 # verify meta info - packet/octet delta
1531 self.vapi.ipfix_flush()
1532 cflow = self.wait_for_cflow_packet(self.collector, templates[0], timeout=8)
1533 self.verify_cflow_data(ipfix_decoder, capture, cflow)
1534
1535 self.collector.get_capture(2)
1536
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001537 # cleanup
Alexander Chernavindab1dfe2023-10-26 11:48:06 +00001538 ipfix.remove_vpp_config()
Alexander Chernavinf68afe82023-10-03 12:45:51 +00001539
Ole Troan5c749732017-03-13 13:39:52 +01001540
Klement Sekerab23ffd72021-05-31 16:08:53 +02001541@unittest.skipUnless(config.extended, "part of extended tests")
Pavel Kotucek89111d02017-06-12 08:26:13 +02001542class ReenableFP(MethodHolder):
Ole Troan5c749732017-03-13 13:39:52 +01001543 """Re-enable Flowprobe feature"""
1544
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001545 @classmethod
1546 def setUpClass(cls):
1547 super(ReenableFP, cls).setUpClass()
1548
1549 @classmethod
1550 def tearDownClass(cls):
1551 super(ReenableFP, cls).tearDownClass()
1552
Ole Troan5c749732017-03-13 13:39:52 +01001553 def test_0001(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001554 """disable flowprobe feature after first packets and re-enable
1555 after few packets"""
Ole Troan5c749732017-03-13 13:39:52 +01001556 self.logger.info("FFP_TEST_START_0001")
1557 self.pg_enable_capture(self.pg_interfaces)
1558 self.pkts = []
1559
Pavel Kotucek89111d02017-06-12 08:26:13 +02001560 ipfix = VppCFLOW(test=self)
Ole Troan5c749732017-03-13 13:39:52 +01001561 ipfix.add_vpp_config()
1562
1563 ipfix_decoder = IPFIXDecoder()
1564 # template packet should arrive immediately
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001565 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001566 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1567
1568 self.create_stream()
1569 self.send_packets()
1570
1571 # make sure the one packet we expect actually showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001572 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001573 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001574 self.collector.get_capture(4)
1575
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001576 # disable FPP feature
Ole Troan5c749732017-03-13 13:39:52 +01001577 ipfix.disable_flowprobe_feature()
1578 self.pg_enable_capture([self.collector])
1579
1580 self.send_packets()
1581
1582 # make sure no one packet arrived in active timer span
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001583 self.vapi.ipfix_flush()
Klement Sekerac4794572021-09-08 15:15:59 +02001584 self.sleep(5, "wait before verifying no packets sent")
1585 self.collector.assert_nothing_captured()
Ole Troan5c749732017-03-13 13:39:52 +01001586
1587 # enable FPP feature
1588 ipfix.enable_flowprobe_feature()
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001589 self.vapi.ipfix_flush()
Ole Troan5c749732017-03-13 13:39:52 +01001590 templates = ipfix.verify_templates(ipfix_decoder, timeout=3)
1591
1592 self.send_packets()
1593
1594 # make sure the next packets (templates and data) we expect actually
1595 # showed up
Paul Vinciguerra21b83e92019-06-24 09:55:46 -04001596 self.vapi.ipfix_flush()
Pavel Kotucek89111d02017-06-12 08:26:13 +02001597 self.wait_for_cflow_packet(self.collector, templates[1], 5)
Ole Troan5c749732017-03-13 13:39:52 +01001598 self.collector.get_capture(4)
1599
1600 ipfix.remove_vpp_config()
1601 self.logger.info("FFP_TEST_FINISH_0001")
1602
1603
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001604if __name__ == "__main__":
Ole Troan5c749732017-03-13 13:39:52 +01001605 unittest.main(testRunner=VppTestRunner)