@@ -6,13 +6,13 @@ use clap::Args;
66use futures:: channel:: mpsc:: UnboundedReceiver ;
77use futures:: { StreamExt , try_join} ;
88use libc:: { EHOSTUNREACH , ENETUNREACH } ;
9+ use log:: { debug, trace, warn} ;
910use rtnetlink:: Error :: NetlinkError ;
1011use rtnetlink:: packet_core:: { NetlinkMessage , NetlinkPayload } ;
11- use rtnetlink:: packet_route:: address:: { AddressAttribute , AddressMessage } ;
1212use rtnetlink:: packet_route:: route:: { RouteAddress , RouteAttribute , RouteMessage , RouteType , RouteVia } ;
1313use rtnetlink:: packet_route:: rule:: { RuleAction , RuleAttribute , RuleMessage } ;
1414use rtnetlink:: packet_route:: { AddressFamily , RouteNetlinkMessage } ;
15- use rtnetlink:: { Handle , RouteMessageBuilder } ;
15+ use rtnetlink:: { Handle , MulticastGroup , RouteMessageBuilder } ;
1616use serde:: { Deserialize , Serialize } ;
1717use std:: collections:: { BTreeMap , BTreeSet } ;
1818use std:: io;
@@ -21,9 +21,10 @@ use std::time::Duration;
2121use tokio:: select;
2222use tokio:: time:: { Interval , interval} ;
2323
24- // TODO: maintain device info similar to BIRD's "device" protocol, and use it to
25- // ensure only direct traffic to neighbours
26- // For now, we allow any address by `ip route get`.
24+ // We allow redirecting to any address by resolving its next hop using `ip route
25+ // get`. This aligns with the RFC draft v4.
26+ //
27+ // Not handling with ECMP for now.
2728
2829#[ derive( Debug ) ]
2930pub struct RtNetlink < K : Kernel > {
@@ -37,9 +38,11 @@ pub struct RtNetlink<K: Kernel> {
3738
3839impl < K : Kernel > RtNetlink < K > {
3940 pub fn new ( args : RtNetlinkArgs ) -> io:: Result < Self > {
40- let ( conn, handle, msgs) = rtnetlink:: new_connection ( ) ?;
41+ use MulticastGroup :: * ;
42+ let ( conn, handle, msgs) = rtnetlink:: new_multicast_connection ( & [ Ipv4Route , Ipv6Route , Ipv4Rule , Ipv6Rule ] ) ?;
4143 let scan_time = args. route_scan_time ;
4244 tokio:: spawn ( conn) ;
45+ warn ! ( "rtnetlink spawned" ) ;
4346 Ok ( Self {
4447 args,
4548 handle,
@@ -85,9 +88,9 @@ impl<K: Kernel> RtNetlink<K> {
8588 if let Some ( attrs) = & attrs {
8689 msg. attributes . extend ( attrs. iter ( ) . cloned ( ) ) ;
8790 } else {
88- msg. header . kind = RouteType :: Unreachable ;
91+ msg. header . kind = RouteType :: Throw ;
8992 } ;
90- if let Err ( error) = self . handle . route ( ) . add ( msg) . execute ( ) . await {
93+ if let Err ( error) = self . handle . route ( ) . add ( msg) . replace ( ) . execute ( ) . await {
9194 if table_created {
9295 self . rules . remove ( & table_id) ;
9396 self . del_rule ( table_id) . await ;
@@ -137,7 +140,7 @@ impl<K: Kernel> RtNetlink<K> {
137140 . table_id ( table_id)
138141 . build ( ) ;
139142 if self . handle . route ( ) . del ( msg. clone ( ) ) . execute ( ) . await . is_err ( ) {
140- msg. header . kind = RouteType :: Unreachable ;
143+ msg. header . kind = RouteType :: Throw ;
141144 grace ( self . handle . route ( ) . del ( msg) . execute ( ) . await , "failed to delete route" ) ;
142145 }
143146 }
@@ -203,32 +206,20 @@ impl<K: Kernel> RtNetlink<K> {
203206 . unwrap_or_else ( || af_to_wildcard ( msg. header . address_family ) )
204207 }
205208
206- fn addr_msg_dst_prefix ( msg : AddressMessage ) -> IpPrefix {
207- use AddressAttribute :: Address ;
208- let dst_len = msg. header . prefix_len ;
209- ( dst_len != 0 )
210- . then ( || {
211- ( msg. attributes . into_iter ( ) )
212- . filter_map ( |x| if let Address ( ip) = x { Some ( ip) } else { None } )
213- . map ( |x| IpPrefix :: new ( x, dst_len) )
214- . next ( )
215- } )
216- . flatten ( )
217- . unwrap_or_else ( || af_to_wildcard ( msg. header . family ) )
218- }
219-
220209 select ! {
221- _ = self . timer. tick( ) => self . process_all( ) . await ,
222- Some ( ( msg, _) ) = self . msgs. next( ) => match msg. payload {
223- InnerMessage ( msg) => match msg {
224- NewRoute ( msg) | DelRoute ( msg) => self . process_prefix( route_msg_dst_prefix( msg) ) . await ,
225- NewAddress ( msg) | DelAddress ( msg) => self . process_prefix( addr_msg_dst_prefix( msg) ) . await ,
226- NewRule ( msg) | DelRule ( msg) => self . process_prefix( af_to_wildcard( msg. header. family) ) . await ,
227- NewLink ( _) | DelLink ( _) => self . process_all( ) . await ,
210+ _ = self . timer. tick( ) => { warn!( "timer tick" ) ; self . process_all( ) . await }
211+ Some ( ( msg, _) ) = self . msgs. next( ) => {
212+ trace!( "new rtnetlink msg: {msg:?}" ) ;
213+ match msg. payload {
214+ InnerMessage ( msg) => match msg {
215+ // TODO: filter out multicast routes
216+ NewRoute ( msg) | DelRoute ( msg) => self . process_prefix( route_msg_dst_prefix( msg) ) . await ,
217+ NewRule ( msg) | DelRule ( msg) => self . process_prefix( af_to_wildcard( msg. header. family) ) . await ,
218+ _ => Ok ( ( ) ) ,
219+ } ,
228220 _ => Ok ( ( ) ) ,
229- } ,
230- _ => Ok ( ( ) ) ,
231- } ,
221+ }
222+ }
232223 }
233224 }
234225
@@ -249,6 +240,7 @@ impl<K: Kernel> RtNetlink<K> {
249240 for RouteEntry { prefix, next_hop, table_id, attrs } in iter {
250241 let new_attrs = Self :: get_route_from_handle ( handle, prefix. afi ( ) , * next_hop) . await ?;
251242 if * attrs != new_attrs {
243+ debug ! ( "route attrs: {attrs:?} -> {new_attrs:?}" ) ;
252244 * attrs = new_attrs. clone ( ) ;
253245 let mut msg = RouteMessageBuilder :: < IpAddr > :: new ( )
254246 . destination_prefix ( prefix. prefix ( ) , prefix. len ( ) )
@@ -258,7 +250,7 @@ impl<K: Kernel> RtNetlink<K> {
258250 if let Some ( attrs) = & attrs {
259251 msg. attributes . extend ( attrs. iter ( ) . cloned ( ) ) ;
260252 } else {
261- msg. header . kind = RouteType :: Unreachable ;
253+ msg. header . kind = RouteType :: Throw ;
262254 } ;
263255 handle. route ( ) . add ( msg) . replace ( ) . execute ( ) . await ?;
264256 }
0 commit comments