From ecbe6c1c1b87792048512e3aa4913c1ce5b75c82 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 16 Jun 2019 19:59:33 +0200 Subject: bfd: T1183: initial CLI implementation vyos@vyos# show protocols bfd peer 172.18.202.10 { local-address 172.18.201.10 local-interface eth0.201 shutdown } peer 172.18.202.12 { shutdown } --- src/conf_mode/protocols_bfd.py | 76 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100755 src/conf_mode/protocols_bfd.py (limited to 'src/conf_mode') diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py new file mode 100755 index 000000000..7e137c484 --- /dev/null +++ b/src/conf_mode/protocols_bfd.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2019 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import copy +from vyos.config import Config + +default_config_data = { + 'peers': [] +} + +def get_config(): + bfd = copy.deepcopy(default_config_data) + conf = Config() + if not conf.exists('protocols bfd'): + return None + else: + conf.set_level('protocols bfd') + + for peer in conf.list_nodes('peer'): + conf.set_level('protocols bfd peer {0}'.format(peer)) + bfd_peer = { + 'peer': peer, + 'shutdown': False, + 'local-interface': '', + 'local-address': '', + } + + # Check if individual peer is disabled + if conf.exists('shutdown'): + bfd_peer['shutdown'] = True + + # Check if peer has a local source interface configured + if conf.exists('local-interface'): + bfd_peer['local-interface'] = conf.return_value('local-interface') + + # Check if peer has a local source address configured - this is mandatory for IPv6 + if conf.exists('local-address'): + bfd_peer['local-address'] = conf.return_value('local-address') + + bfd['peers'].append(bfd_peer) + + print(bfd) + return bfd + +def verify(bfd): + return None + +def generate(bfd): + return None + +def apply(bfd): + return None + +if __name__ == '__main__': + try: + c = get_config() + verify(c) + generate(c) + apply(c) + except ConfigError as e: + print(e) + sys.exit(1) -- cgit v1.2.3 From 4fa93aefd1e4c525267f90b5fd7797157946c9bd Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sun, 16 Jun 2019 20:20:09 +0200 Subject: bfd: T1183: IPv6 peers require explicit local address/interface --- src/conf_mode/protocols_bfd.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'src/conf_mode') diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 7e137c484..51af67ff6 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -15,7 +15,11 @@ # along with this program. If not, see . # +import sys import copy +import vyos.validate + +from vyos import ConfigError from vyos.config import Config default_config_data = { @@ -33,7 +37,7 @@ def get_config(): for peer in conf.list_nodes('peer'): conf.set_level('protocols bfd peer {0}'.format(peer)) bfd_peer = { - 'peer': peer, + 'remote': peer, 'shutdown': False, 'local-interface': '', 'local-address': '', @@ -53,16 +57,36 @@ def get_config(): bfd['peers'].append(bfd_peer) - print(bfd) return bfd def verify(bfd): + if bfd is None: + return None + + for peer in bfd['peers']: + # Bail out early if peer is shutdown + if peer['shutdown']: + continue + + # IPv6 peers require an explicit local address/interface combination + if vyos.validate.is_ipv6(peer['remote']): + if not (peer['local-interface'] and peer['local-address']): + raise ConfigError("BFD IPv6 peers require explicit local address/interface setting") + + return None def generate(bfd): + if bfd is None: + return None + return None def apply(bfd): + if bfd is None: + return None + + print(bfd) return None if __name__ == '__main__': -- cgit v1.2.3 From 62ca0f55506245865dcc14fd95d68d9a3482df7b Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 21 Jun 2019 21:02:13 +0200 Subject: bfd: T1183: first working FRR bfd peer configuration --- src/conf_mode/protocols_bfd.py | 54 +++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) (limited to 'src/conf_mode') diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 51af67ff6..08d3991ff 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -16,31 +16,56 @@ # import sys +import jinja2 import copy +import os import vyos.validate from vyos import ConfigError from vyos.config import Config +config_file = r'/tmp/bfd.frr' + +# Please be careful if you edit the template. +config_tmpl = """ +! +bfd +{% for peer in old_peers -%} + no peer {{ peer }} +{% endfor -%} +! +{% for peer in new_peers -%} + peer {{ peer.remote }}{% if peer.local_address %} local-address {{ peer.local_address }}{% endif %}{% if peer.local_interface %} interface {{ peer.local_interface }}{% endif %} + {% if not peer.shutdown %}no {% endif %}shutdown +{% endfor -%} +! +""" + default_config_data = { - 'peers': [] + 'new_peers': [], + 'old_peers' : [] } def get_config(): bfd = copy.deepcopy(default_config_data) conf = Config() - if not conf.exists('protocols bfd'): + if not (conf.exists('protocols bfd') or conf.exists_effective('protocols bfd')): return None else: conf.set_level('protocols bfd') + # as we have to use vtysh to talk to FRR we also need to know + # which peers are gone due to a config removal - thus we read in + # all peers (active or to delete) + bfd['old_peers'] = conf.list_effective_nodes('peer') + for peer in conf.list_nodes('peer'): conf.set_level('protocols bfd peer {0}'.format(peer)) bfd_peer = { 'remote': peer, 'shutdown': False, - 'local-interface': '', - 'local-address': '', + 'local_interface': '', + 'local_address': '', } # Check if individual peer is disabled @@ -49,13 +74,13 @@ def get_config(): # Check if peer has a local source interface configured if conf.exists('local-interface'): - bfd_peer['local-interface'] = conf.return_value('local-interface') + bfd_peer['local_interface'] = conf.return_value('local-interface') # Check if peer has a local source address configured - this is mandatory for IPv6 if conf.exists('local-address'): - bfd_peer['local-address'] = conf.return_value('local-address') + bfd_peer['local_address'] = conf.return_value('local-address') - bfd['peers'].append(bfd_peer) + bfd['new_peers'].append(bfd_peer) return bfd @@ -63,17 +88,16 @@ def verify(bfd): if bfd is None: return None - for peer in bfd['peers']: + for peer in bfd['new_peers']: # Bail out early if peer is shutdown if peer['shutdown']: continue # IPv6 peers require an explicit local address/interface combination if vyos.validate.is_ipv6(peer['remote']): - if not (peer['local-interface'] and peer['local-address']): + if not (peer['local_interface'] and peer['local_address']): raise ConfigError("BFD IPv6 peers require explicit local address/interface setting") - return None def generate(bfd): @@ -86,7 +110,15 @@ def apply(bfd): if bfd is None: return None - print(bfd) + tmpl = jinja2.Template(config_tmpl) + config_text = tmpl.render(bfd) + with open(config_file, 'w') as f: + f.write(config_text) + + os.system("sudo vtysh -d bfdd -f " + config_file) + if os.path.exists(config_file): + os.remove(config_file) + return None if __name__ == '__main__': -- cgit v1.2.3 From 1b1f6b20226c92e4beba171159ead8fb21713484 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 21 Jun 2019 21:07:45 +0200 Subject: bfd: T1183: add support for multihop multihop tells the BFD daemon that we should expect packets with TTL less than 254 (because it will take more than one hop) and to listen on the multihop port (4784). When using multi-hop mode echo-mode will not work (see RFC 5883 section 3). --- interface-definitions/protocols-bfd.xml | 6 ++++++ src/conf_mode/protocols_bfd.py | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/conf_mode') diff --git a/interface-definitions/protocols-bfd.xml b/interface-definitions/protocols-bfd.xml index c8b25eb2d..91f0665f9 100644 --- a/interface-definitions/protocols-bfd.xml +++ b/interface-definitions/protocols-bfd.xml @@ -49,6 +49,12 @@ + + + Allow this BFD peer to not be directly connected + + + diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 08d3991ff..92fae990e 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -35,7 +35,7 @@ bfd {% endfor -%} ! {% for peer in new_peers -%} - peer {{ peer.remote }}{% if peer.local_address %} local-address {{ peer.local_address }}{% endif %}{% if peer.local_interface %} interface {{ peer.local_interface }}{% endif %} + peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.local_address %} local-address {{ peer.local_address }}{% endif %}{% if peer.local_interface %} interface {{ peer.local_interface }}{% endif %} {% if not peer.shutdown %}no {% endif %}shutdown {% endfor -%} ! @@ -66,6 +66,7 @@ def get_config(): 'shutdown': False, 'local_interface': '', 'local_address': '', + 'multihop': False } # Check if individual peer is disabled @@ -80,6 +81,12 @@ def get_config(): if conf.exists('local-address'): bfd_peer['local_address'] = conf.return_value('local-address') + # Tell BFD daemon that we should expect packets with TTL less than 254 + # (because it will take more than one hop) and to listen on the multihop + # port (4784) + if conf.exists('multihop'): + bfd_peer['multihop'] = True + bfd['new_peers'].append(bfd_peer) return bfd -- cgit v1.2.3 From c2a8c1a22f432265c73606106046c02e995eb630 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Jun 2019 14:44:45 +0200 Subject: bfd: T1183: adjust CLI syntax for source address/interface Place address/interface under new source node. vyis@vyos# show protocols bfd peer 1.1.1.1 { source { address 1.2.3.4 interface eth0.201 } } --- interface-definitions/protocols-bfd.xml | 45 +++++++++++++++++++-------------- src/conf_mode/protocols_bfd.py | 16 ++++++------ 2 files changed, 34 insertions(+), 27 deletions(-) (limited to 'src/conf_mode') diff --git a/interface-definitions/protocols-bfd.xml b/interface-definitions/protocols-bfd.xml index 91f0665f9..ab8c9e233 100644 --- a/interface-definitions/protocols-bfd.xml +++ b/interface-definitions/protocols-bfd.xml @@ -22,27 +22,34 @@ - + - Local interface to bind our peer listener to - - - + Bind listener to specifid interface/address, mandatory for IPv6 - - - - Local address to bind our peer listener to - - ipv4 - Local IPv4 address used to connect to the peer - - - ipv6 - Local IPv6 address used to connect to the peer - - - + + + + Local interface to bind our peer listener to + + + + + + + + Local address to bind our peer listener to + + ipv4 + Local IPv4 address used to connect to the peer + + + ipv6 + Local IPv6 address used to connect to the peer + + + + + Disable this peer diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 92fae990e..6d2b8382a 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -35,7 +35,7 @@ bfd {% endfor -%} ! {% for peer in new_peers -%} - peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.local_address %} local-address {{ peer.local_address }}{% endif %}{% if peer.local_interface %} interface {{ peer.local_interface }}{% endif %} + peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %} {% if not peer.shutdown %}no {% endif %}shutdown {% endfor -%} ! @@ -64,8 +64,8 @@ def get_config(): bfd_peer = { 'remote': peer, 'shutdown': False, - 'local_interface': '', - 'local_address': '', + 'src_if': '', + 'src_addr': '', 'multihop': False } @@ -74,12 +74,12 @@ def get_config(): bfd_peer['shutdown'] = True # Check if peer has a local source interface configured - if conf.exists('local-interface'): - bfd_peer['local_interface'] = conf.return_value('local-interface') + if conf.exists('source interface'): + bfd_peer['src_if'] = conf.return_value('source interface') # Check if peer has a local source address configured - this is mandatory for IPv6 - if conf.exists('local-address'): - bfd_peer['local_address'] = conf.return_value('local-address') + if conf.exists('source address'): + bfd_peer['src_addr'] = conf.return_value('source address') # Tell BFD daemon that we should expect packets with TTL less than 254 # (because it will take more than one hop) and to listen on the multihop @@ -102,7 +102,7 @@ def verify(bfd): # IPv6 peers require an explicit local address/interface combination if vyos.validate.is_ipv6(peer['remote']): - if not (peer['local_interface'] and peer['local_address']): + if not (peer['src_if'] and peer['src_addr']): raise ConfigError("BFD IPv6 peers require explicit local address/interface setting") return None -- cgit v1.2.3 From 4e4b945b6b88308fe8938663ad12efebf98e08fd Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Jun 2019 14:51:44 +0200 Subject: bfd: T1183: add support to configure detection multiplier Configures the detection multiplier to determine packet loss. The remote transmission interval will be multiplied by this value to determine the connection loss detection timer. The default value is 3. Example: when the local system has detect-multiplier 3 and the remote system has transmission interval 300, the local system will detect failures only after 900 milliseconds without receiving packets. --- interface-definitions/protocols-bfd.xml | 12 ++++++++++++ src/conf_mode/protocols_bfd.py | 8 ++++++++ 2 files changed, 20 insertions(+) (limited to 'src/conf_mode') diff --git a/interface-definitions/protocols-bfd.xml b/interface-definitions/protocols-bfd.xml index ab8c9e233..a731334a0 100644 --- a/interface-definitions/protocols-bfd.xml +++ b/interface-definitions/protocols-bfd.xml @@ -50,6 +50,18 @@ + + + Multiplier to determine packet loss + + 2-255 + Remote transmission interval will be multiplied by this value + + + + + + Disable this peer diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 6d2b8382a..96a41de11 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -36,6 +36,7 @@ bfd ! {% for peer in new_peers -%} peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %} + detect-multiplier {{ peer.multiplier }} {% if not peer.shutdown %}no {% endif %}shutdown {% endfor -%} ! @@ -66,6 +67,7 @@ def get_config(): 'shutdown': False, 'src_if': '', 'src_addr': '', + 'multiplier': '3', 'multihop': False } @@ -81,6 +83,12 @@ def get_config(): if conf.exists('source address'): bfd_peer['src_addr'] = conf.return_value('source address') + # Configures the detection multiplier to determine packet loss. The remote + # transmission interval will be multiplied by this value to determine the + # connection loss detection timer. The default value is 3. + if conf.exists('multiplier'): + bfd_peer['multiplier'] = conf.return_value('multiplier') + # Tell BFD daemon that we should expect packets with TTL less than 254 # (because it will take more than one hop) and to listen on the multihop # port (4784) -- cgit v1.2.3 From 67a35cfc37a5cc34a1b874f69626802ec3d35f94 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Jun 2019 14:59:27 +0200 Subject: bfd: T1183: multihop doesn't accept interface names --- src/conf_mode/protocols_bfd.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/conf_mode') diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 96a41de11..3d60f5358 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -111,7 +111,12 @@ def verify(bfd): # IPv6 peers require an explicit local address/interface combination if vyos.validate.is_ipv6(peer['remote']): if not (peer['src_if'] and peer['src_addr']): - raise ConfigError("BFD IPv6 peers require explicit local address/interface setting") + raise ConfigError('BFD IPv6 peers require explicit local address/interface setting') + + # multihop doesn't accept interface names + if peer['multihop'] and peer['src_if']: + raise ConfigError('multihop does not accept interface names') + return None -- cgit v1.2.3 From 8b8c7424c90275a3814e7c17939cfb3a66145a19 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Jun 2019 15:18:31 +0200 Subject: bfd: T1183: add rx/tx interval configuration vyos@vyos# show protocols bfd { peer 1.1.1.1 { interval { receive 400 transmit 300 } } } --- interface-definitions/protocols-bfd.xml | 31 +++++++++++++++++++++++++++++++ src/conf_mode/protocols_bfd.py | 14 ++++++++++++++ 2 files changed, 45 insertions(+) (limited to 'src/conf_mode') diff --git a/interface-definitions/protocols-bfd.xml b/interface-definitions/protocols-bfd.xml index a731334a0..0e92a7ddd 100644 --- a/interface-definitions/protocols-bfd.xml +++ b/interface-definitions/protocols-bfd.xml @@ -62,6 +62,37 @@ + + + Configure timer intervals + + + + + Minimum interval of receiving control packets + + 10-60000 + Interval in milliseconds + + + + + + + + + Minimum interval of transmitting control packets + + 10-60000 + Interval in milliseconds + + + + + + + + Disable this peer diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 3d60f5358..2f494c2e4 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -37,6 +37,8 @@ bfd {% for peer in new_peers -%} peer {{ peer.remote }}{% if peer.multihop %} multihop{% endif %}{% if peer.src_addr %} local-address {{ peer.src_addr }}{% endif %}{% if peer.src_if %} interface {{ peer.src_if }}{% endif %} detect-multiplier {{ peer.multiplier }} + receive-interval {{ peer.rx_interval }} + transmit-interval {{ peer.tx_interval }} {% if not peer.shutdown %}no {% endif %}shutdown {% endfor -%} ! @@ -68,6 +70,8 @@ def get_config(): 'src_if': '', 'src_addr': '', 'multiplier': '3', + 'rx_interval': '300', + 'tx_interval': '300', 'multihop': False } @@ -95,6 +99,16 @@ def get_config(): if conf.exists('multihop'): bfd_peer['multihop'] = True + # Configures the minimum interval that this system is capable of receiving + # control packets. The default value is 300 milliseconds. + if conf.exists('interval receive'): + bfd_peer['rx_interval'] = conf.return_value('interval receive') + + # The minimum transmission interval (less jitter) that this system wants + # to use to send BFD control packets. + if conf.exists('interval transmit'): + bfd_peer['tx_interval'] = conf.return_value('interval transmit') + bfd['new_peers'].append(bfd_peer) return bfd -- cgit v1.2.3 From 7d5b78242859540955006e11d8ca08b463244950 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 22 Jun 2019 15:21:08 +0200 Subject: bfd: T1183: move "multiplier" configuration node to "interval multiplier" --- interface-definitions/protocols-bfd.xml | 24 ++++++++++++------------ src/conf_mode/protocols_bfd.py | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src/conf_mode') diff --git a/interface-definitions/protocols-bfd.xml b/interface-definitions/protocols-bfd.xml index 0e92a7ddd..47d5bf97d 100644 --- a/interface-definitions/protocols-bfd.xml +++ b/interface-definitions/protocols-bfd.xml @@ -50,18 +50,6 @@ - - - Multiplier to determine packet loss - - 2-255 - Remote transmission interval will be multiplied by this value - - - - - - Configure timer intervals @@ -91,6 +79,18 @@ + + + Multiplier to determine packet loss + + 2-255 + Remote transmission interval will be multiplied by this value + + + + + + diff --git a/src/conf_mode/protocols_bfd.py b/src/conf_mode/protocols_bfd.py index 2f494c2e4..04549f4b4 100755 --- a/src/conf_mode/protocols_bfd.py +++ b/src/conf_mode/protocols_bfd.py @@ -87,12 +87,6 @@ def get_config(): if conf.exists('source address'): bfd_peer['src_addr'] = conf.return_value('source address') - # Configures the detection multiplier to determine packet loss. The remote - # transmission interval will be multiplied by this value to determine the - # connection loss detection timer. The default value is 3. - if conf.exists('multiplier'): - bfd_peer['multiplier'] = conf.return_value('multiplier') - # Tell BFD daemon that we should expect packets with TTL less than 254 # (because it will take more than one hop) and to listen on the multihop # port (4784) @@ -109,6 +103,12 @@ def get_config(): if conf.exists('interval transmit'): bfd_peer['tx_interval'] = conf.return_value('interval transmit') + # Configures the detection multiplier to determine packet loss. The remote + # transmission interval will be multiplied by this value to determine the + # connection loss detection timer. The default value is 3. + if conf.exists('interval multiplier'): + bfd_peer['multiplier'] = conf.return_value('interval multiplier') + bfd['new_peers'].append(bfd_peer) return bfd -- cgit v1.2.3