2 * Routines for Gigamon header disassembly (modified from packet-vlan.c)
4 * Dissector for Gigamon Header and Trailer
5 * Copyright Gigamon 2010
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <epan/packet.h>
31 #include <epan/etypes.h>
32 #include <epan/prefs.h>
33 #include <epan/in_cksum.h>
34 #include <epan/crc32-tvb.h>
35 #include <wsutil/crc32.h>
36 #include <wsutil/pint.h>
37 #include <epan/expert.h>
39 #include "packet-ieee8023.h"
41 #define GMHDR_FTYPE_PKTSIZE 1
42 #define GMHDR_FTYPE_SRCPORT_G 2
43 #define GMHDR_FTYPE_TIMESTAMP_LOCAL 3
44 #define GMHDR_FTYPE_TIMESTAMP_NTP 4
45 #define GMHDR_FTYPE_TIMESTAMP_GPS 5
46 #define GMHDR_FTYPE_TIMESTAMP_1588 6
47 #define GMHDR_FTYPE_FCS 7
48 #define GMHDR_FTYPE_SRCPORT_H 8
50 static const value_string gmhdr_ftype_timestamp
[] = {
51 { GMHDR_FTYPE_TIMESTAMP_LOCAL
, "Local" },
52 { GMHDR_FTYPE_TIMESTAMP_NTP
, "NTP" },
53 { GMHDR_FTYPE_TIMESTAMP_GPS
, "GPS" },
54 { GMHDR_FTYPE_TIMESTAMP_1588
, "1588" },
58 #define GMHDR_SRCPORT_G_PLFM_MASK 0x00f80000
59 #define GMHDR_SRCPORT_G_GID_MASK 0x00078000
60 #define GMHDR_SRCPORT_G_BID_MASK 0x00007c00
61 #define GMHDR_SRCPORT_G_PID_MASK 0x000003ff
62 #define GMHDR_SRCPORT_G_PLFM_SHFT 19
63 #define GMHDR_SRCPORT_G_GID_SHFT 15
64 #define GMHDR_SRCPORT_G_BID_SHFT 10
65 #define GMHDR_SRCPORT_G_PID_SHFT 0
67 #define GMHDR_SRCPORT_H_PLFM_MASK 0xFC000000
68 #define GMHDR_SRCPORT_H_GID_MASK 0x03C00000
69 #define GMHDR_SRCPORT_H_BID_MASK 0x003F0000
70 #define GMHDR_SRCPORT_H_SID_MASK 0x0000FC00
71 #define GMHDR_SRCPORT_H_PID_MASK 0x000003FF
72 #define GMHDR_SRCPORT_H_PLFM_SHFT 26
73 #define GMHDR_SRCPORT_H_GID_SHFT 20
74 #define GMHDR_SRCPORT_H_BID_SHFT 16
75 #define GMHDR_SRCPORT_H_SID_SHFT 10
76 #define GMHDR_SRCPORT_H_PID_SHFT 0
78 static const value_string gmhdr_plfm_str
[] = {
91 static gboolean gmhdr_summary_in_tree
= TRUE
;
92 static gboolean gmtrailer_summary_in_tree
= TRUE
;
93 static gboolean gmhdr_decode_timestamp_trailer
= TRUE
;
95 static int proto_gmhdr
= -1;
96 static int proto_gmtrailer
= -1;
97 static int hf_gmhdr_srcport_g
= -1;
98 static int hf_gmhdr_srcport_g_plfm
= -1;
99 static int hf_gmhdr_srcport_g_gid
= -1;
100 static int hf_gmhdr_srcport_g_bid
= -1;
101 static int hf_gmhdr_srcport_g_pid
= -1;
102 static int hf_gmhdr_pktsize
= -1;
103 static int hf_gmhdr_timestamp
= -1;
104 static int hf_gmhdr_generic
= -1;
105 static int hf_gmhdr_etype
= -1;
106 static int hf_gmhdr_len
= -1;
107 static int hf_gmhdr_trailer
= -1;
108 static int hf_gmhdr_origcrc
= -1;
109 static int hf_gmhdr_srcport_h
= -1;
110 static int hf_gmhdr_srcport_h_plfm
= -1;
111 static int hf_gmhdr_srcport_h_gid
= -1;
112 static int hf_gmhdr_srcport_h_bid
= -1;
113 static int hf_gmhdr_srcport_h_sid
= -1;
114 static int hf_gmhdr_srcport_h_pid
= -1;
116 static int hf_gmtrailer_origcrc
= -1;
117 static int hf_gmtrailer_portid
= -1;
118 static int hf_gmtrailer_timestamp
= -1;
120 static gint ett_gmhdr
= -1;
121 static gint ett_srcport
= -1;
122 static gint ett_gmtrailer
= -1;
124 static expert_field ei_gmhdr_field_length_invalid
= EI_INIT
;
125 static expert_field ei_gmhdr_len
= EI_INIT
;
128 dissect_gmtlv(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*gmhdr_tree
, guint offset
, guint16 length
)
131 proto_tree
*srcport_tree
;
135 guint16 tl
= tvb_get_ntohs(tvb
, offset
);
136 offset
+= 2; /* type + len */
141 case GMHDR_FTYPE_SRCPORT_G
: {
143 guint32 tv
= tvb_get_ntohl(tvb
, offset
) >> 8; /* Only 24-bit field */
146 expert_add_info_format(pinfo
, gmhdr_tree
, &ei_gmhdr_field_length_invalid
, "Field length %u invalid", fl
);
149 ti
= proto_tree_add_item(gmhdr_tree
, hf_gmhdr_srcport_g
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
150 srcport_tree
= proto_item_add_subtree(ti
, ett_srcport
);
151 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_g_plfm
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
152 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_g_gid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
153 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_g_bid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
154 ti
= proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_g_pid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
155 /* If not GV-2404, we need different formula here */
156 pid
= ((tv
& GMHDR_SRCPORT_G_PID_MASK
) >> GMHDR_SRCPORT_G_PID_SHFT
) - 24;
157 if (pid
>= 1 && pid
<= 4) {
158 proto_item_append_text(ti
, " (g%d)", pid
);
162 case GMHDR_FTYPE_PKTSIZE
:
164 expert_add_info_format(pinfo
, gmhdr_tree
, &ei_gmhdr_field_length_invalid
, "Field length %u invalid", fl
);
167 proto_tree_add_item(gmhdr_tree
, hf_gmhdr_pktsize
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
169 case GMHDR_FTYPE_TIMESTAMP_LOCAL
:
170 case GMHDR_FTYPE_TIMESTAMP_NTP
:
171 case GMHDR_FTYPE_TIMESTAMP_GPS
:
172 case GMHDR_FTYPE_TIMESTAMP_1588
:
174 expert_add_info_format(pinfo
, gmhdr_tree
, &ei_gmhdr_field_length_invalid
, "Field length %u invalid", fl
);
177 ti
= proto_tree_add_item(gmhdr_tree
, hf_gmhdr_timestamp
, tvb
, offset
, fl
, ENC_TIME_TIMESPEC
|ENC_BIG_ENDIAN
);
178 proto_item_append_text(ti
, "; Source: %s", val_to_str_const(tl
>>8, gmhdr_ftype_timestamp
, "Unknown"));
180 case GMHDR_FTYPE_FCS
: {
182 expert_add_info_format(pinfo
, gmhdr_tree
, &ei_gmhdr_field_length_invalid
, "Field length %u invalid", fl
);
185 ti
= proto_tree_add_item(gmhdr_tree
, hf_gmhdr_origcrc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
186 proto_item_append_text(ti
, ", CRC (Not Verified)");
189 case GMHDR_FTYPE_SRCPORT_H
: {
191 expert_add_info_format(pinfo
, gmhdr_tree
, &ei_gmhdr_field_length_invalid
, "Field length %u invalid", fl
);
194 ti
= proto_tree_add_item(gmhdr_tree
, hf_gmhdr_srcport_h
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
195 srcport_tree
= proto_item_add_subtree(ti
, ett_srcport
);
196 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_h_plfm
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
197 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_h_gid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
198 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_h_bid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
199 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_h_sid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
200 proto_tree_add_item(srcport_tree
, hf_gmhdr_srcport_h_pid
, tvb
, offset
, fl
, ENC_BIG_ENDIAN
);
204 ti
= proto_tree_add_item(gmhdr_tree
, hf_gmhdr_generic
, tvb
, offset
, fl
, ENC_NA
);
205 proto_item_append_text(ti
, " [Id: %u, Length: %u]", tl
>> 8, fl
);
208 /* Adjust for the field length */
217 dissect_gmhdr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
221 volatile guint16 encap_proto
;
222 volatile gboolean is_802_2
;
223 proto_tree
*volatile gmhdr_tree
= NULL
;
224 volatile guint offset
= 0;
226 length
= tvb_get_guint8(tvb
, offset
); /* Length of the Gigamon header */
229 ti
= proto_tree_add_item(tree
, proto_gmhdr
, tvb
, offset
, length
, ENC_NA
);
231 if (gmhdr_summary_in_tree
) {
232 proto_item_append_text(ti
, ", Length: %u", length
);
235 gmhdr_tree
= proto_item_add_subtree(ti
, ett_gmhdr
);
236 dissect_gmtlv(tvb
, pinfo
, gmhdr_tree
, offset
+1, length
-1);
241 encap_proto
= tvb_get_ntohs(tvb
, offset
);
243 if (encap_proto
<= IEEE_802_3_MAX_LEN
) {
244 /* Is there an 802.2 layer? I can tell by looking at the first 2
245 bytes after the GMHDR header. If they are 0xffff, then what
246 follows the GMHDR header is an IPX payload, meaning no 802.2.
247 (IPX/SPX is they only thing that can be contained inside a
248 straight 802.3 packet, so presumably the same applies for
249 Ethernet GMHDR packets). A non-0xffff value means that there's an
250 802.2 layer inside the GMHDR layer */
253 /* Don't throw an exception for this check (even a BoundsError) */
254 if (tvb_length_remaining(tvb
, offset
) >= 2) {
255 if (tvb_get_ntohs(tvb
, offset
) == 0xffff) {
260 dissect_802_3(encap_proto
, is_802_2
, tvb
, offset
, pinfo
, tree
, gmhdr_tree
,
261 hf_gmhdr_len
, hf_gmhdr_trailer
, &ei_gmhdr_len
, 0);
263 ethertype(encap_proto
, tvb
, offset
, pinfo
, tree
, gmhdr_tree
,
264 hf_gmhdr_etype
, hf_gmhdr_trailer
, 0);
269 dissect_gmtimestamp_trailer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
)
272 guint tvblen
, trailer_len
= 18;
273 proto_tree
*gmtrailer_tree
= NULL
;
275 guint32 orig_crc
, new_crc
, comp_crc
;
279 struct tm
*tm
= NULL
;
281 if ( ! gmhdr_decode_timestamp_trailer
)
284 /* See if this packet has a Gigamon trailer, if yes, then decode it */
285 /* (Don't throw any exceptions while checking for the trailer). */
286 tvblen
= tvb_length(tvb
); /* end+1 */
287 if (tvblen
< trailer_len
)
290 orig_crc
= tvb_get_ntohl(tvb
, offset
);
291 new_crc
= tvb_get_ntohl(tvb
, tvblen
- 4);
293 /* Verify the checksum; if not valid, it means that the trailer is not valid */
294 comp_crc
= CRC32C_SWAP(crc32_ccitt_tvb_seed(tvb
, 14, CRC32C_SWAP(~orig_crc
)));
295 if (comp_crc
!= new_crc
)
298 /* OK: We appear to have a Gigamon trailer */
300 ti
= proto_tree_add_item(tree
, proto_gmtrailer
, tvb
, offset
, trailer_len
- 4, ENC_NA
);
302 if (gmtrailer_summary_in_tree
) {
304 port_num
= tvb_get_ntohs(tvb
, offset
);
306 gmtimev
.secs
= tvb_get_ntohl(tvb
, offset
);
308 gmtimev
.nsecs
= tvb_get_ntohl(tvb
, offset
);
310 tm
= localtime(&gmtimev
.secs
);
311 proto_item_append_text(ti
, ", Port: %d, Timestamp: %d:%d:%d.%d", port_num
, tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
, gmtimev
.nsecs
);
315 gmtrailer_tree
= proto_item_add_subtree(ti
, ett_gmtrailer
);
316 proto_tree_add_item(gmtrailer_tree
, hf_gmtrailer_origcrc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
317 proto_tree_add_item(gmtrailer_tree
, hf_gmtrailer_portid
, tvb
, offset
+4, 2, ENC_BIG_ENDIAN
);
318 proto_tree_add_item(gmtrailer_tree
, hf_gmtrailer_timestamp
, tvb
, offset
+6, 8, ENC_TIME_TIMESPEC
|ENC_BIG_ENDIAN
);
325 dissect_gmtrailer(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void *data _U_
)
328 guint tvblen
, length
;
329 proto_tree
*gmhdr_tree
= NULL
;
331 guint16 cksum
, comp_cksum
, extra_trailer
;
333 /* See if this packet has a Gigamon trailer, if yes, then decode it */
334 /* (Don't throw any exceptions while checking for the trailer). */
335 tvblen
= tvb_length(tvb
); /* end+1 */
339 if (tvb_get_ntohs(tvb
, tvblen
-4) != ETHERTYPE_GIGAMON
) {
343 if (tvb_get_ntohs(tvb
, tvblen
-8) == ETHERTYPE_GIGAMON
) {
349 length
= tvb_get_guint8(tvb
, tvblen
-extra_trailer
-5); /* length of Gigamon header */
350 if ((tvblen
-extra_trailer
-5) != length
)
353 offset
= tvblen
- extra_trailer
- 5 - length
;
355 cksum
= tvb_get_ntohs(tvb
, tvblen
-extra_trailer
-2);
357 /* Verify the checksum; if not valid, it means that the trailer is not valid */
360 vec
.len
= length
+ 3;
361 vec
.ptr
= tvb_get_ptr(tvb
, offset
, vec
.len
);
363 comp_cksum
= in_cksum(&vec
, 1);
364 if (pntohs(&comp_cksum
) != cksum
) {
369 /* OK: We appear to have a Gigamon trailer */
371 ti
= proto_tree_add_item(tree
, proto_gmhdr
, tvb
, offset
, length
+ 5, ENC_NA
);
373 if (gmhdr_summary_in_tree
) {
374 proto_item_append_text(ti
, ", Length: %u, Checksum: 0x%x", length
, cksum
);
377 gmhdr_tree
= proto_item_add_subtree(ti
, ett_gmhdr
);
379 dissect_gmtlv(tvb
, pinfo
, gmhdr_tree
, offset
, length
);
381 proto_tree_add_item(tree
, hf_gmhdr_trailer
, tvb
, length
+ 5, extra_trailer
, ENC_BIG_ENDIAN
);
388 proto_register_gmhdr(void)
390 static hf_register_info hf
[] = {
391 { &hf_gmhdr_srcport_g
, {
392 "Src Port", "gmhdr.srcport_g", FT_UINT24
, BASE_HEX
,
393 NULL
, 0, "Original Source Port", HFILL
}},
394 { &hf_gmhdr_srcport_g_plfm
, {
395 "Platform Id", "gmhdr.srcport_g_plfm", FT_UINT24
, BASE_DEC
,
396 VALS(gmhdr_plfm_str
), GMHDR_SRCPORT_G_PLFM_MASK
, "Original Platform Id", HFILL
}},
397 { &hf_gmhdr_srcport_g_gid
, {
398 "Group Id", "gmhdr.srcport_g_gid", FT_UINT24
, BASE_DEC
,
399 NULL
, GMHDR_SRCPORT_G_GID_MASK
, "Original Source Group Id", HFILL
}},
400 { &hf_gmhdr_srcport_g_bid
, {
401 "Box Id", "gmhdr.srcport_g_bid", FT_UINT24
, BASE_DEC
,
402 NULL
, GMHDR_SRCPORT_G_BID_MASK
, "Original Source Box Id", HFILL
}},
403 { &hf_gmhdr_srcport_g_pid
, {
404 "Port Id", "gmhdr.srcport_g_pid", FT_UINT24
, BASE_DEC
,
405 NULL
, GMHDR_SRCPORT_G_PID_MASK
, "Original Source Port Id", HFILL
}},
406 { &hf_gmhdr_pktsize
, {
407 "Original Packet Size", "gmhdr.pktsize", FT_UINT16
, BASE_DEC
,
408 NULL
, 0, NULL
, HFILL
}},
409 { &hf_gmhdr_timestamp
, {
410 "Time Stamp", "gmhdr.timestamp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
411 NULL
, 0x0, NULL
, HFILL
}},
412 { &hf_gmhdr_generic
, {
413 "Generic Field", "gmhdr.generic", FT_BYTES
, BASE_NONE
,
414 NULL
, 0x0, NULL
, HFILL
}},
416 "Type", "gmhdr.etype", FT_UINT16
, BASE_HEX
,
417 VALS(etype_vals
), 0x0, "Ethertype", HFILL
}},
419 "Length", "gmhdr.len", FT_UINT16
, BASE_DEC
,
420 NULL
, 0x0, NULL
, HFILL
}},
421 { &hf_gmhdr_origcrc
, {
422 "Original CRC", "gmhdr.crc", FT_UINT32
, BASE_HEX
,
423 NULL
, 0x0, "Original Packet CRC", HFILL
}},
424 { &hf_gmhdr_srcport_h
, {
425 "Src Port", "gmhdr.srcport", FT_UINT32
, BASE_HEX
,
426 NULL
, 0, "Original Source Port", HFILL
}},
427 { &hf_gmhdr_srcport_h_plfm
, {
428 "Platform Id", "gmhdr.srcport_plfm", FT_UINT32
, BASE_DEC
,
429 VALS(gmhdr_plfm_str
), GMHDR_SRCPORT_H_PLFM_MASK
, "Original Platform Id", HFILL
}},
430 { &hf_gmhdr_srcport_h_gid
, {
431 "Group Id", "gmhdr.srcport_gid", FT_UINT32
, BASE_DEC
,
432 NULL
, GMHDR_SRCPORT_H_GID_MASK
, "Original Source Group Id", HFILL
}},
433 { &hf_gmhdr_srcport_h_bid
, {
434 "Box Id", "gmhdr.srcport_bid", FT_UINT32
, BASE_DEC
,
435 NULL
, GMHDR_SRCPORT_H_BID_MASK
, "Original Source Box Id", HFILL
}},
436 { &hf_gmhdr_srcport_h_sid
, {
437 "Slot Id", "gmhdr.srcport_sid", FT_UINT32
, BASE_DEC
,
438 NULL
, GMHDR_SRCPORT_H_SID_MASK
, "Original Source Slot Id", HFILL
}},
439 { &hf_gmhdr_srcport_h_pid
, {
440 "Port Id", "gmhdr.srcport_pid", FT_UINT32
, BASE_DEC
,
441 NULL
, GMHDR_SRCPORT_H_PID_MASK
, "Original Source Port Id", HFILL
}},
442 { &hf_gmhdr_trailer
, {
443 "Trailer", "gmhdr.trailer", FT_BYTES
, BASE_NONE
,
444 NULL
, 0x0, "GMHDR Trailer", HFILL
}},
446 static hf_register_info gmtrailer_hf
[] = {
447 { &hf_gmtrailer_origcrc
, {
448 "Original CRC", "gmtrailer.crc", FT_UINT32
, BASE_HEX
,
449 NULL
, 0x0, "Original Packet CRC", HFILL
}},
450 { &hf_gmtrailer_portid
, {
451 "Src Port", "gmtrailer.portid", FT_UINT16
, BASE_HEX
,
452 NULL
, 0x0, "Origin Source Port", HFILL
}},
453 { &hf_gmtrailer_timestamp
, {
454 "Time Stamp", "gmtrailer.timestamp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
455 NULL
, 0x0, NULL
, HFILL
}},
457 static gint
*ett
[] = {
461 static gint
*gmtrailer_ett
[] = {
464 static ei_register_info ei
[] = {
465 { &ei_gmhdr_field_length_invalid
, { "gmhdr.field_length_invalid", PI_MALFORMED
, PI_ERROR
, "Field length invalid", EXPFILL
}},
466 { &ei_gmhdr_len
, { "gmhdr.len.past_end", PI_MALFORMED
, PI_ERROR
, "Length field value goes past the end of the payload", EXPFILL
}},
469 module_t
*gmhdr_module
;
470 module_t
*gmtrailer_module
;
471 expert_module_t
* expert_gmhdr
;
473 proto_gmhdr
= proto_register_protocol("Gigamon Header", "GMHDR", "gmhdr");
474 proto_register_field_array(proto_gmhdr
, hf
, array_length(hf
));
475 proto_register_subtree_array(ett
, array_length(ett
));
476 expert_gmhdr
= expert_register_protocol(proto_gmhdr
);
477 expert_register_field_array(expert_gmhdr
, ei
, array_length(ei
));
479 proto_gmtrailer
= proto_register_protocol("Gigamon Trailer", "GMTRAILER", "gmtrailer");
480 proto_register_field_array(proto_gmtrailer
, gmtrailer_hf
, array_length(gmtrailer_hf
));
481 proto_register_subtree_array(gmtrailer_ett
, array_length(gmtrailer_ett
));
483 gmhdr_module
= prefs_register_protocol(proto_gmhdr
, NULL
);
484 prefs_register_bool_preference(gmhdr_module
, "summary_in_tree",
485 "Show Gigamon header summary in protocol tree",
486 "Whether the Gigamon header summary line should be shown in the protocol tree",
487 &gmhdr_summary_in_tree
);
489 gmtrailer_module
= prefs_register_protocol(proto_gmtrailer
, NULL
);
490 prefs_register_bool_preference(gmtrailer_module
, "summary_in_tree",
491 "Show Gigamon Trailer summary in protocol tree",
492 "Whether the Gigamon Trailer summary line should be shown in the protocol tree",
493 &gmtrailer_summary_in_tree
);
494 prefs_register_bool_preference(gmtrailer_module
, "decode_trailer_timestamp",
495 "Decode Gigamon HW timestamp and source id in trailer",
496 "Whether the Gigamon trailer containing HW timestamp, source id and original CRC should be decoded",
497 &gmhdr_decode_timestamp_trailer
);
501 proto_reg_handoff_gmhdr(void)
503 dissector_handle_t gmhdr_handle
;
505 gmhdr_handle
= create_dissector_handle(dissect_gmhdr
, proto_gmhdr
);
506 dissector_add_uint("ethertype", ETHERTYPE_GIGAMON
, gmhdr_handle
);
507 heur_dissector_add("eth.trailer", dissect_gmtrailer
, proto_gmhdr
);
509 heur_dissector_add("eth.trailer", dissect_gmtimestamp_trailer
, proto_gmtrailer
);