mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 12:09:22 +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",
|
"route_maps": "! Route Maps Config\n",
|
||||||
"bgp": "! BGP Config\n",
|
"bgp": "! BGP Config\n",
|
||||||
"vrf": "! VRF Config\n",
|
"vrf": "! VRF Config\n",
|
||||||
|
"ospf": "! OSPF Config\n",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -684,7 +685,7 @@ def generate_support_bundle():
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def start_topology(tgen):
|
def start_topology(tgen, daemon=None):
|
||||||
"""
|
"""
|
||||||
Starting topology, create tmp files which are loaded to routers
|
Starting topology, create tmp files which are loaded to routers
|
||||||
to start deamons and then start routers
|
to start deamons and then start routers
|
||||||
@ -736,9 +737,16 @@ def start_topology(tgen):
|
|||||||
router.load_config(
|
router.load_config(
|
||||||
TopoRouter.RD_ZEBRA, "{}/{}/zebra.conf".format(TMPDIR, rname)
|
TopoRouter.RD_ZEBRA, "{}/{}/zebra.conf".format(TMPDIR, rname)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Loading empty bgpd.conf file to router, to start the bgp deamon
|
# Loading empty bgpd.conf file to router, to start the bgp deamon
|
||||||
router.load_config(TopoRouter.RD_BGP, "{}/{}/bgpd.conf".format(TMPDIR, rname))
|
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
|
# Starting routers
|
||||||
logger.info("Starting all routers once topology is created")
|
logger.info("Starting all routers once topology is created")
|
||||||
tgen.start_router()
|
tgen.start_router()
|
||||||
@ -811,6 +819,24 @@ def number_to_column(routerName):
|
|||||||
return ord(routerName[0]) - 97
|
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
|
# Common APIs, will be used by all protocols
|
||||||
#############################################
|
#############################################
|
||||||
@ -1394,6 +1420,58 @@ def create_interfaces_cfg(tgen, topo, build=False):
|
|||||||
else:
|
else:
|
||||||
interface_data.append("ipv6 address {}\n".format(intf_addr))
|
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(
|
result = create_common_configuration(
|
||||||
tgen, c_router, interface_data, "interface_config", build=build
|
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
|
from re import search as re_search
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import pytest
|
import pytest
|
||||||
|
import ipaddr
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
# Import topogen and topotest helpers
|
# Import topogen and topotest helpers
|
||||||
from lib.topolog import logger
|
from lib.topolog import logger
|
||||||
@ -41,7 +44,7 @@ from lib.common_config import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from lib.bgp import create_router_bgp
|
from lib.bgp import create_router_bgp
|
||||||
|
from lib.ospf import create_router_ospf
|
||||||
ROUTER_LIST = []
|
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))
|
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[:]
|
listRouters = ROUTER_LIST[:]
|
||||||
|
listSwitches = SWITCH_LIST[:]
|
||||||
|
listAllRouters = deepcopy(listRouters)
|
||||||
|
dictSwitches = {}
|
||||||
|
|
||||||
for routerN in ROUTER_LIST:
|
for routerN in ROUTER_LIST:
|
||||||
logger.info("Topo: Add router {}".format(routerN))
|
logger.info("Topo: Add router {}".format(routerN))
|
||||||
tgen.add_router(routerN)
|
tgen.add_router(routerN)
|
||||||
listRouters.append(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:
|
if "ipv4base" in topo:
|
||||||
ipv4Next = ipaddress.IPv4Address(topo["link_ip_start"]["ipv4"])
|
ipv4Next = ipaddress.IPv4Address(topo["link_ip_start"]["ipv4"])
|
||||||
ipv4Step = 2 ** (32 - topo["link_ip_start"]["v4mask"])
|
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):
|
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),
|
("bgp_community_list", create_bgp_community_lists),
|
||||||
("route_maps", create_route_maps),
|
("route_maps", create_route_maps),
|
||||||
("bgp", create_router_bgp),
|
("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