summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/ospfv3.frr.tmpl43
-rw-r--r--interface-definitions/protocols-ospfv3.xml.in130
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_ospfv3.py63
-rwxr-xr-xsrc/conf_mode/protocols_ospf.py2
-rwxr-xr-xsrc/conf_mode/protocols_ospfv3.py12
5 files changed, 181 insertions, 69 deletions
diff --git a/data/templates/frr/ospfv3.frr.tmpl b/data/templates/frr/ospfv3.frr.tmpl
index c63ef80dc..d08972a80 100644
--- a/data/templates/frr/ospfv3.frr.tmpl
+++ b/data/templates/frr/ospfv3.frr.tmpl
@@ -1,4 +1,47 @@
!
+{% if interface is defined and interface is not none %}
+{% for iface, iface_config in interface.items() %}
+interface {{ iface }}
+{% if iface_config.cost is defined and iface_config.cost is not none %}
+ ipv6 ospf6 cost {{ iface_config.cost }}
+{% endif %}
+{% if iface_config.priority is defined and iface_config.priority is not none %}
+ ipv6 ospf6 priority {{ iface_config.priority }}
+{% endif %}
+{% if iface_config.hello_interval is defined and iface_config.hello_interval is not none %}
+ ipv6 ospf6 hello-interval {{ iface_config.hello_interval }}
+{% endif %}
+{% if iface_config.retransmit_interval is defined and iface_config.retransmit_interval is not none %}
+ ipv6 ospf6 retransmit-interval {{ iface_config.retransmit_interval }}
+{% endif %}
+{% if iface_config.transmit_delay is defined and iface_config.transmit_delay is not none %}
+ ipv6 ospf6 transmit-delay {{ iface_config.transmit_delay }}
+{% endif %}
+{% if iface_config.dead_interval is defined and iface_config.dead_interval is not none %}
+ ipv6 ospf6 dead-interval {{ iface_config.dead_interval }}
+{% endif %}
+{% if iface_config.bfd is defined %}
+ ipv6 ospf6 bfd
+{% endif %}
+{% if iface_config.mtu_ignore is defined %}
+ ipv6 ospf6 mtu-ignore
+{% endif %}
+{% if iface_config.ifmtu is defined and iface_config.ifmtu is not none %}
+ ipv6 ospf6 ifmtu {{ iface_config.ifmtu }}
+{% endif %}
+{% if iface_config.network is defined and iface_config.network is not none %}
+ ipv6 ospf6 network {{ iface_config.network }}
+{% endif %}
+{% if iface_config.instance_id is defined and iface_config.instance_id is not none %}
+ ipv6 ospf6 instance-id {{ iface_config.instance_id }}
+{% endif %}
+{% if iface_config.passive is defined %}
+ ipv6 ospf6 passive
+{% endif %}
+!
+{% endfor %}
+{% endif %}
+!
router ospf6
{% if area is defined and area is not none %}
{% for area_id, area_config in area.items() %}
diff --git a/interface-definitions/protocols-ospfv3.xml.in b/interface-definitions/protocols-ospfv3.xml.in
index e28faa3cf..2559e2b03 100644
--- a/interface-definitions/protocols-ospfv3.xml.in
+++ b/interface-definitions/protocols-ospfv3.xml.in
@@ -41,7 +41,7 @@
</completionHelp>
</properties>
</leafNode>
- <tagNode name="interface">
+ <leafNode name="interface">
<properties>
<help>Enable routing on an IPv6 interface</help>
<completionHelp>
@@ -54,63 +54,9 @@
<constraint>
<validator name="interface-name"/>
</constraint>
+ <multi/>
</properties>
- <children>
- #include <include/ospf-intervals.xml.i>
- #include <include/ospf-interface-common.xml.i>
- <leafNode name="ifmtu">
- <properties>
- <help>Interface MTU</help>
- <valueHelp>
- <format>u32:1-65535</format>
- <description>Interface MTU</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 1-65535"/>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="instance-id">
- <properties>
- <help>Instance Id (default: 0)</help>
- <valueHelp>
- <format>u32:0-255</format>
- <description>Instance Id</description>
- </valueHelp>
- <constraint>
- <validator name="numeric" argument="--range 0-255"/>
- </constraint>
- </properties>
- <defaultValue>0</defaultValue>
- </leafNode>
- <leafNode name="network">
- <properties>
- <help>Network type</help>
- <completionHelp>
- <list>broadcast point-to-point</list>
- </completionHelp>
- <valueHelp>
- <format>broadcast</format>
- <description>Broadcast network type</description>
- </valueHelp>
- <valueHelp>
- <format>point-to-point</format>
- <description>Point-to-point network type</description>
- </valueHelp>
- <constraint>
- <regex>^(broadcast|point-to-point)$</regex>
- </constraint>
- <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage>
- </properties>
- </leafNode>
- <leafNode name="passive">
- <properties>
- <help>Disable forming of adjacency</help>
- <valueless/>
- </properties>
- </leafNode>
- </children>
- </tagNode>
+ </leafNode>
<tagNode name="range">
<properties>
<help>Specify IPv6 prefix (border routers only)</help>
@@ -201,6 +147,76 @@
</node>
</children>
</node>
+ <tagNode name="interface">
+ <properties>
+ <help>Enable routing on an IPv6 interface</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Interface used for routing information exchange</description>
+ </valueHelp>
+ <constraint>
+ <validator name="interface-name"/>
+ </constraint>
+ </properties>
+ <children>
+ #include <include/ospf-intervals.xml.i>
+ #include <include/ospf-interface-common.xml.i>
+ <leafNode name="ifmtu">
+ <properties>
+ <help>Interface MTU</help>
+ <valueHelp>
+ <format>u32:1-65535</format>
+ <description>Interface MTU</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-65535"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="instance-id">
+ <properties>
+ <help>Instance Id (default: 0)</help>
+ <valueHelp>
+ <format>u32:0-255</format>
+ <description>Instance Id</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-255"/>
+ </constraint>
+ </properties>
+ <defaultValue>0</defaultValue>
+ </leafNode>
+ <leafNode name="network">
+ <properties>
+ <help>Network type</help>
+ <completionHelp>
+ <list>broadcast point-to-point</list>
+ </completionHelp>
+ <valueHelp>
+ <format>broadcast</format>
+ <description>Broadcast network type</description>
+ </valueHelp>
+ <valueHelp>
+ <format>point-to-point</format>
+ <description>Point-to-point network type</description>
+ </valueHelp>
+ <constraint>
+ <regex>^(broadcast|point-to-point)$</regex>
+ </constraint>
+ <constraintErrorMessage>Must be broadcast or point-to-point</constraintErrorMessage>
+ </properties>
+ </leafNode>
+ <leafNode name="passive">
+ <properties>
+ <help>Disable forming of adjacency</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </tagNode>
<node name="parameters">
<properties>
<help>OSPFv3 specific parameters</help>
diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py
index 297d5d996..754c4488f 100755
--- a/smoketest/scripts/cli/test_protocols_ospfv3.py
+++ b/smoketest/scripts/cli/test_protocols_ospfv3.py
@@ -25,10 +25,15 @@ from vyos.util import process_named_running
PROCESS_NAME = 'ospf6d'
base_path = ['protocols', 'ospfv3']
+router_id = '192.0.2.1'
+default_area = '0'
def getFRROSPFconfig():
return cmd('vtysh -c "show run" | sed -n "/router ospf6/,/^!/p"')
+def getFRRIFconfig(iface):
+ return cmd(f'vtysh -c "show run" | sed -n "/^interface {iface}/,/^!/p"')
+
class TestProtocolsOSPFv3(unittest.TestCase):
def setUp(self):
self.session = ConfigSession(os.getpid())
@@ -43,23 +48,21 @@ class TestProtocolsOSPFv3(unittest.TestCase):
def test_ospfv3_01_basic(self):
- area = '0'
seq = '10'
prefix = '2001:db8::/32'
acl_name = 'foo-acl-100'
- router_id = '192.0.2.1'
self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'action', 'permit'])
self.session.set(['policy', 'access-list6', acl_name, 'rule', seq, 'source', 'any'])
self.session.set(base_path + ['parameters', 'router-id', router_id])
- self.session.set(base_path + ['area', area, 'range', prefix, 'advertise'])
- self.session.set(base_path + ['area', area, 'export-list', acl_name])
- self.session.set(base_path + ['area', area, 'import-list', acl_name])
+ self.session.set(base_path + ['area', default_area, 'range', prefix, 'advertise'])
+ self.session.set(base_path + ['area', default_area, 'export-list', acl_name])
+ self.session.set(base_path + ['area', default_area, 'import-list', acl_name])
interfaces = Section.interfaces('ethernet')
for interface in interfaces:
- self.session.set(base_path + ['area', area, 'interface', interface])
+ self.session.set(base_path + ['area', default_area, 'interface', interface])
# commit changes
self.session.commit()
@@ -67,13 +70,13 @@ class TestProtocolsOSPFv3(unittest.TestCase):
# Verify FRR ospfd configuration
frrconfig = getFRROSPFconfig()
self.assertIn(f'router ospf6', frrconfig)
- self.assertIn(f' area {area} range {prefix}', frrconfig)
+ self.assertIn(f' area {default_area} range {prefix}', frrconfig)
self.assertIn(f' ospf6 router-id {router_id}', frrconfig)
- self.assertIn(f' area {area} import-list {acl_name}', frrconfig)
- self.assertIn(f' area {area} export-list {acl_name}', frrconfig)
+ self.assertIn(f' area {default_area} import-list {acl_name}', frrconfig)
+ self.assertIn(f' area {default_area} export-list {acl_name}', frrconfig)
for interface in interfaces:
- self.assertIn(f' interface {interface} area {area}', frrconfig)
+ self.assertIn(f' interface {interface} area {default_area}', frrconfig)
self.session.delete(['policy', 'access-list6', acl_name])
@@ -118,6 +121,46 @@ class TestProtocolsOSPFv3(unittest.TestCase):
for protocol in redistribute:
self.assertIn(f' redistribute {protocol} route-map {route_map}', frrconfig)
+ def test_ospfv3_0104_interfaces(self):
+
+ self.session.set(base_path + ['parameters', 'router-id', router_id])
+ self.session.set(base_path + ['area', default_area])
+
+ cost = '100'
+ priority = '10'
+ interfaces = Section.interfaces('ethernet')
+ for interface in interfaces:
+ if_base = base_path + ['interface', interface]
+ self.session.set(if_base + ['bfd'])
+ self.session.set(if_base + ['cost', cost])
+ self.session.set(if_base + ['instance-id', '0'])
+ self.session.set(if_base + ['mtu-ignore'])
+ self.session.set(if_base + ['network', 'point-to-point'])
+ self.session.set(if_base + ['passive'])
+ self.session.set(if_base + ['priority', priority])
+ cost = str(int(cost) + 10)
+ priority = str(int(priority) + 5)
+
+ # commit changes
+ self.session.commit()
+
+ # Verify FRR ospfd configuration
+ frrconfig = getFRROSPFconfig()
+ self.assertIn(f'router ospf6', frrconfig)
+
+ cost = '100'
+ priority = '10'
+ for interface in interfaces:
+ if_config = getFRRIFconfig(interface)
+ self.assertIn(f'interface {interface}', if_config)
+ self.assertIn(f' ipv6 ospf6 bfd', if_config)
+ self.assertIn(f' ipv6 ospf6 cost {cost}', if_config)
+ self.assertIn(f' ipv6 ospf6 mtu-ignore', if_config)
+ self.assertIn(f' ipv6 ospf6 network point-to-point', if_config)
+ self.assertIn(f' ipv6 ospf6 passive', if_config)
+ self.assertIn(f' ipv6 ospf6 priority {priority}', if_config)
+ cost = str(int(cost) + 10)
+ priority = str(int(priority) + 5)
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/protocols_ospf.py b/src/conf_mode/protocols_ospf.py
index 2ce0ab530..6d9eb828b 100755
--- a/src/conf_mode/protocols_ospf.py
+++ b/src/conf_mode/protocols_ospf.py
@@ -137,7 +137,7 @@ def apply(ospf):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section(r'interface \S+', '')
+ frr_cfg.modify_section(r'^interface \S+', '')
frr_cfg.modify_section('^router ospf$', '')
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospf['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)
diff --git a/src/conf_mode/protocols_ospfv3.py b/src/conf_mode/protocols_ospfv3.py
index 6c3aaf426..6f068b196 100755
--- a/src/conf_mode/protocols_ospfv3.py
+++ b/src/conf_mode/protocols_ospfv3.py
@@ -23,6 +23,7 @@ from vyos.configdict import dict_merge
from vyos.configverify import verify_route_maps
from vyos.template import render_to_string
from vyos.util import call
+from vyos.ifconfig import Interface
from vyos.xml import defaults
from vyos import ConfigError
from vyos import frr
@@ -57,6 +58,14 @@ def verify(ospfv3):
return None
verify_route_maps(ospfv3)
+
+ if 'interface' in ospfv3:
+ for ifname, if_config in ospfv3['interface'].items():
+ if 'ifmtu' in if_config:
+ mtu = Interface(ifname).get_mtu()
+ if int(if_config['ifmtu']) > int(mtu):
+ raise ConfigError(f'OSPFv3 ifmtu cannot go beyond physical MTU of "{mtu}"')
+
return None
def generate(ospfv3):
@@ -71,7 +80,8 @@ def apply(ospfv3):
# Save original configuration prior to starting any commit actions
frr_cfg = frr.FRRConfig()
frr_cfg.load_configuration(frr_daemon)
- frr_cfg.modify_section('router ospf6', '')
+ frr_cfg.modify_section(r'^interface \S+', '')
+ frr_cfg.modify_section('^router ospf6$', '')
frr_cfg.add_before(r'(ip prefix-list .*|route-map .*|line vty)', ospfv3['new_frr_config'])
frr_cfg.commit_configuration(frr_daemon)