This commit is contained in:
@ -20,8 +20,8 @@ use crate::rib_manager::RibManager;
|
||||
use crate::rib_manager::RibSnapshot;
|
||||
use crate::rib_manager::RouteManagerCommands;
|
||||
use crate::route_server;
|
||||
use crate::route_server::route_server::bgp_server_admin_service_server::BgpServerAdminServiceServer;
|
||||
use crate::route_server::route_server::route_service_server::RouteServiceServer;
|
||||
use crate::route_server::proto::bgp_server_admin_service_server::BgpServerAdminServiceServer;
|
||||
use crate::route_server::proto::route_service_server::RouteServiceServer;
|
||||
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||
use std::collections::HashMap;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
@ -19,7 +19,7 @@ use crate::filter_eval::FilterEvaluator;
|
||||
use crate::path::path_data::PathData;
|
||||
use crate::path::path_set::PathSource;
|
||||
use crate::rib_manager::RouteManagerCommands;
|
||||
use crate::route_server::route_server::PeerStatus;
|
||||
use crate::route_server::proto::PeerStatus;
|
||||
|
||||
use bgp_packet::capabilities::{
|
||||
BGPCapability, BGPCapabilityTypeValues, BGPCapabilityValue, BGPOpenOptionTypeValues,
|
||||
@ -38,10 +38,10 @@ use bgp_packet::messages::NotificationMessage;
|
||||
use bgp_packet::messages::OpenMessage;
|
||||
use bgp_packet::messages::UpdateMessage;
|
||||
use bgp_packet::nlri::NLRI;
|
||||
use bgp_packet::path_attributes::ASPathAttribute;
|
||||
use bgp_packet::path_attributes::NextHopPathAttribute;
|
||||
use bgp_packet::path_attributes::OriginPathAttribute;
|
||||
use bgp_packet::path_attributes::PathAttribute;
|
||||
use bgp_packet::path_attributes::{ASPathAttribute, MPUnreachNLRIPathAttribute};
|
||||
use bgp_packet::path_attributes::{
|
||||
LargeCommunitiesPathAttribute, LargeCommunitiesPayload, MPReachNLRIPathAttribute,
|
||||
};
|
||||
@ -485,7 +485,7 @@ where
|
||||
};
|
||||
let mut buf = BytesMut::new();
|
||||
self.codec.lock().await.encode(bgp_message, &mut buf)?;
|
||||
conn.write(&buf).await?;
|
||||
conn.write_all(&buf).await?;
|
||||
|
||||
// Update state
|
||||
self.state = BGPState::OpenSent;
|
||||
@ -530,8 +530,104 @@ where
|
||||
}
|
||||
|
||||
PeerCommands::Announce(route_update) => match route_update {
|
||||
RouteUpdate::Announce(announcement) => todo!(),
|
||||
RouteUpdate::Withdraw(withdrawal) => todo!(),
|
||||
RouteUpdate::Announce(announcement) => {
|
||||
// nexthop is not populated in announcement so we set it ourselves here.
|
||||
let nexthop = if let Some(stream) = &self.tcp_stream {
|
||||
stream.local_addr()?
|
||||
} else {
|
||||
bail!("Cannot send route announcement since tcp stream is closed");
|
||||
};
|
||||
let nexthop_attribute: PathAttribute = match nexthop.ip() {
|
||||
IpAddr::V4(ipv4_addr) => {
|
||||
// TODO: In the IPv4 case we also need to add the NLRI to the update msg.
|
||||
PathAttribute::NextHopPathAttribute(NextHopPathAttribute(ipv4_addr))
|
||||
}
|
||||
IpAddr::V6(ipv6_addr) => {
|
||||
PathAttribute::MPReachNLRIPathAttribute(MPReachNLRIPathAttribute {
|
||||
afi: AddressFamilyIdentifier::Ipv6,
|
||||
safi: SubsequentAddressFamilyIdentifier::Unicast,
|
||||
nexthop: ipv6_addr.octets().to_vec(),
|
||||
nlris: announcement.0.clone(),
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
let mut path_attributes = vec![
|
||||
PathAttribute::OriginPathAttribute(announcement.1.origin),
|
||||
ASPathAttribute::from_asns(announcement.1.as_path.clone()),
|
||||
nexthop_attribute,
|
||||
];
|
||||
|
||||
for nlri in &announcement.0 {
|
||||
if !self.filter_evaluator.evaluate_out(
|
||||
&mut path_attributes,
|
||||
&announcement.1.as_path,
|
||||
&nlri,
|
||||
) {
|
||||
bail!("Filter rejected NLRI: {}", nlri);
|
||||
}
|
||||
}
|
||||
|
||||
let update_message = UpdateMessage {
|
||||
path_attributes,
|
||||
withdrawn_nlri: Vec::default(),
|
||||
announced_nlri: Vec::default(),
|
||||
};
|
||||
|
||||
let bgp_message = BGPMessage {
|
||||
msg_type: UPDATE_MESSAGE,
|
||||
payload: BGPSubmessage::UpdateMessage(update_message),
|
||||
};
|
||||
|
||||
let mut buf = BytesMut::new();
|
||||
self.codec
|
||||
.lock()
|
||||
.await
|
||||
.encode(bgp_message, &mut buf)
|
||||
.map_err(|e| eyre!("failed to encode BGP message: {}", e))?;
|
||||
|
||||
if let Some(stream) = self.tcp_stream.as_mut() {
|
||||
stream
|
||||
.write(&buf)
|
||||
.await
|
||||
.map_err(|e| eyre!("Failed to write msg to peer: {}", e))?;
|
||||
}
|
||||
}
|
||||
RouteUpdate::Withdraw(withdrawal) => {
|
||||
// Only IPv6 NLRIs are supported for now.
|
||||
let path_attributes = vec![PathAttribute::MPUnreachNLRIPathAttribute(
|
||||
MPUnreachNLRIPathAttribute {
|
||||
afi: AddressFamilyIdentifier::Ipv6,
|
||||
safi: SubsequentAddressFamilyIdentifier::Unicast,
|
||||
nlris: withdrawal.prefixes,
|
||||
},
|
||||
)];
|
||||
|
||||
let update_message = UpdateMessage {
|
||||
path_attributes,
|
||||
withdrawn_nlri: vec![],
|
||||
announced_nlri: vec![],
|
||||
};
|
||||
|
||||
let bgp_message = BGPMessage {
|
||||
msg_type: UPDATE_MESSAGE,
|
||||
payload: BGPSubmessage::UpdateMessage(update_message),
|
||||
};
|
||||
|
||||
let mut buf = BytesMut::new();
|
||||
self.codec
|
||||
.lock()
|
||||
.await
|
||||
.encode(bgp_message, &mut buf)
|
||||
.map_err(|e| eyre!("failed to encode BGP message: {}", e))?;
|
||||
|
||||
if let Some(stream) = self.tcp_stream.as_mut() {
|
||||
stream
|
||||
.write(&buf)
|
||||
.await
|
||||
.map_err(|e| eyre!("Failed to write msg to peer: {}", e))?;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
PeerCommands::MessageFromPeer(msg) => match self.handle_msg(msg).await {
|
||||
@ -666,7 +762,7 @@ where
|
||||
self.codec.lock().await.encode(bgp_msg, &mut buf)?;
|
||||
match self.tcp_stream.as_mut() {
|
||||
Some(stream) => {
|
||||
stream.write(&buf).await?;
|
||||
stream.write_all(&buf).await?;
|
||||
}
|
||||
None => warn!("Dropped notification message to peer"),
|
||||
}
|
||||
@ -927,7 +1023,7 @@ where
|
||||
};
|
||||
let mut buf = BytesMut::new();
|
||||
self.codec.lock().await.encode(keepalive, &mut buf)?;
|
||||
conn.write(buf.as_ref()).await?;
|
||||
conn.write_all(buf.as_ref()).await?;
|
||||
Ok(())
|
||||
}
|
||||
None => Err(std::io::Error::new(
|
||||
|
||||
@ -12,29 +12,36 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::data_structures::RouteUpdate;
|
||||
use crate::data_structures::RouteWithdraw;
|
||||
use crate::path::path_data::PathData;
|
||||
use crate::path::path_set::PathSet;
|
||||
use crate::path::path_set::PathSource;
|
||||
use crate::peer::PeerCommands;
|
||||
use crate::rib_manager::RibSnapshot;
|
||||
use crate::rib_manager::RouteManagerCommands;
|
||||
use crate::route_server::route_server::bgp_server_admin_service_server::BgpServerAdminService;
|
||||
use crate::route_server::route_server::route_service_server::RouteService;
|
||||
use crate::route_server::route_server::AddressFamily;
|
||||
use crate::route_server::route_server::AnnouncementRequest;
|
||||
use crate::route_server::route_server::AnnouncementResponse;
|
||||
use crate::route_server::route_server::DumpPathsRequest;
|
||||
use crate::route_server::route_server::DumpPathsResponse;
|
||||
use crate::route_server::route_server::Path;
|
||||
use crate::route_server::route_server::Prefix;
|
||||
use crate::route_server::route_server::StreamPathsRequest;
|
||||
use crate::route_server::proto::bgp_server_admin_service_server::BgpServerAdminService;
|
||||
use crate::route_server::proto::route_service_server::RouteService;
|
||||
use crate::route_server::proto::AddressFamily;
|
||||
use crate::route_server::proto::AnnouncementRequest;
|
||||
use crate::route_server::proto::AnnouncementResponse;
|
||||
use crate::route_server::proto::DumpPathsRequest;
|
||||
use crate::route_server::proto::DumpPathsResponse;
|
||||
use crate::route_server::proto::Path;
|
||||
use crate::route_server::proto::Prefix;
|
||||
use crate::route_server::proto::StreamPathsRequest;
|
||||
|
||||
use bgp_packet::constants::AddressFamilyIdentifier;
|
||||
use route_server::PeerStatusRequest;
|
||||
use route_server::PeerStatusResponse;
|
||||
use bgp_packet::nlri::NLRI;
|
||||
use bgp_packet::path_attributes::OriginPathAttribute;
|
||||
use chrono::Utc;
|
||||
use proto::PeerStatusRequest;
|
||||
use proto::PeerStatusResponse;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::net::Ipv6Addr;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::broadcast;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
@ -44,7 +51,7 @@ use tonic::Response;
|
||||
use tonic::Status;
|
||||
use tracing::{info, warn};
|
||||
|
||||
pub mod route_server {
|
||||
pub mod proto {
|
||||
tonic::include_proto!("bgpd.grpc");
|
||||
}
|
||||
|
||||
@ -78,11 +85,8 @@ impl RouteServer {
|
||||
|
||||
/// Converts a rib_manager::PathSet into the proto format PathSet using the
|
||||
/// appropriate address family.
|
||||
fn transform_pathset<A>(
|
||||
mgr_ps: (u64, PathSet<A>),
|
||||
address_family: i32,
|
||||
) -> route_server::PathSet {
|
||||
let mut proto_pathset = route_server::PathSet {
|
||||
fn transform_pathset<A>(mgr_ps: (u64, PathSet<A>), address_family: i32) -> proto::PathSet {
|
||||
let mut proto_pathset = proto::PathSet {
|
||||
epoch: mgr_ps.0,
|
||||
prefix: Some(Prefix {
|
||||
ip_prefix: mgr_ps.1.nlri().prefix.clone(),
|
||||
@ -151,7 +155,50 @@ impl BgpServerAdminService for RouteServer {
|
||||
let request = request.get_ref();
|
||||
|
||||
if let Some(peer) = self.peer_state_machines.get(&request.peer_name) {
|
||||
info!("Would make announcement to peer: {}", &request.peer_name);
|
||||
let prefix = request
|
||||
.prefix
|
||||
.as_ref()
|
||||
.ok_or(Status::invalid_argument("Missing prefix"))?;
|
||||
let nlri = NLRI {
|
||||
afi: AddressFamilyIdentifier::Ipv6,
|
||||
prefix: prefix.ip_prefix.clone(),
|
||||
prefixlen: prefix.prefix_len as u8,
|
||||
};
|
||||
|
||||
if request.add {
|
||||
let path_data = PathData {
|
||||
origin: OriginPathAttribute::IGP,
|
||||
nexthop: Vec::default(),
|
||||
path_source: PathSource::LocallyConfigured,
|
||||
local_pref: 100,
|
||||
med: 100,
|
||||
as_path: vec![210036],
|
||||
path_attributes: Vec::default(),
|
||||
learn_time: Utc::now(),
|
||||
};
|
||||
if let Err(e) = peer.send(PeerCommands::Announce(RouteUpdate::Announce((
|
||||
vec![nlri],
|
||||
Arc::new(path_data),
|
||||
)))) {
|
||||
warn!("Failed to send announcement to peer: {}", e);
|
||||
return Err(Status::internal(format!(
|
||||
"Failed to send message to PeerStateMachine: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
let update = PeerCommands::Announce(RouteUpdate::Withdraw(RouteWithdraw {
|
||||
peer_id: Ipv4Addr::new(0, 0, 0, 0),
|
||||
prefixes: vec![nlri],
|
||||
}));
|
||||
if let Err(e) = peer.send(update) {
|
||||
warn!("Failed to send withdrawal to peer: {}", e);
|
||||
return Err(Status::internal(format!(
|
||||
"Failed to send message to PeerStateMachine: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(Status::invalid_argument(format!(
|
||||
"No such peer: {}",
|
||||
@ -189,7 +236,7 @@ impl RouteService for RouteServer {
|
||||
Ok(result) => {
|
||||
response.epoch = result.epoch;
|
||||
for pathset in result.routes {
|
||||
let mut proto_pathset = route_server::PathSet {
|
||||
let mut proto_pathset = proto::PathSet {
|
||||
epoch: result.epoch,
|
||||
prefix: Some(Prefix {
|
||||
ip_prefix: pathset.nlri().prefix.clone(),
|
||||
@ -236,7 +283,7 @@ impl RouteService for RouteServer {
|
||||
Ok(result) => {
|
||||
response.epoch = result.epoch;
|
||||
for pathset in result.routes {
|
||||
let mut proto_pathset = route_server::PathSet {
|
||||
let mut proto_pathset = proto::PathSet {
|
||||
epoch: result.epoch,
|
||||
prefix: Some(Prefix {
|
||||
ip_prefix: pathset.nlri().prefix.clone(),
|
||||
@ -274,7 +321,7 @@ impl RouteService for RouteServer {
|
||||
}
|
||||
}
|
||||
|
||||
type StreamPathsStream = ReceiverStream<Result<route_server::PathSet, Status>>;
|
||||
type StreamPathsStream = ReceiverStream<Result<proto::PathSet, Status>>;
|
||||
|
||||
async fn stream_paths(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user