1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// SPDX-License-Identifier: MIT
use netlink_packet_core::{Emitable, Parseable};
use crate::{
link::{
link_flag::LinkFlags, link_state::State, InfoData, InfoKind, InfoVxcan,
LinkAttribute, LinkHeader, LinkInfo, LinkLayerType, LinkMessage,
LinkMessageBuffer, LinkMode,
},
AddressFamily,
};
#[test]
fn test_vxcan_get_link_info() {
// Captured from kernel 6.12.69 with iproute2-6.15.0
// ```sh
// sudo ip link add nl0 type nlmon
// sudo ip link set nl0 up
// sudo ip link add vxcan0 type vxcan peer name vxcan1
// sudo ip link set vxcan0 up
// sudo ip link set vxcan1 up
// sudo tcpdump -i nl0 -w create_vxcan.pcap &
// sudo ip link show vxcan0
// sudo pkill tcpdump
// ```
let raw: Vec<u8> = vec![
0x00, 0x00, // AF_UNSPEC and reserved
0x18, 0x01, // Link layer type CAN(280)
0x19, 0x00, 0x00, 0x00, // iface index 25
0xc1, 0x00, 0x01, 0x00, // flags
0x00, 0x00, 0x00, 0x00, // changed flags0
0x0b, 0x00, // length 11
0x03, 0x00, // IFLA_IFNAME
0x76, 0x78, 0x63, 0x61, 0x6e, 0x30, 0x00, 0x00, // "vxcan0\0"
0x08, 0x00, // length 8
0x0d, 0x00, // IFLA_TXQLEN 13
0xe8, 0x03, 0x00, 0x00, // Tx Queue Length 1000
0x05, 0x00, // length 5
0x10, 0x00, // IFLA_OPERSTATE 16
0x06, // Up
0x00, 0x00, 0x00, // padding
0x05, 0x00, // length 5
0x11, 0x00, // IFLA_LINKMODE 17
0x00, // Value 0
0x00, 0x00, 0x00, // padding
0x08, 0x00, // length 5
0x04, 0x00, // IFLA_MTU 4
0x48, 0x00, 0x00, 0x00, // MTU 72
// Some attributes omitted
0x10, 0x00, // length 16
0x12, 0x00, // IFLA_LINKINFO 18
0x0a, 0x00, // length 10
0x01, 0x00, // IFLA_INFO_KIND 1
0x76, 0x78, 0x63, 0x61, 0x6e, 0x00, // "vxcan\0"
0x00, 0x00, // padding
];
let expected = LinkMessage {
header: LinkHeader {
interface_family: AddressFamily::Unspec,
index: 25,
link_layer_type: LinkLayerType::Can,
flags: LinkFlags::LowerUp
| LinkFlags::Noarp
| LinkFlags::Running
| LinkFlags::Up,
change_mask: LinkFlags::empty(),
},
attributes: vec![
LinkAttribute::IfName("vxcan0".to_string()),
LinkAttribute::TxQueueLen(1000),
LinkAttribute::OperState(State::Up),
LinkAttribute::Mode(LinkMode::Default),
LinkAttribute::Mtu(72),
LinkAttribute::LinkInfo(vec![LinkInfo::Kind(InfoKind::Vxcan)]),
],
};
assert_eq!(
expected,
LinkMessage::parse(&LinkMessageBuffer::new(&raw)).unwrap()
);
let mut buf = vec![0; expected.buffer_len()];
expected.emit(&mut buf);
assert_eq!(buf, raw);
}
#[test]
fn test_create_vxcan() {
// Captured from kernel 6.12.69 with iproute2-6.15.0
// ```sh
// sudo ip link add nl0 type nlmon
// sudo ip link set nl0 up
// sudo tcpdump -i nl0 -w create_vxcan.pcap &
// sudo ip link add vxcan0 type vxcan peer name vxcan1
// sudo pkill tcpdump
// ```
//
// Due to the iproute bug (https://issues.redhat.com/browse/RHEL-14964),
// The IFLA_INFO_KIND length has been manually fixed to 10 instead of the 9
// produced by iproute.
let raw: Vec<u8> = vec![
0x00, // interface family AF_UNSPEC
0x00, // reserved
0x00, 0x00, // link layer type 0
0x00, 0x00, 0x00, 0x00, // iface index 0
0x00, 0x00, 0x00, 0x00, // device flags 0
0x00, 0x00, 0x00, 0x00, // change flags 0
0x0b, 0x00, // length 11
0x03, 0x00, // IFLA_IFNAME
0x76, 0x78, 0x63, 0x61, 0x6e, 0x30, 0x00, 0x00, // "vxcan0\0"
0x34, 0x00, // length 52
0x12, 0x00, // IFLA_LINKINFO 18
0x0a, 0x00, // length 10
0x01, 0x00, // IFLA_INFO_KIND 1
0x76, 0x78, 0x63, 0x61, 0x6e, 0x00, // "vxcan\0"
0x00, 0x00, // padding
0x24, 0x00, // length 36
0x02, 0x00, // IFLA_INFO_DATA 2
0x20, 0x00, // length 32
0x01, 0x00, // VETH_INFO_PEER 1
0x00, // Netlink Message header: family AF_UNSPEC
0x00, // reserved
0x00, 0x00, // link layer type 0
0x00, 0x00, 0x00, 0x00, // iface index 0
0x00, 0x00, 0x00, 0x00, // device flags 0
0x00, 0x00, 0x00, 0x00, // change flags 0
0x0b, 0x00, // length 11
0x03, 0x00, // IFLA_IFNAME 3
0x76, 0x78, 0x63, 0x61, 0x6e, 0x31, 0x00, 0x00, // "vxcan1\0"
];
let expected = LinkMessage {
attributes: vec![
LinkAttribute::IfName("vxcan0".to_string()),
LinkAttribute::LinkInfo(vec![
LinkInfo::Kind(InfoKind::Vxcan),
LinkInfo::Data(InfoData::Vxcan(InfoVxcan::Peer(LinkMessage {
attributes: vec![LinkAttribute::IfName(
"vxcan1".to_string(),
)],
..Default::default()
}))),
]),
],
..Default::default()
};
assert_eq!(
expected,
LinkMessage::parse(&LinkMessageBuffer::new(&raw)).unwrap()
);
let mut buf = vec![0; expected.buffer_len()];
expected.emit(&mut buf);
assert_eq!(buf, raw);
}