package org.batfish.z3; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import org.batfish.common.BatfishException; import org.batfish.common.util.CommonUtil; import org.batfish.datamodel.Configuration; import org.batfish.datamodel.DataPlane; import org.batfish.datamodel.Edge; import org.batfish.datamodel.HeaderSpace; import org.batfish.datamodel.IcmpCode; import org.batfish.datamodel.IcmpType; import org.batfish.datamodel.Interface; import org.batfish.datamodel.Ip; import org.batfish.datamodel.IpAccessList; import org.batfish.datamodel.IpAccessListLine; import org.batfish.datamodel.IpProtocol; import org.batfish.datamodel.IpWildcard; import org.batfish.datamodel.LineAction; import org.batfish.datamodel.Prefix; import org.batfish.datamodel.Protocol; import org.batfish.datamodel.State; import org.batfish.datamodel.SubRange; import org.batfish.datamodel.TcpFlags; import org.batfish.datamodel.Zone; import org.batfish.datamodel.collections.EdgeSet; import org.batfish.datamodel.collections.FibMap; import org.batfish.datamodel.collections.FibRow; import org.batfish.datamodel.collections.InterfaceSet; import org.batfish.datamodel.collections.NodeInterfacePair; import org.batfish.datamodel.collections.NodeSet; import org.batfish.datamodel.collections.RoleSet; import org.batfish.z3.node.AcceptExpr; import org.batfish.z3.node.AclDenyExpr; import org.batfish.z3.node.AclMatchExpr; import org.batfish.z3.node.AclNoMatchExpr; import org.batfish.z3.node.AclPermitExpr; import org.batfish.z3.node.AndExpr; import org.batfish.z3.node.BooleanExpr; import org.batfish.z3.node.Comment; import org.batfish.z3.node.DebugExpr; import org.batfish.z3.node.DeclareRelExpr; import org.batfish.z3.node.DeclareVarExpr; import org.batfish.z3.node.DestinationRouteExpr; import org.batfish.z3.node.DropAclExpr; import org.batfish.z3.node.DropAclInExpr; import org.batfish.z3.node.DropAclOutExpr; import org.batfish.z3.node.DropExpr; import org.batfish.z3.node.DropNoRouteExpr; import org.batfish.z3.node.DropNullRouteExpr; import org.batfish.z3.node.EqExpr; import org.batfish.z3.node.ExternalDestinationIpExpr; import org.batfish.z3.node.ExternalSourceIpExpr; import org.batfish.z3.node.ExtractExpr; import org.batfish.z3.node.InboundInterfaceExpr; import org.batfish.z3.node.IntExpr; import org.batfish.z3.node.LitIntExpr; import org.batfish.z3.node.NodeAcceptExpr; import org.batfish.z3.node.NodeDropAclExpr; import org.batfish.z3.node.NodeDropAclInExpr; import org.batfish.z3.node.NodeDropAclOutExpr; import org.batfish.z3.node.NodeDropExpr; import org.batfish.z3.node.NodeDropNoRouteExpr; import org.batfish.z3.node.NodeDropNullRouteExpr; import org.batfish.z3.node.NodeTransitExpr; import org.batfish.z3.node.NonInboundNullSrcZoneExpr; import org.batfish.z3.node.NonInboundSrcInterfaceExpr; import org.batfish.z3.node.NonInboundSrcZoneExpr; import org.batfish.z3.node.NotExpr; import org.batfish.z3.node.OrExpr; import org.batfish.z3.node.OriginateExpr; import org.batfish.z3.node.OriginateVrfExpr; import org.batfish.z3.node.PacketRelExpr; import org.batfish.z3.node.PolicyDenyExpr; import org.batfish.z3.node.PolicyExpr; import org.batfish.z3.node.PostInExpr; import org.batfish.z3.node.PostInInterfaceExpr; import org.batfish.z3.node.PostInVrfExpr; import org.batfish.z3.node.PostOutInterfaceExpr; import org.batfish.z3.node.PreInInterfaceExpr; import org.batfish.z3.node.PreOutEdgeExpr; import org.batfish.z3.node.PreOutExpr; import org.batfish.z3.node.PreOutInterfaceExpr; import org.batfish.z3.node.QueryRelationExpr; import org.batfish.z3.node.RangeMatchExpr; import org.batfish.z3.node.RoleAcceptExpr; import org.batfish.z3.node.RoleOriginateExpr; import org.batfish.z3.node.RuleExpr; import org.batfish.z3.node.SaneExpr; import org.batfish.z3.node.Statement; import org.batfish.z3.node.TrueExpr; import org.batfish.z3.node.UnoriginalExpr; import org.batfish.z3.node.VarIntExpr; import com.microsoft.z3.BitVecExpr; import com.microsoft.z3.BoolExpr; import com.microsoft.z3.Context; import com.microsoft.z3.FuncDecl; import com.microsoft.z3.Z3Exception; public class Synthesizer { public static final int DSCP_BITS = 6; public static final String DSCP_VAR = "dscp"; public static final String DST_IP_VAR = "dst_ip"; public static final String DST_PORT_VAR = "dst_port"; public static final int ECN_BITS = 2; public static final String ECN_VAR = "ecn"; public static final int FRAGMENT_OFFSET_BITS = 13; public static final String FRAGMENT_OFFSET_VAR = "fragment_offset"; public static final int ICMP_CODE_BITS = 8; public static final String ICMP_CODE_VAR = "icmp_code"; public static final int ICMP_TYPE_BITS = 8; public static final String ICMP_TYPE_VAR = "icmp_type"; public static final int IP_BITS = 32; public static final String IP_PROTOCOL_VAR = "ip_prot"; public static final int PACKET_LENGTH_BITS = 16; public static final String PACKET_LENGTH_VAR = "packet_length"; public static final Map<String, Integer> PACKET_VAR_SIZES = initPacketVarSizes(); public static final List<String> PACKET_VARS = getPacketVars(); public static final int PORT_BITS = 16; public static final int PROTOCOL_BITS = 8; public static final String SRC_IP_VAR = "src_ip"; public static final String SRC_PORT_VAR = "src_port"; public static final int STATE_BITS = 2; public static final String STATE_VAR = "state"; public static final int TCP_FLAGS_ACK_BITS = 1; public static final String TCP_FLAGS_ACK_VAR = "tcp_flags_ack"; public static final int TCP_FLAGS_CWR_BITS = 1; public static final String TCP_FLAGS_CWR_VAR = "tcp_flags_cwr"; public static final int TCP_FLAGS_ECE_BITS = 1; public static final String TCP_FLAGS_ECE_VAR = "tcp_flags_ece"; public static final int TCP_FLAGS_FIN_BITS = 1; public static final String TCP_FLAGS_FIN_VAR = "tcp_flags_fin"; public static final int TCP_FLAGS_PSH_BITS = 1; public static final String TCP_FLAGS_PSH_VAR = "tcp_flags_psh"; public static final int TCP_FLAGS_RST_BITS = 1; public static final String TCP_FLAGS_RST_VAR = "tcp_flags_rst"; public static final int TCP_FLAGS_SYN_BITS = 1; public static final String TCP_FLAGS_SYN_VAR = "tcp_flags_syn"; public static final int TCP_FLAGS_URG_BITS = 1; public static final String TCP_FLAGS_URG_VAR = "tcp_flags_urg"; @SuppressWarnings("unused") private static void debug(BooleanExpr condition, List<Statement> statements) { RuleExpr rule = new RuleExpr(condition, DebugExpr.INSTANCE); statements.add(rule); } private static BooleanExpr getMatchAclRules_portHelper(Set<SubRange> ranges, String portVar) { return new RangeMatchExpr(portVar, PORT_BITS, ranges); } private static List<String> getPacketVars() { List<String> vars = new ArrayList<>(); vars.add(SRC_IP_VAR); vars.add(DST_IP_VAR); vars.add(SRC_PORT_VAR); vars.add(DST_PORT_VAR); vars.add(IP_PROTOCOL_VAR); vars.add(DSCP_VAR); vars.add(ECN_VAR); vars.add(FRAGMENT_OFFSET_VAR); vars.add(ICMP_TYPE_VAR); vars.add(ICMP_CODE_VAR); vars.add(PACKET_LENGTH_VAR); vars.add(STATE_VAR); vars.add(TCP_FLAGS_CWR_VAR); vars.add(TCP_FLAGS_ECE_VAR); vars.add(TCP_FLAGS_URG_VAR); vars.add(TCP_FLAGS_ACK_VAR); vars.add(TCP_FLAGS_PSH_VAR); vars.add(TCP_FLAGS_RST_VAR); vars.add(TCP_FLAGS_SYN_VAR); vars.add(TCP_FLAGS_FIN_VAR); return vars; } public static Map<String, FuncDecl> getRelDeclFuncDecls( List<Statement> existingStatements, Context ctx) throws Z3Exception { Map<String, FuncDecl> funcDecls = new LinkedHashMap<>(); Set<String> relations = new TreeSet<>(); for (Statement existingStatement : existingStatements) { relations.addAll(existingStatement.getRelations()); } relations.add(QueryRelationExpr.NAME); for (String packetRel : relations) { List<Integer> sizes = new ArrayList<>(); sizes.addAll(PACKET_VAR_SIZES.values()); DeclareRelExpr declaration = new DeclareRelExpr(packetRel, sizes); funcDecls.put(packetRel, declaration.toFuncDecl(ctx)); } return funcDecls; } public static List<Statement> getVarDeclExprs() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Variable Declarations")); for (Entry<String, Integer> e : PACKET_VAR_SIZES.entrySet()) { String var = e.getKey(); int size = e.getValue(); statements.add(new DeclareVarExpr(var, size)); } return statements; } public static String indent(int n) { String output = ""; for (int i = 0; i < n; i++) { output += " "; } return output; } private static Map<String, Integer> initPacketVarSizes() { Map<String, Integer> varSizes = new LinkedHashMap<>(); varSizes.put(SRC_IP_VAR, IP_BITS); varSizes.put(DST_IP_VAR, IP_BITS); varSizes.put(SRC_PORT_VAR, PORT_BITS); varSizes.put(DST_PORT_VAR, PORT_BITS); varSizes.put(IP_PROTOCOL_VAR, PROTOCOL_BITS); varSizes.put(DSCP_VAR, DSCP_BITS); varSizes.put(ECN_VAR, ECN_BITS); varSizes.put(FRAGMENT_OFFSET_VAR, FRAGMENT_OFFSET_BITS); varSizes.put(ICMP_TYPE_VAR, ICMP_TYPE_BITS); varSizes.put(ICMP_CODE_VAR, ICMP_CODE_BITS); varSizes.put(PACKET_LENGTH_VAR, PACKET_LENGTH_BITS); varSizes.put(STATE_VAR, STATE_BITS); varSizes.put(TCP_FLAGS_CWR_VAR, TCP_FLAGS_CWR_BITS); varSizes.put(TCP_FLAGS_ECE_VAR, TCP_FLAGS_ECE_BITS); varSizes.put(TCP_FLAGS_URG_VAR, TCP_FLAGS_URG_BITS); varSizes.put(TCP_FLAGS_ACK_VAR, TCP_FLAGS_ACK_BITS); varSizes.put(TCP_FLAGS_PSH_VAR, TCP_FLAGS_PSH_BITS); varSizes.put(TCP_FLAGS_RST_VAR, TCP_FLAGS_RST_BITS); varSizes.put(TCP_FLAGS_SYN_VAR, TCP_FLAGS_SYN_BITS); varSizes.put(TCP_FLAGS_FIN_VAR, TCP_FLAGS_FIN_BITS); return varSizes; } private static boolean isLoopbackInterface(String ifaceName) { String lcIfaceName = ifaceName.toLowerCase(); return lcIfaceName.startsWith("lo"); } public static BooleanExpr matchHeaderSpace(HeaderSpace headerSpace) { AndExpr match = new AndExpr(); Set<IpWildcard> srcIpWildcards = headerSpace.getSrcIps(); Set<IpWildcard> srcIpWildcardsBlacklist = headerSpace.getNotSrcIps(); Set<IpWildcard> srcOrDstIpWildcards = headerSpace.getSrcOrDstIps(); Set<IpWildcard> dstIpWildcards = headerSpace.getDstIps(); Set<IpWildcard> dstIpWildcardsBlacklist = headerSpace.getNotDstIps(); Set<IpProtocol> ipProtocols = headerSpace.getIpProtocols(); Set<IpProtocol> notIpProtocols = headerSpace.getNotIpProtocols(); Set<SubRange> srcPortRanges = new LinkedHashSet<>(); srcPortRanges.addAll(headerSpace.getSrcPorts()); Set<SubRange> notSrcPortRanges = new LinkedHashSet<>(); notSrcPortRanges.addAll(headerSpace.getNotSrcPorts()); Set<SubRange> srcOrDstPortRanges = new LinkedHashSet<>(); srcOrDstPortRanges.addAll(headerSpace.getSrcOrDstPorts()); Set<SubRange> dstPortRanges = new LinkedHashSet<>(); dstPortRanges.addAll(headerSpace.getDstPorts()); Set<SubRange> notDstPortRanges = new LinkedHashSet<>(); notDstPortRanges.addAll(headerSpace.getNotDstPorts()); Set<Protocol> dstProtocols = headerSpace.getDstProtocols(); Set<Protocol> notDstProtocols = headerSpace.getNotDstProtocols(); Set<Protocol> srcProtocols = headerSpace.getSrcProtocols(); Set<Protocol> notSrcProtocols = headerSpace.getNotSrcProtocols(); Set<Protocol> srcOrDstProtocols = headerSpace.getSrcOrDstProtocols(); Set<SubRange> fragmentOffsetRanges = new LinkedHashSet<>(); fragmentOffsetRanges.addAll(headerSpace.getFragmentOffsets()); Set<SubRange> notFragmentOffsetRanges = new LinkedHashSet<>(); notFragmentOffsetRanges.addAll(headerSpace.getNotFragmentOffsets()); Set<SubRange> icmpTypes = headerSpace.getIcmpTypes(); Set<SubRange> notIcmpTypes = headerSpace.getNotIcmpTypes(); Set<SubRange> icmpCodes = headerSpace.getIcmpCodes(); Set<SubRange> notIcmpCodes = headerSpace.getNotIcmpCodes(); Set<SubRange> packetLengths = headerSpace.getPacketLengths(); Set<SubRange> notPacketLengths = headerSpace.getNotPacketLengths(); Set<State> states = headerSpace.getStates(); List<TcpFlags> tcpFlags = headerSpace.getTcpFlags(); Set<Integer> dscps = headerSpace.getDscps(); Set<Integer> notDscps = headerSpace.getDscps(); Set<Integer> ecns = headerSpace.getEcns(); Set<Integer> notEcns = headerSpace.getEcns(); // match ipProtocols if (ipProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (IpProtocol protocol : ipProtocols) { int protocolNumber = protocol.number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchesSomeProtocol.addDisjunct(matchProtocol); } match.addConjunct(matchesSomeProtocol); } // don't match notIpProtocols if (notIpProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (IpProtocol protocol : notIpProtocols) { int protocolNumber = protocol.number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchesSomeProtocol.addDisjunct(matchProtocol); } match.addConjunct(new NotExpr(matchesSomeProtocol)); } // destination protocols if (dstProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (Protocol protocol : dstProtocols) { AndExpr matchProtocolAndPort = new AndExpr(); int protocolNumber = protocol.getIpProtocol().number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchProtocolAndPort.addConjunct(matchProtocol); Integer port = protocol.getPort(); if (port != null) { VarIntExpr portVar = new VarIntExpr(DST_PORT_VAR); LitIntExpr portLit = new LitIntExpr(port, PORT_BITS); EqExpr matchPort = new EqExpr(portVar, portLit); matchProtocolAndPort.addConjunct(matchPort); } matchesSomeProtocol.addDisjunct(matchProtocolAndPort); } match.addConjunct(matchesSomeProtocol); } // not destination protocols if (notDstProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (Protocol protocol : notDstProtocols) { AndExpr matchProtocolAndPort = new AndExpr(); int protocolNumber = protocol.getIpProtocol().number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchProtocolAndPort.addConjunct(matchProtocol); Integer port = protocol.getPort(); if (port != null) { VarIntExpr portVar = new VarIntExpr(DST_PORT_VAR); LitIntExpr portLit = new LitIntExpr(port, PORT_BITS); EqExpr matchPort = new EqExpr(portVar, portLit); matchProtocolAndPort.addConjunct(matchPort); } matchesSomeProtocol.addDisjunct(matchProtocolAndPort); } NotExpr notMatch = new NotExpr(matchesSomeProtocol); match.addConjunct(notMatch); } // source protocols if (srcProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (Protocol protocol : srcProtocols) { AndExpr matchProtocolAndPort = new AndExpr(); int protocolNumber = protocol.getIpProtocol().number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchProtocolAndPort.addConjunct(matchProtocol); Integer port = protocol.getPort(); if (port != null) { VarIntExpr portVar = new VarIntExpr(SRC_PORT_VAR); LitIntExpr portLit = new LitIntExpr(port, PORT_BITS); EqExpr matchPort = new EqExpr(portVar, portLit); matchProtocolAndPort.addConjunct(matchPort); } matchesSomeProtocol.addDisjunct(matchProtocolAndPort); } match.addConjunct(matchesSomeProtocol); } // not source protocols if (notSrcProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (Protocol protocol : notSrcProtocols) { AndExpr matchProtocolAndPort = new AndExpr(); int protocolNumber = protocol.getIpProtocol().number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchProtocolAndPort.addConjunct(matchProtocol); Integer port = protocol.getPort(); if (port != null) { VarIntExpr portVar = new VarIntExpr(SRC_PORT_VAR); LitIntExpr portLit = new LitIntExpr(port, PORT_BITS); EqExpr matchPort = new EqExpr(portVar, portLit); matchProtocolAndPort.addConjunct(matchPort); } matchesSomeProtocol.addDisjunct(matchProtocolAndPort); } NotExpr notMatch = new NotExpr(matchesSomeProtocol); match.addConjunct(notMatch); } // source or destination protocols if (srcOrDstProtocols.size() > 0) { OrExpr matchesSomeProtocol = new OrExpr(); for (Protocol protocol : srcOrDstProtocols) { AndExpr matchProtocolAndPort = new AndExpr(); int protocolNumber = protocol.getIpProtocol().number(); VarIntExpr protocolVar = new VarIntExpr(IP_PROTOCOL_VAR); LitIntExpr protocolLit = new LitIntExpr(protocolNumber, PROTOCOL_BITS); EqExpr matchProtocol = new EqExpr(protocolVar, protocolLit); matchProtocolAndPort.addConjunct(matchProtocol); Integer port = protocol.getPort(); if (port != null) { VarIntExpr dstPortVar = new VarIntExpr(DST_PORT_VAR); VarIntExpr srcPortVar = new VarIntExpr(SRC_PORT_VAR); LitIntExpr portLit = new LitIntExpr(port, PORT_BITS); EqExpr matchDstPort = new EqExpr(dstPortVar, portLit); EqExpr matchSrcPort = new EqExpr(srcPortVar, portLit); OrExpr matchSrcOrDstPort = new OrExpr(); matchSrcOrDstPort.addDisjunct(matchDstPort); matchSrcOrDstPort.addDisjunct(matchSrcPort); matchProtocolAndPort.addConjunct(matchSrcOrDstPort); } matchesSomeProtocol.addDisjunct(matchProtocolAndPort); } match.addConjunct(matchesSomeProtocol); } // match srcIp if (srcIpWildcards.size() > 0) { OrExpr matchSomeSrcIpRange = new OrExpr(); for (IpWildcard srcIpWildcard : srcIpWildcards) { if (srcIpWildcard.isPrefix()) { Prefix srcPrefix = srcIpWildcard.toPrefix(); long srcIp = srcPrefix.getAddress().asLong(); int srcIpWildcardBits = IP_BITS - srcPrefix.getPrefixLength(); int srcIpStart = srcIpWildcardBits; int srcIpEnd = IP_BITS - 1; if (srcIpStart < IP_BITS) { IntExpr extractSrcIp = newExtractExpr(SRC_IP_VAR, srcIpStart, srcIpEnd); LitIntExpr srcIpMatchLit = new LitIntExpr(srcIp, srcIpStart, srcIpEnd); EqExpr matchsrcIp = new EqExpr(extractSrcIp, srcIpMatchLit); matchSomeSrcIpRange.addDisjunct(matchsrcIp); } else { matchSomeSrcIpRange.addDisjunct(TrueExpr.INSTANCE); } } else { long srcIp = srcIpWildcard.getIp().asLong(); long wildcard = srcIpWildcard.getWildcard().asLong(); AndExpr matchSrcIp = new AndExpr(); for (int currentBitIndex = 0; currentBitIndex < IP_BITS; currentBitIndex++) { long mask = 1l << currentBitIndex; long currentWildcardBit = mask & wildcard; boolean useBit = currentWildcardBit == 0; if (useBit) { IntExpr extractSrcIp = new ExtractExpr(SRC_IP_VAR, currentBitIndex, currentBitIndex); LitIntExpr srcIpMatchLit = new LitIntExpr(srcIp, currentBitIndex, currentBitIndex); EqExpr matchSrcIpBit = new EqExpr(extractSrcIp, srcIpMatchLit); matchSrcIp.addConjunct(matchSrcIpBit); } } matchSomeSrcIpRange.addDisjunct(matchSrcIp); } } match.addConjunct(matchSomeSrcIpRange); } // don't match srcIpBlacklist if (srcIpWildcardsBlacklist.size() > 0) { OrExpr matchSomeSrcIpRange = new OrExpr(); for (IpWildcard srcIpWildcard : srcIpWildcardsBlacklist) { if (srcIpWildcard.isPrefix()) { Prefix srcPrefix = srcIpWildcard.toPrefix(); long srcIp = srcPrefix.getAddress().asLong(); int srcIpWildcardBits = IP_BITS - srcPrefix.getPrefixLength(); int srcIpStart = srcIpWildcardBits; int srcIpEnd = IP_BITS - 1; if (srcIpStart < IP_BITS) { IntExpr extractSrcIp = newExtractExpr(SRC_IP_VAR, srcIpStart, srcIpEnd); LitIntExpr srcIpMatchLit = new LitIntExpr(srcIp, srcIpStart, srcIpEnd); EqExpr matchsrcIp = new EqExpr(extractSrcIp, srcIpMatchLit); matchSomeSrcIpRange.addDisjunct(matchsrcIp); } else { matchSomeSrcIpRange.addDisjunct(TrueExpr.INSTANCE); } } else { long srcIp = srcIpWildcard.getIp().asLong(); long wildcard = srcIpWildcard.getWildcard().asLong(); AndExpr matchSrcIp = new AndExpr(); for (int currentBitIndex = 0; currentBitIndex < IP_BITS; currentBitIndex++) { long mask = 1l << currentBitIndex; long currentWildcardBit = mask & wildcard; boolean useBit = currentWildcardBit == 0; if (useBit) { IntExpr extractSrcIp = new ExtractExpr(SRC_IP_VAR, currentBitIndex, currentBitIndex); LitIntExpr srcIpMatchLit = new LitIntExpr(srcIp, currentBitIndex, currentBitIndex); EqExpr matchSrcIpBit = new EqExpr(extractSrcIp, srcIpMatchLit); matchSrcIp.addConjunct(matchSrcIpBit); } } matchSomeSrcIpRange.addDisjunct(matchSrcIp); } } match.addConjunct(new NotExpr(matchSomeSrcIpRange)); } // match srcOrDstIp if (srcOrDstIpWildcards.size() > 0) { OrExpr matchSomeSrcOrDstIpRange = new OrExpr(); for (IpWildcard srcOrDstIpWildcard : srcOrDstIpWildcards) { if (srcOrDstIpWildcard.isPrefix()) { Prefix srcOrDstPrefix = srcOrDstIpWildcard.toPrefix(); long srcOrDstIp = srcOrDstPrefix.getAddress().asLong(); int srcOrDstIpWildcardBits = IP_BITS - srcOrDstPrefix.getPrefixLength(); int srcOrDstIpStart = srcOrDstIpWildcardBits; int srcOrDstIpEnd = IP_BITS - 1; if (srcOrDstIpStart < IP_BITS) { IntExpr extractSrcIp = newExtractExpr(SRC_IP_VAR, srcOrDstIpStart, srcOrDstIpEnd); IntExpr extractDstIp = newExtractExpr(DST_IP_VAR, srcOrDstIpStart, srcOrDstIpEnd); LitIntExpr srcOrDstIpMatchLit = new LitIntExpr(srcOrDstIp, srcOrDstIpStart, srcOrDstIpEnd); EqExpr matchSrcIp = new EqExpr(extractSrcIp, srcOrDstIpMatchLit); EqExpr matchDstIp = new EqExpr(extractDstIp, srcOrDstIpMatchLit); matchSomeSrcOrDstIpRange.addDisjunct(matchSrcIp); matchSomeSrcOrDstIpRange.addDisjunct(matchDstIp); } else { matchSomeSrcOrDstIpRange.addDisjunct(TrueExpr.INSTANCE); } } else { long srcOrDstIp = srcOrDstIpWildcard.getIp().asLong(); long wildcard = srcOrDstIpWildcard.getWildcard().asLong(); AndExpr matchSrcIp = new AndExpr(); AndExpr matchDstIp = new AndExpr(); for (int currentBitIndex = 0; currentBitIndex < IP_BITS; currentBitIndex++) { long mask = 1l << currentBitIndex; long currentWildcardBit = mask & wildcard; boolean useBit = currentWildcardBit == 0; if (useBit) { IntExpr extractSrcIp = new ExtractExpr(SRC_IP_VAR, currentBitIndex, currentBitIndex); IntExpr extractDstIp = new ExtractExpr(DST_IP_VAR, currentBitIndex, currentBitIndex); LitIntExpr srcOrDstIpMatchLit = new LitIntExpr(srcOrDstIp, currentBitIndex, currentBitIndex); EqExpr matchSrcIpBit = new EqExpr(extractSrcIp, srcOrDstIpMatchLit); EqExpr matchDstIpBit = new EqExpr(extractDstIp, srcOrDstIpMatchLit); matchSrcIp.addConjunct(matchSrcIpBit); matchDstIp.addConjunct(matchDstIpBit); } } matchSomeSrcOrDstIpRange.addDisjunct(matchSrcIp); matchSomeSrcOrDstIpRange.addDisjunct(matchDstIp); } } match.addConjunct(matchSomeSrcOrDstIpRange); } // match dstIp if (dstIpWildcards.size() > 0) { OrExpr matchSomeDstIpRange = new OrExpr(); for (IpWildcard dstIpWildcard : dstIpWildcards) { if (dstIpWildcard.isPrefix()) { Prefix dstPrefix = dstIpWildcard.toPrefix(); long dstIp = dstPrefix.getAddress().asLong(); int dstIpWildcardBits = IP_BITS - dstPrefix.getPrefixLength(); int dstIpStart = dstIpWildcardBits; int dstIpEnd = IP_BITS - 1; if (dstIpStart < IP_BITS) { IntExpr extractDstIp = newExtractExpr(DST_IP_VAR, dstIpStart, dstIpEnd); LitIntExpr dstIpMatchLit = new LitIntExpr(dstIp, dstIpStart, dstIpEnd); EqExpr matchDstIp = new EqExpr(extractDstIp, dstIpMatchLit); matchSomeDstIpRange.addDisjunct(matchDstIp); } else { matchSomeDstIpRange.addDisjunct(TrueExpr.INSTANCE); } } else { long dstIp = dstIpWildcard.getIp().asLong(); long wildcard = dstIpWildcard.getWildcard().asLong(); AndExpr matchDstIp = new AndExpr(); for (int currentBitIndex = 0; currentBitIndex < IP_BITS; currentBitIndex++) { long mask = 1l << currentBitIndex; long currentWildcardBit = mask & wildcard; boolean useBit = currentWildcardBit == 0; if (useBit) { IntExpr extractSrcIp = new ExtractExpr(DST_IP_VAR, currentBitIndex, currentBitIndex); LitIntExpr dstIpMatchLit = new LitIntExpr(dstIp, currentBitIndex, currentBitIndex); EqExpr matchDstIpBit = new EqExpr(extractSrcIp, dstIpMatchLit); matchDstIp.addConjunct(matchDstIpBit); } } matchSomeDstIpRange.addDisjunct(matchDstIp); } } match.addConjunct(matchSomeDstIpRange); } // don't match dstIpBlacklist if (dstIpWildcardsBlacklist.size() > 0) { OrExpr matchSomeDstIpRange = new OrExpr(); for (IpWildcard dstIpWildcard : dstIpWildcardsBlacklist) { if (dstIpWildcard.isPrefix()) { Prefix dstPrefix = dstIpWildcard.toPrefix(); long dstIp = dstPrefix.getAddress().asLong(); int dstIpWildcardBits = IP_BITS - dstPrefix.getPrefixLength(); int dstIpStart = dstIpWildcardBits; int dstIpEnd = IP_BITS - 1; if (dstIpStart < IP_BITS) { IntExpr extractDstIp = newExtractExpr(DST_IP_VAR, dstIpStart, dstIpEnd); LitIntExpr dstIpMatchLit = new LitIntExpr(dstIp, dstIpStart, dstIpEnd); EqExpr matchDstIp = new EqExpr(extractDstIp, dstIpMatchLit); matchSomeDstIpRange.addDisjunct(matchDstIp); } else { matchSomeDstIpRange.addDisjunct(TrueExpr.INSTANCE); } } else { long dstIp = dstIpWildcard.getIp().asLong(); long wildcard = dstIpWildcard.getWildcard().asLong(); AndExpr matchDstIp = new AndExpr(); for (int currentBitIndex = 0; currentBitIndex < IP_BITS; currentBitIndex++) { long mask = 1l << currentBitIndex; long currentWildcardBit = mask & wildcard; boolean useBit = currentWildcardBit == 0; if (useBit) { IntExpr extractSrcIp = new ExtractExpr(DST_IP_VAR, currentBitIndex, currentBitIndex); LitIntExpr dstIpMatchLit = new LitIntExpr(dstIp, currentBitIndex, currentBitIndex); EqExpr matchDstIpBit = new EqExpr(extractSrcIp, dstIpMatchLit); matchDstIp.addConjunct(matchDstIpBit); } } matchSomeDstIpRange.addDisjunct(matchDstIp); } } match.addConjunct(new NotExpr(matchSomeDstIpRange)); } // match srcPort if (srcPortRanges != null && srcPortRanges.size() > 0) { BooleanExpr matchSrcPort = getMatchAclRules_portHelper(srcPortRanges, SRC_PORT_VAR); match.addConjunct(matchSrcPort); } // don't match notSrcPort if (notSrcPortRanges != null && notSrcPortRanges.size() > 0) { BooleanExpr matchSrcPort = getMatchAclRules_portHelper( notSrcPortRanges, SRC_PORT_VAR); match.addConjunct(new NotExpr(matchSrcPort)); } // match srcOrDstPort if (srcOrDstPortRanges != null && srcOrDstPortRanges.size() > 0) { BooleanExpr matchSrcPort = getMatchAclRules_portHelper( srcOrDstPortRanges, SRC_PORT_VAR); BooleanExpr matchDstPort = getMatchAclRules_portHelper( srcOrDstPortRanges, DST_PORT_VAR); OrExpr matchSrcOrDstPort = new OrExpr(); matchSrcOrDstPort.addDisjunct(matchSrcPort); matchSrcOrDstPort.addDisjunct(matchDstPort); match.addConjunct(matchSrcOrDstPort); } // match dstPort if (dstPortRanges != null && dstPortRanges.size() > 0) { BooleanExpr matchDstPort = getMatchAclRules_portHelper(dstPortRanges, DST_PORT_VAR); match.addConjunct(matchDstPort); } // don't match notDstPort if (notDstPortRanges != null && notDstPortRanges.size() > 0) { BooleanExpr matchDstPort = getMatchAclRules_portHelper( notDstPortRanges, DST_PORT_VAR); match.addConjunct(new NotExpr(matchDstPort)); } // match dscp if (!dscps.isEmpty()) { OrExpr matchSomeDscp = new OrExpr(); match.addConjunct(matchSomeDscp); for (int dscp : dscps) { EqExpr matchCurrentDscp = new EqExpr(new VarIntExpr(DSCP_VAR), new LitIntExpr(dscp, DSCP_BITS)); matchSomeDscp.addDisjunct(matchCurrentDscp); } } // don't match notDscp if (!notDscps.isEmpty()) { OrExpr matchSomeDscp = new OrExpr(); match.addConjunct(new NotExpr(matchSomeDscp)); for (int dscp : notDscps) { EqExpr matchCurrentDscp = new EqExpr(new VarIntExpr(DSCP_VAR), new LitIntExpr(dscp, DSCP_BITS)); matchSomeDscp.addDisjunct(matchCurrentDscp); } } // match ecn if (!ecns.isEmpty()) { OrExpr matchSomeEcn = new OrExpr(); match.addConjunct(matchSomeEcn); for (int ecn : ecns) { EqExpr matchCurrentEcn = new EqExpr(new VarIntExpr(ECN_VAR), new LitIntExpr(ecn, ECN_BITS)); matchSomeEcn.addDisjunct(matchCurrentEcn); } } // don't match notEcn if (!notEcns.isEmpty()) { OrExpr matchSomeEcn = new OrExpr(); match.addConjunct(new NotExpr(matchSomeEcn)); for (int ecn : notEcns) { EqExpr matchCurrentEcn = new EqExpr(new VarIntExpr(ECN_VAR), new LitIntExpr(ecn, ECN_BITS)); matchSomeEcn.addDisjunct(matchCurrentEcn); } } // match fragmentOffset if (fragmentOffsetRanges != null && fragmentOffsetRanges.size() > 0) { BooleanExpr matchFragmentOffset = new RangeMatchExpr( FRAGMENT_OFFSET_VAR, FRAGMENT_OFFSET_BITS, fragmentOffsetRanges); match.addConjunct(matchFragmentOffset); } // don't match notFragmentOffset if (notFragmentOffsetRanges != null && notFragmentOffsetRanges.size() > 0) { BooleanExpr matchFragmentOffset = new RangeMatchExpr( FRAGMENT_OFFSET_VAR, FRAGMENT_OFFSET_BITS, notFragmentOffsetRanges); match.addConjunct(new NotExpr(matchFragmentOffset)); } // match connection-tracking state if (!states.isEmpty()) { OrExpr matchSomeState = new OrExpr(); match.addConjunct(matchSomeState); for (State state : states) { EqExpr matchCurrentState = new EqExpr(new VarIntExpr(STATE_VAR), new LitIntExpr(state.number(), STATE_BITS)); matchSomeState.addDisjunct(matchCurrentState); } } // match icmpTypes if (icmpTypes != null && icmpTypes.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(ICMP_TYPE_VAR, ICMP_TYPE_BITS, icmpTypes); match.addConjunct(matchRange); } // don't match notIcmpTypes if (notIcmpTypes != null && notIcmpTypes.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(ICMP_TYPE_VAR, ICMP_TYPE_BITS, notIcmpTypes); match.addConjunct(new NotExpr(matchRange)); } // match icmpCodes if (icmpCodes != null && icmpCodes.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(ICMP_CODE_VAR, ICMP_CODE_BITS, icmpCodes); match.addConjunct(matchRange); } // don't match notIcmpCodes if (notIcmpCodes != null && notIcmpCodes.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(ICMP_CODE_VAR, ICMP_CODE_BITS, notIcmpCodes); match.addConjunct(new NotExpr(matchRange)); } // match packetLengths if (packetLengths != null && packetLengths.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(PACKET_LENGTH_VAR, PACKET_LENGTH_BITS, packetLengths); match.addConjunct(matchRange); } // don't match notPacketLengths if (notPacketLengths != null && notPacketLengths.size() > 0) { BooleanExpr matchRange = new RangeMatchExpr(PACKET_LENGTH_VAR, PACKET_LENGTH_BITS, notPacketLengths); match.addConjunct(new NotExpr(matchRange)); } // match tcp-flags if (!tcpFlags.isEmpty()) { OrExpr matchSomeTcpFlags = new OrExpr(); match.addConjunct(matchSomeTcpFlags); for (TcpFlags currentTcpFlags : tcpFlags) { AndExpr matchCurrentTcpFlags = new AndExpr(); matchSomeTcpFlags.addDisjunct(matchCurrentTcpFlags); LitIntExpr one = new LitIntExpr(1, 1); LitIntExpr zero = new LitIntExpr(0, 1); if (currentTcpFlags.getUseCwr()) { LitIntExpr bit = currentTcpFlags.getCwr() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_CWR_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseEce()) { LitIntExpr bit = currentTcpFlags.getEce() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_ECE_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseUrg()) { LitIntExpr bit = currentTcpFlags.getUrg() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_URG_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseAck()) { LitIntExpr bit = currentTcpFlags.getAck() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_ACK_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUsePsh()) { LitIntExpr bit = currentTcpFlags.getPsh() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_PSH_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseRst()) { LitIntExpr bit = currentTcpFlags.getRst() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_RST_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseSyn()) { LitIntExpr bit = currentTcpFlags.getSyn() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_SYN_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } if (currentTcpFlags.getUseFin()) { LitIntExpr bit = currentTcpFlags.getFin() ? one : zero; EqExpr matchFlag = new EqExpr(new VarIntExpr(TCP_FLAGS_FIN_VAR), bit); matchCurrentTcpFlags.addConjunct(matchFlag); } } } if (headerSpace.getNegate()) { return new NotExpr(match); } else { return match; } } private static IntExpr newExtractExpr(String var, int low, int high) { int varSize = PACKET_VAR_SIZES.get(var); return newExtractExpr(var, varSize, low, high); } private static IntExpr newExtractExpr(String var, int varSize, int low, int high) { if (low == 0 && high == varSize - 1) { return new VarIntExpr(var); } else { return new ExtractExpr(var, low, high); } } private final Map<String, Configuration> _configurations; private final FibMap _fibs; private InterfaceSet _flowSinks; // private final PolicyRouteFibNodeMap _prFibs; private final boolean _simplify; private final EdgeSet _topologyEdges; private final Map<String, Set<Interface>> _topologyInterfaces; private List<String> _warnings; public Synthesizer(Map<String, Configuration> configurations, boolean simplify) { _configurations = configurations; _fibs = null; // _prFibs = null; _topologyEdges = null; _flowSinks = null; _simplify = simplify; _topologyInterfaces = null; _warnings = new ArrayList<>(); } public Synthesizer(Map<String, Configuration> configurations, DataPlane dataPlane, boolean simplify) { _configurations = configurations; _fibs = dataPlane.getFibs(); // _prFibs = dataPlane.getPolicyRouteFibNodeMap(); _topologyEdges = dataPlane.getTopologyEdges(); _flowSinks = dataPlane.getFlowSinks(); _simplify = simplify; _topologyInterfaces = new TreeMap<>(); _warnings = new ArrayList<>(); computeTopologyInterfaces(); pruneInterfaces(); } private void computeTopologyInterfaces() { for (String hostname : _configurations.keySet()) { _topologyInterfaces.put(hostname, new TreeSet<Interface>()); } for (Edge edge : _topologyEdges) { String hostname = edge.getNode1(); if (!_topologyInterfaces.containsKey(hostname)) { _topologyInterfaces.put(hostname, new TreeSet<Interface>()); } Set<Interface> interfaces = _topologyInterfaces.get(hostname); String interfaceName = edge.getInt1(); Interface i = _configurations.get(hostname).getInterfaces() .get(interfaceName); interfaces.add(i); } for (String hostname : _configurations.keySet()) { Configuration c = _configurations.get(hostname); Map<String, Interface> nodeInterfaces = c.getInterfaces(); for (String ifaceName : nodeInterfaces.keySet()) { if (isFlowSink(hostname, ifaceName)) { Interface iface = nodeInterfaces.get(ifaceName); if (iface.getActive()) { Set<Interface> interfaces = _topologyInterfaces.get(hostname); interfaces.add(iface); } } } } } private List<Statement> getAcceptRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Node accept lead to universal accept")); for (String nodeName : _configurations.keySet()) { NodeAcceptExpr nodeAccept = new NodeAcceptExpr(nodeName); RuleExpr connectAccepts = new RuleExpr(nodeAccept, AcceptExpr.INSTANCE); statements.add(connectAccepts); } return statements; } private List<Statement> getDestRouteToPreOutEdgeRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rules for sending destination routed packets to preoutIface stage")); for (String hostname : _fibs.keySet()) { Configuration c = _configurations.get(hostname); c.getVrfs().forEach((vrfName, vrf) -> { TreeSet<FibRow> fibSet = new TreeSet<>( _fibs.get(hostname).get(vrfName)); if (fibSet.isEmpty() || !fibSet.first().getPrefix().equals(Prefix.ZERO)) { // no default route, so add one that drops traffic FibRow dropDefaultRow = new FibRow(Prefix.ZERO, FibRow.DROP_INTERFACE, "", ""); fibSet.add(dropDefaultRow); } FibRow[] fib = fibSet.toArray(new FibRow[] {}); for (int i = 0; i < fib.length; i++) { FibRow currentRow = fib[i]; Set<FibRow> notRows = new TreeSet<>(); for (int j = i + 1; j < fib.length; j++) { FibRow specificRow = fib[j]; long currentStart = currentRow.getPrefix().getAddress() .asLong(); long currentEnd = currentRow.getPrefix().getEndAddress() .asLong(); long specificStart = specificRow.getPrefix().getAddress() .asLong(); long specificEnd = specificRow.getPrefix().getEndAddress() .asLong(); // check whether later prefix is contained in this one if (currentStart <= specificStart && specificEnd <= currentEnd) { if (currentStart == specificStart && currentEnd == specificEnd) { // load balancing continue; } if (currentRow.getInterface() .equals(specificRow.getInterface()) && currentRow.getNextHop() .equals(specificRow.getNextHop()) && currentRow.getNextHopInterface() .equals(specificRow.getNextHopInterface())) { // no need to exclude packets matching the more specific // prefix, // since they would go out same edge continue; } // exclude packets that match a more specific prefix that // would go out a different interface notRows.add(specificRow); } else { break; } } AndExpr conditions = new AndExpr(); PostInVrfExpr postInVrf = new PostInVrfExpr(hostname, vrfName); conditions.addConjunct(postInVrf); DestinationRouteExpr destRoute = new DestinationRouteExpr( hostname); conditions.addConjunct(destRoute); String ifaceOutName = currentRow.getInterface(); PacketRelExpr action; if (isLoopbackInterface(ifaceOutName) || CommonUtil.isNullInterface(ifaceOutName)) { action = new NodeDropNullRouteExpr(hostname); } else if (ifaceOutName.equals(FibRow.DROP_INTERFACE)) { action = new NodeDropNoRouteExpr(hostname); } else { String nextHop = currentRow.getNextHop(); String ifaceInName = currentRow.getNextHopInterface(); action = new PreOutEdgeExpr(hostname, ifaceOutName, nextHop, ifaceInName); } // must not match more specific routes for (FibRow notRow : notRows) { int prefixLength = notRow.getPrefix().getPrefixLength(); long prefix = notRow.getPrefix().getAddress().asLong(); int first = IP_BITS - prefixLength; if (first >= IP_BITS) { continue; } int last = IP_BITS - 1; LitIntExpr prefixFragmentLit = new LitIntExpr(prefix, first, last); IntExpr prefixFragmentExt = newExtractExpr(DST_IP_VAR, first, last); NotExpr noPrefixMatch = new NotExpr(); EqExpr prefixMatch = new EqExpr(prefixFragmentExt, prefixFragmentLit); noPrefixMatch.SetArgument(prefixMatch); conditions.addConjunct(noPrefixMatch); } // must match route int prefixLength = currentRow.getPrefix().getPrefixLength(); long prefix = currentRow.getPrefix().getAddress().asLong(); int first = IP_BITS - prefixLength; if (first < IP_BITS) { int last = IP_BITS - 1; LitIntExpr prefixFragmentLit = new LitIntExpr(prefix, first, last); IntExpr prefixFragmentExt = newExtractExpr(DST_IP_VAR, first, last); EqExpr prefixMatch = new EqExpr(prefixFragmentExt, prefixFragmentLit); conditions.addConjunct(prefixMatch); } // then we forward out specified interface (or drop) RuleExpr rule = new RuleExpr(conditions, action); statements.add(rule); } }); } return statements; } private List<Statement> getDropRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Node drop lead to universal drop")); for (String nodeName : _configurations.keySet()) { NodeDropExpr nodeDrop = new NodeDropExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropExpr.INSTANCE); statements.add(connectDrops); } statements.add(new Comment("Node drop_acl lead to universal drop_acl")); for (String nodeName : _configurations.keySet()) { NodeDropAclExpr nodeDrop = new NodeDropAclExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropAclExpr.INSTANCE); statements.add(connectDrops); NodeDropExpr nodeDropBase = new NodeDropExpr(nodeName); RuleExpr connectNodeDrops = new RuleExpr(nodeDrop, nodeDropBase); statements.add(connectNodeDrops); } statements.add(new RuleExpr(DropAclExpr.INSTANCE, DropExpr.INSTANCE)); statements .add(new Comment("Node drop_acl_in lead to universal drop_acl_in")); for (String nodeName : _configurations.keySet()) { NodeDropAclInExpr nodeDrop = new NodeDropAclInExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropAclInExpr.INSTANCE); statements.add(connectDrops); NodeDropAclExpr nodeDropBase = new NodeDropAclExpr(nodeName); RuleExpr connectNodeDrops = new RuleExpr(nodeDrop, nodeDropBase); statements.add(connectNodeDrops); } statements .add(new RuleExpr(DropAclInExpr.INSTANCE, DropAclExpr.INSTANCE)); statements.add( new Comment("Node drop_acl_out lead to universal drop_acl_out")); for (String nodeName : _configurations.keySet()) { NodeDropAclOutExpr nodeDrop = new NodeDropAclOutExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropAclOutExpr.INSTANCE); statements.add(connectDrops); NodeDropAclExpr nodeDropBase = new NodeDropAclExpr(nodeName); RuleExpr connectNodeDrops = new RuleExpr(nodeDrop, nodeDropBase); statements.add(connectNodeDrops); } statements .add(new RuleExpr(DropAclOutExpr.INSTANCE, DropAclExpr.INSTANCE)); statements.add( new Comment("Node drop_no_route lead to universal drop_no_route")); for (String nodeName : _configurations.keySet()) { NodeDropNoRouteExpr nodeDrop = new NodeDropNoRouteExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropNoRouteExpr.INSTANCE); statements.add(connectDrops); NodeDropExpr nodeDropBase = new NodeDropExpr(nodeName); RuleExpr connectNodeDrops = new RuleExpr(nodeDrop, nodeDropBase); statements.add(connectNodeDrops); } statements.add(new RuleExpr(DropNoRouteExpr.INSTANCE, DropExpr.INSTANCE)); statements.add(new Comment( "Node drop_null_route lead to universal drop_null_route")); for (String nodeName : _configurations.keySet()) { NodeDropNullRouteExpr nodeDrop = new NodeDropNullRouteExpr(nodeName); RuleExpr connectDrops = new RuleExpr(nodeDrop, DropNullRouteExpr.INSTANCE); statements.add(connectDrops); NodeDropExpr nodeDropBase = new NodeDropExpr(nodeName); RuleExpr connectNodeDrops = new RuleExpr(nodeDrop, nodeDropBase); statements.add(connectNodeDrops); } statements .add(new RuleExpr(DropNullRouteExpr.INSTANCE, DropExpr.INSTANCE)); return statements; } private List<Statement> getExternalDstIpRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rule for matching external Destination IP - one not assigned to an active interface of any provided node")); Set<Ip> interfaceIps = new TreeSet<>(); for (Entry<String, Configuration> e : _configurations.entrySet()) { Configuration c = e.getValue(); for (Interface i : c.getInterfaces().values()) { if (i.getActive()) { Prefix prefix = i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); interfaceIps.add(ip); } } } } OrExpr dstIpMatchesSomeInterfaceIp = new OrExpr(); for (Ip ip : interfaceIps) { EqExpr dstIpMatchesSpecificInterfaceIp = new EqExpr( new VarIntExpr(DST_IP_VAR), new LitIntExpr(ip)); dstIpMatchesSomeInterfaceIp .addDisjunct(dstIpMatchesSpecificInterfaceIp); } NotExpr externalDstIp = new NotExpr(dstIpMatchesSomeInterfaceIp); RuleExpr externalDstIpRule = new RuleExpr(externalDstIp, ExternalDestinationIpExpr.INSTANCE); statements.add(externalDstIpRule); return statements; } private List<Statement> getExternalSrcIpRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rule for matching external Source IP - one not assigned to an active interface of any provided node")); Set<Ip> interfaceIps = new TreeSet<>(); for (Entry<String, Configuration> e : _configurations.entrySet()) { Configuration c = e.getValue(); for (Interface i : c.getInterfaces().values()) { if (i.getActive()) { Prefix prefix = i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); interfaceIps.add(ip); } } } } OrExpr srcIpMatchesSomeInterfaceIp = new OrExpr(); for (Ip ip : interfaceIps) { EqExpr srcIpMatchesSpecificInterfaceIp = new EqExpr( new VarIntExpr(SRC_IP_VAR), new LitIntExpr(ip)); srcIpMatchesSomeInterfaceIp .addDisjunct(srcIpMatchesSpecificInterfaceIp); } NotExpr externalSrcIp = new NotExpr(srcIpMatchesSomeInterfaceIp); RuleExpr externalSrcIpRule = new RuleExpr(externalSrcIp, ExternalSourceIpExpr.INSTANCE); statements.add(externalSrcIpRule); return statements; } private List<Statement> getFlowSinkAcceptRules() { List<Statement> statements = new ArrayList<>(); statements.add( new Comment("Post out flow sink interface leads to node accept")); for (NodeInterfacePair f : _flowSinks) { String hostname = f.getHostname(); String ifaceName = f.getInterface(); if (isFlowSink(hostname, ifaceName)) { PostOutInterfaceExpr postOutIface = new PostOutInterfaceExpr( hostname, ifaceName); NodeAcceptExpr nodeAccept = new NodeAcceptExpr(hostname); RuleExpr flowSinkAccept = new RuleExpr(postOutIface, nodeAccept); statements.add(flowSinkAccept); } } return statements; } private List<Statement> getInboundInterfaceToNodeAccept() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rules for connecting inbound_interface to node_accept")); for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); NodeAcceptExpr nodeAccept = new NodeAcceptExpr(hostname); for (Interface i : c.getInterfaces().values()) { String ifaceName = i.getName(); String vrf = i.getVrfName(); InboundInterfaceExpr inboundInterface = new InboundInterfaceExpr( hostname, ifaceName); // deal with origination totally independently of zone stuff AndExpr originateAcceptConditions = new AndExpr(); OriginateVrfExpr originate = new OriginateVrfExpr(hostname, vrf); originateAcceptConditions.addConjunct(inboundInterface); originateAcceptConditions.addConjunct(originate); RuleExpr originateToNodeAccept = new RuleExpr( originateAcceptConditions, nodeAccept); statements.add(originateToNodeAccept); Zone inboundZone = i.getZone(); AndExpr acceptConditions = new AndExpr(); acceptConditions.addConjunct(inboundInterface); if (inboundZone != null) { IpAccessList hostFilter = inboundZone.getToHostFilter(); if (hostFilter != null) { AclPermitExpr hostFilterPermit = new AclPermitExpr(hostname, hostFilter.getName()); acceptConditions.addConjunct(hostFilterPermit); } String inboundFilterName; IpAccessList inboundInterfaceFilter = inboundZone .getInboundInterfaceFilters().get(ifaceName); if (inboundInterfaceFilter != null) { inboundFilterName = inboundInterfaceFilter.getName(); } else { IpAccessList inboundFilter = inboundZone.getInboundFilter(); inboundFilterName = inboundFilter.getName(); } AclPermitExpr inboundFilterPermit = new AclPermitExpr(hostname, inboundFilterName); acceptConditions.addConjunct(inboundFilterPermit); } else { // no inbound zone. // accept if packet was orginated at this node and default // inbound action is accept if (c.getDefaultInboundAction() == LineAction.REJECT || c.getDefaultCrossZoneAction() == LineAction.REJECT) { acceptConditions.addConjunct(originate); } } if (inboundZone != null) { OrExpr crossFilterSatisfied = new OrExpr(); // If packet came in on inbound interface, accept. PostInInterfaceExpr postInInboundInterface = new PostInInterfaceExpr( hostname, ifaceName); crossFilterSatisfied.addDisjunct(postInInboundInterface); // Otherwise, the packet must be permitted by the appropriate // cross-zone filter for (Zone srcZone : c.getZones().values()) { AndExpr crossZoneConditions = new AndExpr(); String srcZoneName = srcZone.getName(); IpAccessList crossZoneFilter = srcZone.getToZonePolicies() .get(inboundZone.getName()); NonInboundSrcZoneExpr nonInboundSrcZone = new NonInboundSrcZoneExpr( hostname, srcZoneName); crossZoneConditions.addConjunct(nonInboundSrcZone); if (crossZoneFilter != null) { AclPermitExpr crossZonePermit = new AclPermitExpr(hostname, crossZoneFilter.getName()); crossZoneConditions.addConjunct(crossZonePermit); crossFilterSatisfied.addDisjunct(crossZoneConditions); } else if (c.getDefaultCrossZoneAction() == LineAction.ACCEPT) { crossFilterSatisfied.addDisjunct(crossZoneConditions); } } // handle case where src interface is not in a zone if (c.getDefaultCrossZoneAction() == LineAction.ACCEPT) { NonInboundNullSrcZoneExpr nonInboundNullSrcZone = new NonInboundNullSrcZoneExpr( hostname); crossFilterSatisfied.addDisjunct(nonInboundNullSrcZone); } acceptConditions.addConjunct(crossFilterSatisfied); } RuleExpr inboundInterfaceToNodeAccept = new RuleExpr( acceptConditions, nodeAccept); statements.add(inboundInterfaceToNodeAccept); } } return statements; } private List<Statement> getInboundInterfaceToNodeDrop() { List<Statement> statements = new ArrayList<>(); statements.add( new Comment("Rules for connecting inbound_interface to node_deny")); for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); NodeDropExpr nodeDrop = new NodeDropExpr(hostname); UnoriginalExpr unoriginal = new UnoriginalExpr(hostname); for (Interface i : c.getInterfaces().values()) { String ifaceName = i.getName(); InboundInterfaceExpr inboundInterface = new InboundInterfaceExpr( hostname, ifaceName); Zone inboundZone = i.getZone(); AndExpr dropConditions = new AndExpr(); dropConditions.addConjunct(unoriginal); dropConditions.addConjunct(inboundInterface); OrExpr failConditions = new OrExpr(); if (inboundZone != null) { IpAccessList hostFilter = inboundZone.getToHostFilter(); if (hostFilter != null) { AclDenyExpr hostFilterDeny = new AclDenyExpr(hostname, hostFilter.getName()); failConditions.addDisjunct(hostFilterDeny); } String inboundFilterName; IpAccessList inboundInterfaceFilter = inboundZone .getInboundInterfaceFilters().get(ifaceName); if (inboundInterfaceFilter != null) { inboundFilterName = inboundInterfaceFilter.getName(); } else { IpAccessList inboundFilter = inboundZone.getInboundFilter(); inboundFilterName = inboundFilter.getName(); } AclDenyExpr inboundFilterDeny = new AclDenyExpr(hostname, inboundFilterName); failConditions.addDisjunct(inboundFilterDeny); } else if (c.getDefaultInboundAction() == LineAction.REJECT || c.getDefaultCrossZoneAction() == LineAction.REJECT) { failConditions.addDisjunct(unoriginal); } if (inboundZone != null) { OrExpr crossFilterFailed = new OrExpr(); // If packet didn't come in on inbound interface, drop if denied // by the appropriate cross-zone filter // permitted by the appropriate cross-zone policy for (Zone srcZone : c.getZones().values()) { AndExpr crossZoneConditions = new AndExpr(); String srcZoneName = srcZone.getName(); IpAccessList crossZoneFilter = srcZone.getToZonePolicies() .get(inboundZone.getName()); NonInboundSrcZoneExpr nonInboundSrcZone = new NonInboundSrcZoneExpr( hostname, srcZoneName); crossZoneConditions.addConjunct(nonInboundSrcZone); if (crossZoneFilter != null) { AclDenyExpr crossZoneDeny = new AclDenyExpr(hostname, crossZoneFilter.getName()); crossZoneConditions.addConjunct(crossZoneDeny); crossFilterFailed.addDisjunct(crossZoneConditions); } else if (c.getDefaultCrossZoneAction() == LineAction.REJECT) { crossFilterFailed.addDisjunct(crossZoneConditions); } } // handle case where src interface is not in a zone if (c.getDefaultCrossZoneAction() == LineAction.REJECT) { NonInboundNullSrcZoneExpr nonInboundNullSrcZone = new NonInboundNullSrcZoneExpr( hostname); crossFilterFailed.addDisjunct(nonInboundNullSrcZone); } failConditions.addDisjunct(crossFilterFailed); } dropConditions.addConjunct(failConditions); RuleExpr inboundInterfaceToNodeDrop = new RuleExpr(dropConditions, nodeDrop); statements.add(inboundInterfaceToNodeDrop); } } return statements; } private List<Statement> getMatchAclRules() { List<Statement> statements = new ArrayList<>(); Comment comment = new Comment( "Rules for how packets can match acl lines"); statements.add(comment); Map<String, Map<String, IpAccessList>> matchAcls = new TreeMap<>(); // first we find out which acls we need to process // if data plane was provided as input, only check acls for topology // nodes/interfaces if (_topologyInterfaces != null) { for (String hostname : _topologyInterfaces.keySet()) { Configuration node = _configurations.get(hostname); Map<String, IpAccessList> aclMap = new TreeMap<>(); Set<Interface> interfaces = _topologyInterfaces.get(hostname); for (Interface iface : interfaces) { if (iface.getPrefix() != null) { IpAccessList aclIn = iface.getIncomingFilter(); IpAccessList aclOut = iface.getOutgoingFilter(); String routePolicy = iface.getRoutingPolicyName(); if (aclIn != null) { String name = aclIn.getName(); aclMap.put(name, aclIn); } if (aclOut != null) { String name = aclOut.getName(); aclMap.put(name, aclOut); } if (routePolicy != null) { throw new BatfishException( "Currently do not support interface routing-policy: '" + hostname + ":" + iface.getName() + ":" + routePolicy + "'"); // for (PolicyMapClause clause : routePolicy.getClauses()) // { // for (PolicyMapMatchLine matchLine : clause // .getMatchLines()) { // if (matchLine // .getType() == PolicyMapMatchType.IP_ACCESS_LIST) { // PolicyMapMatchIpAccessListLine matchAclLine = // (PolicyMapMatchIpAccessListLine) matchLine; // for (IpAccessList acl : matchAclLine.getLists()) { // String name = acl.getName(); // aclMap.put(name, acl); // } // } // } // } } } } for (Zone zone : node.getZones().values()) { IpAccessList fromHostFilter = zone.getFromHostFilter(); if (fromHostFilter != null) { aclMap.put(fromHostFilter.getName(), fromHostFilter); } IpAccessList toHostFilter = zone.getToHostFilter(); if (toHostFilter != null) { aclMap.put(toHostFilter.getName(), toHostFilter); } IpAccessList inboundFilter = zone.getInboundFilter(); if (inboundFilter != null) { aclMap.put(inboundFilter.getName(), inboundFilter); } for (IpAccessList inboundInterfaceFilter : zone .getInboundInterfaceFilters().values()) { aclMap.put(inboundInterfaceFilter.getName(), inboundInterfaceFilter); } for (IpAccessList toZoneFilter : zone.getToZonePolicies() .values()) { aclMap.put(toZoneFilter.getName(), toZoneFilter); } } if (aclMap.size() > 0) { matchAcls.put(hostname, aclMap); } } } else { // topology is null. just add all acls. for (Entry<String, Configuration> e : _configurations.entrySet()) { String hostname = e.getKey(); Configuration c = e.getValue(); matchAcls.put(hostname, c.getIpAccessLists()); } } for (Entry<String, Map<String, IpAccessList>> e : matchAcls.entrySet()) { String hostname = e.getKey(); Map<String, IpAccessList> aclMap = e.getValue(); for (String aclName : aclMap.keySet()) { statements.addAll(getMatchAclRules(hostname, aclName)); } } return statements; } private List<Statement> getMatchAclRules(String hostname, String aclName) { List<Statement> statements = new ArrayList<>(); Configuration c = _configurations.get(hostname); IpAccessList acl = c.getIpAccessLists().get(aclName); List<IpAccessListLine> lines = acl.getLines(); for (int i = 0; i < lines.size(); i++) { IpAccessListLine line = lines.get(i); AndExpr matchConditions = new AndExpr(); // ** must not match previous rule ** BooleanExpr prevNoMatch = (i > 0) ? new AclNoMatchExpr(hostname, aclName, i - 1) : TrueExpr.INSTANCE; BooleanExpr matchLineCriteria = matchHeaderSpace(line); matchConditions.addConjunct(prevNoMatch); matchConditions.addConjunct(matchLineCriteria); AclMatchExpr match = new AclMatchExpr(hostname, aclName, i); RuleExpr matchRule = new RuleExpr(matchConditions, match); statements.add(matchRule); // no match rule AndExpr noMatchConditions = new AndExpr(); BooleanExpr noMatchLineCriteria = new NotExpr(matchLineCriteria); noMatchConditions.addConjunct(noMatchLineCriteria); noMatchConditions.addConjunct(prevNoMatch); AclNoMatchExpr noMatch = new AclNoMatchExpr(hostname, aclName, i); RuleExpr noMatchRule = new RuleExpr(noMatchConditions, noMatch); statements.add(noMatchRule); // permit/deny rule for match PolicyExpr aclAction; switch (line.getAction()) { case ACCEPT: aclAction = new AclPermitExpr(hostname, aclName); break; case REJECT: aclAction = new AclDenyExpr(hostname, aclName); break; default: throw new Error("invalid action"); } RuleExpr action = new RuleExpr(match, aclAction); statements.add(action); } // deny rule for not matching last line int lastLineIndex = acl.getLines().size() - 1; AclDenyExpr aclDeny = new AclDenyExpr(hostname, aclName); AclNoMatchExpr noMatchLast = new AclNoMatchExpr(hostname, aclName, lastLineIndex); RuleExpr implicitDeny = new RuleExpr(noMatchLast, aclDeny); statements.add(implicitDeny); return statements; } private List<Statement> getNodeAcceptToRoleAcceptRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Connect node_accept to role_accept")); for (Entry<String, Configuration> e : _configurations.entrySet()) { String hostname = e.getKey(); Configuration c = e.getValue(); NodeAcceptExpr nodeAccept = new NodeAcceptExpr(hostname); RoleSet roles = c.getRoles(); if (roles != null) { for (String role : roles) { RoleAcceptExpr roleAccept = new RoleAcceptExpr(role); RuleExpr rule = new RuleExpr(nodeAccept, roleAccept); statements.add(rule); } } } return statements; } public NodeSet getNodeSet() { NodeSet nodes = new NodeSet(); nodes.addAll(_configurations.keySet()); return nodes; } private List<Statement> getOriginateToPostInRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Connect originate to post_in")); for (String hostname : _configurations.keySet()) { OriginateExpr originate = new OriginateExpr(hostname); PostInExpr postIn = new PostInExpr(hostname); RuleExpr rule = new RuleExpr(originate, postIn); statements.add(rule); } return statements; } private List<Statement> getOriginateVrfToPostInVrfRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Connect originate to post_in_vrf")); for (String hostname : _configurations.keySet()) { OriginateExpr originate = new OriginateExpr(hostname); for (String vrf : _configurations.get(hostname).getVrfs().keySet()) { OriginateVrfExpr originateVrf = new OriginateVrfExpr(hostname, vrf); PostInVrfExpr postInVrf = new PostInVrfExpr(hostname, vrf); RuleExpr rule = new RuleExpr(originateVrf, postInVrf); statements.add(rule); RuleExpr orule = new RuleExpr(originateVrf, originate); statements.add(orule); } } return statements; } private List<Statement> getPolicyRouteRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Policy-based routing rules")); for (Entry<String, Set<Interface>> e : _topologyInterfaces.entrySet()) { String hostname = e.getKey(); // PreOutExpr preOut = new PreOutExpr(hostname); // PolicyRouteFibIpMap ipMap = _prFibs.get(hostname); Set<Interface> interfaces = e.getValue(); for (Interface iface : interfaces) { String ifaceName = iface.getName(); // PostInInterfaceExpr postInInterface = new PostInInterfaceExpr( // hostname, ifaceName); String p = iface.getRoutingPolicyName(); if (p != null) { throw new BatfishException( "Currently do not support interface routing-policy: '" + hostname + ":" + ifaceName + ":" + p + "'"); // String policyName = p.getName(); // PolicyPermitExpr permit = new PolicyPermitExpr(hostname, // policyName); // PolicyDenyExpr deny = new PolicyDenyExpr(hostname, // policyName); // // List<PolicyMapClause> clauses = p.getClauses(); // for (int i = 0; i < clauses.size(); i++) { // PolicyMapClause clause = clauses.get(i); // PolicyMapAction action = clause.getAction(); // PolicyMatchExpr match = new PolicyMatchExpr(hostname, // policyName, i); // PolicyNoMatchExpr noMatch = new PolicyNoMatchExpr(hostname, // policyName, i); // BooleanExpr prevNoMatch = (i > 0) // ? new PolicyNoMatchExpr(hostname, policyName, i - 1) // : TrueExpr.INSTANCE; // /** // * If clause matches, and clause number (matched) is that of a // * permit clause, and out interface is among next hops, then // * policy permit on out interface // */ // switch (action) { // case PERMIT: // for (PolicyMapSetLine setLine : clause.getSetLines()) { // if (setLine.getType() == PolicyMapSetType.NEXT_HOP) { // PolicyMapSetNextHopLine setNextHopLine = // (PolicyMapSetNextHopLine) setLine; // for (Ip nextHopIp : setNextHopLine.getNextHops()) { // EdgeSet edges = ipMap.get(nextHopIp); // /** // * If packet reaches postin_interface on inInt, // * and preout, and inInt has policy, and policy // * matches on out interface, then preout_edge on // * out interface and corresponding in interface // * // */ // for (Edge edge : edges) { // String outInterface = edge.getInt1(); // String nextHop = edge.getNode2(); // String inInterface = edge.getInt2(); // if (!hostname.equals(edge.getNode1())) { // throw new BatfishException("Invalid edge"); // } // AndExpr forwardConditions = new AndExpr(); // forwardConditions.addConjunct(postInInterface); // forwardConditions.addConjunct(preOut); // forwardConditions.addConjunct(match); // if (isNullInterface(outInterface)) { // NodeDropExpr nodeDrop = new NodeDropExpr( // hostname); // RuleExpr dropRule = new RuleExpr( // forwardConditions, nodeDrop); // statements.add(dropRule); // } // else { // PreOutEdgeExpr preOutEdge = new PreOutEdgeExpr( // hostname, outInterface, nextHop, // inInterface); // RuleExpr preOutEdgeRule = new RuleExpr( // forwardConditions, preOutEdge); // statements.add(preOutEdgeRule); // } // } // } // } // } // RuleExpr permitRule = new RuleExpr(match, permit); // statements.add(permitRule); // break; // case DENY: // /** // * If clause matches and clause is deny clause, just deny // */ // RuleExpr denyRule = new RuleExpr(match, deny); // statements.add(denyRule); // break; // default: // throw new Error("bad action"); // } // // /** // * For each clause, if we reach that clause, then if any acl // * in that clause permits, or there are no acls, clause, if // * the packet then the packet is matched by that clause. // * // * If all (at least one) acls deny, then the packed is not // * matched by that clause // * // * If there are no acls to match, then the packet is matched // * by that clause. // * // */ // boolean hasMatchIp = false; // AndExpr allAclsDeny = new AndExpr(); // OrExpr someAclPermits = new OrExpr(); // for (PolicyMapMatchLine matchLine : clause.getMatchLines()) { // if (matchLine // .getType() == PolicyMapMatchType.IP_ACCESS_LIST) { // hasMatchIp = true; // PolicyMapMatchIpAccessListLine matchIpLine = // (PolicyMapMatchIpAccessListLine) matchLine; // for (IpAccessList acl : matchIpLine.getLists()) { // String aclName = acl.getName(); // AclDenyExpr currentAclDeny = new AclDenyExpr( // hostname, aclName); // allAclsDeny.addConjunct(currentAclDeny); // AclPermitExpr currentAclPermit = new AclPermitExpr( // hostname, aclName); // someAclPermits.addDisjunct(currentAclPermit); // } // } // } // AndExpr matchConditions = new AndExpr(); // matchConditions.addConjunct(prevNoMatch); // if (hasMatchIp) { // /** // * no match if all acls deny // */ // AndExpr noMatchConditions = new AndExpr(); // noMatchConditions.addConjunct(prevNoMatch); // noMatchConditions.addConjunct(allAclsDeny); // RuleExpr noMatchRule = new RuleExpr(noMatchConditions, // noMatch); // statements.add(noMatchRule); // // /** // * match if some acl permits // */ // matchConditions.addConjunct(someAclPermits); // } // RuleExpr matchRule = new RuleExpr(matchConditions, match); // statements.add(matchRule); // } // /** // * If the packet reaches the last clause, and is not matched by // * that clause, then it is denied by the policy. // */ // int lastIndex = p.getClauses().size() - 1; // PolicyNoMatchExpr noMatchLast = new // PolicyNoMatchExpr(hostname, // policyName, lastIndex); // RuleExpr noMatchDeny = new RuleExpr(noMatchLast, deny); // statements.add(noMatchDeny); } } } return statements; } private List<Statement> getPostInInterfaceToNonInboundSrcInterface() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rules for connecting postin_interface to non_inbound_src_interface")); for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); for (Interface i : c.getInterfaces().values()) { String ifaceName = i.getName(); AndExpr conditions = new AndExpr(); OrExpr dstIpMatchesInterface = new OrExpr(); Prefix prefix = i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); EqExpr dstIpMatches = new EqExpr(new VarIntExpr(DST_IP_VAR), new LitIntExpr(ip)); dstIpMatchesInterface.addDisjunct(dstIpMatches); } NotExpr dstIpNoMatchSrcInterface = new NotExpr( dstIpMatchesInterface); conditions.addConjunct(dstIpNoMatchSrcInterface); PostInInterfaceExpr postInInterface = new PostInInterfaceExpr( hostname, ifaceName); conditions.addConjunct(postInInterface); NonInboundSrcInterfaceExpr nonInboundSrcInterface = new NonInboundSrcInterfaceExpr( hostname, ifaceName); Zone srcZone = i.getZone(); if (srcZone != null) { NonInboundSrcZoneExpr nonInboundSrcZone = new NonInboundSrcZoneExpr( hostname, srcZone.getName()); RuleExpr nonInboundSrcInterfaceToNonInboundSrcZone = new RuleExpr( nonInboundSrcInterface, nonInboundSrcZone); statements.add(nonInboundSrcInterfaceToNonInboundSrcZone); } else if (c.getDefaultCrossZoneAction() == LineAction.ACCEPT) { NonInboundNullSrcZoneExpr nonInboundNullSrcZone = new NonInboundNullSrcZoneExpr( hostname); RuleExpr nonInboundSrcInterfaceToNonInboundNullSrcZone = new RuleExpr( nonInboundSrcInterface, nonInboundNullSrcZone); statements.add(nonInboundSrcInterfaceToNonInboundNullSrcZone); } RuleExpr postInInterfaceToNonInboundSrcInterface = new RuleExpr( conditions, nonInboundSrcInterface); statements.add(postInInterfaceToNonInboundSrcInterface); } } return statements; } private List<Statement> getPostInInterfaceToPostInRules() { List<Statement> statements = new ArrayList<>(); statements .add(new Comment("Rules for connecting postInInterface to postIn")); for (Entry<String, Set<Interface>> e : _topologyInterfaces.entrySet()) { String hostname = e.getKey(); Set<Interface> interfaces = e.getValue(); UnoriginalExpr unoriginal = new UnoriginalExpr(hostname); for (Interface i : interfaces) { String vrfName = i.getVrfName(); String ifaceName = i.getName(); PostInInterfaceExpr postInIface = new PostInInterfaceExpr(hostname, ifaceName); PostInExpr postIn = new PostInExpr(hostname); RuleExpr postInInterfaceToPostIn = new RuleExpr(postInIface, postIn); statements.add(postInInterfaceToPostIn); PostInVrfExpr postInVrf = new PostInVrfExpr(hostname, vrfName); RuleExpr postInInterfaceToPostInVrf = new RuleExpr(postInIface, postInVrf); statements.add(postInInterfaceToPostInVrf); RuleExpr postInInterfaceToUnoriginal = new RuleExpr(postInIface, unoriginal); statements.add(postInInterfaceToUnoriginal); } } return statements; } private List<Statement> getPostInToInboundInterface() { List<Statement> statements = new ArrayList<>(); statements.add( new Comment("Rules for connecting post_in to inbound_interface")); for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); PostInExpr postIn = new PostInExpr(hostname); for (Interface i : c.getInterfaces().values()) { String ifaceName = i.getName(); OrExpr dstIpMatchesInterface = new OrExpr(); Prefix prefix = i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); EqExpr dstIpMatches = new EqExpr(new VarIntExpr(DST_IP_VAR), new LitIntExpr(ip)); dstIpMatchesInterface.addDisjunct(dstIpMatches); } AndExpr inboundInterfaceConditions = new AndExpr(); inboundInterfaceConditions.addConjunct(dstIpMatchesInterface); inboundInterfaceConditions.addConjunct(postIn); InboundInterfaceExpr inboundInterface = new InboundInterfaceExpr( hostname, ifaceName); RuleExpr postInToInboundInterface = new RuleExpr( inboundInterfaceConditions, inboundInterface); statements.add(postInToInboundInterface); } } return statements; } /* * private List<Statement> getPostInToNodeAcceptRules() { List<Statement> * statements = new ArrayList<Statement>(); statements .add(new * Comment("Rules for connecting post_in to node_accept")); for * (Configuration c : _configurations.values()) { String hostname = * c.getHostname(); PostInExpr postIn = new PostInExpr(hostname); for * (Interface i : c.getInterfaces().values()) { String ifaceName = * i.getName(); OrExpr someDstIpMatches = new OrExpr(); Prefix prefix = * i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); EqExpr * dstIpMatches = new EqExpr(new VarIntExpr(DST_IP_VAR), new LitIntExpr(ip)); * someDstIpMatches.addDisjunct(dstIpMatches); } AndExpr * inboundInterfaceConditions = new AndExpr(); * inboundInterfaceConditions.addConjunct(someDstIpMatches); * inboundInterfaceConditions.addConjunct(postIn); InboundInterfaceExpr * inboundInterface = new InboundInterfaceExpr( hostname, ifaceName); * RuleExpr postInToInboundInterface = new RuleExpr( * inboundInterfaceConditions, inboundInterface); AndExpr acceptConditions = * new AndExpr(); PassHostFilterExpr passHostFilter = new * PassHostFilterExpr(hostname); PassInboundFilterExpr passInboundFilter = * new PassInboundFilterExpr( hostname, ifaceName); PostInInterfaceExpr * postInInterface = new PostInInterfaceExpr( hostname, ifaceName); * acceptConditions.addConjunct(postInInterface); * acceptConditions.addConjunct(passHostFilter); * acceptConditions.addConjunct(passInboundFilter); * statements.add(postInToInboundInterface); } NodeAcceptExpr nodeAccept = * new NodeAcceptExpr(hostname); AndExpr conditions = new AndExpr(); * conditions.addConjunct(postIn); conditions.addConjunct(someDstIpMatches); * RuleExpr rule = new RuleExpr(conditions, nodeAccept); * statements.add(rule); } return statements; } */ private List<Statement> getPostInToPreOutRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("postin ==> preout:", "forward to preout if for each ip address on an interface, destination ip does not match")); for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); OrExpr someDstIpMatch = new OrExpr(); for (Interface i : c.getInterfaces().values()) { Prefix prefix = i.getPrefix(); if (prefix != null) { Ip ip = prefix.getAddress(); EqExpr dstIpMatches = new EqExpr(new VarIntExpr(DST_IP_VAR), new LitIntExpr(ip)); someDstIpMatch.addDisjunct(dstIpMatches); } } NotExpr noDstIpMatch = new NotExpr(someDstIpMatch); PostInExpr postIn = new PostInExpr(hostname); PreOutExpr preOut = new PreOutExpr(hostname); AndExpr conditions = new AndExpr(); conditions.addConjunct(postIn); conditions.addConjunct(noDstIpMatch); RuleExpr rule = new RuleExpr(conditions, preOut); statements.add(rule); } return statements; } private List<Statement> getPostOutIfaceToNodeTransitRules() { List<Statement> statements = new ArrayList<>(); statements .add(new Comment("Rules connecting postout_iface to node_transit")); for (Entry<String, Set<Interface>> e : _topologyInterfaces.entrySet()) { String hostname = e.getKey(); Set<Interface> interfaces = e.getValue(); NodeTransitExpr nodeTransit = new NodeTransitExpr(hostname); for (Interface iface : interfaces) { String ifaceName = iface.getName(); PostOutInterfaceExpr postOutIface = new PostOutInterfaceExpr( hostname, ifaceName); RuleExpr rule = new RuleExpr(postOutIface, nodeTransit); statements.add(rule); } } return statements; } private List<Statement> getPreInInterfaceToPostInInterfaceRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Connect prein_interface to postin_interface, possibly through acl")); for (String hostname : _topologyInterfaces.keySet()) { Set<Interface> interfaces = _topologyInterfaces.get(hostname); for (Interface iface : interfaces) { String ifaceName = iface.getName(); if (isFlowSink(hostname, ifaceName)) { continue; } NodeDropAclInExpr nodeDrop = new NodeDropAclInExpr(hostname); PreInInterfaceExpr preInIface = new PreInInterfaceExpr(hostname, ifaceName); PostInInterfaceExpr postInIface = new PostInInterfaceExpr(hostname, ifaceName); AndExpr conditions = new AndExpr(); conditions.addConjunct(preInIface); IpAccessList inAcl = iface.getIncomingFilter(); if (inAcl != null) { String aclName = inAcl.getName(); AclPermitExpr aclPermit = new AclPermitExpr(hostname, aclName); conditions.addConjunct(aclPermit); AndExpr dropConditions = new AndExpr(); AclDenyExpr aclDeny = new AclDenyExpr(hostname, aclName); dropConditions.addConjunct(preInIface); dropConditions.addConjunct(aclDeny); RuleExpr drop = new RuleExpr(dropConditions, nodeDrop); statements.add(drop); } RuleExpr preInToPostIn = new RuleExpr(conditions, postInIface); statements.add(preInToPostIn); } } return statements; } private List<Statement> getPreOutEdgeToPreOutInterfaceRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("PreOutEdge => PreOutInterface")); for (NodeInterfacePair f : _flowSinks) { String hostnameOut = f.getHostname(); String hostnameIn = Configuration.NODE_NONE_NAME; String intOut = f.getInterface(); String intIn = Interface.FLOW_SINK_TERMINATION_NAME; PreOutEdgeExpr preOutEdge = new PreOutEdgeExpr(hostnameOut, intOut, hostnameIn, intIn); PreOutInterfaceExpr preOutInt = new PreOutInterfaceExpr(hostnameOut, intOut); RuleExpr rule = new RuleExpr(preOutEdge, preOutInt); statements.add(rule); } for (Edge edge : _topologyEdges) { String hostnameOut = edge.getNode1(); String hostnameIn = edge.getNode2(); String intOut = edge.getInt1(); String intIn = edge.getInt2(); PreOutEdgeExpr preOutEdge = new PreOutEdgeExpr(hostnameOut, intOut, hostnameIn, intIn); PreOutInterfaceExpr preOutInt = new PreOutInterfaceExpr(hostnameOut, intOut); RuleExpr rule = new RuleExpr(preOutEdge, preOutInt); statements.add(rule); } return statements; } private List<Statement> getPreOutInterfaceToPostOutInterfaceRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Connect preout_interface to postout_interface, possibly through acl")); for (String hostname : _topologyInterfaces.keySet()) { Configuration c = _configurations.get(hostname); Set<Interface> interfaces = _topologyInterfaces.get(hostname); OriginateExpr originate = new OriginateExpr(hostname); UnoriginalExpr unoriginal = new UnoriginalExpr(hostname); for (Interface iface : interfaces) { String ifaceName = iface.getName(); NodeDropAclOutExpr nodeDrop = new NodeDropAclOutExpr(hostname); PreOutInterfaceExpr preOutIface = new PreOutInterfaceExpr(hostname, ifaceName); PostOutInterfaceExpr postOutIface = new PostOutInterfaceExpr( hostname, ifaceName); AndExpr outConditions = new AndExpr(); AndExpr dropConditions = new AndExpr(); outConditions.addConjunct(preOutIface); dropConditions.addConjunct(preOutIface); OrExpr filterDeny = new OrExpr(); OrExpr crossZonePermit = new OrExpr(); IpAccessList outAcl = iface.getOutgoingFilter(); if (outAcl != null) { String aclName = outAcl.getName(); AclPermitExpr aclPermit = new AclPermitExpr(hostname, aclName); outConditions.addConjunct(aclPermit); AclDenyExpr aclDeny = new AclDenyExpr(hostname, aclName); filterDeny.addDisjunct(aclDeny); } dropConditions.addConjunct(filterDeny); // handle cross-zone filter // first handle case where outgoing interface has no zone Zone outZone = iface.getZone(); if (outZone == null) { if (c.getDefaultCrossZoneAction() == LineAction.REJECT) { filterDeny.addDisjunct(unoriginal); } else { crossZonePermit.addDisjunct(TrueExpr.INSTANCE); } } else { // outgoing interface has zone // now handle case of original packet IpAccessList fromHostFilter = outZone.getFromHostFilter(); if (fromHostFilter != null) { String fromHostFilterName = fromHostFilter.getName(); AclPermitExpr hostFilterPermit = new AclPermitExpr(hostname, fromHostFilterName); AndExpr originateCrossZonePermit = new AndExpr(); originateCrossZonePermit.addConjunct(hostFilterPermit); originateCrossZonePermit.addConjunct(originate); crossZonePermit.addDisjunct(originateCrossZonePermit); AclDenyExpr hostFilterDeny = new AclDenyExpr(hostname, fromHostFilterName); AndExpr originateCrossZoneDeny = new AndExpr(); originateCrossZoneDeny.addConjunct(hostFilterDeny); originateCrossZoneDeny.addConjunct(originate); filterDeny.addDisjunct(originateCrossZoneDeny); } else { crossZonePermit.addDisjunct(originate); } // now handle unoriginal packets // null src zone: NonInboundNullSrcZoneExpr nonInboundNullSrcZone = new NonInboundNullSrcZoneExpr( hostname); if (c.getDefaultCrossZoneAction() == LineAction.REJECT) { filterDeny.addDisjunct(nonInboundNullSrcZone); } else { // default for null src zone is to accept crossZonePermit.addDisjunct(nonInboundNullSrcZone); } // now handle cases of each possible src zone (still unoriginal) for (Zone srcZone : c.getZones().values()) { String srcZoneName = srcZone.getName(); NonInboundSrcZoneExpr nonInboundSrcZone = new NonInboundSrcZoneExpr( hostname, srcZoneName); IpAccessList crossZoneFilter = srcZone.getToZonePolicies() .get(outZone.getName()); // no policy for this pair of zones - use default cross-zone // action if (crossZoneFilter == null) { if (c.getDefaultCrossZoneAction() == LineAction.REJECT) { filterDeny.addDisjunct(nonInboundSrcZone); } else { crossZonePermit.addDisjunct(nonInboundSrcZone); } } else { // there is a cross-zone filter String crossZoneFilterName = crossZoneFilter.getName(); AclPermitExpr crossZoneFilterPermit = new AclPermitExpr( hostname, crossZoneFilterName); AclDenyExpr crossZoneFilterDeny = new AclDenyExpr(hostname, crossZoneFilterName); AndExpr deniedByCrossZoneFilter = new AndExpr(); deniedByCrossZoneFilter.addConjunct(nonInboundSrcZone); deniedByCrossZoneFilter.addConjunct(crossZoneFilterDeny); filterDeny.addDisjunct(deniedByCrossZoneFilter); AndExpr allowedByCrossZoneFilter = new AndExpr(); allowedByCrossZoneFilter.addConjunct(nonInboundSrcZone); allowedByCrossZoneFilter .addConjunct(crossZoneFilterPermit); crossZonePermit.addDisjunct(allowedByCrossZoneFilter); } } } outConditions.addConjunct(crossZonePermit); RuleExpr drop = new RuleExpr(dropConditions, nodeDrop); statements.add(drop); RuleExpr preOutToPostOut = new RuleExpr(outConditions, postOutIface); statements.add(preOutToPostOut); } } return statements; } private List<Statement> getPreOutToDestRouteRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment( "Rules for sending packets from preout to destroute stage")); for (String hostname : _configurations.keySet()) { /** * if a packet whose source node is a given node reaches preout on that * node, then it reaches destroute */ PreOutExpr preOut = new PreOutExpr(hostname); OriginateExpr originate = new OriginateExpr(hostname); DestinationRouteExpr destRoute = new DestinationRouteExpr(hostname); AndExpr originConditions = new AndExpr(); originConditions.addConjunct(preOut); originConditions.addConjunct(originate); RuleExpr originDestRoute = new RuleExpr(originConditions, destRoute); statements.add(originDestRoute); } for (Entry<String, Set<Interface>> e : _topologyInterfaces.entrySet()) { String hostname = e.getKey(); PreOutExpr preOut = new PreOutExpr(hostname); DestinationRouteExpr destRoute = new DestinationRouteExpr(hostname); Set<Interface> interfaces = e.getValue(); for (Interface i : interfaces) { String ifaceName = i.getName(); /** * if a packet reaches postin_interface on interface, and interface * is not policy-routed, and it reaches preout, then it reaches * destroute */ /** * if a packet reaches postin_interface on intefrace, and interface * is policy-routed by policy, and policy denies, and it reaches * preout, then it reaches destroute * */ PostInInterfaceExpr postInInterface = new PostInInterfaceExpr( hostname, ifaceName); AndExpr receivedDestRouteConditions = new AndExpr(); receivedDestRouteConditions.addConjunct(postInInterface); receivedDestRouteConditions.addConjunct(preOut); String policyName = i.getRoutingPolicyName(); if (policyName != null) { PolicyDenyExpr policyDeny = new PolicyDenyExpr(hostname, policyName); receivedDestRouteConditions.addConjunct(policyDeny); } RuleExpr receivedDestRoute = new RuleExpr( receivedDestRouteConditions, destRoute); statements.add(receivedDestRoute); } } return statements; } private List<Statement> getRoleOriginateToNodeOriginateRules() { List<Statement> statements = new ArrayList<>(); statements .add(new Comment("Rules connecting role_originate to R_originate")); for (Entry<String, Configuration> e : _configurations.entrySet()) { String hostname = e.getKey(); Configuration c = e.getValue(); OriginateExpr nodeOriginate = new OriginateExpr(hostname); RoleSet roles = c.getRoles(); if (roles != null) { for (String role : roles) { RoleOriginateExpr roleOriginate = new RoleOriginateExpr(role); RuleExpr rule = new RuleExpr(roleOriginate, nodeOriginate); statements.add(rule); } } } return statements; } private List<Statement> getSane() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Make sure packet fields make sense")); AndExpr noPortNumbers = new AndExpr(); EqExpr noDstPort = new EqExpr(new VarIntExpr(DST_PORT_VAR), new LitIntExpr(0, PORT_BITS)); EqExpr noSrcPort = new EqExpr(new VarIntExpr(SRC_PORT_VAR), new LitIntExpr(0, PORT_BITS)); noPortNumbers.addConjunct(noDstPort); noPortNumbers.addConjunct(noSrcPort); AndExpr noTcpFlags = new AndExpr(); LitIntExpr zero = new LitIntExpr(0, 1); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_CWR_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_ECE_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_URG_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_ACK_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_PSH_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_RST_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_SYN_VAR), zero)); noTcpFlags .addConjunct(new EqExpr(new VarIntExpr(TCP_FLAGS_FIN_VAR), zero)); EqExpr noIcmpCode = new EqExpr(new VarIntExpr(ICMP_CODE_VAR), new LitIntExpr(IcmpCode.UNSET, ICMP_CODE_BITS)); EqExpr noIcmpType = new EqExpr(new VarIntExpr(ICMP_TYPE_VAR), new LitIntExpr(IcmpType.UNSET, ICMP_TYPE_BITS)); AndExpr noIcmp = new AndExpr(); noIcmp.addConjunct(noIcmpType); noIcmp.addConjunct(noIcmpCode); EqExpr icmpProtocol = new EqExpr(new VarIntExpr(IP_PROTOCOL_VAR), new LitIntExpr(IpProtocol.ICMP.number(), PROTOCOL_BITS)); EqExpr tcpProtocol = new EqExpr(new VarIntExpr(IP_PROTOCOL_VAR), new LitIntExpr(IpProtocol.TCP.number(), PROTOCOL_BITS)); EqExpr udpProtocol = new EqExpr(new VarIntExpr(IP_PROTOCOL_VAR), new LitIntExpr(IpProtocol.UDP.number(), PROTOCOL_BITS)); AndExpr tcp = new AndExpr(); tcp.addConjunct(tcpProtocol); tcp.addConjunct(noIcmp); AndExpr udp = new AndExpr(); udp.addConjunct(udpProtocol); udp.addConjunct(noIcmp); udp.addConjunct(noTcpFlags); AndExpr icmp = new AndExpr(); icmp.addConjunct(icmpProtocol); icmp.addConjunct(noTcpFlags); icmp.addConjunct(noPortNumbers); AndExpr otherIp = new AndExpr(); otherIp.addConjunct(noIcmp); otherIp.addConjunct(noTcpFlags); otherIp.addConjunct(noPortNumbers); OrExpr isSane = new OrExpr(); isSane.addDisjunct(icmp); isSane.addDisjunct(tcp); isSane.addDisjunct(udp); isSane.addDisjunct(otherIp); RuleExpr rule = new RuleExpr(isSane, SaneExpr.INSTANCE); statements.add(rule); return statements; } private List<Statement> getToNeighborsRules() { List<Statement> statements = new ArrayList<>(); statements.add(new Comment("Topology edge rules")); for (Edge edge : _topologyEdges) { String hostnameOut = edge.getNode1(); String hostnameIn = edge.getNode2(); String intOut = edge.getInt1(); String intIn = edge.getInt2(); if (isFlowSink(hostnameIn, intIn) || isFlowSink(hostnameOut, intOut)) { continue; } PostOutInterfaceExpr postOutIface = new PostOutInterfaceExpr( hostnameOut, intOut); PreOutEdgeExpr preOutEdge = new PreOutEdgeExpr(hostnameOut, intOut, hostnameIn, intIn); PreInInterfaceExpr preInIface = new PreInInterfaceExpr(hostnameIn, intIn); AndExpr conditions = new AndExpr(); conditions.addConjunct(postOutIface); conditions.addConjunct(preOutEdge); RuleExpr propagateToAdjacent = new RuleExpr(conditions, preInIface); statements.add(propagateToAdjacent); } return statements; } public List<String> getWarnings() { return _warnings; } private boolean isFlowSink(String hostname, String ifaceName) { NodeInterfacePair f = new NodeInterfacePair(hostname, ifaceName); return _flowSinks.contains(f); } private void pruneInterfaces() { for (Configuration c : _configurations.values()) { String hostname = c.getHostname(); Set<String> prunedInterfaces = new HashSet<>(); Map<String, Interface> interfaces = c.getInterfaces(); Set<Interface> topologyInterfaces = _topologyInterfaces.get(hostname); for (Interface i : interfaces.values()) { String ifaceName = i.getName(); if ((!i.getActive() && !topologyInterfaces.contains(i))) { prunedInterfaces.add(ifaceName); } if (!i.getActive() && topologyInterfaces.contains(i)) { Interface blankInterface = new Interface(ifaceName, c); blankInterface.setActive(false); interfaces.put(ifaceName, blankInterface); } } for (String i : prunedInterfaces) { interfaces.remove(i); } } } public NodProgram synthesizeNodAclProgram(String hostname, String aclName, Context ctx) throws Z3Exception { List<Statement> ruleStatements = new ArrayList<>(); List<Statement> sane = getSane(); List<Statement> matchAclRules = getMatchAclRules(hostname, aclName); ruleStatements.addAll(sane); ruleStatements.addAll(matchAclRules); return synthesizeNodProgram(ctx, ruleStatements); } public NodProgram synthesizeNodDataPlaneProgram(Context ctx) throws Z3Exception { List<Statement> ruleStatements = new ArrayList<>(); List<Statement> dropRules = getDropRules(); List<Statement> acceptRules = getAcceptRules(); List<Statement> sane = getSane(); List<Statement> flowSinkAcceptRules = getFlowSinkAcceptRules(); List<Statement> originateToPostInRules = getOriginateToPostInRules(); List<Statement> originateVrfToPostInVrfRules = getOriginateVrfToPostInVrfRules(); List<Statement> postInInterfaceToPostInRules = getPostInInterfaceToPostInRules(); List<Statement> postInInterfaceToNonInboundSrcInterface = getPostInInterfaceToNonInboundSrcInterface(); List<Statement> postInToInboundInterface = getPostInToInboundInterface(); List<Statement> inboundInterfaceToNodeAccept = getInboundInterfaceToNodeAccept(); List<Statement> inboundInterfaceToNodeDrop = getInboundInterfaceToNodeDrop(); List<Statement> postInToPreOutRules = getPostInToPreOutRules(); List<Statement> preOutToDestRouteRules = getPreOutToDestRouteRules(); List<Statement> destRouteToPreOutEdgeRules = getDestRouteToPreOutEdgeRules(); List<Statement> preOutEdgeToPreOutInterfaceRules = getPreOutEdgeToPreOutInterfaceRules(); List<Statement> policyRouteRules = getPolicyRouteRules(); List<Statement> matchAclRules = getMatchAclRules(); List<Statement> toNeighborsRules = getToNeighborsRules(); List<Statement> preInInterfaceToPostInInterfaceRules = getPreInInterfaceToPostInInterfaceRules(); List<Statement> preOutInterfaceToPostOutInterfaceRules = getPreOutInterfaceToPostOutInterfaceRules(); List<Statement> nodeAcceptToRoleAcceptRules = getNodeAcceptToRoleAcceptRules(); List<Statement> externalSrcIpRules = getExternalSrcIpRules(); List<Statement> externalDstIpRules = getExternalDstIpRules(); List<Statement> postOutIfaceToNodeTransitRules = getPostOutIfaceToNodeTransitRules(); List<Statement> roleOriginateToNodeOriginateRules = getRoleOriginateToNodeOriginateRules(); ruleStatements.addAll(dropRules); ruleStatements.addAll(acceptRules); ruleStatements.addAll(sane); ruleStatements.addAll(flowSinkAcceptRules); ruleStatements.addAll(originateToPostInRules); ruleStatements.addAll(originateVrfToPostInVrfRules); ruleStatements.addAll(postInInterfaceToPostInRules); ruleStatements.addAll(postInInterfaceToNonInboundSrcInterface); ruleStatements.addAll(postInToInboundInterface); ruleStatements.addAll(inboundInterfaceToNodeAccept); ruleStatements.addAll(inboundInterfaceToNodeDrop); ruleStatements.addAll(postInToPreOutRules); ruleStatements.addAll(preOutToDestRouteRules); ruleStatements.addAll(destRouteToPreOutEdgeRules); ruleStatements.addAll(preOutEdgeToPreOutInterfaceRules); ruleStatements.addAll(policyRouteRules); ruleStatements.addAll(matchAclRules); ruleStatements.addAll(toNeighborsRules); ruleStatements.addAll(preInInterfaceToPostInInterfaceRules); ruleStatements.addAll(preOutInterfaceToPostOutInterfaceRules); ruleStatements.addAll(nodeAcceptToRoleAcceptRules); ruleStatements.addAll(externalSrcIpRules); ruleStatements.addAll(externalDstIpRules); ruleStatements.addAll(postOutIfaceToNodeTransitRules); ruleStatements.addAll(roleOriginateToNodeOriginateRules); return synthesizeNodProgram(ctx, ruleStatements); } private NodProgram synthesizeNodProgram(Context ctx, List<Statement> ruleStatements) { NodProgram nodProgram = new NodProgram(ctx); Map<String, FuncDecl> relDeclFuncDecls = getRelDeclFuncDecls( ruleStatements, ctx); nodProgram.getRelationDeclarations().putAll(relDeclFuncDecls); Map<String, BitVecExpr> variables = nodProgram.getVariables(); Map<String, BitVecExpr> variablesAsConsts = nodProgram .getVariablesAsConsts(); int deBruinIndex = 0; for (Entry<String, Integer> e : PACKET_VAR_SIZES.entrySet()) { String var = e.getKey(); int size = e.getValue(); BitVecExpr varExpr = (BitVecExpr) ctx.mkBound(deBruinIndex, ctx.mkBitVecSort(size)); BitVecExpr varAsConstExpr = (BitVecExpr) ctx.mkConst(var, ctx.mkBitVecSort(size)); variables.put(var, varExpr); variablesAsConsts.put(var, varAsConstExpr); deBruinIndex++; } List<BoolExpr> rules = nodProgram.getRules(); for (Statement rawStatement : ruleStatements) { Statement statement; if (_simplify) { statement = rawStatement.simplify(); } else { statement = rawStatement; } if (statement instanceof RuleExpr) { RuleExpr ruleExpr = (RuleExpr) statement; BoolExpr rule = ruleExpr.toBoolExpr(nodProgram); rules.add(rule); } } return nodProgram; } }