1use core::mem;
2
3#[repr(C)]
8#[derive(Debug, Copy, Clone)]
9#[cfg_attr(feature = "wincode", derive(wincode::SchemaRead, wincode::SchemaWrite))]
10#[cfg_attr(feature = "wincode", wincode(assert_zero_copy))]
11pub struct Mpls {
12 pub lbl_tc_s: [u8; 3],
15 pub ttl: u8,
17}
18
19impl Mpls {
20 pub const LEN: usize = mem::size_of::<Mpls>();
21
22 #[inline]
24 pub fn label(&self) -> u32 {
25 let upper_bits = (self.lbl_tc_s[0] as u32) << 12;
26 let middle_bits = (self.lbl_tc_s[1] as u32) << 4;
27 let lower_bits = ((self.lbl_tc_s[2] & 0xF0) >> 4) as u32;
28 upper_bits | middle_bits | lower_bits
29 }
30
31 #[inline]
34 pub fn set_label(&mut self, label: u32) {
35 self.lbl_tc_s[0] = ((label >> 12) & 0xFF) as u8;
36 self.lbl_tc_s[1] = ((label >> 4) & 0xFF) as u8;
37
38 let preserved_bits = self.lbl_tc_s[2] & 0x0F;
40 self.lbl_tc_s[2] = ((label & 0x0F) << 4) as u8 | preserved_bits;
41 }
42
43 #[inline]
46 pub fn tc(&self) -> u8 {
47 (self.lbl_tc_s[2] & 0xE) >> 1
48 }
49
50 #[inline]
54 pub fn set_tc(&mut self, tc_value: u8) {
55 let preserved_bits = self.lbl_tc_s[2] & 0xF1;
56 self.lbl_tc_s[2] = preserved_bits | ((tc_value & 0x07) << 1);
57 }
58
59 #[inline]
62 pub fn s(&self) -> u8 {
63 self.lbl_tc_s[2] & 0x01
64 }
65
66 #[inline]
70 pub fn set_s(&mut self, s_value: u8) {
71 let preserved_bits = self.lbl_tc_s[2] & 0xFE;
72 self.lbl_tc_s[2] = preserved_bits | (s_value & 0x01);
73 }
74
75 #[inline]
77 pub fn ttl(&self) -> u8 {
78 self.ttl
79 }
80
81 #[inline]
84 pub fn set_ttl(&mut self, ttl_value: u8) {
85 self.ttl = ttl_value;
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*; unsafe fn mpls_from_bytes(bytes: &[u8; Mpls::LEN]) -> &Mpls {
94 &*(bytes.as_ptr() as *const Mpls)
95 }
96
97 unsafe fn mpls_from_bytes_mut(bytes: &mut [u8; Mpls::LEN]) -> &mut Mpls {
98 &mut *(bytes.as_mut_ptr() as *mut Mpls)
99 }
100
101 #[test]
102 fn test_mpls_getters() {
103 let mpls_bytes: [u8; Mpls::LEN] = [0xAB, 0xCD, 0xEB, 0x40];
108 let mpls_header = unsafe { mpls_from_bytes(&mpls_bytes) };
109
110 assert_eq!(mpls_header.label(), 0xABCDE);
111 assert_eq!(mpls_header.tc(), 0x05); assert_eq!(mpls_header.s(), 0x01);
113 assert_eq!(mpls_header.ttl(), 0x40);
114 }
115
116 #[test]
117 fn test_mpls_set_label() {
118 let mut mpls_bytes: [u8; Mpls::LEN] = [0x00, 0x00, 0x00, 0x00];
119 let mpls_header = unsafe { mpls_from_bytes_mut(&mut mpls_bytes) };
120
121 mpls_header.set_label(0x12345);
122 assert_eq!(mpls_header.label(), 0x12345);
127 assert_eq!(mpls_bytes, [0x12, 0x34, 0x50, 0x00]);
128
129 mpls_bytes = [0xFF, 0xFF, 0x0F, 0xFF];
131 let mpls_header2 = unsafe { mpls_from_bytes_mut(&mut mpls_bytes) };
132 mpls_header2.set_label(0xABCDE);
133 assert_eq!(mpls_header2.label(), 0xABCDE);
138 assert_eq!(mpls_header2.tc(), 0x07); assert_eq!(mpls_header2.s(), 0x01); assert_eq!(mpls_bytes, [0xAB, 0xCD, 0xEF, 0xFF]);
141 }
142
143 #[test]
144 fn test_mpls_set_tc() {
145 let mut mpls_bytes: [u8; Mpls::LEN] = [0x00, 0x00, 0xA5, 0x00];
146 let mpls_header = unsafe { mpls_from_bytes_mut(&mut mpls_bytes) };
147
148 mpls_header.set_tc(0x06);
149 assert_eq!(mpls_header.tc(), 0x06);
150 assert_eq!(((mpls_bytes[2] & 0xF0) >> 4), 0x0A);
151 assert_eq!((mpls_bytes[2] & 0x01), 0x01);
152 assert_eq!(mpls_bytes, [0x00, 0x00, 0xAD, 0x00]);
153 }
154
155 #[test]
156 fn test_mpls_set_s() {
157 let mut mpls_bytes: [u8; Mpls::LEN] = [0x00, 0x00, 0xA6, 0x00];
158 let mpls_header = unsafe { mpls_from_bytes_mut(&mut mpls_bytes) };
159
160 mpls_header.set_s(0x01);
161 assert_eq!(mpls_header.s(), 0x01);
162 assert_eq!(((mpls_bytes[2] & 0xF0) >> 4), 0x0A); assert_eq!(((mpls_bytes[2] & 0x0E) >> 1), 0x03); assert_eq!(mpls_bytes, [0x00, 0x00, 0xA7, 0x00]);
165 }
166
167 #[test]
168 fn test_mpls_set_ttl() {
169 let mut mpls_bytes: [u8; Mpls::LEN] = [0x12, 0x34, 0x56, 0x00];
170 let mpls_header = unsafe { mpls_from_bytes_mut(&mut mpls_bytes) };
171
172 mpls_header.set_ttl(0xFF);
173 assert_eq!(mpls_header.ttl(), 0xFF);
174 assert_eq!(mpls_bytes, [0x12, 0x34, 0x56, 0xFF]);
175 }
176}