diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d7e6e7..711b6cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,6 +15,12 @@ jobs: steps: - uses: actions/checkout@v3 + - name: Install necessary dependencies + run: | + sudo apt update + sudo apt install "linux-modules-extra-$(uname -r)" + sudo modprobe vrf + - name: Install Rust Stable run: | rustup override set stable diff --git a/src/link/add.rs b/src/link/add.rs index 93f2cb1..c3ca62b 100644 --- a/src/link/add.rs +++ b/src/link/add.rs @@ -14,8 +14,8 @@ use netlink_packet_core::{ use netlink_packet_route::{ link::{ InfoBond, InfoData, InfoKind, InfoMacVlan, InfoMacVtap, InfoVeth, - InfoVlan, InfoVxlan, InfoXfrm, LinkAttribute, LinkFlag, LinkInfo, - LinkMessage, VlanQosMapping, + InfoVlan, InfoVrf, InfoVxlan, InfoXfrm, LinkAttribute, LinkFlag, + LinkInfo, LinkMessage, VlanQosMapping, }, RouteNetlinkMessage, }; @@ -787,6 +787,15 @@ impl LinkAddRequest { request } + pub fn vrf(self, name: String, table_id: u32) -> Self { + self.name(name.clone()) + .link_info( + InfoKind::Vrf, + Some(InfoData::Vrf(vec![InfoVrf::TableId(table_id)])), + ) + .append_nla(LinkAttribute::IfName(name)) + } + /// Replace existing matching link. pub fn replace(self) -> Self { Self { diff --git a/src/link/test.rs b/src/link/test.rs index 1688fd0..d9b3f89 100644 --- a/src/link/test.rs +++ b/src/link/test.rs @@ -2,7 +2,8 @@ use futures::stream::TryStreamExt; use netlink_packet_route::link::{ - InfoData, InfoKind, InfoMacVlan, LinkAttribute, LinkInfo, LinkMessage, + InfoData, InfoKind, InfoMacVlan, InfoVrf, LinkAttribute, LinkInfo, + LinkMessage, }; use tokio::runtime::Runtime; @@ -78,6 +79,33 @@ fn create_get_delete_macvlan() { .unwrap(); } +#[test] +fn create_delete_vrf() { + const VRF_IFACE_NAME: &str = "vrf2222"; + const VRF_TABLE: u32 = 2222; + let rt = Runtime::new().unwrap(); + let handle = rt.block_on(_create_vrf(VRF_IFACE_NAME, VRF_TABLE)); + assert!(handle.is_ok()); + + let mut handle = handle.unwrap(); + let msg = rt.block_on(_get_iface(&mut handle, VRF_IFACE_NAME.to_owned())); + assert!(msg.is_ok()); + assert!(has_nla( + msg.as_ref().unwrap(), + &LinkAttribute::IfName(VRF_IFACE_NAME.to_string()) + )); + assert!(has_nla( + msg.as_ref().unwrap(), + &LinkAttribute::LinkInfo(vec![ + LinkInfo::Kind(InfoKind::Vrf), + LinkInfo::Data(InfoData::Vrf(vec![InfoVrf::TableId(VRF_TABLE),])) + ]) + )); + + rt.block_on(_del_iface(&mut handle, msg.unwrap().header.index)) + .unwrap(); +} + fn has_nla(msg: &LinkMessage, nla: &LinkAttribute) -> bool { msg.attributes.iter().any(|x| x == nla) } @@ -128,3 +156,12 @@ async fn _create_macvlan( req.execute().await?; Ok(link_handle) } + +async fn _create_vrf(name: &str, table: u32) -> Result { + let (conn, handle, _) = new_connection().unwrap(); + tokio::spawn(conn); + let link_handle = handle.link(); + let req = link_handle.add().vrf(name.to_string(), table); + req.execute().await?; + Ok(link_handle) +}