use of org.batfish.datamodel.Edge in project batfish by batfish.
the class Client method initEnvironment.
private boolean initEnvironment(String paramsLine, FileWriter outWriter) {
InitEnvironmentParams params = parseInitEnvironmentParams(paramsLine);
String newEnvName;
String paramsLocation = params.getSourcePath();
String paramsName = params.getNewEnvironmentName();
String paramsPrefix = params.getNewEnvironmentPrefix();
String testrigName = params.getDoDelta() ? _currDeltaTestrig : _currTestrig;
if (paramsName != null) {
newEnvName = paramsName;
} else if (paramsPrefix != null) {
newEnvName = paramsPrefix + UUID.randomUUID();
} else {
newEnvName = DEFAULT_DELTA_ENV_PREFIX + UUID.randomUUID();
}
String paramsBaseEnv = params.getSourceEnvironmentName();
String baseEnvName = paramsBaseEnv != null ? paramsBaseEnv : BfConsts.RELPATH_DEFAULT_ENVIRONMENT_NAME;
String fileToSend;
SortedSet<String> paramsNodeBlacklist = params.getNodeBlacklist();
SortedSet<NodeInterfacePair> paramsInterfaceBlacklist = params.getInterfaceBlacklist();
SortedSet<Edge> paramsEdgeBlacklist = params.getEdgeBlacklist();
if (paramsLocation == null || Files.isDirectory(Paths.get(paramsLocation)) || !paramsNodeBlacklist.isEmpty() || !paramsInterfaceBlacklist.isEmpty() || !paramsEdgeBlacklist.isEmpty()) {
Path tempFile = CommonUtil.createTempFile("batfish_client_tmp_env_", ".zip");
fileToSend = tempFile.toString();
if (paramsLocation != null && Files.isDirectory(Paths.get(paramsLocation)) && paramsNodeBlacklist.isEmpty() && paramsInterfaceBlacklist.isEmpty() && paramsEdgeBlacklist.isEmpty()) {
ZipUtility.zipFiles(Paths.get(paramsLocation), tempFile);
} else {
Path tempDir = CommonUtil.createTempDirectory("batfish_client_tmp_env_");
if (paramsLocation != null) {
if (Files.isDirectory(Paths.get(paramsLocation))) {
CommonUtil.copyDirectory(Paths.get(paramsLocation), tempDir);
} else if (Files.isRegularFile(Paths.get(paramsLocation))) {
UnzipUtility.unzip(Paths.get(paramsLocation), tempDir);
} else {
throw new BatfishException("Invalid environment directory or zip: '" + paramsLocation + "'");
}
}
if (!paramsNodeBlacklist.isEmpty()) {
String nodeBlacklistText;
try {
nodeBlacklistText = BatfishObjectMapper.writePrettyString(paramsNodeBlacklist);
} catch (JsonProcessingException e) {
throw new BatfishException("Failed to write node blacklist to string", e);
}
Path nodeBlacklistFilePath = tempDir.resolve(BfConsts.RELPATH_NODE_BLACKLIST_FILE);
CommonUtil.writeFile(nodeBlacklistFilePath, nodeBlacklistText);
}
if (!paramsInterfaceBlacklist.isEmpty()) {
String interfaceBlacklistText;
try {
interfaceBlacklistText = BatfishObjectMapper.writePrettyString(paramsInterfaceBlacklist);
} catch (JsonProcessingException e) {
throw new BatfishException("Failed to write interface blacklist to string", e);
}
Path interfaceBlacklistFilePath = tempDir.resolve(BfConsts.RELPATH_INTERFACE_BLACKLIST_FILE);
CommonUtil.writeFile(interfaceBlacklistFilePath, interfaceBlacklistText);
}
if (!paramsEdgeBlacklist.isEmpty()) {
String edgeBlacklistText;
try {
edgeBlacklistText = BatfishObjectMapper.writePrettyString(paramsEdgeBlacklist);
} catch (JsonProcessingException e) {
throw new BatfishException("Failed to write edge blacklist to string", e);
}
Path edgeBlacklistFilePath = tempDir.resolve(BfConsts.RELPATH_EDGE_BLACKLIST_FILE);
CommonUtil.writeFile(edgeBlacklistFilePath, edgeBlacklistText);
}
ZipUtility.zipFiles(tempDir, tempFile);
}
} else if (Files.isRegularFile(Paths.get(paramsLocation))) {
fileToSend = paramsLocation;
} else {
throw new BatfishException("Invalid environment directory or zip: '" + paramsLocation + "'");
}
if (!uploadEnv(fileToSend, testrigName, newEnvName, baseEnvName)) {
return false;
}
_currDeltaEnv = newEnvName;
_currDeltaTestrig = _currTestrig;
_logger.output("Active delta testrig->environment is set");
_logger.infof("to %s->%s\n", _currDeltaTestrig, _currDeltaEnv);
_logger.output("\n");
WorkItem wItemProcessEnv = WorkItemBuilder.getWorkItemProcessEnvironment(_currContainerName, _currDeltaTestrig, _currDeltaEnv);
if (!execute(wItemProcessEnv, outWriter)) {
return false;
}
return true;
}
use of org.batfish.datamodel.Edge in project batfish by batfish.
the class CommonUtil method synthesizeTopology.
public static Topology synthesizeTopology(Map<String, Configuration> configurations) {
SortedSet<Edge> edges = new TreeSet<>();
Map<Prefix, Set<NodeInterfacePair>> prefixInterfaces = new HashMap<>();
configurations.forEach((nodeName, node) -> {
for (Entry<String, Interface> e : node.getInterfaces().entrySet()) {
String ifaceName = e.getKey();
Interface iface = e.getValue();
if (!iface.isLoopback(node.getConfigurationFormat()) && iface.getActive()) {
for (InterfaceAddress address : iface.getAllAddresses()) {
if (address.getNetworkBits() < Prefix.MAX_PREFIX_LENGTH) {
Prefix prefix = address.getPrefix();
NodeInterfacePair pair = new NodeInterfacePair(nodeName, ifaceName);
Set<NodeInterfacePair> interfaceBucket = prefixInterfaces.computeIfAbsent(prefix, k -> new HashSet<>());
interfaceBucket.add(pair);
}
}
}
}
});
for (Set<NodeInterfacePair> bucket : prefixInterfaces.values()) {
for (NodeInterfacePair p1 : bucket) {
for (NodeInterfacePair p2 : bucket) {
if (!p1.equals(p2)) {
Edge edge = new Edge(p1, p2);
edges.add(edge);
}
}
}
}
return new Topology(edges);
}
use of org.batfish.datamodel.Edge in project batfish by batfish.
the class BdpEngine method processFlows.
@Override
public SortedMap<Flow, Set<FlowTrace>> processFlows(DataPlane dataPlane, Set<Flow> flows) {
Map<Flow, Set<FlowTrace>> flowTraces = new ConcurrentHashMap<>();
BdpDataPlane dp = (BdpDataPlane) dataPlane;
flows.parallelStream().forEach(flow -> {
Set<FlowTrace> currentFlowTraces = new TreeSet<>();
flowTraces.put(flow, currentFlowTraces);
String ingressNodeName = flow.getIngressNode();
if (ingressNodeName == null) {
throw new BatfishException("Cannot construct flow trace since ingressNode is not specified");
}
Ip dstIp = flow.getDstIp();
if (dstIp == null) {
throw new BatfishException("Cannot construct flow trace since dstIp is not specified");
}
Set<Edge> visitedEdges = Collections.emptySet();
List<FlowTraceHop> hops = new ArrayList<>();
Set<String> dstIpOwners = dp._ipOwners.get(dstIp);
SortedSet<Edge> edges = new TreeSet<>();
String ingressInterfaceName = flow.getIngressInterface();
if (ingressInterfaceName != null) {
edges.add(new Edge(TRACEROUTE_INGRESS_NODE_NAME, TRACEROUTE_INGRESS_NODE_INTERFACE_NAME, ingressNodeName, ingressInterfaceName));
processCurrentNextHopInterfaceEdges(dp, TRACEROUTE_INGRESS_NODE_NAME, visitedEdges, hops, currentFlowTraces, flow, flow, dstIp, dstIpOwners, null, new TreeSet<>(), null, null, edges, false);
} else {
collectFlowTraces(dp, ingressNodeName, visitedEdges, hops, currentFlowTraces, flow, flow);
}
});
return new TreeMap<>(flowTraces);
}
use of org.batfish.datamodel.Edge in project batfish by batfish.
the class BdpEngine method collectFlowTraces.
private void collectFlowTraces(BdpDataPlane dp, String currentNodeName, Set<Edge> visitedEdges, List<FlowTraceHop> hopsSoFar, Set<FlowTrace> flowTraces, Flow originalFlow, Flow transformedFlow) {
Ip dstIp = transformedFlow.getDstIp();
Set<String> dstIpOwners = dp._ipOwners.get(dstIp);
if (dstIpOwners != null && dstIpOwners.contains(currentNodeName)) {
FlowTrace trace = new FlowTrace(FlowDisposition.ACCEPTED, hopsSoFar, FlowDisposition.ACCEPTED.toString());
flowTraces.add(trace);
} else {
Node currentNode = dp._nodes.get(currentNodeName);
String vrfName;
if (hopsSoFar.isEmpty()) {
vrfName = transformedFlow.getIngressVrf();
} else {
FlowTraceHop lastHop = hopsSoFar.get(hopsSoFar.size() - 1);
String receivingInterface = lastHop.getEdge().getInt2();
vrfName = currentNode._c.getInterfaces().get(receivingInterface).getVrf().getName();
}
VirtualRouter currentVirtualRouter = currentNode._virtualRouters.get(vrfName);
Map<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> nextHopInterfacesByRoute = currentVirtualRouter._fib.getNextHopInterfacesByRoute(dstIp);
Map<String, Map<Ip, Set<AbstractRoute>>> nextHopInterfacesWithRoutes = currentVirtualRouter._fib.getNextHopInterfaces(dstIp);
if (!nextHopInterfacesWithRoutes.isEmpty()) {
for (String nextHopInterfaceName : nextHopInterfacesWithRoutes.keySet()) {
// SortedSet<String> routesForThisNextHopInterface = new
// TreeSet<>(
// nextHopInterfacesWithRoutes.get(nextHopInterfaceName)
// .stream().map(ar -> ar.toString())
// .collect(Collectors.toSet()));
SortedSet<String> routesForThisNextHopInterface = new TreeSet<>();
Ip finalNextHopIp = null;
for (Entry<AbstractRoute, Map<String, Map<Ip, Set<AbstractRoute>>>> e : nextHopInterfacesByRoute.entrySet()) {
AbstractRoute routeCandidate = e.getKey();
Map<String, Map<Ip, Set<AbstractRoute>>> routeCandidateNextHopInterfaces = e.getValue();
if (routeCandidateNextHopInterfaces.containsKey(nextHopInterfaceName)) {
Ip nextHopIp = routeCandidate.getNextHopIp();
if (!nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) {
Set<Ip> finalNextHopIps = routeCandidateNextHopInterfaces.get(nextHopInterfaceName).keySet();
if (finalNextHopIps.size() > 1) {
throw new BatfishException("Can not currently handle multiple final next hop ips across multiple " + "routes leading to one next hop interface");
}
Ip newFinalNextHopIp = finalNextHopIps.iterator().next();
if (finalNextHopIp != null && !newFinalNextHopIp.equals(finalNextHopIp)) {
throw new BatfishException("Can not currently handle multiple final next hop ips for same next hop " + "interface");
}
finalNextHopIp = newFinalNextHopIp;
}
routesForThisNextHopInterface.add(routeCandidate + "_fnhip:" + finalNextHopIp);
}
}
NodeInterfacePair nextHopInterface = new NodeInterfacePair(currentNodeName, nextHopInterfaceName);
if (nextHopInterfaceName.equals(Interface.NULL_INTERFACE_NAME)) {
List<FlowTraceHop> newHops = new ArrayList<>(hopsSoFar);
Edge newEdge = new Edge(nextHopInterface, new NodeInterfacePair(Configuration.NODE_NONE_NAME, Interface.NULL_INTERFACE_NAME));
FlowTraceHop newHop = new FlowTraceHop(newEdge, routesForThisNextHopInterface, hopFlow(originalFlow, transformedFlow));
newHops.add(newHop);
FlowTrace nullRouteTrace = new FlowTrace(FlowDisposition.NULL_ROUTED, newHops, FlowDisposition.NULL_ROUTED.toString());
flowTraces.add(nullRouteTrace);
} else {
Interface outgoingInterface = dp._nodes.get(nextHopInterface.getHostname())._c.getInterfaces().get(nextHopInterface.getInterface());
// Apply any relevant source NAT rules.
transformedFlow = applySourceNat(transformedFlow, outgoingInterface.getSourceNats());
SortedSet<Edge> edges = dp._topology.getInterfaceEdges().get(nextHopInterface);
if (edges != null) {
boolean continueToNextNextHopInterface = false;
continueToNextNextHopInterface = processCurrentNextHopInterfaceEdges(dp, currentNodeName, visitedEdges, hopsSoFar, flowTraces, originalFlow, transformedFlow, dstIp, dstIpOwners, nextHopInterfaceName, routesForThisNextHopInterface, finalNextHopIp, nextHopInterface, edges, true);
if (continueToNextNextHopInterface) {
continue;
}
} else {
/*
* Should only get here for delta environment where
* non-flow-sink interface from base has no edges in delta
*/
Edge neighborUnreachbleEdge = new Edge(nextHopInterface, new NodeInterfacePair(Configuration.NODE_NONE_NAME, Interface.NULL_INTERFACE_NAME));
FlowTraceHop neighborUnreachableHop = new FlowTraceHop(neighborUnreachbleEdge, routesForThisNextHopInterface, hopFlow(originalFlow, transformedFlow));
List<FlowTraceHop> newHops = new ArrayList<>(hopsSoFar);
newHops.add(neighborUnreachableHop);
/**
* Check if denied out. If not, make standard neighbor-unreachable trace.
*/
IpAccessList outFilter = outgoingInterface.getOutgoingFilter();
boolean denied = false;
if (outFilter != null) {
FlowDisposition disposition = FlowDisposition.DENIED_OUT;
denied = flowTraceDeniedHelper(flowTraces, originalFlow, transformedFlow, newHops, outFilter, disposition);
}
if (!denied) {
FlowTrace trace = new FlowTrace(FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK, newHops, FlowDisposition.NEIGHBOR_UNREACHABLE_OR_EXITS_NETWORK.toString());
flowTraces.add(trace);
}
}
}
}
} else {
FlowTrace trace = new FlowTrace(FlowDisposition.NO_ROUTE, hopsSoFar, FlowDisposition.NO_ROUTE.toString());
flowTraces.add(trace);
}
}
}
use of org.batfish.datamodel.Edge in project batfish by batfish.
the class BdpEngine method flowTraceDeniedHelper.
private boolean flowTraceDeniedHelper(Set<FlowTrace> flowTraces, Flow originalFlow, Flow transformedFlow, List<FlowTraceHop> newHops, IpAccessList filter, FlowDisposition disposition) {
boolean out = disposition == FlowDisposition.DENIED_OUT;
FilterResult outResult = filter.filter(transformedFlow);
boolean denied = outResult.getAction() == LineAction.REJECT;
if (denied) {
String outFilterName = filter.getName();
Integer matchLine = outResult.getMatchLine();
String lineDesc;
if (matchLine != null) {
lineDesc = filter.getLines().get(matchLine).getName();
if (lineDesc == null) {
lineDesc = "line:" + matchLine;
}
} else {
lineDesc = "no-match";
}
String notes = disposition + "{" + outFilterName + "}{" + lineDesc + "}";
if (out) {
FlowTraceHop lastHop = newHops.get(newHops.size() - 1);
newHops.remove(newHops.size() - 1);
Edge lastEdge = lastHop.getEdge();
Edge deniedOutEdge = new Edge(lastEdge.getFirst(), new NodeInterfacePair(Configuration.NODE_NONE_NAME, Interface.NULL_INTERFACE_NAME));
FlowTraceHop deniedOutHop = new FlowTraceHop(deniedOutEdge, lastHop.getRoutes(), hopFlow(originalFlow, transformedFlow));
newHops.add(deniedOutHop);
}
FlowTrace trace = new FlowTrace(disposition, newHops, notes);
flowTraces.add(trace);
}
return denied;
}
Aggregations