summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-01-29 15:01:48 +0100
committerChristian Poessinger <christian@poessinger.com>2021-01-29 15:01:48 +0100
commitb17b6d8931b142dcd3e2ddc4e213929bfafe9948 (patch)
tree66aee7e2e85e28cb9b166d8e5ab8fef884862f76
parent323c0c3b8c109394ec8caf3f105633b0691fdef7 (diff)
downloadvyos-1x-b17b6d8931b142dcd3e2ddc4e213929bfafe9948.tar.gz
vyos-1x-b17b6d8931b142dcd3e2ddc4e213929bfafe9948.zip
ospf: T3267: move "interface ip ospf" configuration to "protocols ospf interface"
For easier maintenance and operability move the interface specific protocol setting of OSPF to the OSPF protocol section. This is now also in-line with IS-IS. This means to migrate: ethernet eth0 { vif 202 { ip { ospf { authentication { md5 { key-id 10 { md5-key vyosvyos } } } dead-interval 40 hello-interval 10 priority 1 retransmit-interval 5 transmit-delay 1 } } } } to protocols { ospf { interface eth0.201 { authentication { md5 { key-id 10 { md5-key vyosvyos } } } dead-interval 40 hello-interval 10 priority 1 retransmit-interval 5 transmit-delay 1 } }
-rw-r--r--data/templates/frr/ospf.frr.tmpl46
-rw-r--r--interface-definitions/include/ospf-authentication.xml.i45
-rw-r--r--interface-definitions/include/ospf-intervals.xml.i54
-rw-r--r--interface-definitions/protocols-ospf.xml.in186
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py13
-rwxr-xr-xsrc/migration-scripts/interfaces/19-to-2082
6 files changed, 327 insertions, 99 deletions
diff --git a/data/templates/frr/ospf.frr.tmpl b/data/templates/frr/ospf.frr.tmpl
index 07699290c..01a711259 100644
--- a/data/templates/frr/ospf.frr.tmpl
+++ b/data/templates/frr/ospf.frr.tmpl
@@ -1,4 +1,44 @@
!
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+{% if iface_config.authentication is defined and iface_config.authentication is not none %}
+{% if iface_config.authentication.plaintext_password is defined and iface_config.authentication.plaintext_password is not none %}
+ ip ospf authentication-key {{ iface_config.authentication.plaintext_password }}
+{% elif iface_config.authentication.md5 is defined %}
+ ip ospf authentication message-digest
+{% if iface_config.authentication.md5.key_id is defined and iface_config.authentication.md5.key_id is not none %}
+{% for key, key_config in iface_config.authentication.md5.key_id.items() %}
+ ip ospf message-digest-key {{ key }} md5 {{ key_config.md5_key }}
+{% endfor %}
+{% endif %}
+{% endif %}
+{% endif %}
+{# interval configurations all have default values #}
+{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %}
+ ip ospf hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %}
+ ip ospf retransmit-interval {{ iface_config.retransmit_interval }}
+{% endif %}
+{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %}
+ ip ospf transmit-delay {{ iface_config.transmit_delay }}
+{% endif %}
+{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %}
+ ip ospf dead-interval {{ iface_config.dead_interval }}
+{% endif %}
+{% if iface_config.bfd is defined %}
+ ip ospf bfd
+{% endif %}
+{% if iface_config.mtu_ignore is defined %}
+ ip ospf mtu-ignore
+{% endif %}
+{% if iface_config.network is defined and iface_config.network is not none %}
+ ip ospf network {{ iface_config.network }}
+{% endif %}
+{% endfor %}
+{% endif %}
+!
router ospf
{% if access_list is defined and access_list is not none %}
{% for acl, acl_config in access_list.items() %}
@@ -50,10 +90,8 @@ router ospf
{% endfor %}
{% endif %}
{% endif %}
-{% if link_config.dead_interval is defined and link_config.dead_interval is not none %}
-{# The following values are default values #}
- area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.retransmit_interval }} dead-interval {{ link_config.dead_interval }}
-{% endif %}
+{# The following values are default values #}
+ area {{ area_id }} virtual-link {{ link }} hello-interval {{ link_config.hello_interval }} retransmit-interval {{ link_config.retransmit_interval }} transmit-delay {{ link_config.transmit_delay }} dead-interval {{ link_config.dead_interval }}
{% endfor %}
{% endif %}
{% endfor %}
diff --git a/interface-definitions/include/ospf-authentication.xml.i b/interface-definitions/include/ospf-authentication.xml.i
new file mode 100644
index 000000000..0963e5cc0
--- /dev/null
+++ b/interface-definitions/include/ospf-authentication.xml.i
@@ -0,0 +1,45 @@
+<!-- included start from ospf-authentication.xml.i -->
+<node name="authentication">
+ <properties>
+ <help>Authentication</help>
+ </properties>
+ <children>
+ <node name="md5">
+ <properties>
+ <help>MD5 key id</help>
+ </properties>
+ <children>
+ <tagNode name="key-id">
+ <properties>
+ <help>MD5 key id</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>MD5 key id</description>
+ </valueHelp>
+ </properties>
+ <children>
+ <leafNode name="md5-key">
+ <properties>
+ <help>MD5 authentication type</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>MD5 Key (16 characters or less)</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ <leafNode name="plaintext-password">
+ <properties>
+ <help>Plain text password</help>
+ <valueHelp>
+ <format>txt</format>
+ <description>Plain text password (8 characters or less)</description>
+ </valueHelp>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- included end -->
diff --git a/interface-definitions/include/ospf-intervals.xml.i b/interface-definitions/include/ospf-intervals.xml.i
new file mode 100644
index 000000000..e532bd14b
--- /dev/null
+++ b/interface-definitions/include/ospf-intervals.xml.i
@@ -0,0 +1,54 @@
+<!-- included start from ospf-intervals.xml.i -->
+<leafNode name="dead-interval">
+ <properties>
+ <help>Interval after which a neighbor is declared dead (default: 40)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Neighbor dead interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>40</defaultValue>
+</leafNode>
+<leafNode name="hello-interval">
+ <properties>
+ <help>Interval between hello packets (default: 10)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Hello interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>10</defaultValue>
+</leafNode>
+<leafNode name="retransmit-interval">
+ <properties>
+ <help>Interval between retransmitting lost link state advertisements (default: 5)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Retransmit interval (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>5</defaultValue>
+</leafNode>
+<leafNode name="transmit-delay">
+ <properties>
+ <help>Link state transmit delay (default: 1)</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Link state transmit delay (seconds)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ <defaultValue>1</defaultValue>
+</leafNode>
+<!-- included end -->
diff --git a/interface-definitions/protocols-ospf.xml.in b/interface-definitions/protocols-ospf.xml.in
index 074d0db63..1051e3741 100644
--- a/interface-definitions/protocols-ospf.xml.in
+++ b/interface-definitions/protocols-ospf.xml.in
@@ -275,101 +275,8 @@
</constraint>
</properties>
<children>
- <node name="authentication">
- <properties>
- <help>Authentication</help>
- </properties>
- <children>
- <node name="md5">
- <properties>
- <help>MD5 key id</help>
- </properties>
- <children>
- <tagNode name="key-id">
- <properties>
- <help>MD5 key id</help>
- <valueHelp>
- <format>u32:1-255</format>
- <description>MD5 key id</description>
- </valueHelp>
- </properties>
- <children>
- <leafNode name="md5-key">
- <properties>
- <help>MD5 authentication type</help>
- <valueHelp>
- <format>txt</format>
- <description>MD5 Key (16 characters or less)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
- </tagNode>
- </children>
- </node>
- <leafNode name="plaintext-password">
- <properties>
- <help>Plain text password</help>
- <valueHelp>
- <format>txt</format>
- <description>Plain text password (8 characters or less)</description>
- </valueHelp>
- </properties>
- </leafNode>
- </children>
- </node>
- <leafNode name="dead-interval">
- <properties>
- <help>Interval after which a neighbor is declared dead (default: 40)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Neighbor dead interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>40</defaultValue>
- </leafNode>
- <leafNode name="hello-interval">
- <properties>
- <help>Interval between hello packets (default: 10)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Hello interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>10</defaultValue>
- </leafNode>
- <leafNode name="retransmit-interval">
- <properties>
- <help>Interval between retransmitting lost link state advertisements (default: 5)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Retransmit interval (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>5</defaultValue>
- </leafNode>
- <leafNode name="transmit-delay">
- <properties>
- <help>Link state transmit delay (default: 1)</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Link state transmit delay (seconds)</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- <defaultValue>1</defaultValue>
- </leafNode>
+ #include <include/ospf-authentication.xml.i>
+ #include <include/ospf-intervals.xml.i>
</children>
</tagNode>
</children>
@@ -491,6 +398,95 @@
</node>
</children>
</node>
+ <tagNode name="interface">
+ <properties>
+ <help>Interface related configuration</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ </properties>
+ <children>
+ #include <include/ospf-authentication.xml.i>
+ #include <include/ospf-intervals.xml.i>
+ <leafNode name="bandwidth">
+ <properties>
+ <help>Bandwidth of interface (Megabit/sec)</help>
+ <valueHelp>
+ <format>u32:1-100000</format>
+ <description>Bandwidth in Megabit/sec (for calculating OSPF cost)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-100000"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="bfd">
+ <properties>
+ <help>Enable Bidirectional Forwarding Detection (BFD) support</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="cost">
+ <properties>
+ <help>Interface cost</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>OSPF interface cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="mtu-ignore">
+ <properties>
+ <help>Disable Maximum Transmission Unit (MTU) mismatch detection</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="network">
+ <properties>
+ <help>Network type</help>
+ <completionHelp>
+ <list>broadcast non-broadcast point-to-multipoint point-to-point</list>
+ </completionHelp>
+ <valueHelp>
+ <format>broadcast</format>
+ <description>Broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>non-broadcast</format>
+ <description>Non-broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-multipoint</format>
+ <description>Point-to-multipoint network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-point</format>
+ <description>Point-to-point network type</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(broadcast|non-broadcast|point-to-multipoint|point-to-point)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be broadcast, non-broadcast, point-to-multipoint or point-to-point</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="priority">
+ <properties>
+ <help>Router priority (default: 1)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>OSPF router priority cost</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>1</defaultValue>
+ </leafNode>
+ </children>
+ </tagNode>
<node name="log-adjacency-changes">
<properties>
<help>Log changes in adjacency state</help>
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 7c0ffbd27..a1ca7725f 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -21,6 +21,7 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configverify import verify_route_maps
+from vyos.configverify import verify_interface_exists
from vyos.template import render
from vyos.template import render_to_string
from vyos.util import call
@@ -76,6 +77,7 @@ def get_config(config=None):
# clean them out and add them manually :(
del default_values['neighbor']
del default_values['area']['virtual_link']
+ del default_values['interface']
# merge in remaining default values
ospf = dict_merge(default_values, ospf)
@@ -94,6 +96,12 @@ def get_config(config=None):
ospf['area'][area]['virtual_link'][virtual_link] = dict_merge(
default_values, ospf['area'][area]['virtual_link'][virtual_link])
+ if 'interface' in ospf:
+ default_values = defaults(base + ['interface'])
+ for interface in ospf['interface']:
+ ospf['interface'][interface] = dict_merge(default_values,
+ ospf['interface'][interface])
+
# We also need some additional information from the config, prefix-lists
# and route-maps for instance. They will be used in verify()
base = ['policy']
@@ -108,6 +116,11 @@ def verify(ospf):
return None
verify_route_maps(ospf)
+
+ if 'interface' in ospf:
+ for interface in ospf['interface']:
+ verify_interface_exists(interface)
+
return None
def generate(ospf):
diff --git a/src/migration-scripts/interfaces/19-to-20 b/src/migration-scripts/interfaces/19-to-20
new file mode 100755
index 000000000..7ea1ed267
--- /dev/null
+++ b/src/migration-scripts/interfaces/19-to-20
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
+
+from sys import exit, argv
+from vyos.configtree import ConfigTree
+
+if __name__ == '__main__':
+ if (len(argv) < 1):
+ print("Must specify file name!")
+ exit(1)
+
+ file_name = argv[1]
+ with open(file_name, 'r') as f:
+ config_file = f.read()
+
+ config = ConfigTree(config_file)
+
+ #
+ # Migrate "interface ethernet eth0 ip ospf" to "protocols ospf interface eth0"
+ #
+ for type in config.list_nodes(['interfaces']):
+ for interface in config.list_nodes(['interfaces', type]):
+
+ ip_ospf = ['interfaces', type, interface, 'ip', 'ospf']
+ if config.exists(ip_ospf):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(ip_ospf, ['protocols', 'ospf', 'interface', interface])
+ config.delete(ip_ospf)
+
+ vif_path = ['interfaces', type, interface, 'vif']
+ if config.exists(vif_path):
+ for vif in config.list_nodes(vif_path):
+ vif_ospf_path = vif_path + [vif, 'ip', 'ospf']
+ if config.exists(vif_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif}'])
+ config.delete(vif_ospf_path)
+
+ vif_s_path = ['interfaces', type, interface, 'vif-s']
+ if config.exists(vif_s_path):
+ for vif_s in config.list_nodes(vif_s_path):
+ vif_s_ospf_path = vif_s_path + [vif_s, 'ip', 'ospf']
+ if config.exists(vif_s_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_s_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif_s}'])
+
+ vif_c_path = ['interfaces', type, interface, 'vif-s', vif_s, 'vif-c']
+ if config.exists(vif_c_path):
+ for vif_c in config.list_nodes(vif_c_path):
+ vif_c_ospf_path = vif_c_path + [vif_c, 'ip', 'ospf']
+ print(vif_c_ospf_path)
+ if config.exists(vif_c_ospf_path):
+ config.set(['protocols', 'ospf', 'interface'])
+ config.set_tag(['protocols', 'ospf', 'interface'])
+ config.copy(vif_c_ospf_path, ['protocols', 'ospf', 'interface', f'{interface}.{vif_s}.{vif_c}'])
+ config.delete(vif_c_ospf_path)
+
+ config.delete(vif_s_ospf_path)
+
+ try:
+ with open(file_name, 'w') as f:
+ f.write(config.to_string())
+ except OSError as e:
+ print("Failed to save the modified config: {}".format(e))
+ exit(1)
+