blob: ebc815cb701ce978c08d6568af74397cee4a5744 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Klement Sekerad3ba5152017-02-14 03:09:17 +01002""" BFD tests """
Klement Sekera0e3c0de2016-09-29 14:43:44 +02003
Klement Sekeraa57a9702017-02-02 06:58:07 +01004from __future__ import division
Paul Vinciguerra00671cf2018-11-25 12:47:04 -08005
Klement Sekerab17dd962017-01-09 07:43:48 +01006import binascii
Klement Sekeracdaf0d82022-02-14 20:20:22 +00007from collections import namedtuple
Paul Vinciguerra00671cf2018-11-25 12:47:04 -08008import hashlib
Paul Vinciguerra2f156312020-05-02 22:34:40 -04009import ipaddress
Paul Vinciguerra090096b2020-12-03 00:42:46 -050010import reprlib
Klement Sekera0e3c0de2016-09-29 14:43:44 +020011import time
Paul Vinciguerra00671cf2018-11-25 12:47:04 -080012import unittest
Klement Sekera239790f2017-02-16 10:53:53 +010013from random import randint, shuffle, getrandbits
Dave Wallace8800f732023-08-31 00:47:44 -040014from socket import AF_INET, AF_INET6
Abdel Baig17a91812024-09-03 11:52:20 -040015from parameterized import parameterized, parameterized_class
Paul Vinciguerra00671cf2018-11-25 12:47:04 -080016
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070017import scapy.compat
Klement Sekerad3ba5152017-02-14 03:09:17 +010018from scapy.layers.inet import UDP, IP
19from scapy.layers.inet6 import IPv6
Neale Ranns52cd4962019-06-05 10:28:17 +000020from scapy.layers.l2 import Ether, GRE
Paul Vinciguerra00671cf2018-11-25 12:47:04 -080021from scapy.packet import Raw
22
Klement Sekerab23ffd72021-05-31 16:08:53 +020023from config import config
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020024from bfd import (
25 VppBFDAuthKey,
26 BFD,
27 BFDAuthType,
28 VppBFDUDPSession,
29 BFDDiagCode,
30 BFDState,
31 BFD_vpp_echo,
Abdel Baig17a91812024-09-03 11:52:20 -040032 BFD_UDP_SH_PORT,
33 BFD_UDP_MH_PORT,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020034)
Dave Wallace8800f732023-08-31 00:47:44 -040035from framework import VppTestCase
36from asfframework import (
37 tag_fixme_vpp_workers,
38 tag_fixme_debian11,
39 tag_run_solo,
40 VppTestRunner,
41)
Klement Sekera0e3c0de2016-09-29 14:43:44 +020042from util import ppp
Neale Rannsc0a93142018-09-05 15:42:26 -070043from vpp_ip import DpoProto
44from vpp_ip_route import VppIpRoute, VppRoutePath
Paul Vinciguerra00671cf2018-11-25 12:47:04 -080045from vpp_lo_interface import VppLoInterface
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020046from vpp_papi_provider import UnexpectedApiReturnValueError, CliFailedCommandError
Paul Vinciguerra00671cf2018-11-25 12:47:04 -080047from vpp_pg_interface import CaptureTimeoutError, is_ipv6_misc
Neale Ranns52cd4962019-06-05 10:28:17 +000048from vpp_gre_interface import VppGreInterface
Klement Sekera0e3c0de2016-09-29 14:43:44 +020049
Klement Sekerad3ba5152017-02-14 03:09:17 +010050USEC_IN_SEC = 1000000
Abdel Baig17a91812024-09-03 11:52:20 -040051BFD_STATS_V4_SH_PATH = "/bfd/udp4/sessions"
52BFD_STATS_V6_SH_PATH = "/bfd/udp6/sessions"
53BFD_STATS_V4_MH_PATH = "/bfd/udp4/sessions_mh"
54BFD_STATS_V6_MH_PATH = "/bfd/udp6/sessions_mh"
55BFD_IPV4_REMOTE_ADDR = "2.2.2.2"
56BFD_IPV6_REMOTE_ADDR = "2::2"
57BFD_IPV4_REMOTE_ADDR2 = "3.3.3.3"
58BFD_IPV6_REMOTE_ADDR2 = "3::3"
59
60
61def set_ipv4_pfx_route_info(cls, pg_if, dst_ip, set_src):
62 try:
63 if cls.multihop:
64 paths = []
65 # Get list of all the next hops
66 for nh_host in pg_if.remote_hosts:
67 nh_host_ip = nh_host.ip4
68 paths.append(VppRoutePath(nh_host_ip, pg_if.sw_if_index))
69 cls.dst_ip_net = dst_ip
70 # Create a route pointing to list of next hops
71 if paths:
72 rip = VppIpRoute(cls, cls.dst_ip_net, 32, paths)
73 rip.add_vpp_config()
74 cls.logger.info("Route via %s on %s created" % (paths, pg_if.name))
75 if set_src:
76 cls.src_ip_net = cls.loopback0.local_ip4
77 else:
78 cls.dst_ip_net = pg_if.remote_ip4
79 if set_src:
80 cls.src_ip_net = pg_if.local_ip4
81 except BaseException:
82 cls.vapi.want_bfd_events(enable_disable=0)
83 raise
84
85
86def set_ipv6_pfx_route_info(cls, pg_if, dst_ip, set_src):
87 try:
88 if cls.multihop:
89 paths = []
90 # Get list of all the next hops
91 for nh_host in pg_if.remote_hosts:
92 nh_host_ip = nh_host.ip6
93 paths.append(VppRoutePath(nh_host_ip, pg_if.sw_if_index))
94 cls.dst_ip6_net = dst_ip
95 # Create a route pointing to list of next hops
96 if paths:
97 rip = VppIpRoute(cls, cls.dst_ip6_net, 128, paths)
98 rip.add_vpp_config()
99 cls.logger.info("Route via %s on %s created" % (paths, pg_if.name))
100 if set_src:
101 cls.src_ip6_net = cls.loopback0.local_ip6
102 else:
103 cls.dst_ip6_net = cls.pg0.remote_ip6
104 if set_src:
105 cls.src_ip6_net = cls.pg0.local_ip6
106 except BaseException:
107 cls.vapi.want_bfd_events(enable_disable=0)
108 raise
Klement Sekera3e0a3562016-12-19 09:05:21 +0100109
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200110
Klement Sekerab17dd962017-01-09 07:43:48 +0100111class AuthKeyFactory(object):
112 """Factory class for creating auth keys with unique conf key ID"""
113
114 def __init__(self):
115 self._conf_key_ids = {}
116
117 def create_random_key(self, test, auth_type=BFDAuthType.keyed_sha1):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200118 """create a random key with unique conf key id"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100119 conf_key_id = randint(0, 0xFFFFFFFF)
120 while conf_key_id in self._conf_key_ids:
121 conf_key_id = randint(0, 0xFFFFFFFF)
122 self._conf_key_ids[conf_key_id] = 1
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700123 key = scapy.compat.raw(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200124 bytearray([randint(0, 255) for _ in range(randint(1, 20))])
125 )
126 return VppBFDAuthKey(
127 test=test, auth_type=auth_type, conf_key_id=conf_key_id, key=key
128 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100129
130
Abdel Baig17a91812024-09-03 11:52:20 -0400131@parameterized_class(
132 [
133 {"multihop": False},
134 {"multihop": True},
135 ]
136)
Klement Sekerae4504c62016-12-08 10:16:41 +0100137class BFDAPITestCase(VppTestCase):
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200138
Klement Sekerad3ba5152017-02-14 03:09:17 +0100139 pg0 = None
140 pg1 = None
Abdel Baig17a91812024-09-03 11:52:20 -0400141 interface0 = None
142 interface1 = None
143 src_ip_net = ""
144 dst_ip_net = ""
145 src_ip_net2 = ""
146 dst_ip_net2 = ""
147 src_ip6_net = ""
148 dst_ip6_net = ""
149 src_ip6_net2 = ""
150 dst_ip6_net2 = ""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100151
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200152 @classmethod
153 def setUpClass(cls):
Klement Sekerae4504c62016-12-08 10:16:41 +0100154 super(BFDAPITestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -0400155 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
156 cls.__doc__ = (
157 f"""""Bidirectional Forwarding Detection (BFD) - API, {hoptype_str}"""
158 )
Damjan Marion07a38572018-01-21 06:44:18 -0800159 cls.vapi.cli("set log class bfd level debug")
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200160 try:
Klement Sekera10db26f2017-01-11 08:16:53 +0100161 cls.create_pg_interfaces(range(2))
Abdel Baig17a91812024-09-03 11:52:20 -0400162 cls.create_loopback_interfaces(2)
163 cls.loopback0 = cls.lo_interfaces[0]
164 cls.loopback0.config_ip4()
165 cls.loopback0.admin_up()
166 cls.loopback1 = cls.lo_interfaces[1]
167 cls.loopback1.config_ip4()
168 cls.loopback1.admin_up()
Klement Sekera10db26f2017-01-11 08:16:53 +0100169 for i in cls.pg_interfaces:
170 i.config_ip4()
Klement Sekerab17dd962017-01-09 07:43:48 +0100171 i.config_ip6()
Klement Sekera10db26f2017-01-11 08:16:53 +0100172 i.resolve_arp()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200173
174 except Exception:
Klement Sekerae4504c62016-12-08 10:16:41 +0100175 super(BFDAPITestCase, cls).tearDownClass()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200176 raise
177
Paul Vinciguerra8d991d92019-01-25 14:05:48 -0800178 @classmethod
179 def tearDownClass(cls):
180 super(BFDAPITestCase, cls).tearDownClass()
181
Klement Sekerab17dd962017-01-09 07:43:48 +0100182 def setUp(self):
183 super(BFDAPITestCase, self).setUp()
184 self.factory = AuthKeyFactory()
185
Abdel Baig17a91812024-09-03 11:52:20 -0400186 if self.multihop:
187 self.interface0 = None
188 self.interface1 = None
189 self.src_ip_net = self.loopback0.local_ip4
190 self.src_ip6_net = self.loopback0.local_ip6
191 self.dst_ip_net = BFD_IPV4_REMOTE_ADDR
192 self.dst_ip6_net = BFD_IPV6_REMOTE_ADDR
193 self.src_ip_net2 = self.loopback1.local_ip4
194 self.src_ip6_net2 = self.loopback1.local_ip6
195 self.dst_ip_net2 = BFD_IPV4_REMOTE_ADDR2
196 self.dst_ip6_net2 = BFD_IPV6_REMOTE_ADDR2
197 else:
198 self.interface0 = self.pg0
199 self.interface1 = self.pg1
200 self.src_ip_net = self.pg0.local_ip4
201 self.src_ip6_net = self.pg0.local_ip6
202 self.dst_ip_net = self.pg0.remote_ip4
203 self.dst_ip6_net = self.pg0.remote_ip6
204 self.src_ip_net2 = self.pg1.local_ip4
205 self.src_ip6_net2 = self.pg1.local_ip6
206 self.dst_ip_net2 = BFD_IPV4_REMOTE_ADDR2
207 self.dst_ip6_net2 = BFD_IPV6_REMOTE_ADDR2
208
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200209 def test_add_bfd(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200210 """create a BFD session"""
Abdel Baig17a91812024-09-03 11:52:20 -0400211 session = VppBFDUDPSession(
212 self,
213 self.interface0,
214 self.dst_ip_net,
215 local_addr=self.src_ip_net,
216 multihop=self.multihop,
217 )
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200218 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100219 self.logger.debug("Session state is %s", session.state)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200220 session.remove_vpp_config()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200221 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100222 self.logger.debug("Session state is %s", session.state)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200223 session.remove_vpp_config()
224
225 def test_double_add(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200226 """create the same BFD session twice (negative case)"""
Abdel Baig17a91812024-09-03 11:52:20 -0400227 session = VppBFDUDPSession(
228 self,
229 self.interface0,
230 self.dst_ip_net,
231 local_addr=self.src_ip_net,
232 multihop=self.multihop,
233 )
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200234 session.add_vpp_config()
Klement Sekerae0545ef2017-01-25 08:00:40 +0100235
Klement Sekera7d6afb32018-11-08 11:52:04 +0100236 with self.vapi.assert_negative_api_retval():
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200237 session.add_vpp_config()
Klement Sekerae0545ef2017-01-25 08:00:40 +0100238
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200239 session.remove_vpp_config()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200240
Klement Sekerab17dd962017-01-09 07:43:48 +0100241 def test_add_bfd6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200242 """create IPv6 BFD session"""
Abdel Baig17a91812024-09-03 11:52:20 -0400243 session = VppBFDUDPSession(
244 self,
245 self.interface0,
246 self.dst_ip6_net,
247 local_addr=self.src_ip6_net,
248 af=AF_INET6,
249 multihop=self.multihop,
250 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100251 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100252 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100253 session.remove_vpp_config()
254 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100255 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100256 session.remove_vpp_config()
257
Klement Sekeraa57a9702017-02-02 06:58:07 +0100258 def test_mod_bfd(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200259 """modify BFD session parameters"""
260 session = VppBFDUDPSession(
261 self,
Abdel Baig17a91812024-09-03 11:52:20 -0400262 self.interface0,
263 self.dst_ip_net,
264 local_addr=self.src_ip_net,
265 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200266 desired_min_tx=50000,
267 required_min_rx=10000,
268 detect_mult=1,
269 )
Klement Sekeraa57a9702017-02-02 06:58:07 +0100270 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100271 s = session.get_bfd_udp_session_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200272 self.assert_equal(
273 session.desired_min_tx, s.desired_min_tx, "desired min transmit interval"
274 )
275 self.assert_equal(
276 session.required_min_rx, s.required_min_rx, "required min receive interval"
277 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100278 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 session.modify_parameters(
280 desired_min_tx=session.desired_min_tx * 2,
281 required_min_rx=session.required_min_rx * 2,
282 detect_mult=session.detect_mult * 2,
283 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100284 s = session.get_bfd_udp_session_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200285 self.assert_equal(
286 session.desired_min_tx, s.desired_min_tx, "desired min transmit interval"
287 )
288 self.assert_equal(
289 session.required_min_rx, s.required_min_rx, "required min receive interval"
290 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100291 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
Klement Sekeraa57a9702017-02-02 06:58:07 +0100292
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000293 def test_upd_bfd(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200294 """Create/Modify w/ Update BFD session parameters"""
295 session = VppBFDUDPSession(
296 self,
Abdel Baig17a91812024-09-03 11:52:20 -0400297 self.interface0,
298 self.dst_ip_net,
299 local_addr=self.src_ip_net,
300 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200301 desired_min_tx=50000,
302 required_min_rx=10000,
303 detect_mult=1,
304 )
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000305 session.upd_vpp_config()
306 s = session.get_bfd_udp_session_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200307 self.assert_equal(
308 session.desired_min_tx, s.desired_min_tx, "desired min transmit interval"
309 )
310 self.assert_equal(
311 session.required_min_rx, s.required_min_rx, "required min receive interval"
312 )
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000313
314 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200315 session.upd_vpp_config(
316 desired_min_tx=session.desired_min_tx * 2,
317 required_min_rx=session.required_min_rx * 2,
318 detect_mult=session.detect_mult * 2,
319 )
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000320 s = session.get_bfd_udp_session_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200321 self.assert_equal(
322 session.desired_min_tx, s.desired_min_tx, "desired min transmit interval"
323 )
324 self.assert_equal(
325 session.required_min_rx, s.required_min_rx, "required min receive interval"
326 )
Neale Ranns63f2c7d2022-02-09 13:47:29 +0000327 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
328
Klement Sekerab17dd962017-01-09 07:43:48 +0100329 def test_add_sha1_keys(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200330 """add SHA1 keys"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100331 key_count = 10
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 keys = [self.factory.create_random_key(self) for i in range(0, key_count)]
Klement Sekerab17dd962017-01-09 07:43:48 +0100333 for key in keys:
334 self.assertFalse(key.query_vpp_config())
335 for key in keys:
336 key.add_vpp_config()
337 for key in keys:
338 self.assertTrue(key.query_vpp_config())
339 # remove randomly
snaramre73aff472019-12-02 05:49:28 +0000340 indexes = list(range(key_count))
Klement Sekerad3ba5152017-02-14 03:09:17 +0100341 shuffle(indexes)
Klement Sekerab17dd962017-01-09 07:43:48 +0100342 removed = []
343 for i in indexes:
344 key = keys[i]
345 key.remove_vpp_config()
346 removed.append(i)
347 for j in range(key_count):
348 key = keys[j]
349 if j in removed:
350 self.assertFalse(key.query_vpp_config())
351 else:
352 self.assertTrue(key.query_vpp_config())
353 # should be removed now
354 for key in keys:
355 self.assertFalse(key.query_vpp_config())
356 # add back and remove again
357 for key in keys:
358 key.add_vpp_config()
359 for key in keys:
360 self.assertTrue(key.query_vpp_config())
361 for key in keys:
362 key.remove_vpp_config()
363 for key in keys:
364 self.assertFalse(key.query_vpp_config())
365
366 def test_add_bfd_sha1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200367 """create a BFD session (SHA1)"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100368 key = self.factory.create_random_key(self)
369 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -0400370 session = VppBFDUDPSession(
371 self,
372 self.interface0,
373 self.dst_ip_net,
374 local_addr=self.src_ip_net,
375 multihop=self.multihop,
376 sha1_key=key,
377 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100378 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100379 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100380 session.remove_vpp_config()
381 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100382 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100383 session.remove_vpp_config()
384
385 def test_double_add_sha1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200386 """create the same BFD session twice (negative case) (SHA1)"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100387 key = self.factory.create_random_key(self)
388 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -0400389 session = VppBFDUDPSession(
390 self,
391 self.interface0,
392 self.dst_ip_net,
393 local_addr=self.src_ip_net,
394 multihop=self.multihop,
395 sha1_key=key,
396 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100397 session.add_vpp_config()
398 with self.assertRaises(Exception):
399 session.add_vpp_config()
400
Klement Sekerad3ba5152017-02-14 03:09:17 +0100401 def test_add_auth_nonexistent_key(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200402 """create BFD session using non-existent SHA1 (negative case)"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100403 session = VppBFDUDPSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200404 self,
Abdel Baig17a91812024-09-03 11:52:20 -0400405 self.interface0,
406 self.dst_ip_net,
407 local_addr=self.src_ip_net,
408 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200409 sha1_key=self.factory.create_random_key(self),
410 )
Abdel Baig17a91812024-09-03 11:52:20 -0400411 self.session = VppBFDUDPSession(
412 self,
413 self.interface0,
414 self.dst_ip_net,
415 local_addr=self.src_ip_net,
416 multihop=self.multihop,
417 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100418 with self.assertRaises(Exception):
419 session.add_vpp_config()
420
421 def test_shared_sha1_key(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200422 """single SHA1 key shared by multiple BFD sessions"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100423 key = self.factory.create_random_key(self)
424 key.add_vpp_config()
425 sessions = [
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200426 VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -0400427 self,
428 self.interface0,
429 self.dst_ip_net,
430 local_addr=self.src_ip_net,
431 multihop=self.multihop,
432 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200433 ),
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200434 VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -0400435 self,
436 self.interface0,
437 self.dst_ip6_net,
438 local_addr=self.src_ip6_net,
439 af=AF_INET6,
440 multihop=self.multihop,
441 sha1_key=key,
442 ),
443 VppBFDUDPSession(
444 self,
445 self.interface1,
446 self.dst_ip_net2,
447 local_addr=self.src_ip_net2,
448 multihop=self.multihop,
449 sha1_key=key,
450 ),
451 VppBFDUDPSession(
452 self,
453 self.interface1,
454 self.dst_ip6_net2,
455 local_addr=self.src_ip6_net2,
456 af=AF_INET6,
457 multihop=self.multihop,
458 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200459 ),
460 ]
Klement Sekerab17dd962017-01-09 07:43:48 +0100461 for s in sessions:
462 s.add_vpp_config()
463 removed = 0
464 for s in sessions:
465 e = key.get_bfd_auth_keys_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200466 self.assert_equal(
467 e.use_count, len(sessions) - removed, "Use count for shared key"
468 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100469 s.remove_vpp_config()
470 removed += 1
471 e = key.get_bfd_auth_keys_dump_entry()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200472 self.assert_equal(
473 e.use_count, len(sessions) - removed, "Use count for shared key"
474 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100475
476 def test_activate_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200477 """activate SHA1 authentication"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100478 key = self.factory.create_random_key(self)
479 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -0400480 session = VppBFDUDPSession(
481 self,
482 self.interface0,
483 self.dst_ip_net,
484 local_addr=self.src_ip_net,
485 multihop=self.multihop,
486 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100487 session.add_vpp_config()
488 session.activate_auth(key)
489
490 def test_deactivate_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 """deactivate SHA1 authentication"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100492 key = self.factory.create_random_key(self)
493 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -0400494 session = VppBFDUDPSession(
495 self,
496 self.interface0,
497 self.dst_ip_net,
498 local_addr=self.src_ip_net,
499 multihop=self.multihop,
500 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100501 session.add_vpp_config()
502 session.activate_auth(key)
503 session.deactivate_auth()
504
505 def test_change_key(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200506 """change SHA1 key"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100507 key1 = self.factory.create_random_key(self)
508 key2 = self.factory.create_random_key(self)
509 while key2.conf_key_id == key1.conf_key_id:
510 key2 = self.factory.create_random_key(self)
511 key1.add_vpp_config()
512 key2.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -0400513 session = VppBFDUDPSession(
514 self,
515 self.interface0,
516 self.dst_ip_net,
517 local_addr=self.src_ip_net,
518 multihop=self.multihop,
519 sha1_key=key1,
520 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100521 session.add_vpp_config()
522 session.activate_auth(key2)
Klement Sekera10db26f2017-01-11 08:16:53 +0100523
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700524 def test_set_del_udp_echo_source(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200525 """set/del udp echo source"""
Abdel Baig17a91812024-09-03 11:52:20 -0400526
527 if self.multihop:
528 self.skipTest(
529 f"Skipping because echo functionality is not supported with multihop"
530 )
531
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700532 self.create_loopback_interfaces(1)
533 self.loopback0 = self.lo_interfaces[0]
534 self.loopback0.admin_up()
535 echo_source = self.vapi.bfd_udp_get_echo_source()
536 self.assertFalse(echo_source.is_set)
537 self.assertFalse(echo_source.have_usable_ip4)
538 self.assertFalse(echo_source.have_usable_ip6)
539
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200540 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700541 echo_source = self.vapi.bfd_udp_get_echo_source()
542 self.assertTrue(echo_source.is_set)
543 self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index)
544 self.assertFalse(echo_source.have_usable_ip4)
545 self.assertFalse(echo_source.have_usable_ip6)
546
547 self.loopback0.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200548 echo_ip4 = ipaddress.IPv4Address(
549 int(ipaddress.IPv4Address(self.loopback0.local_ip4)) ^ 1
550 ).packed
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700551 echo_source = self.vapi.bfd_udp_get_echo_source()
552 self.assertTrue(echo_source.is_set)
553 self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index)
554 self.assertTrue(echo_source.have_usable_ip4)
Jakub Grajciar4682feb2019-09-02 13:28:52 +0200555 self.assertEqual(echo_source.ip4_addr.packed, echo_ip4)
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700556 self.assertFalse(echo_source.have_usable_ip6)
557
558 self.loopback0.config_ip6()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200559 echo_ip6 = ipaddress.IPv6Address(
560 int(ipaddress.IPv6Address(self.loopback0.local_ip6)) ^ 1
561 ).packed
Paul Vinciguerra2f156312020-05-02 22:34:40 -0400562
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700563 echo_source = self.vapi.bfd_udp_get_echo_source()
564 self.assertTrue(echo_source.is_set)
565 self.assertEqual(echo_source.sw_if_index, self.loopback0.sw_if_index)
566 self.assertTrue(echo_source.have_usable_ip4)
Jakub Grajciar4682feb2019-09-02 13:28:52 +0200567 self.assertEqual(echo_source.ip4_addr.packed, echo_ip4)
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700568 self.assertTrue(echo_source.have_usable_ip6)
Jakub Grajciar4682feb2019-09-02 13:28:52 +0200569 self.assertEqual(echo_source.ip6_addr.packed, echo_ip6)
Matus Fabian2d3c7b92018-10-02 03:22:18 -0700570
571 self.vapi.bfd_udp_del_echo_source()
572 echo_source = self.vapi.bfd_udp_get_echo_source()
573 self.assertFalse(echo_source.is_set)
574 self.assertFalse(echo_source.have_usable_ip4)
575 self.assertFalse(echo_source.have_usable_ip6)
576
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200577
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200578class BFDTestSession(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200579 """BFD session as seen from test framework side"""
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200580
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200581 def __init__(
582 self,
583 test,
584 interface,
585 af,
586 detect_mult=3,
587 sha1_key=None,
588 bfd_key_id=None,
589 our_seq_number=None,
590 tunnel_header=None,
591 phy_interface=None,
Abdel Baig17a91812024-09-03 11:52:20 -0400592 multihop=False,
593 local_addr=None,
594 peer_addr=None,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200595 ):
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200596 self.test = test
Klement Sekera46a87ad2017-01-02 08:22:23 +0100597 self.af = af
Klement Sekerab17dd962017-01-09 07:43:48 +0100598 self.sha1_key = sha1_key
599 self.bfd_key_id = bfd_key_id
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200600 self.interface = interface
Neale Ranns52cd4962019-06-05 10:28:17 +0000601 if phy_interface:
602 self.phy_interface = phy_interface
603 else:
604 self.phy_interface = self.interface
Klement Sekerad3ba5152017-02-14 03:09:17 +0100605 self.udp_sport = randint(49152, 65535)
606 if our_seq_number is None:
607 self.our_seq_number = randint(0, 40000000)
608 else:
609 self.our_seq_number = our_seq_number
Klement Sekerab17dd962017-01-09 07:43:48 +0100610 self.vpp_seq_number = None
Klement Sekerad3ba5152017-02-14 03:09:17 +0100611 self.my_discriminator = 0
Klement Sekera2e01dfa2017-04-03 08:10:08 +0200612 self.desired_min_tx = 300000
613 self.required_min_rx = 300000
Klement Sekera239790f2017-02-16 10:53:53 +0100614 self.required_min_echo_rx = None
Klement Sekerad3ba5152017-02-14 03:09:17 +0100615 self.detect_mult = detect_mult
616 self.diag = BFDDiagCode.no_diagnostic
617 self.your_discriminator = None
618 self.state = BFDState.down
619 self.auth_type = BFDAuthType.no_auth
Neale Ranns52cd4962019-06-05 10:28:17 +0000620 self.tunnel_header = tunnel_header
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000621 self.tx_packets = 0
622 self.rx_packets = 0
623 self.tx_packets_echo = 0
624 self.rx_packets_echo = 0
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200625
Abdel Baig17a91812024-09-03 11:52:20 -0400626 if multihop:
627 self.sw_if_index = 0
628 BFD.udp_dport = BFD_UDP_MH_PORT
629 else:
630 BFD.udp_dport = BFD_UDP_SH_PORT
631 self.sw_if_index = self.interface.sw_if_index
632
633 if local_addr:
634 self.local_addr = local_addr
635 else:
636 if self.af == AF_INET:
637 self.local_addr = self.interface.local_ip4
638 else:
639 self.local_addr = self.interface.local_ip6
640
641 if peer_addr:
642 self.peer_addr = peer_addr
643 else:
644 if self.af == AF_INET:
645 self.peer_addr = self.interface.remote_ip4
646 else:
647 self.peer_addr = self.interface.remote_ip6
648
Klement Sekerab17dd962017-01-09 07:43:48 +0100649 def inc_seq_num(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200650 """increment sequence number, wrapping if needed"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100651 if self.our_seq_number == 0xFFFFFFFF:
652 self.our_seq_number = 0
653 else:
654 self.our_seq_number += 1
655
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200656 def update(
657 self,
658 my_discriminator=None,
659 your_discriminator=None,
660 desired_min_tx=None,
661 required_min_rx=None,
662 required_min_echo_rx=None,
663 detect_mult=None,
664 diag=None,
665 state=None,
666 auth_type=None,
667 ):
668 """update BFD parameters associated with session"""
Klement Sekera239790f2017-02-16 10:53:53 +0100669 if my_discriminator is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100670 self.my_discriminator = my_discriminator
Klement Sekera239790f2017-02-16 10:53:53 +0100671 if your_discriminator is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100672 self.your_discriminator = your_discriminator
Klement Sekera239790f2017-02-16 10:53:53 +0100673 if required_min_rx is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100674 self.required_min_rx = required_min_rx
Klement Sekera239790f2017-02-16 10:53:53 +0100675 if required_min_echo_rx is not None:
676 self.required_min_echo_rx = required_min_echo_rx
677 if desired_min_tx is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100678 self.desired_min_tx = desired_min_tx
Klement Sekera239790f2017-02-16 10:53:53 +0100679 if detect_mult is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100680 self.detect_mult = detect_mult
Klement Sekera239790f2017-02-16 10:53:53 +0100681 if diag is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100682 self.diag = diag
Klement Sekera239790f2017-02-16 10:53:53 +0100683 if state is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100684 self.state = state
Klement Sekera239790f2017-02-16 10:53:53 +0100685 if auth_type is not None:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100686 self.auth_type = auth_type
687
688 def fill_packet_fields(self, packet):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200689 """set packet fields with known values in packet"""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100690 bfd = packet[BFD]
691 if self.my_discriminator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200692 self.test.logger.debug(
693 "BFD: setting packet.my_discriminator=%s", self.my_discriminator
694 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100695 bfd.my_discriminator = self.my_discriminator
696 if self.your_discriminator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200697 self.test.logger.debug(
698 "BFD: setting packet.your_discriminator=%s", self.your_discriminator
699 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100700 bfd.your_discriminator = self.your_discriminator
701 if self.required_min_rx:
702 self.test.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200703 "BFD: setting packet.required_min_rx_interval=%s", self.required_min_rx
704 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100705 bfd.required_min_rx_interval = self.required_min_rx
Klement Sekera239790f2017-02-16 10:53:53 +0100706 if self.required_min_echo_rx:
707 self.test.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200708 "BFD: setting packet.required_min_echo_rx=%s", self.required_min_echo_rx
709 )
Klement Sekera239790f2017-02-16 10:53:53 +0100710 bfd.required_min_echo_rx_interval = self.required_min_echo_rx
Klement Sekerad3ba5152017-02-14 03:09:17 +0100711 if self.desired_min_tx:
712 self.test.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200713 "BFD: setting packet.desired_min_tx_interval=%s", self.desired_min_tx
714 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100715 bfd.desired_min_tx_interval = self.desired_min_tx
716 if self.detect_mult:
717 self.test.logger.debug(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200718 "BFD: setting packet.detect_mult=%s", self.detect_mult
719 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100720 bfd.detect_mult = self.detect_mult
721 if self.diag:
722 self.test.logger.debug("BFD: setting packet.diag=%s", self.diag)
723 bfd.diag = self.diag
724 if self.state:
725 self.test.logger.debug("BFD: setting packet.state=%s", self.state)
726 bfd.state = self.state
727 if self.auth_type:
728 # this is used by a negative test-case
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200729 self.test.logger.debug("BFD: setting packet.auth_type=%s", self.auth_type)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100730 bfd.auth_type = self.auth_type
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200731
732 def create_packet(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200733 """create a BFD packet, reflecting the current state of session"""
Klement Sekerab17dd962017-01-09 07:43:48 +0100734 if self.sha1_key:
735 bfd = BFD(flags="A")
736 bfd.auth_type = self.sha1_key.auth_type
737 bfd.auth_len = BFD.sha1_auth_len
738 bfd.auth_key_id = self.bfd_key_id
739 bfd.auth_seq_num = self.our_seq_number
740 bfd.length = BFD.sha1_auth_len + BFD.bfd_pkt_len
741 else:
742 bfd = BFD()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200743 packet = Ether(
744 src=self.phy_interface.remote_mac, dst=self.phy_interface.local_mac
745 )
Neale Ranns52cd4962019-06-05 10:28:17 +0000746 if self.tunnel_header:
747 packet = packet / self.tunnel_header
Klement Sekera46a87ad2017-01-02 08:22:23 +0100748 if self.af == AF_INET6:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 packet = (
750 packet
751 / IPv6(
Abdel Baig17a91812024-09-03 11:52:20 -0400752 src=self.peer_addr,
753 dst=self.local_addr,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200754 hlim=255,
755 )
756 / UDP(sport=self.udp_sport, dport=BFD.udp_dport)
757 / bfd
758 )
Klement Sekera46a87ad2017-01-02 08:22:23 +0100759 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200760 packet = (
761 packet
Abdel Baig17a91812024-09-03 11:52:20 -0400762 / IP(src=self.peer_addr, dst=self.local_addr, ttl=255)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200763 / UDP(sport=self.udp_sport, dport=BFD.udp_dport)
764 / bfd
765 )
Klement Sekera3e0a3562016-12-19 09:05:21 +0100766 self.test.logger.debug("BFD: Creating packet")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100767 self.fill_packet_fields(packet)
Klement Sekerab17dd962017-01-09 07:43:48 +0100768 if self.sha1_key:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200769 hash_material = (
770 scapy.compat.raw(packet[BFD])[:32]
771 + self.sha1_key.key
772 + b"\0" * (20 - len(self.sha1_key.key))
773 )
774 self.test.logger.debug(
775 "BFD: Calculated SHA1 hash: %s"
776 % hashlib.sha1(hash_material).hexdigest()
777 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100778 packet[BFD].auth_key_hash = hashlib.sha1(hash_material).digest()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200779 return packet
780
Klement Sekerad3ba5152017-02-14 03:09:17 +0100781 def send_packet(self, packet=None, interface=None):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 """send packet on interface, creating the packet if needed"""
Klement Sekeraa57a9702017-02-02 06:58:07 +0100783 if packet is None:
784 packet = self.create_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100785 if interface is None:
Neale Ranns52cd4962019-06-05 10:28:17 +0000786 interface = self.phy_interface
Klement Sekeraa57a9702017-02-02 06:58:07 +0100787 self.test.logger.debug(ppp("Sending packet:", packet))
Klement Sekerad3ba5152017-02-14 03:09:17 +0100788 interface.add_stream(packet)
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000789 self.tx_packets += 1
Klement Sekera9225dee2016-12-12 08:36:58 +0100790 self.test.pg_start()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200791
Klement Sekerab17dd962017-01-09 07:43:48 +0100792 def verify_sha1_auth(self, packet):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200793 """Verify correctness of authentication in BFD layer."""
Klement Sekerab17dd962017-01-09 07:43:48 +0100794 bfd = packet[BFD]
795 self.test.assert_equal(bfd.auth_len, 28, "Auth section length")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200796 self.test.assert_equal(bfd.auth_type, self.sha1_key.auth_type, BFDAuthType)
Klement Sekerab17dd962017-01-09 07:43:48 +0100797 self.test.assert_equal(bfd.auth_key_id, self.bfd_key_id, "Key ID")
798 self.test.assert_equal(bfd.auth_reserved, 0, "Reserved")
799 if self.vpp_seq_number is None:
800 self.vpp_seq_number = bfd.auth_seq_num
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200801 self.test.logger.debug(
802 "Received initial sequence number: %s" % self.vpp_seq_number
803 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100804 else:
805 recvd_seq_num = bfd.auth_seq_num
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200806 self.test.logger.debug(
807 "Received followup sequence number: %s" % recvd_seq_num
808 )
809 if self.vpp_seq_number < 0xFFFFFFFF:
810 if self.sha1_key.auth_type == BFDAuthType.meticulous_keyed_sha1:
811 self.test.assert_equal(
812 recvd_seq_num, self.vpp_seq_number + 1, "BFD sequence number"
813 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100814 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200815 self.test.assert_in_range(
816 recvd_seq_num,
817 self.vpp_seq_number,
818 self.vpp_seq_number + 1,
819 "BFD sequence number",
820 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100821 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200822 if self.sha1_key.auth_type == BFDAuthType.meticulous_keyed_sha1:
823 self.test.assert_equal(recvd_seq_num, 0, "BFD sequence number")
Klement Sekerab17dd962017-01-09 07:43:48 +0100824 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200825 self.test.assertIn(
826 recvd_seq_num,
827 (self.vpp_seq_number, 0),
828 "BFD sequence number not one of "
829 "(%s, 0)" % self.vpp_seq_number,
830 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100831 self.vpp_seq_number = recvd_seq_num
832 # last 20 bytes represent the hash - so replace them with the key,
833 # pad the result with zeros and hash the result
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200834 hash_material = (
835 bfd.original[:-20]
836 + self.sha1_key.key
837 + b"\0" * (20 - len(self.sha1_key.key))
838 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100839 expected_hash = hashlib.sha1(hash_material).hexdigest()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200840 self.test.assert_equal(
841 binascii.hexlify(bfd.auth_key_hash), expected_hash.encode(), "Auth key hash"
842 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100843
844 def verify_bfd(self, packet):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200845 """Verify correctness of BFD layer."""
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200846 bfd = packet[BFD]
847 self.test.assert_equal(bfd.version, 1, "BFD version")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200848 self.test.assert_equal(
849 bfd.your_discriminator, self.my_discriminator, "BFD - your discriminator"
850 )
Klement Sekerab17dd962017-01-09 07:43:48 +0100851 if self.sha1_key:
852 self.verify_sha1_auth(packet)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200853
854
Klement Sekerad3ba5152017-02-14 03:09:17 +0100855def bfd_session_up(test):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200856 """Bring BFD session up"""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100857 test.logger.info("BFD: Waiting for slow hello")
Neale Ranns52cd4962019-06-05 10:28:17 +0000858 p = wait_for_bfd_packet(test, 2, is_tunnel=test.vpp_session.is_tunnel)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100859 old_offset = None
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200860 if hasattr(test, "vpp_clock_offset"):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100861 old_offset = test.vpp_clock_offset
snaramre73aff472019-12-02 05:49:28 +0000862 test.vpp_clock_offset = time.time() - float(p.time)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200863 test.logger.debug("BFD: Calculated vpp clock offset: %s", test.vpp_clock_offset)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100864 if old_offset:
865 test.assertAlmostEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200866 old_offset,
867 test.vpp_clock_offset,
868 delta=0.5,
869 msg="vpp clock offset not stable (new: %s, old: %s)"
870 % (test.vpp_clock_offset, old_offset),
871 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100872 test.logger.info("BFD: Sending Init")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200873 test.test_session.update(
874 my_discriminator=randint(0, 40000000),
875 your_discriminator=p[BFD].my_discriminator,
876 state=BFDState.init,
877 )
878 if (
879 test.test_session.sha1_key
880 and test.test_session.sha1_key.auth_type == BFDAuthType.meticulous_keyed_sha1
881 ):
Klement Sekera73884482017-02-23 09:26:30 +0100882 test.test_session.inc_seq_num()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100883 test.test_session.send_packet()
884 test.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +0100885 e = test.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100886 verify_event(test, e, expected_state=BFDState.up)
887 test.logger.info("BFD: Session is Up")
888 test.test_session.update(state=BFDState.up)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200889 if (
890 test.test_session.sha1_key
891 and test.test_session.sha1_key.auth_type == BFDAuthType.meticulous_keyed_sha1
892 ):
Klement Sekera73884482017-02-23 09:26:30 +0100893 test.test_session.inc_seq_num()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100894 test.test_session.send_packet()
895 test.assert_equal(test.vpp_session.state, BFDState.up, BFDState)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200896
Klement Sekera46a87ad2017-01-02 08:22:23 +0100897
Klement Sekerad3ba5152017-02-14 03:09:17 +0100898def bfd_session_down(test):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200899 """Bring BFD session down"""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100900 test.assert_equal(test.vpp_session.state, BFDState.up, BFDState)
901 test.test_session.update(state=BFDState.down)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200902 if (
903 test.test_session.sha1_key
904 and test.test_session.sha1_key.auth_type == BFDAuthType.meticulous_keyed_sha1
905 ):
Klement Sekera73884482017-02-23 09:26:30 +0100906 test.test_session.inc_seq_num()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100907 test.test_session.send_packet()
908 test.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +0100909 e = test.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100910 verify_event(test, e, expected_state=BFDState.down)
911 test.logger.info("BFD: Session is Down")
912 test.assert_equal(test.vpp_session.state, BFDState.down, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +0100913
Klement Sekera46a87ad2017-01-02 08:22:23 +0100914
Klement Sekera73884482017-02-23 09:26:30 +0100915def verify_bfd_session_config(test, session, state=None):
916 dump = session.get_bfd_udp_session_dump_entry()
917 test.assertIsNotNone(dump)
918 # since dump is not none, we have verified that sw_if_index and addresses
919 # are valid (in get_bfd_udp_session_dump_entry)
920 if state:
921 test.assert_equal(dump.state, state, "session state")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200922 test.assert_equal(
923 dump.required_min_rx, session.required_min_rx, "required min rx interval"
924 )
925 test.assert_equal(
926 dump.desired_min_tx, session.desired_min_tx, "desired min tx interval"
927 )
928 test.assert_equal(dump.detect_mult, session.detect_mult, "detect multiplier")
Klement Sekera73884482017-02-23 09:26:30 +0100929 if session.sha1_key is None:
930 test.assert_equal(dump.is_authenticated, 0, "is_authenticated flag")
931 else:
932 test.assert_equal(dump.is_authenticated, 1, "is_authenticated flag")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200933 test.assert_equal(dump.bfd_key_id, session.bfd_key_id, "bfd key id")
934 test.assert_equal(
935 dump.conf_key_id, session.sha1_key.conf_key_id, "config key id"
936 )
Klement Sekera73884482017-02-23 09:26:30 +0100937
938
Klement Sekerad3ba5152017-02-14 03:09:17 +0100939def verify_ip(test, packet):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200940 """Verify correctness of IP layer."""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100941 if test.vpp_session.af == AF_INET6:
942 ip = packet[IPv6]
Abdel Baig17a91812024-09-03 11:52:20 -0400943 local_ip = test.vpp_session.local_addr
944 remote_ip = test.vpp_session.peer_addr
Klement Sekerad3ba5152017-02-14 03:09:17 +0100945 test.assert_equal(ip.hlim, 255, "IPv6 hop limit")
946 else:
947 ip = packet[IP]
Abdel Baig17a91812024-09-03 11:52:20 -0400948 local_ip = test.vpp_session.local_addr
949 remote_ip = test.vpp_session.peer_addr
Klement Sekerad3ba5152017-02-14 03:09:17 +0100950 test.assert_equal(ip.ttl, 255, "IPv4 TTL")
951 test.assert_equal(ip.src, local_ip, "IP source address")
952 test.assert_equal(ip.dst, remote_ip, "IP destination address")
953
954
955def verify_udp(test, packet):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200956 """Verify correctness of UDP layer."""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100957 udp = packet[UDP]
958 test.assert_equal(udp.dport, BFD.udp_dport, "UDP destination port")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200959 test.assert_in_range(
960 udp.sport, BFD.udp_sport_min, BFD.udp_sport_max, "UDP source port"
961 )
Klement Sekerad3ba5152017-02-14 03:09:17 +0100962
963
964def verify_event(test, event, expected_state):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200965 """Verify correctness of event values."""
Klement Sekerad3ba5152017-02-14 03:09:17 +0100966 e = event
Paul Vinciguerra090096b2020-12-03 00:42:46 -0500967 test.logger.debug("BFD: Event: %s" % reprlib.repr(e))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200968 test.assert_equal(
Abdel Baig17a91812024-09-03 11:52:20 -0400969 e.sw_if_index, test.vpp_session._sw_if_index, "BFD interface index"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200970 )
Jakub Grajciar4682feb2019-09-02 13:28:52 +0200971
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200972 test.assert_equal(
973 str(e.local_addr), test.vpp_session.local_addr, "Local IPv6 address"
974 )
975 test.assert_equal(str(e.peer_addr), test.vpp_session.peer_addr, "Peer IPv6 address")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100976 test.assert_equal(e.state, expected_state, BFDState)
977
978
Neale Ranns52cd4962019-06-05 10:28:17 +0000979def wait_for_bfd_packet(test, timeout=1, pcap_time_min=None, is_tunnel=False):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200980 """wait for BFD packet and verify its correctness
Klement Sekerad3ba5152017-02-14 03:09:17 +0100981
982 :param timeout: how long to wait
983 :param pcap_time_min: ignore packets with pcap timestamp lower than this
984
985 :returns: tuple (packet, time spent waiting for packet)
986 """
987 test.logger.info("BFD: Waiting for BFD packet")
988 deadline = time.time() + timeout
989 counter = 0
990 while True:
991 counter += 1
992 # sanity check
993 test.assert_in_range(counter, 0, 100, "number of packets ignored")
994 time_left = deadline - time.time()
995 if time_left < 0:
996 raise CaptureTimeoutError("Packet did not arrive within timeout")
997 p = test.pg0.wait_for_packet(timeout=time_left)
Klement Sekeracdaf0d82022-02-14 20:20:22 +0000998 test.test_session.rx_packets += 1
Klement Sekerad3ba5152017-02-14 03:09:17 +0100999 test.logger.debug(ppp("BFD: Got packet:", p))
1000 if pcap_time_min is not None and p.time < pcap_time_min:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001001 test.logger.debug(
1002 ppp(
1003 "BFD: ignoring packet (pcap time %s < "
1004 "pcap time min %s):" % (p.time, pcap_time_min),
1005 p,
1006 )
1007 )
Klement Sekera46a87ad2017-01-02 08:22:23 +01001008 else:
Klement Sekerad3ba5152017-02-14 03:09:17 +01001009 break
Klement Sekera617d4292022-09-20 15:10:10 +02001010 test.logger.debug(test.vapi.ppcli("show trace"))
Neale Ranns52cd4962019-06-05 10:28:17 +00001011 if is_tunnel:
1012 # strip an IP layer and move to the next
1013 p = p[IP].payload
1014
Klement Sekerad3ba5152017-02-14 03:09:17 +01001015 bfd = p[BFD]
1016 if bfd is None:
1017 raise Exception(ppp("Unexpected or invalid BFD packet:", p))
1018 if bfd.payload:
1019 raise Exception(ppp("Unexpected payload in BFD packet:", bfd))
1020 verify_ip(test, p)
1021 verify_udp(test, p)
1022 test.test_session.verify_bfd(p)
1023 return p
Klement Sekera3e0a3562016-12-19 09:05:21 +01001024
Klement Sekera46a87ad2017-01-02 08:22:23 +01001025
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001026BFDStats = namedtuple("BFDStats", "rx rx_echo tx tx_echo")
1027
1028
1029def bfd_grab_stats_snapshot(test, bs_idx=0, thread_index=None):
1030 s = test.statistics
1031 ti = thread_index
1032 if ti is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001033 rx = s["/bfd/rx-session-counters"][:, bs_idx].sum_packets()
1034 rx_echo = s["/bfd/rx-session-echo-counters"][:, bs_idx].sum_packets()
1035 tx = s["/bfd/tx-session-counters"][:, bs_idx].sum_packets()
1036 tx_echo = s["/bfd/tx-session-echo-counters"][:, bs_idx].sum_packets()
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001037 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001038 rx = s["/bfd/rx-session-counters"][ti, bs_idx].sum_packets()
1039 rx_echo = s["/bfd/rx-session-echo-counters"][ti, bs_idx].sum_packets()
1040 tx = s["/bfd/tx-session-counters"][ti, bs_idx].sum_packets()
1041 tx_echo = s["/bfd/tx-session-echo-counters"][ti, bs_idx].sum_packets()
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001042 return BFDStats(rx, rx_echo, tx, tx_echo)
1043
1044
1045def bfd_stats_diff(stats_before, stats_after):
1046 rx = stats_after.rx - stats_before.rx
1047 rx_echo = stats_after.rx_echo - stats_before.rx_echo
1048 tx = stats_after.tx - stats_before.tx
1049 tx_echo = stats_after.tx_echo - stats_before.tx_echo
1050 return BFDStats(rx, rx_echo, tx, tx_echo)
1051
1052
Abdel Baig17a91812024-09-03 11:52:20 -04001053@parameterized_class(
1054 [
1055 {"multihop": False},
1056 {"multihop": True},
1057 ]
1058)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00001059@tag_run_solo
Dave Wallace670724c2022-09-20 21:52:18 -04001060@tag_fixme_debian11
Klement Sekerad3ba5152017-02-14 03:09:17 +01001061class BFD4TestCase(VppTestCase):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001062 pg0 = None
Abdel Baig17a91812024-09-03 11:52:20 -04001063 interface0 = None
Klement Sekerad3ba5152017-02-14 03:09:17 +01001064 vpp_clock_offset = None
1065 vpp_session = None
1066 test_session = None
Abdel Baig17a91812024-09-03 11:52:20 -04001067 src_ip_net = ""
1068 dst_ip_net = ""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001069
Klement Sekera46a87ad2017-01-02 08:22:23 +01001070 @classmethod
1071 def setUpClass(cls):
1072 super(BFD4TestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04001073 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
1074 cls.__doc__ = (
1075 f"""""Bidirectional Forwarding Detection (BFD) - IPv4, {hoptype_str}"""
1076 )
Damjan Marion07a38572018-01-21 06:44:18 -08001077 cls.vapi.cli("set log class bfd level debug")
Klement Sekera46a87ad2017-01-02 08:22:23 +01001078 try:
1079 cls.create_pg_interfaces([0])
Klement Sekerab9ef2732018-06-24 22:49:33 +02001080 cls.create_loopback_interfaces(1)
Klement Sekera239790f2017-02-16 10:53:53 +01001081 cls.loopback0 = cls.lo_interfaces[0]
1082 cls.loopback0.config_ip4()
1083 cls.loopback0.admin_up()
Klement Sekera46a87ad2017-01-02 08:22:23 +01001084 cls.pg0.config_ip4()
Klement Sekera46a87ad2017-01-02 08:22:23 +01001085 cls.pg0.configure_ipv4_neighbors()
1086 cls.pg0.admin_up()
1087 cls.pg0.resolve_arp()
1088
1089 except Exception:
1090 super(BFD4TestCase, cls).tearDownClass()
1091 raise
1092
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08001093 @classmethod
1094 def tearDownClass(cls):
1095 super(BFD4TestCase, cls).tearDownClass()
1096
Klement Sekera46a87ad2017-01-02 08:22:23 +01001097 def setUp(self):
1098 super(BFD4TestCase, self).setUp()
Klement Sekerab17dd962017-01-09 07:43:48 +01001099 self.factory = AuthKeyFactory()
Klement Sekera46a87ad2017-01-02 08:22:23 +01001100 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001101 self.pg0.enable_capture()
Abdel Baig17a91812024-09-03 11:52:20 -04001102 set_ipv4_pfx_route_info(self, self.pg0, BFD_IPV4_REMOTE_ADDR, True)
1103
Klement Sekera46a87ad2017-01-02 08:22:23 +01001104 try:
Abdel Baig17a91812024-09-03 11:52:20 -04001105 if self.multihop:
1106 self.interface0 = None
1107 self.bfd_udp4_sessions = self.statistics[BFD_STATS_V4_MH_PATH]
1108 self.bfd_udp6_sessions = self.statistics[BFD_STATS_V6_MH_PATH]
1109 else:
1110 self.interface0 = self.pg0
1111 self.bfd_udp4_sessions = self.statistics[BFD_STATS_V4_SH_PATH]
1112 self.bfd_udp6_sessions = self.statistics[BFD_STATS_V6_SH_PATH]
1113
Klement Sekera617d4292022-09-20 15:10:10 +02001114 self.vapi.cli("trace add bfd-process 500")
Abdel Baig17a91812024-09-03 11:52:20 -04001115 self.vpp_session = VppBFDUDPSession(
1116 self,
1117 self.interface0,
1118 self.dst_ip_net,
1119 local_addr=self.src_ip_net,
1120 multihop=self.multihop,
1121 )
Klement Sekera46a87ad2017-01-02 08:22:23 +01001122 self.vpp_session.add_vpp_config()
1123 self.vpp_session.admin_up()
Abdel Baig17a91812024-09-03 11:52:20 -04001124 self.test_session = BFDTestSession(
1125 self,
1126 self.pg0,
1127 AF_INET,
1128 local_addr=self.src_ip_net,
1129 peer_addr=self.dst_ip_net,
1130 multihop=self.multihop,
1131 )
Jakub Grajciar4682feb2019-09-02 13:28:52 +02001132 except BaseException:
Klement Sekera46a87ad2017-01-02 08:22:23 +01001133 self.vapi.want_bfd_events(enable_disable=0)
1134 raise
1135
1136 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001137 if not self.vpp_dead:
1138 self.vapi.want_bfd_events(enable_disable=0)
1139 self.vapi.collect_events() # clear the event queue
1140 super(BFD4TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01001141
1142 def test_session_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001143 """bring BFD session up"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001144 bfd_session_up(self)
Abdel Baig17a91812024-09-03 11:52:20 -04001145 if self.multihop:
1146 bfd_udp4_sessions = self.statistics[BFD_STATS_V4_MH_PATH]
1147 bfd_udp6_sessions = self.statistics[BFD_STATS_V6_MH_PATH]
1148 else:
1149 bfd_udp4_sessions = self.statistics[BFD_STATS_V4_SH_PATH]
1150 bfd_udp6_sessions = self.statistics[BFD_STATS_V6_SH_PATH]
1151
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001152 self.assert_equal(bfd_udp4_sessions - self.bfd_udp4_sessions, 1)
1153 self.assert_equal(bfd_udp6_sessions, self.bfd_udp6_sessions)
Klement Sekerab17dd962017-01-09 07:43:48 +01001154
Klement Sekera73884482017-02-23 09:26:30 +01001155 def test_session_up_by_ip(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 """bring BFD session up - first frame looked up by address pair"""
Klement Sekera73884482017-02-23 09:26:30 +01001157 self.logger.info("BFD: Sending Slow control frame")
1158 self.test_session.update(my_discriminator=randint(0, 40000000))
1159 self.test_session.send_packet()
1160 self.pg0.enable_capture()
1161 p = self.pg0.wait_for_packet(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001162 self.assert_equal(
1163 p[BFD].your_discriminator,
1164 self.test_session.my_discriminator,
1165 "BFD - your discriminator",
1166 )
Klement Sekera73884482017-02-23 09:26:30 +01001167 self.assert_equal(p[BFD].state, BFDState.init, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001168 self.test_session.update(
1169 your_discriminator=p[BFD].my_discriminator, state=BFDState.up
1170 )
Klement Sekera73884482017-02-23 09:26:30 +01001171 self.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +01001172 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekera73884482017-02-23 09:26:30 +01001173 verify_event(self, e, expected_state=BFDState.init)
1174 self.logger.info("BFD: Sending Up")
1175 self.test_session.send_packet()
1176 self.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +01001177 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekera73884482017-02-23 09:26:30 +01001178 verify_event(self, e, expected_state=BFDState.up)
1179 self.logger.info("BFD: Session is Up")
1180 self.test_session.update(state=BFDState.up)
1181 self.test_session.send_packet()
1182 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1183
Klement Sekerab17dd962017-01-09 07:43:48 +01001184 def test_session_down(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001185 """bring BFD session down"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001186 bfd_session_up(self)
1187 bfd_session_down(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001188
1189 def test_hold_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001190 """hold BFD session up"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001191 bfd_session_up(self)
1192 for dummy in range(self.test_session.detect_mult * 2):
1193 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001194 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001195 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekera46a87ad2017-01-02 08:22:23 +01001196
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001197 def test_slow_timer(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001198 """verify slow periodic control frames while session down"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001199 packet_count = 3
1200 self.logger.info("BFD: Waiting for %d BFD packets", packet_count)
1201 prev_packet = wait_for_bfd_packet(self, 2)
1202 for dummy in range(packet_count):
1203 next_packet = wait_for_bfd_packet(self, 2)
1204 time_diff = next_packet.time - prev_packet.time
Klement Sekerae4504c62016-12-08 10:16:41 +01001205 # spec says the range should be <0.75, 1>, allow extra 0.05 margin
1206 # to work around timing issues
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001207 self.assert_in_range(time_diff, 0.70, 1.05, "time between slow packets")
Klement Sekerad3ba5152017-02-14 03:09:17 +01001208 prev_packet = next_packet
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001209
1210 def test_zero_remote_min_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001211 """no packets when zero remote required min rx interval"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001212 bfd_session_up(self)
1213 self.test_session.update(required_min_rx=0)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001214 self.test_session.send_packet()
Klement Sekera239790f2017-02-16 10:53:53 +01001215 for dummy in range(self.test_session.detect_mult):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001216 self.sleep(
1217 self.vpp_session.required_min_rx / USEC_IN_SEC,
1218 "sleep before transmitting bfd packet",
1219 )
Klement Sekera239790f2017-02-16 10:53:53 +01001220 self.test_session.send_packet()
Klement Sekeraa57a9702017-02-02 06:58:07 +01001221 try:
Klement Sekera239790f2017-02-16 10:53:53 +01001222 p = wait_for_bfd_packet(self, timeout=0)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001223 self.logger.error(ppp("Received unexpected packet:", p))
Klement Sekerad3ba5152017-02-14 03:09:17 +01001224 except CaptureTimeoutError:
Klement Sekeraa57a9702017-02-02 06:58:07 +01001225 pass
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001226 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekera2e01dfa2017-04-03 08:10:08 +02001227 self.test_session.update(required_min_rx=300000)
Klement Sekera239790f2017-02-16 10:53:53 +01001228 for dummy in range(3):
1229 self.test_session.send_packet()
1230 wait_for_bfd_packet(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001231 self, timeout=self.test_session.required_min_rx / USEC_IN_SEC
1232 )
1233 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001234
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001235 def test_conn_down(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001236 """verify session goes down after inactivity"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001237 bfd_session_up(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001238 detection_time = (
1239 self.test_session.detect_mult
1240 * self.vpp_session.required_min_rx
1241 / USEC_IN_SEC
1242 )
Klement Sekerac48829b2017-02-14 07:55:57 +01001243 self.sleep(detection_time, "waiting for BFD session time-out")
Ole Troan4376ab22021-03-03 10:40:05 +01001244 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerad3ba5152017-02-14 03:09:17 +01001245 verify_event(self, e, expected_state=BFDState.down)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001246
Klement Sekera4d39f9c2020-01-17 10:01:52 +00001247 def test_peer_discr_reset_sess_down(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001248 """peer discriminator reset after session goes down"""
Klement Sekera4d39f9c2020-01-17 10:01:52 +00001249 bfd_session_up(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001250 detection_time = (
1251 self.test_session.detect_mult
1252 * self.vpp_session.required_min_rx
1253 / USEC_IN_SEC
1254 )
Klement Sekera4d39f9c2020-01-17 10:01:52 +00001255 self.sleep(detection_time, "waiting for BFD session time-out")
1256 self.test_session.my_discriminator = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001257 wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera4d39f9c2020-01-17 10:01:52 +00001258
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001259 def test_large_required_min_rx(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001260 """large remote required min rx interval"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001261 bfd_session_up(self)
1262 p = wait_for_bfd_packet(self)
Klement Sekera637b9c42016-12-08 05:19:14 +01001263 interval = 3000000
Klement Sekerad3ba5152017-02-14 03:09:17 +01001264 self.test_session.update(required_min_rx=interval)
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001265 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001266 time_mark = time.time()
Klement Sekera637b9c42016-12-08 05:19:14 +01001267 count = 0
Klement Sekeraa57a9702017-02-02 06:58:07 +01001268 # busy wait here, trying to collect a packet or event, vpp is not
1269 # allowed to send packets and the session will timeout first - so the
1270 # Up->Down event must arrive before any packets do
Klement Sekerad3ba5152017-02-14 03:09:17 +01001271 while time.time() < time_mark + interval / USEC_IN_SEC:
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001272 try:
Klement Sekerad3ba5152017-02-14 03:09:17 +01001273 p = wait_for_bfd_packet(self, timeout=0)
1274 # if vpp managed to send a packet before we did the session
1275 # session update, then that's fine, ignore it
1276 if p.time < time_mark - self.vpp_clock_offset:
1277 continue
Klement Sekeraa57a9702017-02-02 06:58:07 +01001278 self.logger.error(ppp("Received unexpected packet:", p))
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001279 count += 1
Klement Sekerad3ba5152017-02-14 03:09:17 +01001280 except CaptureTimeoutError:
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001281 pass
Klement Sekeraa57a9702017-02-02 06:58:07 +01001282 events = self.vapi.collect_events()
1283 if len(events) > 0:
Klement Sekerad3ba5152017-02-14 03:09:17 +01001284 verify_event(self, events[0], BFDState.down)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001285 break
1286 self.assert_equal(count, 0, "number of packets received")
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001287
Klement Sekerad3ba5152017-02-14 03:09:17 +01001288 def test_immediate_remote_min_rx_reduction(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001289 """immediately honor remote required min rx reduction"""
Klement Sekera3e0a3562016-12-19 09:05:21 +01001290 self.vpp_session.remove_vpp_config()
Klement Sekera10db26f2017-01-11 08:16:53 +01001291 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04001292 self,
1293 self.interface0,
1294 self.dst_ip_net,
1295 local_addr=self.src_ip_net,
1296 multihop=self.multihop,
1297 desired_min_tx=10000,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001298 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001299 self.pg0.enable_capture()
Klement Sekera3e0a3562016-12-19 09:05:21 +01001300 self.vpp_session.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001301 self.test_session.update(desired_min_tx=1000000, required_min_rx=1000000)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001302 bfd_session_up(self)
1303 reference_packet = wait_for_bfd_packet(self)
1304 time_mark = time.time()
1305 interval = 300000
1306 self.test_session.update(required_min_rx=interval)
Klement Sekera3e0a3562016-12-19 09:05:21 +01001307 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001308 extra_time = time.time() - time_mark
1309 p = wait_for_bfd_packet(self)
1310 # first packet is allowed to be late by time we spent doing the update
1311 # calculated in extra_time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001312 self.assert_in_range(
1313 p.time - reference_packet.time,
1314 0.95 * 0.75 * interval / USEC_IN_SEC,
1315 1.05 * interval / USEC_IN_SEC + extra_time,
1316 "time between BFD packets",
1317 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001318 reference_packet = p
1319 for dummy in range(3):
1320 p = wait_for_bfd_packet(self)
1321 diff = p.time - reference_packet.time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001322 self.assert_in_range(
1323 diff,
1324 0.95 * 0.75 * interval / USEC_IN_SEC,
1325 1.05 * interval / USEC_IN_SEC,
1326 "time between BFD packets",
1327 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001328 reference_packet = p
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001329
Klement Sekeraa57a9702017-02-02 06:58:07 +01001330 def test_modify_req_min_rx_double(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001331 """modify session - double required min rx"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001332 bfd_session_up(self)
1333 p = wait_for_bfd_packet(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001334 self.test_session.update(desired_min_tx=10000, required_min_rx=10000)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001335 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001336 # double required min rx
Klement Sekeraa57a9702017-02-02 06:58:07 +01001337 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001338 required_min_rx=2 * self.vpp_session.required_min_rx
1339 )
1340 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001341 # poll bit needs to be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001342 self.assertIn("P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet")
Klement Sekeraa57a9702017-02-02 06:58:07 +01001343 # finish poll sequence with final packet
1344 final = self.test_session.create_packet()
1345 final[BFD].flags = "F"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001346 timeout = (
1347 self.test_session.detect_mult
1348 * max(self.test_session.desired_min_tx, self.vpp_session.required_min_rx)
1349 / USEC_IN_SEC
1350 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001351 self.test_session.send_packet(final)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001352 time_mark = time.time()
Ole Troan4376ab22021-03-03 10:40:05 +01001353 e = self.vapi.wait_for_event(2 * timeout, "bfd_udp_session_event")
Klement Sekerad3ba5152017-02-14 03:09:17 +01001354 verify_event(self, e, expected_state=BFDState.down)
1355 time_to_event = time.time() - time_mark
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001356 self.assert_in_range(
1357 time_to_event, 0.9 * timeout, 1.1 * timeout, "session timeout"
1358 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001359
1360 def test_modify_req_min_rx_halve(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001361 """modify session - halve required min rx"""
Klement Sekeraa57a9702017-02-02 06:58:07 +01001362 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001363 required_min_rx=2 * self.vpp_session.required_min_rx
1364 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001365 bfd_session_up(self)
1366 p = wait_for_bfd_packet(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001367 self.test_session.update(desired_min_tx=10000, required_min_rx=10000)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001368 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001369 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001370 # halve required min rx
1371 old_required_min_rx = self.vpp_session.required_min_rx
1372 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001373 required_min_rx=self.vpp_session.required_min_rx // 2
1374 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001375 # now we wait 0.8*3*old-req-min-rx and the session should still be up
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001376 self.sleep(
1377 0.8 * self.vpp_session.detect_mult * old_required_min_rx / USEC_IN_SEC,
1378 "wait before finishing poll sequence",
1379 )
1380 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerad3ba5152017-02-14 03:09:17 +01001381 p = wait_for_bfd_packet(self)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001382 # poll bit needs to be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001383 self.assertIn("P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet")
Klement Sekeraa57a9702017-02-02 06:58:07 +01001384 # finish poll sequence with final packet
1385 final = self.test_session.create_packet()
1386 final[BFD].flags = "F"
1387 self.test_session.send_packet(final)
1388 # now the session should time out under new conditions
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001389 detection_time = (
1390 self.test_session.detect_mult
1391 * self.vpp_session.required_min_rx
1392 / USEC_IN_SEC
1393 )
Klement Sekera2e01dfa2017-04-03 08:10:08 +02001394 before = time.time()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001395 e = self.vapi.wait_for_event(2 * detection_time, "bfd_udp_session_event")
Klement Sekera2e01dfa2017-04-03 08:10:08 +02001396 after = time.time()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001397 self.assert_in_range(
1398 after - before,
1399 0.9 * detection_time,
1400 1.1 * detection_time,
1401 "time before bfd session goes down",
1402 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001403 verify_event(self, e, expected_state=BFDState.down)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001404
Klement Sekeraa57a9702017-02-02 06:58:07 +01001405 def test_modify_detect_mult(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001406 """modify detect multiplier"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001407 bfd_session_up(self)
1408 p = wait_for_bfd_packet(self)
Klement Sekeraa57a9702017-02-02 06:58:07 +01001409 self.vpp_session.modify_parameters(detect_mult=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001410 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
1411 self.assert_equal(
1412 self.vpp_session.detect_mult, p[BFD].detect_mult, "detect mult"
1413 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001414 # poll bit must not be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001415 self.assertNotIn(
1416 "P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet"
1417 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001418 self.vpp_session.modify_parameters(detect_mult=10)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001419 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
1420 self.assert_equal(
1421 self.vpp_session.detect_mult, p[BFD].detect_mult, "detect mult"
1422 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001423 # poll bit must not be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001424 self.assertNotIn(
1425 "P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet"
1426 )
Klement Sekeraa57a9702017-02-02 06:58:07 +01001427
Klement Sekera239790f2017-02-16 10:53:53 +01001428 def test_queued_poll(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001429 """test poll sequence queueing"""
Klement Sekera239790f2017-02-16 10:53:53 +01001430 bfd_session_up(self)
1431 p = wait_for_bfd_packet(self)
1432 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 required_min_rx=2 * self.vpp_session.required_min_rx
1434 )
Klement Sekera239790f2017-02-16 10:53:53 +01001435 p = wait_for_bfd_packet(self)
1436 poll_sequence_start = time.time()
1437 poll_sequence_length_min = 0.5
1438 send_final_after = time.time() + poll_sequence_length_min
1439 # poll bit needs to be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001440 self.assertIn("P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet")
1441 self.assert_equal(
1442 p[BFD].required_min_rx_interval,
1443 self.vpp_session.required_min_rx,
1444 "BFD required min rx interval",
1445 )
Klement Sekera239790f2017-02-16 10:53:53 +01001446 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001447 required_min_rx=2 * self.vpp_session.required_min_rx
1448 )
Klement Sekera239790f2017-02-16 10:53:53 +01001449 # 2nd poll sequence should be queued now
1450 # don't send the reply back yet, wait for some time to emulate
1451 # longer round-trip time
1452 packet_count = 0
1453 while time.time() < send_final_after:
1454 self.test_session.send_packet()
1455 p = wait_for_bfd_packet(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001456 self.assert_equal(
1457 len(self.vapi.collect_events()), 0, "number of bfd events"
1458 )
1459 self.assert_equal(
1460 p[BFD].required_min_rx_interval,
1461 self.vpp_session.required_min_rx,
1462 "BFD required min rx interval",
1463 )
Klement Sekera239790f2017-02-16 10:53:53 +01001464 packet_count += 1
1465 # poll bit must be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001466 self.assertIn(
1467 "P", p.sprintf("%BFD.flags%"), "Poll bit not set in BFD packet"
1468 )
Klement Sekera239790f2017-02-16 10:53:53 +01001469 final = self.test_session.create_packet()
1470 final[BFD].flags = "F"
1471 self.test_session.send_packet(final)
1472 # finish 1st with final
1473 poll_sequence_length = time.time() - poll_sequence_start
1474 # vpp must wait for some time before starting new poll sequence
1475 poll_no_2_started = False
1476 for dummy in range(2 * packet_count):
1477 p = wait_for_bfd_packet(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001478 self.assert_equal(
1479 len(self.vapi.collect_events()), 0, "number of bfd events"
1480 )
Klement Sekera239790f2017-02-16 10:53:53 +01001481 if "P" in p.sprintf("%BFD.flags%"):
1482 poll_no_2_started = True
1483 if time.time() < poll_sequence_start + poll_sequence_length:
1484 raise Exception("VPP started 2nd poll sequence too soon")
1485 final = self.test_session.create_packet()
1486 final[BFD].flags = "F"
1487 self.test_session.send_packet(final)
1488 break
1489 else:
1490 self.test_session.send_packet()
1491 self.assertTrue(poll_no_2_started, "2nd poll sequence not performed")
1492 # finish 2nd with final
1493 final = self.test_session.create_packet()
1494 final[BFD].flags = "F"
1495 self.test_session.send_packet(final)
1496 p = wait_for_bfd_packet(self)
1497 # poll bit must not be set
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001498 self.assertNotIn("P", p.sprintf("%BFD.flags%"), "Poll bit set in BFD packet")
Klement Sekera239790f2017-02-16 10:53:53 +01001499
Paul Vinciguerra7ade2f52019-12-06 11:06:02 -05001500 # returning inconsistent results requiring retries in per-patch tests
Klement Sekerab23ffd72021-05-31 16:08:53 +02001501 @unittest.skipUnless(config.extended, "part of extended tests")
Klement Sekera73884482017-02-23 09:26:30 +01001502 def test_poll_response(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001503 """test correct response to control frame with poll bit set"""
Klement Sekera73884482017-02-23 09:26:30 +01001504 bfd_session_up(self)
1505 poll = self.test_session.create_packet()
1506 poll[BFD].flags = "P"
1507 self.test_session.send_packet(poll)
1508 final = wait_for_bfd_packet(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001509 self, pcap_time_min=time.time() - self.vpp_clock_offset
1510 )
Klement Sekera73884482017-02-23 09:26:30 +01001511 self.assertIn("F", final.sprintf("%BFD.flags%"))
1512
Klement Sekerad3ba5152017-02-14 03:09:17 +01001513 def test_no_periodic_if_remote_demand(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001514 """no periodic frames outside poll sequence if remote demand set"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01001515 bfd_session_up(self)
1516 demand = self.test_session.create_packet()
1517 demand[BFD].flags = "D"
1518 self.test_session.send_packet(demand)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001519 transmit_time = (
1520 0.9
1521 * max(self.vpp_session.required_min_rx, self.test_session.desired_min_tx)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001522 / USEC_IN_SEC
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001523 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01001524 count = 0
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001525 for dummy in range(self.test_session.detect_mult * 2):
Paul Vinciguerra0f6602c2019-03-10 09:10:54 -07001526 self.sleep(transmit_time)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001527 self.test_session.send_packet(demand)
1528 try:
1529 p = wait_for_bfd_packet(self, timeout=0)
1530 self.logger.error(ppp("Received unexpected packet:", p))
1531 count += 1
1532 except CaptureTimeoutError:
1533 pass
1534 events = self.vapi.collect_events()
1535 for e in events:
1536 self.logger.error("Received unexpected event: %s", e)
1537 self.assert_equal(count, 0, "number of packets received")
1538 self.assert_equal(len(events), 0, "number of events received")
Klement Sekera46a87ad2017-01-02 08:22:23 +01001539
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001540 def test_echo_looped_back(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001541 """echo packets looped back"""
Abdel Baig17a91812024-09-03 11:52:20 -04001542
1543 if self.multihop:
1544 self.skipTest(
1545 f"Skipping because echo functionality is not supported with multihop"
1546 )
1547
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001548 bfd_session_up(self)
1549 stats_before = bfd_grab_stats_snapshot(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001550 self.pg0.enable_capture()
1551 echo_packet_count = 10
1552 # random source port low enough to increment a few times..
1553 udp_sport_tx = randint(1, 50000)
1554 udp_sport_rx = udp_sport_tx
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 echo_packet = (
1556 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1557 / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4)
1558 / UDP(dport=BFD.udp_dport_echo)
1559 / Raw("this should be looped back")
1560 )
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001561 for dummy in range(echo_packet_count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001562 self.sleep(0.01, "delay between echo packets")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001563 echo_packet[UDP].sport = udp_sport_tx
1564 udp_sport_tx += 1
1565 self.logger.debug(ppp("Sending packet:", echo_packet))
1566 self.pg0.add_stream(echo_packet)
1567 self.pg_start()
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001568 self.logger.debug(self.vapi.ppcli("show trace"))
1569 counter = 0
1570 bfd_control_packets_rx = 0
1571 while counter < echo_packet_count:
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001572 p = self.pg0.wait_for_packet(1)
1573 self.logger.debug(ppp("Got packet:", p))
1574 ether = p[Ether]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001575 self.assert_equal(self.pg0.remote_mac, ether.dst, "Destination MAC")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001576 self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC")
1577 ip = p[IP]
1578 self.assert_equal(self.pg0.remote_ip4, ip.dst, "Destination IP")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001579 udp = p[UDP]
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001580 if udp.dport == BFD.udp_dport:
1581 bfd_control_packets_rx += 1
1582 continue
1583 self.assert_equal(self.pg0.remote_ip4, ip.src, "Source IP")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001584 self.assert_equal(udp.dport, BFD.udp_dport_echo, "UDP destination port")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001585 self.assert_equal(udp.sport, udp_sport_rx, "UDP source port")
1586 udp_sport_rx += 1
Klement Sekera239790f2017-02-16 10:53:53 +01001587 # need to compare the hex payload here, otherwise BFD_vpp_echo
1588 # gets in way
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001589 self.assertEqual(
1590 scapy.compat.raw(p[UDP].payload),
1591 scapy.compat.raw(echo_packet[UDP].payload),
1592 "Received packet is not the echo packet sent",
1593 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001594 counter += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001595 self.assert_equal(
1596 udp_sport_tx,
1597 udp_sport_rx,
1598 "UDP source port (== ECHO packet identifier for test purposes)",
1599 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001600 stats_after = bfd_grab_stats_snapshot(self)
1601 diff = bfd_stats_diff(stats_before, stats_after)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001602 self.assertEqual(0, diff.rx, "RX counter bumped but no BFD packets sent")
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001603 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001604 0, diff.rx_echo, "RX echo counter bumped but no BFD session exists"
1605 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001606 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001607 0, diff.tx_echo, "TX echo counter bumped but no BFD session exists"
1608 )
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001609
Klement Sekera239790f2017-02-16 10:53:53 +01001610 def test_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001611 """echo function"""
Abdel Baig17a91812024-09-03 11:52:20 -04001612
1613 if self.multihop:
1614 self.skipTest(
1615 f"Skipping because echo functionality is not supported with multihop"
1616 )
1617
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001618 stats_before = bfd_grab_stats_snapshot(self)
Klement Sekera239790f2017-02-16 10:53:53 +01001619 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001620 self.test_session.update(required_min_echo_rx=150000)
Klement Sekera239790f2017-02-16 10:53:53 +01001621 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001622 detection_time = (
1623 self.test_session.detect_mult
1624 * self.vpp_session.required_min_rx
1625 / USEC_IN_SEC
1626 )
Klement Sekera239790f2017-02-16 10:53:53 +01001627 # echo shouldn't work without echo source set
Klement Sekera3cfa5582017-04-19 07:10:58 +00001628 for dummy in range(10):
1629 sleep = self.vpp_session.required_min_rx / USEC_IN_SEC
Klement Sekera239790f2017-02-16 10:53:53 +01001630 self.sleep(sleep, "delay before sending bfd packet")
1631 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001632 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
1633 self.assert_equal(
1634 p[BFD].required_min_rx_interval,
1635 self.vpp_session.required_min_rx,
1636 "BFD required min rx interval",
1637 )
Klement Sekera3cfa5582017-04-19 07:10:58 +00001638 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001639 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001640 echo_seen = False
Klement Sekera239790f2017-02-16 10:53:53 +01001641 # should be turned on - loopback echo packets
1642 for dummy in range(3):
1643 loop_until = time.time() + 0.75 * detection_time
1644 while time.time() < loop_until:
1645 p = self.pg0.wait_for_packet(1)
1646 self.logger.debug(ppp("Got packet:", p))
1647 if p[UDP].dport == BFD.udp_dport_echo:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001648 self.assert_equal(p[IP].dst, self.pg0.local_ip4, "BFD ECHO dst IP")
1649 self.assertNotEqual(
1650 p[IP].src,
1651 self.loopback0.local_ip4,
1652 "BFD ECHO src IP equal to loopback IP",
1653 )
Klement Sekera239790f2017-02-16 10:53:53 +01001654 self.logger.debug(ppp("Looping back packet:", p))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001655 self.assert_equal(
1656 p[Ether].dst,
1657 self.pg0.remote_mac,
1658 "ECHO packet destination MAC address",
1659 )
John Lo1904c472017-03-10 17:15:22 -05001660 p[Ether].dst = self.pg0.local_mac
Klement Sekera239790f2017-02-16 10:53:53 +01001661 self.pg0.add_stream(p)
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001662 self.test_session.rx_packets_echo += 1
1663 self.test_session.tx_packets_echo += 1
Klement Sekera239790f2017-02-16 10:53:53 +01001664 self.pg_start()
Klement Sekera3cfa5582017-04-19 07:10:58 +00001665 echo_seen = True
Klement Sekera239790f2017-02-16 10:53:53 +01001666 elif p.haslayer(BFD):
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001667 self.test_session.rx_packets += 1
Klement Sekera3cfa5582017-04-19 07:10:58 +00001668 if echo_seen:
1669 self.assertGreaterEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001670 p[BFD].required_min_rx_interval, 1000000
1671 )
Klement Sekera239790f2017-02-16 10:53:53 +01001672 if "P" in p.sprintf("%BFD.flags%"):
1673 final = self.test_session.create_packet()
1674 final[BFD].flags = "F"
1675 self.test_session.send_packet(final)
1676 else:
1677 raise Exception(ppp("Received unknown packet:", p))
1678
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001679 self.assert_equal(
1680 len(self.vapi.collect_events()), 0, "number of bfd events"
1681 )
Klement Sekera239790f2017-02-16 10:53:53 +01001682 self.test_session.send_packet()
Klement Sekera3cfa5582017-04-19 07:10:58 +00001683 self.assertTrue(echo_seen, "No echo packets received")
Klement Sekera239790f2017-02-16 10:53:53 +01001684
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001685 stats_after = bfd_grab_stats_snapshot(self)
1686 diff = bfd_stats_diff(stats_before, stats_after)
1687 # our rx is vpp tx and vice versa, also tolerate one packet off
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001688 self.assert_in_range(
1689 self.test_session.tx_packets, diff.rx - 1, diff.rx + 1, "RX counter"
1690 )
1691 self.assert_in_range(
1692 self.test_session.rx_packets, diff.tx - 1, diff.tx + 1, "TX counter"
1693 )
1694 self.assert_in_range(
1695 self.test_session.tx_packets_echo,
1696 diff.rx_echo - 1,
1697 diff.rx_echo + 1,
1698 "RX echo counter",
1699 )
1700 self.assert_in_range(
1701 self.test_session.rx_packets_echo,
1702 diff.tx_echo - 1,
1703 diff.tx_echo + 1,
1704 "TX echo counter",
1705 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00001706
Klement Sekera239790f2017-02-16 10:53:53 +01001707 def test_echo_fail(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001708 """session goes down if echo function fails"""
Abdel Baig17a91812024-09-03 11:52:20 -04001709
1710 if self.multihop:
1711 self.skipTest(
1712 f"Skipping because echo functionality is not supported with multihop"
1713 )
1714
Klement Sekera239790f2017-02-16 10:53:53 +01001715 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001716 self.test_session.update(required_min_echo_rx=150000)
Klement Sekera239790f2017-02-16 10:53:53 +01001717 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001718 detection_time = (
1719 self.test_session.detect_mult
1720 * self.vpp_session.required_min_rx
1721 / USEC_IN_SEC
1722 )
1723 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera239790f2017-02-16 10:53:53 +01001724 # echo function should be used now, but we will drop the echo packets
1725 verified_diag = False
1726 for dummy in range(3):
1727 loop_until = time.time() + 0.75 * detection_time
1728 while time.time() < loop_until:
1729 p = self.pg0.wait_for_packet(1)
1730 self.logger.debug(ppp("Got packet:", p))
1731 if p[UDP].dport == BFD.udp_dport_echo:
1732 # dropped
1733 pass
1734 elif p.haslayer(BFD):
1735 if "P" in p.sprintf("%BFD.flags%"):
1736 self.assertGreaterEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001737 p[BFD].required_min_rx_interval, 1000000
1738 )
Klement Sekera239790f2017-02-16 10:53:53 +01001739 final = self.test_session.create_packet()
1740 final[BFD].flags = "F"
1741 self.test_session.send_packet(final)
1742 if p[BFD].state == BFDState.down:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001743 self.assert_equal(
1744 p[BFD].diag, BFDDiagCode.echo_function_failed, BFDDiagCode
1745 )
Klement Sekera239790f2017-02-16 10:53:53 +01001746 verified_diag = True
1747 else:
1748 raise Exception(ppp("Received unknown packet:", p))
1749 self.test_session.send_packet()
1750 events = self.vapi.collect_events()
1751 self.assert_equal(len(events), 1, "number of bfd events")
1752 self.assert_equal(events[0].state, BFDState.down, BFDState)
1753 self.assertTrue(verified_diag, "Incorrect diagnostics code received")
1754
1755 def test_echo_stop(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001756 """echo function stops if peer sets required min echo rx zero"""
Abdel Baig17a91812024-09-03 11:52:20 -04001757
1758 if self.multihop:
1759 self.skipTest(
1760 f"Skipping because echo functionality is not supported with multihop"
1761 )
1762
Klement Sekera239790f2017-02-16 10:53:53 +01001763 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001764 self.test_session.update(required_min_echo_rx=150000)
Klement Sekera239790f2017-02-16 10:53:53 +01001765 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001766 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera239790f2017-02-16 10:53:53 +01001767 # wait for first echo packet
1768 while True:
1769 p = self.pg0.wait_for_packet(1)
1770 self.logger.debug(ppp("Got packet:", p))
1771 if p[UDP].dport == BFD.udp_dport_echo:
1772 self.logger.debug(ppp("Looping back packet:", p))
John Lo1904c472017-03-10 17:15:22 -05001773 p[Ether].dst = self.pg0.local_mac
Klement Sekera239790f2017-02-16 10:53:53 +01001774 self.pg0.add_stream(p)
1775 self.pg_start()
1776 break
1777 elif p.haslayer(BFD):
1778 # ignore BFD
1779 pass
1780 else:
1781 raise Exception(ppp("Received unknown packet:", p))
1782 self.test_session.update(required_min_echo_rx=0)
1783 self.test_session.send_packet()
1784 # echo packets shouldn't arrive anymore
1785 for dummy in range(5):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001786 wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera239790f2017-02-16 10:53:53 +01001787 self.test_session.send_packet()
1788 events = self.vapi.collect_events()
1789 self.assert_equal(len(events), 0, "number of bfd events")
1790
Klement Sekera73884482017-02-23 09:26:30 +01001791 def test_echo_source_removed(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001792 """echo function stops if echo source is removed"""
Abdel Baig17a91812024-09-03 11:52:20 -04001793
1794 if self.multihop:
1795 self.skipTest(
1796 f"Skipping because echo functionality is not supported with multihop"
1797 )
1798
Klement Sekera73884482017-02-23 09:26:30 +01001799 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001800 self.test_session.update(required_min_echo_rx=150000)
Klement Sekera73884482017-02-23 09:26:30 +01001801 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera73884482017-02-23 09:26:30 +01001803 # wait for first echo packet
1804 while True:
1805 p = self.pg0.wait_for_packet(1)
1806 self.logger.debug(ppp("Got packet:", p))
1807 if p[UDP].dport == BFD.udp_dport_echo:
1808 self.logger.debug(ppp("Looping back packet:", p))
John Lo1904c472017-03-10 17:15:22 -05001809 p[Ether].dst = self.pg0.local_mac
Klement Sekera73884482017-02-23 09:26:30 +01001810 self.pg0.add_stream(p)
1811 self.pg_start()
1812 break
1813 elif p.haslayer(BFD):
1814 # ignore BFD
1815 pass
1816 else:
1817 raise Exception(ppp("Received unknown packet:", p))
1818 self.vapi.bfd_udp_del_echo_source()
1819 self.test_session.send_packet()
1820 # echo packets shouldn't arrive anymore
1821 for dummy in range(5):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera73884482017-02-23 09:26:30 +01001823 self.test_session.send_packet()
1824 events = self.vapi.collect_events()
1825 self.assert_equal(len(events), 0, "number of bfd events")
1826
Klement Sekera239790f2017-02-16 10:53:53 +01001827 def test_stale_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001828 """stale echo packets don't keep a session up"""
Abdel Baig17a91812024-09-03 11:52:20 -04001829
1830 if self.multihop:
1831 self.skipTest(
1832 f"Skipping because echo functionality is not supported with multihop"
1833 )
1834
Klement Sekera239790f2017-02-16 10:53:53 +01001835 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001836 self.test_session.update(required_min_echo_rx=150000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001837 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera239790f2017-02-16 10:53:53 +01001838 self.test_session.send_packet()
1839 # should be turned on - loopback echo packets
1840 echo_packet = None
1841 timeout_at = None
1842 timeout_ok = False
1843 for dummy in range(10 * self.vpp_session.detect_mult):
1844 p = self.pg0.wait_for_packet(1)
1845 if p[UDP].dport == BFD.udp_dport_echo:
1846 if echo_packet is None:
1847 self.logger.debug(ppp("Got first echo packet:", p))
1848 echo_packet = p
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001849 timeout_at = (
1850 time.time()
1851 + self.vpp_session.detect_mult
1852 * self.test_session.required_min_echo_rx
1853 / USEC_IN_SEC
1854 )
Klement Sekera239790f2017-02-16 10:53:53 +01001855 else:
1856 self.logger.debug(ppp("Got followup echo packet:", p))
1857 self.logger.debug(ppp("Looping back first echo packet:", p))
John Lo1904c472017-03-10 17:15:22 -05001858 echo_packet[Ether].dst = self.pg0.local_mac
Klement Sekera239790f2017-02-16 10:53:53 +01001859 self.pg0.add_stream(echo_packet)
1860 self.pg_start()
1861 elif p.haslayer(BFD):
1862 self.logger.debug(ppp("Got packet:", p))
1863 if "P" in p.sprintf("%BFD.flags%"):
1864 final = self.test_session.create_packet()
1865 final[BFD].flags = "F"
1866 self.test_session.send_packet(final)
1867 if p[BFD].state == BFDState.down:
1868 self.assertIsNotNone(
1869 timeout_at,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001870 "Session went down before first echo packet received",
1871 )
Klement Sekera239790f2017-02-16 10:53:53 +01001872 now = time.time()
1873 self.assertGreaterEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001874 now,
1875 timeout_at,
1876 "Session timeout at %s, but is expected at %s"
1877 % (now, timeout_at),
1878 )
1879 self.assert_equal(
1880 p[BFD].diag, BFDDiagCode.echo_function_failed, BFDDiagCode
1881 )
Klement Sekera239790f2017-02-16 10:53:53 +01001882 events = self.vapi.collect_events()
1883 self.assert_equal(len(events), 1, "number of bfd events")
1884 self.assert_equal(events[0].state, BFDState.down, BFDState)
1885 timeout_ok = True
1886 break
1887 else:
1888 raise Exception(ppp("Received unknown packet:", p))
1889 self.test_session.send_packet()
1890 self.assertTrue(timeout_ok, "Expected timeout event didn't occur")
1891
1892 def test_invalid_echo_checksum(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001893 """echo packets with invalid checksum don't keep a session up"""
Abdel Baig17a91812024-09-03 11:52:20 -04001894
1895 if self.multihop:
1896 self.skipTest(
1897 f"Skipping because echo functionality is not supported with multihop"
1898 )
1899
Klement Sekera239790f2017-02-16 10:53:53 +01001900 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00001901 self.test_session.update(required_min_echo_rx=150000)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera239790f2017-02-16 10:53:53 +01001903 self.test_session.send_packet()
1904 # should be turned on - loopback echo packets
1905 timeout_at = None
1906 timeout_ok = False
1907 for dummy in range(10 * self.vpp_session.detect_mult):
1908 p = self.pg0.wait_for_packet(1)
1909 if p[UDP].dport == BFD.udp_dport_echo:
1910 self.logger.debug(ppp("Got echo packet:", p))
1911 if timeout_at is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001912 timeout_at = (
1913 time.time()
1914 + self.vpp_session.detect_mult
1915 * self.test_session.required_min_echo_rx
1916 / USEC_IN_SEC
1917 )
Klement Sekera239790f2017-02-16 10:53:53 +01001918 p[BFD_vpp_echo].checksum = getrandbits(64)
John Lo1904c472017-03-10 17:15:22 -05001919 p[Ether].dst = self.pg0.local_mac
Klement Sekera239790f2017-02-16 10:53:53 +01001920 self.logger.debug(ppp("Looping back modified echo packet:", p))
1921 self.pg0.add_stream(p)
1922 self.pg_start()
1923 elif p.haslayer(BFD):
1924 self.logger.debug(ppp("Got packet:", p))
1925 if "P" in p.sprintf("%BFD.flags%"):
1926 final = self.test_session.create_packet()
1927 final[BFD].flags = "F"
1928 self.test_session.send_packet(final)
1929 if p[BFD].state == BFDState.down:
1930 self.assertIsNotNone(
1931 timeout_at,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001932 "Session went down before first echo packet received",
1933 )
Klement Sekera239790f2017-02-16 10:53:53 +01001934 now = time.time()
1935 self.assertGreaterEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001936 now,
1937 timeout_at,
1938 "Session timeout at %s, but is expected at %s"
1939 % (now, timeout_at),
1940 )
1941 self.assert_equal(
1942 p[BFD].diag, BFDDiagCode.echo_function_failed, BFDDiagCode
1943 )
Klement Sekera239790f2017-02-16 10:53:53 +01001944 events = self.vapi.collect_events()
1945 self.assert_equal(len(events), 1, "number of bfd events")
1946 self.assert_equal(events[0].state, BFDState.down, BFDState)
1947 timeout_ok = True
1948 break
1949 else:
1950 raise Exception(ppp("Received unknown packet:", p))
1951 self.test_session.send_packet()
1952 self.assertTrue(timeout_ok, "Expected timeout event didn't occur")
1953
Klement Sekerac48829b2017-02-14 07:55:57 +01001954 def test_admin_up_down(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001955 """put session admin-up and admin-down"""
Klement Sekerac48829b2017-02-14 07:55:57 +01001956 bfd_session_up(self)
1957 self.vpp_session.admin_down()
1958 self.pg0.enable_capture()
Ole Troan4376ab22021-03-03 10:40:05 +01001959 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerac48829b2017-02-14 07:55:57 +01001960 verify_event(self, e, expected_state=BFDState.admin_down)
1961 for dummy in range(2):
1962 p = wait_for_bfd_packet(self)
Klement Sekera73884482017-02-23 09:26:30 +01001963 self.assert_equal(p[BFD].state, BFDState.admin_down, BFDState)
Klement Sekerac48829b2017-02-14 07:55:57 +01001964 # try to bring session up - shouldn't be possible
1965 self.test_session.update(state=BFDState.init)
1966 self.test_session.send_packet()
1967 for dummy in range(2):
1968 p = wait_for_bfd_packet(self)
Klement Sekera73884482017-02-23 09:26:30 +01001969 self.assert_equal(p[BFD].state, BFDState.admin_down, BFDState)
Klement Sekerac48829b2017-02-14 07:55:57 +01001970 self.vpp_session.admin_up()
1971 self.test_session.update(state=BFDState.down)
Ole Troan4376ab22021-03-03 10:40:05 +01001972 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerac48829b2017-02-14 07:55:57 +01001973 verify_event(self, e, expected_state=BFDState.down)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001974 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera73884482017-02-23 09:26:30 +01001975 self.assert_equal(p[BFD].state, BFDState.down, BFDState)
Klement Sekerac48829b2017-02-14 07:55:57 +01001976 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001977 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera73884482017-02-23 09:26:30 +01001978 self.assert_equal(p[BFD].state, BFDState.init, BFDState)
Ole Troan4376ab22021-03-03 10:40:05 +01001979 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerac48829b2017-02-14 07:55:57 +01001980 verify_event(self, e, expected_state=BFDState.init)
1981 self.test_session.update(state=BFDState.up)
1982 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001983 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera73884482017-02-23 09:26:30 +01001984 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Ole Troan4376ab22021-03-03 10:40:05 +01001985 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekerac48829b2017-02-14 07:55:57 +01001986 verify_event(self, e, expected_state=BFDState.up)
1987
Klement Sekera239790f2017-02-16 10:53:53 +01001988 def test_config_change_remote_demand(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001989 """configuration change while peer in demand mode"""
Klement Sekera239790f2017-02-16 10:53:53 +01001990 bfd_session_up(self)
1991 demand = self.test_session.create_packet()
1992 demand[BFD].flags = "D"
1993 self.test_session.send_packet(demand)
1994 self.vpp_session.modify_parameters(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001995 required_min_rx=2 * self.vpp_session.required_min_rx
1996 )
1997 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekera239790f2017-02-16 10:53:53 +01001998 # poll bit must be set
1999 self.assertIn("P", p.sprintf("%BFD.flags%"), "Poll bit not set")
2000 # terminate poll sequence
2001 final = self.test_session.create_packet()
2002 final[BFD].flags = "D+F"
2003 self.test_session.send_packet(final)
2004 # vpp should be quiet now again
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002005 transmit_time = (
2006 0.9
2007 * max(self.vpp_session.required_min_rx, self.test_session.desired_min_tx)
Klement Sekera239790f2017-02-16 10:53:53 +01002008 / USEC_IN_SEC
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002009 )
Klement Sekera239790f2017-02-16 10:53:53 +01002010 count = 0
2011 for dummy in range(self.test_session.detect_mult * 2):
Paul Vinciguerra0f6602c2019-03-10 09:10:54 -07002012 self.sleep(transmit_time)
Klement Sekera239790f2017-02-16 10:53:53 +01002013 self.test_session.send_packet(demand)
2014 try:
2015 p = wait_for_bfd_packet(self, timeout=0)
2016 self.logger.error(ppp("Received unexpected packet:", p))
2017 count += 1
2018 except CaptureTimeoutError:
2019 pass
2020 events = self.vapi.collect_events()
2021 for e in events:
2022 self.logger.error("Received unexpected event: %s", e)
2023 self.assert_equal(count, 0, "number of packets received")
2024 self.assert_equal(len(events), 0, "number of events received")
2025
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002026 def test_intf_deleted(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002027 """interface with bfd session deleted"""
Klement Sekerabeaded52018-06-24 10:30:37 +02002028 intf = VppLoInterface(self)
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002029 intf.config_ip4()
2030 intf.admin_up()
2031 sw_if_index = intf.sw_if_index
Abdel Baig17a91812024-09-03 11:52:20 -04002032
2033 # Setup routing info for multihop
2034 set_ipv4_pfx_route_info(self, intf, BFD_IPV4_REMOTE_ADDR2, False)
2035
2036 vpp_session = VppBFDUDPSession(
2037 self,
2038 intf,
2039 self.dst_ip_net,
2040 local_addr=self.src_ip_net,
2041 multihop=self.multihop,
2042 )
2043
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002044 vpp_session.add_vpp_config()
2045 vpp_session.admin_up()
2046 intf.remove_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04002047
2048 # BFD session is removed only for single-hop session
2049 if self.multihop:
2050 self.assertTrue(vpp_session.query_vpp_config())
2051 else:
2052 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
2053 self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index")
2054 self.assertFalse(vpp_session.query_vpp_config())
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002055
Klement Sekerad3ba5152017-02-14 03:09:17 +01002056
Abdel Baig17a91812024-09-03 11:52:20 -04002057@parameterized_class(
2058 [
2059 {"multihop": False},
2060 {"multihop": True},
2061 ]
2062)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00002063@tag_run_solo
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002064@tag_fixme_vpp_workers
Klement Sekerad3ba5152017-02-14 03:09:17 +01002065class BFD6TestCase(VppTestCase):
Klement Sekerad3ba5152017-02-14 03:09:17 +01002066 pg0 = None
Abdel Baig17a91812024-09-03 11:52:20 -04002067 interface0 = None
Klement Sekerad3ba5152017-02-14 03:09:17 +01002068 vpp_clock_offset = None
2069 vpp_session = None
2070 test_session = None
Abdel Baig17a91812024-09-03 11:52:20 -04002071 src_ip6_net = ""
2072 dst_ip6_net = ""
Klement Sekerad3ba5152017-02-14 03:09:17 +01002073
Klement Sekera46a87ad2017-01-02 08:22:23 +01002074 @classmethod
2075 def setUpClass(cls):
2076 super(BFD6TestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04002077 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
2078 cls.__doc__ = (
2079 f"""""Bidirectional Forwarding Detection (BFD) - IPv6, {hoptype_str}"""
2080 )
Damjan Marion07a38572018-01-21 06:44:18 -08002081 cls.vapi.cli("set log class bfd level debug")
Klement Sekera46a87ad2017-01-02 08:22:23 +01002082 try:
2083 cls.create_pg_interfaces([0])
2084 cls.pg0.config_ip6()
2085 cls.pg0.configure_ipv6_neighbors()
2086 cls.pg0.admin_up()
2087 cls.pg0.resolve_ndp()
Klement Sekerab9ef2732018-06-24 22:49:33 +02002088 cls.create_loopback_interfaces(1)
Klement Sekera239790f2017-02-16 10:53:53 +01002089 cls.loopback0 = cls.lo_interfaces[0]
2090 cls.loopback0.config_ip6()
2091 cls.loopback0.admin_up()
Klement Sekera46a87ad2017-01-02 08:22:23 +01002092
2093 except Exception:
2094 super(BFD6TestCase, cls).tearDownClass()
2095 raise
2096
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08002097 @classmethod
2098 def tearDownClass(cls):
2099 super(BFD6TestCase, cls).tearDownClass()
2100
Klement Sekera46a87ad2017-01-02 08:22:23 +01002101 def setUp(self):
2102 super(BFD6TestCase, self).setUp()
Klement Sekerab17dd962017-01-09 07:43:48 +01002103 self.factory = AuthKeyFactory()
Klement Sekera46a87ad2017-01-02 08:22:23 +01002104 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01002105 self.pg0.enable_capture()
Abdel Baig17a91812024-09-03 11:52:20 -04002106 set_ipv6_pfx_route_info(self, self.pg0, BFD_IPV6_REMOTE_ADDR, True)
2107
Klement Sekera46a87ad2017-01-02 08:22:23 +01002108 try:
Abdel Baig17a91812024-09-03 11:52:20 -04002109 if self.multihop:
2110 self.interface0 = None
2111 self.bfd_udp4_sessions = self.statistics[BFD_STATS_V4_MH_PATH]
2112 self.bfd_udp6_sessions = self.statistics[BFD_STATS_V6_MH_PATH]
2113 else:
2114 self.interface0 = self.pg0
2115 self.bfd_udp4_sessions = self.statistics[BFD_STATS_V4_SH_PATH]
2116 self.bfd_udp6_sessions = self.statistics[BFD_STATS_V6_SH_PATH]
2117
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002118 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002119 self,
2120 self.interface0,
2121 self.dst_ip6_net,
2122 local_addr=self.src_ip6_net,
2123 af=AF_INET6,
2124 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002125 )
Klement Sekera46a87ad2017-01-02 08:22:23 +01002126 self.vpp_session.add_vpp_config()
2127 self.vpp_session.admin_up()
Abdel Baig17a91812024-09-03 11:52:20 -04002128 self.test_session = BFDTestSession(
2129 self,
2130 self.pg0,
2131 AF_INET6,
2132 local_addr=self.src_ip6_net,
2133 peer_addr=self.dst_ip6_net,
2134 multihop=self.multihop,
2135 )
Klement Sekera46a87ad2017-01-02 08:22:23 +01002136 self.logger.debug(self.vapi.cli("show adj nbr"))
Jakub Grajciar4682feb2019-09-02 13:28:52 +02002137 except BaseException:
Klement Sekera46a87ad2017-01-02 08:22:23 +01002138 self.vapi.want_bfd_events(enable_disable=0)
2139 raise
2140
2141 def tearDown(self):
Abdel Baig17a91812024-09-03 11:52:20 -04002142 self.vpp_session.remove_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +01002143 if not self.vpp_dead:
2144 self.vapi.want_bfd_events(enable_disable=0)
2145 self.vapi.collect_events() # clear the event queue
2146 super(BFD6TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01002147
2148 def test_session_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002149 """bring BFD session up"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01002150 bfd_session_up(self)
Abdel Baig17a91812024-09-03 11:52:20 -04002151 if self.multihop:
2152 bfd_udp4_sessions = self.statistics[BFD_STATS_V4_MH_PATH]
2153 bfd_udp6_sessions = self.statistics[BFD_STATS_V6_MH_PATH]
2154 else:
2155 bfd_udp4_sessions = self.statistics[BFD_STATS_V4_SH_PATH]
2156 bfd_udp6_sessions = self.statistics[BFD_STATS_V6_SH_PATH]
2157
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002158 self.assert_equal(bfd_udp4_sessions, self.bfd_udp4_sessions)
2159 self.assert_equal(bfd_udp6_sessions - self.bfd_udp6_sessions, 1)
Klement Sekerab17dd962017-01-09 07:43:48 +01002160
Klement Sekera73884482017-02-23 09:26:30 +01002161 def test_session_up_by_ip(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002162 """bring BFD session up - first frame looked up by address pair"""
Klement Sekera73884482017-02-23 09:26:30 +01002163 self.logger.info("BFD: Sending Slow control frame")
2164 self.test_session.update(my_discriminator=randint(0, 40000000))
2165 self.test_session.send_packet()
2166 self.pg0.enable_capture()
2167 p = self.pg0.wait_for_packet(1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002168 self.assert_equal(
2169 p[BFD].your_discriminator,
2170 self.test_session.my_discriminator,
2171 "BFD - your discriminator",
2172 )
Klement Sekera73884482017-02-23 09:26:30 +01002173 self.assert_equal(p[BFD].state, BFDState.init, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002174 self.test_session.update(
2175 your_discriminator=p[BFD].my_discriminator, state=BFDState.up
2176 )
Klement Sekera73884482017-02-23 09:26:30 +01002177 self.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +01002178 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekera73884482017-02-23 09:26:30 +01002179 verify_event(self, e, expected_state=BFDState.init)
2180 self.logger.info("BFD: Sending Up")
2181 self.test_session.send_packet()
2182 self.logger.info("BFD: Waiting for event")
Ole Troan4376ab22021-03-03 10:40:05 +01002183 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
Klement Sekera73884482017-02-23 09:26:30 +01002184 verify_event(self, e, expected_state=BFDState.up)
2185 self.logger.info("BFD: Session is Up")
2186 self.test_session.update(state=BFDState.up)
2187 self.test_session.send_packet()
2188 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
2189
Klement Sekerab17dd962017-01-09 07:43:48 +01002190 def test_hold_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002191 """hold BFD session up"""
Klement Sekerad3ba5152017-02-14 03:09:17 +01002192 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002193 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01002194 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002195 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002196 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01002197 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
2198
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002199 def test_echo_looped_back(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002200 """echo packets looped back"""
Abdel Baig17a91812024-09-03 11:52:20 -04002201
2202 if self.multihop:
2203 self.skipTest(
2204 f"Skipping because echo functionality is not supported with multihop"
2205 )
2206
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002207 bfd_session_up(self)
2208 stats_before = bfd_grab_stats_snapshot(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002209 self.pg0.enable_capture()
2210 echo_packet_count = 10
2211 # random source port low enough to increment a few times..
2212 udp_sport_tx = randint(1, 50000)
2213 udp_sport_rx = udp_sport_tx
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002214 echo_packet = (
2215 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2216 / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6)
2217 / UDP(dport=BFD.udp_dport_echo)
2218 / Raw("this should be looped back")
2219 )
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002220 for dummy in range(echo_packet_count):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002221 self.sleep(0.01, "delay between echo packets")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002222 echo_packet[UDP].sport = udp_sport_tx
2223 udp_sport_tx += 1
2224 self.logger.debug(ppp("Sending packet:", echo_packet))
2225 self.pg0.add_stream(echo_packet)
2226 self.pg_start()
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002227 counter = 0
2228 bfd_control_packets_rx = 0
2229 while counter < echo_packet_count:
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002230 p = self.pg0.wait_for_packet(1)
2231 self.logger.debug(ppp("Got packet:", p))
2232 ether = p[Ether]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002233 self.assert_equal(self.pg0.remote_mac, ether.dst, "Destination MAC")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002234 self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC")
2235 ip = p[IPv6]
2236 self.assert_equal(self.pg0.remote_ip6, ip.dst, "Destination IP")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002237 udp = p[UDP]
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002238 if udp.dport == BFD.udp_dport:
2239 bfd_control_packets_rx += 1
2240 continue
2241 self.assert_equal(self.pg0.remote_ip6, ip.src, "Source IP")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002242 self.assert_equal(udp.dport, BFD.udp_dport_echo, "UDP destination port")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002243 self.assert_equal(udp.sport, udp_sport_rx, "UDP source port")
2244 udp_sport_rx += 1
Klement Sekera239790f2017-02-16 10:53:53 +01002245 # need to compare the hex payload here, otherwise BFD_vpp_echo
2246 # gets in way
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002247 self.assertEqual(
2248 scapy.compat.raw(p[UDP].payload),
2249 scapy.compat.raw(echo_packet[UDP].payload),
2250 "Received packet is not the echo packet sent",
2251 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002252 counter += 1
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002253 self.assert_equal(
2254 udp_sport_tx,
2255 udp_sport_rx,
2256 "UDP source port (== ECHO packet identifier for test purposes)",
2257 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002258 stats_after = bfd_grab_stats_snapshot(self)
2259 diff = bfd_stats_diff(stats_before, stats_after)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002260 self.assertEqual(0, diff.rx, "RX counter bumped but no BFD packets sent")
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002261 self.assertEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002262 0, diff.rx_echo, "RX echo counter bumped but no BFD session exists"
2263 )
2264 self.assertEqual(
2265 0, diff.tx_echo, "TX echo counter bumped but no BFD session exists"
2266 )
Klement Sekera239790f2017-02-16 10:53:53 +01002267
2268 def test_echo(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002269 """echo function"""
Abdel Baig17a91812024-09-03 11:52:20 -04002270
2271 if self.multihop:
2272 self.skipTest(
2273 f"Skipping because echo functionality is not supported with multihop"
2274 )
2275
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002276 stats_before = bfd_grab_stats_snapshot(self)
Klement Sekera239790f2017-02-16 10:53:53 +01002277 bfd_session_up(self)
Klement Sekera3cfa5582017-04-19 07:10:58 +00002278 self.test_session.update(required_min_echo_rx=150000)
Klement Sekera239790f2017-02-16 10:53:53 +01002279 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002280 detection_time = (
2281 self.test_session.detect_mult
2282 * self.vpp_session.required_min_rx
2283 / USEC_IN_SEC
2284 )
Klement Sekera239790f2017-02-16 10:53:53 +01002285 # echo shouldn't work without echo source set
Klement Sekera3cfa5582017-04-19 07:10:58 +00002286 for dummy in range(10):
2287 sleep = self.vpp_session.required_min_rx / USEC_IN_SEC
Klement Sekera239790f2017-02-16 10:53:53 +01002288 self.sleep(sleep, "delay before sending bfd packet")
2289 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002290 p = wait_for_bfd_packet(self, pcap_time_min=time.time() - self.vpp_clock_offset)
2291 self.assert_equal(
2292 p[BFD].required_min_rx_interval,
2293 self.vpp_session.required_min_rx,
2294 "BFD required min rx interval",
2295 )
Klement Sekera3cfa5582017-04-19 07:10:58 +00002296 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002297 self.vapi.bfd_udp_set_echo_source(sw_if_index=self.loopback0.sw_if_index)
Klement Sekera3cfa5582017-04-19 07:10:58 +00002298 echo_seen = False
Klement Sekera239790f2017-02-16 10:53:53 +01002299 # should be turned on - loopback echo packets
2300 for dummy in range(3):
2301 loop_until = time.time() + 0.75 * detection_time
2302 while time.time() < loop_until:
2303 p = self.pg0.wait_for_packet(1)
2304 self.logger.debug(ppp("Got packet:", p))
2305 if p[UDP].dport == BFD.udp_dport_echo:
2306 self.assert_equal(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002307 p[IPv6].dst, self.pg0.local_ip6, "BFD ECHO dst IP"
2308 )
2309 self.assertNotEqual(
2310 p[IPv6].src,
2311 self.loopback0.local_ip6,
2312 "BFD ECHO src IP equal to loopback IP",
2313 )
Klement Sekera239790f2017-02-16 10:53:53 +01002314 self.logger.debug(ppp("Looping back packet:", p))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002315 self.assert_equal(
2316 p[Ether].dst,
2317 self.pg0.remote_mac,
2318 "ECHO packet destination MAC address",
2319 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002320 self.test_session.rx_packets_echo += 1
2321 self.test_session.tx_packets_echo += 1
John Lo1904c472017-03-10 17:15:22 -05002322 p[Ether].dst = self.pg0.local_mac
Klement Sekera239790f2017-02-16 10:53:53 +01002323 self.pg0.add_stream(p)
2324 self.pg_start()
Klement Sekera3cfa5582017-04-19 07:10:58 +00002325 echo_seen = True
Klement Sekera239790f2017-02-16 10:53:53 +01002326 elif p.haslayer(BFD):
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002327 self.test_session.rx_packets += 1
Klement Sekera3cfa5582017-04-19 07:10:58 +00002328 if echo_seen:
2329 self.assertGreaterEqual(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002330 p[BFD].required_min_rx_interval, 1000000
2331 )
Klement Sekera239790f2017-02-16 10:53:53 +01002332 if "P" in p.sprintf("%BFD.flags%"):
2333 final = self.test_session.create_packet()
2334 final[BFD].flags = "F"
2335 self.test_session.send_packet(final)
2336 else:
2337 raise Exception(ppp("Received unknown packet:", p))
2338
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002339 self.assert_equal(
2340 len(self.vapi.collect_events()), 0, "number of bfd events"
2341 )
Klement Sekera239790f2017-02-16 10:53:53 +01002342 self.test_session.send_packet()
Klement Sekera3cfa5582017-04-19 07:10:58 +00002343 self.assertTrue(echo_seen, "No echo packets received")
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002344
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002345 stats_after = bfd_grab_stats_snapshot(self)
2346 diff = bfd_stats_diff(stats_before, stats_after)
2347 # our rx is vpp tx and vice versa, also tolerate one packet off
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002348 self.assert_in_range(
2349 self.test_session.tx_packets, diff.rx - 1, diff.rx + 1, "RX counter"
2350 )
2351 self.assert_in_range(
2352 self.test_session.rx_packets, diff.tx - 1, diff.tx + 1, "TX counter"
2353 )
2354 self.assert_in_range(
2355 self.test_session.tx_packets_echo,
2356 diff.rx_echo - 1,
2357 diff.rx_echo + 1,
2358 "RX echo counter",
2359 )
2360 self.assert_in_range(
2361 self.test_session.rx_packets_echo,
2362 diff.tx_echo - 1,
2363 diff.tx_echo + 1,
2364 "TX echo counter",
2365 )
Klement Sekeracdaf0d82022-02-14 20:20:22 +00002366
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002367 def test_intf_deleted(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002368 """interface with bfd session deleted"""
Klement Sekerabeaded52018-06-24 10:30:37 +02002369 intf = VppLoInterface(self)
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002370 intf.config_ip6()
2371 intf.admin_up()
2372 sw_if_index = intf.sw_if_index
Abdel Baig17a91812024-09-03 11:52:20 -04002373
2374 # Setup routing info for multihop
2375 set_ipv6_pfx_route_info(self, intf, BFD_IPV6_REMOTE_ADDR2, False)
2376
2377 vpp_session = VppBFDUDPSession(
2378 self,
2379 intf,
2380 self.dst_ip6_net,
2381 local_addr=self.src_ip6_net,
2382 af=AF_INET6,
2383 multihop=self.multihop,
2384 )
2385
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002386 vpp_session.add_vpp_config()
2387 vpp_session.admin_up()
2388 intf.remove_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04002389
2390 # BFD session is removed only for single-hop session
2391 if self.multihop:
2392 self.assertTrue(vpp_session.query_vpp_config())
2393 else:
2394 e = self.vapi.wait_for_event(1, "bfd_udp_session_event")
2395 self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index")
2396 self.assertFalse(vpp_session.query_vpp_config())
Klement Sekeraf3bcdbf2017-05-02 07:38:01 +02002397
Klement Sekerab17dd962017-01-09 07:43:48 +01002398
Abdel Baig17a91812024-09-03 11:52:20 -04002399@parameterized_class(
2400 [
2401 {"multihop": False},
2402 {"multihop": True},
2403 ]
2404)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00002405@tag_run_solo
Neale Ranns88fc83e2017-04-05 08:11:14 -07002406class BFDFIBTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002407 """BFD-FIB interactions (IPv6)"""
Neale Ranns88fc83e2017-04-05 08:11:14 -07002408
2409 vpp_session = None
2410 test_session = None
Abdel Baig17a91812024-09-03 11:52:20 -04002411 src_ip6_net = ""
2412 dst_ip6_net = ""
Neale Ranns88fc83e2017-04-05 08:11:14 -07002413
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08002414 @classmethod
2415 def setUpClass(cls):
2416 super(BFDFIBTestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04002417 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
2418 cls.__doc__ = f"""""BFD-FIB interactions (IPv6) - {hoptype_str}"""
2419 cls.vapi.cli("set log class bfd level debug")
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08002420
2421 @classmethod
2422 def tearDownClass(cls):
2423 super(BFDFIBTestCase, cls).tearDownClass()
2424
Neale Ranns88fc83e2017-04-05 08:11:14 -07002425 def setUp(self):
2426 super(BFDFIBTestCase, self).setUp()
2427 self.create_pg_interfaces(range(1))
Abdel Baig17a91812024-09-03 11:52:20 -04002428 self.create_loopback_interfaces(1)
2429 self.loopback0 = self.lo_interfaces[0]
2430 self.loopback0.config_ip6()
2431 self.loopback0.admin_up()
Neale Ranns88fc83e2017-04-05 08:11:14 -07002432
2433 self.vapi.want_bfd_events()
2434 self.pg0.enable_capture()
2435
2436 for i in self.pg_interfaces:
2437 i.admin_up()
2438 i.config_ip6()
2439 i.configure_ipv6_neighbors()
2440
Abdel Baig17a91812024-09-03 11:52:20 -04002441 set_ipv6_pfx_route_info(self, self.pg0, BFD_IPV6_REMOTE_ADDR, True)
2442
Neale Ranns88fc83e2017-04-05 08:11:14 -07002443 def tearDown(self):
2444 if not self.vpp_dead:
Jakub Grajciar4682feb2019-09-02 13:28:52 +02002445 self.vapi.want_bfd_events(enable_disable=False)
Neale Ranns88fc83e2017-04-05 08:11:14 -07002446
2447 super(BFDFIBTestCase, self).tearDown()
2448
2449 @staticmethod
2450 def pkt_is_not_data_traffic(p):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002451 """not data traffic implies BFD or the usual IPv6 ND/RA"""
Neale Ranns88fc83e2017-04-05 08:11:14 -07002452 if p.haslayer(BFD) or is_ipv6_misc(p):
2453 return True
2454 return False
2455
2456 def test_session_with_fib(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002457 """BFD-FIB interactions"""
Neale Ranns88fc83e2017-04-05 08:11:14 -07002458
2459 # packets to match against both of the routes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002460 p = [
2461 (
2462 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2463 / IPv6(src="3001::1", dst="2001::1")
2464 / UDP(sport=1234, dport=1234)
2465 / Raw(b"\xa5" * 100)
2466 ),
2467 (
2468 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2469 / IPv6(src="3001::1", dst="2002::1")
2470 / UDP(sport=1234, dport=1234)
2471 / Raw(b"\xa5" * 100)
2472 ),
2473 ]
Neale Ranns88fc83e2017-04-05 08:11:14 -07002474
Abdel Baig17a91812024-09-03 11:52:20 -04002475 # Two different routes via a next-hop that will have a BFD session.
2476 # One of the routes is non-recursive route only for single-hop.
2477 if self.multihop:
2478 intf_index = 0xFFFFFFFF
2479 else:
2480 intf_index = self.pg0.sw_if_index
2481
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002482 ip_2001_s_64 = VppIpRoute(
2483 self,
2484 "2001::",
2485 64,
Abdel Baig17a91812024-09-03 11:52:20 -04002486 [VppRoutePath(self.dst_ip6_net, intf_index)],
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002487 )
2488 ip_2002_s_64 = VppIpRoute(
Abdel Baig17a91812024-09-03 11:52:20 -04002489 self, "2002::", 64, [VppRoutePath(self.dst_ip6_net, 0xFFFFFFFF)]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002490 )
Neale Ranns88fc83e2017-04-05 08:11:14 -07002491 ip_2001_s_64.add_vpp_config()
2492 ip_2002_s_64.add_vpp_config()
2493
2494 # bring the session up now the routes are present
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002495 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002496 self,
2497 self.pg0,
2498 self.dst_ip6_net,
2499 local_addr=self.src_ip6_net,
2500 af=AF_INET6,
2501 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002502 )
Neale Ranns88fc83e2017-04-05 08:11:14 -07002503 self.vpp_session.add_vpp_config()
2504 self.vpp_session.admin_up()
Abdel Baig17a91812024-09-03 11:52:20 -04002505 self.test_session = BFDTestSession(
2506 self,
2507 self.pg0,
2508 AF_INET6,
2509 local_addr=self.src_ip6_net,
2510 peer_addr=self.dst_ip6_net,
2511 multihop=self.multihop,
2512 )
Neale Ranns88fc83e2017-04-05 08:11:14 -07002513
2514 # session is up - traffic passes
2515 bfd_session_up(self)
2516
2517 self.pg0.add_stream(p)
2518 self.pg_start()
2519 for packet in p:
2520 captured = self.pg0.wait_for_packet(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002521 1, filter_out_fn=self.pkt_is_not_data_traffic
2522 )
2523 self.assertEqual(captured[IPv6].dst, packet[IPv6].dst)
Neale Ranns88fc83e2017-04-05 08:11:14 -07002524
Abdel Baig17a91812024-09-03 11:52:20 -04002525 # session is down - traffic is dropped
Neale Ranns88fc83e2017-04-05 08:11:14 -07002526 bfd_session_down(self)
2527
2528 self.pg0.add_stream(p)
2529 self.pg_start()
2530 with self.assertRaises(CaptureTimeoutError):
2531 self.pg0.wait_for_packet(1, self.pkt_is_not_data_traffic)
2532
2533 # session is up - traffic passes
2534 bfd_session_up(self)
2535
2536 self.pg0.add_stream(p)
2537 self.pg_start()
2538 for packet in p:
2539 captured = self.pg0.wait_for_packet(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002540 1, filter_out_fn=self.pkt_is_not_data_traffic
2541 )
2542 self.assertEqual(captured[IPv6].dst, packet[IPv6].dst)
Neale Ranns88fc83e2017-04-05 08:11:14 -07002543
2544
Klement Sekerab23ffd72021-05-31 16:08:53 +02002545@unittest.skipUnless(config.extended, "part of extended tests")
Neale Ranns52cd4962019-06-05 10:28:17 +00002546class BFDTunTestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002547 """BFD over GRE tunnel"""
Neale Ranns52cd4962019-06-05 10:28:17 +00002548
2549 vpp_session = None
2550 test_session = None
2551
2552 @classmethod
2553 def setUpClass(cls):
2554 super(BFDTunTestCase, cls).setUpClass()
2555
2556 @classmethod
2557 def tearDownClass(cls):
2558 super(BFDTunTestCase, cls).tearDownClass()
2559
2560 def setUp(self):
2561 super(BFDTunTestCase, self).setUp()
2562 self.create_pg_interfaces(range(1))
2563
2564 self.vapi.want_bfd_events()
2565 self.pg0.enable_capture()
2566
2567 for i in self.pg_interfaces:
2568 i.admin_up()
2569 i.config_ip4()
2570 i.resolve_arp()
2571
2572 def tearDown(self):
2573 if not self.vpp_dead:
2574 self.vapi.want_bfd_events(enable_disable=0)
2575
2576 super(BFDTunTestCase, self).tearDown()
2577
2578 @staticmethod
2579 def pkt_is_not_data_traffic(p):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002580 """not data traffic implies BFD or the usual IPv6 ND/RA"""
Neale Ranns52cd4962019-06-05 10:28:17 +00002581 if p.haslayer(BFD) or is_ipv6_misc(p):
2582 return True
2583 return False
2584
2585 def test_bfd_o_gre(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002586 """BFD-o-GRE"""
Neale Ranns52cd4962019-06-05 10:28:17 +00002587
2588 # A GRE interface over which to run a BFD session
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002589 gre_if = VppGreInterface(self, self.pg0.local_ip4, self.pg0.remote_ip4)
Neale Ranns52cd4962019-06-05 10:28:17 +00002590 gre_if.add_vpp_config()
2591 gre_if.admin_up()
2592 gre_if.config_ip4()
2593
2594 # bring the session up now the routes are present
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002595 self.vpp_session = VppBFDUDPSession(
2596 self, gre_if, gre_if.remote_ip4, is_tunnel=True
2597 )
Neale Ranns52cd4962019-06-05 10:28:17 +00002598 self.vpp_session.add_vpp_config()
2599 self.vpp_session.admin_up()
2600
2601 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002602 self,
2603 gre_if,
2604 AF_INET,
2605 tunnel_header=(IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / GRE()),
2606 phy_interface=self.pg0,
2607 )
Neale Ranns52cd4962019-06-05 10:28:17 +00002608
2609 # packets to match against both of the routes
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002610 p = [
2611 (
2612 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2613 / IP(src=self.pg0.remote_ip4, dst=gre_if.remote_ip4)
2614 / UDP(sport=1234, dport=1234)
2615 / Raw(b"\xa5" * 100)
2616 )
2617 ]
Neale Ranns52cd4962019-06-05 10:28:17 +00002618
2619 # session is up - traffic passes
2620 bfd_session_up(self)
2621
2622 self.send_and_expect(self.pg0, p, self.pg0)
2623
2624 # bring session down
2625 bfd_session_down(self)
2626
2627
Abdel Baig17a91812024-09-03 11:52:20 -04002628@parameterized_class(
2629 [
2630 {"multihop": False},
2631 {"multihop": True},
2632 ]
2633)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00002634@tag_run_solo
Klement Sekerad3ba5152017-02-14 03:09:17 +01002635class BFDSHA1TestCase(VppTestCase):
Klement Sekerad3ba5152017-02-14 03:09:17 +01002636 pg0 = None
2637 vpp_clock_offset = None
2638 vpp_session = None
2639 test_session = None
Abdel Baig17a91812024-09-03 11:52:20 -04002640 src_ip_net = ""
2641 dst_ip_net = ""
Klement Sekerad3ba5152017-02-14 03:09:17 +01002642
Klement Sekerab17dd962017-01-09 07:43:48 +01002643 @classmethod
2644 def setUpClass(cls):
2645 super(BFDSHA1TestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04002646 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
2647 cls.__doc__ = f"""""Bidirectional Forwarding Detection (BFD) - SHA1 auth - {hoptype_str}"""
Damjan Marion07a38572018-01-21 06:44:18 -08002648 cls.vapi.cli("set log class bfd level debug")
Klement Sekerab17dd962017-01-09 07:43:48 +01002649 try:
2650 cls.create_pg_interfaces([0])
Abdel Baig17a91812024-09-03 11:52:20 -04002651 cls.create_loopback_interfaces(1)
2652 cls.loopback0 = cls.lo_interfaces[0]
2653 cls.loopback0.config_ip4()
2654 cls.loopback0.admin_up()
Klement Sekerab17dd962017-01-09 07:43:48 +01002655 cls.pg0.config_ip4()
Abdel Baig17a91812024-09-03 11:52:20 -04002656 cls.pg0.configure_ipv4_neighbors()
Klement Sekerab17dd962017-01-09 07:43:48 +01002657 cls.pg0.admin_up()
2658 cls.pg0.resolve_arp()
2659
2660 except Exception:
2661 super(BFDSHA1TestCase, cls).tearDownClass()
2662 raise
2663
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08002664 @classmethod
2665 def tearDownClass(cls):
2666 super(BFDSHA1TestCase, cls).tearDownClass()
2667
Klement Sekerab17dd962017-01-09 07:43:48 +01002668 def setUp(self):
2669 super(BFDSHA1TestCase, self).setUp()
2670 self.factory = AuthKeyFactory()
2671 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01002672 self.pg0.enable_capture()
Abdel Baig17a91812024-09-03 11:52:20 -04002673 set_ipv4_pfx_route_info(self, self.pg0, BFD_IPV4_REMOTE_ADDR, True)
Klement Sekerab17dd962017-01-09 07:43:48 +01002674
2675 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +01002676 if not self.vpp_dead:
Jakub Grajciar4682feb2019-09-02 13:28:52 +02002677 self.vapi.want_bfd_events(enable_disable=False)
Klement Sekerad3ba5152017-02-14 03:09:17 +01002678 self.vapi.collect_events() # clear the event queue
2679 super(BFDSHA1TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01002680
2681 def test_session_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002682 """bring BFD session up"""
Klement Sekerab17dd962017-01-09 07:43:48 +01002683 key = self.factory.create_random_key(self)
2684 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002685 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002686 self,
2687 self.pg0,
2688 self.dst_ip_net,
2689 local_addr=self.src_ip_net,
2690 multihop=self.multihop,
2691 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002692 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002693 self.vpp_session.add_vpp_config()
2694 self.vpp_session.admin_up()
2695 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002696 self,
2697 self.pg0,
2698 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04002699 local_addr=self.src_ip_net,
2700 peer_addr=self.dst_ip_net,
2701 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002702 sha1_key=key,
2703 bfd_key_id=self.vpp_session.bfd_key_id,
2704 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01002705 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002706
2707 def test_hold_up(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002708 """hold BFD session up"""
Klement Sekerab17dd962017-01-09 07:43:48 +01002709 key = self.factory.create_random_key(self)
2710 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002711 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002712 self,
2713 self.pg0,
2714 self.dst_ip_net,
2715 local_addr=self.src_ip_net,
2716 multihop=self.multihop,
2717 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002718 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002719 self.vpp_session.add_vpp_config()
2720 self.vpp_session.admin_up()
2721 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002722 self,
2723 self.pg0,
2724 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04002725 local_addr=self.src_ip_net,
2726 peer_addr=self.dst_ip_net,
2727 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002728 sha1_key=key,
2729 bfd_key_id=self.vpp_session.bfd_key_id,
2730 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01002731 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01002732 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01002733 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002734 self.test_session.send_packet()
2735 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
2736
2737 def test_hold_up_meticulous(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002738 """hold BFD session up - meticulous auth"""
2739 key = self.factory.create_random_key(self, BFDAuthType.meticulous_keyed_sha1)
Klement Sekerab17dd962017-01-09 07:43:48 +01002740 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002741 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002742 self,
2743 self.pg0,
2744 self.dst_ip_net,
2745 local_addr=self.src_ip_net,
2746 multihop=self.multihop,
2747 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002748 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002749 self.vpp_session.add_vpp_config()
2750 self.vpp_session.admin_up()
Klement Sekerad3ba5152017-02-14 03:09:17 +01002751 # specify sequence number so that it wraps
Klement Sekerab17dd962017-01-09 07:43:48 +01002752 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002753 self,
2754 self.pg0,
2755 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04002756 local_addr=self.src_ip_net,
2757 peer_addr=self.dst_ip_net,
2758 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002759 sha1_key=key,
Klement Sekerad3ba5152017-02-14 03:09:17 +01002760 bfd_key_id=self.vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002761 our_seq_number=0xFFFFFFFF - 4,
2762 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01002763 bfd_session_up(self)
2764 for dummy in range(30):
2765 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002766 self.test_session.inc_seq_num()
2767 self.test_session.send_packet()
2768 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
2769
2770 def test_send_bad_seq_number(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002771 """session is not kept alive by msgs with bad sequence numbers"""
2772 key = self.factory.create_random_key(self, BFDAuthType.meticulous_keyed_sha1)
Klement Sekerab17dd962017-01-09 07:43:48 +01002773 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002774 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002775 self,
2776 self.pg0,
2777 self.dst_ip_net,
2778 local_addr=self.src_ip_net,
2779 multihop=self.multihop,
2780 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002781 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002782 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01002783 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002784 self,
2785 self.pg0,
2786 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04002787 local_addr=self.src_ip_net,
2788 peer_addr=self.dst_ip_net,
2789 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002790 sha1_key=key,
2791 bfd_key_id=self.vpp_session.bfd_key_id,
2792 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01002793 bfd_session_up(self)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002794 detection_time = (
2795 self.test_session.detect_mult
2796 * self.vpp_session.required_min_rx
2797 / USEC_IN_SEC
2798 )
Klement Sekera239790f2017-02-16 10:53:53 +01002799 send_until = time.time() + 2 * detection_time
2800 while time.time() < send_until:
Klement Sekerad3ba5152017-02-14 03:09:17 +01002801 self.test_session.send_packet()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002802 self.sleep(
2803 0.7 * self.vpp_session.required_min_rx / USEC_IN_SEC,
2804 "time between bfd packets",
2805 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002806 e = self.vapi.collect_events()
2807 # session should be down now, because the sequence numbers weren't
2808 # updated
2809 self.assert_equal(len(e), 1, "number of bfd events")
Klement Sekerad3ba5152017-02-14 03:09:17 +01002810 verify_event(self, e[0], expected_state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01002811
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002812 def execute_rogue_session_scenario(
2813 self,
2814 vpp_bfd_udp_session,
2815 legitimate_test_session,
2816 rogue_test_session,
2817 rogue_bfd_values=None,
2818 ):
2819 """execute a rogue session interaction scenario
Klement Sekerab17dd962017-01-09 07:43:48 +01002820
2821 1. create vpp session, add config
2822 2. bring the legitimate session up
2823 3. copy the bfd values from legitimate session to rogue session
2824 4. apply rogue_bfd_values to rogue session
2825 5. set rogue session state to down
2826 6. send message to take the session down from the rogue session
2827 7. assert that the legitimate session is unaffected
2828 """
2829
2830 self.vpp_session = vpp_bfd_udp_session
2831 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01002832 self.test_session = legitimate_test_session
2833 # bring vpp session up
Klement Sekerad3ba5152017-02-14 03:09:17 +01002834 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002835 # send packet from rogue session
Klement Sekerad3ba5152017-02-14 03:09:17 +01002836 rogue_test_session.update(
2837 my_discriminator=self.test_session.my_discriminator,
2838 your_discriminator=self.test_session.your_discriminator,
2839 desired_min_tx=self.test_session.desired_min_tx,
2840 required_min_rx=self.test_session.required_min_rx,
2841 detect_mult=self.test_session.detect_mult,
2842 diag=self.test_session.diag,
2843 state=self.test_session.state,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002844 auth_type=self.test_session.auth_type,
2845 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002846 if rogue_bfd_values:
2847 rogue_test_session.update(**rogue_bfd_values)
2848 rogue_test_session.update(state=BFDState.down)
2849 rogue_test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +01002850 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01002851 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
2852
2853 def test_mismatch_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002854 """session is not brought down by unauthenticated msg"""
Klement Sekerab17dd962017-01-09 07:43:48 +01002855 key = self.factory.create_random_key(self)
2856 key.add_vpp_config()
2857 vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002858 self,
2859 self.pg0,
2860 self.dst_ip_net,
2861 local_addr=self.src_ip_net,
2862 multihop=self.multihop,
2863 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002864 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002865 legitimate_test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002866 self,
2867 self.pg0,
2868 AF_INET,
2869 local_addr=self.src_ip_net,
2870 peer_addr=self.dst_ip_net,
2871 multihop=self.multihop,
2872 sha1_key=key,
2873 bfd_key_id=vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002874 )
Abdel Baig17a91812024-09-03 11:52:20 -04002875 rogue_test_session = BFDTestSession(
2876 self,
2877 self.pg0,
2878 AF_INET,
2879 local_addr=self.src_ip_net,
2880 peer_addr=self.dst_ip_net,
2881 multihop=self.multihop,
2882 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002883 self.execute_rogue_session_scenario(
2884 vpp_session, legitimate_test_session, rogue_test_session
2885 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002886
2887 def test_mismatch_bfd_key_id(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002888 """session is not brought down by msg with non-existent key-id"""
Klement Sekerab17dd962017-01-09 07:43:48 +01002889 key = self.factory.create_random_key(self)
2890 key.add_vpp_config()
2891 vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002892 self,
2893 self.pg0,
2894 self.dst_ip_net,
2895 local_addr=self.src_ip_net,
2896 multihop=self.multihop,
2897 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002898 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002899 # pick a different random bfd key id
2900 x = randint(0, 255)
2901 while x == vpp_session.bfd_key_id:
2902 x = randint(0, 255)
2903 legitimate_test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002904 self,
2905 self.pg0,
2906 AF_INET,
2907 local_addr=self.src_ip_net,
2908 peer_addr=self.dst_ip_net,
2909 multihop=self.multihop,
2910 sha1_key=key,
2911 bfd_key_id=vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002912 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002913 rogue_test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002914 self,
2915 self.pg0,
2916 AF_INET,
2917 local_addr=self.src_ip_net,
2918 peer_addr=self.dst_ip_net,
2919 multihop=self.multihop,
2920 sha1_key=key,
2921 bfd_key_id=x,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002922 )
2923 self.execute_rogue_session_scenario(
2924 vpp_session, legitimate_test_session, rogue_test_session
2925 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002926
2927 def test_mismatched_auth_type(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002928 """session is not brought down by msg with wrong auth type"""
Klement Sekerab17dd962017-01-09 07:43:48 +01002929 key = self.factory.create_random_key(self)
2930 key.add_vpp_config()
2931 vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002932 self,
2933 self.pg0,
2934 self.dst_ip_net,
2935 local_addr=self.src_ip_net,
2936 multihop=self.multihop,
2937 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002938 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002939 legitimate_test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002940 self,
2941 self.pg0,
2942 AF_INET,
2943 local_addr=self.src_ip_net,
2944 peer_addr=self.dst_ip_net,
2945 multihop=self.multihop,
2946 sha1_key=key,
2947 bfd_key_id=vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002948 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002949 rogue_test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002950 self,
2951 self.pg0,
2952 AF_INET,
2953 local_addr=self.src_ip_net,
2954 peer_addr=self.dst_ip_net,
2955 multihop=self.multihop,
2956 sha1_key=key,
2957 bfd_key_id=vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002958 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002959 self.execute_rogue_session_scenario(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002960 vpp_session,
2961 legitimate_test_session,
2962 rogue_test_session,
2963 {"auth_type": BFDAuthType.keyed_md5},
2964 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002965
2966 def test_restart(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002967 """simulate remote peer restart and resynchronization"""
2968 key = self.factory.create_random_key(self, BFDAuthType.meticulous_keyed_sha1)
Klement Sekerab17dd962017-01-09 07:43:48 +01002969 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002970 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04002971 self,
2972 self.pg0,
2973 self.dst_ip_net,
2974 local_addr=self.src_ip_net,
2975 multihop=self.multihop,
2976 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002977 )
Klement Sekerab17dd962017-01-09 07:43:48 +01002978 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01002979 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002980 self,
2981 self.pg0,
2982 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04002983 local_addr=self.src_ip_net,
2984 peer_addr=self.dst_ip_net,
2985 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002986 sha1_key=key,
2987 bfd_key_id=self.vpp_session.bfd_key_id,
2988 our_seq_number=0,
2989 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01002990 bfd_session_up(self)
2991 # don't send any packets for 2*detection_time
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002992 detection_time = (
2993 self.test_session.detect_mult
2994 * self.vpp_session.required_min_rx
2995 / USEC_IN_SEC
2996 )
Klement Sekera87134932017-03-07 11:39:27 +01002997 self.sleep(2 * detection_time, "simulating peer restart")
Klement Sekerad3ba5152017-02-14 03:09:17 +01002998 events = self.vapi.collect_events()
2999 self.assert_equal(len(events), 1, "number of bfd events")
3000 verify_event(self, events[0], expected_state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01003001 self.test_session.update(state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01003002 # reset sequence number
3003 self.test_session.our_seq_number = 0
Klement Sekerad3ba5152017-02-14 03:09:17 +01003004 self.test_session.vpp_seq_number = None
3005 # now throw away any pending packets
3006 self.pg0.enable_capture()
Klement Sekera4d39f9c2020-01-17 10:01:52 +00003007 self.test_session.my_discriminator = 0
Klement Sekerad3ba5152017-02-14 03:09:17 +01003008 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01003009
3010
Abdel Baig17a91812024-09-03 11:52:20 -04003011@parameterized_class(
3012 [
3013 {"multihop": False},
3014 {"multihop": True},
3015 ]
3016)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00003017@tag_run_solo
Klement Sekerad3ba5152017-02-14 03:09:17 +01003018class BFDAuthOnOffTestCase(VppTestCase):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003019 pg0 = None
3020 vpp_session = None
3021 test_session = None
3022
Klement Sekerab17dd962017-01-09 07:43:48 +01003023 @classmethod
3024 def setUpClass(cls):
3025 super(BFDAuthOnOffTestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04003026 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
3027 cls.__doc__ = f"""""Bidirectional Forwarding Detection (BFD) - changing auth - {hoptype_str}"""
Damjan Marion07a38572018-01-21 06:44:18 -08003028 cls.vapi.cli("set log class bfd level debug")
Klement Sekerab17dd962017-01-09 07:43:48 +01003029 try:
3030 cls.create_pg_interfaces([0])
Abdel Baig17a91812024-09-03 11:52:20 -04003031 cls.create_loopback_interfaces(1)
3032 cls.loopback0 = cls.lo_interfaces[0]
3033 cls.loopback0.config_ip4()
3034 cls.loopback0.admin_up()
Klement Sekerab17dd962017-01-09 07:43:48 +01003035 cls.pg0.config_ip4()
Abdel Baig17a91812024-09-03 11:52:20 -04003036 cls.pg0.configure_ipv4_neighbors()
Klement Sekerab17dd962017-01-09 07:43:48 +01003037 cls.pg0.admin_up()
3038 cls.pg0.resolve_arp()
3039
3040 except Exception:
3041 super(BFDAuthOnOffTestCase, cls).tearDownClass()
3042 raise
3043
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08003044 @classmethod
3045 def tearDownClass(cls):
3046 super(BFDAuthOnOffTestCase, cls).tearDownClass()
3047
Klement Sekerab17dd962017-01-09 07:43:48 +01003048 def setUp(self):
3049 super(BFDAuthOnOffTestCase, self).setUp()
3050 self.factory = AuthKeyFactory()
3051 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01003052 self.pg0.enable_capture()
Abdel Baig17a91812024-09-03 11:52:20 -04003053 set_ipv4_pfx_route_info(self, self.pg0, BFD_IPV4_REMOTE_ADDR, True)
Klement Sekerab17dd962017-01-09 07:43:48 +01003054
3055 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003056 if not self.vpp_dead:
Jakub Grajciar4682feb2019-09-02 13:28:52 +02003057 self.vapi.want_bfd_events(enable_disable=False)
Klement Sekerad3ba5152017-02-14 03:09:17 +01003058 self.vapi.collect_events() # clear the event queue
3059 super(BFDAuthOnOffTestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01003060
3061 def test_auth_on_immediate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003062 """turn auth on without disturbing session state (immediate)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003063 key = self.factory.create_random_key(self)
3064 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003065 self.vpp_session = VppBFDUDPSession(
3066 self,
3067 self.pg0,
3068 self.dst_ip_net,
3069 local_addr=self.src_ip_net,
3070 multihop=self.multihop,
3071 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003072 self.vpp_session.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003073 self.test_session = BFDTestSession(
3074 self,
3075 self.pg0,
3076 AF_INET,
3077 local_addr=self.src_ip_net,
3078 peer_addr=self.dst_ip_net,
3079 multihop=self.multihop,
3080 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003081 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003082 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003083 p = wait_for_bfd_packet(self)
3084 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003085 self.test_session.send_packet()
3086 self.vpp_session.activate_auth(key)
3087 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
3088 self.test_session.sha1_key = key
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003089 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003090 p = wait_for_bfd_packet(self)
3091 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003092 self.test_session.send_packet()
3093 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003094 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01003095
3096 def test_auth_off_immediate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003097 """turn auth off without disturbing session state (immediate)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003098 key = self.factory.create_random_key(self)
3099 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003100 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003101 self,
3102 self.pg0,
3103 self.dst_ip_net,
3104 local_addr=self.src_ip_net,
3105 multihop=self.multihop,
3106 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003107 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003108 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01003109 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003110 self,
3111 self.pg0,
3112 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04003113 local_addr=self.src_ip_net,
3114 peer_addr=self.dst_ip_net,
3115 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003116 sha1_key=key,
3117 bfd_key_id=self.vpp_session.bfd_key_id,
3118 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003119 bfd_session_up(self)
3120 # self.vapi.want_bfd_events(enable_disable=0)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003121 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003122 p = wait_for_bfd_packet(self)
3123 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
3124 self.test_session.inc_seq_num()
Klement Sekerab17dd962017-01-09 07:43:48 +01003125 self.test_session.send_packet()
3126 self.vpp_session.deactivate_auth()
3127 self.test_session.bfd_key_id = None
3128 self.test_session.sha1_key = None
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003129 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003130 p = wait_for_bfd_packet(self)
3131 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
3132 self.test_session.inc_seq_num()
Klement Sekerab17dd962017-01-09 07:43:48 +01003133 self.test_session.send_packet()
3134 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003135 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01003136
3137 def test_auth_change_key_immediate(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003138 """change auth key without disturbing session state (immediate)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003139 key1 = self.factory.create_random_key(self)
3140 key1.add_vpp_config()
3141 key2 = self.factory.create_random_key(self)
3142 key2.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003143 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003144 self,
3145 self.pg0,
3146 self.dst_ip_net,
3147 local_addr=self.src_ip_net,
3148 multihop=self.multihop,
3149 sha1_key=key1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003150 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003151 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01003152 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003153 self,
3154 self.pg0,
3155 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04003156 local_addr=self.src_ip_net,
3157 peer_addr=self.dst_ip_net,
3158 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003159 sha1_key=key1,
3160 bfd_key_id=self.vpp_session.bfd_key_id,
3161 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003162 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003163 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003164 p = wait_for_bfd_packet(self)
3165 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003166 self.test_session.send_packet()
3167 self.vpp_session.activate_auth(key2)
3168 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
3169 self.test_session.sha1_key = key2
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003170 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003171 p = wait_for_bfd_packet(self)
3172 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003173 self.test_session.send_packet()
3174 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003175 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01003176
3177 def test_auth_on_delayed(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003178 """turn auth on without disturbing session state (delayed)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003179 key = self.factory.create_random_key(self)
3180 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003181 self.vpp_session = VppBFDUDPSession(
3182 self,
3183 self.pg0,
3184 self.dst_ip_net,
3185 local_addr=self.src_ip_net,
3186 multihop=self.multihop,
3187 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003188 self.vpp_session.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003189 self.test_session = BFDTestSession(
3190 self,
3191 self.pg0,
3192 AF_INET,
3193 local_addr=self.src_ip_net,
3194 peer_addr=self.dst_ip_net,
3195 multihop=self.multihop,
3196 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003197 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003198 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003199 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01003200 self.test_session.send_packet()
3201 self.vpp_session.activate_auth(key, delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003202 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003203 p = wait_for_bfd_packet(self)
3204 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003205 self.test_session.send_packet()
3206 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
3207 self.test_session.sha1_key = key
3208 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003209 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003210 p = wait_for_bfd_packet(self)
3211 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003212 self.test_session.send_packet()
3213 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003214 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01003215
3216 def test_auth_off_delayed(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003217 """turn auth off without disturbing session state (delayed)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003218 key = self.factory.create_random_key(self)
3219 key.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003220 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003221 self,
3222 self.pg0,
3223 self.dst_ip_net,
3224 local_addr=self.src_ip_net,
3225 multihop=self.multihop,
3226 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003227 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003228 self.vpp_session.add_vpp_config()
Klement Sekerab17dd962017-01-09 07:43:48 +01003229 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003230 self,
3231 self.pg0,
3232 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04003233 local_addr=self.src_ip_net,
3234 peer_addr=self.dst_ip_net,
3235 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003236 sha1_key=key,
3237 bfd_key_id=self.vpp_session.bfd_key_id,
3238 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003239 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003240 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003241 p = wait_for_bfd_packet(self)
3242 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003243 self.test_session.send_packet()
3244 self.vpp_session.deactivate_auth(delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003245 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003246 p = wait_for_bfd_packet(self)
3247 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003248 self.test_session.send_packet()
3249 self.test_session.bfd_key_id = None
3250 self.test_session.sha1_key = None
3251 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003252 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003253 p = wait_for_bfd_packet(self)
3254 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003255 self.test_session.send_packet()
3256 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003257 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekerab17dd962017-01-09 07:43:48 +01003258
3259 def test_auth_change_key_delayed(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003260 """change auth key without disturbing session state (delayed)"""
Klement Sekerab17dd962017-01-09 07:43:48 +01003261 key1 = self.factory.create_random_key(self)
3262 key1.add_vpp_config()
3263 key2 = self.factory.create_random_key(self)
3264 key2.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003265 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003266 self,
3267 self.pg0,
3268 self.dst_ip_net,
3269 local_addr=self.src_ip_net,
3270 multihop=self.multihop,
3271 sha1_key=key1,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003272 )
Klement Sekerab17dd962017-01-09 07:43:48 +01003273 self.vpp_session.add_vpp_config()
3274 self.vpp_session.admin_up()
3275 self.test_session = BFDTestSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003276 self,
3277 self.pg0,
3278 AF_INET,
Abdel Baig17a91812024-09-03 11:52:20 -04003279 local_addr=self.src_ip_net,
3280 peer_addr=self.dst_ip_net,
3281 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003282 sha1_key=key1,
3283 bfd_key_id=self.vpp_session.bfd_key_id,
3284 )
Klement Sekerad3ba5152017-02-14 03:09:17 +01003285 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003286 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003287 p = wait_for_bfd_packet(self)
3288 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003289 self.test_session.send_packet()
3290 self.vpp_session.activate_auth(key2, delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003291 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003292 p = wait_for_bfd_packet(self)
3293 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003294 self.test_session.send_packet()
3295 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
3296 self.test_session.sha1_key = key2
3297 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01003298 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01003299 p = wait_for_bfd_packet(self)
3300 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01003301 self.test_session.send_packet()
3302 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003303 self.assert_equal(len(self.vapi.collect_events()), 0, "number of bfd events")
Klement Sekera46a87ad2017-01-02 08:22:23 +01003304
Klement Sekera73884482017-02-23 09:26:30 +01003305
Abdel Baig17a91812024-09-03 11:52:20 -04003306@parameterized_class(
3307 [
3308 {"multihop": False},
3309 {"multihop": True},
3310 ]
3311)
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00003312@tag_run_solo
Klement Sekera73884482017-02-23 09:26:30 +01003313class BFDCLITestCase(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003314 """Bidirectional Forwarding Detection (BFD) (CLI)"""
3315
Klement Sekera73884482017-02-23 09:26:30 +01003316 pg0 = None
3317
3318 @classmethod
3319 def setUpClass(cls):
3320 super(BFDCLITestCase, cls).setUpClass()
Abdel Baig17a91812024-09-03 11:52:20 -04003321 hoptype_str = "MultiHop" if cls.multihop else "SingleHop"
3322 cls.__doc__ = (
3323 f"""""Bidirectional Forwarding Detection (BFD) - CLI - {hoptype_str}"""
3324 )
Damjan Marion07a38572018-01-21 06:44:18 -08003325 cls.vapi.cli("set log class bfd level debug")
Klement Sekera73884482017-02-23 09:26:30 +01003326 try:
Abdel Baig17a91812024-09-03 11:52:20 -04003327 cls.create_pg_interfaces([0])
3328 cls.create_loopback_interfaces(1)
3329 cls.loopback0 = cls.lo_interfaces[0]
3330 cls.loopback0.config_ip4()
3331 cls.loopback0.config_ip6()
3332 cls.loopback0.admin_up()
Klement Sekera73884482017-02-23 09:26:30 +01003333 cls.pg0.config_ip4()
3334 cls.pg0.config_ip6()
Abdel Baig17a91812024-09-03 11:52:20 -04003335 cls.pg0.configure_ipv4_neighbors()
3336 cls.pg0.admin_up()
Klement Sekera73884482017-02-23 09:26:30 +01003337 cls.pg0.resolve_arp()
3338 cls.pg0.resolve_ndp()
3339
3340 except Exception:
3341 super(BFDCLITestCase, cls).tearDownClass()
3342 raise
3343
Paul Vinciguerra8d991d92019-01-25 14:05:48 -08003344 @classmethod
3345 def tearDownClass(cls):
3346 super(BFDCLITestCase, cls).tearDownClass()
3347
Klement Sekera73884482017-02-23 09:26:30 +01003348 def setUp(self):
3349 super(BFDCLITestCase, self).setUp()
3350 self.factory = AuthKeyFactory()
3351 self.pg0.enable_capture()
Abdel Baig17a91812024-09-03 11:52:20 -04003352 set_ipv4_pfx_route_info(self, self.pg0, BFD_IPV4_REMOTE_ADDR, True)
3353 set_ipv6_pfx_route_info(self, self.pg0, BFD_IPV6_REMOTE_ADDR, True)
3354
3355 if self.multihop:
3356 self.cli_str = "multihop"
3357 else:
3358 self.cli_str = "interface %s" % self.pg0.name
Klement Sekera73884482017-02-23 09:26:30 +01003359
3360 def tearDown(self):
3361 try:
Jakub Grajciar4682feb2019-09-02 13:28:52 +02003362 self.vapi.want_bfd_events(enable_disable=False)
Klement Sekera73884482017-02-23 09:26:30 +01003363 except UnexpectedApiReturnValueError:
3364 # some tests aren't subscribed, so this is not an issue
3365 pass
3366 self.vapi.collect_events() # clear the event queue
3367 super(BFDCLITestCase, self).tearDown()
3368
3369 def cli_verify_no_response(self, cli):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003370 """execute a CLI, asserting that the response is empty"""
3371 self.assert_equal(self.vapi.cli(cli), "", "CLI command response")
Klement Sekera73884482017-02-23 09:26:30 +01003372
3373 def cli_verify_response(self, cli, expected):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003374 """execute a CLI, asserting that the response matches expectation"""
Jakub Grajciar4682feb2019-09-02 13:28:52 +02003375 try:
3376 reply = self.vapi.cli(cli)
3377 except CliFailedCommandError as cli_error:
3378 reply = str(cli_error)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003379 self.assert_equal(reply.strip(), expected, "CLI command response")
Klement Sekera73884482017-02-23 09:26:30 +01003380
3381 def test_show(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003382 """show commands"""
Klement Sekera73884482017-02-23 09:26:30 +01003383 k1 = self.factory.create_random_key(self)
3384 k1.add_vpp_config()
3385 k2 = self.factory.create_random_key(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003386 self, auth_type=BFDAuthType.meticulous_keyed_sha1
3387 )
Klement Sekera73884482017-02-23 09:26:30 +01003388 k2.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003389 s1 = VppBFDUDPSession(
3390 self,
3391 self.pg0,
3392 self.dst_ip_net,
3393 local_addr=self.src_ip_net,
3394 multihop=self.multihop,
3395 )
Klement Sekera73884482017-02-23 09:26:30 +01003396 s1.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003397 s2 = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003398 self,
3399 self.pg0,
3400 self.dst_ip6_net,
3401 local_addr=self.src_ip6_net,
3402 af=AF_INET6,
3403 multihop=self.multihop,
3404 sha1_key=k2,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003405 )
Klement Sekera73884482017-02-23 09:26:30 +01003406 s2.add_vpp_config()
3407 self.logger.info(self.vapi.ppcli("show bfd keys"))
3408 self.logger.info(self.vapi.ppcli("show bfd sessions"))
3409 self.logger.info(self.vapi.ppcli("show bfd"))
3410
3411 def test_set_del_sha1_key(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003412 """set/delete SHA1 auth key"""
Klement Sekera73884482017-02-23 09:26:30 +01003413 k = self.factory.create_random_key(self)
3414 self.registry.register(k, self.logger)
3415 self.cli_verify_no_response(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003416 "bfd key set conf-key-id %s type keyed-sha1 secret %s"
3417 % (
3418 k.conf_key_id,
3419 "".join("{:02x}".format(scapy.compat.orb(c)) for c in k.key),
3420 )
3421 )
Klement Sekera73884482017-02-23 09:26:30 +01003422 self.assertTrue(k.query_vpp_config())
3423 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003424 self,
3425 self.pg0,
3426 self.dst_ip_net,
3427 local_addr=self.src_ip_net,
3428 multihop=self.multihop,
3429 sha1_key=k,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003430 )
Klement Sekera73884482017-02-23 09:26:30 +01003431 self.vpp_session.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003432 self.test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003433 self,
3434 self.pg0,
3435 AF_INET,
3436 local_addr=self.src_ip_net,
3437 peer_addr=self.dst_ip_net,
3438 multihop=self.multihop,
3439 sha1_key=k,
3440 bfd_key_id=self.vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003441 )
Klement Sekera73884482017-02-23 09:26:30 +01003442 self.vapi.want_bfd_events()
3443 bfd_session_up(self)
3444 bfd_session_down(self)
3445 # try to replace the secret for the key - should fail because the key
3446 # is in-use
3447 k2 = self.factory.create_random_key(self)
3448 self.cli_verify_response(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003449 "bfd key set conf-key-id %s type keyed-sha1 secret %s"
3450 % (
3451 k.conf_key_id,
3452 "".join("{:02x}".format(scapy.compat.orb(c)) for c in k2.key),
3453 ),
Klement Sekera73884482017-02-23 09:26:30 +01003454 "bfd key set: `bfd_auth_set_key' API call failed, "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003455 "rv=-103:BFD object in use",
3456 )
Klement Sekera73884482017-02-23 09:26:30 +01003457 # manipulating the session using old secret should still work
3458 bfd_session_up(self)
3459 bfd_session_down(self)
3460 self.vpp_session.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003461 self.cli_verify_no_response("bfd key del conf-key-id %s" % k.conf_key_id)
Klement Sekera73884482017-02-23 09:26:30 +01003462 self.assertFalse(k.query_vpp_config())
3463
3464 def test_set_del_meticulous_sha1_key(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003465 """set/delete meticulous SHA1 auth key"""
Klement Sekera73884482017-02-23 09:26:30 +01003466 k = self.factory.create_random_key(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003467 self, auth_type=BFDAuthType.meticulous_keyed_sha1
3468 )
Klement Sekera73884482017-02-23 09:26:30 +01003469 self.registry.register(k, self.logger)
3470 self.cli_verify_no_response(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003471 "bfd key set conf-key-id %s type meticulous-keyed-sha1 secret %s"
3472 % (
3473 k.conf_key_id,
3474 "".join("{:02x}".format(scapy.compat.orb(c)) for c in k.key),
3475 )
3476 )
Klement Sekera73884482017-02-23 09:26:30 +01003477 self.assertTrue(k.query_vpp_config())
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003478 self.vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003479 self,
3480 self.pg0,
3481 self.dst_ip6_net,
3482 local_addr=self.src_ip6_net,
3483 af=AF_INET6,
3484 multihop=self.multihop,
3485 sha1_key=k,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003486 )
Klement Sekera73884482017-02-23 09:26:30 +01003487 self.vpp_session.add_vpp_config()
3488 self.vpp_session.admin_up()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003489 self.test_session = BFDTestSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003490 self,
3491 self.pg0,
3492 AF_INET6,
3493 local_addr=self.src_ip6_net,
3494 peer_addr=self.dst_ip6_net,
3495 multihop=self.multihop,
3496 sha1_key=k,
3497 bfd_key_id=self.vpp_session.bfd_key_id,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003498 )
Klement Sekera73884482017-02-23 09:26:30 +01003499 self.vapi.want_bfd_events()
3500 bfd_session_up(self)
3501 bfd_session_down(self)
3502 # try to replace the secret for the key - should fail because the key
3503 # is in-use
3504 k2 = self.factory.create_random_key(self)
3505 self.cli_verify_response(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003506 "bfd key set conf-key-id %s type keyed-sha1 secret %s"
3507 % (
3508 k.conf_key_id,
3509 "".join("{:02x}".format(scapy.compat.orb(c)) for c in k2.key),
3510 ),
Klement Sekera73884482017-02-23 09:26:30 +01003511 "bfd key set: `bfd_auth_set_key' API call failed, "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003512 "rv=-103:BFD object in use",
3513 )
Klement Sekera73884482017-02-23 09:26:30 +01003514 # manipulating the session using old secret should still work
3515 bfd_session_up(self)
3516 bfd_session_down(self)
3517 self.vpp_session.remove_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003518 self.cli_verify_no_response("bfd key del conf-key-id %s" % k.conf_key_id)
Klement Sekera73884482017-02-23 09:26:30 +01003519 self.assertFalse(k.query_vpp_config())
3520
3521 def test_add_mod_del_bfd_udp(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003522 """create/modify/delete IPv4 BFD UDP session"""
Abdel Baig17a91812024-09-03 11:52:20 -04003523 vpp_session = VppBFDUDPSession(
3524 self,
3525 self.pg0,
3526 self.dst_ip_net,
3527 local_addr=self.src_ip_net,
3528 multihop=self.multihop,
3529 )
Klement Sekera73884482017-02-23 09:26:30 +01003530 self.registry.register(vpp_session, self.logger)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003531 cli_add_cmd = (
Abdel Baig17a91812024-09-03 11:52:20 -04003532 "bfd udp session add %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003533 "peer-addr %s desired-min-tx %s required-min-rx %s "
3534 "detect-mult %s"
3535 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003536 self.cli_str,
3537 self.src_ip_net,
3538 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003539 vpp_session.desired_min_tx,
3540 vpp_session.required_min_rx,
3541 vpp_session.detect_mult,
3542 )
3543 )
Klement Sekera73884482017-02-23 09:26:30 +01003544 self.cli_verify_no_response(cli_add_cmd)
3545 # 2nd add should fail
3546 self.cli_verify_response(
3547 cli_add_cmd,
3548 "bfd udp session add: `bfd_add_add_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003549 " failed, rv=-101:Duplicate BFD object",
3550 )
Klement Sekera73884482017-02-23 09:26:30 +01003551 verify_bfd_session_config(self, vpp_session)
Abdel Baig17a91812024-09-03 11:52:20 -04003552
Klement Sekera73884482017-02-23 09:26:30 +01003553 mod_session = VppBFDUDPSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003554 self,
3555 self.pg0,
Abdel Baig17a91812024-09-03 11:52:20 -04003556 self.dst_ip_net,
3557 local_addr=self.src_ip_net,
3558 multihop=self.multihop,
Klement Sekera73884482017-02-23 09:26:30 +01003559 required_min_rx=2 * vpp_session.required_min_rx,
3560 desired_min_tx=3 * vpp_session.desired_min_tx,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003561 detect_mult=4 * vpp_session.detect_mult,
3562 )
Klement Sekera73884482017-02-23 09:26:30 +01003563 self.cli_verify_no_response(
Abdel Baig17a91812024-09-03 11:52:20 -04003564 "bfd udp session mod %s local-addr %s peer-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003565 "desired-min-tx %s required-min-rx %s detect-mult %s"
3566 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003567 self.cli_str,
3568 self.src_ip_net,
3569 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003570 mod_session.desired_min_tx,
3571 mod_session.required_min_rx,
3572 mod_session.detect_mult,
3573 )
3574 )
Klement Sekera73884482017-02-23 09:26:30 +01003575 verify_bfd_session_config(self, mod_session)
Abdel Baig17a91812024-09-03 11:52:20 -04003576 cli_del_cmd = "bfd udp session del %s local-addr %s peer-addr %s" % (
3577 self.cli_str,
3578 self.src_ip_net,
3579 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003580 )
Klement Sekera73884482017-02-23 09:26:30 +01003581 self.cli_verify_no_response(cli_del_cmd)
3582 # 2nd del is expected to fail
3583 self.cli_verify_response(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003584 cli_del_cmd,
3585 "bfd udp session del: `bfd_udp_del_session' API call"
3586 " failed, rv=-102:No such BFD object",
3587 )
Klement Sekera73884482017-02-23 09:26:30 +01003588 self.assertFalse(vpp_session.query_vpp_config())
3589
Abdel Baig17a91812024-09-03 11:52:20 -04003590 if self.multihop:
3591 # specifying multihop and interface should fail
3592 cli_add_cmd = (
3593 "bfd udp session add multihop interface %s local-addr 1.1.1.1 "
3594 "peer-addr 2.2.2.2 desired-min-tx 50000 required-min-rx 1000 "
3595 "detect-mult 3" % (self.pg0.name)
3596 )
3597 self.cli_verify_response(
3598 cli_add_cmd,
3599 "bfd udp session add: Incompatible parameter combination, "
3600 "interface cannot be specified when multihop is enabled",
3601 )
3602 cli_mod_cmd = (
3603 "bfd udp session mod multihop interface %s local-addr 1.1.1.1 "
3604 "peer-addr 2.2.2.2 desired-min-tx 50000 required-min-rx 1000 "
3605 "detect-mult 3" % (self.pg0.name)
3606 )
3607 self.cli_verify_response(
3608 cli_mod_cmd,
3609 "bfd udp session mod: Incompatible parameter combination, "
3610 "interface cannot be specified when multihop is enabled",
3611 )
3612 cli_del_cmd = (
3613 "bfd udp session del multihop interface %s local-addr 1.1.1.1 "
3614 "peer-addr 2.2.2.2" % (self.pg0.name)
3615 )
3616 self.cli_verify_response(
3617 cli_del_cmd,
3618 "bfd udp session del: Incompatible parameter combination, "
3619 "interface cannot be specified when multihop is enabled",
3620 )
3621
3622 # Not specifying multihop or interface should fail
3623 cli_add_cmd = (
3624 "bfd udp session add local-addr 1.1.1.1 peer-addr 2.2.2.2 "
3625 "desired-min-tx 50000 required-min-rx 1000 detect-mult 3"
3626 )
3627 self.cli_verify_response(
3628 cli_add_cmd,
3629 "bfd udp session add: Incompatible parameter combination, "
3630 "interface must be set if not multihop",
3631 )
3632 cli_mod_cmd = (
3633 "bfd udp session mod local-addr 1.1.1.1 peer-addr 2.2.2.2 "
3634 "desired-min-tx 50000 required-min-rx 1000 detect-mult 3"
3635 )
3636 self.cli_verify_response(
3637 cli_mod_cmd,
3638 "bfd udp session mod: Incompatible parameter combination, "
3639 "interface must be set if not multihop",
3640 )
3641 cli_del_cmd = "bfd udp session del local-addr 1.1.1.1 peer-addr 2.2.2.2 "
3642 self.cli_verify_response(
3643 cli_del_cmd,
3644 "bfd udp session del: Incompatible parameter combination, "
3645 "interface must be set if not multihop",
3646 )
3647
Klement Sekera73884482017-02-23 09:26:30 +01003648 def test_add_mod_del_bfd_udp6(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003649 """create/modify/delete IPv6 BFD UDP session"""
Abdel Baig17a91812024-09-03 11:52:20 -04003650 vpp_session = VppBFDUDPSession(
3651 self,
3652 self.pg0,
3653 self.dst_ip6_net,
3654 local_addr=self.src_ip6_net,
3655 af=AF_INET6,
3656 multihop=self.multihop,
3657 )
Klement Sekera73884482017-02-23 09:26:30 +01003658 self.registry.register(vpp_session, self.logger)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003659 cli_add_cmd = (
Abdel Baig17a91812024-09-03 11:52:20 -04003660 "bfd udp session add %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003661 "peer-addr %s desired-min-tx %s required-min-rx %s "
3662 "detect-mult %s"
3663 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003664 self.cli_str,
3665 self.src_ip6_net,
3666 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003667 vpp_session.desired_min_tx,
3668 vpp_session.required_min_rx,
3669 vpp_session.detect_mult,
3670 )
3671 )
Klement Sekera73884482017-02-23 09:26:30 +01003672 self.cli_verify_no_response(cli_add_cmd)
3673 # 2nd add should fail
3674 self.cli_verify_response(
3675 cli_add_cmd,
3676 "bfd udp session add: `bfd_add_add_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003677 " failed, rv=-101:Duplicate BFD object",
3678 )
Klement Sekera73884482017-02-23 09:26:30 +01003679 verify_bfd_session_config(self, vpp_session)
3680 mod_session = VppBFDUDPSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003681 self,
3682 self.pg0,
Abdel Baig17a91812024-09-03 11:52:20 -04003683 self.dst_ip6_net,
3684 local_addr=self.src_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003685 af=AF_INET6,
Abdel Baig17a91812024-09-03 11:52:20 -04003686 multihop=self.multihop,
Klement Sekera73884482017-02-23 09:26:30 +01003687 required_min_rx=2 * vpp_session.required_min_rx,
3688 desired_min_tx=3 * vpp_session.desired_min_tx,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003689 detect_mult=4 * vpp_session.detect_mult,
3690 )
Klement Sekera73884482017-02-23 09:26:30 +01003691 self.cli_verify_no_response(
Abdel Baig17a91812024-09-03 11:52:20 -04003692 "bfd udp session mod %s local-addr %s peer-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003693 "desired-min-tx %s required-min-rx %s detect-mult %s"
3694 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003695 self.cli_str,
3696 self.src_ip6_net,
3697 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003698 mod_session.desired_min_tx,
3699 mod_session.required_min_rx,
3700 mod_session.detect_mult,
3701 )
3702 )
Klement Sekera73884482017-02-23 09:26:30 +01003703 verify_bfd_session_config(self, mod_session)
Abdel Baig17a91812024-09-03 11:52:20 -04003704 cli_del_cmd = "bfd udp session del %s local-addr %s peer-addr %s" % (
3705 self.cli_str,
3706 self.src_ip6_net,
3707 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003708 )
Klement Sekera73884482017-02-23 09:26:30 +01003709 self.cli_verify_no_response(cli_del_cmd)
3710 # 2nd del is expected to fail
3711 self.cli_verify_response(
3712 cli_del_cmd,
3713 "bfd udp session del: `bfd_udp_del_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003714 " failed, rv=-102:No such BFD object",
3715 )
Klement Sekera73884482017-02-23 09:26:30 +01003716 self.assertFalse(vpp_session.query_vpp_config())
3717
3718 def test_add_mod_del_bfd_udp_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003719 """create/modify/delete IPv4 BFD UDP session (authenticated)"""
Klement Sekera73884482017-02-23 09:26:30 +01003720 key = self.factory.create_random_key(self)
3721 key.add_vpp_config()
3722 vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003723 self,
3724 self.pg0,
3725 self.dst_ip_net,
3726 local_addr=self.src_ip_net,
3727 multihop=self.multihop,
3728 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003729 )
Klement Sekera73884482017-02-23 09:26:30 +01003730 self.registry.register(vpp_session, self.logger)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003731 cli_add_cmd = (
Abdel Baig17a91812024-09-03 11:52:20 -04003732 "bfd udp session add %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003733 "peer-addr %s desired-min-tx %s required-min-rx %s "
3734 "detect-mult %s conf-key-id %s bfd-key-id %s"
3735 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003736 self.cli_str,
3737 self.src_ip_net,
3738 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003739 vpp_session.desired_min_tx,
3740 vpp_session.required_min_rx,
3741 vpp_session.detect_mult,
3742 key.conf_key_id,
3743 vpp_session.bfd_key_id,
3744 )
3745 )
Klement Sekera73884482017-02-23 09:26:30 +01003746 self.cli_verify_no_response(cli_add_cmd)
3747 # 2nd add should fail
3748 self.cli_verify_response(
3749 cli_add_cmd,
3750 "bfd udp session add: `bfd_add_add_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003751 " failed, rv=-101:Duplicate BFD object",
3752 )
Klement Sekera73884482017-02-23 09:26:30 +01003753 verify_bfd_session_config(self, vpp_session)
3754 mod_session = VppBFDUDPSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003755 self,
3756 self.pg0,
Abdel Baig17a91812024-09-03 11:52:20 -04003757 self.dst_ip_net,
3758 local_addr=self.src_ip_net,
3759 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003760 sha1_key=key,
Klement Sekera73884482017-02-23 09:26:30 +01003761 bfd_key_id=vpp_session.bfd_key_id,
3762 required_min_rx=2 * vpp_session.required_min_rx,
3763 desired_min_tx=3 * vpp_session.desired_min_tx,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003764 detect_mult=4 * vpp_session.detect_mult,
3765 )
Klement Sekera73884482017-02-23 09:26:30 +01003766 self.cli_verify_no_response(
Abdel Baig17a91812024-09-03 11:52:20 -04003767 "bfd udp session mod %s local-addr %s peer-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003768 "desired-min-tx %s required-min-rx %s detect-mult %s"
3769 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003770 self.cli_str,
3771 self.src_ip_net,
3772 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003773 mod_session.desired_min_tx,
3774 mod_session.required_min_rx,
3775 mod_session.detect_mult,
3776 )
3777 )
Klement Sekera73884482017-02-23 09:26:30 +01003778 verify_bfd_session_config(self, mod_session)
Abdel Baig17a91812024-09-03 11:52:20 -04003779 cli_del_cmd = "bfd udp session del %s local-addr %s peer-addr %s" % (
3780 self.cli_str,
3781 self.src_ip_net,
3782 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003783 )
Klement Sekera73884482017-02-23 09:26:30 +01003784 self.cli_verify_no_response(cli_del_cmd)
3785 # 2nd del is expected to fail
3786 self.cli_verify_response(
3787 cli_del_cmd,
3788 "bfd udp session del: `bfd_udp_del_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003789 " failed, rv=-102:No such BFD object",
3790 )
Klement Sekera73884482017-02-23 09:26:30 +01003791 self.assertFalse(vpp_session.query_vpp_config())
3792
3793 def test_add_mod_del_bfd_udp6_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003794 """create/modify/delete IPv6 BFD UDP session (authenticated)"""
Klement Sekera73884482017-02-23 09:26:30 +01003795 key = self.factory.create_random_key(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003796 self, auth_type=BFDAuthType.meticulous_keyed_sha1
3797 )
Klement Sekera73884482017-02-23 09:26:30 +01003798 key.add_vpp_config()
3799 vpp_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003800 self,
3801 self.pg0,
3802 self.dst_ip6_net,
3803 local_addr=self.src_ip6_net,
3804 af=AF_INET6,
3805 multihop=self.multihop,
3806 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003807 )
Klement Sekera73884482017-02-23 09:26:30 +01003808 self.registry.register(vpp_session, self.logger)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003809 cli_add_cmd = (
Abdel Baig17a91812024-09-03 11:52:20 -04003810 "bfd udp session add %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003811 "peer-addr %s desired-min-tx %s required-min-rx %s "
3812 "detect-mult %s conf-key-id %s bfd-key-id %s"
3813 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003814 self.cli_str,
3815 self.src_ip6_net,
3816 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003817 vpp_session.desired_min_tx,
3818 vpp_session.required_min_rx,
3819 vpp_session.detect_mult,
3820 key.conf_key_id,
3821 vpp_session.bfd_key_id,
3822 )
3823 )
Klement Sekera73884482017-02-23 09:26:30 +01003824 self.cli_verify_no_response(cli_add_cmd)
3825 # 2nd add should fail
3826 self.cli_verify_response(
3827 cli_add_cmd,
3828 "bfd udp session add: `bfd_add_add_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003829 " failed, rv=-101:Duplicate BFD object",
3830 )
Klement Sekera73884482017-02-23 09:26:30 +01003831 verify_bfd_session_config(self, vpp_session)
3832 mod_session = VppBFDUDPSession(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003833 self,
3834 self.pg0,
Abdel Baig17a91812024-09-03 11:52:20 -04003835 self.dst_ip6_net,
3836 local_addr=self.src_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003837 af=AF_INET6,
Abdel Baig17a91812024-09-03 11:52:20 -04003838 multihop=self.multihop,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003839 sha1_key=key,
Klement Sekera73884482017-02-23 09:26:30 +01003840 bfd_key_id=vpp_session.bfd_key_id,
3841 required_min_rx=2 * vpp_session.required_min_rx,
3842 desired_min_tx=3 * vpp_session.desired_min_tx,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003843 detect_mult=4 * vpp_session.detect_mult,
3844 )
Klement Sekera73884482017-02-23 09:26:30 +01003845 self.cli_verify_no_response(
Abdel Baig17a91812024-09-03 11:52:20 -04003846 "bfd udp session mod %s local-addr %s peer-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003847 "desired-min-tx %s required-min-rx %s detect-mult %s"
3848 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003849 self.cli_str,
3850 self.src_ip6_net,
3851 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003852 mod_session.desired_min_tx,
3853 mod_session.required_min_rx,
3854 mod_session.detect_mult,
3855 )
3856 )
Klement Sekera73884482017-02-23 09:26:30 +01003857 verify_bfd_session_config(self, mod_session)
Abdel Baig17a91812024-09-03 11:52:20 -04003858 cli_del_cmd = "bfd udp session del %s local-addr %s peer-addr %s" % (
3859 self.cli_str,
3860 self.src_ip6_net,
3861 self.dst_ip6_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003862 )
Klement Sekera73884482017-02-23 09:26:30 +01003863 self.cli_verify_no_response(cli_del_cmd)
3864 # 2nd del is expected to fail
3865 self.cli_verify_response(
3866 cli_del_cmd,
3867 "bfd udp session del: `bfd_udp_del_session' API call"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003868 " failed, rv=-102:No such BFD object",
3869 )
Klement Sekera73884482017-02-23 09:26:30 +01003870 self.assertFalse(vpp_session.query_vpp_config())
3871
3872 def test_auth_on_off(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003873 """turn authentication on and off"""
Klement Sekera73884482017-02-23 09:26:30 +01003874 key = self.factory.create_random_key(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003875 self, auth_type=BFDAuthType.meticulous_keyed_sha1
3876 )
Klement Sekera73884482017-02-23 09:26:30 +01003877 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003878 session = VppBFDUDPSession(
3879 self,
3880 self.pg0,
3881 self.dst_ip_net,
3882 local_addr=self.src_ip_net,
3883 multihop=self.multihop,
3884 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003885 auth_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003886 self,
3887 self.pg0,
3888 self.dst_ip_net,
3889 local_addr=self.src_ip_net,
3890 multihop=self.multihop,
3891 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003892 )
Klement Sekera73884482017-02-23 09:26:30 +01003893 session.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003894 cli_activate = (
Abdel Baig17a91812024-09-03 11:52:20 -04003895 "bfd udp session auth activate %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003896 "peer-addr %s conf-key-id %s bfd-key-id %s"
3897 % (
Abdel Baig17a91812024-09-03 11:52:20 -04003898 self.cli_str,
3899 self.src_ip_net,
3900 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003901 key.conf_key_id,
3902 auth_session.bfd_key_id,
3903 )
3904 )
Klement Sekera73884482017-02-23 09:26:30 +01003905 self.cli_verify_no_response(cli_activate)
3906 verify_bfd_session_config(self, auth_session)
3907 self.cli_verify_no_response(cli_activate)
3908 verify_bfd_session_config(self, auth_session)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003909 cli_deactivate = (
Abdel Baig17a91812024-09-03 11:52:20 -04003910 "bfd udp session auth deactivate %s local-addr %s "
3911 "peer-addr %s" % (self.cli_str, self.src_ip_net, self.dst_ip_net)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003912 )
Klement Sekera73884482017-02-23 09:26:30 +01003913 self.cli_verify_no_response(cli_deactivate)
3914 verify_bfd_session_config(self, session)
3915 self.cli_verify_no_response(cli_deactivate)
3916 verify_bfd_session_config(self, session)
3917
Abdel Baig17a91812024-09-03 11:52:20 -04003918 if self.multihop:
3919 # specifying multihop and interface should fail
3920 cli_activate = (
3921 "bfd udp session auth activate multihop interface %s "
3922 "local-addr %s peer-addr %s conf-key-id %s bfd-key-id %s"
3923 % (
3924 self.pg0.name,
3925 self.src_ip_net,
3926 self.dst_ip_net,
3927 key.conf_key_id,
3928 auth_session.bfd_key_id,
3929 )
3930 )
3931 self.cli_verify_response(
3932 cli_activate,
3933 "bfd udp session auth activate: Incompatible parameter "
3934 "combination, interface cannot be specified when multihop "
3935 "is enabled",
3936 )
3937 cli_deactivate = (
3938 "bfd udp session auth deactivate multihop interface %s "
3939 "local-addr %s peer-addr %s"
3940 % (
3941 self.pg0.name,
3942 self.src_ip_net,
3943 self.dst_ip_net,
3944 )
3945 )
3946 self.cli_verify_response(
3947 cli_deactivate,
3948 "bfd udp session auth deactivate: Incompatible parameter "
3949 "combination, interface cannot be specified when multihop "
3950 "is enabled",
3951 )
3952 # Not specifying multihop or interface should fail
3953 cli_activate = (
3954 "bfd udp session auth activate local-addr %s peer-addr %s "
3955 "conf-key-id %s bfd-key-id %s"
3956 % (
3957 self.src_ip_net,
3958 self.dst_ip_net,
3959 key.conf_key_id,
3960 auth_session.bfd_key_id,
3961 )
3962 )
3963 self.cli_verify_response(
3964 cli_activate,
3965 "bfd udp session auth activate: Incompatible parameter "
3966 "combination, interface must be set if not multihop",
3967 )
3968 cli_deactivate = (
3969 "bfd udp session auth deactivate local-addr %s peer-addr %s "
3970 % (
3971 self.src_ip_net,
3972 self.dst_ip_net,
3973 )
3974 )
3975 self.cli_verify_response(
3976 cli_deactivate,
3977 "bfd udp session auth deactivate: Incompatible parameter "
3978 "combination, interface must be set if not multihop",
3979 )
3980
Klement Sekera73884482017-02-23 09:26:30 +01003981 def test_auth_on_off_delayed(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003982 """turn authentication on and off (delayed)"""
Klement Sekera73884482017-02-23 09:26:30 +01003983 key = self.factory.create_random_key(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003984 self, auth_type=BFDAuthType.meticulous_keyed_sha1
3985 )
Klement Sekera73884482017-02-23 09:26:30 +01003986 key.add_vpp_config()
Abdel Baig17a91812024-09-03 11:52:20 -04003987 session = VppBFDUDPSession(
3988 self,
3989 self.pg0,
3990 self.dst_ip_net,
3991 local_addr=self.src_ip_net,
3992 multihop=self.multihop,
3993 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02003994 auth_session = VppBFDUDPSession(
Abdel Baig17a91812024-09-03 11:52:20 -04003995 self,
3996 self.pg0,
3997 self.dst_ip_net,
3998 local_addr=self.src_ip_net,
3999 multihop=self.multihop,
4000 sha1_key=key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004001 )
Klement Sekera73884482017-02-23 09:26:30 +01004002 session.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004003 cli_activate = (
Abdel Baig17a91812024-09-03 11:52:20 -04004004 "bfd udp session auth activate %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004005 "peer-addr %s conf-key-id %s bfd-key-id %s delayed yes"
4006 % (
Abdel Baig17a91812024-09-03 11:52:20 -04004007 self.cli_str,
4008 self.src_ip_net,
4009 self.dst_ip_net,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004010 key.conf_key_id,
4011 auth_session.bfd_key_id,
4012 )
4013 )
Klement Sekera73884482017-02-23 09:26:30 +01004014 self.cli_verify_no_response(cli_activate)
4015 verify_bfd_session_config(self, auth_session)
4016 self.cli_verify_no_response(cli_activate)
4017 verify_bfd_session_config(self, auth_session)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004018 cli_deactivate = (
Abdel Baig17a91812024-09-03 11:52:20 -04004019 "bfd udp session auth deactivate %s local-addr %s "
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004020 "peer-addr %s delayed yes"
Abdel Baig17a91812024-09-03 11:52:20 -04004021 % (self.cli_str, self.src_ip_net, self.dst_ip_net)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004022 )
Klement Sekera73884482017-02-23 09:26:30 +01004023 self.cli_verify_no_response(cli_deactivate)
4024 verify_bfd_session_config(self, session)
4025 self.cli_verify_no_response(cli_deactivate)
4026 verify_bfd_session_config(self, session)
4027
4028 def test_admin_up_down(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004029 """put session admin-up and admin-down"""
Abdel Baig17a91812024-09-03 11:52:20 -04004030 session = VppBFDUDPSession(
4031 self,
4032 self.pg0,
4033 self.dst_ip_net,
4034 local_addr=self.src_ip_net,
4035 multihop=self.multihop,
4036 )
Klement Sekera73884482017-02-23 09:26:30 +01004037 session.add_vpp_config()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004038 cli_down = (
Abdel Baig17a91812024-09-03 11:52:20 -04004039 "bfd udp session set-flags admin down %s local-addr %s "
4040 "peer-addr %s " % (self.cli_str, self.src_ip_net, self.dst_ip_net)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004041 )
4042 cli_up = (
Abdel Baig17a91812024-09-03 11:52:20 -04004043 "bfd udp session set-flags admin up %s local-addr %s "
4044 "peer-addr %s " % (self.cli_str, self.src_ip_net, self.dst_ip_net)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004045 )
Klement Sekera73884482017-02-23 09:26:30 +01004046 self.cli_verify_no_response(cli_down)
4047 verify_bfd_session_config(self, session, state=BFDState.admin_down)
4048 self.cli_verify_no_response(cli_up)
4049 verify_bfd_session_config(self, session, state=BFDState.down)
4050
Abdel Baig17a91812024-09-03 11:52:20 -04004051 if self.multihop:
4052 # specifying multihop and interface should fail
4053 cli_up = (
4054 "bfd udp session set-flags admin up multihop interface %s "
4055 "local-addr %s peer-addr %s"
4056 % (
4057 self.pg0.name,
4058 self.src_ip_net,
4059 self.dst_ip_net,
4060 )
4061 )
4062 self.cli_verify_response(
4063 cli_up,
4064 "bfd udp session set-flags: Incompatible parameter "
4065 "combination, interface cannot be specified when multihop "
4066 "is enabled",
4067 )
4068 # Not specifying multihop or interface should fail
4069 cli_up = (
4070 "bfd udp session set-flags admin up local-addr %s peer-addr %s "
4071 % (
4072 self.src_ip_net,
4073 self.dst_ip_net,
4074 )
4075 )
4076 self.cli_verify_response(
4077 cli_up,
4078 "bfd udp session set-flags: Incompatible parameter "
4079 "combination, interface must be set if not multihop",
4080 )
4081
Klement Sekera73884482017-02-23 09:26:30 +01004082 def test_set_del_udp_echo_source(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004083 """set/del udp echo source"""
Abdel Baig17a91812024-09-03 11:52:20 -04004084
4085 if self.multihop:
4086 self.skipTest(
4087 f"Skipping because echo functionality is not supported with multihop"
4088 )
4089
Klement Sekerab9ef2732018-06-24 22:49:33 +02004090 self.create_loopback_interfaces(1)
Klement Sekera73884482017-02-23 09:26:30 +01004091 self.loopback0 = self.lo_interfaces[0]
4092 self.loopback0.admin_up()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004093 self.cli_verify_response("show bfd echo-source", "UDP echo source is not set.")
Klement Sekera73884482017-02-23 09:26:30 +01004094 cli_set = "bfd udp echo-source set interface %s" % self.loopback0.name
4095 self.cli_verify_no_response(cli_set)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004096 self.cli_verify_response(
4097 "show bfd echo-source",
4098 "UDP echo source is: %s\n"
4099 "IPv4 address usable as echo source: none\n"
4100 "IPv6 address usable as echo source: none" % self.loopback0.name,
4101 )
Klement Sekera73884482017-02-23 09:26:30 +01004102 self.loopback0.config_ip4()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004103 echo_ip4 = str(
4104 ipaddress.IPv4Address(
4105 int(ipaddress.IPv4Address(self.loopback0.local_ip4)) ^ 1
4106 )
4107 )
4108 self.cli_verify_response(
4109 "show bfd echo-source",
4110 "UDP echo source is: %s\n"
4111 "IPv4 address usable as echo source: %s\n"
4112 "IPv6 address usable as echo source: none"
4113 % (self.loopback0.name, echo_ip4),
4114 )
4115 echo_ip6 = str(
4116 ipaddress.IPv6Address(
4117 int(ipaddress.IPv6Address(self.loopback0.local_ip6)) ^ 1
4118 )
4119 )
Klement Sekera73884482017-02-23 09:26:30 +01004120 self.loopback0.config_ip6()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004121 self.cli_verify_response(
4122 "show bfd echo-source",
4123 "UDP echo source is: %s\n"
4124 "IPv4 address usable as echo source: %s\n"
4125 "IPv6 address usable as echo source: %s"
4126 % (self.loopback0.name, echo_ip4, echo_ip6),
4127 )
Klement Sekera73884482017-02-23 09:26:30 +01004128 cli_del = "bfd udp echo-source del"
4129 self.cli_verify_no_response(cli_del)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004130 self.cli_verify_response("show bfd echo-source", "UDP echo source is not set.")
Klement Sekera73884482017-02-23 09:26:30 +01004131
Jakub Grajciar4682feb2019-09-02 13:28:52 +02004132
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02004133if __name__ == "__main__":
Klement Sekera0e3c0de2016-09-29 14:43:44 +02004134 unittest.main(testRunner=VppTestRunner)