Search in sources :

Example 1 with SetNextHop

use of org.batfish.datamodel.routing_policy.statement.SetNextHop in project batfish by batfish.

the class VpnConnection method applyToVpnGateway.

public void applyToVpnGateway(AwsConfiguration awsConfiguration, Region region, Warnings warnings) {
    if (!awsConfiguration.getConfigurationNodes().containsKey(_vpnGatewayId)) {
        warnings.redFlag(String.format("VPN Gateway \"%s\" referred by VPN connection \"%s\" not found", _vpnGatewayId, _vpnConnectionId));
        return;
    }
    Configuration vpnGatewayCfgNode = awsConfiguration.getConfigurationNodes().get(_vpnGatewayId);
    for (int i = 0; i < _ipsecTunnels.size(); i++) {
        int idNum = i + 1;
        String vpnId = _vpnConnectionId + "-" + idNum;
        IpsecTunnel ipsecTunnel = _ipsecTunnels.get(i);
        if (ipsecTunnel.getCgwBgpAsn() != -1 && (_staticRoutesOnly || _routes.size() != 0)) {
            throw new BatfishException("Unexpected combination of BGP and static routes for VPN connection: \"" + _vpnConnectionId + "\"");
        }
        // create representation structures and add to configuration node
        IpsecVpn ipsecVpn = new IpsecVpn(vpnId, vpnGatewayCfgNode);
        vpnGatewayCfgNode.getIpsecVpns().put(vpnId, ipsecVpn);
        IpsecPolicy ipsecPolicy = new IpsecPolicy(vpnId);
        vpnGatewayCfgNode.getIpsecPolicies().put(vpnId, ipsecPolicy);
        ipsecVpn.setIpsecPolicy(ipsecPolicy);
        IpsecProposal ipsecProposal = new IpsecProposal(vpnId, -1);
        vpnGatewayCfgNode.getIpsecProposals().put(vpnId, ipsecProposal);
        ipsecPolicy.getProposals().put(vpnId, ipsecProposal);
        IkeGateway ikeGateway = new IkeGateway(vpnId);
        vpnGatewayCfgNode.getIkeGateways().put(vpnId, ikeGateway);
        ipsecVpn.setIkeGateway(ikeGateway);
        IkePolicy ikePolicy = new IkePolicy(vpnId);
        vpnGatewayCfgNode.getIkePolicies().put(vpnId, ikePolicy);
        ikeGateway.setIkePolicy(ikePolicy);
        IkeProposal ikeProposal = new IkeProposal(vpnId, -1);
        vpnGatewayCfgNode.getIkeProposals().put(vpnId, ikeProposal);
        ikePolicy.getProposals().put(vpnId, ikeProposal);
        String externalInterfaceName = "external" + idNum;
        InterfaceAddress externalInterfaceAddress = new InterfaceAddress(ipsecTunnel.getVgwOutsideAddress(), Prefix.MAX_PREFIX_LENGTH);
        Interface externalInterface = Utils.newInterface(externalInterfaceName, vpnGatewayCfgNode, externalInterfaceAddress);
        String vpnInterfaceName = "vpn" + idNum;
        InterfaceAddress vpnInterfaceAddress = new InterfaceAddress(ipsecTunnel.getVgwInsideAddress(), ipsecTunnel.getVgwInsidePrefixLength());
        Interface vpnInterface = Utils.newInterface(vpnInterfaceName, vpnGatewayCfgNode, vpnInterfaceAddress);
        // Set fields within representation structures
        // ipsec
        ipsecVpn.setBindInterface(vpnInterface);
        ipsecPolicy.setPfsKeyGroup(toDiffieHellmanGroup(ipsecTunnel.getIpsecPerfectForwardSecrecy()));
        ipsecProposal.setAuthenticationAlgorithm(toIpsecAuthenticationAlgorithm(ipsecTunnel.getIpsecAuthProtocol()));
        ipsecProposal.setEncryptionAlgorithm(toEncryptionAlgorithm(ipsecTunnel.getIpsecEncryptionProtocol()));
        ipsecProposal.setProtocol(toIpsecProtocol(ipsecTunnel.getIpsecProtocol()));
        ipsecProposal.setLifetimeSeconds(ipsecTunnel.getIpsecLifetime());
        // ike
        ikeGateway.setExternalInterface(externalInterface);
        ikeGateway.setAddress(ipsecTunnel.getCgwOutsideAddress());
        ikeGateway.setLocalIp(externalInterface.getAddress().getIp());
        if (ipsecTunnel.getIkePreSharedKeyHash() != null) {
            ikePolicy.setPreSharedKeyHash(ipsecTunnel.getIkePreSharedKeyHash());
            ikeProposal.setAuthenticationMethod(IkeAuthenticationMethod.PRE_SHARED_KEYS);
        }
        ikeProposal.setAuthenticationAlgorithm(toIkeAuthenticationAlgorithm(ipsecTunnel.getIkeAuthProtocol()));
        ikeProposal.setDiffieHellmanGroup(toDiffieHellmanGroup(ipsecTunnel.getIkePerfectForwardSecrecy()));
        ikeProposal.setEncryptionAlgorithm(toEncryptionAlgorithm(ipsecTunnel.getIkeEncryptionProtocol()));
        ikeProposal.setLifetimeSeconds(ipsecTunnel.getIkeLifetime());
        // bgp (if configured)
        if (ipsecTunnel.getVgwBgpAsn() != -1) {
            BgpProcess proc = vpnGatewayCfgNode.getDefaultVrf().getBgpProcess();
            if (proc == null) {
                proc = new BgpProcess();
                proc.setRouterId(ipsecTunnel.getVgwInsideAddress());
                proc.setMultipathEquivalentAsPathMatchMode(MultipathEquivalentAsPathMatchMode.EXACT_PATH);
                vpnGatewayCfgNode.getDefaultVrf().setBgpProcess(proc);
            }
            BgpNeighbor cgBgpNeighbor = new BgpNeighbor(ipsecTunnel.getCgwInsideAddress(), vpnGatewayCfgNode);
            cgBgpNeighbor.setVrf(Configuration.DEFAULT_VRF_NAME);
            proc.getNeighbors().put(cgBgpNeighbor.getPrefix(), cgBgpNeighbor);
            cgBgpNeighbor.setRemoteAs(ipsecTunnel.getCgwBgpAsn());
            cgBgpNeighbor.setLocalAs(ipsecTunnel.getVgwBgpAsn());
            cgBgpNeighbor.setLocalIp(ipsecTunnel.getVgwInsideAddress());
            cgBgpNeighbor.setDefaultMetric(BGP_NEIGHBOR_DEFAULT_METRIC);
            cgBgpNeighbor.setSendCommunity(false);
            VpnGateway vpnGateway = region.getVpnGateways().get(_vpnGatewayId);
            List<String> attachmentVpcIds = vpnGateway.getAttachmentVpcIds();
            if (attachmentVpcIds.size() != 1) {
                throw new BatfishException("Not sure what routes to advertise since VPN Gateway: \"" + _vpnGatewayId + "\" for VPN connection: \"" + _vpnConnectionId + "\" is linked to multiple VPCs");
            }
            String vpcId = attachmentVpcIds.get(0);
            // iBGP connection to VPC
            Configuration vpcNode = awsConfiguration.getConfigurationNodes().get(vpcId);
            Ip vpcIfaceAddress = vpcNode.getInterfaces().get(_vpnGatewayId).getAddress().getIp();
            Ip vgwToVpcIfaceAddress = vpnGatewayCfgNode.getInterfaces().get(vpcId).getAddress().getIp();
            BgpNeighbor vgwToVpcBgpNeighbor = new BgpNeighbor(vpcIfaceAddress, vpnGatewayCfgNode);
            proc.getNeighbors().put(vgwToVpcBgpNeighbor.getPrefix(), vgwToVpcBgpNeighbor);
            vgwToVpcBgpNeighbor.setVrf(Configuration.DEFAULT_VRF_NAME);
            vgwToVpcBgpNeighbor.setLocalAs(ipsecTunnel.getVgwBgpAsn());
            vgwToVpcBgpNeighbor.setLocalIp(vgwToVpcIfaceAddress);
            vgwToVpcBgpNeighbor.setRemoteAs(ipsecTunnel.getVgwBgpAsn());
            vgwToVpcBgpNeighbor.setDefaultMetric(BGP_NEIGHBOR_DEFAULT_METRIC);
            vgwToVpcBgpNeighbor.setSendCommunity(true);
            // iBGP connection from VPC
            BgpNeighbor vpcToVgwBgpNeighbor = new BgpNeighbor(vgwToVpcIfaceAddress, vpcNode);
            BgpProcess vpcProc = new BgpProcess();
            vpcNode.getDefaultVrf().setBgpProcess(vpcProc);
            vpcProc.setMultipathEquivalentAsPathMatchMode(MultipathEquivalentAsPathMatchMode.EXACT_PATH);
            vpcProc.setRouterId(vpcIfaceAddress);
            vpcProc.getNeighbors().put(vpcToVgwBgpNeighbor.getPrefix(), vpcToVgwBgpNeighbor);
            vpcToVgwBgpNeighbor.setVrf(Configuration.DEFAULT_VRF_NAME);
            vpcToVgwBgpNeighbor.setLocalAs(ipsecTunnel.getVgwBgpAsn());
            vpcToVgwBgpNeighbor.setLocalIp(vpcIfaceAddress);
            vpcToVgwBgpNeighbor.setRemoteAs(ipsecTunnel.getVgwBgpAsn());
            vpcToVgwBgpNeighbor.setDefaultMetric(BGP_NEIGHBOR_DEFAULT_METRIC);
            vpcToVgwBgpNeighbor.setSendCommunity(true);
            String rpRejectAllName = "~REJECT_ALL~";
            String rpAcceptAllEbgpAndSetNextHopSelfName = "~ACCEPT_ALL_EBGP_AND_SET_NEXT_HOP_SELF~";
            If acceptIffEbgp = new If();
            acceptIffEbgp.setGuard(new MatchProtocol(RoutingProtocol.BGP));
            acceptIffEbgp.setTrueStatements(ImmutableList.of(Statements.ExitAccept.toStaticStatement()));
            acceptIffEbgp.setFalseStatements(ImmutableList.of(Statements.ExitReject.toStaticStatement()));
            RoutingPolicy vgwRpAcceptAllBgp = new RoutingPolicy(rpAcceptAllEbgpAndSetNextHopSelfName, vpnGatewayCfgNode);
            vpnGatewayCfgNode.getRoutingPolicies().put(vgwRpAcceptAllBgp.getName(), vgwRpAcceptAllBgp);
            vgwRpAcceptAllBgp.setStatements(ImmutableList.of(new SetNextHop(new SelfNextHop(), false), acceptIffEbgp));
            vgwToVpcBgpNeighbor.setExportPolicy(rpAcceptAllEbgpAndSetNextHopSelfName);
            RoutingPolicy vgwRpRejectAll = new RoutingPolicy(rpRejectAllName, vpnGatewayCfgNode);
            vpnGatewayCfgNode.getRoutingPolicies().put(rpRejectAllName, vgwRpRejectAll);
            vgwToVpcBgpNeighbor.setImportPolicy(rpRejectAllName);
            String rpAcceptAllName = "~ACCEPT_ALL~";
            RoutingPolicy vpcRpAcceptAll = new RoutingPolicy(rpAcceptAllName, vpcNode);
            vpcNode.getRoutingPolicies().put(rpAcceptAllName, vpcRpAcceptAll);
            vpcRpAcceptAll.setStatements(ImmutableList.of(Statements.ExitAccept.toStaticStatement()));
            vpcToVgwBgpNeighbor.setImportPolicy(rpAcceptAllName);
            RoutingPolicy vpcRpRejectAll = new RoutingPolicy(rpRejectAllName, vpcNode);
            vpcNode.getRoutingPolicies().put(rpRejectAllName, vpcRpRejectAll);
            vpcToVgwBgpNeighbor.setExportPolicy(rpRejectAllName);
            Vpc vpc = region.getVpcs().get(vpcId);
            String originationPolicyName = vpnId + "_origination";
            RoutingPolicy originationRoutingPolicy = new RoutingPolicy(originationPolicyName, vpnGatewayCfgNode);
            vpnGatewayCfgNode.getRoutingPolicies().put(originationPolicyName, originationRoutingPolicy);
            cgBgpNeighbor.setExportPolicy(originationPolicyName);
            If originationIf = new If();
            List<Statement> statements = originationRoutingPolicy.getStatements();
            statements.add(originationIf);
            statements.add(Statements.ExitReject.toStaticStatement());
            originationIf.getTrueStatements().add(new SetOrigin(new LiteralOrigin(OriginType.IGP, null)));
            originationIf.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
            RouteFilterList originationRouteFilter = new RouteFilterList(originationPolicyName);
            vpnGatewayCfgNode.getRouteFilterLists().put(originationPolicyName, originationRouteFilter);
            vpc.getCidrBlockAssociations().forEach(prefix -> {
                RouteFilterLine matchOutgoingPrefix = new RouteFilterLine(LineAction.ACCEPT, prefix, new SubRange(prefix.getPrefixLength(), prefix.getPrefixLength()));
                originationRouteFilter.addLine(matchOutgoingPrefix);
            });
            Conjunction conj = new Conjunction();
            originationIf.setGuard(conj);
            conj.getConjuncts().add(new MatchProtocol(RoutingProtocol.STATIC));
            conj.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new NamedPrefixSet(originationPolicyName)));
        }
        // static routes (if configured)
        for (Prefix staticRoutePrefix : _routes) {
            StaticRoute staticRoute = StaticRoute.builder().setNetwork(staticRoutePrefix).setNextHopIp(ipsecTunnel.getCgwInsideAddress()).setAdministrativeCost(Route.DEFAULT_STATIC_ROUTE_ADMIN).setMetric(Route.DEFAULT_STATIC_ROUTE_COST).build();
            vpnGatewayCfgNode.getDefaultVrf().getStaticRoutes().add(staticRoute);
        }
    }
}
Also used : IpsecVpn(org.batfish.datamodel.IpsecVpn) Configuration(org.batfish.datamodel.Configuration) BgpProcess(org.batfish.datamodel.BgpProcess) LiteralOrigin(org.batfish.datamodel.routing_policy.expr.LiteralOrigin) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) Ip(org.batfish.datamodel.Ip) Prefix(org.batfish.datamodel.Prefix) SelfNextHop(org.batfish.datamodel.routing_policy.expr.SelfNextHop) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) IpsecProposal(org.batfish.datamodel.IpsecProposal) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) SubRange(org.batfish.datamodel.SubRange) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) RouteFilterLine(org.batfish.datamodel.RouteFilterLine) IkeProposal(org.batfish.datamodel.IkeProposal) BatfishException(org.batfish.common.BatfishException) StaticRoute(org.batfish.datamodel.StaticRoute) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) Statement(org.batfish.datamodel.routing_policy.statement.Statement) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) DestinationNetwork(org.batfish.datamodel.routing_policy.expr.DestinationNetwork) IpsecPolicy(org.batfish.datamodel.IpsecPolicy) IkeGateway(org.batfish.datamodel.IkeGateway) RouteFilterList(org.batfish.datamodel.RouteFilterList) IkePolicy(org.batfish.datamodel.IkePolicy) If(org.batfish.datamodel.routing_policy.statement.If) Interface(org.batfish.datamodel.Interface)

Example 2 with SetNextHop

use of org.batfish.datamodel.routing_policy.statement.SetNextHop in project batfish by batfish.

the class TransferBDD method compute.

/*
   * Convert a list of statements into a Z3 boolean expression for the transfer function.
   */
private TransferResult<TransferReturn, BDD> compute(List<Statement> statements, TransferParam<BDDRoute> p) {
    boolean doesReturn = false;
    TransferResult<TransferReturn, BDD> result = new TransferResult<>();
    result = result.setReturnValue(new TransferReturn(p.getData(), factory.zero())).setFallthroughValue(factory.zero()).setReturnAssignedValue(factory.zero());
    for (Statement stmt : statements) {
        if (stmt instanceof StaticStatement) {
            StaticStatement ss = (StaticStatement) stmt;
            switch(ss.getType()) {
                case ExitAccept:
                    doesReturn = true;
                    p.debug("ExitAccept");
                    result = returnValue(result, true);
                    break;
                case ReturnTrue:
                    doesReturn = true;
                    p.debug("ReturnTrue");
                    result = returnValue(result, true);
                    break;
                case ExitReject:
                    doesReturn = true;
                    p.debug("ExitReject");
                    result = returnValue(result, false);
                    break;
                case ReturnFalse:
                    doesReturn = true;
                    p.debug("ReturnFalse");
                    result = returnValue(result, false);
                    break;
                case SetDefaultActionAccept:
                    p.debug("SetDefaulActionAccept");
                    p = p.setDefaultAccept(true);
                    break;
                case SetDefaultActionReject:
                    p.debug("SetDefaultActionReject");
                    p = p.setDefaultAccept(false);
                    break;
                case SetLocalDefaultActionAccept:
                    p.debug("SetLocalDefaultActionAccept");
                    p = p.setDefaultAcceptLocal(true);
                    break;
                case SetLocalDefaultActionReject:
                    p.debug("SetLocalDefaultActionReject");
                    p = p.setDefaultAcceptLocal(false);
                    break;
                case ReturnLocalDefaultAction:
                    p.debug("ReturnLocalDefaultAction");
                    // TODO: need to set local default action in an environment
                    if (p.getDefaultAcceptLocal()) {
                        result = returnValue(result, true);
                    } else {
                        result = returnValue(result, false);
                    }
                    break;
                case FallThrough:
                    p.debug("Fallthrough");
                    result = fallthrough(result);
                    break;
                case Return:
                    // TODO: assumming this happens at the end of the function, so it is ignored for now.
                    p.debug("Return");
                    break;
                case RemovePrivateAs:
                    p.debug("RemovePrivateAs");
                    // System.out.println("Warning: use of unimplemented feature RemovePrivateAs");
                    break;
                default:
                    throw new BatfishException("TODO: computeTransferFunction: " + ss.getType());
            }
        } else if (stmt instanceof If) {
            p.debug("If");
            If i = (If) stmt;
            TransferResult<TransferReturn, BDD> r = compute(i.getGuard(), p.indent());
            BDD guard = r.getReturnValue().getSecond();
            p.debug("guard: ");
            BDDRoute current = result.getReturnValue().getFirst();
            TransferParam<BDDRoute> pTrue = p.indent().setData(current.deepCopy());
            TransferParam<BDDRoute> pFalse = p.indent().setData(current.deepCopy());
            p.debug("True Branch");
            TransferResult<TransferReturn, BDD> trueBranch = compute(i.getTrueStatements(), pTrue);
            p.debug("True Branch: " + trueBranch.getReturnValue().getFirst().hashCode());
            p.debug("False Branch");
            TransferResult<TransferReturn, BDD> falseBranch = compute(i.getFalseStatements(), pFalse);
            p.debug("False Branch: " + trueBranch.getReturnValue().getFirst().hashCode());
            BDDRoute r1 = trueBranch.getReturnValue().getFirst();
            BDDRoute r2 = falseBranch.getReturnValue().getFirst();
            BDDRoute recordVal = ite(guard, r1, r2);
            // update return values
            BDD returnVal = ite(guard, trueBranch.getReturnValue().getSecond(), falseBranch.getReturnValue().getSecond());
            // p.debug("New Return Value (neg): " + returnVal.not());
            BDD returnAss = ite(guard, trueBranch.getReturnAssignedValue(), falseBranch.getReturnAssignedValue());
            // p.debug("New Return Assigned: " + returnAss);
            BDD fallThrough = ite(guard, trueBranch.getFallthroughValue(), falseBranch.getFallthroughValue());
            // p.debug("New fallthrough: " + fallThrough);
            result = result.setReturnValue(new TransferReturn(recordVal, returnVal)).setReturnAssignedValue(returnAss).setFallthroughValue(fallThrough);
            p.debug("If return: " + result.getReturnValue().getFirst().hashCode());
        } else if (stmt instanceof SetDefaultPolicy) {
            p.debug("SetDefaultPolicy");
            p = p.setDefaultPolicy((SetDefaultPolicy) stmt);
        } else if (stmt instanceof SetMetric) {
            p.debug("SetMetric");
            SetMetric sm = (SetMetric) stmt;
            LongExpr ie = sm.getMetric();
            BDD isBGP = p.getData().getProtocolHistory().value(Protocol.BGP);
            BDD updateMed = isBGP.and(result.getReturnAssignedValue());
            BDD updateMet = isBGP.not().and(result.getReturnAssignedValue());
            BDDInteger newValue = applyLongExprModification(p.indent(), p.getData().getMetric(), ie);
            BDDInteger med = ite(updateMed, p.getData().getMed(), newValue);
            BDDInteger met = ite(updateMet, p.getData().getMetric(), newValue);
            p.getData().setMetric(met);
            p.getData().setMetric(med);
        } else if (stmt instanceof SetOspfMetricType) {
            p.debug("SetOspfMetricType");
            SetOspfMetricType somt = (SetOspfMetricType) stmt;
            OspfMetricType mt = somt.getMetricType();
            BDDDomain<OspfType> current = result.getReturnValue().getFirst().getOspfMetric();
            BDDDomain<OspfType> newValue = new BDDDomain<>(current);
            if (mt == OspfMetricType.E1) {
                p.indent().debug("Value: E1");
                newValue.setValue(OspfType.E1);
            } else {
                p.indent().debug("Value: E2");
                newValue.setValue(OspfType.E1);
            }
            newValue = ite(result.getReturnAssignedValue(), p.getData().getOspfMetric(), newValue);
            p.getData().setOspfMetric(newValue);
        } else if (stmt instanceof SetLocalPreference) {
            p.debug("SetLocalPreference");
            SetLocalPreference slp = (SetLocalPreference) stmt;
            IntExpr ie = slp.getLocalPreference();
            BDDInteger newValue = applyIntExprModification(p.indent(), p.getData().getLocalPref(), ie);
            newValue = ite(result.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
            p.getData().setLocalPref(newValue);
        } else if (stmt instanceof AddCommunity) {
            p.debug("AddCommunity");
            AddCommunity ac = (AddCommunity) stmt;
            Set<CommunityVar> comms = _graph.findAllCommunities(_conf, ac.getExpr());
            for (CommunityVar cvar : comms) {
                if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
                    p.indent().debug("Value: " + cvar);
                    BDD comm = p.getData().getCommunities().get(cvar);
                    BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.one());
                    p.indent().debug("New Value: " + newValue);
                    p.getData().getCommunities().put(cvar, newValue);
                }
            }
        } else if (stmt instanceof SetCommunity) {
            p.debug("SetCommunity");
            SetCommunity sc = (SetCommunity) stmt;
            Set<CommunityVar> comms = _graph.findAllCommunities(_conf, sc.getExpr());
            for (CommunityVar cvar : comms) {
                if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
                    p.indent().debug("Value: " + cvar);
                    BDD comm = p.getData().getCommunities().get(cvar);
                    BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.one());
                    p.indent().debug("New Value: " + newValue);
                    p.getData().getCommunities().put(cvar, newValue);
                }
            }
        } else if (stmt instanceof DeleteCommunity) {
            p.debug("DeleteCommunity");
            DeleteCommunity ac = (DeleteCommunity) stmt;
            Set<CommunityVar> comms = _graph.findAllCommunities(_conf, ac.getExpr());
            Set<CommunityVar> toDelete = new HashSet<>();
            // Find comms to delete
            for (CommunityVar cvar : comms) {
                if (cvar.getType() == Type.REGEX) {
                    toDelete.addAll(_commDeps.get(cvar));
                } else {
                    toDelete.add(cvar);
                }
            }
            // Delete the comms
            for (CommunityVar cvar : toDelete) {
                if (!_policyQuotient.getCommsAssignedButNotMatched().contains(cvar)) {
                    p.indent().debug("Value: " + cvar.getValue() + ", " + cvar.getType());
                    BDD comm = p.getData().getCommunities().get(cvar);
                    BDD newValue = ite(result.getReturnAssignedValue(), comm, factory.zero());
                    p.indent().debug("New Value: " + newValue);
                    p.getData().getCommunities().put(cvar, newValue);
                }
            }
        } else if (stmt instanceof RetainCommunity) {
            p.debug("RetainCommunity");
        // no op
        } else if (stmt instanceof PrependAsPath) {
            p.debug("PrependAsPath");
            PrependAsPath pap = (PrependAsPath) stmt;
            Integer prependCost = prependLength(pap.getExpr());
            p.indent().debug("Cost: " + prependCost);
            BDDInteger met = p.getData().getMetric();
            BDDInteger newValue = met.add(BDDInteger.makeFromValue(met.getFactory(), 32, prependCost));
            newValue = ite(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
            p.getData().setMetric(newValue);
        } else if (stmt instanceof SetOrigin) {
            p.debug("SetOrigin");
        // System.out.println("Warning: use of unimplemented feature SetOrigin");
        // TODO: implement me
        } else if (stmt instanceof SetNextHop) {
            p.debug("SetNextHop");
        // System.out.println("Warning: use of unimplemented feature SetNextHop");
        // TODO: implement me
        } else {
            throw new BatfishException("TODO: statement transfer function: " + stmt);
        }
    }
    // If this is the outermost call, then we relate the variables
    if (p.getInitialCall()) {
        p.debug("InitialCall finalizing");
        // Apply the default action
        if (!doesReturn) {
            p.debug("Applying default action: " + p.getDefaultAccept());
            if (p.getDefaultAccept()) {
                result = returnValue(result, true);
            } else {
                result = returnValue(result, false);
            }
        }
        // Set all the values to 0 if the return is not true;
        TransferReturn ret = result.getReturnValue();
        BDDRoute retVal = ite(ret.getSecond(), ret.getFirst(), zeroedRecord());
        result = result.setReturnValue(new TransferReturn(retVal, ret.getSecond()));
    }
    return result;
}
Also used : BDD(net.sf.javabdd.BDD) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet) Set(java.util.Set) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) HashSet(java.util.HashSet) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) TransferResult(org.batfish.symbolic.TransferResult) RetainCommunity(org.batfish.datamodel.routing_policy.statement.RetainCommunity) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) SetCommunity(org.batfish.datamodel.routing_policy.statement.SetCommunity) OspfType(org.batfish.symbolic.OspfType) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) HashSet(java.util.HashSet) BatfishException(org.batfish.common.BatfishException) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) Statement(org.batfish.datamodel.routing_policy.statement.Statement) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) DeleteCommunity(org.batfish.datamodel.routing_policy.statement.DeleteCommunity) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) AddCommunity(org.batfish.datamodel.routing_policy.statement.AddCommunity) CommunityVar(org.batfish.symbolic.CommunityVar) OspfMetricType(org.batfish.datamodel.OspfMetricType) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) SetLocalPreference(org.batfish.datamodel.routing_policy.statement.SetLocalPreference) TransferParam(org.batfish.symbolic.TransferParam) PrependAsPath(org.batfish.datamodel.routing_policy.statement.PrependAsPath) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) If(org.batfish.datamodel.routing_policy.statement.If)

Example 3 with SetNextHop

use of org.batfish.datamodel.routing_policy.statement.SetNextHop in project batfish by batfish.

the class CiscoConfiguration method toBgpProcess.

private org.batfish.datamodel.BgpProcess toBgpProcess(final Configuration c, BgpProcess proc, String vrfName) {
    org.batfish.datamodel.BgpProcess newBgpProcess = new org.batfish.datamodel.BgpProcess();
    org.batfish.datamodel.Vrf v = c.getVrfs().get(vrfName);
    BgpTieBreaker tieBreaker = proc.getTieBreaker();
    if (tieBreaker != null) {
        newBgpProcess.setTieBreaker(tieBreaker);
    }
    MultipathEquivalentAsPathMatchMode multipathEquivalentAsPathMatchMode = proc.getAsPathMultipathRelax() ? MultipathEquivalentAsPathMatchMode.PATH_LENGTH : MultipathEquivalentAsPathMatchMode.EXACT_PATH;
    newBgpProcess.setMultipathEquivalentAsPathMatchMode(multipathEquivalentAsPathMatchMode);
    Integer maximumPaths = proc.getMaximumPaths();
    Integer maximumPathsEbgp = proc.getMaximumPathsEbgp();
    Integer maximumPathsIbgp = proc.getMaximumPathsIbgp();
    boolean multipathEbgp = false;
    boolean multipathIbgp = false;
    if (maximumPaths != null && maximumPaths > 1) {
        multipathEbgp = true;
        multipathIbgp = true;
    }
    if (maximumPathsEbgp != null && maximumPathsEbgp > 1) {
        multipathEbgp = true;
    }
    if (maximumPathsIbgp != null && maximumPathsIbgp > 1) {
        multipathIbgp = true;
    }
    newBgpProcess.setMultipathEbgp(multipathEbgp);
    newBgpProcess.setMultipathIbgp(multipathIbgp);
    Map<Prefix, BgpNeighbor> newBgpNeighbors = newBgpProcess.getNeighbors();
    int defaultMetric = proc.getDefaultMetric();
    Ip bgpRouterId = getBgpRouterId(c, vrfName, proc);
    MatchPrefixSet matchDefaultRoute = new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(Prefix.ZERO, new SubRange(0, 0))))));
    matchDefaultRoute.setComment("match default route");
    MatchPrefix6Set matchDefaultRoute6 = new MatchPrefix6Set(new DestinationNetwork6(), new ExplicitPrefix6Set(new Prefix6Space(Collections.singleton(new Prefix6Range(Prefix6.ZERO, new SubRange(0, 0))))));
    matchDefaultRoute.setComment("match default route");
    newBgpProcess.setRouterId(bgpRouterId);
    Set<BgpAggregateIpv4Network> summaryOnlyNetworks = new HashSet<>();
    Set<BgpAggregateIpv6Network> summaryOnlyIpv6Networks = new HashSet<>();
    List<BooleanExpr> attributeMapPrefilters = new ArrayList<>();
    // add generated routes for aggregate ipv4 addresses
    for (Entry<Prefix, BgpAggregateIpv4Network> e : proc.getAggregateNetworks().entrySet()) {
        Prefix prefix = e.getKey();
        BgpAggregateIpv4Network aggNet = e.getValue();
        boolean summaryOnly = aggNet.getSummaryOnly();
        int prefixLength = prefix.getPrefixLength();
        SubRange prefixRange = new SubRange(prefixLength + 1, Prefix.MAX_PREFIX_LENGTH);
        if (summaryOnly) {
            summaryOnlyNetworks.add(aggNet);
        }
        // create generation policy for aggregate network
        String generationPolicyName = "~AGGREGATE_ROUTE_GEN:" + vrfName + ":" + prefix + "~";
        RoutingPolicy currentGeneratedRoutePolicy = new RoutingPolicy(generationPolicyName, c);
        If currentGeneratedRouteConditional = new If();
        currentGeneratedRoutePolicy.getStatements().add(currentGeneratedRouteConditional);
        currentGeneratedRouteConditional.setGuard(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(new PrefixRange(prefix, prefixRange))))));
        currentGeneratedRouteConditional.getTrueStatements().add(Statements.ReturnTrue.toStaticStatement());
        c.getRoutingPolicies().put(generationPolicyName, currentGeneratedRoutePolicy);
        GeneratedRoute.Builder gr = new GeneratedRoute.Builder();
        gr.setNetwork(prefix);
        gr.setAdmin(CISCO_AGGREGATE_ROUTE_ADMIN_COST);
        gr.setGenerationPolicy(generationPolicyName);
        gr.setDiscard(true);
        // set attribute map for aggregate network
        String attributeMapName = aggNet.getAttributeMap();
        Conjunction applyCurrentAggregateAttributesConditions = new Conjunction();
        applyCurrentAggregateAttributesConditions.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(new PrefixSpace(Collections.singleton(PrefixRange.fromPrefix(prefix))))));
        applyCurrentAggregateAttributesConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.AGGREGATE));
        BooleanExpr weInterior = BooleanExprs.True.toStaticBooleanExpr();
        if (attributeMapName != null) {
            int attributeMapLine = aggNet.getAttributeMapLine();
            RouteMap attributeMap = _routeMaps.get(attributeMapName);
            if (attributeMap != null) {
                // need to apply attribute changes if this specific route is
                // matched
                weInterior = new CallExpr(attributeMapName);
                attributeMap.getReferers().put(aggNet, "attribute-map of aggregate route: " + prefix);
                gr.setAttributePolicy(attributeMapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, attributeMapName, CiscoStructureUsage.BGP_AGGREGATE_ATTRIBUTE_MAP, attributeMapLine);
            }
        }
        v.getGeneratedRoutes().add(gr.build());
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weInterior, OriginType.IGP);
        applyCurrentAggregateAttributesConditions.getConjuncts().add(we);
        attributeMapPrefilters.add(applyCurrentAggregateAttributesConditions);
    }
    // TODO: merge with above to make cleaner
    for (Entry<Prefix6, BgpAggregateIpv6Network> e : proc.getAggregateIpv6Networks().entrySet()) {
        Prefix6 prefix6 = e.getKey();
        BgpAggregateIpv6Network aggNet = e.getValue();
        boolean summaryOnly = aggNet.getSummaryOnly();
        int prefixLength = prefix6.getPrefixLength();
        SubRange prefixRange = new SubRange(prefixLength + 1, Prefix.MAX_PREFIX_LENGTH);
        if (summaryOnly) {
            summaryOnlyIpv6Networks.add(aggNet);
        }
        // create generation policy for aggregate network
        String generationPolicyName = "~AGGREGATE_ROUTE6_GEN:" + vrfName + ":" + prefix6 + "~";
        RoutingPolicy currentGeneratedRoutePolicy = new RoutingPolicy(generationPolicyName, c);
        If currentGeneratedRouteConditional = new If();
        currentGeneratedRoutePolicy.getStatements().add(currentGeneratedRouteConditional);
        currentGeneratedRouteConditional.setGuard(new MatchPrefix6Set(new DestinationNetwork6(), new ExplicitPrefix6Set(new Prefix6Space(Collections.singleton(new Prefix6Range(prefix6, prefixRange))))));
        currentGeneratedRouteConditional.getTrueStatements().add(Statements.ReturnTrue.toStaticStatement());
        c.getRoutingPolicies().put(generationPolicyName, currentGeneratedRoutePolicy);
        GeneratedRoute6 gr = new GeneratedRoute6(prefix6, CISCO_AGGREGATE_ROUTE_ADMIN_COST);
        gr.setGenerationPolicy(generationPolicyName);
        gr.setDiscard(true);
        v.getGeneratedIpv6Routes().add(gr);
        // set attribute map for aggregate network
        String attributeMapName = aggNet.getAttributeMap();
        if (attributeMapName != null) {
            int attributeMapLine = aggNet.getAttributeMapLine();
            RouteMap attributeMap = _routeMaps.get(attributeMapName);
            if (attributeMap != null) {
                attributeMap.getReferers().put(aggNet, "attribute-map of aggregate ipv6 route: " + prefix6);
                gr.setAttributePolicy(attributeMapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, attributeMapName, CiscoStructureUsage.BGP_AGGREGATE_ATTRIBUTE_MAP, attributeMapLine);
            }
        }
    }
    /*
     * Create common bgp export policy. This policy encompasses network
     * statements, aggregate-address with/without summary-only, redistribution
     * from other protocols, and default-origination
     */
    String bgpCommonExportPolicyName = "~BGP_COMMON_EXPORT_POLICY:" + vrfName + "~";
    RoutingPolicy bgpCommonExportPolicy = new RoutingPolicy(bgpCommonExportPolicyName, c);
    c.getRoutingPolicies().put(bgpCommonExportPolicyName, bgpCommonExportPolicy);
    List<Statement> bgpCommonExportStatements = bgpCommonExportPolicy.getStatements();
    // create policy for denying suppressed summary-only networks
    if (summaryOnlyNetworks.size() > 0) {
        If suppressSummaryOnly = new If();
        bgpCommonExportStatements.add(suppressSummaryOnly);
        suppressSummaryOnly.setComment("Suppress summarized of summary-only aggregate-address networks");
        String matchSuppressedSummaryOnlyRoutesName = "~MATCH_SUPPRESSED_SUMMARY_ONLY:" + vrfName + "~";
        RouteFilterList matchSuppressedSummaryOnlyRoutes = new RouteFilterList(matchSuppressedSummaryOnlyRoutesName);
        c.getRouteFilterLists().put(matchSuppressedSummaryOnlyRoutesName, matchSuppressedSummaryOnlyRoutes);
        for (BgpAggregateIpv4Network summaryOnlyNetwork : summaryOnlyNetworks) {
            Prefix prefix = summaryOnlyNetwork.getPrefix();
            int prefixLength = prefix.getPrefixLength();
            RouteFilterLine line = new RouteFilterLine(LineAction.ACCEPT, prefix, new SubRange(prefixLength + 1, Prefix.MAX_PREFIX_LENGTH));
            matchSuppressedSummaryOnlyRoutes.addLine(line);
        }
        suppressSummaryOnly.setGuard(new MatchPrefixSet(new DestinationNetwork(), new NamedPrefixSet(matchSuppressedSummaryOnlyRoutesName)));
        suppressSummaryOnly.getTrueStatements().add(Statements.ReturnFalse.toStaticStatement());
    }
    If preFilter = new If();
    bgpCommonExportStatements.add(preFilter);
    bgpCommonExportStatements.add(Statements.ReturnFalse.toStaticStatement());
    Disjunction preFilterConditions = new Disjunction();
    preFilter.setGuard(preFilterConditions);
    preFilter.getTrueStatements().add(Statements.ReturnTrue.toStaticStatement());
    preFilterConditions.getDisjuncts().addAll(attributeMapPrefilters);
    // create redistribution origination policies
    // redistribute rip
    BgpRedistributionPolicy redistributeRipPolicy = proc.getRedistributionPolicies().get(RoutingProtocol.RIP);
    if (redistributeRipPolicy != null) {
        BooleanExpr weInterior = BooleanExprs.True.toStaticBooleanExpr();
        Conjunction exportRipConditions = new Conjunction();
        exportRipConditions.setComment("Redistribute RIP routes into BGP");
        exportRipConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.RIP));
        String mapName = redistributeRipPolicy.getRouteMap();
        if (mapName != null) {
            int mapLine = redistributeRipPolicy.getRouteMapLine();
            RouteMap redistributeRipRouteMap = _routeMaps.get(mapName);
            if (redistributeRipRouteMap != null) {
                redistributeRipRouteMap.getReferers().put(proc, "RIP redistribution route-map");
                weInterior = new CallExpr(mapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_REDISTRIBUTE_RIP_MAP, mapLine);
            }
        }
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weInterior, OriginType.INCOMPLETE);
        exportRipConditions.getConjuncts().add(we);
        preFilterConditions.getDisjuncts().add(exportRipConditions);
    }
    // redistribute static
    BgpRedistributionPolicy redistributeStaticPolicy = proc.getRedistributionPolicies().get(RoutingProtocol.STATIC);
    if (redistributeStaticPolicy != null) {
        BooleanExpr weInterior = BooleanExprs.True.toStaticBooleanExpr();
        Conjunction exportStaticConditions = new Conjunction();
        exportStaticConditions.setComment("Redistribute static routes into BGP");
        exportStaticConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.STATIC));
        String mapName = redistributeStaticPolicy.getRouteMap();
        if (mapName != null) {
            int mapLine = redistributeStaticPolicy.getRouteMapLine();
            RouteMap redistributeStaticRouteMap = _routeMaps.get(mapName);
            if (redistributeStaticRouteMap != null) {
                redistributeStaticRouteMap.getReferers().put(proc, "static redistribution route-map");
                weInterior = new CallExpr(mapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_REDISTRIBUTE_STATIC_MAP, mapLine);
            }
        }
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weInterior, OriginType.INCOMPLETE);
        exportStaticConditions.getConjuncts().add(we);
        preFilterConditions.getDisjuncts().add(exportStaticConditions);
    }
    // redistribute connected
    BgpRedistributionPolicy redistributeConnectedPolicy = proc.getRedistributionPolicies().get(RoutingProtocol.CONNECTED);
    if (redistributeConnectedPolicy != null) {
        BooleanExpr weInterior = BooleanExprs.True.toStaticBooleanExpr();
        Conjunction exportConnectedConditions = new Conjunction();
        exportConnectedConditions.setComment("Redistribute connected routes into BGP");
        exportConnectedConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.CONNECTED));
        String mapName = redistributeConnectedPolicy.getRouteMap();
        if (mapName != null) {
            int mapLine = redistributeConnectedPolicy.getRouteMapLine();
            RouteMap redistributeConnectedRouteMap = _routeMaps.get(mapName);
            if (redistributeConnectedRouteMap != null) {
                redistributeConnectedRouteMap.getReferers().put(proc, "connected redistribution route-map");
                weInterior = new CallExpr(mapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_REDISTRIBUTE_CONNECTED_MAP, mapLine);
            }
        }
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weInterior, OriginType.INCOMPLETE);
        exportConnectedConditions.getConjuncts().add(we);
        preFilterConditions.getDisjuncts().add(exportConnectedConditions);
    }
    // redistribute ospf
    BgpRedistributionPolicy redistributeOspfPolicy = proc.getRedistributionPolicies().get(RoutingProtocol.OSPF);
    if (redistributeOspfPolicy != null) {
        BooleanExpr weInterior = BooleanExprs.True.toStaticBooleanExpr();
        Conjunction exportOspfConditions = new Conjunction();
        exportOspfConditions.setComment("Redistribute OSPF routes into BGP");
        exportOspfConditions.getConjuncts().add(new MatchProtocol(RoutingProtocol.OSPF));
        String mapName = redistributeOspfPolicy.getRouteMap();
        if (mapName != null) {
            int mapLine = redistributeOspfPolicy.getRouteMapLine();
            RouteMap redistributeOspfRouteMap = _routeMaps.get(mapName);
            if (redistributeOspfRouteMap != null) {
                redistributeOspfRouteMap.getReferers().put(proc, "ospf redistribution route-map");
                weInterior = new CallExpr(mapName);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_REDISTRIBUTE_OSPF_MAP, mapLine);
            }
        }
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weInterior, OriginType.INCOMPLETE);
        exportOspfConditions.getConjuncts().add(we);
        preFilterConditions.getDisjuncts().add(exportOspfConditions);
    }
    // cause ip peer groups to inherit unset fields from owning named peer
    // group if it exists, and then always from process master peer group
    Set<LeafBgpPeerGroup> leafGroups = new LinkedHashSet<>();
    leafGroups.addAll(proc.getIpPeerGroups().values());
    leafGroups.addAll(proc.getIpv6PeerGroups().values());
    leafGroups.addAll(proc.getDynamicIpPeerGroups().values());
    leafGroups.addAll(proc.getDynamicIpv6PeerGroups().values());
    for (LeafBgpPeerGroup lpg : leafGroups) {
        lpg.inheritUnsetFields(proc, this);
    }
    _unusedPeerGroups = new TreeMap<>();
    int fakePeerCounter = -1;
    // peer groups / peer templates
    for (Entry<String, NamedBgpPeerGroup> e : proc.getNamedPeerGroups().entrySet()) {
        String name = e.getKey();
        NamedBgpPeerGroup namedPeerGroup = e.getValue();
        if (!namedPeerGroup.getInherited()) {
            _unusedPeerGroups.put(name, namedPeerGroup.getDefinitionLine());
            Ip fakeIp = new Ip(fakePeerCounter);
            IpBgpPeerGroup fakePg = new IpBgpPeerGroup(fakeIp);
            fakePg.setGroupName(name);
            fakePg.setActive(false);
            fakePg.setShutdown(true);
            leafGroups.add(fakePg);
            fakePg.inheritUnsetFields(proc, this);
            fakePeerCounter--;
        }
        namedPeerGroup.inheritUnsetFields(proc, this);
    }
    // separate because peer sessions can inherit from other peer sessions
    _unusedPeerSessions = new TreeMap<>();
    int fakeGroupCounter = 1;
    for (NamedBgpPeerGroup namedPeerGroup : proc.getPeerSessions().values()) {
        namedPeerGroup.getParentSession(proc, this).inheritUnsetFields(proc, this);
    }
    for (Entry<String, NamedBgpPeerGroup> e : proc.getPeerSessions().entrySet()) {
        String name = e.getKey();
        NamedBgpPeerGroup namedPeerGroup = e.getValue();
        if (!namedPeerGroup.getInherited()) {
            _unusedPeerSessions.put(name, namedPeerGroup.getDefinitionLine());
            String fakeNamedPgName = "~FAKE_PG_" + fakeGroupCounter + "~";
            NamedBgpPeerGroup fakeNamedPg = new NamedBgpPeerGroup(fakeNamedPgName, -1);
            fakeNamedPg.setPeerSession(name);
            proc.getNamedPeerGroups().put(fakeNamedPgName, fakeNamedPg);
            Ip fakeIp = new Ip(fakePeerCounter);
            IpBgpPeerGroup fakePg = new IpBgpPeerGroup(fakeIp);
            fakePg.setGroupName(fakeNamedPgName);
            fakePg.setActive(false);
            fakePg.setShutdown(true);
            leafGroups.add(fakePg);
            fakePg.inheritUnsetFields(proc, this);
            fakeGroupCounter++;
            fakePeerCounter--;
        }
    }
    // create origination prefilter from listed advertised networks
    proc.getIpNetworks().forEach((prefix, bgpNetwork) -> {
        String mapName = bgpNetwork.getRouteMapName();
        BooleanExpr weExpr = BooleanExprs.True.toStaticBooleanExpr();
        if (mapName != null) {
            int mapLine = bgpNetwork.getRouteMapLine();
            RouteMap routeMap = _routeMaps.get(mapName);
            if (routeMap != null) {
                weExpr = new CallExpr(mapName);
                routeMap.getReferers().put(proc, "bgp ipv4 advertised network route-map");
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_NETWORK_ORIGINATION_ROUTE_MAP, mapLine);
            }
        }
        BooleanExpr we = bgpRedistributeWithEnvironmentExpr(weExpr, OriginType.IGP);
        Conjunction exportNetworkConditions = new Conjunction();
        PrefixSpace space = new PrefixSpace();
        space.addPrefix(prefix);
        exportNetworkConditions.getConjuncts().add(new MatchPrefixSet(new DestinationNetwork(), new ExplicitPrefixSet(space)));
        exportNetworkConditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.BGP)));
        exportNetworkConditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.IBGP)));
        // TODO: ban aggregates?
        exportNetworkConditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.AGGREGATE)));
        exportNetworkConditions.getConjuncts().add(we);
        preFilterConditions.getDisjuncts().add(exportNetworkConditions);
    });
    String localFilter6Name = "~BGP_NETWORK6_NETWORKS_FILTER:" + vrfName + "~";
    Route6FilterList localFilter6 = new Route6FilterList(localFilter6Name);
    proc.getIpv6Networks().forEach((prefix6, bgpNetwork6) -> {
        int prefixLen = prefix6.getPrefixLength();
        Route6FilterLine line = new Route6FilterLine(LineAction.ACCEPT, prefix6, new SubRange(prefixLen, prefixLen));
        localFilter6.addLine(line);
        String mapName = bgpNetwork6.getRouteMapName();
        if (mapName != null) {
            int mapLine = bgpNetwork6.getRouteMapLine();
            RouteMap routeMap = _routeMaps.get(mapName);
            if (routeMap != null) {
                routeMap.getReferers().put(proc, "bgp ipv6 advertised network route-map");
                BooleanExpr we = bgpRedistributeWithEnvironmentExpr(new CallExpr(mapName), OriginType.IGP);
                Conjunction exportNetwork6Conditions = new Conjunction();
                Prefix6Space space6 = new Prefix6Space();
                space6.addPrefix6(prefix6);
                exportNetwork6Conditions.getConjuncts().add(new MatchPrefix6Set(new DestinationNetwork6(), new ExplicitPrefix6Set(space6)));
                exportNetwork6Conditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.BGP)));
                exportNetwork6Conditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.IBGP)));
                // TODO: ban aggregates?
                exportNetwork6Conditions.getConjuncts().add(new Not(new MatchProtocol(RoutingProtocol.AGGREGATE)));
                exportNetwork6Conditions.getConjuncts().add(we);
                preFilterConditions.getDisjuncts().add(exportNetwork6Conditions);
            } else {
                undefined(CiscoStructureType.ROUTE_MAP, mapName, CiscoStructureUsage.BGP_NETWORK6_ORIGINATION_ROUTE_MAP, mapLine);
            }
        }
    });
    c.getRoute6FilterLists().put(localFilter6Name, localFilter6);
    MatchProtocol isEbgp = new MatchProtocol(RoutingProtocol.BGP);
    MatchProtocol isIbgp = new MatchProtocol(RoutingProtocol.IBGP);
    preFilterConditions.getDisjuncts().add(isEbgp);
    preFilterConditions.getDisjuncts().add(isIbgp);
    for (LeafBgpPeerGroup lpg : leafGroups) {
        // update source
        String updateSourceInterface = lpg.getUpdateSource();
        boolean ipv4 = lpg.getNeighborPrefix() != null;
        Ip updateSource = getUpdateSource(c, vrfName, lpg, updateSourceInterface, ipv4);
        RoutingPolicy importPolicy = null;
        String inboundRouteMapName = lpg.getInboundRouteMap();
        if (inboundRouteMapName != null) {
            int inboundRouteMapLine = lpg.getInboundRouteMapLine();
            importPolicy = c.getRoutingPolicies().get(inboundRouteMapName);
            if (importPolicy == null) {
                undefined(CiscoStructureType.ROUTE_MAP, inboundRouteMapName, CiscoStructureUsage.BGP_INBOUND_ROUTE_MAP, inboundRouteMapLine);
            } else {
                RouteMap inboundRouteMap = _routeMaps.get(inboundRouteMapName);
                inboundRouteMap.getReferers().put(lpg, "inbound route-map for leaf peer-group: " + lpg.getName());
            }
        }
        String inboundRoute6MapName = lpg.getInboundRoute6Map();
        RoutingPolicy importPolicy6 = null;
        if (inboundRoute6MapName != null) {
            int inboundRoute6MapLine = lpg.getInboundRoute6MapLine();
            importPolicy6 = c.getRoutingPolicies().get(inboundRoute6MapName);
            if (importPolicy6 == null) {
                undefined(CiscoStructureType.ROUTE_MAP, inboundRoute6MapName, CiscoStructureUsage.BGP_INBOUND_ROUTE6_MAP, inboundRoute6MapLine);
            } else {
                RouteMap inboundRouteMap = _routeMaps.get(inboundRoute6MapName);
                inboundRouteMap.getReferers().put(lpg, "inbound route-map for leaf peer-group: " + lpg.getName());
            }
        }
        String peerExportPolicyName = "~BGP_PEER_EXPORT_POLICY:" + vrfName + ":" + lpg.getName() + "~";
        RoutingPolicy peerExportPolicy = new RoutingPolicy(peerExportPolicyName, c);
        if (lpg.getActive() && !lpg.getShutdown()) {
            c.getRoutingPolicies().put(peerExportPolicyName, peerExportPolicy);
        }
        if (lpg.getNextHopSelf() != null && lpg.getNextHopSelf()) {
            peerExportPolicy.getStatements().add(new SetNextHop(new SelfNextHop(), false));
        }
        if (lpg.getRemovePrivateAs() != null && lpg.getRemovePrivateAs()) {
            peerExportPolicy.getStatements().add(Statements.RemovePrivateAs.toStaticStatement());
        }
        If peerExportConditional = new If();
        peerExportConditional.setComment("peer-export policy main conditional: exitAccept if true / exitReject if false");
        peerExportPolicy.getStatements().add(peerExportConditional);
        Conjunction peerExportConditions = new Conjunction();
        peerExportConditional.setGuard(peerExportConditions);
        peerExportConditional.getTrueStatements().add(Statements.ExitAccept.toStaticStatement());
        peerExportConditional.getFalseStatements().add(Statements.ExitReject.toStaticStatement());
        Disjunction localOrCommonOrigination = new Disjunction();
        peerExportConditions.getConjuncts().add(localOrCommonOrigination);
        localOrCommonOrigination.getDisjuncts().add(new CallExpr(bgpCommonExportPolicyName));
        String outboundRouteMapName = lpg.getOutboundRouteMap();
        if (outboundRouteMapName != null) {
            int outboundRouteMapLine = lpg.getOutboundRouteMapLine();
            RouteMap outboundRouteMap = _routeMaps.get(outboundRouteMapName);
            if (outboundRouteMap == null) {
                undefined(CiscoStructureType.ROUTE_MAP, outboundRouteMapName, CiscoStructureUsage.BGP_OUTBOUND_ROUTE_MAP, outboundRouteMapLine);
            } else {
                outboundRouteMap.getReferers().put(lpg, "outbound route-map for leaf peer-group: " + lpg.getName());
                peerExportConditions.getConjuncts().add(new CallExpr(outboundRouteMapName));
            }
        }
        String outboundRoute6MapName = lpg.getOutboundRoute6Map();
        if (outboundRoute6MapName != null) {
            int outboundRoute6MapLine = lpg.getOutboundRoute6MapLine();
            RouteMap outboundRoute6Map = _routeMaps.get(outboundRoute6MapName);
            if (outboundRoute6Map == null) {
                undefined(CiscoStructureType.ROUTE_MAP, outboundRoute6MapName, CiscoStructureUsage.BGP_OUTBOUND_ROUTE6_MAP, outboundRoute6MapLine);
            } else {
                outboundRoute6Map.getReferers().put(lpg, "outbound ipv6 route-map for leaf peer-group: " + lpg.getName());
            }
        }
        // set up default export policy for this peer group
        GeneratedRoute.Builder defaultRoute = null;
        GeneratedRoute6.Builder defaultRoute6 = null;
        if (lpg.getDefaultOriginate()) {
            if (ipv4) {
                localOrCommonOrigination.getDisjuncts().add(matchDefaultRoute);
            } else {
                localOrCommonOrigination.getDisjuncts().add(matchDefaultRoute6);
            }
            defaultRoute = new GeneratedRoute.Builder();
            defaultRoute.setNetwork(Prefix.ZERO);
            defaultRoute.setAdmin(MAX_ADMINISTRATIVE_COST);
            defaultRoute6 = new GeneratedRoute6.Builder();
            defaultRoute6.setNetwork(Prefix6.ZERO);
            defaultRoute6.setAdmin(MAX_ADMINISTRATIVE_COST);
            String defaultOriginateMapName = lpg.getDefaultOriginateMap();
            if (defaultOriginateMapName != null) {
                // originate contingent on
                // generation policy
                int defaultOriginateMapLine = lpg.getDefaultOriginateMapLine();
                RoutingPolicy defaultRouteGenerationPolicy = c.getRoutingPolicies().get(defaultOriginateMapName);
                if (defaultRouteGenerationPolicy == null) {
                    undefined(CiscoStructureType.ROUTE_MAP, defaultOriginateMapName, CiscoStructureUsage.BGP_DEFAULT_ORIGINATE_ROUTE_MAP, defaultOriginateMapLine);
                } else {
                    RouteMap defaultRouteGenerationRouteMap = _routeMaps.get(defaultOriginateMapName);
                    defaultRouteGenerationRouteMap.getReferers().put(lpg, "default route generation policy for leaf peer-group: " + lpg.getName());
                    defaultRoute.setGenerationPolicy(defaultOriginateMapName);
                }
            } else {
                String defaultRouteGenerationPolicyName = "~BGP_DEFAULT_ROUTE_GENERATION_POLICY:" + vrfName + ":" + lpg.getName() + "~";
                RoutingPolicy defaultRouteGenerationPolicy = new RoutingPolicy(defaultRouteGenerationPolicyName, c);
                If defaultRouteGenerationConditional = new If();
                defaultRouteGenerationPolicy.getStatements().add(defaultRouteGenerationConditional);
                if (ipv4) {
                    defaultRouteGenerationConditional.setGuard(matchDefaultRoute);
                } else {
                    defaultRouteGenerationConditional.setGuard(matchDefaultRoute6);
                }
                defaultRouteGenerationConditional.getTrueStatements().add(Statements.ReturnTrue.toStaticStatement());
                if (lpg.getActive() && !lpg.getShutdown()) {
                    c.getRoutingPolicies().put(defaultRouteGenerationPolicyName, defaultRouteGenerationPolicy);
                }
                if (ipv4) {
                    defaultRoute.setGenerationPolicy(defaultRouteGenerationPolicyName);
                } else {
                    defaultRoute6.setGenerationPolicy(defaultRouteGenerationPolicyName);
                }
            }
        }
        Ip clusterId = lpg.getClusterId();
        if (clusterId == null) {
            clusterId = bgpRouterId;
        }
        boolean routeReflectorClient = lpg.getRouteReflectorClient();
        boolean sendCommunity = lpg.getSendCommunity();
        boolean additionalPathsReceive = lpg.getAdditionalPathsReceive();
        boolean additionalPathsSelectAll = lpg.getAdditionalPathsSelectAll();
        boolean additionalPathsSend = lpg.getAdditionalPathsSend();
        boolean advertiseInactive = lpg.getAdvertiseInactive();
        boolean ebgpMultihop = lpg.getEbgpMultihop();
        boolean allowasIn = lpg.getAllowAsIn();
        boolean disablePeerAsCheck = lpg.getDisablePeerAsCheck();
        String inboundPrefixListName = lpg.getInboundPrefixList();
        if (inboundPrefixListName != null) {
            int inboundPrefixListLine = lpg.getInboundPrefixListLine();
            ReferenceCountedStructure inboundPrefixList;
            if (ipv4) {
                inboundPrefixList = _prefixLists.get(inboundPrefixListName);
            } else {
                inboundPrefixList = _prefix6Lists.get(inboundPrefixListName);
            }
            if (inboundPrefixList != null) {
                inboundPrefixList.getReferers().put(lpg, "inbound prefix-list for neighbor: '" + lpg.getName() + "'");
            } else {
                if (ipv4) {
                    undefined(CiscoStructureType.PREFIX_LIST, inboundPrefixListName, CiscoStructureUsage.BGP_INBOUND_PREFIX_LIST, inboundPrefixListLine);
                } else {
                    undefined(CiscoStructureType.PREFIX6_LIST, inboundPrefixListName, CiscoStructureUsage.BGP_INBOUND_PREFIX6_LIST, inboundPrefixListLine);
                }
            }
        }
        String outboundPrefixListName = lpg.getOutboundPrefixList();
        if (outboundPrefixListName != null) {
            int outboundPrefixListLine = lpg.getOutboundPrefixListLine();
            ReferenceCountedStructure outboundPrefixList;
            if (ipv4) {
                outboundPrefixList = _prefixLists.get(outboundPrefixListName);
            } else {
                outboundPrefixList = _prefix6Lists.get(outboundPrefixListName);
            }
            if (outboundPrefixList != null) {
                outboundPrefixList.getReferers().put(lpg, "outbound prefix-list for neighbor: '" + lpg.getName() + "'");
            } else {
                if (ipv4) {
                    undefined(CiscoStructureType.PREFIX_LIST, outboundPrefixListName, CiscoStructureUsage.BGP_OUTBOUND_PREFIX_LIST, outboundPrefixListLine);
                } else {
                    undefined(CiscoStructureType.PREFIX6_LIST, outboundPrefixListName, CiscoStructureUsage.BGP_OUTBOUND_PREFIX6_LIST, outboundPrefixListLine);
                }
            }
        }
        String description = lpg.getDescription();
        if (lpg.getActive() && !lpg.getShutdown()) {
            if (lpg.getRemoteAs() == null) {
                _w.redFlag("No remote-as set for peer: " + lpg.getName());
                continue;
            }
            Integer pgLocalAs = lpg.getLocalAs();
            int localAs = pgLocalAs != null ? pgLocalAs : proc.getName();
            BgpNeighbor newNeighbor;
            if (lpg instanceof IpBgpPeerGroup) {
                IpBgpPeerGroup ipg = (IpBgpPeerGroup) lpg;
                Ip neighborAddress = ipg.getIp();
                newNeighbor = new BgpNeighbor(neighborAddress, c);
            } else if (lpg instanceof DynamicIpBgpPeerGroup) {
                DynamicIpBgpPeerGroup dpg = (DynamicIpBgpPeerGroup) lpg;
                Prefix neighborAddressRange = dpg.getPrefix();
                newNeighbor = new BgpNeighbor(neighborAddressRange, c);
            } else if (lpg instanceof Ipv6BgpPeerGroup || lpg instanceof DynamicIpv6BgpPeerGroup) {
                // TODO: implement ipv6 bgp neighbors
                continue;
            } else {
                throw new VendorConversionException("Invalid BGP leaf neighbor type");
            }
            newBgpNeighbors.put(newNeighbor.getPrefix(), newNeighbor);
            newNeighbor.setAdditionalPathsReceive(additionalPathsReceive);
            newNeighbor.setAdditionalPathsSelectAll(additionalPathsSelectAll);
            newNeighbor.setAdditionalPathsSend(additionalPathsSend);
            newNeighbor.setAdvertiseInactive(advertiseInactive);
            newNeighbor.setAllowLocalAsIn(allowasIn);
            newNeighbor.setAllowRemoteAsOut(disablePeerAsCheck);
            newNeighbor.setRouteReflectorClient(routeReflectorClient);
            newNeighbor.setClusterId(clusterId.asLong());
            newNeighbor.setDefaultMetric(defaultMetric);
            newNeighbor.setDescription(description);
            newNeighbor.setEbgpMultihop(ebgpMultihop);
            if (defaultRoute != null) {
                newNeighbor.getGeneratedRoutes().add(defaultRoute.build());
            }
            newNeighbor.setGroup(lpg.getGroupName());
            if (importPolicy != null) {
                newNeighbor.setImportPolicy(inboundRouteMapName);
            }
            newNeighbor.setLocalAs(localAs);
            newNeighbor.setLocalIp(updateSource);
            newNeighbor.setExportPolicy(peerExportPolicyName);
            newNeighbor.setRemoteAs(lpg.getRemoteAs());
            newNeighbor.setSendCommunity(sendCommunity);
            newNeighbor.setVrf(vrfName);
        }
    }
    return newBgpProcess;
}
Also used : MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) LinkedHashSet(java.util.LinkedHashSet) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) ExplicitPrefix6Set(org.batfish.datamodel.routing_policy.expr.ExplicitPrefix6Set) ArrayList(java.util.ArrayList) DestinationNetwork6(org.batfish.datamodel.routing_policy.expr.DestinationNetwork6) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) PrefixSpace(org.batfish.datamodel.PrefixSpace) GeneratedRoute6(org.batfish.datamodel.GeneratedRoute6) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) VendorConversionException(org.batfish.common.VendorConversionException) Route6FilterLine(org.batfish.datamodel.Route6FilterLine) Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) Not(org.batfish.datamodel.routing_policy.expr.Not) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) BgpTieBreaker(org.batfish.datamodel.BgpTieBreaker) GeneratedRoute(org.batfish.datamodel.GeneratedRoute) If(org.batfish.datamodel.routing_policy.statement.If) Ip(org.batfish.datamodel.Ip) Prefix(org.batfish.datamodel.Prefix) SelfNextHop(org.batfish.datamodel.routing_policy.expr.SelfNextHop) MultipathEquivalentAsPathMatchMode(org.batfish.datamodel.MultipathEquivalentAsPathMatchMode) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) ReferenceCountedStructure(org.batfish.common.util.ReferenceCountedStructure) SubRange(org.batfish.datamodel.SubRange) RouteFilterLine(org.batfish.datamodel.RouteFilterLine) PrefixRange(org.batfish.datamodel.PrefixRange) CallStatement(org.batfish.datamodel.routing_policy.statement.CallStatement) Statement(org.batfish.datamodel.routing_policy.statement.Statement) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) Route6FilterList(org.batfish.datamodel.Route6FilterList) Prefix6Space(org.batfish.datamodel.Prefix6Space) Prefix6Range(org.batfish.datamodel.Prefix6Range) BigInteger(java.math.BigInteger) DestinationNetwork(org.batfish.datamodel.routing_policy.expr.DestinationNetwork) RouteFilterList(org.batfish.datamodel.RouteFilterList) Prefix6(org.batfish.datamodel.Prefix6)

Example 4 with SetNextHop

use of org.batfish.datamodel.routing_policy.statement.SetNextHop in project batfish by batfish.

the class TransferSSA method compute.

/*
   * Convert a list of statements into a Z3 boolean expression for the transfer function.
   */
private TransferResult<BoolExpr, BoolExpr> compute(List<Statement> statements, TransferParam<SymbolicRoute> p, TransferResult<BoolExpr, BoolExpr> result) {
    boolean doesReturn = false;
    for (Statement stmt : statements) {
        if (stmt instanceof StaticStatement) {
            StaticStatement ss = (StaticStatement) stmt;
            switch(ss.getType()) {
                case ExitAccept:
                    doesReturn = true;
                    p.debug("ExitAccept");
                    result = returnValue(p, result, true);
                    break;
                case ReturnTrue:
                    doesReturn = true;
                    p.debug("ReturnTrue");
                    result = returnValue(p, result, true);
                    break;
                case ExitReject:
                    doesReturn = true;
                    p.debug("ExitReject");
                    result = returnValue(p, result, false);
                    break;
                case ReturnFalse:
                    doesReturn = true;
                    p.debug("ReturnFalse");
                    result = returnValue(p, result, false);
                    break;
                case SetDefaultActionAccept:
                    p.debug("SetDefaulActionAccept");
                    p = p.setDefaultAccept(true);
                    break;
                case SetDefaultActionReject:
                    p.debug("SetDefaultActionReject");
                    p = p.setDefaultAccept(false);
                    break;
                case SetLocalDefaultActionAccept:
                    p.debug("SetLocalDefaultActionAccept");
                    p = p.setDefaultAcceptLocal(true);
                    break;
                case SetLocalDefaultActionReject:
                    p.debug("SetLocalDefaultActionReject");
                    p = p.setDefaultAcceptLocal(false);
                    break;
                case ReturnLocalDefaultAction:
                    p.debug("ReturnLocalDefaultAction");
                    // TODO: need to set local default action in an environment
                    if (p.getDefaultAcceptLocal()) {
                        result = returnValue(p, result, true);
                    } else {
                        result = returnValue(p, result, false);
                    }
                    break;
                case FallThrough:
                    p.debug("Fallthrough");
                    result = fallthrough(p, result);
                    break;
                case Return:
                    // TODO: assumming this happens at the end of the function, so it is ignored for now.
                    p.debug("Return");
                    break;
                case RemovePrivateAs:
                    p.debug("RemovePrivateAs");
                    System.out.println("Warning: use of unimplemented feature RemovePrivateAs");
                    break;
                default:
                    throw new BatfishException("TODO: computeTransferFunction: " + ss.getType());
            }
        } else if (stmt instanceof If) {
            p.debug("If");
            If i = (If) stmt;
            TransferResult<BoolExpr, BoolExpr> r = compute(i.getGuard(), p);
            result = result.addChangedVariables(r);
            BoolExpr guard = (BoolExpr) r.getReturnValue().simplify();
            String str = guard.toString();
            // If there are updates in the guard, add them to the parameter p before entering branches
            for (Pair<String, Expr> changed : r.getChangedVariables()) {
                p.debug("CHANGED: " + changed.getFirst());
                updateSingleValue(p, changed.getFirst(), changed.getSecond());
            }
            p.debug("guard: " + str);
            // If we know the branch ahead of time, then specialize
            switch(str) {
                case "true":
                    p.debug("True Branch");
                    result = compute(i.getTrueStatements(), p.indent(), result);
                    break;
                case "false":
                    p.debug("False Branch");
                    compute(i.getFalseStatements(), p.indent(), result);
                    break;
                default:
                    p.debug("True Branch");
                    // clear changed variables before proceeding
                    TransferParam<SymbolicRoute> p1 = p.indent().setData(p.getData().copy());
                    TransferParam<SymbolicRoute> p2 = p.indent().setData(p.getData().copy());
                    TransferResult<BoolExpr, BoolExpr> trueBranch = compute(i.getTrueStatements(), p1, initialResult());
                    p.debug("False Branch");
                    TransferResult<BoolExpr, BoolExpr> falseBranch = compute(i.getFalseStatements(), p2, initialResult());
                    p.debug("JOIN");
                    PList<Pair<String, Pair<Expr, Expr>>> pairs = trueBranch.mergeChangedVariables(falseBranch);
                    // Extract and deal with the return value first so that other
                    // variables have this reflected in their value
                    int idx = pairs.find(pair -> pair.getFirst().equals("RETURN"));
                    if (idx >= 0) {
                        Pair<String, Pair<Expr, Expr>> ret = pairs.get(idx);
                        pairs = pairs.minus(idx);
                        pairs = pairs.plus(pairs.size(), ret);
                    }
                    for (Pair<String, Pair<Expr, Expr>> pair : pairs) {
                        String s = pair.getFirst();
                        p.debug("CHANGED: " + s);
                        Pair<Expr, Expr> x = joinPoint(p, result, guard, pair);
                        result = result.addChangedVariable(s, x.getFirst());
                        if (s.equals("RETURN")) {
                            result = result.setReturnValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
                        }
                        if (s.equals("FALLTHROUGH")) {
                            result = result.setFallthroughValue((BoolExpr) x.getFirst()).setReturnAssignedValue((BoolExpr) x.getSecond());
                        }
                    }
                    break;
            }
        } else if (stmt instanceof SetDefaultPolicy) {
            p.debug("SetDefaultPolicy");
            p = p.setDefaultPolicy((SetDefaultPolicy) stmt);
        } else if (stmt instanceof SetMetric) {
            p.debug("SetMetric");
            // TODO: what is the semantics for BGP? Is this MED?
            if (!_current.getProto().isBgp()) {
                SetMetric sm = (SetMetric) stmt;
                LongExpr ie = sm.getMetric();
                ArithExpr newValue = applyLongExprModification(p.getData().getMetric(), ie);
                newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
                ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
                p.getData().setMetric(x);
                result = result.addChangedVariable("METRIC", x);
            }
        } else if (stmt instanceof SetOspfMetricType) {
            p.debug("SetOspfMetricType");
            SetOspfMetricType somt = (SetOspfMetricType) stmt;
            OspfMetricType mt = somt.getMetricType();
            SymbolicOspfType t;
            if (mt == OspfMetricType.E1) {
                t = new SymbolicOspfType(_enc, OspfType.E1);
            } else {
                t = new SymbolicOspfType(_enc, OspfType.E2);
            }
            BitVecExpr newValue = t.getBitVec();
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getOspfType().getBitVec(), newValue);
            BitVecExpr x = createBitVecVariableWith(p, "OSPF-TYPE", 2, newValue);
            p.getData().getOspfType().setBitVec(x);
            result = result.addChangedVariable("OSPF-TYPE", x);
        } else if (stmt instanceof SetLocalPreference) {
            p.debug("SetLocalPreference");
            SetLocalPreference slp = (SetLocalPreference) stmt;
            IntExpr ie = slp.getLocalPreference();
            ArithExpr newValue = applyIntExprModification(p.getData().getLocalPref(), ie);
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getLocalPref(), newValue);
            ArithExpr x = createArithVariableWith(p, "LOCAL-PREF", newValue);
            p.getData().setLocalPref(x);
            result = result.addChangedVariable("LOCAL-PREF", x);
        } else if (stmt instanceof AddCommunity) {
            p.debug("AddCommunity");
            AddCommunity ac = (AddCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
            for (CommunityVar cvar : comms) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof SetCommunity) {
            p.debug("SetCommunity");
            SetCommunity sc = (SetCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, sc.getExpr());
            for (CommunityVar cvar : comms) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkTrue());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof DeleteCommunity) {
            p.debug("DeleteCommunity");
            DeleteCommunity ac = (DeleteCommunity) stmt;
            Set<CommunityVar> comms = _enc.getGraph().findAllCommunities(_conf, ac.getExpr());
            Set<CommunityVar> toDelete = new HashSet<>();
            // Find comms to delete
            for (CommunityVar cvar : comms) {
                if (cvar.getType() == Type.REGEX) {
                    toDelete.addAll(_enc.getCommunityDependencies().get(cvar));
                } else {
                    toDelete.add(cvar);
                }
            }
            // Delete each community
            for (CommunityVar cvar : toDelete) {
                BoolExpr newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getCommunities().get(cvar), _enc.mkFalse());
                BoolExpr x = createBoolVariableWith(p, cvar.getValue(), newValue);
                p.getData().getCommunities().put(cvar, x);
                result = result.addChangedVariable(cvar.getValue(), x);
            }
        } else if (stmt instanceof RetainCommunity) {
            p.debug("RetainCommunity");
        // no op
        } else if (stmt instanceof PrependAsPath) {
            p.debug("PrependAsPath");
            PrependAsPath pap = (PrependAsPath) stmt;
            Integer prependCost = prependLength(pap.getExpr());
            ArithExpr newValue = _enc.mkSum(p.getData().getMetric(), _enc.mkInt(prependCost));
            newValue = _enc.mkIf(result.getReturnAssignedValue(), p.getData().getMetric(), newValue);
            ArithExpr x = createArithVariableWith(p, "METRIC", newValue);
            p.getData().setMetric(x);
            result = result.addChangedVariable("METRIC", x);
        } else if (stmt instanceof SetOrigin) {
            p.debug("SetOrigin");
            System.out.println("Warning: use of unimplemented feature SetOrigin");
        } else if (stmt instanceof SetNextHop) {
            p.debug("SetNextHop");
            System.out.println("Warning: use of unimplemented feature SetNextHop");
        } else {
            String s = (_isExport ? "export" : "import");
            String msg = String.format("Unimplemented feature %s for %s transfer function on interface %s", stmt.toString(), s, _graphEdge.toString());
            throw new BatfishException(msg);
        }
    }
    // If this is the outermost call, then we relate the variables
    if (p.getInitialCall()) {
        p.debug("InitialCall finalizing");
        // Apply the default action
        if (!doesReturn) {
            p.debug("Applying default action: " + p.getDefaultAccept());
            if (p.getDefaultAccept()) {
                result = returnValue(p, result, true);
            } else {
                result = returnValue(p, result, false);
            }
        }
        BoolExpr related = relateVariables(p, result);
        BoolExpr retValue = _enc.mkIf(result.getReturnValue(), related, _enc.mkNot(_current.getPermitted()));
        result = result.setReturnValue(retValue);
    }
    return result;
}
Also used : IncrementMetric(org.batfish.datamodel.routing_policy.expr.IncrementMetric) MatchAsPath(org.batfish.datamodel.routing_policy.expr.MatchAsPath) RetainCommunity(org.batfish.datamodel.routing_policy.statement.RetainCommunity) Not(org.batfish.datamodel.routing_policy.expr.Not) Disjunction(org.batfish.datamodel.routing_policy.expr.Disjunction) CommunityListLine(org.batfish.datamodel.CommunityListLine) RouteFilterList(org.batfish.datamodel.RouteFilterList) Interface(org.batfish.datamodel.Interface) Map(java.util.Map) AddCommunity(org.batfish.datamodel.routing_policy.statement.AddCommunity) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) DecrementLocalPreference(org.batfish.datamodel.routing_policy.expr.DecrementLocalPreference) Pair(org.batfish.common.Pair) MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) Statement(org.batfish.datamodel.routing_policy.statement.Statement) Conjunction(org.batfish.datamodel.routing_policy.expr.Conjunction) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet) DisjunctionChain(org.batfish.datamodel.routing_policy.expr.DisjunctionChain) Set(java.util.Set) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) CommunitySetExpr(org.batfish.datamodel.routing_policy.expr.CommunitySetExpr) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) Graph(org.batfish.symbolic.Graph) DeleteCommunity(org.batfish.datamodel.routing_policy.statement.DeleteCommunity) List(java.util.List) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) IncrementLocalPreference(org.batfish.datamodel.routing_policy.expr.IncrementLocalPreference) BooleanExprs(org.batfish.datamodel.routing_policy.expr.BooleanExprs) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) MatchProtocol(org.batfish.datamodel.routing_policy.expr.MatchProtocol) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) OspfMetricType(org.batfish.datamodel.OspfMetricType) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) AsPathListExpr(org.batfish.datamodel.routing_policy.expr.AsPathListExpr) If(org.batfish.datamodel.routing_policy.statement.If) CommunityVar(org.batfish.symbolic.CommunityVar) HashMap(java.util.HashMap) DecrementMetric(org.batfish.datamodel.routing_policy.expr.DecrementMetric) BatfishException(org.batfish.common.BatfishException) LiteralInt(org.batfish.datamodel.routing_policy.expr.LiteralInt) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) ArrayList(java.util.ArrayList) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) HashSet(java.util.HashSet) LiteralLong(org.batfish.datamodel.routing_policy.expr.LiteralLong) CommunityList(org.batfish.datamodel.CommunityList) TransferResult(org.batfish.symbolic.TransferResult) RouteFilterLine(org.batfish.datamodel.RouteFilterLine) SubRange(org.batfish.datamodel.SubRange) Type(org.batfish.symbolic.CommunityVar.Type) BoolExpr(com.microsoft.z3.BoolExpr) Configuration(org.batfish.datamodel.Configuration) MatchIpv4(org.batfish.datamodel.routing_policy.expr.MatchIpv4) LineAction(org.batfish.datamodel.LineAction) ArithExpr(com.microsoft.z3.ArithExpr) MatchIpv6(org.batfish.datamodel.routing_policy.expr.MatchIpv6) WithEnvironmentExpr(org.batfish.datamodel.routing_policy.expr.WithEnvironmentExpr) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) PrefixRange(org.batfish.datamodel.PrefixRange) PrefixSetExpr(org.batfish.datamodel.routing_policy.expr.PrefixSetExpr) BitVecExpr(com.microsoft.z3.BitVecExpr) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) GraphEdge(org.batfish.symbolic.GraphEdge) SetCommunity(org.batfish.datamodel.routing_policy.statement.SetCommunity) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) PrependAsPath(org.batfish.datamodel.routing_policy.statement.PrependAsPath) TransferParam(org.batfish.symbolic.TransferParam) Expr(com.microsoft.z3.Expr) GeneratedRoute(org.batfish.datamodel.GeneratedRoute) MultipliedAs(org.batfish.datamodel.routing_policy.expr.MultipliedAs) OspfType(org.batfish.symbolic.OspfType) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) Protocol(org.batfish.symbolic.Protocol) SetLocalPreference(org.batfish.datamodel.routing_policy.statement.SetLocalPreference) Collections(java.util.Collections) ConjunctionChain(org.batfish.datamodel.routing_policy.expr.ConjunctionChain) LiteralAsList(org.batfish.datamodel.routing_policy.expr.LiteralAsList) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) Prefix(org.batfish.datamodel.Prefix) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) PList(org.batfish.symbolic.collections.PList) BoolExpr(com.microsoft.z3.BoolExpr) MatchCommunitySet(org.batfish.datamodel.routing_policy.expr.MatchCommunitySet) MatchPrefix6Set(org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set) InlineCommunitySet(org.batfish.datamodel.routing_policy.expr.InlineCommunitySet) Set(java.util.Set) NamedPrefixSet(org.batfish.datamodel.routing_policy.expr.NamedPrefixSet) HashSet(java.util.HashSet) ExplicitPrefixSet(org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet) MatchPrefixSet(org.batfish.datamodel.routing_policy.expr.MatchPrefixSet) NamedCommunitySet(org.batfish.datamodel.routing_policy.expr.NamedCommunitySet) PList(org.batfish.symbolic.collections.PList) TransferResult(org.batfish.symbolic.TransferResult) RetainCommunity(org.batfish.datamodel.routing_policy.statement.RetainCommunity) SetMetric(org.batfish.datamodel.routing_policy.statement.SetMetric) SetCommunity(org.batfish.datamodel.routing_policy.statement.SetCommunity) SetNextHop(org.batfish.datamodel.routing_policy.statement.SetNextHop) Pair(org.batfish.common.Pair) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) HashSet(java.util.HashSet) ArithExpr(com.microsoft.z3.ArithExpr) BatfishException(org.batfish.common.BatfishException) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) Statement(org.batfish.datamodel.routing_policy.statement.Statement) StaticStatement(org.batfish.datamodel.routing_policy.statement.Statements.StaticStatement) SetOrigin(org.batfish.datamodel.routing_policy.statement.SetOrigin) DeleteCommunity(org.batfish.datamodel.routing_policy.statement.DeleteCommunity) SetDefaultPolicy(org.batfish.datamodel.routing_policy.statement.SetDefaultPolicy) AddCommunity(org.batfish.datamodel.routing_policy.statement.AddCommunity) CommunityVar(org.batfish.symbolic.CommunityVar) BitVecExpr(com.microsoft.z3.BitVecExpr) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) CommunitySetExpr(org.batfish.datamodel.routing_policy.expr.CommunitySetExpr) CallExpr(org.batfish.datamodel.routing_policy.expr.CallExpr) BooleanExpr(org.batfish.datamodel.routing_policy.expr.BooleanExpr) AsPathListExpr(org.batfish.datamodel.routing_policy.expr.AsPathListExpr) BoolExpr(com.microsoft.z3.BoolExpr) ArithExpr(com.microsoft.z3.ArithExpr) WithEnvironmentExpr(org.batfish.datamodel.routing_policy.expr.WithEnvironmentExpr) PrefixSetExpr(org.batfish.datamodel.routing_policy.expr.PrefixSetExpr) BitVecExpr(com.microsoft.z3.BitVecExpr) Expr(com.microsoft.z3.Expr) LongExpr(org.batfish.datamodel.routing_policy.expr.LongExpr) OspfMetricType(org.batfish.datamodel.OspfMetricType) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) SetLocalPreference(org.batfish.datamodel.routing_policy.statement.SetLocalPreference) TransferParam(org.batfish.symbolic.TransferParam) PrependAsPath(org.batfish.datamodel.routing_policy.statement.PrependAsPath) SetOspfMetricType(org.batfish.datamodel.routing_policy.statement.SetOspfMetricType) IntExpr(org.batfish.datamodel.routing_policy.expr.IntExpr) If(org.batfish.datamodel.routing_policy.statement.If)

Aggregations

MatchPrefixSet (org.batfish.datamodel.routing_policy.expr.MatchPrefixSet)4 NamedPrefixSet (org.batfish.datamodel.routing_policy.expr.NamedPrefixSet)4 If (org.batfish.datamodel.routing_policy.statement.If)4 SetNextHop (org.batfish.datamodel.routing_policy.statement.SetNextHop)4 Statement (org.batfish.datamodel.routing_policy.statement.Statement)4 HashSet (java.util.HashSet)3 BatfishException (org.batfish.common.BatfishException)3 BgpNeighbor (org.batfish.datamodel.BgpNeighbor)3 Prefix (org.batfish.datamodel.Prefix)3 RouteFilterLine (org.batfish.datamodel.RouteFilterLine)3 RouteFilterList (org.batfish.datamodel.RouteFilterList)3 SubRange (org.batfish.datamodel.SubRange)3 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)3 Conjunction (org.batfish.datamodel.routing_policy.expr.Conjunction)3 ExplicitPrefixSet (org.batfish.datamodel.routing_policy.expr.ExplicitPrefixSet)3 MatchPrefix6Set (org.batfish.datamodel.routing_policy.expr.MatchPrefix6Set)3 MatchProtocol (org.batfish.datamodel.routing_policy.expr.MatchProtocol)3 ArrayList (java.util.ArrayList)2 Set (java.util.Set)2 GeneratedRoute (org.batfish.datamodel.GeneratedRoute)2