From Dan Gora:
authorjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 25 May 2009 06:50:34 +0000 (06:50 +0000)
committerjake <jake@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 25 May 2009 06:50:34 +0000 (06:50 +0000)
This patch adds support for the I-TDM control protocol specified in PICMG SFP.1 chapter 3.12.
This control protocol is used to "automatically" initialize new I-TDM data flows.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@28468 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dissectors/packet-itdm.c

index 3a6ed872aab3d361839c224c5db6ca678c487673..fc7511aa5e34bbfce20e9a73f21cd57d57e1401b 100644 (file)
@@ -51,14 +51,28 @@ static int hf_itdm_chloc2    = -1;
 static int hf_itdm_pktrate   = -1;
 static int hf_itdm_cxnsize   = -1;
 
+/* I-TDM control protocol fields */
+static int hf_itdm_ctl_transid   = -1;
+static int hf_itdm_ctl_command   = -1;
+static int hf_itdm_ctl_flowid    = -1;
+static int hf_itdm_ctl_dm        = -1;
+static int hf_itdm_ctl_emts      = -1;
+static int hf_itdm_ctl_pktrate   = -1;
+static int hf_itdm_ctl_ptid      = -1;
+static int hf_itdm_ctl_cksum     = -1;
+
+
 /* Initialize the subtree pointers */
 static gint ett_itdm       = -1;
+static gint ett_itdm_ctl   = -1;
 
 /* ZZZZ some magic number.. */
 static guint gbl_ItdmMPLSLabel = 0x99887;
+static guint gbl_ItdmCTLFlowNo = 0;
 
 static dissector_handle_t data_handle;
 
+/* I-TDM 125usec mode commands for data flows */
 #define ITDM_CMD_NEW_CHAN     1
 #define ITDM_CMD_CLOSE_CHAN   2
 #define ITDM_CMD_RELOC_CHAN   3
@@ -71,6 +85,18 @@ static dissector_handle_t data_handle;
 #define ITDM_CHLOC1_OFFSET   14
 #define ITDM_CHLOC2_OFFSET   16
 
+/* I-TDM commands for I-TDM control flows */
+#define ITDM_CTL_TRANSID_OFFSET    10
+#define ITDM_CTL_CMD_OFFSET        14
+#define ITDM_CTL_FLOWID_OFFSET     15
+#define ITDM_CTL_ITDM_MODE_OFFSET  18
+#define ITDM_CTL_EMTS_OFFSET       20
+#define ITDM_CTL_PKTRATE_OFFSET    22
+#define ITDM_CTL_PAIRED_TRANSID_OFFSET    26
+#define ITDM_CTL_CRC_OFFSET        30
+
+#define ITDM_CTL_CMD_AFI_REQ  1
+
 static const value_string sop_eop_vals[] = {
        { 0x0, "Middle of Packet" },
        { 0x1, "End of Packet" },
@@ -79,18 +105,10 @@ static const value_string sop_eop_vals[] = {
        { 0, NULL }
 };
 
-#if 0
-static const value_string ack_vals[] = {
-       { 0x0, "Normal Command" },
-       { 0x1, "Acknowledging a command from remote node" },
-       { 0, NULL }
-};
-#else
 static const true_false_string ack_tfs = {
        "Acknowledging a command from remote node",
        "Normal Command"
 };
-#endif
 
 static const value_string chcmd_vals[] = {
        { 0x0, "Reserved" },
@@ -112,6 +130,46 @@ static const value_string chcmd_vals[] = {
        { 0, NULL }
 };
 
+static const value_string itdm_ctl_command_vals[] = {
+       { 0x0, "Not Used" },
+       { 0x1, "AFI_REQ: Alloc Flow ID Req" },
+       { 0x2, "AFI_RSP: Alloc Flow ID Rsp - Req Accepted." },
+       { 0x3, "DFI_REQ: Dealloc Flow ID Req" },
+       { 0x4, "DFI_RSP: Dealloc Flow ID Rsp - Req Accepted." },
+
+       { 0x10, "AFI_RSP: Reject: Data Mode Field value Not Supported." },
+       { 0x11, "AFI_RSP: Reject: Explicit Multi-timeslot value Not Supported." },
+       { 0x12, "AFI_RSP: Reject: Packet Rate value Not Supported." },
+       { 0x13, "AFI_RSP: Reject: Checksum Invalid." },
+       { 0x14, "AFI_RSP: Reject: No more flows available." },
+
+       { 0x20, "DFI_RSP: Reject: Data Mode Field value does not match Flow ID." },
+       { 0x21, "DFI_RSP: Reject: Explicit Multi-timeslots value does not match." },
+       { 0x22, "DFI_RSP: Reject: Packet Rate value does not match." },
+       { 0x23, "DFI_RSP: Reject: Checksum Invalid." },
+       { 0x24, "DFI_RSP: Reject: Flow ID invalid (out of range)." },
+       { 0x25, "DFI_RSP: Reject: Flow ID not currently allocated." },
+       { 0x26, "DFI_RSP: Reject: Other Flow ID in pair has active connections." },
+       { 0, NULL }
+};
+
+static const value_string itdm_ctl_data_mode_vals[] = {
+       { 0, "Not Used." },
+       { 1, "I-TDM 1ms Data Mode." },
+       { 2, "I-TDM 125usec Data Mode." },
+       { 3, "I-TDM Explicit Multi-timeslot Data Mode." },
+       { 4, "I-TDM CAS Signaling Data Mode." },
+       { 0, NULL }
+};
+
+static const value_string itdm_ctl_pktrate_vals[] = {
+       { 0x447A0000, "I-TDM 1ms Data Mode." },
+       { 0x45FA0000, "I-TDM 125usec/EMTS Data Mode." },
+       { 0x43A6AAAB, "I-TDM T1 CAS Mode." },
+       { 0x43FA0000, "I-TDM E1 CAS Mode." },
+       { 0, NULL }
+};
+
 static void
 dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -207,7 +265,102 @@ dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                        offset += 2;
                }
        }
-  };
+  }
+
+  next_tvb = tvb_new_subset(tvb, offset, -1 , -1);
+  call_dissector(data_handle, next_tvb, pinfo, tree);
+}
+
+static void
+dissect_itdm_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+  tvbuff_t     *next_tvb;
+  proto_item *itdm_ctl_item = NULL;
+  proto_tree *itdm_ctl_tree = NULL;
+  int offset;
+  guint32 flowid;
+  guint8 command;
+  guint32 trans_id;
+  guint32 paired_trans_id;
+  guint32 allocd_flowid;
+
+  if (check_col(pinfo->cinfo, COL_PROTOCOL))
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM-Control");
+
+  flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
+  command = tvb_get_guint8(tvb, ITDM_CTL_CMD_OFFSET);
+  allocd_flowid = tvb_get_ntoh24(tvb, ITDM_CTL_FLOWID_OFFSET);
+  trans_id = tvb_get_ntohl(tvb, ITDM_CTL_TRANSID_OFFSET);
+  paired_trans_id = tvb_get_ntohl(tvb, ITDM_CTL_PAIRED_TRANSID_OFFSET);
+
+  if (check_col(pinfo->cinfo, COL_INFO))
+  {
+    col_add_fstr(pinfo->cinfo, COL_INFO,
+      "Flow %d Command %s ",
+      flowid, val_to_str(command, itdm_ctl_command_vals, "Reserved"));
+
+    if (command != ITDM_CTL_CMD_AFI_REQ )
+    {
+      col_append_fstr(pinfo->cinfo, COL_INFO,
+        " Alloc'd FlowID %d", allocd_flowid);
+    }
+
+    col_append_fstr(pinfo->cinfo, COL_INFO, " TransID 0x%x ", trans_id);
+
+    if (command != ITDM_CTL_CMD_AFI_REQ )
+    {
+      col_append_fstr(pinfo->cinfo, COL_INFO,
+        " Paired TransID 0x%x", paired_trans_id);
+    }
+  }
+
+  offset = 0;
+
+  if (tree)
+  {
+       itdm_ctl_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, FALSE);
+       itdm_ctl_tree = proto_item_add_subtree(itdm_ctl_item, ett_itdm_ctl);
+
+       /* These eventually should go into a SFP.0 dissector... */
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_timestamp, tvb, offset, 2, FALSE);
+       offset += 2;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_seqnum, tvb, offset, 1, FALSE);
+       offset += 1;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_sop_eop, tvb, offset, 1, FALSE);
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_last_pack, tvb, offset, 1, FALSE);
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_pktlen, tvb, offset, 2, FALSE);
+       offset += 2;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_chksum, tvb, offset, 2, FALSE);
+       offset += 2;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_uid, tvb, offset, 3, FALSE);
+       offset += 3;
+
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_transid, tvb, offset, 4, FALSE);
+       offset += 4;
+
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_command, tvb, offset, 1, FALSE);
+       offset += 1;
+       if (command != ITDM_CTL_CMD_AFI_REQ) {
+               proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_flowid, tvb, offset, 3, FALSE);
+       }
+       offset += 3;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_dm, tvb, offset, 1, FALSE);
+       offset += 1;
+       /* rsvd.. */
+       offset += 1;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_emts, tvb, offset, 2, FALSE);
+       offset += 2;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_pktrate, tvb, offset, 4, FALSE);
+       offset += 4;
+       if (command != ITDM_CTL_CMD_AFI_REQ) {
+               proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_ptid, tvb, offset, 4, FALSE);
+       }
+       offset += 4;
+       /* rsvd.. */
+       offset += 2;
+       proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_cksum, tvb, offset, 2, FALSE);
+       offset += 2;
+  }
 
   next_tvb = tvb_new_subset(tvb, offset, -1 , -1);
   call_dissector(data_handle, next_tvb, pinfo, tree);
@@ -216,11 +369,23 @@ dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 static void
 dissect_itdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       /* ZZZ for now, always 125 usec mode */
+  guint32 flowid;
+
+       /* ZZZ for now, 125 usec mode and I-TDM control protocol 
+        * need to add 1ms mode */
        if (tvb_length(tvb) < 18)
                return;
 
-       dissect_itdm_125usec(tvb, pinfo, tree);
+       /* See if this packet is a data flow or the I-TDM control flow. */
+       flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
+
+       /* gbl_ItdmCTLFlowNo is the configurable flow number where
+        * the control protocol resides... Usually 0.
+        */
+       if (flowid == gbl_ItdmCTLFlowNo)
+               dissect_itdm_control(tvb, pinfo, tree);
+       else
+               dissect_itdm_125usec(tvb, pinfo, tree);
 }
 
 void proto_reg_handoff_itdm(void);
@@ -259,11 +424,29 @@ proto_register_itdm(void)
     { &hf_itdm_pktrate,{ "IEEE 754 Packet Rate", "itdm.pktrate",
                         FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
     { &hf_itdm_cxnsize, { "Connection Size", "itdm.cxnsize",
-                        FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }
+                        FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+
+    { &hf_itdm_ctl_transid, { "Transaction ID", "itdm.ctl_transid",
+                        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_command, { "Control Command", "itdm.ctl_cmd",
+                        FT_UINT8, BASE_DEC, VALS(itdm_ctl_command_vals), 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_flowid, { "Allocated Flow ID", "itdm.ctl_flowid",
+                        FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_dm, { "I-TDM Data Mode", "itdm.ctl_dm",
+                        FT_UINT8, BASE_DEC, VALS(itdm_ctl_data_mode_vals), 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_emts, { "I-TDM Explicit Multi-timeslot Size", "itdm.ctlemts",
+                        FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_pktrate, { "I-TDM Packet Rate", "itdm.ctl_pktrate",
+                        FT_UINT32, BASE_HEX, VALS(itdm_ctl_pktrate_vals), 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_ptid, { "Paired Transaction ID", "itdm.ctl_ptid",
+                        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
+    { &hf_itdm_ctl_cksum, { "ITDM Control Message Checksum", "itdm.ctl_cksum",
+                        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }
   };
 
   static gint *ett[] = {
-    &ett_itdm
+    &ett_itdm,
+    &ett_itdm_ctl
   };
 
   module_t *itdm_module;
@@ -275,10 +458,16 @@ proto_register_itdm(void)
   proto_register_subtree_array(ett, array_length(ett));
 
   itdm_module = prefs_register_protocol(proto_itdm, proto_reg_handoff_itdm);
+
   prefs_register_uint_preference(itdm_module, "mpls_label",
     "ITDM MPLS label (Flow Bundle ID in hex)",
     "The MPLS label (aka Flow Bundle ID) used by ITDM traffic.",
     16, &gbl_ItdmMPLSLabel);
+
+  prefs_register_uint_preference(itdm_module, "ctl_flowno",
+    "I-TDM Control Protocol Flow Number",
+    "Flow Number used by I-TDM Control Protocol traffic.",
+    10, &gbl_ItdmCTLFlowNo);
 }
 
 void