/** * Explain the flow space permitted by an {@link IpAccessList}. The {@code invariantExp} allows * scoping the explanation to a space of interest (use {@link TrueExpr} to explain the entire * space). */ public static AclLineMatchExpr explain( BDDPacket bddPacket, BDDSourceManager mgr, AclLineMatchExpr invariantExpr, IpAccessList acl, Map<String, IpAccessList> namedAcls, Map<String, IpSpace> namedIpSpaces) { return explainWithProvenance(bddPacket, mgr, invariantExpr, acl, namedAcls, namedIpSpaces) .getMatchExpr(); }
private static AclLineMatchExprWithProvenance<IpAccessListLineIndex> explainWithProvenance( IpAccessListToBDD ipAccessListToBDD, IpAccessList acl, Map<String, IpAccessList> namedAcls, IdentityHashMap<AclLineMatchExpr, IpAccessListLineIndex> literalsToLines) { // Convert acl to a single expression. AclLineMatchExpr aclExpr = AclToAclLineMatchExpr.toAclLineMatchExpr(ipAccessListToBDD, acl, namedAcls); // Reduce that expression to normal form. AclLineMatchExpr aclExprNf = AclLineMatchExprNormalizer.normalize(ipAccessListToBDD, aclExpr); // Simplify the normal form AclLineMatchExprWithProvenance<AclLineMatchExpr> aclExprNfExplained = AclExplanation.explainNormalForm(aclExprNf); // join the provenance information from the normal form with the literalsToLines mapping // above to obtain provenance back to the original acl lines IdentityHashMap<AclLineMatchExpr, Set<IpAccessListLineIndex>> conjunctsToLines = new IdentityHashMap<>(); for (Map.Entry<AclLineMatchExpr, Set<AclLineMatchExpr>> entry : aclExprNfExplained.getProvenance().entrySet()) { AclLineMatchExpr conjunct = entry.getKey(); conjunctsToLines.put( conjunct, entry.getValue().stream() .map(literalsToLines::get) .collect(ImmutableSet.toImmutableSet())); } return new AclLineMatchExprWithProvenance<>( aclExprNfExplained.getMatchExpr(), conjunctsToLines); }
return new AclLineMatchExprWithProvenance<>(TrueExpr.INSTANCE, new IdentityHashMap<>()); return new AclLineMatchExprWithProvenance<>(conjuncts.first(), conjunctsProvenance); return new AclLineMatchExprWithProvenance<>(new AndMatchExpr(conjuncts), conjunctsProvenance);
public static AclLineMatchExprWithProvenance<AclLineMatchExpr> explainNormalForm( AclLineMatchExpr nf) { /* * A normal form is either a factor or a disjunction of factors. */ if (nf instanceof OrMatchExpr) { /* * Each disjunct is a factor. */ SortedSet<AclLineMatchExprWithProvenance<AclLineMatchExpr>> disjunctsWithProvenance = ((OrMatchExpr) nf) .getDisjuncts().stream() .map(AclExplanation::explainFactor) .collect(ImmutableSortedSet.toImmutableSortedSet(Ordering.natural())); List<AclLineMatchExpr> disjuncts = new LinkedList<>(); IdentityHashMap<AclLineMatchExpr, Set<AclLineMatchExpr>> provenance = new IdentityHashMap<>(); for (AclLineMatchExprWithProvenance<AclLineMatchExpr> matchExprWithProvenance : disjunctsWithProvenance) { disjuncts.add(matchExprWithProvenance.getMatchExpr()); provenance.putAll(matchExprWithProvenance.getProvenance()); } return new AclLineMatchExprWithProvenance<>(new OrMatchExpr(disjuncts), provenance); } return explainFactor(nf); } }
/** * Explain the flow space permitted by one {@link IpAccessList} ({@code permitAcl}) but denied by * another ({@code denyAcl}). The {@code invariantExp} allows scoping the explanation to a space * of interest (use {@link TrueExpr} to explain the entire difference). */ public static AclLineMatchExpr explainDifferential( BDDPacket bddPacket, BDDSourceManager mgr, AclLineMatchExpr invariantExpr, IpAccessList denyAcl, Map<String, IpAccessList> denyNamedAcls, Map<String, IpSpace> denyNamedIpSpaces, IpAccessList permitAcl, Map<String, IpAccessList> permitNamedAcls, Map<String, IpSpace> permitNamedIpSpaces) { return explainDifferentialWithProvenance( bddPacket, mgr, invariantExpr, denyAcl, denyNamedAcls, denyNamedIpSpaces, permitAcl, permitNamedAcls, permitNamedIpSpaces) .getMatchExpr(); }