diff --git a/data/templates/frr/ospfd.frr.j2 b/data/templates/frr/ospfd.frr.j2 index 121ecf677..040628e82 100644 --- a/data/templates/frr/ospfd.frr.j2 +++ b/data/templates/frr/ospfd.frr.j2 @@ -1,259 +1,262 @@ ! {% if interface is vyos_defined %} {% for iface, iface_config in interface.items() %} interface {{ iface }} {% if iface_config.authentication.plaintext_password is vyos_defined %} ip ospf authentication-key {{ iface_config.authentication.plaintext_password }} {% elif iface_config.authentication.md5 is vyos_defined %} ip ospf authentication message-digest {% if iface_config.authentication.md5.key_id is vyos_defined %} {% 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 %} {% if iface_config.area is vyos_defined %} ip ospf area {{ iface_config.area }} {% endif %} {% if iface_config.bandwidth is vyos_defined %} bandwidth {{ iface_config.bandwidth }} {% endif %} {% if iface_config.cost is vyos_defined %} ip ospf cost {{ iface_config.cost }} {% endif %} {% if iface_config.priority is vyos_defined %} ip ospf priority {{ iface_config.priority }} {% endif %} {% if iface_config.hello_interval is vyos_defined %} ip ospf hello-interval {{ iface_config.hello_interval }} {% endif %} {% if iface_config.retransmit_interval is vyos_defined %} ip ospf retransmit-interval {{ iface_config.retransmit_interval }} {% endif %} {% if iface_config.transmit_delay is vyos_defined %} ip ospf transmit-delay {{ iface_config.transmit_delay }} {% endif %} {% if iface_config.dead_interval is vyos_defined %} ip ospf dead-interval {{ iface_config.dead_interval }} {% elif iface_config.hello_multiplier is vyos_defined %} ip ospf dead-interval minimal hello-multiplier {{ iface_config.hello_multiplier }} {% endif %} {% if iface_config.bfd is vyos_defined %} ip ospf bfd {% endif %} {% if iface_config.bfd.profile is vyos_defined %} ip ospf bfd profile {{ iface_config.bfd.profile }} {% endif %} {% if iface_config.ldp_sync.disable is vyos_defined %} no ip ospf mpls ldp-sync {% elif iface_config.ldp_sync.holddown is vyos_defined %} ip ospf mpls ldp-sync ip ospf mpls ldp-sync holddown {{ iface_config.ldp_sync.holddown }} {% endif %} {% if iface_config.mtu_ignore is vyos_defined %} ip ospf mtu-ignore {% endif %} {% if iface_config.network is vyos_defined %} ip ospf network {{ iface_config.network }} {% endif %} {% if iface_config.passive is vyos_defined %} {{ 'no ' if iface_config.passive.disable is vyos_defined }}ip ospf passive {% endif %} exit ! {% endfor %} {% endif %} ! router ospf {{ 'vrf ' ~ vrf if vrf is vyos_defined }} {% if access_list is vyos_defined %} {% for acl, acl_config in access_list.items() %} {% for protocol in acl_config.export if acl_config.export is vyos_defined %} distribute-list {{ acl }} out {{ protocol }} {% endfor %} {% endfor %} {% endif %} {% if aggregation.timer is vyos_defined %} aggregation timer {{ aggregation.timer }} {% endif %} {% if area is vyos_defined %} {% for area_id, area_config in area.items() %} {% if area_config.area_type is vyos_defined %} {% for type, type_config in area_config.area_type.items() if type != 'normal' %} area {{ area_id }} {{ type }} {{ 'no-summary' if type_config.no_summary is vyos_defined }} {% if type_config.default_cost is vyos_defined %} area {{ area_id }} default-cost {{ type_config.default_cost }} {% endif %} {% endfor %} {% endif %} {% if area_config.authentication is vyos_defined %} area {{ area_id }} authentication {{ 'message-digest' if area_config.authentication is vyos_defined('md5') }} {% endif %} {% for network in area_config.network if area_config.network is vyos_defined %} network {{ network }} area {{ area_id }} {% endfor %} {% if area_config.range is vyos_defined %} {% for range, range_config in area_config.range.items() %} {% if range_config.not_advertise is vyos_defined %} area {{ area_id }} range {{ range }} not-advertise {% else %} area {{ area_id }} range {{ range }} {% endif %} {% if range_config.cost is vyos_defined %} area {{ area_id }} range {{ range }} cost {{ range_config.cost }} {% endif %} {% if range_config.substitute is vyos_defined %} area {{ area_id }} range {{ range }} substitute {{ range_config.substitute }} {% endif %} {% endfor %} {% endif %} {% if area_config.export_list is vyos_defined %} area {{ area_id }} export-list {{ area_config.export_list }} {% endif %} {% if area_config.import_list is vyos_defined %} area {{ area_id }} import-list {{ area_config.import_list }} {% endif %} {% if area_config.shortcut is vyos_defined %} area {{ area_id }} shortcut {{ area_config.shortcut }} {% endif %} {% if area_config.virtual_link is vyos_defined %} {% for link, link_config in area_config.virtual_link.items() %} {% if link_config.authentication.plaintext_password is vyos_defined %} area {{ area_id }} virtual-link {{ link }} authentication-key {{ link_config.authentication.plaintext_password }} {% elif link_config.authentication.md5.key_id is vyos_defined %} {% for key, key_config in link_config.authentication.md5.key_id.items() %} area {{ area_id }} virtual-link {{ link }} message-digest-key {{ key }} md5 {{ key_config.md5_key }} {% endfor %} {% 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 %} {% endif %} {% if auto_cost.reference_bandwidth is vyos_defined %} auto-cost reference-bandwidth {{ auto_cost.reference_bandwidth }} {% endif %} +{% if capability.opaque is vyos_defined %} + capability opaque +{% endif %} {% if default_information.originate is vyos_defined %} default-information originate {{ 'always' if default_information.originate.always is vyos_defined }} {{ 'metric ' + default_information.originate.metric if default_information.originate.metric is vyos_defined }} {{ 'metric-type ' + default_information.originate.metric_type if default_information.originate.metric_type is vyos_defined }} {{ 'route-map ' + default_information.originate.route_map if default_information.originate.route_map is vyos_defined }} {% endif %} {% if default_metric is vyos_defined %} default-metric {{ default_metric }} {% endif %} {% if maximum_paths is vyos_defined %} maximum-paths {{ maximum_paths }} {% endif %} {% if ldp_sync.holddown is vyos_defined %} mpls ldp-sync holddown {{ ldp_sync.holddown }} {% elif ldp_sync is vyos_defined %} mpls ldp-sync {% endif %} {% if distance.global is vyos_defined %} distance {{ distance.global }} {% endif %} {% if distance.ospf is vyos_defined %} distance ospf {{ 'intra-area ' + distance.ospf.intra_area if distance.ospf.intra_area is vyos_defined }} {{ 'inter-area ' + distance.ospf.inter_area if distance.ospf.inter_area is vyos_defined }} {{ 'external ' + distance.ospf.external if distance.ospf.external is vyos_defined }} {% endif %} {% if graceful_restart is vyos_defined %} {% if graceful_restart.grace_period is vyos_defined %} graceful-restart grace-period {{ graceful_restart.grace_period }} {% endif %} {% if graceful_restart.helper.enable.router_id is vyos_defined %} {% for router_id in graceful_restart.helper.enable.router_id %} graceful-restart helper enable {{ router_id }} {% endfor %} {% elif graceful_restart.helper.enable is vyos_defined %} graceful-restart helper enable {% endif %} {% if graceful_restart.helper.planned_only is vyos_defined %} graceful-restart helper planned-only {% endif %} {% if graceful_restart.helper.no_strict_lsa_checking is vyos_defined %} no graceful-restart helper strict-lsa-checking {% endif %} {% if graceful_restart.helper.supported_grace_time is vyos_defined %} graceful-restart helper supported-grace-time {{ graceful_restart.helper.supported_grace_time }} {% endif %} {% endif %} {% if log_adjacency_changes is vyos_defined %} log-adjacency-changes {{ "detail" if log_adjacency_changes.detail is vyos_defined }} {% endif %} {% if max_metric.router_lsa.administrative is vyos_defined %} max-metric router-lsa administrative {% endif %} {% if max_metric.router_lsa.on_shutdown is vyos_defined %} max-metric router-lsa on-shutdown {{ max_metric.router_lsa.on_shutdown }} {% endif %} {% if max_metric.router_lsa.on_startup is vyos_defined %} max-metric router-lsa on-startup {{ max_metric.router_lsa.on_startup }} {% endif %} {% if mpls_te.enable is vyos_defined %} mpls-te on mpls-te router-address {{ mpls_te.router_address }} {% endif %} {% if neighbor is vyos_defined %} {% for address, address_config in neighbor.items() %} neighbor {{ address }} {{ 'priority ' + address_config.priority if address_config.priority is vyos_defined }} {{ 'poll-interval ' + address_config.poll_interval if address_config.poll_interval is vyos_defined }} {% endfor %} {% endif %} {% if parameters.abr_type is vyos_defined %} ospf abr-type {{ parameters.abr_type }} {% endif %} {% if parameters.opaque_lsa is vyos_defined %} ospf opaque-lsa {% endif %} {% if parameters.rfc1583_compatibility is vyos_defined %} ospf rfc1583compatibility {% endif %} {% if parameters.router_id is vyos_defined %} ospf router-id {{ parameters.router_id }} {% endif %} {% if passive_interface is vyos_defined('default') %} passive-interface default {% endif %} {% if redistribute is vyos_defined %} {% for protocol, protocols_options in redistribute.items() %} {% if protocol == 'table' %} {% for table, table_options in protocols_options.items() %} redistribute {{ protocol }} {{ table }} {{ 'metric ' + table_options.metric if table_options.metric is vyos_defined }} {{ 'metric-type ' + table_options.metric_type if table_options.metric_type is vyos_defined }} {{ 'route-map ' + table_options.route_map if table_options.route_map is vyos_defined }} {% endfor %} {% else %} redistribute {{ protocol }} {{ 'metric ' + protocols_options.metric if protocols_options.metric is vyos_defined }} {{ 'metric-type ' + protocols_options.metric_type if protocols_options.metric_type is vyos_defined }} {{ 'route-map ' + protocols_options.route_map if protocols_options.route_map is vyos_defined }} {% endif %} {% endfor %} {% endif %} {% if refresh.timers is vyos_defined %} refresh timer {{ refresh.timers }} {% endif %} {% if summary_address is vyos_defined %} {% for prefix, prefix_options in summary_address.items() %} summary-address {{ prefix }} {{ 'tag ' + prefix_options.tag if prefix_options.tag is vyos_defined }}{{ 'no-advertise' if prefix_options.no_advertise is vyos_defined }} {% endfor %} {% endif %} {% if segment_routing is vyos_defined %} {% if segment_routing.maximum_label_depth is vyos_defined %} segment-routing node-msd {{ segment_routing.maximum_label_depth }} {% endif %} {% if segment_routing.global_block is vyos_defined %} {% if segment_routing.local_block is vyos_defined %} segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} local-block {{ segment_routing.local_block.low_label_value }} {{ segment_routing.local_block.high_label_value }} {% else %} segment-routing global-block {{ segment_routing.global_block.low_label_value }} {{ segment_routing.global_block.high_label_value }} {% endif %} {% endif %} {% if segment_routing.prefix is vyos_defined %} {% for prefix, prefix_config in segment_routing.prefix.items() %} {% if prefix_config.index is vyos_defined %} {% if prefix_config.index.value is vyos_defined %} segment-routing prefix {{ prefix }} index {{ prefix_config.index.value }} {{ 'explicit-null' if prefix_config.index.explicit_null is vyos_defined }} {{ 'no-php-flag' if prefix_config.index.no_php_flag is vyos_defined }} {% endif %} {% endif %} {% endfor %} {% endif %} segment-routing on {% endif %} {% if timers.throttle.spf.delay is vyos_defined and timers.throttle.spf.initial_holdtime is vyos_defined and timers.throttle.spf.max_holdtime is vyos_defined %} {# Timer values have default values #} timers throttle spf {{ timers.throttle.spf.delay }} {{ timers.throttle.spf.initial_holdtime }} {{ timers.throttle.spf.max_holdtime }} {% endif %} exit ! diff --git a/interface-definitions/include/ospf/protocol-common-config.xml.i b/interface-definitions/include/ospf/protocol-common-config.xml.i index 438093222..c4778e126 100644 --- a/interface-definitions/include/ospf/protocol-common-config.xml.i +++ b/interface-definitions/include/ospf/protocol-common-config.xml.i @@ -1,946 +1,959 @@ <!-- include start from ospf/protocol-common-config.xml.i --> <node name="aggregation"> <properties> <help>External route aggregation</help> </properties> <children> <leafNode name="timer"> <properties> <help>Delay timer</help> <valueHelp> <format>u32:5-1800</format> <description>Timer interval in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-1800"/> </constraint> </properties> <defaultValue>5</defaultValue> </leafNode> </children> </node> <tagNode name="access-list"> <properties> <help>Access list to filter networks in routing updates</help> <completionHelp> <path>policy access-list</path> </completionHelp> <valueHelp> <format>u32</format> <description>Access-list number</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> <children> <leafNode name="export"> <properties> <help>Filter for outgoing routing update</help> <completionHelp> <list>bgp connected kernel rip static</list> </completionHelp> <valueHelp> <format>bgp</format> <description>Filter BGP routes</description> </valueHelp> <valueHelp> <format>connected</format> <description>Filter connected routes</description> </valueHelp> <valueHelp> <format>isis</format> <description>Filter IS-IS routes</description> </valueHelp> <valueHelp> <format>kernel</format> <description>Filter Kernel routes</description> </valueHelp> <valueHelp> <format>rip</format> <description>Filter RIP routes</description> </valueHelp> <valueHelp> <format>static</format> <description>Filter static routes</description> </valueHelp> <constraint> <regex>(bgp|connected|isis|kernel|rip|static)</regex> </constraint> <constraintErrorMessage>Must be bgp, connected, kernel, rip, or static</constraintErrorMessage> <multi/> </properties> </leafNode> </children> </tagNode> <tagNode name="area"> <properties> <help>OSPF area settings</help> <valueHelp> <format>u32</format> <description>OSPF area number in decimal notation</description> </valueHelp> <valueHelp> <format>ipv4</format> <description>OSPF area number in dotted decimal notation</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> <validator name="ip-address"/> </constraint> </properties> <children> <node name="area-type"> <properties> <help>Area type</help> </properties> <children> <leafNode name="normal"> <properties> <help>Normal OSPF area</help> <valueless/> </properties> </leafNode> <node name="nssa"> <properties> <help>Not-So-Stubby OSPF area</help> </properties> <children> <leafNode name="default-cost"> <properties> <help>Summary-default cost of an NSSA area</help> <valueHelp> <format>u32:0-16777215</format> <description>Summary default cost</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-16777215"/> </constraint> </properties> </leafNode> <leafNode name="no-summary"> <properties> <help>Do not inject inter-area routes into stub</help> <valueless/> </properties> </leafNode> <leafNode name="translate"> <properties> <help>Configure NSSA-ABR</help> <completionHelp> <list>always candidate never</list> </completionHelp> <valueHelp> <format>always</format> <description>Always translate LSA types</description> </valueHelp> <valueHelp> <format>candidate</format> <description>Translate for election</description> </valueHelp> <valueHelp> <format>never</format> <description>Never translate LSA types</description> </valueHelp> <constraint> <regex>(always|candidate|never)</regex> </constraint> </properties> <defaultValue>candidate</defaultValue> </leafNode> </children> </node> <node name="stub"> <properties> <help>Stub OSPF area</help> </properties> <children> <leafNode name="default-cost"> <properties> <help>Summary-default cost</help> <valueHelp> <format>u32:0-16777215</format> <description>Summary default cost</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-16777215"/> </constraint> </properties> </leafNode> <leafNode name="no-summary"> <properties> <help>Do not inject inter-area routes into the stub</help> <valueless/> </properties> </leafNode> </children> </node> </children> </node> <leafNode name="authentication"> <properties> <help>OSPF area authentication type</help> <completionHelp> <list>plaintext-password md5</list> </completionHelp> <valueHelp> <format>plaintext-password</format> <description>Use plain-text authentication</description> </valueHelp> <valueHelp> <format>md5</format> <description>Use MD5 authentication</description> </valueHelp> <constraint> <regex>(plaintext-password|md5)</regex> </constraint> </properties> </leafNode> <leafNode name="network"> <properties> <help>OSPF network</help> <valueHelp> <format>ipv4net</format> <description>OSPF network</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> </constraint> <multi/> </properties> </leafNode> <tagNode name="range"> <properties> <help>Summarize routes matching a prefix (border routers only)</help> <valueHelp> <format>ipv4net</format> <description>Area range prefix</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> </constraint> </properties> <children> <leafNode name="cost"> <properties> <help>Metric for this range</help> <valueHelp> <format>u32:0-16777215</format> <description>Metric for this range</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-16777215"/> </constraint> </properties> </leafNode> <leafNode name="not-advertise"> <properties> <help>Do not advertise this range</help> <valueless/> </properties> </leafNode> <leafNode name="substitute"> <properties> <help>Advertise area range as another prefix</help> <valueHelp> <format>ipv4net</format> <description>Advertise area range as another prefix</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> </constraint> </properties> </leafNode> </children> </tagNode> <leafNode name="shortcut"> <properties> <help>Area shortcut mode</help> <completionHelp> <list>default disable enable</list> </completionHelp> <valueHelp> <format>default</format> <description>Set default</description> </valueHelp> <valueHelp> <format>disable</format> <description>Disable shortcutting mode</description> </valueHelp> <valueHelp> <format>enable</format> <description>Enable shortcutting mode</description> </valueHelp> <constraint> <regex>(default|disable|enable)</regex> </constraint> </properties> </leafNode> <leafNode name="export-list"> <properties> <help>Set the filter for networks announced to other areas</help> <completionHelp> <path>policy access-list</path> </completionHelp> <valueHelp> <format>u32</format> <description>Access-list number</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> <leafNode name="import-list"> <properties> <help>Set the filter for networks from other areas announced</help> <completionHelp> <path>policy access-list</path> </completionHelp> <valueHelp> <format>u32</format> <description>Access-list number</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> </constraint> </properties> </leafNode> <tagNode name="virtual-link"> <properties> <help>Virtual link</help> <valueHelp> <format>ipv4</format> <description>OSPF area in dotted decimal notation</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> <validator name="ip-address"/> </constraint> </properties> <children> #include <include/ospf/authentication.xml.i> #include <include/ospf/intervals.xml.i> </children> </tagNode> </children> </tagNode> #include <include/ospf/auto-cost.xml.i> +<node name="capability"> + <properties> + <help>Enable specific OSPF features</help> + </properties> + <children> + <leafNode name="opaque"> + <properties> + <help>Opaque LSA</help> + <valueless/> + </properties> + </leafNode> + </children> +</node> #include <include/ospf/default-information.xml.i> <leafNode name="default-metric"> <properties> <help>Metric of redistributed routes</help> <valueHelp> <format>u32:0-16777214</format> <description>Metric of redistributed routes</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-16777214"/> </constraint> </properties> </leafNode> #include <include/ospf/graceful-restart.xml.i> <node name="graceful-restart"> <children> <node name="helper"> <children> <leafNode name="no-strict-lsa-checking"> <properties> <help>Disable strict LSA check</help> <valueless/> </properties> </leafNode> </children> </node> </children> </node> <leafNode name="maximum-paths"> <properties> <help>Maximum multiple paths (ECMP)</help> <valueHelp> <format>u32:1-64</format> <description>Maximum multiple paths (ECMP)</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-64"/> </constraint> </properties> </leafNode> #include <include/isis/ldp-sync-protocol.xml.i> <node name="distance"> <properties> <help>Administrative distance</help> </properties> <children> #include <include/ospf/distance-global.xml.i> <node name="ospf"> <properties> <help>OSPF administrative distance</help> </properties> <children> #include <include/ospf/distance-per-protocol.xml.i> </children> </node> </children> </node> <tagNode name="interface"> <properties> <help>Interface configuration</help> <completionHelp> <script>${vyos_completion_dir}/list_interfaces</script> </completionHelp> <valueHelp> <format>txt</format> <description>Interface name</description> </valueHelp> <constraint> #include <include/constraint/interface-name.xml.i> </constraint> </properties> <children> <leafNode name="area"> <properties> <help>Enable OSPF on this interface</help> <completionHelp> <path>protocols ospf area</path> </completionHelp> <valueHelp> <format>u32</format> <description>OSPF area ID as decimal notation</description> </valueHelp> <valueHelp> <format>ipv4</format> <description>OSPF area ID in IP address notation</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-4294967295"/> <validator name="ip-address"/> </constraint> </properties> </leafNode> #include <include/ospf/authentication.xml.i> #include <include/ospf/intervals.xml.i> #include <include/ospf/interface-common.xml.i> #include <include/isis/ldp-sync-interface.xml.i> <leafNode name="bandwidth"> <properties> <help>Interface bandwidth (Mbit/s)</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="hello-multiplier"> <properties> <help>Hello multiplier factor</help> <valueHelp> <format>u32:1-10</format> <description>Number of Hellos to send each second</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-10"/> </constraint> </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> <node name="passive"> <properties> <help>Suppress routing updates on an interface</help> </properties> <children> #include <include/generic-disable-node.xml.i> </children> </node> </children> </tagNode> #include <include/ospf/log-adjacency-changes.xml.i> <node name="max-metric"> <properties> <help>OSPF maximum and infinite-distance metric</help> </properties> <children> <node name="router-lsa"> <properties> <help>Advertise own Router-LSA with infinite distance (stub router)</help> </properties> <children> <leafNode name="administrative"> <properties> <help>Administratively apply, for an indefinite period</help> <valueless/> </properties> </leafNode> <leafNode name="on-shutdown"> <properties> <help>Advertise stub-router prior to full shutdown of OSPF</help> <valueHelp> <format>u32:5-100</format> <description>Time (seconds) to advertise self as stub-router</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-100"/> </constraint> </properties> </leafNode> <leafNode name="on-startup"> <properties> <help>Automatically advertise stub Router-LSA on startup of OSPF</help> <valueHelp> <format>u32:5-86400</format> <description>Time (seconds) to advertise self as stub-router</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 5-86400"/> </constraint> </properties> </leafNode> </children> </node> </children> </node> <node name="mpls-te"> <properties> <help>MultiProtocol Label Switching-Traffic Engineering (MPLS-TE) parameters</help> </properties> <children> <leafNode name="enable"> <properties> <help>Enable MPLS-TE functionality</help> <valueless/> </properties> </leafNode> <leafNode name="router-address"> <properties> <help>Stable IP address of the advertising router</help> <valueHelp> <format>ipv4</format> <description>Stable IP address of the advertising router</description> </valueHelp> <constraint> <validator name="ipv4-address"/> </constraint> </properties> <defaultValue>0.0.0.0</defaultValue> </leafNode> </children> </node> <tagNode name="neighbor"> <properties> <help>Specify neighbor router</help> <valueHelp> <format>ipv4</format> <description>Neighbor IP address</description> </valueHelp> <constraint> <validator name="ipv4-address"/> </constraint> </properties> <children> <leafNode name="poll-interval"> <properties> <help>Dead neighbor polling interval</help> <valueHelp> <format>u32:1-65535</format> <description>Seconds between dead neighbor polling interval</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-65535"/> </constraint> </properties> <defaultValue>60</defaultValue> </leafNode> <leafNode name="priority"> <properties> <help>Neighbor priority in seconds</help> <valueHelp> <format>u32:0-255</format> <description>Neighbor priority</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-255"/> </constraint> </properties> <defaultValue>0</defaultValue> </leafNode> </children> </tagNode> <node name="parameters"> <properties> <help>OSPF specific parameters</help> </properties> <children> <leafNode name="abr-type"> <properties> <help>OSPF ABR type</help> <completionHelp> <list>cisco ibm shortcut standard</list> </completionHelp> <valueHelp> <format>cisco</format> <description>Cisco ABR type</description> </valueHelp> <valueHelp> <format>ibm</format> <description>IBM ABR type</description> </valueHelp> <valueHelp> <format>shortcut</format> <description>Shortcut ABR type</description> </valueHelp> <valueHelp> <format>standard</format> <description>Standard ABR type</description> </valueHelp> <constraint> <regex>(cisco|ibm|shortcut|standard)</regex> </constraint> </properties> <defaultValue>cisco</defaultValue> </leafNode> <leafNode name="opaque-lsa"> <properties> <help>Enable the Opaque-LSA capability (rfc2370)</help> <valueless/> </properties> </leafNode> <leafNode name="rfc1583-compatibility"> <properties> <help>Enable RFC1583 criteria for handling AS external routes</help> <valueless/> </properties> </leafNode> #include <include/router-id.xml.i> </children> </node> <leafNode name="passive-interface"> <properties> <help>Suppress routing updates on an interface</help> <completionHelp> <list>default</list> </completionHelp> <valueHelp> <format>default</format> <description>Default to suppress routing updates on all interfaces</description> </valueHelp> <constraint> <regex>(default)</regex> </constraint> </properties> </leafNode> <node name="segment-routing"> <properties> <help>Segment-Routing (SPRING) settings</help> </properties> <children> <node name="global-block"> <properties> <help>Segment Routing Global Block label range</help> </properties> <children> #include <include/segment-routing-label-value.xml.i> </children> </node> <node name="local-block"> <properties> <help>Segment Routing Local Block label range</help> </properties> <children> #include <include/segment-routing-label-value.xml.i> </children> </node> <leafNode name="maximum-label-depth"> <properties> <help>Maximum MPLS labels allowed for this router</help> <valueHelp> <format>u32:1-16</format> <description>MPLS label depth</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-16"/> </constraint> </properties> </leafNode> <tagNode name="prefix"> <properties> <help>Static IPv4 prefix segment/label mapping</help> <valueHelp> <format>ipv4net</format> <description>IPv4 prefix segment</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> </constraint> </properties> <children> <node name="index"> <properties> <help>Specify the index value of prefix segment/label ID</help> </properties> <children> <leafNode name="value"> <properties> <help>Specify the index value of prefix segment/label ID</help> <valueHelp> <format>u32:0-65535</format> <description>The index segment/label ID value</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-65535"/> </constraint> </properties> </leafNode> <leafNode name="explicit-null"> <properties> <help>Request upstream neighbor to replace segment/label with explicit null label</help> <valueless/> </properties> </leafNode> <leafNode name="no-php-flag"> <properties> <help>Do not request penultimate hop popping for segment/label</help> <valueless/> </properties> </leafNode> </children> </node> </children> </tagNode> </children> </node> <node name="redistribute"> <properties> <help>Redistribute information from another routing protocol</help> </properties> <children> <node name="bgp"> <properties> <help>Redistribute BGP routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="connected"> <properties> <help>Redistribute connected routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="isis"> <properties> <help>Redistribute IS-IS routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="kernel"> <properties> <help>Redistribute Kernel routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="rip"> <properties> <help>Redistribute RIP routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="babel"> <properties> <help>Redistribute Babel routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <node name="static"> <properties> <help>Redistribute statically configured routes</help> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </node> <tagNode name="table"> <properties> <help>Redistribute non-main Kernel Routing Table</help> <completionHelp> <path>protocols static table</path> </completionHelp> <valueHelp> <format>u32:1-200</format> <description>Policy route table number</description> </valueHelp> </properties> <children> #include <include/ospf/metric.xml.i> #include <include/ospf/metric-type.xml.i> #include <include/route-map.xml.i> </children> </tagNode> </children> </node> <node name="refresh"> <properties> <help>Adjust refresh parameters</help> </properties> <children> <leafNode name="timers"> <properties> <help>Refresh timer</help> <valueHelp> <format>u32:10-1800</format> <description>Timer value in seconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 10-1800"/> </constraint> </properties> </leafNode> </children> </node> <tagNode name="summary-address"> <properties> <help>External summary address</help> <valueHelp> <format>ipv4net</format> <description>OSPF area number in dotted decimal notation</description> </valueHelp> <constraint> <validator name="ipv4-prefix"/> </constraint> </properties> <children> <leafNode name="no-advertise"> <properties> <help>Don not advertise summary route</help> <valueless/> </properties> </leafNode> <leafNode name="tag"> <properties> <help>Router tag</help> <valueHelp> <format>u32:1-4294967295</format> <description>Router tag value</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 1-4294967295"/> </constraint> </properties> </leafNode> </children> </tagNode> <node name="timers"> <properties> <help>Adjust routing timers</help> </properties> <children> <node name="throttle"> <properties> <help>Throttling adaptive timers</help> </properties> <children> <node name="spf"> <properties> <help>OSPF SPF timers</help> </properties> <children> <leafNode name="delay"> <properties> <help>Delay from the first change received to SPF calculation</help> <valueHelp> <format>u32:0-600000</format> <description>Delay in milliseconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-600000"/> </constraint> </properties> <defaultValue>200</defaultValue> </leafNode> <leafNode name="initial-holdtime"> <properties> <help>Initial hold time between consecutive SPF calculations</help> <valueHelp> <format>u32:0-600000</format> <description>Initial hold time in milliseconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-600000"/> </constraint> </properties> <defaultValue>1000</defaultValue> </leafNode> <leafNode name="max-holdtime"> <properties> <help>Maximum hold time</help> <valueHelp> <format>u32:0-600000</format> <description>Max hold time in milliseconds</description> </valueHelp> <constraint> <validator name="numeric" argument="--range 0-600000"/> </constraint> </properties> <defaultValue>10000</defaultValue> </leafNode> </children> </node> </children> </node> </children> </node> <!-- include end --> diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index f4b540694..80befbfd6 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -1,508 +1,510 @@ #!/usr/bin/env python3 # # Copyright (C) 2021-2022 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/>. import unittest from base_vyostest_shim import VyOSUnitTestSHIM from vyos.configsession import ConfigSessionError from vyos.ifconfig import Section from vyos.utils.process import process_named_running PROCESS_NAME = 'ospfd' base_path = ['protocols', 'ospf'] route_map = 'foo-bar-baz10' class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase): @classmethod def setUpClass(cls): super(TestProtocolsOSPF, cls).setUpClass() cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '10', 'action', 'permit']) cls.cli_set(cls, ['policy', 'route-map', route_map, 'rule', '20', 'action', 'permit']) # ensure we can also run this test on a live system - so lets clean # out the current configuration :) cls.cli_delete(cls, base_path) @classmethod def tearDownClass(cls): cls.cli_delete(cls, ['policy', 'route-map', route_map]) super(TestProtocolsOSPF, cls).tearDownClass() def tearDown(self): # Check for running process self.assertTrue(process_named_running(PROCESS_NAME)) self.cli_delete(base_path) self.cli_commit() def test_ospf_01_defaults(self): # commit changes self.cli_set(base_path) self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults def test_ospf_02_simple(self): router_id = '127.0.0.1' abr_type = 'ibm' bandwidth = '1000' metric = '123' self.cli_set(base_path + ['auto-cost', 'reference-bandwidth', bandwidth]) self.cli_set(base_path + ['parameters', 'router-id', router_id]) self.cli_set(base_path + ['parameters', 'abr-type', abr_type]) self.cli_set(base_path + ['parameters', 'opaque-lsa']) self.cli_set(base_path + ['parameters', 'rfc1583-compatibility']) self.cli_set(base_path + ['log-adjacency-changes', 'detail']) self.cli_set(base_path + ['default-metric', metric]) self.cli_set(base_path + ['passive-interface', 'default']) self.cli_set(base_path + ['area', '10', 'area-type', 'stub']) self.cli_set(base_path + ['area', '10', 'network', '10.0.0.0/16']) self.cli_set(base_path + ['area', '10', 'range', '10.0.1.0/24']) self.cli_set(base_path + ['area', '10', 'range', '10.0.2.0/24', 'not-advertise']) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' compatible rfc1583', frrconfig) self.assertIn(f' auto-cost reference-bandwidth {bandwidth}', frrconfig) self.assertIn(f' ospf router-id {router_id}', frrconfig) self.assertIn(f' ospf abr-type {abr_type}', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults self.assertIn(f' capability opaque', frrconfig) self.assertIn(f' default-metric {metric}', frrconfig) self.assertIn(f' passive-interface default', frrconfig) self.assertIn(f' area 10 stub', frrconfig) self.assertIn(f' network 10.0.0.0/16 area 10', frrconfig) self.assertIn(f' area 10 range 10.0.1.0/24', frrconfig) self.assertNotIn(f' area 10 range 10.0.1.0/24 not-advertise', frrconfig) self.assertIn(f' area 10 range 10.0.2.0/24 not-advertise', frrconfig) def test_ospf_03_access_list(self): acl = '100' seq = '10' protocols = ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static'] self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'action', 'permit']) self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'source', 'any']) self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'destination', 'any']) for ptotocol in protocols: self.cli_set(base_path + ['access-list', acl, 'export', ptotocol]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults for ptotocol in protocols: self.assertIn(f' distribute-list {acl} out {ptotocol}', frrconfig) # defaults self.cli_delete(['policy', 'access-list', acl]) def test_ospf_04_default_originate(self): seq = '100' metric = '50' metric_type = '1' self.cli_set(base_path + ['default-information', 'originate', 'metric', metric]) self.cli_set(base_path + ['default-information', 'originate', 'metric-type', metric_type]) self.cli_set(base_path + ['default-information', 'originate', 'route-map', route_map]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults self.assertIn(f' default-information originate metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) # Now set 'always' self.cli_set(base_path + ['default-information', 'originate', 'always']) self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f' default-information originate always metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) def test_ospf_05_options(self): global_distance = '128' intra_area = '100' inter_area = '110' external = '120' on_startup = '30' on_shutdown = '60' refresh = '50' aggregation_timer = '100' summary_nets = { '10.0.1.0/24' : {}, '10.0.2.0/24' : {'tag' : '50'}, '10.0.3.0/24' : {'no_advertise' : {}}, } self.cli_set(base_path + ['distance', 'global', global_distance]) self.cli_set(base_path + ['distance', 'ospf', 'external', external]) self.cli_set(base_path + ['distance', 'ospf', 'intra-area', intra_area]) self.cli_set(base_path + ['max-metric', 'router-lsa', 'on-startup', on_startup]) self.cli_set(base_path + ['max-metric', 'router-lsa', 'on-shutdown', on_shutdown]) self.cli_set(base_path + ['mpls-te', 'enable']) self.cli_set(base_path + ['refresh', 'timers', refresh]) self.cli_set(base_path + ['aggregation', 'timer', aggregation_timer]) for summary, summary_options in summary_nets.items(): self.cli_set(base_path + ['summary-address', summary]) if 'tag' in summary_options: self.cli_set(base_path + ['summary-address', summary, 'tag', summary_options['tag']]) if 'no_advertise' in summary_options: self.cli_set(base_path + ['summary-address', summary, 'no-advertise']) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' mpls-te on', frrconfig) self.assertIn(f' mpls-te router-address 0.0.0.0', frrconfig) # default self.assertIn(f' distance {global_distance}', frrconfig) self.assertIn(f' distance ospf intra-area {intra_area} external {external}', frrconfig) self.assertIn(f' max-metric router-lsa on-startup {on_startup}', frrconfig) self.assertIn(f' max-metric router-lsa on-shutdown {on_shutdown}', frrconfig) self.assertIn(f' refresh timer {refresh}', frrconfig) self.assertIn(f' aggregation timer {aggregation_timer}', frrconfig) for summary, summary_options in summary_nets.items(): self.assertIn(f' summary-address {summary}', frrconfig) if 'tag' in summary_options: tag = summary_options['tag'] self.assertIn(f' summary-address {summary} tag {tag}', frrconfig) if 'no_advertise' in summary_options: self.assertIn(f' summary-address {summary} no-advertise', frrconfig) # enable inter-area self.cli_set(base_path + ['distance', 'ospf', 'inter-area', inter_area]) self.cli_commit() frrconfig = self.getFRRconfig('router ospf') self.assertIn(f' distance ospf intra-area {intra_area} inter-area {inter_area} external {external}', frrconfig) def test_ospf_06_neighbor(self): priority = '10' poll_interval = '20' neighbors = ['1.1.1.1', '2.2.2.2', '3.3.3.3'] for neighbor in neighbors: self.cli_set(base_path + ['neighbor', neighbor, 'priority', priority]) self.cli_set(base_path + ['neighbor', neighbor, 'poll-interval', poll_interval]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) for neighbor in neighbors: self.assertIn(f' neighbor {neighbor} priority {priority} poll-interval {poll_interval}', frrconfig) # default def test_ospf_07_redistribute(self): metric = '15' metric_type = '1' redistribute = ['bgp', 'connected', 'isis', 'kernel', 'rip', 'static'] for protocol in redistribute: self.cli_set(base_path + ['redistribute', protocol, 'metric', metric]) self.cli_set(base_path + ['redistribute', protocol, 'route-map', route_map]) self.cli_set(base_path + ['redistribute', protocol, 'metric-type', metric_type]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) for protocol in redistribute: self.assertIn(f' redistribute {protocol} metric {metric} metric-type {metric_type} route-map {route_map}', frrconfig) def test_ospf_08_virtual_link(self): networks = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'] area = '10' shortcut = 'enable' virtual_link = '192.0.2.1' hello = '6' retransmit = '5' transmit = '5' dead = '40' self.cli_set(base_path + ['area', area, 'shortcut', shortcut]) self.cli_set(base_path + ['area', area, 'virtual-link', virtual_link, 'hello-interval', hello]) self.cli_set(base_path + ['area', area, 'virtual-link', virtual_link, 'retransmit-interval', retransmit]) self.cli_set(base_path + ['area', area, 'virtual-link', virtual_link, 'transmit-delay', transmit]) self.cli_set(base_path + ['area', area, 'virtual-link', virtual_link, 'dead-interval', dead]) for network in networks: self.cli_set(base_path + ['area', area, 'network', network]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' area {area} shortcut {shortcut}', frrconfig) self.assertIn(f' area {area} virtual-link {virtual_link} hello-interval {hello} retransmit-interval {retransmit} transmit-delay {transmit} dead-interval {dead}', frrconfig) for network in networks: self.assertIn(f' network {network} area {area}', frrconfig) def test_ospf_09_interface_configuration(self): interfaces = Section.interfaces('ethernet') password = 'vyos1234' bandwidth = '10000' cost = '150' network = 'point-to-point' priority = '200' bfd_profile = 'vyos-test' self.cli_set(base_path + ['passive-interface', 'default']) for interface in interfaces: base_interface = base_path + ['interface', interface] self.cli_set(base_interface + ['authentication', 'plaintext-password', password]) self.cli_set(base_interface + ['bandwidth', bandwidth]) self.cli_set(base_interface + ['bfd', 'profile', bfd_profile]) self.cli_set(base_interface + ['cost', cost]) self.cli_set(base_interface + ['mtu-ignore']) self.cli_set(base_interface + ['network', network]) self.cli_set(base_interface + ['priority', priority]) self.cli_set(base_interface + ['passive', 'disable']) # commit changes self.cli_commit() frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' passive-interface default', frrconfig) for interface in interfaces: config = self.getFRRconfig(f'interface {interface}') self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf authentication-key {password}', config) self.assertIn(f' ip ospf bfd', config) self.assertIn(f' ip ospf bfd profile {bfd_profile}', config) self.assertIn(f' ip ospf cost {cost}', config) self.assertIn(f' ip ospf mtu-ignore', config) self.assertIn(f' ip ospf network {network}', config) self.assertIn(f' ip ospf priority {priority}', config) self.assertIn(f' no ip ospf passive', config) self.assertIn(f' bandwidth {bandwidth}', config) def test_ospf_11_interface_area(self): area = '0' interfaces = Section.interfaces('ethernet') self.cli_set(base_path + ['area', area, 'network', '10.0.0.0/8']) for interface in interfaces: self.cli_set(base_path + ['interface', interface, 'area', area]) # we can not have bot area network and interface area set with self.assertRaises(ConfigSessionError): self.cli_commit() self.cli_delete(base_path + ['area', area, 'network']) self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) for interface in interfaces: config = self.getFRRconfig(f'interface {interface}') self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf area {area}', config) def test_ospf_12_vrfs(self): # It is safe to assume that when the basic VRF test works, all # other OSPF related features work, as we entirely inherit the CLI # templates and Jinja2 FRR template. table = '1000' vrf = 'blue' vrf_base = ['vrf', 'name', vrf] vrf_iface = 'eth1' self.cli_set(vrf_base + ['table', table]) self.cli_set(vrf_base + ['protocols', 'ospf', 'interface', vrf_iface]) self.cli_set(['interfaces', 'ethernet', vrf_iface, 'vrf', vrf]) # Also set a default VRF OSPF config self.cli_set(base_path) self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults frrconfig = self.getFRRconfig(f'router ospf vrf {vrf}') self.assertIn(f'router ospf vrf {vrf}', frrconfig) self.assertIn(f' auto-cost reference-bandwidth 100', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # defaults # cleanup self.cli_delete(['vrf', 'name', vrf]) self.cli_delete(['interfaces', 'ethernet', vrf_iface, 'vrf']) def test_ospf_13_export_list(self): # Verify explort-list works on ospf-area acl = '100' seq = '10' area = '0.0.0.10' network = '10.0.0.0/8' self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'action', 'permit']) self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'source', 'any']) self.cli_set(['policy', 'access-list', acl, 'rule', seq, 'destination', 'any']) self.cli_set(base_path + ['area', area, 'network', network]) self.cli_set(base_path + ['area', area, 'export-list', acl]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) # default self.assertIn(f' network {network} area {area}', frrconfig) self.assertIn(f' area {area} export-list {acl}', frrconfig) def test_ospf_14_segment_routing_configuration(self): global_block_low = "300" global_block_high = "399" local_block_low = "400" local_block_high = "499" interface = 'lo' maximum_stack_size = '5' prefix_one = '192.168.0.1/32' prefix_two = '192.168.0.2/32' prefix_one_value = '1' prefix_two_value = '2' self.cli_set(base_path + ['interface', interface]) self.cli_set(base_path + ['segment-routing', 'maximum-label-depth', maximum_stack_size]) self.cli_set(base_path + ['segment-routing', 'global-block', 'low-label-value', global_block_low]) self.cli_set(base_path + ['segment-routing', 'global-block', 'high-label-value', global_block_high]) self.cli_set(base_path + ['segment-routing', 'local-block', 'low-label-value', local_block_low]) self.cli_set(base_path + ['segment-routing', 'local-block', 'high-label-value', local_block_high]) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_one, 'index', 'value', prefix_one_value]) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_one, 'index', 'explicit-null']) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_two, 'index', 'value', prefix_two_value]) self.cli_set(base_path + ['segment-routing', 'prefix', prefix_two, 'index', 'no-php-flag']) # Commit all changes self.cli_commit() # Verify all changes frrconfig = self.getFRRconfig('router ospf') self.assertIn(f' segment-routing on', frrconfig) self.assertIn(f' segment-routing global-block {global_block_low} {global_block_high} local-block {local_block_low} {local_block_high}', frrconfig) self.assertIn(f' segment-routing node-msd {maximum_stack_size}', frrconfig) self.assertIn(f' segment-routing prefix {prefix_one} index {prefix_one_value} explicit-null', frrconfig) self.assertIn(f' segment-routing prefix {prefix_two} index {prefix_two_value} no-php-flag', frrconfig) def test_ospf_15_ldp_sync(self): holddown = "500" interface = 'lo' interfaces = Section.interfaces('ethernet') self.cli_set(base_path + ['interface', interface]) self.cli_set(base_path + ['ldp-sync', 'holddown', holddown]) # Commit main OSPF changes self.cli_commit() # Verify main OSPF changes frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) self.assertIn(f' timers throttle spf 200 1000 10000', frrconfig) self.assertIn(f' mpls ldp-sync holddown {holddown}', frrconfig) for interface in interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'holddown', holddown]) # Commit interface changes for holddown self.cli_commit() # Verify interface changes for holddown config = self.getFRRconfig(f'interface {interface}') self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf dead-interval 40', config) self.assertIn(f' ip ospf mpls ldp-sync', config) self.assertIn(f' ip ospf mpls ldp-sync holddown {holddown}', config) for interface in interfaces: self.cli_set(base_path + ['interface', interface, 'ldp-sync', 'disable']) # Commit interface changes for disable self.cli_commit() # Verify interface changes for disable config = self.getFRRconfig(f'interface {interface}') self.assertIn(f'interface {interface}', config) self.assertIn(f' ip ospf dead-interval 40', config) self.assertIn(f' no ip ospf mpls ldp-sync', config) def test_ospf_16_graceful_restart(self): period = '300' supported_grace_time = '400' router_ids = ['192.0.2.1', '192.0.2.2'] + self.cli_set(base_path + ['capability', 'opaque']) self.cli_set(base_path + ['graceful-restart', 'grace-period', period]) self.cli_set(base_path + ['graceful-restart', 'helper', 'planned-only']) self.cli_set(base_path + ['graceful-restart', 'helper', 'no-strict-lsa-checking']) self.cli_set(base_path + ['graceful-restart', 'helper', 'supported-grace-time', supported_grace_time]) for router_id in router_ids: self.cli_set(base_path + ['graceful-restart', 'helper', 'enable', 'router-id', router_id]) # commit changes self.cli_commit() # Verify FRR ospfd configuration frrconfig = self.getFRRconfig('router ospf') self.assertIn(f'router ospf', frrconfig) + self.assertIn(f' capability opaque', frrconfig) self.assertIn(f' graceful-restart grace-period {period}', frrconfig) self.assertIn(f' graceful-restart helper planned-only', frrconfig) self.assertIn(f' no graceful-restart helper strict-lsa-checking', frrconfig) self.assertIn(f' graceful-restart helper supported-grace-time {supported_grace_time}', frrconfig) for router_id in router_ids: self.assertIn(f' graceful-restart helper enable {router_id}', frrconfig) if __name__ == '__main__': unittest.main(verbosity=2)