use of org.batfish.datamodel.StaticRoute in project batfish by batfish.
the class Graph method getOriginatedNetworks.
/*
* Collects and returns all originated prefixes for the given
* router as well as the protocol. Static routes and connected
* routes are treated as originating the prefix.
*/
public static Set<Prefix> getOriginatedNetworks(Configuration conf, Protocol proto) {
Set<Prefix> acc = new HashSet<>();
if (proto.isOspf()) {
OspfProcess ospf = conf.getDefaultVrf().getOspfProcess();
for (OspfArea area : ospf.getAreas().values()) {
for (String ifaceName : area.getInterfaces()) {
Interface iface = conf.getInterfaces().get(ifaceName);
if (iface.getActive() && iface.getOspfEnabled()) {
acc.add(iface.getAddress().getPrefix());
}
}
}
return acc;
}
if (proto.isBgp()) {
RoutingPolicy defaultPol = findCommonRoutingPolicy(conf, Protocol.BGP);
if (defaultPol != null) {
AstVisitor v = new AstVisitor();
v.visit(conf, defaultPol.getStatements(), stmt -> {
}, expr -> {
if (expr instanceof Conjunction) {
Conjunction c = (Conjunction) expr;
if (c.getConjuncts().size() >= 2) {
BooleanExpr be1 = c.getConjuncts().get(0);
BooleanExpr be2 = c.getConjuncts().get(1);
if (be1 instanceof MatchPrefixSet && be2 instanceof Not) {
MatchPrefixSet mps = (MatchPrefixSet) be1;
Not n = (Not) be2;
if (n.getExpr() instanceof MatchProtocol) {
MatchProtocol mp = (MatchProtocol) n.getExpr();
if (mp.getProtocol() == RoutingProtocol.BGP) {
PrefixSetExpr e = mps.getPrefixSet();
if (e instanceof ExplicitPrefixSet) {
ExplicitPrefixSet eps = (ExplicitPrefixSet) e;
Set<PrefixRange> ranges = eps.getPrefixSpace().getPrefixRanges();
for (PrefixRange r : ranges) {
acc.add(r.getPrefix());
}
}
}
}
}
}
}
});
}
return acc;
}
if (proto.isConnected()) {
for (Interface iface : conf.getInterfaces().values()) {
InterfaceAddress address = iface.getAddress();
if (address != null) {
acc.add(address.getPrefix());
}
}
return acc;
}
if (proto.isStatic()) {
for (StaticRoute sr : conf.getDefaultVrf().getStaticRoutes()) {
if (sr.getNetwork() != null) {
acc.add(sr.getNetwork());
}
}
return acc;
}
throw new BatfishException("ERROR: getOriginatedNetworks: " + proto.name());
}
use of org.batfish.datamodel.StaticRoute in project batfish by batfish.
the class Graph method isEdgeUsed.
/*
* Check if a topology edge is used in a particular protocol.
*/
public boolean isEdgeUsed(Configuration conf, Protocol proto, GraphEdge ge) {
Interface iface = ge.getStart();
// Use a null routed edge, but only for the static protocol
if (ge.isNullEdge()) {
return proto.isStatic();
}
// Don't use if interface is not active
if (!isInterfaceActive(proto, iface)) {
return false;
}
// Exclude abstract iBGP edges from all protocols except BGP
if (iface.getName().startsWith("iBGP-")) {
return proto.isBgp();
}
// Never use Loopbacks for any protocol except connected
if (ge.getStart().isLoopback(conf.getConfigurationFormat())) {
return proto.isConnected();
}
// Don't use ospf over edges to hosts / external
if ((ge.getPeer() == null || isHost(ge.getPeer())) && proto.isOspf()) {
return false;
}
// Only use specified edges from static routes
if (proto.isStatic()) {
List<StaticRoute> srs = getStaticRoutes().get(conf.getName(), iface.getName());
return iface.getActive() && srs != null && srs.size() > 0;
}
// Only use an edge in BGP if there is an explicit peering
if (proto.isBgp()) {
BgpNeighbor n1 = _ebgpNeighbors.get(ge);
BgpNeighbor n2 = _ibgpNeighbors.get(ge);
return n1 != null || n2 != null;
}
return true;
}
use of org.batfish.datamodel.StaticRoute in project batfish by batfish.
the class Graph method addNullRouteEdges.
/*
* Add graph edges to represent the null interface when used by a static route
*/
private void addNullRouteEdges() {
for (Entry<String, List<StaticRoute>> entry : _nullStaticRoutes.entrySet()) {
String router = entry.getKey();
List<StaticRoute> srs = entry.getValue();
for (StaticRoute sr : srs) {
String name = sr.getNextHopInterface();
// Create null route interface
Interface iface = new Interface(name);
iface.setActive(true);
iface.setAddress(new InterfaceAddress(sr.getNetwork().getStartIp(), sr.getNextHopIp().numSubnetBits()));
iface.setBandwidth(0.);
// Add static route to all static routes list
Map<String, List<StaticRoute>> map = _staticRoutes.get(router);
List<StaticRoute> routes = map.computeIfAbsent(name, k -> new ArrayList<>());
routes.add(sr);
// Create and add graph edge for null route
GraphEdge ge = new GraphEdge(iface, null, router, null, false, true);
_allRealEdges.add(ge);
_allEdges.add(ge);
List<GraphEdge> edges = _edgeMap.computeIfAbsent(router, k -> new ArrayList<>());
edges.add(ge);
}
}
}
use of org.batfish.datamodel.StaticRoute in project batfish by batfish.
the class Graph method initStaticRoutes.
/*
* Collect all static routes after inferring which interface they indicate
* should be used for the next-hop.
*/
private void initStaticRoutes() {
for (Entry<String, Configuration> entry : _configurations.entrySet()) {
String router = entry.getKey();
Configuration conf = entry.getValue();
Map<String, List<StaticRoute>> map = new HashMap<>();
_staticRoutes.put(router, map);
for (StaticRoute sr : conf.getDefaultVrf().getStaticRoutes()) {
boolean someIface = false;
for (GraphEdge ge : _edgeMap.get(router)) {
Interface here = ge.getStart();
Interface there = ge.getEnd();
// Check if next-hop interface is specified
String hereName = here.getName();
someIface = true;
if (hereName.equals(sr.getNextHopInterface())) {
List<StaticRoute> srs = map.computeIfAbsent(hereName, k -> new ArrayList<>());
srs.add(sr);
map.put(hereName, srs);
}
// Check if next-hop ip corresponds to direct interface
Ip nhIp = sr.getNextHopIp();
boolean isNextHop = there != null && there.getAddress() != null && there.getAddress().getIp().equals(nhIp);
if (isNextHop) {
someIface = true;
List<StaticRoute> srs = map.computeIfAbsent(hereName, k -> new ArrayList<>());
srs.add(sr);
map.put(here.getName(), srs);
}
}
if (Graph.isNullRouted(sr)) {
List<StaticRoute> nulls = _nullStaticRoutes.computeIfAbsent(router, k -> new ArrayList<>());
nulls.add(sr);
}
if (!someIface && !Graph.isNullRouted(sr)) {
_hasStaticRouteWithDynamicNextHop = true;
}
}
}
}
use of org.batfish.datamodel.StaticRoute 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);
}
}
}
}
Aggregations