2 * Routines for Fibre Channel Single Byte Protocol (SBCCS); used in FICON.
3 * This decoder is for FC-SB3 version 1.4
4 * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
17 #include "packet-fc.h"
18 #include "packet-fcsb3.h"
20 void proto_register_fcsbccs(void);
21 void proto_reg_handoff_fcsbccs(void);
23 static dissector_handle_t fc_sbccs_handle
;
25 /* Initialize the protocol and registered fields */
26 static int proto_fc_sbccs
;
27 static int hf_sbccs_chid
;
28 static int hf_sbccs_cuid
;
29 static int hf_sbccs_devaddr
;
30 static int hf_sbccs_ccw
;
31 static int hf_sbccs_token
;
32 static int hf_sbccs_dib_iucnt
;
33 static int hf_sbccs_dib_datacnt
;
34 static int hf_sbccs_dib_ccw_cmd
;
35 static int hf_sbccs_dib_ccw_cnt
;
36 static int hf_sbccs_dib_residualcnt
;
37 static int hf_sbccs_dib_qtuf
;
38 static int hf_sbccs_dib_qtu
;
39 static int hf_sbccs_dib_dtuf
;
40 static int hf_sbccs_dib_dtu
;
41 static int hf_sbccs_dib_ctlfn
;
42 static int hf_sbccs_lrc
;
43 static int hf_sbccs_dib_iupacing
;
44 static int hf_sbccs_dev_xcp_code
;
45 static int hf_sbccs_prg_pth_errcode
;
46 static int hf_sbccs_prg_rsp_errcode
;
47 static int hf_sbccs_dib_ctccntr
;
48 static int hf_sbccs_dib_lprcode
;
49 static int hf_sbccs_dib_tin_imgid_cnt
;
50 static int hf_sbccs_dib_lrjcode
;
51 static int hf_sbccs_dib_ioprio
;
52 static int hf_sbccs_dib_linkctlfn
;
53 static int hf_sbccs_iui
;
54 static int hf_sbccs_iui_as
;
55 static int hf_sbccs_iui_es
;
56 static int hf_sbccs_iui_val
;
57 static int hf_sbccs_dhflags
;
58 static int hf_sbccs_dhflags_end
;
59 static int hf_sbccs_dhflags_chaining
;
60 static int hf_sbccs_dhflags_earlyend
;
61 static int hf_sbccs_dhflags_nocrc
;
62 static int hf_sbccs_dib_ccw_flags
;
63 static int hf_sbccs_dib_ccw_flags_cd
;
64 static int hf_sbccs_dib_ccw_flags_cc
;
65 static int hf_sbccs_dib_ccw_flags_sli
;
66 static int hf_sbccs_dib_ccw_flags_crr
;
67 static int hf_sbccs_dib_cmdflags
;
68 static int hf_sbccs_dib_cmdflags_du
;
69 static int hf_sbccs_dib_cmdflags_coc
;
70 static int hf_sbccs_dib_cmdflags_syr
;
71 static int hf_sbccs_dib_cmdflags_rex
;
72 static int hf_sbccs_dib_cmdflags_sss
;
73 static int hf_sbccs_dib_statusflags
;
74 static int hf_sbccs_dib_statusflags_ffc
;
75 static int hf_sbccs_dib_statusflags_ci
;
76 static int hf_sbccs_dib_statusflags_cr
;
77 static int hf_sbccs_dib_statusflags_lri
;
78 static int hf_sbccs_dib_statusflags_rv
;
79 static int hf_sbccs_dib_status
;
80 static int hf_sbccs_dib_status_attention
;
81 static int hf_sbccs_dib_status_modifier
;
82 static int hf_sbccs_dib_status_cue
;
83 static int hf_sbccs_dib_status_busy
;
84 static int hf_sbccs_dib_status_channelend
;
85 static int hf_sbccs_dib_status_deviceend
;
86 static int hf_sbccs_dib_status_unit_check
;
87 static int hf_sbccs_dib_status_unit_exception
;
88 static int hf_sbccs_dib_ctlparam
;
89 static int hf_sbccs_dib_ctlparam_rc
;
90 static int hf_sbccs_dib_ctlparam_ru
;
91 static int hf_sbccs_dib_ctlparam_ro
;
92 static int hf_sbccs_dib_linkctlinfo
;
93 static int hf_sbccs_dib_linkctlinfo_ctcconn
;
94 static int hf_sbccs_dib_linkctlinfo_ecrcg
;
95 static int hf_sbccs_logical_path
;
97 /* Initialize the subtree pointers */
98 static int ett_fc_sbccs
;
99 static int ett_sbccs_iui
;
100 static int ett_sbccs_dhflags
;
101 static int ett_sbccs_dib_ccw_flags
;
102 static int ett_sbccs_dib_cmdflags
;
103 static int ett_sbccs_dib_statusflags
;
104 static int ett_sbccs_dib_status
;
105 static int ett_sbccs_dib_ctlparam
;
106 static int ett_sbccs_dib_linkctlinfo
;
115 static const value_string fc_sbccs_iu_val
[] = {
116 {FC_SBCCS_IU_DATA
, "Data"},
117 {FC_SBCCS_IU_CMD_HDR
, "Command Header"},
118 {FC_SBCCS_IU_STATUS
, "Status"},
119 {FC_SBCCS_IU_CTL
, "Control"},
120 {FC_SBCCS_IU_CMD_DATA
, "Command Header & Data"},
121 {FC_SBCCS_IU_CMD_LINK_CTL
, "Link Control"},
127 static const value_string fc_sbccs_dib_cmd_val
[] = {
133 { 5, "Write (Modifier)"},
134 { 6, "Read (Modifier)"},
135 { 7, "Control (Modifier)"},
137 { 9, "Write (Modifier)"},
138 {10, "Read (Modifier)"},
139 {11, "Control (Modifier)"},
140 {12, "Read Backward"},
141 {13, "Write (Modifier)"},
142 {14, "Read (Modifier)"},
143 {15, "Control (Modifier)"},
147 static const value_string fc_sbccs_dib_ctl_fn_val
[] = {
148 {FC_SBCCS_CTL_FN_CTL_END
, "Control End"},
149 {FC_SBCCS_CTL_FN_CMD_RSP
, "Command Response"},
150 {FC_SBCCS_CTL_FN_STK_STS
, "Stack Status"},
151 {FC_SBCCS_CTL_FN_CANCEL
, "Cancel"},
152 {FC_SBCCS_CTL_FN_SYS_RST
, "System Reset"},
153 {FC_SBCCS_CTL_FN_SEL_RST
, "Selective Reset"},
154 {FC_SBCCS_CTL_FN_REQ_STS
, "Request Status"},
155 {FC_SBCCS_CTL_FN_DEV_XCP
, "Device Level Exception"},
156 {FC_SBCCS_CTL_FN_STS_ACC
, "Status Accepted"},
157 {FC_SBCCS_CTL_FN_DEV_ACK
, "Device-Level Ack"},
158 {FC_SBCCS_CTL_FN_PRG_PTH
, "Purge Path"},
159 {FC_SBCCS_CTL_FN_PRG_RSP
, "Purge Path Response"},
163 static const value_string fc_sbccs_dib_dev_xcpcode_val
[] = {
164 {1, "Address Exception"},
168 static const value_string fc_sbccs_dib_purge_path_err_val
[] = {
169 { 0, "Error Code Xfer Not Supported"},
170 { 1, "SB-3 Protocol Timeout"},
171 { 2, "SB-3 Link Failure"},
173 { 4, "SB-3 Offline Condition"},
174 { 5, "FC-PH Link Failure"},
175 { 6, "SB-3 Length Error"},
177 { 8, "SB-3 CRC Error"},
178 { 9, "IU Count Error"},
179 {10, "SB-3 Link Level Protocol Error"},
180 {11, "SB-3 Device Level Protocol Error"},
181 {12, "Receive ABTS"},
182 {13, "Cancel Function Timeout"},
183 {14, "Abnormal Termination of Xchg"},
188 static const value_string fc_sbccs_dib_purge_path_rsp_err_val
[] = {
190 { 1, "SB-3 Protocol Timeout"},
191 { 2, "SB-3 Link Failure"},
192 { 3, "Logical Path Timeout Error"},
193 { 4, "SB-3 Offline Condition"},
194 { 5, "FC-PH Link Failure"},
195 { 6, "SB-3 Length Error"},
197 { 8, "SB-3 CRC Error"},
198 { 9, "IU Count Error"},
199 {10, "SB-3 Link Level Protocol Error"},
200 {11, "SB-3 Device Level Protocol Error"},
201 {12, "Receive ABTS"},
203 {14, "Abnormal Termination of Xchg"},
204 {15, "Logical Path Not Estd"},
205 {16, "Test Init Result Error"},
209 static const value_string fc_sbccs_dib_link_ctl_fn_val
[] = {
210 {FC_SBCCS_LINK_CTL_FN_ELP
, "ELP"},
211 {FC_SBCCS_LINK_CTL_FN_RLP
, "RLP"},
212 {FC_SBCCS_LINK_CTL_FN_TIN
, "TIN"},
213 {FC_SBCCS_LINK_CTL_FN_LPE
, "LPE"},
214 {FC_SBCCS_LINK_CTL_FN_LPR
, "LPR"},
215 {FC_SBCCS_LINK_CTL_FN_TIR
, "TIR"},
216 {FC_SBCCS_LINK_CTL_FN_LRJ
, "LRJ"},
217 {FC_SBCCS_LINK_CTL_FN_LBY
, "LBY"},
218 {FC_SBCCS_LINK_CTL_FN_LACK
, "LACK"},
222 static const value_string fc_sbccs_dib_lpr_errcode_val
[] = {
223 {0x0, "Response to RLP"},
224 {0x1, "Optional Features Conflict"},
225 {0x2, "Out of Resources"},
226 {0x3, "Device Init In Progress"},
227 {0x4, "No CU Image"},
231 static const value_string fc_sbccs_dib_lrj_errcode_val
[] = {
232 {0x6, "Logical Path Not Estd"},
233 {0x9, "Protocol Error"},
238 dissect_iui_flags (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint16_t flags
)
240 static int * const iui_flags
[] = {
247 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_iui
,
248 ett_sbccs_iui
, iui_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
252 dissect_linkctlinfo (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint16_t flags
)
254 static int * const linkctlinfo_flags
[] = {
255 &hf_sbccs_dib_linkctlinfo_ctcconn
,
256 &hf_sbccs_dib_linkctlinfo_ecrcg
,
260 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_linkctlinfo
,
261 ett_sbccs_dib_linkctlinfo
, linkctlinfo_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
266 dissect_dh_flags (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint16_t flags
)
268 static int * const dh_flags
[] = {
269 &hf_sbccs_dhflags_end
,
270 &hf_sbccs_dhflags_chaining
,
271 &hf_sbccs_dhflags_earlyend
,
272 &hf_sbccs_dhflags_nocrc
,
276 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dhflags
,
277 ett_sbccs_dhflags
, dh_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
282 dissect_ccw_flags (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint8_t flags
)
284 static int * const ccw_flags
[] = {
285 &hf_sbccs_dib_ccw_flags_cd
,
286 &hf_sbccs_dib_ccw_flags_cc
,
287 &hf_sbccs_dib_ccw_flags_sli
,
288 &hf_sbccs_dib_ccw_flags_crr
,
292 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_ccw_flags
,
293 ett_sbccs_dib_ccw_flags
, ccw_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
298 dissect_cmd_flags (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint8_t flags
)
300 static int * const cmd_flags
[] = {
301 &hf_sbccs_dib_cmdflags_du
,
302 &hf_sbccs_dib_cmdflags_coc
,
303 &hf_sbccs_dib_cmdflags_syr
,
304 &hf_sbccs_dib_cmdflags_rex
,
305 &hf_sbccs_dib_cmdflags_sss
,
309 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_cmdflags
,
310 ett_sbccs_dib_cmdflags
, cmd_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
313 static const value_string status_ffc_val
[] = {
315 { 1, "FFC:Queuing Information Valid" },
316 { 2, "FFC:Resetting Event" },
322 dissect_status_flags (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint8_t flags
)
324 static int * const status_flags
[] = {
325 &hf_sbccs_dib_statusflags_ffc
,
326 &hf_sbccs_dib_statusflags_ci
,
327 &hf_sbccs_dib_statusflags_cr
,
328 &hf_sbccs_dib_statusflags_lri
,
329 &hf_sbccs_dib_statusflags_rv
,
333 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_statusflags
,
334 ett_sbccs_dib_statusflags
, status_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
339 dissect_status (packet_info
*pinfo
, proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint8_t flags
)
341 static int * const status_flags
[] = {
342 &hf_sbccs_dib_status_attention
,
343 &hf_sbccs_dib_status_modifier
,
344 &hf_sbccs_dib_status_cue
,
345 &hf_sbccs_dib_status_busy
,
346 &hf_sbccs_dib_status_channelend
,
347 &hf_sbccs_dib_status_deviceend
,
348 &hf_sbccs_dib_status_unit_check
,
349 &hf_sbccs_dib_status_unit_exception
,
352 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_status
,
353 ett_sbccs_dib_status
, status_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
356 col_append_str(pinfo
->cinfo
, COL_INFO
, " Attention");
360 col_append_str(pinfo
->cinfo
, COL_INFO
, " Status Modifier");
364 col_append_str(pinfo
->cinfo
, COL_INFO
, " Control-Unit End");
368 col_append_str(pinfo
->cinfo
, COL_INFO
, " Busy");
371 col_append_str(pinfo
->cinfo
, COL_INFO
, " Channel End");
375 col_append_str(pinfo
->cinfo
, COL_INFO
, " Device End");
379 col_append_str(pinfo
->cinfo
, COL_INFO
, " Unit Check");
383 col_append_str(pinfo
->cinfo
, COL_INFO
, " Unit Exception");
389 dissect_sel_rst_param (proto_tree
*parent_tree
, tvbuff_t
*tvb
, int offset
, uint32_t flags
)
391 static int * const rst_param_flags
[] = {
392 &hf_sbccs_dib_ctlparam_rc
,
393 &hf_sbccs_dib_ctlparam_ru
,
394 &hf_sbccs_dib_ctlparam_ro
,
398 proto_tree_add_bitmask_value_with_flags(parent_tree
, tvb
, offset
, hf_sbccs_dib_ctlparam
,
399 ett_sbccs_dib_ctlparam
, rst_param_flags
, flags
, BMT_NO_FALSE
|BMT_NO_TFS
);
402 static void get_fc_sbccs_conv_data (tvbuff_t
*tvb
, unsigned offset
,
403 uint16_t *ch_cu_id
, uint16_t *dev_addr
,
406 *ch_cu_id
= *dev_addr
= *ccw
= 0;
408 *ch_cu_id
= (tvb_get_uint8 (tvb
, offset
+1)) << 8;
409 *ch_cu_id
|= tvb_get_uint8 (tvb
, offset
+3);
410 *dev_addr
= tvb_get_ntohs (tvb
, offset
+4);
411 *ccw
= tvb_get_ntohs (tvb
, offset
+10);
414 /* Decode both the SB-3 and basic IU header */
416 dissect_fc_sbccs_sb3_iu_hdr (tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
419 proto_tree
*sb3hdr_tree
;
420 proto_tree
*iuhdr_tree
;
421 uint8_t iui
, dhflags
;
424 /* Decode the basic SB3 and IU header and determine type of frame */
425 type
= get_fc_sbccs_iu_type (tvb
, offset
);
427 col_add_str (pinfo
->cinfo
, COL_INFO
, val_to_str (type
, fc_sbccs_iu_val
,
431 /* Dissect SB3 header first */
432 sb3hdr_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, FC_SBCCS_SB3_HDR_SIZE
,
433 ett_fc_sbccs
, NULL
, "SB-3 Header");
435 proto_tree_add_item (sb3hdr_tree
, hf_sbccs_chid
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
436 proto_tree_add_item (sb3hdr_tree
, hf_sbccs_cuid
, tvb
, offset
+3, 1, ENC_BIG_ENDIAN
);
437 proto_tree_add_item (sb3hdr_tree
, hf_sbccs_devaddr
, tvb
, offset
+4, 2, ENC_BIG_ENDIAN
);
439 /* Dissect IU Header */
440 iuhdr_tree
= proto_tree_add_subtree(tree
, tvb
, offset
+ FC_SBCCS_SB3_HDR_SIZE
,
441 FC_SBCCS_IU_HDR_SIZE
, ett_fc_sbccs
, NULL
, "IU Header");
442 offset
+= FC_SBCCS_SB3_HDR_SIZE
;
444 iui
= tvb_get_uint8 (tvb
, offset
);
445 dissect_iui_flags(iuhdr_tree
, tvb
, offset
, iui
);
447 dhflags
= tvb_get_uint8 (tvb
, offset
+1);
448 dissect_dh_flags(iuhdr_tree
, tvb
, offset
+1, dhflags
);
450 proto_tree_add_item (iuhdr_tree
, hf_sbccs_ccw
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
451 proto_tree_add_item (iuhdr_tree
, hf_sbccs_token
, tvb
, offset
+5, 3, ENC_BIG_ENDIAN
);
455 static void dissect_fc_sbccs_dib_data_hdr (tvbuff_t
*tvb
,
456 packet_info
*pinfo _U_
,
457 proto_tree
*tree
, unsigned offset
)
460 proto_tree_add_item (tree
, hf_sbccs_dib_iucnt
, tvb
, offset
+9, 1, ENC_BIG_ENDIAN
);
461 proto_tree_add_item (tree
, hf_sbccs_dib_datacnt
, tvb
, offset
+10, 2, ENC_BIG_ENDIAN
);
462 proto_tree_add_item (tree
, hf_sbccs_lrc
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
466 static void dissect_fc_sbccs_dib_cmd_hdr (tvbuff_t
*tvb
, packet_info
*pinfo
,
467 proto_tree
*tree
, unsigned offset
)
471 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
472 ": %s", val_to_str (tvb_get_uint8 (tvb
, offset
),
473 fc_sbccs_dib_cmd_val
,
477 proto_tree_add_item (tree
, hf_sbccs_dib_ccw_cmd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
479 flags
= tvb_get_uint8 (tvb
, offset
+1);
480 dissect_ccw_flags(tree
, tvb
, offset
+1, flags
);
482 proto_tree_add_item (tree
, hf_sbccs_dib_ccw_cnt
, tvb
, offset
+2, 2, ENC_BIG_ENDIAN
);
483 proto_tree_add_item (tree
, hf_sbccs_dib_ioprio
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
485 flags
= tvb_get_uint8 (tvb
, offset
+7);
486 dissect_cmd_flags(tree
, tvb
, offset
+7, flags
);
488 proto_tree_add_item (tree
, hf_sbccs_dib_iucnt
, tvb
, offset
+9, 1, ENC_BIG_ENDIAN
);
489 proto_tree_add_item (tree
, hf_sbccs_dib_datacnt
, tvb
, offset
+10, 2, ENC_BIG_ENDIAN
);
490 proto_tree_add_item (tree
, hf_sbccs_lrc
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
495 static void dissect_fc_sbccs_dib_status_hdr (tvbuff_t
*tvb
, packet_info
*pinfo
,
496 proto_tree
*tree
, unsigned offset
)
499 bool rv_valid
, qparam_valid
;
501 uint16_t supp_status_cnt
= 0;
504 flags
= tvb_get_uint8 (tvb
, offset
);
505 rv_valid
= flags
& 0x1; /* if residual count is valid */
506 qparam_valid
= (((flags
& 0xE0) >> 5) == 0x1); /* From the FFC field */
507 dissect_status_flags(tree
, tvb
, offset
, flags
);
509 flags
= tvb_get_uint8 (tvb
, offset
+1);
510 dissect_status(pinfo
, tree
, tvb
, offset
+1, flags
);
513 proto_tree_add_item (tree
, hf_sbccs_dib_residualcnt
, tvb
, offset
+2,
517 proto_tree_add_item (tree
, hf_sbccs_dib_iupacing
, tvb
, offset
+3,
522 proto_tree_add_item (tree
, hf_sbccs_dib_qtuf
, tvb
, offset
+4, 1, ENC_BIG_ENDIAN
);
523 proto_tree_add_item (tree
, hf_sbccs_dib_qtu
, tvb
, offset
+4, 2, ENC_BIG_ENDIAN
);
526 proto_tree_add_item (tree
, hf_sbccs_dib_dtuf
, tvb
, offset
+6, 1, ENC_BIG_ENDIAN
);
527 proto_tree_add_item (tree
, hf_sbccs_dib_dtu
, tvb
, offset
+6, 2, ENC_BIG_ENDIAN
);
529 proto_tree_add_item (tree
, hf_sbccs_dib_iucnt
, tvb
, offset
+9, 1, ENC_BIG_ENDIAN
);
530 proto_tree_add_item (tree
, hf_sbccs_dib_datacnt
, tvb
, offset
+10, 2, ENC_BIG_ENDIAN
);
531 proto_tree_add_item (tree
, hf_sbccs_lrc
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
534 supp_status_cnt
= tvb_get_ntohs (tvb
, offset
+10);
536 if (supp_status_cnt
) {
537 next_tvb
= tvb_new_subset_remaining (tvb
, offset
+FC_SBCCS_DIB_LRC_HDR_SIZE
);
538 call_data_dissector(next_tvb
, pinfo
, tree
);
542 static void dissect_fc_sbccs_dib_ctl_hdr (tvbuff_t
*tvb
, packet_info
*pinfo
,
543 proto_tree
*tree
, unsigned offset
)
547 ctlfn
= tvb_get_uint8 (tvb
, offset
);
548 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
551 fc_sbccs_dib_ctl_fn_val
,
555 proto_tree_add_item (tree
, hf_sbccs_dib_ctlfn
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
557 /* Control Function Parameter is to be interpreted in some cases */
559 case FC_SBCCS_CTL_FN_SEL_RST
:
560 dissect_sel_rst_param(tree
, tvb
, offset
+1, tvb_get_ntoh24 (tvb
, offset
+1));
562 case FC_SBCCS_CTL_FN_DEV_XCP
:
563 proto_tree_add_item (tree
, hf_sbccs_dev_xcp_code
, tvb
, offset
+1,
566 case FC_SBCCS_CTL_FN_PRG_PTH
:
567 proto_tree_add_item (tree
, hf_sbccs_prg_pth_errcode
, tvb
, offset
+1,
571 proto_tree_add_item (tree
, hf_sbccs_dib_ctlparam
, tvb
, offset
+1,
576 proto_tree_add_item (tree
, hf_sbccs_dib_iucnt
, tvb
, offset
+9, 1, ENC_BIG_ENDIAN
);
577 proto_tree_add_item (tree
, hf_sbccs_dib_datacnt
, tvb
, offset
+10, 2, ENC_BIG_ENDIAN
);
578 proto_tree_add_item (tree
, hf_sbccs_lrc
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
580 if (ctlfn
== FC_SBCCS_CTL_FN_PRG_RSP
) {
581 /* Need to decode the LESBs */
582 proto_tree_add_item (tree
, hf_sbccs_prg_rsp_errcode
, tvb
, offset
+60,
588 static void dissect_fc_sbccs_dib_link_hdr (tvbuff_t
*tvb
, packet_info
*pinfo
,
589 proto_tree
*tree
, unsigned offset
)
593 unsigned link_payload_len
, i
;
595 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
597 val_to_str (tvb_get_uint8 (tvb
, offset
+1),
598 fc_sbccs_dib_link_ctl_fn_val
,
602 link_ctl
= tvb_get_uint8 (tvb
, offset
+1);
603 proto_tree_add_item (tree
, hf_sbccs_dib_linkctlfn
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
605 ctl_info
= tvb_get_ntohs (tvb
, offset
+2);
607 case FC_SBCCS_LINK_CTL_FN_ELP
:
608 case FC_SBCCS_LINK_CTL_FN_LPE
:
609 dissect_linkctlinfo(tree
, tvb
, offset
+2, ctl_info
);
611 case FC_SBCCS_LINK_CTL_FN_LPR
:
612 proto_tree_add_item (tree
, hf_sbccs_dib_lprcode
, tvb
, offset
+2, 1,
615 case FC_SBCCS_LINK_CTL_FN_TIN
:
616 proto_tree_add_item (tree
, hf_sbccs_dib_tin_imgid_cnt
, tvb
,
617 offset
+3, 1, ENC_BIG_ENDIAN
);
619 case FC_SBCCS_LINK_CTL_FN_TIR
:
620 proto_tree_add_item (tree
, hf_sbccs_dib_tin_imgid_cnt
, tvb
,
621 offset
+3, 1, ENC_BIG_ENDIAN
);
623 case FC_SBCCS_LINK_CTL_FN_LRJ
:
624 proto_tree_add_item (tree
, hf_sbccs_dib_lrjcode
, tvb
, offset
+2,
632 proto_tree_add_item (tree
, hf_sbccs_dib_ctccntr
, tvb
, offset
+4, 2, ENC_BIG_ENDIAN
);
633 proto_tree_add_item (tree
, hf_sbccs_dib_iucnt
, tvb
, offset
+9, 1, ENC_BIG_ENDIAN
);
634 proto_tree_add_item (tree
, hf_sbccs_dib_datacnt
, tvb
, offset
+10, 2, ENC_BIG_ENDIAN
);
635 proto_tree_add_item (tree
, hf_sbccs_lrc
, tvb
, offset
+12, 4, ENC_BIG_ENDIAN
);
637 if (link_ctl
== FC_SBCCS_LINK_CTL_FN_TIR
) {
638 link_payload_len
= tvb_get_ntohs (tvb
, offset
+10);
642 while (i
< link_payload_len
) {
643 proto_tree_add_bytes_format(tree
, hf_sbccs_logical_path
, tvb
, offset
, 4,
644 NULL
, "Logical Paths %d-%d: %s",
646 tvb_bytes_to_str_punct(pinfo
->pool
, tvb
, offset
, 4, ':'));
654 static int dissect_fc_sbccs (tvbuff_t
*tvb
, packet_info
*pinfo
,
655 proto_tree
*tree
, void* data _U_
)
658 uint16_t ch_cu_id
, dev_addr
, ccw
;
661 proto_tree
*sb3_tree
= NULL
;
662 proto_tree
*dib_tree
= NULL
;
664 conversation_t
*conversation
;
666 sb3_task_id_t task_key
;
669 /* Make entries in Protocol column and Info column on summary display */
670 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FC-SB3");
672 /* Decode the basic SB3 and IU header and determine type of frame */
673 type
= get_fc_sbccs_iu_type (tvb
, offset
);
674 get_fc_sbccs_conv_data (tvb
, offset
, &ch_cu_id
, &dev_addr
, &ccw
);
676 col_add_str (pinfo
->cinfo
, COL_INFO
, val_to_str (type
, fc_sbccs_iu_val
,
679 /* Retrieve conversation state to determine expected payload */
680 conversation
= find_conversation (pinfo
->num
, &pinfo
->src
, &pinfo
->dst
,
681 CONVERSATION_SBCCS
, ch_cu_id
, dev_addr
, 0);
685 task_key
.conv_id
= conversation
->index
;
686 task_key
.task_id
= ccw
;
689 else if ((type
== FC_SBCCS_IU_CMD_HDR
) ||
690 (type
!= FC_SBCCS_IU_CMD_DATA
)) {
694 conversation_new (pinfo
->num
, &pinfo
->src
, &pinfo
->dst
,
695 CONVERSATION_SBCCS
, ch_cu_id
, dev_addr
, 0);
697 task_key
.conv_id
= conversation
->index
;
698 task_key
.task_id
= ccw
;
703 ti
= proto_tree_add_protocol_format (tree
, proto_fc_sbccs
, tvb
, 0, -1,
705 sb3_tree
= proto_item_add_subtree (ti
, ett_fc_sbccs
);
707 dissect_fc_sbccs_sb3_iu_hdr (tvb
, pinfo
, sb3_tree
, offset
);
708 offset
+= (FC_SBCCS_SB3_HDR_SIZE
+ FC_SBCCS_IU_HDR_SIZE
);
710 dib_tree
= proto_tree_add_subtree(sb3_tree
, tvb
, offset
,
711 FC_SBCCS_DIB_LRC_HDR_SIZE
, ett_fc_sbccs
, NULL
, "DIB Header");
714 offset
+= (FC_SBCCS_SB3_HDR_SIZE
+ FC_SBCCS_IU_HDR_SIZE
);
718 case FC_SBCCS_IU_DATA
:
719 dissect_fc_sbccs_dib_data_hdr (tvb
, pinfo
, dib_tree
, offset
);
721 case FC_SBCCS_IU_CMD_HDR
:
722 case FC_SBCCS_IU_CMD_DATA
:
723 dissect_fc_sbccs_dib_cmd_hdr (tvb
, pinfo
, dib_tree
, offset
);
725 case FC_SBCCS_IU_STATUS
:
726 dissect_fc_sbccs_dib_status_hdr (tvb
, pinfo
, dib_tree
, offset
);
728 case FC_SBCCS_IU_CTL
:
729 dissect_fc_sbccs_dib_ctl_hdr (tvb
, pinfo
, dib_tree
, offset
);
731 case FC_SBCCS_IU_CMD_LINK_CTL
:
732 dissect_fc_sbccs_dib_link_hdr (tvb
, pinfo
, dib_tree
, offset
);
735 next_tvb
= tvb_new_subset_remaining (tvb
, offset
);
736 call_data_dissector(next_tvb
, pinfo
, dib_tree
);
740 if ((get_fc_sbccs_iu_type (tvb
, 0) != FC_SBCCS_IU_CTL
) &&
741 (get_fc_sbccs_iu_type (tvb
, 0) != FC_SBCCS_IU_CMD_LINK_CTL
)) {
742 next_tvb
= tvb_new_subset_remaining (tvb
, offset
+FC_SBCCS_DIB_LRC_HDR_SIZE
);
743 call_data_dissector(next_tvb
, pinfo
, tree
);
745 return tvb_captured_length(tvb
);
748 /* Register the protocol with Wireshark */
750 /* this format is required because a script is used to build the C function
751 that calls all the protocol registration.
755 proto_register_fcsbccs (void)
757 /* Setup list of header fields See Section 1.6.1 for details*/
758 static hf_register_info hf
[] = {
760 { "Channel Image ID", "fcsb3.chid",
761 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
765 { "Control Unit Image ID", "fcsb3.cuid",
766 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
770 { "Device Address", "fcsb3.devaddr",
771 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
775 { "Information Unit Identifier", "fcsb3.iui",
776 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
780 { "DH Flags", "fcsb3.dhflags",
781 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
785 { "CCW Number", "fcsb3.ccw",
786 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
790 { "Token", "fcsb3.token",
791 FT_UINT24
, BASE_DEC
, NULL
, 0x0,
794 { &hf_sbccs_dib_iucnt
,
795 { "DIB IU Count", "fcsb3.iucnt",
796 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
799 { &hf_sbccs_dib_datacnt
,
800 { "DIB Data Byte Count", "fcsb3.databytecnt",
801 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
804 { &hf_sbccs_dib_ccw_cmd
,
805 { "CCW Command", "fcsb3.ccwcmd",
806 FT_UINT8
, BASE_HEX
, VALS (fc_sbccs_dib_cmd_val
), 0x0,
809 { &hf_sbccs_dib_ccw_cnt
,
810 { "CCW Count", "fcsb3.ccwcnt",
811 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
814 { &hf_sbccs_dib_ioprio
,
815 { "I/O Priority", "fcsb3.ioprio",
816 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
819 { &hf_sbccs_dib_status
,
820 { "Status", "fcsb3.status",
821 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
824 { &hf_sbccs_dib_residualcnt
,
825 { "Residual Count", "fcsb3.residualcnt",
826 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
829 { &hf_sbccs_dib_iupacing
,
830 { "IU Pacing", "fcsb3.iupacing",
831 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
834 { &hf_sbccs_dib_qtuf
,
835 { "Queue-Time Unit Factor", "fcsb3.qtuf",
836 FT_UINT8
, BASE_DEC
, NULL
, 0xF0,
840 { "Queue-Time Unit", "fcsb3.qtu",
841 FT_UINT16
, BASE_DEC
, NULL
, 0x0FFF,
844 { &hf_sbccs_dib_dtuf
,
845 { "Defer-Time Unit Function", "fcsb3.dtuf",
846 FT_UINT8
, BASE_DEC
, NULL
, 0xF0,
850 { "Defer-Time Unit", "fcsb3.dtu",
851 FT_UINT16
, BASE_DEC
, NULL
, 0x0FFF,
854 { &hf_sbccs_dib_ctlfn
,
855 { "Control Function", "fcsb3.ctlfn",
856 FT_UINT8
, BASE_HEX
, VALS (fc_sbccs_dib_ctl_fn_val
), 0x0,
859 { &hf_sbccs_dib_linkctlfn
,
860 { "Link Control Function", "fcsb3.linkctlfn",
861 FT_UINT8
, BASE_HEX
, VALS (fc_sbccs_dib_link_ctl_fn_val
), 0x0,
864 { &hf_sbccs_dib_ctccntr
,
865 { "CTC Counter", "fcsb3.ctccntr",
866 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
870 { "LRC", "fcsb3.lrc",
871 FT_UINT32
, BASE_HEX
, NULL
, 0x0,
874 { &hf_sbccs_dev_xcp_code
,
875 { "Device Level Exception Code", "fcsb3.dip.xcpcode",
876 FT_UINT8
, BASE_DEC
, VALS (fc_sbccs_dib_dev_xcpcode_val
), 0x0,
879 { &hf_sbccs_prg_pth_errcode
,
880 { "Purge Path Error Code", "fcsb3.purgepathcode",
881 FT_UINT8
, BASE_DEC
, VALS (fc_sbccs_dib_purge_path_err_val
), 0x0,
884 { &hf_sbccs_prg_rsp_errcode
,
885 { "Purge Path Response Error Code", "fcsb3.purgepathrspcode",
886 FT_UINT8
, BASE_DEC
, VALS (fc_sbccs_dib_purge_path_rsp_err_val
), 0x0,
889 { &hf_sbccs_dib_lprcode
,
890 { "LPR Reason Code", "fcsb3.lprcode",
891 FT_UINT8
, BASE_DEC
, VALS (fc_sbccs_dib_lpr_errcode_val
), 0xF,
894 { &hf_sbccs_dib_tin_imgid_cnt
,
895 { "TIN Image ID", "fcsb3.tinimageidcnt",
896 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
899 { &hf_sbccs_dib_lrjcode
,
900 { "LRJ Reason Code", "fcsb3.lrjcode",
901 FT_UINT8
, BASE_HEX
, VALS (fc_sbccs_dib_lrj_errcode_val
), 0x7F,
905 { "AS", "fcsb3.iui.as",
906 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
910 { "ES", "fcsb3.iui.es",
911 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
915 { "Val", "fcsb3.iui.val",
916 FT_UINT8
, BASE_HEX
, VALS(fc_sbccs_iu_val
), 0x07,
919 { &hf_sbccs_dhflags_end
,
920 { "End", "fcsb3.dhflags.end",
921 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x80,
924 { &hf_sbccs_dhflags_chaining
,
925 { "Chaining", "fcsb3.dhflags.chaining",
926 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
929 { &hf_sbccs_dhflags_earlyend
,
930 { "Early End", "fcsb3.dhflags.earlyend",
931 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
934 { &hf_sbccs_dhflags_nocrc
,
935 { "No CRC", "fcsb3.dhflags.nocrc",
936 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x04,
939 { &hf_sbccs_dib_ccw_flags
,
940 { "CCW Control Flags", "fcsb3.ccwflags",
941 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
944 { &hf_sbccs_dib_ccw_flags_cd
,
945 { "CD", "fcsb3.ccwflags.cd",
946 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x80,
949 { &hf_sbccs_dib_ccw_flags_cc
,
950 { "CC", "fcsb3.ccwflags.cc",
951 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x40,
954 { &hf_sbccs_dib_ccw_flags_sli
,
955 { "SLI", "fcsb3.ccwflags.sli",
956 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x20,
959 { &hf_sbccs_dib_ccw_flags_crr
,
960 { "CRR", "fcsb3.ccwflags.crr",
961 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
964 { &hf_sbccs_dib_cmdflags
,
965 { "Command Flags", "fcsb3.cmdflags",
966 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
969 { &hf_sbccs_dib_cmdflags_du
,
970 { "DU", "fcsb3.cmdflags.du",
971 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
974 { &hf_sbccs_dib_cmdflags_coc
,
975 { "COC", "fcsb3.cmdflags.coc",
976 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
979 { &hf_sbccs_dib_cmdflags_syr
,
980 { "SYR", "fcsb3.cmdflags.syr",
981 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x04,
984 { &hf_sbccs_dib_cmdflags_rex
,
985 { "REX", "fcsb3.cmdflags.rex",
986 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x02,
989 { &hf_sbccs_dib_cmdflags_sss
,
990 { "SSS", "fcsb3.cmdflags.sss",
991 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x01,
994 { &hf_sbccs_dib_statusflags
,
995 { "Status Flags", "fcsb3.statusflags",
996 FT_UINT8
, BASE_HEX
, NULL
, 0,
999 { &hf_sbccs_dib_statusflags_ffc
,
1000 { "FFC", "fcsb3.statusflags.ffc",
1001 FT_UINT8
, BASE_HEX
, VALS(status_ffc_val
), 0xE0,
1004 { &hf_sbccs_dib_statusflags_ci
,
1005 { "CI", "fcsb3.statusflags.ci",
1006 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
1009 { &hf_sbccs_dib_statusflags_cr
,
1010 { "CR", "fcsb3.statusflags.cr",
1011 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x04,
1014 { &hf_sbccs_dib_statusflags_lri
,
1015 { "LRI", "fcsb3.statusflags.lri",
1016 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x02,
1019 { &hf_sbccs_dib_statusflags_rv
,
1020 { "RV", "fcsb3.statusflags.rv",
1021 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x01,
1024 { &hf_sbccs_dib_status_attention
,
1025 { "Attention", "fcsb3.status.attention",
1026 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x80,
1029 { &hf_sbccs_dib_status_modifier
,
1030 { "Status Modifier", "fcsb3.status.modifier",
1031 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x40,
1034 { &hf_sbccs_dib_status_cue
,
1035 { "Control-Unit End", "fcsb3.status.cue",
1036 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x20,
1039 { &hf_sbccs_dib_status_busy
,
1040 { "Busy", "fcsb3.status.busy",
1041 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x10,
1044 { &hf_sbccs_dib_status_channelend
,
1045 { "Channel End", "fcsb3.status.channel_end",
1046 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x08,
1049 { &hf_sbccs_dib_status_deviceend
,
1050 { "Device End", "fcsb3.status.device_end",
1051 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x04,
1054 { &hf_sbccs_dib_status_unit_check
,
1055 { "Unit Check", "fcsb3.status.unit_check",
1056 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x02,
1059 { &hf_sbccs_dib_status_unit_exception
,
1060 { "Unit Exception", "fcsb3.status.unitexception",
1061 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x01,
1064 { &hf_sbccs_dib_ctlparam
,
1065 { "Control Parameters", "fcsb3.ctlparam",
1066 FT_UINT24
, BASE_HEX
, NULL
, 0x0,
1069 { &hf_sbccs_dib_ctlparam_rc
,
1070 { "RC", "fcsb3.ctlparam.rc",
1071 FT_BOOLEAN
, 24, TFS(&tfs_set_notset
), 0x000080,
1074 { &hf_sbccs_dib_ctlparam_ru
,
1075 { "RU", "fcsb3.ctlparam.ru",
1076 FT_BOOLEAN
, 24, TFS(&tfs_set_notset
), 0x000010,
1079 { &hf_sbccs_dib_ctlparam_ro
,
1080 { "RO", "fcsb3.ctlparam.ro",
1081 FT_BOOLEAN
, 24, TFS(&tfs_set_notset
), 0x000008,
1084 { &hf_sbccs_dib_linkctlinfo
,
1085 { "Link Control Information", "fcsb3.linkctlinfo",
1086 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
1089 { &hf_sbccs_dib_linkctlinfo_ctcconn
,
1090 { "CTC Conn", "fcsb3.linkctlinfo.ctc_conn",
1091 FT_BOOLEAN
, 16, TFS(&tfs_supported_not_supported
), 0x0080,
1094 { &hf_sbccs_dib_linkctlinfo_ecrcg
,
1095 { "Enhanced CRC Generation", "fcsb3.linkctlinfo.ecrcg",
1096 FT_BOOLEAN
, 16, TFS(&tfs_supported_not_supported
), 0x0001,
1099 { &hf_sbccs_logical_path
,
1100 { "Logical Path", "fcsb3.logical_path",
1101 FT_BYTES
, SEP_COLON
, NULL
, 0x0,
1106 /* Setup protocol subtree array */
1107 static int *ett
[] = {
1111 &ett_sbccs_dib_ccw_flags
,
1112 &ett_sbccs_dib_cmdflags
,
1113 &ett_sbccs_dib_statusflags
,
1114 &ett_sbccs_dib_status
,
1115 &ett_sbccs_dib_ctlparam
,
1116 &ett_sbccs_dib_linkctlinfo
,
1119 /* Register the protocol name and description */
1120 proto_fc_sbccs
= proto_register_protocol ("Fibre Channel Single Byte Command",
1123 proto_register_field_array(proto_fc_sbccs
, hf
, array_length(hf
));
1124 proto_register_subtree_array(ett
, array_length(ett
));
1126 fc_sbccs_handle
= register_dissector("fcsb3", dissect_fc_sbccs
, proto_fc_sbccs
);
1130 proto_reg_handoff_fcsbccs (void)
1132 dissector_add_uint("fc.ftype", FC_FTYPE_SBCCS
, fc_sbccs_handle
);
1136 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1141 * indent-tabs-mode: nil
1144 * vi: set shiftwidth=4 tabstop=8 expandtab:
1145 * :indentSize=4:tabSize=8:noTabs=true: