2 * Routines for analyzing Cisco FabricPath MiM packets
3 * Copyright 2011, Leonard Tracy <letracy@cisco.com>
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 modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (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 along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
33 #include <epan/packet.h>
34 #include <epan/etypes.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/prefs.h>
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 /* Ethernet heuristic dissectors (such as this one) get called for
61 * every Ethernet frame Wireshark handles. In order to not impose that
62 * performance penalty on everyone this dissector disables itself by
65 * This is done separately from the disabled protocols list mainly so
66 * we can disable it by default. XXX Maybe there's a better way.
68 static gboolean mim_enable_dissector
= FALSE
;
70 static const true_false_string ig_tfs
= {
71 "Group address (multicast/broadcast)",
72 "Individual address (unicast)"
74 static const true_false_string ul_tfs
= {
75 "Locally administered address (this is NOT the factory default)",
76 "Globally unique address (factory default)"
78 static const true_false_string ooodl_tfs
= {
79 "Out of order delivery (If DA) or Do not learn (If SA)",
80 "Deliver in order (If DA) or Learn (If SA)"
83 static dissector_handle_t eth_dissector
;
86 #define FP_PROTO_COL_NAME "FabricPath"
87 #define FP_PROTO_COL_INFO "Cisco FabricPath MiM Encapsulated Frame"
89 #define FP_FIELD_LEN 3
91 #define FP_EID_MASK 0x00FCC0
92 #define FP_3B_EID_MASK 0xFCC000
94 #define FP_UL_MASK 0x020000
95 #define FP_IG_MASK 0x010000
96 #define FP_EID2_MASK 0x00C000
97 #define FP_RES_MASK 0x002000
98 #define FP_OOO_MASK 0x001000
99 #define FP_SWID_MASK 0x000FFF
103 #define FP_SSWID_LEN 1
104 #define FP_FTAG_LEN 2
106 #define FP_FTAG_MASK 0xFFC0
107 #define FP_TTL_MASK 0x003F
109 #define FP_HMAC_IG_MASK G_GINT64_CONSTANT(0x010000000000)
110 #define FP_HMAC_SWID_MASK G_GINT64_CONSTANT(0x000FFF000000)
111 #define FP_HMAC_SSWID_MASK G_GINT64_CONSTANT(0x000000FF0000)
112 #define FP_HMAC_LID_MASK G_GINT64_CONSTANT(0x00000000FFFF)
115 #define FP_HMAC_LEN 6
116 #define FP_HEADER_SIZE (16)
119 static int dissect_fp( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
);
120 void proto_reg_handoff_fabricpath(void);
124 dissect_fp_heur (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
130 * Is ethertype ETHERTYPE_DCE
133 type
= tvb_get_ntohs (tvb
, 12);
135 if (type
== ETHERTYPE_DCE
) {
136 dissect_fp (tvb
, pinfo
, tree
, NULL
);
144 fp_is_ig_set (guint64 hmac
)
146 if (hmac
& FP_HMAC_IG_MASK
) {
154 fp_get_hmac_addr (guint64 hmac
, guint16
*swid
, guint16
*sswid
, guint16
*lid
) {
156 if (!swid
|| !sswid
|| !lid
) {
160 *swid
= (guint16
) ((hmac
& FP_HMAC_SWID_MASK
) >> 24);
161 *sswid
= (guint16
) ((hmac
& FP_HMAC_SSWID_MASK
) >> 16);
162 *lid
= (guint16
) (hmac
& FP_HMAC_LID_MASK
);
166 fp_add_hmac (tvbuff_t
*tvb
, proto_tree
*tree
, int offset
) {
174 eid
= tvb_get_ntohs(tvb
, offset
);
177 eid
= ((eid
& 0x00C0) >> 6) + ((eid
& 0xFC00) >> 8);
178 proto_tree_add_uint(tree
, hf_eid
, tvb
, offset
, FP_BF_LEN
, eid
);
180 proto_tree_add_item (tree
, hf_ul
, tvb
, offset
, FP_BF_LEN
, ENC_NA
);
181 proto_tree_add_item (tree
, hf_ig
, tvb
, offset
, FP_BF_LEN
, ENC_NA
);
182 proto_tree_add_item (tree
, hf_ooodl
, tvb
, offset
, FP_BF_LEN
, ENC_NA
);
183 proto_tree_add_item (tree
, hf_swid
, tvb
, offset
, FP_BF_LEN
, ENC_BIG_ENDIAN
);
186 proto_tree_add_item (tree
, hf_sswid
, tvb
, offset
, FP_SSWID_LEN
, ENC_BIG_ENDIAN
);
187 offset
+= FP_SSWID_LEN
;
189 proto_tree_add_item (tree
, hf_lid
, tvb
, offset
, FP_LID_LEN
, ENC_BIG_ENDIAN
);
190 /*offset += FP_LID_LEN;*/
193 /* FabricPath MiM Dissector */
195 dissect_fp( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
198 proto_tree
*fp_tree
;
199 proto_tree
*fp_addr_tree
;
210 const guint8
*dst_addr
= NULL
;
211 gboolean dest_ig
= FALSE
;
213 col_set_str( pinfo
->cinfo
, COL_PROTOCOL
, FP_PROTO_COL_NAME
) ;
214 col_set_str( pinfo
->cinfo
, COL_INFO
, FP_PROTO_COL_INFO
) ;
218 hmac_dst
= tvb_get_ntoh48 (tvb
, 0);
219 hmac_src
= tvb_get_ntoh48 (tvb
, 6);
221 dest_ig
= fp_is_ig_set(hmac_dst
);
223 fp_get_hmac_addr (hmac_dst
, &dswid
, &dsswid
, &dlid
);
225 hmac_dst
= GUINT64_TO_BE (hmac_dst
);
226 /* Get pointer to most sig byte of destination address
229 dst_addr
= ((const guint8
*) &hmac_dst
) + 2;
234 fp_get_hmac_addr (hmac_src
, &sswid
, &ssswid
, &slid
);
236 if (PTREE_DATA(tree
)->visible
) {
239 ti
= proto_tree_add_protocol_format(tree
, proto_fp
, tvb
, 0, FP_HEADER_SIZE
,
240 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %s (%s)",
242 get_ether_name(dst_addr
), ether_to_str(dst_addr
));
244 ti
= proto_tree_add_protocol_format(tree
, proto_fp
, tvb
, 0, FP_HEADER_SIZE
,
245 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %03x.%02x.%04x",
247 dswid
, dsswid
, dlid
);
250 ti
= proto_tree_add_item( tree
, proto_fp
, tvb
, 0, -1, ENC_NA
) ;
252 fp_tree
= proto_item_add_subtree( ti
, ett_mim
) ;
255 /* Add dest and source heir. mac */
258 proto_tree_add_ether( fp_tree
, hf_d_hmac_mc
, tvb
, offset
, 6,
262 ti
= proto_tree_add_none_format (fp_tree
, hf_d_hmac
, tvb
, offset
, 6, "Destination: %03x.%02x.%04x", dswid
, dsswid
, dlid
);
263 fp_addr_tree
= proto_item_add_subtree (ti
, ett_hmac
);
264 fp_add_hmac (tvb
, fp_addr_tree
, offset
);
267 offset
+= FP_HMAC_LEN
;
268 ti
= proto_tree_add_none_format (fp_tree
, hf_s_hmac
, tvb
, offset
, 6,
269 "Source: %03x.%02x.%04x", sswid
, ssswid
, slid
);
270 fp_addr_tree
= proto_item_add_subtree (ti
, ett_hmac
);
271 fp_add_hmac (tvb
, fp_addr_tree
, offset
);
273 offset
+= FP_HMAC_LEN
;
277 proto_tree_add_item (fp_tree
, hf_ftag
, tvb
, offset
, FP_FTAG_LEN
, ENC_BIG_ENDIAN
);
279 proto_tree_add_item (fp_tree
, hf_ttl
, tvb
, offset
, FP_FTAG_LEN
, ENC_BIG_ENDIAN
);
282 /* call the eth dissector */
283 next_tvb
= tvb_new_subset_remaining( tvb
, FP_HEADER_SIZE
) ;
284 call_dissector( eth_dissector
, next_tvb
, pinfo
, tree
) ;
286 return tvb_length( tvb
) ;
289 /* Register the protocol with Wireshark */
291 proto_register_mim(void)
293 static hf_register_info hf
[] = {
295 { "Source HMAC", "cfp.s_hmac",
296 FT_NONE
, BASE_NONE
, NULL
,
297 0, "Source Hierarchical MAC", HFILL
}},
300 { "Destination HMAC", "cfp.d_hmac",
301 FT_NONE
, BASE_NONE
, NULL
,
302 0, "Destination Hierarchical MAC", HFILL
}},
305 { "MC Destination", "cfp.d_hmac",
306 FT_ETHER
, BASE_NONE
, NULL
,
307 0, "Multicast Destination Address", HFILL
}},
310 { "FTAG", "cfp.ftag",
311 FT_UINT16
, BASE_DEC
, NULL
, FP_FTAG_MASK
,
312 "FTAG field identifying forwarding distribution tree.", HFILL
}},
316 FT_UINT16
, BASE_DEC
, NULL
, FP_TTL_MASK
,
317 "The remaining hop count for this frame", HFILL
}},
320 { "switch-id", "cfp.swid",
321 FT_UINT24
, BASE_DEC_HEX
, NULL
, FP_SWID_MASK
,
322 "Switch-id/nickname of switch in FabricPath network", HFILL
}},
325 { "sub-switch-id", "cfp.sswid",
326 FT_UINT8
, BASE_DEC_HEX
, NULL
, 0x0,
327 "Sub-switch-id of switch in FabricPath network", HFILL
}},
330 { "End Node ID", "cfp.eid",
331 FT_UINT24
, BASE_DEC_HEX
, NULL
, FP_3B_EID_MASK
,
332 "Cisco FabricPath End node ID", HFILL
}},
335 { "Source LID", "cfp.lid",
336 FT_UINT16
, BASE_DEC_HEX
, NULL
, 0x0,
337 "Source or Destination Port index on switch in FabricPath network", HFILL
}},
340 { "U/L bit", "cfp.ul",
341 FT_BOOLEAN
, 24, TFS(&ul_tfs
), FP_UL_MASK
,
342 "Specifies if this is a locally administered or globally unique (IEEE assigned) address", HFILL
}},
345 { "I/G bit", "cfp.ig",
346 FT_BOOLEAN
, 24 /* FP_BF_LEN */, TFS(&ig_tfs
), FP_IG_MASK
,
347 "Specifies if this is an individual (unicast) or group (broadcast/multicast) address", HFILL
}},
350 { "OOO/DL Bit", "cfp.ooodl",
351 FT_BOOLEAN
, 24 /* FP_BF_LEN */, TFS(&ooodl_tfs
), FP_OOO_MASK
,
352 "Specifies Out of Order Delivery OK in destination address and Do Not Learn when set in source address", HFILL
}}
356 static gint
*ett
[] = {
361 module_t
*mim_module
;
363 proto_fp
= proto_register_protocol("Cisco FabricPath", "CFP", "cfp");
365 mim_module
= prefs_register_protocol (proto_fp
, proto_reg_handoff_fabricpath
);
367 prefs_register_bool_preference (mim_module
, "enable", "Enable dissector",
368 "Enable this dissector (default is false)",
369 &mim_enable_dissector
);
371 proto_register_field_array(proto_fp
, hf
, array_length(hf
));
372 proto_register_subtree_array(ett
, array_length(ett
));
376 proto_reg_handoff_fabricpath(void)
379 dissector_handle_t fp_handle;
380 fp_handle = new_create_dissector_handle(dissect_fp, proto_fp);
381 dissector_add_uint("ethertype", ETHERTYPE_DCE, fp_handle);
383 static gboolean prefs_initialized
= FALSE
;
385 if (!prefs_initialized
) {
387 * Using Heuristic dissector (As opposed to
388 * registering the ethertype) in order to
389 * get outer source and destination MAC
390 * before the standard ethernet dissector
392 heur_dissector_add ("eth", dissect_fp_heur
, proto_fp
);
393 eth_dissector
= find_dissector( "eth" );
394 prefs_initialized
= TRUE
;
397 proto_set_decoding(proto_fp
, mim_enable_dissector
);