BFD: modify session parameters
Change-Id: I666e5c0cc71a3693640960c93cdd1907f84fbe23
Signed-off-by: Klement Sekera <ksekera@cisco.com>
diff --git a/test/test_bfd.py b/test/test_bfd.py
index 5f86147..aedd56e 100644
--- a/test/test_bfd.py
+++ b/test/test_bfd.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python
+from __future__ import division
import unittest
import hashlib
import binascii
@@ -81,6 +82,33 @@
self.logger.debug("Session state is %s" % str(session.state))
session.remove_vpp_config()
+ def test_mod_bfd(self):
+ """ modify BFD session parameters """
+ session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4,
+ desired_min_tx=50000,
+ required_min_rx=10000,
+ detect_mult=1)
+ session.add_vpp_config()
+ e = session.get_bfd_udp_session_dump_entry()
+ self.assert_equal(session.desired_min_tx,
+ e.desired_min_tx,
+ "desired min transmit interval")
+ self.assert_equal(session.required_min_rx,
+ e.required_min_rx,
+ "required min receive interval")
+ self.assert_equal(session.detect_mult, e.detect_mult, "detect mult")
+ session.modify_parameters(desired_min_tx=session.desired_min_tx * 2,
+ required_min_rx=session.required_min_rx * 2,
+ detect_mult=session.detect_mult * 2)
+ e = session.get_bfd_udp_session_dump_entry()
+ self.assert_equal(session.desired_min_tx,
+ e.desired_min_tx,
+ "desired min transmit interval")
+ self.assert_equal(session.required_min_rx,
+ e.required_min_rx,
+ "required min receive interval")
+ self.assert_equal(session.detect_mult, e.detect_mult, "detect mult")
+
def test_add_sha1_keys(self):
""" add SHA1 keys """
key_count = 10
@@ -194,6 +222,7 @@
session.deactivate_auth()
def test_change_key(self):
+ """ change SHA1 key """
key1 = self.factory.create_random_key(self)
key2 = self.factory.create_random_key(self)
while key2.conf_key_id == key1.conf_key_id:
@@ -273,10 +302,11 @@
packet[BFD].auth_key_hash = hashlib.sha1(hash_material).digest()
return packet
- def send_packet(self):
- p = self.create_packet()
- self.test.logger.debug(ppp("Sending packet:", p))
- self.test.pg0.add_stream([p])
+ def send_packet(self, packet=None):
+ if packet is None:
+ packet = self.create_packet()
+ self.test.logger.debug(ppp("Sending packet:", packet))
+ self.test.pg0.add_stream([packet])
self.test.pg_start()
def verify_sha1_auth(self, packet):
@@ -521,11 +551,25 @@
e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
self.verify_event(e, expected_state=BFDState.up)
- try:
- p = self.pg0.wait_for_packet(timeout=1)
- except:
- return
- raise Exception(ppp("Received unexpected BFD packet:", p))
+ cap = 2 * self.vpp_session.desired_min_tx *\
+ self.vpp_session.detect_mult
+ now = time.time()
+ count = 0
+ # busy wait here, trying to collect a packet or event, vpp is not
+ # allowed to send packets and the session will timeout first - so the
+ # Up->Down event must arrive before any packets do
+ while time.time() < now + cap / us_in_sec:
+ try:
+ p, ttp = self.wait_for_bfd_packet(timeout=0)
+ self.logger.error(ppp("Received unexpected packet:", p))
+ count += 1
+ except:
+ pass
+ events = self.vapi.collect_events()
+ if len(events) > 0:
+ self.verify_event(events[0], BFDState.down)
+ break
+ self.assert_equal(count, 0, "number of packets received")
def test_conn_down(self):
""" verify session goes down after inactivity """
@@ -542,20 +586,27 @@
def test_large_required_min_rx(self):
""" large remote RequiredMinRxInterval """
self.bfd_session_up()
+ self.wait_for_bfd_packet()
interval = 3000000
self.test_session.update(required_min_rx_interval=interval)
self.test_session.send_packet()
now = time.time()
count = 0
+ # busy wait here, trying to collect a packet or event, vpp is not
+ # allowed to send packets and the session will timeout first - so the
+ # Up->Down event must arrive before any packets do
while time.time() < now + interval / us_in_sec:
try:
- p = self.wait_for_bfd_packet()
- if count > 1:
- self.logger.error(ppp("Received unexpected packet:", p))
+ p, ttp = self.wait_for_bfd_packet(timeout=0)
+ self.logger.error(ppp("Received unexpected packet:", p))
count += 1
except:
pass
- self.assert_in_range(count, 0, 1, "number of packets received")
+ events = self.vapi.collect_events()
+ if len(events) > 0:
+ self.verify_event(events[0], BFDState.down)
+ break
+ self.assert_equal(count, 0, "number of packets received")
def test_immediate_remote_min_rx_reduce(self):
""" immediately honor remote min rx reduction """
@@ -583,6 +634,93 @@
1.10 * interval / us_in_sec,
"time between BFD packets")
+ def test_modify_req_min_rx_double(self):
+ """ modify session - double required min rx """
+ self.bfd_session_up()
+ self.wait_for_bfd_packet()
+ self.test_session.update(desired_min_tx_interval=10000,
+ required_min_rx_interval=10000)
+ self.test_session.send_packet()
+ # first double required min rx
+ self.vpp_session.modify_parameters(
+ required_min_rx=2 * self.vpp_session.required_min_rx)
+ p, ttp = self.wait_for_bfd_packet()
+ # poll bit needs to be set
+ self.assertIn("P", p.sprintf("%BFD.flags%"),
+ "Poll bit not set in BFD packet")
+ # finish poll sequence with final packet
+ final = self.test_session.create_packet()
+ final[BFD].flags = "F"
+ self.test_session.send_packet(final)
+ # now we can wait 0.9*3*req-min-rx and the session should still be up
+ self.sleep(0.9 * self.vpp_session.detect_mult *
+ self.vpp_session.required_min_rx / us_in_sec)
+ self.assert_equal(len(self.vapi.collect_events()), 0,
+ "number of bfd events")
+
+ def test_modify_req_min_rx_halve(self):
+ """ modify session - halve required min rx """
+ self.vpp_session.modify_parameters(
+ required_min_rx=2 * self.vpp_session.required_min_rx)
+ self.bfd_session_up()
+ self.wait_for_bfd_packet()
+ self.test_session.update(desired_min_tx_interval=10000,
+ required_min_rx_interval=10000)
+ self.test_session.send_packet()
+ p, ttp = self.wait_for_bfd_packet()
+ # halve required min rx
+ old_required_min_rx = self.vpp_session.required_min_rx
+ self.vpp_session.modify_parameters(
+ required_min_rx=0.5 * self.vpp_session.required_min_rx)
+ # now we wait 0.8*3*old-req-min-rx and the session should still be up
+ self.sleep(0.8 * self.vpp_session.detect_mult *
+ old_required_min_rx / us_in_sec)
+ self.assert_equal(len(self.vapi.collect_events()), 0,
+ "number of bfd events")
+ p, ttp = self.wait_for_bfd_packet()
+ # poll bit needs to be set
+ self.assertIn("P", p.sprintf("%BFD.flags%"),
+ "Poll bit not set in BFD packet")
+ # finish poll sequence with final packet
+ final = self.test_session.create_packet()
+ final[BFD].flags = "F"
+ self.test_session.send_packet(final)
+ # now the session should time out under new conditions
+ before = time.time()
+ e = self.vapi.wait_for_event(1, "bfd_udp_session_details")
+ after = time.time()
+ detection_time = self.vpp_session.detect_mult *\
+ self.vpp_session.required_min_rx / us_in_sec
+ self.assert_in_range(after - before,
+ 0.9 * detection_time,
+ 1.1 * detection_time,
+ "time before bfd session goes down")
+ self.verify_event(e, expected_state=BFDState.down)
+
+ def test_modify_des_min_tx(self):
+ """ modify desired min tx interval """
+ pass
+
+ def test_modify_detect_mult(self):
+ """ modify detect multiplier """
+ self.bfd_session_up()
+ self.vpp_session.modify_parameters(detect_mult=1)
+ p, ttp = self.wait_for_bfd_packet()
+ self.assert_equal(self.vpp_session.detect_mult,
+ p[BFD].detect_mult,
+ "detect mult")
+ # poll bit must not be set
+ self.assertNotIn("P", p.sprintf("%BFD.flags%"),
+ "Poll bit not set in BFD packet")
+ self.vpp_session.modify_parameters(detect_mult=10)
+ p, ttp = self.wait_for_bfd_packet()
+ self.assert_equal(self.vpp_session.detect_mult,
+ p[BFD].detect_mult,
+ "detect mult")
+ # poll bit must not be set
+ self.assertNotIn("P", p.sprintf("%BFD.flags%"),
+ "Poll bit not set in BFD packet")
+
class BFD6TestCase(VppTestCase, BFDCommonCode):
"""Bidirectional Forwarding Detection (BFD) (IPv6) """