1#![deny(missing_docs)]
9
10use packet_dissector_core::dissector::{DispatchHint, DissectResult, Dissector};
11use packet_dissector_core::error::PacketError;
12use packet_dissector_core::field::{FieldDescriptor, FieldType, FieldValue};
13use packet_dissector_core::packet::DissectBuffer;
14use packet_dissector_core::util::{read_be_u16, read_be_u24};
15
16const MIN_HEADER_SIZE: usize = 8;
22
23const FD_VERSION: usize = 0;
25const FD_OPT_LEN: usize = 1;
26const FD_OAM: usize = 2;
27const FD_CRITICAL: usize = 3;
28const FD_RESERVED: usize = 4;
29const FD_PROTOCOL_TYPE: usize = 5;
30const FD_VNI: usize = 6;
31const FD_RESERVED2: usize = 7;
32const FD_OPTIONS: usize = 8;
33
34static FIELD_DESCRIPTORS: &[FieldDescriptor] = &[
35 FieldDescriptor::new("version", "Version", FieldType::U8),
36 FieldDescriptor::new("opt_len", "Options Length", FieldType::U8),
37 FieldDescriptor::new("oam", "OAM", FieldType::U8),
38 FieldDescriptor::new("critical", "Critical Options Present", FieldType::U8),
39 FieldDescriptor::new("reserved", "Reserved", FieldType::U8),
40 FieldDescriptor::new("protocol_type", "Protocol Type", FieldType::U16),
41 FieldDescriptor::new("vni", "Virtual Network Identifier", FieldType::U32),
42 FieldDescriptor::new("reserved2", "Reserved", FieldType::U8),
43 FieldDescriptor::new("options", "Options", FieldType::Bytes).optional(),
44];
45
46pub struct GeneveDissector;
48
49impl Dissector for GeneveDissector {
50 fn name(&self) -> &'static str {
51 "Generic Network Virtualization Encapsulation"
52 }
53
54 fn short_name(&self) -> &'static str {
55 "GENEVE"
56 }
57
58 fn field_descriptors(&self) -> &'static [FieldDescriptor] {
59 FIELD_DESCRIPTORS
60 }
61
62 fn dissect<'pkt>(
63 &self,
64 data: &'pkt [u8],
65 buf: &mut DissectBuffer<'pkt>,
66 offset: usize,
67 ) -> Result<DissectResult, PacketError> {
68 if data.len() < MIN_HEADER_SIZE {
69 return Err(PacketError::Truncated {
70 expected: MIN_HEADER_SIZE,
71 actual: data.len(),
72 });
73 }
74
75 let version = (data[0] >> 6) & 0x03;
77 if version != 0 {
78 return Err(PacketError::InvalidFieldValue {
79 field: "version",
80 value: version as u32,
81 });
82 }
83
84 let opt_len = data[0] & 0x3F;
86 let header_len = MIN_HEADER_SIZE + (opt_len as usize) * 4;
87
88 if data.len() < header_len {
89 return Err(PacketError::Truncated {
90 expected: header_len,
91 actual: data.len(),
92 });
93 }
94
95 let oam = (data[1] >> 7) & 1;
97 let critical = (data[1] >> 6) & 1;
99 let reserved = data[1] & 0x3F;
101
102 let protocol_type = read_be_u16(data, 2)?;
104
105 let vni = read_be_u24(data, 4)?;
107
108 let reserved2 = data[7];
110
111 buf.begin_layer(
112 self.short_name(),
113 None,
114 FIELD_DESCRIPTORS,
115 offset..offset + header_len,
116 );
117 buf.push_field(
118 &FIELD_DESCRIPTORS[FD_VERSION],
119 FieldValue::U8(version),
120 offset..offset + 1,
121 );
122 buf.push_field(
123 &FIELD_DESCRIPTORS[FD_OPT_LEN],
124 FieldValue::U8(opt_len),
125 offset..offset + 1,
126 );
127 buf.push_field(
128 &FIELD_DESCRIPTORS[FD_OAM],
129 FieldValue::U8(oam),
130 offset + 1..offset + 2,
131 );
132 buf.push_field(
133 &FIELD_DESCRIPTORS[FD_CRITICAL],
134 FieldValue::U8(critical),
135 offset + 1..offset + 2,
136 );
137 buf.push_field(
138 &FIELD_DESCRIPTORS[FD_RESERVED],
139 FieldValue::U8(reserved),
140 offset + 1..offset + 2,
141 );
142 buf.push_field(
143 &FIELD_DESCRIPTORS[FD_PROTOCOL_TYPE],
144 FieldValue::U16(protocol_type),
145 offset + 2..offset + 4,
146 );
147 buf.push_field(
148 &FIELD_DESCRIPTORS[FD_VNI],
149 FieldValue::U32(vni),
150 offset + 4..offset + 7,
151 );
152 buf.push_field(
153 &FIELD_DESCRIPTORS[FD_RESERVED2],
154 FieldValue::U8(reserved2),
155 offset + 7..offset + 8,
156 );
157
158 if opt_len > 0 {
162 buf.push_field(
163 &FIELD_DESCRIPTORS[FD_OPTIONS],
164 FieldValue::Bytes(&data[8..header_len]),
165 offset + 8..offset + header_len,
166 );
167 }
168 buf.end_layer();
169
170 Ok(DissectResult::new(
171 header_len,
172 DispatchHint::ByEtherType(protocol_type),
173 ))
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 fn dissect(data: &[u8]) -> Result<(DissectBuffer<'_>, DissectResult), PacketError> {
201 let mut buf = DissectBuffer::new();
202 let result = GeneveDissector.dissect(data, &mut buf, 0)?;
203 Ok((buf, result))
204 }
205
206 #[test]
207 fn parse_geneve_basic() {
208 let raw: &[u8] = &[
211 0x00, 0x00, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, ];
217 let (buf, result) = dissect(raw).unwrap();
218 assert_eq!(result.bytes_consumed, 8);
219 assert_eq!(result.next, DispatchHint::ByEtherType(0x6558));
220
221 let layer = buf.layer_by_name("GENEVE").unwrap();
222 assert_eq!(
223 buf.field_by_name(layer, "version").unwrap().value,
224 FieldValue::U8(0)
225 );
226 assert_eq!(
227 buf.field_by_name(layer, "opt_len").unwrap().value,
228 FieldValue::U8(0)
229 );
230 assert_eq!(
231 buf.field_by_name(layer, "oam").unwrap().value,
232 FieldValue::U8(0)
233 );
234 assert_eq!(
235 buf.field_by_name(layer, "critical").unwrap().value,
236 FieldValue::U8(0)
237 );
238 assert_eq!(
239 buf.field_by_name(layer, "reserved").unwrap().value,
240 FieldValue::U8(0)
241 );
242 assert_eq!(
243 buf.field_by_name(layer, "protocol_type").unwrap().value,
244 FieldValue::U16(0x6558)
245 );
246 assert_eq!(
247 buf.field_by_name(layer, "vni").unwrap().value,
248 FieldValue::U32(1)
249 );
250 assert_eq!(
251 buf.field_by_name(layer, "reserved2").unwrap().value,
252 FieldValue::U8(0)
253 );
254 assert!(buf.field_by_name(layer, "options").is_none());
255 }
256
257 #[test]
258 fn parse_geneve_invalid_version() {
259 let raw: &[u8] = &[
261 0x40, 0x00, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, ];
267 let err = GeneveDissector
268 .dissect(raw, &mut DissectBuffer::new(), 0)
269 .unwrap_err();
270 assert!(matches!(
271 err,
272 PacketError::InvalidFieldValue {
273 field: "version",
274 value: 1
275 }
276 ));
277 }
278
279 #[test]
280 fn parse_geneve_with_options() {
281 let raw: &[u8] = &[
283 0x02, 0x00, 0x65, 0x58, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
290 ];
291 let (buf, result) = dissect(raw).unwrap();
292 assert_eq!(result.bytes_consumed, 16);
293
294 let layer = buf.layer_by_name("GENEVE").unwrap();
295 assert_eq!(
296 buf.field_by_name(layer, "opt_len").unwrap().value,
297 FieldValue::U8(2)
298 );
299 assert_eq!(
300 buf.field_by_name(layer, "vni").unwrap().value,
301 FieldValue::U32(10)
302 );
303 assert_eq!(
304 buf.field_by_name(layer, "options").unwrap().value,
305 FieldValue::Bytes(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08])
306 );
307 }
308
309 #[test]
310 fn parse_geneve_oam_flag() {
311 let raw: &[u8] = &[
313 0x00, 0x80, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, ];
319 let (buf, _) = dissect(raw).unwrap();
320 let layer = buf.layer_by_name("GENEVE").unwrap();
321 assert_eq!(
322 buf.field_by_name(layer, "oam").unwrap().value,
323 FieldValue::U8(1)
324 );
325 assert_eq!(
326 buf.field_by_name(layer, "critical").unwrap().value,
327 FieldValue::U8(0)
328 );
329 }
330
331 #[test]
332 fn parse_geneve_critical_flag() {
333 let raw: &[u8] = &[
335 0x00, 0x40, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, ];
341 let (buf, _) = dissect(raw).unwrap();
342 let layer = buf.layer_by_name("GENEVE").unwrap();
343 assert_eq!(
344 buf.field_by_name(layer, "oam").unwrap().value,
345 FieldValue::U8(0)
346 );
347 assert_eq!(
348 buf.field_by_name(layer, "critical").unwrap().value,
349 FieldValue::U8(1)
350 );
351 }
352
353 #[test]
354 fn parse_geneve_vni() {
355 let raw: &[u8] = &[
357 0x00, 0x00, 0x65, 0x58, 0xAB, 0xCD, 0xEF, 0x00, ];
363 let (buf, _) = dissect(raw).unwrap();
364 let layer = buf.layer_by_name("GENEVE").unwrap();
365 assert_eq!(
366 buf.field_by_name(layer, "vni").unwrap().value,
367 FieldValue::U32(0x00AB_CDEF)
368 );
369 }
370
371 #[test]
372 fn parse_geneve_dispatch_ipv6() {
373 let raw: &[u8] = &[
375 0x00, 0x00, 0x86, 0xDD, 0x00, 0x00, 0x01, 0x00, ];
381 let (_, result) = dissect(raw).unwrap();
382 assert_eq!(result.next, DispatchHint::ByEtherType(0x86DD));
383 }
384
385 #[test]
386 fn parse_geneve_truncated() {
387 let raw: &[u8] = &[0x00, 0x00, 0x65, 0x58, 0x00, 0x00, 0x01]; let err = GeneveDissector
389 .dissect(raw, &mut DissectBuffer::new(), 0)
390 .unwrap_err();
391 assert!(matches!(
392 err,
393 PacketError::Truncated {
394 expected: 8,
395 actual: 7
396 }
397 ));
398 }
399
400 #[test]
401 fn parse_geneve_truncated_options() {
402 let raw: &[u8] = &[
404 0x01, 0x00, 0x65, 0x58, 0x00, 0x00, 0x01, 0x00, ];
411 let err = GeneveDissector
412 .dissect(raw, &mut DissectBuffer::new(), 0)
413 .unwrap_err();
414 assert!(matches!(
415 err,
416 PacketError::Truncated {
417 expected: 12,
418 actual: 8
419 }
420 ));
421 }
422
423 #[test]
424 fn parse_geneve_with_offset() {
425 let raw: &[u8] = &[
426 0x01, 0xC0, 0x65, 0x58, 0x00, 0x00, 0x0A, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, ];
433 let mut buf = DissectBuffer::new();
434 let result = GeneveDissector.dissect(raw, &mut buf, 100).unwrap();
435 assert_eq!(result.bytes_consumed, 12);
436
437 let layer = buf.layer_by_name("GENEVE").unwrap();
438 assert_eq!(layer.range, 100..112);
439 assert_eq!(buf.field_by_name(layer, "version").unwrap().range, 100..101);
440 assert_eq!(
441 buf.field_by_name(layer, "protocol_type").unwrap().range,
442 102..104
443 );
444 assert_eq!(buf.field_by_name(layer, "vni").unwrap().range, 104..107);
445 assert_eq!(buf.field_by_name(layer, "options").unwrap().range, 108..112);
446 }
447
448 #[test]
449 fn parse_geneve_all_invalid_versions() {
450 for version in [1u8, 2, 3] {
453 let raw: &[u8] = &[
454 version << 6, 0x00,
456 0x65,
457 0x58,
458 0x00,
459 0x00,
460 0x01,
461 0x00,
462 ];
463 let err = GeneveDissector
464 .dissect(raw, &mut DissectBuffer::new(), 0)
465 .unwrap_err();
466 assert!(
467 matches!(
468 err,
469 PacketError::InvalidFieldValue {
470 field: "version",
471 value,
472 } if value == u32::from(version)
473 ),
474 "expected InvalidFieldValue for Ver={version}, got {err:?}",
475 );
476 }
477 }
478
479 #[test]
480 fn parse_geneve_reserved_bits_set() {
481 let raw: &[u8] = &[
485 0x00, 0x3F, 0x65, 0x58, 0x00, 0x00, 0x01, 0xFF, ];
491 let (buf, _) = dissect(raw).unwrap();
492 let layer = buf.layer_by_name("GENEVE").unwrap();
493 assert_eq!(
494 buf.field_by_name(layer, "reserved").unwrap().value,
495 FieldValue::U8(0x3F)
496 );
497 assert_eq!(
498 buf.field_by_name(layer, "reserved2").unwrap().value,
499 FieldValue::U8(0xFF)
500 );
501 assert_eq!(
503 buf.field_by_name(layer, "oam").unwrap().value,
504 FieldValue::U8(0)
505 );
506 assert_eq!(
507 buf.field_by_name(layer, "critical").unwrap().value,
508 FieldValue::U8(0)
509 );
510 }
511
512 #[test]
513 fn parse_geneve_max_opt_len() {
514 const MAX_OPT_LEN_WORDS: u8 = 0x3F;
519 const OPTIONS_BYTES: usize = MAX_OPT_LEN_WORDS as usize * 4;
520 const TOTAL_HEADER: usize = 8 + OPTIONS_BYTES;
521
522 let mut raw = vec![0u8; TOTAL_HEADER];
523 raw[0] = MAX_OPT_LEN_WORDS; raw[1] = 0x00; raw[2] = 0x65;
526 raw[3] = 0x58; raw[4] = 0x00;
528 raw[5] = 0x00;
529 raw[6] = 0x2A; raw[7] = 0x00;
531 for (i, slot) in raw[8..].iter_mut().enumerate() {
532 *slot = (i & 0xFF) as u8;
533 }
534
535 let (buf, result) = dissect(&raw).unwrap();
536 assert_eq!(result.bytes_consumed, TOTAL_HEADER);
537 assert_eq!(result.next, DispatchHint::ByEtherType(0x6558));
538
539 let layer = buf.layer_by_name("GENEVE").unwrap();
540 assert_eq!(layer.range, 0..TOTAL_HEADER);
541 assert_eq!(
542 buf.field_by_name(layer, "opt_len").unwrap().value,
543 FieldValue::U8(MAX_OPT_LEN_WORDS)
544 );
545 let options = buf.field_by_name(layer, "options").unwrap();
546 assert_eq!(options.range, 8..TOTAL_HEADER);
547 assert_eq!(options.value, FieldValue::Bytes(&raw[8..TOTAL_HEADER]));
548 }
549
550 #[test]
551 fn field_descriptors_consistent() {
552 let descs = GeneveDissector.field_descriptors();
553 assert_eq!(descs.len(), 9);
554 assert_eq!(descs[FD_VERSION].name, "version");
555 assert_eq!(descs[FD_OPT_LEN].name, "opt_len");
556 assert_eq!(descs[FD_OAM].name, "oam");
557 assert_eq!(descs[FD_CRITICAL].name, "critical");
558 assert_eq!(descs[FD_RESERVED].name, "reserved");
559 assert_eq!(descs[FD_PROTOCOL_TYPE].name, "protocol_type");
560 assert_eq!(descs[FD_VNI].name, "vni");
561 assert_eq!(descs[FD_RESERVED2].name, "reserved2");
562 assert_eq!(descs[FD_OPTIONS].name, "options");
563 }
564}