@@ -9,7 +9,8 @@ use netlink_packet_route::{
9
9
route:: {
10
10
MplsLabel , RouteAddress , RouteAttribute , RouteFlags , RouteHeader ,
11
11
RouteLwEnCapType , RouteLwTunnelEncap , RouteMessage , RouteMplsIpTunnel ,
12
- RouteProtocol , RouteScope , RouteType ,
12
+ RouteNextHop , RouteNextHopFlags , RouteProtocol , RouteScope , RouteType ,
13
+ RouteVia ,
13
14
} ,
14
15
AddressFamily ,
15
16
} ;
@@ -20,6 +21,12 @@ pub struct RouteMessageBuilder<T = IpAddr> {
20
21
_phantom : PhantomData < T > ,
21
22
}
22
23
24
+ #[ derive( Debug , Clone ) ]
25
+ pub struct RouteNextHopBuilder {
26
+ address_family : AddressFamily ,
27
+ nexthop : RouteNextHop ,
28
+ }
29
+
23
30
impl < T > RouteMessageBuilder < T > {
24
31
/// Create default RouteMessage with header set to:
25
32
/// * route: [RouteHeader::RT_TABLE_MAIN]
@@ -76,6 +83,14 @@ impl<T> RouteMessageBuilder<T> {
76
83
self
77
84
}
78
85
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
+
79
94
/// Sets the route priority (metric)
80
95
pub fn priority ( mut self , priority : u32 ) -> Self {
81
96
self . message
@@ -467,3 +482,70 @@ impl Default for RouteMessageBuilder<MplsLabel> {
467
482
Self :: new ( )
468
483
}
469
484
}
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