diff options
author | Jaap Keuter <jaap.keuter@xs4all.nl> | 2007-09-20 06:50:53 +0000 |
---|---|---|
committer | Jaap Keuter <jaap.keuter@xs4all.nl> | 2007-09-20 06:50:53 +0000 |
commit | 79986b222d4f5d1386a10e1aa2814091d3ae996b (patch) | |
tree | 0ecae720654ce3d02a8e74dae388ae7015a2ec5c /epan | |
parent | bd81c014c3534ed854f86521974ef436b861a4f4 (diff) |
From Joe Eykholt:
At an August 2007 meeting, a T11 committee made changes to the encapsulation
protocol for FCoE. For the latest info, see http://fcoe.com.
The attached patch will update the dissector to handle the new version also.
svn path=/trunk/; revision=22915
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-fcoe.c | 107 |
1 files changed, 68 insertions, 39 deletions
diff --git a/epan/dissectors/packet-fcoe.c b/epan/dissectors/packet-fcoe.c index 82ec3b8f44..bf2a081906 100644 --- a/epan/dissectors/packet-fcoe.c +++ b/epan/dissectors/packet-fcoe.c @@ -1,4 +1,3 @@ - /* * packet-fcoe.c * Routines for FCoE dissection - Fibre Channel over Ethernet @@ -47,7 +46,8 @@ #include <epan/etypes.h> #include <epan/expert.h> -#define FCOE_ENCAP_HEADER_LEN 2 +#define FCOE_HEADER_LEN 14 /* header: version, SOF, and padding */ +#define FCOE_TRAILER_LEN 8 /* trailer: CRC, EOF, and padding */ typedef enum { FCOE_EOFn = 0x41, @@ -61,14 +61,14 @@ typedef enum { } fcoe_eof_t; typedef enum { - FCOE_SOFf = 0x8, - FCOE_SOFi4 = 0x9, - FCOE_SOFi2 = 0xD, - FCOE_SOFi3 = 0xE, - FCOE_SOFn4 = 0x1, - FCOE_SOFn2 = 0x5, - FCOE_SOFn3 = 0x6, - FCOE_SOFc4 = 0x9 + FCOE_SOFf = 0x28, + FCOE_SOFi4 = 0x29, + FCOE_SOFi2 = 0x2D, + FCOE_SOFi3 = 0x2E, + FCOE_SOFn4 = 0x31, + FCOE_SOFn2 = 0x35, + FCOE_SOFn3 = 0x36, + FCOE_SOFc4 = 0x39 } fcoe_sof_t; static const value_string fcoe_eof_vals[] = { @@ -113,8 +113,10 @@ static dissector_handle_t fc_handle; static void dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - gint eof_offset = 0; + gint crc_offset; + gint eof_offset; gint frame_len = 0; + gint header_len = FCOE_HEADER_LEN; guint version; char *ver; guint16 len_sof; @@ -123,6 +125,7 @@ dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guint8 eof = 0; const char *eof_str; char *crc_msg; + char *len_msg; proto_item *ti; proto_item *item; proto_tree *fcoe_tree = NULL; @@ -131,33 +134,51 @@ dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) gboolean crc_exists; guint32 crc_computed = 0; guint32 crc = 0; - - if (bytes_remaining < FCOE_ENCAP_HEADER_LEN) { - return; - } - - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCOE"); - len_sof = tvb_get_ntohs(tvb, 0); - frame_len = (len_sof & 0x3ff0) >> 2; - sof = len_sof & 0xf; - version = len_sof >> 14; - next_tvb = tvb_new_subset(tvb, FCOE_ENCAP_HEADER_LEN, -1, frame_len - 4); - - if (tree) { + /* + * For now, handle both the version defined before and after August 2007. + * In the newer version, byte 1 is reserved and always zero. In the old + * version, it'll never be zero. + */ + if (tvb_get_guint8(tvb, 1)) { + header_len = 2; + len_sof = tvb_get_ntohs(tvb, 0); + frame_len = ((len_sof & 0x3ff0) >> 2) - 4; + sof = len_sof & 0xf; + sof |= (sof < 8) ? 0x30 : 0x20; + version = len_sof >> 14; + ver = "pre-T11 "; + if (version != 0) { + int ver_buf_len = 24; + ver = ep_alloc(ver_buf_len); + g_snprintf(ver, ver_buf_len, "pre-T11 ver %d ", version); + } + } else { + frame_len = bytes_remaining - FCOE_HEADER_LEN - FCOE_TRAILER_LEN; + sof = tvb_get_guint8(tvb, FCOE_HEADER_LEN - 1); /* * Only version 0 is defined at this point. * Don't print the version in the short summary if it is zero. */ ver = ""; + version = tvb_get_guint8(tvb, 0) >> 4; if (version != 0) { int ver_buf_len = 16; ver = ep_alloc(ver_buf_len); g_snprintf(ver, ver_buf_len, "ver %d ", version); } - eof_offset = FCOE_ENCAP_HEADER_LEN + frame_len; + } + if (frame_len < 0) + return; + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCoE"); + crc_offset = header_len + frame_len; + eof_offset = crc_offset + 4; + next_tvb = tvb_new_subset(tvb, header_len, frame_len, frame_len); + + if (tree) { + eof_str = "none"; if (tvb_bytes_exist(tvb, eof_offset, 1)) { eof = tvb_get_guint8(tvb, eof_offset); @@ -168,28 +189,36 @@ dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) * Check the CRC. */ crc_msg = ""; - crc_exists = tvb_bytes_exist(tvb, eof_offset - 4, 4); + crc_exists = tvb_bytes_exist(tvb, crc_offset, 4); if (crc_exists) { - crc = tvb_get_ntohl(tvb, eof_offset - 4); - crc_computed = crc32_802_tvb(next_tvb, frame_len - 4); + crc = tvb_get_ntohl(tvb, crc_offset); + crc_computed = crc32_802_tvb(next_tvb, frame_len); if (crc != crc_computed) { crc_msg = " [bad FC CRC]"; } } + len_msg = ""; + if ((frame_len % 4) != 0 || frame_len < 24) { + len_msg = " [invalid length]"; + } ti = proto_tree_add_protocol_format(tree, proto_fcoe, tvb, 0, - FCOE_ENCAP_HEADER_LEN, - "FCoE %s(%s/%s) %d bytes%s", ver, + header_len, + "FCoE %s(%s/%s) %d bytes%s%s", ver, val_to_str(sof, fcoe_sof_vals, "0x%x"), - eof_str, frame_len, crc_msg); + eof_str, frame_len, crc_msg, + len_msg); /* Dissect the FCoE header */ fcoe_tree = proto_item_add_subtree(ti, ett_fcoe); - proto_tree_add_uint(fcoe_tree, hf_fcoe_sof, tvb, 1, 1, sof); proto_tree_add_uint(fcoe_tree, hf_fcoe_ver, tvb, 0, 1, version); - proto_tree_add_uint(fcoe_tree, hf_fcoe_len, tvb, 0, 2, frame_len); + if (tvb_get_guint8(tvb, 1)) { + proto_tree_add_uint(fcoe_tree, hf_fcoe_len, tvb, 0, 2, frame_len); + } + proto_tree_add_uint(fcoe_tree, hf_fcoe_sof, tvb, + header_len - 1, 1, sof); /* * Create the CRC information. @@ -198,11 +227,11 @@ dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if (crc_exists) { if (crc == crc_computed) { item = proto_tree_add_uint_format(fcoe_tree, hf_fcoe_crc, tvb, - eof_offset - 4, 4, crc, + crc_offset, 4, crc, "CRC: %8.8x [valid]", crc); } else { item = proto_tree_add_uint_format(fcoe_tree, hf_fcoe_crc, tvb, - eof_offset - 4, 4, crc, + crc_offset, 4, crc, "CRC: %8.8x " "[error: should be %8.8x]", crc, crc_computed); @@ -213,11 +242,11 @@ dissect_fcoe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) } crc_tree = proto_item_add_subtree(item, ett_fcoe_crc); ti = proto_tree_add_boolean(crc_tree, hf_fcoe_crc_bad, tvb, - eof_offset - 4, 4, + crc_offset, 4, crc_exists && crc != crc_computed); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_boolean(crc_tree, hf_fcoe_crc_good, tvb, - eof_offset - 4, 4, + crc_offset, 4, crc_exists && crc == crc_computed); PROTO_ITEM_SET_GENERATED(ti); @@ -266,7 +295,7 @@ proto_register_fcoe(void) { &hf_fcoe_ver, {"Version", "fcoe.ver", FT_UINT32, BASE_DEC, NULL, 0, "", HFILL}}, { &hf_fcoe_len, - {"Frame length", "fcoe.len", FT_UINT32, + {"Frame length", "fcoe.len", FT_UINT32, BASE_DEC, NULL, 0, "", HFILL}}, { &hf_fcoe_crc, {"CRC", "fcoe.crc", FT_UINT32, BASE_HEX, NULL, 0, "", HFILL}}, |