@@ -9,7 +9,8 @@ use netlink_packet_route::{
99 route:: {
1010 MplsLabel , RouteAddress , RouteAttribute , RouteFlags , RouteHeader ,
1111 RouteLwEnCapType , RouteLwTunnelEncap , RouteMessage , RouteMplsIpTunnel ,
12- RouteProtocol , RouteScope , RouteType ,
12+ RouteNextHop , RouteNextHopFlags , RouteProtocol , RouteScope , RouteType ,
13+ RouteVia ,
1314 } ,
1415 AddressFamily ,
1516} ;
@@ -20,6 +21,12 @@ pub struct RouteMessageBuilder<T = IpAddr> {
2021 _phantom : PhantomData < T > ,
2122}
2223
24+ #[ derive( Debug , Clone ) ]
25+ pub struct RouteNextHopBuilder {
26+ address_family : AddressFamily ,
27+ nexthop : RouteNextHop ,
28+ }
29+
2330impl < T > RouteMessageBuilder < T > {
2431 /// Create default RouteMessage with header set to:
2532 /// * route: [RouteHeader::RT_TABLE_MAIN]
@@ -76,6 +83,14 @@ impl<T> RouteMessageBuilder<T> {
7683 self
7784 }
7885
86+ /// Sets multiple nexthop entries for the route.
87+ pub fn multipath ( mut self , nexthops : Vec < RouteNextHop > ) -> Self {
88+ self . message
89+ . attributes
90+ . push ( RouteAttribute :: MultiPath ( nexthops) ) ;
91+ self
92+ }
93+
7994 /// Sets the route priority (metric)
8095 pub fn priority ( mut self , priority : u32 ) -> Self {
8196 self . message
@@ -467,3 +482,70 @@ impl Default for RouteMessageBuilder<MplsLabel> {
467482 Self :: new ( )
468483 }
469484}
485+
486+ impl RouteNextHopBuilder {
487+ /// Create default RouteNexthop for a route with the given address family.
488+ pub fn new ( address_family : AddressFamily ) -> Self {
489+ Self {
490+ address_family,
491+ nexthop : Default :: default ( ) ,
492+ }
493+ }
494+
495+ /// Sets the nexthop interface index.
496+ pub fn interface ( mut self , index : u32 ) -> Self {
497+ self . nexthop . interface_index = index;
498+ self
499+ }
500+
501+ /// Sets the nexthop (via) address.
502+ pub fn via ( mut self , addr : IpAddr ) -> Result < Self , InvalidRouteMessage > {
503+ use AddressFamily :: * ;
504+ let attr = match ( self . address_family , addr) {
505+ ( Inet , addr @ IpAddr :: V4 ( _) ) | ( Inet6 , addr @ IpAddr :: V6 ( _) ) => {
506+ RouteAttribute :: Gateway ( addr. into ( ) )
507+ }
508+ ( Inet , IpAddr :: V6 ( v6) ) => RouteAttribute :: Via ( RouteVia :: Inet6 ( v6) ) ,
509+ ( Mpls , _) => RouteAttribute :: Via ( addr. into ( ) ) ,
510+ ( af, _) => return Err ( InvalidRouteMessage :: AddressFamily ( af) ) ,
511+ } ;
512+ self . nexthop . attributes . push ( attr) ;
513+ Ok ( self )
514+ }
515+
516+ /// Marks the nexthop as directly reachable (on-link).
517+ ///
518+ /// Indicates that the nexthop is reachable without passing through a
519+ /// connected subnet.
520+ pub fn onlink ( mut self ) -> Self {
521+ self . nexthop . flags . insert ( RouteNextHopFlags :: Onlink ) ;
522+ self
523+ }
524+
525+ /// Sets the nexthop MPLS encapsulation labels.
526+ pub fn mpls ( mut self , labels : Vec < MplsLabel > ) -> Self {
527+ if labels. is_empty ( ) {
528+ return self ;
529+ }
530+ if self . address_family == AddressFamily :: Mpls {
531+ self . nexthop
532+ . attributes
533+ . push ( RouteAttribute :: NewDestination ( labels) ) ;
534+ } else {
535+ self . nexthop
536+ . attributes
537+ . push ( RouteAttribute :: EncapType ( RouteLwEnCapType :: Mpls ) ) ;
538+ let encap = RouteLwTunnelEncap :: Mpls (
539+ RouteMplsIpTunnel :: Destination ( labels) ,
540+ ) ;
541+ self . nexthop
542+ . attributes
543+ . push ( RouteAttribute :: Encap ( vec ! [ encap] ) ) ;
544+ }
545+ self
546+ }
547+
548+ pub fn build ( self ) -> RouteNextHop {
549+ self . nexthop
550+ }
551+ }
0 commit comments