Refactored client binary.
This commit is contained in:
@ -1,50 +0,0 @@
|
|||||||
[package]
|
|
||||||
authors = ["Rayhaan Jaufeerally <rayhaan@rayhaan.ch>"]
|
|
||||||
edition = "2021"
|
|
||||||
name = "bgpd"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "bgp_server"
|
|
||||||
path = "src/main.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "route_client"
|
|
||||||
path = "src/route_client/main.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "streamer_cli"
|
|
||||||
path = "src/streamer_cli/main.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
anyhow = "1.0.71"
|
|
||||||
async-trait = "0.1.57"
|
|
||||||
byteorder = "1.4.3"
|
|
||||||
bytes = "1.*"
|
|
||||||
clap = { version = "3.2.8", features = ["cargo", "derive"] }
|
|
||||||
futures = "0.3"
|
|
||||||
ip_network_table-deps-treebitmap = "0.5.0"
|
|
||||||
ipnet = "2.3.0"
|
|
||||||
libc = "0.2.126"
|
|
||||||
log = "0.4"
|
|
||||||
netlink = "0.1.1"
|
|
||||||
netlink-packet-route = "0.19.0"
|
|
||||||
netlink-packet-utils = "0.5.2"
|
|
||||||
nom = "7.1"
|
|
||||||
prost = "0.8"
|
|
||||||
rtnetlink = "0.14.1"
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0.64"
|
|
||||||
signal-hook = { version = "0.3.17", features = ["extended-siginfo"] }
|
|
||||||
signal-hook-tokio = "0.3.0"
|
|
||||||
stderrlog = "0.5.1"
|
|
||||||
tokio = { version = "1.13.0", features = ["full"] }
|
|
||||||
tokio-stream = { version = "0.1.7", features = ["net"] }
|
|
||||||
tokio-util = { version = "0.6.7", features = ["codec"] }
|
|
||||||
tonic = { version = "0.5", features = ["compression"] }
|
|
||||||
tracing = "0.1"
|
|
||||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
|
||||||
warp = "0.3.5"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tonic-build = { version = "0.5.1", features = ["compression", "prost"] }
|
|
||||||
@ -1 +0,0 @@
|
|||||||
edition = "2018"
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
pub mod bgp_packet;
|
|
||||||
pub mod route_client;
|
|
||||||
pub mod server;
|
|
||||||
30
bin/Cargo.toml
Normal file
30
bin/Cargo.toml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
[package]
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
name = "bgpd_bin"
|
||||||
|
repository.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bgp_server.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
eyre.workspace = true
|
||||||
|
libc.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
route_client.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
signal-hook = { version = "0.3.17", features = ["extended-siginfo"] }
|
||||||
|
signal-hook-tokio = "0.3.0"
|
||||||
|
tokio.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "bgp_server"
|
||||||
|
path = "src/bgp_server/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "client"
|
||||||
|
path = "src/client/main.rs"
|
||||||
@ -12,8 +12,8 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use bgpd::server::bgp_server::Server;
|
use bgp_server::bgp_server::Server;
|
||||||
use bgpd::server::config::ServerConfig;
|
use bgp_server::config::ServerConfig;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use core::sync::atomic::AtomicBool;
|
use core::sync::atomic::AtomicBool;
|
||||||
use libc::SIGUSR1;
|
use libc::SIGUSR1;
|
||||||
77
bin/src/client/main.rs
Normal file
77
bin/src/client/main.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use clap::Parser;
|
||||||
|
use eyre::Result;
|
||||||
|
use tracing::instrument::WithSubscriber;
|
||||||
|
use tracing::log::LevelFilter;
|
||||||
|
use tracing::{info, warn};
|
||||||
|
use tracing_subscriber::filter;
|
||||||
|
use tracing_subscriber::prelude::*;
|
||||||
|
|
||||||
|
use route_client::netlink::NetlinkConnector;
|
||||||
|
use route_client::{run_connector_v4, run_connector_v6};
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[clap(
|
||||||
|
author = "Rayhaan Jaufeerally <rayhaan@rayhaan.ch>",
|
||||||
|
version = "0.1",
|
||||||
|
about = "Installs routes from a BGP speaker via streaming RPC to the forwarding plane"
|
||||||
|
)]
|
||||||
|
struct Cli {
|
||||||
|
#[clap(long = "route_server")]
|
||||||
|
route_server: String,
|
||||||
|
#[clap(long = "rt_table")]
|
||||||
|
rt_table: Option<u32>,
|
||||||
|
dry_run: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
let args = Cli::parse();
|
||||||
|
|
||||||
|
tracing_subscriber::fmt().pretty().init();
|
||||||
|
|
||||||
|
info!("Starting route client");
|
||||||
|
|
||||||
|
let rt_table = match args.rt_table {
|
||||||
|
Some(table) => table,
|
||||||
|
None => 201,
|
||||||
|
};
|
||||||
|
|
||||||
|
let v4_joinhandle = {
|
||||||
|
let server_addr = args.route_server.clone();
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
run_connector_v4::<NetlinkConnector>(
|
||||||
|
server_addr.clone(),
|
||||||
|
rt_table,
|
||||||
|
args.dry_run,
|
||||||
|
NetlinkConnector::new(Some(rt_table)).await.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let v6_joinhandle = {
|
||||||
|
let server_addr = args.route_server.clone();
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
run_connector_v6::<NetlinkConnector>(
|
||||||
|
server_addr,
|
||||||
|
rt_table,
|
||||||
|
args.dry_run,
|
||||||
|
NetlinkConnector::new(Some(rt_table)).await.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = v4_joinhandle => {
|
||||||
|
warn!("Unexpected exit of IPv4 connector");
|
||||||
|
},
|
||||||
|
_ = v6_joinhandle => {
|
||||||
|
warn!("Unexpected exit of IPv6 connector");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -31,7 +31,7 @@ extern crate clap;
|
|||||||
#[clap(
|
#[clap(
|
||||||
author = "Rayhaan Jaufeerally <rayhaan@rayhaan.ch>",
|
author = "Rayhaan Jaufeerally <rayhaan@rayhaan.ch>",
|
||||||
version = "0.1",
|
version = "0.1",
|
||||||
about = "A program to install routes from BGP into the Linux control plane"
|
about = "A utility for dumping routes from the bgp_server."
|
||||||
)]
|
)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
server_address: String,
|
server_address: String,
|
||||||
19
crates/bgp_packet/Cargo.toml
Normal file
19
crates/bgp_packet/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "bgp_packet"
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1.4.3"
|
||||||
|
bytes.workspace = true
|
||||||
|
nom = "7.1"
|
||||||
|
serde.workspace = true
|
||||||
|
tokio-util = { version = "0.7.10", features = ["codec"] }
|
||||||
@ -12,12 +12,12 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::constants::AddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::constants::SubsequentAddressFamilyIdentifier;
|
use crate::constants::SubsequentAddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::traits::BGPParserError;
|
use crate::traits::BGPParserError;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
use nom::number::complete::{be_u16, be_u8};
|
use nom::number::complete::{be_u16, be_u8};
|
||||||
use nom::Err::Failure;
|
use nom::Err::Failure;
|
||||||
@ -694,9 +694,9 @@ mod tests {
|
|||||||
use super::ExtendedNextHopEncodingCapability;
|
use super::ExtendedNextHopEncodingCapability;
|
||||||
use super::FourByteASNCapability;
|
use super::FourByteASNCapability;
|
||||||
use super::OpenOption;
|
use super::OpenOption;
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier::Ipv6;
|
use crate::constants::AddressFamilyIdentifier::Ipv6;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_four_byte_asn_capability() {
|
fn test_four_byte_asn_capability() {
|
||||||
@ -12,15 +12,15 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::capabilities::OpenOption;
|
use crate::capabilities::OpenOption;
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::constants::AddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::constants::SubsequentAddressFamilyIdentifier;
|
use crate::constants::SubsequentAddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use crate::nlri::NLRI;
|
||||||
use crate::bgp_packet::path_attributes::PathAttribute;
|
use crate::path_attributes::PathAttribute;
|
||||||
use crate::bgp_packet::traits::BGPParserError;
|
use crate::traits::BGPParserError;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
use byteorder::{ByteOrder, NetworkEndian};
|
use byteorder::{ByteOrder, NetworkEndian};
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
@ -545,11 +545,11 @@ impl Display for UpdateMessage {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::BGPMessage;
|
use super::BGPMessage;
|
||||||
use super::Codec;
|
use super::Codec;
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier::Ipv6;
|
use crate::constants::AddressFamilyIdentifier::Ipv6;
|
||||||
use crate::bgp_packet::messages::AddressFamilyIdentifier::Ipv4;
|
use crate::messages::AddressFamilyIdentifier::Ipv4;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
|
|
||||||
use bytes::BufMut;
|
use bytes::BufMut;
|
||||||
use tokio_util::codec::{Decoder, Encoder};
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
@ -12,11 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::constants::AddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::traits::BGPParserError;
|
use crate::traits::BGPParserError;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
use nom::bytes::complete::take;
|
use nom::bytes::complete::take;
|
||||||
use nom::number::complete::be_u8;
|
use nom::number::complete::be_u8;
|
||||||
use nom::Err::Failure;
|
use nom::Err::Failure;
|
||||||
@ -254,10 +254,10 @@ mod tests {
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use super::NLRI;
|
use super::NLRI;
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier::{Ipv4, Ipv6};
|
use crate::constants::AddressFamilyIdentifier::{Ipv4, Ipv6};
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_nlri_v6() {
|
fn test_basic_nlri_v6() {
|
||||||
@ -12,13 +12,13 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::constants::AddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::constants::SubsequentAddressFamilyIdentifier;
|
use crate::constants::SubsequentAddressFamilyIdentifier;
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use crate::nlri::NLRI;
|
||||||
use crate::bgp_packet::traits::BGPParserError;
|
use crate::traits::BGPParserError;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
use byteorder::ByteOrder;
|
use byteorder::ByteOrder;
|
||||||
use byteorder::NetworkEndian;
|
use byteorder::NetworkEndian;
|
||||||
use nom::number::complete::{be_u16, be_u32, be_u8};
|
use nom::number::complete::{be_u16, be_u32, be_u8};
|
||||||
@ -976,11 +976,11 @@ impl fmt::Display for MPUnreachNLRIPathAttribute {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier::Ipv6;
|
use crate::constants::AddressFamilyIdentifier::Ipv6;
|
||||||
use crate::bgp_packet::constants::SubsequentAddressFamilyIdentifier::Unicast;
|
use crate::constants::SubsequentAddressFamilyIdentifier::Unicast;
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use crate::traits::ParserContext;
|
||||||
use crate::bgp_packet::traits::ReadablePacket;
|
use crate::traits::ReadablePacket;
|
||||||
use crate::bgp_packet::traits::WritablePacket;
|
use crate::traits::WritablePacket;
|
||||||
|
|
||||||
use super::ASPathAttribute;
|
use super::ASPathAttribute;
|
||||||
use super::CommunitiesPathAttribute;
|
use super::CommunitiesPathAttribute;
|
||||||
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
//! Implements high level abstractions for use in the BGP parser.
|
//! Implements high level abstractions for use in the BGP parser.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::constants::AddressFamilyIdentifier;
|
||||||
use nom::error::ErrorKind;
|
use nom::error::ErrorKind;
|
||||||
use nom::error::ParseError;
|
use nom::error::ParseError;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
37
crates/route_client/Cargo.toml
Normal file
37
crates/route_client/Cargo.toml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[package]
|
||||||
|
name = "route_client"
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-trait.workspace = true
|
||||||
|
bgp_packet.workspace = true
|
||||||
|
byteorder = "1.4.3"
|
||||||
|
bytes.workspace = true
|
||||||
|
eyre.workspace = true
|
||||||
|
futures.workspace = true
|
||||||
|
ip_network_table-deps-treebitmap.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
netlink-packet-route.workspace = true
|
||||||
|
netlink-packet-utils.workspace = true
|
||||||
|
nom = "7.1"
|
||||||
|
prost.workspace = true
|
||||||
|
rtnetlink.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
tokio-stream = "0.1.14"
|
||||||
|
tokio-util = { version = "0.7.10", features = ["codec"] }
|
||||||
|
tokio.workspace = true
|
||||||
|
tonic.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
warp.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tonic-build = { version = "0.5.1", features = ["compression", "prost"] }
|
||||||
@ -12,9 +12,6 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
|
||||||
use crate::route_client::southbound_interface::SouthboundInterface;
|
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
use ip_network_table_deps_treebitmap::address::Address;
|
use ip_network_table_deps_treebitmap::address::Address;
|
||||||
use ip_network_table_deps_treebitmap::IpLookupTable;
|
use ip_network_table_deps_treebitmap::IpLookupTable;
|
||||||
@ -25,6 +22,11 @@ use std::net::{IpAddr, Ipv4Addr};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
|
|
||||||
|
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||||
|
use bgp_packet::nlri::NLRI;
|
||||||
|
|
||||||
|
use crate::southbound_interface::SouthboundInterface;
|
||||||
|
|
||||||
/// fib_state implements the logic to maintain forwarding routes in the FIB.
|
/// fib_state implements the logic to maintain forwarding routes in the FIB.
|
||||||
/// This for now means the Linux Kernel via Netlink, but in the future can
|
/// This for now means the Linux Kernel via Netlink, but in the future can
|
||||||
/// be extended to include other targets such as OpenFlow or even program
|
/// be extended to include other targets such as OpenFlow or even program
|
||||||
@ -12,9 +12,10 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use bgpd::route_client::netlink::NetlinkConnector;
|
pub mod fib_state;
|
||||||
use bgpd::route_client::southbound_interface::SouthboundInterface;
|
pub mod netlink;
|
||||||
use clap::Parser;
|
pub mod southbound_interface;
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@ -23,27 +24,28 @@ use std::net::Ipv4Addr;
|
|||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tonic::transport::Uri;
|
|
||||||
|
|
||||||
use bgpd::bgp_packet::constants::AddressFamilyIdentifier;
|
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||||
use bgpd::bgp_packet::nlri::NLRI;
|
use bgp_packet::nlri::NLRI;
|
||||||
use bgpd::route_client::fib_state::FibState;
|
|
||||||
|
|
||||||
|
use eyre::{anyhow, Result};
|
||||||
use ip_network_table_deps_treebitmap::IpLookupTable;
|
use ip_network_table_deps_treebitmap::IpLookupTable;
|
||||||
use tonic::transport::Endpoint;
|
use tonic::transport::Endpoint;
|
||||||
|
use tonic::transport::Uri;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use crate::fib_state::FibState;
|
||||||
|
use crate::netlink::NetlinkConnector;
|
||||||
use crate::proto::route_service_client::RouteServiceClient;
|
use crate::proto::route_service_client::RouteServiceClient;
|
||||||
|
use crate::southbound_interface::SouthboundInterface;
|
||||||
|
|
||||||
pub mod proto {
|
pub mod proto {
|
||||||
tonic::include_proto!("bgpd.grpc");
|
tonic::include_proto!("bgpd.grpc");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vec_to_array<T, const N: usize>(v: Vec<T>) -> Result<[T; N], anyhow::Error> {
|
fn vec_to_array<T, const N: usize>(v: Vec<T>) -> Result<[T; N]> {
|
||||||
v.try_into()
|
v.try_into()
|
||||||
.map_err(|_| anyhow::Error::msg("Wrong size of Vec".to_string()))
|
.map_err(|_| eyre::Error::msg("Wrong size of Vec".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Temporary hack to select the route to install to the FIB.
|
/// Temporary hack to select the route to install to the FIB.
|
||||||
@ -62,12 +64,12 @@ fn select_best_route(ps: &proto::PathSet) -> Option<proto::Path> {
|
|||||||
selected
|
selected
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_connector_v4<S: SouthboundInterface>(
|
pub async fn run_connector_v4<S: SouthboundInterface>(
|
||||||
route_server: String,
|
route_server: String,
|
||||||
rt_table: u32,
|
rt_table: u32,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
southbound: S,
|
southbound: S,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> Result<()> {
|
||||||
// Create netlink socket.
|
// Create netlink socket.
|
||||||
let mut fib_state = FibState::<Ipv4Addr, S> {
|
let mut fib_state = FibState::<Ipv4Addr, S> {
|
||||||
fib: IpLookupTable::new(),
|
fib: IpLookupTable::new(),
|
||||||
@ -132,7 +134,7 @@ async fn run_connector_v4<S: SouthboundInterface>(
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn run_connector_v6<S: SouthboundInterface>(
|
pub async fn run_connector_v6<S: SouthboundInterface>(
|
||||||
route_server: String,
|
route_server: String,
|
||||||
rt_table: u32,
|
rt_table: u32,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
@ -201,72 +203,3 @@ async fn run_connector_v6<S: SouthboundInterface>(
|
|||||||
|
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[clap(
|
|
||||||
author = "Rayhaan Jaufeerally <rayhaan@rayhaan.ch>",
|
|
||||||
version = "0.1",
|
|
||||||
about = "Installs routes from a BGP speaker via streaming RPC to the forwarding plane"
|
|
||||||
)]
|
|
||||||
struct Cli {
|
|
||||||
#[clap(long = "route_server")]
|
|
||||||
route_server: String,
|
|
||||||
#[clap(long = "rt_table")]
|
|
||||||
rt_table: Option<u32>,
|
|
||||||
dry_run: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<()> {
|
|
||||||
let args = Cli::parse();
|
|
||||||
|
|
||||||
let _init_log = stderrlog::new()
|
|
||||||
.verbosity(2) // Shows info level.
|
|
||||||
.show_module_names(true)
|
|
||||||
.init();
|
|
||||||
info!("Starting route client");
|
|
||||||
|
|
||||||
let rt_table = match args.rt_table {
|
|
||||||
Some(table) => table,
|
|
||||||
None => 201,
|
|
||||||
};
|
|
||||||
|
|
||||||
let v4_joinhandle = {
|
|
||||||
let server_addr = args.route_server.clone();
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
run_connector_v4::<NetlinkConnector>(
|
|
||||||
server_addr.clone(),
|
|
||||||
rt_table,
|
|
||||||
args.dry_run,
|
|
||||||
NetlinkConnector::new(Some(rt_table)).await.unwrap(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let v6_joinhandle = {
|
|
||||||
let server_addr = args.route_server.clone();
|
|
||||||
tokio::task::spawn(async move {
|
|
||||||
run_connector_v6::<NetlinkConnector>(
|
|
||||||
server_addr,
|
|
||||||
rt_table,
|
|
||||||
args.dry_run,
|
|
||||||
NetlinkConnector::new(Some(rt_table)).await.unwrap(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
_ = v4_joinhandle => {
|
|
||||||
warn!("Unexpected exit of IPv4 connector");
|
|
||||||
},
|
|
||||||
_ = v6_joinhandle => {
|
|
||||||
warn!("Unexpected exit of IPv6 connector");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::bgp_packet::{constants::AddressFamilyIdentifier, nlri::NLRI};
|
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use bgp_packet::{constants::AddressFamilyIdentifier, nlri::NLRI};
|
||||||
|
use eyre::{eyre, Result};
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use netlink_packet_route::route::RouteAddress;
|
use netlink_packet_route::route::RouteAddress;
|
||||||
use netlink_packet_route::route::RouteAttribute;
|
use netlink_packet_route::route::RouteAttribute;
|
||||||
@ -38,7 +38,7 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
let addr: Ipv6Addr = match prefix.try_into()? {
|
let addr: Ipv6Addr = match prefix.try_into()? {
|
||||||
IpAddr::V6(addr) => addr,
|
IpAddr::V6(addr) => addr,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(anyhow::Error::from(std::io::Error::new(
|
return Err(eyre::Error::from(std::io::Error::new(
|
||||||
ErrorKind::InvalidInput,
|
ErrorKind::InvalidInput,
|
||||||
"Got non-IPv6 address from NLRI",
|
"Got non-IPv6 address from NLRI",
|
||||||
)))
|
)))
|
||||||
@ -47,7 +47,7 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
let gw_addr: Ipv6Addr = match nexthop.clone().try_into()? {
|
let gw_addr: Ipv6Addr = match nexthop.clone().try_into()? {
|
||||||
IpAddr::V6(addr) => addr,
|
IpAddr::V6(addr) => addr,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(anyhow::Error::from(std::io::Error::new(
|
return Err(eyre::Error::from(std::io::Error::new(
|
||||||
ErrorKind::InvalidInput,
|
ErrorKind::InvalidInput,
|
||||||
"Got non-IPv6 gateway for IPv6 NLRI",
|
"Got non-IPv6 gateway for IPv6 NLRI",
|
||||||
)))
|
)))
|
||||||
@ -61,14 +61,14 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
if let Some(table_id) = self.table {
|
if let Some(table_id) = self.table {
|
||||||
mutation = mutation.table(table_id.try_into().unwrap());
|
mutation = mutation.table(table_id.try_into().unwrap());
|
||||||
}
|
}
|
||||||
mutation.execute().await.map_err(|e| anyhow::Error::from(e))
|
mutation.execute().await.map_err(|e| eyre::Error::from(e))
|
||||||
}
|
}
|
||||||
AddressFamilyIdentifier::Ipv4 => {
|
AddressFamilyIdentifier::Ipv4 => {
|
||||||
let prefix_len = prefix.prefixlen;
|
let prefix_len = prefix.prefixlen;
|
||||||
let addr: Ipv4Addr = match prefix.clone().try_into()? {
|
let addr: Ipv4Addr = match prefix.clone().try_into()? {
|
||||||
IpAddr::V4(addr) => addr,
|
IpAddr::V4(addr) => addr,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(anyhow::Error::from(std::io::Error::new(
|
return Err(eyre::Error::from(std::io::Error::new(
|
||||||
ErrorKind::InvalidInput,
|
ErrorKind::InvalidInput,
|
||||||
"Got non-IPv4 address from NLRI",
|
"Got non-IPv4 address from NLRI",
|
||||||
)))
|
)))
|
||||||
@ -77,7 +77,7 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
let gw_addr = match nexthop.clone().try_into()? {
|
let gw_addr = match nexthop.clone().try_into()? {
|
||||||
IpAddr::V4(addr) => addr,
|
IpAddr::V4(addr) => addr,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(anyhow::Error::from(std::io::Error::new(
|
return Err(eyre::Error::from(std::io::Error::new(
|
||||||
ErrorKind::InvalidInput,
|
ErrorKind::InvalidInput,
|
||||||
"Got non-IPv4 gateway for IPv4 NLRI",
|
"Got non-IPv4 gateway for IPv4 NLRI",
|
||||||
)))
|
)))
|
||||||
@ -91,7 +91,7 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
if let Some(table_id) = self.table {
|
if let Some(table_id) = self.table {
|
||||||
mutation = mutation.table(table_id.try_into().unwrap());
|
mutation = mutation.table(table_id.try_into().unwrap());
|
||||||
}
|
}
|
||||||
mutation.execute().await.map_err(|e| anyhow::Error::from(e))
|
mutation.execute().await.map_err(|e| eyre::Error::from(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,10 +100,10 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
let rt_handle = self.handle.route();
|
let rt_handle = self.handle.route();
|
||||||
let destination = match prefix.afi {
|
let destination = match prefix.afi {
|
||||||
AddressFamilyIdentifier::Ipv4 => {
|
AddressFamilyIdentifier::Ipv4 => {
|
||||||
RouteAddress::Inet(prefix.clone().try_into().map_err(|e: String| anyhow!(e))?)
|
RouteAddress::Inet(prefix.clone().try_into().map_err(|e: String| eyre!(e))?)
|
||||||
}
|
}
|
||||||
AddressFamilyIdentifier::Ipv6 => {
|
AddressFamilyIdentifier::Ipv6 => {
|
||||||
RouteAddress::Inet6(prefix.clone().try_into().map_err(|e: String| anyhow!(e))?)
|
RouteAddress::Inet6(prefix.clone().try_into().map_err(|e: String| eyre!(e))?)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let nexthop = match nexthop {
|
let nexthop = match nexthop {
|
||||||
@ -131,7 +131,7 @@ impl SouthboundInterface for NetlinkConnector {
|
|||||||
.del(rt_msg)
|
.del(rt_msg)
|
||||||
.execute()
|
.execute()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| anyhow::Error::from(e))
|
.map_err(|e| eyre::Error::from(e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,11 +14,12 @@
|
|||||||
|
|
||||||
use std::{collections::HashMap, net::IpAddr};
|
use std::{collections::HashMap, net::IpAddr};
|
||||||
|
|
||||||
use crate::bgp_packet::{constants::AddressFamilyIdentifier, nlri::NLRI};
|
|
||||||
use anyhow::{anyhow, Result};
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
use eyre::{eyre, Result};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
|
use bgp_packet::{constants::AddressFamilyIdentifier, nlri::NLRI};
|
||||||
|
|
||||||
/// SouthboundInterface provides a uniform API to network forwarding elements
|
/// SouthboundInterface provides a uniform API to network forwarding elements
|
||||||
/// These are devices or targets that perform packet routing and are the end
|
/// These are devices or targets that perform packet routing and are the end
|
||||||
/// consumers of packet routing data.
|
/// consumers of packet routing data.
|
||||||
@ -60,7 +61,7 @@ impl SouthboundInterface for DummyVerifier {
|
|||||||
// Check that the route is not already present.
|
// Check that the route is not already present.
|
||||||
match self.route_state.get(&prefix) {
|
match self.route_state.get(&prefix) {
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
return Err(anyhow!(
|
return Err(eyre!(
|
||||||
"Prefix {} with nexthop {} already contained in route_state! when trying to add {} -> {}",
|
"Prefix {} with nexthop {} already contained in route_state! when trying to add {} -> {}",
|
||||||
prefix, value, prefix, nexthop,
|
prefix, value, prefix, nexthop,
|
||||||
));
|
));
|
||||||
@ -80,7 +81,7 @@ impl SouthboundInterface for DummyVerifier {
|
|||||||
match self.route_state.remove(&prefix) {
|
match self.route_state.remove(&prefix) {
|
||||||
Some(entry) => {
|
Some(entry) => {
|
||||||
if entry != nexthop {
|
if entry != nexthop {
|
||||||
return Err(anyhow!(
|
return Err(eyre!(
|
||||||
"Removed entry's nexthop did not match: {} vs requested {}",
|
"Removed entry's nexthop did not match: {} vs requested {}",
|
||||||
entry,
|
entry,
|
||||||
nexthop
|
nexthop
|
||||||
@ -88,7 +89,7 @@ impl SouthboundInterface for DummyVerifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(anyhow!(
|
return Err(eyre!(
|
||||||
"Requested removal of route {} that was not in route_state",
|
"Requested removal of route {} that was not in route_state",
|
||||||
prefix
|
prefix
|
||||||
));
|
));
|
||||||
31
crates/server/Cargo.toml
Normal file
31
crates/server/Cargo.toml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[package]
|
||||||
|
name = "bgp_server"
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bgp_packet.workspace = true
|
||||||
|
byteorder = "1.4.3"
|
||||||
|
bytes.workspace = true
|
||||||
|
ip_network_table-deps-treebitmap.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
nom = "7.1"
|
||||||
|
prost.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
tokio-stream = "0.1.14"
|
||||||
|
tokio-util = { version = "0.7.10", features = ["codec"] }
|
||||||
|
tokio.workspace = true
|
||||||
|
tonic.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
warp.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
tonic-build = { version = "0.5.1", features = ["compression", "prost"] }
|
||||||
@ -12,6 +12,8 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
pub mod fib_state;
|
fn main() {
|
||||||
pub mod netlink;
|
tonic_build::configure()
|
||||||
pub mod southbound_interface;
|
.compile(&["proto/route_service.proto"], &["proto"])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
83
crates/server/proto/route_service.proto
Normal file
83
crates/server/proto/route_service.proto
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2021 Rayhaan Jaufeerally.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package bgpd.grpc;
|
||||||
|
|
||||||
|
enum AddressFamily {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
IPv4 = 1;
|
||||||
|
IPv6 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Prefix {
|
||||||
|
bytes ip_prefix = 1;
|
||||||
|
int32 prefix_len = 2;
|
||||||
|
AddressFamily address_family = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path represents the metadata associated with the route to a particular
|
||||||
|
// prefix.
|
||||||
|
message Path {
|
||||||
|
bytes nexthop = 1;
|
||||||
|
string peer_name = 2;
|
||||||
|
uint32 local_pref = 3;
|
||||||
|
uint32 med = 4;
|
||||||
|
repeated uint32 as_path = 5;
|
||||||
|
// TODO: Path attributes. Not yet supported because we need to generate proto
|
||||||
|
// definitions for all of them.
|
||||||
|
}
|
||||||
|
|
||||||
|
message PathSet {
|
||||||
|
uint64 epoch = 1;
|
||||||
|
Prefix prefix = 2;
|
||||||
|
repeated Path paths = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StreamPathsRequest { AddressFamily address_family = 1; }
|
||||||
|
|
||||||
|
message DumpPathsRequest { AddressFamily address_family = 1; };
|
||||||
|
|
||||||
|
message DumpPathsResponse {
|
||||||
|
uint64 epoch = 1;
|
||||||
|
repeated PathSet path_sets = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
service RouteService {
|
||||||
|
// DumpPaths returns all the paths currently in the RIB.
|
||||||
|
rpc DumpPaths(DumpPathsRequest) returns (DumpPathsResponse);
|
||||||
|
// StreamPaths dumps the existing routes and starts streaming updates to the
|
||||||
|
// RIB.
|
||||||
|
rpc StreamPaths(StreamPathsRequest) returns (stream PathSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
message PeerStatusRequest {}
|
||||||
|
|
||||||
|
message PeerStatus {
|
||||||
|
string peer_name = 1;
|
||||||
|
string state = 2;
|
||||||
|
uint64 session_established_time = 3;
|
||||||
|
uint64 last_messaage_time = 4;
|
||||||
|
uint64 route_updates_in = 5;
|
||||||
|
uint64 route_updates_out = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PeerStatusResponse { repeated PeerStatus peer_status = 1; }
|
||||||
|
|
||||||
|
// BGPServerAdminService implements an administrative interface to
|
||||||
|
// view the status and control the operation of this BGP server.
|
||||||
|
service BGPServerAdminService {
|
||||||
|
rpc PeerStatus(PeerStatusRequest) returns (PeerStatusResponse);
|
||||||
|
}
|
||||||
@ -12,16 +12,16 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::config::PeerConfig;
|
||||||
use crate::server::config::PeerConfig;
|
use crate::config::ServerConfig;
|
||||||
use crate::server::config::ServerConfig;
|
use crate::peer::PeerCommands;
|
||||||
use crate::server::peer::PeerCommands;
|
use crate::peer::PeerStateMachine;
|
||||||
use crate::server::peer::PeerStateMachine;
|
use crate::rib_manager::RibManager;
|
||||||
use crate::server::rib_manager::RibManager;
|
use crate::rib_manager::RibSnapshot;
|
||||||
use crate::server::rib_manager::RibSnapshot;
|
use crate::rib_manager::RouteManagerCommands;
|
||||||
use crate::server::rib_manager::RouteManagerCommands;
|
use crate::route_server;
|
||||||
use crate::server::route_server;
|
use crate::route_server::route_server::route_service_server::RouteServiceServer;
|
||||||
use crate::server::route_server::route_server::route_service_server::RouteServiceServer;
|
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::{AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier};
|
use bgp_packet::constants::{AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||||
|
|
||||||
@ -12,8 +12,8 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use bgp_packet::nlri::NLRI;
|
||||||
use crate::bgp_packet::path_attributes::PathAttribute;
|
use bgp_packet::path_attributes::PathAttribute;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
/// RouteInfo encapsulates information received about a particular BGP route.
|
/// RouteInfo encapsulates information received about a particular BGP route.
|
||||||
@ -12,39 +12,37 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::capabilities::{
|
use crate::config::PrefixAnnouncement;
|
||||||
|
use crate::config::{PeerConfig, ServerConfig};
|
||||||
|
use crate::data_structures::RouteAnnounce;
|
||||||
|
use crate::data_structures::RouteWithdraw;
|
||||||
|
use crate::data_structures::{RouteInfo, RouteUpdate};
|
||||||
|
use crate::rib_manager::RouteManagerCommands;
|
||||||
|
use bgp_packet::capabilities::{
|
||||||
BGPCapability, BGPCapabilityTypeValues, BGPCapabilityValue, BGPOpenOptionTypeValues,
|
BGPCapability, BGPCapabilityTypeValues, BGPCapabilityValue, BGPOpenOptionTypeValues,
|
||||||
FourByteASNCapability, MultiprotocolCapability, OpenOption, OpenOptionCapabilities,
|
FourByteASNCapability, MultiprotocolCapability, OpenOption, OpenOptionCapabilities,
|
||||||
OpenOptions,
|
OpenOptions,
|
||||||
};
|
};
|
||||||
use crate::bgp_packet::constants::{
|
use bgp_packet::constants::{AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier, AS_TRANS};
|
||||||
AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier, AS_TRANS,
|
use bgp_packet::messages::BGPMessage;
|
||||||
};
|
use bgp_packet::messages::BGPMessageTypeValues;
|
||||||
use crate::bgp_packet::messages::BGPMessage;
|
use bgp_packet::messages::BGPMessageTypeValues::OPEN_MESSAGE;
|
||||||
use crate::bgp_packet::messages::BGPMessageTypeValues;
|
use bgp_packet::messages::BGPMessageTypeValues::UPDATE_MESSAGE;
|
||||||
use crate::bgp_packet::messages::BGPMessageTypeValues::OPEN_MESSAGE;
|
use bgp_packet::messages::BGPSubmessage;
|
||||||
use crate::bgp_packet::messages::BGPMessageTypeValues::UPDATE_MESSAGE;
|
use bgp_packet::messages::Codec;
|
||||||
use crate::bgp_packet::messages::BGPSubmessage;
|
use bgp_packet::messages::KeepaliveMessage;
|
||||||
use crate::bgp_packet::messages::Codec;
|
use bgp_packet::messages::NotificationMessage;
|
||||||
use crate::bgp_packet::messages::KeepaliveMessage;
|
use bgp_packet::messages::OpenMessage;
|
||||||
use crate::bgp_packet::messages::NotificationMessage;
|
use bgp_packet::messages::UpdateMessage;
|
||||||
use crate::bgp_packet::messages::OpenMessage;
|
use bgp_packet::nlri::NLRI;
|
||||||
use crate::bgp_packet::messages::UpdateMessage;
|
use bgp_packet::path_attributes::ASPathAttribute;
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use bgp_packet::path_attributes::NextHopPathAttribute;
|
||||||
use crate::bgp_packet::path_attributes::ASPathAttribute;
|
use bgp_packet::path_attributes::OriginPathAttribute;
|
||||||
use crate::bgp_packet::path_attributes::NextHopPathAttribute;
|
use bgp_packet::path_attributes::PathAttribute;
|
||||||
use crate::bgp_packet::path_attributes::OriginPathAttribute;
|
use bgp_packet::path_attributes::{
|
||||||
use crate::bgp_packet::path_attributes::PathAttribute;
|
|
||||||
use crate::bgp_packet::path_attributes::{
|
|
||||||
LargeCommunitiesPathAttribute, LargeCommunitiesPayload, MPReachNLRIPathAttribute,
|
LargeCommunitiesPathAttribute, LargeCommunitiesPayload, MPReachNLRIPathAttribute,
|
||||||
};
|
};
|
||||||
use crate::bgp_packet::traits::ParserContext;
|
use bgp_packet::traits::ParserContext;
|
||||||
use crate::server::config::PrefixAnnouncement;
|
|
||||||
use crate::server::config::{PeerConfig, ServerConfig};
|
|
||||||
use crate::server::data_structures::RouteAnnounce;
|
|
||||||
use crate::server::data_structures::RouteWithdraw;
|
|
||||||
use crate::server::data_structures::{RouteInfo, RouteUpdate};
|
|
||||||
use crate::server::rib_manager::RouteManagerCommands;
|
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use ip_network_table_deps_treebitmap::address::Address;
|
use ip_network_table_deps_treebitmap::address::Address;
|
||||||
use ip_network_table_deps_treebitmap::IpLookupTable;
|
use ip_network_table_deps_treebitmap::IpLookupTable;
|
||||||
@ -12,27 +12,25 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use crate::config::PeerConfig;
|
||||||
use crate::server::data_structures::RouteAnnounce;
|
use crate::data_structures::RouteAnnounce;
|
||||||
use std::collections::BTreeMap;
|
use crate::data_structures::RouteUpdate;
|
||||||
|
use crate::peer::PeerCommands;
|
||||||
use crate::bgp_packet::path_attributes::PathAttribute;
|
|
||||||
use crate::server::config::PeerConfig;
|
|
||||||
use crate::server::data_structures::RouteUpdate;
|
|
||||||
use crate::server::peer::PeerCommands;
|
|
||||||
|
|
||||||
use tracing::{info, trace, warn};
|
|
||||||
|
|
||||||
use std::cmp::Eq;
|
use std::cmp::Eq;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use bgp_packet::nlri::NLRI;
|
||||||
|
use bgp_packet::path_attributes::PathAttribute;
|
||||||
use ip_network_table_deps_treebitmap::address::Address;
|
use ip_network_table_deps_treebitmap::address::Address;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::sync::Mutex;
|
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
|
use tracing::{info, trace, warn};
|
||||||
|
|
||||||
use super::data_structures::RouteWithdraw;
|
use super::data_structures::RouteWithdraw;
|
||||||
|
|
||||||
@ -227,7 +225,7 @@ where
|
|||||||
// reannouncement or fresh announcement.
|
// reannouncement or fresh announcement.
|
||||||
match path_set.paths.get_mut(&update.peer) {
|
match path_set.paths.get_mut(&update.peer) {
|
||||||
// Peer already announced this route before.
|
// Peer already announced this route before.
|
||||||
Some(mut existing) => {
|
Some(existing) => {
|
||||||
trace!(
|
trace!(
|
||||||
"Updating existing path attributes for NLRI: {}/{}",
|
"Updating existing path attributes for NLRI: {}/{}",
|
||||||
addr,
|
addr,
|
||||||
@ -329,12 +327,13 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::rib_manager::RibManager;
|
||||||
use crate::bgp_packet::nlri::NLRI;
|
use crate::rib_manager::RouteAnnounce;
|
||||||
use crate::server::rib_manager::RibManager;
|
use crate::rib_manager::RouteManagerCommands;
|
||||||
use crate::server::rib_manager::RouteAnnounce;
|
use crate::rib_manager::RouteUpdate;
|
||||||
use crate::server::rib_manager::RouteManagerCommands;
|
|
||||||
use crate::server::rib_manager::RouteUpdate;
|
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||||
|
use bgp_packet::nlri::NLRI;
|
||||||
|
|
||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@ -12,19 +12,19 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use crate::bgp_packet::constants::AddressFamilyIdentifier;
|
use crate::peer::PeerCommands;
|
||||||
use crate::server::peer::PeerCommands;
|
use crate::rib_manager;
|
||||||
use crate::server::rib_manager;
|
use crate::rib_manager::RibSnapshot;
|
||||||
use crate::server::rib_manager::RibSnapshot;
|
use crate::rib_manager::RouteManagerCommands;
|
||||||
use crate::server::rib_manager::RouteManagerCommands;
|
use crate::route_server::route_server::route_service_server::RouteService;
|
||||||
use crate::server::route_server::route_server::route_service_server::RouteService;
|
use crate::route_server::route_server::AddressFamily;
|
||||||
use crate::server::route_server::route_server::AddressFamily;
|
use crate::route_server::route_server::DumpPathsRequest;
|
||||||
use crate::server::route_server::route_server::DumpPathsRequest;
|
use crate::route_server::route_server::DumpPathsResponse;
|
||||||
use crate::server::route_server::route_server::DumpPathsResponse;
|
use crate::route_server::route_server::Path;
|
||||||
use crate::server::route_server::route_server::Path;
|
use crate::route_server::route_server::PathSet;
|
||||||
use crate::server::route_server::route_server::PathSet;
|
use crate::route_server::route_server::Prefix;
|
||||||
use crate::server::route_server::route_server::Prefix;
|
use crate::route_server::route_server::StreamPathsRequest;
|
||||||
use crate::server::route_server::route_server::StreamPathsRequest;
|
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
@ -1,21 +1,19 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "integration_tests"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Rayhaan Jaufeerally <rayhaan@rayhaan.ch>"]
|
authors = ["Rayhaan Jaufeerally <rayhaan@rayhaan.ch>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
name = "integration_tests"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bgpd = { path = "../../bgpd" }
|
bgp_packet.workspace = true
|
||||||
bytes = "1.*"
|
bgp_server.workspace = true
|
||||||
tokio = { version = "1.6.1", features = ["full"] }
|
bytes = "1.*"
|
||||||
tokio-util = { version = "0.6.7", features = ["codec"] }
|
libc = "0.2.126"
|
||||||
tracing = "0.1"
|
tokio = { version = "1.6.1", features = ["full"] }
|
||||||
tracing-subscriber = "0.2"
|
tokio-util = { version = "0.7.10", features = ["codec"] }
|
||||||
libc = "0.2.126"
|
tracing = "0.1"
|
||||||
|
tracing-subscriber = "0.2"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serial_test = "0.5.1"
|
serial_test = "0.5.1"
|
||||||
|
|
||||||
[unstable]
|
|
||||||
thread_id_value = true
|
|
||||||
@ -12,12 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use bgpd::bgp_packet;
|
use bgp_packet::constants::{AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier};
|
||||||
use bgpd::bgp_packet::constants::{AddressFamilyIdentifier, SubsequentAddressFamilyIdentifier};
|
use bgp_packet::messages::BGPSubmessage;
|
||||||
use bgpd::bgp_packet::messages::BGPSubmessage;
|
use bgp_packet::traits::ParserContext;
|
||||||
use bgpd::bgp_packet::traits::ParserContext;
|
use bgp_server::bgp_server::Server;
|
||||||
use bgpd::server::bgp_server::Server;
|
use bgp_server::config::{PeerConfig, ServerConfig};
|
||||||
use bgpd::server::config::{PeerConfig, ServerConfig};
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
@ -27,6 +26,7 @@ use std::net::TcpStream;
|
|||||||
use std::net::{IpAddr, SocketAddrV6};
|
use std::net::{IpAddr, SocketAddrV6};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio_util::codec::Decoder;
|
use tokio_util::codec::Decoder;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user