Switch a bunch of dissectors over to using tvb_new_subset_remaining()
[obnox/wireshark/wip.git] / epan / dissectors / packet-itdm.c
1 /* packet-itdm.c
2  * Routines for I-TDM (Internal TDM) dissection
3  * Compliant to PICMG SFP.0 and SFP.1 March 24, 2005
4  *
5  * Copyright 2008, Dan Gora <dg [AT] adax.com>
6  *
7  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "epan/prefs.h"
35
36 /* Initialize the protocol and registered fields */
37 static int proto_itdm        = -1;
38 static int hf_itdm_timestamp = -1;
39 static int hf_itdm_seqnum    = -1;
40 static int hf_itdm_sop_eop   = -1;
41 static int hf_itdm_last_pack = -1;
42 static int hf_itdm_pktlen    = -1;
43 static int hf_itdm_chksum    = -1;
44 static int hf_itdm_uid       = -1;
45 static int hf_itdm_ack       = -1;
46 static int hf_itdm_act       = -1;
47 static int hf_itdm_chcmd     = -1;
48 static int hf_itdm_chid      = -1;
49 static int hf_itdm_chloc1    = -1;
50 static int hf_itdm_chloc2    = -1;
51 static int hf_itdm_pktrate   = -1;
52 static int hf_itdm_cxnsize   = -1;
53
54 /* I-TDM control protocol fields */
55 static int hf_itdm_ctl_transid   = -1;
56 static int hf_itdm_ctl_command   = -1;
57 static int hf_itdm_ctl_flowid    = -1;
58 static int hf_itdm_ctl_dm        = -1;
59 static int hf_itdm_ctl_emts      = -1;
60 static int hf_itdm_ctl_pktrate   = -1;
61 static int hf_itdm_ctl_ptid      = -1;
62 static int hf_itdm_ctl_cksum     = -1;
63
64
65 /* Initialize the subtree pointers */
66 static gint ett_itdm       = -1;
67 static gint ett_itdm_ctl   = -1;
68
69 /* ZZZZ some magic number.. */
70 static guint gbl_ItdmMPLSLabel = 0x99887;
71 static guint gbl_ItdmCTLFlowNo = 0;
72
73 static dissector_handle_t data_handle;
74
75 /* I-TDM 125usec mode commands for data flows */
76 #define ITDM_CMD_NEW_CHAN     1
77 #define ITDM_CMD_CLOSE_CHAN   2
78 #define ITDM_CMD_RELOC_CHAN   3
79 #define ITDM_CMD_CYCLIC_REAF  4
80 #define ITDM_CMD_PACKET_RATE  5
81
82 #define ITDM_FLOWID_OFFSET    7
83 #define ITDM_CHCMD_OFFSET    10
84 #define ITDM_CHANID_OFFSET   11
85 #define ITDM_CHLOC1_OFFSET   14
86 #define ITDM_CHLOC2_OFFSET   16
87
88 /* I-TDM commands for I-TDM control flows */
89 #define ITDM_CTL_TRANSID_OFFSET    10
90 #define ITDM_CTL_CMD_OFFSET        14
91 #define ITDM_CTL_FLOWID_OFFSET     15
92 #define ITDM_CTL_ITDM_MODE_OFFSET  18
93 #define ITDM_CTL_EMTS_OFFSET       20
94 #define ITDM_CTL_PKTRATE_OFFSET    22
95 #define ITDM_CTL_PAIRED_TRANSID_OFFSET    26
96 #define ITDM_CTL_CRC_OFFSET        30
97
98 #define ITDM_CTL_CMD_AFI_REQ  1
99
100 static const value_string sop_eop_vals[] = {
101         { 0x0, "Middle of Packet" },
102         { 0x1, "End of Packet" },
103         { 0x2, "Start of Packet" },
104         { 0x3, "Complete Packet" },
105         { 0, NULL }
106 };
107
108 static const true_false_string ack_tfs = {
109         "Acknowledging a command from remote node",
110         "Normal Command"
111 };
112
113 static const value_string chcmd_vals[] = {
114         { 0x0, "Reserved" },
115         { 0x1, "New Channel ID" },
116         { 0x2, "Close Channel ID" },
117         { 0x3, "Relocate Channel ID" },
118         { 0x4, "Cyclic Reaffirmation" },
119         { 0x5, "Packet Rate Integrity Check" },
120         { 0x6, "Reserved" },
121         { 0x7, "Reserved" },
122         { 0x8, "Reserved" },
123         { 0x9, "Reserved" },
124         { 0xa, "Reserved" },
125         { 0xb, "Reserved" },
126         { 0xc, "Reserved" },
127         { 0xd, "Reserved" },
128         { 0xe, "Reserved" },
129         { 0xf, "Reserved" },
130         { 0, NULL }
131 };
132
133 static const value_string itdm_ctl_command_vals[] = {
134         { 0x0, "Not Used" },
135         { 0x1, "AFI_REQ: Alloc Flow ID Req" },
136         { 0x2, "AFI_RSP: Alloc Flow ID Rsp - Req Accepted." },
137         { 0x3, "DFI_REQ: Dealloc Flow ID Req" },
138         { 0x4, "DFI_RSP: Dealloc Flow ID Rsp - Req Accepted." },
139
140         { 0x10, "AFI_RSP: Reject: Data Mode Field value Not Supported." },
141         { 0x11, "AFI_RSP: Reject: Explicit Multi-timeslot value Not Supported." },
142         { 0x12, "AFI_RSP: Reject: Packet Rate value Not Supported." },
143         { 0x13, "AFI_RSP: Reject: Checksum Invalid." },
144         { 0x14, "AFI_RSP: Reject: No more flows available." },
145
146         { 0x20, "DFI_RSP: Reject: Data Mode Field value does not match Flow ID." },
147         { 0x21, "DFI_RSP: Reject: Explicit Multi-timeslots value does not match." },
148         { 0x22, "DFI_RSP: Reject: Packet Rate value does not match." },
149         { 0x23, "DFI_RSP: Reject: Checksum Invalid." },
150         { 0x24, "DFI_RSP: Reject: Flow ID invalid (out of range)." },
151         { 0x25, "DFI_RSP: Reject: Flow ID not currently allocated." },
152         { 0x26, "DFI_RSP: Reject: Other Flow ID in pair has active connections." },
153         { 0, NULL }
154 };
155
156 static const value_string itdm_ctl_data_mode_vals[] = {
157         { 0, "Not Used." },
158         { 1, "I-TDM 1ms Data Mode." },
159         { 2, "I-TDM 125usec Data Mode." },
160         { 3, "I-TDM Explicit Multi-timeslot Data Mode." },
161         { 4, "I-TDM CAS Signaling Data Mode." },
162         { 0, NULL }
163 };
164
165 static const value_string itdm_ctl_pktrate_vals[] = {
166         { 0x447A0000, "I-TDM 1ms Data Mode." },
167         { 0x45FA0000, "I-TDM 125usec/EMTS Data Mode." },
168         { 0x43A6AAAB, "I-TDM T1 CAS Mode." },
169         { 0x43FA0000, "I-TDM E1 CAS Mode." },
170         { 0, NULL }
171 };
172
173 static void
174 dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
175 {
176   tvbuff_t      *next_tvb;
177   proto_item *itdm_item = NULL;
178   proto_tree *itdm_tree = NULL;
179   int offset;
180   guint32 flowid;
181   guint32 chanid;
182   guint16 chloc1;
183   guint16 chloc2;
184   guint8 chcmd;
185   guint8 actbit;
186   guint8 ackbit;
187
188
189   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM");
190
191   flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
192   chanid = tvb_get_ntoh24(tvb, ITDM_CHANID_OFFSET);
193   chcmd  = tvb_get_guint8(tvb, ITDM_CHCMD_OFFSET);
194   chloc1 = tvb_get_ntohs(tvb, ITDM_CHLOC1_OFFSET);
195   actbit = (chcmd & 0x10) ? 1 : 0;
196   ackbit = (chcmd & 0x20) ? 1 : 0;
197   chcmd  = chcmd & 0x0f;
198
199   if (check_col(pinfo->cinfo, COL_INFO))
200   {
201     col_add_fstr(pinfo->cinfo, COL_INFO,
202       "Flow %d Chan %d ACT %d ACK %d %s",
203       flowid, chanid, actbit, ackbit,
204       val_to_str(chcmd, chcmd_vals, "Reserved"));
205     if (chcmd == ITDM_CMD_NEW_CHAN ||
206         chcmd == ITDM_CMD_CLOSE_CHAN ||
207         chcmd == ITDM_CMD_CYCLIC_REAF)
208     {
209       col_append_fstr(pinfo->cinfo, COL_INFO,
210         " Loc1 %d", chloc1);
211     }
212     else if (chcmd == ITDM_CMD_RELOC_CHAN)
213     {
214       chloc2 = tvb_get_ntohs(tvb, ITDM_CHLOC2_OFFSET);
215       col_append_fstr(pinfo->cinfo, COL_INFO,
216         " Loc1 %d Loc2 %d", chloc1, chloc2);
217     }
218   }
219
220   offset = 0;
221
222   if (tree)
223   {
224         itdm_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, FALSE);
225         itdm_tree = proto_item_add_subtree(itdm_item, ett_itdm);
226
227         proto_tree_add_item(itdm_tree, hf_itdm_timestamp, tvb, offset, 2, FALSE);
228         offset += 2;
229         proto_tree_add_item(itdm_tree, hf_itdm_seqnum, tvb, offset, 1, FALSE);
230         offset += 1;
231         proto_tree_add_item(itdm_tree, hf_itdm_sop_eop, tvb, offset, 1, FALSE);
232         proto_tree_add_item(itdm_tree, hf_itdm_last_pack, tvb, offset, 1, FALSE);
233         proto_tree_add_item(itdm_tree, hf_itdm_pktlen, tvb, offset, 2, FALSE);
234         offset += 2;
235         proto_tree_add_item(itdm_tree, hf_itdm_chksum, tvb, offset, 2, FALSE);
236         offset += 2;
237         proto_tree_add_item(itdm_tree, hf_itdm_uid, tvb, offset, 3, FALSE);
238         offset += 3;
239         proto_tree_add_item(itdm_tree, hf_itdm_ack, tvb, offset, 1, FALSE);
240         proto_tree_add_item(itdm_tree, hf_itdm_act, tvb, offset, 1, FALSE);
241         proto_tree_add_item(itdm_tree, hf_itdm_chcmd, tvb, offset, 1, FALSE);
242         offset += 1;
243         proto_tree_add_item(itdm_tree, hf_itdm_chid, tvb, offset, 3, FALSE);
244         offset += 3;
245         if (chcmd == ITDM_CMD_PACKET_RATE)
246         {
247                 proto_tree_add_item(itdm_tree, hf_itdm_pktrate, tvb, offset, 4, FALSE);
248                 offset += 4;
249         }
250         else
251         {
252                 proto_tree_add_item(itdm_tree, hf_itdm_chloc1, tvb, offset, 2, FALSE);
253                 offset += 2;
254                 if (chcmd == ITDM_CMD_CYCLIC_REAF ||
255                     chcmd == ITDM_CMD_NEW_CHAN ||
256                     chcmd == ITDM_CMD_CLOSE_CHAN)
257                 {
258                         proto_tree_add_item(itdm_tree, hf_itdm_cxnsize, tvb, offset, 2, FALSE);
259                         offset += 2;
260                 }
261                 else
262                 {
263                         proto_tree_add_item(itdm_tree, hf_itdm_chloc2, tvb, offset, 2, FALSE);
264                         offset += 2;
265                 }
266         }
267   }
268
269   next_tvb = tvb_new_subset_remaining(tvb, offset);
270   call_dissector(data_handle, next_tvb, pinfo, tree);
271 }
272
273 static void
274 dissect_itdm_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
275 {
276   tvbuff_t      *next_tvb;
277   proto_item *itdm_ctl_item = NULL;
278   proto_tree *itdm_ctl_tree = NULL;
279   int offset;
280   guint32 flowid;
281   guint8 command;
282   guint32 trans_id;
283   guint32 paired_trans_id;
284   guint32 allocd_flowid;
285
286   col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM-Control");
287
288   flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
289   command = tvb_get_guint8(tvb, ITDM_CTL_CMD_OFFSET);
290   allocd_flowid = tvb_get_ntoh24(tvb, ITDM_CTL_FLOWID_OFFSET);
291   trans_id = tvb_get_ntohl(tvb, ITDM_CTL_TRANSID_OFFSET);
292   paired_trans_id = tvb_get_ntohl(tvb, ITDM_CTL_PAIRED_TRANSID_OFFSET);
293
294   if (check_col(pinfo->cinfo, COL_INFO))
295   {
296     col_add_fstr(pinfo->cinfo, COL_INFO,
297       "Flow %d Command %s ",
298       flowid, val_to_str(command, itdm_ctl_command_vals, "Reserved"));
299
300     if (command != ITDM_CTL_CMD_AFI_REQ )
301     {
302       col_append_fstr(pinfo->cinfo, COL_INFO,
303         " Alloc'd FlowID %d", allocd_flowid);
304     }
305
306     col_append_fstr(pinfo->cinfo, COL_INFO, " TransID 0x%x ", trans_id);
307
308     if (command != ITDM_CTL_CMD_AFI_REQ )
309     {
310       col_append_fstr(pinfo->cinfo, COL_INFO,
311         " Paired TransID 0x%x", paired_trans_id);
312     }
313   }
314
315   offset = 0;
316
317   if (tree)
318   {
319         itdm_ctl_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, FALSE);
320         itdm_ctl_tree = proto_item_add_subtree(itdm_ctl_item, ett_itdm_ctl);
321
322         /* These eventually should go into a SFP.0 dissector... */
323         proto_tree_add_item(itdm_ctl_tree, hf_itdm_timestamp, tvb, offset, 2, FALSE);
324         offset += 2;
325         proto_tree_add_item(itdm_ctl_tree, hf_itdm_seqnum, tvb, offset, 1, FALSE);
326         offset += 1;
327         proto_tree_add_item(itdm_ctl_tree, hf_itdm_sop_eop, tvb, offset, 1, FALSE);
328         proto_tree_add_item(itdm_ctl_tree, hf_itdm_last_pack, tvb, offset, 1, FALSE);
329         proto_tree_add_item(itdm_ctl_tree, hf_itdm_pktlen, tvb, offset, 2, FALSE);
330         offset += 2;
331         proto_tree_add_item(itdm_ctl_tree, hf_itdm_chksum, tvb, offset, 2, FALSE);
332         offset += 2;
333         proto_tree_add_item(itdm_ctl_tree, hf_itdm_uid, tvb, offset, 3, FALSE);
334         offset += 3;
335
336         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_transid, tvb, offset, 4, FALSE);
337         offset += 4;
338
339         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_command, tvb, offset, 1, FALSE);
340         offset += 1;
341         if (command != ITDM_CTL_CMD_AFI_REQ) {
342                 proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_flowid, tvb, offset, 3, FALSE);
343         }
344         offset += 3;
345         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_dm, tvb, offset, 1, FALSE);
346         offset += 1;
347         /* rsvd.. */
348         offset += 1;
349         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_emts, tvb, offset, 2, FALSE);
350         offset += 2;
351         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_pktrate, tvb, offset, 4, FALSE);
352         offset += 4;
353         if (command != ITDM_CTL_CMD_AFI_REQ) {
354                 proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_ptid, tvb, offset, 4, FALSE);
355         }
356         offset += 4;
357         /* rsvd.. */
358         offset += 2;
359         proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_cksum, tvb, offset, 2, FALSE);
360         offset += 2;
361   }
362
363   next_tvb = tvb_new_subset_remaining(tvb, offset);
364   call_dissector(data_handle, next_tvb, pinfo, tree);
365 }
366
367 static void
368 dissect_itdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
369 {
370   guint32 flowid;
371
372         /* ZZZ for now, 125 usec mode and I-TDM control protocol 
373          * need to add 1ms mode */
374         if (tvb_length(tvb) < 18)
375                 return;
376
377         /* See if this packet is a data flow or the I-TDM control flow. */
378         flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
379
380         /* gbl_ItdmCTLFlowNo is the configurable flow number where
381          * the control protocol resides... Usually 0.
382          */
383         if (flowid == gbl_ItdmCTLFlowNo)
384                 dissect_itdm_control(tvb, pinfo, tree);
385         else
386                 dissect_itdm_125usec(tvb, pinfo, tree);
387 }
388
389 void proto_reg_handoff_itdm(void);
390
391 void
392 proto_register_itdm(void)
393 {
394
395   static hf_register_info hf[] = {
396     { &hf_itdm_timestamp,{ "Timestamp", "itdm.timestamp",
397                         FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
398     { &hf_itdm_seqnum,{ "Sequence Number", "itdm.seqnum",
399                         FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
400     { &hf_itdm_sop_eop,{ "Start/End of Packet", "itdm.sop_eop",
401                         FT_UINT8, BASE_DEC, VALS(sop_eop_vals), 0xc0, NULL, HFILL } },
402     { &hf_itdm_last_pack,{ "Last Packet", "itdm.last_pack",
403                         FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x20, NULL, HFILL } },
404     { &hf_itdm_pktlen,{ "Packet Length", "itdm.pktlen",
405                         FT_UINT16, BASE_DEC, NULL, 0x07ff, NULL, HFILL } },
406     { &hf_itdm_chksum,{ "Checksum", "itdm.chksum",
407                         FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
408     { &hf_itdm_uid,{ "Flow ID", "itdm.uid",
409                         FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } },
410     { &hf_itdm_ack,{ "ACK", "itdm.ack",
411                         FT_BOOLEAN, 8, TFS(&ack_tfs), 0x20, NULL, HFILL } },
412     { &hf_itdm_act,{ "Activate", "itdm.act",
413                         FT_BOOLEAN, 8, TFS(&tfs_true_false), 0x10, NULL, HFILL } },
414     { &hf_itdm_chcmd,{ "Channel Command", "itdm.chcmd",
415                         FT_UINT8, BASE_DEC, VALS(chcmd_vals), 0x0f, NULL, HFILL } },
416     { &hf_itdm_chid,{ "Channel ID", "itdm.chid",
417                         FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } },
418     { &hf_itdm_chloc1,{ "Channel Location 1", "itdm.chloc1",
419                         FT_UINT16, BASE_DEC, NULL, 0x1ff, NULL, HFILL } },
420     { &hf_itdm_chloc2,{ "Channel Location 2", "itdm.chloc2",
421                         FT_UINT16, BASE_DEC, NULL, 0x1ff, NULL, HFILL } },
422     { &hf_itdm_pktrate,{ "IEEE 754 Packet Rate", "itdm.pktrate",
423                          FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
424     { &hf_itdm_cxnsize, { "Connection Size", "itdm.cxnsize",
425                          FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
426
427     { &hf_itdm_ctl_transid, { "Transaction ID", "itdm.ctl_transid",
428                          FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
429     { &hf_itdm_ctl_command, { "Control Command", "itdm.ctl_cmd",
430                          FT_UINT8, BASE_DEC, VALS(itdm_ctl_command_vals), 0x0, NULL, HFILL } },
431     { &hf_itdm_ctl_flowid, { "Allocated Flow ID", "itdm.ctl_flowid",
432                          FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } },
433     { &hf_itdm_ctl_dm, { "I-TDM Data Mode", "itdm.ctl_dm",
434                          FT_UINT8, BASE_DEC, VALS(itdm_ctl_data_mode_vals), 0x0, NULL, HFILL } },
435     { &hf_itdm_ctl_emts, { "I-TDM Explicit Multi-timeslot Size", "itdm.ctlemts",
436                          FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
437     { &hf_itdm_ctl_pktrate, { "I-TDM Packet Rate", "itdm.ctl_pktrate",
438                          FT_UINT32, BASE_HEX, VALS(itdm_ctl_pktrate_vals), 0x0, NULL, HFILL } },
439     { &hf_itdm_ctl_ptid, { "Paired Transaction ID", "itdm.ctl_ptid",
440                          FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
441     { &hf_itdm_ctl_cksum, { "ITDM Control Message Checksum", "itdm.ctl_cksum",
442                          FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }
443   };
444
445   static gint *ett[] = {
446     &ett_itdm,
447     &ett_itdm_ctl
448   };
449
450   module_t *itdm_module;
451
452   proto_itdm = proto_register_protocol("Internal TDM", "ITDM", "itdm");
453   register_dissector("itdm", dissect_itdm, proto_itdm);
454
455   proto_register_field_array(proto_itdm, hf, array_length(hf));
456   proto_register_subtree_array(ett, array_length(ett));
457
458   itdm_module = prefs_register_protocol(proto_itdm, proto_reg_handoff_itdm);
459
460   prefs_register_uint_preference(itdm_module, "mpls_label",
461     "ITDM MPLS label (Flow Bundle ID in hex)",
462     "The MPLS label (aka Flow Bundle ID) used by ITDM traffic.",
463     16, &gbl_ItdmMPLSLabel);
464
465   prefs_register_uint_preference(itdm_module, "ctl_flowno",
466     "I-TDM Control Protocol Flow Number",
467     "Flow Number used by I-TDM Control Protocol traffic.",
468     10, &gbl_ItdmCTLFlowNo);
469 }
470
471 void
472 proto_reg_handoff_itdm(void)
473 {
474         static gboolean Initialized=FALSE;
475         static dissector_handle_t itdm_handle;
476         static guint ItdmMPLSLabel;
477
478         if (!Initialized) {
479                 itdm_handle = find_dissector("itdm");;
480                 data_handle = find_dissector("data");
481                 Initialized=TRUE;
482         } else {
483                 dissector_delete("mpls.label", ItdmMPLSLabel, itdm_handle);
484         }
485
486         ItdmMPLSLabel = gbl_ItdmMPLSLabel;
487         dissector_add("mpls.label", gbl_ItdmMPLSLabel, itdm_handle);
488 }