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 static expert_field ei_erspan_version_unknown
= EI_INIT
;
89 #define PROTO_SHORT_NAME "ERSPAN"
90 #define PROTO_LONG_NAME "Encapsulated Remote Switch Packet ANalysis"
92 /* Global ERSPAN Preference */
93 static gboolean pref_fake_erspan
= FALSE
;
95 #define ERSPAN_DIRECTION_INCOMING 0
96 #define ERSPAN_DIRECTION_OUTGOING 1
97 static const value_string erspan_direction_vals
[] = {
98 {ERSPAN_DIRECTION_INCOMING
, "Incoming"},
99 {ERSPAN_DIRECTION_OUTGOING
, "Outgoing"},
103 static const value_string erspan_truncated_vals
[] = {
104 {0, "Not truncated"},
109 static const value_string erspan_version_vals
[] = {
115 static dissector_handle_t ethnofcs_handle
;
118 erspan_fmt_timestamp(gchar
*result
, guint32 timeval
)
120 g_snprintf(result
, ITEM_LABEL_LENGTH
, "%.4f", (((gfloat
)timeval
)/10000));
124 dissect_erspan(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
128 proto_tree
*erspan_tree
= NULL
;
133 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PROTO_SHORT_NAME
);
134 col_set_str(pinfo
->cinfo
, COL_INFO
, PROTO_SHORT_NAME
":");
138 ti
= proto_tree_add_item(tree
, proto_erspan
, tvb
, offset
, -1,
140 erspan_tree
= proto_item_add_subtree(ti
, ett_erspan
);
143 if(pref_fake_erspan
) {
144 /* Some vendor don't include ERSPAN Header...*/
145 eth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
146 call_dissector(ethnofcs_handle
, eth_tvb
, pinfo
, tree
);
151 version
= tvb_get_ntohs(tvb
, offset
) >> 12;
153 ti_ver
= proto_tree_add_item(erspan_tree
, hf_erspan_version
, tvb
, offset
, 2,
155 if ((version
!= 1) && (version
!= 2 )) {
156 expert_add_info(pinfo
, ti_ver
, &ei_erspan_version_unknown
);
159 proto_tree_add_item(erspan_tree
, hf_erspan_vlan
, tvb
, offset
, 2,
163 proto_tree_add_item(erspan_tree
, hf_erspan_priority
, tvb
, offset
, 2,
165 proto_tree_add_item(erspan_tree
, hf_erspan_unknown2
, tvb
, offset
, 2,
168 proto_tree_add_item(erspan_tree
, hf_erspan_direction
, tvb
,
169 offset
, 2, ENC_BIG_ENDIAN
);
170 else /* version = 2 */
171 proto_tree_add_item(erspan_tree
, hf_erspan_unknown3
, tvb
,
172 offset
, 2, ENC_BIG_ENDIAN
);
173 proto_tree_add_item(erspan_tree
, hf_erspan_truncated
, tvb
, offset
, 2,
175 proto_tree_add_item(erspan_tree
, hf_erspan_spanid
, tvb
, offset
, 2,
180 proto_tree_add_item(erspan_tree
, hf_erspan_timestamp
, tvb
,
181 offset
, 4, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(erspan_tree
, hf_erspan_unknown4
, tvb
,
188 proto_tree_add_item(erspan_tree
, hf_erspan_direction2
, tvb
,
189 offset
, 2, ENC_BIG_ENDIAN
);
190 proto_tree_add_item(erspan_tree
, hf_erspan_unknown5
, tvb
,
191 offset
, 2, ENC_BIG_ENDIAN
);
194 proto_tree_add_item(erspan_tree
, hf_erspan_unknown6
, tvb
,
198 proto_tree_add_item(erspan_tree
, hf_erspan_unknown7
, tvb
, offset
, 4,
208 eth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
209 call_dissector(ethnofcs_handle
, eth_tvb
, pinfo
, tree
);
213 proto_register_erspan(void)
215 module_t
*erspan_module
;
216 expert_module_t
* expert_erspan
;
218 static hf_register_info hf
[] = {
220 { &hf_erspan_version
,
221 { "Version", "erspan.version", FT_UINT16
, BASE_DEC
, VALS(erspan_version_vals
),
222 0xf000, NULL
, HFILL
}},
225 { "Vlan", "erspan.vlan", FT_UINT16
, BASE_DEC
, NULL
,
226 0x0fff, NULL
, HFILL
}},
228 { &hf_erspan_priority
,
229 { "Priority", "erspan.priority", FT_UINT16
, BASE_DEC
, NULL
,
230 0xe000, NULL
, HFILL
}},
232 { &hf_erspan_unknown2
,
233 { "Unknown2", "erspan.unknown2", FT_UINT16
, BASE_DEC
, NULL
,
234 0x1000, NULL
, HFILL
}},
236 { &hf_erspan_direction
,
237 { "Direction", "erspan.direction", FT_UINT16
, BASE_DEC
, VALS(erspan_direction_vals
),
238 0x0800, NULL
, HFILL
}},
240 { &hf_erspan_unknown3
,
241 { "Unknown3", "erspan.unknown3", FT_UINT16
, BASE_DEC
, NULL
,
242 0x0800, NULL
, HFILL
}},
244 { &hf_erspan_truncated
,
245 { "Truncated", "erspan.truncated", FT_UINT16
, BASE_DEC
, VALS(erspan_truncated_vals
),
246 0x0400, "ERSPAN packet exceeded the MTU size", HFILL
}},
249 { "SpanID", "erspan.spanid", FT_UINT16
, BASE_DEC
, NULL
,
250 0x03ff, NULL
, HFILL
}},
252 { &hf_erspan_timestamp
,
253 { "Timestamp", "erspan.timestamp", FT_UINT32
, BASE_CUSTOM
, erspan_fmt_timestamp
,
256 { &hf_erspan_unknown4
,
257 { "Unknown4", "erspan.unknown4", FT_BYTES
, BASE_NONE
, NULL
,
260 { &hf_erspan_direction2
,
261 { "Direction2", "erspan.direction2", FT_UINT16
, BASE_DEC
, VALS(erspan_direction_vals
),
262 0x0008, NULL
, HFILL
}},
264 { &hf_erspan_unknown5
,
265 { "Unknown5", "erspan.unknown5", FT_UINT16
, BASE_HEX
, NULL
,
266 0xfff7, NULL
, HFILL
}},
268 { &hf_erspan_unknown6
,
269 { "Unknown6", "erspan.unknown6", FT_BYTES
, BASE_NONE
, NULL
,
272 { &hf_erspan_unknown7
,
273 { "Unknown7", "erspan.unknown7", FT_BYTES
, BASE_NONE
, NULL
,
278 static gint
*ett
[] = {
282 static ei_register_info ei
[] = {
283 { &ei_erspan_version_unknown
, { "erspan.version.unknown", PI_UNDECODED
, PI_WARN
, "Unknown version, please report or test to use fake ERSPAN preference", EXPFILL
}},
286 proto_erspan
= proto_register_protocol(PROTO_LONG_NAME
, PROTO_SHORT_NAME
, "erspan");
287 proto_register_field_array(proto_erspan
, hf
, array_length(hf
));
288 proto_register_subtree_array(ett
, array_length(ett
));
289 expert_erspan
= expert_register_protocol(proto_erspan
);
290 expert_register_field_array(expert_erspan
, ei
, array_length(ei
));
292 /* register dissection preferences */
293 erspan_module
= prefs_register_protocol(proto_erspan
, NULL
);
295 prefs_register_bool_preference(erspan_module
, "fake_erspan",
296 "FORCE to decode fake ERSPAN frame",
297 "When set, dissector will FORCE to decode directly Ethernet Frame"
298 "Some vendor use fake ERSPAN frame (with not ERSPAN Header)",
303 proto_reg_handoff_erspan(void)
305 dissector_handle_t erspan_handle
;
307 ethnofcs_handle
= find_dissector("eth_withoutfcs");
309 erspan_handle
= create_dissector_handle(dissect_erspan
, proto_erspan
);
310 dissector_add_uint("gre.proto", GRE_ERSPAN_88BE
, erspan_handle
);
311 dissector_add_uint("gre.proto", GRE_ERSPAN_22EB
, erspan_handle
);