//! A peer that sends us a table while not reading what we send it must //! not stop us reading it: two routers sending each other their tables at //! once would otherwise each wait on the other for ever. use std::net::Ipv4Addr; use std::sync::Arc; use std::time::Duration; use bgp_integration_tests::announcement::Announcement; use bgp_integration_tests::prefix; use bgp_integration_tests::test_peer::TestPeer; use bgp_integration_tests::test_server::TestServer; use bgp_server::policy::ExportPolicy; use eyre::Result; const LOCAL_ASN: u32 = 64601; const ROUTES: u32 = 100_000; fn nth(n: u32) -> bgp_primitives::ip_prefix::IpPrefix { let [a, b, c, _] = (0x0a00_0000u32 + n * 256).to_be_bytes(); prefix(&format!("{a}.{b}.{c}.0/24")) } #[tokio::test] async fn a_peer_that_does_not_read_is_still_read() -> Result<()> { let server = TestServer::start_with(LOCAL_ASN, |c| { c.export = Arc::new(ExportPolicy { learned_routes: true, all_paths: false, ..ExportPolicy::default() }); }) .await?; // One peer's table, for the server to pass on. let mut first = server .established(64701, Ipv4Addr::new(10, 0, 0, 1)) .await?; // A route to an UPDATE, each with attributes of its own, as a real // table has them: passing it on is then megabytes, not a few hundred // UPDATEs that the socket buffers would take whole. for i in 0..ROUTES { first .announce( Announcement::of([nth(i).into()], &[64701, 64510]) .with_communities(&[((i >> 16) as u16 + 1, i as u16)]), ) .await?; } server.wait_for_routes(ROUTES as usize).await?; // A second peer, which the server starts sending that table to as // soon as it is up, sends a table of its own and reads nothing back: // the server's writes to it fill its socket and stop. The server has // to go on reading it all the same. The peer's receive buffer is // small, as a real link's window would be, so that this happens with // the first few hundred kilobytes and not after the loopback's // megabytes. let socket = tokio::net::TcpSocket::new_v4()?; socket.set_recv_buffer_size(16 * 1024)?; let stream = socket.connect(server.addr).await?; let mut second = TestPeer::from_stream(stream); second .handshake(64702, Ipv4Addr::new(10, 0, 0, 2), 90) .await?; server.wait_for_sessions(2).await?; // Sent over a couple of seconds, so that the server's export to the // peer is well under way while the peer is still sending. let sending = async { for start in (0..ROUTES).step_by(100) { second .announce(Announcement::of( (start..start + 100).map(|i| nth(i).into()), &[64702, 64510], )) .await?; if start % 2000 == 0 { tokio::time::sleep(Duration::from_millis(40)).await; } } Ok::<_, eyre::Report>(()) }; tokio::time::timeout(Duration::from_secs(30), sending) .await .expect("the server reads the peer's table though the peer reads nothing")?; tokio::time::timeout( Duration::from_secs(30), server.wait_for_routes(2 * ROUTES as usize), ) .await .expect("every route is in the table")?; Ok(()) }