std::unique_ptr<UnicastRoute> makeUnicastRoute(std::string prefixStr, std::string nxtHop, AdminDistance distance=AdminDistance::MAX_ADMIN_DISTANCE) { std::vector<std::string> vec; folly::split("/", prefixStr, vec); EXPECT_EQ(2, vec.size()); auto nr = std::make_unique<UnicastRoute>(); nr->dest.ip = toBinaryAddress(IPAddress(vec.at(0))); nr->dest.prefixLength = folly::to<uint8_t>(vec.at(1)); nr->nextHopAddrs.push_back(toBinaryAddress(IPAddress(nxtHop))); nr->adminDistance = distance; nr->__isset.adminDistance = true; return nr; }
// Test for the ThriftHandler::syncFib method TEST(ThriftTest, syncFib) { RouterID rid = RouterID(0); // Create a config cfg::SwitchConfig config; config.vlans.resize(1); config.vlans[0].id = 1; config.interfaces.resize(1); config.interfaces[0].intfID = 1; config.interfaces[0].vlanID = 1; config.interfaces[0].routerID = 0; config.interfaces[0].__isset.mac = true; config.interfaces[0].mac = "00:02:00:00:00:01"; config.interfaces[0].ipAddresses.resize(3); config.interfaces[0].ipAddresses[0] = "10.0.0.1/24"; config.interfaces[0].ipAddresses[1] = "192.168.0.19/24"; config.interfaces[0].ipAddresses[2] = "2401:db00:2110:3001::0001/64"; // Create a mock SwSwitch using the config, and wrap it in a ThriftHandler auto handle = createTestHandle(&config); auto sw = handle->getSw(); sw->initialConfigApplied(std::chrono::steady_clock::now()); sw->fibSynced(); ThriftHandler handler(sw); // // Add a few BGP routes // auto cli1_nhop4 = "11.11.11.11"; auto cli1_nhop6 = "11:11::0"; auto cli2_nhop4 = "22.22.22.22"; auto cli2_nhop6 = "22:22::0"; auto cli3_nhop6 = "33:33::0"; auto cli1_nhop6b = "44:44::0"; // These routes will include nexthops from client 10 only auto prefixA4 = "7.1.0.0/16"; auto prefixA6 = "aaaa:1::0/64"; handler.addUnicastRoute(10, makeUnicastRoute(prefixA4, cli1_nhop4)); handler.addUnicastRoute(10, makeUnicastRoute(prefixA6, cli1_nhop6)); // This route will include nexthops from clients 10 and 20 auto prefixB4 = "7.2.0.0/16"; handler.addUnicastRoute(10, makeUnicastRoute(prefixB4, cli1_nhop4)); handler.addUnicastRoute(20, makeUnicastRoute(prefixB4, cli2_nhop4)); // This route will include nexthops from clients 10 and 20 and 30 auto prefixC6 = "aaaa:3::0/64"; handler.addUnicastRoute(10, makeUnicastRoute(prefixC6, cli1_nhop6)); handler.addUnicastRoute(20, makeUnicastRoute(prefixC6, cli2_nhop6)); handler.addUnicastRoute(30, makeUnicastRoute(prefixC6, cli3_nhop6)); // These routes will not be used until fibSync happens. auto prefixD4 = "7.4.0.0/16"; auto prefixD6 = "aaaa:4::0/64"; // // Test the state of things before calling syncFib // // Make sure all the static and link-local routes are there auto tables2 = sw->getState()->getRouteTables(); GET_ROUTE_V4(tables2, rid, "10.0.0.0/24"); GET_ROUTE_V4(tables2, rid, "192.168.0.0/24"); GET_ROUTE_V6(tables2, rid, "2401:db00:2110:3001::/64"); GET_ROUTE_V6(tables2, rid, "fe80::/64"); // Make sure the client 10&20&30 routes are there. GET_ROUTE_V4(tables2, rid, prefixA4); GET_ROUTE_V6(tables2, rid, prefixA6); GET_ROUTE_V4(tables2, rid, prefixB4); GET_ROUTE_V6(tables2, rid, prefixC6); // Make sure there are no more routes than the ones we just tested // plus the 1 default route that gets added automatically EXPECT_EQ(4 + 1, tables2->getRouteTable(rid)->getRibV4()->size()); EXPECT_EQ(4 + 1, tables2->getRouteTable(rid)->getRibV6()->size()); EXPECT_NO_ROUTE(tables2, rid, prefixD4); EXPECT_NO_ROUTE(tables2, rid, prefixD6); // // Now use syncFib to remove all the routes for client 10 and add // some new ones // Statics, link-locals, and clients 20 and 30 should remain unchanged. // auto newRoutes = std::make_unique<std::vector<UnicastRoute>>(); UnicastRoute nr1 = *makeUnicastRoute(prefixC6, cli1_nhop6b).get(); UnicastRoute nr2 = *makeUnicastRoute(prefixD6, cli1_nhop6b).get(); UnicastRoute nr3 = *makeUnicastRoute(prefixD4, cli1_nhop4).get(); newRoutes->push_back(nr1); newRoutes->push_back(nr2); newRoutes->push_back(nr3); handler.syncFib(10, std::move(newRoutes)); // // Test the state of things after syncFib // // Make sure all the static and link-local routes are still there auto tables3 = sw->getState()->getRouteTables(); GET_ROUTE_V4(tables3, rid, "10.0.0.0/24"); GET_ROUTE_V4(tables3, rid, "192.168.0.0/24"); GET_ROUTE_V6(tables3, rid, "2401:db00:2110:3001::/64"); GET_ROUTE_V6(tables3, rid, "fe80::/64"); // The prefixA* routes should have disappeared EXPECT_NO_ROUTE(tables3, rid, prefixA4); EXPECT_NO_ROUTE(tables3, rid, prefixA6); // The prefixB4 route should have client 20 only auto rt1 = GET_ROUTE_V4(tables3, rid, prefixB4); ASSERT_TRUE(rt1->getFields() ->nexthopsmulti.isSame(ClientID(20), RouteNextHopEntry(makeNextHops({cli2_nhop4})))); auto bestNextHops = rt1->getBestEntry().second->getNextHopSet(); EXPECT_EQ(IPAddress(cli2_nhop4), bestNextHops.begin()->addr()); // The prefixC6 route should have clients 20 & 30, and a new value for // client 10 auto rt2 = GET_ROUTE_V6(tables3, rid, prefixC6); ASSERT_TRUE(rt2->getFields() ->nexthopsmulti.isSame(ClientID(20), RouteNextHopEntry(makeNextHops({cli2_nhop6})))); ASSERT_TRUE(rt2->getFields() ->nexthopsmulti.isSame(ClientID(30), RouteNextHopEntry(makeNextHops({cli3_nhop6})))); ASSERT_TRUE(rt2->getFields() ->nexthopsmulti.isSame(ClientID(10), RouteNextHopEntry(makeNextHops({cli1_nhop6b})))); // The prefixD4 and prefixD6 routes should have been created GET_ROUTE_V4(tables3, rid, prefixD4); GET_ROUTE_V6(tables3, rid, prefixD6); // Make sure there are no more routes (ie. the old ones were deleted) // + the one that gets added by default EXPECT_EQ(4 + 1, tables3->getRouteTable(rid)->getRibV4()->size()); EXPECT_EQ(4 + 1, tables3->getRouteTable(rid)->getRibV6()->size()); }