2 * Routines for the disassembly of Cisco's ERSPAN protocol
4 * Copyright 2005 Joerg Mayer (see AUTHORS file)
5 * Updates for newer versions by Jason Masker <jason at masker.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 * Find out the Unknown values
31 * No real specs exist. Some general description can be found at:
32 * http://www.cisco.com/en/US/products/hw/routers/ps368/products_configuration_guide_chapter09186a008069952a.html
34 * Some information on ERSPAN type III can be found at:
35 * 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
37 * For ERSPAN packets, the "protocol type" field value in the GRE header
38 * is 0x88BE (version 1) or 0x22EB (version 2).
40 * ERSPAN type II is version 1
41 * ERSPAN type III is version 2
43 * 0000000: d4c3 b2a1 0200 0400 0000 0000 0000 0000 <-- pcap header
45 * 0000010: 7100 0000 <-- 0x71 (DLT_TYPE) = linux_cooked_capture (of course not)
46 * 0000010: 7507 f845 11d1 0500 <-- pcap record header
47 * 0000020: 7a00 0000 7a00 0000
48 * 0000020: 0000 030a 0000 0000 <-- unknown
50 * 0000030: 0000 88be <-- GRE header (version 1)
51 * 0000030: 1002 0001 0000 0380 <-- ERSPAN header (01: erspan-id)
52 * 0000040: 00d0 b7a7 7480 0015 c721 75c0 0800 4500 <-- Ethernet packet
61 #include <epan/packet.h>
62 #include <epan/greproto.h>
63 #include <epan/prefs.h>
64 #include <epan/expert.h>
66 void proto_register_erspan(void);
67 void proto_reg_handoff_erspan(void);
69 static int proto_erspan = -1;
71 static gint ett_erspan = -1;
73 static int hf_erspan_version = -1;
74 static int hf_erspan_vlan = -1;
75 static int hf_erspan_priority = -1;
76 static int hf_erspan_unknown2 = -1;
77 static int hf_erspan_direction = -1;
78 static int hf_erspan_unknown3 = -1;
79 static int hf_erspan_truncated = -1;
80 static int hf_erspan_spanid = -1;
81 static int hf_erspan_timestamp = -1;
82 static int hf_erspan_unknown4 = -1;
83 static int hf_erspan_direction2 = -1;
84 static int hf_erspan_unknown5 = -1;
85 static int hf_erspan_unknown6 = -1;
86 static int hf_erspan_unknown7 = -1;
88 static expert_field ei_erspan_version_unknown = EI_INIT;
90 #define PROTO_SHORT_NAME "ERSPAN"
91 #define PROTO_LONG_NAME "Encapsulated Remote Switch Packet ANalysis"
93 /* Global ERSPAN Preference */
94 static gboolean pref_fake_erspan = FALSE;
96 #define ERSPAN_DIRECTION_INCOMING 0
97 #define ERSPAN_DIRECTION_OUTGOING 1
98 static const value_string erspan_direction_vals[] = {
99 {ERSPAN_DIRECTION_INCOMING, "Incoming"},
100 {ERSPAN_DIRECTION_OUTGOING, "Outgoing"},
104 static const value_string erspan_truncated_vals[] = {
105 {0, "Not truncated"},
110 static const value_string erspan_version_vals[] = {
116 static dissector_handle_t ethnofcs_handle;
119 erspan_fmt_timestamp(gchar *result, guint32 timeval)
121 g_snprintf(result, ITEM_LABEL_LENGTH, "%.4f", (((gfloat)timeval)/10000));
125 dissect_erspan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
129 proto_tree *erspan_tree = NULL;
134 col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
135 col_set_str(pinfo->cinfo, COL_INFO, PROTO_SHORT_NAME ":");
139 ti = proto_tree_add_item(tree, proto_erspan, tvb, offset, -1,
141 erspan_tree = proto_item_add_subtree(ti, ett_erspan);
144 if(pref_fake_erspan) {
145 /* Some vendor don't include ERSPAN Header...*/
146 eth_tvb = tvb_new_subset_remaining(tvb, offset);
147 call_dissector(ethnofcs_handle, eth_tvb, pinfo, tree);
152 version = tvb_get_ntohs(tvb, offset) >> 12;
154 ti_ver = proto_tree_add_item(erspan_tree, hf_erspan_version, tvb, offset, 2,
156 if ((version != 1) && (version != 2 )) {
157 expert_add_info(pinfo, ti_ver, &ei_erspan_version_unknown);
160 proto_tree_add_item(erspan_tree, hf_erspan_vlan, tvb, offset, 2,
164 proto_tree_add_item(erspan_tree, hf_erspan_priority, tvb, offset, 2,
166 proto_tree_add_item(erspan_tree, hf_erspan_unknown2, tvb, offset, 2,
169 proto_tree_add_item(erspan_tree, hf_erspan_direction, tvb,
170 offset, 2, ENC_BIG_ENDIAN);
171 else /* version = 2 */
172 proto_tree_add_item(erspan_tree, hf_erspan_unknown3, tvb,
173 offset, 2, ENC_BIG_ENDIAN);
174 proto_tree_add_item(erspan_tree, hf_erspan_truncated, tvb, offset, 2,
176 proto_tree_add_item(erspan_tree, hf_erspan_spanid, tvb, offset, 2,
181 proto_tree_add_item(erspan_tree, hf_erspan_timestamp, tvb,
182 offset, 4, ENC_BIG_ENDIAN);
185 proto_tree_add_item(erspan_tree, hf_erspan_unknown4, tvb,
189 proto_tree_add_item(erspan_tree, hf_erspan_direction2, tvb,
190 offset, 2, ENC_BIG_ENDIAN);
191 proto_tree_add_item(erspan_tree, hf_erspan_unknown5, tvb,
192 offset, 2, ENC_BIG_ENDIAN);
195 proto_tree_add_item(erspan_tree, hf_erspan_unknown6, tvb,
199 proto_tree_add_item(erspan_tree, hf_erspan_unknown7, tvb, offset, 4,
209 eth_tvb = tvb_new_subset_remaining(tvb, offset);
210 call_dissector(ethnofcs_handle, eth_tvb, pinfo, tree);
214 proto_register_erspan(void)
216 module_t *erspan_module;
217 expert_module_t* expert_erspan;
219 static hf_register_info hf[] = {
221 { &hf_erspan_version,
222 { "Version", "erspan.version", FT_UINT16, BASE_DEC, VALS(erspan_version_vals),
223 0xf000, NULL, HFILL }},
226 { "Vlan", "erspan.vlan", FT_UINT16, BASE_DEC, NULL,
227 0x0fff, NULL, HFILL }},
229 { &hf_erspan_priority,
230 { "Priority", "erspan.priority", FT_UINT16, BASE_DEC, NULL,
231 0xe000, NULL, HFILL }},
233 { &hf_erspan_unknown2,
234 { "Unknown2", "erspan.unknown2", FT_UINT16, BASE_DEC, NULL,
235 0x1000, NULL, HFILL }},
237 { &hf_erspan_direction,
238 { "Direction", "erspan.direction", FT_UINT16, BASE_DEC, VALS(erspan_direction_vals),
239 0x0800, NULL, HFILL }},
241 { &hf_erspan_unknown3,
242 { "Unknown3", "erspan.unknown3", FT_UINT16, BASE_DEC, NULL,
243 0x0800, NULL, HFILL }},
245 { &hf_erspan_truncated,
246 { "Truncated", "erspan.truncated", FT_UINT16, BASE_DEC, VALS(erspan_truncated_vals),
247 0x0400, "ERSPAN packet exceeded the MTU size", HFILL }},
250 { "SpanID", "erspan.spanid", FT_UINT16, BASE_DEC, NULL,
251 0x03ff, NULL, HFILL }},
253 { &hf_erspan_timestamp,
254 { "Timestamp", "erspan.timestamp", FT_UINT32, BASE_CUSTOM, erspan_fmt_timestamp,
257 { &hf_erspan_unknown4,
258 { "Unknown4", "erspan.unknown4", FT_BYTES, BASE_NONE, NULL,
261 { &hf_erspan_direction2,
262 { "Direction2", "erspan.direction2", FT_UINT16, BASE_DEC, VALS(erspan_direction_vals),
263 0x0008, NULL, HFILL }},
265 { &hf_erspan_unknown5,
266 { "Unknown5", "erspan.unknown5", FT_UINT16, BASE_HEX, NULL,
267 0xfff7, NULL, HFILL }},
269 { &hf_erspan_unknown6,
270 { "Unknown6", "erspan.unknown6", FT_BYTES, BASE_NONE, NULL,
273 { &hf_erspan_unknown7,
274 { "Unknown7", "erspan.unknown7", FT_BYTES, BASE_NONE, NULL,
279 static gint *ett[] = {
283 static ei_register_info ei[] = {
284 { &ei_erspan_version_unknown, { "erspan.version.unknown", PI_UNDECODED, PI_WARN, "Unknown version, please report or test to use fake ERSPAN preference", EXPFILL }},
287 proto_erspan = proto_register_protocol(PROTO_LONG_NAME, PROTO_SHORT_NAME, "erspan");
288 proto_register_field_array(proto_erspan, hf, array_length(hf));
289 proto_register_subtree_array(ett, array_length(ett));
290 expert_erspan = expert_register_protocol(proto_erspan);
291 expert_register_field_array(expert_erspan, ei, array_length(ei));
293 /* register dissection preferences */
294 erspan_module = prefs_register_protocol(proto_erspan, NULL);
296 prefs_register_bool_preference(erspan_module, "fake_erspan",
297 "FORCE to decode fake ERSPAN frame",
298 "When set, dissector will FORCE to decode directly Ethernet Frame"
299 "Some vendor use fake ERSPAN frame (with not ERSPAN Header)",
304 proto_reg_handoff_erspan(void)
306 dissector_handle_t erspan_handle;
308 ethnofcs_handle = find_dissector("eth_withoutfcs");
310 erspan_handle = create_dissector_handle(dissect_erspan, proto_erspan);
311 dissector_add_uint("gre.proto", GRE_ERSPAN_88BE, erspan_handle);
312 dissector_add_uint("gre.proto", GRE_ERSPAN_22EB, erspan_handle);