use of org.batfish.datamodel.answers.AnswerElement 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.datamodel.answers.AnswerElement in project batfish by batfish.
the class Batfish method answer.
public Answer answer() {
Question question = null;
// return right away if we cannot parse the question successfully
try (ActiveSpan parseQuestionSpan = GlobalTracer.get().buildSpan("Parse question").startActive()) {
// avoid not used warning
assert parseQuestionSpan != null;
question = Question.parseQuestion(_settings.getQuestionPath());
} catch (Exception e) {
Answer answer = new Answer();
BatfishException exception = new BatfishException("Could not parse question", e);
answer.setStatus(AnswerStatus.FAILURE);
answer.addAnswerElement(exception.getBatfishStackTrace());
return answer;
}
if (_settings.getDifferential()) {
question.setDifferential(true);
}
boolean dp = question.getDataPlane();
boolean diff = question.getDifferential();
boolean diffActive = _settings.getDiffActive() && !diff;
_settings.setDiffActive(diffActive);
_settings.setDiffQuestion(diff);
try (ActiveSpan loadConfigurationSpan = GlobalTracer.get().buildSpan("Load configurations").startActive()) {
// avoid not used warning
assert loadConfigurationSpan != null;
// Ensures configurations are parsed and ready
loadConfigurations();
}
try (ActiveSpan initQuestionEnvSpan = GlobalTracer.get().buildSpan("Init question environment").startActive()) {
// avoid not used warning
assert initQuestionEnvSpan != null;
initQuestionEnvironments(question, diff, diffActive, dp);
}
AnswerElement answerElement = null;
BatfishException exception = null;
try (ActiveSpan getAnswerSpan = GlobalTracer.get().buildSpan("Get answer").startActive()) {
// avoid not used warning
assert getAnswerSpan != null;
if (question.getDifferential()) {
answerElement = Answerer.create(question, this).answerDiff();
} else {
answerElement = Answerer.create(question, this).answer();
}
} catch (Exception e) {
exception = new BatfishException("Failed to answer question", e);
}
Answer answer = new Answer();
answer.setQuestion(question);
if (exception == null) {
// success
answer.setStatus(AnswerStatus.SUCCESS);
answer.addAnswerElement(answerElement);
} else {
// failure
answer.setStatus(AnswerStatus.FAILURE);
answer.addAnswerElement(exception.getBatfishStackTrace());
}
return answer;
}
use of org.batfish.datamodel.answers.AnswerElement in project batfish by batfish.
the class Batfish method serializeHostConfigs.
private SortedMap<String, VendorConfiguration> serializeHostConfigs(Path testRigPath, Path outputPath, ParseVendorConfigurationAnswerElement answerElement) {
SortedMap<Path, String> configurationData = readConfigurationFiles(testRigPath, BfConsts.RELPATH_HOST_CONFIGS_DIR);
// read the host files
SortedMap<String, VendorConfiguration> allHostConfigurations;
try (ActiveSpan parseHostConfigsSpan = GlobalTracer.get().buildSpan("Parse host configs").startActive()) {
// avoid unused warning
assert parseHostConfigsSpan != null;
allHostConfigurations = parseVendorConfigurations(configurationData, answerElement, ConfigurationFormat.HOST);
}
if (allHostConfigurations == null) {
throw new BatfishException("Exiting due to parser errors");
}
_logger.infof("Testrig:%s in container:%s has total number of host configs:%d", getTestrigName(), getContainerName(), allHostConfigurations.size());
// split into hostConfigurations and overlayConfigurations
SortedMap<String, VendorConfiguration> overlayConfigurations = allHostConfigurations.entrySet().stream().filter(e -> ((HostConfiguration) e.getValue()).getOverlay()).collect(toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v1, TreeMap::new));
SortedMap<String, VendorConfiguration> nonOverlayHostConfigurations = allHostConfigurations.entrySet().stream().filter(e -> !((HostConfiguration) e.getValue()).getOverlay()).collect(toMap(Entry::getKey, Entry::getValue, (v1, v2) -> v1, TreeMap::new));
// read and associate iptables files for specified hosts
SortedMap<Path, String> iptablesData = new TreeMap<>();
readIptableFiles(testRigPath, allHostConfigurations, iptablesData, answerElement);
SortedMap<String, VendorConfiguration> iptablesConfigurations = parseVendorConfigurations(iptablesData, answerElement, ConfigurationFormat.IPTABLES);
for (VendorConfiguration vc : allHostConfigurations.values()) {
HostConfiguration hostConfig = (HostConfiguration) vc;
if (hostConfig.getIptablesFile() != null) {
Path path = Paths.get(testRigPath.toString(), hostConfig.getIptablesFile());
String relativePathStr = _testrigSettings.getBasePath().relativize(path).toString();
if (iptablesConfigurations.containsKey(relativePathStr)) {
hostConfig.setIptablesVendorConfig((IptablesVendorConfiguration) iptablesConfigurations.get(relativePathStr));
}
}
}
// now, serialize
_logger.info("\n*** SERIALIZING VENDOR CONFIGURATION STRUCTURES ***\n");
_logger.resetTimer();
CommonUtil.createDirectories(outputPath);
Map<Path, VendorConfiguration> output = new TreeMap<>();
nonOverlayHostConfigurations.forEach((name, vc) -> {
Path currentOutputPath = outputPath.resolve(name);
output.put(currentOutputPath, vc);
});
serializeObjects(output);
// serialize warnings
serializeObject(answerElement, _testrigSettings.getParseAnswerPath());
_logger.printElapsedTime();
return overlayConfigurations;
}
use of org.batfish.datamodel.answers.AnswerElement in project batfish by batfish.
the class PropertyChecker method checkReachability.
/*
* Check if a collection of routers will be reachable to
* one or more destinations.
*/
public AnswerElement checkReachability(HeaderLocationQuestion q) {
return checkProperty(q, (enc, srcRouters, destPorts) -> {
PropertyAdder pa = new PropertyAdder(enc.getMainSlice());
return pa.instrumentReachability(destPorts);
}, (vp) -> {
if (vp.getResult().isVerified()) {
return new SmtReachabilityAnswerElement(vp.getResult(), new FlowHistory());
} else {
FlowHistory fh;
CounterExample ce = new CounterExample(vp.getModel());
String testrigName = _batfish.getTestrigName();
if (q.getDiffType() != null) {
fh = ce.buildFlowHistoryDiff(testrigName, vp.getSrcRouters(), vp.getEnc(), vp.getEncDiff(), vp.getProp(), vp.getPropDiff());
} else {
Map<String, Boolean> reachVals = vp.getProp().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> ce.isTrue(entry.getValue()) ^ q.getNegate()));
fh = ce.buildFlowHistory(testrigName, vp.getSrcRouters(), vp.getEnc(), reachVals);
}
return new SmtReachabilityAnswerElement(vp.getResult(), fh);
}
});
}
use of org.batfish.datamodel.answers.AnswerElement in project batfish by batfish.
the class IpsecVpnStatusAnswerer method answer.
@Override
public AnswerElement answer() {
IpsecVpnStatusQuestion question = (IpsecVpnStatusQuestion) _question;
Map<String, Configuration> configurations = _batfish.loadConfigurations();
Set<String> includeNodes1 = question.getNode1Regex().getMatchingNodes(configurations);
Set<String> includeNodes2 = question.getNode2Regex().getMatchingNodes(configurations);
CommonUtil.initRemoteIpsecVpns(configurations);
IpsecVpnStatusAnswerElement answerElement = new IpsecVpnStatusAnswerElement();
for (Configuration c : configurations.values()) {
if (!includeNodes1.contains(c.getHostname())) {
continue;
}
for (IpsecVpn ipsecVpn : c.getIpsecVpns().values()) {
IpsecVpnInfo vpnInfo = analyzeIpsecVpn(ipsecVpn);
if ((vpnInfo.getRemoteEndpoint() == null || includeNodes2.contains(vpnInfo.getRemoteEndpoint().getHostname())) && vpnInfo.getProblems().stream().anyMatch(v -> question.matchesProblem(v))) {
answerElement.getIpsecVpns().add(vpnInfo);
}
}
}
return answerElement;
}
Aggregations