use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class BatfishCompressor method compress.
public Map<String, Configuration> compress(HeaderSpace h) {
DestinationClasses dcs = DestinationClasses.create(_batfish, _graph, h, true);
ArrayList<Supplier<NetworkSlice>> ecs = NetworkSlice.allSlices(dcs, 0);
Optional<Map<GraphEdge, EquivalenceClassFilter>> opt = ecs.stream().map(Supplier::get).map(this::processSlice).reduce(this::mergeFilters);
if (!opt.isPresent()) {
return new HashMap<>();
}
Map<GraphEdge, EquivalenceClassFilter> filters = opt.get();
Table2<String, GraphEdge, EquivalenceClassFilter> filtersByRouter = new Table2<>();
for (Entry<GraphEdge, EquivalenceClassFilter> entry : filters.entrySet()) {
GraphEdge ge = entry.getKey();
filtersByRouter.put(ge.getRouter(), ge, entry.getValue());
}
return applyFilters(filtersByRouter);
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class EncoderSlice method initForwardingAcross.
/*
* Initialize boolean expressions to represent that traffic sent along
* and edge will reach the other side of the edge.
*/
private void initForwardingAcross() {
_symbolicDecisions.getDataForwarding().forEach((router, edge, var) -> {
BoolExpr inAcl;
if (edge.getEnd() == null) {
inAcl = mkTrue();
} else {
GraphEdge ge = getGraph().getOtherEnd().get(edge);
inAcl = _inboundAcls.get(ge);
if (inAcl == null) {
inAcl = mkTrue();
}
}
_forwardsAcross.put(router, edge, mkAnd(var, inAcl));
});
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class EncoderSlice method addImportConstraint.
/*
* Creates the transfer function to represent import filters
* between two symbolic records. The import filter depends
* heavily on the protocol.
*/
private void addImportConstraint(LogicalEdge e, SymbolicRoute varsOther, Configuration conf, Protocol proto, GraphEdge ge, String router) {
SymbolicRoute vars = e.getSymbolicRecord();
Interface iface = ge.getStart();
ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
assert (failed != null);
BoolExpr notFailed = mkEq(failed, mkInt(0));
if (vars.getIsUsed()) {
if (proto.isConnected()) {
Prefix p = iface.getAddress().getPrefix();
BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
BoolExpr per = vars.getPermitted();
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(1));
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
BoolExpr values = mkAnd(per, len, ad, lp, met);
add(mkIf(relevant, values, mkNot(vars.getPermitted())));
}
if (proto.isStatic()) {
List<StaticRoute> srs = getGraph().getStaticRoutes().get(router, iface.getName());
assert (srs != null);
BoolExpr acc = mkNot(vars.getPermitted());
for (StaticRoute sr : srs) {
Prefix p = sr.getNetwork();
BoolExpr relevant = mkAnd(interfaceActive(iface, proto), isRelevantFor(p, _symbolicPacket.getDstIp()), notFailed);
BoolExpr per = vars.getPermitted();
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(p.getPrefixLength()));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(sr.getAdministrativeCost()));
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr met = safeEq(vars.getMetric(), mkInt(0));
BoolExpr values = mkAnd(per, len, ad, lp, met);
acc = mkIf(relevant, values, acc);
}
add(acc);
}
if (proto.isOspf() || proto.isBgp()) {
BoolExpr val = mkNot(vars.getPermitted());
if (varsOther != null) {
// BoolExpr isRoot = relevantOrigination(originations);
BoolExpr active = interfaceActive(iface, proto);
// Handle iBGP by checking reachability to the next hop to send messages
boolean isNonClient = (proto.isBgp()) && (getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP);
boolean isClient = (proto.isBgp()) && (getGraph().peerType(ge) == Graph.BgpSendType.TO_RR);
BoolExpr receiveMessage;
String currentRouter = ge.getRouter();
String peerRouter = ge.getPeer();
if (_encoder.getModelIgp() && isNonClient) {
// Lookup reachabilty based on peer next-hop
receiveMessage = _encoder.getSliceReachability().get(currentRouter).get(peerRouter);
/* EncoderSlice peerSlice = _encoder.getSlice(peerRouter);
BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
BoolExpr all =
mkAnd(srcPort, srcIp, tcpAck,
tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
receiveMessage = mkImplies(all, receiveMessage); */
} else if (_encoder.getModelIgp() && isClient) {
// Lookup reachability based on client id tag to find next hop
BoolExpr acc = mkTrue();
for (Map.Entry<String, Integer> entry : getGraph().getOriginatorId().entrySet()) {
String r = entry.getKey();
Integer id = entry.getValue();
if (!r.equals(currentRouter)) {
BoolExpr reach = _encoder.getSliceReachability().get(currentRouter).get(r);
/* EncoderSlice peerSlice = _encoder.getSlice(r);
BoolExpr srcPort = mkEq(peerSlice.getSymbolicPacket().getSrcPort(), mkInt(179));
BoolExpr srcIp = mkEq(peerSlice.getSymbolicPacket().getSrcIp(), mkInt(0));
BoolExpr tcpAck = mkEq(peerSlice.getSymbolicPacket().getTcpAck(), mkFalse());
BoolExpr tcpCwr = mkEq(peerSlice.getSymbolicPacket().getTcpCwr(), mkFalse());
BoolExpr tcpEce = mkEq(peerSlice.getSymbolicPacket().getTcpEce(), mkFalse());
BoolExpr tcpFin = mkEq(peerSlice.getSymbolicPacket().getTcpFin(), mkFalse());
BoolExpr tcpPsh = mkEq(peerSlice.getSymbolicPacket().getTcpPsh(), mkFalse());
BoolExpr tcpRst = mkEq(peerSlice.getSymbolicPacket().getTcpRst(), mkFalse());
BoolExpr tcpSyn = mkEq(peerSlice.getSymbolicPacket().getTcpSyn(), mkFalse());
BoolExpr tcpUrg = mkEq(peerSlice.getSymbolicPacket().getTcpUrg(), mkFalse());
BoolExpr icmpCode = mkEq(peerSlice.getSymbolicPacket().getIcmpCode(), mkInt(0));
BoolExpr icmpType = mkEq(peerSlice.getSymbolicPacket().getIcmpType(), mkInt(0));
BoolExpr all =
mkAnd(srcPort, srcIp, tcpAck,
tcpCwr, tcpEce, tcpFin, tcpPsh, tcpRst, tcpSyn, tcpUrg, icmpCode, icmpType);
reach = mkImplies(all, reach); */
acc = mkAnd(acc, mkImplies(varsOther.getClientId().checkIfValue(id), reach));
}
}
receiveMessage = acc;
// Just check if the link is failed
} else {
receiveMessage = notFailed;
}
// Take into account BGP loop prevention
// The path length will prevent any isolated loops
BoolExpr loop = mkFalse();
if (proto.isBgp() && ge.getPeer() != null) {
String peer = ge.getPeer();
GraphEdge gePeer = getGraph().getOtherEnd().get(ge);
loop = getSymbolicDecisions().getControlForwarding().get(peer, gePeer);
}
assert (loop != null);
BoolExpr usable = mkAnd(mkNot(loop), active, varsOther.getPermitted(), receiveMessage);
BoolExpr importFunction;
RoutingPolicy pol = getGraph().findImportRoutingPolicy(router, proto, e.getEdge());
if (Encoder.ENABLE_DEBUGGING && pol != null) {
System.out.println("Import Policy: " + pol.getName());
}
List<Statement> statements;
if (pol == null) {
Statements.StaticStatement s = new Statements.StaticStatement(Statements.ExitAccept);
statements = Collections.singletonList(s);
} else {
statements = pol.getStatements();
}
// OSPF cost calculated based on incoming interface
Integer cost = proto.isOspf() ? addedCost(proto, ge) : 0;
TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, false);
importFunction = f.compute();
BoolExpr acc = mkIf(usable, importFunction, val);
if (Encoder.ENABLE_DEBUGGING) {
System.out.println("IMPORT FUNCTION: " + router + " " + varsOther.getName());
System.out.println(importFunction.simplify());
System.out.println("\n\n");
}
add(acc);
} else {
add(val);
}
}
}
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class EncoderSlice method addForwardingVariables.
/*
* Initalizes variables representing the control plane and
* data plane final forwarding decisions
*/
private void addForwardingVariables() {
for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
for (GraphEdge edge : edges) {
String iface = edge.getStart().getName();
String cName = _encoder.getId() + "_" + _sliceName + "CONTROL-FORWARDING_" + router + "_" + iface;
BoolExpr cForward = getCtx().mkBoolConst(cName);
getAllVariables().put(cForward.toString(), cForward);
_symbolicDecisions.getControlForwarding().put(router, edge, cForward);
// Don't add data forwarding variable for abstract edge
if (!edge.isAbstract()) {
String dName = _encoder.getId() + "_" + _sliceName + "DATA-FORWARDING_" + router + "_" + iface;
BoolExpr dForward = getCtx().mkBoolConst(dName);
getAllVariables().put(dForward.toString(), dForward);
_symbolicDecisions.getDataForwarding().put(router, edge, dForward);
}
}
}
}
use of org.batfish.symbolic.GraphEdge in project batfish by batfish.
the class EncoderSlice method addDataForwardingConstraints.
/*
* Constraints for the final data plane forwarding behavior.
* Forwarding occurs in the data plane if the control plane decides
* to use an interface, and no ACL blocks the packet:
*
* data_fwd(iface) = control_fwd(iface) and not acl(iface)
*/
private void addDataForwardingConstraints() {
for (Entry<String, List<GraphEdge>> entry : getGraph().getEdgeMap().entrySet()) {
String router = entry.getKey();
List<GraphEdge> edges = entry.getValue();
for (GraphEdge ge : edges) {
// setup forwarding for non-abstract edges
if (!ge.isAbstract()) {
BoolExpr fwd = mkFalse();
BoolExpr cForward = _symbolicDecisions.getControlForwarding().get(router, ge);
BoolExpr dForward = _symbolicDecisions.getDataForwarding().get(router, ge);
assert (cForward != null);
assert (dForward != null);
// out the current edge ge, the we use ge.
for (GraphEdge ge2 : getGraph().getEdgeMap().get(router)) {
if (ge2.isAbstract()) {
BoolExpr ctrlFwd = getSymbolicDecisions().getControlForwarding().get(router, ge2);
Graph.BgpSendType st = getGraph().peerType(ge2);
// If Route reflectors, then next hop based on ID
if (st == Graph.BgpSendType.TO_RR) {
SymbolicRoute record = getSymbolicDecisions().getBestNeighbor().get(router);
// adjust for iBGP in main slice
BoolExpr acc = mkFalse();
if (isMainSlice()) {
for (Entry<String, Integer> entry2 : getGraph().getOriginatorId().entrySet()) {
String r = entry2.getKey();
Integer id = entry2.getValue();
EncoderSlice s = _encoder.getSlice(r);
// Make sure
if (otherSliceHasEdge(s, router, ge)) {
BoolExpr outEdge = s.getSymbolicDecisions().getDataForwarding().get(router, ge);
acc = mkOr(acc, mkAnd(record.getClientId().checkIfValue(id), outEdge));
}
}
}
fwd = mkOr(fwd, mkAnd(ctrlFwd, acc));
} else {
// adjust for iBGP in main slice
if (isMainSlice()) {
EncoderSlice s = _encoder.getSlice(ge2.getPeer());
if (otherSliceHasEdge(s, router, ge)) {
BoolExpr outEdge = s.getSymbolicDecisions().getDataForwarding().get(router, ge);
fwd = mkOr(fwd, mkAnd(ctrlFwd, outEdge));
}
}
}
}
}
fwd = mkOr(fwd, cForward);
BoolExpr acl = _outboundAcls.get(ge);
if (acl == null) {
acl = mkTrue();
}
BoolExpr notBlocked = mkAnd(fwd, acl);
add(mkEq(notBlocked, dForward));
}
}
}
}
Aggregations