mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
yanger: Move ietf-ospf implementation to separate module
This commit is contained in:
@@ -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
|
||||
@@ -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"}]}}
|
||||
Reference in New Issue
Block a user