2 * Routines for analyzing Cisco FabricPath MiM packets
3 * Copyright 2011, Leonard Tracy <letracy@cisco.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
30 #include <epan/packet.h>
31 #include <epan/etypes.h>
32 #include <epan/addr_resolv.h>
33 #include <epan/prefs.h>
35 void proto_register_mim(void);
36 void proto_reg_handoff_fabricpath(void);
38 static int proto_fp = -1 ;
39 static gint ett_mim = -1 ;
40 static gint ett_hmac = -1 ;
42 /* Main protocol items */
43 static int hf_s_hmac = -1;
44 static int hf_d_hmac = -1;
45 static int hf_d_hmac_mc = -1;
46 static int hf_ftag = -1;
47 static int hf_ttl = -1;
52 static int hf_swid = -1 ;
53 static int hf_sswid = -1;
54 static int hf_eid = -1;
55 static int hf_lid = -1;
56 static int hf_ul = -1;
57 static int hf_ig = -1;
58 static int hf_ooodl = -1;
60 static const true_false_string ig_tfs = {
61 "Group address (multicast/broadcast)",
62 "Individual address (unicast)"
64 static const true_false_string ul_tfs = {
65 "Locally administered address (this is NOT the factory default)",
66 "Globally unique address (factory default)"
68 static const true_false_string ooodl_tfs = {
69 "Out of order delivery (If DA) or Do not learn (If SA)",
70 "Deliver in order (If DA) or Learn (If SA)"
73 static dissector_handle_t eth_dissector ;
76 #define FP_PROTO_COL_NAME "FabricPath"
77 #define FP_PROTO_COL_INFO "Cisco FabricPath MiM Encapsulated Frame"
79 #define FP_FIELD_LEN 3
81 #define FP_EID_MASK 0x00FCC0
82 #define FP_3B_EID_MASK 0xFCC000
84 #define FP_UL_MASK 0x020000
85 #define FP_IG_MASK 0x010000
86 #define FP_EID2_MASK 0x00C000
87 #define FP_RES_MASK 0x002000
88 #define FP_OOO_MASK 0x001000
89 #define FP_SWID_MASK 0x000FFF
93 #define FP_SSWID_LEN 1
96 #define FP_FTAG_MASK 0xFFC0
97 #define FP_TTL_MASK 0x003F
99 #define FP_HMAC_IG_MASK G_GINT64_CONSTANT(0x010000000000)
100 #define FP_HMAC_SWID_MASK G_GINT64_CONSTANT(0x000FFF000000)
101 #define FP_HMAC_SSWID_MASK G_GINT64_CONSTANT(0x000000FF0000)
102 #define FP_HMAC_LID_MASK G_GINT64_CONSTANT(0x00000000FFFF)
105 #define FP_HMAC_LEN 6
106 #define FP_HEADER_SIZE (16)
109 static int dissect_fp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ );
113 dissect_fp_heur (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
119 * Is ethertype ETHERTYPE_DCE
122 type = tvb_get_ntohs (tvb, 12);
124 if (type == ETHERTYPE_DCE) {
125 dissect_fp (tvb, pinfo, tree, NULL);
133 fp_is_ig_set (guint64 hmac)
135 if (hmac & FP_HMAC_IG_MASK) {
143 fp_get_hmac_addr (guint64 hmac, guint16 *swid, guint16 *sswid, guint16 *lid) {
145 if (!swid || !sswid || !lid) {
149 *swid = (guint16) ((hmac & FP_HMAC_SWID_MASK) >> 24);
150 *sswid = (guint16) ((hmac & FP_HMAC_SSWID_MASK) >> 16);
151 *lid = (guint16) (hmac & FP_HMAC_LID_MASK);
155 fp_add_hmac (tvbuff_t *tvb, proto_tree *tree, int offset) {
163 eid = tvb_get_ntohs(tvb, offset);
166 eid = ((eid & 0x00C0) >> 6) + ((eid & 0xFC00) >> 8);
167 proto_tree_add_uint(tree, hf_eid, tvb, offset, FP_BF_LEN, eid);
169 proto_tree_add_item (tree, hf_ul, tvb, offset, FP_BF_LEN, ENC_NA);
170 proto_tree_add_item (tree, hf_ig, tvb, offset, FP_BF_LEN, ENC_NA);
171 proto_tree_add_item (tree, hf_ooodl, tvb, offset, FP_BF_LEN, ENC_NA);
172 proto_tree_add_item (tree, hf_swid, tvb, offset, FP_BF_LEN, ENC_BIG_ENDIAN);
175 proto_tree_add_item (tree, hf_sswid, tvb, offset, FP_SSWID_LEN, ENC_BIG_ENDIAN);
176 offset += FP_SSWID_LEN;
178 proto_tree_add_item (tree, hf_lid, tvb, offset, FP_LID_LEN, ENC_BIG_ENDIAN);
179 /*offset += FP_LID_LEN;*/
182 /* FabricPath MiM Dissector */
184 dissect_fp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
187 proto_tree *fp_tree ;
188 proto_tree *fp_addr_tree ;
199 const guint8 *dst_addr = NULL;
200 gboolean dest_ig = FALSE;
202 col_set_str( pinfo->cinfo, COL_PROTOCOL, FP_PROTO_COL_NAME ) ;
203 col_set_str( pinfo->cinfo, COL_INFO, FP_PROTO_COL_INFO ) ;
207 hmac_dst = tvb_get_ntoh48 (tvb, 0);
208 hmac_src = tvb_get_ntoh48 (tvb, 6);
210 dest_ig = fp_is_ig_set(hmac_dst);
212 fp_get_hmac_addr (hmac_dst, &dswid, &dsswid, &dlid);
214 hmac_dst = GUINT64_TO_BE (hmac_dst);
215 /* Get pointer to most sig byte of destination address
218 dst_addr = ((const guint8 *) &hmac_dst) + 2;
223 fp_get_hmac_addr (hmac_src, &sswid, &ssswid, &slid);
225 if (PTREE_DATA(tree)->visible) {
229 set_address(ðer_addr, AT_ETHER, 6, dst_addr);
231 ti = proto_tree_add_protocol_format(tree, proto_fp, tvb, 0, FP_HEADER_SIZE,
232 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %s",
234 address_with_resolution_to_str(wmem_packet_scope(), ðer_addr));
236 ti = proto_tree_add_protocol_format(tree, proto_fp, tvb, 0, FP_HEADER_SIZE,
237 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %03x.%02x.%04x",
239 dswid, dsswid, dlid);
242 ti = proto_tree_add_item( tree, proto_fp, tvb, 0, -1, ENC_NA ) ;
244 fp_tree = proto_item_add_subtree( ti, ett_mim ) ;
247 /* Add dest and source heir. mac */
250 proto_tree_add_ether( fp_tree, hf_d_hmac_mc, tvb, offset, 6,
254 ti = proto_tree_add_none_format (fp_tree, hf_d_hmac, tvb, offset, 6, "Destination: %03x.%02x.%04x", dswid, dsswid, dlid);
255 fp_addr_tree = proto_item_add_subtree (ti, ett_hmac);
256 fp_add_hmac (tvb, fp_addr_tree, offset);
259 offset += FP_HMAC_LEN;
260 ti = proto_tree_add_none_format (fp_tree, hf_s_hmac, tvb, offset, 6,
261 "Source: %03x.%02x.%04x", sswid, ssswid, slid);
262 fp_addr_tree = proto_item_add_subtree (ti, ett_hmac);
263 fp_add_hmac (tvb, fp_addr_tree, offset);
265 offset += FP_HMAC_LEN;
269 proto_tree_add_item (fp_tree, hf_ftag, tvb, offset, FP_FTAG_LEN, ENC_BIG_ENDIAN);
271 proto_tree_add_item (fp_tree, hf_ttl, tvb, offset, FP_FTAG_LEN, ENC_BIG_ENDIAN);
274 /* call the eth dissector */
275 next_tvb = tvb_new_subset_remaining( tvb, FP_HEADER_SIZE) ;
276 call_dissector( eth_dissector, next_tvb, pinfo, tree ) ;
278 return tvb_captured_length( tvb ) ;
281 /* Register the protocol with Wireshark */
283 proto_register_mim(void)
285 static hf_register_info hf[] = {
287 { "Source HMAC", "cfp.s_hmac",
288 FT_NONE, BASE_NONE, NULL,
289 0, "Source Hierarchical MAC", HFILL }},
292 { "Destination HMAC", "cfp.d_hmac",
293 FT_NONE, BASE_NONE, NULL,
294 0, "Destination Hierarchical MAC", HFILL }},
297 { "MC Destination", "cfp.d_hmac_mc",
298 FT_ETHER, BASE_NONE, NULL,
299 0, "Multicast Destination Address", HFILL }},
302 { "FTAG", "cfp.ftag",
303 FT_UINT16, BASE_DEC, NULL, FP_FTAG_MASK,
304 "FTAG field identifying forwarding distribution tree.", HFILL }},
308 FT_UINT16, BASE_DEC, NULL, FP_TTL_MASK,
309 "The remaining hop count for this frame", HFILL }},
312 { "switch-id", "cfp.swid",
313 FT_UINT24, BASE_DEC_HEX, NULL, FP_SWID_MASK,
314 "Switch-id/nickname of switch in FabricPath network", HFILL }},
317 { "sub-switch-id", "cfp.sswid",
318 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
319 "Sub-switch-id of switch in FabricPath network", HFILL }},
322 { "End Node ID", "cfp.eid",
323 FT_UINT24, BASE_DEC_HEX, NULL, FP_3B_EID_MASK,
324 "Cisco FabricPath End node ID", HFILL }},
327 { "Source LID", "cfp.lid",
328 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
329 "Source or Destination Port index on switch in FabricPath network", HFILL }},
332 { "U/L bit", "cfp.ul",
333 FT_BOOLEAN, 24, TFS(&ul_tfs), FP_UL_MASK,
334 "Specifies if this is a locally administered or globally unique (IEEE assigned) address", HFILL }},
337 { "I/G bit", "cfp.ig",
338 FT_BOOLEAN, 24 /* FP_BF_LEN */, TFS(&ig_tfs), FP_IG_MASK,
339 "Specifies if this is an individual (unicast) or group (broadcast/multicast) address", HFILL }},
342 { "OOO/DL Bit", "cfp.ooodl",
343 FT_BOOLEAN, 24 /* FP_BF_LEN */, TFS(&ooodl_tfs), FP_OOO_MASK,
344 "Specifies Out of Order Delivery OK in destination address and Do Not Learn when set in source address", HFILL }}
348 static gint *ett[] = {
353 module_t *mim_module;
355 proto_fp = proto_register_protocol("Cisco FabricPath", "CFP", "cfp");
357 mim_module = prefs_register_protocol (proto_fp, proto_reg_handoff_fabricpath);
359 prefs_register_obsolete_preference (mim_module, "enable");
361 proto_register_field_array(proto_fp, hf, array_length(hf));
362 proto_register_subtree_array(ett, array_length(ett));
366 proto_reg_handoff_fabricpath(void)
369 dissector_handle_t fp_handle;
370 fp_handle = new_create_dissector_handle(dissect_fp, proto_fp);
371 dissector_add_uint("ethertype", ETHERTYPE_DCE, fp_handle);
373 static gboolean prefs_initialized = FALSE;
375 if (!prefs_initialized) {
377 * Using Heuristic dissector (As opposed to
378 * registering the ethertype) in order to
379 * get outer source and destination MAC
380 * before the standard ethernet dissector
382 heur_dissector_add ("eth", dissect_fp_heur, "Cisco FabricPath over Ethernet", "fp_eth", proto_fp, HEURISTIC_DISABLE);
383 eth_dissector = find_dissector( "eth" );
384 prefs_initialized = TRUE;
389 * Editor modelines - http://www.wireshark.org/tools/modelines.html
394 * indent-tabs-mode: nil
397 * ex: set shiftwidth=2 tabstop=8 expandtab:
398 * :indentSize=2:tabSize=8:noTabs=true: