Operational: Add support for multiple next-hop for routes

This commit is contained in:
Mattias Walström
2024-01-08 10:04:44 +01:00
committed by Joachim Wiberg
parent c0e7a6c03c
commit 35d74cecd4
4 changed files with 68 additions and 35 deletions
+28 -13
View File
@@ -60,25 +60,41 @@ class Route:
self.prefix = data.get(f'ietf-{ip}-unicast-routing:destination-prefix', '') self.prefix = data.get(f'ietf-{ip}-unicast-routing:destination-prefix', '')
self.protocol = data.get('source-protocol','')[14:] self.protocol = data.get('source-protocol','')[14:]
self.pref = data.get('route-preference','') self.pref = data.get('route-preference','')
self.next_hop = []
interface = get_json_data(None, self.data, 'next-hop', 'outgoing-interface') next_hop_list=get_json_data(None, self.data, 'next-hop', 'next-hop-list')
address = get_json_data(None, self.data, 'next-hop', f'ietf-{ip}-unicast-routing:next-hop-address') if next_hop_list:
special = get_json_data(None, self.data, 'next-hop', 'special-next-hop') for nh in next_hop_list["next-hop"]:
if interface: if(nh.get(f"ietf-{ip}-unicast-routing:address")):
self.next_hop = interface self.next_hop.append(nh[f"ietf-{ip}-unicast-routing:address"])
elif address: elif(nh.get("outgoing-interface")):
self.next_hop = address self.next_hop.append(nh["outgoing-interface"])
elif special: else:
self.next_hop = special self.next_hop.append("unspecified")
else: else:
self.next_hop = "unspecified" interface = get_json_data(None, self.data, 'next-hop', 'outgoing-interface')
address = get_json_data(None, self.data, 'next-hop', f'ietf-{ip}-unicast-routing:next-hop-address')
special = get_json_data(None, self.data, 'next-hop', 'special-next-hop')
nh = ""
if interface:
self.nh = interface
elif address:
self.nh = address
elif special:
self.nh = special
else:
self.nh = "unspecified"
self.next_hop.append(nh)
def print(self): def print(self):
row = f"{self.prefix:<{PadRoute.prefix}}" row = f"{self.prefix:<{PadRoute.prefix}}"
row += f"{self.next_hop:<{PadRoute.next_hop}}" row += f"{self.next_hop[0]:<{PadRoute.next_hop}}"
row += f"{self.pref:>{PadRoute.pref}} " row += f"{self.pref:>{PadRoute.pref}} "
row += f"{self.protocol:<{PadRoute.protocol}}" row += f"{self.protocol:<{PadRoute.protocol}}"
print(row) print(row)
for nh in self.next_hop[1:]:
row = f"{'':<{PadRoute.prefix}}"
row += f"{nh:<{PadRoute.next_hop}}"
print(row)
class Software: class Software:
"""Software bundle class """ """Software bundle class """
@@ -384,7 +400,6 @@ def ietf_routing(json, ip="ipv4"):
continue; continue;
routes = get_json_data(None, rib, "routes", "route") routes = get_json_data(None, rib, "routes", "route")
if routes: if routes:
for r in routes: for r in routes:
route = Route(r, ip) route = Route(r, ip)
+23 -13
View File
@@ -129,7 +129,7 @@ def get_routes(routes, proto, data):
host_prefix_length="128" host_prefix_length="128"
for d in data: for d in data:
new = {} new = {}
next_hop = {}
if(d['dst'] == "default"): if(d['dst'] == "default"):
d['dst'] = default d['dst'] = default
if(d['dst'].find('/') == -1): if(d['dst'].find('/') == -1):
@@ -141,18 +141,28 @@ def get_routes(routes, proto, data):
else: else:
new['route-preference'] = 0 new['route-preference'] = 0
if d['type'] == "blackhole": if d.get('nexthops'):
next_hop['special-next-hop'] = "blackhole" next_hops = []
if d['type'] == "unreachable": for n in d.get('nexthops'):
next_hop['special-next-hop'] = "unreachable" next_hop = {}
if(n.get("dev")):
if d['type'] == "unicast": next_hop['outgoing-interface'] = n['dev']
if(d.get("gateway")): if(n.get("gateway")):
next_hop[f'ietf-{proto}-unicast-routing:next-hop-address'] = d['gateway'] next_hop[f'ietf-{proto}-unicast-routing:address'] = n['gateway']
elif(d.get("dev")): next_hops.append(next_hop)
next_hop['outgoing-interface'] = d['dev'] insert(new,'next-hop','next-hop-list','next-hop',next_hops)
else:
new['next-hop'] = next_hop next_hop = {}
if d['type'] == "blackhole":
next_hop['special-next-hop'] = "blackhole"
if d['type'] == "unreachable":
next_hop['special-next-hop'] = "unreachable"
if d['type'] == "unicast":
if(d.get("dev")):
next_hop['outgoing-interface'] = d['dev']
if(d.get("gateway")):
next_hop[f'ietf-{proto}-unicast-routing:next-hop-address'] = d['gateway']
new['next-hop'] = next_hop
out['route'].append(new) out['route'].append(new)
insert(routes, 'routes', out) insert(routes, 'routes', out)
@@ -130,9 +130,6 @@ module infix-routing {
deviation "/ietf-r:routing/ietf-r:ribs/ietf-r:rib/ietf-r:active-route" { deviation "/ietf-r:routing/ietf-r:ribs/ietf-r:rib/ietf-r:active-route" {
deviate not-supported; deviate not-supported;
} }
deviation "/ietf-r:routing/ietf-r:ribs/ietf-r:rib/ietf-r:routes/ietf-r:route/ietf-r:next-hop/ietf-r:next-hop-options/ietf-r:next-hop-list" {
deviate not-supported;
}
/* OSPF */ /* OSPF */
+17 -6
View File
@@ -7,18 +7,29 @@ def _get_routes(target, protocol):
return r.get("routes", {}).get("route",{}) return r.get("routes", {}).get("route",{})
return {} return {}
def _exist_route(target, prefix, nexthop, version,source_protocol): def _exist_route(target, prefix, nexthop, version, source_protocol):
routes = _get_routes(target, version) routes = _get_routes(target, version)
for r in routes: for r in routes:
if r["destination-prefix"] != prefix: if r["destination-prefix"] != prefix:
continue continue
if source_protocol and r.get("source-protocol") != source_protocol:
continue if not nexthop and not source_protocol: # Only want the route to exist
return True
if source_protocol and r.get("source-protocol") == source_protocol:
return True
nh = r["next-hop"] nh = r["next-hop"]
if nexthop and nh["next-hop-address"] != nexthop: next_hop_list = nh.get("next-hop-list")
continue if nexthop:
return True if next_hop_list:
for nhl in next_hop_list["next-hop"]:
address = nhl.get("address")
if address == nexthop:
return True
else:
if nh["next-hop-address"] == nexthop:
return True
return False return False
def ipv4_route_exist(target, prefix, nexthop=None,source_protocol=None): def ipv4_route_exist(target, prefix, nexthop=None,source_protocol=None):