Search in sources :

Example 6 with OriginType

use of org.batfish.datamodel.OriginType in project batfish by batfish.

the class VirtualRouter method propagateBgpRoutes.

int propagateBgpRoutes(Map<Ip, Set<String>> ipOwners, int dependentRoutesIterations, SortedSet<Prefix> oscillatingPrefixes, Map<String, Node> nodes) {
    int numRoutes = 0;
    _receivedBgpAdvertisements = new LinkedHashSet<>();
    _prevSentBgpAdvertisements = _sentBgpAdvertisements != null ? _sentBgpAdvertisements : new LinkedHashSet<>();
    _sentBgpAdvertisements = new LinkedHashSet<>();
    // If we have no BGP process, nothing to do
    if (_vrf.getBgpProcess() == null) {
        return numRoutes;
    }
    int ebgpAdminCost = RoutingProtocol.BGP.getDefaultAdministrativeCost(_c.getConfigurationFormat());
    int ibgpAdminCost = RoutingProtocol.IBGP.getDefaultAdministrativeCost(_c.getConfigurationFormat());
    for (BgpNeighbor neighbor : _vrf.getBgpProcess().getNeighbors().values()) {
        Ip localIp = neighbor.getLocalIp();
        Set<String> localIpOwners = ipOwners.get(localIp);
        String hostname = _c.getHostname();
        if (localIpOwners == null || !localIpOwners.contains(hostname)) {
            continue;
        }
        BgpNeighbor remoteBgpNeighbor = neighbor.getRemoteBgpNeighbor();
        if (remoteBgpNeighbor == null) {
            continue;
        }
        int localAs = neighbor.getLocalAs();
        int remoteAs = neighbor.getRemoteAs();
        Configuration remoteConfig = remoteBgpNeighbor.getOwner();
        String remoteHostname = remoteConfig.getHostname();
        String remoteVrfName = remoteBgpNeighbor.getVrf();
        Vrf remoteVrf = remoteConfig.getVrfs().get(remoteVrfName);
        VirtualRouter remoteVirtualRouter = nodes.get(remoteHostname)._virtualRouters.get(remoteVrfName);
        RoutingPolicy remoteExportPolicy = remoteConfig.getRoutingPolicies().get(remoteBgpNeighbor.getExportPolicy());
        boolean ebgpSession = localAs != remoteAs;
        BgpMultipathRib targetRib = ebgpSession ? _ebgpStagingRib : _ibgpStagingRib;
        RoutingProtocol targetProtocol = ebgpSession ? RoutingProtocol.BGP : RoutingProtocol.IBGP;
        Set<AbstractRoute> remoteCandidateRoutes = Collections.newSetFromMap(new IdentityHashMap<>());
        // Add IGP routes
        Set<AbstractRoute> activeRemoteRoutes = Collections.newSetFromMap(new IdentityHashMap<>());
        activeRemoteRoutes.addAll(remoteVirtualRouter._prevMainRib.getRoutes());
        for (AbstractRoute remoteCandidateRoute : activeRemoteRoutes) {
            if (remoteCandidateRoute.getProtocol() != RoutingProtocol.BGP && remoteCandidateRoute.getProtocol() != RoutingProtocol.IBGP) {
                remoteCandidateRoutes.add(remoteCandidateRoute);
            }
        }
        /*
       * bgp advertise-external
       *
       * When this is set, add best eBGP path independently of whether
       * it is preempted by an iBGP or IGP route. Only applicable to
       * iBGP sessions.
       */
        boolean advertiseExternal = !ebgpSession && remoteBgpNeighbor.getAdvertiseExternal();
        if (advertiseExternal) {
            remoteCandidateRoutes.addAll(remoteVirtualRouter._prevEbgpBestPathRib.getRoutes());
        }
        /*
       * bgp advertise-inactive
       *
       * When this is set, add best BGP path independently of whether
       * it is preempted by an IGP route. Only applicable to eBGP
       * sessions.
       */
        boolean advertiseInactive = ebgpSession && remoteBgpNeighbor.getAdvertiseInactive();
        /* Add best bgp paths if they are active, or if advertise-inactive */
        for (AbstractRoute remoteCandidateRoute : remoteVirtualRouter._prevBgpBestPathRib.getRoutes()) {
            if (advertiseInactive || activeRemoteRoutes.contains(remoteCandidateRoute)) {
                remoteCandidateRoutes.add(remoteCandidateRoute);
            }
        }
        /* Add all bgp paths if additional-paths active for this session */
        boolean additionalPaths = !ebgpSession && neighbor.getAdditionalPathsReceive() && remoteBgpNeighbor.getAdditionalPathsSend() && remoteBgpNeighbor.getAdditionalPathsSelectAll();
        if (additionalPaths) {
            remoteCandidateRoutes.addAll(remoteVirtualRouter._prevBgpMultipathRib.getRoutes());
        }
        for (AbstractRoute remoteRoute : remoteCandidateRoutes) {
            BgpRoute.Builder transformedOutgoingRouteBuilder = new BgpRoute.Builder();
            transformedOutgoingRouteBuilder.setReceivedFromIp(remoteBgpNeighbor.getLocalIp());
            RoutingProtocol remoteRouteProtocol = remoteRoute.getProtocol();
            boolean remoteRouteIsBgp = remoteRouteProtocol == RoutingProtocol.IBGP || remoteRouteProtocol == RoutingProtocol.BGP;
            // originatorIP
            Ip originatorIp;
            if (!ebgpSession && remoteRouteProtocol.equals(RoutingProtocol.IBGP)) {
                BgpRoute bgpRemoteRoute = (BgpRoute) remoteRoute;
                originatorIp = bgpRemoteRoute.getOriginatorIp();
            } else {
                originatorIp = remoteVrf.getBgpProcess().getRouterId();
            }
            transformedOutgoingRouteBuilder.setOriginatorIp(originatorIp);
            // note whether new route is received from route reflector client
            transformedOutgoingRouteBuilder.setReceivedFromRouteReflectorClient(!ebgpSession && neighbor.getRouteReflectorClient());
            // for bgp remote route)
            if (remoteRouteIsBgp) {
                BgpRoute bgpRemoteRoute = (BgpRoute) remoteRoute;
                transformedOutgoingRouteBuilder.setOriginType(bgpRemoteRoute.getOriginType());
                if (ebgpSession && bgpRemoteRoute.getAsPath().containsAs(remoteBgpNeighbor.getRemoteAs()) && !remoteBgpNeighbor.getAllowRemoteAsOut()) {
                    // disable-peer-as-check (getAllowRemoteAsOut) is set
                    continue;
                }
                /*
           * route reflection: reflect everything received from
           * clients to clients and non-clients. reflect everything
           * received from non-clients to clients. Do not reflect to
           * originator
           */
                Ip remoteOriginatorIp = bgpRemoteRoute.getOriginatorIp();
                /*
           *  iBGP speaker should not send out routes to iBGP neighbor whose router-id is
           *  same as originator id of advertisement
           */
                if (!ebgpSession && remoteOriginatorIp != null && _vrf.getBgpProcess().getRouterId().equals(remoteOriginatorIp)) {
                    continue;
                }
                if (remoteRouteProtocol.equals(RoutingProtocol.IBGP) && !ebgpSession) {
                    /*
             *  The remote route is iBGP. The session is iBGP. We consider whether to reflect, and
             *  modify the outgoing route as appropriate.
             */
                    boolean remoteRouteReceivedFromRouteReflectorClient = bgpRemoteRoute.getReceivedFromRouteReflectorClient();
                    boolean sendingToRouteReflectorClient = remoteBgpNeighbor.getRouteReflectorClient();
                    Ip remoteReceivedFromIp = bgpRemoteRoute.getReceivedFromIp();
                    boolean remoteRouteOriginatedByRemoteNeighbor = remoteReceivedFromIp.equals(Ip.ZERO);
                    if (!remoteRouteReceivedFromRouteReflectorClient && !sendingToRouteReflectorClient && !remoteRouteOriginatedByRemoteNeighbor) {
                        /*
               * Neither reflecting nor originating this iBGP route, so don't send
               */
                        continue;
                    }
                    transformedOutgoingRouteBuilder.getClusterList().addAll(bgpRemoteRoute.getClusterList());
                    if (!remoteRouteOriginatedByRemoteNeighbor) {
                        // we are reflecting, so we need to get the clusterid associated with the remoteRoute
                        BgpNeighbor remoteReceivedFromSession = remoteVrf.getBgpProcess().getNeighbors().get(new Prefix(remoteReceivedFromIp, Prefix.MAX_PREFIX_LENGTH));
                        long newClusterId = remoteReceivedFromSession.getClusterId();
                        transformedOutgoingRouteBuilder.getClusterList().add(newClusterId);
                    }
                    Set<Long> localClusterIds = _vrf.getBgpProcess().getClusterIds();
                    Set<Long> outgoingClusterList = transformedOutgoingRouteBuilder.getClusterList();
                    if (localClusterIds.stream().anyMatch(outgoingClusterList::contains)) {
                        /*
               *  receiver will reject new route if it contains any of its local cluster ids
               */
                        continue;
                    }
                }
            }
            // Outgoing communities
            if (remoteRouteIsBgp) {
                BgpRoute bgpRemoteRoute = (BgpRoute) remoteRoute;
                transformedOutgoingRouteBuilder.setAsPath(bgpRemoteRoute.getAsPath().getAsSets());
                if (remoteBgpNeighbor.getSendCommunity()) {
                    transformedOutgoingRouteBuilder.getCommunities().addAll(bgpRemoteRoute.getCommunities());
                }
            }
            if (ebgpSession) {
                SortedSet<Integer> newAsPathElement = new TreeSet<>();
                newAsPathElement.add(remoteAs);
                transformedOutgoingRouteBuilder.getAsPath().add(0, newAsPathElement);
            }
            // Outgoing protocol
            transformedOutgoingRouteBuilder.setProtocol(targetProtocol);
            transformedOutgoingRouteBuilder.setNetwork(remoteRoute.getNetwork());
            // Outgoing metric
            if (remoteRouteIsBgp) {
                transformedOutgoingRouteBuilder.setMetric(remoteRoute.getMetric());
            }
            // Outgoing nextHopIp
            // Outgoing localPreference
            Ip nextHopIp;
            int localPreference;
            if (ebgpSession || !remoteRouteIsBgp) {
                nextHopIp = remoteBgpNeighbor.getLocalIp();
                localPreference = BgpRoute.DEFAULT_LOCAL_PREFERENCE;
            } else {
                nextHopIp = remoteRoute.getNextHopIp();
                BgpRoute remoteIbgpRoute = (BgpRoute) remoteRoute;
                localPreference = remoteIbgpRoute.getLocalPreference();
            }
            if (nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) {
                // should only happen for ibgp
                String nextHopInterface = remoteRoute.getNextHopInterface();
                InterfaceAddress nextHopAddress = remoteVrf.getInterfaces().get(nextHopInterface).getAddress();
                if (nextHopAddress == null) {
                    throw new BatfishException("remote route's nextHopInterface has no address");
                }
                nextHopIp = nextHopAddress.getIp();
            }
            transformedOutgoingRouteBuilder.setNextHopIp(nextHopIp);
            transformedOutgoingRouteBuilder.setLocalPreference(localPreference);
            // Outgoing srcProtocol
            transformedOutgoingRouteBuilder.setSrcProtocol(remoteRoute.getProtocol());
            /*
         * CREATE OUTGOING ROUTE
         */
            boolean acceptOutgoing = remoteExportPolicy.process(remoteRoute, transformedOutgoingRouteBuilder, localIp, remoteVrfName, Direction.OUT);
            if (acceptOutgoing) {
                BgpRoute transformedOutgoingRoute = transformedOutgoingRouteBuilder.build();
                // Record sent advertisement
                BgpAdvertisementType sentType = ebgpSession ? BgpAdvertisementType.EBGP_SENT : BgpAdvertisementType.IBGP_SENT;
                Ip sentReceivedFromIp = transformedOutgoingRoute.getReceivedFromIp();
                Ip sentOriginatorIp = transformedOutgoingRoute.getOriginatorIp();
                SortedSet<Long> sentClusterList = transformedOutgoingRoute.getClusterList();
                boolean sentReceivedFromRouteReflectorClient = transformedOutgoingRoute.getReceivedFromRouteReflectorClient();
                AsPath sentAsPath = transformedOutgoingRoute.getAsPath();
                SortedSet<Long> sentCommunities = transformedOutgoingRoute.getCommunities();
                Prefix sentNetwork = remoteRoute.getNetwork();
                Ip sentNextHopIp;
                String sentSrcNode = remoteHostname;
                String sentSrcVrf = remoteVrfName;
                Ip sentSrcIp = remoteBgpNeighbor.getLocalIp();
                String sentDstNode = hostname;
                String sentDstVrf = _vrf.getName();
                Ip sentDstIp = neighbor.getLocalIp();
                int sentWeight = -1;
                if (ebgpSession) {
                    sentNextHopIp = nextHopIp;
                } else {
                    sentNextHopIp = transformedOutgoingRoute.getNextHopIp();
                }
                int sentLocalPreference = transformedOutgoingRoute.getLocalPreference();
                long sentMed = transformedOutgoingRoute.getMetric();
                OriginType sentOriginType = transformedOutgoingRoute.getOriginType();
                RoutingProtocol sentSrcProtocol = targetProtocol;
                BgpRoute.Builder transformedIncomingRouteBuilder = new BgpRoute.Builder();
                // Incoming originatorIp
                transformedIncomingRouteBuilder.setOriginatorIp(sentOriginatorIp);
                // Incoming receivedFromIp
                transformedIncomingRouteBuilder.setReceivedFromIp(sentReceivedFromIp);
                // Incoming clusterList
                transformedIncomingRouteBuilder.getClusterList().addAll(sentClusterList);
                // Incoming receivedFromRouteReflectorClient
                transformedIncomingRouteBuilder.setReceivedFromRouteReflectorClient(sentReceivedFromRouteReflectorClient);
                // Incoming asPath
                transformedIncomingRouteBuilder.setAsPath(sentAsPath.getAsSets());
                // Incoming communities
                transformedIncomingRouteBuilder.getCommunities().addAll(sentCommunities);
                // Incoming protocol
                transformedIncomingRouteBuilder.setProtocol(targetProtocol);
                // Incoming network
                transformedIncomingRouteBuilder.setNetwork(sentNetwork);
                // Incoming nextHopIp
                transformedIncomingRouteBuilder.setNextHopIp(sentNextHopIp);
                // Incoming localPreference
                transformedIncomingRouteBuilder.setLocalPreference(sentLocalPreference);
                // Incoming admin
                int admin = ebgpSession ? ebgpAdminCost : ibgpAdminCost;
                transformedIncomingRouteBuilder.setAdmin(admin);
                // Incoming metric
                transformedIncomingRouteBuilder.setMetric(sentMed);
                // Incoming originType
                transformedIncomingRouteBuilder.setOriginType(sentOriginType);
                // Incoming srcProtocol
                transformedIncomingRouteBuilder.setSrcProtocol(sentSrcProtocol);
                String importPolicyName = neighbor.getImportPolicy();
                if (transformedOutgoingRoute.getAsPath().containsAs(neighbor.getLocalAs()) && !neighbor.getAllowLocalAsIn()) {
                    // disable-peer-as-check (getAllowRemoteAsOut) is set
                    continue;
                }
                BgpAdvertisement sentAdvert = new BgpAdvertisement(sentType, sentNetwork, sentNextHopIp, sentSrcNode, sentSrcVrf, sentSrcIp, sentDstNode, sentDstVrf, sentDstIp, sentSrcProtocol, sentOriginType, sentLocalPreference, sentMed, sentOriginatorIp, sentAsPath, sentCommunities, sentClusterList, sentWeight);
                Prefix prefix = remoteRoute.getNetwork();
                boolean isOscillatingPrefix = oscillatingPrefixes.contains(prefix);
                boolean hasAdvertisementPriorityDuringRecovery = hasAdvertisementPriorityDuringRecovery(remoteRoute, dependentRoutesIterations, oscillatingPrefixes, neighbor, remoteBgpNeighbor);
                if (isOscillatingPrefix && !hasAdvertisementPriorityDuringRecovery && !_prevSentBgpAdvertisements.contains(sentAdvert)) {
                    continue;
                }
                _sentBgpAdvertisements.add(sentAdvert);
                /*
           * CREATE INCOMING ROUTE
           */
                boolean acceptIncoming = true;
                if (importPolicyName != null) {
                    RoutingPolicy importPolicy = _c.getRoutingPolicies().get(importPolicyName);
                    if (importPolicy != null) {
                        acceptIncoming = importPolicy.process(transformedOutgoingRoute, transformedIncomingRouteBuilder, remoteBgpNeighbor.getLocalIp(), _key, Direction.IN);
                    }
                }
                if (acceptIncoming) {
                    BgpRoute transformedIncomingRoute = transformedIncomingRouteBuilder.build();
                    BgpAdvertisementType receivedType = ebgpSession ? BgpAdvertisementType.EBGP_RECEIVED : BgpAdvertisementType.IBGP_RECEIVED;
                    Prefix receivedNetwork = sentNetwork;
                    Ip receivedNextHopIp = sentNextHopIp;
                    String receivedSrcNode = sentSrcNode;
                    String receivedSrcVrf = sentSrcVrf;
                    Ip receivedSrcIp = sentSrcIp;
                    String receivedDstNode = sentDstNode;
                    String receivedDstVrf = sentDstVrf;
                    Ip receivedDstIp = sentDstIp;
                    RoutingProtocol receivedSrcProtocol = sentSrcProtocol;
                    OriginType receivedOriginType = transformedIncomingRoute.getOriginType();
                    int receivedLocalPreference = transformedIncomingRoute.getLocalPreference();
                    long receivedMed = transformedIncomingRoute.getMetric();
                    Ip receivedOriginatorIp = sentOriginatorIp;
                    AsPath receivedAsPath = transformedIncomingRoute.getAsPath();
                    SortedSet<Long> receivedCommunities = transformedIncomingRoute.getCommunities();
                    SortedSet<Long> receivedClusterList = sentClusterList;
                    int receivedWeight = transformedIncomingRoute.getWeight();
                    BgpAdvertisement receivedAdvert = new BgpAdvertisement(receivedType, receivedNetwork, receivedNextHopIp, receivedSrcNode, receivedSrcVrf, receivedSrcIp, receivedDstNode, receivedDstVrf, receivedDstIp, receivedSrcProtocol, receivedOriginType, receivedLocalPreference, receivedMed, receivedOriginatorIp, receivedAsPath, receivedCommunities, receivedClusterList, receivedWeight);
                    if (targetRib.mergeRoute(transformedIncomingRoute)) {
                        numRoutes++;
                    }
                    _receivedBgpAdvertisements.add(receivedAdvert);
                }
            }
        }
    }
    return numRoutes;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) RoutingProtocol(org.batfish.datamodel.RoutingProtocol) Configuration(org.batfish.datamodel.Configuration) BgpAdvertisementType(org.batfish.datamodel.BgpAdvertisement.BgpAdvertisementType) Ip(org.batfish.datamodel.Ip) Vrf(org.batfish.datamodel.Vrf) Prefix(org.batfish.datamodel.Prefix) BgpNeighbor(org.batfish.datamodel.BgpNeighbor) TreeSet(java.util.TreeSet) BgpRoute(org.batfish.datamodel.BgpRoute) AbstractRoute(org.batfish.datamodel.AbstractRoute) BatfishException(org.batfish.common.BatfishException) OriginType(org.batfish.datamodel.OriginType) InterfaceAddress(org.batfish.datamodel.InterfaceAddress) RoutingPolicy(org.batfish.datamodel.routing_policy.RoutingPolicy) AsPath(org.batfish.datamodel.AsPath) BgpAdvertisement(org.batfish.datamodel.BgpAdvertisement)

Aggregations

OriginType (org.batfish.datamodel.OriginType)6 BgpRoute (org.batfish.datamodel.BgpRoute)5 Prefix (org.batfish.datamodel.Prefix)4 TreeSet (java.util.TreeSet)3 BatfishException (org.batfish.common.BatfishException)3 AsPath (org.batfish.datamodel.AsPath)3 BgpAdvertisement (org.batfish.datamodel.BgpAdvertisement)3 BgpAdvertisementType (org.batfish.datamodel.BgpAdvertisement.BgpAdvertisementType)3 BgpNeighbor (org.batfish.datamodel.BgpNeighbor)3 Ip (org.batfish.datamodel.Ip)3 RoutingProtocol (org.batfish.datamodel.RoutingProtocol)3 RoutingPolicy (org.batfish.datamodel.routing_policy.RoutingPolicy)3 AbstractRoute (org.batfish.datamodel.AbstractRoute)2 Configuration (org.batfish.datamodel.Configuration)2 InterfaceAddress (org.batfish.datamodel.InterfaceAddress)2 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayList (java.util.ArrayList)1 Collections.singletonList (java.util.Collections.singletonList)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1