In this blog post, we want to show how to enable a zone-based firewall on the Cisco SD-WAN platform. The example continues on the topology in the Direct Internet Access article. We introduced an additional site to demonstrate that the configuration applied doesn’t affect inter-site traffic.
The diagram below shows the topology with a PC behind CSR1. It can access the Internet without any restrictions after enabling Direct Internet Access. If we want to restrict what is reachable from the service side, two options are available – access lists attached to the internal interface and zone-based firewall functionality. As on the traditional, non-SD-WAN router, access-lists are used in scenarios when no stateful inspection is required, for example, when you want to drop RFC 1918 traffic coming from your guest WIFI segment. Cisco zone-based firewall adds the ability to identify the application and stateful inspection, which allows return traffic if it’s part of the permitted session.
Initial setup for DIA blocking all outbound traffic
The first section will create and associate a security policy that will block all traffic from the internal network to the Internet.
To apply the firewall rules, use a localized security policy. Navigate to Configuration > Policy. Click on Add Security Policy. Choose a custom policy from the list below, as this option shows all possible configuration elements.
The first screen in the wizard is firewall configuration. Click on Add Firewall Policy, and then on Create New.
Define source and destination zone pairs by clicking on Apply Zone-Pairs button. Select source and destination zones. You can create zones within the wizard by specifying which VPNs will be part of them.
Provide Name and Description for the firewall policy. We can add rules as required; however, we want to drop all the traffic first. The default action, which is applied when no rules match the packet, is Drop (you can change this behavior by selecting Pass in the dropdown menu).
Review created firewall policy and press Next.
We’ve clicked through all remaining pages of the wizard without adding any configuration. On the “Policy summary” page, provide Security Policy Name and its description.
After clicking on the Save Policy button, we can see the policy we’ve just created in the list.
Now it’s time to apply the policy to the device. The device template applies the policy to the device.
Choose ISR1-Security-Policy in the Security Policy dropdown. And press the Update button to push the configuration to the device.
The listing below shows the config lines are sent to the device based on the configuration we’ve made so far (you can check this via configuration difference preview before the configuration push). As we haven’t specified any specific rules, the policy uses only the class-default class with drop action. The ‘inspect’ firewall policy is defined and applied within the zone-pair configuration block.
parameter-map type inspect-global
alert on
log dropped-packets
multi-tenancy
vpn zone security
policy-map type inspect VPN1-to-VPN0
class class-default
drop
zone security VPN0
vpn 0
zone security VPN1
vpn 1
zone-pair security ZP_VPN1_VPN0_VPN1-to-VPN0 source VPN1 destination VPN0
service-policy type inspect VPN1-to-VPN0
The test shows that the ICMP traffic is blocked as soon as the policy is applied.
To demonstrate that our policy didn’t affect traffic within VPN 1, let’s ping the PC behind CSR02 at another site.
Adjust policy to allow ICMP traffic
This section will allow ICMP traffic to the Internet by modifying the policy.
Return to the policy list via Configuration > Security. Choose the policy that we’ve created earlier and press Edit.
Click on the firewall section, choose the “VPN1-to-VPN0” firewall rule and press Edit.
Add the new rule by clicking on the “Add Rule” button.
Specify ACL entry name and choose action to apply. Drop is self-descriptive. Inspect creates a stateful record of the session and automatically allows return traffic. Pass action – will not allow return traffic; for this action to work, you will be required to create another zone-pair for reverse direction and explicitly allow return traffic.
Define matching traffic and action. Protocol number 1 matches ICMP. Select one of the pre-defined protocols for TCP and UDP traffic. If unavailable or non-standard port numbers need to be specified, use ‘tcp’ or ‘udp’ as a protocol along with the “Destination Ports” condition.
Review the rule, save it, and its parent firewall policy.
vManage sends the following commands to the device.
The first three commands are object groups that identify the source, destination, and protocol.
Then access list is defined using the object groups. The class map that follows uses the ACL as a “match” condition.
Finally, policy-map now has a custom class-map statement placed above the default. The action for this traffic is ‘inspect,’ so return packets are automatically allowed.
object-group network VPN1-to-VPN0-seq-Allow_ICMP-network-dstn-og_
host 15.15.15.10
object-group network VPN1-to-VPN0-seq-Allow_ICMP-network-src-og_
192.168.11.0 255.255.255.0
object-group service VPN1-to-VPN0-seq-Allow_ICMP-service-og_
icmp
ip access-list extended VPN1-to-VPN0-seq-Allow_ICMP-acl_
permit object-group VPN1-to-VPN0-seq-Allow_ICMP-service-og_ object-group VPN1-to-VPN0-seq-Allow_ICMP-network-src-og_ object-group VPN1-to-VPN0-seq-Allow_ICMP-network-dstn-og_
class-map type inspect match-all VPN1-to-VPN0-seq-1-cm_
match access-group name VPN1-to-VPN0-seq-Allow_ICMP-acl_
policy-map type inspect VPN1-to-VPN0
class type inspect VPN1-to-VPN0-seq-1-cm_
inspect
class class-default
drop
To monitor or troubleshoot firewall sessions, use the Real-Time menu in the device monitoring, as shown in the screenshot below. The following options provide relevant real-time information:
Policy Zone Pair Sessions – displays list of sessions and which zone pair and class map is matched for each session
Policy Zone Pair Statistics – shows statistics of packets and bytes matching per class-map
IP NAT Translation – displays NAT translations, which can be useful in DIA troubleshooting scenarios
To view active sessions using CLI as they are passing, use show policy-firewall sessions command:
CSR01#show policy-firewall sessions platform ?
all detailed information
destination-port Destination Port Number
detail detail on or off
icmp Protocol Type ICMP
imprecise imprecise information
session session information
source-port Source Port
source-vrf Source Vrf ID
standby standby information
tcp Protocol Type TCP
udp Protocol Type UDP
v4-destination-address IPv4 Desination Address
v4-source-address IPv4 Source Address
v6-destination-address IPv6 Desination Address
v6-source-address IPv6 Source Address
| Output modifiers
<cr> <cr>
It is possible to filter the output using one of the keywords above. We will display all sessions with 'all' keyword.
CSR01#show policy-firewall sessions platform all
--show platform hardware qfp active feature firewall datapath scb any any any any any all any --
[s=session i=imprecise channel c=control channel d=data channel A/D=appfw action allow/deny]
Session ID:0x00000001 192.168.11.10 8 15.15.15.10 1 proto 1 (1:1:1:1) (0x3:icmp) [sc]
To display detailed information on the session, which includes ingress and egress interfaces, translated addresses, and other information use detail keyword.
SD-WAN deployments use the Internet as the transport to replace WAN networks traditionally designed to leverage centralized Internet access via the data center. Direct Internet Access (DIA) refers to the configuration when Internet-facing traffic breaks out directly from the branch router.
Is Network Address Translation (NAT) required for DIA to operate? Yes, NAT maintains a translation table, that tracks outbound sessions from the service side VPNs (LAN), so the return traffic can be sent back without having to leak service VPN routes into VPN 0.
In the Cisco SD-WAN solution, transport-facing and user-facing interfaces belong to different VPNs or VRFs. VPN 0 contains transport (or underlay) network-facing interfaces, such as Internet and MPLS. Service-side VPNs contain user-facing interfaces.
The figure below shows logical VPN isolation within a router. In the routing table of VPN 0, there will be no entries for subnets where Host A and Host B are located. These subnets can even have the same IP addresses.
For DIA to work we need to allow traffic to flow between these virtual routers (or VPNs). To direct traffic from service-side VPNs we can use either static routes or a centralized data policy. NAT in transport VPN allows return traffic to be sent back.
Direct Internet Access on Cisco SD-WAN platforms is enabled in 2 steps. The first one is the NAT configuration on the transport interface. The second step directs traffic from service-side VPN using either a static route or centralized data policy.
Step 1: Enable NAT on the transport interface
Let’s start with a very basic topology, shown in Figure 2.
Edge router has a device template assigned, which references a basic set of feature templates required to provide connectivity.
The first step of both static route and policy-based configuration is to enable NAT on an interface in the transport VPN – GigabitEthernet2. This is done by adjusting the interface template.
The following commands are pushed to the device.
ip nat inside source list nat-dia-vpn-hop-access-list interface GigabitEthernet2 overload
ip nat translation tcp-timeout 3600
ip nat translation udp-timeout 60
interface GigabitEthernet2
ip nat outside
We couldn’t find a way to modify the nat-dia-vpn-hop-access-list used in ip nat insidecommand. This ACL is not visible in the running configuration or in the output of show ip access-lists. In IOS-XE this access list identifies traffic to be translated. In SD-WAN, however, to achieve this data policy needs to be configured.
Step 2: Direct traffic from service-side VPN
There are 2 ways to achieve this:
Static route in service VPN template
Centralized data policy
Step 2 (option 1): Static Route Configuration
Let’s configure a static default route under VPN 1 (Service VPN). Note that VPN is selected as a gateway option.
The static route command that is pushed to the device looks like this: ip nat route vrf 1 0.0.0.0 0.0.0.0 global
Note that the static route command has nat keyword. If we turn off NAT enabled in the previous step, the route will disappear. This essentially means that you have to do address translation for the configuration to work.
Let’s do the test from our test PC, confirming that the remote server sees the request as it’s coming from the router’s external IP address.
To check the list of translations, we can run the following command on the router:
CSR01#show ip nat translations verbose
Pro Inside global Inside local Outside local Outside global
tcp 21.1.1.2:5062 192.168.11.10:49158 15.15.15.10:80 15.15.15.10:80
create: 11/14/21 23:16:21, use: 11/14/21 23:16:27, timeout: 00:00:56
RuleID : 1
Flags: timing-out
ALG Application Type: NA
WLAN-Flags: unknown
Mac-Address: 0000.0000.0000 Input-IDB:
VRF: 1, entry-id: 0xe9f7f840, use_count:1
In_pkts: 7 In_bytes: 978, Out_pkts: 7 Out_bytes: 982
Output-IDB: GigabitEthernet2
CSR01#show ip nat translation
Pro Inside global Inside local Outside local Outside global
tcp 21.1.1.2:5062 192.168.11.10:49158 15.15.15.10:80 15.15.15.10:80
Step 2 (Option 2): Centralized policy
We have removed the static route created in Step 2 (option 1), as the traffic will be directed by the centralized policy.
To implement DIA we will configure the traffic data section of the centralized policy that will match traffic coming from 192.168.11.0/24 (LAN segment) to 15.15.15.10/32 (the webserver).
Only one centralized policy can be activated globally at a time. The centralized policy contains multiple component policies. In this example, we will define a data policy, which then can be applied to a site list. In the following steps, we will create a new policy.
Create a centralized policy
Navigate to Configuration > Policies and click on Add Policy button.
The first step of creating a policy is called “Create Groups of Interest”. These are variables that we can later use in the policy. For our example, we will define:
Data Prefix – for source prefix 192.168.11.0/24, and we will use 15.15.15.10/32 directly in our traffic matching configuration without variable definition
Site List – we want apply only to a single site with Site ID of 1; it is recommended not to have the same site in multiple site lists to ensure that only 1 policy of each type is applied to that site
VPN List – service VPN 1
After defining all required variables and pressing the Next button, we are moved to the Topology and VPN Membership section of the wizard (see the top part of the screenshot below). We don’t need to configure anything for our data policy, so we just press Next.
On the Configure Traffic Rules step of the wizard click on the “Traffic Data” section of the policy, click on Add Policy > Create New (refer to the bottom part of the next screenshot).
In a new data policy window enter the name and description of the policy. Adjust the default action to Accept to ensure that the packets that don’t match our criteria for DIA will not be dropped. Finally, press + button to add a rule that will be matching DIA traffic and apply NAT to it.
In the pop-up window select Custom policy. The other options are just a subset of the match and set conditions tailored for different scenarios, custom lists all of them.
Custom rule is added on top of the default action. If there are several rules, you can re-arrange them on the left panel. Ensure that the Match section is selected, add Source and Destination data prefixes to set the conditions for the rule.
Select the data prefix that we set up earlier in groups of interest as the source. Type-in destination as the actual address without the use of the variable. Both options lead to the same result, however, the use of variables allows you to use descriptive naming of the object plus adjusting the values outside of the policy configuration. Click on the Actions button.
Select NAT VPN action, as shown in the following screenshot. The fallback option is useful when you want this traffic to follow the routing table when NAT cannot be used, for example, when the interface is down. Press the “Save data policy” button.
The next screenshot list the data policy that we built in the previous step. Notice that the reference count is 0, as we haven’t yet applied it yet. Press Next.
The final step is to apply the policy. Click on the Traffic Data section, and then under data-policy-1 press “New Site List and VPN List”. In the pop-up window select “From Service” direction, site-1 as the site list, and VPN1 as the VPN list. Press the Save Policy button.
The final step is to activate the policy.
At this stage vManage will push the policy to vSmart as part of its running-config:
vSmart will use OMP to distribute the policy to edge routers. In contrast to vSmart, edge routers will not display the policy in the running configuration. Use show sdwan policy from-vsmart command instead.
Let’s check from the client machine that NAT works:
CSR01#show ip nat translation
Pro Inside global Inside local Outside local Outside global
tcp 21.1.1.2:5064 192.168.11.10:62121 15.15.15.10:80 15.15.15.10:80
This blog post describes configuring a site-to-site IPsec VPN tunnel from a Cisco SD-WAN IOS-XE-based router to a non-SD-WAN device.
How to enable configure Cisco SD-WAN IPsec Tunnels to a non-SD-WAN device? In Cisco SD-WAN template-based deployment, IPsec tunnels are configured via the Cisco VPN Interface IPsec feature template. This template is then applied to the Transport VPN (0) or one of the Service VPNs.
Cisco SD-WAN IPSec Tunnels Step-by-step
The logical elements required to be configured shown in Figure 1. All pre-configured elements have check mark symbols next to them.
In our example, the edge device has a device template attached with basic configuration applied, such as system and transport interfaces, sufficient for the router to have control connections to the controllers.
The device template uses a service VPN, which is described by the Cisco VPN feature template. This type of template, despite its name, is not related to IPsec VPN settings. Cisco VPN feature template defines VRF settings and is a container for routing and participating interface information. In our example, the user-facing interface is assumed to be configured and associated with the VRF.
While it is possible to configure all child templates from within the device template, in our example, we will pre-configure child feature templates first and then select them in the device template.
Create and Configure Cisco VPN Interface IPsec Feature Template
The first two steps deal with configuration of IPsec feature template.
Step 1. Create feature template
Select Configuration section of the side menu
Click on Templates
Click on the Feature tab
Click on Add Template button
Select model of devices that this feature template will be applied
Select Cisco VPN Interface IPsec
Step 2. Configure feature template
Customize IPSec tunnel parameters. There are 5 sections in IPsec template:
Basic configuration, such as name and IP address of the tunnel interface and its underlying source (local router) and destination (remote router)
Dead-peer detection settings
IKE or Phase 1 parameters
IPSEC or Phase 2 parameters
Advanced Settings
SD-WAN requires an IP-numbered interface (/30) and supports route-based tunnels known as VTI (Virtual Template Interface) in Cisco IOS documentation.
Instead of specifying interesting traffic using ACL known as policy-based tunnels, route-based tunnels use static or dynamic routing over a tunnel interface.
As figure 4 shows, there are various options available for both IKE and IPSEC security parameters. These need to match between tunnel endpoints.
Adjust device template to use IPsec Feature Template
Step 3. Add feature template to the device template.
IPsec interface template can now be attached to the service VPNs. Figure 6 shows how to modify the existing device template.
Routing Configuration
Step 4. Set-up routing over the tunnel. This can be static or dynamic-routing protocol-based. In the screenshot below, the static route configuration is shown.
Step 5. Test the tunnel.
As the tunnels are VTI-based and have Layer 3 addresses on both sides, the simplest test is to ping the remote side of the tunnel.
There is limited information available via real-time monitoring using vManage web interface. Native SD-WAN tunnels are also IPSec-based. These tunnels have centralized authentication and key management done by OMP instead of IKE/ISAKMP protocols used in non-SD-WAN tunnels. Real-time device options that contain string IKE in their name will be relevant to us in the context of this article.
Using SSH connection to the router these 2 commands can be used to check operational details of the tunnel:
show crypto isakmp sa / show crypto ikev2 sa
show crypto ipsec sa
We will demonstrate output of these commands in the practical example below.
Cisco SD-WAN IPSec Tunnels Example
Now it’s time for a practical example. We will establish an IPsec tunnel to a Cisco IOS-XE router configured to match VPN gateways settings in public clouds. For example, AWS provides sample configuration files for different platforms (see this URL). We will apply configuration from the Cisco IOS sample, and we can assume that if our router can work with it, it will work with a real AWS gateway. The configuration is slightly adjusted to use IKEv2 by replacing all isakmp commands with IKEv2-variants.
External router configuration
Non SD-WAN router shown on the top in figure 10 has the following configuration:
interface GigabitEthernet2
ip address 5.5.5.10 255.255.255.0
ip route 0.0.0.0 0.0.0.0 5.5.5.1
crypto ikev2 keyring KEYRING-1
peer 21.1.1.2
address 21.1.1.2
pre-shared-key cisco
crypto ikev2 proposal IKE-PROPOSAL-1
encryption aes-cbc-256
integrity sha1
group 16
crypto ikev2 policy IKE-POLICY-1
match address local 5.5.5.10
proposal IKE-PROPOSAL-1
crypto ikev2 profile IKE-PROFILE-1
match address local interface GigabitEthernet2
match identity remote address 21.1.1.2 255.255.255.255
authentication remote pre-share
authentication local pre-share
keyring local KEYRING-1
crypto ipsec transform-set TRANSFORM-SET esp-256-aes esp-sha-hmac
mode tunnel
crypto ipsec profile IPSEC-PROFILE-1
set security-association lifetime kilobytes 102400000
set transform-set TRANSFORM-SET
set ikev2-profile IKE-PROFILE-1
interface Tunnel0
ip address 169.254.23.2 255.255.255.252
ip tcp adjust-mss 1400
tunnel source GigabitEthernet2
tunnel mode ipsec ipv4
tunnel destination 21.1.1.2
tunnel protection ipsec profile IPSEC-PROFILE-1
ip route 192.168.22.0 255.255.255.0 Tunnel0
SD-WAN configuration
We followed the same steps described in the first part of the article to configure vManage. To make it easier to follow, the majority of parameters are hardcoded into the template. In a real deployment, per-device variables can be used to allow for template re-use.
Then the feature template was added to the device template under VPN 1 section (see Figure 6 above) and route to 192.168.15.0/24 was added to VPN 1 feature template (see Figure 8).
Testing and Validation
Let’s assume that we have access only to the SD-WAN router, and testing will be done only from one side of the connection. We will use the router’s command-line interface via SSH from the vManage web console, as it gives access to information not available via the web interface.
The first test that we perform is checking if the remote side of the tunnel is reachable. The “vrf 1” parameter makes sure that the router uses the correct interface.
CSR01#ping vrf 1 169.254.23.2
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 169.254.23.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/1 ms
CSR01#
If ping responses are not received, we can run “show crypto ikev2 sa” and “show crypto ipsec sa” commands. The first command displays if the IKEv2 security association is established, which is a prerequisite for IPSEC security associations. The troubleshooting should start here. If IKEv1 is used, the command is “show crypto isakmp sa.”
CSR01#show crypto ikev2 sa
IPv4 Crypto IKEv2 SA
Tunnel-id Local Remote fvrf/ivrf Status
1 21.1.1.2/500 5.5.5.10/500 none/1 READY
Encr: AES-CBC, keysize: 256, PRF: SHA1, Hash: SHA96, DH Grp:16, Auth sign: PSK, Auth verify: PSK
Life/Active Time: 86400/545 sec
IPv6 Crypto IKEv2 SA
We were running ping of the tunnel interface in our example, which is directly connected to both routers. This test might be successful; however, the connectivity between devices behind the tunnel gateways may still not work.
In this case, we can use the “show crypto ipsec sa” command. It displays a set of counters for the number of encrypted and decrypted packets.
If the encrypted packets count is not increasing, that usually suggests a local routing problem when traffic is not being sent out of the tunnel interface.
If the encrypted packets count does increase but decrypted doesn’t, it can mean that the remote router has routing misconfiguration.
There are some useful debug commands available, such as “debug crypto ikev2”. It can generate extensive output on a router with multiple tunnels, so be careful not to overload the production router. In the example below, we’ve changed the key on the other side of the tunnel to break the tunnel. Auth exchange failed message is logged, suggesting that we have mismatched keys and “show crypto ikev2” will not display any tunnels.
CSR01#debug crypto ikev2
Payload contents:
VID IDi AUTH SA TSi TSr NOTIFY(INITIAL_CONTACT) NOTIFY(SET_WINDOW_SIZE) NOTIFY(ESP_TFC_NO_SUPPORT) NOTIFY(NON_FIRST_FRAGS)
*Jul 10 00:46:36.630: IKEv2:(SESSION ID = 2,SA ID = 1):Sending Packet [To 5.5.5.10:500/From 21.1.1.2:500/VRF i0:f0]
Initiator SPI : EE7E2D729412F370 - Responder SPI : B37D8CA8BAB8C150 Message id: 1
IKEv2 IKE_AUTH Exchange REQUEST
Payload contents:
ENCR
*Jul 10 00:46:36.633: IKEv2:(SESSION ID = 2,SA ID = 1):Received Packet [From 5.5.5.10:500/To 21.1.1.2:500/VRF i0:f0]
Initiator SPI : EE7E2D729412F370 - Responder SPI : B37D8CA8BAB8C150 Message id: 1
IKEv2 IKE_AUTH Exchange RESPONSE
Payload contents:
NOTIFY(AUTHENTICATION_FAILED)
*Jul 10 00:46:36.633: IKEv2:(SESSION ID = 2,SA ID = 1):Process auth response notify
*Jul 10 00:46:36.633: IKEv2-ERROR:(SESSION ID = 2,SA ID = 1):
*Jul 10 00:46:36.633: IKEv2:(SESSION ID = 2,SA ID = 1):Auth exchange failed
*Jul 10 00:46:36.633: IKEv2-ERROR:(SESSION ID = 2,SA ID = 1):: Auth exchange failed
*Jul 10 00:46:36.633: IKEv2:(SESSION ID = 2,SA ID = 1):Abort exchange
*Jul 10 00:46:36.633: IKEv2:(SESSION ID = 2,SA ID = 1):Deleting SA
CSR01# show crypto ikev2 sa
CSR01#
And finally we can perform end to end test from the test machines using ping and tracert commands.
CCNA Exam (200-301) blueprint includes only a single dynamic routing protocol – OSPF (Open Shortest Path First).
The protocol is simple to enable. The basic configuration of OSPF requires only a couple of commands. However, to understand how the protocol works an exam candidate must learn OSPF components, some of them are complex. CCNA exam tests knowledge of OSPF operation in a single-area network. Multi-area components are covered in CCNP-level exams.
Routing protocols help routers to exchange reachability information and calculate the best path to the remote networks. In this blog post, we will explain how OSPF routers perform these tasks.
CCNA Exam blueprint at the time of writing comprised of the topics listed below.
The exam expects knowledge of the following facts about OSPF:
OSPF is a link-state routing protocol
OSPFv2 is the current version for IPv4; IPv6 is supported by OSPFv3
OSPF uses IP protocol number 89
2 multicast groups are reserved and used for some of the OSPFv2 protocol messages – 224.0.0.5 (AllSPFRouters) and 224.0.0.6 (AllDRRouters)
OSPF on Cisco devices has an administrative distance of 110
Overview and Basic Configuration
OSPF builds a link-state database (per area), which contains information about routers, their interfaces, and networks. The database content is synchronized across all routers.
Each router applies the Shortest Path algorithm to the database. As the result, the loop-free tree of the most efficient paths is derived. The router performing calculation is at the root of the tree having paths to every other router and network.
Initial OSPF configuration on a Cisco router uses 2 parameters:
Process ID
Router ID
Process ID
OSPF configuration starts with enabling it globally using “router ospf <process-id>” command.
The process ID is a locally significant number and doesn’t have to be the same on different routers in the network. It is possible to start several independent OSPF processes on a router, which will be assigned different process IDs.
The example below enables the OSPF process with an ID of 100 on a router. Basic router configuration, such as the assignment of IP addresses to interfaces, is omitted.
After OSPF is enabled, “show ip ospf” command confirms that the process is started.
Router# show ip ospf
Routing Process "ospf 100" with ID 10.10.10.2
<output is truncated>
Router ID
Router ID provides an identifier for an OSPF router in the form of an IPv4 address, which doesn’t need to be reachable by other OSPF routers and is not used in data forwarding. Ensure that the router ID is unique across the network. Router ID associates information with the router generating it. It is also used in multiple election processes as a tie-breaker.
As Figure 1 shows Router ID is part of the OSPF header and effectively part of every OSPF packet that the router generates.
By default, the OSPF process will automatically assign Router ID by selecting the highest IP address of a loopback interface on the router. If there are no loopback interfaces available, then the highest IP address of a non-loopback interface is selected. As shown in Figure 2, the router has 2 physical and 2 loopback interfaces configured. Numbers are shown next to the interface name in green display the priority of interfaces for the purpose of Router ID selection.
“show ip ospf” output from the example above demonstrates that the router ID was selected to match the highest IP address of a loopback interface (10.10.10.2). The example also demonstrates that candidate interfaces for router ID selection don’t have to run OSPF.
Setting Router ID manually is a recommended best practice, that ensures that IDs are allocated to OSPF speakers in a pre-determined manner.
Let’s change router ID manually to 10.0.0.1.
Router(config)# router ospf 100
Router(config-router)# router-id 10.0.0.1
% OSPF: Reload or use "clear ip ospf process" command, for this to take effect
Router ID change requires the process restart. It will disrupt the packet flow, so it should be planned for in the production environment. To confirm that router ID is now adjusted let’s clear the OSPF process and then execute “show ip ospf” command.
Router# clear ip ospf 100 process
Reset OSPF process 100? [no]: yes
Router# show ip ospf
Routing Process "ospf 100" with ID 10.0.0.1
<output is truncated>
Link-State View of the Network
This section introduces some important concepts that will help to understand link-state advertisements (LSAs), the algorithm, and neighbor adjacencies described later in the article.
To visualize how OSPF sees a network, let’s use a sample network topology shown in Figure 3. All routers and networks are part of the same area.
Network Types
If more than 2 routers can attach to a network, it is a multi-access network, which can be divided into 3 subtypes:
Broadcast multi-access
Non-broadcast multi-access
Point-to-multipoint
A network connecting a maximum of 2 routers classified as a point-to-point network. It can be a physical point-to-point technology, or a multi-access network, such as Ethernet, administratively configured as point-to-point.
Only point-to-point and broadcast networks are listed in the blueprint of the CCNA exam. These types are commonly used and routers can auto-discover each other without any additional configuration.
For demonstration purposes, assume that yellow links (X-A, X-B, A-B) are point-to-point and blue links (A-C, B-D, C-D-Z) are multi-access broadcast networks in the sample topology shown in Figure 3.
OSPF database describes a network as a directed graph, with routers and subnets as vertices, connected to each other with the directional edges.
Let’s first re-draw the diagram displaying only routers and subnets as vertices without any connections between them.
Routers are connected bi-directionally to each other over point-to-point links, i.e. not connected via subnet vertices. We will explain how numbered point-to-point subnet vertex is connected to the routers in the next step. For now, these links are introduced between routers:
X -> A, A -> X
X -> B, B -> X
A -> B, B -> A
Transit Networks
Each multi-access broadcast network is a vertex on the graph if there are two or more routers connected to it. Such networks are called a transit and represented by vertices, which connect bi-directionally to the attached routers:
A -> N5, N5 -> A, C -> N5, N5 -> C
B -> N6, N6 -> B, D -> N6, N6 -> D
C -> N7, N7 -> C, D -> N7, N7 -> D, Z -> N7, N7 -> Z
Networks N5 and N6 have only two routers connected in this topology, however, as per our earlier assumption, the underlying data link is a multi-access broadcast network, such as Ethernet. Therefore, router pairs (A-C) and (B-D) are not connected directly as was the case on point-to-point networks. Instead, they bi-directionally connect to the transit network vertices.
Figure 5 shows the resulting connectivity.
Stub Networks
Finally, N1 and N8 are multi-access broadcast networks with each having only a single router connected. Both are considered to be stub networks and described by unidirectional connections from routers X and Z.
Numbered point-to-point subnets are also represented as stub networks, connected using directional link from each router: X -> N2, A -> N2, X -> N3, B -> N3, A -> N4, B -> N4. Point-to-point networks are not transit vertices, which is different to broadcast multi-access networks (N5, N6, and N7).
One of the reasons for this is that the physical point-to-point links can be unnumbered (when there are no IP addresses assigned to both sides), in which case no network vertex exists. Also, physical point-to-point links can have IPs allocated from different subnets on each side of the connection. In this case, each router has a unidirectional connection to the IP address on the other side, which are also represented as stubs.
The summary of new connections:
X -> N1
X -> N2, A -> N2
A -> N4, B -> N4
X -> N3, B -> N3
Z -> N8
Interface Cost
OSPF uses cumulative cost as the metric to compare multiple paths to the same destination. Figure 7 shows an updated diagram with associated costs displayed next to each directional edge. The cost for each vertex is calculated in the outbound direction.
Cisco routers calculate cost by dividing reference bandwidth by interface bandwidth. Consider that the reference bandwidth is 100Mbps. Interfaces of 100Mbps and higher will have a cost of 1. 10Mbps interface is 10-times slower than 100Mbps, so it will be assigned a cost of 10.
The cost value can also be manually specified using “ip ospf cost <cost-value>” interface command. As each connection between routers is represented by 2 directional edges, the cost doesn’t have to match on each side of the link. While routers connected over point-to-point links usually should have the same cost, edges from transit networks always have the cost of 0 (for example, N5 -> A).
Reference Bandwidth
As mentioned in the previous section, Cisco routers use reference bandwidth to calculate interface cost. “show ip ospf” command displays the reference bandwidth, which has default value of 100Mbps:
Router#show ip ospf
<output is truncated>
Reference bandwidth unit is 100 mbps
The virtual router that we are using in this lab has Gigabit interfaces, however, as the default reference bandwidth is 100Mbps, all interfaces with a speed higher than 100Mbps have the cost of 1.
The reference bandwidth should be adjusted on all routers in the network to match the highest bandwidth interface in the network.
Selecting Best Path
The best path within the area is calculated by each router applying the Dijkstra algorithm to its link-state database. A simplified overview of the algorithm is presented below. For more detailed information, refer to the RFC (https://tools.ietf.org/html/rfc2328#page-161).
The algorithm starts with a vertex representing the router performing the calculation. The distance to directly adjacent vertices (i.e. other routers or transit networks) is calculated and recorded in a candidate list.
The algorithm then changes the focus to the closest vertex from the candidate list. Its adjacent non-visited vertices are added to the candidate list along with their distances. The current vertex is now considered to be visited. It is removed from the candidate list and added to the shortest path.
The algorithm goes through the updated candidate list and selects the closest vertex. The process in the previous paragraph repeats till there will be no unvisited vertices left – as the result of the algorithm all reachable vertices will be added to the shortest-path tree.
After distance to all routers and transit networks is known, distances to stub networks are added via the corresponding router.
Neighbors and Adjacencies
Hello Protocol
Hello protocol is responsible for 2 tasks:
Neighbor discovery and establishment of bidirectional communication
Designated and Backup Designated Routers election on a broadcast multi-access network
OSPF routers automatically discover each other by periodically sending multicast Hello packets. On broadcast and point-to-point networks routers send Hello packets to the AllSPFRouters multicast group address (224.0.0.5).
The format of Hello packet is shown in Figure 8.
A router receiving any OSPF packet, including Hello packets, checks that Area is the same as locally configured on the router and that the authentication parameters are correct.
Then Hello-specific parameters are validated. Fields listed in the first line of the Hello packet must match between two routers to establish bidirectional communication:
Network mask must match on multi-access networks, however, is not being compared on point-to-point links.
Hello and Router Dead Intervals (in seconds) specify how often Hello packets are sent and how long other routers should wait for a Hello packet before declaring advertising router dead.
Options include a flag called E-bit. When this flag is set, the area is capable of processing External routing information, i.e. is not a stub. This flag must match between neighbors too.
Routers include a list of neighbors on the same network segment if they have received Hello packets from them. If a router sees itself in the list of neighbors from another router it knows that bidirectional communication is established.
Neighbors go through series of states as part of Hello protocol.
Down is a state when 2 neighbors haven’t seen or stopped receiving Hello packets from each other.
In Attempt state, available only in NBMA (Non-Broadcast Multi-Access) networks, no Hello packets were received from a manually configured neighbor. The local router sends periodical unicast Hello packets to a such neighbor.
Init state means that a Hello packet has been received from the neighbor, but the router hasn’t seen itself in the list of the neighbors.
In the 2-Way state, the router receives Hello packets from the neighbor. The local router appears in the Neighbors field of these Hello packets.
Hello protocol responsibilities end when neighbors achieve the 2-Way state. Only valid neighbors will be able to reach the 2-Way state. Further stages are controlled by the Database Exchange process and routers progressing past 2-Way are referred to as adjacent routers.
On point-to-point networks, valid neighbors always become adjacent. However, on multi-access networks adjacency is established in a dual-hub-and-spokes fashion. Hubs are called a Designated Router (DR) and Backup Designated Router (BDR).
DR and BDR on Multi-Access Broadcast networks
Designated Router and Backup Designated Routers are elected on multi-access broadcast networks to decrease the number of network adjacencies required to be built (full-mesh vs dual-hub-and-spokes).
The election is based on configurable router’s interface priority and the highest router ID serves as a tie-breaker. Numerically higher priority wins. If it is set to 0, the router is not eligible to become a DR or BDR.
Hello protocol facilitates the election process by having 3 fields within the Hello packet – DR, BDR, and Router priority. If a router joins a network and receives packets with DR and BDR populated, it will not initiate the election process even if it has a better priority. This behavior is described as being non-preemptive.
Designated Router has also an important purpose – it originates Network Link State Advertisements (LSAs) representing transit network. We will discuss LSAs after we review the next stages that lead to adjacency – Database Exchange.
Database Exchange
Neighbors that have established bidirectional communication can start a process to form OSPF adjacency and synchronize their databases. As mentioned previously, routers on point-to-point links always become adjacent and routers on multi-access networks become adjacent only with DR and BDR routers.
Routers progress through a set of states before reaching a fully synchronized state:
In the Exstart state, routers decide which router will be responsible for managing the database synchronization process. Router with the highest Router ID performs the master role and its neighbor operates as a slave. OSPF Database Description packets describe LSAs that constitute each router’s database. If either neighbor sees missing or newer LSA, it will add it to the Link State Request list.
By reaching Exstart state, the routers have already progressed through all Hello protocol stages and most of the protocol parameters are found to be compatible. During the Exstart stage, theDatabase Description packet MTU field is compared with the receiving router’s interface MTU. If it doesn’t match on both sides of the adjacency, one of the routers will drop the Database Description packets. This will prevent progressing to the next stages. The behavior can be disabled on Cisco routers.
During Exchange state routers describe their link state databases by exchanging Database Description packets. The Master increments sequence numbers and waits for the Slave to acknowledge the last sequence number received from the Master.
In Loading state routers send each other Link State Request packets asking the neighbor to send LSAs that were discovered during Exchange state.
Routers in Full state are fully adjacent and have synchronized their Link State Database.
Link State Advertisements
Link State Advertisements (LSAs) describe router and network state. As reviewed in the Link-State View of the Network section earlier, OSPF sees a network as a graph of vertices connected to each other. Different types of LSAs correspond to different types of vertices, for example, a router LSA is a representation of a router vertex and a network LSA – of a transit network vertex.
We will discuss only intra-area types of LSAs (Router and Network) in this blog post. There are also other types of LSAs that exist describing inter-area and external destinations.
All LSAs share the same header. Some fields can have different values depending on the LSA type. LSA header comprises of (some of the fields are omitted in the description below and diagrams):
LSA Type. 1 is Router LSA, 2 is Network LSA
Link State ID. For Router LSA – Router ID, for Network LSA – interface IP address of the Designated Router.
Advertising Router. Router ID of the router originated LSA.
LS Age. In seconds, increments as routers transmit LSA and while it is stored in the database. Used to age out LSAs once they reach MaxAge, after which such LSAs must be re-flooded.
LS Sequence Number. Assigned by the originating router and is used for versioning of LSAs.
Router LSA
Router LSA describes the router’s links. Each link is described by several fields (not all fields are shown in the diagram and the description below):
Link ID. Depending on link type can be neighbor’s Router ID, DR’s IP address, or Network IP address.
Link Data. Depending on link type, identifies the local interface of the router or subnet mask (see mapping in the diagram below).
Network LSA
This LSA describes a multi-access network. Designated Router (DR) generates this LSA and lists all attached OSPF routers on the segment with which it formed an adjacency.
Link State ID in the header is DR’s IP address on the network. The mask is carried as a field with LSA, which makes it possible to identify the network address.
OSPF Packets
Earlier we have explored how OSPF sees the network, how routers describe their links and networks by generating LSAs that are flooded through the area. We also discussed how two routers synchronize their databases by becoming adjacent.
This section provides an overview of different types of packets that OSPF uses to distribute LSAs. Hello packet was introduced in the “Neighbors and Adjacencies” section. Figures 9 to 12 show the remaining types of OSPF packets.
Database Description packets are used during the Database Exchange process. The packet has fields describing interface MTU, various options controlling database exchange process, and sequence numbers. The payload consists of LSA headers, which format we reviewed in the previous section.
The next packet is the Link State Request packet. A router learns missing LSAs from received Database Description packets. To request those LSAs, the router sends a Link State Request packet which contains enough information to identify the LSA. These fields are LS Type, ID, and Advertising Router. The other LSA header fields, such as LS Age and LS Sequence Number, are not included. This means that the router is requesting the most recent version of LSA and not for the specific instance of LSA.
The next 2 packets are Link State Update and Acknowledgement packets. These are used to reliably flood LSAs throughout the network. Link State Update carries a list of full LSAs with their headers.
Link State Acknowledgement packet is used to explicitly confirm the receipt of a Link State Update packet.
Let’s finalize the configuration of our sample network and review different diagnostic commands.
OSPF Configuration and show commands
In this section, we will enable OSPF on different types of network interfaces using the sample topology we used earlier.
Point-to-Point Interfaces
Let’s enable OSPF between X, A, and B. In this topology, a Layer 3 LAN switch X connects to two WAN routers (A and B), which are also connected to each other.
Switch X configuration is shown in the listing below.
X(config)#router ospf 100
X(config-router)#network 172.16.100.0 0.0.0.3 area 0
X(config-router)#network 172.16.100.4 0.0.0.3 area 0
X(config-router)#network 10.0.0.0 0.0.0.255 area 0
network command’s purpose is to identify interfaces that will have OSPF running and which area they will be placed in. The command uses a wildcard mask, which reverses the logic of the subnet mask. In a wildcard mask, binary 0 means “match” and 1 means “ignore”.
As subnet masks use consecutive 1s followed by consecutive 0s, it can be easily converted to wildcard mask by subtracting mask value from 255.255.255.255. For example, the hostmask of 255.255.255.255 converts to a wildcard mask of 0.0.0.0.
It is possible to use a less specific wildcard mask with a network command to match multiple interfaces with a single statement. For example, instead of the 3 commands above, we could use “network 0.0.0.0 255.255.255.255 area 0”, which would enable OSPF on all interfaces and place them into area 0.
Some data-links technologies are physically point-to-point and some of them are not. As we use Ethernet in this topology, which, by default, is treated as a multi-access network additional OSPF command is required, as shown in the listing below:
There is also an alternative way to enable OSPF on interfaces available in Cisco IOS-XE. Instead of performing configuration under the OSPF process, the interface-level mode can be used. Commands in OSPF process mode are still required for global parameters, such as setting router ID. The listing below demonstrates configuration on router A, a similar configuration is also applied to router B.
“show ip ospf interface” command provides relevant to OSPF interface information. The network type of both interfaces is set to point-to-point with the cost of 1.
The next important information in the output below is the OSPF timers value. Hello timer defines how often Hello messages are sent and Dead interval specifies when the router will declare another one as dead without receiving hello messages. The values are automatically selected based on the network type or can be manually configured. Timers must match between neighbors.
In the example, hello and dead intervals have default values of 10 and 40.
X#show ip ospf interface
GigabitEthernet2.12 is up, line protocol is up
Internet Address 172.16.100.1/30, Interface ID 13, Area 0
Attached via Network Statement
Process ID 100, Router ID 10.0.0.1, Network Type POINT_TO_POINT, Cost: 1
<output truncated>
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
<output truncated>
Neighbor Count is 1, Adjacent neighbor count is 1
Adjacent with neighbor 10.0.255.1
GigabitEthernet2.13 is up, line protocol is up
Internet Address 172.16.100.5/30, Interface ID 14, Area 0
Attached via Network Statement
Process ID 100, Router ID 10.0.0.1, Network Type POINT_TO_POINT, Cost: 1
<output truncated>
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
<output truncated>
Neighbor Count is 1, Adjacent neighbor count is 1
Adjacent with neighbor 10.0.254.1
Interfaces were added using the router process “network <x> area <y>” configuration command, and this is indicated by the “Attached via Network Statement” line.
On routers A and B we used alternative configuration on the interface – “ip ospf <x> area <y>“. On these routers “Attached via Interface Enable” would be displayed instead.
“show ip ospf neighbors” command displays information about neighbors. Neighbor ID displays Router ID, and address specifies IP address of network interface over which neighbor is reachable. On point-to-point networks, neighbors always become adjacent and should be in FULL state. Because DR and BDRs are not elected on point-to-point networks priority value of 0 is set for both neighbors.
Deadtime is a count-down timer, which starts at 40 seconds and in normal conditions will not drop below 30 seconds, as hello packets are transmitted every 10 seconds.
X#show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
10.0.254.1 0 FULL/ - 00:00:34 172.16.100.6 GigabitEthernet2.13
10.0.255.1 0 FULL/ - 00:00:39 172.16.100.2 GigabitEthernet2.12
Broadcast Multi-Access Network Interfaces
Let’s now finalize the configuration of the network topology by enabling connections between WAN routers (A <> C, B <> D), and connectivity between WAN routers C, D, and a switch Z.
The commands used for the configuration are similar to the ones shown in the previous sections. All remaining network connections are broadcast multi-access networks, which is the default OSPF network type on Ethernet interfaces. We will omit the configuration from the previous examples that set the network type to point-to-point.
Earlier, we used interface-based configuration on routers A and B. We will apply interface-level commands for additional interfaces.
A
interface Gi2.24
ip ospf 100 area 0
B
interface Gi2.35
ip ospf 100 area 0
For the remaining routers, we will use the router process-based configuration. For demonstration purposes, we will set router IDs as some random values to demonstrate that these addresses are neither required to be reachable over OSPF nor belong to any of the router’s interfaces. And instead of specifying individual network statements for each interface, we will use 1 wide statement that will enable OSPF on all interfaces at once.
C
router ospf 44
router-id 4.4.4.4
network 0.0.0.0 255.255.255.255 area 0
D
router ospf 55
router-id 55.55.55.55
network 0.0.0.0 255.255.255.255 area 0
Z
router ospf 66
router-id 66.6.6.6
network 0.0.0.0 255.255.255.255 area 0
The next example shows “show ip ospf interface” command output on router Z. Both interfaces have OSPF network type of broadcast, which is the default for Ethernet. A manually configured router ID of 66.6.6.6 is also displayed.
Z#show ip ospf interface
GigabitEthernet2.456 is up, line protocol is up
Internet Address 10.0.2.2/29, Interface ID 12, Area 0
Attached via Network Statement
Process ID 66, Router ID 66.6.6.6, Network Type BROADCAST, Cost: 1
<output truncated>
Transmit Delay is 1 sec, State DR, Priority 1
Designated Router (ID) 66.6.6.6, Interface address 10.0.2.2
Backup Designated router (ID) 55.55.55.55, Interface address 10.0.2.3
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
<output truncated>
Neighbor Count is 2, Adjacent neighbor count is 2
Adjacent with neighbor 4.4.4.4
Adjacent with neighbor 55.55.55.55 (Backup Designated Router)
GigabitEthernet2.2 is up, line protocol is up
Internet Address 10.0.3.1/24, Interface ID 11, Area 0
Attached via Network Statement
Process ID 66, Router ID 66.6.6.6, Network Type BROADCAST, Cost: 1
<output truncated>
Transmit Delay is 1 sec, State DR, Priority 1
Designated Router (ID) 66.6.6.6, Interface address 10.0.3.1
No backup designated router on this network
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
<output truncated>
Neighbor Count is 0, Adjacent neighbor count is 0
“State DR” means that the router performs the role of the Designated Router on the network segment. Backup DR will have a state listed as BDR, and all other routers will be in DROTHER state. “Priority 1” is the default priority, so the router with the highest Router ID is elected as DR if all routers start at the same time. As the process is not preemptive, the role of DR can be performed by the router with a smaller priority or Router ID value if it starts before other routers.
Information about Designated Router and Backup Designated Routers is displayed next, followed by Hello and Dead timer settings.
The last lines of output list information about neighbors and adjacencies on the interface. Both DR and BDR become adjacent with all neighbors on the network. Routers that are neither DR nor BDR will display all routers on the segment as neighbors, however, establish adjacencies only with DR and BDR.
Link State Database
In this section, we will explore the link state database on router Z.
“show ip ospf database” command displays the content of the database. For the purpose of CCNA exam preparation, the example focuses on a single-area topology.
Z#show ip ospf database
OSPF Router with ID (66.6.6.6) (Process ID 66)
Router Link States (Area 0)
Link ID ADV Router Age Seq# Checksum Link count
4.4.4.4 4.4.4.4 64 0x80000014 0x00EFCE 2
10.0.0.1 10.0.0.1 1655 0x80000005 0x00F639 5
10.0.254.1 10.0.254.1 116 0x8000000A 0x00B55B 5
10.0.255.1 10.0.255.1 336 0x80000007 0x00DE3B 5
55.55.55.55 55.55.55.55 64 0x80000011 0x00B077 2
66.6.6.6 66.6.6.6 208 0x8000000C 0x0071D4 2
Net Link States (Area 0)
Link ID ADV Router Age Seq# Checksum
10.0.2.1 4.4.4.4 209 0x80000002 0x00C617
10.0.254.1 10.0.254.1 300 0x80000001 0x00C27F
10.0.255.1 10.0.255.1 1730 0x80000002 0x00B753
Router LSA
Each router generates a Router LSA, with Link ID matching the generating router’s ID. 6 LSAs are displayed matching number of routers in our topology. To understand link count, review the previous section called “Link-State View of the Network” and Figure 6, where each outbound arrow from a router is counted as a link.
For example, let’s review in detail the content of router LSA with ID 10.0.255.1 (Router A). Below is part of Figure 6 focusing on router A.
“show ip ospf database router <router-id>” command displays detailed information about router LSA. As the link-state database is the same on all routers we can gather output on any routers in the same area. In the example below, the command is launched on router Z.
Z#show ip ospf database router 10.0.255.1
OSPF Router with ID (66.6.6.6) (Process ID 66)
Router Link States (Area 0)
LS age: 142
Options: (No TOS-capability, DC)
LS Type: Router Links
Link State ID: 10.0.255.1
Advertising Router: 10.0.255.1
LS Seq Number: 80000006
Checksum: 0xE03A
Length: 84
Number of Links: 5
Link connected to: a Transit Network
(Link ID) Designated Router address: 10.0.255.1
(Link Data) Router Interface address: 10.0.255.1
Number of MTID metrics: 0
TOS 0 Metrics: 1
Link connected to: another Router (point-to-point)
(Link ID) Neighboring Router ID: 10.0.254.1
(Link Data) Router Interface address: 172.16.100.9
Number of MTID metrics: 0
TOS 0 Metrics: 1
Link connected to: a Stub Network
(Link ID) Network/subnet number: 172.16.100.8
(Link Data) Network Mask: 255.255.255.252
Number of MTID metrics: 0
TOS 0 Metrics: 1
Link connected to: another Router (point-to-point)
(Link ID) Neighboring Router ID: 10.0.0.1
(Link Data) Router Interface address: 172.16.100.2
Number of MTID metrics: 0
TOS 0 Metrics: 1
Link connected to: a Stub Network
(Link ID) Network/subnet number: 172.16.100.0
(Link Data) Network Mask: 255.255.255.252
Number of MTID metrics: 0
TOS 0 Metrics: 1
The links in the output are shown in the following order:
A -> N5 (A is BDR on this network, so the output displays its own IP address as DR)
A -> B (A has point-to-point connectivity to B over N4; this is described by this link and additional link from A to N4 listed below)
A -> N4 (numbered subnet for the point-to-point link is represented as a connection to a stub network)
A -> X
A -> N2
Network LSA
The next example focuses on the network LSA which represents a transit network. To display network LSA, run “show ip ospf database network <id>” command. For this example, we will use the N7 network (10.0.2.0/29) connecting routers C, D, and Z.
Network LSA ID matches the IP address of Designated Router (router Z) on this network and it lists router IDs of attached routers. The output shows routers Z, C, and D as attached to N7.
Z#show ip ospf database network 10.0.2.2
OSPF Router with ID (66.6.6.6) (Process ID 66)
Net Link States (Area 0)
LS age: 1435
Options: (No TOS-capability, DC)
LS Type: Network Links
Link State ID: 10.0.2.2 (address of Designated Router)
Advertising Router: 66.6.6.6
LS Seq Number: 80000002
Checksum: 0x7325
Length: 36
Network Mask: /29
Attached Router: 66.6.6.6
Attached Router: 4.4.4.4
Attached Router: 55.55.55.55
Network mask (/29) is also stored as part of the network LSA, which together with Link State ID represented by DR’s IP address can be used to obtain network IP prefix – 10.0.2.0/29.
represented by DR’s IP address can be used to obtain network IP prefix – 10.0.2.0/29.
Self-Test Questions
How OSPF router ID is selected if it's not manually configured?
The highest IP address on a loopback interface. If there are no loopback interfaces, select the highest IP address assigned to a physical interface.
What OSPF uses to compare multiple paths to a destination?
By combining costs of interfaces through each path. Each interface’s cost reflects how many times its bandwidth is smaller than a reference bandwidth. If interface speed is faster or the same as the reference value, then 1 is used as cost.
What is the difference between neighbors and adjacent routers?
Neighbors are the router that can communicate with each other and have matching parameters. Adjacency is formed between neighbors for the purpose of exchanging routing information. On multi-access networks, some of the neighbors don’t establish adjacency between each other.
What are 2 main tasks of OSPF Hello protocol?
Neighbor discovery and DR election
Explain what is router and network LSAs?
Link State Advertisement is a unit of information that is stored in each router’s Link State Database. Each router LSA represents a router and its links. Network LSA describes a transit network and lists routers connected to it.
In this blog post, we will discuss the JavaScript Object Notation (JSON) data format. The target audience is CCNA and CCNP candidates preparing for the exams.
The content provides fundamental overview of the following topics:
CCNA exam
6.7 Interpret JSON encoded data
CCNP ENCOR exam
6.2 Construct valid JSON encoded file
JSON Overview
JSON is an open standard text-based file format to store and exchange serialized data. Serialization is the process of converting an object into a format that can be stored or transported to later recreate it.
JSON was originally derived from JavaScript, however, many other programming languages can interpret and generate JSON data. Figure 1 shows how JSON components fit together.
JSON text can represent one of the following values (orange and blue circles):
String
Number
Literal name (false, true, null)
Array
Object
JSON simple values
Strings, numbers, and literals
The simple values can represent some text or number and cannot contain other values. For example, below are examples of valid JSON texts:
Listing 1
"I'm a JSON"
100
true
null
As per RFC 8259, JSON text can be represented by any serialized value. Some specifications of JSON require that valid JSON text must be an object or an array.
Note that the string values must be enclosed in quotation marks.
JSON structured data values
Structural characters
JSON values that represent structured data (blue circles) created using 6 structural characters listed below:
Square brackets [] – beginning and end of an array
Curly brackets {} – beginning and end of an object
Colon : – Name separator
Comma , – Value separator
JSON allows the use of whitespaces, such as spaces, tabs, and new lines to format the text for readability. Contrasted to Python, indentation is used only for readability.
Array
An array contains zero or multiple ordered elements. Elements don’t have to be of the same type.
Listing 2
[ "abc", 23, null ]
Object
An object contains zero or multiple members, separated by commas. Each member is in the name: value format. Name must be unique within an object.
Arrays and objects can contain both simple values, other arrays, and other objects.
For instance, below is the object, as we can see it starts with an opening curly brace. The object contains 2 members with name tags of “primary_address” and “secondary_address”. Each of the member’s value is another object that consists of 2 more members, named “address” and “mask”.
Let’s create an array that will contain 2 objects representing addresses. The opening square bracket starts the definition of an array. Then we wrap each of the members from the previous example into curly brackets to create an object, as array stores elements – not members consisting of name: value pairs.
In one of the previous blog posts dedicated to REST API, we’ve programmatically extracted a JSON representation of an interface from the IOS-XE router. This listing below shows several router’s interfaces, so we can have some arrays in the example.
Let’s interpret this document. Figure 2 shows the structure of the JSON code from the example above.
The top-level object (#1) has a single member with the name of “Cisco-IOS-XE-native:interface”. This member’s value is another object (#2).
The object #2 also has a single member named “GigabitEthernet”, whose value is an array (#3).
Array contains 2 elements – object #4 and object #5.
Object #4 has 4 members, with the following names:
“name”
“ip”
“mop”
“Cisco-IOS-XE-ethernet:negotiation”
Member called “name” has a string value of “1”. The next member named “ip” has an object (#6) as a value. Object #6 has a single member with the name of “address” having another object (#7) as a value.
The pattern of finding array elements and object members should be apparent by now.
How to construct JSON encoded data
Online Tools
The easiest way to create a JSON encoded data is to use one of the available online JSON editors. For example, one is available via this URL. It automatically checks JSON file syntax, which can be useful to find a missing bracket. The other feature of this tool is the ability to auto-format code into a compact format or full format (with line breaks and indentation, as shown in the previous example).
The screenshot of the tool with JSON text from the previous example is shown below.
Python Collections Overview
To continue with the following examples, we recommend checking this article (URL) for a brief quick start and Python installation instructions.
Let’s discuss several Python fundamental topics before proceeding with the practical examples.
Data Structures: lists and dictionaries
Lists and dictionaries are examples of collections in Python. Python’s JSON module maps lists to JSON arrays, and dictionaries to JSON objects.
The syntax is identical between matching pairs of data structures, as shown in Figure 4.
The listing below shows an example of a list and a dictionary definition in Python.
A list is defined in Python using square brackets. Python uses None instead of null literal in JSON.
The dictionary is wrapped with curly brackets and has familiar from JSON example syntax. JSON’s name tag (value just before the colon) corresponds to a dictionary key in Python. It is followed by a colon and a value, which is in our example a string.
We will save and read JSON files to and from a file saved on the disk in the next examples.
To open a file for read access in Python the following code is used:
Listing 12
with open("json_test.json","r") as json_file:
… some code that makes use of json_file
To open the same file for write access, use “w” instead of “r” as a parameter for the open() function. Use of keyword “with” ensures that the file is properly closed after the use.
Decoding JSON in Python example
Python module called json provides JSON encoding and decoding capabilities. There are 2 methods performing these functions:
dumps – Python data structure to JSON text
loads – JSON text into Python data structure
Let’s create a text file containing JSON text from Listing 6 and save it as json_ios_xe.json.
As the next step, we will create a file named json_example.py that will have the following Python code in it.
Listing 13
import json
with open("json_ios_xe_interfaces.json", "r") as json_file:
json_file_content = json_file.read()
decoded_json = json.loads(json_file_content)
print(decoded_json)
print()
print(type(decoded_json))
Line #1 imports json module, so we can use its feature in our code.
The code in line #3 opens our file for read-only access. The access to the file content is provided via json_file variable. The code in line #4 reads-in content of the file into a string variable.
Line #5 uses json.loads() function to read the string representation of JSON text. The returned value is assigned to the decoded_json variable. As the JSON text is a JSON object, the decoded_json object will be a Python dictionary.
Line #7 prints the Python dictionary, followed by an empty line created by line #8. Finally, line #9 prints out the type of decoded_json object, so we can validate that it is in fact a Python dictionary.
In this example, we will use the dictionary created in the previous example, change the IP address to “192.168.7.5” and will encode it as another JSON file.
The first task is to identify the full path to the IP address. We have several nested layers of hierarchy within the outer-most dictionary. To access inner dictionaries and lists we will append [<index_or_key_name>] to the parent identifier.
In the example above the index of [0] is used, as the ‘GigabitEthernet’ key has the value of a list and we are interested in the first element.
Below is the full listing of a program code that changes the IP address and saves it as a new JSON file on the disk.
Listing 16
import json
with open("json_ios_xe.json", "r") as json_file:
json_file_content = json_file.read()
decoded_json = json.loads(json_file_content)
decoded_json['Cisco-IOS-XE-native:interface']['GigabitEthernet'][0]['ip']['address']['primary']['address'] = \
"192.168.7.5"
encoded_json_compact = json.dumps(decoded_json)
encoded_json_indented = json.dumps(decoded_json, indent = 4)
with open("json_ios_xe_compact.json", "w") as json_file:
json_file.write(encoded_json_compact)
with open("json_ios_xe_indented.json", "w") as json_file:
json_file.write(encoded_json_indented)
Line #8 sets the value to a new IP address. Lines #11 and #12 create a string containing JSON text, it passes our modified dictionary called decoded_json to json.dumps() function. The example demonstrates that the named parameter called “indent” can be passed to the dumps() method to perform the formatting of the JSON file.
Line #15 and #18 saving the resulted text to files on the disk.
Let’s run the code and see the result.
Listing 17
c:\PythonExamples>python json_example.py
Two new files are created in c:\PythonExamples folder, as shown in the screenshot below.
Self-Test Questions
List 6 types of value types that JSON text can represent?
String, number, Boolean (false, true), null, array, and object.
Describe JSON array and the process of defining one.
A JSON array contains ordered elements and defined using square brackets. For example, [ “abc”, 23, null ]
Describe JSON object and the process of defining one.
A JSON object contains members separated by a comma. Each member has a name and value separated by a colon. It is defined using curly brackets. For example, { “address”: “192.168.8.1”, “mask”: “255.255.255.255” }
Name Python types that are mapped to JSON's array and object
Python’s list maps to JSON array, and Python’s dictionary maps to a JSON object
What Python's module is responsible for encoding and decoding of JSON-formatted data?
json module. To decode use json.loads() and to encode – json.dumps().
In this blog post, we will provide an introduction to Python components and scripts in the context of Cisco certification. We will show how to get started with Python and explain the most commonly used elements of Python scripts – variables, functions, program flow, conditional logic, and “for” loops.
The content aims to help CCNP/CCIE Enterprise track candidates to prepare for the ENCOR exam, which includes the following topic:
6.1 Interpret basic Python components and scripts
Many CCNP tracks have automation sections that assume some knowledge of Python. DevNet track expects more extensive knowledge in Python.
Python Installation
Python is an interpreted language, which means that the code of a program is not pre-compiled into an executable that contains machine instructions. Python code can be opened and edited with any text editor. Python programs have a .py extension.
To run a Python code an interpreter is required. It reads the code and converts it into machine instructions.
Python is available for different platforms. Python 3.x is the recommended version and we will use it in our examples.
To download Python installation files navigate to this URL. Start the installer.
We use Windows 10 in our examples. Enable the checkbox “Add Python 3.x to PATH” and press Install Now.
Start Windows CLI utility by starting typing “Command Prompt”. Once started type in the following command to confirm that Python interpreter is available.
Microsoft Windows [Version 10.0.18362.836]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\PythonExamples>python --version
Python 3.8.3
Keep the command prompt window opened.
Hello World!
We will start with a simple “Hello World!” example.
Open a text editor, such as Notepad, and type-in the following code:
print("Hello World!")
The example uses a built-in print() function that displays a message on the screen.
Save the file as hello_world.py in a folder on your computer. To run the program, we will pass the full file name to python interpreter:
A variable stores some value, which can be accessed in the code by using its name. In Python, variables are not declared and can be used by assigning a value to them.
Let’s add a few more lines to the hello_world file. The new code creates a line number variable that is changed after each use. First two times it was statically set to 2 and 3, and in the line, before the last, we’ve just incremented its value by 1. The print function is being provided with 2 arguments – descriptive text and the line number variable.
print("Hello World!")
line_number = 2
print("This is the line number", line_number)
line_number = 3
print("This is the line number", line_number)
line_number = line_number + 1
print("This is the line number", line_number)
When the program is launched the following output is displayed on the screen.
C:\PythonExamples>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2
This is the line number 3
This is the line number 4
Functions
A function minimizes the amount of duplicate code. It can also provide better structure and improve the readability of program code, by wrapping related logic under the function definition, which can be called by a descriptive name from other places of the program.
Let’s adjust our program to demonstrate the use of functions.
def line_number_printer(number):
print("This is the line number", number)
def calculate_next_line_number(previous_number):
return previous_number + 1
print("Hello World!")
line_number = 2
line_number_printer(line_number)
line_number = calculate_next_line_number(line_number)
line_number_printer(line_number)
line_number = calculate_next_line_number(line_number)
line_number_printer(line_number)
The program produces exactly the same output as the code in the previous example.
We have introduced 2 functions:
line_number_printer(number)
calculate_next_line_number(previous_number)
Figure 2 shows how the functions are defined and used in the example above. Not all lines from the example are shown for brevity.
Let’s go through the diagram and discuss each element:
A function’s definition must precede its use. The code within the definition is not executed unless it is called.
Function definition starts with a keyword “def”.
The function name should be in lower case with underscore used as a word separator. Python’s style guide is called PEP 8. It explains different elements of style, such as the naming convention and how the code must be formatted (https://www.python.org/dev/peps/pep-0008).
A function can accept a value as an input in the form of parameter. Variable name in parentheses stores value supplied when the function was called. This variable is available for use within the function body.
The line containing function definition ends with a colon showing that function statements will follow in the next lines.
The code statements within a function are indented. PEP 8 recommends the use of spaces for indentation instead of tabs. Also, 4 spaces should separate each indentation level.
A function can be invoked to perform some action without returning any values to the caller. It can also return a value; such as a result of a calculation or a success code back to the caller. To create such a function, a statement starting with keyword return is used. When this statement is encountered, function execution stops.
Conditional Logic
Conditional logic statements allow us to perform certain actions based on an evaluation result of a condition. Let’s modify our example, so the line_number_print function displays different strings depending on whether the number is odd or even. The listing below shows the modifications made, the remaining code is not changed.
def line_number_printer(number):
if number % 2 == 0:
print("This is the line number", number, "and it is even")
else:
print("This is the line number", number, "and it is odd")
When the program is launched the following output is displayed on the screen.
C:\PythonExamples\>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2 and it is even
This is the line number 3 and it is odd
This is the line number 4 and it is even
Figure 3 shows how conditional logic is used in the example above.
Let’s go through the diagram and discuss each element:
“if” keyword is followed by a logical test that can be either True or False.
If the test is evaluated as True, the statement (or multiple statements) under the “if” section is executed.
As with the functions, the body of “if” or “else” sections comprises of indented statements.
If the test is evaluated as False, the statement (or multiple statements) under the “else” section is executed.
for Loops
The “for” loops can be used to apply an action to each element of a collection. For example, we can store a list of switch interfaces in a list. To check the status of each of these interfaces we can use the “for” loop to iterate through the list and then run a command against each of the interfaces.
Let’s rewrite our program using “for” loops to automatically assign line numbers.
The listing below shows the complete code, as we removed the line calculation function and multiple calls to print function.
def line_number_printer(number):
if number % 2 == 0:
print("This is the line number", number, "and it is even")
else:
print("This is the line number", number, "and it is odd")
print("Hello World!")
for line_number in range(2, 5):
line_number_printer(line_number)
When the program is launched the same output is displayed on the screen.
C:\PythonExamples>python c:\PythonExamples\hello_world.py
Hello World!
This is the line number 2 and it is even
This is the line number 3 and it is odd
This is the line number 4 and it is even
Figure 4 shows how “for” loop is used in the example above.
Let’s go through the diagram and discuss each element:
“for” keyword is followed by a variable name that will be changing its value on each pass.
“in” keyword is followed by a list of values that will be assigned one at a time to the “for” variable on each iteration.
Statements that perform actual work during each cycle are indented under the “for” loop.
Not shown in the example, “break” keyword stops loop processing and continues with the code following the loop. Similarly, the “continue” keyword stops the current pass processing, but in contrast to “break”, it starts the next cycle of the loop.
Self-Test Tasks:
Task 1
Write a function that accepts a number and prints it out followed by “is the number passed as a parameter”.
Task 2
Write a function that accepts a number and prints out “Greater than 10” or “Less or equal than 10” depending on the number that was provided. The greater operator is “>” and less or equal is “<=”.
Task 3
Write a “for” loop that iterates over a list of interfaces Ethernet1/1, Ethernet1/2, and Ethernet1/3 and prints out the output below. To supply interfaces for “for” loop, use a list [ “Ethernet1/1”, “Ethernet1/2”, “Ethernet1/3” ]
interface Ethernet1/1
description Added by Automation Script
no shutdown
interface Ethernet1/2
description Added by Automation Script
no shutdown
interface Ethernet1/3
description Added by Automation Script
no shutdown
Self-Test Answers:
Task 1
def print_number(number):
print(number, "is the number passed as a parameter")
Task 2
def compare_number_to_ten(number):
if number > 10:
print("Greater than 10")
else:
print("Less or equal than 10")
Task3
for interface_name in [ "Ethernet1/1", "Ethernet1/2", "Ethernet1/3" ]:
print("interface", interface_name)
print(" description Added by Automation Script")
print(" no shutdown")