Skip to content

Commit 230a729

Browse files
committed
Introduce LinkMessageBuilder
**API BREAK** To remove the duplicate error of `LinkAddRequest` and `LinkSetRequest`, this patch introduce `LinkMessageBuilder` to generate `LinkMessage` for link handlers to use. The `impl LinkMessageBuilder<T>` holds the common functions available for all interface types. The `impl LinkMessageBuilder<LinkVlan>` holds VLAN specific functions. The LinkMessageBuilder is designed for advanced user, wrapper functions are created for common use cases. For example, to create a VLAN interface: ```rus let (connection, handle, _) = new_connection().unwrap(); tokio::spawn(connection); handle .link() .add( LinkVlan::new("vlan100", 10, 100) .up() .build() ) .execute() .await .map_err(|e| format!("{e}")) ``` These patches included these new structures to generate matching LinkMessageBuilder: * `LinkUnspec` (for matching existing interface) * `LinkDummy` * `LinkVeth` * `LinkVlan` * `LinkVxlan` * `LinkMacVlan` * `LinkMacVtap` * `LinkWireguard` * `LinkBondPort` Special note: * Due to confliction, the previous VxLAN `link()` function changed to `dev()`. The `link()` is the share function for all interface types. The API is matching with `ip link` command line option for vxlan. Please check `examples/create_vxlan.rs` for usage. * The `LinkHandler::set_bond_port()` changed to `LinkHandler::set_port()`, please check `examples/set_bond_port.rs` for usage. * The `message_mut()` function is removed from `LinkSetRequest` and `LinkAddRequest`, user should modify the LinkMessage before sent to handler. Signed-off-by: Gris Ge <fge@redhat.com>
1 parent d6e8b4c commit 230a729

37 files changed

+1784
-1192
lines changed

examples/create_bond.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
// SPDX-License-Identifier: MIT
22

3-
use netlink_packet_route::link::BondMode;
4-
use rtnetlink::new_connection;
53
use std::net::{Ipv4Addr, Ipv6Addr};
64

5+
use rtnetlink::{new_connection, packet_route::link::BondMode, LinkBond};
6+
77
#[tokio::main]
88
async fn main() -> Result<(), String> {
99
let (connection, handle, _) = new_connection().unwrap();
1010
tokio::spawn(connection);
11-
handle
12-
.link()
13-
.add()
14-
.bond("my-bond".into())
11+
12+
let message = LinkBond::new("my-bond")
1513
.mode(BondMode::ActiveBackup)
1614
.miimon(100)
1715
.updelay(100)
@@ -26,6 +24,11 @@ async fn main() -> Result<(), String> {
2624
Ipv6Addr::new(0xfd02, 0, 0, 0, 0, 0, 0, 2),
2725
])
2826
.up()
27+
.build();
28+
29+
handle
30+
.link()
31+
.add(message)
2932
.execute()
3033
.await
3134
.map_err(|e| format!("{e}"))

examples/create_bridge.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
// SPDX-License-Identifier: MIT
22

3-
use rtnetlink::new_connection;
3+
use rtnetlink::{new_connection, LinkBridge};
44

55
#[tokio::main]
66
async fn main() -> Result<(), String> {
77
let (connection, handle, _) = new_connection().unwrap();
88
tokio::spawn(connection);
9+
910
handle
1011
.link()
11-
.add()
12-
.bridge("my-bridge-1".into())
12+
.add(LinkBridge::new("my-bridge").build())
1313
.execute()
1414
.await
1515
.map_err(|e| format!("{e}"))

examples/create_dummy.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
use rtnetlink::{new_connection, LinkDummy};
4+
5+
#[tokio::main]
6+
async fn main() -> Result<(), String> {
7+
let (connection, handle, _) = new_connection().unwrap();
8+
tokio::spawn(connection);
9+
10+
handle
11+
.link()
12+
.add(LinkDummy::new("dummy0").build())
13+
.execute()
14+
.await
15+
.map_err(|e| format!("{e}"))
16+
}

examples/create_macvlan.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
// SPDX-License-Identifier: MIT
22

3-
use futures::stream::TryStreamExt;
4-
use macaddr::MacAddr;
5-
use rtnetlink::{new_connection, Error, Handle};
63
use std::{env, str::FromStr};
74

8-
use netlink_packet_route::link::{LinkAttribute, MacVlanMode};
5+
use futures::stream::TryStreamExt;
6+
use macaddr::MacAddr;
7+
use rtnetlink::{
8+
new_connection, packet_route::link::MacVlanMode, Error, Handle, LinkMacVlan,
9+
};
910

1011
#[tokio::main]
1112
async fn main() -> Result<(), String> {
@@ -37,19 +38,20 @@ async fn create_macvlan(
3738
link_name: String,
3839
mac_address: Option<Vec<u8>>,
3940
) -> Result<(), Error> {
40-
let mut links = handle.link().get().match_name(link_name.clone()).execute();
41-
if let Some(link) = links.try_next().await? {
42-
let mut request = handle.link().add().macvlan(
43-
"test_macvlan".into(),
44-
link.header.index,
41+
let mut parent_links =
42+
handle.link().get().match_name(link_name.clone()).execute();
43+
if let Some(parent) = parent_links.try_next().await? {
44+
let mut builder = LinkMacVlan::new(
45+
"my-macvlan",
46+
parent.header.index,
4547
MacVlanMode::Bridge,
4648
);
4749
if let Some(mac) = mac_address {
48-
request
49-
.message_mut()
50-
.attributes
51-
.push(LinkAttribute::Address(mac));
50+
builder = builder.address(mac);
5251
}
52+
let message = builder.build();
53+
let request = handle.link().add(message);
54+
5355
request.execute().await?
5456
} else {
5557
println!("no link {link_name} found");

examples/create_macvtap.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// SPDX-License-Identifier: MIT
22

3-
use futures::stream::TryStreamExt;
4-
use netlink_packet_route::link::MacVtapMode;
5-
use rtnetlink::{new_connection, Error, Handle};
63
use std::env;
74

5+
use futures::stream::TryStreamExt;
6+
use rtnetlink::{
7+
new_connection, packet_route::link::MacVtapMode, Error, Handle, LinkMacVtap,
8+
};
9+
810
#[tokio::main]
911
async fn main() -> Result<(), String> {
1012
let args: Vec<String> = env::args().collect();
@@ -24,18 +26,22 @@ async fn main() -> Result<(), String> {
2426

2527
async fn create_macvtap(
2628
handle: Handle,
27-
veth_name: String,
29+
link_name: String,
2830
) -> Result<(), Error> {
29-
let mut links = handle.link().get().match_name(veth_name.clone()).execute();
30-
if let Some(link) = links.try_next().await? {
31-
let request = handle.link().add().macvtap(
32-
"test_macvtap".into(),
33-
link.header.index,
31+
let mut parent_links =
32+
handle.link().get().match_name(link_name.clone()).execute();
33+
if let Some(parent) = parent_links.try_next().await? {
34+
let message = LinkMacVtap::new(
35+
"test_macvtap",
36+
parent.header.index,
3437
MacVtapMode::Bridge,
35-
);
38+
)
39+
.build();
40+
41+
let request = handle.link().add(message);
3642
request.execute().await?
3743
} else {
38-
println!("no link link {veth_name} found");
44+
println!("no link link {link_name} found");
3945
}
4046
Ok(())
4147
}

examples/create_veth.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// SPDX-License-Identifier: MIT
22

3-
use rtnetlink::new_connection;
4-
3+
use rtnetlink::{new_connection, LinkVeth};
54
#[tokio::main]
65
async fn main() -> Result<(), String> {
76
let (connection, handle, _) = new_connection().unwrap();
87
tokio::spawn(connection);
8+
99
handle
1010
.link()
11-
.add()
12-
.veth("veth-rs-1".into(), "veth-rs-2".into())
11+
.add(LinkVeth::new("veth1", "veth1-peer").build())
1312
.execute()
1413
.await
1514
.map_err(|e| format!("{e}"))

examples/create_vlan.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::{env, error::Error as StdError, str::FromStr};
44

5-
use rtnetlink::{new_connection, QosMapping};
5+
use rtnetlink::{new_connection, LinkVlan, QosMapping};
66

77
fn parse_mapping(parameter: &str) -> Result<QosMapping, Box<dyn StdError>> {
88
let (from, to) = parameter
@@ -109,10 +109,14 @@ async fn main() -> Result<(), String> {
109109
let (connection, handle, _) = new_connection().unwrap();
110110
tokio::spawn(connection);
111111

112+
let message = LinkVlan::new(&name, base, id)
113+
.up()
114+
.qos(ingress, egress)
115+
.build();
116+
112117
handle
113118
.link()
114-
.add()
115-
.vlan_with_qos(name, base, id, ingress, egress)
119+
.add(message)
116120
.execute()
117121
.await
118122
.map_err(|err| format!("Netlink request failed: {err}"))

examples/create_vrf.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
use rtnetlink::{new_connection, LinkVrf};
4+
5+
#[tokio::main]
6+
async fn main() -> Result<(), String> {
7+
let (connection, handle, _) = new_connection().unwrap();
8+
tokio::spawn(connection);
9+
10+
handle
11+
.link()
12+
.add(LinkVrf::new("my-vrf", 101).build())
13+
.execute()
14+
.await
15+
.map_err(|e| format!("{e}"))
16+
}

examples/create_vxlan.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22

33
use futures::stream::TryStreamExt;
4-
use rtnetlink::{new_connection, Error, Handle};
4+
use rtnetlink::{new_connection, Error, Handle, LinkVxlan};
55
use std::env;
66

77
#[tokio::main]
@@ -24,15 +24,13 @@ async fn main() -> Result<(), String> {
2424
async fn create_vxlan(handle: Handle, name: String) -> Result<(), Error> {
2525
let mut links = handle.link().get().match_name(name.clone()).execute();
2626
if let Some(link) = links.try_next().await? {
27-
handle
28-
.link()
29-
.add()
30-
.vxlan("vxlan0".into(), 10u32)
31-
.link(link.header.index)
32-
.port(4789)
27+
let message = LinkVxlan::new("vxlan0", 10)
28+
.dev(link.header.index)
3329
.up()
34-
.execute()
35-
.await?
30+
.port(4789)
31+
.build();
32+
33+
handle.link().add(message).execute().await?
3634
} else {
3735
println!("no link link {name} found");
3836
}

examples/create_wireguard.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
use rtnetlink::{new_connection, LinkWireguard};
4+
5+
#[tokio::main]
6+
async fn main() -> Result<(), String> {
7+
let (connection, handle, _) = new_connection().unwrap();
8+
tokio::spawn(connection);
9+
10+
handle
11+
.link()
12+
.add(LinkWireguard::new("my-wg").build())
13+
.execute()
14+
.await
15+
.map_err(|e| format!("{e}"))
16+
}

0 commit comments

Comments
 (0)