Commit 2b2ade7c authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Service component - L3NM gNMI OpenConfig Service Handler:

- Corrected static_routes structure and metrics management
parent a31cab6b
Loading
Loading
Loading
Loading
+13 −17
Original line number Diff line number Diff line
@@ -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))
+24 −10
Original line number Diff line number Diff line
@@ -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