• 12 November 2025

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

  1. All IP addresses have been preconfigured for you.
  2. 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/0

Goal 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/0

When 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: 1

When 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)#end

After 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/0

Now, 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…