yanger: Move ietf-ospf implementation to separate module

This commit is contained in:
Tobias Waldekranz
2025-01-10 09:57:40 +01:00
parent 8812ae7052
commit a0e4e813dd
4 changed files with 160 additions and 150 deletions
+156
View File
@@ -0,0 +1,156 @@
from .common import insert
from .host import HOST
def frr_to_ietf_neighbor_state(state):
"""Fetch OSPF neighbor state from Frr"""
state = state.split("/")[0]
if state == "TwoWay":
return "2-way"
return state.lower()
def add_routes(ospf):
"""Fetch OSPF routes from Frr"""
cmd = ['vtysh', '-c', "show ip ospf route json"]
data = HOST.run_json(cmd, default=[])
if data == []:
return # No OSPF routes available
routes = []
for prefix, info in data.items():
if prefix.find("/") == -1: # Ignore router IDs
continue
route = {}
route["prefix"] = prefix
nexthops = []
routetype = info["routeType"].split(" ")
if len(routetype) > 1:
if routetype[1] == "E1":
route["route-type"] = "external-1"
elif routetype[1] == "E2":
route["route-type"] = "external-2"
elif routetype[1] == "IA":
route["route-type"] = "inter-area"
elif routetype[0] == "N":
route["route-type"] = "intra-area"
for hop in info["nexthops"]:
nexthop = {}
if hop["ip"] != " ":
nexthop["next-hop"] = hop["ip"]
else:
nexthop["outgoing-interface"] = hop["directlyAttachedTo"]
nexthops.append(nexthop)
route["next-hops"] = {}
route["next-hops"]["next-hop"] = nexthops
routes.append(route)
insert(ospf, "ietf-ospf:local-rib", "ietf-ospf:route", routes)
def add_areas(control_protocols):
"""Populate OSPF status"""
cmd = ['/usr/libexec/statd/ospf-status']
data = HOST.run_json(cmd, default={})
if data == {}:
return # No OSPF data available
control_protocol = {}
control_protocol["type"] = "infix-routing:ospfv2"
control_protocol["name"] = "default"
control_protocol["ietf-ospf:ospf"] = {}
control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"] = {}
control_protocol["ietf-ospf:ospf"]["ietf-ospf:router-id"] = data.get("routerId")
control_protocol["ietf-ospf:ospf"]["ietf-ospf:address-family"] = "ipv4"
areas = []
for area_id, values in data.get("areas", {}).items():
area = {}
area["ietf-ospf:area-id"] = area_id
area["ietf-ospf:interfaces"] = {}
if values.get("area-type"):
area["ietf-ospf:area-type"] = values["area-type"]
interfaces = []
for iface in values.get("interfaces", {}):
interface = {}
interface["ietf-ospf:neighbors"] = {}
interface["name"] = iface["name"]
if iface.get("drId"):
interface["dr-router-id"] = iface["drId"]
if iface.get("drAddress"):
interface["dr-ip-addr"] = iface["drAddress"]
if iface.get("bdrId"):
interface["bdr-router-id"] = iface["bdrId"]
if iface.get("bdrAddress"):
interface["bdr-ip-addr"] = iface["bdrAddress"]
if iface.get("timerPassiveIface"):
interface["passive"] = True
else:
interface["passive"] = False
interface["enabled"] = iface["ospfEnabled"]
if iface["networkType"] == "POINTOPOINT":
interface["interface-type"] = "point-to-point"
if iface["networkType"] == "BROADCAST":
interface["interface-type"] = "broadcast"
if iface.get("state"):
# Wev've never seen "DependUpon", and has no entry in
# the YANG model, but is listed before down in Frr
xlate = {
"DependUpon": "down",
"Down": "down",
"Waiting": "waiting",
"Loopback": "loopback",
"Point-To-Point": "point-to-point",
"DROther": "dr-other",
"Backup": "bdr",
"DR": "dr"
}
val = xlate.get(iface["state"], "unknown")
interface["state"] = val
neighbors = []
for neigh in iface["neighbors"]:
neighbor = {}
neighbor["neighbor-router-id"] = neigh["neighborIp"]
neighbor["address"] = neigh["ifaceAddress"]
neighbor["dead-timer"] = neigh["routerDeadIntervalTimerDueMsec"]
neighbor["state"] = frr_to_ietf_neighbor_state(neigh["nbrState"])
if neigh.get("routerDesignatedId"):
neighbor["dr-router-id"] = neigh["routerDesignatedId"]
if neigh.get("routerDesignatedBackupId"):
neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"]
neighbors.append(neighbor)
interface["ietf-ospf:neighbors"] = {}
interface["ietf-ospf:neighbors"]["ietf-ospf:neighbor"] = neighbors
interfaces.append(interface)
area["ietf-ospf:interfaces"]["ietf-ospf:interface"] = interfaces
areas.append(area)
add_routes(control_protocol["ietf-ospf:ospf"])
control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"]["ietf-ospf:area"] = areas
insert(control_protocols, "control-plane-protocol", [control_protocol])
def operational():
out = {
"ietf-routing:routing": {
"control-plane-protocols": {
}
}
}
add_areas(out['ietf-routing:routing']['control-plane-protocols'])
return out
+2 -150
View File
@@ -307,148 +307,6 @@ def add_ipv6_route(routes):
get_routes(routes, "ipv6", data)
def frr_to_ietf_neighbor_state(state):
"""Fetch OSPF neighbor state from Frr"""
state = state.split("/")[0]
if state == "TwoWay":
return "2-way"
return state.lower()
def add_ospf_routes(ospf):
"""Fetch OSPF routes from Frr"""
cmd = ['vtysh', '-c', "show ip ospf rout json"]
data = run_json_cmd(cmd, "", check=False, default=[])
if data == []:
return # No OSPF routes available
routes = []
for prefix, info in data.items():
if prefix.find("/") == -1: # Ignore router IDs
continue
route = {}
route["prefix"] = prefix
nexthops = []
routetype = info["routeType"].split(" ")
if len(routetype) > 1:
if routetype[1] == "E1":
route["route-type"] = "external-1"
elif routetype[1] == "E2":
route["route-type"] = "external-2"
elif routetype[1] == "IA":
route["route-type"] = "inter-area"
elif routetype[0] == "N":
route["route-type"] = "intra-area"
for hop in info["nexthops"]:
nexthop = {}
if hop["ip"] != " ":
nexthop["next-hop"] = hop["ip"]
else:
nexthop["outgoing-interface"] = hop["directlyAttachedTo"]
nexthops.append(nexthop)
route["next-hops"] = {}
route["next-hops"]["next-hop"] = nexthops
routes.append(route)
insert(ospf, "ietf-ospf:local-rib", "ietf-ospf:route", routes)
def add_ospf(control_protocols):
"""Populate OSPF status"""
cmd = ['/usr/libexec/statd/ospf-status']
data = run_json_cmd(cmd, "", check=False, default={})
if data == {}:
return # No OSPF data available
control_protocol = {}
control_protocol["type"] = "infix-routing:ospfv2"
control_protocol["name"] = "default"
control_protocol["ietf-ospf:ospf"] = {}
control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"] = {}
control_protocol["ietf-ospf:ospf"]["ietf-ospf:router-id"] = data.get("routerId")
control_protocol["ietf-ospf:ospf"]["ietf-ospf:address-family"] = "ipv4"
areas = []
for area_id, values in data.get("areas", {}).items():
area = {}
area["ietf-ospf:area-id"] = area_id
area["ietf-ospf:interfaces"] = {}
if values.get("area-type"):
area["ietf-ospf:area-type"] = values["area-type"]
interfaces = []
for iface in values.get("interfaces", {}):
interface = {}
interface["ietf-ospf:neighbors"] = {}
interface["name"] = iface["name"]
if iface.get("drId"):
interface["dr-router-id"] = iface["drId"]
if iface.get("drAddress"):
interface["dr-ip-addr"] = iface["drAddress"]
if iface.get("bdrId"):
interface["bdr-router-id"] = iface["bdrId"]
if iface.get("bdrAddress"):
interface["bdr-ip-addr"] = iface["bdrAddress"]
if iface.get("timerPassiveIface"):
interface["passive"] = True
else:
interface["passive"] = False
interface["enabled"] = iface["ospfEnabled"]
if iface["networkType"] == "POINTOPOINT":
interface["interface-type"] = "point-to-point"
if iface["networkType"] == "BROADCAST":
interface["interface-type"] = "broadcast"
if iface.get("state"):
# Wev've never seen "DependUpon", and has no entry in
# the YANG model, but is listed before down in Frr
xlate = {
"DependUpon": "down",
"Down": "down",
"Waiting": "waiting",
"Loopback": "loopback",
"Point-To-Point": "point-to-point",
"DROther": "dr-other",
"Backup": "bdr",
"DR": "dr"
}
val = xlate.get(iface["state"], "unknown")
interface["state"] = val
neighbors = []
for neigh in iface["neighbors"]:
neighbor = {}
neighbor["neighbor-router-id"] = neigh["neighborIp"]
neighbor["address"] = neigh["ifaceAddress"]
neighbor["dead-timer"] = neigh["routerDeadIntervalTimerDueMsec"]
neighbor["state"] = frr_to_ietf_neighbor_state(neigh["nbrState"])
if neigh.get("routerDesignatedId"):
neighbor["dr-router-id"] = neigh["routerDesignatedId"]
if neigh.get("routerDesignatedBackupId"):
neighbor["bdr-router-id"] = neigh["routerDesignatedBackupId"]
neighbors.append(neighbor)
interface["ietf-ospf:neighbors"] = {}
interface["ietf-ospf:neighbors"]["ietf-ospf:neighbor"] = neighbors
interfaces.append(interface)
area["ietf-ospf:interfaces"]["ietf-ospf:interface"] = interfaces
areas.append(area)
add_ospf_routes(control_protocol["ietf-ospf:ospf"])
control_protocol["ietf-ospf:ospf"]["ietf-ospf:areas"]["ietf-ospf:area"] = areas
insert(control_protocols, "control-plane-protocol", [control_protocol])
def get_bridge_port_pvid(ifname):
data = run_json_cmd(['bridge', '-j', 'vlan', 'show', 'dev', ifname],
f"bridge-vlan-show-dev-{ifname}.json")
@@ -1001,14 +859,8 @@ def main():
add_ipv6_route(ipv6routes)
elif args.model == 'ietf-ospf':
yang_data = {
"ietf-routing:routing": {
"control-plane-protocols": {
}
}
}
add_ospf(yang_data['ietf-routing:routing']['control-plane-protocols'])
from . import ietf_ospf
yang_data = ietf_ospf.operational()
elif args.model == 'ietf-hardware':
from . import ietf_hardware
yang_data = ietf_hardware.operational()
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"10.0.0.1/32":{"routeType":"N","transit":false,"cost":0,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"lo"}]},"10.0.0.2/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.0.3/32":{"routeType":"N","transit":false,"cost":2000,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"10.0.0.4/32":{"routeType":"N IA","cost":2001,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.12.0/30":{"routeType":"N","transit":true,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":" ","directlyAttachedTo":"e5"}]},"10.0.13.0/30":{"routeType":"N","transit":true,"cost":2000,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"e6"}]},"10.0.23.0/30":{"routeType":"N","transit":true,"cost":2001,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"10.0.24.0/30":{"routeType":"N IA","cost":2001,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"10.0.41.0/30":{"routeType":"N IA","cost":2002,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.8.1/32":{"routeType":"N","transit":false,"cost":0,"area":"0.0.0.1","nexthops":[{"ip":" ","directlyAttachedTo":"lo"}]},"11.0.9.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.10.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.11.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.12.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.13.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.14.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"11.0.15.1/32":{"routeType":"N","transit":false,"cost":1,"area":"0.0.0.0","nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]},"192.168.3.0/24":{"routeType":"N","transit":false,"cost":2001,"area":"0.0.0.1","nexthops":[{"ip":"10.0.13.2","via":"e6","advertisedRouter":"10.0.0.3"}]},"1.1.1.1":{"routeType":"R ","cost":1,"area":"0.0.0.0","routerType":"abr","nexthops":[{"ip":"10.0.12.2","via":"e5"}]},"10.0.0.4":{"routeType":"R ","cost":2001,"area":"0.0.0.0","IA":true,"ia":true,"routerType":"asbr","nexthops":[{"ip":"10.0.12.2","via":"e5"}]},"192.168.4.0/24":{"routeType":"N E2","cost":2001,"type2cost":20,"tag":0,"nexthops":[{"ip":"10.0.12.2","via":"e5","advertisedRouter":"1.1.1.1"}]}}