1use core::mem;
2
3#[repr(C, packed)]
10#[derive(Debug, Copy, Clone)]
11#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
12pub struct VxlanHdr {
13 pub flags: u8,
15 pub _reserved1: [u8; 3],
17 pub vni: [u8; 3],
20 pub _reserved2: u8,
21}
22
23pub const VXLAN_I_FLAG_MASK: u8 = 0x08;
25
26impl VxlanHdr {
27 pub const LEN: usize = mem::size_of::<VxlanHdr>();
29
30 pub fn new(vni: u32) -> Self {
40 let mut hdr = VxlanHdr {
41 flags: VXLAN_I_FLAG_MASK,
42 _reserved1: [0u8; 3],
43 vni: [0u8; 3],
44 _reserved2: 0u8,
45 };
46 hdr.set_vni(vni);
47 hdr
48 }
49
50 pub fn with_flags(flags: u8, vni: [u8; 3]) -> Self {
61 Self {
62 flags,
63 _reserved1: [0; 3],
64 vni,
65 _reserved2: 0,
66 }
67 }
68
69 #[inline]
74 pub fn flags(&self) -> u8 {
75 self.flags
76 }
77
78 #[inline]
83 pub fn set_flags(&mut self, flags: u8) {
84 self.flags = flags;
85 }
86
87 #[inline]
92 pub fn vni_present(&self) -> bool {
93 (self.flags & VXLAN_I_FLAG_MASK) == VXLAN_I_FLAG_MASK
94 }
95
96 #[inline]
103 pub fn set_vni_present(&mut self, present: bool) {
104 if present {
105 self.flags |= VXLAN_I_FLAG_MASK;
106 } else {
107 self.flags &= !VXLAN_I_FLAG_MASK;
108 }
109 }
110
111 #[inline]
116 pub fn vni(&self) -> u32 {
117 u32::from_be_bytes([0, self.vni[0], self.vni[1], self.vni[2]])
118 }
119
120 #[inline]
127 pub fn set_vni(&mut self, vni: u32) {
128 let vni_24bit = vni & 0x00FF_FFFF;
129 let vni_bytes = vni_24bit.to_be_bytes();
130 self.vni[0] = vni_bytes[1];
131 self.vni[1] = vni_bytes[2];
132 self.vni[2] = vni_bytes[3];
133 }
134}
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn test_vxlanhdr_len() {
141 assert_eq!(VxlanHdr::LEN, 8, "VXLAN header length should be 8 bytes");
142 }
143
144 #[test]
145 fn test_vxlanhdr_new() {
146 let vni_val: u32 = 0xABCDEF;
147 let hdr = VxlanHdr::new(vni_val);
148 assert_eq!(
149 hdr.flags(),
150 VXLAN_I_FLAG_MASK,
151 "Flags should have I-flag set and others zero"
152 );
153 assert!(hdr.vni_present(), "VNI present flag should be set by new()");
154 assert_eq!(hdr.vni(), vni_val, "VNI should be set correctly by new()");
155 }
156
157 #[test]
158 fn test_flags_management() {
159 let mut hdr = VxlanHdr::new(0x123);
160 hdr.set_flags(0xFF);
161 assert_eq!(hdr.flags(), 0xFF);
162 assert!(
163 hdr.vni_present(),
164 "I-flag should be set if flags byte is 0xFF"
165 );
166 hdr.set_flags(0x00);
167 assert!(
168 !hdr.vni_present(),
169 "I-flag should be clear if flags byte is 0x00"
170 );
171 hdr.set_vni_present(true);
172 assert_eq!(
173 hdr.flags(),
174 VXLAN_I_FLAG_MASK,
175 "set_vni_present(true) should set I-flag"
176 );
177 assert!(hdr.vni_present());
178 hdr.set_vni_present(false);
179 assert_eq!(
180 hdr.flags(),
181 0x00,
182 "set_vni_present(false) should clear I-flag"
183 );
184 assert!(!hdr.vni_present());
185 hdr.set_flags(0xF0);
186 assert!(!hdr.vni_present());
187 hdr.set_vni_present(true);
188 assert_eq!(
189 hdr.flags(),
190 0xF0 | VXLAN_I_FLAG_MASK,
191 "Setting I-flag should preserve other bits"
192 );
193 assert!(hdr.vni_present());
194 hdr.set_vni_present(false);
195 assert_eq!(
196 hdr.flags(),
197 0xF0 & !VXLAN_I_FLAG_MASK,
198 "Clearing I-flag should preserve other bits"
199 );
200 assert!(!hdr.vni_present());
201 }
202
203 #[test]
204 fn test_vni_management() {
205 let mut hdr = VxlanHdr::new(0);
206 let vni_val: u32 = 0xABCDEF;
207 hdr.set_vni(vni_val);
208 assert_eq!(hdr.vni(), vni_val, "VNI should be set correctly");
209 let large_vni: u32 = 0x12ABCDEF;
210 hdr.set_vni(large_vni);
211 assert_eq!(hdr.vni(), 0xABCDEF, "VNI should be masked to 24 bits");
212 hdr.set_vni(0);
213 assert_eq!(hdr.vni(), 0, "VNI should be settable to 0");
214 let max_vni: u32 = 0xFFFFFF;
215 hdr.set_vni(max_vni);
216 assert_eq!(hdr.vni(), max_vni, "Max 24-bit VNI should be settable");
217 hdr.set_vni(0x123456);
218 assert_eq!(hdr.vni(), 0x123456, "VNI should be updated");
219 }
220
221 #[test]
222 fn test_field_storage_and_retrieval_direct_manipulation() {
223 let mut hdr = VxlanHdr::with_flags(0x08, [0xAB, 0xCD, 0xEF]);
224 hdr.flags = 0x08;
225 hdr.vni = [0xAB, 0xCD, 0xEF];
226 assert_eq!(hdr.flags(), 0x08);
227 assert!(hdr.vni_present());
228 assert_eq!(hdr.vni(), 0xABCDEF);
229 hdr.set_vni_present(false);
230 assert_eq!(
231 hdr.flags, 0x00,
232 "Direct field check after set_vni_present(false)"
233 );
234 hdr.set_vni(0x654321);
235 assert_eq!(hdr.vni[0], 0x65, "Byte 0 of vni after set_vni");
236 assert_eq!(hdr.vni[1], 0x43, "Byte 1 of vni after set_vni");
237 assert_eq!(hdr.vni[2], 0x21, "Byte 2 of vni after set_vni");
238 assert_eq!(hdr.vni(), 0x654321);
239 assert_eq!(
240 hdr.vni[0], 0x65,
241 "Byte 0 of vni preserved after set_reserved2"
242 );
243 assert_eq!(hdr.vni(), 0x654321);
244 }
245}