2 * Routines for the disassembly of Cisco's ERSPAN protocol
6 * Copyright 2005 Joerg Mayer (see AUTHORS file)
7 * Updates for newer versions by Jason Masker <jason at masker.net>
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 * Find out the Unknown values
33 * No real specs exist. Some general description can be found at:
34 * http://www.cisco.com/en/US/products/hw/routers/ps368/products_configuration_guide_chapter09186a008069952a.html
36 * Some information on ERSPAN type III can be found at:
37 * http://www.cisco.com/en/US/docs/switches/datacenter/nexus1000/sw/4_0_4_s_v_1_3/system_management/configuration/guide/n1000v_system_9span.html
39 * For ERSPAN packets, the "protocol type" field value in the GRE header
40 * is 0x88BE (version 1) or 0x22EB (version 2).
42 * ERSPAN type II is version 1
43 * ERSPAN type III is version 2
45 * 0000000: d4c3 b2a1 0200 0400 0000 0000 0000 0000 <-- pcap header
47 * 0000010: 7100 0000 <-- 0x71 (DLT_TYPE) = linux_cooked_capture (of course not)
48 * 0000010: 7507 f845 11d1 0500 <-- pcap record header
49 * 0000020: 7a00 0000 7a00 0000
50 * 0000020: 0000 030a 0000 0000 <-- unknown
52 * 0000030: 0000 88be <-- GRE header (version 1)
53 * 0000030: 1002 0001 0000 0380 <-- ERSPAN header (01: erspan-id)
54 * 0000040: 00d0 b7a7 7480 0015 c721 75c0 0800 4500 <-- Ethernet packet
63 #include <epan/packet.h>
64 #include <epan/greproto.h>
65 #include <epan/prefs.h>
66 #include <epan/expert.h>
68 static int proto_erspan = -1;
70 static gint ett_erspan = -1;
72 static int hf_erspan_version = -1;
73 static int hf_erspan_vlan = -1;
74 static int hf_erspan_priority = -1;
75 static int hf_erspan_unknown2 = -1;
76 static int hf_erspan_direction = -1;
77 static int hf_erspan_unknown3 = -1;
78 static int hf_erspan_truncated = -1;
79 static int hf_erspan_spanid = -1;
80 static int hf_erspan_timestamp = -1;
81 static int hf_erspan_unknown4 = -1;
82 static int hf_erspan_direction2 = -1;
83 static int hf_erspan_unknown5 = -1;
84 static int hf_erspan_unknown6 = -1;
85 static int hf_erspan_unknown7 = -1;
87 #define PROTO_SHORT_NAME "ERSPAN"
88 #define PROTO_LONG_NAME "Encapsulated Remote Switch Packet ANalysis"
90 /* Global ERSPAN Preference */
91 static gboolean pref_fake_erspan = FALSE;
93 #define ERSPAN_DIRECTION_INCOMING 0
94 #define ERSPAN_DIRECTION_OUTGOING 1
95 static const value_string erspan_direction_vals[] = {
96 {ERSPAN_DIRECTION_INCOMING, "Incoming"},
97 {ERSPAN_DIRECTION_OUTGOING, "Outgoing"},
101 static const value_string erspan_truncated_vals[] = {
102 {0, "Not truncated"},
107 static const value_string erspan_version_vals[] = {
113 static dissector_handle_t ethnofcs_handle;
116 erspan_fmt_timestamp(gchar *result, guint32 timeval)
118 g_snprintf(result, ITEM_LABEL_LENGTH, "%.4f", (((gfloat)timeval)/10000));
122 dissect_erspan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
126 proto_tree *erspan_tree = NULL;
131 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
132 col_set_str(pinfo->cinfo, COL_INFO, PROTO_SHORT_NAME ":");
136 ti = proto_tree_add_item(tree, proto_erspan, tvb, offset, -1,
138 erspan_tree = proto_item_add_subtree(ti, ett_erspan);
141 if(pref_fake_erspan) {
142 /* Some vendor don't include ERSPAN Header...*/
143 eth_tvb = tvb_new_subset_remaining(tvb, offset);
144 call_dissector(ethnofcs_handle, eth_tvb, pinfo, tree);
149 version = tvb_get_ntohs(tvb, offset) >> 12;
150 ti_ver = proto_tree_add_item(erspan_tree, hf_erspan_version, tvb, offset, 2,
152 if ((version != 1) && (version != 2 )) {
153 expert_add_info_format(pinfo, ti_ver, PI_UNDECODED, PI_WARN, "Unknown version, please report or test to use fake ERSPAN preference");
156 proto_tree_add_item(erspan_tree, hf_erspan_vlan, tvb, offset, 2,
160 proto_tree_add_item(erspan_tree, hf_erspan_priority, tvb, offset, 2,
162 proto_tree_add_item(erspan_tree, hf_erspan_unknown2, tvb, offset, 2,
165 proto_tree_add_item(erspan_tree, hf_erspan_direction, tvb,
166 offset, 2, ENC_BIG_ENDIAN);
167 else /* version = 2 */
168 proto_tree_add_item(erspan_tree, hf_erspan_unknown3, tvb,
169 offset, 2, ENC_BIG_ENDIAN);
170 proto_tree_add_item(erspan_tree, hf_erspan_truncated, tvb, offset, 2,
172 proto_tree_add_item(erspan_tree, hf_erspan_spanid, tvb, offset, 2,
177 proto_tree_add_item(erspan_tree, hf_erspan_timestamp, tvb,
178 offset, 4, ENC_BIG_ENDIAN);
181 proto_tree_add_item(erspan_tree, hf_erspan_unknown4, tvb,
185 proto_tree_add_item(erspan_tree, hf_erspan_direction2, tvb,
186 offset, 2, ENC_BIG_ENDIAN);
187 proto_tree_add_item(erspan_tree, hf_erspan_unknown5, tvb,
188 offset, 2, ENC_BIG_ENDIAN);
191 proto_tree_add_item(erspan_tree, hf_erspan_unknown6, tvb,
195 proto_tree_add_item(erspan_tree, hf_erspan_unknown7, tvb, offset, 4,
205 eth_tvb = tvb_new_subset_remaining(tvb, offset);
206 call_dissector(ethnofcs_handle, eth_tvb, pinfo, tree);
210 proto_register_erspan(void)
212 module_t *erspan_module;
214 static hf_register_info hf[] = {
216 { &hf_erspan_version,
217 { "Version", "erspan.version", FT_UINT16, BASE_DEC, VALS(erspan_version_vals),
218 0xf000, NULL, HFILL }},
221 { "Vlan", "erspan.vlan", FT_UINT16, BASE_DEC, NULL,
222 0x0fff, NULL, HFILL }},
224 { &hf_erspan_priority,
225 { "Priority", "erspan.priority", FT_UINT16, BASE_DEC, NULL,
226 0xe000, NULL, HFILL }},
228 { &hf_erspan_unknown2,
229 { "Unknown2", "erspan.unknown2", FT_UINT16, BASE_DEC, NULL,
230 0x1000, NULL, HFILL }},
232 { &hf_erspan_direction,
233 { "Direction", "erspan.direction", FT_UINT16, BASE_DEC, VALS(erspan_direction_vals),
234 0x0800, NULL, HFILL }},
236 { &hf_erspan_unknown3,
237 { "Unknown3", "erspan.unknown3", FT_UINT16, BASE_DEC, NULL,
238 0x0800, NULL, HFILL }},
240 { &hf_erspan_truncated,
241 { "Truncated", "erspan.truncated", FT_UINT16, BASE_DEC, VALS(erspan_truncated_vals),
242 0x0400, "ERSPAN packet exceeded the MTU size", HFILL }},
245 { "SpanID", "erspan.spanid", FT_UINT16, BASE_DEC, NULL,
246 0x03ff, NULL, HFILL }},
248 { &hf_erspan_timestamp,
249 { "Timestamp", "erspan.timestamp", FT_UINT32, BASE_CUSTOM, erspan_fmt_timestamp,
252 { &hf_erspan_unknown4,
253 { "Unknown4", "erspan.unknown4", FT_BYTES, BASE_NONE, NULL,
256 { &hf_erspan_direction2,
257 { "Direction2", "erspan.direction2", FT_UINT16, BASE_DEC, VALS(erspan_direction_vals),
258 0x0008, NULL, HFILL }},
260 { &hf_erspan_unknown5,
261 { "Unknown5", "erspan.unknown5", FT_UINT16, BASE_HEX, NULL,
262 0xfff7, NULL, HFILL }},
264 { &hf_erspan_unknown6,
265 { "Unknown6", "erspan.unknown6", FT_BYTES, BASE_NONE, NULL,
268 { &hf_erspan_unknown7,
269 { "Unknown7", "erspan.unknown7", FT_BYTES, BASE_NONE, NULL,
273 static gint *ett[] = {
277 proto_erspan = proto_register_protocol(PROTO_LONG_NAME,
278 PROTO_SHORT_NAME, "erspan");
279 proto_register_field_array(proto_erspan, hf, array_length(hf));
280 proto_register_subtree_array(ett, array_length(ett));
282 /* register dissection preferences */
283 erspan_module = prefs_register_protocol(proto_erspan, NULL);
285 prefs_register_bool_preference(erspan_module, "fake_erspan",
286 "FORCE to decode fake ERSPAN frame",
287 "When set, dissector will FORCE to decode directly Ethernet Frame"
288 "Some vendor use fake ERSPAN frame (with not ERSPAN Header)",
293 proto_reg_handoff_erspan(void)
295 dissector_handle_t erspan_handle;
297 ethnofcs_handle = find_dissector("eth_withoutfcs");
299 erspan_handle = create_dissector_handle(dissect_erspan, proto_erspan);
300 dissector_add_uint("gre.proto", GRE_ERSPAN_88BE, erspan_handle);
301 dissector_add_uint("gre.proto", GRE_ERSPAN_22EB, erspan_handle);