diff options
Diffstat (limited to 'epan/dissectors/packet-fc.c')
-rw-r--r-- | epan/dissectors/packet-fc.c | 118 |
1 files changed, 93 insertions, 25 deletions
diff --git a/epan/dissectors/packet-fc.c b/epan/dissectors/packet-fc.c index 386bb7b523..320411b669 100644 --- a/epan/dissectors/packet-fc.c +++ b/epan/dissectors/packet-fc.c @@ -57,7 +57,7 @@ #include <epan/emem.h> #define FC_HEADER_SIZE 24 -#define FC_RCTL_EISL 0x50 +#define FC_RCTL_VFT 0x50 #define MDSHDR_TRAILER_SIZE 6 /* Size of various fields in FC header in bytes */ @@ -107,9 +107,17 @@ static int hf_fc_rxid = -1; static int hf_fc_param = -1; static int hf_fc_ftype = -1; /* Derived field, non-existent in FC hdr */ static int hf_fc_reassembled = -1; -static int hf_fc_eisl = -1; static int hf_fc_relative_offset = -1; +/* VFT fields */ +static int hf_fc_vft = -1; +static int hf_fc_vft_rctl = -1; +static int hf_fc_vft_ver = -1; +static int hf_fc_vft_type = -1; +static int hf_fc_vft_pri = -1; +static int hf_fc_vft_vf_id = -1; +static int hf_fc_vft_hop_ct = -1; + /* Network_Header fields */ static int hf_fc_nh_da = -1; static int hf_fc_nh_sa = -1; @@ -130,6 +138,7 @@ static int hf_fc_bls_vendor = -1; static gint ett_fc = -1; static gint ett_fctl = -1; static gint ett_fcbls = -1; +static gint ett_fc_vft = -1; static dissector_table_t fcftype_dissector_table; static dissector_handle_t data_handle; @@ -203,7 +212,7 @@ const value_string fc_fc4_val[] = { {FC_TYPE_SNMP, "SNMP"}, {FC_TYPE_SB_FROM_CU, "SB-3(CU->Channel)"}, {FC_TYPE_SB_TO_CU, "SB-3(Channel->CU)"}, - {0, NULL}, + {0, NULL} }; static const value_string fc_ftype_vals [] = { @@ -219,7 +228,7 @@ static const value_string fc_ftype_vals [] = { {FC_FTYPE_LINKCTL, "Link Ctl"}, {FC_FTYPE_SBCCS, "SBCCS"}, {FC_FTYPE_OHMS, "OHMS(Cisco MDS)"}, - {0, NULL}, + {0, NULL} }; static const value_string fc_wka_vals[] _U_ = { @@ -234,7 +243,7 @@ static const value_string fc_wka_vals[] _U_ = { {FC_WKA_FABRIC_CTRLR, "Fabric Ctlr"}, {FC_WKA_FPORT, "F_Port Server"}, {FC_WKA_BCAST, "Broadcast ID"}, - {0, NULL}, + {0, NULL} }; static const value_string fc_routing_val[] = { @@ -244,7 +253,7 @@ static const value_string fc_routing_val[] = { {FC_RCTL_VIDEO, "Video_Data"}, {FC_RCTL_BLS, "Basic Link Services"}, {FC_RCTL_LINK_CTL, "Link_Control Frame"}, - {0, NULL}, + {0, NULL} }; static const value_string fc_iu_val[] = { @@ -256,7 +265,7 @@ static const value_string fc_iu_val[] = { {FC_IU_DATA_DESCRIPTOR , "Data Descriptor"}, {FC_IU_UNSOLICITED_CMD , "Unsolicited Command"}, {FC_IU_CMD_STATUS , "Command Status"}, - {0, NULL}, + {0, NULL} }; @@ -444,8 +453,45 @@ static const true_false_string tfs_fc_fctl_rel_offset = { "rel offset NOT set" }; - - +/* + * Dissect the VFT header. + */ +static void +dissect_fc_vft(proto_tree *parent_tree, + tvbuff_t *tvb, int offset) +{ + proto_item *item = NULL; + proto_tree *tree = NULL; + guint8 rctl; + guint8 ver; + guint8 type; + guint8 pri; + guint16 vf_id; + guint8 hop_ct; + + rctl = tvb_get_guint8(tvb, offset); + type = tvb_get_guint8(tvb, offset + 1); + ver = (type >> 6) & 3; + type = (type >> 2) & 0xf; + vf_id = tvb_get_ntohs(tvb, offset + 2); + pri = (vf_id >> 13) & 7; + vf_id = (vf_id >> 1) & 0xfff; + hop_ct = tvb_get_guint8(tvb, offset + 4); + + if (parent_tree) { + item = proto_tree_add_uint_format(parent_tree, hf_fc_vft, tvb, offset, + 8, vf_id, "VFT Header: " + "VF_ID %d Pri %d Hop Count %d", + vf_id, pri, hop_ct); + tree = proto_item_add_subtree(item, ett_fc_vft); + } + proto_tree_add_uint(tree, hf_fc_vft_rctl, tvb, offset, 1, rctl); + proto_tree_add_uint(tree, hf_fc_vft_ver, tvb, offset + 1, 1, ver); + proto_tree_add_uint(tree, hf_fc_vft_type, tvb, offset + 1, 1, type); + proto_tree_add_uint(tree, hf_fc_vft_pri, tvb, offset + 2, 1, pri); + proto_tree_add_uint(tree, hf_fc_vft_vf_id, tvb, offset + 2, 2, vf_id); + proto_tree_add_uint(tree, hf_fc_vft_hop_ct, tvb, offset + 4, 1, hop_ct); +} /* code to dissect the F_CTL bitmask */ static void @@ -563,14 +609,14 @@ static const value_string fc_bls_proto_val[] = { {FC_BLS_BAACC , "BA_ACC"}, {FC_BLS_BARJT , "BA_RJT"}, {FC_BLS_PRMT , "PRMT"}, - {0, NULL}, + {0, NULL} }; static const value_string fc_els_proto_val[] = { {0x01 , "Solicited Data"}, {0x02 , "Request"}, {0x03 , "Reply"}, - {0, NULL}, + {0, NULL} }; /* Code to actually dissect the packets */ @@ -581,7 +627,8 @@ dissect_fc_helper (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean proto_item *ti=NULL; proto_tree *fc_tree = NULL; tvbuff_t *next_tvb; - int offset = 0, next_offset, eisl_offset = -1; + int offset = 0, next_offset; + int vft_offset = -1; gboolean is_lastframe_inseq, is_1frame_inseq, is_valid_frame; gboolean is_exchg_resp = 0; fragment_data *fcfrag_head; @@ -611,11 +658,16 @@ dissect_fc_helper (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean fchdr.r_ctl = tvb_get_guint8 (tvb, offset); - /* If the R_CTL is the EISL field, skip the first 8 bytes to retrieve the - * real FC header. EISL is Cisco-proprietary and is not decoded. + /* + * If the frame contains a VFT (virtual fabric tag), decode it + * as a separate header before the FC frame header. + * + * This used to be called the Cisco-proprietary EISL field, but is now + * standardized in FC-FS-2. See section 10.2.4. */ - if (fchdr.r_ctl == FC_RCTL_EISL) { - eisl_offset = offset; + if (fchdr.r_ctl == FC_RCTL_VFT) { + pinfo->vsan = (tvb_get_ntohs(tvb, offset + 2) >> 1) & 0xfff; + vft_offset = offset; offset += 8; fchdr.r_ctl = tvb_get_guint8 (tvb, offset); } @@ -710,7 +762,6 @@ dissect_fc_helper (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean fc_tree = proto_item_add_subtree (ti, ett_fc); } - /* put some nice exchange data in the tree */ if(!(fchdr.fctl&FC_FCTL_EXCHANGE_FIRST)){ proto_item *it; @@ -759,13 +810,10 @@ dissect_fc_helper (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean fc_lctl_proto_val, "LCTL 0x%x")); } - - /* Highlight EISL header, if present */ - if (eisl_offset != -1) { - proto_tree_add_item (fc_tree, hf_fc_eisl, tvb, eisl_offset, 8, 0); - } - + if (vft_offset >= 0) { + dissect_fc_vft(fc_tree, tvb, vft_offset); + } switch (fchdr.r_ctl & 0xF0) { case FC_RCTL_DEV_DATA: @@ -1284,17 +1332,37 @@ proto_register_fc(void) { &hf_fc_time, { "Time from Exchange First", "fc.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Time since the first frame of the Exchange", HFILL }}, - { &hf_fc_eisl, - {"EISL Header", "fc.eisl", FT_BYTES, BASE_HEX, NULL, 0, "EISL Header", HFILL}}, { &hf_fc_relative_offset, {"Relative Offset", "fc.relative_offset", FT_UINT32, BASE_DEC, NULL, 0, "Relative offset of data", HFILL}}, + { &hf_fc_vft, + {"VFT Header", "fc.vft", FT_UINT16, BASE_DEC, NULL, + 0, "VFT Header", HFILL}}, + { &hf_fc_vft_rctl, + {"R_CTL", "fc.vft.rctl", FT_UINT8, BASE_HEX, NULL, + 0, "R_CTL", HFILL}}, + { &hf_fc_vft_ver, + {"Version", "fc.vft.ver", FT_UINT8, BASE_DEC, NULL, + 0, "Version of VFT header", HFILL}}, + { &hf_fc_vft_type, + {"Type", "fc.vft.type", FT_UINT8, BASE_DEC, NULL, + 0, "Type of tagged frame", HFILL}}, + { &hf_fc_vft_pri, + {"Priority", "fc.vft.type", FT_UINT8, BASE_DEC, NULL, + 0, "QoS Priority", HFILL}}, + { &hf_fc_vft_vf_id, + {"VF_ID", "fc.vft.vf_id", FT_UINT16, BASE_DEC, NULL, + 0, "Virtual Fabric ID", HFILL}}, + { &hf_fc_vft_hop_ct, + {"HopCT", "fc.vft.hop_ct", FT_UINT8, BASE_DEC, NULL, + 0, "Hop Count", HFILL}}, }; /* Setup protocol subtree array */ static gint *ett[] = { &ett_fc, &ett_fcbls, + &ett_fc_vft, &ett_fctl }; |