d6b316cf83ec6299efd0b47a5b46a0b6e257ddaf
[obnox/wireshark/wip.git] / epan / dissectors / packet-cfm.c
1 /* packet-cfm.c
2  * Routines for CFM EOAM (IEEE 802.1ag) dissection
3  * Copyright 2007, Keith Mercer <keith.mercer@alcatel-lucent.com>
4  * Copyright 2011, Peter Nahas <pnahas@mrv.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /* This code is based on the IEEE P802.1ag/D8.1 document, and on the ITU-T Y.1731
28  * recommendation (05/2006,) which is not formally released at the time of this
29  * dissector development.  Any updates to these documents may require additional
30  * modifications to this code.
31  */
32
33
34 #ifdef HAVE_CONFIG_H
35 # include "config.h"
36 #endif
37
38 #include <epan/packet.h>
39 #include <glib.h>
40 #include <epan/etypes.h>
41
42 /** Value declarations for CFM EOAM (IEEE 802.1ag) dissection */
43 #define IEEE8021 0x00
44 #define CCM 0x01
45 #define LBR 0x02
46 #define LBM 0x03
47 #define LTR 0x04
48 #define LTM 0X05
49
50 #define AIS 0x21
51 #define LCK 0x23
52 #define TST 0x25
53 #define APS 0x27
54 #define RAPS 0x28
55 #define MCC 0x29
56 #define LMM 0x2B
57 #define LMR 0x2A
58 #define ODM 0x2D
59 #define DMM 0x2F
60 #define DMR 0x2E
61 #define EXM 0x31
62 #define EXR 0x30
63 #define VSM 0x33
64 #define VSR 0x32
65 #define SLM 0x37
66 #define SLR 0x36
67
68 #define END_TLV         0x00
69 #define SENDER_ID_TLV   0x01
70 #define PORT_STAT_TLV   0x02
71 #define DATA_TLV        0x03
72 #define INTERF_STAT_TLV 0x04
73 #define REPLY_ING_TLV   0x05
74 #define REPLY_EGR_TLV   0x06
75 #define LTM_EGR_ID_TLV  0x07
76 #define LTR_EGR_ID_TLV  0x08
77 #define ORG_SPEC_TLV    0x1F
78 #define TEST_TLV        0x20
79
80 static int proto_cfm = -1;
81
82 static const value_string opcodetypenames[] = {
83         { IEEE8021,     "Reserved for IEEE 802.1" },
84         { CCM,          "Continuity Check Message (CCM)" },
85         { LBR,          "Loopback Reply (LBR)" },
86         { LBM,          "Loopback Message (LBM)" },
87         { LTR,          "Linktrace Reply (LTR)" },
88         { LTM,          "Linktrace Message (LTM)" },
89         { AIS,          "Alarm Indication Signal (AIS)" },
90         { LCK,          "Lock Signal (LCK)" },
91         { TST,          "Test Signal (TST)" },
92         { APS,          "Automatic Protection Switching (APS)" },
93         { RAPS,         "Ring-Automatic Protection Switching (R-APS)" },
94         { MCC,          "Maintenance Communication Channel (MCC)" },
95         { LMM,          "Loss Measurement Message (LMM)" },
96         { LMR,          "Loss Measurement Reply (LMR)" },
97         { ODM,          "One Way Delay Measurement (1DM)" },
98         { DMM,          "Delay Measurement Message (DMM)" },
99         { DMR,          "Delay Measurement Reply (DMR)" },
100         { EXM,          "Experimental OAM Message (EXM)" },
101         { EXR,          "Experimental OAM Reply (EXR)" },
102         { VSM,          "Vendor Specific Message (VSM)" },
103         { VSR,          "Vendor Specific Reply (VSR)" },
104         { SLM,          "Synthetic Loss Message (SLM)"},
105         { SLR,          "Synthetic Loss Reply (SLR))"},
106         { 0,            NULL }
107 };
108 static const value_string CCM_IntervalFieldEncoding[] = {
109         { 0, "invalid" },
110         { 1, "Trans Int 3.33ms, max Lifetime 11.66ms, min Lifetime 10.83ms" },
111         { 2, "Trans Int 10ms, max Lifetime 35ms, min Lifetime 32.5ms" },
112         { 3, "Trans Int 100ms, max Lifetime 350ms, min Lifetime 325ms" },
113         { 4, "Trans Int 1s, max Lifetime 3.5s, min Lifetime 3.25s" },
114         { 5, "Trans Int 10s, max Lifetime 35s, min Lifetime 32.5s" },
115         { 6, "Trans Int 1min, max Lifetime 3.5min, min Lifetime 3.25min" },
116         { 7, "Trans Int 10min, max Lifetime 35min, min Lifetime 32.5min" },
117         { 0, NULL }
118 };
119 static const value_string mdnameformattypes[] = {
120         { 0, "Reserved for IEEE 802.1" },
121         { 1, "No Maintenance Domain Name preset" },
122         { 2, "RFC1035 DNS Name" },
123         { 3, "MAC address + 2-octet integer" },
124         { 4, "Character String" },
125         { 0, NULL }
126 };
127 static const value_string manameformattypes[] = {
128         { 0,  "Reserved for IEEE 802.1" },
129         { 1,  "Primary VID" },
130         { 2,  "Character String" },
131         { 3,  "2-octet integer" },
132         { 4,  "RFC 2685 VPN ID" },
133         { 32, "ICC-based Format" },
134         { 0, NULL }
135 };
136 static const value_string relayactiontypes[] = {
137         { 1, "RlyHit" },
138         { 2, "RlyFDB" },
139         { 3, "RlyMPDB" },
140         { 0, NULL }
141 };
142 static const value_string aislckperiodtypes[] = {
143         { 0, "Invalid Value for AIS/LCK PDU's" },
144         { 1, "Invalid Value for AIS/LCK PDU's" },
145         { 2, "Invalid Value for AIS/LCK PDU's" },
146         { 3, "Invalid Value for AIS/LCK PDU's" },
147         { 4, "1 frame per second" },
148         { 5, "Invalid Value for AIS/LCK PDU's" },
149         { 6, "1 frame per minute" },
150         { 7, "Invalid Value for AIS/LCK PDU's" },
151         { 0, NULL }
152 };
153 static const value_string tlvtypefieldvalues[] = {
154         { END_TLV               , "End TLV" },
155         { SENDER_ID_TLV         , "Sender ID TLV" },
156         { PORT_STAT_TLV         , "Port Status TLV" },
157         { DATA_TLV              , "Data TLV" },
158         { INTERF_STAT_TLV       , "Interface Status TLV" },
159         { REPLY_ING_TLV         , "Reply Ingress TLV" },
160         { REPLY_EGR_TLV         , "Reply Egress TLV" },
161         { LTM_EGR_ID_TLV        , "LTM Egress Identifier TLV" },
162         { LTR_EGR_ID_TLV        , "LTR Egress Identifier TLV" },
163         { ORG_SPEC_TLV          , "Organizational-Specific TLV" },
164         { TEST_TLV              , "Test TLV" },
165         { 0                     , NULL }
166 };
167 static const value_string portstatTLVvalues[] = {
168         { 1, "psBlocked" },
169         { 2, "psUp" },
170         { 0, NULL }
171 };
172 static const value_string interfacestatTLVvalues[] = {
173         { 1, "isUp" },
174         { 2, "isDown" },
175         { 3, "isTesting" },
176         { 4, "isUnknown" },
177         { 5, "isDormant" },
178         { 6, "isNotPresent" },
179         { 7, "isLowerLayerDown" },
180         { 0, NULL }
181 };
182 static const value_string replyingressTLVvalues[] = {
183         { 1, "IngOK" },
184         { 2, "IngDown" },
185         { 3, "IngBlocked" },
186         { 4, "IngVID" },
187         { 0, NULL }
188 };
189 static const value_string replyegressTLVvalues[] = {
190         { 1, "EgrOK" },
191         { 2, "EgrDown" },
192         { 3, "EgrBlocked" },
193         { 4, "EgrVID" },
194         { 0, NULL }
195 };
196 static const value_string testTLVpatterntypes[] = {
197         { 0, "Null signal without CRC-32" },
198         { 1, "Null signal with CRC-32" },
199         { 2, "PRBS (2.e-31 -1), without CRC-32" },
200         { 3, "PRBS (2.e-31 -1), with CRC-32" },
201         { 0, NULL }
202 };
203 static const value_string rapsrequeststatevalues[] = {
204         { 0,  "No Request" },
205         { 11, "Signal Failure" },
206         { 0,  NULL }
207 };
208 static const value_string rapsrplblockedvalues[] = {
209         { 0, "Not Blocked" },
210         { 1, "Blocked" },
211         { 0, NULL }
212 };
213 static const value_string rapsdnfvalues[] = {
214         { 0, "Flush DB" },
215         { 1, "Do Not Flush DB" },
216         { 0, NULL }
217 };
218
219
220 static int hf_cfm_md_level = -1;
221 static int hf_cfm_version = -1;
222 static int hf_cfm_opcode = -1;
223
224 static int hf_cfm_flags = -1;
225 static int hf_cfm_flags_RDI = -1;
226 static int hf_cfm_flags_ccm_Reserved = -1;
227 static int hf_cfm_flags_Interval = -1;
228 static int hf_cfm_flags_UseFDBonly = -1;
229 static int hf_cfm_flags_ltm_Reserved = -1;
230 static int hf_cfm_flags_ltr_Reserved = -1;
231 static int hf_cfm_flags_FwdYes = -1;
232 static int hf_cfm_flags_TerminalMEP = -1;
233 static int hf_cfm_first_tlv_offset = -1;
234
235 static int hf_cfm_ccm_pdu = -1;
236 static int hf_cfm_ccm_seq_number = -1;
237 static int hf_cfm_ccm_ma_ep_id = -1;
238 static int hf_cfm_ccm_maid = -1;
239 static int hf_cfm_maid_md_name_format = -1;
240 static int hf_cfm_maid_md_name_length = -1;
241 static int hf_cfm_maid_md_name_string = -1;
242 static int hf_cfm_maid_md_name_hex = -1;
243 static int hf_cfm_maid_md_name_mac = -1;
244 static int hf_cfm_maid_md_name_mac_id = -1;
245 static int hf_cfm_maid_ma_name_format = -1;
246 static int hf_cfm_maid_ma_name_length = -1;
247 static int hf_cfm_maid_ma_name_string = -1;
248 static int hf_cfm_maid_ma_name_hex = -1;
249 static int hf_cfm_maid_padding = -1;
250 static int hf_cfm_ccm_itu_t_y1731 = -1;
251 static int hf_cfm_itu_TxFCf = -1;
252 static int hf_cfm_itu_RxFCb = -1;
253 static int hf_cfm_itu_TxFCb = -1;
254 static int hf_cfm_itu_reserved = -1;
255
256 static int hf_cfm_lbm_pdu = -1;
257 static int hf_cfm_lb_transaction_id = -1;
258
259 static int hf_cfm_lbr_pdu = -1;
260
261 static int hf_cfm_ltm_pdu = -1;
262 static int hf_cfm_lt_transaction_id = -1;
263 static int hf_cfm_lt_ttl = -1;
264 static int hf_cfm_ltm_orig_addr = -1;
265 static int hf_cfm_ltm_targ_addr = -1;
266
267 static int hf_cfm_ltr_pdu = -1;
268 static int hf_cfm_ltr_relay_action = -1;
269
270 static int hf_cfm_ais_pdu = -1;
271 static int hf_cfm_flags_ais_lck_Reserved = -1;
272 static int hf_cfm_flags_ais_lck_Period = -1;
273
274 static int hf_cfm_lck_pdu = -1;
275
276 static int hf_cfm_tst_pdu = -1;
277 static int hf_cfm_flags_Reserved = -1;
278 static int hf_cfm_tst_sequence_num = -1;
279
280 static int hf_cfm_aps_pdu = -1;
281 static int hf_cfm_aps_data = -1;
282
283 static int hf_cfm_raps_pdu = -1;
284 static int hf_cfm_raps_req_st = -1;
285 static int hf_cfm_raps_flags = -1;
286 static int hf_cfm_raps_flags_rb = -1;
287 static int hf_cfm_raps_flags_dnf = -1;
288 static int hf_cfm_raps_node_id = -1;
289 static int hf_cfm_raps_reserved = -1;
290
291 static int hf_cfm_mcc_pdu = -1;
292 static int hf_cfm_mcc_data = -1;
293
294 static int hf_cfm_lmm_pdu = -1;
295 static int hf_cfm_lmr_pdu = -1;
296 static int hf_cfm_lmm_lmr_TxFCf = -1;
297 static int hf_cfm_lmm_lmr_RxFCf = -1;
298 static int hf_cfm_lmm_lmr_TxFCb = -1;
299
300 static int hf_cfm_odm_pdu = -1;
301 static int hf_cfm_odm_dmm_dmr_TxTimestampf = -1;
302 static int hf_cfm_odm_dmm_dmr_RxTimestampf = -1;
303
304 static int hf_cfm_dmm_pdu = -1;
305 static int hf_cfm_dmr_pdu = -1;
306 static int hf_cfm_dmm_dmr_TxTimestampb = -1;
307 static int hf_cfm_dmm_dmr_RxTimestampb = -1;
308
309 static int hf_cfm_exm_pdu = -1;
310 static int hf_cfm_exr_pdu = -1;
311 static int hf_cfm_exm_exr_data = -1;
312
313 static int hf_cfm_vsm_pdu = -1;
314 static int hf_cfm_vsr_pdu = -1;
315 static int hf_cfm_vsm_vsr_data = -1;
316
317 static int hf_cfm_slm_pdu = -1;
318 static int hf_cfm_slr_pdu = -1;
319 static int hf_cfm_slm_src_mep = -1;
320 static int hf_cfm_slr_rsp_mep = -1;
321 static int hf_cfm_slm_testid = -1;
322 static int hf_cfm_slm_txfcf  = -1;
323 static int hf_cfm_slr_txfcb  = -1;
324
325 static int hf_cfm_all_tlvs = -1;
326 static int hf_cfm_tlv_type = -1;
327 static int hf_cfm_tlv_length = -1;
328 static int hf_tlv_chassis_id_length = -1;
329 static int hf_tlv_chassis_id_subtype = -1;
330 static int hf_tlv_chassis_id = -1;
331 static int hf_tlv_ma_domain_length = -1;
332 static int hf_tlv_ma_domain = -1;
333 static int hf_tlv_management_addr_length = -1;
334 static int hf_tlv_management_addr = -1;
335 static int hf_tlv_port_status_value = -1;
336 static int hf_tlv_data_value = -1;
337 static int hf_tlv_interface_status_value = -1;
338
339 static int hf_tlv_reply_ingress_action = -1;
340 static int hf_tlv_reply_ingress_mac_address = -1;
341 static int hf_tlv_reply_ing_egr_portid_length = -1;
342 static int hf_tlv_reply_ing_egr_portid_subtype = -1;
343 static int hf_tlv_reply_ing_egr_portid = -1;
344 static int hf_tlv_reply_egress_action = -1;
345 static int hf_tlv_reply_egress_mac_address = -1;
346 static int hf_tlv_ltr_egress_last_id_mac = -1;
347 static int hf_tlv_ltr_egress_last_id_unique_identifier = -1;
348 static int hf_tlv_ltr_egress_next_id_mac = -1;
349 static int hf_tlv_ltr_egress_next_id_unique_identifier = -1;
350 static int hf_tlv_ltm_egress_id_mac = -1;
351 static int hf_tlv_ltm_egress_id_unique_identifier = -1;
352 static int hf_tlv_org_spec_oui = -1;
353 static int hf_tlv_org_spec_subtype = -1;
354 static int hf_tlv_org_spec_value = -1;
355 static int hf_tlv_tst_test_pattern_type = -1;
356 static int hf_tlv_tst_test_pattern = -1;
357 static int hf_tlv_tst_CRC32 = -1;
358
359 static gint ett_cfm = -1;
360 static gint ett_cfm_flags = -1;
361 static gint ett_cfm_ccm_maid = -1;
362 static gint ett_cfm_ccm_itu = -1;
363 static gint ett_cfm_pdu = -1;
364 static gint ett_cfm_all_tlvs = -1;
365 static gint ett_cfm_tlv = -1;
366 static gint ett_cfm_raps_flags = -1;
367
368 /* CFM EOAM sub-protocol dissectors: CCM, LBM, LBR, LTM, LTR */
369 static int dissect_cfm_ccm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
370 {
371         gint maid_offset;
372         gint itu_offset;
373
374         guint8 cfm_maid_md_name_format;
375         guint8 cfm_maid_ma_name_format;
376         guint8 cfm_maid_ma_name_length;
377
378         proto_item *ti;
379         proto_item *fi;
380         proto_item *mi;
381         proto_item *wi;
382         proto_tree *cfm_pdu_tree;
383         proto_tree *cfm_flag_tree;
384         proto_tree *cfm_ccm_maid_tree;
385         proto_tree *cfm_ccm_itu_tree;
386
387
388         ti = proto_tree_add_item(tree, hf_cfm_ccm_pdu, tvb, offset, -1, ENC_NA);
389         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
390
391         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
392         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
393         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_RDI, tvb, offset, 1, ENC_BIG_ENDIAN);
394         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ccm_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
395         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Interval, tvb, offset, 1, ENC_BIG_ENDIAN);
396
397         offset += 1;
398         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
399         offset += 1;
400         proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_seq_number, tvb, offset, 4, ENC_BIG_ENDIAN);
401         offset += 4;
402         proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_ma_ep_id, tvb, offset, 2, ENC_BIG_ENDIAN);
403         offset += 2;
404
405         /* dissect CCM MAID */
406         mi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_maid, tvb, offset, 48, ENC_NA);
407         cfm_ccm_maid_tree = proto_item_add_subtree(mi, ett_cfm_ccm_maid);
408         maid_offset = offset;
409         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_format, tvb, maid_offset, 1, ENC_BIG_ENDIAN);
410         cfm_maid_md_name_format = tvb_get_guint8(tvb, maid_offset);
411         maid_offset += 1;
412         if (cfm_maid_md_name_format != 1) {
413                 guint8 cfm_maid_md_name_length;
414                 proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_length,
415                                 tvb, maid_offset, 1, ENC_BIG_ENDIAN);
416                 cfm_maid_md_name_length = tvb_get_guint8(tvb, maid_offset);
417                 maid_offset += 1;
418                 if (cfm_maid_md_name_length) {
419                         if (cfm_maid_md_name_format == 3) {
420                                 /* MD name format is MAC + 2 octet id */
421                                 if (cfm_maid_md_name_length != 8) {
422                                         /* the MD name of type MAC should be 8 octets but if
423                                          * it isn't we are going to try and process it anyways.*/
424                                         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_hex,
425                                                 tvb, maid_offset, cfm_maid_md_name_length, ENC_NA);
426                                 } else {
427                                         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_mac,
428                                                 tvb, maid_offset, 6, ENC_NA);
429                                         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_mac_id,
430                                                 tvb, maid_offset+6, 2, ENC_NA);
431                                 }
432                         } else {
433                                 /* MD name format is regular string or DNS string */
434                                 proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_string,
435                                         tvb, maid_offset, cfm_maid_md_name_length, ENC_ASCII|ENC_NA);
436                         }
437                         maid_offset += cfm_maid_md_name_length;
438                 }
439         }
440         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_format, tvb, maid_offset, 1, ENC_BIG_ENDIAN);
441         cfm_maid_ma_name_format = tvb_get_guint8(tvb, maid_offset);
442         maid_offset += 1;
443         proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_length, tvb, maid_offset, 1, ENC_BIG_ENDIAN);
444         cfm_maid_ma_name_length = tvb_get_guint8(tvb, maid_offset);
445         maid_offset += 1;
446         if ((cfm_maid_ma_name_format == 2) ||
447             (cfm_maid_ma_name_format == 32)) {
448                 proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_string,
449                         tvb, maid_offset, cfm_maid_ma_name_length, ENC_ASCII|ENC_NA);
450         } else {
451                 proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_hex,
452                         tvb, maid_offset, cfm_maid_ma_name_length, ENC_NA);
453         }
454         maid_offset += cfm_maid_ma_name_length;
455         offset += 48;
456         if (offset > maid_offset) {
457                 gint padding_length;
458                 padding_length = offset - maid_offset;
459                 proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_padding,
460                         tvb, maid_offset, padding_length, ENC_NA);
461         }
462
463         /* Dissect 16 octets reserved for Y.1731, samples of the wrap-around frame counters */
464         wi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_itu_t_y1731, tvb, offset, 16, ENC_NA);
465         cfm_ccm_itu_tree = proto_item_add_subtree(wi, ett_cfm_ccm_itu);
466         itu_offset = offset;
467         proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_itu_TxFCf, tvb, itu_offset, 4, ENC_NA);
468         itu_offset += 4;
469         proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_itu_RxFCb, tvb, itu_offset, 4, ENC_NA);
470         itu_offset += 4;
471         proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_itu_TxFCb, tvb, itu_offset, 4, ENC_NA);
472         itu_offset += 4;
473         proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_itu_reserved, tvb, itu_offset, 4, ENC_NA);
474         itu_offset += 4;
475
476         offset += 16;
477         return offset;
478 }
479
480 static int dissect_cfm_lbm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
481 {
482         proto_item *ti;
483         proto_tree *cfm_pdu_tree;
484
485         ti = proto_tree_add_item(tree, hf_cfm_lbm_pdu, tvb, offset, -1, ENC_NA);
486         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
487
488         proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
489         offset += 1;
490         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
491         offset += 1;
492         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lb_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
493         offset += 4;
494         return offset;
495 }
496
497 static int dissect_cfm_lbr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
498 {
499         proto_item *ti;
500         proto_tree *cfm_pdu_tree;
501
502         ti = proto_tree_add_item(tree, hf_cfm_lbr_pdu, tvb, offset, -1, ENC_NA);
503         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
504
505         proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
506         offset += 1;
507         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
508         offset += 1;
509         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lb_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
510         offset += 4;
511         return offset;
512 }
513
514 static int dissect_cfm_ltm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
515 {
516         proto_item *ti;
517         proto_item *fi;
518         proto_tree *cfm_pdu_tree;
519         proto_tree *cfm_flag_tree;
520
521         ti = proto_tree_add_item(tree, hf_cfm_ltm_pdu, tvb, offset, -1, ENC_NA);
522         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
523
524         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
525         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
526         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_UseFDBonly, tvb, offset, 1, ENC_BIG_ENDIAN);
527         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ltm_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
528         offset += 1;
529
530         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
531         offset += 1;
532         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lt_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
533         offset += 4;
534         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lt_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
535         offset += 1;
536         proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_orig_addr, tvb, offset, 6, ENC_NA);
537         offset += 6;
538         proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_targ_addr, tvb, offset, 6, ENC_NA);
539         offset += 6;
540         return offset;
541 }
542
543 static int dissect_cfm_ltr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
544 {
545         proto_item *ti;
546         proto_item *fi;
547         proto_tree *cfm_pdu_tree;
548         proto_tree *cfm_flag_tree;
549
550         ti = proto_tree_add_item(tree, hf_cfm_ltr_pdu, tvb, offset, -1, ENC_NA);
551         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
552
553         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
554         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
555         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_UseFDBonly, tvb, offset, 1, ENC_BIG_ENDIAN);
556         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_FwdYes, tvb, offset, 1, ENC_BIG_ENDIAN);
557         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_TerminalMEP, tvb, offset, 1, ENC_BIG_ENDIAN);
558         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ltr_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
559         offset += 1;
560
561         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
562         offset += 1;
563         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lt_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
564         offset += 4;
565         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lt_ttl, tvb, offset, 1, ENC_BIG_ENDIAN);
566         offset += 1;
567         proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltr_relay_action, tvb, offset, 1, ENC_BIG_ENDIAN);
568         offset += 1;
569         return offset;
570 }
571
572 static int dissect_cfm_ais(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
573 {
574         proto_item *ti;
575         proto_item *fi;
576         proto_tree *cfm_pdu_tree;
577         proto_tree *cfm_flag_tree;
578
579         ti = proto_tree_add_item(tree, hf_cfm_ais_pdu, tvb, offset, -1, ENC_NA);
580         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
581
582         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
583         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
584         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
585         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Period, tvb, offset, 1, ENC_BIG_ENDIAN);
586         offset += 1;
587
588         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
589         offset += 1;
590
591         return offset;
592 }
593
594 static int dissect_cfm_lck(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
595 {
596         proto_item *ti;
597         proto_item *fi;
598         proto_tree *cfm_pdu_tree;
599         proto_tree *cfm_flag_tree;
600
601         ti = proto_tree_add_item(tree, hf_cfm_lck_pdu, tvb, offset, -1, ENC_NA);
602         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
603
604         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
605         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
606         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
607         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Period, tvb, offset, 1, ENC_BIG_ENDIAN);
608         offset += 1;
609
610         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
611         offset += 1;
612
613         return offset;
614 }
615
616 static int dissect_cfm_tst(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
617 {
618         proto_item *ti;
619         proto_item *fi;
620         proto_tree *cfm_pdu_tree;
621         proto_tree *cfm_flag_tree;
622
623         ti = proto_tree_add_item(tree, hf_cfm_tst_pdu, tvb, offset, -1, ENC_NA);
624         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
625
626         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
627         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
628         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
629         offset += 1;
630
631         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
632         offset += 1;
633
634         proto_tree_add_item(cfm_pdu_tree, hf_cfm_tst_sequence_num, tvb, offset, 4, ENC_BIG_ENDIAN);
635         offset += 4;
636
637         return offset;
638 }
639
640 static int dissect_cfm_aps(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
641 {
642         gint cfm_tlv_offset;
643         proto_item *ti;
644         proto_item *fi;
645         proto_tree *cfm_pdu_tree;
646         proto_tree *cfm_flag_tree;
647
648         ti = proto_tree_add_item(tree, hf_cfm_aps_pdu, tvb, offset, -1, ENC_NA);
649         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
650
651         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
652         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
653         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
654         offset += 1;
655
656         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
657         offset += 1;
658
659         /* The APS data field was not defined at the time of this code being written
660          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
661          * the TLV offset and perform a hex dump */
662         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
663         if (cfm_tlv_offset > 0) {
664                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_data, tvb, offset, cfm_tlv_offset, ENC_NA);
665                 offset += cfm_tlv_offset;
666         }
667
668         return offset;
669 }
670
671 static int dissect_cfm_raps(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
672 {
673         proto_item *ti;
674         proto_item *fi;
675         proto_item *ri;
676         proto_tree *cfm_pdu_tree;
677         proto_tree *cfm_flag_tree;
678         proto_tree *raps_flag_tree;
679
680         ti = proto_tree_add_item(tree, hf_cfm_raps_pdu, tvb, offset, -1, ENC_NA);
681         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
682
683         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
684         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
685         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
686         offset += 1;
687
688         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
689         offset += 1;
690
691         proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_req_st, tvb, offset, 1, ENC_BIG_ENDIAN);
692         offset += 1;
693
694         ri = proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
695         raps_flag_tree = proto_item_add_subtree(ri, ett_cfm_raps_flags);
696         proto_tree_add_item(raps_flag_tree, hf_cfm_raps_flags_rb, tvb, offset, 1, ENC_BIG_ENDIAN);
697         proto_tree_add_item(raps_flag_tree, hf_cfm_raps_flags_dnf, tvb, offset, 1, ENC_BIG_ENDIAN);
698         offset += 1;
699
700         proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_node_id, tvb, offset, 6, ENC_NA);
701         offset += 6;
702
703         proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_reserved, tvb, offset, 24, ENC_NA);
704         offset += 24;
705
706         return offset;
707 }
708
709 static int dissect_cfm_mcc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
710 {
711         gint cfm_tlv_offset;
712         proto_item *ti;
713         proto_item *fi;
714         proto_tree *cfm_pdu_tree;
715         proto_tree *cfm_flag_tree;
716
717         ti = proto_tree_add_item(tree, hf_cfm_mcc_pdu, tvb, offset, -1, ENC_NA);
718         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
719
720         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
721         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
722         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
723         offset += 1;
724
725         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
726         offset += 1;
727
728         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_oui, tvb, offset, 3, ENC_NA);
729         offset += 3;
730         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_subtype, tvb, offset, 1, ENC_NA);
731         offset += 1;
732
733         /* The MCC data field was not defined at the time of this code being written
734          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
735          * the TLV offset and perform a hex dump */
736         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
737         /* Remove OUI and subtype from the offset */
738         cfm_tlv_offset -= 4;
739         if (cfm_tlv_offset > 0) {
740                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_mcc_data, tvb, offset, cfm_tlv_offset, ENC_NA);
741                 offset += cfm_tlv_offset;
742         }
743
744         return offset;
745 }
746
747 static int dissect_cfm_lmm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
748 {
749         proto_item *ti;
750         proto_item *fi;
751         proto_tree *cfm_pdu_tree;
752         proto_tree *cfm_flag_tree;
753
754         ti = proto_tree_add_item(tree, hf_cfm_lmm_pdu, tvb, offset, -1, ENC_NA);
755         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
756
757         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
758         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
759         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
760         offset += 1;
761
762         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
763         offset += 1;
764
765         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCf, tvb, offset, 4, ENC_NA);
766         offset += 4;
767         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_RxFCf, tvb, offset, 4, ENC_NA);
768         offset += 4;
769         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCb, tvb, offset, 4, ENC_NA);
770         offset += 4;
771
772         return offset;
773 }
774
775 static int dissect_cfm_lmr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
776 {
777         proto_item *ti;
778         proto_item *fi;
779         proto_tree *cfm_pdu_tree;
780         proto_tree *cfm_flag_tree;
781
782         ti = proto_tree_add_item(tree, hf_cfm_lmr_pdu, tvb, offset, -1, ENC_NA);
783         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
784
785         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
786         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
787         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
788         offset += 1;
789
790         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
791         offset += 1;
792
793         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCf, tvb, offset, 4, ENC_NA);
794         offset += 4;
795         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_RxFCf, tvb, offset, 4, ENC_NA);
796         offset += 4;
797         proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCb, tvb, offset, 4, ENC_NA);
798         offset += 4;
799
800         return offset;
801 }
802
803 static int dissect_cfm_odm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
804 {
805         proto_item *ti;
806         proto_item *fi;
807         proto_tree *cfm_pdu_tree;
808         proto_tree *cfm_flag_tree;
809
810         ti = proto_tree_add_item(tree, hf_cfm_odm_pdu, tvb, offset, -1, ENC_NA);
811         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
812
813         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
814         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
815         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
816         offset += 1;
817
818         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
819         offset += 1;
820
821         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_NA);
822         offset += 8;
823         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_NA);
824         offset += 8;
825
826         return offset;
827 }
828
829 static int dissect_cfm_dmm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
830 {
831         proto_item *ti;
832         proto_item *fi;
833         proto_tree *cfm_pdu_tree;
834         proto_tree *cfm_flag_tree;
835
836         ti = proto_tree_add_item(tree, hf_cfm_dmm_pdu, tvb, offset, -1, ENC_NA);
837         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
838
839         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
840         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
841         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
842         offset += 1;
843
844         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
845         offset += 1;
846
847         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_NA);
848         offset += 8;
849         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_NA);
850         offset += 8;
851         proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_TxTimestampb, tvb, offset, 8, ENC_NA);
852         offset += 8;
853         proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_RxTimestampb, tvb, offset, 8, ENC_NA);
854         offset += 8;
855
856         return offset;
857 }
858
859 static int dissect_cfm_dmr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
860 {
861         proto_item *ti;
862         proto_item *fi;
863         proto_tree *cfm_pdu_tree;
864         proto_tree *cfm_flag_tree;
865
866         ti = proto_tree_add_item(tree, hf_cfm_dmr_pdu, tvb, offset, -1, ENC_NA);
867         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
868
869         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
870         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
871         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
872         offset += 1;
873
874         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
875         offset += 1;
876
877         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_NA);
878         offset += 8;
879         proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_NA);
880         offset += 8;
881         proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_TxTimestampb, tvb, offset, 8, ENC_NA);
882         offset += 8;
883         proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_RxTimestampb, tvb, offset, 8, ENC_NA);
884         offset += 8;
885
886         return offset;
887 }
888
889 static int dissect_cfm_exm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
890 {
891         gint cfm_tlv_offset;
892         proto_item *ti;
893         proto_item *fi;
894         proto_tree *cfm_pdu_tree;
895         proto_tree *cfm_flag_tree;
896
897         ti = proto_tree_add_item(tree, hf_cfm_exm_pdu, tvb, offset, -1, ENC_NA);
898         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
899
900         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
901         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
902         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
903         offset += 1;
904
905         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
906         offset += 1;
907
908         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_oui, tvb, offset, 3, ENC_NA);
909         offset += 3;
910         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_subtype, tvb, offset, 1, ENC_NA);
911         offset += 1;
912
913         /* The EXM data field was not defined at the time of this code being written
914          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
915          * the TLV offset and perform a hex dump */
916         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
917         /* Remove OUI and subtype from the offset */
918         cfm_tlv_offset -= 4;
919         if (cfm_tlv_offset > 0) {
920                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exm_exr_data, tvb, offset, cfm_tlv_offset, ENC_NA);
921                 offset += cfm_tlv_offset;
922         }
923
924         return offset;
925 }
926
927 static int dissect_cfm_exr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
928 {
929         gint cfm_tlv_offset;
930         proto_item *ti;
931         proto_item *fi;
932         proto_tree *cfm_pdu_tree;
933         proto_tree *cfm_flag_tree;
934
935         ti = proto_tree_add_item(tree, hf_cfm_exr_pdu, tvb, offset, -1, ENC_NA);
936         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
937
938         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
939         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
940         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
941         offset += 1;
942
943         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
944         offset += 1;
945
946         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_oui, tvb, offset, 3, ENC_NA);
947         offset += 3;
948         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_subtype, tvb, offset, 1, ENC_NA);
949         offset += 1;
950
951         /* The EXR data field was not defined at the time of this code being written
952          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
953          * the TLV offset and perform a hex dump */
954         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
955         /* Remove OUI and subtype from the offset */
956         cfm_tlv_offset -= 4;
957         if (cfm_tlv_offset > 0) {
958                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exm_exr_data, tvb, offset, cfm_tlv_offset, ENC_NA);
959                 offset += cfm_tlv_offset;
960         }
961
962         return offset;
963 }
964
965 static int dissect_cfm_vsm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
966 {
967         gint cfm_tlv_offset;
968         proto_item *ti;
969         proto_item *fi;
970         proto_tree *cfm_pdu_tree;
971         proto_tree *cfm_flag_tree;
972
973         ti = proto_tree_add_item(tree, hf_cfm_vsm_pdu, tvb, offset, -1, ENC_NA);
974         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
975
976         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
977         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
978         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
979         offset += 1;
980
981         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
982         offset += 1;
983
984         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_oui, tvb, offset, 3, ENC_NA);
985         offset += 3;
986         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_subtype, tvb, offset, 1, ENC_NA);
987         offset += 1;
988
989         /* The VSM data field was not defined at the time of this code being written
990          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
991          * the TLV offset and perform a hex dump */
992         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
993         /* Remove OUI and subtype from the offset */
994         cfm_tlv_offset -= 4;
995         if (cfm_tlv_offset > 0) {
996                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsm_vsr_data, tvb, offset, cfm_tlv_offset, ENC_NA);
997                 offset += cfm_tlv_offset;
998         }
999
1000         return offset;
1001 }
1002
1003 static int dissect_cfm_vsr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1004 {
1005         gint cfm_tlv_offset;
1006         proto_item *ti;
1007         proto_item *fi;
1008         proto_tree *cfm_pdu_tree;
1009         proto_tree *cfm_flag_tree;
1010
1011         ti = proto_tree_add_item(tree, hf_cfm_vsr_pdu, tvb, offset, -1, ENC_NA);
1012         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1013
1014         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1015         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1016         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1017         offset += 1;
1018
1019         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
1020         offset += 1;
1021
1022         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_oui, tvb, offset, 3, ENC_NA);
1023         offset += 3;
1024         proto_tree_add_item(cfm_pdu_tree, hf_tlv_org_spec_subtype, tvb, offset, 1, ENC_NA);
1025         offset += 1;
1026
1027         /* The VSR data field was not defined at the time of this code being written
1028          * ITU-T Y.1731 (05/2006), so we are simply going to determine the length based on
1029          * the TLV offset and perform a hex dump */
1030         cfm_tlv_offset = tvb_get_guint8(tvb, 3);
1031         /* Remove OUI and subtype from the offset */
1032         cfm_tlv_offset -= 4;
1033         if (cfm_tlv_offset > 0) {
1034                 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsm_vsr_data, tvb, offset, cfm_tlv_offset, ENC_NA);
1035                 offset += cfm_tlv_offset;
1036         }
1037
1038         return offset;
1039 }
1040
1041 static int dissect_cfm_slm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1042 {
1043         proto_item *ti;
1044         proto_item *fi;
1045         proto_tree *cfm_pdu_tree;
1046         proto_tree *cfm_flag_tree;
1047
1048         ti = proto_tree_add_item(tree, hf_cfm_slm_pdu, tvb, offset, -1, ENC_NA);
1049         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1050
1051         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1052         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1053         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1054         offset += 1;
1055
1056         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
1057         offset += 1;
1058
1059         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_src_mep, tvb, offset, 2, ENC_NA);
1060         offset += 2;
1061         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_rsp_mep, tvb, offset, 2, ENC_NA);
1062         offset += 2;
1063         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_testid, tvb, offset, 4, ENC_NA);
1064         offset += 4;
1065         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_txfcf, tvb, offset, 4, ENC_BIG_ENDIAN);
1066         offset += 4;
1067         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_txfcb, tvb, offset, 4, ENC_BIG_ENDIAN);
1068         offset += 4;
1069
1070         return offset;
1071 }
1072
1073 static int dissect_cfm_slr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1074 {
1075         proto_item *ti;
1076         proto_item *fi;
1077         proto_tree *cfm_pdu_tree;
1078         proto_tree *cfm_flag_tree;
1079
1080         ti = proto_tree_add_item(tree, hf_cfm_slr_pdu, tvb, offset, -1, ENC_NA);
1081         cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1082
1083         fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
1084         cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1085         proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1086         offset += 1;
1087
1088         proto_tree_add_item(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
1089         offset += 1;
1090
1091         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_src_mep, tvb, offset, 2, ENC_NA);
1092         offset += 2;
1093         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_rsp_mep, tvb, offset, 2, ENC_NA);
1094         offset += 2;
1095         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_testid, tvb, offset, 4, ENC_NA);
1096         offset += 4;
1097         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_txfcf, tvb, offset, 4, ENC_BIG_ENDIAN);
1098         offset += 4;
1099         proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_txfcb, tvb, offset, 4, ENC_BIG_ENDIAN);
1100         offset += 4;
1101
1102         return offset;
1103 }
1104
1105
1106 /* Main CFM EOAM protocol dissector */
1107 static void dissect_cfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1108 {
1109         gint offset = 0;
1110         guint8 cfm_pdu_type;
1111
1112         /* display the CFM protol name */
1113         col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFM");
1114
1115         /* Clear out stuff in the info column */
1116         col_clear(pinfo->cinfo, COL_INFO);
1117
1118         /* provide info column with CFM packet type (opcode)*/
1119         cfm_pdu_type = tvb_get_guint8(tvb, 1);
1120
1121         col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
1122         val_to_str(cfm_pdu_type, opcodetypenames, "Unknown (0x%02x)"));
1123
1124         if (tree) { /* we are being asked for details */
1125                 gint cfm_tlv_offset;
1126                 proto_item *ti;
1127                 proto_tree *cfm_tree;
1128
1129                 /* isolate the payload of the packet */
1130                 ti = proto_tree_add_item(tree, proto_cfm, tvb, 0, -1, ENC_BIG_ENDIAN);
1131
1132
1133                 /* report type of CFM packet to base of dissection tree */
1134                 proto_item_append_text(ti, ", Type %s",
1135                         val_to_str(cfm_pdu_type, opcodetypenames, "Unknown (0x%02x)"));
1136
1137                 /* dissecting the common CFM header */
1138                 cfm_tree = proto_item_add_subtree(ti, ett_cfm);
1139                 proto_tree_add_item(cfm_tree, hf_cfm_md_level, tvb, offset, 1, ENC_BIG_ENDIAN);
1140                 proto_tree_add_item(cfm_tree, hf_cfm_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1141                 offset += 1;
1142                 proto_tree_add_item(cfm_tree, hf_cfm_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
1143                 offset += 1;
1144
1145                 switch(cfm_pdu_type) {
1146                 case CCM:
1147                         offset = dissect_cfm_ccm(tvb, pinfo, tree, offset);
1148                         break;
1149                 case LBM:
1150                         offset = dissect_cfm_lbm(tvb, pinfo, tree, offset);
1151                         break;
1152                 case LBR:
1153                         offset = dissect_cfm_lbr(tvb, pinfo, tree, offset);
1154                         break;
1155                 case LTM:
1156                         offset = dissect_cfm_ltm(tvb, pinfo, tree, offset);
1157                         break;
1158                 case LTR:
1159                         offset = dissect_cfm_ltr(tvb, pinfo, tree, offset);
1160                         break;
1161                 case AIS:
1162                         offset = dissect_cfm_ais(tvb, pinfo, tree, offset);
1163                         break;
1164                 case LCK:
1165                         offset = dissect_cfm_lck(tvb, pinfo, tree, offset);
1166                         break;
1167                 case TST:
1168                         offset = dissect_cfm_tst(tvb, pinfo, tree, offset);
1169                         break;
1170                 case APS:
1171                         offset = dissect_cfm_aps(tvb, pinfo, tree, offset);
1172                         break;
1173                 case RAPS:
1174                         offset = dissect_cfm_raps(tvb, pinfo, tree, offset);
1175                         break;
1176                 case MCC:
1177                         offset = dissect_cfm_mcc(tvb, pinfo, tree, offset);
1178                         break;
1179                 case LMM:
1180                         offset = dissect_cfm_lmm(tvb, pinfo, tree, offset);
1181                         break;
1182                 case LMR:
1183                         offset = dissect_cfm_lmr(tvb, pinfo, tree, offset);
1184                         break;
1185                 case ODM:
1186                         offset = dissect_cfm_odm(tvb, pinfo, tree, offset);
1187                         break;
1188                 case DMM:
1189                         offset = dissect_cfm_dmm(tvb, pinfo, tree, offset);
1190                         break;
1191                 case DMR:
1192                         offset = dissect_cfm_dmr(tvb, pinfo, tree, offset);
1193                         break;
1194                 case EXM:
1195                         offset = dissect_cfm_exm(tvb, pinfo, tree, offset);
1196                         break;
1197                 case EXR:
1198                         offset = dissect_cfm_exr(tvb, pinfo, tree, offset);
1199                         break;
1200                 case VSM:
1201                         offset = dissect_cfm_vsm(tvb, pinfo, tree, offset);
1202                         break;
1203                 case VSR:
1204                         offset = dissect_cfm_vsr(tvb, pinfo, tree, offset);
1205                         break;
1206                 case SLM:
1207                         offset = dissect_cfm_slm(tvb, pinfo, tree, offset);
1208                         break;
1209                 case SLR:
1210                         offset = dissect_cfm_slr(tvb, pinfo, tree, offset);
1211                         break;
1212                 }
1213
1214                 /* Get the TLV offset and add the offset of the common CFM header*/
1215                 cfm_tlv_offset = tvb_get_guint8(tvb, 3);
1216                 cfm_tlv_offset += 4;
1217
1218                 /* Begin dissecting the TLV's */
1219                 /* the TLV offset should be the same as where the pdu left off or we have a problem */
1220                 if ((cfm_tlv_offset == offset) && (cfm_tlv_offset > 3)) {
1221                         proto_tree *cfm_all_tlvs_tree;
1222                         guint8 cfm_tlv_type = 255;
1223                         ti = proto_tree_add_item(tree, hf_cfm_all_tlvs, tvb, cfm_tlv_offset, -1, ENC_NA);
1224                         cfm_all_tlvs_tree = proto_item_add_subtree(ti, ett_cfm_all_tlvs);
1225
1226                         while (cfm_tlv_type != END_TLV)
1227                         {
1228                                 guint16 cfm_tlv_length;
1229                                 gint tlv_header_modifier;
1230                                 proto_item *fi;
1231                                 proto_tree *cfm_tlv_tree;
1232                                 cfm_tlv_type = tvb_get_guint8(tvb, cfm_tlv_offset);
1233
1234                                 if (cfm_tlv_type == END_TLV) {
1235                                         tlv_header_modifier = 1;
1236                                         cfm_tlv_length = 0;
1237                                 } else {
1238                                         tlv_header_modifier = 3;
1239                                         cfm_tlv_length = tvb_get_ntohs(tvb, cfm_tlv_offset+1);
1240                                 }
1241
1242                                 fi = proto_tree_add_text(cfm_all_tlvs_tree, tvb, cfm_tlv_offset, cfm_tlv_length+tlv_header_modifier,
1243                                                "TLV: %s (t=%d,l=%d)", val_to_str(cfm_tlv_type, tlvtypefieldvalues, "Unknown (0x%02x)"),
1244                                                cfm_tlv_type, cfm_tlv_length);
1245                                 cfm_tlv_tree = proto_item_add_subtree(fi, ett_cfm_tlv);
1246
1247                                 proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_type, tvb, cfm_tlv_offset, 1, ENC_BIG_ENDIAN);
1248                                 cfm_tlv_offset += 1;
1249                                 if  (cfm_tlv_type != END_TLV) {
1250                                         proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_length, tvb, cfm_tlv_offset, 2, ENC_BIG_ENDIAN);
1251                                         cfm_tlv_offset += 2;
1252
1253                                         if  (cfm_tlv_length != 0) {
1254                                                 gint   tlv_data_offset;
1255                                                 guint8 tlv_chassis_id_length;
1256                                                 guint8 tlv_tst_test_pattern_type;
1257
1258                                                 tlv_data_offset = cfm_tlv_offset;
1259
1260                                                 switch(cfm_tlv_type) {
1261                                                 case SENDER_ID_TLV:
1262                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_length,
1263                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1264                                                         tlv_chassis_id_length = tvb_get_guint8(tvb,tlv_data_offset);
1265                                                         tlv_data_offset += 1;
1266
1267                                                         if (tlv_chassis_id_length > 0) {
1268                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_subtype,
1269                                                                                 tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1270                                                                 tlv_data_offset += 1;
1271                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id,
1272                                                                                 tvb, tlv_data_offset, tlv_chassis_id_length, ENC_NA);
1273                                                                 tlv_data_offset += tlv_chassis_id_length;
1274                                                         }
1275
1276                                                         /* If the TLV length is greater than the number of octets used for the
1277                                                          * Chassis ID, then we must have a Management Address Domain */
1278                                                         if (cfm_tlv_length > (2 + tlv_chassis_id_length)) {
1279                                                                 guint8 tlv_ma_domain_length;
1280                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain_length,
1281                                                                                 tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1282                                                                 tlv_ma_domain_length = tvb_get_guint8(tvb,tlv_data_offset);
1283                                                                 tlv_data_offset += 1;
1284                                                                 if (tlv_ma_domain_length > 0) {
1285                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain,
1286                                                                                 tvb, tlv_data_offset, tlv_ma_domain_length, ENC_NA);
1287                                                                         tlv_data_offset += tlv_ma_domain_length;
1288                                                                 }
1289
1290                                                                 /* If the TLV length is greater than the number of octets used for the
1291                                                                  * Chassis ID and the Management Address Domain, then we must have a
1292                                                                  * Management Address */
1293                                                                 if (cfm_tlv_length > (2 + tlv_chassis_id_length + 1 + tlv_ma_domain_length)) {
1294                                                                         guint8 tlv_management_addr_length;
1295                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr_length,
1296                                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1297                                                                         tlv_management_addr_length = tvb_get_guint8(tvb,tlv_data_offset);
1298                                                                         tlv_data_offset += 1;
1299                                                                         if (tlv_management_addr_length > 0) {
1300                                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr,
1301                                                                                         tvb, tlv_data_offset, tlv_management_addr_length, ENC_NA);
1302                                                                                 tlv_data_offset += tlv_management_addr_length;
1303                                                                         }
1304                                                                 }
1305                                                         }
1306                                                         break;
1307                                                 case PORT_STAT_TLV:
1308                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_port_status_value,
1309                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1310                                                         tlv_data_offset += 1;
1311                                                         break;
1312                                                 case DATA_TLV:
1313                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_data_value,
1314                                                                         tvb, tlv_data_offset, cfm_tlv_length, ENC_NA);
1315                                                         tlv_data_offset += cfm_tlv_length;
1316                                                         break;
1317                                                 case INTERF_STAT_TLV:
1318                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_interface_status_value,
1319                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1320                                                         tlv_data_offset += 1;
1321                                                         break;
1322                                                 case REPLY_ING_TLV:
1323                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_action,
1324                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1325                                                         tlv_data_offset += 1;
1326                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_mac_address,
1327                                                                         tvb, tlv_data_offset, 6, ENC_NA);
1328                                                         tlv_data_offset += 6;
1329
1330                                                         /* For the IEEE standard if the TLV length is greater than 7 then we have
1331                                                          * an ingress port ID
1332                                                          */
1333                                                         if (cfm_tlv_length > 7) {
1334                                                                 guint8 tlv_reply_ingress_portid_length;
1335                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
1336                                                                                 tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1337                                                                 tlv_reply_ingress_portid_length = tvb_get_guint8(tvb,tlv_data_offset);
1338                                                                 tlv_data_offset += 1;
1339
1340                                                                 if (tlv_reply_ingress_portid_length > 0) {
1341                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_subtype,
1342                                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1343                                                                         tlv_data_offset += 1;
1344                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid,
1345                                                                                         tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_NA);
1346                                                                         tlv_data_offset += tlv_reply_ingress_portid_length;
1347                                                                 }
1348                                                         }
1349                                                         break;
1350                                                 case REPLY_EGR_TLV:
1351                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_action,
1352                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1353                                                         tlv_data_offset += 1;
1354                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_mac_address,
1355                                                                         tvb, tlv_data_offset, 6, ENC_NA);
1356                                                         tlv_data_offset += 6;
1357
1358                                                         /* For the IEEE standard if the TLV length is greater than 7 then we have
1359                                                          * an egress port ID
1360                                                          */
1361                                                         if (cfm_tlv_length > 7) {
1362                                                                 guint8 tlv_reply_egress_portid_length;
1363                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
1364                                                                                 tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1365                                                                 tlv_reply_egress_portid_length = tvb_get_guint8(tvb,tlv_data_offset);
1366                                                                 tlv_data_offset += 1;
1367
1368                                                                 if (tlv_reply_egress_portid_length > 0) {
1369                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_subtype,
1370                                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1371                                                                         tlv_data_offset += 1;
1372                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid,
1373                                                                                         tvb, tlv_data_offset, tlv_reply_egress_portid_length, ENC_NA);
1374                                                                         tlv_data_offset += tlv_reply_egress_portid_length;
1375                                                                 }
1376                                                         }
1377                                                         break;
1378                                                 case LTM_EGR_ID_TLV:
1379                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_unique_identifier,
1380                                                                         tvb, tlv_data_offset, 2, ENC_NA);
1381                                                         tlv_data_offset += 2;
1382                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_mac,
1383                                                                         tvb, tlv_data_offset, 6, ENC_NA);
1384                                                         tlv_data_offset += 6;
1385                                                         break;
1386                                                 case LTR_EGR_ID_TLV:
1387                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_last_id_unique_identifier,
1388                                                                         tvb, tlv_data_offset, 2, ENC_NA);
1389                                                         tlv_data_offset += 2;
1390                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_last_id_mac,
1391                                                                         tvb, tlv_data_offset, 6, ENC_NA);
1392                                                         tlv_data_offset += 6;
1393                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_next_id_unique_identifier,
1394                                                                         tvb, tlv_data_offset, 2, ENC_NA);
1395                                                         tlv_data_offset += 2;
1396                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_next_id_mac,
1397                                                                         tvb, tlv_data_offset, 6, ENC_NA);
1398                                                         tlv_data_offset += 6;
1399                                                         break;
1400                                                 case ORG_SPEC_TLV:
1401                                                         /* The TLV length must be long enough to include the OUI
1402                                                          * and the subtype.
1403                                                          */
1404                                                         if (cfm_tlv_length > 3) {
1405                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_oui,
1406                                                                         tvb, tlv_data_offset, 3, ENC_NA);
1407                                                                 tlv_data_offset += 3;
1408                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_subtype,
1409                                                                         tvb, tlv_data_offset, 1, ENC_NA);
1410                                                                 tlv_data_offset += 1;
1411                                                                 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_value,
1412                                                                         tvb, tlv_data_offset, cfm_tlv_length-4, ENC_NA);
1413                                                                 tlv_data_offset -= 4;
1414                                                         }
1415                                                         tlv_data_offset += cfm_tlv_length;
1416                                                         break;
1417                                                 case TEST_TLV:
1418                                                         /* There is a discrepancy in the recommendation ITU-T Y.1731
1419                                                          * where the test pattern type may or may not be included in
1420                                                          * the TLV length.  Going to assume that it is included in the
1421                                                          * length which corresponds with the typical format for TLV's
1422                                                          * until the recommendation is more clear in this regard. */
1423                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_test_pattern_type,
1424                                                                         tvb, tlv_data_offset, 1, ENC_BIG_ENDIAN);
1425                                                         tlv_tst_test_pattern_type = tvb_get_guint8(tvb,tlv_data_offset);
1426                                                         tlv_data_offset += 1;
1427                                                         if (cfm_tlv_length > 0) {
1428                                                                 switch (tlv_tst_test_pattern_type) {
1429                                                                 case 0:
1430                                                                 case 2:
1431                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_test_pattern,
1432                                                                                         tvb, tlv_data_offset, cfm_tlv_length-1, ENC_NA);
1433                                                                         tlv_data_offset += cfm_tlv_length;
1434                                                                         break;
1435                                                                 case 1:
1436                                                                 case 3:
1437                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_test_pattern,
1438                                                                                 tvb, tlv_data_offset, cfm_tlv_length-5, ENC_NA);
1439                                                                         tlv_data_offset += (cfm_tlv_length-5);
1440                                                                         proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_CRC32,
1441                                                                                         tvb, tlv_data_offset, 4, ENC_NA);
1442                                                                         tlv_data_offset += 4;
1443                                                                         break;
1444                                                                 }
1445                                                         }
1446                                                         break;
1447                                                 }
1448
1449
1450                                                 cfm_tlv_offset += cfm_tlv_length;
1451                                         }
1452                                 }
1453                         }
1454                 }
1455         }
1456 }
1457
1458 /* Register CFM EOAM protocol */
1459 void proto_register_cfm(void)
1460 {
1461         static hf_register_info hf[] = {
1462                 { &hf_cfm_md_level,
1463                         { "CFM MD Level", "cfm.md.level", FT_UINT8,
1464                         BASE_DEC, NULL, 0xe0, NULL, HFILL }
1465                 },
1466                 { &hf_cfm_version,
1467                         { "CFM Version", "cfm.version", FT_UINT8,
1468                         BASE_DEC, NULL, 0x1f, NULL, HFILL }
1469                 },
1470                 { &hf_cfm_opcode,
1471                         { "CFM OpCode", "cfm.opcode", FT_UINT8,
1472                         BASE_DEC, VALS(opcodetypenames), 0x0, NULL, HFILL }
1473                 },
1474
1475                 /* CFM CCM*/
1476                 { &hf_cfm_ccm_pdu,
1477                         { "CFM CCM PDU", "cfm.ccm.pdu", FT_NONE,
1478                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1479                 },
1480                 { &hf_cfm_flags,
1481                         { "Flags", "cfm.flags", FT_UINT8,
1482                         BASE_HEX, NULL, 0x0, NULL, HFILL }
1483                 },
1484                 { &hf_cfm_flags_RDI,
1485                         { "RDI", "cfm.flags.rdi", FT_UINT8,
1486                         BASE_DEC, NULL, 0x80, NULL, HFILL }
1487                 },
1488                 { &hf_cfm_flags_ccm_Reserved,
1489                         { "Reserved", "cfm.flags.ccm.reserved", FT_UINT8,
1490                         BASE_DEC, NULL, 0x78, NULL, HFILL }
1491                 },
1492                 { &hf_cfm_flags_Interval,
1493                         { "Interval Field", "cfm.flags.interval", FT_UINT8,
1494                         BASE_DEC, VALS(CCM_IntervalFieldEncoding), 0x07, NULL, HFILL }
1495                 },
1496                 { &hf_cfm_first_tlv_offset,
1497                         { "First TLV Offset", "cfm.first.tlv.offset", FT_UINT8,
1498                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1499                 },
1500                 { &hf_cfm_ccm_seq_number,
1501                         { "Sequence Number", "cfm.ccm.seq.num", FT_UINT32,
1502                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1503                 },
1504                 { &hf_cfm_ccm_ma_ep_id,
1505                         { "Maintenance Association End Point Identifier", "cfm.ccm.ma.ep.id",
1506                          FT_UINT16, BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
1507                 },
1508                 { &hf_cfm_ccm_maid,
1509                         { "Maintenance Association Identifier (MEG ID)", "cfm.ccm.maid", FT_NONE,
1510                          BASE_NONE, NULL, 0x0, NULL, HFILL }
1511                 },
1512                 { &hf_cfm_maid_md_name_format,
1513                         { "MD Name Format", "cfm.maid.md.name.format", FT_UINT8,
1514                         BASE_DEC, VALS(mdnameformattypes), 0x0, NULL, HFILL }
1515                 },
1516                 { &hf_cfm_maid_md_name_length,
1517                         { "MD Name Length", "cfm.maid.md.name.length", FT_UINT8,
1518                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1519                 },
1520                 { &hf_cfm_maid_md_name_string,
1521                         { "MD Name (String)", "cfm.maid.md.name", FT_STRING,
1522                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1523                 },
1524                 { &hf_cfm_maid_md_name_hex,
1525                         { "MD Name", "cfm.maid.md.name", FT_BYTES,
1526                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1527                 },
1528                 { &hf_cfm_maid_md_name_mac,
1529                         { "MD Name (MAC)", "cfm.maid.md.name.mac", FT_ETHER,
1530                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1531                 },
1532                 { &hf_cfm_maid_md_name_mac_id,
1533                         { "MD Name (MAC)", "cfm.maid.md.name.mac.id", FT_BYTES,
1534                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1535                 },
1536                 { &hf_cfm_maid_ma_name_format,
1537                         { "Short MA Name (MEG ID) Format", "cfm.maid.ma.name.format", FT_UINT8,
1538                         BASE_DEC, VALS(manameformattypes), 0x0, NULL, HFILL }
1539                 },
1540                 { &hf_cfm_maid_ma_name_length,
1541                         { "Short MA Name (MEG ID) Length", "cfm.maid.ma.name.length", FT_UINT8,
1542                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1543                 },
1544                 { &hf_cfm_maid_ma_name_string,
1545                         { "Short MA Name", "cfm.maid.ma.name", FT_STRING,
1546                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1547                 },
1548                 { &hf_cfm_maid_ma_name_hex,
1549                         { "Short MA Name", "cfm.maid.ma.name", FT_BYTES,
1550                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1551                 },
1552                 { &hf_cfm_maid_padding,
1553                         { "Zero-Padding", "cfm.ccm.maid.padding", FT_NONE,
1554                          BASE_NONE, NULL, 0x0, NULL, HFILL }
1555                 },
1556                 { &hf_cfm_ccm_itu_t_y1731,
1557                         { "Defined by ITU-T Y.1731", "cfm.ccm.itu.t.y1731", FT_NONE,
1558                          BASE_NONE, NULL, 0x0, NULL, HFILL }
1559                 },
1560                 { &hf_cfm_itu_TxFCf,
1561                         { "TxFCf", "cfm.itu.txfcf", FT_BYTES,
1562                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1563                 },
1564                 { &hf_cfm_itu_RxFCb,
1565                         { "RxFCb", "cfm.itu.rxfcb", FT_BYTES,
1566                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1567                 },
1568                 { &hf_cfm_itu_TxFCb,
1569                         { "TxFCb", "cfm.itu.txfcb", FT_BYTES,
1570                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1571                 },
1572                 { &hf_cfm_itu_reserved,
1573                         { "Reserved", "cfm.itu.reserved", FT_BYTES,
1574                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1575                 },
1576
1577                 /* CFM LBM*/
1578                 { &hf_cfm_lbm_pdu,
1579                         { "CFM LBM PDU", "cfm.lbm.pdu", FT_NONE,
1580                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1581                 },
1582                 { &hf_cfm_lb_transaction_id,
1583                         { "Loopback Transaction Identifier", "cfm.lb.transaction.id", FT_UINT32,
1584                         BASE_DEC, NULL, 0x0, NULL, HFILL        }
1585                 },
1586
1587                 /* CFM LBR*/
1588                 { &hf_cfm_lbr_pdu,
1589                         { "CFM LBR PDU", "cfm.lbr.pdu", FT_NONE,
1590                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1591                 },
1592
1593                 /* CFM LTM*/
1594                 { &hf_cfm_ltm_pdu,
1595                         { "CFM LTM PDU", "cfm.ltm.pdu", FT_NONE,
1596                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1597                 },
1598                 { &hf_cfm_flags_UseFDBonly,
1599                         { "UseFDBonly", "cfm.flags.usefdbonly", FT_UINT8,
1600                         BASE_DEC, NULL, 0x80, NULL, HFILL }
1601                 },
1602                 { &hf_cfm_flags_ltm_Reserved,
1603                         { "Reserved", "cfm.flags.ltm.reserved", FT_UINT8,
1604                         BASE_DEC, NULL, 0x7F, NULL, HFILL }
1605                 },
1606                 { &hf_cfm_lt_transaction_id,
1607                         { "Linktrace Transaction Identifier", "cfm.lt.transaction.id", FT_UINT32,
1608                         BASE_DEC, NULL, 0x0, NULL, HFILL        }
1609                 },
1610                 { &hf_cfm_lt_ttl,
1611                         { "Linktrace TTL", "cfm.lt.ttl", FT_UINT8,
1612                         BASE_DEC, NULL, 0x0, NULL, HFILL        }
1613                 },
1614                 { &hf_cfm_ltm_orig_addr,
1615                         { "Linktrace Message: Original Address", "cfm.ltm.orig.addr", FT_ETHER,
1616                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1617                 },
1618                 { &hf_cfm_ltm_targ_addr,
1619                         { "Linktrace Message:   Target Address", "cfm.ltm.targ.addr", FT_ETHER,
1620                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1621                 },
1622
1623                 /* CFM LTR*/
1624                 { &hf_cfm_ltr_pdu,
1625                         { "CFM LTR PDU", "cfm.ltr.pdu", FT_NONE,
1626                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1627                 },
1628                 { &hf_cfm_flags_FwdYes,
1629                         { "FwdYes", "cfm.flags.fwdyes", FT_UINT8,
1630                         BASE_DEC, NULL, 0x40, NULL, HFILL }
1631                 },
1632                 { &hf_cfm_flags_TerminalMEP,
1633                         { "TerminalMEP", "cfm.flags.ltr.terminalmep", FT_UINT8,
1634                         BASE_DEC, NULL, 0x20, NULL, HFILL }
1635                 },
1636                 { &hf_cfm_flags_ltr_Reserved,
1637                         { "Reserved", "cfm.flags.ltr.reserved", FT_UINT8,
1638                         BASE_DEC, NULL, 0x1F, NULL, HFILL }
1639                 },
1640                 { &hf_cfm_ltr_relay_action,
1641                         { "Linktrace Reply Relay Action", "cfm.ltr.relay.action", FT_UINT8,
1642                         BASE_DEC, VALS(relayactiontypes), 0x0, NULL, HFILL}
1643                 },
1644
1645                 /* CFM AIS*/
1646                 { &hf_cfm_ais_pdu,
1647                         { "CFM AIS PDU", "cfm.ais.pdu", FT_NONE,
1648                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1649                 },
1650                 { &hf_cfm_flags_ais_lck_Reserved,
1651                         { "Reserved", "cfm.flags.reserved", FT_UINT8,
1652                         BASE_DEC, NULL, 0xF8, NULL, HFILL }
1653                 },
1654                 { &hf_cfm_flags_ais_lck_Period,
1655                         { "Period", "cfm.flags.period", FT_UINT8,
1656                         BASE_DEC, VALS(aislckperiodtypes), 0x07, NULL, HFILL }
1657                 },
1658
1659                 /* CFM LCK */
1660                 { &hf_cfm_lck_pdu,
1661                         { "CFM LCK PDU", "cfm.lck.pdu", FT_NONE,
1662                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1663                 },
1664
1665                 /* CFM TST */
1666                 { &hf_cfm_tst_pdu,
1667                         { "CFM TST PDU", "cfm.tst.pdu", FT_NONE,
1668                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1669                 },
1670                 { &hf_cfm_flags_Reserved,
1671                         { "Reserved", "cfm.flags.reserved", FT_UINT8,
1672                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1673                 },
1674                 { &hf_cfm_tst_sequence_num,
1675                         { "Sequence Number", "cfm.tst.sequence.num", FT_UINT32,
1676                         BASE_DEC, NULL, 0x0, NULL, HFILL        }
1677                 },
1678
1679                 /* CFM APS */
1680                 { &hf_cfm_aps_pdu,
1681                         { "CFM APS PDU", "cfm.aps.pdu", FT_NONE,
1682                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1683                 },
1684                 { &hf_cfm_aps_data,
1685                         { "APS data", "cfm.aps.data", FT_BYTES,
1686                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1687                 },
1688
1689                 /* CFM R-APS */
1690                 { &hf_cfm_raps_pdu,
1691                         { "CFM R-APS PDU", "cfm.raps.pdu", FT_NONE,
1692                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1693                 },
1694                 { &hf_cfm_raps_req_st,
1695                         { "Request/State", "cfm.raps.req.st", FT_UINT8,
1696                         BASE_HEX, VALS(rapsrequeststatevalues), 0xF0, NULL, HFILL }
1697                 },
1698                 { &hf_cfm_raps_flags,
1699                         { "R-APS Flags", "cfm.raps.flags", FT_UINT8,
1700                         BASE_HEX, NULL, 0x0, NULL, HFILL }
1701                 },
1702                 { &hf_cfm_raps_flags_rb,
1703                         { "RPL Blocked", "cfm.raps.flags.rb", FT_UINT8,
1704                         BASE_HEX, VALS(rapsrplblockedvalues), 0x80, NULL, HFILL }
1705                 },
1706                 { &hf_cfm_raps_flags_dnf,
1707                         { "Do Not Flush", "cfm.raps.flags.dnf", FT_UINT8,
1708                         BASE_HEX, VALS(rapsdnfvalues), 0x40, NULL, HFILL }
1709                 },
1710                 { &hf_cfm_raps_node_id,
1711                         { "R-APS Node ID", "cfm.raps.node.id", FT_ETHER,
1712                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1713                 },
1714                 { &hf_cfm_raps_reserved,
1715                         { "R-APS Reserved", "cfm.raps.reserved", FT_BYTES,
1716                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1717                 },
1718
1719                 /* CFM MCC */
1720                 { &hf_cfm_mcc_pdu,
1721                         { "CFM MCC PDU", "cfm.mcc.pdu", FT_NONE,
1722                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1723                 },
1724                 { &hf_cfm_mcc_data,
1725                         { "MCC data", "cfm.mcc.data", FT_BYTES,
1726                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1727                 },
1728
1729                 /* CFM LMM */
1730                 { &hf_cfm_lmm_pdu,
1731                         { "CFM LMM PDU", "cfm.lmm.pdu", FT_NONE,
1732                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1733                 },
1734                 { &hf_cfm_lmm_lmr_TxFCf,
1735                         { "TxFCf", "cfm.lmm.lmr.txfcf", FT_BYTES,
1736                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1737                 },
1738                 { &hf_cfm_lmm_lmr_RxFCf,
1739                         { "RxFCf", "cfm.lmm.lmr.rxfcf", FT_BYTES,
1740                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1741                 },
1742                 { &hf_cfm_lmm_lmr_TxFCb,
1743                         { "TxFCb", "cfm.lmm.lmr.txfcb", FT_BYTES,
1744                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1745                 },
1746
1747
1748                 /* CFM LMR */
1749                 { &hf_cfm_lmr_pdu,
1750                         { "CFM LMR PDU", "cfm.lmr.pdu", FT_NONE,
1751                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1752                 },
1753
1754                 /* CFM 1DM */
1755                 { &hf_cfm_odm_pdu,
1756                         { "CFM 1DM PDU", "cfm.odm.pdu", FT_NONE,
1757                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1758                 },
1759                 { &hf_cfm_odm_dmm_dmr_TxTimestampf,
1760                         { "TxTimestampf", "cfm.odm.dmm.dmr.txtimestampf", FT_BYTES,
1761                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1762                 },
1763                 { &hf_cfm_odm_dmm_dmr_RxTimestampf,
1764                         { "RxTimestampf", "cfm.odm.dmm.dmr.rxtimestampf", FT_BYTES,
1765                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1766                 },
1767
1768                 /* CFM DMM */
1769                 { &hf_cfm_dmm_pdu,
1770                         { "CFM DMM PDU", "cfm.dmm.pdu", FT_NONE,
1771                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1772                 },
1773                 { &hf_cfm_dmm_dmr_TxTimestampb,
1774                         { "TxTimestampb", "cfm.dmm.dmr.txtimestampb", FT_BYTES,
1775                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1776                 },
1777                 { &hf_cfm_dmm_dmr_RxTimestampb,
1778                         { "RxTimestampb", "cfm.dmm.dmr.rxtimestampb", FT_BYTES,
1779                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1780                 },
1781
1782                 /* CFM DMR */
1783                 { &hf_cfm_dmr_pdu,
1784                         { "CFM DMR PDU", "cfm.dmr.pdu", FT_NONE,
1785                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1786                 },
1787
1788                 /* CFM EXM */
1789                 { &hf_cfm_exm_pdu,
1790                         { "CFM EXM PDU", "cfm.exm.pdu", FT_NONE,
1791                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1792                 },
1793                 { &hf_cfm_exm_exr_data,
1794                         { "EXM/EXR data", "cfm.mcc.data", FT_BYTES,
1795                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1796                 },
1797
1798                 /* CFM EXR */
1799                 { &hf_cfm_exr_pdu,
1800                         { "CFM EXR PDU", "cfm.exr.pdu", FT_NONE,
1801                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1802                 },
1803
1804                 /* CFM VSM */
1805                 { &hf_cfm_vsm_pdu,
1806                         { "CFM VSM PDU", "cfm.vsm.pdu", FT_NONE,
1807                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1808                 },
1809                 { &hf_cfm_vsm_vsr_data,
1810                         { "VSM/VSR data", "cfm.mcc.data", FT_BYTES,
1811                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1812                 },
1813
1814                 /* CFM VSR */
1815                 { &hf_cfm_vsr_pdu,
1816                         { "CFM VSR PDU", "cfm.vsr.pdu", FT_NONE,
1817                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1818                 },
1819
1820                 /* Synthetic Loss values */
1821                 { &hf_cfm_slm_pdu,
1822                         { "CFM SLM PDU", "cfm.slm.pdu", FT_NONE,
1823                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1824                 },
1825                 { &hf_cfm_slr_pdu,
1826                         { "CFM SLR PDU", "cfm.slr.pdu", FT_NONE,
1827                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1828                 },
1829                 { &hf_cfm_slm_src_mep,
1830                         { "SrcMepID", "cfm.slm.src_mep_id", FT_BYTES,
1831                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1832                 },
1833                 { &hf_cfm_slr_rsp_mep,
1834                         { "RspMepID", "cfm.slr.rsp_mep_id", FT_BYTES,
1835                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1836                 },
1837                 { &hf_cfm_slm_testid,
1838                         { "TestID", "cfm.slm.test_id", FT_BYTES,
1839                         BASE_NONE, NULL, 0x0, NULL, HFILL }
1840                 },
1841                 { &hf_cfm_slm_txfcf,
1842                         { "TxFcF", "cfm.slm.txfcf", FT_UINT32,
1843                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1844                 },
1845                 { &hf_cfm_slr_txfcb,
1846                         { "TxFcB", "cfm.slr.txfcb", FT_UINT32,
1847                         BASE_DEC, NULL, 0x0, NULL, HFILL }
1848                 },
1849
1850                 /******************************* TLVs ****************************/
1851                 { &hf_cfm_all_tlvs,
1852                         { "CFM TLVs", "cfm.all.tlvs", FT_NONE,
1853                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1854                 },
1855                 { &hf_cfm_tlv_type,
1856                         { "TLV Type", "cfm.tlv.type", FT_UINT8,
1857                         BASE_DEC, VALS(tlvtypefieldvalues), 0x0, NULL, HFILL}
1858                 },
1859                 { &hf_cfm_tlv_length,
1860                         { "TLV Length", "cfm.tlv.length", FT_UINT16,
1861                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1862                 },
1863                                 /* Sender ID TLV */
1864                 { &hf_tlv_chassis_id_length,
1865                         { "Chassis ID Length", "cfm.tlv.chassis.id.length", FT_UINT8,
1866                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1867                 },
1868                 { &hf_tlv_chassis_id_subtype,
1869                         { "Chassis ID Sub-type", "cfm.tlv.chassis.id.subtype", FT_UINT8,
1870                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1871                 },
1872                 { &hf_tlv_chassis_id,
1873                         { "Chassis ID", "cfm.tlv.chassis.id", FT_BYTES,
1874                         BASE_NONE, NULL, 0x0, NULL, HFILL}
1875                 },
1876                 { &hf_tlv_ma_domain_length,
1877                         { "Management Address Domain Length", "cfm.tlv.ma.domain.length", FT_UINT8,
1878                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1879                 },
1880                 { &hf_tlv_ma_domain,
1881                         { "Management Address Domain", "cfm.tlv.ma.domain", FT_BYTES,
1882                         BASE_NONE, NULL, 0x0, NULL, HFILL}
1883                 },
1884                 { &hf_tlv_management_addr_length,
1885                         { "Management Address Length", "cfm.tlv.management.addr.length", FT_UINT8,
1886                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1887                 },
1888                 { &hf_tlv_management_addr,
1889                         { "Management Address", "cfm.tlv.management.addr", FT_BYTES,
1890                         BASE_NONE, NULL, 0x0, NULL, HFILL}
1891                 },
1892
1893                                 /* Port Status TLV */
1894                 { &hf_tlv_port_status_value,
1895                         { "Port Status value", "cfm.tlv.port.status.value", FT_UINT8,
1896                         BASE_DEC, VALS(portstatTLVvalues), 0x0, NULL, HFILL}
1897                 },
1898
1899                                 /* Data TLV */
1900                 { &hf_tlv_data_value,
1901                         { "Data Value", "cfm.tlv.data.value", FT_BYTES,
1902                         BASE_NONE, NULL, 0x0, NULL, HFILL}
1903                 },
1904
1905                                 /* Interface status TLV */
1906                 { &hf_tlv_interface_status_value,
1907                         { "Interface Status value", "cfm.tlv.port.interface.value", FT_UINT8,
1908                         BASE_DEC, VALS(interfacestatTLVvalues), 0x0, NULL, HFILL}
1909                 },
1910
1911                                 /* Reply Ingress TLV */
1912                 { &hf_tlv_reply_ingress_action,
1913                         { "Ingress Action", "cfm.tlv.reply.ingress.action", FT_UINT8,
1914                         BASE_DEC, VALS(replyingressTLVvalues), 0x0, NULL, HFILL}
1915                 },
1916                 { &hf_tlv_reply_ingress_mac_address,
1917                         { "Ingress MAC address", "cfm.tlv.reply.ingress.mac.address", FT_ETHER,
1918                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1919                 },
1920                 { &hf_tlv_reply_ing_egr_portid_length,
1921                         { "Chassis ID Length", "cfm.tlv.chassis.id.length", FT_UINT8,
1922                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1923                 },
1924                 { &hf_tlv_reply_ing_egr_portid_subtype,
1925                         { "Chassis ID Sub-type", "cfm.tlv.chassis.id.subtype", FT_UINT8,
1926                         BASE_DEC, NULL, 0x0, NULL, HFILL}
1927                 },
1928                 { &hf_tlv_reply_ing_egr_portid,
1929                         { "Chassis ID", "cfm.tlv.chassis.id", FT_BYTES,
1930                         BASE_NONE, NULL, 0x0, NULL, HFILL}
1931                 },
1932
1933                                 /* Reply Egress TLV */
1934                 { &hf_tlv_reply_egress_action,
1935                         { "Egress Action", "cfm.tlv.reply.egress.action", FT_UINT8,
1936                         BASE_DEC, VALS(replyegressTLVvalues), 0x0, NULL, HFILL}
1937                 },
1938                 { &hf_tlv_reply_egress_mac_address,
1939                         { "Egress MAC address", "cfm.tlv.reply.egress.mac.address", FT_ETHER,
1940                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1941                 },
1942
1943                                 /* LTM Egress Identifier TLV */
1944                 { &hf_tlv_ltm_egress_id_mac,
1945                         { "Egress Identifier - MAC of LT Initiator/Responder", "cfm.tlv.ltm.egress.id.mac", FT_ETHER,
1946                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1947                 },
1948                 { &hf_tlv_ltm_egress_id_unique_identifier,
1949                         { "Egress Identifier - Unique Identifier", "cfm.tlv.ltm.egress.id.ui", FT_BYTES,
1950                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1951                 },
1952
1953                                 /* LTR Egress Identifier TLV */
1954                 { &hf_tlv_ltr_egress_last_id_mac,
1955                         { "Last Egress Identifier - MAC address", "cfm.tlv.ltr.egress.last.id.mac", FT_ETHER,
1956                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1957                 },
1958                 { &hf_tlv_ltr_egress_last_id_unique_identifier,
1959                         { "Last Egress Identifier - Unique Identifier", "cfm.tlv.ltr.egress.last.id.ui", FT_BYTES,
1960                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1961                 },
1962                 { &hf_tlv_ltr_egress_next_id_mac,
1963                         { "Next Egress Identifier - MAC address", "cfm.tlv.ltr.egress.next.id.mac", FT_ETHER,
1964                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1965                 },
1966                 { &hf_tlv_ltr_egress_next_id_unique_identifier,
1967                         { "Next Egress Identifier - Unique Identifier", "cfm.tlv.ltr.egress.next.id.ui", FT_BYTES,
1968                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1969                 },
1970
1971                                 /* Organization-Specific TLV */
1972                 { &hf_tlv_org_spec_oui,
1973                         { "OUI", "cfm.tlv.org.spec.oui", FT_BYTES,
1974                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1975                 },
1976                 { &hf_tlv_org_spec_subtype,
1977                         { "Sub-Type", "cfm.tlv.org.spec.subtype", FT_BYTES,
1978                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1979                 },
1980                 { &hf_tlv_org_spec_value,
1981                         { "Value", "cfm.tlv.org.spec.value", FT_BYTES,
1982                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1983                 },
1984
1985                                 /* Test TLV */
1986                 { &hf_tlv_tst_test_pattern_type,
1987                         { "Test Pattern Type", "cfm.tlv.tst.test.pattern.type", FT_UINT8,
1988                         BASE_DEC, VALS(testTLVpatterntypes), 0x0, NULL, HFILL}
1989                 },
1990                 { &hf_tlv_tst_test_pattern,
1991                         { "Test Pattern", "cfm.tlv.tst.test.pattern", FT_NONE,
1992                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1993                 },
1994                 { &hf_tlv_tst_CRC32,
1995                         { "CRC-32", "cfm.tlv.tst.crc32", FT_BYTES,
1996                         BASE_NONE, NULL, 0x0, NULL, HFILL       }
1997                 },
1998         };
1999
2000         /* Setup protocol subtree array */
2001         static gint *ett[] = {
2002                 &ett_cfm,
2003                 &ett_cfm_flags,
2004                 &ett_cfm_ccm_maid,
2005                 &ett_cfm_ccm_itu,
2006                 &ett_cfm_pdu,
2007                 &ett_cfm_all_tlvs,
2008                 &ett_cfm_tlv,
2009                 &ett_cfm_raps_flags
2010         };
2011
2012         proto_cfm = proto_register_protocol (
2013                 "CFM EOAM 802.1ag/ITU Protocol", /* name */
2014                 "CFM", /* short name */
2015                 "cfm" /* abbrev */
2016                 );
2017
2018         register_dissector("cfm", dissect_cfm, proto_cfm);
2019
2020         proto_register_field_array(proto_cfm, hf, array_length(hf));
2021         proto_register_subtree_array(ett, array_length(ett));
2022
2023 }
2024
2025 /* Register CFM OEAM protocol handler */
2026 void proto_reg_handoff_cfm(void)
2027 {
2028         dissector_handle_t cfm_handle;
2029         cfm_handle = create_dissector_handle(dissect_cfm, proto_cfm);
2030         dissector_add_uint("ethertype", ETHERTYPE_CFM, cfm_handle);
2031 }
2032