@Test public void testNonExistentInterface() { NetworkFactory nf = new NetworkFactory(); Warnings warnings = new Warnings(true, true, true); IspModelingUtils.populateIspModels( nf.configurationBuilder().setHostname("conf").build(), ImmutableSet.of("init"), ImmutableList.of(), ImmutableList.of(), ImmutableList.of(), Maps.newHashMap(), warnings); assertThat( warnings.getRedFlagWarnings(), equalTo( ImmutableList.of( new Warning( "ISP Modeling: Cannot find interface init on node conf", TAG_RED_FLAG)))); }
@VisibleForTesting static void populateIspModels( @Nonnull Configuration remoteCfg, @Nonnull Set<String> remoteInterfaces, @Nonnull List<Ip> remoteIps, @Nonnull List<Long> remoteAsnsList, @Nonnull List<IspNodeInfo> ispNodeInfos, Map<Long, IspModel> allIspModels, @Nonnull Warnings warnings) { Set<Ip> remoteIpsSet = ImmutableSet.copyOf(remoteIps); LongSpace remoteAsns = remoteAsnsList.isEmpty() ? ALL_AS_NUMBERS : LongSpace.builder().includingAll(remoteAsnsList).build(); Map<String, Interface> lowerCasedInterfaces = remoteCfg.getAllInterfaces().entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Entry::getValue)); for (String remoteIfaceName : remoteInterfaces) { Interface remoteIface = lowerCasedInterfaces.get(remoteIfaceName.toLowerCase()); if (remoteIface == null) { warnings.redFlag( String.format( "ISP Modeling: Cannot find interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } Map<Ip, InterfaceAddress> ipToInterfaceAddresses = remoteIface.getAllAddresses().stream() .collect( ImmutableMap.toImmutableMap( addr -> addr instanceof ConcreteInterfaceAddress ? ((ConcreteInterfaceAddress) addr).getIp() : ((LinkLocalAddress) addr).getIp(), Function.identity())); List<BgpPeerConfig> validRemoteBgpPeerConfigs = remoteCfg.getVrfs().values().stream() .map(Vrf::getBgpProcess) .filter(Objects::nonNull) .flatMap( bgpProcess -> Streams.concat( bgpProcess.getActiveNeighbors().values().stream(), bgpProcess.getInterfaceNeighbors().values().stream())) .filter( bgpPeerConfig -> isValidBgpPeerConfig( bgpPeerConfig, ipToInterfaceAddresses.keySet(), remoteIpsSet, remoteAsns)) .collect(Collectors.toList()); if (validRemoteBgpPeerConfigs.isEmpty()) { warnings.redFlag( String.format( "ISP Modeling: Cannot find any valid eBGP configurations for interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } for (BgpPeerConfig bgpPeerConfig : validRemoteBgpPeerConfigs) { long asn = bgpPeerConfig.getRemoteAsns().least(); List<IspNodeInfo> matchingInfos = ispNodeInfos.stream().filter(i -> i.getAsn() == asn).collect(Collectors.toList()); @Nullable String ispName = matchingInfos.stream().map(IspNodeInfo::getName).findFirst().orElse(null); IspTrafficFiltering filtering = matchingInfos.stream() .map(IspNodeInfo::getIspTrafficFiltering) .filter(Objects::nonNull) .findFirst() .orElse(IspTrafficFiltering.blockReservedAddressesAtInternet()); Set<Prefix> additionalPrefixes = matchingInfos.stream() .flatMap( i -> i.getAdditionalAnnouncements().stream().map(IspAnnouncement::getPrefix)) .collect(ImmutableSet.toImmutableSet()); IspModel ispInfo = allIspModels.computeIfAbsent( asn, k -> IspModel.builder() .setAsn(asn) .setName(ispName) .setAdditionalPrefixesToInternet(additionalPrefixes) .setTrafficFiltering(filtering) .build()); InterfaceAddress interfaceAddress = bgpPeerConfig instanceof BgpActivePeerConfig ? ConcreteInterfaceAddress.create( ((BgpActivePeerConfig) bgpPeerConfig).getPeerAddress(), ((ConcreteInterfaceAddress) ipToInterfaceAddresses.get(bgpPeerConfig.getLocalIp())) .getNetworkBits()) : LINK_LOCAL_ADDRESS; ispInfo.addNeighbor( new Remote(remoteCfg.getHostname(), remoteIfaceName, interfaceAddress, bgpPeerConfig)); } } }
IspModelingUtils { @VisibleForTesting static void populateIspModels( @Nonnull Configuration remoteCfg, @Nonnull Set<String> remoteInterfaces, @Nonnull List<Ip> remoteIps, @Nonnull List<Long> remoteAsnsList, @Nonnull List<IspNodeInfo> ispNodeInfos, Map<Long, IspModel> allIspModels, @Nonnull Warnings warnings) { Set<Ip> remoteIpsSet = ImmutableSet.copyOf(remoteIps); LongSpace remoteAsns = remoteAsnsList.isEmpty() ? ALL_AS_NUMBERS : LongSpace.builder().includingAll(remoteAsnsList).build(); Map<String, Interface> lowerCasedInterfaces = remoteCfg.getAllInterfaces().entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Entry::getValue)); for (String remoteIfaceName : remoteInterfaces) { Interface remoteIface = lowerCasedInterfaces.get(remoteIfaceName.toLowerCase()); if (remoteIface == null) { warnings.redFlag( String.format( "ISP Modeling: Cannot find interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } Map<Ip, InterfaceAddress> ipToInterfaceAddresses = remoteIface.getAllAddresses().stream() .collect( ImmutableMap.toImmutableMap( addr -> addr instanceof ConcreteInterfaceAddress ? ((ConcreteInterfaceAddress) addr).getIp() : ((LinkLocalAddress) addr).getIp(), Function.identity())); List<BgpPeerConfig> validRemoteBgpPeerConfigs = remoteCfg.getVrfs().values().stream() .map(Vrf::getBgpProcess) .filter(Objects::nonNull) .flatMap( bgpProcess -> Streams.concat( bgpProcess.getActiveNeighbors().values().stream(), bgpProcess.getInterfaceNeighbors().values().stream())) .filter( bgpPeerConfig -> isValidBgpPeerConfig( bgpPeerConfig, ipToInterfaceAddresses.keySet(), remoteIpsSet, remoteAsns)) .collect(Collectors.toList()); if (validRemoteBgpPeerConfigs.isEmpty()) { warnings.redFlag( String.format( "ISP Modeling: Cannot find any valid eBGP configurations for interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } for (BgpPeerConfig bgpPeerConfig : validRemoteBgpPeerConfigs) { long asn = bgpPeerConfig.getRemoteAsns().least(); List<IspNodeInfo> matchingInfos = ispNodeInfos.stream().filter(i -> i.getAsn() == asn).collect(Collectors.toList()); @Nullable String ispName = matchingInfos.stream().map(IspNodeInfo::getName).findFirst().orElse(null); IspTrafficFiltering filtering = matchingInfos.stream() .map(IspNodeInfo::getIspTrafficFiltering) .filter(Objects::nonNull) .findFirst() .orElse(IspTrafficFiltering.blockReservedAddressesAtInternet()); Set<Prefix> additionalPrefixes = matchingInfos.stream() .flatMap( i -> i.getAdditionalAnnouncements().stream().map(IspAnnouncement::getPrefix)) .collect(ImmutableSet.toImmutableSet()); IspModel ispInfo = allIspModels.computeIfAbsent( asn, k -> IspModel.builder() .setAsn(asn) .setName(ispName) .setAdditionalPrefixesToInternet(additionalPrefixes) .setTrafficFiltering(filtering) .build()); InterfaceAddress interfaceAddress = bgpPeerConfig instanceof BgpActivePeerConfig ? ConcreteInterfaceAddress.create( ((BgpActivePeerConfig) bgpPeerConfig).getPeerAddress(), ((ConcreteInterfaceAddress) ipToInterfaceAddresses.get(bgpPeerConfig.getLocalIp())) .getNetworkBits()) : LINK_LOCAL_ADDRESS; ispInfo.addNeighbor( new Remote(remoteCfg.getHostname(), remoteIfaceName, interfaceAddress, bgpPeerConfig)); } } } }
IspModelingUtils { @VisibleForTesting static void populateIspModels( @Nonnull Configuration remoteCfg, @Nonnull Set<String> remoteInterfaces, @Nonnull List<Ip> remoteIps, @Nonnull List<Long> remoteAsnsList, @Nonnull List<IspNodeInfo> ispNodeInfos, Map<Long, IspModel> allIspModels, @Nonnull Warnings warnings) { Set<Ip> remoteIpsSet = ImmutableSet.copyOf(remoteIps); LongSpace remoteAsns = remoteAsnsList.isEmpty() ? ALL_AS_NUMBERS : LongSpace.builder().includingAll(remoteAsnsList).build(); Map<String, Interface> lowerCasedInterfaces = remoteCfg.getAllInterfaces().entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Entry::getValue)); for (String remoteIfaceName : remoteInterfaces) { Interface remoteIface = lowerCasedInterfaces.get(remoteIfaceName.toLowerCase()); if (remoteIface == null) { warnings.redFlag( String.format( "ISP Modeling: Cannot find interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } Map<Ip, InterfaceAddress> ipToInterfaceAddresses = remoteIface.getAllAddresses().stream() .collect( ImmutableMap.toImmutableMap( addr -> addr instanceof ConcreteInterfaceAddress ? ((ConcreteInterfaceAddress) addr).getIp() : ((LinkLocalAddress) addr).getIp(), Function.identity())); List<BgpPeerConfig> validRemoteBgpPeerConfigs = remoteCfg.getVrfs().values().stream() .map(Vrf::getBgpProcess) .filter(Objects::nonNull) .flatMap( bgpProcess -> Streams.concat( bgpProcess.getActiveNeighbors().values().stream(), bgpProcess.getInterfaceNeighbors().values().stream())) .filter( bgpPeerConfig -> isValidBgpPeerConfig( bgpPeerConfig, ipToInterfaceAddresses.keySet(), remoteIpsSet, remoteAsns)) .collect(Collectors.toList()); if (validRemoteBgpPeerConfigs.isEmpty()) { warnings.redFlag( String.format( "ISP Modeling: Cannot find any valid eBGP configurations for interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } for (BgpPeerConfig bgpPeerConfig : validRemoteBgpPeerConfigs) { long asn = bgpPeerConfig.getRemoteAsns().least(); List<IspNodeInfo> matchingInfos = ispNodeInfos.stream().filter(i -> i.getAsn() == asn).collect(Collectors.toList()); @Nullable String ispName = matchingInfos.stream().map(IspNodeInfo::getName).findFirst().orElse(null); IspTrafficFiltering filtering = matchingInfos.stream() .map(IspNodeInfo::getIspTrafficFiltering) .filter(Objects::nonNull) .findFirst() .orElse(IspTrafficFiltering.blockReservedAddressesAtInternet()); Set<Prefix> additionalPrefixes = matchingInfos.stream() .flatMap( i -> i.getAdditionalAnnouncements().stream().map(IspAnnouncement::getPrefix)) .collect(ImmutableSet.toImmutableSet()); IspModel ispInfo = allIspModels.computeIfAbsent( asn, k -> IspModel.builder() .setAsn(asn) .setName(ispName) .setAdditionalPrefixesToInternet(additionalPrefixes) .setTrafficFiltering(filtering) .build()); InterfaceAddress interfaceAddress = bgpPeerConfig instanceof BgpActivePeerConfig ? ConcreteInterfaceAddress.create( ((BgpActivePeerConfig) bgpPeerConfig).getPeerAddress(), ((ConcreteInterfaceAddress) ipToInterfaceAddresses.get(bgpPeerConfig.getLocalIp())) .getNetworkBits()) : LINK_LOCAL_ADDRESS; ispInfo.addNeighbor( new Remote(remoteCfg.getHostname(), remoteIfaceName, interfaceAddress, bgpPeerConfig)); } } } private  IspModelingUtils(); }
IspModelingUtils { @VisibleForTesting static void populateIspModels( @Nonnull Configuration remoteCfg, @Nonnull Set<String> remoteInterfaces, @Nonnull List<Ip> remoteIps, @Nonnull List<Long> remoteAsnsList, @Nonnull List<IspNodeInfo> ispNodeInfos, Map<Long, IspModel> allIspModels, @Nonnull Warnings warnings) { Set<Ip> remoteIpsSet = ImmutableSet.copyOf(remoteIps); LongSpace remoteAsns = remoteAsnsList.isEmpty() ? ALL_AS_NUMBERS : LongSpace.builder().includingAll(remoteAsnsList).build(); Map<String, Interface> lowerCasedInterfaces = remoteCfg.getAllInterfaces().entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Entry::getValue)); for (String remoteIfaceName : remoteInterfaces) { Interface remoteIface = lowerCasedInterfaces.get(remoteIfaceName.toLowerCase()); if (remoteIface == null) { warnings.redFlag( String.format( "ISP Modeling: Cannot find interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } Map<Ip, InterfaceAddress> ipToInterfaceAddresses = remoteIface.getAllAddresses().stream() .collect( ImmutableMap.toImmutableMap( addr -> addr instanceof ConcreteInterfaceAddress ? ((ConcreteInterfaceAddress) addr).getIp() : ((LinkLocalAddress) addr).getIp(), Function.identity())); List<BgpPeerConfig> validRemoteBgpPeerConfigs = remoteCfg.getVrfs().values().stream() .map(Vrf::getBgpProcess) .filter(Objects::nonNull) .flatMap( bgpProcess -> Streams.concat( bgpProcess.getActiveNeighbors().values().stream(), bgpProcess.getInterfaceNeighbors().values().stream())) .filter( bgpPeerConfig -> isValidBgpPeerConfig( bgpPeerConfig, ipToInterfaceAddresses.keySet(), remoteIpsSet, remoteAsns)) .collect(Collectors.toList()); if (validRemoteBgpPeerConfigs.isEmpty()) { warnings.redFlag( String.format( "ISP Modeling: Cannot find any valid eBGP configurations for interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } for (BgpPeerConfig bgpPeerConfig : validRemoteBgpPeerConfigs) { long asn = bgpPeerConfig.getRemoteAsns().least(); List<IspNodeInfo> matchingInfos = ispNodeInfos.stream().filter(i -> i.getAsn() == asn).collect(Collectors.toList()); @Nullable String ispName = matchingInfos.stream().map(IspNodeInfo::getName).findFirst().orElse(null); IspTrafficFiltering filtering = matchingInfos.stream() .map(IspNodeInfo::getIspTrafficFiltering) .filter(Objects::nonNull) .findFirst() .orElse(IspTrafficFiltering.blockReservedAddressesAtInternet()); Set<Prefix> additionalPrefixes = matchingInfos.stream() .flatMap( i -> i.getAdditionalAnnouncements().stream().map(IspAnnouncement::getPrefix)) .collect(ImmutableSet.toImmutableSet()); IspModel ispInfo = allIspModels.computeIfAbsent( asn, k -> IspModel.builder() .setAsn(asn) .setName(ispName) .setAdditionalPrefixesToInternet(additionalPrefixes) .setTrafficFiltering(filtering) .build()); InterfaceAddress interfaceAddress = bgpPeerConfig instanceof BgpActivePeerConfig ? ConcreteInterfaceAddress.create( ((BgpActivePeerConfig) bgpPeerConfig).getPeerAddress(), ((ConcreteInterfaceAddress) ipToInterfaceAddresses.get(bgpPeerConfig.getLocalIp())) .getNetworkBits()) : LINK_LOCAL_ADDRESS; ispInfo.addNeighbor( new Remote(remoteCfg.getHostname(), remoteIfaceName, interfaceAddress, bgpPeerConfig)); } } } private  IspModelingUtils(); static String getDefaultIspNodeName(long asn); static String internetToIspInterfaceName(String ispHostname); static String ispToRemoteInterfaceName(String remoteHostname, String remoteInterfaceName); static ModeledNodes getInternetAndIspNodes(
      @Nonnull Map<String, Configuration> configurations,
      @Nonnull List<IspConfiguration> ispConfigurations,
      @Nonnull BatfishLogger logger,
      @Nonnull Warnings warnings); static RoutingPolicy installRoutingPolicyAdvertiseStatic(
      String policyName, Configuration node, PrefixSpace prefixSpace); static Statement getAdvertiseStaticStatement(PrefixSpace prefixSpace); static Statement getAdvertiseBgpStatement(); }
IspModelingUtils { @VisibleForTesting static void populateIspModels( @Nonnull Configuration remoteCfg, @Nonnull Set<String> remoteInterfaces, @Nonnull List<Ip> remoteIps, @Nonnull List<Long> remoteAsnsList, @Nonnull List<IspNodeInfo> ispNodeInfos, Map<Long, IspModel> allIspModels, @Nonnull Warnings warnings) { Set<Ip> remoteIpsSet = ImmutableSet.copyOf(remoteIps); LongSpace remoteAsns = remoteAsnsList.isEmpty() ? ALL_AS_NUMBERS : LongSpace.builder().includingAll(remoteAsnsList).build(); Map<String, Interface> lowerCasedInterfaces = remoteCfg.getAllInterfaces().entrySet().stream() .collect(Collectors.toMap(entry -> entry.getKey().toLowerCase(), Entry::getValue)); for (String remoteIfaceName : remoteInterfaces) { Interface remoteIface = lowerCasedInterfaces.get(remoteIfaceName.toLowerCase()); if (remoteIface == null) { warnings.redFlag( String.format( "ISP Modeling: Cannot find interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } Map<Ip, InterfaceAddress> ipToInterfaceAddresses = remoteIface.getAllAddresses().stream() .collect( ImmutableMap.toImmutableMap( addr -> addr instanceof ConcreteInterfaceAddress ? ((ConcreteInterfaceAddress) addr).getIp() : ((LinkLocalAddress) addr).getIp(), Function.identity())); List<BgpPeerConfig> validRemoteBgpPeerConfigs = remoteCfg.getVrfs().values().stream() .map(Vrf::getBgpProcess) .filter(Objects::nonNull) .flatMap( bgpProcess -> Streams.concat( bgpProcess.getActiveNeighbors().values().stream(), bgpProcess.getInterfaceNeighbors().values().stream())) .filter( bgpPeerConfig -> isValidBgpPeerConfig( bgpPeerConfig, ipToInterfaceAddresses.keySet(), remoteIpsSet, remoteAsns)) .collect(Collectors.toList()); if (validRemoteBgpPeerConfigs.isEmpty()) { warnings.redFlag( String.format( "ISP Modeling: Cannot find any valid eBGP configurations for interface %s on node %s", remoteIfaceName, remoteCfg.getHostname())); continue; } for (BgpPeerConfig bgpPeerConfig : validRemoteBgpPeerConfigs) { long asn = bgpPeerConfig.getRemoteAsns().least(); List<IspNodeInfo> matchingInfos = ispNodeInfos.stream().filter(i -> i.getAsn() == asn).collect(Collectors.toList()); @Nullable String ispName = matchingInfos.stream().map(IspNodeInfo::getName).findFirst().orElse(null); IspTrafficFiltering filtering = matchingInfos.stream() .map(IspNodeInfo::getIspTrafficFiltering) .filter(Objects::nonNull) .findFirst() .orElse(IspTrafficFiltering.blockReservedAddressesAtInternet()); Set<Prefix> additionalPrefixes = matchingInfos.stream() .flatMap( i -> i.getAdditionalAnnouncements().stream().map(IspAnnouncement::getPrefix)) .collect(ImmutableSet.toImmutableSet()); IspModel ispInfo = allIspModels.computeIfAbsent( asn, k -> IspModel.builder() .setAsn(asn) .setName(ispName) .setAdditionalPrefixesToInternet(additionalPrefixes) .setTrafficFiltering(filtering) .build()); InterfaceAddress interfaceAddress = bgpPeerConfig instanceof BgpActivePeerConfig ? ConcreteInterfaceAddress.create( ((BgpActivePeerConfig) bgpPeerConfig).getPeerAddress(), ((ConcreteInterfaceAddress) ipToInterfaceAddresses.get(bgpPeerConfig.getLocalIp())) .getNetworkBits()) : LINK_LOCAL_ADDRESS; ispInfo.addNeighbor( new Remote(remoteCfg.getHostname(), remoteIfaceName, interfaceAddress, bgpPeerConfig)); } } } private  IspModelingUtils(); static String getDefaultIspNodeName(long asn); static String internetToIspInterfaceName(String ispHostname); static String ispToRemoteInterfaceName(String remoteHostname, String remoteInterfaceName); static ModeledNodes getInternetAndIspNodes(
      @Nonnull Map<String, Configuration> configurations,
      @Nonnull List<IspConfiguration> ispConfigurations,
      @Nonnull BatfishLogger logger,
      @Nonnull Warnings warnings); static RoutingPolicy installRoutingPolicyAdvertiseStatic(
      String policyName, Configuration node, PrefixSpace prefixSpace); static Statement getAdvertiseStaticStatement(PrefixSpace prefixSpace); static Statement getAdvertiseBgpStatement(); static final String INTERNET_HOST_NAME; static final String INTERNET_OUT_INTERFACE; static final Set<Prefix> INTERNET_NULL_ROUTED_PREFIXES; }