From 2b2ade7ce06c98623ee870f147eb3825cb9f3667 Mon Sep 17 00:00:00 2001 From: gifrerenom <lluis.gifre@cttc.es> Date: Sat, 11 May 2024 17:14:59 +0000 Subject: [PATCH] Service component - L3NM gNMI OpenConfig Service Handler: - Corrected static_routes structure and metrics management --- .../ConfigRuleComposer.py | 30 +++++++--------- .../StaticRouteGenerator.py | 34 +++++++++++++------ 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py index 5db2c5b2f..42747a1ae 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/ConfigRuleComposer.py @@ -22,7 +22,7 @@ from service.service.service_handler_api.AnyTreeTools import TreeNode NETWORK_INSTANCE = 'teraflowsdn' RE_IF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$') -RE_SR = re.compile(r'^\/network_instance\[([^\]]+)\]\/protocols\[STATIC\]/route\[ ([^\:]+)\:([^\]]+)\]$') +RE_SR = re.compile(r'^\/network_instance\[([^\]]+)\]\/protocols\[STATIC\]/route\[([^\:]+)\:([^\]]+)\]$') def _interface( interface : str, if_type : Optional[str] = 'l3ipvlan', index : int = 0, vlan_id : Optional[int] = None, @@ -52,15 +52,15 @@ def _network_instance_protocol_static(ni_name : str) -> Tuple[str, Dict]: return _network_instance_protocol(ni_name, 'STATIC') def _network_instance_protocol_static_route( - ni_name : str, prefix : str, next_hop : str, index : int = 0, metric : Optional[int] = None + ni_name : str, prefix : str, next_hop : str, metric : int ) -> Tuple[str, Dict]: protocol = 'STATIC' - path = '/network_instance[{:s}]/protocols[{:s}]/static_route[{:s}:{:d}]'.format(ni_name, protocol, prefix, index) + path = '/network_instance[{:s}]/protocols[{:s}]/static_route[{:s}:{:d}]'.format(ni_name, protocol, prefix, metric) + index = 'AUTO_{:d}_{:s}'.format(metric, next_hop.replace('.', '-')) data = { 'name': ni_name, 'identifier': protocol, 'protocol_name': protocol, - 'prefix': prefix, 'index': index, 'next_hop': next_hop + 'prefix': prefix, 'index': index, 'next_hop': next_hop, 'metric': metric } - if metric is not None: data['metric'] = metric return path, data def _network_instance_interface(ni_name : str, interface : str, sub_interface_index : int) -> Tuple[str, Dict]: @@ -113,9 +113,7 @@ class DeviceComposer: self.objekt : Optional[Device] = None self.endpoints : Dict[str, EndpointComposer] = dict() self.connected : Set[str] = set() - - # {prefix => {index => (next_hop, metric)}} - self.static_routes : Dict[str, Dict[int, Tuple[str, Optional[int]]]] = dict() + self.static_routes : Dict[str, Dict[int, str]] = dict() # {prefix => {metric => next_hop}} def get_endpoint(self, endpoint_uuid : str) -> EndpointComposer: if endpoint_uuid not in self.endpoints: @@ -147,22 +145,20 @@ class DeviceComposer: match = RE_SR.match(config_rule_custom.resource_key) if match is not None: - ni_name, prefix, index = match.groups() + ni_name, prefix, metric = match.groups() if ni_name != NETWORK_INSTANCE: continue resource_value : Dict = json.loads(config_rule_custom.resource_value) next_hop = resource_value['next_hop'] - metric = resource_value.get('metric') - self.static_routes.setdefault(prefix, dict())[index] = (next_hop, metric) + self.static_routes.setdefault(prefix, dict())[metric] = next_hop if settings is None: return json_settings : Dict = settings.value static_routes : List[Dict] = json_settings.get('static_routes', []) for static_route in static_routes: prefix = static_route['prefix'] - index = static_route.get('index', 0) next_hop = static_route['next_hop'] - metric = static_route.get('metric') - self.static_routes.setdefault(prefix, dict())[index] = (next_hop, metric) + metric = static_route.get('metric', 0) + self.static_routes.setdefault(prefix, dict())[metric] = next_hop def get_config_rules(self, network_instance_name : str, delete : bool = False) -> List[Dict]: SELECTED_DEVICES = {DeviceTypeEnum.PACKET_ROUTER.value, DeviceTypeEnum.EMULATED_PACKET_ROUTER.value} @@ -178,11 +174,11 @@ class DeviceComposer: config_rules.append( json_config_rule(*_network_instance_protocol_static(network_instance_name)) ) - for prefix, indexed_static_rule in self.static_routes.items(): - for index, (next_hop, metric) in indexed_static_rule.items(): + for prefix, metric_next_hop in self.static_routes.items(): + for metric, next_hop in metric_next_hop.items(): config_rules.append( json_config_rule(*_network_instance_protocol_static_route( - network_instance_name, prefix, next_hop, index=index, metric=metric + network_instance_name, prefix, next_hop, metric )) ) if delete: config_rules = list(reversed(config_rules)) diff --git a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py index 6479a07fe..a16e4d5b1 100644 --- a/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py +++ b/src/service/service/service_handlers/l3nm_gnmi_openconfig/StaticRouteGenerator.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import json, logging, netaddr +import json, logging, netaddr, sys from typing import List, Optional, Tuple from .ConfigRuleComposer import ConfigRuleComposer @@ -153,7 +153,8 @@ class StaticRouteGenerator: if ip_network_a in ROOT_NEIGHBOR_ROUTING_NETWORK: continue endpoint_a_ip_network = _compose_ipv4_network(endpoint_a.ipv4_address, endpoint_a.ipv4_prefix_len) next_hop = str(endpoint_a_ip_network.ip) - device_b.static_routes.setdefault(ip_network_a, dict())[0] = (next_hop, None) + metric = 1 + device_b.static_routes.setdefault(ip_network_a, dict())[metric] = next_hop # Compute static routes from networks connected in device_b for ip_network_b in device_b.connected: @@ -162,22 +163,35 @@ class StaticRouteGenerator: if ip_network_b in ROOT_NEIGHBOR_ROUTING_NETWORK: continue endpoint_b_ip_network = _compose_ipv4_network(endpoint_b.ipv4_address, endpoint_b.ipv4_prefix_len) next_hop = str(endpoint_b_ip_network.ip) - device_a.static_routes.setdefault(ip_network_b, dict())[0] = (next_hop, None) + metric = 1 + device_a.static_routes.setdefault(ip_network_b, dict())[metric] = next_hop # Propagate static routes from networks connected in device_a - for ip_network_a in device_a.static_routes.keys(): + for ip_network_a, metric_next_hop in device_a.static_routes.items(): if ip_network_a in device_b.connected: continue - if ip_network_a in device_b.static_routes: continue if ip_network_a in ROOT_NEIGHBOR_ROUTING_NETWORK: continue endpoint_a_ip_network = _compose_ipv4_network(endpoint_a.ipv4_address, endpoint_a.ipv4_prefix_len) - next_hop = str(endpoint_a_ip_network.ip) - device_b.static_routes.setdefault(ip_network_a, dict())[0] = (next_hop, None) + if ip_network_a in device_b.static_routes: + current_metric = min(device_b.static_routes[ip_network_a].keys()) + else: + current_metric = int(sys.float_info.max) + for metric, next_hop in metric_next_hop.items(): + new_metric = metric + 1 + if new_metric >= current_metric: continue + next_hop_a = str(endpoint_a_ip_network.ip) + device_b.static_routes.setdefault(ip_network_a, dict())[metric] = next_hop_a # Propagate static routes from networks connected in device_b for ip_network_b in device_b.static_routes.keys(): if ip_network_b in device_a.connected: continue - if ip_network_b in device_a.static_routes: continue if ip_network_b in ROOT_NEIGHBOR_ROUTING_NETWORK: continue endpoint_b_ip_network = _compose_ipv4_network(endpoint_b.ipv4_address, endpoint_b.ipv4_prefix_len) - next_hop = str(endpoint_b_ip_network.ip) - device_a.static_routes.setdefault(ip_network_b, dict())[0] = (next_hop, None) + if ip_network_b in device_a.static_routes: + current_metric = min(device_a.static_routes[ip_network_b].keys()) + else: + current_metric = int(sys.float_info.max) + for metric, next_hop in metric_next_hop.items(): + new_metric = metric + 1 + if new_metric >= current_metric: continue + next_hop_b = str(endpoint_b_ip_network.ip) + device_a.static_routes.setdefault(ip_network_b, dict())[metric] = next_hop_b -- GitLab