blob: 64e9301ac5fdc700d14bf0aef773fce5fd77e0e1 [file] [log] [blame]
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001#!/usr/bin/env python
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
Klement Sekera0e3c0de2016-09-29 14:43:44 +02005import unittest
Klement Sekerab17dd962017-01-09 07:43:48 +01006import hashlib
7import binascii
Klement Sekera0e3c0de2016-09-29 14:43:44 +02008import time
Klement Sekerad3ba5152017-02-14 03:09:17 +01009from random import randint, shuffle
10from socket import AF_INET, AF_INET6
Klement Sekeraaeeac3b2017-02-14 07:11:52 +010011from scapy.packet import Raw
Klement Sekerad3ba5152017-02-14 03:09:17 +010012from scapy.layers.l2 import Ether
13from scapy.layers.inet import UDP, IP
14from scapy.layers.inet6 import IPv6
15from bfd import VppBFDAuthKey, BFD, BFDAuthType, VppBFDUDPSession, \
16 BFDDiagCode, BFDState
17from framework import VppTestCase, VppTestRunner
18from vpp_pg_interface import CaptureTimeoutError
Klement Sekera0e3c0de2016-09-29 14:43:44 +020019from util import ppp
20
Klement Sekerad3ba5152017-02-14 03:09:17 +010021USEC_IN_SEC = 1000000
Klement Sekera3e0a3562016-12-19 09:05:21 +010022
Klement Sekera0e3c0de2016-09-29 14:43:44 +020023
Klement Sekerab17dd962017-01-09 07:43:48 +010024class AuthKeyFactory(object):
25 """Factory class for creating auth keys with unique conf key ID"""
26
27 def __init__(self):
28 self._conf_key_ids = {}
29
30 def create_random_key(self, test, auth_type=BFDAuthType.keyed_sha1):
Klement Sekerad3ba5152017-02-14 03:09:17 +010031 """ create a random key with unique conf key id """
Klement Sekerab17dd962017-01-09 07:43:48 +010032 conf_key_id = randint(0, 0xFFFFFFFF)
33 while conf_key_id in self._conf_key_ids:
34 conf_key_id = randint(0, 0xFFFFFFFF)
35 self._conf_key_ids[conf_key_id] = 1
Klement Sekerad3ba5152017-02-14 03:09:17 +010036 key = str(bytearray([randint(0, 255) for _ in range(randint(1, 20))]))
Klement Sekerab17dd962017-01-09 07:43:48 +010037 return VppBFDAuthKey(test=test, auth_type=auth_type,
38 conf_key_id=conf_key_id, key=key)
39
40
Klement Sekerae4504c62016-12-08 10:16:41 +010041class BFDAPITestCase(VppTestCase):
42 """Bidirectional Forwarding Detection (BFD) - API"""
Klement Sekera0e3c0de2016-09-29 14:43:44 +020043
Klement Sekerad3ba5152017-02-14 03:09:17 +010044 pg0 = None
45 pg1 = None
46
Klement Sekera0e3c0de2016-09-29 14:43:44 +020047 @classmethod
48 def setUpClass(cls):
Klement Sekerae4504c62016-12-08 10:16:41 +010049 super(BFDAPITestCase, cls).setUpClass()
Klement Sekera0e3c0de2016-09-29 14:43:44 +020050
51 try:
Klement Sekera10db26f2017-01-11 08:16:53 +010052 cls.create_pg_interfaces(range(2))
53 for i in cls.pg_interfaces:
54 i.config_ip4()
Klement Sekerab17dd962017-01-09 07:43:48 +010055 i.config_ip6()
Klement Sekera10db26f2017-01-11 08:16:53 +010056 i.resolve_arp()
Klement Sekera0e3c0de2016-09-29 14:43:44 +020057
58 except Exception:
Klement Sekerae4504c62016-12-08 10:16:41 +010059 super(BFDAPITestCase, cls).tearDownClass()
Klement Sekera0e3c0de2016-09-29 14:43:44 +020060 raise
61
Klement Sekerab17dd962017-01-09 07:43:48 +010062 def setUp(self):
63 super(BFDAPITestCase, self).setUp()
64 self.factory = AuthKeyFactory()
65
Klement Sekera0e3c0de2016-09-29 14:43:44 +020066 def test_add_bfd(self):
67 """ create a BFD session """
68 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
69 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +010070 self.logger.debug("Session state is %s", session.state)
Klement Sekera0e3c0de2016-09-29 14:43:44 +020071 session.remove_vpp_config()
Klement Sekera0e3c0de2016-09-29 14:43:44 +020072 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +010073 self.logger.debug("Session state is %s", session.state)
Klement Sekera0e3c0de2016-09-29 14:43:44 +020074 session.remove_vpp_config()
75
76 def test_double_add(self):
77 """ create the same BFD session twice (negative case) """
78 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
79 session.add_vpp_config()
Klement Sekerae0545ef2017-01-25 08:00:40 +010080
81 with self.vapi.expect_negative_api_retval():
Klement Sekera0e3c0de2016-09-29 14:43:44 +020082 session.add_vpp_config()
Klement Sekerae0545ef2017-01-25 08:00:40 +010083
Klement Sekera0e3c0de2016-09-29 14:43:44 +020084 session.remove_vpp_config()
Klement Sekera0e3c0de2016-09-29 14:43:44 +020085
Klement Sekerab17dd962017-01-09 07:43:48 +010086 def test_add_bfd6(self):
87 """ create IPv6 BFD session """
88 session = VppBFDUDPSession(
89 self, self.pg0, self.pg0.remote_ip6, af=AF_INET6)
90 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +010091 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +010092 session.remove_vpp_config()
93 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +010094 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +010095 session.remove_vpp_config()
96
Klement Sekeraa57a9702017-02-02 06:58:07 +010097 def test_mod_bfd(self):
98 """ modify BFD session parameters """
99 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
100 desired_min_tx=50000,
101 required_min_rx=10000,
102 detect_mult=1)
103 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100104 s = session.get_bfd_udp_session_dump_entry()
Klement Sekeraa57a9702017-02-02 06:58:07 +0100105 self.assert_equal(session.desired_min_tx,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100106 s.desired_min_tx,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100107 "desired min transmit interval")
108 self.assert_equal(session.required_min_rx,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100109 s.required_min_rx,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100110 "required min receive interval")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100111 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
Klement Sekeraa57a9702017-02-02 06:58:07 +0100112 session.modify_parameters(desired_min_tx=session.desired_min_tx * 2,
113 required_min_rx=session.required_min_rx * 2,
114 detect_mult=session.detect_mult * 2)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100115 s = session.get_bfd_udp_session_dump_entry()
Klement Sekeraa57a9702017-02-02 06:58:07 +0100116 self.assert_equal(session.desired_min_tx,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100117 s.desired_min_tx,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100118 "desired min transmit interval")
119 self.assert_equal(session.required_min_rx,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100120 s.required_min_rx,
Klement Sekeraa57a9702017-02-02 06:58:07 +0100121 "required min receive interval")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100122 self.assert_equal(session.detect_mult, s.detect_mult, "detect mult")
Klement Sekeraa57a9702017-02-02 06:58:07 +0100123
Klement Sekerab17dd962017-01-09 07:43:48 +0100124 def test_add_sha1_keys(self):
125 """ add SHA1 keys """
126 key_count = 10
127 keys = [self.factory.create_random_key(
128 self) for i in range(0, key_count)]
129 for key in keys:
130 self.assertFalse(key.query_vpp_config())
131 for key in keys:
132 key.add_vpp_config()
133 for key in keys:
134 self.assertTrue(key.query_vpp_config())
135 # remove randomly
136 indexes = range(key_count)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100137 shuffle(indexes)
Klement Sekerab17dd962017-01-09 07:43:48 +0100138 removed = []
139 for i in indexes:
140 key = keys[i]
141 key.remove_vpp_config()
142 removed.append(i)
143 for j in range(key_count):
144 key = keys[j]
145 if j in removed:
146 self.assertFalse(key.query_vpp_config())
147 else:
148 self.assertTrue(key.query_vpp_config())
149 # should be removed now
150 for key in keys:
151 self.assertFalse(key.query_vpp_config())
152 # add back and remove again
153 for key in keys:
154 key.add_vpp_config()
155 for key in keys:
156 self.assertTrue(key.query_vpp_config())
157 for key in keys:
158 key.remove_vpp_config()
159 for key in keys:
160 self.assertFalse(key.query_vpp_config())
161
162 def test_add_bfd_sha1(self):
163 """ create a BFD session (SHA1) """
164 key = self.factory.create_random_key(self)
165 key.add_vpp_config()
166 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
167 sha1_key=key)
168 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100169 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100170 session.remove_vpp_config()
171 session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100172 self.logger.debug("Session state is %s", session.state)
Klement Sekerab17dd962017-01-09 07:43:48 +0100173 session.remove_vpp_config()
174
175 def test_double_add_sha1(self):
176 """ create the same BFD session twice (negative case) (SHA1) """
177 key = self.factory.create_random_key(self)
178 key.add_vpp_config()
179 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
180 sha1_key=key)
181 session.add_vpp_config()
182 with self.assertRaises(Exception):
183 session.add_vpp_config()
184
Klement Sekerad3ba5152017-02-14 03:09:17 +0100185 def test_add_auth_nonexistent_key(self):
Klement Sekerab17dd962017-01-09 07:43:48 +0100186 """ create BFD session using non-existent SHA1 (negative case) """
187 session = VppBFDUDPSession(
188 self, self.pg0, self.pg0.remote_ip4,
189 sha1_key=self.factory.create_random_key(self))
190 with self.assertRaises(Exception):
191 session.add_vpp_config()
192
193 def test_shared_sha1_key(self):
194 """ share single SHA1 key between multiple BFD sessions """
195 key = self.factory.create_random_key(self)
196 key.add_vpp_config()
197 sessions = [
198 VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
199 sha1_key=key),
200 VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip6,
201 sha1_key=key, af=AF_INET6),
202 VppBFDUDPSession(self, self.pg1, self.pg1.remote_ip4,
203 sha1_key=key),
204 VppBFDUDPSession(self, self.pg1, self.pg1.remote_ip6,
205 sha1_key=key, af=AF_INET6)]
206 for s in sessions:
207 s.add_vpp_config()
208 removed = 0
209 for s in sessions:
210 e = key.get_bfd_auth_keys_dump_entry()
211 self.assert_equal(e.use_count, len(sessions) - removed,
212 "Use count for shared key")
213 s.remove_vpp_config()
214 removed += 1
215 e = key.get_bfd_auth_keys_dump_entry()
216 self.assert_equal(e.use_count, len(sessions) - removed,
217 "Use count for shared key")
218
219 def test_activate_auth(self):
220 """ activate SHA1 authentication """
221 key = self.factory.create_random_key(self)
222 key.add_vpp_config()
223 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
224 session.add_vpp_config()
225 session.activate_auth(key)
226
227 def test_deactivate_auth(self):
228 """ deactivate SHA1 authentication """
229 key = self.factory.create_random_key(self)
230 key.add_vpp_config()
231 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
232 session.add_vpp_config()
233 session.activate_auth(key)
234 session.deactivate_auth()
235
236 def test_change_key(self):
Klement Sekeraa57a9702017-02-02 06:58:07 +0100237 """ change SHA1 key """
Klement Sekerab17dd962017-01-09 07:43:48 +0100238 key1 = self.factory.create_random_key(self)
239 key2 = self.factory.create_random_key(self)
240 while key2.conf_key_id == key1.conf_key_id:
241 key2 = self.factory.create_random_key(self)
242 key1.add_vpp_config()
243 key2.add_vpp_config()
244 session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
245 sha1_key=key1)
246 session.add_vpp_config()
247 session.activate_auth(key2)
Klement Sekera10db26f2017-01-11 08:16:53 +0100248
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200249
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200250class BFDTestSession(object):
Klement Sekera3e0a3562016-12-19 09:05:21 +0100251 """ BFD session as seen from test framework side """
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200252
Klement Sekerab17dd962017-01-09 07:43:48 +0100253 def __init__(self, test, interface, af, detect_mult=3, sha1_key=None,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100254 bfd_key_id=None, our_seq_number=None):
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200255 self.test = test
Klement Sekera46a87ad2017-01-02 08:22:23 +0100256 self.af = af
Klement Sekerab17dd962017-01-09 07:43:48 +0100257 self.sha1_key = sha1_key
258 self.bfd_key_id = bfd_key_id
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200259 self.interface = interface
Klement Sekerad3ba5152017-02-14 03:09:17 +0100260 self.udp_sport = randint(49152, 65535)
261 if our_seq_number is None:
262 self.our_seq_number = randint(0, 40000000)
263 else:
264 self.our_seq_number = our_seq_number
Klement Sekerab17dd962017-01-09 07:43:48 +0100265 self.vpp_seq_number = None
Klement Sekerad3ba5152017-02-14 03:09:17 +0100266 self.my_discriminator = 0
267 self.desired_min_tx = 100000
268 self.required_min_rx = 100000
269 self.detect_mult = detect_mult
270 self.diag = BFDDiagCode.no_diagnostic
271 self.your_discriminator = None
272 self.state = BFDState.down
273 self.auth_type = BFDAuthType.no_auth
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200274
Klement Sekerab17dd962017-01-09 07:43:48 +0100275 def inc_seq_num(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100276 """ increment sequence number, wrapping if needed """
Klement Sekerab17dd962017-01-09 07:43:48 +0100277 if self.our_seq_number == 0xFFFFFFFF:
278 self.our_seq_number = 0
279 else:
280 self.our_seq_number += 1
281
Klement Sekerad3ba5152017-02-14 03:09:17 +0100282 def update(self, my_discriminator=None, your_discriminator=None,
283 desired_min_tx=None, required_min_rx=None, detect_mult=None,
284 diag=None, state=None, auth_type=None):
285 """ update BFD parameters associated with session """
286 if my_discriminator:
287 self.my_discriminator = my_discriminator
288 if your_discriminator:
289 self.your_discriminator = your_discriminator
290 if required_min_rx:
291 self.required_min_rx = required_min_rx
292 if desired_min_tx:
293 self.desired_min_tx = desired_min_tx
294 if detect_mult:
295 self.detect_mult = detect_mult
296 if diag:
297 self.diag = diag
298 if state:
299 self.state = state
300 if auth_type:
301 self.auth_type = auth_type
302
303 def fill_packet_fields(self, packet):
304 """ set packet fields with known values in packet """
305 bfd = packet[BFD]
306 if self.my_discriminator:
307 self.test.logger.debug("BFD: setting packet.my_discriminator=%s",
308 self.my_discriminator)
309 bfd.my_discriminator = self.my_discriminator
310 if self.your_discriminator:
311 self.test.logger.debug("BFD: setting packet.your_discriminator=%s",
312 self.your_discriminator)
313 bfd.your_discriminator = self.your_discriminator
314 if self.required_min_rx:
315 self.test.logger.debug(
316 "BFD: setting packet.required_min_rx_interval=%s",
317 self.required_min_rx)
318 bfd.required_min_rx_interval = self.required_min_rx
319 if self.desired_min_tx:
320 self.test.logger.debug(
321 "BFD: setting packet.desired_min_tx_interval=%s",
322 self.desired_min_tx)
323 bfd.desired_min_tx_interval = self.desired_min_tx
324 if self.detect_mult:
325 self.test.logger.debug(
326 "BFD: setting packet.detect_mult=%s", self.detect_mult)
327 bfd.detect_mult = self.detect_mult
328 if self.diag:
329 self.test.logger.debug("BFD: setting packet.diag=%s", self.diag)
330 bfd.diag = self.diag
331 if self.state:
332 self.test.logger.debug("BFD: setting packet.state=%s", self.state)
333 bfd.state = self.state
334 if self.auth_type:
335 # this is used by a negative test-case
336 self.test.logger.debug("BFD: setting packet.auth_type=%s",
337 self.auth_type)
338 bfd.auth_type = self.auth_type
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200339
340 def create_packet(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100341 """ create a BFD packet, reflecting the current state of session """
Klement Sekerab17dd962017-01-09 07:43:48 +0100342 if self.sha1_key:
343 bfd = BFD(flags="A")
344 bfd.auth_type = self.sha1_key.auth_type
345 bfd.auth_len = BFD.sha1_auth_len
346 bfd.auth_key_id = self.bfd_key_id
347 bfd.auth_seq_num = self.our_seq_number
348 bfd.length = BFD.sha1_auth_len + BFD.bfd_pkt_len
349 else:
350 bfd = BFD()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100351 if self.af == AF_INET6:
352 packet = (Ether(src=self.interface.remote_mac,
353 dst=self.interface.local_mac) /
354 IPv6(src=self.interface.remote_ip6,
355 dst=self.interface.local_ip6,
356 hlim=255) /
357 UDP(sport=self.udp_sport, dport=BFD.udp_dport) /
Klement Sekerab17dd962017-01-09 07:43:48 +0100358 bfd)
Klement Sekera46a87ad2017-01-02 08:22:23 +0100359 else:
360 packet = (Ether(src=self.interface.remote_mac,
361 dst=self.interface.local_mac) /
362 IP(src=self.interface.remote_ip4,
363 dst=self.interface.local_ip4,
364 ttl=255) /
365 UDP(sport=self.udp_sport, dport=BFD.udp_dport) /
Klement Sekerab17dd962017-01-09 07:43:48 +0100366 bfd)
Klement Sekera3e0a3562016-12-19 09:05:21 +0100367 self.test.logger.debug("BFD: Creating packet")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100368 self.fill_packet_fields(packet)
Klement Sekerab17dd962017-01-09 07:43:48 +0100369 if self.sha1_key:
370 hash_material = str(packet[BFD])[:32] + self.sha1_key.key + \
371 "\0" * (20 - len(self.sha1_key.key))
372 self.test.logger.debug("BFD: Calculated SHA1 hash: %s" %
373 hashlib.sha1(hash_material).hexdigest())
374 packet[BFD].auth_key_hash = hashlib.sha1(hash_material).digest()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200375 return packet
376
Klement Sekerad3ba5152017-02-14 03:09:17 +0100377 def send_packet(self, packet=None, interface=None):
378 """ send packet on interface, creating the packet if needed """
Klement Sekeraa57a9702017-02-02 06:58:07 +0100379 if packet is None:
380 packet = self.create_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100381 if interface is None:
382 interface = self.test.pg0
Klement Sekeraa57a9702017-02-02 06:58:07 +0100383 self.test.logger.debug(ppp("Sending packet:", packet))
Klement Sekerad3ba5152017-02-14 03:09:17 +0100384 interface.add_stream(packet)
Klement Sekera9225dee2016-12-12 08:36:58 +0100385 self.test.pg_start()
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200386
Klement Sekerab17dd962017-01-09 07:43:48 +0100387 def verify_sha1_auth(self, packet):
388 """ Verify correctness of authentication in BFD layer. """
389 bfd = packet[BFD]
390 self.test.assert_equal(bfd.auth_len, 28, "Auth section length")
391 self.test.assert_equal(bfd.auth_type, self.sha1_key.auth_type,
392 BFDAuthType)
393 self.test.assert_equal(bfd.auth_key_id, self.bfd_key_id, "Key ID")
394 self.test.assert_equal(bfd.auth_reserved, 0, "Reserved")
395 if self.vpp_seq_number is None:
396 self.vpp_seq_number = bfd.auth_seq_num
397 self.test.logger.debug("Received initial sequence number: %s" %
398 self.vpp_seq_number)
399 else:
400 recvd_seq_num = bfd.auth_seq_num
401 self.test.logger.debug("Received followup sequence number: %s" %
402 recvd_seq_num)
403 if self.vpp_seq_number < 0xffffffff:
404 if self.sha1_key.auth_type == \
405 BFDAuthType.meticulous_keyed_sha1:
406 self.test.assert_equal(recvd_seq_num,
407 self.vpp_seq_number + 1,
408 "BFD sequence number")
409 else:
410 self.test.assert_in_range(recvd_seq_num,
411 self.vpp_seq_number,
412 self.vpp_seq_number + 1,
413 "BFD sequence number")
414 else:
415 if self.sha1_key.auth_type == \
416 BFDAuthType.meticulous_keyed_sha1:
417 self.test.assert_equal(recvd_seq_num, 0,
418 "BFD sequence number")
419 else:
420 self.test.assertIn(recvd_seq_num, (self.vpp_seq_number, 0),
421 "BFD sequence number not one of "
422 "(%s, 0)" % self.vpp_seq_number)
423 self.vpp_seq_number = recvd_seq_num
424 # last 20 bytes represent the hash - so replace them with the key,
425 # pad the result with zeros and hash the result
426 hash_material = bfd.original[:-20] + self.sha1_key.key + \
427 "\0" * (20 - len(self.sha1_key.key))
428 expected_hash = hashlib.sha1(hash_material).hexdigest()
429 self.test.assert_equal(binascii.hexlify(bfd.auth_key_hash),
430 expected_hash, "Auth key hash")
431
432 def verify_bfd(self, packet):
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200433 """ Verify correctness of BFD layer. """
434 bfd = packet[BFD]
435 self.test.assert_equal(bfd.version, 1, "BFD version")
436 self.test.assert_equal(bfd.your_discriminator,
Klement Sekerad3ba5152017-02-14 03:09:17 +0100437 self.my_discriminator,
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200438 "BFD - your discriminator")
Klement Sekerab17dd962017-01-09 07:43:48 +0100439 if self.sha1_key:
440 self.verify_sha1_auth(packet)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200441
442
Klement Sekerad3ba5152017-02-14 03:09:17 +0100443def bfd_session_up(test):
444 """ Bring BFD session up """
445 test.logger.info("BFD: Waiting for slow hello")
446 p = wait_for_bfd_packet(test, 2)
447 old_offset = None
448 if hasattr(test, 'vpp_clock_offset'):
449 old_offset = test.vpp_clock_offset
450 test.vpp_clock_offset = time.time() - p.time
451 test.logger.debug("BFD: Calculated vpp clock offset: %s",
452 test.vpp_clock_offset)
453 if old_offset:
454 test.assertAlmostEqual(
455 old_offset, test.vpp_clock_offset, delta=0.1,
456 msg="vpp clock offset not stable (new: %s, old: %s)" %
457 (test.vpp_clock_offset, old_offset))
458 test.logger.info("BFD: Sending Init")
459 test.test_session.update(my_discriminator=randint(0, 40000000),
460 your_discriminator=p[BFD].my_discriminator,
461 state=BFDState.init)
462 test.test_session.send_packet()
463 test.logger.info("BFD: Waiting for event")
464 e = test.vapi.wait_for_event(1, "bfd_udp_session_details")
465 verify_event(test, e, expected_state=BFDState.up)
466 test.logger.info("BFD: Session is Up")
467 test.test_session.update(state=BFDState.up)
468 test.test_session.send_packet()
469 test.assert_equal(test.vpp_session.state, BFDState.up, BFDState)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200470
Klement Sekera46a87ad2017-01-02 08:22:23 +0100471
Klement Sekerad3ba5152017-02-14 03:09:17 +0100472def bfd_session_down(test):
473 """ Bring BFD session down """
474 test.assert_equal(test.vpp_session.state, BFDState.up, BFDState)
475 test.test_session.update(state=BFDState.down)
476 test.test_session.send_packet()
477 test.logger.info("BFD: Waiting for event")
478 e = test.vapi.wait_for_event(1, "bfd_udp_session_details")
479 verify_event(test, e, expected_state=BFDState.down)
480 test.logger.info("BFD: Session is Down")
481 test.assert_equal(test.vpp_session.state, BFDState.down, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +0100482
Klement Sekera46a87ad2017-01-02 08:22:23 +0100483
Klement Sekerad3ba5152017-02-14 03:09:17 +0100484def verify_ip(test, packet):
485 """ Verify correctness of IP layer. """
486 if test.vpp_session.af == AF_INET6:
487 ip = packet[IPv6]
488 local_ip = test.pg0.local_ip6
489 remote_ip = test.pg0.remote_ip6
490 test.assert_equal(ip.hlim, 255, "IPv6 hop limit")
491 else:
492 ip = packet[IP]
493 local_ip = test.pg0.local_ip4
494 remote_ip = test.pg0.remote_ip4
495 test.assert_equal(ip.ttl, 255, "IPv4 TTL")
496 test.assert_equal(ip.src, local_ip, "IP source address")
497 test.assert_equal(ip.dst, remote_ip, "IP destination address")
498
499
500def verify_udp(test, packet):
501 """ Verify correctness of UDP layer. """
502 udp = packet[UDP]
503 test.assert_equal(udp.dport, BFD.udp_dport, "UDP destination port")
504 test.assert_in_range(udp.sport, BFD.udp_sport_min, BFD.udp_sport_max,
505 "UDP source port")
506
507
508def verify_event(test, event, expected_state):
509 """ Verify correctness of event values. """
510 e = event
511 test.logger.debug("BFD: Event: %s" % repr(e))
512 test.assert_equal(e.sw_if_index,
513 test.vpp_session.interface.sw_if_index,
514 "BFD interface index")
515 is_ipv6 = 0
516 if test.vpp_session.af == AF_INET6:
517 is_ipv6 = 1
518 test.assert_equal(e.is_ipv6, is_ipv6, "is_ipv6")
519 if test.vpp_session.af == AF_INET:
520 test.assert_equal(e.local_addr[:4], test.vpp_session.local_addr_n,
521 "Local IPv4 address")
522 test.assert_equal(e.peer_addr[:4], test.vpp_session.peer_addr_n,
523 "Peer IPv4 address")
524 else:
525 test.assert_equal(e.local_addr, test.vpp_session.local_addr_n,
526 "Local IPv6 address")
527 test.assert_equal(e.peer_addr, test.vpp_session.peer_addr_n,
528 "Peer IPv6 address")
529 test.assert_equal(e.state, expected_state, BFDState)
530
531
532def wait_for_bfd_packet(test, timeout=1, pcap_time_min=None):
533 """ wait for BFD packet and verify its correctness
534
535 :param timeout: how long to wait
536 :param pcap_time_min: ignore packets with pcap timestamp lower than this
537
538 :returns: tuple (packet, time spent waiting for packet)
539 """
540 test.logger.info("BFD: Waiting for BFD packet")
541 deadline = time.time() + timeout
542 counter = 0
543 while True:
544 counter += 1
545 # sanity check
546 test.assert_in_range(counter, 0, 100, "number of packets ignored")
547 time_left = deadline - time.time()
548 if time_left < 0:
549 raise CaptureTimeoutError("Packet did not arrive within timeout")
550 p = test.pg0.wait_for_packet(timeout=time_left)
551 test.logger.debug(ppp("BFD: Got packet:", p))
552 if pcap_time_min is not None and p.time < pcap_time_min:
553 test.logger.debug(ppp("BFD: ignoring packet (pcap time %s < "
554 "pcap time min %s):" %
555 (p.time, pcap_time_min), p))
Klement Sekera46a87ad2017-01-02 08:22:23 +0100556 else:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100557 break
558 bfd = p[BFD]
559 if bfd is None:
560 raise Exception(ppp("Unexpected or invalid BFD packet:", p))
561 if bfd.payload:
562 raise Exception(ppp("Unexpected payload in BFD packet:", bfd))
563 verify_ip(test, p)
564 verify_udp(test, p)
565 test.test_session.verify_bfd(p)
566 return p
Klement Sekera3e0a3562016-12-19 09:05:21 +0100567
Klement Sekera46a87ad2017-01-02 08:22:23 +0100568
Klement Sekerad3ba5152017-02-14 03:09:17 +0100569class BFD4TestCase(VppTestCase):
Klement Sekera46a87ad2017-01-02 08:22:23 +0100570 """Bidirectional Forwarding Detection (BFD)"""
571
Klement Sekerad3ba5152017-02-14 03:09:17 +0100572 pg0 = None
573 vpp_clock_offset = None
574 vpp_session = None
575 test_session = None
576
Klement Sekera46a87ad2017-01-02 08:22:23 +0100577 @classmethod
578 def setUpClass(cls):
579 super(BFD4TestCase, cls).setUpClass()
580 try:
581 cls.create_pg_interfaces([0])
582 cls.pg0.config_ip4()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100583 cls.pg0.configure_ipv4_neighbors()
584 cls.pg0.admin_up()
585 cls.pg0.resolve_arp()
586
587 except Exception:
588 super(BFD4TestCase, cls).tearDownClass()
589 raise
590
591 def setUp(self):
592 super(BFD4TestCase, self).setUp()
Klement Sekerab17dd962017-01-09 07:43:48 +0100593 self.factory = AuthKeyFactory()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100594 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100595 self.pg0.enable_capture()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100596 try:
597 self.vpp_session = VppBFDUDPSession(self, self.pg0,
598 self.pg0.remote_ip4)
599 self.vpp_session.add_vpp_config()
600 self.vpp_session.admin_up()
601 self.test_session = BFDTestSession(self, self.pg0, AF_INET)
602 except:
603 self.vapi.want_bfd_events(enable_disable=0)
604 raise
605
606 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100607 if not self.vpp_dead:
608 self.vapi.want_bfd_events(enable_disable=0)
609 self.vapi.collect_events() # clear the event queue
610 super(BFD4TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +0100611
612 def test_session_up(self):
613 """ bring BFD session up """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100614 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +0100615
616 def test_session_down(self):
617 """ bring BFD session down """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100618 bfd_session_up(self)
619 bfd_session_down(self)
Klement Sekerab17dd962017-01-09 07:43:48 +0100620
621 def test_hold_up(self):
622 """ hold BFD session up """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100623 bfd_session_up(self)
624 for dummy in range(self.test_session.detect_mult * 2):
625 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +0100626 self.test_session.send_packet()
627 self.assert_equal(len(self.vapi.collect_events()), 0,
628 "number of bfd events")
Klement Sekera46a87ad2017-01-02 08:22:23 +0100629
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200630 def test_slow_timer(self):
Klement Sekerae4504c62016-12-08 10:16:41 +0100631 """ verify slow periodic control frames while session down """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100632 packet_count = 3
633 self.logger.info("BFD: Waiting for %d BFD packets", packet_count)
634 prev_packet = wait_for_bfd_packet(self, 2)
635 for dummy in range(packet_count):
636 next_packet = wait_for_bfd_packet(self, 2)
637 time_diff = next_packet.time - prev_packet.time
Klement Sekerae4504c62016-12-08 10:16:41 +0100638 # spec says the range should be <0.75, 1>, allow extra 0.05 margin
639 # to work around timing issues
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200640 self.assert_in_range(
Klement Sekerad3ba5152017-02-14 03:09:17 +0100641 time_diff, 0.70, 1.05, "time between slow packets")
642 prev_packet = next_packet
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200643
644 def test_zero_remote_min_rx(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100645 """ no packets when zero remote required min rx interval """
646 bfd_session_up(self)
647 self.test_session.update(required_min_rx=0)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200648 self.test_session.send_packet()
Klement Sekeraa57a9702017-02-02 06:58:07 +0100649 cap = 2 * self.vpp_session.desired_min_tx *\
Klement Sekerad3ba5152017-02-14 03:09:17 +0100650 self.test_session.detect_mult
651 time_mark = time.time()
Klement Sekeraa57a9702017-02-02 06:58:07 +0100652 count = 0
653 # busy wait here, trying to collect a packet or event, vpp is not
654 # allowed to send packets and the session will timeout first - so the
655 # Up->Down event must arrive before any packets do
Klement Sekerad3ba5152017-02-14 03:09:17 +0100656 while time.time() < time_mark + cap / USEC_IN_SEC:
Klement Sekeraa57a9702017-02-02 06:58:07 +0100657 try:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100658 p = wait_for_bfd_packet(
659 self, timeout=0,
660 pcap_time_min=time_mark - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100661 self.logger.error(ppp("Received unexpected packet:", p))
662 count += 1
Klement Sekerad3ba5152017-02-14 03:09:17 +0100663 except CaptureTimeoutError:
Klement Sekeraa57a9702017-02-02 06:58:07 +0100664 pass
665 events = self.vapi.collect_events()
666 if len(events) > 0:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100667 verify_event(self, events[0], BFDState.down)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100668 break
669 self.assert_equal(count, 0, "number of packets received")
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200670
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200671 def test_conn_down(self):
Klement Sekerae4504c62016-12-08 10:16:41 +0100672 """ verify session goes down after inactivity """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100673 bfd_session_up(self)
674 for dummy in range(self.test_session.detect_mult):
675 wait_for_bfd_packet(self)
676 self.assert_equal(len(self.vapi.collect_events()), 0,
677 "number of bfd events")
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200678 e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100679 verify_event(self, e, expected_state=BFDState.down)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200680
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200681 def test_large_required_min_rx(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100682 """ large remote required min rx interval """
683 bfd_session_up(self)
684 p = wait_for_bfd_packet(self)
Klement Sekera637b9c42016-12-08 05:19:14 +0100685 interval = 3000000
Klement Sekerad3ba5152017-02-14 03:09:17 +0100686 self.test_session.update(required_min_rx=interval)
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200687 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100688 time_mark = time.time()
Klement Sekera637b9c42016-12-08 05:19:14 +0100689 count = 0
Klement Sekeraa57a9702017-02-02 06:58:07 +0100690 # busy wait here, trying to collect a packet or event, vpp is not
691 # allowed to send packets and the session will timeout first - so the
692 # Up->Down event must arrive before any packets do
Klement Sekerad3ba5152017-02-14 03:09:17 +0100693 while time.time() < time_mark + interval / USEC_IN_SEC:
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200694 try:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100695 p = wait_for_bfd_packet(self, timeout=0)
696 # if vpp managed to send a packet before we did the session
697 # session update, then that's fine, ignore it
698 if p.time < time_mark - self.vpp_clock_offset:
699 continue
Klement Sekeraa57a9702017-02-02 06:58:07 +0100700 self.logger.error(ppp("Received unexpected packet:", p))
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200701 count += 1
Klement Sekerad3ba5152017-02-14 03:09:17 +0100702 except CaptureTimeoutError:
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200703 pass
Klement Sekeraa57a9702017-02-02 06:58:07 +0100704 events = self.vapi.collect_events()
705 if len(events) > 0:
Klement Sekerad3ba5152017-02-14 03:09:17 +0100706 verify_event(self, events[0], BFDState.down)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100707 break
708 self.assert_equal(count, 0, "number of packets received")
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200709
Klement Sekerad3ba5152017-02-14 03:09:17 +0100710 def test_immediate_remote_min_rx_reduction(self):
711 """ immediately honor remote required min rx reduction """
Klement Sekera3e0a3562016-12-19 09:05:21 +0100712 self.vpp_session.remove_vpp_config()
Klement Sekera10db26f2017-01-11 08:16:53 +0100713 self.vpp_session = VppBFDUDPSession(
714 self, self.pg0, self.pg0.remote_ip4, desired_min_tx=10000)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100715 self.pg0.enable_capture()
Klement Sekera3e0a3562016-12-19 09:05:21 +0100716 self.vpp_session.add_vpp_config()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100717 self.test_session.update(desired_min_tx=1000000,
718 required_min_rx=1000000)
719 bfd_session_up(self)
720 reference_packet = wait_for_bfd_packet(self)
721 time_mark = time.time()
722 interval = 300000
723 self.test_session.update(required_min_rx=interval)
Klement Sekera3e0a3562016-12-19 09:05:21 +0100724 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100725 extra_time = time.time() - time_mark
726 p = wait_for_bfd_packet(self)
727 # first packet is allowed to be late by time we spent doing the update
728 # calculated in extra_time
729 self.assert_in_range(p.time - reference_packet.time,
730 .95 * 0.75 * interval / USEC_IN_SEC,
731 1.05 * interval / USEC_IN_SEC + extra_time,
Klement Sekera3e0a3562016-12-19 09:05:21 +0100732 "time between BFD packets")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100733 reference_packet = p
734 for dummy in range(3):
735 p = wait_for_bfd_packet(self)
736 diff = p.time - reference_packet.time
737 self.assert_in_range(diff, .95 * .75 * interval / USEC_IN_SEC,
738 1.05 * interval / USEC_IN_SEC,
739 "time between BFD packets")
740 reference_packet = p
Klement Sekera0e3c0de2016-09-29 14:43:44 +0200741
Klement Sekeraa57a9702017-02-02 06:58:07 +0100742 def test_modify_req_min_rx_double(self):
743 """ modify session - double required min rx """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100744 bfd_session_up(self)
745 p = wait_for_bfd_packet(self)
746 self.test_session.update(desired_min_tx=10000,
747 required_min_rx=10000)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100748 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100749 # double required min rx
Klement Sekeraa57a9702017-02-02 06:58:07 +0100750 self.vpp_session.modify_parameters(
751 required_min_rx=2 * self.vpp_session.required_min_rx)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100752 p = wait_for_bfd_packet(
753 self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100754 # poll bit needs to be set
755 self.assertIn("P", p.sprintf("%BFD.flags%"),
756 "Poll bit not set in BFD packet")
757 # finish poll sequence with final packet
758 final = self.test_session.create_packet()
759 final[BFD].flags = "F"
Klement Sekerad3ba5152017-02-14 03:09:17 +0100760 timeout = self.test_session.detect_mult * \
761 max(self.test_session.desired_min_tx,
762 self.vpp_session.required_min_rx) / USEC_IN_SEC
Klement Sekeraa57a9702017-02-02 06:58:07 +0100763 self.test_session.send_packet(final)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100764 time_mark = time.time()
765 e = self.vapi.wait_for_event(2 * timeout, "bfd_udp_session_details")
766 verify_event(self, e, expected_state=BFDState.down)
767 time_to_event = time.time() - time_mark
768 self.assert_in_range(time_to_event, .9 * timeout,
769 1.1 * timeout, "session timeout")
Klement Sekeraa57a9702017-02-02 06:58:07 +0100770
771 def test_modify_req_min_rx_halve(self):
772 """ modify session - halve required min rx """
773 self.vpp_session.modify_parameters(
774 required_min_rx=2 * self.vpp_session.required_min_rx)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100775 bfd_session_up(self)
776 p = wait_for_bfd_packet(self)
777 self.test_session.update(desired_min_tx=10000,
778 required_min_rx=10000)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100779 self.test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100780 p = wait_for_bfd_packet(
781 self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100782 # halve required min rx
783 old_required_min_rx = self.vpp_session.required_min_rx
784 self.vpp_session.modify_parameters(
785 required_min_rx=0.5 * self.vpp_session.required_min_rx)
786 # now we wait 0.8*3*old-req-min-rx and the session should still be up
787 self.sleep(0.8 * self.vpp_session.detect_mult *
Klement Sekerad3ba5152017-02-14 03:09:17 +0100788 old_required_min_rx / USEC_IN_SEC)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100789 self.assert_equal(len(self.vapi.collect_events()), 0,
790 "number of bfd events")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100791 p = wait_for_bfd_packet(self)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100792 # poll bit needs to be set
793 self.assertIn("P", p.sprintf("%BFD.flags%"),
794 "Poll bit not set in BFD packet")
795 # finish poll sequence with final packet
796 final = self.test_session.create_packet()
797 final[BFD].flags = "F"
798 self.test_session.send_packet(final)
799 # now the session should time out under new conditions
800 before = time.time()
801 e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
802 after = time.time()
803 detection_time = self.vpp_session.detect_mult *\
Klement Sekerad3ba5152017-02-14 03:09:17 +0100804 self.vpp_session.required_min_rx / USEC_IN_SEC
Klement Sekeraa57a9702017-02-02 06:58:07 +0100805 self.assert_in_range(after - before,
806 0.9 * detection_time,
807 1.1 * detection_time,
808 "time before bfd session goes down")
Klement Sekerad3ba5152017-02-14 03:09:17 +0100809 verify_event(self, e, expected_state=BFDState.down)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100810
811 def test_modify_des_min_tx(self):
812 """ modify desired min tx interval """
813 pass
814
815 def test_modify_detect_mult(self):
816 """ modify detect multiplier """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100817 bfd_session_up(self)
818 p = wait_for_bfd_packet(self)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100819 self.vpp_session.modify_parameters(detect_mult=1)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100820 p = wait_for_bfd_packet(
821 self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100822 self.assert_equal(self.vpp_session.detect_mult,
823 p[BFD].detect_mult,
824 "detect mult")
825 # poll bit must not be set
826 self.assertNotIn("P", p.sprintf("%BFD.flags%"),
827 "Poll bit not set in BFD packet")
828 self.vpp_session.modify_parameters(detect_mult=10)
Klement Sekerad3ba5152017-02-14 03:09:17 +0100829 p = wait_for_bfd_packet(
830 self, pcap_time_min=time.time() - self.vpp_clock_offset)
Klement Sekeraa57a9702017-02-02 06:58:07 +0100831 self.assert_equal(self.vpp_session.detect_mult,
832 p[BFD].detect_mult,
833 "detect mult")
834 # poll bit must not be set
835 self.assertNotIn("P", p.sprintf("%BFD.flags%"),
836 "Poll bit not set in BFD packet")
837
Klement Sekerad3ba5152017-02-14 03:09:17 +0100838 def test_no_periodic_if_remote_demand(self):
839 """ no periodic frames outside poll sequence if remote demand set """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100840 bfd_session_up(self)
841 demand = self.test_session.create_packet()
842 demand[BFD].flags = "D"
843 self.test_session.send_packet(demand)
844 transmit_time = 0.9 \
845 * max(self.vpp_session.required_min_rx,
846 self.test_session.desired_min_tx) \
847 / USEC_IN_SEC
848 count = 0
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100849 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100850 time.sleep(transmit_time)
851 self.test_session.send_packet(demand)
852 try:
853 p = wait_for_bfd_packet(self, timeout=0)
854 self.logger.error(ppp("Received unexpected packet:", p))
855 count += 1
856 except CaptureTimeoutError:
857 pass
858 events = self.vapi.collect_events()
859 for e in events:
860 self.logger.error("Received unexpected event: %s", e)
861 self.assert_equal(count, 0, "number of packets received")
862 self.assert_equal(len(events), 0, "number of events received")
Klement Sekera46a87ad2017-01-02 08:22:23 +0100863
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100864 def test_echo_looped_back(self):
865 """ echo packets looped back """
866 # don't need a session in this case..
867 self.vpp_session.remove_vpp_config()
868 self.pg0.enable_capture()
869 echo_packet_count = 10
870 # random source port low enough to increment a few times..
871 udp_sport_tx = randint(1, 50000)
872 udp_sport_rx = udp_sport_tx
873 echo_packet = (Ether(src=self.pg0.remote_mac,
874 dst=self.pg0.local_mac) /
875 IP(src=self.pg0.remote_ip4,
876 dst=self.pg0.local_ip4) /
877 UDP(dport=BFD.udp_dport_echo) /
878 Raw("this should be looped back"))
879 for dummy in range(echo_packet_count):
880 self.sleep(.01, "delay between echo packets")
881 echo_packet[UDP].sport = udp_sport_tx
882 udp_sport_tx += 1
883 self.logger.debug(ppp("Sending packet:", echo_packet))
884 self.pg0.add_stream(echo_packet)
885 self.pg_start()
886 for dummy in range(echo_packet_count):
887 p = self.pg0.wait_for_packet(1)
888 self.logger.debug(ppp("Got packet:", p))
889 ether = p[Ether]
890 self.assert_equal(self.pg0.remote_mac,
891 ether.dst, "Destination MAC")
892 self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC")
893 ip = p[IP]
894 self.assert_equal(self.pg0.remote_ip4, ip.dst, "Destination IP")
895 self.assert_equal(self.pg0.local_ip4, ip.src, "Destination IP")
896 udp = p[UDP]
897 self.assert_equal(udp.dport, BFD.udp_dport_echo,
898 "UDP destination port")
899 self.assert_equal(udp.sport, udp_sport_rx, "UDP source port")
900 udp_sport_rx += 1
901 self.assertTrue(p.haslayer(Raw) and p[Raw] == echo_packet[Raw],
902 "Received packet is not the echo packet sent")
903 self.assert_equal(udp_sport_tx, udp_sport_rx, "UDP source port (== "
904 "ECHO packet identifier for test purposes)")
905
Klement Sekerad3ba5152017-02-14 03:09:17 +0100906
907class BFD6TestCase(VppTestCase):
Klement Sekera46a87ad2017-01-02 08:22:23 +0100908 """Bidirectional Forwarding Detection (BFD) (IPv6) """
909
Klement Sekerad3ba5152017-02-14 03:09:17 +0100910 pg0 = None
911 vpp_clock_offset = None
912 vpp_session = None
913 test_session = None
914
Klement Sekera46a87ad2017-01-02 08:22:23 +0100915 @classmethod
916 def setUpClass(cls):
917 super(BFD6TestCase, cls).setUpClass()
918 try:
919 cls.create_pg_interfaces([0])
920 cls.pg0.config_ip6()
921 cls.pg0.configure_ipv6_neighbors()
922 cls.pg0.admin_up()
923 cls.pg0.resolve_ndp()
924
925 except Exception:
926 super(BFD6TestCase, cls).tearDownClass()
927 raise
928
929 def setUp(self):
930 super(BFD6TestCase, self).setUp()
Klement Sekerab17dd962017-01-09 07:43:48 +0100931 self.factory = AuthKeyFactory()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100932 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +0100933 self.pg0.enable_capture()
Klement Sekera46a87ad2017-01-02 08:22:23 +0100934 try:
935 self.vpp_session = VppBFDUDPSession(self, self.pg0,
936 self.pg0.remote_ip6,
937 af=AF_INET6)
938 self.vpp_session.add_vpp_config()
939 self.vpp_session.admin_up()
940 self.test_session = BFDTestSession(self, self.pg0, AF_INET6)
941 self.logger.debug(self.vapi.cli("show adj nbr"))
942 except:
943 self.vapi.want_bfd_events(enable_disable=0)
944 raise
945
946 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100947 if not self.vpp_dead:
948 self.vapi.want_bfd_events(enable_disable=0)
949 self.vapi.collect_events() # clear the event queue
950 super(BFD6TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +0100951
952 def test_session_up(self):
953 """ bring BFD session up """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100954 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +0100955
956 def test_hold_up(self):
957 """ hold BFD session up """
Klement Sekerad3ba5152017-02-14 03:09:17 +0100958 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100959 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +0100960 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +0100961 self.test_session.send_packet()
962 self.assert_equal(len(self.vapi.collect_events()), 0,
963 "number of bfd events")
964 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
965
Klement Sekeraaeeac3b2017-02-14 07:11:52 +0100966 def test_echo_looped_back(self):
967 """ echo packets looped back """
968 # don't need a session in this case..
969 self.vpp_session.remove_vpp_config()
970 self.pg0.enable_capture()
971 echo_packet_count = 10
972 # random source port low enough to increment a few times..
973 udp_sport_tx = randint(1, 50000)
974 udp_sport_rx = udp_sport_tx
975 echo_packet = (Ether(src=self.pg0.remote_mac,
976 dst=self.pg0.local_mac) /
977 IPv6(src=self.pg0.remote_ip6,
978 dst=self.pg0.local_ip6) /
979 UDP(dport=BFD.udp_dport_echo) /
980 Raw("this should be looped back"))
981 for dummy in range(echo_packet_count):
982 self.sleep(.01, "delay between echo packets")
983 echo_packet[UDP].sport = udp_sport_tx
984 udp_sport_tx += 1
985 self.logger.debug(ppp("Sending packet:", echo_packet))
986 self.pg0.add_stream(echo_packet)
987 self.pg_start()
988 for dummy in range(echo_packet_count):
989 p = self.pg0.wait_for_packet(1)
990 self.logger.debug(ppp("Got packet:", p))
991 ether = p[Ether]
992 self.assert_equal(self.pg0.remote_mac,
993 ether.dst, "Destination MAC")
994 self.assert_equal(self.pg0.local_mac, ether.src, "Source MAC")
995 ip = p[IPv6]
996 self.assert_equal(self.pg0.remote_ip6, ip.dst, "Destination IP")
997 self.assert_equal(self.pg0.local_ip6, ip.src, "Destination IP")
998 udp = p[UDP]
999 self.assert_equal(udp.dport, BFD.udp_dport_echo,
1000 "UDP destination port")
1001 self.assert_equal(udp.sport, udp_sport_rx, "UDP source port")
1002 udp_sport_rx += 1
1003 self.assertTrue(p.haslayer(Raw) and p[Raw] == echo_packet[Raw],
1004 "Received packet is not the echo packet sent")
1005 self.assert_equal(udp_sport_tx, udp_sport_rx, "UDP source port (== "
1006 "ECHO packet identifier for test purposes)")
1007
Klement Sekerab17dd962017-01-09 07:43:48 +01001008
Klement Sekerad3ba5152017-02-14 03:09:17 +01001009class BFDSHA1TestCase(VppTestCase):
Klement Sekerab17dd962017-01-09 07:43:48 +01001010 """Bidirectional Forwarding Detection (BFD) (SHA1 auth) """
1011
Klement Sekerad3ba5152017-02-14 03:09:17 +01001012 pg0 = None
1013 vpp_clock_offset = None
1014 vpp_session = None
1015 test_session = None
1016
Klement Sekerab17dd962017-01-09 07:43:48 +01001017 @classmethod
1018 def setUpClass(cls):
1019 super(BFDSHA1TestCase, cls).setUpClass()
1020 try:
1021 cls.create_pg_interfaces([0])
1022 cls.pg0.config_ip4()
1023 cls.pg0.admin_up()
1024 cls.pg0.resolve_arp()
1025
1026 except Exception:
1027 super(BFDSHA1TestCase, cls).tearDownClass()
1028 raise
1029
1030 def setUp(self):
1031 super(BFDSHA1TestCase, self).setUp()
1032 self.factory = AuthKeyFactory()
1033 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001034 self.pg0.enable_capture()
Klement Sekerab17dd962017-01-09 07:43:48 +01001035
1036 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001037 if not self.vpp_dead:
1038 self.vapi.want_bfd_events(enable_disable=0)
1039 self.vapi.collect_events() # clear the event queue
1040 super(BFDSHA1TestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01001041
1042 def test_session_up(self):
1043 """ bring BFD session up """
1044 key = self.factory.create_random_key(self)
1045 key.add_vpp_config()
1046 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1047 self.pg0.remote_ip4,
1048 sha1_key=key)
1049 self.vpp_session.add_vpp_config()
1050 self.vpp_session.admin_up()
1051 self.test_session = BFDTestSession(
1052 self, self.pg0, AF_INET, sha1_key=key,
1053 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001054 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001055
1056 def test_hold_up(self):
1057 """ hold BFD session up """
1058 key = self.factory.create_random_key(self)
1059 key.add_vpp_config()
1060 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1061 self.pg0.remote_ip4,
1062 sha1_key=key)
1063 self.vpp_session.add_vpp_config()
1064 self.vpp_session.admin_up()
1065 self.test_session = BFDTestSession(
1066 self, self.pg0, AF_INET, sha1_key=key,
1067 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001068 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001069 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001070 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001071 self.test_session.send_packet()
1072 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1073
1074 def test_hold_up_meticulous(self):
1075 """ hold BFD session up - meticulous auth """
1076 key = self.factory.create_random_key(
1077 self, BFDAuthType.meticulous_keyed_sha1)
1078 key.add_vpp_config()
1079 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1080 self.pg0.remote_ip4, sha1_key=key)
1081 self.vpp_session.add_vpp_config()
1082 self.vpp_session.admin_up()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001083 # specify sequence number so that it wraps
Klement Sekerab17dd962017-01-09 07:43:48 +01001084 self.test_session = BFDTestSession(
1085 self, self.pg0, AF_INET, sha1_key=key,
Klement Sekerad3ba5152017-02-14 03:09:17 +01001086 bfd_key_id=self.vpp_session.bfd_key_id,
1087 our_seq_number=0xFFFFFFFF - 4)
1088 bfd_session_up(self)
1089 for dummy in range(30):
1090 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001091 self.test_session.inc_seq_num()
1092 self.test_session.send_packet()
1093 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1094
1095 def test_send_bad_seq_number(self):
1096 """ session is not kept alive by msgs with bad seq numbers"""
1097 key = self.factory.create_random_key(
1098 self, BFDAuthType.meticulous_keyed_sha1)
1099 key.add_vpp_config()
1100 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1101 self.pg0.remote_ip4, sha1_key=key)
1102 self.vpp_session.add_vpp_config()
1103 self.vpp_session.admin_up()
1104 self.test_session = BFDTestSession(
1105 self, self.pg0, AF_INET, sha1_key=key,
1106 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001107 bfd_session_up(self)
1108 detection_time = self.vpp_session.detect_mult *\
1109 self.vpp_session.required_min_rx / USEC_IN_SEC
1110 session_timeout = time.time() + detection_time
1111 while time.time() < session_timeout:
1112 self.assert_equal(len(self.vapi.collect_events()), 0,
1113 "number of bfd events")
1114 wait_for_bfd_packet(self)
1115 self.test_session.send_packet()
1116 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001117 self.test_session.send_packet()
1118 e = self.vapi.collect_events()
1119 # session should be down now, because the sequence numbers weren't
1120 # updated
1121 self.assert_equal(len(e), 1, "number of bfd events")
Klement Sekerad3ba5152017-02-14 03:09:17 +01001122 verify_event(self, e[0], expected_state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01001123
1124 def execute_rogue_session_scenario(self, vpp_bfd_udp_session,
1125 legitimate_test_session,
1126 rogue_test_session,
1127 rogue_bfd_values=None):
1128 """ execute a rogue session interaction scenario
1129
1130 1. create vpp session, add config
1131 2. bring the legitimate session up
1132 3. copy the bfd values from legitimate session to rogue session
1133 4. apply rogue_bfd_values to rogue session
1134 5. set rogue session state to down
1135 6. send message to take the session down from the rogue session
1136 7. assert that the legitimate session is unaffected
1137 """
1138
1139 self.vpp_session = vpp_bfd_udp_session
1140 self.vpp_session.add_vpp_config()
1141 self.vpp_session.admin_up()
1142 self.test_session = legitimate_test_session
1143 # bring vpp session up
Klement Sekerad3ba5152017-02-14 03:09:17 +01001144 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001145 # send packet from rogue session
Klement Sekerad3ba5152017-02-14 03:09:17 +01001146 rogue_test_session.update(
1147 my_discriminator=self.test_session.my_discriminator,
1148 your_discriminator=self.test_session.your_discriminator,
1149 desired_min_tx=self.test_session.desired_min_tx,
1150 required_min_rx=self.test_session.required_min_rx,
1151 detect_mult=self.test_session.detect_mult,
1152 diag=self.test_session.diag,
1153 state=self.test_session.state,
1154 auth_type=self.test_session.auth_type)
Klement Sekerab17dd962017-01-09 07:43:48 +01001155 if rogue_bfd_values:
1156 rogue_test_session.update(**rogue_bfd_values)
1157 rogue_test_session.update(state=BFDState.down)
1158 rogue_test_session.send_packet()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001159 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001160 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1161
1162 def test_mismatch_auth(self):
1163 """ session is not brought down by unauthenticated msg """
1164 key = self.factory.create_random_key(self)
1165 key.add_vpp_config()
1166 vpp_session = VppBFDUDPSession(
1167 self, self.pg0, self.pg0.remote_ip4, sha1_key=key)
1168 legitimate_test_session = BFDTestSession(
1169 self, self.pg0, AF_INET, sha1_key=key,
1170 bfd_key_id=vpp_session.bfd_key_id)
1171 rogue_test_session = BFDTestSession(self, self.pg0, AF_INET)
1172 self.execute_rogue_session_scenario(vpp_session,
1173 legitimate_test_session,
1174 rogue_test_session)
1175
1176 def test_mismatch_bfd_key_id(self):
1177 """ session is not brought down by msg with non-existent key-id """
1178 key = self.factory.create_random_key(self)
1179 key.add_vpp_config()
1180 vpp_session = VppBFDUDPSession(
1181 self, self.pg0, self.pg0.remote_ip4, sha1_key=key)
1182 # pick a different random bfd key id
1183 x = randint(0, 255)
1184 while x == vpp_session.bfd_key_id:
1185 x = randint(0, 255)
1186 legitimate_test_session = BFDTestSession(
1187 self, self.pg0, AF_INET, sha1_key=key,
1188 bfd_key_id=vpp_session.bfd_key_id)
1189 rogue_test_session = BFDTestSession(
1190 self, self.pg0, AF_INET, sha1_key=key, bfd_key_id=x)
1191 self.execute_rogue_session_scenario(vpp_session,
1192 legitimate_test_session,
1193 rogue_test_session)
1194
1195 def test_mismatched_auth_type(self):
1196 """ session is not brought down by msg with wrong auth type """
1197 key = self.factory.create_random_key(self)
1198 key.add_vpp_config()
1199 vpp_session = VppBFDUDPSession(
1200 self, self.pg0, self.pg0.remote_ip4, sha1_key=key)
1201 legitimate_test_session = BFDTestSession(
1202 self, self.pg0, AF_INET, sha1_key=key,
1203 bfd_key_id=vpp_session.bfd_key_id)
1204 rogue_test_session = BFDTestSession(
1205 self, self.pg0, AF_INET, sha1_key=key,
1206 bfd_key_id=vpp_session.bfd_key_id)
1207 self.execute_rogue_session_scenario(
1208 vpp_session, legitimate_test_session, rogue_test_session,
1209 {'auth_type': BFDAuthType.keyed_md5})
1210
1211 def test_restart(self):
1212 """ simulate remote peer restart and resynchronization """
1213 key = self.factory.create_random_key(
1214 self, BFDAuthType.meticulous_keyed_sha1)
1215 key.add_vpp_config()
1216 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1217 self.pg0.remote_ip4, sha1_key=key)
1218 self.vpp_session.add_vpp_config()
1219 self.vpp_session.admin_up()
1220 self.test_session = BFDTestSession(
1221 self, self.pg0, AF_INET, sha1_key=key,
1222 bfd_key_id=self.vpp_session.bfd_key_id, our_seq_number=0)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001223 bfd_session_up(self)
1224 # don't send any packets for 2*detection_time
1225 detection_time = self.vpp_session.detect_mult *\
1226 self.vpp_session.required_min_rx / USEC_IN_SEC
1227 self.sleep(detection_time, "simulating peer restart")
1228 events = self.vapi.collect_events()
1229 self.assert_equal(len(events), 1, "number of bfd events")
1230 verify_event(self, events[0], expected_state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01001231 self.test_session.update(state=BFDState.down)
Klement Sekerab17dd962017-01-09 07:43:48 +01001232 # reset sequence number
1233 self.test_session.our_seq_number = 0
Klement Sekerad3ba5152017-02-14 03:09:17 +01001234 self.test_session.vpp_seq_number = None
1235 # now throw away any pending packets
1236 self.pg0.enable_capture()
1237 bfd_session_up(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001238
1239
Klement Sekerad3ba5152017-02-14 03:09:17 +01001240class BFDAuthOnOffTestCase(VppTestCase):
Klement Sekerab17dd962017-01-09 07:43:48 +01001241 """Bidirectional Forwarding Detection (BFD) (changing auth) """
1242
Klement Sekerad3ba5152017-02-14 03:09:17 +01001243 pg0 = None
1244 vpp_session = None
1245 test_session = None
1246
Klement Sekerab17dd962017-01-09 07:43:48 +01001247 @classmethod
1248 def setUpClass(cls):
1249 super(BFDAuthOnOffTestCase, cls).setUpClass()
1250 try:
1251 cls.create_pg_interfaces([0])
1252 cls.pg0.config_ip4()
1253 cls.pg0.admin_up()
1254 cls.pg0.resolve_arp()
1255
1256 except Exception:
1257 super(BFDAuthOnOffTestCase, cls).tearDownClass()
1258 raise
1259
1260 def setUp(self):
1261 super(BFDAuthOnOffTestCase, self).setUp()
1262 self.factory = AuthKeyFactory()
1263 self.vapi.want_bfd_events()
Klement Sekerad3ba5152017-02-14 03:09:17 +01001264 self.pg0.enable_capture()
Klement Sekerab17dd962017-01-09 07:43:48 +01001265
1266 def tearDown(self):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001267 if not self.vpp_dead:
1268 self.vapi.want_bfd_events(enable_disable=0)
1269 self.vapi.collect_events() # clear the event queue
1270 super(BFDAuthOnOffTestCase, self).tearDown()
Klement Sekerab17dd962017-01-09 07:43:48 +01001271
1272 def test_auth_on_immediate(self):
1273 """ turn auth on without disturbing session state (immediate) """
1274 key = self.factory.create_random_key(self)
1275 key.add_vpp_config()
1276 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1277 self.pg0.remote_ip4)
1278 self.vpp_session.add_vpp_config()
1279 self.vpp_session.admin_up()
1280 self.test_session = BFDTestSession(self, self.pg0, AF_INET)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001281 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001282 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001283 p = wait_for_bfd_packet(self)
1284 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001285 self.test_session.send_packet()
1286 self.vpp_session.activate_auth(key)
1287 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
1288 self.test_session.sha1_key = key
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001289 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001290 p = wait_for_bfd_packet(self)
1291 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001292 self.test_session.send_packet()
1293 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1294 self.assert_equal(len(self.vapi.collect_events()), 0,
1295 "number of bfd events")
1296
1297 def test_auth_off_immediate(self):
1298 """ turn auth off without disturbing session state (immediate) """
1299 key = self.factory.create_random_key(self)
1300 key.add_vpp_config()
1301 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1302 self.pg0.remote_ip4, sha1_key=key)
1303 self.vpp_session.add_vpp_config()
1304 self.vpp_session.admin_up()
1305 self.test_session = BFDTestSession(
1306 self, self.pg0, AF_INET, sha1_key=key,
1307 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001308 bfd_session_up(self)
1309 # self.vapi.want_bfd_events(enable_disable=0)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001310 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001311 p = wait_for_bfd_packet(self)
1312 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
1313 self.test_session.inc_seq_num()
Klement Sekerab17dd962017-01-09 07:43:48 +01001314 self.test_session.send_packet()
1315 self.vpp_session.deactivate_auth()
1316 self.test_session.bfd_key_id = None
1317 self.test_session.sha1_key = None
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001318 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001319 p = wait_for_bfd_packet(self)
1320 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
1321 self.test_session.inc_seq_num()
Klement Sekerab17dd962017-01-09 07:43:48 +01001322 self.test_session.send_packet()
1323 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1324 self.assert_equal(len(self.vapi.collect_events()), 0,
1325 "number of bfd events")
1326
1327 def test_auth_change_key_immediate(self):
1328 """ change auth key without disturbing session state (immediate) """
1329 key1 = self.factory.create_random_key(self)
1330 key1.add_vpp_config()
1331 key2 = self.factory.create_random_key(self)
1332 key2.add_vpp_config()
1333 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1334 self.pg0.remote_ip4, sha1_key=key1)
1335 self.vpp_session.add_vpp_config()
1336 self.vpp_session.admin_up()
1337 self.test_session = BFDTestSession(
1338 self, self.pg0, AF_INET, sha1_key=key1,
1339 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001340 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001341 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001342 p = wait_for_bfd_packet(self)
1343 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001344 self.test_session.send_packet()
1345 self.vpp_session.activate_auth(key2)
1346 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
1347 self.test_session.sha1_key = key2
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001348 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001349 p = wait_for_bfd_packet(self)
1350 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001351 self.test_session.send_packet()
1352 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1353 self.assert_equal(len(self.vapi.collect_events()), 0,
1354 "number of bfd events")
1355
1356 def test_auth_on_delayed(self):
1357 """ turn auth on without disturbing session state (delayed) """
1358 key = self.factory.create_random_key(self)
1359 key.add_vpp_config()
1360 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1361 self.pg0.remote_ip4)
1362 self.vpp_session.add_vpp_config()
1363 self.vpp_session.admin_up()
1364 self.test_session = BFDTestSession(self, self.pg0, AF_INET)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001365 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001366 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001367 wait_for_bfd_packet(self)
Klement Sekerab17dd962017-01-09 07:43:48 +01001368 self.test_session.send_packet()
1369 self.vpp_session.activate_auth(key, delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001370 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001371 p = wait_for_bfd_packet(self)
1372 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001373 self.test_session.send_packet()
1374 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
1375 self.test_session.sha1_key = key
1376 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001377 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001378 p = wait_for_bfd_packet(self)
1379 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001380 self.test_session.send_packet()
1381 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1382 self.assert_equal(len(self.vapi.collect_events()), 0,
1383 "number of bfd events")
1384
1385 def test_auth_off_delayed(self):
1386 """ turn auth off without disturbing session state (delayed) """
1387 key = self.factory.create_random_key(self)
1388 key.add_vpp_config()
1389 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1390 self.pg0.remote_ip4, sha1_key=key)
1391 self.vpp_session.add_vpp_config()
1392 self.vpp_session.admin_up()
1393 self.test_session = BFDTestSession(
1394 self, self.pg0, AF_INET, sha1_key=key,
1395 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001396 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001397 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001398 p = wait_for_bfd_packet(self)
1399 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001400 self.test_session.send_packet()
1401 self.vpp_session.deactivate_auth(delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001402 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001403 p = wait_for_bfd_packet(self)
1404 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001405 self.test_session.send_packet()
1406 self.test_session.bfd_key_id = None
1407 self.test_session.sha1_key = None
1408 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001409 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001410 p = wait_for_bfd_packet(self)
1411 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001412 self.test_session.send_packet()
1413 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1414 self.assert_equal(len(self.vapi.collect_events()), 0,
1415 "number of bfd events")
1416
1417 def test_auth_change_key_delayed(self):
1418 """ change auth key without disturbing session state (delayed) """
1419 key1 = self.factory.create_random_key(self)
1420 key1.add_vpp_config()
1421 key2 = self.factory.create_random_key(self)
1422 key2.add_vpp_config()
1423 self.vpp_session = VppBFDUDPSession(self, self.pg0,
1424 self.pg0.remote_ip4, sha1_key=key1)
1425 self.vpp_session.add_vpp_config()
1426 self.vpp_session.admin_up()
1427 self.test_session = BFDTestSession(
1428 self, self.pg0, AF_INET, sha1_key=key1,
1429 bfd_key_id=self.vpp_session.bfd_key_id)
Klement Sekerad3ba5152017-02-14 03:09:17 +01001430 bfd_session_up(self)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001431 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001432 p = wait_for_bfd_packet(self)
1433 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001434 self.test_session.send_packet()
1435 self.vpp_session.activate_auth(key2, delayed=True)
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001436 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001437 p = wait_for_bfd_packet(self)
1438 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001439 self.test_session.send_packet()
1440 self.test_session.bfd_key_id = self.vpp_session.bfd_key_id
1441 self.test_session.sha1_key = key2
1442 self.test_session.send_packet()
Klement Sekeraaeeac3b2017-02-14 07:11:52 +01001443 for dummy in range(self.test_session.detect_mult * 2):
Klement Sekerad3ba5152017-02-14 03:09:17 +01001444 p = wait_for_bfd_packet(self)
1445 self.assert_equal(p[BFD].state, BFDState.up, BFDState)
Klement Sekerab17dd962017-01-09 07:43:48 +01001446 self.test_session.send_packet()
1447 self.assert_equal(self.vpp_session.state, BFDState.up, BFDState)
1448 self.assert_equal(len(self.vapi.collect_events()), 0,
1449 "number of bfd events")
Klement Sekera46a87ad2017-01-02 08:22:23 +01001450
Klement Sekera0e3c0de2016-09-29 14:43:44 +02001451if __name__ == '__main__':
1452 unittest.main(testRunner=VppTestRunner)