use of org.batfish.datamodel.routing_policy.statement.If in project batfish by batfish.
the class JuniperConfiguration method createBgpProcess.
private BgpProcess createBgpProcess(RoutingInstance routingInstance) {
initDefaultBgpExportPolicy();
initDefaultBgpImportPolicy();
String vrfName = routingInstance.getName();
Vrf vrf = _c.getVrfs().get(vrfName);
BgpProcess proc = new BgpProcess();
Ip routerId = routingInstance.getRouterId();
if (routerId == null) {
routerId = _defaultRoutingInstance.getRouterId();
if (routerId == null) {
routerId = Ip.ZERO;
}
}
proc.setRouterId(routerId);
BgpGroup mg = routingInstance.getMasterBgpGroup();
boolean multipathEbgp = false;
boolean multipathIbgp = false;
boolean multipathMultipleAs = false;
boolean multipathEbgpSet = false;
boolean multipathIbgpSet = false;
boolean multipathMultipleAsSet = false;
if (mg.getLocalAs() == null) {
Integer routingInstanceAs = routingInstance.getAs();
if (routingInstanceAs == null) {
routingInstanceAs = _defaultRoutingInstance.getAs();
}
if (routingInstanceAs == null) {
_w.redFlag("BGP BROKEN FOR THIS ROUTER: Cannot determine local autonomous system");
} else {
mg.setLocalAs(routingInstanceAs);
}
}
// Set default authentication algorithm if missing
if (mg.getAuthenticationAlgorithm() == null) {
mg.setAuthenticationAlgorithm(DEFAULT_BGP_AUTHENTICATION_ALGORITHM);
}
for (IpBgpGroup ig : routingInstance.getIpBgpGroups().values()) {
ig.cascadeInheritance();
}
_unreferencedBgpGroups = new TreeMap<>();
int fakeIpCounter = 0;
for (Entry<String, NamedBgpGroup> e : routingInstance.getNamedBgpGroups().entrySet()) {
fakeIpCounter++;
String name = e.getKey();
NamedBgpGroup group = e.getValue();
if (!group.getIpv6() && !group.getInherited()) {
_unreferencedBgpGroups.put(name, group.getDefinitionLine());
Ip fakeIp = new Ip(-1 * fakeIpCounter);
IpBgpGroup dummy = new IpBgpGroup(fakeIp);
dummy.setParent(group);
dummy.cascadeInheritance();
routingInstance.getIpBgpGroups().put(fakeIp, dummy);
}
}
for (Entry<Ip, IpBgpGroup> e : routingInstance.getIpBgpGroups().entrySet()) {
Ip ip = e.getKey();
IpBgpGroup ig = e.getValue();
BgpNeighbor neighbor = new BgpNeighbor(ip, _c);
neighbor.setVrf(vrfName);
// route reflection
Ip declaredClusterId = ig.getClusterId();
if (declaredClusterId != null) {
neighbor.setRouteReflectorClient(true);
neighbor.setClusterId(declaredClusterId.asLong());
} else {
neighbor.setClusterId(routerId.asLong());
}
// multipath multiple-as
boolean currentGroupMultipathMultipleAs = ig.getMultipathMultipleAs();
if (multipathMultipleAsSet && currentGroupMultipathMultipleAs != multipathMultipleAs) {
_w.redFlag("Currently do not support mixed multipath-multiple-as/non-multipath-multiple-as bgp" + "groups on Juniper - FORCING NON-MULTIPATH-MULTIPLE-AS");
multipathMultipleAs = false;
} else {
multipathMultipleAs = currentGroupMultipathMultipleAs;
multipathMultipleAsSet = true;
}
String authenticationKeyChainName = ig.getAuthenticationKeyChainName();
if (ig.getAuthenticationKeyChainName() != null) {
if (!_c.getAuthenticationKeyChains().containsKey(authenticationKeyChainName)) {
authenticationKeyChainName = null;
} else if (ig.getAuthenticationKey() != null) {
_w.redFlag("Both authentication-key and authentication-key-chain specified for neighbor " + ig.getRemoteAddress());
}
}
BgpAuthenticationSettings bgpAuthenticationSettings = new BgpAuthenticationSettings();
bgpAuthenticationSettings.setAuthenticationAlgorithm(ig.getAuthenticationAlgorithm());
bgpAuthenticationSettings.setAuthenticationKey(ig.getAuthenticationKey());
bgpAuthenticationSettings.setAuthenticationKeyChainName(authenticationKeyChainName);
neighbor.setAuthenticationSettings(bgpAuthenticationSettings);
Boolean ebgpMultihop = ig.getEbgpMultihop();
if (ebgpMultihop == null) {
ebgpMultihop = false;
}
neighbor.setEbgpMultihop(ebgpMultihop);
Integer loops = ig.getLoops();
boolean allowLocalAsIn = loops != null && loops > 0;
neighbor.setAllowLocalAsIn(allowLocalAsIn);
Boolean advertisePeerAs = ig.getAdvertisePeerAs();
if (advertisePeerAs == null) {
advertisePeerAs = false;
}
neighbor.setAllowRemoteAsOut(advertisePeerAs);
Boolean advertiseExternal = ig.getAdvertiseExternal();
if (advertiseExternal == null) {
advertiseExternal = false;
}
neighbor.setAdvertiseExternal(advertiseExternal);
Boolean advertiseInactive = ig.getAdvertiseInactive();
if (advertiseInactive == null) {
advertiseInactive = false;
}
neighbor.setAdvertiseInactive(advertiseInactive);
neighbor.setGroup(ig.getGroupName());
// import policies
String peerImportPolicyName = "~PEER_IMPORT_POLICY:" + ig.getRemoteAddress() + "~";
neighbor.setImportPolicy(peerImportPolicyName);
RoutingPolicy peerImportPolicy = new RoutingPolicy(peerImportPolicyName, _c);
_c.getRoutingPolicies().put(peerImportPolicyName, peerImportPolicy);
// default import policy is to accept
peerImportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_IMPORT_POLICY_NAME));
peerImportPolicy.getStatements().add(Statements.SetDefaultActionAccept.toStaticStatement());
List<BooleanExpr> importPolicyCalls = new ArrayList<>();
ig.getImportPolicies().forEach((importPolicyName, importPolicyLine) -> {
PolicyStatement importPolicy = _policyStatements.get(importPolicyName);
if (importPolicy == null) {
undefined(JuniperStructureType.POLICY_STATEMENT, importPolicyName, JuniperStructureUsage.BGP_IMPORT_POLICY, importPolicyLine);
} else {
setPolicyStatementReferent(importPolicyName, ig.getImportPolicies(), "BGP import policy for neighbor: " + ig.getRemoteAddress());
CallExpr callPolicy = new CallExpr(importPolicyName);
importPolicyCalls.add(callPolicy);
}
});
If peerImportPolicyConditional = new If();
DisjunctionChain importPolicyChain = new DisjunctionChain(importPolicyCalls);
peerImportPolicyConditional.setGuard(importPolicyChain);
peerImportPolicy.getStatements().add(peerImportPolicyConditional);
peerImportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
peerImportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
// export policies
String peerExportPolicyName = "~PEER_EXPORT_POLICY:" + ig.getRemoteAddress() + "~";
neighbor.setExportPolicy(peerExportPolicyName);
RoutingPolicy peerExportPolicy = new RoutingPolicy(peerExportPolicyName, _c);
_c.getRoutingPolicies().put(peerExportPolicyName, peerExportPolicy);
peerExportPolicy.getStatements().add(new SetDefaultPolicy(DEFAULT_BGP_EXPORT_POLICY_NAME));
/*
* For new BGP advertisements, i.e. those that are created from non-BGP
* routes, an origin code must be set. By default, Juniper sets the origin
* code to IGP.
*/
If setOriginForNonBgp = new If();
Disjunction isBgp = new Disjunction();
isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.BGP));
isBgp.getDisjuncts().add(new MatchProtocol(RoutingProtocol.IBGP));
setOriginForNonBgp.setGuard(isBgp);
setOriginForNonBgp.getFalseStatements().add(new SetOrigin(new LiteralOrigin(OriginType.IGP, null)));
peerExportPolicy.getStatements().add(setOriginForNonBgp);
List<BooleanExpr> exportPolicyCalls = new ArrayList<>();
ig.getExportPolicies().forEach((exportPolicyName, exportPolicyLine) -> {
PolicyStatement exportPolicy = _policyStatements.get(exportPolicyName);
if (exportPolicy == null) {
undefined(JuniperStructureType.POLICY_STATEMENT, exportPolicyName, JuniperStructureUsage.BGP_EXPORT_POLICY, exportPolicyLine);
} else {
setPolicyStatementReferent(exportPolicyName, ig.getExportPolicies(), "BGP export policy for neighbor: " + ig.getRemoteAddress());
CallExpr callPolicy = new CallExpr(exportPolicyName);
exportPolicyCalls.add(callPolicy);
}
});
If peerExportPolicyConditional = new If();
DisjunctionChain exportPolicyChain = new DisjunctionChain(exportPolicyCalls);
peerExportPolicyConditional.setGuard(exportPolicyChain);
peerExportPolicyConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
peerExportPolicyConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
peerExportPolicy.getStatements().add(peerExportPolicyConditional);
// inherit local-as
neighbor.setLocalAs(ig.getLocalAs());
if (neighbor.getLocalAs() == null) {
_w.redFlag("Missing local-as for neighbor: " + ig.getRemoteAddress());
continue;
}
/*
* inherit peer-as, or use local-as if internal
*
* Also set multipath
*/
if (ig.getType() == BgpGroupType.INTERNAL) {
neighbor.setRemoteAs(ig.getLocalAs());
boolean currentGroupMultipathIbgp = ig.getMultipath();
if (multipathIbgpSet && currentGroupMultipathIbgp != multipathIbgp) {
_w.redFlag("Currently do not support mixed iBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH IBGP");
multipathIbgp = false;
} else {
multipathIbgp = currentGroupMultipathIbgp;
multipathIbgpSet = true;
}
} else {
neighbor.setRemoteAs(ig.getPeerAs());
boolean currentGroupMultipathEbgp = ig.getMultipath();
if (multipathEbgpSet && currentGroupMultipathEbgp != multipathEbgp) {
_w.redFlag("Currently do not support mixed eBGP multipath/non-multipath bgp groups on Juniper " + "- FORCING NON-MULTIPATH EBGP");
multipathEbgp = false;
} else {
multipathEbgp = currentGroupMultipathEbgp;
multipathEbgpSet = true;
}
}
// TODO: implement better behavior than setting default metric to 0
neighbor.setDefaultMetric(0);
// TODO: find out if there is a juniper equivalent of cisco
// send-community
neighbor.setSendCommunity(true);
// inherit update-source
Ip localIp = ig.getLocalAddress();
if (localIp == null) {
// peer
outerloop: for (org.batfish.datamodel.Interface iface : vrf.getInterfaces().values()) {
for (InterfaceAddress address : iface.getAllAddresses()) {
if (address.getPrefix().containsIp(ip)) {
localIp = address.getIp();
break outerloop;
}
}
}
}
if (localIp == null && _defaultAddressSelection) {
initFirstLoopbackInterface();
if (_lo0 != null) {
InterfaceAddress lo0Unit0Address = _lo0.getPrimaryAddress();
if (lo0Unit0Address != null) {
localIp = lo0Unit0Address.getIp();
}
}
}
if (localIp == null && ip.valid()) {
_w.redFlag("Could not determine local ip for bgp peering with neighbor ip: " + ip);
} else {
neighbor.setLocalIp(localIp);
}
if (neighbor.getGroup() == null || !_unreferencedBgpGroups.containsKey(neighbor.getGroup())) {
proc.getNeighbors().put(neighbor.getPrefix(), neighbor);
}
}
proc.setMultipathEbgp(multipathEbgpSet);
proc.setMultipathIbgp(multipathIbgp);
MultipathEquivalentAsPathMatchMode multipathEquivalentAsPathMatchMode = multipathMultipleAs ? MultipathEquivalentAsPathMatchMode.PATH_LENGTH : MultipathEquivalentAsPathMatchMode.FIRST_AS;
proc.setMultipathEquivalentAsPathMatchMode(multipathEquivalentAsPathMatchMode);
return proc;
}
use of org.batfish.datamodel.routing_policy.statement.If in project batfish by batfish.
the class PsThenReject method applyTo.
@Override
public void applyTo(List<Statement> statements, JuniperConfiguration juniperVendorConfiguration, Configuration c, Warnings warnings) {
If ifStatement = new If();
ifStatement.setGuard(BooleanExprs.CallExprContext.toStaticBooleanExpr());
ifStatement.setTrueStatements(Collections.singletonList(Statements.ReturnFalse.toStaticStatement()));
ifStatement.setFalseStatements(Collections.singletonList(Statements.ExitReject.toStaticStatement()));
statements.add(ifStatement);
}
use of org.batfish.datamodel.routing_policy.statement.If in project batfish by batfish.
the class PsThenAccept method applyTo.
@Override
public void applyTo(List<Statement> statements, JuniperConfiguration juniperVendorConfiguration, Configuration c, Warnings w) {
If ifStatement = new If();
ifStatement.setGuard(BooleanExprs.CallExprContext.toStaticBooleanExpr());
ifStatement.setTrueStatements(Collections.singletonList(Statements.ReturnTrue.toStaticStatement()));
ifStatement.setFalseStatements(Collections.singletonList(Statements.ExitAccept.toStaticStatement()));
statements.add(ifStatement);
}
use of org.batfish.datamodel.routing_policy.statement.If in project batfish by batfish.
the class EncoderSlice method addExportConstraint.
/*
* Creates the transfer function to represent export filters
* between two symbolic records. The import filter depends
* heavily on the protocol.
*/
private void addExportConstraint(LogicalEdge e, SymbolicRoute varsOther, @Nullable SymbolicRoute ospfRedistribVars, @Nullable SymbolicRoute overallBest, Configuration conf, Protocol proto, GraphEdge ge, String router, boolean usedExport, Set<Prefix> originations) {
SymbolicRoute vars = e.getSymbolicRecord();
Interface iface = ge.getStart();
ArithExpr failed = getSymbolicFailures().getFailedVariable(e.getEdge());
assert (failed != null);
BoolExpr notFailed = mkEq(failed, mkInt(0));
// only add constraints once when using a single copy of export variables
if (!_optimizations.getSliceCanKeepSingleExportVar().get(router).get(proto) || !usedExport) {
if (proto.isConnected()) {
BoolExpr val = mkNot(vars.getPermitted());
add(val);
}
if (proto.isStatic()) {
BoolExpr val = mkNot(vars.getPermitted());
add(val);
}
if (proto.isOspf() || proto.isBgp()) {
// BGP cost based on export
Integer cost = proto.isBgp() ? addedCost(proto, ge) : 0;
BoolExpr val = mkNot(vars.getPermitted());
BoolExpr active = interfaceActive(iface, proto);
// Apply BGP export policy and cost based on peer type
// (1) EBGP --> ALL
// (2) CLIENT --> ALL
// (3) NONCLIENT --> EBGP, CLIENT
boolean isNonClientEdge = proto.isBgp() && getGraph().peerType(ge) != Graph.BgpSendType.TO_EBGP;
boolean isClientEdge = proto.isBgp() && getGraph().peerType(ge) == Graph.BgpSendType.TO_CLIENT;
boolean isInternalExport = varsOther.isBest() && _optimizations.getNeedBgpInternal().contains(router);
BoolExpr doExport = mkTrue();
if (isInternalExport && proto.isBgp() && isNonClientEdge) {
if (isClientEdge) {
cost = 0;
} else {
// Lookup if we learned from iBGP, and if so, don't export the route
SymbolicRoute other = getBestNeighborPerProtocol(router, proto);
assert other != null;
assert other.getBgpInternal() != null;
if (other.getBgpInternal() != null) {
doExport = mkNot(other.getBgpInternal());
cost = 0;
}
}
}
BoolExpr acc;
RoutingPolicy pol = getGraph().findExportRoutingPolicy(router, proto, e.getEdge());
if (Encoder.ENABLE_DEBUGGING && pol != null) {
System.out.println("Export policy (" + _sliceName + "," + ge + "): " + pol.getName());
}
// We have to wrap this with the right thing for some reason
List<Statement> statements;
Statements.StaticStatement s1 = new Statements.StaticStatement(Statements.ExitAccept);
Statements.StaticStatement s2 = new Statements.StaticStatement(Statements.ExitReject);
if (proto.isOspf()) {
If i = new If();
List<Statement> stmts = (pol == null ? Collections.singletonList(s2) : pol.getStatements());
i.setTrueStatements(Collections.singletonList(s1));
i.setFalseStatements(stmts);
BooleanExpr expr = new MatchProtocol(RoutingProtocol.OSPF);
i.setGuard(expr);
statements = Collections.singletonList(i);
} else {
statements = (pol == null ? Collections.singletonList(s1) : pol.getStatements());
}
TransferSSA f = new TransferSSA(this, conf, varsOther, vars, proto, statements, cost, ge, true);
acc = f.compute();
BoolExpr usable = mkAnd(active, doExport, varsOther.getPermitted(), notFailed);
// will maintain the same preference when adding to the cost.
if (ospfRedistribVars != null) {
assert overallBest != null;
f = new TransferSSA(this, conf, overallBest, ospfRedistribVars, proto, statements, cost, ge, true);
BoolExpr acc2 = f.compute();
// System.out.println("ADDING: \n" + acc2.simplify());
add(acc2);
BoolExpr usable2 = mkAnd(active, doExport, ospfRedistribVars.getPermitted(), notFailed);
BoolExpr geq = greaterOrEqual(conf, proto, ospfRedistribVars, varsOther, e);
BoolExpr isBetter = mkNot(mkAnd(ospfRedistribVars.getPermitted(), geq));
BoolExpr usesOspf = mkAnd(varsOther.getPermitted(), isBetter);
BoolExpr eq = equal(conf, proto, ospfRedistribVars, vars, e, false);
BoolExpr eqPer = mkEq(ospfRedistribVars.getPermitted(), vars.getPermitted());
acc = mkIf(usesOspf, mkIf(usable, acc, val), mkIf(usable2, mkAnd(eq, eqPer), val));
} else {
acc = mkIf(usable, acc, val);
}
for (Prefix p : originations) {
// For OSPF, we need to explicitly initiate a route
if (proto.isOspf()) {
BoolExpr ifaceUp = interfaceActive(iface, proto);
BoolExpr relevantPrefix = isRelevantFor(p, _symbolicPacket.getDstIp());
BoolExpr relevant = mkAnd(ifaceUp, relevantPrefix);
int adminDistance = defaultAdminDistance(conf, proto);
int prefixLength = p.getPrefixLength();
BoolExpr per = vars.getPermitted();
BoolExpr lp = safeEq(vars.getLocalPref(), mkInt(0));
BoolExpr ad = safeEq(vars.getAdminDist(), mkInt(adminDistance));
BoolExpr met = safeEq(vars.getMetric(), mkInt(cost));
BoolExpr med = safeEq(vars.getMed(), mkInt(100));
BoolExpr len = safeEq(vars.getPrefixLength(), mkInt(prefixLength));
BoolExpr type = safeEqEnum(vars.getOspfType(), OspfType.O);
BoolExpr area = safeEqEnum(vars.getOspfArea(), iface.getOspfAreaName());
BoolExpr internal = safeEq(vars.getBgpInternal(), mkFalse());
BoolExpr igpMet = safeEq(vars.getIgpMetric(), mkInt(0));
BoolExpr comms = mkTrue();
for (Map.Entry<CommunityVar, BoolExpr> entry : vars.getCommunities().entrySet()) {
comms = mkAnd(comms, mkNot(entry.getValue()));
}
BoolExpr values = mkAnd(per, lp, ad, met, med, len, type, area, internal, igpMet, comms);
// Don't originate OSPF route when there is a better redistributed route
if (ospfRedistribVars != null) {
BoolExpr betterLen = mkGt(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
BoolExpr equalLen = mkEq(ospfRedistribVars.getPrefixLength(), mkInt(prefixLength));
BoolExpr betterAd = mkLt(ospfRedistribVars.getAdminDist(), mkInt(110));
BoolExpr better = mkOr(betterLen, mkAnd(equalLen, betterAd));
BoolExpr betterRedistributed = mkAnd(ospfRedistribVars.getPermitted(), better);
relevant = mkAnd(relevant, mkNot(betterRedistributed));
}
acc = mkIf(relevant, values, acc);
}
}
add(acc);
if (Encoder.ENABLE_DEBUGGING) {
System.out.println("EXPORT: " + router + " " + varsOther.getName() + " " + ge);
System.out.println(acc.simplify());
System.out.println("\n\n");
}
}
}
}
use of org.batfish.datamodel.routing_policy.statement.If in project batfish by batfish.
the class Optimizations method computeKeepAdminDistance.
/*
* Check if administrative distance needs to be kept for
* every single message. If it is never set with a custom
* value, then it can be inferred for the best choice based
* on the default protocol value.
*/
private boolean computeKeepAdminDistance() {
if (!Optimizations.ENABLE_SLICING_OPTIMIZATION) {
return true;
}
AstVisitor v = new AstVisitor();
Boolean[] val = new Boolean[1];
val[0] = false;
_encoderSlice.getGraph().getConfigurations().forEach((router, conf) -> conf.getRoutingPolicies().forEach((name, pol) -> v.visit(conf, pol.getStatements(), stmt -> {
if (stmt instanceof SetOspfMetricType) {
val[0] = true;
}
}, expr -> {
})));
return val[0];
}
Aggregations