mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 08:56:13 +00:00
Merge pull request #6814 from gpnaveen/ospf_basic_functionality
tests: ospf basic functionality topojson testcases.
This commit is contained in:
commit
dfc51e66bf
@ -258,6 +258,7 @@ def create_common_configuration(
|
||||
"route_maps": "! Route Maps Config\n",
|
||||
"bgp": "! BGP Config\n",
|
||||
"vrf": "! VRF Config\n",
|
||||
"ospf": "! OSPF Config\n",
|
||||
}
|
||||
)
|
||||
|
||||
@ -684,7 +685,7 @@ def generate_support_bundle():
|
||||
return True
|
||||
|
||||
|
||||
def start_topology(tgen):
|
||||
def start_topology(tgen, daemon=None):
|
||||
"""
|
||||
Starting topology, create tmp files which are loaded to routers
|
||||
to start deamons and then start routers
|
||||
@ -736,9 +737,16 @@ def start_topology(tgen):
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA, "{}/{}/zebra.conf".format(TMPDIR, rname)
|
||||
)
|
||||
|
||||
# Loading empty bgpd.conf file to router, to start the bgp deamon
|
||||
router.load_config(TopoRouter.RD_BGP, "{}/{}/bgpd.conf".format(TMPDIR, rname))
|
||||
|
||||
if daemon and 'ospfd' in daemon:
|
||||
# Loading empty ospf.conf file to router, to start the bgp deamon
|
||||
router.load_config(
|
||||
TopoRouter.RD_OSPF,
|
||||
'{}/{}/ospfd.conf'.format(TMPDIR, rname)
|
||||
)
|
||||
# Starting routers
|
||||
logger.info("Starting all routers once topology is created")
|
||||
tgen.start_router()
|
||||
@ -811,6 +819,24 @@ def number_to_column(routerName):
|
||||
return ord(routerName[0]) - 97
|
||||
|
||||
|
||||
def topo_daemons(tgen, topo):
|
||||
"""
|
||||
Returns daemon list required for the suite based on topojson.
|
||||
"""
|
||||
daemon_list = []
|
||||
|
||||
router_list = tgen.routers()
|
||||
ROUTER_LIST = sorted(
|
||||
router_list.keys(), key=lambda x: int(re_search("\d+", x).group(0))
|
||||
)
|
||||
|
||||
for rtr in ROUTER_LIST:
|
||||
if 'ospf' in topo['routers'][rtr] and 'ospfd' not in daemon_list:
|
||||
daemon_list.append('ospfd')
|
||||
|
||||
return daemon_list
|
||||
|
||||
|
||||
#############################################
|
||||
# Common APIs, will be used by all protocols
|
||||
#############################################
|
||||
@ -1394,6 +1420,58 @@ def create_interfaces_cfg(tgen, topo, build=False):
|
||||
else:
|
||||
interface_data.append("ipv6 address {}\n".format(intf_addr))
|
||||
|
||||
if 'ospf' in data:
|
||||
ospf_data = data['ospf']
|
||||
if 'area' in ospf_data:
|
||||
intf_ospf_area = c_data["links"][destRouterLink][
|
||||
"ospf"]["area"]
|
||||
if "delete" in data and data["delete"]:
|
||||
interface_data.append("no ip ospf area")
|
||||
else:
|
||||
interface_data.append("ip ospf area {}".format(
|
||||
intf_ospf_area
|
||||
))
|
||||
|
||||
if "hello_interval" in ospf_data:
|
||||
intf_ospf_hello = c_data["links"][destRouterLink][
|
||||
"ospf"]["hello_interval"]
|
||||
if "delete" in data and data["delete"]:
|
||||
interface_data.append("no ip ospf "\
|
||||
" hello-interval")
|
||||
else:
|
||||
interface_data.append("ip ospf "\
|
||||
" hello-interval {}".format(intf_ospf_hello))
|
||||
|
||||
if "dead_interval" in ospf_data:
|
||||
intf_ospf_dead = c_data["links"][destRouterLink][
|
||||
"ospf"]["dead_interval"]
|
||||
if "delete" in data and data["delete"]:
|
||||
interface_data.append("no ip ospf"\
|
||||
" dead-interval")
|
||||
else:
|
||||
interface_data.append("ip ospf "\
|
||||
" dead-interval {}".format(intf_ospf_dead))
|
||||
|
||||
if "network" in ospf_data:
|
||||
intf_ospf_nw = c_data["links"][destRouterLink][
|
||||
"ospf"]["network"]
|
||||
if "delete" in data and data["delete"]:
|
||||
interface_data.append("no ip ospf"\
|
||||
" network {}".format(intf_ospf_nw))
|
||||
else:
|
||||
interface_data.append("ip ospf"\
|
||||
" network {}".format(intf_ospf_nw))
|
||||
|
||||
if "priority" in ospf_data:
|
||||
intf_ospf_nw = c_data["links"][destRouterLink][
|
||||
"ospf"]["priority"]
|
||||
|
||||
if "delete" in data and data["delete"]:
|
||||
interface_data.append("no ip ospf"\
|
||||
" priority")
|
||||
else:
|
||||
interface_data.append("ip ospf"\
|
||||
" priority {}".format(intf_ospf_nw))
|
||||
result = create_common_configuration(
|
||||
tgen, c_router, interface_data, "interface_config", build=build
|
||||
)
|
||||
|
1182
tests/topotests/lib/ospf.py
Normal file
1182
tests/topotests/lib/ospf.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,9 @@ from json import dumps as json_dumps
|
||||
from re import search as re_search
|
||||
import ipaddress
|
||||
import pytest
|
||||
import ipaddr
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
# Import topogen and topotest helpers
|
||||
from lib.topolog import logger
|
||||
@ -41,7 +44,7 @@ from lib.common_config import (
|
||||
)
|
||||
|
||||
from lib.bgp import create_router_bgp
|
||||
|
||||
from lib.ospf import create_router_ospf
|
||||
ROUTER_LIST = []
|
||||
|
||||
|
||||
@ -58,12 +61,27 @@ def build_topo_from_json(tgen, topo):
|
||||
topo["routers"].keys(), key=lambda x: int(re_search("\d+", x).group(0))
|
||||
)
|
||||
|
||||
SWITCH_LIST = []
|
||||
if "switches" in topo:
|
||||
SWITCH_LIST = sorted(
|
||||
topo["switches"].keys(), key=lambda x: int(re_search("\d+", x).group(0))
|
||||
)
|
||||
|
||||
listRouters = ROUTER_LIST[:]
|
||||
listSwitches = SWITCH_LIST[:]
|
||||
listAllRouters = deepcopy(listRouters)
|
||||
dictSwitches = {}
|
||||
|
||||
for routerN in ROUTER_LIST:
|
||||
logger.info("Topo: Add router {}".format(routerN))
|
||||
tgen.add_router(routerN)
|
||||
listRouters.append(routerN)
|
||||
|
||||
for switchN in SWITCH_LIST:
|
||||
logger.info("Topo: Add switch {}".format(switchN))
|
||||
dictSwitches[switchN] = tgen.add_switch(switchN)
|
||||
listSwitches.append(switchN)
|
||||
|
||||
if "ipv4base" in topo:
|
||||
ipv4Next = ipaddress.IPv4Address(topo["link_ip_start"]["ipv4"])
|
||||
ipv4Step = 2 ** (32 - topo["link_ip_start"]["v4mask"])
|
||||
@ -191,6 +209,72 @@ def build_topo_from_json(tgen, topo):
|
||||
),
|
||||
)
|
||||
|
||||
switch_count = 0
|
||||
add_switch_to_topo = []
|
||||
while listSwitches != []:
|
||||
curSwitch = listSwitches.pop(0)
|
||||
# Physical Interfaces
|
||||
if "links" in topo['switches'][curSwitch]:
|
||||
for destRouterLink, data in sorted(
|
||||
topo['switches'][curSwitch]['links'].iteritems()):
|
||||
|
||||
# Loopback interfaces
|
||||
if "dst_node" in data:
|
||||
destRouter = data['dst_node']
|
||||
|
||||
elif "-" in destRouterLink:
|
||||
# Spliting and storing destRouterLink data in tempList
|
||||
tempList = destRouterLink.split("-")
|
||||
# destRouter
|
||||
destRouter = tempList.pop(0)
|
||||
else:
|
||||
destRouter = destRouterLink
|
||||
|
||||
if destRouter in listAllRouters:
|
||||
|
||||
topo['routers'][destRouter]['links'][curSwitch] = \
|
||||
deepcopy(topo['switches'][curSwitch]['links'][destRouterLink])
|
||||
|
||||
# Assigning name to interfaces
|
||||
topo['routers'][destRouter]['links'][curSwitch]['interface'] = \
|
||||
'{}-{}-eth{}'.format(destRouter, curSwitch, topo['routers'] \
|
||||
[destRouter]['nextIfname'])
|
||||
|
||||
topo['switches'][curSwitch]['links'][destRouter]['interface'] = \
|
||||
'{}-{}-eth{}'.format(curSwitch, destRouter, topo['routers'] \
|
||||
[destRouter]['nextIfname'])
|
||||
|
||||
topo['routers'][destRouter]['nextIfname'] += 1
|
||||
|
||||
# Add links
|
||||
dictSwitches[curSwitch].add_link(tgen.gears[destRouter], \
|
||||
topo['switches'][curSwitch]['links'][destRouter]['interface'],
|
||||
topo['routers'][destRouter]['links'][curSwitch]['interface'],
|
||||
)
|
||||
|
||||
# IPv4
|
||||
if 'ipv4' in topo['routers'][destRouter]['links'][curSwitch]:
|
||||
if topo['routers'][destRouter]['links'][curSwitch]['ipv4'] == 'auto':
|
||||
topo['routers'][destRouter]['links'][curSwitch]['ipv4'] = \
|
||||
'{}/{}'.format(ipv4Next, topo['link_ip_start'][ \
|
||||
'v4mask'])
|
||||
ipv4Next += 1
|
||||
# IPv6
|
||||
if 'ipv6' in topo['routers'][destRouter]['links'][curSwitch]:
|
||||
if topo['routers'][destRouter]['links'][curSwitch]['ipv6'] == 'auto':
|
||||
topo['routers'][destRouter]['links'][curSwitch]['ipv6'] = \
|
||||
'{}/{}'.format(ipv6Next, topo['link_ip_start'][ \
|
||||
'v6mask'])
|
||||
ipv6Next = ipaddr.IPv6Address(int(ipv6Next) + ipv6Step)
|
||||
|
||||
logger.debug(
|
||||
"Generated link data for router: %s\n%s",
|
||||
curRouter,
|
||||
json_dumps(
|
||||
topo["routers"][curRouter]["links"], indent=4, sort_keys=True
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def build_config_from_json(tgen, topo, save_bkup=True):
|
||||
"""
|
||||
@ -210,6 +294,7 @@ def build_config_from_json(tgen, topo, save_bkup=True):
|
||||
("bgp_community_list", create_bgp_community_lists),
|
||||
("route_maps", create_route_maps),
|
||||
("bgp", create_router_bgp),
|
||||
("ospf", create_router_ospf)
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,166 @@
|
||||
{
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
},
|
||||
"redistribute": [
|
||||
{
|
||||
"redist_type": "static"
|
||||
},
|
||||
{
|
||||
"redist_type": "connected"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
342
tests/topotests/ospf_basic_functionality/ospf_ecmp.json
Normal file
342
tests/topotests/ospf_basic_functionality/ospf_ecmp.json
Normal file
@ -0,0 +1,342 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link4": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link5": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link6": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link7": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r1-link1": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link2": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link3": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link4": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link5": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link6": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r1-link7": {
|
||||
"nbr": "r1"
|
||||
},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link4": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link5": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link6": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r0-link7": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR3"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r0-link1": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link2": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link3": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link4": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link5": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link6": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r0-link7": {
|
||||
"nbr": "r0"
|
||||
},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR1",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
234
tests/topotests/ospf_basic_functionality/ospf_ecmp_lan.json
Normal file
234
tests/topotests/ospf_basic_functionality/ospf_ecmp_lan.json
Normal file
@ -0,0 +1,234 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"switches": {
|
||||
"s1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 98
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 99
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r4": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r5": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r6": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r7": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r3-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR3"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR1",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r4": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.4",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r5": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.5",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r6": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.6",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r7": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.7",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
138
tests/topotests/ospf_basic_functionality/ospf_lan.json
Normal file
138
tests/topotests/ospf_basic_functionality/ospf_lan.json
Normal file
@ -0,0 +1,138 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"switches": {
|
||||
"s1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 98
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 99
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"priority": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r3-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR3"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR1",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
188
tests/topotests/ospf_basic_functionality/ospf_nssa.json
Normal file
188
tests/topotests/ospf_basic_functionality/ospf_nssa.json
Normal file
@ -0,0 +1,188 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto"
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR3"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.2",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR1",
|
||||
"ospf": {
|
||||
"area": "0.0.0.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"area": [{
|
||||
"id": "0.0.0.2",
|
||||
"type": "nssa"
|
||||
}],
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
159
tests/topotests/ospf_basic_functionality/ospf_routemaps.json
Normal file
159
tests/topotests/ospf_basic_functionality/ospf_routemaps.json
Normal file
@ -0,0 +1,159 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
168
tests/topotests/ospf_basic_functionality/ospf_rte_calc.json
Normal file
168
tests/topotests/ospf_basic_functionality/ospf_rte_calc.json
Normal file
@ -0,0 +1,168 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
188
tests/topotests/ospf_basic_functionality/ospf_single_area.json
Normal file
188
tests/topotests/ospf_basic_functionality/ospf_single_area.json
Normal file
@ -0,0 +1,188 @@
|
||||
{
|
||||
|
||||
"ipv4base": "10.0.0.0",
|
||||
"ipv4mask": 24,
|
||||
"link_ip_start": {
|
||||
"ipv4": "10.0.0.0",
|
||||
"v4mask": 24
|
||||
},
|
||||
"lo_prefix": {
|
||||
"ipv4": "1.0.",
|
||||
"v4mask": 32
|
||||
},
|
||||
"routers": {
|
||||
"r0": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.0",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR3"
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.1",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r2": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.2",
|
||||
"neighbors": {
|
||||
"r1": {},
|
||||
"r0": {},
|
||||
"r3": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"r3": {
|
||||
"links": {
|
||||
"lo": {
|
||||
"ipv4": "auto",
|
||||
"type": "loopback"
|
||||
},
|
||||
"r0": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4,
|
||||
"network": "point-to-point"
|
||||
}
|
||||
},
|
||||
"r1": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r2": {
|
||||
"ipv4": "auto",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0",
|
||||
"hello_interval": 1,
|
||||
"dead_interval": 4
|
||||
}
|
||||
},
|
||||
"r1-link0": {
|
||||
"ipv4": "auto",
|
||||
"description": "DummyIntftoR1",
|
||||
"ospf": {
|
||||
"area": "0.0.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ospf": {
|
||||
"router_id": "100.1.1.3",
|
||||
"neighbors": {
|
||||
"r0": {},
|
||||
"r1": {},
|
||||
"r2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,891 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
from time import sleep
|
||||
from copy import deepcopy
|
||||
import json
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
step,
|
||||
shutdown_bringup_interface,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
from lib.ospf import verify_ospf_neighbor, config_ospf_interface, clear_ospf
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_authentication.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
"""
|
||||
TOPOOLOGY =
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
|
||||
TESTCASES =
|
||||
1. Verify ospf authentication with Simple password authentication.
|
||||
2. Verify ospf authentication with MD5 authentication.
|
||||
3. Verify ospf authentication with different authentication methods.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_authentication_simple_pass_tc28_p1(request):
|
||||
"""
|
||||
OSPF Authentication - Verify ospf authentication with Simple
|
||||
password authentication.
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
reset_config_on_routers(tgen)
|
||||
step(
|
||||
"Configure ospf with on R1 and R2, enable ospf on R1 interface"
|
||||
"connected to R2 with simple password authentication using ip ospf "
|
||||
"authentication Simple password cmd."
|
||||
)
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("clear ip ospf after configuring the authentication.")
|
||||
clear_ospf(tgen, "r1")
|
||||
|
||||
step("Verify that the neighbour is not FULL between R1 and R2.")
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, expected=False)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"On R2 enable ospf on interface with simple password authentication "
|
||||
"using ip ospf authentication Simple password cmd."
|
||||
)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 "
|
||||
"using show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"Disable simple password authentication on R2 using no ip ospf "
|
||||
"authentication Simple password cmd."
|
||||
)
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": True,
|
||||
"authentication-key": "ospf",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify on R1 neighbour is deleted for R2 after dead interval expiry")
|
||||
# wait till the dead time expiry
|
||||
sleep(6)
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(
|
||||
tgen, topo, dut=dut, expected=False, attempts=5
|
||||
)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Again On R2 enable ospf on interface with Simple password auth")
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 using"
|
||||
" show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Shut no shut interface on R1")
|
||||
dut = "r1"
|
||||
intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
dut = "r2"
|
||||
step(
|
||||
"Verify that the neighbour is not FULL between R1 and R2 using "
|
||||
"show ip ospf neighbor cmd."
|
||||
)
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, expected=False)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 using "
|
||||
"show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change Ip address on R1 and R2")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r1"]["links"]["r2"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r1"]["links"]["r2"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(intf_ip.split("/")[1])
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
|
||||
reset_config_on_routers(tgen, routerName="r1")
|
||||
dut = "r1"
|
||||
intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
# clear ip ospf after configuring the authentication.
|
||||
clear_ospf(tgen, "r1")
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 with new "
|
||||
"ip address using show ip ospf "
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_authentication_md5_tc29_p1(request):
|
||||
"""
|
||||
OSPF Authentication - Verify ospf authentication with MD5 authentication.
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
reset_config_on_routers(tgen)
|
||||
step(
|
||||
"Configure ospf with on R1 and R2, enable ospf on R1 interface "
|
||||
"connected to R2 with message-digest authentication using ip "
|
||||
"ospf authentication message-digest cmd."
|
||||
)
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that the neighbour is not FULL between R1 and R2.")
|
||||
# wait for dead time expiry.
|
||||
sleep(6)
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(
|
||||
tgen, topo, dut=dut, expected=False, attempts=3
|
||||
)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"On R2 enable ospf on interface with message-digest authentication"
|
||||
" using ip ospf authentication message-digest password cmd."
|
||||
)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 "
|
||||
"using show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"Disable message-digest authentication on R2 using no ip ospf "
|
||||
"authentication message-digest password cmd."
|
||||
)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify on R1 ,nbr is deleted for R2 after dead interval expiry")
|
||||
# wait till the dead timer expiry
|
||||
sleep(6)
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(
|
||||
tgen, topo, dut=dut, expected=False, attempts=5
|
||||
)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Again On R2 enable ospf on interface with message-digest auth")
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 using"
|
||||
" show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Shut no shut interface on R1")
|
||||
dut = "r1"
|
||||
intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
dut = "r2"
|
||||
step(
|
||||
"Verify that the neighbour is not FULL between R1 and R2 using "
|
||||
"show ip ospf neighbor cmd."
|
||||
)
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, expected=False)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 using "
|
||||
"show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change Ip address on R1 and R2")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
|
||||
intf_ip = topo_modify_change_ip["routers"]["r1"]["links"]["r2"]["ipv4"]
|
||||
|
||||
topo_modify_change_ip["routers"]["r1"]["links"]["r2"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(intf_ip.split("/")[1])
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
|
||||
reset_config_on_routers(tgen, routerName="r1")
|
||||
dut = "r1"
|
||||
intf = topo["routers"]["r1"]["links"]["r2"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
clear_ospf(tgen, "r1")
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 with new "
|
||||
"ip address using show ip ospf "
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_authentication_different_auths_tc30_p1(request):
|
||||
"""
|
||||
OSPF Authentication - Verify ospf authentication with different
|
||||
authentication methods.
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
reset_config_on_routers(tgen)
|
||||
step(
|
||||
"Configure ospf with on R1 and R2, enable ospf on R1 interface "
|
||||
"connected to R2 with message-digest authentication using ip "
|
||||
"ospf authentication message-digest cmd."
|
||||
)
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
# wait for dead timer expiry
|
||||
sleep(6)
|
||||
step("Verify that the neighbour is not FULL between R1 and R2.")
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(
|
||||
tgen, topo, dut=dut, expected=False, attempts=5
|
||||
)
|
||||
assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"On R2 enable ospf on interface with message-digest authentication"
|
||||
" using ip ospf authentication message-digest password cmd."
|
||||
)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 "
|
||||
"using show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(" Delete the configured password on both the routers.")
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the deletion is successful and neighbour is FULL"
|
||||
" between R1 and R2 using show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change the authentication type to simple password.")
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {"ospf": {"authentication": True, "authentication-key": "ospf"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the deletion is successful and neighbour is"
|
||||
" FULL between R1 and R2 using show ip "
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change the password in simple password.")
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {"ospf": {"authentication": True, "authentication-key": "OSPFv4"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {"ospf": {"authentication": True, "authentication-key": "OSPFv4"}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the deletion is successful and neighbour is"
|
||||
" FULL between R1 and R2 using show ip "
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Delete the password authentication on the interface ")
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": True,
|
||||
"authentication-key": "OSPFv4",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": True,
|
||||
"authentication-key": "OSPFv4",
|
||||
"del_action": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the deletion is successful and neighbour is"
|
||||
" FULL between R1 and R2 using show ip "
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Enable Md5 authentication on the interface")
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "ospf",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that the neighbour is FULL between R1 and R2 using"
|
||||
" show ip ospf neighbor cmd."
|
||||
)
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change the MD5 authentication password")
|
||||
|
||||
r1_ospf_auth = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r2": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "OSPFv4",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r1_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
r2_ospf_auth = {
|
||||
"r2": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"authentication": "message-digest",
|
||||
"authentication-key": "OSPFv4",
|
||||
"message-digest-key": "10",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = config_ospf_interface(tgen, topo, r2_ospf_auth)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
495
tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
Normal file
495
tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
Normal file
@ -0,0 +1,495 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
from time import sleep
|
||||
from copy import deepcopy
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
step,
|
||||
create_route_maps,
|
||||
shutdown_bringup_interface,
|
||||
create_interfaces_cfg,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.topolog import logger
|
||||
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
config_ospf_interface,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_interface,
|
||||
)
|
||||
|
||||
topo = None
|
||||
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_ecmp.json".format(CWD)
|
||||
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
# Global variables
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
]
|
||||
}
|
||||
"""
|
||||
TOPOLOGY :
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
|
||||
TESTCASES :
|
||||
1. Verify OSPF ECMP with max path configured as 8 (ECMPconfigured at FRR level)
|
||||
2. Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
def red_static(dut, config=True):
|
||||
"""Local def for Redstribute static routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {"ospf": {"redistribute": [{"redist_type": "static", "delete": True}]}}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
def red_connected(dut, config=True):
|
||||
"""Local def for Redstribute connected routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "connected", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase: Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_ecmp_tc16_p0(request):
|
||||
"""
|
||||
Verify OSPF ECMP.
|
||||
|
||||
Verify OSPF ECMP with max path configured as 8 (ECMP
|
||||
configured at FRR level)
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
step("Configure 8 interfaces between R1 and R2 and enable ospf in area 0.")
|
||||
reset_config_on_routers(tgen)
|
||||
step("Verify that OSPF is up with 8 neighborship sessions.")
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Configure a static route in R0 and redistribute in OSPF.")
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0",}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r0"
|
||||
red_static(dut)
|
||||
|
||||
step("Verify that route in R2 in stalled with 8 next hops.")
|
||||
nh = []
|
||||
for item in range(1, 7):
|
||||
nh.append(topo["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0])
|
||||
|
||||
nh2 = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
|
||||
nh.append(nh2)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("shut no shut all the interfaces on the remote router - R2")
|
||||
dut = "r1"
|
||||
for intfr in range(1, 7):
|
||||
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
for intfr in range(1, 7):
|
||||
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("shut no shut on all the interfaces on DUT (r1)")
|
||||
for intfr in range(1, 7):
|
||||
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
for intfr in range(1, 7):
|
||||
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
step(
|
||||
"Verify that all the neighbours are up and routes are installed"
|
||||
" with 8 next hop in ospf and ip route tables on R1."
|
||||
)
|
||||
|
||||
step("Verify that OSPF is up with 8 neighborship sessions.")
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(" Un configure static route on R0")
|
||||
|
||||
dut = "r0"
|
||||
red_static(dut, config=False)
|
||||
|
||||
# Wait for R0 to flush external LSAs.
|
||||
sleep(10)
|
||||
|
||||
step("Verify that route is withdrawn from R2.")
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(
|
||||
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen,
|
||||
"ipv4",
|
||||
dut,
|
||||
input_dict,
|
||||
protocol=protocol,
|
||||
next_hop=nh,
|
||||
attempts=5,
|
||||
expected=False,
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Re configure the static route in R0.")
|
||||
dut = "r0"
|
||||
red_static(dut)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_ecmp_tc17_p0(request):
|
||||
"""
|
||||
Verify OSPF ECMP.
|
||||
|
||||
Verify OSPF ECMP with max path configured as 2 (Edge having 2 uplink ports)
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
step("Configure 2 interfaces between R1 and R2 & enable ospf in area 0.")
|
||||
reset_config_on_routers(tgen)
|
||||
step("Verify that OSPF is up with 2 neighborship sessions.")
|
||||
dut = "r1"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Configure a static route in R0 and redistribute in OSPF.")
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0",}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r0"
|
||||
red_static(dut)
|
||||
|
||||
step("Verify that route in R2 in stalled with 2 next hops.")
|
||||
|
||||
nh1 = topo["routers"]["r0"]["links"]["r1-link1"]["ipv4"].split("/")[0]
|
||||
nh2 = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
nh = [nh1, nh2]
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(" Un configure static route on R0")
|
||||
|
||||
dut = "r0"
|
||||
red_static(dut, config=False)
|
||||
# sleep till the route gets withdrawn
|
||||
sleep(10)
|
||||
|
||||
step("Verify that route is withdrawn from R2.")
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(
|
||||
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen,
|
||||
"ipv4",
|
||||
dut,
|
||||
input_dict,
|
||||
protocol=protocol,
|
||||
next_hop=nh,
|
||||
attempts=5,
|
||||
expected=False,
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Reconfigure the static route in R0.Change ECMP value to 2.")
|
||||
dut = "r0"
|
||||
red_static(dut)
|
||||
|
||||
step("Configure cost on R0 as 100")
|
||||
r0_ospf_cost = {"r0": {"links": {"r1": {"ospf": {"cost": 100}}}}}
|
||||
result = config_ospf_interface(tgen, topo, r0_ospf_cost)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
369
tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
Normal file
369
tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
Normal file
@ -0,0 +1,369 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
create_interfaces_cfg,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
check_address_types,
|
||||
step,
|
||||
create_route_maps,
|
||||
shutdown_bringup_interface,
|
||||
stop_router,
|
||||
start_router,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.bgp import verify_bgp_convergence, create_router_bgp
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
config_ospf_interface,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_interface,
|
||||
)
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
# Reading the data from JSON File for topology creation
|
||||
|
||||
jsonFile = "{}/ospf_ecmp_lan.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
],
|
||||
"ipv6": ["1::1/128", "1::2/128", "1::3/128", "1::4/128", "1::5/128"],
|
||||
}
|
||||
MASK = {"ipv4": "32", "ipv6": "128"}
|
||||
NEXT_HOP = {
|
||||
"ipv4": ["10.0.0.1", "10.0.1.1", "10.0.2.1", "10.0.3.1", "10.0.4.1"],
|
||||
"ipv6": ["Null0", "Null0", "Null0", "Null0", "Null0"],
|
||||
}
|
||||
"""
|
||||
TOPOOLOGY =
|
||||
Please view in a fixed-width font such as Courier.
|
||||
Topo : Broadcast Networks
|
||||
+---+ +---+ +---+ +---+
|
||||
|R0 + +R1 + +R2 + +R3 |
|
||||
+-+-+ +-+-+ +-+-+ +-+-+
|
||||
| | | |
|
||||
| | | |
|
||||
--+-----------+--------------+---------------+-----
|
||||
Ethernet Segment
|
||||
|
||||
TESTCASES =
|
||||
1. Verify OSPF ECMP with max path configured as 8
|
||||
(Edge having 1 uplink port as broadcast network,
|
||||
connect to 8 TORs - LAN case)
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, lan=True)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module():
|
||||
"""Teardown the pytest environment"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
try:
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
except OSError:
|
||||
# OSError exception is raised when mininet tries to stop switch
|
||||
# though switch is stopped once but mininet tries to stop same
|
||||
# switch again, where it ended up with exception
|
||||
pass
|
||||
|
||||
|
||||
def red_static(dut, config=True):
|
||||
"""Local def for Redstribute static routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "static", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
def red_connected(dut, config=True):
|
||||
"""Local def for Redstribute connected routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "connected", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase: Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_lan_ecmp_tc18_p0(request):
|
||||
"""
|
||||
OSPF ECMP.
|
||||
|
||||
Verify OSPF ECMP with max path configured as 8
|
||||
(Edge having 1 uplink port as broadcast network,
|
||||
connect to 8 TORs - LAN case)
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
step(". Configure ospf in all the routers on LAN interface.")
|
||||
reset_config_on_routers(tgen)
|
||||
step("Verify that OSPF is up with 8 neighborship sessions.")
|
||||
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, lan=True)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(
|
||||
"Configure a static route in all the routes and "
|
||||
"redistribute static/connected in OSPF."
|
||||
)
|
||||
|
||||
for rtr in topo["routers"]:
|
||||
input_dict = {
|
||||
rtr: {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0"}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
dut = rtr
|
||||
red_static(dut)
|
||||
|
||||
step(
|
||||
"Verify that route in R0 in stalled with 8 hops. "
|
||||
"Verify ospf route table and ip route table."
|
||||
)
|
||||
|
||||
nh = []
|
||||
for rtr in topo["routers"]:
|
||||
nh.append(topo["routers"][rtr]["links"]["s1"]["ipv4"].split("/")[0])
|
||||
nh.remove(topo["routers"]["r1"]["links"]["s1"]["ipv4"].split("/")[0])
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(" clear ip ospf interface on DUT(r0)")
|
||||
clear_ospf(tgen, "r0")
|
||||
|
||||
step(
|
||||
"Verify that after clearing the ospf interface all the "
|
||||
"neighbours are up and routes are installed with 8 next hop "
|
||||
"in ospf and ip route tables on R0"
|
||||
)
|
||||
|
||||
dut = "r0"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, lan=True)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(" clear ip ospf interface on R2")
|
||||
clear_ospf(tgen, "r2")
|
||||
|
||||
dut = "r2"
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, lan=True)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Delete static/connected cmd in ospf in all the routes one by one.")
|
||||
for rtr in topo["routers"]:
|
||||
input_dict = {
|
||||
rtr: {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": NETWORK["ipv4"][0],
|
||||
"no_of_ip": 5,
|
||||
"next_hop": "Null0",
|
||||
"delete": True,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Verify that all the routes are withdrawn from R0")
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(
|
||||
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen,
|
||||
"ipv4",
|
||||
dut,
|
||||
input_dict,
|
||||
protocol=protocol,
|
||||
next_hop=nh,
|
||||
attempts=5,
|
||||
expected=False,
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
724
tests/topotests/ospf_basic_functionality/test_ospf_lan.py
Normal file
724
tests/topotests/ospf_basic_functionality/test_ospf_lan.py
Normal file
@ -0,0 +1,724 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
from copy import deepcopy
|
||||
import ipaddress
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
create_interfaces_cfg,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
check_address_types,
|
||||
step,
|
||||
create_route_maps,
|
||||
shutdown_bringup_interface,
|
||||
stop_router,
|
||||
start_router,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.bgp import verify_bgp_convergence, create_router_bgp
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
config_ospf_interface,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_interface,
|
||||
)
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_lan.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
]
|
||||
}
|
||||
|
||||
"""
|
||||
Topology:
|
||||
|
||||
Please view in a fixed-width font such as Courier.
|
||||
Topo : Broadcast Networks
|
||||
+---+ +---+ +---+ +---+
|
||||
|R0 + +R1 + +R2 + +R3 |
|
||||
+-+-+ +-+-+ +-+-+ +-+-+
|
||||
| | | |
|
||||
| | | |
|
||||
--+-----------+--------------+---------------+-----
|
||||
Ethernet Segment
|
||||
|
||||
Testcases:
|
||||
1. OSPF Hello protocol - Verify DR BDR Elections
|
||||
2. OSPF IFSM -Verify state change events on DR / BDR / DR Other
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, lan=True)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module():
|
||||
"""Teardown the pytest environment"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
try:
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology
|
||||
|
||||
except OSError:
|
||||
# OSError exception is raised when mininet tries to stop switch
|
||||
# though switch is stopped once but mininet tries to stop same
|
||||
# switch again, where it ended up with exception
|
||||
pass
|
||||
|
||||
|
||||
def red_static(dut, config=True):
|
||||
"""Local def for Redstribute static routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "static", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
def red_connected(dut, config=True):
|
||||
"""Local def for Redstribute connected routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "connected", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase: Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_lan_tc1_p0(request):
|
||||
"""
|
||||
OSPF Hello protocol - Verify DR BDR Elections
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
step("Verify that DR BDR DRother are elected in the LAN.")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "DR"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that all the routers are in FULL state with DR and BDR "
|
||||
"in the topology"
|
||||
)
|
||||
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r0": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r1"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Configure DR pririty 100 on R0 and clear ospf neighbors " "on all the routers."
|
||||
)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"priority": 100},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Clear ospf neighbours in all routers")
|
||||
for rtr in ["r0", "r1", "r2", "r3"]:
|
||||
clear_ospf(tgen, rtr)
|
||||
|
||||
step("Verify that DR election is triggered and R0 is elected as DR")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Configure DR pririty 150 on R0 and clear ospf neighbors " "on all the routers."
|
||||
)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"priority": 150},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Clear ospf neighbours in all routers")
|
||||
for rtr in ["r0", "r1"]:
|
||||
clear_ospf(tgen, rtr)
|
||||
|
||||
step("Verify that DR election is triggered and R0 is elected as DR")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Configure DR priority 0 on R0 & Clear ospf nbrs on all the routers")
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"priority": 0},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Clear ospf neighbours in all routers")
|
||||
for rtr in ["r1"]:
|
||||
clear_ospf(tgen, rtr)
|
||||
|
||||
step("Verify that DR election is triggered and R0 is elected as DRother")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "DR"},
|
||||
"r2": {"state": "2-Way", "role": "DROther"},
|
||||
"r3": {"state": "2-Way", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Configure DR priority to default on R0 and Clear ospf neighbors"
|
||||
" on all the routers"
|
||||
)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"priority": 100},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Clear ospf neighbours in all routers")
|
||||
for rtr in ["r0", "r1"]:
|
||||
clear_ospf(tgen, rtr)
|
||||
|
||||
step("Verify that DR election is triggered and R0 is elected as DR")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Shut interface on R0")
|
||||
dut = "r0"
|
||||
intf = topo["routers"]["r0"]["links"]["s1"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, lan=True, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("No Shut interface on R0")
|
||||
dut = "r0"
|
||||
intf = topo["routers"]["r0"]["links"]["s1"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r1": {"state": "Full", "role": "DR"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
step("Verify that after no shut ospf neighbours are full on R0.")
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Clear ospf on DR router in the topology.")
|
||||
clear_ospf(tgen, "r0")
|
||||
|
||||
step("Verify that BDR is getting promoted to DR after clear.")
|
||||
step("Verify that all the nbrs are in FULL state with the elected DR.")
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ip on LAN intf on R0 to other ip from the same subnet.")
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(intf_ip.split("/")[1])
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
|
||||
step(
|
||||
"Verify that OSPF is in FULL state with other routers with "
|
||||
"newly configured IP."
|
||||
)
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ospf router id on the R0 and clear ip ospf interface.")
|
||||
change_rid = {"r0": {"ospf": {"router_id": "100.1.1.100"}}}
|
||||
|
||||
result = create_router_ospf(tgen, topo, change_rid)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
topo["routers"]["r0"]["ospf"]["router_id"] = "100.1.1.100"
|
||||
step("Reload the FRR router")
|
||||
|
||||
stop_router(tgen, "r0")
|
||||
start_router(tgen, "r0")
|
||||
|
||||
step(
|
||||
"Verify that OSPF is in FULL state with other routers with"
|
||||
" newly configured router id."
|
||||
)
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r0": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r1"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Reconfigure the original router id and clear ip ospf interface.")
|
||||
change_rid = {"r0": {"ospf": {"router_id": "100.1.1.0"}}}
|
||||
result = create_router_ospf(tgen, topo, change_rid)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
topo["routers"]["r0"]["ospf"]["router_id"] = "100.1.1.0"
|
||||
step("Reload the FRR router")
|
||||
# stop/start -> restart FRR router and verify
|
||||
stop_router(tgen, "r0")
|
||||
start_router(tgen, "r0")
|
||||
|
||||
step("Verify that OSPF is enabled with router id previously configured.")
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"ospf": {
|
||||
"neighbors": {
|
||||
"r0": {"state": "Full", "role": "Backup"},
|
||||
"r2": {"state": "Full", "role": "DROther"},
|
||||
"r3": {"state": "Full", "role": "DROther"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dut = "r1"
|
||||
result = verify_ospf_neighbor(tgen, topo, dut, input_dict, lan=True)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_lan_tc2_p0(request):
|
||||
"""
|
||||
OSPF IFSM -Verify state change events on DR / BDR / DR Other
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
step(
|
||||
"Verify that OSPF is subscribed to multi cast services "
|
||||
"(All SPF, all DR Routers)."
|
||||
)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"ospf": {
|
||||
"priority": 98,
|
||||
"timerDeadSecs": 4,
|
||||
"area": "0.0.0.3",
|
||||
"mcastMemberOspfDesignatedRouters": True,
|
||||
"mcastMemberOspfAllRouters": True,
|
||||
"ospfEnabled": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the ip address")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["s1"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ip on the R0 interface")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(intf_ip.split("/")[1])
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"ospf": {
|
||||
"ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
|
||||
"s1"
|
||||
]["ipv4"].split("/")[0],
|
||||
"ipAddressPrefixlen": int(
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["s1"][
|
||||
"ipv4"
|
||||
].split("/")[1]
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Modify the mask on the R0 interface")
|
||||
ip_addr = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
|
||||
mask = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
|
||||
step("Delete the ip address")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": ip_addr,
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ip on the R0 interface")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["s1"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(int(intf_ip.split("/")[1]) + 1)
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"ospf": {
|
||||
"ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
|
||||
"s1"
|
||||
]["ipv4"].split("/")[0],
|
||||
"ipAddressPrefixlen": int(
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["s1"][
|
||||
"ipv4"
|
||||
].split("/")[1]
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the area id on the interface")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"area": "0.0.0.3"},
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"s1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["s1"]["interface"],
|
||||
"ospf": {"area": "0.0.0.2"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {"links": {"s1": {"ospf": {"area": "0.0.0.2", "ospfEnabled": True}}}}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
336
tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
Normal file
336
tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
Normal file
@ -0,0 +1,336 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import ipaddress
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
config_ospf_interface,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_interface,
|
||||
)
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
from lib.topolog import logger
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
step,
|
||||
create_route_maps,
|
||||
shutdown_bringup_interface,
|
||||
create_interfaces_cfg,
|
||||
topo_daemons
|
||||
)
|
||||
from ipaddress import IPv4Address
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
from mininet.topo import Topo
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_nssa.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
]
|
||||
}
|
||||
"""
|
||||
TOPOOLOGY =
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
|
||||
|
||||
|
||||
TESTCASES =
|
||||
1. OSPF Learning - Verify OSPF can learn different types of LSA and
|
||||
processes them.[Edge learning different types of LSAs]
|
||||
2. Verify that ospf non back bone area can be configured as NSSA area
|
||||
3. Verify that ospf NSSA area DUT is capable receiving & processing
|
||||
Type7 N2 route.
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
def red_static(dut, config=True):
|
||||
"""Local def for Redstribute static routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {"ospf": {"redistribute": [{"redist_type": "static", "delete": True}]}}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
def red_connected(dut, config=True):
|
||||
"""Local def for Redstribute connected routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "connected", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase: Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_learning_tc15_p0(request):
|
||||
"""Verify OSPF can learn different types of LSA and processes them.
|
||||
|
||||
OSPF Learning : Edge learning different types of LSAs.
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
step("Configure area 1 as NSSA Area")
|
||||
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step("Verify that Type 3 summary LSA is originated for the same Area 0")
|
||||
ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv4"]
|
||||
ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
|
||||
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N IA"}]
|
||||
}
|
||||
}
|
||||
|
||||
dut = "r0"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict = {
|
||||
"r2": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0"}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Redistribute static route in R2 ospf.")
|
||||
dut = "r2"
|
||||
red_static(dut)
|
||||
|
||||
step("Verify that Type 5 LSA is originated by R2.")
|
||||
dut = "r0"
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that R0 receives Type 4 summary LSA.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 1, "routeType": "N E2"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Change area 1 as non nssa area (on the fly changing area" " type on DUT).")
|
||||
|
||||
for rtr in ["r1", "r2", "r3"]:
|
||||
input_dict = {
|
||||
rtr: {"ospf": {"area": [{"id": "0.0.0.2", "type": "nssa", "delete": True}]}}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Verify that OSPF neighbours are reset after changing area type.")
|
||||
step("Verify that ABR R2 originates type 5 LSA in area 1.")
|
||||
step("Verify that route is calculated and installed in R1.")
|
||||
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 1, "routeType": "N E2"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
540
tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
Normal file
540
tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
Normal file
@ -0,0 +1,540 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
from copy import deepcopy
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
create_prefix_lists,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
check_address_types,
|
||||
step,
|
||||
create_route_maps,
|
||||
verify_prefix_lists,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_database,
|
||||
)
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_routemaps.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
]
|
||||
}
|
||||
routerids = ["100.1.1.0", "100.1.1.1", "100.1.1.2", "100.1.1.3"]
|
||||
|
||||
"""
|
||||
TOPOOLOGY =
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
|
||||
TESTCASES =
|
||||
1. OSPF Route map - Verify OSPF route map support functionality.
|
||||
2. Verify OSPF route map support functionality when route map is not
|
||||
configured at system level but configured in OSPF
|
||||
3. Verify OSPF route map support functionality with set/match clauses
|
||||
/call/continue/goto in a route-map to see if it takes immediate effect.
|
||||
4. Verify OSPF route map support functionality
|
||||
when route map actions are toggled.
|
||||
5. Verify OSPF route map support functionality with multiple sequence
|
||||
numbers in a single route-map for different match/set clauses.
|
||||
6. Verify OSPF route map support functionality when we add/remove route-maps
|
||||
with multiple set clauses and without any match statement.(Set only)
|
||||
7. Verify OSPF route map support functionality when we
|
||||
add/remove route-maps with multiple match clauses and without
|
||||
any set statement.(Match only)
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_routemaps_functionality_tc20_p0(request):
|
||||
"""
|
||||
OSPF route map support functionality.
|
||||
|
||||
Verify OSPF route map support functionality when route map is not
|
||||
configured at system level but configured in OSPF
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step("Create static routes(10.0.20.1/32 and 10.0.20.2/32) in R0")
|
||||
# Create Static routes
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0",}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Redistribute to ospf using route map ( non existent route map)")
|
||||
ospf_red_r1 = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "static", "route_map": "rmap_ipv4"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red_r1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that routes are not allowed in OSPF even tough no "
|
||||
"matching routing map is configured."
|
||||
)
|
||||
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, attempts=2, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_rib(
|
||||
tgen, "ipv4", dut, input_dict, protocol=protocol, attempts=2, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step(
|
||||
"configure the route map with the same name that is used "
|
||||
"in the ospf with deny rule."
|
||||
)
|
||||
|
||||
# Create route map
|
||||
routemaps = {"r0": {"route_maps": {"rmap_ipv4": [{"action": "deny"}]}}}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that now route map is activated & routes are denied in OSPF.")
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_rib(
|
||||
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
# Create route map
|
||||
routemaps = {"r0": {"route_maps": {"rmap_ipv4": [{"action": "deny"}]}}}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that now route map is activated & routes are denied in OSPF.")
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_rib(
|
||||
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Delete the route map.")
|
||||
# Create route map
|
||||
routemaps = {
|
||||
"r0": {"route_maps": {"rmap_ipv4": [{"action": "deny", "delete": True}]}}
|
||||
}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that routes are allowed in OSPF even tough "
|
||||
"no matching routing map is configured."
|
||||
)
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
result = verify_rib(
|
||||
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_routemaps_functionality_tc24_p0(request):
|
||||
"""
|
||||
OSPF Route map - Multiple set clauses.
|
||||
|
||||
Verify OSPF route map support functionality when we
|
||||
add/remove route-maps with multiple match clauses and without
|
||||
any set statement.(Match only)
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step(
|
||||
"Create static routes(10.0.20.1/32) in R1 and redistribute to "
|
||||
"OSPF using route map."
|
||||
)
|
||||
# Create Static routes
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 1, "next_hop": "Null0",}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
ospf_red_r0 = {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "static", "route_map": "rmap_ipv4"}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red_r0)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
# Create ip prefix list
|
||||
pfx_list = {
|
||||
"r0": {
|
||||
"prefix_lists": {
|
||||
"ipv4": {
|
||||
"pf_list_1_ipv4": [
|
||||
{"seqid": 10, "network": "any", "action": "permit"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_prefix_lists(tgen, pfx_list)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that prefix-list is created in R0.")
|
||||
result = verify_prefix_lists(tgen, pfx_list)
|
||||
assert result is not True, (
|
||||
"Testcase {} : Failed \n Prefix list not "
|
||||
"present. Error: {}".format(tc_name, result)
|
||||
)
|
||||
|
||||
# Create route map
|
||||
routemaps = {
|
||||
"r0": {
|
||||
"route_maps": {
|
||||
"rmap_ipv4": [
|
||||
{
|
||||
"action": "permit",
|
||||
"match": {"ipv4": {"prefix_lists": "pf_list_1_ipv4"}},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that metric falls back to original metric for ospf routes.")
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Create static routes(10.0.20.1/32) in R1 and redistribute to "
|
||||
"OSPF using route map."
|
||||
)
|
||||
# Create Static routes
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": NETWORK["ipv4"][1],
|
||||
"no_of_ip": 1,
|
||||
"next_hop": "Null0",
|
||||
"tag": 1000,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
# Create ip prefix list
|
||||
pfx_list = {
|
||||
"r0": {
|
||||
"prefix_lists": {
|
||||
"ipv4": {
|
||||
"pf_list_1_ipv4": [
|
||||
{"seqid": 10, "network": "any", "action": "permit"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_prefix_lists(tgen, pfx_list)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that prefix-list is created in R0.")
|
||||
result = verify_prefix_lists(tgen, pfx_list)
|
||||
assert result is not True, (
|
||||
"Testcase {} : Failed \n Prefix list not "
|
||||
"present. Error: {}".format(tc_name, result)
|
||||
)
|
||||
|
||||
# Create route map
|
||||
routemaps = {
|
||||
"r0": {
|
||||
"route_maps": {
|
||||
"rmap_ipv4": [{"action": "permit", "match": {"ipv4": {"tag": "1000"}}}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that metric falls back to original metric for ospf routes.")
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the match clause with tag in route map")
|
||||
# Create route map
|
||||
routemaps = {
|
||||
"r0": {
|
||||
"route_maps": {
|
||||
"rmap_ipv4": [
|
||||
{
|
||||
"action": "permit",
|
||||
"match": {"ipv4": {"tag": "1000", "delete": True}},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that metric falls back to original metric for ospf routes.")
|
||||
dut = "r1"
|
||||
protocol = "ospf"
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the match clause with metric in route map.")
|
||||
|
||||
# Create route map
|
||||
routemaps = {
|
||||
"r0": {
|
||||
"route_maps": {
|
||||
"rmap_ipv4": [
|
||||
{
|
||||
"action": "permit",
|
||||
"match": {"ipv4": {"prefix_lists": "pf_list_1_ipv4"}},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_route_maps(tgen, routemaps)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
612
tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
Normal file
612
tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
Normal file
@ -0,0 +1,612 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import ipaddress
|
||||
import json
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
create_interfaces_cfg,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
step,
|
||||
shutdown_bringup_interface,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.bgp import verify_bgp_convergence, create_router_bgp
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
)
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
|
||||
# number of retries.
|
||||
nretry = 5
|
||||
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_rte_calc.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
NETWORK = {
|
||||
"ipv4": [
|
||||
"11.0.20.1/32",
|
||||
"11.0.20.2/32",
|
||||
"11.0.20.3/32",
|
||||
"11.0.20.4/32",
|
||||
"11.0.20.5/32",
|
||||
]
|
||||
}
|
||||
TOPOOLOGY = """
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
"""
|
||||
|
||||
TESTCASES = """
|
||||
1. Test OSPF intra area route calculations.
|
||||
2. Test OSPF inter area route calculations.
|
||||
3. Test OSPF redistribution of connected routes.
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
def red_static(dut, config=True):
|
||||
"""Local def for Redstribute static routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "static", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase : Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
def red_connected(dut, config=True):
|
||||
"""Local def for Redstribute connected routes inside ospf."""
|
||||
global topo
|
||||
tgen = get_topogen()
|
||||
if config:
|
||||
ospf_red = {dut: {"ospf": {"redistribute": [{"redist_type": "connected"}]}}}
|
||||
else:
|
||||
ospf_red = {
|
||||
dut: {
|
||||
"ospf": {
|
||||
"redistribute": [{"redist_type": "connected", "del_action": True}]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase: Failed \n Error: {}".format(result)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_redistribution_tc5_p0(request):
|
||||
"""Test OSPF intra area route calculations."""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step("Verify that OSPF neighbors are FULL.")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("verify intra area route is calculated for r0-r3 interface ip in R1")
|
||||
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
|
||||
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
input_dict = {
|
||||
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the ip address on newly configured interface of R0")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r1"
|
||||
for num in range(0, nretry):
|
||||
result = verify_ospf_rib(
|
||||
tgen, dut, input_dict, next_hop=nh, expected=False)
|
||||
if result is not True:
|
||||
break
|
||||
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen,
|
||||
"ipv4",
|
||||
dut,
|
||||
input_dict,
|
||||
protocol=protocol,
|
||||
next_hop=nh,
|
||||
attempts=5,
|
||||
expected=False,
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Add back the deleted ip address on newly configured interface of R0")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Shut no shut interface on R0")
|
||||
dut = "r0"
|
||||
intf = topo["routers"]["r0"]["links"]["r3"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
step("un shut the OSPF interface on R0")
|
||||
dut = "r0"
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_redistribution_tc6_p0(request):
|
||||
"""Test OSPF inter area route calculations."""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step("Verify that OSPF neighbors are FULL.")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("verify intra area route is calculated for r0-r3 interface ip in R1")
|
||||
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
|
||||
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
input_dict = {
|
||||
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the ip address on newly configured loopback of R0")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r1"
|
||||
for num in range(0, nretry):
|
||||
result = verify_ospf_rib(
|
||||
tgen, dut, input_dict, next_hop=nh, expected=False)
|
||||
if result is not True:
|
||||
break
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(
|
||||
tgen,
|
||||
"ipv4",
|
||||
dut,
|
||||
input_dict,
|
||||
protocol=protocol,
|
||||
next_hop=nh,
|
||||
expected=False,
|
||||
)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Add back the deleted ip address on newly configured interface of R0")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Shut no shut interface on R0")
|
||||
dut = "r0"
|
||||
intf = topo["routers"]["r0"]["links"]["r3"]["interface"]
|
||||
shutdown_bringup_interface(tgen, dut, intf, False)
|
||||
|
||||
step("un shut the OSPF interface on R0")
|
||||
dut = "r0"
|
||||
shutdown_bringup_interface(tgen, dut, intf, True)
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "ospf"
|
||||
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_redistribution_tc8_p1(request):
|
||||
"""
|
||||
Test OSPF redistribution of connected routes.
|
||||
|
||||
Verify OSPF redistribution of connected routes when bgp multi hop
|
||||
neighbor is configured using ospf routes
|
||||
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
global topo
|
||||
step("Bring up the base config.")
|
||||
step(
|
||||
"Configure loopback interface on all routers, and redistribut"
|
||||
"e connected routes into ospf"
|
||||
)
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step(
|
||||
"verify that connected routes -loopback is found in all routers"
|
||||
"advertised/exchaged via ospf"
|
||||
)
|
||||
for rtr in topo["routers"]:
|
||||
red_static(rtr)
|
||||
red_connected(rtr)
|
||||
for node in topo["routers"]:
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{
|
||||
"network": topo["routers"][node]["links"]["lo"]["ipv4"],
|
||||
"no_of_ip": 1,
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
for rtr in topo["routers"]:
|
||||
result = verify_rib(tgen, "ipv4", rtr, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Configure E BGP multi hop using the loopback addresses.")
|
||||
as_num = 100
|
||||
for node in topo["routers"]:
|
||||
as_num += 1
|
||||
topo["routers"][node].update(
|
||||
{
|
||||
"bgp": {
|
||||
"local_as": as_num,
|
||||
"address_family": {"ipv4": {"unicast": {"neighbor": {}}}},
|
||||
}
|
||||
}
|
||||
)
|
||||
for node in topo["routers"]:
|
||||
for rtr in topo["routers"]:
|
||||
if node is not rtr:
|
||||
topo["routers"][node]["bgp"]["address_family"]["ipv4"]["unicast"][
|
||||
"neighbor"
|
||||
].update(
|
||||
{
|
||||
rtr: {
|
||||
"dest_link": {
|
||||
"lo": {"source_link": "lo", "ebgp_multihop": 2}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
result = create_router_bgp(tgen, topo, topo["routers"])
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Verify that BGP neighbor is ESTABLISHED")
|
||||
result = verify_bgp_convergence(tgen, topo)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
step(
|
||||
"Configure couple of static routes in R0 and "
|
||||
"Redistribute static routes in R1 bgp."
|
||||
)
|
||||
|
||||
for rtr in topo["routers"]:
|
||||
ospf_red = {
|
||||
rtr: {"ospf": {"redistribute": [{"redist_type": "static", "delete": True}]}}
|
||||
}
|
||||
result = create_router_ospf(tgen, topo, ospf_red)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"static_routes": [
|
||||
{"network": NETWORK["ipv4"][0], "no_of_ip": 5, "next_hop": "Null0",}
|
||||
]
|
||||
}
|
||||
}
|
||||
result = create_static_routes(tgen, input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
configure_bgp_on_r0 = {
|
||||
"r0": {
|
||||
"bgp": {
|
||||
"address_family": {
|
||||
"ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = create_router_bgp(tgen, topo, configure_bgp_on_r0)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
protocol = "bgp"
|
||||
for rtr in ["r1", "r2", "r3"]:
|
||||
result = verify_rib(tgen, "ipv4", rtr, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Clear ospf neighbours in R0")
|
||||
for rtr in topo["routers"]:
|
||||
clear_ospf(tgen, rtr)
|
||||
|
||||
step("Verify that OSPF neighbours are reset and forms new adjacencies.")
|
||||
# Api call verify whether OSPF is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("Verify that BGP neighbours are reset and forms new adjacencies.")
|
||||
result = verify_bgp_convergence(tgen, topo)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
protocol = "bgp"
|
||||
for rtr in ["r1", "r2", "r3"]:
|
||||
result = verify_rib(tgen, "ipv4", rtr, input_dict, protocol=protocol)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
@ -0,0 +1,781 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
#
|
||||
# Copyright (c) 2020 by VMware, Inc. ("VMware")
|
||||
# Used Copyright (c) 2018 by Network Device Education Foundation, Inc.
|
||||
# ("NetDEF") in this file.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
|
||||
"""OSPF Basic Functionality Automation."""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import pytest
|
||||
import json
|
||||
from copy import deepcopy
|
||||
from ipaddress import IPv4Address
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
sys.path.append(os.path.join(CWD, "../lib/"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from mininet.topo import Topo
|
||||
from lib.topogen import Topogen, get_topogen
|
||||
import ipaddress
|
||||
|
||||
# Import topoJson from lib, to create topology and initial configuration
|
||||
from lib.common_config import (
|
||||
start_topology,
|
||||
write_test_header,
|
||||
write_test_footer,
|
||||
reset_config_on_routers,
|
||||
verify_rib,
|
||||
create_static_routes,
|
||||
step,
|
||||
create_route_maps,
|
||||
shutdown_bringup_interface,
|
||||
create_interfaces_cfg,
|
||||
topo_daemons
|
||||
)
|
||||
from lib.topolog import logger
|
||||
from lib.topojson import build_topo_from_json, build_config_from_json
|
||||
|
||||
from lib.ospf import (
|
||||
verify_ospf_neighbor,
|
||||
config_ospf_interface,
|
||||
clear_ospf,
|
||||
verify_ospf_rib,
|
||||
create_router_ospf,
|
||||
verify_ospf_interface,
|
||||
verify_ospf_database,
|
||||
)
|
||||
|
||||
# Global variables
|
||||
topo = None
|
||||
|
||||
# Reading the data from JSON File for topology creation
|
||||
jsonFile = "{}/ospf_single_area.json".format(CWD)
|
||||
try:
|
||||
with open(jsonFile, "r") as topoJson:
|
||||
topo = json.load(topoJson)
|
||||
except IOError:
|
||||
assert False, "Could not read file {}".format(jsonFile)
|
||||
|
||||
"""
|
||||
TOPOOLOGY =
|
||||
Please view in a fixed-width font such as Courier.
|
||||
+---+ A1 +---+
|
||||
+R1 +------------+R2 |
|
||||
+-+-+- +--++
|
||||
| -- -- |
|
||||
| -- A0 -- |
|
||||
A0| ---- |
|
||||
| ---- | A2
|
||||
| -- -- |
|
||||
| -- -- |
|
||||
+-+-+- +-+-+
|
||||
+R0 +-------------+R3 |
|
||||
+---+ A3 +---+
|
||||
|
||||
TESTCASES =
|
||||
1. OSPF IFSM -Verify state change events on p2p network.
|
||||
2. OSPF Timers - Verify OSPF interface timer hello interval functionality
|
||||
3. OSPF Timers - Verify OSPF interface timer dead interval functionality
|
||||
4. Verify ospf show commands with json output.
|
||||
"""
|
||||
|
||||
|
||||
class CreateTopo(Topo):
|
||||
"""
|
||||
Test topology builder.
|
||||
|
||||
* `Topo`: Topology object
|
||||
"""
|
||||
|
||||
def build(self, *_args, **_opts):
|
||||
"""Build function."""
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Building topology from json file
|
||||
build_topo_from_json(tgen, topo)
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
"""
|
||||
Sets up the pytest environment
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
global topo
|
||||
testsuite_run_time = time.asctime(time.localtime(time.time()))
|
||||
logger.info("Testsuite start time: {}".format(testsuite_run_time))
|
||||
logger.info("=" * 40)
|
||||
|
||||
logger.info("Running setup_module to create topology")
|
||||
|
||||
# This function initiates the topology build with Topogen...
|
||||
tgen = Topogen(CreateTopo, mod.__name__)
|
||||
# ... and here it calls Mininet initialization functions.
|
||||
|
||||
# get list of daemons needs to be started for this suite.
|
||||
daemons = topo_daemons(tgen, topo)
|
||||
|
||||
# Starting topology, create tmp files which are loaded to routers
|
||||
# to start deamons and then start routers
|
||||
start_topology(tgen, daemons)
|
||||
|
||||
# Creating configuration from JSON
|
||||
build_config_from_json(tgen, topo)
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
logger.info("Running setup_module() done")
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
"""
|
||||
Teardown the pytest environment.
|
||||
|
||||
* `mod`: module name
|
||||
"""
|
||||
|
||||
logger.info("Running teardown_module to delete topology")
|
||||
|
||||
tgen = get_topogen()
|
||||
|
||||
# Stop toplogy and Remove tmp files
|
||||
tgen.stop_topology()
|
||||
|
||||
logger.info(
|
||||
"Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
|
||||
)
|
||||
logger.info("=" * 40)
|
||||
|
||||
|
||||
# ##################################
|
||||
# Test cases start here.
|
||||
# ##################################
|
||||
|
||||
|
||||
def test_ospf_p2p_tc3_p0(request):
|
||||
"""OSPF IFSM -Verify state change events on p2p network."""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
step(
|
||||
"Verify that OSPF is subscribed to multi cast services "
|
||||
"(All SPF, all DR Routers)."
|
||||
)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
step("Verify that config is successful.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {"ospf": {"mcastMemberOspfAllRouters": True, "ospfEnabled": True}}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Delete the ip address")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo["routers"]["r0"]["links"]["r3"]["ipv4"],
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ip on the R0 interface")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(intf_ip.split("/")[1])
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ospf": {
|
||||
"ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
|
||||
"r3"
|
||||
]["ipv4"].split("/")[0],
|
||||
"ipAddressPrefixlen": int(
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
|
||||
"ipv4"
|
||||
].split("/")[1]
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Modify the mask on the R0 interface")
|
||||
ip_addr = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
mask = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
step("Delete the ip address")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": ip_addr,
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("Change the ip on the R0 interface")
|
||||
|
||||
topo_modify_change_ip = deepcopy(topo)
|
||||
intf_ip = topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["r3"]["ipv4"] = str(
|
||||
IPv4Address(unicode(intf_ip.split("/")[0])) + 3
|
||||
) + "/{}".format(int(intf_ip.split("/")[1]) + 1)
|
||||
|
||||
build_config_from_json(tgen, topo_modify_change_ip, save_bkup=False)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ospf": {
|
||||
"ipAddress": topo_modify_change_ip["routers"]["r0"]["links"][
|
||||
"r3"
|
||||
]["ipv4"].split("/")[0],
|
||||
"ipAddressPrefixlen": int(
|
||||
topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
|
||||
"ipv4"
|
||||
].split("/")[1]
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"ipv4": topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
|
||||
"ipv4"
|
||||
],
|
||||
"interface": topo_modify_change_ip["routers"]["r0"]["links"]["r3"][
|
||||
"interface"
|
||||
],
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
build_config_from_json(tgen, topo, save_bkup=False)
|
||||
|
||||
step("Change the area id on the interface")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"ospf": {"area": "0.0.0.0"},
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"ospf": {"area": "0.0.0.1"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
step("Verify that interface is enabled in ospf.")
|
||||
dut = "r0"
|
||||
input_dict = {
|
||||
"r0": {"links": {"r3": {"ospf": {"area": "0.0.0.1", "ospfEnabled": True}}}}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"ospf": {"area": "0.0.0.1"},
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r3": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
|
||||
"ospf": {"area": "0.0.0.0"},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, input_dict)
|
||||
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
# Api call verify whether BGP is converged
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_hello_tc10_p0(request):
|
||||
"""
|
||||
OSPF timers.
|
||||
|
||||
Verify OSPF interface timer hello interval functionality
|
||||
"""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step("Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
step("modify hello timer from default value to some other value on r1")
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 11, "dead_interval": 12},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"verify that new timer value is configured and applied using "
|
||||
"the show ip ospf interface command."
|
||||
)
|
||||
dut = "r1"
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"links": {"r0": {"ospf": {"timerMsecs": 11 * 1000, "timerDeadSecs": 12}}}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("modify hello timer from default value to r1 hello timer on r2")
|
||||
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 11, "dead_interval": 12},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that new timer value is configured.")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {"r1": {"ospf": {"timerMsecs": 11 * 1000, "timerDeadSecs": 12}}}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that ospf neighbours are full")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("reconfigure the default hello timer value to default on r1 and r2")
|
||||
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 10, "dead_interval": 40},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 10, "dead_interval": 40},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that new timer value is configured.")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {"r1": {"ospf": {"timerMsecs": 10 * 1000, "timerDeadSecs": 40}}}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that ospf neighbours are full")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("reconfigure the default hello timer value to default on r1 and r2")
|
||||
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 10, "dead_interval": 40},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 10, "dead_interval": 40},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that new timer value is configured.")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {"r1": {"ospf": {"timerMsecs": 10 * 1000, "timerDeadSecs": 40}}}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that ospf neighbours are full")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step("configure hello timer = 1 on r1 and r2")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 1, "dead_interval": 4},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 1, "dead_interval": 4},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that new timer value is configured.")
|
||||
input_dict = {
|
||||
"r0": {"links": {"r1": {"ospf": {"timerMsecs": 1 * 1000, "timerDeadSecs": 4}}}}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that ospf neighbours are full")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(" Configure hello timer = 65535")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 65535, "dead_interval": 4},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 65535, "dead_interval": 4},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that new timer value is configured.")
|
||||
input_dict = {
|
||||
"r0": {
|
||||
"links": {"r1": {"ospf": {"timerMsecs": 65535 * 1000, "timerDeadSecs": 4}}}
|
||||
}
|
||||
}
|
||||
dut = "r0"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step("verify that ospf neighbours are full")
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
|
||||
step(" Try configuring timer values outside range for example 65536")
|
||||
topo1 = {
|
||||
"r0": {
|
||||
"links": {
|
||||
"r1": {
|
||||
"interface": topo["routers"]["r0"]["links"]["r1"]["interface"],
|
||||
"ospf": {"hello_interval": 65536, "dead_interval": 4},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is not True, "Testcase {} : Failed \n Error: {}".format(
|
||||
tc_name, result
|
||||
)
|
||||
|
||||
step("Unconfigure the hello timer from the interface from r1 and r2.")
|
||||
|
||||
topo1 = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"interface": topo["routers"]["r1"]["links"]["r0"]["interface"],
|
||||
"ospf": {"hello_interval": 65535},
|
||||
"delete": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = create_interfaces_cfg(tgen, topo1)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
step(
|
||||
"Verify that timer value is deleted from intf & " "set to default value 40 sec."
|
||||
)
|
||||
input_dict = {"r1": {"links": {"r0": {"ospf": {"timerMsecs": 10 * 1000}}}}}
|
||||
dut = "r1"
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
def test_ospf_show_p1(request):
|
||||
"""Verify ospf show commands with json output."""
|
||||
tc_name = request.node.name
|
||||
write_test_header(tc_name)
|
||||
tgen = get_topogen()
|
||||
|
||||
# Don't run this test if we have any failure.
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
global topo
|
||||
step(" Bring up the base config as per the topology")
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
ospf_covergence = verify_ospf_neighbor(tgen, topo)
|
||||
assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
|
||||
ospf_covergence
|
||||
)
|
||||
dut = "r1"
|
||||
input_dict = {
|
||||
"r1": {
|
||||
"links": {
|
||||
"r0": {
|
||||
"ospf": {
|
||||
"ifUp": True,
|
||||
"ifFlags": "<UP,BROADCAST,RUNNING,MULTICAST>",
|
||||
"ospfEnabled": True,
|
||||
"ipAddressPrefixlen": 24,
|
||||
"ospfIfType": "Broadcast",
|
||||
"area": "0.0.0.0",
|
||||
"networkType": "BROADCAST",
|
||||
"cost": 10,
|
||||
"transmitDelaySecs": 1,
|
||||
"state": "DR",
|
||||
"priority": 1,
|
||||
"mcastMemberOspfAllRouters": True,
|
||||
"timerMsecs": 1000,
|
||||
"timerDeadSecs": 4,
|
||||
"timerWaitSecs": 4,
|
||||
"timerRetransmitSecs": 5,
|
||||
"nbrCount": 1,
|
||||
"nbrAdjacentCount": 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = verify_ospf_interface(tgen, topo, dut=dut, input_dict=input_dict)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
# show ip ospf route
|
||||
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
|
||||
ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
|
||||
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
|
||||
input_dict = {
|
||||
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
|
||||
}
|
||||
|
||||
dut = "r1"
|
||||
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
|
||||
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
|
||||
|
||||
write_test_footer(tc_name)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
Loading…
Reference in New Issue
Block a user