Example #1
0
def validate_route_nexthops(routes,
                            interfaces,
                            sources,
                            enable_color,
                            quiet=False):
    """
    Validate between fib routes and lm interfaces

    :param routes: list network_types.UnicastRoute (structured routes)
    :param interfaces: dict<interface-name, InterfaceDetail>
    """

    # record invalid routes in dict<error, list<route_db>>
    invalid_routes = defaultdict(list)

    # define error types
    MISSING_NEXTHOP = "Nexthop does not exist"
    INVALID_SUBNET = "Nexthop address is not in the same subnet as interface"
    INVALID_LINK_LOCAL = "Nexthop address is not link local"

    # return error type
    error_msg = []

    for route in routes:
        dest = ipnetwork.sprint_prefix(route.dest)
        # record invalid nexthops in dict<error, list<nexthops>>
        invalid_nexthop = defaultdict(list)
        for nextHop in get_route_nexthops(route):
            nh = nextHop.address
            if nh.ifName not in interfaces or not interfaces[
                    nh.ifName].info.isUp:
                invalid_nexthop[MISSING_NEXTHOP].append(
                    ip_nexthop_to_str(nextHop))
                continue
            # if nexthop addr is v4, make sure it belongs to same subnets as
            # interface addr
            if ipnetwork.ip_version(nh.addr) == 4:
                networks = interfaces[nh.ifName].info.networks
                if networks is None:
                    # maintain backward compatbility
                    networks = []
                for prefix in networks:
                    if ipnetwork.ip_version(
                            prefix.prefixAddress.addr
                    ) == 4 and not ipnetwork.is_same_subnet(
                            nh.addr, prefix.prefixAddress.addr, "31"):
                        invalid_nexthop[INVALID_SUBNET].append(
                            ip_nexthop_to_str(nextHop))
            # if nexthop addr is v6, make sure it's a link local addr
            elif ipnetwork.ip_version(
                    nh.addr) == 6 and not ipnetwork.is_link_local(nh.addr):
                invalid_nexthop[INVALID_LINK_LOCAL].append(
                    ip_nexthop_to_str(nextHop))

        # build routes per error type
        for k, v in invalid_nexthop.items():
            invalid_routes[k].extend(build_routes([dest], v))

    # if all good, then return early
    if not invalid_routes:
        if not quiet:
            if enable_color:
                click.echo(click.style("PASS", bg="green", fg="black"))
            else:
                click.echo("PASS")
            print("Route validation successful")
        return True, error_msg

    # Something failed.. report it
    if not quiet:
        if enable_color:
            click.echo(click.style("FAIL", bg="red", fg="black"))
        else:
            click.echo("FAIL")
        print("Route validation failed")
    # Output report per error type
    for err, route_db in invalid_routes.items():
        caption = "Error: {}".format(err)
        if not quiet:
            print_unicast_routes(caption, route_db)
        else:
            error_msg.append(caption)

    return False, error_msg
Example #2
0
def validate_route_nexthops(routes, interfaces, sources, enable_color,
                            quiet=False):
    '''
    Validate between fib routes and lm interfaces

    :param routes: list ip_types.UnicastRoute (structured routes)
    :param interfaces: dict<interface-name, InterfaceDetail>
    '''

    # record invalid routes in dict<error, list<route_db>>
    invalid_routes = defaultdict(list)

    # define error types
    MISSING_NEXTHOP = 'Nexthop does not exist'
    INVALID_SUBNET = 'Nexthop address is not in the same subnet as interface'
    INVALID_LINK_LOCAL = 'Nexthop address is not link local'

    # return error type
    error_msg = []

    for route in routes:
        dest = ipnetwork.sprint_prefix(route.dest)
        # record invalid nexthops in dict<error, list<nexthops>>
        invalid_nexthop = defaultdict(list)
        for nh in route.nexthops:
            if nh.ifName not in interfaces or not interfaces[nh.ifName].info.isUp:
                invalid_nexthop[MISSING_NEXTHOP].append(ip_nexthop_to_str(nh))
                continue
            # if nexthop addr is v4, make sure it belongs to same subnets as
            # interface addr
            if ipnetwork.ip_version(nh.addr) == 4:
                for addr in interfaces[nh.ifName].info.v4Addrs:
                    if not ipnetwork.is_same_subnet(nh.addr, addr.addr, '31'):
                        invalid_nexthop[INVALID_SUBNET].append(ip_nexthop_to_str(nh))
            # if nexthop addr is v6, make sure it's a link local addr
            elif (ipnetwork.ip_version(nh.addr) == 6 and
                  not ipnetwork.is_link_local(nh.addr)):
                invalid_nexthop[INVALID_LINK_LOCAL].append(ip_nexthop_to_str(nh))

        # build routes per error type
        for k, v in invalid_nexthop.items():
            invalid_routes[k].extend(build_routes([dest], v))

    # if all good, then return early
    if not invalid_routes:
        if not quiet:
            if enable_color:
                click.echo(click.style('PASS', bg='green', fg='black'))
            else:
                click.echo('PASS')
            print('Route validation successful')
        return True, error_msg

    # Something failed.. report it
    if not quiet:
        if enable_color:
            click.echo(click.style('FAIL', bg='red', fg='black'))
        else:
            click.echo('FAIL')
        print('Route validation failed')
    # Output report per error type
    for err, route_db in invalid_routes.items():
        caption = 'Error: {}'.format(err)
        if not quiet:
            print_routes(caption, route_db)
        else:
            error_msg.append(caption)

    return False, error_msg