use of org.batfish.datamodel.AbstractRoute in project batfish by batfish.
the class VirtualRouter method initBgpAggregateRoutes.
/**
* This function creates BGP routes from generated routes that go into the BGP RIB, but cannot be
* imported into the main RIB. The purpose of these routes is to prevent the local router from
* accepting advertisements less desirable than the local generated ones for the given network.
* They are not themselves advertised.
*/
void initBgpAggregateRoutes() {
// first import aggregates
switch(_c.getConfigurationFormat()) {
case JUNIPER:
case JUNIPER_SWITCH:
return;
// $CASES-OMITTED$
default:
break;
}
for (AbstractRoute grAbstract : _generatedRib.getRoutes()) {
GeneratedRoute gr = (GeneratedRoute) grAbstract;
BgpRoute.Builder b = new BgpRoute.Builder();
b.setAdmin(gr.getAdministrativeCost());
b.setAsPath(gr.getAsPath().getAsSets());
b.setMetric(gr.getMetric());
b.setSrcProtocol(RoutingProtocol.AGGREGATE);
b.setProtocol(RoutingProtocol.AGGREGATE);
b.setNetwork(gr.getNetwork());
b.setLocalPreference(BgpRoute.DEFAULT_LOCAL_PREFERENCE);
/* Note: Origin type and originator IP should get overwritten, but are needed initially */
b.setOriginatorIp(_vrf.getBgpProcess().getRouterId());
b.setOriginType(OriginType.INCOMPLETE);
b.setReceivedFromIp(Ip.ZERO);
BgpRoute br = b.build();
br.setNonRouting(true);
_bgpMultipathRib.mergeRoute(br);
_bgpBestPathRib.mergeRoute(br);
}
}
use of org.batfish.datamodel.AbstractRoute in project batfish by batfish.
the class VirtualRouter method computeBgpAdvertisementsToOutside.
int computeBgpAdvertisementsToOutside(Map<Ip, Set<String>> ipOwners) {
int numAdvertisements = 0;
// If we have no BGP process, nothing to do
if (_vrf.getBgpProcess() == null) {
return numAdvertisements;
}
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;
}
Prefix remotePrefix = neighbor.getPrefix();
if (remotePrefix.getPrefixLength() != Prefix.MAX_PREFIX_LENGTH) {
// Do not support dynamic outside neighbors
continue;
}
Ip remoteIp = remotePrefix.getStartIp();
if (ipOwners.get(remoteIp) != null) {
// Skip if neighbor is not outside the network
continue;
}
int localAs = neighbor.getLocalAs();
int remoteAs = neighbor.getRemoteAs();
String remoteHostname = remoteIp.toString();
String remoteVrfName = Configuration.DEFAULT_VRF_NAME;
RoutingPolicy exportPolicy = _c.getRoutingPolicies().get(neighbor.getExportPolicy());
boolean ebgpSession = localAs != remoteAs;
RoutingProtocol targetProtocol = ebgpSession ? RoutingProtocol.BGP : RoutingProtocol.IBGP;
Set<AbstractRoute> candidateRoutes = Collections.newSetFromMap(new IdentityHashMap<>());
// Add IGP routes
Set<AbstractRoute> activeRoutes = Collections.newSetFromMap(new IdentityHashMap<>());
activeRoutes.addAll(_mainRib.getRoutes());
for (AbstractRoute candidateRoute : activeRoutes) {
if (candidateRoute.getProtocol() != RoutingProtocol.BGP && candidateRoute.getProtocol() != RoutingProtocol.IBGP) {
candidateRoutes.add(candidateRoute);
}
}
/*
* 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 && neighbor.getAdvertiseExternal();
if (advertiseExternal) {
candidateRoutes.addAll(_ebgpBestPathRib.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 && neighbor.getAdvertiseInactive();
/* Add best bgp paths if they are active, or if advertise-inactive */
for (AbstractRoute candidateRoute : _bgpBestPathRib.getRoutes()) {
if (advertiseInactive || activeRoutes.contains(candidateRoute)) {
candidateRoutes.add(candidateRoute);
}
}
/* Add all bgp paths if additional-paths active for this session */
boolean additionalPaths = !ebgpSession && neighbor.getAdditionalPathsSend() && neighbor.getAdditionalPathsSelectAll();
if (additionalPaths) {
candidateRoutes.addAll(_bgpMultipathRib.getRoutes());
}
for (AbstractRoute route : candidateRoutes) {
BgpRoute.Builder transformedOutgoingRouteBuilder = new BgpRoute.Builder();
RoutingProtocol routeProtocol = route.getProtocol();
boolean routeIsBgp = routeProtocol == RoutingProtocol.IBGP || routeProtocol == RoutingProtocol.BGP;
// originatorIP
Ip originatorIp;
if (!ebgpSession && routeProtocol.equals(RoutingProtocol.IBGP)) {
BgpRoute bgpRoute = (BgpRoute) route;
originatorIp = bgpRoute.getOriginatorIp();
} else {
originatorIp = _vrf.getBgpProcess().getRouterId();
}
transformedOutgoingRouteBuilder.setOriginatorIp(originatorIp);
transformedOutgoingRouteBuilder.setReceivedFromIp(neighbor.getLocalIp());
// for bgp remote route)
if (routeIsBgp) {
BgpRoute bgpRoute = (BgpRoute) route;
transformedOutgoingRouteBuilder.setOriginType(bgpRoute.getOriginType());
if (ebgpSession && bgpRoute.getAsPath().containsAs(neighbor.getRemoteAs()) && !neighbor.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 routeOriginatorIp = bgpRoute.getOriginatorIp();
/*
* iBGP speaker should not send out routes to iBGP neighbor whose router-id is
* same as originator id of advertisement
*/
if (!ebgpSession && routeOriginatorIp != null && remoteIp.equals(routeOriginatorIp)) {
continue;
}
if (routeProtocol.equals(RoutingProtocol.IBGP) && !ebgpSession) {
boolean routeReceivedFromRouteReflectorClient = bgpRoute.getReceivedFromRouteReflectorClient();
boolean sendingToRouteReflectorClient = neighbor.getRouteReflectorClient();
transformedOutgoingRouteBuilder.getClusterList().addAll(bgpRoute.getClusterList());
if (!routeReceivedFromRouteReflectorClient && !sendingToRouteReflectorClient) {
continue;
}
if (sendingToRouteReflectorClient) {
// sender adds its local cluster id to clusterlist of
// new route
transformedOutgoingRouteBuilder.getClusterList().add(neighbor.getClusterId());
}
}
}
// Outgoing communities
if (routeIsBgp) {
BgpRoute bgpRoute = (BgpRoute) route;
transformedOutgoingRouteBuilder.setAsPath(bgpRoute.getAsPath().getAsSets());
if (neighbor.getSendCommunity()) {
transformedOutgoingRouteBuilder.getCommunities().addAll(bgpRoute.getCommunities());
}
}
if (ebgpSession) {
SortedSet<Integer> newAsPathElement = new TreeSet<>();
newAsPathElement.add(localAs);
transformedOutgoingRouteBuilder.getAsPath().add(0, newAsPathElement);
}
// Outgoing protocol
transformedOutgoingRouteBuilder.setProtocol(targetProtocol);
transformedOutgoingRouteBuilder.setNetwork(route.getNetwork());
// Outgoing metric
if (routeIsBgp) {
transformedOutgoingRouteBuilder.setMetric(route.getMetric());
}
// Outgoing nextHopIp
// Outgoing localPreference
Ip nextHopIp;
int localPreference;
if (ebgpSession || !routeIsBgp) {
nextHopIp = neighbor.getLocalIp();
localPreference = BgpRoute.DEFAULT_LOCAL_PREFERENCE;
} else {
nextHopIp = route.getNextHopIp();
BgpRoute ibgpRoute = (BgpRoute) route;
localPreference = ibgpRoute.getLocalPreference();
}
if (nextHopIp.equals(Route.UNSET_ROUTE_NEXT_HOP_IP)) {
// should only happen for ibgp
String nextHopInterface = route.getNextHopInterface();
InterfaceAddress nextHopAddress = _c.getInterfaces().get(nextHopInterface).getAddress();
if (nextHopAddress == null) {
throw new BatfishException("route's nextHopInterface has no address");
}
nextHopIp = nextHopAddress.getIp();
}
transformedOutgoingRouteBuilder.setNextHopIp(nextHopIp);
transformedOutgoingRouteBuilder.setLocalPreference(localPreference);
// Outgoing srcProtocol
transformedOutgoingRouteBuilder.setSrcProtocol(route.getProtocol());
/*
* CREATE OUTGOING ROUTE
*/
boolean acceptOutgoing = exportPolicy.process(route, transformedOutgoingRouteBuilder, remoteIp, remoteVrfName, Direction.OUT);
if (acceptOutgoing) {
BgpRoute transformedOutgoingRoute = transformedOutgoingRouteBuilder.build();
// Record sent advertisement
BgpAdvertisementType sentType = ebgpSession ? BgpAdvertisementType.EBGP_SENT : BgpAdvertisementType.IBGP_SENT;
Ip sentOriginatorIp = transformedOutgoingRoute.getOriginatorIp();
SortedSet<Long> sentClusterList = transformedOutgoingRoute.getClusterList();
AsPath sentAsPath = transformedOutgoingRoute.getAsPath();
SortedSet<Long> sentCommunities = transformedOutgoingRoute.getCommunities();
Prefix sentNetwork = route.getNetwork();
Ip sentNextHopIp;
String sentSrcNode = hostname;
String sentSrcVrf = _vrf.getName();
Ip sentSrcIp = neighbor.getLocalIp();
String sentDstNode = remoteHostname;
String sentDstVrf = remoteVrfName;
Ip sentDstIp = remoteIp;
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;
BgpAdvertisement sentAdvert = new BgpAdvertisement(sentType, sentNetwork, sentNextHopIp, sentSrcNode, sentSrcVrf, sentSrcIp, sentDstNode, sentDstVrf, sentDstIp, sentSrcProtocol, sentOriginType, sentLocalPreference, sentMed, sentOriginatorIp, sentAsPath, sentCommunities, sentClusterList, sentWeight);
_sentBgpAdvertisements.add(sentAdvert);
numAdvertisements++;
}
}
}
return numAdvertisements;
}
use of org.batfish.datamodel.AbstractRoute in project batfish by batfish.
the class BdpDataPlanePluginTest method testIbgpRejectSameNeighborID.
@Test
public void testIbgpRejectSameNeighborID() throws IOException {
String testrigName = "ibgp-reject-routerid-match";
List<String> configurationNames = ImmutableList.of("r1", "r2", "r3", "r4");
Batfish batfish = BatfishTestUtils.getBatfishFromTestrigText(TestrigText.builder().setConfigurationText(TESTRIGS_PREFIX + testrigName, configurationNames).build(), _folder);
BdpDataPlanePlugin dataPlanePlugin = new BdpDataPlanePlugin();
dataPlanePlugin.initialize(batfish);
batfish.computeDataPlane(false);
SortedMap<String, SortedMap<String, SortedSet<AbstractRoute>>> routes = dataPlanePlugin.getRoutes(batfish.loadDataPlane());
SortedSet<AbstractRoute> r2Routes = routes.get("r2").get(DEFAULT_VRF_NAME);
SortedSet<AbstractRoute> r3Routes = routes.get("r3").get(DEFAULT_VRF_NAME);
Set<Prefix> r2Prefixes = r2Routes.stream().map(r -> r.getNetwork()).collect(Collectors.toSet());
Set<Prefix> r3Prefixes = r3Routes.stream().map(r -> r.getNetwork()).collect(Collectors.toSet());
// 9.9.9.9/32 is the prefix we test with
Prefix r1AdvertisedPrefix = Prefix.parse("9.9.9.9/32");
// Ensure that the prefix is accepted by r2, because router ids are different
assertThat(r1AdvertisedPrefix, isIn(r2Prefixes));
// Ensure that the prefix is rejected by r3, because router ids are the same
assertThat(r1AdvertisedPrefix, not(isIn(r3Prefixes)));
}
use of org.batfish.datamodel.AbstractRoute in project batfish by batfish.
the class BdpDataPlanePluginTest method testIosRtStaticMatchesBdp.
@Test
public void testIosRtStaticMatchesBdp() throws IOException {
String testrigResourcePrefix = TESTRIGS_PREFIX + "ios-rt-static-ad";
List<String> configurationNames = ImmutableList.of("r1");
List<String> routingTableNames = ImmutableList.of("r1");
Batfish batfish = BatfishTestUtils.getBatfishFromTestrigText(TestrigText.builder().setConfigurationText(testrigResourcePrefix, configurationNames).setRoutingTablesText(testrigResourcePrefix, routingTableNames).build(), _folder);
BdpDataPlanePlugin dataPlanePlugin = new BdpDataPlanePlugin();
dataPlanePlugin.initialize(batfish);
batfish.computeDataPlane(false);
SortedMap<String, RoutesByVrf> environmentRoutes = batfish.loadEnvironmentRoutingTables();
SortedMap<String, SortedMap<String, SortedSet<AbstractRoute>>> routes = dataPlanePlugin.getRoutes(batfish.loadDataPlane());
Prefix staticRoutePrefix = Prefix.parse("10.0.0.0/8");
SortedSet<AbstractRoute> r1BdpRoutes = routes.get("r1").get(DEFAULT_VRF_NAME);
AbstractRoute r1BdpRoute = r1BdpRoutes.stream().filter(r -> r.getNetwork().equals(staticRoutePrefix)).findFirst().get();
SortedSet<Route> r1EnvironmentRoutes = environmentRoutes.get("r1").get(DEFAULT_VRF_NAME);
Route r1EnvironmentRoute = r1EnvironmentRoutes.stream().filter(r -> r.getNetwork().equals(staticRoutePrefix)).findFirst().get();
assertThat(r1BdpRoute.getAdministrativeCost(), equalTo(r1EnvironmentRoute.getAdministrativeCost()));
assertThat(r1BdpRoute.getMetric(), equalTo(r1EnvironmentRoute.getMetric()));
assertThat(r1BdpRoute.getProtocol(), equalTo(r1EnvironmentRoute.getProtocol()));
}
use of org.batfish.datamodel.AbstractRoute in project batfish by batfish.
the class BdpDataPlanePluginTest method testBgpOscillationRecovery.
private void testBgpOscillationRecovery(MockBdpSettings bdpSettings) throws IOException {
String testrigName = "bgp-oscillation";
List<String> configurationNames = ImmutableList.of("r1", "r2", "r3");
Batfish batfish = BatfishTestUtils.getBatfishFromTestrigText(TestrigText.builder().setConfigurationText(TESTRIGS_PREFIX + testrigName, configurationNames).build(), _folder);
Settings settings = batfish.getSettings();
settings.setBdpDetail(bdpSettings.getBdpDetail());
settings.setBdpMaxOscillationRecoveryAttempts(bdpSettings.getBdpMaxOscillationRecoveryAttempts());
settings.setBdpMaxRecordedIterations(bdpSettings.getBdpMaxRecordedIterations());
settings.setBdpPrintAllIterations(bdpSettings.getBdpPrintAllIterations());
settings.setBdpPrintOscillatingIterations(bdpSettings.getBdpPrintOscillatingIterations());
settings.setBdpRecordAllIterations(bdpSettings.getBdpRecordAllIterations());
BdpDataPlanePlugin dataPlanePlugin = new BdpDataPlanePlugin();
dataPlanePlugin.initialize(batfish);
/*
* Data plane computation succeeds iff recovery is enabled. If disabled, an exception is thrown
* and should be expected by caller.
*/
batfish.computeDataPlane(false);
SortedMap<String, SortedMap<String, SortedSet<AbstractRoute>>> routes = dataPlanePlugin.getRoutes(batfish.loadDataPlane());
Prefix bgpPrefix = Prefix.parse("1.1.1.1/32");
SortedSet<AbstractRoute> r2Routes = routes.get("r2").get(DEFAULT_VRF_NAME);
SortedSet<AbstractRoute> r3Routes = routes.get("r3").get(DEFAULT_VRF_NAME);
Stream<AbstractRoute> r2MatchingRoutes = r2Routes.stream().filter(r -> r.getNetwork().equals(bgpPrefix));
Stream<AbstractRoute> r3MatchingRoutes = r3Routes.stream().filter(r -> r.getNetwork().equals(bgpPrefix));
AbstractRoute r2Route = r2Routes.stream().filter(r -> r.getNetwork().equals(bgpPrefix)).findAny().get();
AbstractRoute r3Route = r3Routes.stream().filter(r -> r.getNetwork().equals(bgpPrefix)).findAny().get();
String r2NextHop = r2Route.getNextHop();
String r3NextHop = r3Route.getNextHop();
int routesWithR1AsNextHop = 0;
if (r2Route.getNextHop().equals("r1")) {
routesWithR1AsNextHop++;
}
if (r3Route.getNextHop().equals("r1")) {
routesWithR1AsNextHop++;
}
boolean r2AsNextHop = r3NextHop.equals("r2");
boolean r3AsNextHop = r2NextHop.equals("r3");
/*
* Data plane computation should succeed as follows if recovery is enabled.
*/
assertThat(r2MatchingRoutes.count(), equalTo(1L));
assertThat(r3MatchingRoutes.count(), equalTo(1L));
assertThat(routesWithR1AsNextHop, equalTo(1));
assertTrue((r2AsNextHop && !r3AsNextHop) || (!r2AsNextHop && r3AsNextHop));
}
Aggregations