Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cfm.c
blobc86906602955a7fb51f9dddbd00fc003ba795484
1 /* packet-cfm.c
2 * Routines for CFM EOAM dissection
3 * Copyright 2007, Keith Mercer <keith.mercer@alcatel-lucent.com>
4 * Copyright 2011, Peter Nahas <pnahas@mrv.com>
5 * Copyright 2012, Wim Leflere <wim.leflere-ext@oneaccess-net.com>
6 * Copyright 2013, Andreas Urke <arurke@gmail.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
15 /* This code is based on the following documents:
16 * - IEEE 802.1Q-2022 - IEEE Standard for Local and metropolitan area networks — Bridges and Bridged Networks
17 * - ITU-T Rec. G.8013/Y.1731 (08/2015) - OAM functions and mechanisms for Ethernet-based networks
18 * - ITU-T Rec. G.8031/Y.1342 (01/2015) - Ethernet linear protection switching
19 * - ITU-T Rec. G.8032/Y.1344 (03/2020) - Ethernet ring protection switching
20 * - ITU-T Rec. G.8113/Y.1372 (04/2016) - OAM mechanisms for MPLS-TP in packet transport networks
21 * - IEEE 802.1AB-2016 - IEEE Standard for Local and metropolitan area networks — Station and Media Access Control Connectivity Discovery
24 #include "config.h"
26 #include <epan/packet.h>
27 #include <epan/expert.h>
28 #include <epan/etypes.h>
29 #include <epan/afn.h>
30 #include <epan/tfs.h>
31 #include "packet-mpls.h"
34 /* Value declarations for CFM EOAM dissection */
35 /* CFM Common header */
36 #define CFM_COMMON_HEADER_LEN 4
37 #define CFM_LEVEL_VERSION_OFFSET 0
38 #define CFM_LEVEL_MASK 0xE0
39 #define CFM_LEVEL_SHIFT 5
40 #define CFM_VERSION_MASK 0x1F
41 #define CFM_VERSION_SHIFT 0
42 #define CFM_OPCODE_OFFSET 1
43 #define CFM_FLAGS_OFFSET 2
44 #define CFM_1ST_TLV_OFFSET 3
46 /* Defined by IEEE 802.1Q */
47 #define IEEE8021 0x00
48 #define CCM 0x01
49 #define LBR 0x02
50 #define LBM 0x03
51 #define LTR 0x04
52 #define LTM 0X05
53 #define RFM 0x06
54 #define SFM 0x07
56 /* Defined by ITU-T G.8013/Y.1731 */
57 #define GNM 0x20
58 #define AIS 0x21
59 #define LCK 0x23
60 #define TST 0x25
61 #define APS 0x27
62 #define RAPS 0x28
63 #define MCC 0x29
64 #define LMM 0x2B
65 #define LMR 0x2A
66 #define ODM 0x2D
67 #define DMM 0x2F
68 #define DMR 0x2E
69 #define EXM 0x31
70 #define EXR 0x30
71 #define VSM 0x33
72 #define VSR 0x32
73 #define CSF 0x34
74 #define OSL 0x35
75 #define SLM 0x37
76 #define SLR 0x36
78 /* Defined by IEEE 802.1Q */
79 #define END_TLV 0x00
80 #define SENDER_ID_TLV 0x01
81 #define PORT_STAT_TLV 0x02
82 #define DATA_TLV 0x03
83 #define INTERF_STAT_TLV 0x04
84 #define REPLY_ING_TLV 0x05
85 #define REPLY_EGR_TLV 0x06
86 #define LTM_EGR_ID_TLV 0x07
87 #define LTR_EGR_ID_TLV 0x08
88 #define PPB_TE_MIP_TLV 0x09
89 #define DATA_PART1_TLV 0x0A
90 #define DATA_PART2_TLV 0x0B
91 #define TRUNC_DATA_TLV 0x0C
92 // XXX - Does this TLV even exist?
93 #define GNM_TLV 0x0D
94 #define ORG_SPEC_TLV 0x1F
95 /* Defined by ITU-T Y.1731 */
96 #define TEST_TLV 0x20
97 /* Defined by ITU-T Y.1372.1 */
98 #define TGT_MEP_MIP_ID_TLV 0x21
99 #define RPL_MEP_MIP_ID_TLV 0x22
100 #define REQ_MEP_ID_TLV 0x23
101 /* Defined by ITU-T Y.1731 */
102 #define TEST_ID_TLV 0x24
104 /* Sub-OpCode for GNM */
105 #define BNM 0x01
107 /* MAID values */
108 #define MD_NAME_FMT_RESVD 0
109 #define MD_NAME_FMT_NONE 1
110 #define MD_NAME_FMT_DOMAIN 2
111 #define MD_NAME_FMT_MAC_ID 3
112 #define MD_NAME_FMT_STRING 4
114 #define MA_NAME_FMT_RESVD 0
115 #define MA_NAME_FMT_PVID 1
116 #define MA_NAME_FMT_STRING 2
117 #define MA_NAME_FMT_ID 3
118 #define MA_NAME_FMT_VPN_ID 4
119 #define MA_NAME_FMT_ICC 32
120 #define MA_NAME_FMT_ICC_CC 33
122 /* R-APS values */
123 #define RAPS_REQ_ST_MASK 0xF0
124 #define RAPS_REQ_ST_SHIFT 4
125 #define RAPS_SUB_CODE_MASK 0x0F
126 #define RAPS_SUB_CODE_SHIFT 0
128 #define RAPS_REQ_ST_NO_REQ 0
129 #define RAPS_REQ_ST_MAN_SW 7
130 #define RAPS_REQ_ST_SIG_FAIL 11
131 #define RAPS_REQ_ST_FCED_SW 13
132 #define RAPS_REQ_ST_EVENT 14
135 static const value_string opcode_type_name_vals[] = {
136 { IEEE8021, "Reserved for IEEE 802.1" },
137 { CCM, "Continuity Check Message (CCM)" },
138 { LBR, "Loopback Reply (LBR)" },
139 { LBM, "Loopback Message (LBM)" },
140 { LTR, "Linktrace Reply (LTR)" },
141 { LTM, "Linktrace Message (LTM)" },
142 { RFM, "Reflected Frame Message (RFM)" },
143 { SFM, "Send Frame Message (SFM)" },
144 { GNM, "Generic Notification Message (GNM)" },
145 { AIS, "Alarm Indication Signal (AIS)" },
146 { LCK, "Lock Signal (LCK)" },
147 { TST, "Test Signal (TST)" },
148 { APS, "Automatic Protection Switching (APS)" },
149 { RAPS, "Ring-Automatic Protection Switching (R-APS)" },
150 { MCC, "Maintenance Communication Channel (MCC)" },
151 { LMM, "Loss Measurement Message (LMM)" },
152 { LMR, "Loss Measurement Reply (LMR)" },
153 { ODM, "One Way Delay Measurement (1DM)" },
154 { DMM, "Delay Measurement Message (DMM)" },
155 { DMR, "Delay Measurement Reply (DMR)" },
156 { EXM, "Experimental OAM Message (EXM)" },
157 { EXR, "Experimental OAM Reply (EXR)" },
158 { VSM, "Vendor Specific Message (VSM)" },
159 { VSR, "Vendor Specific Reply (VSR)" },
160 { CSF, "Client Signal Fail (CSF)" },
161 { OSL, "One Way Synthetic Loss Measurement (1SL)" },
162 { SLM, "Synthetic Loss Message (SLM)" },
163 { SLR, "Synthetic Loss Reply (SLR)" },
164 { 0, NULL }
167 static const value_string tlv_type_field_vals[] = {
168 { END_TLV, "End TLV" },
169 { SENDER_ID_TLV, "Sender ID TLV" },
170 { PORT_STAT_TLV, "Port Status TLV" },
171 { DATA_TLV, "Data TLV" },
172 { INTERF_STAT_TLV, "Interface Status TLV" },
173 { REPLY_ING_TLV, "Reply Ingress TLV" },
174 { REPLY_EGR_TLV, "Reply Egress TLV" },
175 { LTM_EGR_ID_TLV, "LTM Egress Identifier TLV" },
176 { LTR_EGR_ID_TLV, "LTR Egress Identifier TLV" },
177 { PPB_TE_MIP_TLV, "PBB-TE MIP TLV" },
178 { DATA_PART1_TLV, "Data Part 1 TLV" },
179 { DATA_PART2_TLV, "Data Part 2 TLV" },
180 { TRUNC_DATA_TLV, "Truncated Data TLV" },
181 { GNM_TLV, "Generic Notification Message TLV" },
182 { ORG_SPEC_TLV, "Organizational-Specific TLV" },
183 { TEST_TLV, "Test TLV" },
184 { TGT_MEP_MIP_ID_TLV, "Target MEP/MIP ID TLV" },
185 { RPL_MEP_MIP_ID_TLV, "Replying MEP/MIP ID TLV" },
186 { REQ_MEP_ID_TLV, "Requesting MEP ID TLV" },
187 { TEST_ID_TLV, "Test ID TLV" },
188 { 0, NULL }
191 static const value_string md_name_format_type_vals[] = {
192 { MD_NAME_FMT_RESVD, "Reserved for IEEE 802.1" },
193 { MD_NAME_FMT_NONE, "No Maintenance Domain Name present" },
194 { MD_NAME_FMT_DOMAIN, "Domain Name-based string" },
195 { MD_NAME_FMT_MAC_ID, "MAC address + 2-octet integer" },
196 { MD_NAME_FMT_STRING, "Character String" },
197 { 0, NULL }
200 static const value_string ma_name_format_type_vals[] = {
201 // IEEE 802.1Q
202 { MA_NAME_FMT_RESVD, "Reserved for IEEE 802.1" },
203 { MA_NAME_FMT_PVID, "Primary VID" },
204 { MA_NAME_FMT_STRING, "Character String" },
205 { MA_NAME_FMT_ID, "2-octet integer" },
206 { MA_NAME_FMT_VPN_ID, "RFC 2685 VPN ID" },
207 // Y.1731 Annex A
208 { MA_NAME_FMT_ICC, "ICC-based Format" },
209 { MA_NAME_FMT_ICC_CC, "ICC and CC based Format" },
210 { 0, NULL }
213 static const value_string ccm_interval_field_encoding_vals[] = {
214 { 0, "invalid" },
215 { 1, "Trans Int 3.33ms, max Lifetime 11.66ms, min Lifetime 10.83ms" },
216 { 2, "Trans Int 10ms, max Lifetime 35ms, min Lifetime 32.5ms" },
217 { 3, "Trans Int 100ms, max Lifetime 350ms, min Lifetime 325ms" },
218 { 4, "Trans Int 1s, max Lifetime 3.5s, min Lifetime 3.25s" },
219 { 5, "Trans Int 10s, max Lifetime 35s, min Lifetime 32.5s" },
220 { 6, "Trans Int 1min, max Lifetime 3.5min, min Lifetime 3.25min" },
221 { 7, "Trans Int 10min, max Lifetime 35min, min Lifetime 32.5min" },
222 { 0, NULL }
225 static const value_string relay_action_type_vals[] = {
226 { 1, "RlyHit" },
227 { 2, "RlyFDB" },
228 { 3, "RlyMPDB" },
229 { 0, NULL }
232 static const value_string ais_lck_period_type_vals[] = {
233 { 0, "Invalid Value for AIS/LCK PDU's" },
234 { 1, "Invalid Value for AIS/LCK PDU's" },
235 { 2, "Invalid Value for AIS/LCK PDU's" },
236 { 3, "Invalid Value for AIS/LCK PDU's" },
237 { 4, "1 frame per second" },
238 { 5, "Invalid Value for AIS/LCK PDU's" },
239 { 6, "1 frame per minute" },
240 { 7, "Invalid Value for AIS/LCK PDU's" },
241 { 0, NULL }
244 static const value_string sender_id_tlv_chassis_id_subtype_vals[] = {
245 { 1, "Chassis component" },
246 { 2, "Interface alias" },
247 { 3, "Port component" },
248 { 4, "MAC address" },
249 { 5, "Network address" },
250 { 6, "Interface name" },
251 { 7, "Locally assigned" },
252 { 0, NULL }
255 static const value_string port_stat_tlv_vals[] = {
256 { 1, "psBlocked" },
257 { 2, "psUp" },
258 { 0, NULL }
261 static const value_string interface_stat_tlv_vals[] = {
262 { 1, "isUp" },
263 { 2, "isDown" },
264 { 3, "isTesting" },
265 { 4, "isUnknown" },
266 { 5, "isDormant" },
267 { 6, "isNotPresent" },
268 { 7, "isLowerLayerDown" },
269 { 0, NULL }
272 static const value_string reply_ingress_tlv_vals[] = {
273 { 1, "IngOK" },
274 { 2, "IngDown" },
275 { 3, "IngBlocked" },
276 { 4, "IngVID" },
277 { 0, NULL }
280 static const value_string reply_egress_tlv_vals[] = {
281 { 1, "EgrOK" },
282 { 2, "EgrDown" },
283 { 3, "EgrBlocked" },
284 { 4, "EgrVID" },
285 { 0, NULL }
288 static const value_string aps_request_state_vals[] = {
289 { 0, "No request" },
290 { 1, "Do not revert" },
291 { 2, "Reverse request" },
292 { 3, "Unknown" },
293 { 4, "Exercise" },
294 { 5, "Wait to restore" },
295 { 6, "Depreciated" },
296 { 7, "Manual switch" },
297 { 8, "Unknown" },
298 { 9, "Signal degrade" },
299 { 10, "Unknown" },
300 { 11, "Signal fail for working" },
301 { 12, "Unknown" },
302 { 13, "Forced switch" },
303 { 14, "Signal fail on protection" },
304 { 15, "Lockout of protection" },
305 { 0, NULL }
308 static const true_false_string tfs_aps_protection_type_A = {
309 "APS channel",
310 "No APS channel"
313 static const true_false_string tfs_aps_protection_type_B = {
314 "1:1 (no permanent bridge)",
315 "1+1 (permanent bridge)"
318 static const true_false_string tfs_aps_protection_type_D = {
319 "Bidirectional switching",
320 "Unidirectional switching"
323 static const true_false_string tfs_aps_protection_type_R = {
324 "Revertive operation",
325 "Non-revertive operation"
328 static const value_string aps_requested_signal_values[] = {
329 { 0, "Null" },
330 { 1, "Normal traffic" },
331 { 0, NULL }
334 static const value_string aps_bridged_signal_values[] = {
335 { 0, "Null" },
336 { 1, "Normal traffic" },
337 { 0, NULL }
340 static const value_string aps_bridge_type_values[] = {
341 { 0, "Selector" },
342 { 1, "Broadcast" },
343 { 0, NULL }
346 static const value_string raps_request_state_values[] = {
347 { RAPS_REQ_ST_NO_REQ, "No Request" },
348 { RAPS_REQ_ST_MAN_SW, "Manual Switch" },
349 { RAPS_REQ_ST_SIG_FAIL, "Signal Fail" },
350 { RAPS_REQ_ST_FCED_SW, "Forced Switch" },
351 { RAPS_REQ_ST_EVENT, "Event" },
352 { 0, NULL }
355 static const value_string rasp_event_subcode_vals[] = {
356 { 0, "Flush Request" },
357 { 0, NULL }
360 static const true_false_string tfs_rasp_rpl_blocked = {
361 "Blocked",
362 "Not Blocked"
365 static const true_false_string tfs_rasp_dnf = {
366 "Do Not Flush DB",
367 "May Flush DB"
370 static const true_false_string tfs_rasp_bpr = {
371 "Ring link 1",
372 "Ring link 0"
375 static const value_string gnm_sub_opcode_type_name_vals[] = {
376 { BNM, "Bandwidth Notification Message" },
377 { 0, NULL }
380 static const value_string cfm_bnm_flags_period_vals[] = {
381 { 0, "Invalid" },
382 { 1, "For further study" },
383 { 2, "For further study" },
384 { 3, "For further study" },
385 { 4, "1s" },
386 { 5, "10s" },
387 { 6, "1 min" },
388 { 7, "Invalid" },
389 { 0, NULL }
392 static const value_string cfm_csf_flags_type_vals[] = {
393 { 0, "LOS" },
394 { 1, "FDI/AIS" },
395 { 2, "RDI" },
396 { 3, "DCI" },
397 { 0, NULL }
400 static const value_string cfm_csf_flags_period_vals[] = {
401 { 0, "Invalid" },
402 { 1, "For further study" },
403 { 2, "For further study" },
404 { 3, "For further study" },
405 { 4, "1s" },
406 { 5, "For further study" },
407 { 6, "1 min" },
408 { 7, "For further study" },
409 { 0, NULL }
412 static const true_false_string tfs_lmm_lmr_type = {
413 "Proactive",
414 "On-demand"
417 static const true_false_string tfs_odm_dmm_dmr_type = {
418 "Proactive",
419 "On-demand"
422 static const value_string test_tlv_pattern_type_vals[] = {
423 { 0, "Null signal without CRC-32" },
424 { 1, "Null signal with CRC-32" },
425 { 2, "PRBS (2.e-31 -1), without CRC-32" },
426 { 3, "PRBS (2.e-31 -1), with CRC-32" },
427 { 0, NULL }
430 static const value_string mep_mip_id_tlv_subtype_vals[] = {
431 { 0x00, "Discovery ingress/node MEP/MIP" },
432 { 0x01, "Discovery egress MEP/MIP" },
433 { 0x02, "MEP ID" },
434 { 0x03, "MIP ID" },
435 { 0, NULL }
438 static const value_string req_mep_id_tlv_lb_vals[] = {
439 { 0x00, "LBM PDU" },
440 { 0x01, "LBR PDU" },
441 { 0, NULL }
445 void proto_register_cfm(void);
446 void proto_reg_handoff_cfm(void);
448 static int proto_cfm;
450 static int hf_cfm_md_level;
451 static int hf_cfm_version;
452 static int hf_cfm_opcode;
453 static int hf_cfm_flags;
454 static int hf_cfm_flags_Reserved;
455 static int hf_cfm_first_tlv_offset;
457 static int hf_cfm_mep_id;
458 static int hf_cfm_maid;
459 static int hf_cfm_maid_md_name_format;
460 static int hf_cfm_maid_md_name_length;
461 static int hf_cfm_maid_md_name_string;
462 static int hf_cfm_maid_md_name_hex;
463 static int hf_cfm_maid_md_name_mac;
464 static int hf_cfm_maid_md_name_mac_id;
465 static int hf_cfm_maid_ma_name_format;
466 static int hf_cfm_maid_ma_name_length;
467 static int hf_cfm_maid_ma_name_pvid;
468 static int hf_cfm_maid_ma_name_string;
469 static int hf_cfm_maid_ma_name_id;
470 static int hf_cfm_maid_ma_name_vpnid_oui;
471 static int hf_cfm_maid_ma_name_vpnid_index;
472 static int hf_cfm_maid_ma_name_icc_umc;
473 static int hf_cfm_maid_ma_name_cc;
474 static int hf_cfm_maid_ma_name_hex;
475 static int hf_cfm_maid_padding;
477 static int hf_cfm_ccm_pdu;
478 static int hf_cfm_ccm_flags_RDI;
479 static int hf_cfm_ccm_flags_Traffic;
480 static int hf_cfm_ccm_flags_Reserved;
481 static int hf_cfm_ccm_flags_Interval;
482 static int hf_cfm_ccm_seq_number;
483 static int hf_cfm_ccm_itu_t_y1731;
484 static int hf_cfm_ccm_itu_TxFCf;
485 static int hf_cfm_ccm_itu_RxFCb;
486 static int hf_cfm_ccm_itu_TxFCb;
487 static int hf_cfm_ccm_itu_reserved;
489 static int hf_cfm_lbm_pdu;
490 static int hf_cfm_lbm_lbr_transaction_id;
492 static int hf_cfm_lbr_pdu;
494 static int hf_cfm_ltm_pdu;
495 static int hf_cfm_ltm_flags_UseFDBonly;
496 static int hf_cfm_ltm_flags_Reserved;
497 static int hf_cfm_ltm_ltr_transaction_id;
498 static int hf_cfm_ltm_ltr_ttl;
499 static int hf_cfm_ltm_orig_addr;
500 static int hf_cfm_ltm_targ_addr;
502 static int hf_cfm_ltr_pdu;
503 static int hf_cfm_ltr_flags_UseFDBonly;
504 static int hf_cfm_ltr_flags_FwdYes;
505 static int hf_cfm_ltr_flags_TerminalMEP;
506 static int hf_cfm_ltr_flags_Reserved;
507 static int hf_cfm_ltr_relay_action;
509 static int hf_cfm_rfm_pdu;
510 static int hf_cfm_rfm_transaction_id;
512 static int hf_cfm_sfm_pdu;
513 static int hf_cfm_sfm_transaction_id;
515 static int hf_cfm_gnm_pdu;
516 static int hf_cfm_gnm_unknown_flags;
517 static int hf_cfm_gnm_subopcode;
519 static int hf_cfm_bnm_flags_Reserved;
520 static int hf_cfm_bnm_flags_Period;
521 static int hf_cfm_bnm_pdu;
522 static int hf_cfm_bnm_nominal_bw;
523 static int hf_cfm_bnm_current_bw;
524 static int hf_cfm_bnm_port_id;
526 static int hf_cfm_ais_pdu;
527 static int hf_cfm_ais_flags_Reserved;
528 static int hf_cfm_ais_flags_Period;
530 static int hf_cfm_lck_pdu;
531 static int hf_cfm_lck_flags_Reserved;
532 static int hf_cfm_lck_flags_Period;
534 static int hf_cfm_tst_pdu;
535 static int hf_cfm_tst_sequence_num;
537 static int hf_cfm_aps_pdu;
538 static int hf_cfm_aps_req_st;
539 static int hf_cfm_aps_protection_type_A;
540 static int hf_cfm_aps_protection_type_B;
541 static int hf_cfm_aps_protection_type_D;
542 static int hf_cfm_aps_protection_type_R;
543 static int hf_cfm_aps_requested_signal;
544 static int hf_cfm_aps_bridged_signal;
545 static int hf_cfm_aps_bridge_type;
547 static int hf_cfm_raps_pdu;
548 static int hf_cfm_raps_req_st;
549 static int hf_cfm_raps_event_subcode;
550 static int hf_cfm_raps_subcode_reserved;
551 static int hf_cfm_raps_status;
552 static int hf_cfm_raps_status_rb;
553 static int hf_cfm_raps_status_dnf;
554 static int hf_cfm_raps_status_bpr;
555 static int hf_cfm_raps_status_reserved_v1;
556 static int hf_cfm_raps_status_reserved_v2;
557 static int hf_cfm_raps_node_id;
558 static int hf_cfm_raps_reserved;
560 static int hf_cfm_mcc_pdu;
561 static int hf_cfm_mcc_oui;
562 static int hf_cfm_mcc_subopcode;
563 static int hf_cfm_mcc_data;
565 static int hf_cfm_lmm_pdu;
566 static int hf_cfm_lmm_lmr_flags_Reserved;
567 static int hf_cfm_lmm_lmr_flags_Type;
568 static int hf_cfm_lmm_lmr_TxFCf;
569 static int hf_cfm_lmm_lmr_RxFCf;
570 static int hf_cfm_lmm_lmr_TxFCb;
572 static int hf_cfm_lmr_pdu;
574 static int hf_cfm_odm_pdu;
575 static int hf_cfm_odm_dmm_dmr_flags_Reserved;
576 static int hf_cfm_odm_dmm_dmr_flags_Type;
577 static int hf_cfm_odm_dmm_dmr_TxTimestampf;
578 static int hf_cfm_odm_dmm_dmr_RxTimestampf;
580 static int hf_cfm_dmm_pdu;
581 static int hf_cfm_dmm_dmr_TxTimestampb;
582 static int hf_cfm_dmm_dmr_RxTimestampb;
584 static int hf_cfm_dmr_pdu;
586 static int hf_cfm_exm_pdu;
587 static int hf_cfm_exm_oui;
588 static int hf_cfm_exm_subopcode;
589 static int hf_cfm_exm_data;
591 static int hf_cfm_exr_pdu;
592 static int hf_cfm_exr_oui;
593 static int hf_cfm_exr_subopcode;
594 static int hf_cfm_exr_data;
596 static int hf_cfm_vsm_pdu;
597 static int hf_cfm_vsm_oui;
598 static int hf_cfm_vsm_subopcode;
599 static int hf_cfm_vsm_data;
601 static int hf_cfm_vsr_pdu;
602 static int hf_cfm_vsr_oui;
603 static int hf_cfm_vsr_subopcode;
604 static int hf_cfm_vsr_data;
606 static int hf_cfm_csf_pdu;
607 static int hf_cfm_csf_flags_Reserved;
608 static int hf_cfm_csf_flags_Type;
609 static int hf_cfm_csf_flags_Period;
611 static int hf_cfm_osl_pdu;
612 static int hf_cfm_osl_src_mep;
613 static int hf_cfm_osl_reserved;
614 static int hf_cfm_osl_testid;
615 static int hf_cfm_osl_txfcf;
617 static int hf_cfm_slm_pdu;
618 static int hf_cfm_slm_slr_src_mep;
619 static int hf_cfm_slm_reserved;
620 static int hf_cfm_slm_slr_testid;
621 static int hf_cfm_slm_slr_txfcf;
623 static int hf_cfm_slr_pdu;
624 static int hf_cfm_slr_rsp_mep;
625 static int hf_cfm_slr_txfcb;
627 static int hf_cfm_unknown_pdu;
628 static int hf_cfm_unknown_flags;
629 static int hf_cfm_unknown_data;
631 static int hf_cfm_all_tlvs;
632 static int hf_cfm_tlv_type;
633 static int hf_cfm_tlv_length;
635 static int hf_tlv_chassis_id_length;
636 static int hf_tlv_chassis_id_subtype;
637 static int hf_tlv_chassis_id_chassis_component;
638 static int hf_tlv_chassis_id_interface_alias;
639 static int hf_tlv_chassis_id_port_component;
640 static int hf_tlv_chassis_id_mac_address;
641 static int hf_tlv_chassis_id_network_address_family;
642 static int hf_tlv_chassis_id_network_address_ipv4;
643 static int hf_tlv_chassis_id_network_address_ipv6;
644 static int hf_tlv_chassis_id_network_address_unknown;
645 static int hf_tlv_chassis_id_interface_name;
646 static int hf_tlv_chassis_id_locally_assigned;
647 static int hf_tlv_chassis_id_unknown;
648 static int hf_tlv_ma_domain_length;
649 static int hf_tlv_ma_domain;
650 static int hf_tlv_management_addr_length;
651 static int hf_tlv_management_addr_ipv4;
652 static int hf_tlv_management_addr_ipv6;
653 static int hf_tlv_management_addr_eth;
654 static int hf_tlv_management_addr_unknown;
655 static int hf_tlv_port_status_value;
656 static int hf_tlv_data_value;
657 static int hf_tlv_interface_status_value;
659 static int hf_tlv_reply_ingress_action;
660 static int hf_tlv_reply_ingress_mac_address;
661 static int hf_tlv_reply_ing_egr_portid_length;
662 static int hf_tlv_reply_ing_egr_portid_subtype;
663 static int hf_tlv_reply_ing_egr_portid_interface_alias;
664 static int hf_tlv_reply_ing_egr_portid_port_component;
665 static int hf_tlv_reply_ing_egr_portid_mac_address;
666 static int hf_tlv_reply_ing_egr_portid_network_address_family;
667 static int hf_tlv_reply_ing_egr_portid_network_address_ipv4;
668 static int hf_tlv_reply_ing_egr_portid_network_address_ipv6;
669 static int hf_tlv_reply_ing_egr_portid_network_address_unknown;
670 static int hf_tlv_reply_ing_egr_portid_interface_name;
671 static int hf_tlv_reply_ing_egr_portid_agent_circuit_id;
672 static int hf_tlv_reply_ing_egr_portid_locally_assigned;
673 static int hf_tlv_reply_ing_egr_portid_unknown;
674 static int hf_tlv_reply_egress_action;
675 static int hf_tlv_reply_egress_mac_address;
677 static int hf_tlv_ltr_egress_last_id_mac;
678 static int hf_tlv_ltr_egress_last_id_unique_identifier;
679 static int hf_tlv_ltr_egress_next_id_mac;
680 static int hf_tlv_ltr_egress_next_id_unique_identifier;
681 static int hf_tlv_ltm_egress_id_mac;
682 static int hf_tlv_ltm_egress_id_unique_identifier;
684 static int hf_tlv_pbb_te_mip_mac_address;
685 static int hf_tlv_pbb_te_reverse_vid;
686 static int hf_tlv_pbb_te_reverse_mac;
688 static int hf_tlv_org_spec_oui;
689 static int hf_tlv_org_spec_subtype;
690 static int hf_tlv_org_spec_value;
691 static int hf_tlv_tst_test_pattern_type;
692 static int hf_tlv_tst_test_pattern;
693 static int hf_tlv_tst_CRC32;
695 static int hf_tlv_tgt_rpl_mep_mip_id_subtype;
696 static int hf_tlv_tgt_rpl_padding;
697 static int hf_tlv_tgt_rpl_mep_id;
698 static int hf_tlv_tgt_rpl_mip_id_icc;
699 static int hf_tlv_tgt_rpl_mip_id_node_id;
700 static int hf_tlv_tgt_rpl_mip_id_if_num;
701 static int hf_tlv_tgt_rpl_mip_id_cc;
703 static int hf_tlv_req_mep_id_lb;
704 static int hf_tlv_req_mep_id_reserved;
706 static int hf_tlv_tst_id_test_id;
708 static int hf_tlv_unknown_data;
710 static int ett_cfm;
711 static int ett_cfm_pdu;
712 static int ett_cfm_flags;
713 static int ett_cfm_maid;
714 static int ett_cfm_ccm_itu;
715 static int ett_cfm_all_tlvs;
716 static int ett_cfm_tlv;
717 static int ett_cfm_raps_status;
719 static expert_field ei_tlv_tst_id_length;
720 static expert_field ei_tlv_management_addr_length;
722 static dissector_handle_t cfm_handle;
724 /* CFM EOAM sub-protocol dissectors */
726 static int dissect_mep_maid(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
728 proto_item *ti;
729 proto_tree *cfm_maid_tree;
731 int maid_offset;
733 uint32_t maid_md_name_format;
734 uint32_t maid_ma_name_format;
735 uint32_t maid_ma_name_length;
738 proto_tree_add_item(tree, hf_cfm_mep_id, tvb, offset, 2, ENC_BIG_ENDIAN);
739 offset += 2;
741 ti = proto_tree_add_item(tree, hf_cfm_maid, tvb, offset, 48, ENC_NA);
742 cfm_maid_tree = proto_item_add_subtree(ti, ett_cfm_maid);
743 maid_offset = offset;
744 proto_tree_add_item_ret_uint(cfm_maid_tree, hf_cfm_maid_md_name_format, tvb, maid_offset, 1, ENC_NA, &maid_md_name_format);
745 maid_offset += 1;
747 if (maid_md_name_format != MD_NAME_FMT_NONE) { // NOTE: true for IEEE 802.1Q CCM only
748 uint8_t maid_md_name_length;
749 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_length,
750 tvb, maid_offset, 1, ENC_NA);
751 maid_md_name_length = tvb_get_uint8(tvb, maid_offset);
752 maid_offset += 1;
753 if (maid_md_name_length) { // NOTE: Between 1 and 43
754 switch (maid_md_name_format) {
755 case MD_NAME_FMT_MAC_ID:
756 if (maid_md_name_length != 8) {
757 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_hex,
758 tvb, maid_offset, maid_md_name_length, ENC_NA);
759 } else {
760 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_mac,
761 tvb, maid_offset, 6, ENC_NA);
762 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_mac_id,
763 tvb, maid_offset + 6, 2, ENC_NA);
765 break;
766 case MD_NAME_FMT_DOMAIN:
767 case MD_NAME_FMT_STRING:
768 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_string,
769 tvb, maid_offset, maid_md_name_length, ENC_ASCII|ENC_NA);
770 break;
771 default:
772 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_md_name_hex,
773 tvb, maid_offset, maid_md_name_length, ENC_NA);
774 break;
776 maid_offset += maid_md_name_length;
779 proto_tree_add_item_ret_uint(cfm_maid_tree, hf_cfm_maid_ma_name_format, tvb, maid_offset, 1, ENC_NA, &maid_ma_name_format);
780 maid_offset += 1;
781 proto_tree_add_item_ret_uint(cfm_maid_tree, hf_cfm_maid_ma_name_length, tvb, maid_offset, 1, ENC_NA, &maid_ma_name_length);
782 maid_offset += 1;
784 switch (maid_ma_name_format) {
785 case MA_NAME_FMT_RESVD:
786 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
787 tvb, maid_offset, maid_ma_name_length, ENC_NA);
788 break;
789 case MA_NAME_FMT_PVID:
790 if (maid_ma_name_length != 2) {
791 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
792 tvb, maid_offset, maid_ma_name_length, ENC_NA);
793 } else {
794 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_pvid,
795 tvb, maid_offset, 2, ENC_NA);
797 break;
798 case MA_NAME_FMT_STRING:
799 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_string,
800 tvb, maid_offset, maid_ma_name_length, ENC_ASCII|ENC_NA);
801 break;
802 case MA_NAME_FMT_ID:
803 if (maid_ma_name_length != 2) {
804 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
805 tvb, maid_offset, maid_ma_name_length, ENC_NA);
806 } else {
807 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_id,
808 tvb, maid_offset, 2, ENC_NA);
810 break;
811 case MA_NAME_FMT_VPN_ID:
812 if (maid_ma_name_length != 7) {
813 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
814 tvb, maid_offset, maid_ma_name_length, ENC_NA);
815 } else {
816 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_vpnid_oui,
817 tvb, maid_offset, 3, ENC_NA);
818 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_vpnid_index,
819 tvb, maid_offset + 3, 4, ENC_NA);
821 break;
822 case MA_NAME_FMT_ICC:
823 if (maid_ma_name_length != 13) {
824 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
825 tvb, maid_offset, maid_ma_name_length, ENC_NA);
826 } else {
827 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_icc_umc,
828 tvb, maid_offset, 13, ENC_ASCII|ENC_NA);
830 break;
831 case MA_NAME_FMT_ICC_CC:
832 if (maid_ma_name_length != 15) {
833 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
834 tvb, maid_offset, maid_ma_name_length, ENC_NA);
835 } else {
836 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_cc,
837 tvb, maid_offset, 2, ENC_ASCII|ENC_NA);
838 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_icc_umc,
839 tvb, maid_offset + 2, 13, ENC_ASCII|ENC_NA);
841 break;
842 default:
843 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_ma_name_hex,
844 tvb, maid_offset, maid_ma_name_length, ENC_NA);
845 break;
848 maid_offset += maid_ma_name_length;
849 offset += 48;
850 if (offset > maid_offset) {
851 int padding_length;
852 padding_length = offset - maid_offset;
853 proto_tree_add_item(cfm_maid_tree, hf_cfm_maid_padding,
854 tvb, maid_offset, padding_length, ENC_NA);
857 return offset;
860 static int dissect_cfm_ccm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
862 proto_item *ti;
863 proto_item *fi;
864 proto_tree *cfm_pdu_tree;
865 proto_tree *cfm_flag_tree;
866 uint32_t first_tlv_offset;
867 int start_offset = offset;
868 int length_remaining;
870 proto_item *wi;
871 proto_tree *cfm_ccm_itu_tree;
873 ti = proto_tree_add_item(tree, hf_cfm_ccm_pdu, tvb, offset, -1, ENC_NA);
874 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
876 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
877 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
878 proto_tree_add_item(cfm_flag_tree, hf_cfm_ccm_flags_RDI, tvb, offset, 1, ENC_NA);
879 proto_tree_add_item(cfm_flag_tree, hf_cfm_ccm_flags_Traffic, tvb, offset, 1, ENC_NA);
880 proto_tree_add_item(cfm_flag_tree, hf_cfm_ccm_flags_Reserved, tvb, offset, 1, ENC_NA);
881 proto_tree_add_item(cfm_flag_tree, hf_cfm_ccm_flags_Interval, tvb, offset, 1, ENC_NA);
882 offset += 1;
884 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
885 offset += 1;
887 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_seq_number, tvb, offset, 4, ENC_BIG_ENDIAN); // NOTE: Zero in Y.1731
888 offset += 4;
890 /* dissect CCM MEP ID + MAID */
891 offset = dissect_mep_maid(tvb, pinfo, cfm_pdu_tree, offset);
893 /* Dissect 16 octets reserved for Y.1731, samples of the wrap-around frame counters */
894 wi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_ccm_itu_t_y1731, tvb, offset, 16, ENC_NA);
895 cfm_ccm_itu_tree = proto_item_add_subtree(wi, ett_cfm_ccm_itu);
896 proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_ccm_itu_TxFCf, tvb, offset, 4, ENC_NA);
897 offset += 4;
898 proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_ccm_itu_RxFCb, tvb, offset, 4, ENC_NA);
899 offset += 4;
900 proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_ccm_itu_TxFCb, tvb, offset, 4, ENC_NA);
901 offset += 4;
902 proto_tree_add_item(cfm_ccm_itu_tree, hf_cfm_ccm_itu_reserved, tvb, offset, 4, ENC_NA);
903 offset += 4;
905 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
907 if (length_remaining > 0) {
908 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
909 offset += length_remaining;
912 proto_item_set_len(ti, offset - start_offset);
913 return offset;
916 static int dissect_cfm_lbm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
918 proto_item *ti;
919 proto_item *fi;
920 proto_tree *cfm_pdu_tree;
921 proto_tree *cfm_flag_tree;
922 uint32_t first_tlv_offset;
923 int start_offset = offset;
924 int length_remaining;
926 ti = proto_tree_add_item(tree, hf_cfm_lbm_pdu, tvb, offset, -1, ENC_NA);
927 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
929 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
930 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
931 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
932 offset += 1;
934 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
935 offset += 1;
937 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lbm_lbr_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
938 offset += 4;
940 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
942 if (length_remaining > 0) {
943 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
944 offset += length_remaining;
947 proto_item_set_len(ti, offset - start_offset);
948 return offset;
951 static int dissect_cfm_lbr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
953 proto_item *ti;
954 proto_item *fi;
955 proto_tree *cfm_pdu_tree;
956 proto_tree *cfm_flag_tree;
957 uint32_t first_tlv_offset;
958 int start_offset = offset;
959 int length_remaining;
961 ti = proto_tree_add_item(tree, hf_cfm_lbr_pdu, tvb, offset, -1, ENC_NA);
962 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
964 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
965 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
966 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
967 offset += 1;
969 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
970 offset += 1;
972 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lbm_lbr_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
973 offset += 4;
975 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
977 if (length_remaining > 0) {
978 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
979 offset += length_remaining;
982 proto_item_set_len(ti, offset - start_offset);
983 return offset;
986 static int dissect_cfm_ltm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
988 proto_item *ti;
989 proto_item *fi;
990 proto_tree *cfm_pdu_tree;
991 proto_tree *cfm_flag_tree;
992 uint32_t first_tlv_offset;
993 int start_offset = offset;
994 int length_remaining;
996 ti = proto_tree_add_item(tree, hf_cfm_ltm_pdu, tvb, offset, -1, ENC_NA);
997 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
999 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1000 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1001 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltm_flags_UseFDBonly, tvb, offset, 1, ENC_NA);
1002 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltm_flags_Reserved, tvb, offset, 1, ENC_NA);
1003 offset += 1;
1005 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1006 offset += 1;
1008 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_ltr_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1009 offset += 4;
1010 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_ltr_ttl, tvb, offset, 1, ENC_NA);
1011 offset += 1;
1012 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_orig_addr, tvb, offset, 6, ENC_NA);
1013 offset += 6;
1014 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_targ_addr, tvb, offset, 6, ENC_NA);
1015 offset += 6;
1017 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1019 if (length_remaining > 0) {
1020 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1021 offset += length_remaining;
1024 proto_item_set_len(ti, offset - start_offset);
1025 return offset;
1028 static int dissect_cfm_ltr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1030 proto_item *ti;
1031 proto_item *fi;
1032 proto_tree *cfm_pdu_tree;
1033 proto_tree *cfm_flag_tree;
1034 uint32_t first_tlv_offset;
1035 int start_offset = offset;
1036 int length_remaining;
1038 ti = proto_tree_add_item(tree, hf_cfm_ltr_pdu, tvb, offset, -1, ENC_NA);
1039 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1041 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1042 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1043 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltr_flags_UseFDBonly, tvb, offset, 1, ENC_NA);
1044 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltr_flags_FwdYes, tvb, offset, 1, ENC_NA);
1045 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltr_flags_TerminalMEP, tvb, offset, 1, ENC_NA);
1046 proto_tree_add_item(cfm_flag_tree, hf_cfm_ltr_flags_Reserved, tvb, offset, 1, ENC_NA);
1047 offset += 1;
1049 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1050 offset += 1;
1052 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_ltr_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1053 offset += 4;
1054 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltm_ltr_ttl, tvb, offset, 1, ENC_NA);
1055 offset += 1;
1056 proto_tree_add_item(cfm_pdu_tree, hf_cfm_ltr_relay_action, tvb, offset, 1, ENC_NA);
1057 offset += 1;
1059 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1061 if (length_remaining > 0) {
1062 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1063 offset += length_remaining;
1066 proto_item_set_len(ti, offset - start_offset);
1067 return offset;
1070 static int dissect_cfm_rfm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1072 proto_item *ti;
1073 proto_item *fi;
1074 proto_tree *cfm_pdu_tree;
1075 proto_tree *cfm_flag_tree;
1076 uint32_t first_tlv_offset;
1077 int start_offset = offset;
1078 int length_remaining;
1080 ti = proto_tree_add_item(tree, hf_cfm_rfm_pdu, tvb, offset, -1, ENC_NA);
1081 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1083 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
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_NA);
1086 offset += 1;
1088 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1089 offset += 1;
1091 proto_tree_add_item(cfm_pdu_tree, hf_cfm_rfm_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1092 offset += 4;
1094 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1096 if (length_remaining > 0) {
1097 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1098 offset += length_remaining;
1101 proto_item_set_len(ti, offset - start_offset);
1102 return offset;
1105 static int dissect_cfm_sfm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1107 proto_item *ti;
1108 proto_item *fi;
1109 proto_tree *cfm_pdu_tree;
1110 proto_tree *cfm_flag_tree;
1111 uint32_t first_tlv_offset;
1112 int start_offset = offset;
1113 int length_remaining;
1115 ti = proto_tree_add_item(tree, hf_cfm_sfm_pdu, tvb, offset, -1, ENC_NA);
1116 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1118 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1119 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1120 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1121 offset += 1;
1123 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1124 offset += 1;
1126 proto_tree_add_item(cfm_pdu_tree, hf_cfm_sfm_transaction_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1127 offset += 4;
1129 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1131 if (length_remaining > 0) {
1132 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1133 offset += length_remaining;
1136 proto_item_set_len(ti, offset - start_offset);
1137 return offset;
1140 static int dissect_cfm_bnm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1142 proto_item *ti;
1143 proto_item *fi;
1144 proto_tree *cfm_pdu_tree;
1145 proto_tree *cfm_flag_tree;
1146 uint32_t first_tlv_offset;
1147 int start_offset = offset;
1148 int length_remaining;
1150 ti = proto_tree_add_item(tree, hf_cfm_bnm_pdu, tvb, offset, -1, ENC_NA);
1151 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1153 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1154 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1155 proto_tree_add_item(cfm_flag_tree, hf_cfm_bnm_flags_Reserved, tvb, offset, 1, ENC_NA);
1156 proto_tree_add_item(cfm_flag_tree, hf_cfm_bnm_flags_Period, tvb, offset, 1, ENC_NA);
1157 offset += 1;
1159 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1160 offset += 1;
1162 proto_tree_add_item(cfm_pdu_tree, hf_cfm_gnm_subopcode, tvb, offset, 1, ENC_NA);
1163 offset += 1;
1165 proto_tree_add_item(cfm_pdu_tree, hf_cfm_bnm_nominal_bw, tvb, offset, 4, ENC_BIG_ENDIAN);
1166 offset += 4;
1167 proto_tree_add_item(cfm_pdu_tree, hf_cfm_bnm_current_bw, tvb, offset, 4, ENC_BIG_ENDIAN);
1168 offset += 4;
1169 proto_tree_add_item(cfm_pdu_tree, hf_cfm_bnm_port_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1170 offset += 4;
1172 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1174 if (length_remaining > 0) {
1175 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1176 offset += length_remaining;
1179 proto_item_set_len(ti, offset - start_offset);
1180 return offset;
1183 static int dissect_cfm_gnm_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1185 proto_item *ti;
1186 proto_item *fi;
1187 proto_tree *cfm_pdu_tree;
1188 proto_tree *cfm_flag_tree;
1189 uint32_t first_tlv_offset;
1190 int start_offset = offset;
1191 int length_remaining;
1193 ti = proto_tree_add_item(tree, hf_cfm_gnm_pdu, tvb, offset, -1, ENC_NA);
1194 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1196 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1197 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1198 proto_tree_add_item(cfm_flag_tree, hf_cfm_gnm_unknown_flags, tvb, offset, 1, ENC_NA);
1199 offset += 1;
1201 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1202 offset += 1;
1204 proto_tree_add_item(cfm_pdu_tree, hf_cfm_gnm_subopcode, tvb, offset, 1, ENC_NA);
1205 offset += 1;
1207 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1209 if (length_remaining > 0) {
1210 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1211 offset += length_remaining;
1214 proto_item_set_len(ti, offset - start_offset);
1215 return offset;
1218 static int dissect_cfm_gnm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1220 uint8_t cfm_gnm_pdu_type = tvb_get_uint8(tvb, offset + 4);
1222 switch (cfm_gnm_pdu_type) {
1223 case BNM:
1224 offset = dissect_cfm_bnm(tvb, pinfo, tree, offset);
1225 break;
1226 default:
1227 offset = dissect_cfm_gnm_unknown(tvb, pinfo, tree, offset);
1228 break;
1231 return offset;
1234 static int dissect_cfm_ais(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1236 proto_item *ti;
1237 proto_item *fi;
1238 proto_tree *cfm_pdu_tree;
1239 proto_tree *cfm_flag_tree;
1240 uint32_t first_tlv_offset;
1241 int start_offset = offset;
1242 int length_remaining;
1244 ti = proto_tree_add_item(tree, hf_cfm_ais_pdu, tvb, offset, -1, ENC_NA);
1245 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1247 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1248 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1249 proto_tree_add_item(cfm_flag_tree, hf_cfm_ais_flags_Reserved, tvb, offset, 1, ENC_NA);
1250 proto_tree_add_item(cfm_flag_tree, hf_cfm_ais_flags_Period, tvb, offset, 1, ENC_NA);
1251 offset += 1;
1253 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1254 offset += 1;
1256 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1258 if (length_remaining > 0) {
1259 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1260 offset += length_remaining;
1263 proto_item_set_len(ti, offset - start_offset);
1264 return offset;
1267 static int dissect_cfm_lck(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1269 proto_item *ti;
1270 proto_item *fi;
1271 proto_tree *cfm_pdu_tree;
1272 proto_tree *cfm_flag_tree;
1273 uint32_t first_tlv_offset;
1274 int start_offset = offset;
1275 int length_remaining;
1277 ti = proto_tree_add_item(tree, hf_cfm_lck_pdu, tvb, offset, -1, ENC_NA);
1278 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1280 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1281 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1282 proto_tree_add_item(cfm_flag_tree, hf_cfm_lck_flags_Reserved, tvb, offset, 1, ENC_NA);
1283 proto_tree_add_item(cfm_flag_tree, hf_cfm_lck_flags_Period, tvb, offset, 1, ENC_NA);
1284 offset += 1;
1286 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1287 offset += 1;
1289 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1291 if (length_remaining > 0) {
1292 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1293 offset += length_remaining;
1296 proto_item_set_len(ti, offset - start_offset);
1297 return offset;
1300 static int dissect_cfm_tst(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1302 proto_item *ti;
1303 proto_item *fi;
1304 proto_tree *cfm_pdu_tree;
1305 proto_tree *cfm_flag_tree;
1306 uint32_t first_tlv_offset;
1307 int start_offset = offset;
1308 int length_remaining;
1310 ti = proto_tree_add_item(tree, hf_cfm_tst_pdu, tvb, offset, -1, ENC_NA);
1311 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1313 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1314 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1315 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1316 offset += 1;
1318 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1319 offset += 1;
1321 proto_tree_add_item(cfm_pdu_tree, hf_cfm_tst_sequence_num, tvb, offset, 4, ENC_BIG_ENDIAN);
1322 offset += 4;
1324 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1326 if (length_remaining > 0) {
1327 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1328 offset += length_remaining;
1331 proto_item_set_len(ti, offset - start_offset);
1332 return offset;
1335 static int dissect_cfm_aps(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1337 proto_item *ti;
1338 proto_item *fi;
1339 proto_tree *cfm_pdu_tree;
1340 proto_tree *cfm_flag_tree;
1341 uint32_t first_tlv_offset;
1342 int start_offset = offset;
1343 int length_remaining;
1345 ti = proto_tree_add_item(tree, hf_cfm_aps_pdu, tvb, offset, -1, ENC_NA);
1346 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1348 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1349 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1350 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1351 offset += 1;
1353 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1354 offset += 1;
1356 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_req_st, tvb, offset, 1, ENC_NA);
1357 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_protection_type_A, tvb, offset, 1, ENC_NA);
1358 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_protection_type_B, tvb, offset, 1, ENC_NA);
1359 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_protection_type_D, tvb, offset, 1, ENC_NA);
1360 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_protection_type_R, tvb, offset, 1, ENC_NA);
1361 offset += 1;
1363 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_requested_signal, tvb, offset, 1, ENC_NA);
1364 offset += 1;
1366 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_bridged_signal, tvb, offset, 1, ENC_NA);
1367 offset += 1;
1369 proto_tree_add_item(cfm_pdu_tree, hf_cfm_aps_bridge_type, tvb, offset, 1, ENC_NA);
1370 offset += 1;
1372 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1374 if (length_remaining > 0) {
1375 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1376 offset += length_remaining;
1379 proto_item_set_len(ti, offset - start_offset);
1380 return offset;
1383 static int dissect_cfm_raps(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1385 proto_item *ti;
1386 proto_item *fi;
1387 proto_tree *cfm_pdu_tree;
1388 proto_tree *cfm_flag_tree;
1389 uint32_t first_tlv_offset;
1390 int start_offset = offset;
1391 int length_remaining;
1393 unsigned version;
1394 uint32_t raps_requeststate;
1395 proto_item *ri;
1396 proto_tree *raps_status_tree;
1398 ti = proto_tree_add_item(tree, hf_cfm_raps_pdu, tvb, offset, -1, ENC_NA);
1399 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1401 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1402 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1403 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1404 offset += 1;
1406 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1407 offset += 1;
1409 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_raps_req_st, tvb, offset, 1, ENC_NA, &raps_requeststate);
1411 version = (tvb_get_uint8(tvb, CFM_LEVEL_VERSION_OFFSET) & CFM_VERSION_MASK) >> CFM_VERSION_SHIFT;
1413 if (version == 1 && raps_requeststate == RAPS_REQ_ST_EVENT) {
1414 proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_event_subcode, tvb, offset, 1, ENC_NA);
1415 } else {
1416 proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_subcode_reserved, tvb, offset, 1, ENC_NA);
1419 offset += 1;
1421 ri = proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_status, tvb, offset, 1, ENC_NA);
1422 raps_status_tree = proto_item_add_subtree(ri, ett_cfm_raps_status);
1423 proto_tree_add_item(raps_status_tree, hf_cfm_raps_status_rb, tvb, offset, 1, ENC_NA);
1424 proto_tree_add_item(raps_status_tree, hf_cfm_raps_status_dnf, tvb, offset, 1, ENC_NA);
1426 /* R-APS(G.8032) v2 only */
1427 if (version == 1) {
1428 proto_tree_add_item(raps_status_tree, hf_cfm_raps_status_bpr, tvb, offset, 1, ENC_NA);
1429 proto_tree_add_item(raps_status_tree, hf_cfm_raps_status_reserved_v2, tvb, offset, 1, ENC_NA);
1430 } else {
1431 proto_tree_add_item(raps_status_tree, hf_cfm_raps_status_reserved_v1, tvb, offset, 1, ENC_NA);
1434 offset += 1;
1436 proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_node_id, tvb, offset, 6, ENC_NA);
1437 offset += 6;
1439 proto_tree_add_item(cfm_pdu_tree, hf_cfm_raps_reserved, tvb, offset, 24, ENC_NA);
1440 offset += 24;
1442 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1444 if (length_remaining > 0) {
1445 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1446 offset += length_remaining;
1449 proto_item_set_len(ti, offset - start_offset);
1450 return offset;
1453 static int find_end_tlv(tvbuff_t *tvb, int first_tlv_offset)
1456 * XXX - how to handle TLVs in MCC, EXM, EXR, VSM or VSR PDU data?
1457 * The TLV Offset points to the first TLV, which may part of PDU Data, therefore defined
1458 * 'outside the scope of this standard'. Therefore these cannot be simply handed off the
1459 * standard TLV dissection functions. We do however want to find the End TLV.
1460 * All we can do is iterate over these unknown TLVs, under the assumption they use the
1461 * same format as defined in this standard, until we find the End TLV.
1462 * Don't break dissection if we can't find it this way, e.g. when the captured frame is
1463 * cut short. Then assume all remaining captured frame data is PDU data.
1466 int tlv_tvb_offset = CFM_COMMON_HEADER_LEN + first_tlv_offset;
1467 for (;;) {
1468 // Does a tag exist in the captured data?
1469 if (tvb_bytes_exist(tvb, tlv_tvb_offset, 1)) {
1470 // Is this the End TLV
1471 if (tvb_get_uint8(tvb, tlv_tvb_offset)) {
1472 // Following the tag, does the length exist in the captured data?
1473 if (tvb_captured_length_remaining(tvb, tlv_tvb_offset) < 3) {
1474 tlv_tvb_offset = 0;
1475 break;
1477 // Go to the next tag
1478 tlv_tvb_offset += tvb_get_ntohs(tvb, tlv_tvb_offset + 1) + 3;
1479 } else {
1480 break; // we found the END_TLV
1482 } else {
1483 tlv_tvb_offset = 0;
1484 break;
1488 return tlv_tvb_offset;
1491 static int dissect_cfm_mcc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1493 proto_item *ti;
1494 proto_item *fi;
1495 proto_tree *cfm_pdu_tree;
1496 proto_tree *cfm_flag_tree;
1497 uint32_t first_tlv_offset;
1498 int start_offset = offset;
1499 int tlv_tvb_offset;
1501 ti = proto_tree_add_item(tree, hf_cfm_mcc_pdu, tvb, offset, -1, ENC_NA);
1502 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1504 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1505 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1506 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1507 offset += 1;
1509 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1510 offset += 1;
1512 /* XXX - Introducing a dissector table would allow to register subdissectors based on
1513 * their subopcode, per OUI. The OUI table creation would be similar to the registration
1514 * function in the IEEE 802a dissector.
1517 proto_tree_add_item(cfm_pdu_tree, hf_cfm_mcc_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1518 offset += 3;
1519 proto_tree_add_item(cfm_pdu_tree, hf_cfm_mcc_subopcode, tvb, offset, 1, ENC_NA);
1520 offset += 1;
1522 tlv_tvb_offset = find_end_tlv(tvb, first_tlv_offset);
1524 proto_tree_add_item(cfm_pdu_tree, hf_cfm_mcc_data, tvb, offset, (tlv_tvb_offset) ? (tlv_tvb_offset - offset) : -1, ENC_NA);
1525 offset = (tlv_tvb_offset) ? tlv_tvb_offset : (int)tvb_captured_length(tvb);
1527 proto_item_set_len(ti, offset - start_offset);
1528 return offset;
1531 static int dissect_cfm_lmm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1533 proto_item *ti;
1534 proto_item *fi;
1535 proto_tree *cfm_pdu_tree;
1536 proto_tree *cfm_flag_tree;
1537 uint32_t first_tlv_offset;
1538 int start_offset = offset;
1539 int length_remaining;
1541 ti = proto_tree_add_item(tree, hf_cfm_lmm_pdu, tvb, offset, -1, ENC_NA);
1542 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1544 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1545 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1546 proto_tree_add_item(cfm_flag_tree, hf_cfm_lmm_lmr_flags_Reserved, tvb, offset, 1, ENC_NA);
1547 proto_tree_add_item(cfm_flag_tree, hf_cfm_lmm_lmr_flags_Type, tvb, offset, 1, ENC_NA);
1548 offset += 1;
1550 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1551 offset += 1;
1553 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCf, tvb, offset, 4, ENC_NA);
1554 offset += 4;
1555 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_RxFCf, tvb, offset, 4, ENC_NA);
1556 offset += 4;
1557 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCb, tvb, offset, 4, ENC_NA);
1558 offset += 4;
1560 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1562 if (length_remaining > 0) {
1563 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1564 offset += length_remaining;
1567 proto_item_set_len(ti, offset - start_offset);
1568 return offset;
1571 static int dissect_cfm_lmr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1573 proto_item *ti;
1574 proto_item *fi;
1575 proto_tree *cfm_pdu_tree;
1576 proto_tree *cfm_flag_tree;
1577 uint32_t first_tlv_offset;
1578 int start_offset = offset;
1579 int length_remaining;
1581 ti = proto_tree_add_item(tree, hf_cfm_lmr_pdu, tvb, offset, -1, ENC_NA);
1582 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1584 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1585 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1586 proto_tree_add_item(cfm_flag_tree, hf_cfm_lmm_lmr_flags_Reserved, tvb, offset, 1, ENC_NA);
1587 proto_tree_add_item(cfm_flag_tree, hf_cfm_lmm_lmr_flags_Type, tvb, offset, 1, ENC_NA);
1588 offset += 1;
1590 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1591 offset += 1;
1593 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCf, tvb, offset, 4, ENC_NA);
1594 offset += 4;
1595 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_RxFCf, tvb, offset, 4, ENC_NA);
1596 offset += 4;
1597 proto_tree_add_item(cfm_pdu_tree, hf_cfm_lmm_lmr_TxFCb, tvb, offset, 4, ENC_NA);
1598 offset += 4;
1600 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1602 if (length_remaining > 0) {
1603 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1604 offset += length_remaining;
1607 proto_item_set_len(ti, offset - start_offset);
1608 return offset;
1611 static int dissect_cfm_odm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1613 proto_item *ti;
1614 proto_item *fi;
1615 proto_tree *cfm_pdu_tree;
1616 proto_tree *cfm_flag_tree;
1617 uint32_t first_tlv_offset;
1618 int start_offset = offset;
1619 int length_remaining;
1621 ti = proto_tree_add_item(tree, hf_cfm_odm_pdu, tvb, offset, -1, ENC_NA);
1622 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1624 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1625 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1626 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Reserved, tvb, offset, 1, ENC_NA);
1627 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Type, tvb, offset, 1, ENC_NA);
1628 offset += 1;
1630 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1631 offset += 1;
1633 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1634 offset += 8;
1635 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1636 offset += 8;
1638 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1640 if (length_remaining > 0) {
1641 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1642 offset += length_remaining;
1645 proto_item_set_len(ti, offset - start_offset);
1646 return offset;
1649 static int dissect_cfm_dmm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1651 proto_item *ti;
1652 proto_item *fi;
1653 proto_tree *cfm_pdu_tree;
1654 proto_tree *cfm_flag_tree;
1655 uint32_t first_tlv_offset;
1656 int start_offset = offset;
1657 int length_remaining;
1659 ti = proto_tree_add_item(tree, hf_cfm_dmm_pdu, tvb, offset, -1, ENC_NA);
1660 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1662 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1663 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1664 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Reserved, tvb, offset, 1, ENC_NA);
1665 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Type, tvb, offset, 1, ENC_NA);
1666 offset += 1;
1668 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1669 offset += 1;
1671 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1672 offset += 8;
1673 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1674 offset += 8;
1675 proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_TxTimestampb, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1676 offset += 8;
1677 proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_RxTimestampb, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1678 offset += 8;
1680 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1682 if (length_remaining > 0) {
1683 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1684 offset += length_remaining;
1687 proto_item_set_len(ti, offset - start_offset);
1688 return offset;
1691 static int dissect_cfm_dmr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1693 proto_item *ti;
1694 proto_item *fi;
1695 proto_tree *cfm_pdu_tree;
1696 proto_tree *cfm_flag_tree;
1697 uint32_t first_tlv_offset;
1698 int start_offset = offset;
1699 int length_remaining;
1701 ti = proto_tree_add_item(tree, hf_cfm_dmr_pdu, tvb, offset, -1, ENC_NA);
1702 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1704 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1705 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1706 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Reserved, tvb, offset, 1, ENC_NA);
1707 proto_tree_add_item(cfm_flag_tree, hf_cfm_odm_dmm_dmr_flags_Type, tvb, offset, 1, ENC_NA);
1708 offset += 1;
1710 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1711 offset += 1;
1713 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_TxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1714 offset += 8;
1715 proto_tree_add_item(cfm_pdu_tree, hf_cfm_odm_dmm_dmr_RxTimestampf, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1716 offset += 8;
1717 proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_TxTimestampb, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1718 offset += 8;
1719 proto_tree_add_item(cfm_pdu_tree, hf_cfm_dmm_dmr_RxTimestampb, tvb, offset, 8, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
1720 offset += 8;
1722 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1724 if (length_remaining > 0) {
1725 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1726 offset += length_remaining;
1729 proto_item_set_len(ti, offset - start_offset);
1730 return offset;
1733 static int dissect_cfm_exm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1735 proto_item *ti;
1736 proto_item *fi;
1737 proto_tree *cfm_pdu_tree;
1738 proto_tree *cfm_flag_tree;
1739 uint32_t first_tlv_offset;
1740 int start_offset = offset;
1741 int tlv_tvb_offset;
1743 ti = proto_tree_add_item(tree, hf_cfm_exm_pdu, tvb, offset, -1, ENC_NA);
1744 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1746 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1747 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1748 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1749 offset += 1;
1751 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1752 offset += 1;
1754 /* XXX - Introducing a dissector table would allow to register subdissectors based on
1755 * their subopcode, per OUI. The OUI table creation would be similar to the registration
1756 * function in the IEEE 802a dissector.
1759 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exm_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1760 offset += 3;
1761 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exm_subopcode, tvb, offset, 1, ENC_NA);
1762 offset += 1;
1764 tlv_tvb_offset = find_end_tlv(tvb, first_tlv_offset);
1766 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exm_data, tvb, offset, (tlv_tvb_offset) ? (tlv_tvb_offset - offset) : -1, ENC_NA);
1767 offset = (tlv_tvb_offset) ? tlv_tvb_offset : (int)tvb_captured_length(tvb);
1769 proto_item_set_len(ti, offset - start_offset);
1770 return offset;
1773 static int dissect_cfm_exr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1775 proto_item *ti;
1776 proto_item *fi;
1777 proto_tree *cfm_pdu_tree;
1778 proto_tree *cfm_flag_tree;
1779 uint32_t first_tlv_offset;
1780 int start_offset = offset;
1781 int tlv_tvb_offset;
1783 ti = proto_tree_add_item(tree, hf_cfm_exr_pdu, tvb, offset, -1, ENC_NA);
1784 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1786 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1787 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1788 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1789 offset += 1;
1791 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1792 offset += 1;
1794 /* XXX - Introducing a dissector table would allow to register subdissectors based on
1795 * their subopcode, per OUI. The OUI table creation would be similar to the registration
1796 * function in the IEEE 802a dissector.
1799 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exr_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1800 offset += 3;
1801 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exr_subopcode, tvb, offset, 1, ENC_NA);
1802 offset += 1;
1804 tlv_tvb_offset = find_end_tlv(tvb, first_tlv_offset);
1806 proto_tree_add_item(cfm_pdu_tree, hf_cfm_exr_data, tvb, offset, (tlv_tvb_offset) ? (tlv_tvb_offset - offset) : -1, ENC_NA);
1807 offset = (tlv_tvb_offset) ? tlv_tvb_offset : (int)tvb_captured_length(tvb);
1809 proto_item_set_len(ti, offset - start_offset);
1810 return offset;
1813 static int dissect_cfm_vsm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1815 proto_item *ti;
1816 proto_item *fi;
1817 proto_tree *cfm_pdu_tree;
1818 proto_tree *cfm_flag_tree;
1819 uint32_t first_tlv_offset;
1820 int start_offset = offset;
1821 int tlv_tvb_offset;
1823 ti = proto_tree_add_item(tree, hf_cfm_vsm_pdu, tvb, offset, -1, ENC_NA);
1824 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1826 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1827 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1828 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1829 offset += 1;
1831 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1832 offset += 1;
1834 /* XXX - Introducing a dissector table would allow to register subdissectors based on
1835 * their subopcode, per OUI. The OUI table creation would be similar to the registration
1836 * function in the IEEE 802a dissector.
1839 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsm_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1840 offset += 3;
1841 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsm_subopcode, tvb, offset, 1, ENC_NA);
1842 offset += 1;
1844 tlv_tvb_offset = find_end_tlv(tvb, first_tlv_offset);
1846 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsm_data, tvb, offset, (tlv_tvb_offset) ? (tlv_tvb_offset - offset) : -1, ENC_NA);
1847 offset = (tlv_tvb_offset) ? tlv_tvb_offset : (int)tvb_captured_length(tvb);
1849 proto_item_set_len(ti, offset - start_offset);
1850 return offset;
1853 static int dissect_cfm_vsr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1855 proto_item *ti;
1856 proto_item *fi;
1857 proto_tree *cfm_pdu_tree;
1858 proto_tree *cfm_flag_tree;
1859 uint32_t first_tlv_offset;
1860 int start_offset = offset;
1861 int tlv_tvb_offset;
1863 ti = proto_tree_add_item(tree, hf_cfm_vsr_pdu, tvb, offset, -1, ENC_NA);
1864 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1866 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1867 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1868 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1869 offset += 1;
1871 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1872 offset += 1;
1874 /* XXX - Introducing a dissector table would allow to register subdissectors based on
1875 * their subopcode, per OUI. The OUI table creation would be similar to the registration
1876 * function in the IEEE 802a dissector.
1879 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsr_oui, tvb, offset, 3, ENC_BIG_ENDIAN);
1880 offset += 3;
1881 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsr_subopcode, tvb, offset, 1, ENC_NA);
1882 offset += 1;
1884 tlv_tvb_offset = find_end_tlv(tvb, first_tlv_offset);
1886 proto_tree_add_item(cfm_pdu_tree, hf_cfm_vsr_data, tvb, offset, (tlv_tvb_offset) ? (tlv_tvb_offset - offset) : -1, ENC_NA);
1887 offset = (tlv_tvb_offset) ? tlv_tvb_offset : (int)tvb_captured_length(tvb);
1889 proto_item_set_len(ti, offset - start_offset);
1890 return offset;
1893 static int dissect_cfm_csf(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1895 proto_item *ti;
1896 proto_item *fi;
1897 proto_tree *cfm_pdu_tree;
1898 proto_tree *cfm_flag_tree;
1899 uint32_t first_tlv_offset;
1900 int start_offset = offset;
1901 int length_remaining;
1903 ti = proto_tree_add_item(tree, hf_cfm_csf_pdu, tvb, offset, -1, ENC_NA);
1904 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1906 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1907 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1908 proto_tree_add_item(cfm_flag_tree, hf_cfm_csf_flags_Reserved, tvb, offset, 1, ENC_NA);
1909 proto_tree_add_item(cfm_flag_tree, hf_cfm_csf_flags_Type, tvb, offset, 1, ENC_NA);
1910 proto_tree_add_item(cfm_flag_tree, hf_cfm_csf_flags_Period, tvb, offset, 1, ENC_NA);
1911 offset += 1;
1913 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1914 offset += 1;
1916 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1918 if (length_remaining > 0) {
1919 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1920 offset += length_remaining;
1923 proto_item_set_len(ti, offset - start_offset);
1924 return offset;
1927 static int dissect_cfm_osl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1929 proto_item *ti;
1930 proto_item *fi;
1931 proto_tree *cfm_pdu_tree;
1932 proto_tree *cfm_flag_tree;
1933 uint32_t first_tlv_offset;
1934 int start_offset = offset;
1935 int length_remaining;
1937 ti = proto_tree_add_item(tree, hf_cfm_osl_pdu, tvb, offset, -1, ENC_NA);
1938 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1940 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1941 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1942 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1943 offset += 1;
1945 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1946 offset += 1;
1948 proto_tree_add_item(cfm_pdu_tree, hf_cfm_osl_src_mep, tvb, offset, 2, ENC_BIG_ENDIAN);
1949 offset += 2;
1950 proto_tree_add_item(cfm_pdu_tree, hf_cfm_osl_reserved, tvb, offset, 2, ENC_NA);
1951 offset += 2;
1952 proto_tree_add_item(cfm_pdu_tree, hf_cfm_osl_testid, tvb, offset, 4, ENC_NA);
1953 offset += 4;
1954 proto_tree_add_item(cfm_pdu_tree, hf_cfm_osl_txfcf, tvb, offset, 4, ENC_BIG_ENDIAN);
1955 offset += 4;
1956 proto_tree_add_item(cfm_pdu_tree, hf_cfm_osl_reserved, tvb, offset, 4, ENC_NA);
1957 offset += 4;
1959 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
1961 if (length_remaining > 0) {
1962 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
1963 offset += length_remaining;
1966 proto_item_set_len(ti, offset - start_offset);
1967 return offset;
1970 static int dissect_cfm_slm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1972 proto_item *ti;
1973 proto_item *fi;
1974 proto_tree *cfm_pdu_tree;
1975 proto_tree *cfm_flag_tree;
1976 uint32_t first_tlv_offset;
1977 int start_offset = offset;
1978 int length_remaining;
1980 ti = proto_tree_add_item(tree, hf_cfm_slm_pdu, tvb, offset, -1, ENC_NA);
1981 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
1983 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
1984 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
1985 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
1986 offset += 1;
1988 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
1989 offset += 1;
1991 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_src_mep, tvb, offset, 2, ENC_BIG_ENDIAN);
1992 offset += 2;
1993 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_reserved, tvb, offset, 2, ENC_NA);
1994 offset += 2;
1995 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_testid, tvb, offset, 4, ENC_NA);
1996 offset += 4;
1997 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_txfcf, tvb, offset, 4, ENC_BIG_ENDIAN);
1998 offset += 4;
1999 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_reserved, tvb, offset, 4, ENC_NA);
2000 offset += 4;
2002 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
2004 if (length_remaining > 0) {
2005 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
2006 offset += length_remaining;
2009 proto_item_set_len(ti, offset - start_offset);
2010 return offset;
2013 static int dissect_cfm_slr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
2015 proto_item *ti;
2016 proto_item *fi;
2017 proto_tree *cfm_pdu_tree;
2018 proto_tree *cfm_flag_tree;
2019 uint32_t first_tlv_offset;
2020 int start_offset = offset;
2021 int length_remaining;
2023 ti = proto_tree_add_item(tree, hf_cfm_slr_pdu, tvb, offset, -1, ENC_NA);
2024 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
2026 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
2027 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
2028 proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Reserved, tvb, offset, 1, ENC_NA);
2029 offset += 1;
2031 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
2032 offset += 1;
2034 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_src_mep, tvb, offset, 2, ENC_BIG_ENDIAN);
2035 offset += 2;
2036 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_rsp_mep, tvb, offset, 2, ENC_BIG_ENDIAN);
2037 offset += 2;
2038 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_testid, tvb, offset, 4, ENC_NA);
2039 offset += 4;
2040 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slm_slr_txfcf, tvb, offset, 4, ENC_BIG_ENDIAN);
2041 offset += 4;
2042 proto_tree_add_item(cfm_pdu_tree, hf_cfm_slr_txfcb, tvb, offset, 4, ENC_BIG_ENDIAN);
2043 offset += 4;
2045 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
2047 if (length_remaining > 0) {
2048 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
2049 offset += length_remaining;
2052 proto_item_set_len(ti, offset - start_offset);
2053 return offset;
2056 static int dissect_cfm_unknown(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
2058 proto_item *ti;
2059 proto_item *fi;
2060 proto_tree *cfm_pdu_tree;
2061 proto_tree *cfm_flag_tree;
2062 uint32_t first_tlv_offset;
2063 int start_offset = offset;
2064 int length_remaining;
2066 ti = proto_tree_add_item(tree, hf_cfm_unknown_pdu, tvb, offset, -1, ENC_NA);
2067 cfm_pdu_tree = proto_item_add_subtree(ti, ett_cfm_pdu);
2069 fi = proto_tree_add_item(cfm_pdu_tree, hf_cfm_flags, tvb, offset, 1, ENC_NA);
2070 cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
2071 proto_tree_add_item(cfm_flag_tree, hf_cfm_unknown_flags, tvb, offset, 1, ENC_NA);
2072 offset += 1;
2074 proto_tree_add_item_ret_uint(cfm_pdu_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, ENC_NA, &first_tlv_offset);
2075 offset += 1;
2077 length_remaining = first_tlv_offset - (offset - (start_offset + 2));
2079 if (length_remaining > 0) {
2080 proto_tree_add_item(cfm_pdu_tree, hf_cfm_unknown_data, tvb, offset, length_remaining, ENC_NA);
2081 offset += length_remaining;
2084 proto_item_set_len(ti, offset - start_offset);
2085 return offset;
2088 /* Inspired by packet-lldp.c:dissect_lldp_chassis_id() */
2089 static int sender_id_tlv_chassis_id(proto_tree *cfm_tlv_tree, tvbuff_t *tvb, int tlv_data_offset, uint8_t tlv_chassis_id_length)
2091 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_subtype, tvb, tlv_data_offset, 1, ENC_NA);
2092 uint8_t chassis_id_subtype = tvb_get_uint8(tvb, tlv_data_offset);
2093 tlv_data_offset += 1;
2094 tlv_chassis_id_length -= 1;
2096 switch (chassis_id_subtype) {
2097 case 1:
2098 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_chassis_component, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_UTF_8);
2099 break;
2100 case 2:
2101 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_interface_alias, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_UTF_8);
2102 break;
2103 case 3:
2104 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_port_component, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_NA);
2105 break;
2106 case 4:
2107 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_mac_address, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_NA);
2108 break;
2109 case 5:
2110 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_network_address_family, tvb, tlv_data_offset, 1, ENC_NA);
2112 switch (tvb_get_uint8(tvb, tlv_data_offset)) {
2113 case AFNUM_INET:
2114 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_network_address_ipv4, tvb, tlv_data_offset+1, tlv_chassis_id_length-1, ENC_BIG_ENDIAN);
2115 break;
2116 case AFNUM_INET6:
2117 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_network_address_ipv6, tvb, tlv_data_offset+1, tlv_chassis_id_length-1, ENC_NA);
2118 break;
2119 default:
2120 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_network_address_unknown, tvb, tlv_data_offset+1, tlv_chassis_id_length-1, ENC_NA);
2121 break;
2123 break;
2124 case 6:
2125 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_interface_name, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_UTF_8);
2126 break;
2127 case 7:
2128 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_locally_assigned, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_UTF_8);
2129 break;
2130 default:
2131 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_unknown, tvb, tlv_data_offset, tlv_chassis_id_length, ENC_NA);
2132 break;
2135 tlv_data_offset += tlv_chassis_id_length;
2137 return tlv_data_offset;
2140 static int sender_id_tlv_management_address(proto_tree *cfm_tlv_tree, tvbuff_t *tvb, void *tlv_ma_domain_oid, uint8_t tlv_ma_domain_length, int tlv_data_offset, uint8_t tlv_management_addr_length)
2142 struct {
2143 const uint8_t *oid; // BER encoded
2144 const size_t oid_length;
2145 const int *header_field;
2146 const int encoding;
2147 } management_address_type[] = {
2148 // transportDomainUdpIpv4 : 1.3.6.1.2.1.100.1.1
2149 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x01 }, 8, &hf_tlv_management_addr_ipv4, ENC_BIG_ENDIAN },
2150 // transportDomainUdpIpv6 : 1.3.6.1.2.1.100.1.2
2151 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x02 }, 8, &hf_tlv_management_addr_ipv6, ENC_NA },
2152 // transportDomainTcpIpv4 : 1.3.6.1.2.1.100.1.5
2153 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x05 }, 8, &hf_tlv_management_addr_ipv4, ENC_BIG_ENDIAN },
2154 // transportDomainTcpIpv6 : 1.3.6.1.2.1.100.1.6
2155 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x06 }, 8, &hf_tlv_management_addr_ipv6, ENC_NA },
2156 // transportDomainSctpIpv4 : 1.3.6.1.2.1.100.1.9
2157 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x09 }, 8, &hf_tlv_management_addr_ipv4, ENC_BIG_ENDIAN },
2158 // transportDomainSctpIpv6 : 1.3.6.1.2.1.100.1.10
2159 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x02, 0x01, 0x64, 0x01, 0x0A }, 8, &hf_tlv_management_addr_ipv6, ENC_NA },
2160 // snmpIeee802Domain : 1.3.6.1.6.1.6
2161 { (const uint8_t[]){ 0x2B, 0x06, 0x01, 0x06, 0x01, 0x06 }, 6, &hf_tlv_management_addr_eth, ENC_NA },
2162 // End tag
2163 { NULL, 0, NULL, ENC_NA }
2166 for (size_t i = 0; i < array_length(management_address_type); i++) {
2167 if (management_address_type[i].oid == NULL) {
2168 proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr_unknown,
2169 tvb, tlv_data_offset, tlv_management_addr_length, ENC_NA);
2170 break;
2172 if (tlv_ma_domain_length == management_address_type[i].oid_length) {
2173 if (!(memcmp(tlv_ma_domain_oid, management_address_type[i].oid, tlv_ma_domain_length))) {
2174 proto_tree_add_item(cfm_tlv_tree, *management_address_type[i].header_field,
2175 tvb, tlv_data_offset, tlv_management_addr_length, management_address_type[i].encoding);
2176 break;
2181 tlv_data_offset += tlv_management_addr_length;
2183 return tlv_data_offset;
2186 /* Inspired by packet-lldp.c:dissect_lldp_port_id() */
2187 static int reply_ing_egr_tlv_port_id(proto_tree *cfm_tlv_tree, tvbuff_t *tvb, int tlv_data_offset, uint8_t tlv_reply_ingress_portid_length)
2189 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_subtype,
2190 tvb, tlv_data_offset, 1, ENC_NA);
2191 uint8_t port_id_subtype = tvb_get_uint8(tvb, tlv_data_offset);
2192 tlv_data_offset += 1;
2193 tlv_reply_ingress_portid_length -= 1;
2195 switch (port_id_subtype) {
2196 case 1:
2197 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_interface_alias, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_UTF_8);
2198 break;
2199 case 2:
2200 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_port_component, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_NA);
2201 break;
2202 case 3:
2203 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_mac_address, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_NA);
2204 break;
2205 case 4:
2206 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_network_address_family, tvb, tlv_data_offset, 1, ENC_NA);
2208 switch (tvb_get_uint8(tvb, tlv_data_offset)) {
2209 case AFNUM_INET:
2210 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_network_address_ipv4, tvb, tlv_data_offset+1, tlv_reply_ingress_portid_length-1, ENC_BIG_ENDIAN);
2211 break;
2212 case AFNUM_INET6:
2213 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_network_address_ipv6, tvb, tlv_data_offset+1, tlv_reply_ingress_portid_length-1, ENC_NA);
2214 break;
2215 default:
2216 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_network_address_unknown, tvb, tlv_data_offset+1, tlv_reply_ingress_portid_length-1, ENC_NA);
2217 break;
2219 break;
2220 case 5:
2221 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_interface_name, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_UTF_8);
2222 break;
2223 case 6:
2224 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_agent_circuit_id, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_NA);
2225 break;
2226 case 7:
2227 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_locally_assigned, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_UTF_8);
2228 break;
2229 default:
2230 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_unknown, tvb, tlv_data_offset, tlv_reply_ingress_portid_length, ENC_NA);
2231 break;
2234 tlv_data_offset += tlv_reply_ingress_portid_length;
2236 return tlv_data_offset;
2239 /* Main CFM EOAM protocol dissector */
2240 static int dissect_cfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2242 int offset = 0;
2243 uint8_t cfm_pdu_type;
2245 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFM");
2246 col_clear(pinfo->cinfo, COL_INFO);
2248 cfm_pdu_type = tvb_get_uint8(tvb, CFM_OPCODE_OFFSET);
2249 col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
2250 val_to_str(cfm_pdu_type, opcode_type_name_vals, "Unknown (0x%02x)"));
2252 proto_item *ti;
2253 proto_tree *cfm_tree;
2255 /* isolate the payload of the packet */
2256 ti = proto_tree_add_item(tree, proto_cfm, tvb, 0, -1, ENC_NA);
2258 /* report type of CFM packet to base of dissection tree */
2259 proto_item_append_text(ti, ", Type %s",
2260 val_to_str(cfm_pdu_type, opcode_type_name_vals, "Unknown (0x%02x)"));
2262 /* dissecting the common CFM header */
2263 cfm_tree = proto_item_add_subtree(ti, ett_cfm);
2264 proto_tree_add_item(cfm_tree, hf_cfm_md_level, tvb, offset, 1, ENC_NA);
2265 proto_tree_add_item(cfm_tree, hf_cfm_version, tvb, offset, 1, ENC_NA);
2266 offset += 1;
2267 proto_tree_add_item(cfm_tree, hf_cfm_opcode, tvb, offset, 1, ENC_NA);
2268 offset += 1;
2270 switch (cfm_pdu_type) {
2271 case CCM:
2272 offset = dissect_cfm_ccm(tvb, pinfo, cfm_tree, offset);
2273 break;
2274 case LBM:
2275 offset = dissect_cfm_lbm(tvb, pinfo, cfm_tree, offset);
2276 break;
2277 case LBR:
2278 offset = dissect_cfm_lbr(tvb, pinfo, cfm_tree, offset);
2279 break;
2280 case LTM:
2281 offset = dissect_cfm_ltm(tvb, pinfo, cfm_tree, offset);
2282 break;
2283 case LTR:
2284 offset = dissect_cfm_ltr(tvb, pinfo, cfm_tree, offset);
2285 break;
2286 case RFM:
2287 offset = dissect_cfm_rfm(tvb, pinfo, cfm_tree, offset);
2288 break;
2289 case SFM:
2290 offset = dissect_cfm_sfm(tvb, pinfo, cfm_tree, offset);
2291 break;
2292 case GNM:
2293 offset = dissect_cfm_gnm(tvb, pinfo, cfm_tree, offset);
2294 break;
2295 case AIS:
2296 offset = dissect_cfm_ais(tvb, pinfo, cfm_tree, offset);
2297 break;
2298 case LCK:
2299 offset = dissect_cfm_lck(tvb, pinfo, cfm_tree, offset);
2300 break;
2301 case TST:
2302 offset = dissect_cfm_tst(tvb, pinfo, cfm_tree, offset);
2303 break;
2304 case APS:
2305 offset = dissect_cfm_aps(tvb, pinfo, cfm_tree, offset);
2306 break;
2307 case RAPS:
2308 offset = dissect_cfm_raps(tvb, pinfo, cfm_tree, offset);
2309 break;
2310 case MCC:
2311 offset = dissect_cfm_mcc(tvb, pinfo, cfm_tree, offset);
2312 break;
2313 case LMM:
2314 offset = dissect_cfm_lmm(tvb, pinfo, cfm_tree, offset);
2315 break;
2316 case LMR:
2317 offset = dissect_cfm_lmr(tvb, pinfo, cfm_tree, offset);
2318 break;
2319 case ODM:
2320 offset = dissect_cfm_odm(tvb, pinfo, cfm_tree, offset);
2321 break;
2322 case DMM:
2323 offset = dissect_cfm_dmm(tvb, pinfo, cfm_tree, offset);
2324 break;
2325 case DMR:
2326 offset = dissect_cfm_dmr(tvb, pinfo, cfm_tree, offset);
2327 break;
2328 case EXM:
2329 offset = dissect_cfm_exm(tvb, pinfo, cfm_tree, offset);
2330 break;
2331 case EXR:
2332 offset = dissect_cfm_exr(tvb, pinfo, cfm_tree, offset);
2333 break;
2334 case VSM:
2335 offset = dissect_cfm_vsm(tvb, pinfo, cfm_tree, offset);
2336 break;
2337 case VSR:
2338 offset = dissect_cfm_vsr(tvb, pinfo, cfm_tree, offset);
2339 break;
2340 case CSF:
2341 offset = dissect_cfm_csf(tvb, pinfo, cfm_tree, offset);
2342 break;
2343 case OSL:
2344 offset = dissect_cfm_osl(tvb, pinfo, cfm_tree, offset);
2345 break;
2346 case SLM:
2347 offset = dissect_cfm_slm(tvb, pinfo, cfm_tree, offset);
2348 break;
2349 case SLR:
2350 offset = dissect_cfm_slr(tvb, pinfo, cfm_tree, offset);
2351 break;
2352 default:
2353 offset = dissect_cfm_unknown(tvb, pinfo, cfm_tree, offset);
2354 break;
2357 /* Get the First TLV offset and add the offset of the common CFM header*/
2358 int cfm_first_tlv_offset = tvb_get_uint8(tvb, CFM_1ST_TLV_OFFSET) + CFM_COMMON_HEADER_LEN;
2360 /* The TLV offset should be the same as where the PDU left off or we have a problem */
2361 if (cfm_first_tlv_offset != offset) {
2362 // TODO: Report error, recover and continue
2363 cfm_first_tlv_offset = offset;
2366 /* Begin dissecting the TLV's */
2367 proto_item *cfm_all_tlvs_ti;
2368 proto_tree *cfm_all_tlvs_tree;
2369 cfm_all_tlvs_ti = proto_tree_add_item(cfm_tree, hf_cfm_all_tlvs, tvb, cfm_first_tlv_offset, -1, ENC_NA);
2370 cfm_all_tlvs_tree = proto_item_add_subtree(cfm_all_tlvs_ti, ett_cfm_all_tlvs);
2372 int cfm_tlv_offset = cfm_first_tlv_offset;
2376 uint8_t cfm_tlv_type;
2377 uint16_t cfm_tlv_length;
2378 proto_tree *cfm_tlv_tree;
2379 proto_item *cfm_tlv_ti, *expert_ti;
2380 int tlv_data_offset;
2381 bool test_id_length_bogus = false;
2383 cfm_tlv_type = tvb_get_uint8(tvb, cfm_tlv_offset);
2385 if (cfm_tlv_type == END_TLV) {
2386 cfm_tlv_tree = proto_tree_add_subtree_format(cfm_all_tlvs_tree, tvb, cfm_tlv_offset, 1,
2387 ett_cfm_tlv, NULL, "TLV: End TLV (t=0,l=0)");
2388 proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_type, tvb, cfm_tlv_offset, 1, ENC_NA);
2389 cfm_tlv_offset += 1;
2390 break;
2393 cfm_tlv_length = tvb_get_ntohs(tvb, cfm_tlv_offset+1);
2394 if (cfm_tlv_type == TEST_ID_TLV && cfm_tlv_length == 32) {
2395 /* ITU-T G.8013/Y.1731 9.14.2 indicates that the
2396 * Length of the Test ID TLV "must be 32" (indicating
2397 * the bit length?) even though the Value is 4 octets,
2398 * contradicting IEEE 802.1Q 21.5 TLV format:
2399 * "The 16 bits of the Length field indicate the size,
2400 * in octets, of the Value field."
2402 cfm_tlv_length = 4;
2403 test_id_length_bogus = true;
2406 cfm_tlv_tree = proto_tree_add_subtree_format(cfm_all_tlvs_tree, tvb, cfm_tlv_offset, cfm_tlv_length+3,
2407 ett_cfm_tlv, NULL, "TLV: %s (t=%d,l=%d)", val_to_str(cfm_tlv_type, tlv_type_field_vals, "Unknown (0x%02x)"),
2408 cfm_tlv_type, cfm_tlv_length);
2410 proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_type, tvb, cfm_tlv_offset, 1, ENC_NA);
2411 cfm_tlv_offset += 1;
2413 cfm_tlv_ti = proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_length, tvb, cfm_tlv_offset, 2, ENC_BIG_ENDIAN);
2414 if (test_id_length_bogus) {
2415 expert_add_info(pinfo, cfm_tlv_ti, &ei_tlv_tst_id_length);
2417 cfm_tlv_offset += 2;
2419 if (cfm_tlv_length == 0)
2420 continue;
2422 tlv_data_offset = cfm_tlv_offset;
2424 switch(cfm_tlv_type) {
2425 case SENDER_ID_TLV:
2427 uint8_t tlv_chassis_id_length;
2429 proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_length,
2430 tvb, tlv_data_offset, 1, ENC_NA);
2431 tlv_chassis_id_length = tvb_get_uint8(tvb,tlv_data_offset);
2432 tlv_data_offset += 1;
2434 if (tlv_chassis_id_length > 0) {
2435 tlv_data_offset = sender_id_tlv_chassis_id(cfm_tlv_tree, tvb, tlv_data_offset, tlv_chassis_id_length);
2438 /* IEEE 802.1Q 21.5.3.2 If the Chassis ID Length field
2439 * is 0, then the Chassis ID Subtype is not present.
2441 uint16_t chassis_id_tot_length = tlv_chassis_id_length ? 2 + tlv_chassis_id_length : 1;
2442 /* If the TLV length is greater than the number of octets used for the
2443 * Chassis ID, then we must have a Management Address Domain
2445 if (cfm_tlv_length > chassis_id_tot_length) {
2446 uint8_t tlv_ma_domain_length;
2447 void *tlv_ma_domain_oid = NULL;
2448 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain_length,
2449 tvb, tlv_data_offset, 1, ENC_NA);
2450 tlv_ma_domain_length = tvb_get_uint8(tvb, tlv_data_offset);
2451 tlv_data_offset += 1;
2452 if (tlv_ma_domain_length > 0) {
2453 // Ref ITU-T X690-2002 for OID. RFC 2579 for TDomain.
2454 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain,
2455 tvb, tlv_data_offset, tlv_ma_domain_length, ENC_NA);
2456 tlv_ma_domain_oid = tvb_memdup(pinfo->pool, tvb, tlv_data_offset, tlv_ma_domain_length);
2457 tlv_data_offset += tlv_ma_domain_length;
2460 /* If the TLV length is greater than the number of octets used for the
2461 * Chassis ID and the Management Address Domain, then we must have a
2462 * Management Address
2464 if (cfm_tlv_length > (chassis_id_tot_length + 1 + tlv_ma_domain_length)) {
2465 uint8_t tlv_management_addr_length;
2466 expert_ti = proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr_length,
2467 tvb, tlv_data_offset, 1, ENC_NA);
2468 /* IEEE 802.1Q 21.5.3.6 "[Management Address Length] is not
2469 * present if the Management Address Domain Length is not
2470 * present or contains a 0."
2472 if (tlv_ma_domain_length == 0) {
2473 expert_add_info(pinfo, expert_ti, &ei_tlv_management_addr_length);
2475 tlv_management_addr_length = tvb_get_uint8(tvb, tlv_data_offset);
2476 tlv_data_offset += 1;
2477 if (tlv_management_addr_length > 0) {
2478 tlv_data_offset = sender_id_tlv_management_address(cfm_tlv_tree, tvb, tlv_ma_domain_oid,
2479 tlv_ma_domain_length, tlv_data_offset,
2480 tlv_management_addr_length);
2484 break;
2486 case PORT_STAT_TLV:
2487 proto_tree_add_item(cfm_tlv_tree, hf_tlv_port_status_value,
2488 tvb, tlv_data_offset, 1, ENC_NA);
2489 tlv_data_offset += 1;
2490 break;
2491 case DATA_TLV:
2492 proto_tree_add_item(cfm_tlv_tree, hf_tlv_data_value,
2493 tvb, tlv_data_offset, cfm_tlv_length, ENC_NA);
2494 tlv_data_offset += cfm_tlv_length;
2495 break;
2496 case INTERF_STAT_TLV:
2497 proto_tree_add_item(cfm_tlv_tree, hf_tlv_interface_status_value,
2498 tvb, tlv_data_offset, 1, ENC_NA);
2499 tlv_data_offset += 1;
2500 break;
2501 case REPLY_ING_TLV:
2502 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_action,
2503 tvb, tlv_data_offset, 1, ENC_NA);
2504 tlv_data_offset += 1;
2505 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_mac_address,
2506 tvb, tlv_data_offset, 6, ENC_NA);
2507 tlv_data_offset += 6;
2509 /* For the IEEE standard if the TLV length is greater than 7 then we have an ingress port ID */
2510 if (cfm_tlv_length > 7) {
2511 uint8_t tlv_reply_ingress_portid_length;
2512 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
2513 tvb, tlv_data_offset, 1, ENC_NA);
2514 tlv_reply_ingress_portid_length = tvb_get_uint8(tvb,tlv_data_offset);
2515 tlv_data_offset += 1;
2517 if (tlv_reply_ingress_portid_length > 0) {
2518 tlv_data_offset = reply_ing_egr_tlv_port_id(cfm_tlv_tree, tvb, tlv_data_offset, tlv_reply_ingress_portid_length);
2519 } else {
2520 // TODO: Report error, cannot be zero.
2523 break;
2524 case REPLY_EGR_TLV:
2525 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_action,
2526 tvb, tlv_data_offset, 1, ENC_NA);
2527 tlv_data_offset += 1;
2528 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_mac_address,
2529 tvb, tlv_data_offset, 6, ENC_NA);
2530 tlv_data_offset += 6;
2532 /* For the IEEE standard if the TLV length is greater than 7 then we have an egress port ID */
2533 if (cfm_tlv_length > 7) {
2534 uint8_t tlv_reply_egress_portid_length;
2535 proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
2536 tvb, tlv_data_offset, 1, ENC_NA);
2537 tlv_reply_egress_portid_length = tvb_get_uint8(tvb,tlv_data_offset);
2538 tlv_data_offset += 1;
2540 if (tlv_reply_egress_portid_length > 0) {
2541 tlv_data_offset = reply_ing_egr_tlv_port_id(cfm_tlv_tree, tvb, tlv_data_offset, tlv_reply_egress_portid_length);
2542 } else {
2543 // TODO: Report error, cannot be zero.
2546 break;
2547 case LTM_EGR_ID_TLV:
2548 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_unique_identifier,
2549 tvb, tlv_data_offset, 2, ENC_NA);
2550 tlv_data_offset += 2;
2551 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_mac,
2552 tvb, tlv_data_offset, 6, ENC_NA);
2553 tlv_data_offset += 6;
2554 break;
2555 case LTR_EGR_ID_TLV:
2556 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_last_id_unique_identifier,
2557 tvb, tlv_data_offset, 2, ENC_NA);
2558 tlv_data_offset += 2;
2559 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_last_id_mac,
2560 tvb, tlv_data_offset, 6, ENC_NA);
2561 tlv_data_offset += 6;
2562 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_next_id_unique_identifier,
2563 tvb, tlv_data_offset, 2, ENC_NA);
2564 tlv_data_offset += 2;
2565 proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_next_id_mac,
2566 tvb, tlv_data_offset, 6, ENC_NA);
2567 tlv_data_offset += 6;
2568 break;
2569 case PPB_TE_MIP_TLV:
2570 proto_tree_add_item(cfm_tlv_tree, hf_tlv_pbb_te_mip_mac_address,
2571 tvb, tlv_data_offset, 6, ENC_NA);
2572 tlv_data_offset += 6;
2573 proto_tree_add_item(cfm_tlv_tree, hf_tlv_pbb_te_reverse_vid,
2574 tvb, tlv_data_offset, 2, ENC_BIG_ENDIAN);
2575 tlv_data_offset += 2;
2576 proto_tree_add_item(cfm_tlv_tree, hf_tlv_pbb_te_reverse_mac,
2577 tvb, tlv_data_offset, 6, ENC_NA);
2578 tlv_data_offset += 6;
2579 break;
2580 case DATA_PART1_TLV:
2581 case TRUNC_DATA_TLV:
2582 // TODO: hand off to ethertype dissector
2583 proto_tree_add_item(cfm_tlv_tree, hf_tlv_data_value,
2584 tvb, tlv_data_offset, cfm_tlv_length, ENC_NA);
2585 tlv_data_offset += cfm_tlv_length;
2586 break;
2587 case DATA_PART2_TLV:
2588 // NOTE: Appended to DATA_PART1_TLV this makes a complete Ethernet frame
2589 proto_tree_add_item(cfm_tlv_tree, hf_tlv_data_value,
2590 tvb, tlv_data_offset, cfm_tlv_length, ENC_NA);
2591 tlv_data_offset += cfm_tlv_length;
2592 break;
2593 case ORG_SPEC_TLV:
2594 if (cfm_tlv_length > 3) {
2595 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_oui,
2596 tvb, tlv_data_offset, 3, ENC_BIG_ENDIAN);
2597 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_subtype,
2598 tvb, tlv_data_offset + 3, 1, ENC_NA);
2599 // TODO: introduce subdissector table for this
2600 proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_value,
2601 tvb, tlv_data_offset + 4, cfm_tlv_length-4, ENC_NA);
2602 } else {
2603 // TODO: report error
2605 tlv_data_offset += cfm_tlv_length;
2606 break;
2607 case TEST_TLV:
2609 uint32_t tlv_tst_test_pattern_type;
2611 proto_tree_add_item_ret_uint(cfm_tlv_tree, hf_tlv_tst_test_pattern_type,
2612 tvb, tlv_data_offset, 1, ENC_NA, &tlv_tst_test_pattern_type);
2613 tlv_data_offset += 1;
2614 if (cfm_tlv_length > 1) {
2615 switch (tlv_tst_test_pattern_type) {
2616 case 0:
2617 case 2:
2618 default:
2619 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_test_pattern,
2620 tvb, tlv_data_offset, cfm_tlv_length - 1, ENC_NA);
2621 tlv_data_offset += cfm_tlv_length - 1;
2622 break;
2623 case 1:
2624 case 3:
2625 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_test_pattern,
2626 tvb, tlv_data_offset, cfm_tlv_length - 5, ENC_NA);
2627 tlv_data_offset += cfm_tlv_length - 5;
2628 // TODO: look at using proto_tree_add_checksum()
2629 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_CRC32,
2630 tvb, tlv_data_offset, 4, ENC_NA);
2631 tlv_data_offset += 4;
2632 break;
2634 } else {
2635 // TODO: report error
2637 break;
2639 case TGT_MEP_MIP_ID_TLV:
2640 case RPL_MEP_MIP_ID_TLV:
2642 uint32_t mep_mip_id_subtype;
2644 proto_tree_add_item_ret_uint(cfm_tlv_tree, hf_tlv_tgt_rpl_mep_mip_id_subtype,
2645 tvb, tlv_data_offset, 1, ENC_NA, &mep_mip_id_subtype);
2646 tlv_data_offset += 1;
2647 if (cfm_tlv_length > 1) {
2648 switch (mep_mip_id_subtype) {
2649 case 0x00: // Discovery ingress/node MEP/MIP
2650 case 0x01: // Discovery egress MEP/MIP
2651 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_padding,
2652 tvb, tlv_data_offset, cfm_tlv_length - 1, ENC_NA);
2653 break;
2654 case 0x02: // MEP ID
2655 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_mep_id,
2656 tvb, tlv_data_offset, 2, ENC_BIG_ENDIAN);
2657 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_padding,
2658 tvb, tlv_data_offset + 2, cfm_tlv_length - 3, ENC_NA);
2659 break;
2660 case 0x03: // MIP ID
2661 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_mip_id_icc,
2662 tvb, tlv_data_offset, 6, ENC_ASCII|ENC_NA);
2663 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_mip_id_node_id,
2664 tvb, tlv_data_offset + 6, 4, ENC_BIG_ENDIAN);
2665 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_mip_id_if_num,
2666 tvb, tlv_data_offset + 10, 4, ENC_BIG_ENDIAN);
2667 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_mip_id_cc,
2668 tvb, tlv_data_offset + 14, 2, ENC_ASCII|ENC_NA);
2669 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_padding,
2670 tvb, tlv_data_offset + 16, cfm_tlv_length - 17, ENC_NA);
2671 break;
2672 default:
2673 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tgt_rpl_padding,
2674 tvb, tlv_data_offset, cfm_tlv_length - 1, ENC_NA);
2675 break;
2677 tlv_data_offset += cfm_tlv_length;
2678 } else {
2679 // TODO: report error
2681 break;
2683 case REQ_MEP_ID_TLV:
2684 proto_tree_add_item(cfm_tlv_tree, hf_tlv_req_mep_id_lb,
2685 tvb, tlv_data_offset, 1, ENC_NA);
2686 tlv_data_offset += 1;
2687 tlv_data_offset = dissect_mep_maid(tvb, pinfo, cfm_tlv_tree, tlv_data_offset);
2688 proto_tree_add_item(cfm_tlv_tree, hf_tlv_req_mep_id_reserved,
2689 tvb, tlv_data_offset, 2, ENC_NA);
2690 tlv_data_offset += 2;
2691 break;
2692 case TEST_ID_TLV:
2693 proto_tree_add_item(cfm_tlv_tree, hf_tlv_tst_id_test_id,
2694 tvb, tlv_data_offset, 4, ENC_NA);
2695 tlv_data_offset += 4;
2696 break;
2697 default:
2698 // TODO: report error
2699 proto_tree_add_item(cfm_tlv_tree, hf_tlv_unknown_data,
2700 tvb, tlv_data_offset, cfm_tlv_length, ENC_NA);
2701 tlv_data_offset += cfm_tlv_length;
2702 break;
2705 // TODO: add check here that matches tlv_data_offset to cfm_tlv_offset + cfm_tlv_length
2706 cfm_tlv_offset = tlv_data_offset;
2708 } while (true);
2710 proto_item_set_len(cfm_all_tlvs_ti, cfm_tlv_offset - cfm_first_tlv_offset);
2711 proto_item_set_len(ti, cfm_tlv_offset);
2713 return cfm_tlv_offset;
2716 /* Register CFM EOAM protocol */
2717 void proto_register_cfm(void)
2719 static hf_register_info hf[] = {
2720 /* CFM Common header */
2721 { &hf_cfm_md_level,
2722 { "CFM MD Level", "cfm.md_level", FT_UINT8,
2723 BASE_DEC, NULL, 0xe0, "MD level/MEG level", HFILL }
2725 { &hf_cfm_version,
2726 { "CFM Version", "cfm.version", FT_UINT8,
2727 BASE_DEC, NULL, 0x1f, NULL, HFILL }
2729 { &hf_cfm_opcode,
2730 { "CFM OpCode", "cfm.opcode", FT_UINT8,
2731 BASE_DEC, VALS(opcode_type_name_vals), 0x0, NULL, HFILL }
2733 { &hf_cfm_flags,
2734 { "Flags", "cfm.flags", FT_UINT8,
2735 BASE_HEX, NULL, 0x0, NULL, HFILL }
2737 { &hf_cfm_flags_Reserved,
2738 { "Reserved", "cfm.flags.reserved", FT_UINT8,
2739 BASE_HEX, NULL, 0x0, NULL, HFILL }
2741 { &hf_cfm_first_tlv_offset,
2742 { "First TLV Offset", "cfm.first_tlv_offset", FT_UINT8,
2743 BASE_DEC, NULL, 0x0, NULL, HFILL }
2746 /* MEP and MAID */
2747 { &hf_cfm_mep_id,
2748 { "Maintenance Association Endpoint Identifier", "cfm.mep_id",
2749 FT_UINT16, BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
2751 { &hf_cfm_maid,
2752 { "Maintenance Association Identifier", "cfm.maid", FT_NONE,
2753 BASE_NONE, NULL, 0x0, "MEG ID (G.8013/Y.1731)", HFILL }
2755 { &hf_cfm_maid_md_name_format,
2756 { "MD Name Format", "cfm.maid.md_name.format", FT_UINT8,
2757 BASE_DEC, VALS(md_name_format_type_vals), 0x0, "Reserved (01) in G.8013/Y.1731", HFILL }
2759 { &hf_cfm_maid_md_name_length,
2760 { "MD Name Length", "cfm.maid.md_name.length", FT_UINT8,
2761 BASE_DEC, NULL, 0x0, "MEG ID length (G.8013/Y.1731)", HFILL }
2763 { &hf_cfm_maid_md_name_string,
2764 { "MD Name (String)", "cfm.maid.md_name.string", FT_STRING,
2765 BASE_NONE, NULL, 0x0, NULL, HFILL }
2767 { &hf_cfm_maid_md_name_hex,
2768 { "MD Name", "cfm.maid.md_name.hex", FT_BYTES,
2769 BASE_NONE, NULL, 0x0, NULL, HFILL }
2771 { &hf_cfm_maid_md_name_mac,
2772 { "MD Name (MAC+ID)", "cfm.maid.md_name.mac", FT_ETHER,
2773 BASE_NONE, NULL, 0x0, NULL, HFILL }
2775 { &hf_cfm_maid_md_name_mac_id,
2776 { "MD Name (MAC+ID)", "cfm.maid.md_name.mac.id", FT_BYTES,
2777 BASE_NONE, NULL, 0x0, NULL, HFILL }
2779 { &hf_cfm_maid_ma_name_format,
2780 { "Short MA Name (MEG ID) Format", "cfm.maid.ma_name.format", FT_UINT8,
2781 BASE_DEC, VALS(ma_name_format_type_vals), 0x0, NULL, HFILL }
2783 { &hf_cfm_maid_ma_name_length,
2784 { "Short MA Name (MEG ID) Length", "cfm.maid.ma_name.length", FT_UINT8,
2785 BASE_DEC, NULL, 0x0, NULL, HFILL }
2787 { &hf_cfm_maid_ma_name_pvid,
2788 { "Short MA Name PVID", "cfm.maid.ma_name.pvid", FT_UINT16,
2789 BASE_DEC, NULL, 0x0FFF, NULL, HFILL },
2791 { &hf_cfm_maid_ma_name_string,
2792 { "Short MA Name", "cfm.maid.ma_name.string", FT_STRING,
2793 BASE_NONE, NULL, 0x0, NULL, HFILL }
2795 { &hf_cfm_maid_ma_name_id,
2796 { "Short MA Name ID", "cfm.maid.ma_name.id", FT_UINT16,
2797 BASE_DEC, NULL, 0x0, NULL, HFILL },
2799 { &hf_cfm_maid_ma_name_vpnid_oui,
2800 { "Short MA Name VPN ID OUI", "cfm.maid.ma_name.vpnid.oui", FT_UINT24,
2801 BASE_OUI, NULL, 0x0, NULL, HFILL },
2803 { &hf_cfm_maid_ma_name_vpnid_index,
2804 { "Short MA Name VPN ID index", "cfm.maid.ma_name.vpnid.index", FT_UINT32,
2805 BASE_DEC, NULL, 0x0, NULL, HFILL },
2807 { &hf_cfm_maid_ma_name_icc_umc,
2808 { "MEG ID ICC", "cfm.maid.ma_name.icc", FT_STRING,
2809 BASE_NONE, NULL, 0x0, NULL, HFILL }
2811 { &hf_cfm_maid_ma_name_cc,
2812 { "MEG ID CC", "cfm.maid.ma_name.cc", FT_STRING,
2813 BASE_NONE, NULL, 0x0, NULL, HFILL }
2815 { &hf_cfm_maid_ma_name_hex,
2816 { "Short MA Name", "cfm.maid.ma_name.hex", FT_BYTES,
2817 BASE_NONE, NULL, 0x0, NULL, HFILL }
2819 { &hf_cfm_maid_padding,
2820 { "Zero-Padding", "cfm.ccm.maid.padding", FT_NONE,
2821 BASE_NONE, NULL, 0x0, NULL, HFILL }
2824 /* CFM CCM*/
2825 { &hf_cfm_ccm_pdu,
2826 { "CFM CCM PDU", "cfm.ccm.pdu", FT_NONE,
2827 BASE_NONE, NULL, 0x0, NULL, HFILL }
2829 { &hf_cfm_ccm_flags_RDI,
2830 { "RDI", "cfm.ccm.flags.rdi", FT_UINT8,
2831 BASE_DEC, NULL, 0x80, NULL, HFILL }
2833 { &hf_cfm_ccm_flags_Traffic,
2834 { "Traffic", "cfm.ccm.flags.traffic", FT_UINT8,
2835 BASE_DEC, NULL, 0x40, NULL, HFILL }
2837 { &hf_cfm_ccm_flags_Reserved,
2838 { "Reserved", "cfm.ccm.flags.reserved", FT_UINT8,
2839 BASE_DEC, NULL, 0x38, NULL, HFILL }
2841 { &hf_cfm_ccm_flags_Interval,
2842 { "Interval Field", "cfm.ccm.flags.interval", FT_UINT8,
2843 BASE_DEC, VALS(ccm_interval_field_encoding_vals), 0x07, NULL, HFILL }
2845 { &hf_cfm_ccm_seq_number,
2846 { "Sequence Number", "cfm.ccm.seq_num", FT_UINT32,
2847 BASE_DEC, NULL, 0x0, NULL, HFILL }
2849 { &hf_cfm_ccm_itu_t_y1731,
2850 { "Defined by ITU-T Y.1731", "cfm.ccm.itu", FT_NONE,
2851 BASE_NONE, NULL, 0x0, NULL, HFILL }
2853 { &hf_cfm_ccm_itu_TxFCf,
2854 { "TxFCf", "cfm.ccm.itu.txfcf", FT_UINT32,
2855 BASE_DEC, NULL, 0x0, NULL, HFILL }
2857 { &hf_cfm_ccm_itu_RxFCb,
2858 { "RxFCb", "cfm.ccm.itu.rxfcb", FT_UINT32,
2859 BASE_DEC, NULL, 0x0, NULL, HFILL }
2861 { &hf_cfm_ccm_itu_TxFCb,
2862 { "TxFCb", "cfm.ccm.itu.txfcb", FT_UINT32,
2863 BASE_DEC, NULL, 0x0, NULL, HFILL }
2865 { &hf_cfm_ccm_itu_reserved,
2866 { "Reserved", "cfm.ccm.itu.reserved", FT_BYTES,
2867 BASE_NONE, NULL, 0x0, NULL, HFILL }
2870 /* CFM LBM*/
2871 { &hf_cfm_lbm_pdu,
2872 { "CFM LBM PDU", "cfm.lbm.pdu", FT_NONE,
2873 BASE_NONE, NULL, 0x0, NULL, HFILL }
2875 { &hf_cfm_lbm_lbr_transaction_id,
2876 { "Loopback Transaction Identifier", "cfm.lbm.lbr.transaction_id", FT_UINT32,
2877 BASE_DEC, NULL, 0x0, NULL, HFILL }
2880 /* CFM LBR*/
2881 { &hf_cfm_lbr_pdu,
2882 { "CFM LBR PDU", "cfm.lbr.pdu", FT_NONE,
2883 BASE_NONE, NULL, 0x0, NULL, HFILL }
2886 /* CFM LTM*/
2887 { &hf_cfm_ltm_pdu,
2888 { "CFM LTM PDU", "cfm.ltm.pdu", FT_NONE,
2889 BASE_NONE, NULL, 0x0, NULL, HFILL }
2891 { &hf_cfm_ltm_flags_UseFDBonly,
2892 { "UseFDBonly", "cfm.ltm.flags.usefdbonly", FT_UINT8,
2893 BASE_DEC, NULL, 0x80, NULL, HFILL }
2895 { &hf_cfm_ltm_flags_Reserved,
2896 { "Reserved", "cfm.ltm.flags.reserved", FT_UINT8,
2897 BASE_DEC, NULL, 0x7F, NULL, HFILL }
2899 { &hf_cfm_ltm_ltr_transaction_id,
2900 { "Linktrace Transaction Identifier", "cfm.ltm.ltr.transaction_id", FT_UINT32,
2901 BASE_DEC, NULL, 0x0, NULL, HFILL }
2903 { &hf_cfm_ltm_ltr_ttl,
2904 { "Linktrace TTL", "cfm.ltm.ltr.ttl", FT_UINT8,
2905 BASE_DEC, NULL, 0x0, NULL, HFILL }
2907 { &hf_cfm_ltm_orig_addr,
2908 { "Linktrace Message: Original Address", "cfm.ltm.orig_addr", FT_ETHER,
2909 BASE_NONE, NULL, 0x0, NULL, HFILL }
2911 { &hf_cfm_ltm_targ_addr,
2912 { "Linktrace Message: Target Address", "cfm.ltm.target_addr", FT_ETHER,
2913 BASE_NONE, NULL, 0x0, NULL, HFILL }
2916 /* CFM LTR*/
2917 { &hf_cfm_ltr_pdu,
2918 { "CFM LTR PDU", "cfm.ltr.pdu", FT_NONE,
2919 BASE_NONE, NULL, 0x0, NULL, HFILL }
2921 { &hf_cfm_ltr_flags_UseFDBonly,
2922 { "UseFDBonly", "cfm.ltr.flags.usefdbonly", FT_UINT8,
2923 BASE_DEC, NULL, 0x80, NULL, HFILL }
2925 { &hf_cfm_ltr_flags_FwdYes,
2926 { "FwdYes", "cfm.ltr.flags.fwdyes", FT_UINT8,
2927 BASE_DEC, NULL, 0x40, NULL, HFILL }
2929 { &hf_cfm_ltr_flags_TerminalMEP,
2930 { "TerminalMEP", "cfm.ltr.flags.terminalmep", FT_UINT8,
2931 BASE_DEC, NULL, 0x20, NULL, HFILL }
2933 { &hf_cfm_ltr_flags_Reserved,
2934 { "Reserved", "cfm.ltr.flags.reserved", FT_UINT8,
2935 BASE_DEC, NULL, 0x1F, NULL, HFILL }
2937 { &hf_cfm_ltr_relay_action,
2938 { "Linktrace Reply Relay Action", "cfm.ltr.relay_action", FT_UINT8,
2939 BASE_DEC, VALS(relay_action_type_vals), 0x0, NULL, HFILL }
2942 /* CFM RFM */
2943 { &hf_cfm_rfm_pdu,
2944 { "CFM RFM PDU", "cfm.rfm.pdu", FT_NONE,
2945 BASE_NONE, NULL, 0x0, NULL, HFILL }
2947 { &hf_cfm_rfm_transaction_id,
2948 { "RFM Transaction Identifier", "cfm.rfm.transaction_id", FT_UINT32,
2949 BASE_DEC, NULL, 0x0, NULL, HFILL }
2952 /* CFM SFM */
2953 { &hf_cfm_sfm_pdu,
2954 { "CFM SFM PDU", "cfm.sfm.pdu", FT_NONE,
2955 BASE_NONE, NULL, 0x0, NULL, HFILL }
2957 { &hf_cfm_sfm_transaction_id,
2958 { "SFM Transaction Identifier", "cfm.sfm.transaction_id", FT_UINT32,
2959 BASE_DEC, NULL, 0x0, NULL, HFILL }
2962 /* CFM GNM */
2963 { &hf_cfm_gnm_pdu,
2964 { "CFM GNM PDU", "cfm.gnm.pdu", FT_NONE,
2965 BASE_NONE, NULL, 0x0, NULL, HFILL }
2967 { &hf_cfm_gnm_unknown_flags,
2968 { "Unknown flags", "cfm.gnm.unknown.flags", FT_UINT8,
2969 BASE_HEX, NULL, 0x0, NULL, HFILL }
2971 { &hf_cfm_gnm_subopcode,
2972 { "Sub-OpCode", "cfm.gnm.subopcode", FT_UINT8,
2973 BASE_HEX, VALS(gnm_sub_opcode_type_name_vals), 0x0, NULL, HFILL }
2976 /* CFM BNM*/
2977 { &hf_cfm_bnm_flags_Reserved,
2978 { "Reserved", "cfm.bnm.flags.Reserved", FT_UINT8,
2979 BASE_DEC, NULL, 0xF8, NULL, HFILL }
2981 { &hf_cfm_bnm_flags_Period,
2982 { "Period", "cfm.bnm.flags.Period", FT_UINT8,
2983 BASE_DEC, VALS(cfm_bnm_flags_period_vals), 0x07, NULL, HFILL }
2985 { &hf_cfm_bnm_pdu,
2986 { "CFM BNM PDU", "cfm.bnm.pdu", FT_NONE,
2987 BASE_NONE, NULL, 0x0, NULL, HFILL }
2989 { &hf_cfm_bnm_nominal_bw,
2990 { "Nominal Bandwidth", "cfm.bnm.nominal_bw", FT_UINT32,
2991 BASE_DEC, NULL, 0x0, NULL, HFILL }
2993 { &hf_cfm_bnm_current_bw,
2994 { "Current Bandwidth", "cfm.bnm.current_bw", FT_UINT32,
2995 BASE_DEC, NULL, 0x0, NULL, HFILL }
2997 { &hf_cfm_bnm_port_id,
2998 { "Port ID", "cfm.bnm.port_id", FT_UINT32,
2999 BASE_DEC, NULL, 0x0, NULL, HFILL }
3002 /* CFM AIS*/
3003 { &hf_cfm_ais_pdu,
3004 { "CFM AIS PDU", "cfm.ais.pdu", FT_NONE,
3005 BASE_NONE, NULL, 0x0, NULL, HFILL }
3007 { &hf_cfm_ais_flags_Reserved,
3008 { "Reserved", "cfm.ais.flags.Reserved", FT_UINT8,
3009 BASE_DEC, NULL, 0xF8, NULL, HFILL }
3011 { &hf_cfm_ais_flags_Period,
3012 { "Period", "cfm.ais.flags.Period", FT_UINT8,
3013 BASE_DEC, VALS(ais_lck_period_type_vals), 0x07, NULL, HFILL }
3016 /* CFM LCK */
3017 { &hf_cfm_lck_pdu,
3018 { "CFM LCK PDU", "cfm.lck.pdu", FT_NONE,
3019 BASE_NONE, NULL, 0x0, NULL, HFILL }
3021 { &hf_cfm_lck_flags_Reserved,
3022 { "Reserved", "cfm.lck.flags.Reserved", FT_UINT8,
3023 BASE_DEC, NULL, 0xF8, NULL, HFILL }
3025 { &hf_cfm_lck_flags_Period,
3026 { "Period", "cfm.lck.flags.Period", FT_UINT8,
3027 BASE_DEC, VALS(ais_lck_period_type_vals), 0x07, NULL, HFILL }
3030 /* CFM TST */
3031 { &hf_cfm_tst_pdu,
3032 { "CFM TST PDU", "cfm.tst.pdu", FT_NONE,
3033 BASE_NONE, NULL, 0x0, NULL, HFILL }
3035 { &hf_cfm_tst_sequence_num,
3036 { "Sequence Number", "cfm.tst.sequence_num", FT_UINT32,
3037 BASE_DEC, NULL, 0x0, NULL, HFILL }
3040 /* CFM APS */
3041 { &hf_cfm_aps_pdu,
3042 { "CFM APS PDU", "cfm.aps.pdu", FT_NONE,
3043 BASE_NONE, NULL, 0x0, NULL, HFILL }
3045 { &hf_cfm_aps_req_st,
3046 { "Request/State", "cfm.aps.req_st", FT_UINT8,
3047 BASE_DEC, VALS(aps_request_state_vals), 0xf0, NULL, HFILL }
3049 { &hf_cfm_aps_protection_type_A,
3050 { "Protection type A", "cfm.aps.protec.type_A", FT_BOOLEAN,
3051 8, TFS(&tfs_aps_protection_type_A), 0x08, NULL, HFILL }
3053 { &hf_cfm_aps_protection_type_B,
3054 { "Protection type B", "cfm.aps.protec.type_B", FT_BOOLEAN,
3055 8, TFS(&tfs_aps_protection_type_B), 0x04, NULL, HFILL }
3057 { &hf_cfm_aps_protection_type_D,
3058 { "Protection type D", "cfm.aps.protec.type_D", FT_BOOLEAN,
3059 8, TFS(&tfs_aps_protection_type_D), 0x02, NULL, HFILL }
3061 { &hf_cfm_aps_protection_type_R,
3062 { "Protection type R", "cfm.aps.protec.type_R", FT_BOOLEAN,
3063 8, TFS(&tfs_aps_protection_type_R), 0x01, NULL, HFILL }
3065 { &hf_cfm_aps_requested_signal,
3066 { "Requested signal", "cfm.aps.req_signal", FT_UINT8,
3067 BASE_HEX, VALS(aps_requested_signal_values), 0x0, NULL, HFILL }
3069 { &hf_cfm_aps_bridged_signal,
3070 { "Bridged signal", "cfm.aps.bridged_signal", FT_UINT8,
3071 BASE_HEX, VALS(aps_bridged_signal_values), 0x0, NULL, HFILL }
3073 { &hf_cfm_aps_bridge_type,
3074 { "Bridge type", "cfm.aps.bridge_type", FT_UINT8,
3075 BASE_HEX, VALS(aps_bridge_type_values), 0x80, NULL, HFILL }
3078 /* CFM R-APS */
3079 { &hf_cfm_raps_pdu,
3080 { "CFM R-APS PDU", "cfm.raps.pdu", FT_NONE,
3081 BASE_NONE, NULL, 0x0, NULL, HFILL }
3083 { &hf_cfm_raps_req_st,
3084 { "Request/State", "cfm.raps.req_st", FT_UINT8,
3085 BASE_HEX, VALS(raps_request_state_values), RAPS_REQ_ST_MASK, NULL, HFILL }
3087 { &hf_cfm_raps_event_subcode,
3088 { "Sub-code", "cfm.raps.event.subcode", FT_UINT8,
3089 BASE_HEX, VALS(rasp_event_subcode_vals), RAPS_SUB_CODE_MASK, NULL, HFILL }
3091 { &hf_cfm_raps_subcode_reserved,
3092 { "Reserved", "cfm.raps.subcode.reserved", FT_UINT8,
3093 BASE_HEX, NULL, RAPS_SUB_CODE_MASK, NULL, HFILL }
3095 { &hf_cfm_raps_status,
3096 { "R-APS status", "cfm.raps.status", FT_UINT8,
3097 BASE_HEX, NULL, 0x0, NULL, HFILL }
3099 { &hf_cfm_raps_status_rb,
3100 { "RPL Blocked", "cfm.raps.status.rb", FT_BOOLEAN,
3101 8, TFS(&tfs_rasp_rpl_blocked), 0x80, NULL, HFILL }
3103 { &hf_cfm_raps_status_dnf,
3104 { "Do Not Flush", "cfm.raps.status.dnf", FT_BOOLEAN,
3105 8, TFS(&tfs_rasp_dnf), 0x40, NULL, HFILL }
3107 { &hf_cfm_raps_status_bpr,
3108 { "Blocked Port Reference", "cfm.raps.status.bpr", FT_BOOLEAN,
3109 8, TFS(&tfs_rasp_bpr), 0x20, NULL, HFILL }
3111 { &hf_cfm_raps_status_reserved_v1,
3112 { "Reserved", "cfm.raps.status.reserved_v1", FT_UINT8,
3113 BASE_HEX, NULL, 0x3F, NULL, HFILL }
3115 { &hf_cfm_raps_status_reserved_v2,
3116 { "Reserved", "cfm.raps.status.reserved_v2", FT_UINT8,
3117 BASE_HEX, NULL, 0x1F, NULL, HFILL }
3119 { &hf_cfm_raps_node_id,
3120 { "R-APS Node ID", "cfm.raps.node_id", FT_ETHER,
3121 BASE_NONE, NULL, 0x0, NULL, HFILL }
3123 { &hf_cfm_raps_reserved,
3124 { "R-APS Reserved", "cfm.raps.reserved", FT_BYTES,
3125 BASE_NONE, NULL, 0x0, NULL, HFILL }
3128 /* CFM MCC */
3129 { &hf_cfm_mcc_pdu,
3130 { "CFM MCC PDU", "cfm.mcc.pdu", FT_NONE,
3131 BASE_NONE, NULL, 0x0, NULL, HFILL }
3133 { &hf_cfm_mcc_oui,
3134 { "OUI", "cfm.mcc.oui", FT_UINT24,
3135 BASE_OUI, NULL, 0x0, NULL, HFILL }
3137 { &hf_cfm_mcc_subopcode,
3138 { "Subopcode", "cfm.mcc.subopcode", FT_UINT8,
3139 BASE_DEC, NULL, 0x0, NULL, HFILL }
3141 { &hf_cfm_mcc_data,
3142 { "MCC data", "cfm.mcc.data", FT_BYTES,
3143 BASE_NONE, NULL, 0x0, NULL, HFILL }
3146 /* CFM LMM */
3147 { &hf_cfm_lmm_pdu,
3148 { "CFM LMM PDU", "cfm.lmm.pdu", FT_NONE,
3149 BASE_NONE, NULL, 0x0, NULL, HFILL }
3151 { &hf_cfm_lmm_lmr_flags_Reserved,
3152 { "Reserved", "cfm.lmm.lmr.flags.Reserved", FT_UINT8,
3153 BASE_HEX, NULL, 0xFE, NULL, HFILL }
3155 { &hf_cfm_lmm_lmr_flags_Type,
3156 { "Type", "cfm.lmm.lmr.flags.Type", FT_BOOLEAN,
3157 8, TFS(&tfs_lmm_lmr_type), 0x01, NULL, HFILL }
3159 { &hf_cfm_lmm_lmr_TxFCf,
3160 { "TxFCf", "cfm.lmm.lmr.txfcf", FT_UINT32,
3161 BASE_DEC, NULL, 0x0, NULL, HFILL }
3163 { &hf_cfm_lmm_lmr_RxFCf,
3164 { "RxFCf", "cfm.lmm.lmr.rxfcf", FT_UINT32,
3165 BASE_DEC, NULL, 0x0, NULL, HFILL }
3167 { &hf_cfm_lmm_lmr_TxFCb,
3168 { "TxFCb", "cfm.lmm.lmr.txfcb", FT_UINT32,
3169 BASE_DEC, NULL, 0x0, NULL, HFILL }
3172 /* CFM LMR */
3173 { &hf_cfm_lmr_pdu,
3174 { "CFM LMR PDU", "cfm.lmr.pdu", FT_NONE,
3175 BASE_NONE, NULL, 0x0, NULL, HFILL }
3178 /* CFM 1DM */
3179 { &hf_cfm_odm_pdu,
3180 { "CFM 1DM PDU", "cfm.odm.pdu", FT_NONE,
3181 BASE_NONE, NULL, 0x0, NULL, HFILL }
3183 { &hf_cfm_odm_dmm_dmr_flags_Reserved,
3184 { "Reserved", "cfm.odm.dmm.dmr.flags.Reserved", FT_UINT8,
3185 BASE_HEX, NULL, 0xFE, NULL, HFILL }
3187 { &hf_cfm_odm_dmm_dmr_flags_Type,
3188 { "Type", "cfm.odm.dmm.dmr.flags.Type", FT_BOOLEAN,
3189 8, TFS(&tfs_odm_dmm_dmr_type), 0x01, NULL, HFILL }
3191 { &hf_cfm_odm_dmm_dmr_TxTimestampf,
3192 { "TxTimestampf", "cfm.odm.dmm.dmr.txtimestampf", FT_RELATIVE_TIME,
3193 BASE_NONE, NULL, 0x0, NULL, HFILL }
3195 { &hf_cfm_odm_dmm_dmr_RxTimestampf,
3196 { "RxTimestampf", "cfm.odm.dmm.dmr.rxtimestampf", FT_RELATIVE_TIME,
3197 BASE_NONE, NULL, 0x0, NULL, HFILL }
3200 /* CFM DMM */
3201 { &hf_cfm_dmm_pdu,
3202 { "CFM DMM PDU", "cfm.dmm.pdu", FT_NONE,
3203 BASE_NONE, NULL, 0x0, NULL, HFILL }
3205 { &hf_cfm_dmm_dmr_TxTimestampb,
3206 { "TxTimestampb", "cfm.dmm.dmr.txtimestampb", FT_RELATIVE_TIME,
3207 BASE_NONE, NULL, 0x0, NULL, HFILL }
3209 { &hf_cfm_dmm_dmr_RxTimestampb,
3210 { "RxTimestampb", "cfm.dmm.dmr.rxtimestampb", FT_RELATIVE_TIME,
3211 BASE_NONE, NULL, 0x0, NULL, HFILL }
3214 /* CFM DMR */
3215 { &hf_cfm_dmr_pdu,
3216 { "CFM DMR PDU", "cfm.dmr.pdu", FT_NONE,
3217 BASE_NONE, NULL, 0x0, NULL, HFILL }
3220 /* CFM EXM */
3221 { &hf_cfm_exm_pdu,
3222 { "CFM EXM PDU", "cfm.exm.pdu", FT_NONE,
3223 BASE_NONE, NULL, 0x0, NULL, HFILL }
3225 { &hf_cfm_exm_oui,
3226 { "OUI", "cfm.exm.oui", FT_UINT24,
3227 BASE_OUI, NULL, 0x0, NULL, HFILL }
3229 { &hf_cfm_exm_subopcode,
3230 { "Subopcode", "cfm.exm.subopcode", FT_UINT8,
3231 BASE_DEC, NULL, 0x0, NULL, HFILL }
3233 { &hf_cfm_exm_data,
3234 { "EXM data", "cfm.exm.data", FT_BYTES,
3235 BASE_NONE, NULL, 0x0, NULL, HFILL }
3238 /* CFM EXR */
3239 { &hf_cfm_exr_pdu,
3240 { "CFM EXR PDU", "cfm.exr.pdu", FT_NONE,
3241 BASE_NONE, NULL, 0x0, NULL, HFILL }
3243 { &hf_cfm_exr_oui,
3244 { "OUI", "cfm.exr.oui", FT_UINT24,
3245 BASE_OUI, NULL, 0x0, NULL, HFILL }
3247 { &hf_cfm_exr_subopcode,
3248 { "Subopcode", "cfm.exr.subopcode", FT_UINT8,
3249 BASE_DEC, NULL, 0x0, NULL, HFILL }
3251 { &hf_cfm_exr_data,
3252 { "EXR data", "cfm.exr.data", FT_BYTES,
3253 BASE_NONE, NULL, 0x0, NULL, HFILL }
3256 /* CFM VSM */
3257 { &hf_cfm_vsm_pdu,
3258 { "CFM VSM PDU", "cfm.vsm.pdu", FT_NONE,
3259 BASE_NONE, NULL, 0x0, NULL, HFILL }
3261 { &hf_cfm_vsm_oui,
3262 { "OUI", "cfm.vsm.oui", FT_UINT24,
3263 BASE_OUI, NULL, 0x0, NULL, HFILL }
3265 { &hf_cfm_vsm_subopcode,
3266 { "Subopcode", "cfm.vsm.subopcode", FT_UINT8,
3267 BASE_DEC, NULL, 0x0, NULL, HFILL }
3269 { &hf_cfm_vsm_data,
3270 { "VSM data", "cfm.vsm.data", FT_BYTES,
3271 BASE_NONE, NULL, 0x0, NULL, HFILL }
3274 /* CFM VSR */
3275 { &hf_cfm_vsr_pdu,
3276 { "CFM VSR PDU", "cfm.vsr.pdu", FT_NONE,
3277 BASE_NONE, NULL, 0x0, NULL, HFILL }
3279 { &hf_cfm_vsr_oui,
3280 { "OUI", "cfm.vsr.oui", FT_UINT24,
3281 BASE_OUI, NULL, 0x0, NULL, HFILL }
3283 { &hf_cfm_vsr_subopcode,
3284 { "Subopcode", "cfm.vsr.subopcode", FT_UINT8,
3285 BASE_DEC, NULL, 0x0, NULL, HFILL }
3287 { &hf_cfm_vsr_data,
3288 { "VSR data", "cfm.vsr.data", FT_BYTES,
3289 BASE_NONE, NULL, 0x0, NULL, HFILL }
3292 /* CFM CSF */
3293 { &hf_cfm_csf_pdu,
3294 { "CFM CSF PDU", "cfm.csf.pdu", FT_NONE,
3295 BASE_NONE, NULL, 0x0, NULL, HFILL }
3297 { &hf_cfm_csf_flags_Reserved,
3298 { "Reserved", "cfm.csf.flags.Reserved", FT_UINT8,
3299 BASE_HEX, NULL, 0xC0, NULL, HFILL }
3301 { &hf_cfm_csf_flags_Type,
3302 { "Type", "cfm.csf.flags.Type", FT_UINT8,
3303 BASE_DEC, VALS(cfm_csf_flags_type_vals), 0x38, NULL, HFILL }
3305 { &hf_cfm_csf_flags_Period,
3306 { "Type", "cfm.csf.flags.Period", FT_UINT8,
3307 BASE_DEC, VALS(cfm_csf_flags_period_vals), 0x07, NULL, HFILL }
3310 /* CFM 1SL */
3311 { &hf_cfm_osl_pdu,
3312 { "CFM 1SL PDU", "cfm.osf.pdu", FT_NONE,
3313 BASE_NONE, NULL, 0x0, NULL, HFILL }
3315 { &hf_cfm_osl_src_mep,
3316 { "Source MEP ID", "cfm.osl.src_mep_id", FT_UINT16,
3317 BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
3319 { &hf_cfm_osl_reserved,
3320 { "1SL Reserved", "cfm.osl.reserved", FT_BYTES,
3321 BASE_NONE, NULL, 0x0, NULL, HFILL }
3323 { &hf_cfm_osl_testid,
3324 { "TestID", "cfm.osl.test_id", FT_BYTES,
3325 BASE_NONE, NULL, 0x0, NULL, HFILL }
3327 { &hf_cfm_osl_txfcf,
3328 { "TxFcF", "cfm.osl.txfcf", FT_UINT32,
3329 BASE_DEC, NULL, 0x0, NULL, HFILL }
3332 /* CFM SLM */
3333 { &hf_cfm_slm_pdu,
3334 { "CFM SLM PDU", "cfm.slm.pdu", FT_NONE,
3335 BASE_NONE, NULL, 0x0, NULL, HFILL }
3337 { &hf_cfm_slm_slr_src_mep,
3338 { "Source MEP ID", "cfm.slm.slr.src_mep_id", FT_UINT16,
3339 BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
3341 { &hf_cfm_slm_reserved,
3342 { "SLM Reserved", "cfm.slm.reserved", FT_BYTES,
3343 BASE_NONE, NULL, 0x0, NULL, HFILL }
3345 { &hf_cfm_slm_slr_testid,
3346 { "TestID", "cfm.slm.slr.test_id", FT_BYTES,
3347 BASE_NONE, NULL, 0x0, NULL, HFILL }
3349 { &hf_cfm_slm_slr_txfcf,
3350 { "TxFcF", "cfm.slm.slr.txfcf", FT_UINT32,
3351 BASE_DEC, NULL, 0x0, NULL, HFILL }
3354 /* CFM SLR */
3355 { &hf_cfm_slr_pdu,
3356 { "CFM SLR PDU", "cfm.slr.pdu", FT_NONE,
3357 BASE_NONE, NULL, 0x0, NULL, HFILL }
3359 { &hf_cfm_slr_rsp_mep,
3360 { "Responder MEP ID", "cfm.slr.rsp_mep_id", FT_UINT16,
3361 BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
3363 { &hf_cfm_slr_txfcb,
3364 { "TxFcB", "cfm.slr.txfcb", FT_UINT32,
3365 BASE_DEC, NULL, 0x0, NULL, HFILL }
3368 /* Unknown */
3369 { &hf_cfm_unknown_pdu,
3370 { "Unknown PDU", "cfm.unknown.pdu", FT_NONE,
3371 BASE_NONE, NULL, 0x0, NULL, HFILL }
3373 { &hf_cfm_unknown_flags,
3374 { "Unknown flags", "cfm.unknown.flags", FT_UINT8,
3375 BASE_HEX, NULL, 0x0, NULL, HFILL }
3377 { &hf_cfm_unknown_data,
3378 { "Unknown data", "cfm.unknown.data", FT_BYTES,
3379 BASE_NONE, NULL, 0x0, NULL, HFILL }
3382 /******************************* TLVs ****************************/
3383 { &hf_cfm_all_tlvs,
3384 { "CFM TLVs", "cfm.all_tlvs", FT_NONE,
3385 BASE_NONE, NULL, 0x0, NULL, HFILL }
3387 { &hf_cfm_tlv_type,
3388 { "TLV Type", "cfm.tlv.type", FT_UINT8,
3389 BASE_DEC, VALS(tlv_type_field_vals), 0x0, NULL, HFILL }
3391 { &hf_cfm_tlv_length,
3392 { "TLV Length", "cfm.tlv.length", FT_UINT16,
3393 BASE_DEC, NULL, 0x0, NULL, HFILL }
3395 /* Sender ID TLV */
3396 { &hf_tlv_chassis_id_length,
3397 { "Chassis ID Length", "cfm.tlv.sender_id.chassis_id.length", FT_UINT8,
3398 BASE_DEC, NULL, 0x0, NULL, HFILL }
3400 { &hf_tlv_chassis_id_subtype,
3401 { "Chassis ID Sub-type", "cfm.tlv.sender_id.chassis_id.subtype", FT_UINT8,
3402 BASE_DEC, VALS(sender_id_tlv_chassis_id_subtype_vals), 0x0, NULL, HFILL }
3404 { &hf_tlv_chassis_id_chassis_component,
3405 { "Chassis component", "cfm.tlv.sender_id.chassis_id.chassis_component", FT_STRINGZPAD,
3406 BASE_NONE, NULL, 0x0, NULL, HFILL }
3408 { &hf_tlv_chassis_id_interface_alias,
3409 { "Interface alias", "cfm.tlv.sender_id.chassis_id.intf_alias", FT_STRINGZPAD,
3410 BASE_NONE, NULL, 0x0, NULL, HFILL }
3412 { &hf_tlv_chassis_id_port_component,
3413 { "Port component", "cfm.tlv.sender_id.chassis_id.port_component", FT_BYTES,
3414 BASE_NONE, NULL, 0x0, NULL, HFILL }
3416 { &hf_tlv_chassis_id_mac_address,
3417 { "MAC address", "cfm.tlv.sender_id.chassis_id.mac_address", FT_ETHER,
3418 BASE_NONE, NULL, 0x0, NULL, HFILL }
3420 { &hf_tlv_chassis_id_network_address_family,
3421 { "Network address family", "cfm.tlv.sender_id.chassis_id.network_address.family", FT_UINT8,
3422 BASE_DEC, VALS(afn_vals), 0x0, NULL, HFILL }
3424 { &hf_tlv_chassis_id_network_address_ipv4,
3425 { "Network address", "cfm.tlv.sender_id.chassis_id.network_address.ipv4", FT_IPv4,
3426 BASE_NONE, NULL, 0x0, NULL, HFILL }
3428 { &hf_tlv_chassis_id_network_address_ipv6,
3429 { "Network address", "cfm.tlv.sender_id.chassis_id.network_address.ipv6", FT_IPv6,
3430 BASE_NONE, NULL, 0x0, NULL, HFILL }
3432 { &hf_tlv_chassis_id_network_address_unknown,
3433 { "Network address", "cfm.tlv.sender_id.chassis_id.network_address.unknown", FT_BYTES,
3434 BASE_NONE, NULL, 0x0, NULL, HFILL }
3436 { &hf_tlv_chassis_id_interface_name,
3437 { "Interface name", "cfm.tlv.sender_id.chassis_id.intf_name", FT_STRINGZPAD,
3438 BASE_NONE, NULL, 0x0, NULL, HFILL }
3440 { &hf_tlv_chassis_id_locally_assigned,
3441 { "Locally assigned", "cfm.tlv.sender_id.chassis_id.locally_assigned", FT_STRINGZPAD,
3442 BASE_NONE, NULL, 0x0, NULL, HFILL }
3444 { &hf_tlv_chassis_id_unknown,
3445 { "Unknown", "cfm.tlv.sender_id.chassis_id.unknown", FT_BYTES,
3446 BASE_NONE, NULL, 0x0, NULL, HFILL }
3448 { &hf_tlv_ma_domain_length,
3449 { "Management Address Domain Length", "cfm.tlv.sender_id.ma_domain.length", FT_UINT8,
3450 BASE_DEC, NULL, 0x0, NULL, HFILL }
3452 { &hf_tlv_ma_domain,
3453 { "Management Address Domain", "cfm.tlv.sender_id.ma_domain", FT_OID,
3454 BASE_NONE, NULL, 0x0, NULL, HFILL }
3456 { &hf_tlv_management_addr_length,
3457 { "Management Address Length", "cfm.tlv.sender_id.management_addr.length", FT_UINT8,
3458 BASE_DEC, NULL, 0x0, NULL, HFILL }
3460 { &hf_tlv_management_addr_ipv4,
3461 { "Management Address", "cfm.tlv.sender_id.management_addr.ipv4", FT_IPv4,
3462 BASE_NONE, NULL, 0x0, NULL, HFILL }
3464 { &hf_tlv_management_addr_ipv6,
3465 { "Management Address", "cfm.tlv.sender_id.management_addr.ipv6", FT_IPv6,
3466 BASE_NONE, NULL, 0x0, NULL, HFILL }
3468 { &hf_tlv_management_addr_eth,
3469 { "Management Address", "cfm.tlv.sender_id.management_addr.eth", FT_ETHER,
3470 BASE_NONE, NULL, 0x0, NULL, HFILL }
3472 { &hf_tlv_management_addr_unknown,
3473 { "Management Address", "cfm.tlv.sender_id.management_addr.unknown", FT_BYTES,
3474 BASE_NONE, NULL, 0x0, NULL, HFILL }
3477 /* Port Status TLV */
3478 { &hf_tlv_port_status_value,
3479 { "Port Status value", "cfm.tlv.port_status.value", FT_UINT8,
3480 BASE_DEC, VALS(port_stat_tlv_vals), 0x0, NULL, HFILL }
3483 /* Data TLV, Truncated Data TLV, Data Part 1 TLV, Data Part 2 TLV */
3484 { &hf_tlv_data_value,
3485 { "Data Value", "cfm.tlv.data.value", FT_BYTES,
3486 BASE_NONE, NULL, 0x0, NULL, HFILL }
3489 /* Interface status TLV */
3490 { &hf_tlv_interface_status_value,
3491 { "Interface Status value", "cfm.tlv.intf_status.value", FT_UINT8,
3492 BASE_DEC, VALS(interface_stat_tlv_vals), 0x0, NULL, HFILL }
3495 /* Reply Ingress TLV, Reply Egress TLV */
3496 { &hf_tlv_reply_ingress_action,
3497 { "Ingress Action", "cfm.tlv.reply_ingress.action", FT_UINT8,
3498 BASE_DEC, VALS(reply_ingress_tlv_vals), 0x0, NULL, HFILL }
3500 { &hf_tlv_reply_ingress_mac_address,
3501 { "Ingress MAC address", "cfm.tlv.reply_ingress.mac_address", FT_ETHER,
3502 BASE_NONE, NULL, 0x0, NULL, HFILL }
3504 { &hf_tlv_reply_ing_egr_portid_length,
3505 { "Chassis ID Length", "cfm.tlv.reply_ing_egr.portid.length", FT_UINT8,
3506 BASE_DEC, NULL, 0x0, NULL, HFILL }
3508 { &hf_tlv_reply_ing_egr_portid_subtype,
3509 { "Chassis ID Sub-type", "cfm.tlv.reply_ing_egr.portid.subtype", FT_UINT8,
3510 BASE_DEC, NULL, 0x0, NULL, HFILL }
3512 { &hf_tlv_reply_ing_egr_portid_interface_alias,
3513 { "Interface alias", "cfm.tlv.reply_ing_egr.portid.intf_alias", FT_STRING,
3514 BASE_NONE, NULL, 0x0, NULL, HFILL }
3516 { &hf_tlv_reply_ing_egr_portid_port_component,
3517 { "Port component", "cfm.tlv.reply_ing_egr.portid.port_comp", FT_BYTES,
3518 BASE_NONE, NULL, 0x0, NULL, HFILL }
3520 { &hf_tlv_reply_ing_egr_portid_mac_address,
3521 { "MAC address", "cfm.tlv.reply_ing_egr.portid.mac_address", FT_ETHER,
3522 BASE_NONE, NULL, 0x0, NULL, HFILL }
3524 { &hf_tlv_reply_ing_egr_portid_network_address_family,
3525 { "Network address family", "cfm.tlv.reply_ing_egr.portid.network_address.family", FT_UINT8,
3526 BASE_DEC, NULL, 0x0, NULL, HFILL }
3528 { &hf_tlv_reply_ing_egr_portid_network_address_ipv4,
3529 { "Network address", "cfm.tlv.reply_ing_egr.portid.network_address.ipv4", FT_IPv4,
3530 BASE_NONE, NULL, 0x0, NULL, HFILL }
3532 { &hf_tlv_reply_ing_egr_portid_network_address_ipv6,
3533 { "Network address", "cfm.tlv.reply_ing_egr.portid.network_address.ipv6", FT_IPv6,
3534 BASE_NONE, NULL, 0x0, NULL, HFILL }
3536 { &hf_tlv_reply_ing_egr_portid_network_address_unknown,
3537 { "Network address", "cfm.tlv.reply_ing_egr.portid.network_address.unknown", FT_BYTES,
3538 BASE_NONE, NULL, 0x0, NULL, HFILL }
3540 { &hf_tlv_reply_ing_egr_portid_interface_name,
3541 { "Interface name", "cfm.tlv.reply_ing_egr.portid.intf_name", FT_STRINGZPAD,
3542 BASE_NONE, NULL, 0x0, NULL, HFILL }
3544 { &hf_tlv_reply_ing_egr_portid_agent_circuit_id,
3545 { "Agent circuit ID", "cfm.tlv.reply_ing_egr.portid.agent_circuit_id", FT_BYTES,
3546 BASE_NONE, NULL, 0x0, NULL, HFILL }
3548 { &hf_tlv_reply_ing_egr_portid_locally_assigned,
3549 { "Locally assigned", "cfm.tlv.reply_ing_egr.portid.locally_assigned", FT_STRINGZPAD,
3550 BASE_NONE, NULL, 0x0, NULL, HFILL }
3552 { &hf_tlv_reply_ing_egr_portid_unknown,
3553 { "Chassis ID", "cfm.tlv.reply_ing_egr.portid.unknown", FT_BYTES,
3554 BASE_NONE, NULL, 0x0, NULL, HFILL }
3557 /* Reply Egress TLV */
3558 { &hf_tlv_reply_egress_action,
3559 { "Egress Action", "cfm.tlv.reply_egress.action", FT_UINT8,
3560 BASE_DEC, VALS(reply_egress_tlv_vals), 0x0, NULL, HFILL }
3562 { &hf_tlv_reply_egress_mac_address,
3563 { "Egress MAC address", "cfm.tlv.reply_egress.mac_address", FT_ETHER,
3564 BASE_NONE, NULL, 0x0, NULL, HFILL }
3567 /* LTM Egress Identifier TLV */
3568 { &hf_tlv_ltm_egress_id_mac,
3569 { "Egress Identifier - MAC of LT Initiator/Responder", "cfm.tlv.ltm_egress.id.mac", FT_ETHER,
3570 BASE_NONE, NULL, 0x0, NULL, HFILL }
3572 { &hf_tlv_ltm_egress_id_unique_identifier,
3573 { "Egress Identifier - Unique Identifier", "cfm.tlv.ltm_egress.id.ui", FT_BYTES,
3574 BASE_NONE, NULL, 0x0, NULL, HFILL }
3577 /* LTR Egress Identifier TLV */
3578 { &hf_tlv_ltr_egress_last_id_mac,
3579 { "Last Egress Identifier - MAC address", "cfm.tlv.ltr_egress.last_id.mac", FT_ETHER,
3580 BASE_NONE, NULL, 0x0, NULL, HFILL }
3582 { &hf_tlv_ltr_egress_last_id_unique_identifier,
3583 { "Last Egress Identifier - Unique Identifier", "cfm.tlv.ltr_egress.last_id.ui", FT_BYTES,
3584 BASE_NONE, NULL, 0x0, NULL, HFILL }
3586 { &hf_tlv_ltr_egress_next_id_mac,
3587 { "Next Egress Identifier - MAC address", "cfm.tlv.ltr_egress.next_id.mac", FT_ETHER,
3588 BASE_NONE, NULL, 0x0, NULL, HFILL }
3590 { &hf_tlv_ltr_egress_next_id_unique_identifier,
3591 { "Next Egress Identifier - Unique Identifier", "cfm.tlv.ltr_egress.next_id.ui", FT_BYTES,
3592 BASE_NONE, NULL, 0x0, NULL, HFILL }
3595 /* PBB-TE TLV */
3596 { &hf_tlv_pbb_te_mip_mac_address,
3597 { "MIP MAC address", "cfm.tlv.pbb_te.mip_mac", FT_ETHER,
3598 BASE_NONE, NULL, 0x0, NULL, HFILL }
3600 { &hf_tlv_pbb_te_reverse_vid,
3601 { "Reverse VID", "cfm.tlv.pbb_te.reverse_vid", FT_UINT16,
3602 BASE_DEC, NULL, 0x0, NULL, HFILL }
3604 { &hf_tlv_pbb_te_reverse_mac,
3605 { "Reverse MAC", "cfm.tlv.pbb_te.reverse_mac", FT_ETHER,
3606 BASE_NONE, NULL, 0x0, NULL, HFILL }
3609 /* Organization-Specific TLV */
3610 { &hf_tlv_org_spec_oui,
3611 { "OUI", "cfm.tlv.org_spec.oui", FT_UINT24,
3612 BASE_OUI, NULL, 0x0, NULL, HFILL }
3614 { &hf_tlv_org_spec_subtype,
3615 { "Sub-Type", "cfm.tlv.org_spec.subtype", FT_BYTES,
3616 BASE_NONE, NULL, 0x0, NULL, HFILL }
3618 { &hf_tlv_org_spec_value,
3619 { "Value", "cfm.tlv.org_spec.value", FT_BYTES,
3620 BASE_NONE, NULL, 0x0, NULL, HFILL }
3623 /* Test TLV */
3624 { &hf_tlv_tst_test_pattern_type,
3625 { "Test Pattern Type", "cfm.tlv.tst.test.pattern.type", FT_UINT8,
3626 BASE_DEC, VALS(test_tlv_pattern_type_vals), 0x0, NULL, HFILL }
3628 { &hf_tlv_tst_test_pattern,
3629 { "Test Pattern", "cfm.tlv.tst.test.pattern", FT_NONE,
3630 BASE_NONE, NULL, 0x0, NULL, HFILL }
3632 { &hf_tlv_tst_CRC32,
3633 { "CRC-32", "cfm.tlv.tst.crc32", FT_BYTES,
3634 BASE_NONE, NULL, 0x0, NULL, HFILL }
3637 /* Target MEP/MIP ID TLV, Replying MEP/MIP ID TLV */
3638 { &hf_tlv_tgt_rpl_mep_mip_id_subtype,
3639 { "ID subtype", "cfm.tlv.tgt_rpl_mep_mip.id_subtype", FT_UINT8,
3640 BASE_DEC, VALS(mep_mip_id_tlv_subtype_vals), 0x0, NULL, HFILL }
3642 { &hf_tlv_tgt_rpl_padding,
3643 { "Padding", "cfm.tlv.tgt_rpl_mep_mip.padding", FT_BYTES,
3644 BASE_NONE, NULL, 0x0, NULL, HFILL }
3646 { &hf_tlv_tgt_rpl_mep_id,
3647 { "MEP ID", "cfm.tlv.tgt_rpl_mep_mip.mep_id", FT_UINT16,
3648 BASE_DEC, NULL, 0x1FFF, NULL, HFILL }
3650 { &hf_tlv_tgt_rpl_mip_id_icc,
3651 { "ITU-T Carrier Code", "cfm.tlv.tgt_rpl_mep_mip.icc", FT_STRINGZPAD,
3652 BASE_NONE, NULL, 0x0, NULL, HFILL }
3654 { &hf_tlv_tgt_rpl_mip_id_node_id,
3655 { "Node ID", "cfm.tlv.tgt_rpl_mep_mip.node_id", FT_UINT32,
3656 BASE_DEC, NULL, 0x0, NULL, HFILL }
3658 { &hf_tlv_tgt_rpl_mip_id_if_num,
3659 { "IF Num", "cfm.tlv.tgt_rpl_mep_mip.if_num", FT_UINT32,
3660 BASE_DEC, NULL, 0x0, NULL, HFILL }
3662 { &hf_tlv_tgt_rpl_mip_id_cc,
3663 { "Country Code", "cfm.tlv.tgt_rpl_mep_mip.cc", FT_STRINGZPAD,
3664 BASE_NONE, NULL, 0x0, NULL, HFILL }
3667 /* Requesting MEP ID TLV */
3668 { &hf_tlv_req_mep_id_lb,
3669 { "ID subtype", "cfm.tlv.req_mep_id.lb", FT_UINT8,
3670 BASE_DEC, VALS(req_mep_id_tlv_lb_vals), 0x0, NULL, HFILL }
3672 { &hf_tlv_req_mep_id_reserved,
3673 { "Reserved", "cfm.tlv.req_mep_id.reserved", FT_BYTES,
3674 BASE_NONE, NULL, 0x0, NULL, HFILL }
3677 /* Test ID TLV */
3678 { &hf_tlv_tst_id_test_id,
3679 { "Test ID", "cfm.tlv.tst_id.test_id", FT_BYTES,
3680 BASE_NONE, NULL, 0x0, NULL, HFILL }
3683 /* Unknown TLV */
3684 { &hf_tlv_unknown_data,
3685 { "TLV Data", "cfm.tlv.unknown.data", FT_BYTES,
3686 BASE_NONE, NULL, 0x0, NULL, HFILL }
3690 /* Setup protocol subtree array */
3691 static int *ett[] = {
3692 &ett_cfm,
3693 &ett_cfm_flags,
3694 &ett_cfm_maid,
3695 &ett_cfm_ccm_itu,
3696 &ett_cfm_pdu,
3697 &ett_cfm_all_tlvs,
3698 &ett_cfm_tlv,
3699 &ett_cfm_raps_status,
3702 static ei_register_info ei[] = {
3703 { &ei_tlv_tst_id_length,
3704 { "cfm.tlv.tst_id.length", PI_PROTOCOL, PI_NOTE,
3705 "Test ID TLV length is bits, not octets, unlike other TLVs",
3706 EXPFILL }
3708 { &ei_tlv_management_addr_length,
3709 { "cfm.tlv.sender_id.management_addr.length.zero",
3710 PI_PROTOCOL, PI_WARN,
3711 "Management Address Length should not be present if Management Address Domain Length is 0",
3712 EXPFILL }
3716 expert_module_t* expert_cfm;
3718 proto_cfm = proto_register_protocol("CFM EOAM IEEE 802.1Q/ITU-T Y.1731 Protocol", "CFM", "cfm");
3720 cfm_handle = register_dissector("cfm", dissect_cfm, proto_cfm);
3722 proto_register_field_array(proto_cfm, hf, array_length(hf));
3723 proto_register_subtree_array(ett, array_length(ett));
3724 expert_cfm = expert_register_protocol(proto_cfm);
3725 expert_register_field_array(expert_cfm, ei, array_length(ei));
3728 /* Register CFM EOAM protocol handler */
3729 void proto_reg_handoff_cfm(void)
3731 dissector_add_uint("ethertype", ETHERTYPE_CFM, cfm_handle);
3732 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_MPLSTP_OAM, cfm_handle);
3736 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3738 * Local variables:
3739 * c-basic-offset: 8
3740 * tab-width: 8
3741 * indent-tabs-mode: t
3742 * End:
3744 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
3745 * :indentSize=8:tabSize=8:noTabs=false: