@@ -19,7 +19,7 @@ use super::{
19
19
constants:: {
20
20
ISOLATE_OPTION_FALSE , ISOLATE_OPTION_STRICT , ISOLATE_OPTION_TRUE ,
21
21
NO_CONTAINER_INTERFACE_ERROR , OPTION_ISOLATE , OPTION_METRIC , OPTION_MTU ,
22
- OPTION_NO_DEFAULT_ROUTE ,
22
+ OPTION_NO_DEFAULT_ROUTE , OPTION_VRF ,
23
23
} ,
24
24
core_utils:: { self , get_ipam_addresses, join_netns, parse_option, CoreUtils } ,
25
25
driver:: { self , DriverInfo } ,
@@ -50,6 +50,8 @@ struct InternalData {
50
50
metric : Option < u32 > ,
51
51
/// if set, no default gateway will be added
52
52
no_default_route : bool ,
53
+ /// sef vrf for bridge
54
+ vrf : Option < String > ,
53
55
// TODO: add vlan
54
56
}
55
57
@@ -81,6 +83,7 @@ impl driver::NetworkDriver for Bridge<'_> {
81
83
let metric: u32 = parse_option ( & self . info . network . options , OPTION_METRIC ) ?. unwrap_or ( 100 ) ;
82
84
let no_default_route: bool =
83
85
parse_option ( & self . info . network . options , OPTION_NO_DEFAULT_ROUTE ) ?. unwrap_or ( false ) ;
86
+ let vrf: Option < String > = parse_option ( & self . info . network . options , OPTION_VRF ) ?;
84
87
85
88
let static_mac = match & self . info . per_network_opts . static_mac {
86
89
Some ( mac) => Some ( CoreUtils :: decode_address_from_hex ( mac) ?) ,
@@ -96,6 +99,7 @@ impl driver::NetworkDriver for Bridge<'_> {
96
99
isolate,
97
100
metric : Some ( metric) ,
98
101
no_default_route,
102
+ vrf,
99
103
} ) ;
100
104
Ok ( ( ) )
101
105
}
@@ -494,6 +498,15 @@ fn create_interfaces(
494
498
InfoKind :: Bridge ,
495
499
) ;
496
500
create_link_opts. mtu = data. mtu ;
501
+
502
+ if let Some ( vrf_name) = & data. vrf {
503
+ let vrf = match host. get_link ( netlink:: LinkID :: Name ( vrf_name. to_string ( ) ) ) {
504
+ Ok ( vrf) => check_link_is_vrf ( vrf, vrf_name) ?,
505
+ Err ( err) => return Err ( err) . wrap ( "get vrf to set up bridge interface" ) ,
506
+ } ;
507
+ create_link_opts. primary_index = vrf. header . index ;
508
+ }
509
+
497
510
host. create_link ( create_link_opts) . wrap ( "create bridge" ) ?;
498
511
499
512
if data. ipam . ipv6_enabled {
@@ -672,6 +685,30 @@ fn check_link_is_bridge(msg: LinkMessage, br_name: &str) -> NetavarkResult<LinkM
672
685
) ) )
673
686
}
674
687
688
+ /// make sure the LinkMessage is the kind VRF
689
+ fn check_link_is_vrf ( msg : LinkMessage , vrf_name : & str ) -> NetavarkResult < LinkMessage > {
690
+ for nla in msg. nlas . iter ( ) {
691
+ if let Nla :: Info ( info) = nla {
692
+ for inf in info. iter ( ) {
693
+ if let Info :: Kind ( kind) = inf {
694
+ if * kind == InfoKind :: Vrf {
695
+ return Ok ( msg) ;
696
+ } else {
697
+ return Err ( NetavarkError :: Message ( format ! (
698
+ "vrf {} already exists but is a {:?} interface" ,
699
+ vrf_name, kind
700
+ ) ) ) ;
701
+ }
702
+ }
703
+ }
704
+ }
705
+ }
706
+ Err ( NetavarkError :: Message ( format ! (
707
+ "could not determine namespace link kind for vrf {}" ,
708
+ vrf_name
709
+ ) ) )
710
+ }
711
+
675
712
fn remove_link (
676
713
host : & mut netlink:: Socket ,
677
714
netns : & mut netlink:: Socket ,
0 commit comments