OSPF Single Area Lab with Netmiko
Here is OSPF Single Area Lab prepared by Rene Molenaar. Let’s create a topology on EVE-NG and solve it with Python script using Netmiko.

Goal 1-2
- All IP addresses have been preconfigured for you.
- The following loopback interfaces have been configured:
HongKong: 1.1.1.1 /24
Amsterdam: 2.2.2.2 /24
Barcelona: 3.3.3.3 /24
In my EVE-NG topology, HongKong, Amsterdam and Barcelona have telnet connection info 192.168.29.131:32769 , 192.168.29.131:32770 , 192.168.29.131:32771 respectively. Also, there is no credential to make telnet connection.
This is comptlete script to configure interfaces and run “show ip interface brief” for each router as below.
# Rene Molenar CCNP Route
# OSPF Single Area
# Goal 1-2
from netmiko import ConnectHandler
devices = [{
# HongKong
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32769"
},
{
# Amsterdam
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32770"
},
{
# Barcelona
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32771"
}]
commands = [[
# HongKong
"interface fastEthernet0/0",
"ip address 192.168.12.1 255.255.255.0",
"no shutdown",
"description to_Amsterdam",
"interface fastEthernet1/0",
"ip address 192.168.13.1 255.255.255.0",
"no shutdown",
"description to_Barcelona",
"default interface loopback0",
"interface loopback0",
"ip address 1.1.1.1 255.255.255.0",
],
[
# Amsterdam
"interface fastEthernet0/0",
"ip address 192.168.12.2 255.255.255.0",
"no shutdown",
"description to_HongKong",
"interface fastEthernet1/0",
"ip address 192.168.23.2 255.255.255.0",
"no shutdown",
"description to_Barcelona",
"default interface loopback0",
"interface loopback0",
"ip address 2.2.2.2 255.255.255.0",
],
[
# Barcelona
"interface fastEthernet0/0",
"ip address 192.168.13.3 255.255.255.0",
"no shutdown",
"description to_HongKong",
"interface fastEthernet1/0",
"ip address 192.168.23.3 255.255.255.0",
"no shutdown",
"description to_Amsterdam",
"default interface loopback0",
"interface loopback0",
"ip address 3.3.3.3 255.255.255.0",
]]
device_count = len(devices)
for index in range(0,device_count):
net_connect = ConnectHandler(**devices[index])
net_connect.enable()
net_connect.send_config_set(commands[index])
net_connect.save_config()
commands = [
"show ip interface brief | exclude down ",
"show interface description | exclude down "
] exclude down "
]
output = ""
for device in devices:
net_connect = ConnectHandler(**device)
net_connect.enable()
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_command(commands)
output += "\n\n"
net_connect.disconnect()
print(output)And this is our result as below. All interfaces are configured
HongKong#show ip interface brief | exclude down
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.12.1 YES manual up up
FastEthernet1/0 192.168.13.1 YES manual up up
Loopback0 1.1.1.1 YES manual up up
HongKong#show interface description | exclude down
Interface Status Protocol Description
Fa0/0 up up to_Amsterdam
Fa1/0 up up to_Barcelona
Lo0 up up
HongKong#
Amsterdam#show ip interface brief | exclude down
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.12.2 YES manual up up
FastEthernet1/0 192.168.23.2 YES manual up up
Loopback0 2.2.2.2 YES manual up up
Amsterdam#show interface description | exclude down
Interface Status Protocol Description
Fa0/0 up up to_HongKong
Fa1/0 up up to_Barcelona
Lo0 up up
Amsterdam#
Barcelona#show ip interface brief | exclude down
Interface IP-Address OK? Method Status Protocol
FastEthernet0/0 192.168.13.3 YES manual up up
FastEthernet1/0 192.168.23.3 YES manual up up
Loopback0 3.3.3.3 YES manual up up
Barcelona#show interface description | exclude down
Interface Status Protocol Description
Fa0/0 up up to_HongKong
Fa1/0 up up to_Amsterdam
Lo0 up up
Barcelona#Goal 3-5
3- HongKong: Configure OSPF (process-id 1) and advertise all networks by using a singlenetwork statement. Use area0
4- Amsterdam: Configure OSPF (process-id 1) and advertise all networks by using 2 networkstatements, area0.
5- Barcelona: Configure OSPF (process-id 1) and advertise all networks by using 3 networkstatements, area0.
# Rene Molenar CCNP Route
# OSPF Single Area
# Goal 3-5
from netmiko import ConnectHandler
devices = [{
# HongKong
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32769"
},
{
# Amsterdam
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32770"
},
{
# Barcelona
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32771"
}]
commands = [[
# HongKong
"router ospf 1",
"network 0.0.0.0 0.0.0.0 area 0",
],
[
# Amsterdam
"router ospf 1",
"network 192.168.0.0 0.0.255.255 area 0",
"network 2.2.2.2 0.0.0.0 area 0"
],
[
# Barcelona
"router ospf 1",
"network 192.168.13.0 0.0.0.255 area 0",
"network 192.168.23.3 0.0.0.0 area 0",
"network 3.3.3.3 0.0.0.255 area 0"
]]
device_count = len(devices)
for index in range(0,device_count):
net_connect = ConnectHandler(**devices[index])
net_connect.enable()
net_connect.send_config_set(commands[index])
net_connect.save_config()
commands = "show ip ospf neighbor"
output = ""
for device in devices:
net_connect = ConnectHandler(**device)
net_connect.enable()
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_command(commands)
output += "\n\n"
net_connect.disconnect()
print(output)I configure 3 router as written in the lab document. And adjacencies are in Full state.
HongKong#
Neighbor ID Pri State Dead Time Address Interface
3.3.3.3 1 FULL/DR 00:00:35 192.168.13.3 FastEthernet1/0
2.2.2.2 1 FULL/DR 00:00:35 192.168.12.2 FastEthernet0/0
Amsterdam#
Neighbor ID Pri State Dead Time Address Interface
3.3.3.3 1 FULL/DR 00:00:35 192.168.23.3 FastEthernet1/0
1.1.1.1 1 FULL/BDR 00:00:30 192.168.12.1 FastEthernet0/0
Barcelona#
Neighbor ID Pri State Dead Time Address Interface
2.2.2.2 1 FULL/BDR 00:00:33 192.168.23.2 FastEthernet1/0
1.1.1.1 1 FULL/BDR 00:00:34 192.168.13.1 FastEthernet0/0Goal 6
6. Optional: the loopback interfaces appear as /32’s in the routing table, make sure theyappear as /24’s just as you configured them.
Let’s create a function sends a show commands and returns the output. Then let’s use it with built-in map function.
from netmiko import ConnectHandler
devices = [{
# HongKong
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32769"
},
{
# Amsterdam
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32770"
},
{
# Barcelona
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32771"
}]
commands = [
# HongKong
"show ip route ospf",
# Amsterdam
"show ip route ospf",
# Barcelona
"show ip route ospf"
]
def send_show_command(device, command):
net_connect = ConnectHandler(**device)
net_connect.enable()
output =""
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_command(command)
output += "\n"
net_connect.disconnect()
return output
outputs = list(map(send_show_command, devices, commands))
for output in outputs:
print(output)
As you see output below, our loopback’s subnets are /32 in OSPF. This is about interface OSPF network type.
HongKong#
2.0.0.0/32 is subnetted, 1 subnets
O 2.2.2.2 [110/3] via 192.168.13.3, 02:47:14, FastEthernet1/0
3.0.0.0/32 is subnetted, 1 subnets
O 3.3.3.3 [110/2] via 192.168.13.3, 00:00:21, FastEthernet1/0
O 192.168.23.0/24 [110/2] via 192.168.13.3, 02:47:14, FastEthernet1/0
Amsterdam#
1.0.0.0/32 is subnetted, 1 subnets
O 1.1.1.1 [110/3] via 192.168.23.3, 02:47:12, FastEthernet1/0
O 192.168.13.0/24 [110/2] via 192.168.23.3, 02:47:22, FastEthernet1/0
3.0.0.0/32 is subnetted, 1 subnets
O 3.3.3.3 [110/2] via 192.168.23.3, 00:00:24, FastEthernet1/0
Barcelona#
O 192.168.12.0/24 [110/11] via 192.168.23.2, 02:47:24, FastEthernet1/0
[110/11] via 192.168.13.1, 02:47:14, FastEthernet0/0
1.0.0.0/32 is subnetted, 1 subnets
O 1.1.1.1 [110/2] via 192.168.13.1, 02:47:14, FastEthernet0/0
2.0.0.0/32 is subnetted, 1 subnets
O 2.2.2.2 [110/2] via 192.168.23.2, 02:47:24, FastEthernet1/0When we send “show ip ospf interface loopback 0 | include type” to our send_show_command as command argument, output will be as below. We can see each network types are LOOPBACK.
HongKong#
Process ID 1, Router ID 1.1.1.1, Network Type LOOPBACK, Cost: 1
Amsterdam#
Process ID 1, Router ID 2.2.2.2, Network Type LOOPBACK, Cost: 1
Barcelona#
Process ID 1, Router ID 3.3.3.3, Network Type LOOPBACK, Cost: 1When we change the these interfaces’s network types, our OSPF routes will change as we want. Let’s define a function that sends config commands and returns the outputs and use it in built-in map function.
from netmiko import ConnectHandler
devices = [{
# HongKong
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32769"
},
{
# Amsterdam
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32770"
},
{
# Barcelona
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32771"
}]
commands = [[
# HongKong
"interface loopback 0",
"ip ospf network point-to-point"
],
[
# Amsterdam
"interface loopback 0",
"ip ospf network point-to-point"
],
[
# Barcelona
"interface loopback 0",
"ip ospf network point-to-point"
]]
def send_config_command(device, command):
net_connect = ConnectHandler(**device)
net_connect.enable()
output =""
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_config_set(command)
output += "\n\n"
net_connect.disconnect()
return output
outputs = list(map(send_config_command, devices, commands))
for output in outputs:
print(output)
And here is the output below.
HongKong#
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
HongKong(conf
HongKong(config)#interface loopback 0
HongKong(config-if)#ip ospf network point-to-point
HongKong(config
HongKong(config-if)#end
HongKong#
Amsterdam#
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Amsterdam(con
Amsterdam(config)#interface loopback 0
Amsterdam(config-if)#ip ospf network point-to-point
Amsterdam(co
Amsterdam(config-if)#end
Amsterdam#
Barcelona(conf
interface loopback 0
Barcelona(config-if)#ip ospf network point-to-point
Barcelona(config
Barcelona(config-if)#endAfter sending configs, we can see OSPF routes are now /24 by sending “show ip route ospf” command.
HongKong#
2.0.0.0/24 is subnetted, 1 subnets
O 2.2.2.0 [110/3] via 192.168.13.3, 00:08:10, FastEthernet1/0
3.0.0.0/24 is subnetted, 1 subnets
O 3.3.3.0 [110/2] via 192.168.13.3, 00:08:10, FastEthernet1/0
O 192.168.23.0/24 [110/2] via 192.168.13.3, 00:08:10, FastEthernet1/0
Amsterdam#
1.0.0.0/24 is subnetted, 1 subnets
O 1.1.1.0 [110/3] via 192.168.23.3, 00:08:13, FastEthernet1/0
O 192.168.13.0/24 [110/2] via 192.168.23.3, 00:08:13, FastEthernet1/0
3.0.0.0/24 is subnetted, 1 subnets
O 3.3.3.0 [110/2] via 192.168.23.3, 00:08:13, FastEthernet1/0
Barcelona#
O 192.168.12.0/24 [110/11] via 192.168.23.2, 00:11:25, FastEthernet1/0
[110/11] via 192.168.13.1, 00:11:25, FastEthernet0/0
1.0.0.0/24 is subnetted, 1 subnets
O 1.1.1.0 [110/2] via 192.168.13.1, 00:08:15, FastEthernet0/0
2.0.0.0/24 is subnetted, 1 subnets
O 2.2.2.0 [110/2] via 192.168.23.2, 00:08:15, FastEthernet1/0Now, we have two function to send show and config commands. We can achieve remain goals by using both functions.
Goal 7
7- Amsterdam: change the router-id to 22.22.22.22, make sure you see this change fromBarcelona by using show commands.
For this goal, we are working on a device of Amsterdam. We can write a compact code.
from netmiko import ConnectHandler
amsterdam = {
# Amsterdam
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32770"
}
barcelona = {
# Barcelona
"device_type": "cisco_ios_telnet",
"host": "192.168.29.131",
"port": "32771"
}
config_commands = [
"interface loopback0",
"no ip address",
"ip address 22.22.22.22 255.255.255.0"
]
show_commands = [
"show ip ospf neighbor",
"show ip route ospf"
]
def send_config_command(device, command):
net_connect = ConnectHandler(**device)
net_connect.enable()
output =""
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_config_set(command)
output += "\n\n"
net_connect.disconnect()
return output
def send_show_command(device, command):
net_connect = ConnectHandler(**device)
net_connect.enable()
output =""
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_multiline(command)
output += "\n"
net_connect.disconnect()
return output
def reset_ospf(device):
net_connect = ConnectHandler(**device)
net_connect.enable()
output =""
output += net_connect.find_prompt()
output += "\n"
output += net_connect.send_command("clear ip ospf 1 process", expect_string=r"Reset OSPF process")
output += net_connect.send_command("yes", expect_string=r"#", delay_factor=2)
return output
output = send_config_command(amsterdam, config_commands)
print(output)
output = reset_ospf(amsterdam)
print(output)
output = send_show_command(barcelona, show_commands)
print(output)Amsterdam#
configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Amsterdam(con
Amsterdam(config)#interface loopback0
Amsterdam(config-if)#no ip address
Amsterdam(config-if)#ip address 22.22.22.22 255.255.255.0
Amsterdam(config-if
Amsterdam(config-if)#end
Amsterdam#
Amsterdam#
Reset OSPF process? [no]:
Barcelona#
show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
2.2.2.2 1 FULL/DR 00:00:37 192.168.23.2 FastEthernet1/0
22.22.22.22 1 FULL/DROTHER 00:00:38 192.168.23.2 FastEthernet1/0
1.1.1.1 1 FULL/DR 00:00:38 192.168.13.1 FastEthernet0/0
Barcelona#show ip route ospf
O 192.168.12.0/24 [110/11] via 192.168.23.2, 00:20:11, FastEthernet1/0
[110/11] via 192.168.13.1, 00:20:11, FastEthernet0/0
1.0.0.0/24 is subnetted, 1 subnets
O 1.1.1.0 [110/2] via 192.168.13.1, 00:20:11, FastEthernet0/0
Barcelona#So far, we have seen and used these netmiko functions;
- find_prompt
- send_command
- send_multiline
- send_config_set
And there is an article about using expect_string and delay_factor arguments, here. I advice you to read this article if you want to learn about it.
To be continue…