use of org.batfish.common.Pair in project batfish by batfish.
the class Batfish method answerAclReachability.
@Override
public AnswerElement answerAclReachability(String aclNameRegexStr, NamedStructureEquivalenceSets<?> aclEqSets) {
AclLinesAnswerElement answerElement = new AclLinesAnswerElement();
Pattern aclNameRegex;
try {
aclNameRegex = Pattern.compile(aclNameRegexStr);
} catch (PatternSyntaxException e) {
throw new BatfishException("Supplied regex for nodes is not a valid java regex: \"" + aclNameRegexStr + "\"", e);
}
Map<String, Configuration> configurations = loadConfigurations();
List<NodSatJob<AclLine>> jobs = new ArrayList<>();
for (Entry<String, ?> e : aclEqSets.getSameNamedStructures().entrySet()) {
String aclName = e.getKey();
if (!aclNameRegex.matcher(aclName).matches()) {
continue;
}
// operator error
if (aclName.contains("~ZONE_INTERFACE_FILTER~") || aclName.contains("~INBOUND_ZONE_FILTER~")) {
continue;
}
Set<?> s = (Set<?>) e.getValue();
for (Object o : s) {
NamedStructureEquivalenceSet<?> aclEqSet = (NamedStructureEquivalenceSet<?>) o;
String hostname = aclEqSet.getRepresentativeElement();
SortedSet<String> eqClassNodes = aclEqSet.getNodes();
answerElement.addEquivalenceClass(aclName, hostname, eqClassNodes);
Configuration c = configurations.get(hostname);
IpAccessList acl = c.getIpAccessLists().get(aclName);
int numLines = acl.getLines().size();
if (numLines == 0) {
_logger.redflag("RED_FLAG: Acl \"" + hostname + ":" + aclName + "\" contains no lines\n");
continue;
}
AclReachabilityQuerySynthesizer query = new AclReachabilityQuerySynthesizer(hostname, aclName, numLines);
Synthesizer aclSynthesizer = synthesizeAcls(Collections.singletonMap(hostname, c));
NodSatJob<AclLine> job = new NodSatJob<>(_settings, aclSynthesizer, query);
jobs.add(job);
}
}
Map<AclLine, Boolean> output = new TreeMap<>();
computeNodSatOutput(jobs, output);
// rearrange output for next step
Map<String, Map<String, List<AclLine>>> arrangedAclLines = new TreeMap<>();
for (Entry<AclLine, Boolean> e : output.entrySet()) {
AclLine line = e.getKey();
String hostname = line.getHostname();
Map<String, List<AclLine>> byAclName = arrangedAclLines.computeIfAbsent(hostname, k -> new TreeMap<>());
String aclName = line.getAclName();
List<AclLine> aclLines = byAclName.computeIfAbsent(aclName, k -> new ArrayList<>());
aclLines.add(line);
}
// now get earliest more general lines
List<NodFirstUnsatJob<AclLine, Integer>> step2Jobs = new ArrayList<>();
for (Entry<String, Map<String, List<AclLine>>> e : arrangedAclLines.entrySet()) {
String hostname = e.getKey();
Configuration c = configurations.get(hostname);
Synthesizer aclSynthesizer = synthesizeAcls(Collections.singletonMap(hostname, c));
Map<String, List<AclLine>> byAclName = e.getValue();
for (Entry<String, List<AclLine>> e2 : byAclName.entrySet()) {
String aclName = e2.getKey();
IpAccessList ipAccessList = c.getIpAccessLists().get(aclName);
List<AclLine> lines = e2.getValue();
for (int i = 0; i < lines.size(); i++) {
AclLine line = lines.get(i);
boolean reachable = output.get(line);
if (!reachable) {
List<AclLine> toCheck = new ArrayList<>();
for (int j = 0; j < i; j++) {
AclLine earlierLine = lines.get(j);
boolean earlierIsReachable = output.get(earlierLine);
if (earlierIsReachable) {
toCheck.add(earlierLine);
}
}
EarliestMoreGeneralReachableLineQuerySynthesizer query = new EarliestMoreGeneralReachableLineQuerySynthesizer(line, toCheck, ipAccessList);
NodFirstUnsatJob<AclLine, Integer> job = new NodFirstUnsatJob<>(_settings, aclSynthesizer, query);
step2Jobs.add(job);
}
}
}
}
Map<AclLine, Integer> step2Output = new TreeMap<>();
computeNodFirstUnsatOutput(step2Jobs, step2Output);
for (AclLine line : output.keySet()) {
Integer earliestMoreGeneralReachableLine = step2Output.get(line);
line.setEarliestMoreGeneralReachableLine(earliestMoreGeneralReachableLine);
}
Set<Pair<String, String>> aclsWithUnreachableLines = new TreeSet<>();
Set<Pair<String, String>> allAcls = new TreeSet<>();
int numUnreachableLines = 0;
int numLines = output.entrySet().size();
for (Entry<AclLine, Boolean> e : output.entrySet()) {
AclLine aclLine = e.getKey();
boolean sat = e.getValue();
String hostname = aclLine.getHostname();
String aclName = aclLine.getAclName();
Pair<String, String> qualifiedAclName = new Pair<>(hostname, aclName);
allAcls.add(qualifiedAclName);
if (!sat) {
numUnreachableLines++;
aclsWithUnreachableLines.add(qualifiedAclName);
}
}
for (Entry<AclLine, Boolean> e : output.entrySet()) {
AclLine aclLine = e.getKey();
int index = aclLine.getLine();
boolean sat = e.getValue();
String hostname = aclLine.getHostname();
String aclName = aclLine.getAclName();
Pair<String, String> qualifiedAclName = new Pair<>(hostname, aclName);
IpAccessList ipAccessList = configurations.get(hostname).getIpAccessLists().get(aclName);
IpAccessListLine ipAccessListLine = ipAccessList.getLines().get(index);
AclReachabilityEntry line = new AclReachabilityEntry(index, ipAccessListLine.getName());
if (aclsWithUnreachableLines.contains(qualifiedAclName)) {
if (sat) {
_logger.debugf("%s:%s:%d:'%s' is REACHABLE\n", hostname, aclName, line.getIndex(), line.getName());
answerElement.addReachableLine(hostname, ipAccessList, line);
} else {
_logger.debugf("%s:%s:%d:'%s' is UNREACHABLE\n\t%s\n", hostname, aclName, line.getIndex(), line.getName(), ipAccessListLine.toString());
Integer earliestMoreGeneralLineIndex = aclLine.getEarliestMoreGeneralReachableLine();
if (earliestMoreGeneralLineIndex != null) {
IpAccessListLine earliestMoreGeneralLine = ipAccessList.getLines().get(earliestMoreGeneralLineIndex);
line.setEarliestMoreGeneralLineIndex(earliestMoreGeneralLineIndex);
line.setEarliestMoreGeneralLineName(earliestMoreGeneralLine.getName());
if (!earliestMoreGeneralLine.getAction().equals(ipAccessListLine.getAction())) {
line.setDifferentAction(true);
}
}
answerElement.addUnreachableLine(hostname, ipAccessList, line);
aclsWithUnreachableLines.add(qualifiedAclName);
}
} else {
answerElement.addReachableLine(hostname, ipAccessList, line);
}
}
for (Pair<String, String> qualfiedAcl : aclsWithUnreachableLines) {
String hostname = qualfiedAcl.getFirst();
String aclName = qualfiedAcl.getSecond();
_logger.debugf("%s:%s has at least 1 unreachable line\n", hostname, aclName);
}
int numAclsWithUnreachableLines = aclsWithUnreachableLines.size();
int numAcls = allAcls.size();
double percentUnreachableAcls = 100d * numAclsWithUnreachableLines / numAcls;
double percentUnreachableLines = 100d * numUnreachableLines / numLines;
_logger.debugf("SUMMARY:\n");
_logger.debugf("\t%d/%d (%.1f%%) acls have unreachable lines\n", numAclsWithUnreachableLines, numAcls, percentUnreachableAcls);
_logger.debugf("\t%d/%d (%.1f%%) acl lines are unreachable\n", numUnreachableLines, numLines, percentUnreachableLines);
return answerElement;
}
use of org.batfish.common.Pair in project batfish by batfish.
the class Batfish method pathDiff.
@Override
public AnswerElement pathDiff(ReachabilitySettings reachabilitySettings) {
Settings settings = getSettings();
checkDifferentialDataPlaneQuestionDependencies();
String tag = getDifferentialFlowTag();
// load base configurations and generate base data plane
pushBaseEnvironment();
Map<String, Configuration> baseConfigurations = loadConfigurations();
Synthesizer baseDataPlaneSynthesizer = synthesizeDataPlane();
Topology baseTopology = getEnvironmentTopology();
popEnvironment();
// load diff configurations and generate diff data plane
pushDeltaEnvironment();
Map<String, Configuration> diffConfigurations = loadConfigurations();
Synthesizer diffDataPlaneSynthesizer = synthesizeDataPlane();
Topology diffTopology = getEnvironmentTopology();
popEnvironment();
pushDeltaEnvironment();
SortedSet<String> blacklistNodes = getNodeBlacklist();
Set<NodeInterfacePair> blacklistInterfaces = getInterfaceBlacklist();
SortedSet<Edge> blacklistEdges = getEdgeBlacklist();
popEnvironment();
BlacklistDstIpQuerySynthesizer blacklistQuery = new BlacklistDstIpQuerySynthesizer(null, blacklistNodes, blacklistInterfaces, blacklistEdges, baseConfigurations);
// compute composite program and flows
List<Synthesizer> commonEdgeSynthesizers = ImmutableList.of(baseDataPlaneSynthesizer, diffDataPlaneSynthesizer, baseDataPlaneSynthesizer);
List<CompositeNodJob> jobs = new ArrayList<>();
// generate local edge reachability and black hole queries
SortedSet<Edge> diffEdges = diffTopology.getEdges();
for (Edge edge : diffEdges) {
String ingressNode = edge.getNode1();
String outInterface = edge.getInt1();
String vrf = diffConfigurations.get(ingressNode).getInterfaces().get(outInterface).getVrf().getName();
ReachEdgeQuerySynthesizer reachQuery = new ReachEdgeQuerySynthesizer(ingressNode, vrf, edge, true, reachabilitySettings.getHeaderSpace());
ReachEdgeQuerySynthesizer noReachQuery = new ReachEdgeQuerySynthesizer(ingressNode, vrf, edge, true, new HeaderSpace());
noReachQuery.setNegate(true);
List<QuerySynthesizer> queries = ImmutableList.of(reachQuery, noReachQuery, blacklistQuery);
SortedSet<Pair<String, String>> nodes = ImmutableSortedSet.of(new Pair<>(ingressNode, vrf));
CompositeNodJob job = new CompositeNodJob(settings, commonEdgeSynthesizers, queries, nodes, tag);
jobs.add(job);
}
// we also need queries for nodes next to edges that are now missing,
// in the case that those nodes still exist
List<Synthesizer> missingEdgeSynthesizers = ImmutableList.of(baseDataPlaneSynthesizer, baseDataPlaneSynthesizer);
SortedSet<Edge> baseEdges = baseTopology.getEdges();
SortedSet<Edge> missingEdges = ImmutableSortedSet.copyOf(Sets.difference(baseEdges, diffEdges));
for (Edge missingEdge : missingEdges) {
String ingressNode = missingEdge.getNode1();
String outInterface = missingEdge.getInt1();
if (diffConfigurations.containsKey(ingressNode) && diffConfigurations.get(ingressNode).getInterfaces().containsKey(outInterface)) {
String vrf = diffConfigurations.get(ingressNode).getInterfaces().get(outInterface).getVrf().getName();
ReachEdgeQuerySynthesizer reachQuery = new ReachEdgeQuerySynthesizer(ingressNode, vrf, missingEdge, true, reachabilitySettings.getHeaderSpace());
List<QuerySynthesizer> queries = ImmutableList.of(reachQuery, blacklistQuery);
SortedSet<Pair<String, String>> nodes = ImmutableSortedSet.of(new Pair<>(ingressNode, vrf));
CompositeNodJob job = new CompositeNodJob(settings, missingEdgeSynthesizers, queries, nodes, tag);
jobs.add(job);
}
}
// TODO: maybe do something with nod answer element
Set<Flow> flows = computeCompositeNodOutput(jobs, new NodAnswerElement());
pushBaseEnvironment();
getDataPlanePlugin().processFlows(flows, loadDataPlane());
popEnvironment();
pushDeltaEnvironment();
getDataPlanePlugin().processFlows(flows, loadDataPlane());
popEnvironment();
AnswerElement answerElement = getHistory();
return answerElement;
}
use of org.batfish.common.Pair in project batfish by batfish.
the class AwsConfiguration method getNextGeneratedLinkSubnet.
public synchronized Pair<InterfaceAddress, InterfaceAddress> getNextGeneratedLinkSubnet() {
assert _currentGeneratedIpAsLong % 2 == 0;
InterfaceAddress val = new InterfaceAddress(new Ip(_currentGeneratedIpAsLong), Prefix.MAX_PREFIX_LENGTH - 1);
InterfaceAddress val2 = new InterfaceAddress(new Ip(_currentGeneratedIpAsLong + 1), Prefix.MAX_PREFIX_LENGTH - 1);
_currentGeneratedIpAsLong += 2L;
return new Pair<>(val, val2);
}
use of org.batfish.common.Pair in project batfish by batfish.
the class TransferSSA method joinPoint.
/*
* The [phi] function from SSA that merges variables that may differ across
* different branches of an mkIf statement.
*/
private Pair<Expr, Expr> joinPoint(TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> r, BoolExpr guard, Pair<String, Pair<Expr, Expr>> values) {
String variableName = values.getFirst();
Expr trueBranch = values.getSecond().getFirst();
Expr falseBranch = values.getSecond().getSecond();
if (variableName.equals("RETURN") || variableName.equals("FALLTHROUGH")) {
Expr t = (trueBranch == null ? _enc.mkFalse() : // can use False because the value has not been assigned
trueBranch);
Expr f = (falseBranch == null ? _enc.mkFalse() : falseBranch);
Expr tass = (trueBranch == null ? r.getReturnAssignedValue() : _enc.mkTrue());
Expr fass = (falseBranch == null ? r.getReturnAssignedValue() : _enc.mkTrue());
BoolExpr newAss = _enc.mkIf(guard, (BoolExpr) tass, (BoolExpr) fass);
BoolExpr retAss = createBoolVariableWith(p, "ASSIGNED", newAss);
BoolExpr variable = (variableName.equals("RETURN") ? r.getReturnValue() : r.getFallthroughValue());
BoolExpr newValue = _enc.mkIf(r.getReturnAssignedValue(), variable, _enc.mkIf(guard, (BoolExpr) t, (BoolExpr) f));
BoolExpr ret = createBoolVariableWith(p, variableName, newValue);
return new Pair<>(ret, retAss);
}
if (variableName.equals("PREFIX-LEN")) {
Expr t = (trueBranch == null ? p.getData().getPrefixLength() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getPrefixLength() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getPrefixLength(), newValue);
ArithExpr ret = createArithVariableWith(p, "PREFIX-LEN", newValue);
p.getData().setPrefixLength(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("ADMIN-DIST")) {
Expr t = (trueBranch == null ? p.getData().getAdminDist() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getAdminDist() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getAdminDist(), newValue);
ArithExpr ret = createArithVariableWith(p, "ADMIN-DIST", newValue);
p.getData().setAdminDist(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("LOCAL-PREF")) {
Expr t = (trueBranch == null ? p.getData().getLocalPref() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getLocalPref() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
ArithExpr ret = createArithVariableWith(p, "LOCAL-PREF", newValue);
p.getData().setLocalPref(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("METRIC")) {
Expr t = (trueBranch == null ? p.getData().getMetric() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getMetric() : falseBranch);
ArithExpr newValue = _enc.mkIf(guard, (ArithExpr) t, (ArithExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getMetric(), newValue);
ArithExpr ret = createArithVariableWith(p, "METRIC", newValue);
p.getData().setMetric(ret);
return new Pair<>(ret, null);
}
if (variableName.equals("OSPF-TYPE")) {
Expr t = (trueBranch == null ? p.getData().getOspfType().getBitVec() : trueBranch);
Expr f = (falseBranch == null ? p.getData().getOspfType().getBitVec() : falseBranch);
BitVecExpr newValue = _enc.mkIf(guard, (BitVecExpr) t, (BitVecExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getOspfType().getBitVec(), newValue);
BitVecExpr ret = createBitVecVariableWith(p, "OSPF-TYPE", 2, newValue);
p.getData().getOspfType().setBitVec(ret);
return new Pair<>(ret, null);
}
for (Map.Entry<CommunityVar, BoolExpr> entry : p.getData().getCommunities().entrySet()) {
CommunityVar cvar = entry.getKey();
if (variableName.equals(cvar.getValue())) {
Expr t = (trueBranch == null ? p.getData().getCommunities().get(cvar) : trueBranch);
Expr f = (falseBranch == null ? p.getData().getCommunities().get(cvar) : falseBranch);
BoolExpr newValue = _enc.mkIf(guard, (BoolExpr) t, (BoolExpr) f);
newValue = _enc.mkIf(r.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), newValue);
BoolExpr ret = createBoolVariableWith(p, cvar.getValue(), newValue);
p.getData().getCommunities().put(cvar, ret);
return new Pair<>(ret, null);
}
}
throw new BatfishException("[joinPoint]: unhandled case for " + variableName);
}
use of org.batfish.common.Pair in project batfish by batfish.
the class NodJobChunkingTest method getNodJob.
private NodJob getNodJob() {
StandardReachabilityQuerySynthesizer querySynthesizer = StandardReachabilityQuerySynthesizer.builder().setActions(ImmutableSet.of(ForwardingAction.ACCEPT)).setHeaderSpace(new HeaderSpace()).setFinalNodes(ImmutableSet.of(_dstNode.getHostname())).setIngressNodeVrfs(ImmutableMap.of(_srcNode1.getHostname(), ImmutableSet.of(_srcVrf1.getName()), _srcNode2.getHostname(), ImmutableSet.of(_srcVrf2.getName()))).setTransitNodes(ImmutableSet.of()).setNonTransitNodes(ImmutableSet.of()).build();
SortedSet<Pair<String, String>> ingressNodes = ImmutableSortedSet.of(new Pair<>(_srcNode1.getHostname(), _srcVrf1.getName()), new Pair<>(_srcNode2.getHostname(), _srcVrf2.getName()));
return new NodJob(new Settings(), _synthesizer, querySynthesizer, ingressNodes, "tag", false);
}
Aggregations