diff --git a/projects/minesweeper/src/main/java/org/batfish/minesweeper/Graph.java b/projects/minesweeper/src/main/java/org/batfish/minesweeper/Graph.java index 0e45383bada..30b098b69b7 100644 --- a/projects/minesweeper/src/main/java/org/batfish/minesweeper/Graph.java +++ b/projects/minesweeper/src/main/java/org/batfish/minesweeper/Graph.java @@ -89,25 +89,25 @@ public enum BgpSendType { public static final String BGP_COMMON_FILTER_LIST_NAME = "BGP_COMMON_EXPORT_POLICY"; private static final String NULL_INTERFACE_NAME = "null_interface"; - private IBatfish _batfish; - private Set _routers; - private Map _configurations; + private final IBatfish _batfish; + private final Set _routers; + private final Map _configurations; private final NetworkSnapshot _snapshot; - private Map> _areaIds; - private Table2> _staticRoutes; - private Map> _nullStaticRoutes; - private Map> _neighbors; - private Map> _edgeMap; - private Set _allRealEdges; - private Set _allEdges; - private Map _otherEnd; - private Map _ebgpNeighbors; - private Map _ibgpNeighbors; - private Map _routeReflectorParent; - private Map> _routeReflectorClients; - private Map _originatorId; - private Map _domainMap; - private Map> _domainMapInverse; + private final Map> _areaIds; + private final Table2> _staticRoutes; + private final Map> _nullStaticRoutes; + private final Map> _neighbors; + private final Map> _edgeMap; + private final Set _allRealEdges; + private final Set _allEdges; + private final Map _otherEnd; + private final Map _ebgpNeighbors; + private final Map _ibgpNeighbors; + private final Map _routeReflectorParent; + private final Map> _routeReflectorClients; + private final Map _originatorId; + private final Map _domainMap; + private final Map> _domainMapInverse; /** * The SMT- and BDD-based analyses (see the corresponding smt and bdd packages) handle communities @@ -115,7 +115,7 @@ public enum BgpSendType { * diverge further. Hence we use this flag to build the appropriate Graph object for the given * analysis. */ - private boolean _bddBasedAnalysis; + private final boolean _bddBasedAnalysis; /** * A graph with a static route with a dynamic next hop cannot be encoded to SMT, so some of the @@ -123,27 +123,27 @@ public enum BgpSendType { */ private boolean _hasStaticRouteWithDynamicNextHop; - private Set _allCommunities; + private final Set _allCommunities; /** * Keys are all REGEX vars, and values are lists of EXACT or OTHER vars. This field is only used * by the SMT-based analyses. */ - private SortedMap> _communityDependencies; + private final SortedMap> _communityDependencies; - private Map _namedCommunities; + private final Map _namedCommunities; /** * In order to track community literals and regexes in the BDD-based analysis, we compute a set of * "atomic predicates" for them. */ - private RegexAtomicPredicates _communityAtomicPredicates; + private final RegexAtomicPredicates _communityAtomicPredicates; /** * We also compute a set of atomic predicates for the AS-path regexes that appear in the given * configurations. */ - private RegexAtomicPredicates _asPathRegexAtomicPredicates; + private final RegexAtomicPredicates _asPathRegexAtomicPredicates; /** * Create a graph, loading configurations from the given {@link IBatfish}. @@ -226,13 +226,12 @@ public Graph( _originatorId = new HashMap<>(); _domainMap = new HashMap<>(); _domainMapInverse = new HashMap<>(); - _configurations = configs; _allCommunities = new HashSet<>(); _communityDependencies = new TreeMap<>(); _snapshot = snapshot; _bddBasedAnalysis = bddBasedAnalysis; - if (_configurations == null) { + if (configs == null) { // Since many functions that use the graph mutate the configurations, we must clone them // before that happens. // A simple way to do this is to create a deep clone of each entry using Java serialization. @@ -244,6 +243,8 @@ public Graph( .collect(toMap(Entry::getKey, entry -> SerializationUtils.clone(entry.getValue()))); _configurations = clonedConfigs; + } else { + _configurations = configs; } _routers = _configurations.keySet(); @@ -280,8 +281,10 @@ public Graph( .collect(ImmutableSet.toImmutableSet()); _communityAtomicPredicates = new RegexAtomicPredicates<>(comms, CommunityVar.ALL_COMMUNITIES); } else { + _communityAtomicPredicates = null; initCommDependencies(); } + _namedCommunities = new HashMap<>(); initNamedCommunities(); _asPathRegexAtomicPredicates = new RegexAtomicPredicates<>( @@ -464,8 +467,6 @@ private void initGraph(Topology topology) { routerIfaceMap.put(router, ifacePairs); } - _neighbors = new HashMap<>(); - for (Entry> entry : routerIfaceMap.entrySet()) { String router = entry.getKey(); Set nips = entry.getValue(); @@ -974,7 +975,6 @@ private void initCommDependencies() { * easier to provide intuitive counter examples. */ private void initNamedCommunities() { - _namedCommunities = new HashMap<>(); for (Configuration conf : getConfigurations().values()) { for (Entry entry : conf.getCommunityLists().entrySet()) { String name = entry.getKey(); diff --git a/projects/minesweeper/src/main/java/org/batfish/minesweeper/question/searchroutepolicies/SearchRoutePoliciesAnswerer.java b/projects/minesweeper/src/main/java/org/batfish/minesweeper/question/searchroutepolicies/SearchRoutePoliciesAnswerer.java index 90a5eaf2354..27a07b64164 100644 --- a/projects/minesweeper/src/main/java/org/batfish/minesweeper/question/searchroutepolicies/SearchRoutePoliciesAnswerer.java +++ b/projects/minesweeper/src/main/java/org/batfish/minesweeper/question/searchroutepolicies/SearchRoutePoliciesAnswerer.java @@ -15,9 +15,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMultiset; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Multiset; -import com.google.common.collect.Ordering; import com.google.common.collect.Range; import dk.brics.automaton.Automaton; import java.util.Arrays; @@ -25,7 +23,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.SortedSet; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -42,7 +39,6 @@ import org.batfish.common.plugin.IBatfish; import org.batfish.datamodel.AsPath; import org.batfish.datamodel.Bgpv4Route; -import org.batfish.datamodel.Configuration; import org.batfish.datamodel.Ip; import org.batfish.datamodel.LongSpace; import org.batfish.datamodel.OriginType; @@ -308,15 +304,6 @@ private Optional constraintsToResult( } } - private SortedSet resolvePolicies(SpecifierContext context) { - return _nodeSpecifier.resolve(context).stream() - .flatMap( - node -> - _policySpecifier.resolve(node, context).stream() - .map(policy -> new RoutingPolicyId(node, policy.getName()))) - .collect(ImmutableSortedSet.toImmutableSortedSet(Ordering.natural())); - } - private BDD prefixSpaceToBDD(PrefixSpace space, BDDRoute r, boolean complementPrefixes) { BDDFactory factory = r.getPrefix().getFactory(); if (space.isEmpty()) { @@ -436,18 +423,15 @@ private BDD routeConstraintsToBDD(BgpRouteConstraints constraints, BDDRoute r, G return result; } - private Optional searchPolicy(RoutingPolicy policy) { + /** + * Search a particular route policy for behaviors of interest. + * + * @param policy the routing policy + * @param g a Graph object providing information about the policy's owner configuration + * @return an optional result, if a behavior of interest was found + */ + private Optional searchPolicy(RoutingPolicy policy, Graph g) { TransferReturn result; - Graph g = - new Graph( - _batfish, - _batfish.getSnapshot(), - null, - ImmutableSet.of(policy.getOwner().getHostname()), - _communityRegexes.stream() - .map(RegexCommunitySet::new) - .collect(ImmutableSet.toImmutableSet()), - _asPathRegexes); try { TransferBDD tbdd = new TransferBDD(g, policy.getOwner(), policy.getStatements()); result = tbdd.compute(ImmutableSet.of()).getReturnValue(); @@ -474,15 +458,37 @@ private Optional searchPolicy(RoutingPolicy policy) { return constraintsToResult(intersection, outputRoute, policy, g); } + /** + * Search all of the route policies of a particular node for behaviors of interest. + * + * @param node the node + * @param policies all route policies in that node + * @return all results from analyzing those route policies + */ + private Stream searchPoliciesForNode(String node, Set policies) { + Graph g = + new Graph( + _batfish, + _batfish.getSnapshot(), + null, + ImmutableSet.of(node), + _communityRegexes.stream() + .map(RegexCommunitySet::new) + .collect(ImmutableSet.toImmutableSet()), + _asPathRegexes); + + return policies.stream() + .map(policy -> searchPolicy(policy, g)) + .filter(Optional::isPresent) + .map(Optional::get); + } + @Override public AnswerElement answer(NetworkSnapshot snapshot) { SpecifierContext context = _batfish.specifierContext(snapshot); - SortedSet policies = resolvePolicies(context); Multiset rows = - getPolicies(context, policies) - .map(this::searchPolicy) - .filter(Optional::isPresent) - .map(Optional::get) + _nodeSpecifier.resolve(context).stream() + .flatMap(node -> searchPoliciesForNode(node, _policySpecifier.resolve(node, context))) .map(SearchRoutePoliciesAnswerer::toRow) .collect(ImmutableMultiset.toImmutableMultiset()); @@ -491,16 +497,6 @@ public AnswerElement answer(NetworkSnapshot snapshot) { return answerElement; } - @Nonnull - private Stream getPolicies( - SpecifierContext context, SortedSet policies) { - Map configs = context.getConfigs(); - return policies.stream() - .map( - policyId -> - configs.get(policyId.getNode()).getRoutingPolicies().get(policyId.getPolicy())); - } - @Nullable private static org.batfish.datamodel.questions.BgpRoute toQuestionsBgpRoute( @Nullable Bgpv4Route dataplaneBgpRoute) {