@@ -20,6 +20,9 @@ namespace pcpp
2020#pragma pack(push, 1)
2121 struct geneve_header
2222 {
23+ static constexpr size_t OptionsLengthUnit = 4 ;
24+ static constexpr size_t MaxOptionsLength = ((1 << 6 ) - 1 ) * OptionsLengthUnit;
25+
2326#if (BYTE_ORDER == LITTLE_ENDIAN)
2427 // / Options length in 4-byte units
2528 uint8_t optionsLength : 6 ;
@@ -49,6 +52,33 @@ namespace pcpp
4952 uint8_t vni[3 ];
5053 // / Reserved byte
5154 uint8_t reserved2;
55+
56+ // / @return Options length in bytes
57+ size_t getOptionsLength () const
58+ {
59+ return static_cast <size_t >(optionsLength) * OptionsLengthUnit;
60+ }
61+
62+ // / @param[in] value Options length in bytes
63+ // / @pre value must be divisible by 4 and no greater than MaxOptionsLength
64+ void setOptionsLength (size_t value)
65+ {
66+ optionsLength = static_cast <uint8_t >(value / OptionsLengthUnit);
67+ }
68+
69+ // / @return The 24-bit virtual network identifier
70+ uint32_t getVNI () const
71+ {
72+ return (static_cast <uint32_t >(vni[0 ]) << 16 ) | (static_cast <uint32_t >(vni[1 ]) << 8 ) | vni[2 ];
73+ }
74+
75+ // / @param[in] value The 24-bit virtual network identifier
76+ void setVNI (uint32_t value)
77+ {
78+ vni[0 ] = static_cast <uint8_t >((value >> 16 ) & 0xff );
79+ vni[1 ] = static_cast <uint8_t >((value >> 8 ) & 0xff );
80+ vni[2 ] = static_cast <uint8_t >(value & 0xff );
81+ }
5282 };
5383#pragma pack(pop)
5484 static_assert (sizeof (geneve_header) == 8 , " geneve_header size is not 8 bytes" );
@@ -58,8 +88,19 @@ namespace pcpp
5888#pragma pack(push, 1)
5989 struct geneve_option_header
6090 {
91+ static constexpr size_t DataLengthUnit = 4 ;
92+ static constexpr size_t MaxDataLength = ((1 << 5 ) - 1 ) * DataLengthUnit;
93+ static constexpr uint8_t TypeMask = 0x7f ;
94+ static constexpr uint8_t CriticalBitMask = 0x80 ;
95+
6196 // / Option namespace assigned by IANA
6297 uint16_t optionClass;
98+ // / @return Option class in host byte order
99+ uint16_t getOptionClass () const ;
100+
101+ // / @param[in] value Option class in host byte order
102+ void setOptionClass (uint16_t value);
103+
63104 // / Option type. The most significant bit is the critical bit
64105 uint8_t type;
65106#if (BYTE_ORDER == LITTLE_ENDIAN)
@@ -73,6 +114,60 @@ namespace pcpp
73114 // / Option data length in 4-byte units
74115 uint8_t length : 5 ;
75116#endif
117+
118+ // / @return The 7-bit option type without the critical bit
119+ uint8_t getType () const
120+ {
121+ return extractType (type);
122+ }
123+
124+ // / @param[in] value A raw option type, optionally including the critical bit
125+ // / @return The 7-bit option type without the critical bit
126+ static uint8_t extractType (uint8_t value)
127+ {
128+ return static_cast <uint8_t >(value & TypeMask);
129+ }
130+
131+ // / Round an option data length up to the next 4-byte boundary
132+ // / @param[in] value Unpadded option data length in bytes
133+ // / @return Option data length rounded up to a multiple of 4
134+ static size_t alignDataSize (size_t value)
135+ {
136+ constexpr size_t AlignmentMask = DataLengthUnit - 1 ;
137+ return (value + AlignmentMask) & ~AlignmentMask;
138+ }
139+
140+ // / @return True if the critical bit is set
141+ bool isCritical () const
142+ {
143+ return (type & CriticalBitMask) != 0 ;
144+ }
145+
146+ // / @return Option data length in bytes
147+ size_t getDataSize () const
148+ {
149+ return static_cast <size_t >(length) * DataLengthUnit;
150+ }
151+
152+ // / @param[in] value Option data length in bytes
153+ // / @pre value must be divisible by 4 and no greater than MaxDataLength
154+ void setDataSize (size_t value)
155+ {
156+ length = static_cast <uint8_t >(value / DataLengthUnit);
157+ }
158+
159+ // / @return Total option size including its 4-byte header
160+ size_t getTotalSize () const
161+ {
162+ return sizeof (geneve_option_header) + getDataSize ();
163+ }
164+
165+ // / @param[in] value The 7-bit option type
166+ // / @param[in] critical Whether to set the critical bit
167+ void setType (uint8_t value, bool critical)
168+ {
169+ type = static_cast <uint8_t >(extractType (value) | (critical ? CriticalBitMask : 0 ));
170+ }
76171 };
77172#pragma pack(pop)
78173 static_assert (sizeof (geneve_option_header) == 4 , " geneve_option_header size is not 4 bytes" );
@@ -207,6 +302,7 @@ namespace pcpp
207302 GeneveOptionIterator find (uint16_t optionClass, uint8_t optionType) const ;
208303
209304 // / @return The number of structurally valid options in this range
305+ // / @note This operation has O(n) time complexity, where n is the number of options.
210306 size_t size () const ;
211307
212308 // / @return True if this range contains no options
@@ -254,6 +350,8 @@ namespace pcpp
254350 // / @param[in] dataLen Size of the data in bytes
255351 // / @param[in] prevLayer A pointer to the previous layer
256352 // / @param[in] packet A pointer to the Packet instance where the layer is stored
353+ // / @note This constructor does not validate the input. Use isDataValid() before constructing a standalone
354+ // / parsed layer.
257355 GeneveLayer (uint8_t * data, size_t dataLen, Layer* prevLayer, Packet* packet)
258356 : Layer(data, dataLen, prevLayer, packet, Geneve)
259357 {}
@@ -281,32 +379,38 @@ namespace pcpp
281379 }
282380
283381 // / @return A pointer to the fixed GENEVE header
382+ // / @pre The layer must contain a complete fixed GENEVE header
284383 geneve_header* getGeneveHeader () const
285384 {
286385 return reinterpret_cast <geneve_header*>(m_Data);
287386 }
288387
289388 // / @return The VNI in host byte order
389+ // / @pre The layer must contain a complete fixed GENEVE header
290390 uint32_t getVNI () const ;
291391
292392 // / Set the VNI. Only the least significant 24 bits are used
293393 // / @param[in] vni The VNI to set
394+ // / @pre The layer must contain a complete fixed GENEVE header
294395 void setVNI (uint32_t vni);
295396
296397 // / @return Encapsulated protocol EtherType in host byte order
398+ // / @pre The layer must contain a complete fixed GENEVE header
297399 uint16_t getProtocolType () const ;
298400
299401 // / Set the encapsulated protocol EtherType
300402 // / @param[in] protocolType EtherType in host byte order
403+ // / @pre The layer must contain a complete fixed GENEVE header
301404 void setProtocolType (uint16_t protocolType);
302405
303- // / @return Total options length in bytes
406+ // / @return Total options length in bytes, or zero if the fixed GENEVE header is unavailable or truncated
304407 size_t getOptionsLength () const ;
305408
306- // / @return Number of structurally valid options in this layer
409+ // / @return Number of structurally valid options in this layer, or zero if no valid option range is available
307410 size_t getOptionCount () const ;
308411
309- // / @return A non-owning range over the options in this layer
412+ // / @return A non-owning range over the options in this layer, or an empty range if the fixed GENEVE header is
413+ // / unavailable or truncated
310414 GeneveOptionRange getOptions () const ;
311415
312416 // / Add an option after all existing options
@@ -327,7 +431,8 @@ namespace pcpp
327431 // / Parse the encapsulated protocol according to the Protocol Type field
328432 void parseNextLayer () override ;
329433
330- // / @return Fixed header plus the declared options length
434+ // / @return Zero if no data is available; the available data length if the fixed header is truncated; otherwise,
435+ // / the fixed header plus the declared options length, capped at the available data length
331436 size_t getHeaderLen () const override ;
332437
333438 // / Update the Protocol Type and Critical flag from the following layer and options
0 commit comments