batfish / batfish

Batfish is a network configuration analysis tool that can find bugs and guarantee the correctness of (planned or current) network configurations. It enables network engineers to rapidly and safely evolve their network, without fear of outages or security breaches.

Home Page:http://www.batfish.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

_ebgpv4Rib and _bgpv4Rib of BgpRoutingProcess process two equal-cost EBGP routes differently when multipathIbgp enabled but multipathEbgp disabled

heroinedd opened this issue · comments

Hi, I notice a possible bug of Batfish. That is, when a BgpProcess is multipathIbgp enabled but multipathEbgp disabled (implying multipath enabled, since multipath = multipathIbgp || multipathEbgp), given two equal-cost EBGP routes LEARNED from neighbors, the corresponding BgpRoutingProcess's _ebgpv4Rib will insert only one of them into its RibTree since it is multipath disabled, while its _bgpv4Rib will insert both of the routes into its RibTree since it is multipath enabled.

You can use the following code to find the inconsistency:

    // set up
    NetworkFactory nf = new NetworkFactory();
    Configuration c =
        nf.configurationBuilder()
            .setConfigurationFormat(ConfigurationFormat.CISCO_IOS)
            .setHostname("c1")
            .build();
    Vrf vrf = nf.vrfBuilder().setOwner(c).setName(DEFAULT_VRF_NAME).build();
    BgpProcess bgpProcess = BgpProcess.testBgpProcess(Ip.ZERO);
    bgpProcess.setMultipathIbgp(true);
    bgpProcess.setMultipathEbgp(false);
    vrf.setBgpProcess(bgpProcess);
    Rib mainRib = new Rib();
    mainRib.mergeRouteGetDelta(
        new AnnotatedRoute<>(
            StaticRoute.testBuilder().setNetwork(Prefix.parse("70.0.0.0/24")).build(),
            DEFAULT_VRF_NAME));
    mainRib.mergeRouteGetDelta(
        new AnnotatedRoute<>(
            StaticRoute.testBuilder().setNetwork(Prefix.parse("60.0.0.0/24")).build(),
            DEFAULT_VRF_NAME));

    BgpRoutingProcess routingProcess =
        new BgpRoutingProcess(
            bgpProcess, c, DEFAULT_VRF_NAME, mainRib, BgpTopology.EMPTY, new PrefixTracer());

    // init two equal-cost EBGP routes learned from neighbors
    Prefix pfx = Prefix.parse("10.0.1.0/24");
    Bgpv4Route r1 =
        Bgpv4Route.testBuilder()
            .setNetwork(pfx)
            .setNextHopIp(Ip.parse("70.0.0.1"))
            .setOriginMechanism(OriginMechanism.LEARNED)
            .setReceivedFrom(ReceivedFromIp.of(Ip.parse("70.0.0.1")))
            .build();
    Bgpv4Route r2 =
        Bgpv4Route.testBuilder()
            .setNetwork(pfx)
            .setNextHopIp(Ip.parse("60.0.0.1"))
            .setOriginMechanism(OriginMechanism.LEARNED)
            .setReceivedFrom(ReceivedFromIp.of(Ip.parse("60.0.0.1")))
            .build();

    // insert r1 into _bgpv4Rib and _ebgpv4Rib, the test will success
    routingProcess._bgpv4Rib.mergeRouteGetDelta(r1);
    routingProcess._ebgpv4Rib.mergeRouteGetDelta(r1);
    assertEquals(routingProcess._bgpv4Rib.getRoutes(pfx), routingProcess._ebgpv4Rib.getRoutes(pfx));

    // insert r2 into _bgpv4Rib and _ebgpv4Rib, the test will fail
    routingProcess._bgpv4Rib.mergeRouteGetDelta(r2);
    routingProcess._ebgpv4Rib.mergeRouteGetDelta(r2);
    assertEquals(routingProcess._bgpv4Rib.getRoutes(pfx), routingProcess._ebgpv4Rib.getRoutes(pfx));