aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/Makefile.common2
-rw-r--r--epan/dissectors/packet-cfm.c1053
-rw-r--r--epan/dissectors/packet-cfm.h62
3 files changed, 1117 insertions, 0 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 625991de90..1aa73693b4 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -231,6 +231,7 @@ CLEAN_DISSECTOR_SRC = \
packet-catapult-dct2000.c \
packet-ccsds.c \
packet-cdp.c \
+ packet-cfm.c \
packet-cgmp.c \
packet-chdlc.c \
packet-cigi.c \
@@ -795,6 +796,7 @@ DISSECTOR_INCLUDES = \
packet-camel.h \
packet-chdlc.h \
packet-cdt.h \
+ packet-cfm.h \
packet-cimd.h \
packet-cip.h \
packet-clearcase.h \
diff --git a/epan/dissectors/packet-cfm.c b/epan/dissectors/packet-cfm.c
new file mode 100644
index 0000000000..4214a28e9b
--- /dev/null
+++ b/epan/dissectors/packet-cfm.c
@@ -0,0 +1,1053 @@
+/* packet-cfm.c
+ * Routines for CFM EOAM (IEEE 802.1ag) dissection
+ * Copyright 2007, Keith Mercer <keith.mercer@alcatel-lucent.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* This code is based on the IEEE P802.1ag/D8.1 document, which is not formally
+ * released at the time of this dissector development, and may change requiring
+ * additional modifications to this code.
+ *
+ * The CFM dissector will recognize ITU Y.1731 opcodes but will not be
+ * dissected, with the exception of AIS, until a future version of this code.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/etypes.h>
+#include "packet-cfm.h"
+
+/* forward reference */
+static void dissect_cfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
+static int proto_cfm = -1;
+static dissector_handle_t cfm_handle;
+
+
+static const value_string opcodetypenames[] = {
+ { IEE8021, "Reserved for IEE 802.1" },
+ { CCM, "Continuity Check Message (CCM)" },
+ { LBR, "Loopback Reply (LBR)" },
+ { LBM, "Loopback Message (LBM)" },
+ { LTR, "Linktrace Reply (LTR)" },
+ { LTM, "Linktrace Message (LTM)" },
+ { AIS, "Alarm Indication Signal (AIS)" },
+ { LCK, "Lock Signal (LCK)" },
+ { TST, "Test Signal (TST)" },
+ { APS, "Automatic Protection Switching (APS)" },
+ { MCC, "Maintenance Communication Channel (MCC)" },
+ { LMM, "Loss Measurement Message (LMM)" },
+ { LMR, "Loss Measurement Reply (LMR)" },
+ { ODM, "One Way Delay Measurement (1DM)" },
+ { DMM, "Delay Measurement Message (DMM)" },
+ { DMR, "Delay Measurement Reply (DMR)" },
+ { EXM, "Experimental OAM Message (EXM)" },
+ { EXR, "Experimental OAM Reply (EXR)" },
+ { VSM, "Vendor Specific Message (VSM)" },
+ { VSR, "Vendor Specific Reply (VSR)" },
+ { 0, NULL }
+};
+static const value_string CCM_IntervalFieldEncoding[] = {
+ { 0, "invalid" },
+ { 1, "Trans Int 3.33ms, max Lifetime 11.66ms, min Lifetime 10.83ms" },
+ { 2, "Trans Int 10ms, max Lifetime 35ms, min Lifetime 32.5ms" },
+ { 3, "Trans Int 100ms, max Lifetime 350ms, min Lifetime 325ms" },
+ { 4, "Trans Int 1ms, max Lifetime 3.5s, min Lifetime 3.25s" },
+ { 5, "Trans Int 10s, max Lifetime 35s, min Lifetime 32.5s" },
+ { 6, "Trans Int 1min, max Lifetime 3.5min, min Lifetime 3.25min" },
+ { 7, "Trans Int 10min, max Lifetime 35min, min Lifetime 32.5min" },
+ { 0, NULL }
+};
+static const value_string mdnameformattypes[] = {
+ { 0, "Reserved for IEEE 802.1" },
+ { 1, "No Maintenance Domain Name preset" },
+ { 2, "RFC1035 DNS Name" },
+ { 3, "MAC address + 2-octet integer" },
+ { 4, "Character String" },
+ { 0, NULL }
+};
+static const value_string manameformattypes[] = {
+ { 0, "Reserved for IEEE 802.1" },
+ { 1, "Primary VID" },
+ { 2, "Character String" },
+ { 3, "2-octet integer" },
+ { 4, "RFC 2685 VPN ID" },
+ { 0, NULL }
+};
+static const value_string relayactiontypes[] = {
+ { 1, "RlyHit" },
+ { 2, "RlyFDB" },
+ { 3, "RlyMPDB" },
+ { 0, NULL }
+};
+static const value_string aislckperiodtypes[] = {
+ { 0, "Invalid Value for AIS/LCK PDU's" },
+ { 1, "Invalid Value for AIS/LCK PDU's" },
+ { 2, "Invalid Value for AIS/LCK PDU's" },
+ { 3, "Invalid Value for AIS/LCK PDU's" },
+ { 4, "1 frame per second" },
+ { 5, "Invalid Value for AIS/LCK PDU's" },
+ { 6, "1 frame per minute" },
+ { 7, "Invalid Value for AIS/LCK PDU's" },
+ { 0, NULL }
+};
+static const value_string tlvtypefieldvalues[] = {
+ { END_TLV , "End TLV" },
+ { SENDER_ID_TLV , "Sender ID TLV" },
+ { PORT_STAT_TLV , "Port Status TLV" },
+ { DATA_TLV , "Data TLV" },
+ { INTERF_STAT_TLV , "Interface Status TLV" },
+ { REPLY_ING_TLV , "Reply Ingress TLV" },
+ { REPLY_EGR_TLV , "Reply Egress TLV" },
+ { LTM_EGR_ID_TLV , "LTM Egress Identifier TLV" },
+ { LTR_EGR_ID_TLV , "LTR Egress Identifier TLV" },
+ { ORG_SPEC_TLV , "Organizational-Specific TLV" },
+ { 0 , NULL }
+};
+static const value_string portstatTLVvalues[] = {
+ { 1, "psBlocked" },
+ { 2, "psUp" },
+ { 0, NULL }
+};
+static const value_string interfacestatTLVvalues[] = {
+ { 1, "isUp" },
+ { 2, "isDown" },
+ { 3, "isTesting" },
+ { 4, "isUnknown" },
+ { 5, "isDormant" },
+ { 6, "isNotPresent" },
+ { 7, "isLowerLayerDown" },
+ { 0, NULL }
+};
+static const value_string replyingressTLVvalues[] = {
+ { 1, "IngOK" },
+ { 2, "IngDown" },
+ { 3, "IngBlocked" },
+ { 4, "IngVID" },
+ { 0, NULL }
+};
+static const value_string replyegressTLVvalues[] = {
+ { 1, "EgrOK" },
+ { 2, "EgrDown" },
+ { 3, "EgrBlocked" },
+ { 4, "EgrVID" },
+ { 0, NULL }
+};
+
+
+static int hf_cfm_md_level = -1;
+static int hf_cfm_version = -1;
+static int hf_cfm_opcode = -1;
+
+static int hf_cfm_flags = -1;
+static int hf_cfm_flags_RDI = -1;
+static int hf_cfm_flags_ccm_Reserved = -1;
+static int hf_cfm_flags_Interval = -1;
+static int hf_cfm_flags_UseFDBonly = -1;
+static int hf_cfm_flags_ltm_Reserved = -1;
+static int hf_cfm_flags_ltr_Reserved = -1;
+static int hf_cfm_flags_FwdYes = -1;
+static int hf_cfm_flags_TerminalMEP = -1;
+static int hf_cfm_first_tlv_offset = -1;
+
+static int hf_cfm_ccm_pdu = -1;
+static int hf_cfm_ccm_seq_number = -1;
+static int hf_cfm_ccm_ma_ep_id = -1;
+static int hf_cfm_ccm_maid = -1;
+static int hf_cfm_maid_md_name_format = -1;
+static int hf_cfm_maid_md_name_length = -1;
+static int hf_cfm_maid_md_name_string = -1;
+static int hf_cfm_maid_md_name_hex = -1;
+static int hf_cfm_maid_ma_name_format = -1;
+static int hf_cfm_maid_ma_name_length = -1;
+static int hf_cfm_maid_ma_name_string = -1;
+static int hf_cfm_maid_ma_name_hex = -1;
+static int hf_cfm_maid_padding = -1;
+static int hf_cfm_ccm_itu_t_y1731 = -1;
+
+static int hf_cfm_lbm_pdu = -1;
+static int hf_cfm_lb_transaction_id = -1;
+
+static int hf_cfm_lbr_pdu = -1;
+
+static int hf_cfm_ltm_pdu = -1;
+static int hf_cfm_lt_transaction_id = -1;
+static int hf_cfm_lt_ttl = -1;
+static int hf_cfm_ltm_orig_addr = -1;
+static int hf_cfm_ltm_targ_addr = -1;
+
+static int hf_cfm_ltr_pdu = -1;
+static int hf_cfm_ltr_relay_action = -1;
+
+static int hf_cfm_ais_pdu = -1;
+static int hf_cfm_flags_ais_lck_Reserved = -1;
+static int hf_cfm_flags_ais_lck_Period = -1;
+
+static int hf_cfm_all_tlvs = -1;
+static int hf_cfm_tlv_type = -1;
+static int hf_cfm_tlv_length = -1;
+static int hf_tlv_chassis_id_length = -1;
+static int hf_tlv_chassis_id_subtype = -1;
+static int hf_tlv_chassis_id = -1;
+static int hf_tlv_ma_domain_length = -1;
+static int hf_tlv_ma_domain = -1;
+static int hf_tlv_management_addr_length = -1;
+static int hf_tlv_management_addr = -1;
+static int hf_tlv_port_status_value = -1;
+static int hf_tlv_data_value = -1;
+static int hf_tlv_interface_status_value = -1;
+
+static int hf_tlv_reply_ingress_action = -1;
+static int hf_tlv_reply_ingress_mac_address = -1;
+static int hf_tlv_reply_ing_egr_portid_length = -1;
+static int hf_tlv_reply_ing_egr_portid_subtype = -1;
+static int hf_tlv_reply_ing_egr_portid = -1;
+static int hf_tlv_reply_egress_action = -1;
+static int hf_tlv_reply_egress_mac_address = -1;
+static int hf_tlv_ltr_egress_last_id = -1;
+static int hf_tlv_ltr_egress_next_id = -1;
+static int hf_tlv_ltm_egress_id_mac = -1;
+static int hf_tlv_ltm_egress_id_unique_identifier = -1;
+static int hf_tlv_org_spec_oui = -1;
+static int hf_tlv_org_spec_subtype = -1;
+static int hf_tlv_org_spec_value = -1;
+
+static gint ett_cfm = -1;
+static gint ett_cfm_ccm = -1;
+static gint ett_cfm_flags = -1;
+static gint ett_cfm_ccm_maid = -1;
+static gint ett_cfm_lbm = -1;
+static gint ett_cfm_lbr = -1;
+static gint ett_cfm_ltm = -1;
+static gint ett_cfm_ltr = -1;
+static gint ett_cfm_ais = -1;
+static gint ett_cfm_all_tlvs = -1;
+static gint ett_cfm_tlv = -1;
+
+/* Register CFM EOAM protocol */
+void proto_register_cfm(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_cfm_md_level,
+ { "CFM MD Level", "cfm.md.level", FT_UINT8,
+ BASE_DEC, NULL, 0xe0, NULL, HFILL }
+ },
+ { &hf_cfm_version,
+ { "CFM Version", "cfm.version", FT_UINT8,
+ BASE_DEC, NULL, 0x1f, NULL, HFILL }
+ },
+ { &hf_cfm_opcode,
+ { "CFM OpCode", "cfm.opcode", FT_UINT8,
+ BASE_DEC, VALS(opcodetypenames), 0x0, NULL, HFILL }
+ },
+
+ /* CFM CCM*/
+ { &hf_cfm_ccm_pdu,
+ { "CFM CCM PDU", "cfm.ccm.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_flags,
+ { "Flags", "cfm.flags", FT_UINT8,
+ BASE_HEX, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_flags_RDI,
+ { "RDI", "cfm.flags.rdi", FT_UINT8,
+ BASE_DEC, NULL, 0x80, NULL, HFILL }
+ },
+ { &hf_cfm_flags_ccm_Reserved,
+ { "Reserved", "cfm.flags.ccm.reserved", FT_UINT8,
+ BASE_DEC, NULL, 0x78, NULL, HFILL }
+ },
+ { &hf_cfm_flags_Interval,
+ { "Interval Field", "cfm.flags.interval", FT_UINT8,
+ BASE_DEC, VALS(CCM_IntervalFieldEncoding), 0x07, NULL, HFILL }
+ },
+ { &hf_cfm_first_tlv_offset,
+ { "First TLV Offset", "cfm.first.tlv.offset", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ccm_seq_number,
+ { "Sequence Number", "cfm.ccm.seq.num", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ccm_ma_ep_id,
+ { "Maintenance Association End Point Identifier", "cfm.ccm.ma.ep.id",
+ FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ccm_maid,
+ { "Maintenance Association Identifier", "cfm.ccm.maid", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_md_name_format,
+ { "MD Name Format", "cfm.maid.md.name.format", FT_UINT8,
+ BASE_DEC, VALS(mdnameformattypes), 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_md_name_length,
+ { "MD Name Length", "cfm.maid.md.name.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_md_name_string,
+ { "MD Name", "cfm.maid.md.name", FT_STRING,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_md_name_hex,
+ { "MD Name", "cfm.maid.md.name", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_ma_name_format,
+ { "Short MA Name Format", "cfm.maid.ma.name.format", FT_UINT8,
+ BASE_DEC, VALS(manameformattypes), 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_ma_name_length,
+ { "Short MA Name Length", "cfm.maid.ma.name.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_ma_name_string,
+ { "Short MA Name", "cfm.maid.ma.name", FT_STRING,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_ma_name_hex,
+ { "Short MA Name", "cfm.maid.ma.name", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_maid_padding,
+ { "0 Padding", "cfm.ccm.maid.padding", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ccm_itu_t_y1731,
+ { "Defined by ITU-T Y.1731", "cfm.ccm.itu.t.y1731", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* CFM LBM*/
+ { &hf_cfm_lbm_pdu,
+ { "CFM LBM PDU", "cfm.lbm.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_lb_transaction_id,
+ { "Loopback Transaction Identifier", "cfm.lb.transaction.id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* CFM LBR*/
+ { &hf_cfm_lbr_pdu,
+ { "CFM LBR PDU", "cfm.lbr.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* CFM LTM*/
+ { &hf_cfm_ltm_pdu,
+ { "CFM LTM PDU", "cfm.ltm.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_flags_UseFDBonly,
+ { "RDI", "cfm.flags.usefdbonly", FT_UINT8,
+ BASE_DEC, NULL, 0x80, NULL, HFILL }
+ },
+ { &hf_cfm_flags_ltm_Reserved,
+ { "Reserved", "cfm.flags.ltm.reserved", FT_UINT8,
+ BASE_DEC, NULL, 0x7F, NULL, HFILL }
+ },
+ { &hf_cfm_lt_transaction_id,
+ { "Linktrace Transaction Identifier", "cfm.lt.transaction.id", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_lt_ttl,
+ { "Linktrace TTL", "cfm.lt.ttl", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ltm_orig_addr,
+ { "Linktrace Message: Original Address", "cfm.ltm.orig.addr", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_ltm_targ_addr,
+ { "Linktrace Message: Target Address", "cfm.ltm.targ.addr", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* CFM LTR*/
+ { &hf_cfm_ltr_pdu,
+ { "CFM LTR PDU", "cfm.ltr.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_flags_FwdYes,
+ { "FwdYes", "cfm.flags.fwdyes", FT_UINT8,
+ BASE_DEC, NULL, 0x40, NULL, HFILL }
+ },
+ { &hf_cfm_flags_TerminalMEP,
+ { "TerminalMEP", "cfm.flags.ltr.terminalmep", FT_UINT8,
+ BASE_DEC, NULL, 0x20, NULL, HFILL }
+ },
+ { &hf_cfm_flags_ltr_Reserved,
+ { "Reserved", "cfm.flags.ltr.reserved", FT_UINT8,
+ BASE_DEC, NULL, 0x1F, NULL, HFILL }
+ },
+ { &hf_cfm_ltr_relay_action,
+ { "Linktrace Reply Relay Action", "cfm.ltr.relay.action", FT_UINT8,
+ BASE_DEC, VALS(relayactiontypes), 0x0, NULL, HFILL}
+ },
+
+ /* CFM AIS*/
+ { &hf_cfm_ais_pdu,
+ { "CFM AIS PDU", "cfm.ais.pdu", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_flags_ais_lck_Reserved,
+ { "Reserved", "cfm.flags.reserved", FT_UINT8,
+ BASE_DEC, NULL, 0xF8, NULL, HFILL }
+ },
+ { &hf_cfm_flags_ais_lck_Period,
+ { "Period", "cfm.flags.period", FT_UINT8,
+ BASE_DEC, VALS(aislckperiodtypes), 0x07, NULL, HFILL }
+ },
+
+ /******************************* TLVs ****************************/
+ { &hf_cfm_all_tlvs,
+ { "CFM TLVs", "cfm.all.tlvs", FT_NONE,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_cfm_tlv_type,
+ { "TLV Type", "cfm.tlv.type", FT_UINT8,
+ BASE_DEC, VALS(tlvtypefieldvalues), 0x0, NULL, HFILL}
+ },
+ { &hf_cfm_tlv_length,
+ { "TLV Length", "cfm.tlv.length", FT_UINT16,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ /* Sender ID TLV */
+ { &hf_tlv_chassis_id_length,
+ { "Chassis ID Length", "cfm.tlv.chassis.id.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_chassis_id_subtype,
+ { "Chassis ID Sub-type", "cfm.tlv.chassis.id.subtype", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_chassis_id,
+ { "Chassis ID", "cfm.tlv.chassis.id", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_ma_domain_length,
+ { "Management Address Domain Length", "cfm.tlv.ma.domain.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_ma_domain,
+ { "Management Address Domain", "cfm.tlv.ma.domain", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_management_addr_length,
+ { "Management Address Length", "cfm.tlv.management.addr.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_management_addr,
+ { "Management Address", "cfm.tlv.management.addr", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+
+ /* Port Status TLV */
+ { &hf_tlv_port_status_value,
+ { "Port Status value", "cfm.tlv.port.status.value", FT_UINT8,
+ BASE_DEC, VALS(portstatTLVvalues), 0x0, NULL, HFILL}
+ },
+
+ /* Data TLV */
+ { &hf_tlv_data_value,
+ { "Data Value", "cfm.tlv.data.value", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+
+ /* Interface status TLV */
+ { &hf_tlv_interface_status_value,
+ { "Interface Status value", "cfm.tlv.port.interface.value", FT_UINT8,
+ BASE_DEC, VALS(interfacestatTLVvalues), 0x0, NULL, HFILL}
+ },
+
+ /* Reply Ingress TLV */
+ { &hf_tlv_reply_ingress_action,
+ { "Ingress Action", "cfm.tlv.reply.ingress.action", FT_UINT8,
+ BASE_DEC, VALS(replyingressTLVvalues), 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_reply_ingress_mac_address,
+ { "Ingress MAC address", "cfm.tlv.reply.ingress.mac.address", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_tlv_reply_ing_egr_portid_length,
+ { "Chassis ID Length", "cfm.tlv.chassis.id.length", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_reply_ing_egr_portid_subtype,
+ { "Chassis ID Sub-type", "cfm.tlv.chassis.id.subtype", FT_UINT8,
+ BASE_DEC, NULL, 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_reply_ing_egr_portid,
+ { "Chassis ID", "cfm.tlv.chassis.id", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL}
+ },
+
+ /* Reply Egress TLV */
+ { &hf_tlv_reply_egress_action,
+ { "Egress Action", "cfm.tlv.reply.egress.action", FT_UINT8,
+ BASE_DEC, VALS(replyegressTLVvalues), 0x0, NULL, HFILL}
+ },
+ { &hf_tlv_reply_egress_mac_address,
+ { "Egress MAC address", "cfm.tlv.reply.egress.mac.address", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* LTM Egress Identifier TLV */
+ { &hf_tlv_ltm_egress_id_mac,
+ { "Egress Identifier - MAC of LT Initiator/Responder", "cfm.tlv.ltm.egress.id", FT_ETHER,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_tlv_ltm_egress_id_unique_identifier,
+ { "Egress Identifier - Unique Identifier", "cfm.tlv.ltm.egress.id", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* LTR Egress Identifier TLV */
+ { &hf_tlv_ltr_egress_last_id,
+ { "Last Egress Identifier", "cfm.tlv.ltr.egress.last.id", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_tlv_ltr_egress_next_id,
+ { "Next Egress Identifier", "cfm.tlv.ltr.egress.next.id", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+
+ /* Organization-Specific TLV */
+ { &hf_tlv_org_spec_oui,
+ { "OUI", "cfm.tlv.org.spec.oui", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_tlv_org_spec_subtype,
+ { "Sub-Type", "cfm.tlv.org.spec.subtype", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ },
+ { &hf_tlv_org_spec_value,
+ { "Value", "cfm.tlv.org.spec.value", FT_BYTES,
+ BASE_NONE, NULL, 0x0, NULL, HFILL }
+ }
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_cfm,
+ &ett_cfm_ccm,
+ &ett_cfm_flags,
+ &ett_cfm_ccm_maid,
+ &ett_cfm_lbm,
+ &ett_cfm_lbr,
+ &ett_cfm_ltm,
+ &ett_cfm_ltr,
+ &ett_cfm_ais,
+ &ett_cfm_all_tlvs,
+ &ett_cfm_tlv
+ };
+
+ proto_cfm = proto_register_protocol (
+ "CFM EOAM 802.1ag/ITU Protocol", /* name */
+ "CFM", /* short name */
+ "cfm" /* abbrev */
+ );
+
+ register_dissector("cfm", dissect_cfm, proto_cfm);
+
+ proto_register_field_array(proto_cfm, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+}
+
+/* Register CFM OEAM protocol handler */
+void proto_reg_handoff_cfm(void)
+{
+ static int initialized=FALSE;
+ if (!initialized) {
+ cfm_handle = create_dissector_handle(dissect_cfm, proto_cfm);
+ dissector_add("ethertype", ETHERTYPE_CFM, cfm_handle);
+ }
+}
+
+/* CFM EOAM sub-protocol dissectors: CCM, LBM, LBR, LTM, LTR */
+static int dissect_cfm_ccm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ gint maid_offset = 0;
+ gint padding_length = 0;
+
+ guint8 cfm_maid_md_name_format = 0;
+ guint8 cfm_maid_md_name_length = 0;
+ guint8 cfm_maid_ma_name_format = 0;
+ guint8 cfm_maid_ma_name_length = 0;
+
+ proto_item *ti = NULL;
+ proto_item *fi = NULL;
+ proto_item *mi = NULL;
+ proto_tree *cfm_ccm_tree = NULL;
+ proto_tree *cfm_flag_tree = NULL;
+ proto_tree *cfm_ccm_maid_tree = NULL;
+
+
+ ti = proto_tree_add_item(tree, hf_cfm_ccm_pdu, tvb, offset, -1, FALSE);
+ cfm_ccm_tree = proto_item_add_subtree(ti, ett_cfm_ccm);
+
+ fi = proto_tree_add_item(cfm_ccm_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_RDI, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ccm_Reserved, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_Interval, tvb, offset, 1, FALSE);
+
+ offset += 1;
+ proto_tree_add_item(cfm_ccm_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_ccm_tree, hf_cfm_ccm_seq_number, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(cfm_ccm_tree, hf_cfm_ccm_ma_ep_id, tvb, offset, 2, FALSE);
+ offset += 2;
+
+ mi = proto_tree_add_item(cfm_ccm_tree, hf_cfm_ccm_maid, tvb, offset, 48, FALSE);
+ cfm_ccm_maid_tree = proto_item_add_subtree(mi, ett_cfm_ccm_maid);
+ maid_offset = offset;
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_format, tvb, maid_offset, 1, FALSE);
+ cfm_maid_md_name_format = tvb_get_guint8(tvb, maid_offset);
+ maid_offset += 1;
+ if (cfm_maid_md_name_format != 1) {
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_length,
+ tvb, maid_offset, 1, FALSE);
+ cfm_maid_md_name_length = tvb_get_guint8(tvb, maid_offset);
+ maid_offset += 1;
+ if (cfm_maid_md_name_length) {
+ if (cfm_maid_md_name_format == 3) {
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_hex,
+ tvb, maid_offset, cfm_maid_md_name_length, FALSE);
+ } else {
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_md_name_string,
+ tvb, maid_offset, cfm_maid_md_name_length, FALSE);
+ }
+ maid_offset += cfm_maid_md_name_length;
+ }
+ }
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_format, tvb, maid_offset, 1, FALSE);
+ cfm_maid_ma_name_format = tvb_get_guint8(tvb, maid_offset);
+ maid_offset += 1;
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_length, tvb, maid_offset, 1, FALSE);
+ cfm_maid_ma_name_length = tvb_get_guint8(tvb, maid_offset);
+ maid_offset += 1;
+ if (cfm_maid_ma_name_format == 2) {
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_string,
+ tvb, maid_offset, cfm_maid_ma_name_length, FALSE);
+ } else {
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_ma_name_hex,
+ tvb, maid_offset, cfm_maid_ma_name_length, FALSE);
+ }
+ maid_offset += cfm_maid_ma_name_length;
+ offset += 48;
+ if (offset > maid_offset) {
+ padding_length = offset - maid_offset;
+ proto_tree_add_item(cfm_ccm_maid_tree, hf_cfm_maid_padding,
+ tvb, maid_offset, padding_length, FALSE);
+ }
+
+ proto_tree_add_item(cfm_ccm_tree, hf_cfm_ccm_itu_t_y1731, tvb, offset, 16, FALSE);
+ offset += 16;
+ return offset;
+}
+
+static int dissect_cfm_lbm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *ti = NULL;
+ proto_tree *cfm_lbm_tree = NULL;
+
+ ti = proto_tree_add_item(tree, hf_cfm_lbm_pdu, tvb, offset, -1, FALSE);
+ cfm_lbm_tree = proto_item_add_subtree(ti, ett_cfm_lbm);
+
+ proto_tree_add_item(cfm_lbm_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_lbm_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_lbm_tree, hf_cfm_lb_transaction_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ return offset;
+}
+
+static int dissect_cfm_lbr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *ti = NULL;
+ proto_tree *cfm_lbr_tree = NULL;
+
+ ti = proto_tree_add_item(tree, hf_cfm_lbr_pdu, tvb, offset, -1, FALSE);
+ cfm_lbr_tree = proto_item_add_subtree(ti, ett_cfm_lbr);
+
+ proto_tree_add_item(cfm_lbr_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_lbr_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_lbr_tree, hf_cfm_lb_transaction_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ return offset;
+}
+
+static int dissect_cfm_ltm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *ti = NULL;
+ proto_item *fi = NULL;
+ proto_tree *cfm_ltm_tree = NULL;
+ proto_tree *cfm_flag_tree = NULL;
+
+ ti = proto_tree_add_item(tree, hf_cfm_ltm_pdu, tvb, offset, -1, FALSE);
+ cfm_ltm_tree = proto_item_add_subtree(ti, ett_cfm_ltm);
+
+ fi = proto_tree_add_item(cfm_ltm_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_UseFDBonly, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ltm_Reserved, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(cfm_ltm_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_ltm_tree, hf_cfm_lt_transaction_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(cfm_ltm_tree, hf_cfm_lt_ttl, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_ltm_tree, hf_cfm_ltm_orig_addr, tvb, offset, 6, FALSE);
+ offset += 6;
+ proto_tree_add_item(cfm_ltm_tree, hf_cfm_ltm_targ_addr, tvb, offset, 6, FALSE);
+ offset += 6;
+ return offset;
+}
+
+static int dissect_cfm_ltr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *ti = NULL;
+ proto_item *fi = NULL;
+ proto_tree *cfm_ltr_tree = NULL;
+ proto_tree *cfm_flag_tree = NULL;
+
+ ti = proto_tree_add_item(tree, hf_cfm_ltr_pdu, tvb, offset, -1, FALSE);
+ cfm_ltr_tree = proto_item_add_subtree(ti, ett_cfm_ltr);
+
+ fi = proto_tree_add_item(cfm_ltr_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_UseFDBonly, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_FwdYes, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_TerminalMEP, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ltr_Reserved, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(cfm_ltr_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_ltr_tree, hf_cfm_lt_transaction_id, tvb, offset, 4, FALSE);
+ offset += 4;
+ proto_tree_add_item(cfm_ltr_tree, hf_cfm_lt_ttl, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_ltr_tree, hf_cfm_ltr_relay_action, tvb, offset, 1, FALSE);
+ offset += 1;
+ return offset;
+}
+
+static int dissect_cfm_ais(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+ proto_item *ti = NULL;
+ proto_item *fi = NULL;
+ proto_tree *cfm_ais_tree = NULL;
+ proto_tree *cfm_flag_tree = NULL;
+
+ ti = proto_tree_add_item(tree, hf_cfm_ais_pdu, tvb, offset, -1, FALSE);
+ cfm_ais_tree = proto_item_add_subtree(ti, ett_cfm_ais);
+
+ fi = proto_tree_add_item(cfm_ais_tree, hf_cfm_flags, tvb, offset, 1, FALSE);
+ cfm_flag_tree = proto_item_add_subtree(fi, ett_cfm_flags);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Reserved, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_flag_tree, hf_cfm_flags_ais_lck_Period, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ proto_tree_add_item(cfm_ais_tree, hf_cfm_first_tlv_offset, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ return offset;
+}
+
+
+
+/* Main CFM EOAM protocol dissector */
+static void dissect_cfm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ gint offset = 0;
+ gint cfm_tlv_offset = 0;
+ gint tlv_header_modifier = 0;
+ gint tlv_data_offset = 0;
+
+ guint8 cfm_pdu_type = 0;
+ guint8 cfm_tlv_type = 255;
+ guint16 cfm_tlv_length = 0;
+ guint8 tlv_chassis_id_length = 0;
+ guint8 tlv_ma_domain_length = 0;
+ guint8 tlv_management_addr_length = 0;
+ guint8 tlv_reply_ingress_portid_length = 0;
+ guint8 tlv_reply_egress_portid_length = 0;
+
+ proto_item *ti = NULL;
+ proto_item *fi = NULL;
+ proto_tree *cfm_tree = NULL;
+ proto_tree *cfm_all_tlvs_tree = NULL;
+ proto_tree *cfm_tlv_tree = NULL;
+
+ /* display the CFM protol name */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "CFM");
+ }
+
+ /* Clear out stuff in the info column */
+ if (check_col(pinfo->cinfo,COL_INFO)) {
+ col_clear(pinfo->cinfo,COL_INFO);
+ }
+
+ /* provide info column with CFM packet type (opcode)*/
+ cfm_pdu_type = tvb_get_guint8(tvb, 1);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s",
+ val_to_str(cfm_pdu_type, opcodetypenames, "Unknown (0x%02x)"));
+ }
+
+ if (tree) { /* we are being asked for details */
+
+
+ /* isolate the payload of the packet */
+ ti = proto_tree_add_item(tree, proto_cfm, tvb, 0, -1, FALSE);
+
+
+ /* report type of CFM packet to base of dissection tree */
+ proto_item_append_text(ti, ", Type %s",
+ val_to_str(cfm_pdu_type, opcodetypenames, "Unknown (0x%02x)"));
+
+ /* dissecting the common CFM header */
+ cfm_tree = proto_item_add_subtree(ti, ett_cfm);
+ proto_tree_add_item(cfm_tree, hf_cfm_md_level, tvb, offset, 1, FALSE);
+ proto_tree_add_item(cfm_tree, hf_cfm_version, tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(cfm_tree, hf_cfm_opcode, tvb, offset, 1, FALSE);
+ offset += 1;
+
+ switch(cfm_pdu_type) {
+ case CCM:
+ offset = dissect_cfm_ccm(tvb, pinfo, tree, offset);
+ break;
+ case LBM:
+ offset = dissect_cfm_lbm(tvb, pinfo, tree, offset);
+ break;
+ case LBR:
+ offset = dissect_cfm_lbr(tvb, pinfo, tree, offset);
+ break;
+ case LTM:
+ offset = dissect_cfm_ltm(tvb, pinfo, tree, offset);
+ break;
+ case LTR:
+ offset = dissect_cfm_ltr(tvb, pinfo, tree, offset);
+ break;
+ case AIS:
+ offset = dissect_cfm_ais(tvb, pinfo, tree, offset);
+ }
+
+ /* Get the TLV offset and add the offset of the common CFM header*/
+ cfm_tlv_offset = tvb_get_guint8(tvb, 3);
+ cfm_tlv_offset += 4;
+
+ /* Begin dissecting the TLV's */
+ /* the TLV offset should be the same as where the pdu left off or we have a problem */
+ if ((cfm_tlv_offset == offset) && (cfm_tlv_offset > 4)) {
+ ti = proto_tree_add_item(tree, hf_cfm_all_tlvs, tvb, cfm_tlv_offset, -1, FALSE);
+ cfm_all_tlvs_tree = proto_item_add_subtree(ti, ett_cfm_all_tlvs);
+
+ while (cfm_tlv_type != END_TLV)
+ {
+ cfm_tlv_type = tvb_get_guint8(tvb, cfm_tlv_offset);
+
+ if (cfm_tlv_type == END_TLV) {
+ tlv_header_modifier = 1;
+ cfm_tlv_length = 0;
+ } else {
+ tlv_header_modifier = 3;
+ cfm_tlv_length = tvb_get_ntohs(tvb, cfm_tlv_offset+1);
+ }
+
+ fi = proto_tree_add_text(cfm_all_tlvs_tree, tvb, cfm_tlv_offset, cfm_tlv_length+tlv_header_modifier,
+ "TLV: %s (t=%d,l=%d)", val_to_str(cfm_tlv_type, tlvtypefieldvalues, "Unknown (0x%02x)"),
+ cfm_tlv_type, cfm_tlv_length);
+ cfm_tlv_tree = proto_item_add_subtree(fi, ett_cfm_tlv);
+
+ proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_type, tvb, cfm_tlv_offset, 1, FALSE);
+ cfm_tlv_offset += 1;
+ if ((cfm_tlv_type != END_TLV) && (cfm_tlv_length != 0)) {
+ proto_tree_add_item(cfm_tlv_tree, hf_cfm_tlv_length, tvb, cfm_tlv_offset, 2, FALSE);
+ cfm_tlv_offset += 2;
+
+ tlv_data_offset = cfm_tlv_offset;
+
+ switch(cfm_tlv_type) {
+ case SENDER_ID_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_length,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_chassis_id_length = tvb_get_guint8(tvb,tlv_data_offset);
+ tlv_data_offset += 1;
+
+ if (tlv_chassis_id_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id_subtype,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_chassis_id,
+ tvb, tlv_data_offset, tlv_chassis_id_length, FALSE);
+ tlv_data_offset += tlv_chassis_id_length;
+ }
+
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain_length,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_ma_domain_length = tvb_get_guint8(tvb,tlv_data_offset);
+ tlv_data_offset += 1;
+ if (tlv_ma_domain_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ma_domain,
+ tvb, tlv_data_offset, tlv_ma_domain_length, FALSE);
+ tlv_data_offset += tlv_ma_domain_length;
+ }
+
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr_length,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_management_addr_length = tvb_get_guint8(tvb,tlv_data_offset);
+ tlv_data_offset += 1;
+ if (tlv_management_addr_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_management_addr,
+ tvb, tlv_data_offset, tlv_management_addr_length, FALSE);
+ tlv_data_offset += tlv_management_addr_length;
+ }
+ break;
+ case PORT_STAT_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_port_status_value,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ break;
+ case DATA_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_data_value,
+ tvb, tlv_data_offset, cfm_tlv_length, FALSE);
+ tlv_data_offset += cfm_tlv_length;
+ break;
+ case INTERF_STAT_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_interface_status_value,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ break;
+ case REPLY_ING_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_action,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ingress_mac_address,
+ tvb, tlv_data_offset, 6, FALSE);
+ tlv_data_offset += 6;
+
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_reply_ingress_portid_length = tvb_get_guint8(tvb,tlv_data_offset);
+ tlv_data_offset += 1;
+
+ if (tlv_reply_ingress_portid_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_subtype,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid,
+ tvb, tlv_data_offset, tlv_reply_ingress_portid_length, FALSE);
+ tlv_data_offset += tlv_reply_ingress_portid_length;
+ }
+ break;
+ case REPLY_EGR_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_action,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_egress_mac_address,
+ tvb, tlv_data_offset, 6, FALSE);
+ tlv_data_offset += 6;
+
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_length,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_reply_egress_portid_length = tvb_get_guint8(tvb,tlv_data_offset);
+ tlv_data_offset += 1;
+
+ if (tlv_reply_egress_portid_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid_subtype,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_reply_ing_egr_portid,
+ tvb, tlv_data_offset, tlv_reply_egress_portid_length, FALSE);
+ tlv_data_offset += tlv_reply_egress_portid_length;
+ }
+ break;
+ case LTM_EGR_ID_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_mac,
+ tvb, tlv_data_offset, 6, FALSE);
+ tlv_data_offset += 6;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltm_egress_id_unique_identifier,
+ tvb, tlv_data_offset, 2, FALSE);
+ tlv_data_offset += 2;
+ break;
+ case LTR_EGR_ID_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_last_id,
+ tvb, tlv_data_offset, 8, FALSE);
+ tlv_data_offset += 8;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_ltr_egress_next_id,
+ tvb, tlv_data_offset, 8, FALSE);
+ tlv_data_offset += 8;
+ break;
+ case ORG_SPEC_TLV:
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_oui,
+ tvb, tlv_data_offset, 3, FALSE);
+ tlv_data_offset += 3;
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_subtype,
+ tvb, tlv_data_offset, 1, FALSE);
+ tlv_data_offset += 1;
+
+ if (cfm_tlv_length > 0) {
+ proto_tree_add_item(cfm_tlv_tree, hf_tlv_org_spec_value,
+ tvb, tlv_data_offset, cfm_tlv_length, FALSE);
+ tlv_data_offset -= 4;
+ }
+ tlv_data_offset += cfm_tlv_length;
+
+
+ break;
+ }
+
+
+ cfm_tlv_offset += cfm_tlv_length;
+ }
+
+
+
+ }
+ }
+
+ }
+
+}
+
diff --git a/epan/dissectors/packet-cfm.h b/epan/dissectors/packet-cfm.h
new file mode 100644
index 0000000000..b7ad086c1d
--- /dev/null
+++ b/epan/dissectors/packet-cfm.h
@@ -0,0 +1,62 @@
+/* packet-cfm.h
+ * Value declarations for CFM EOAM (IEEE 802.1ag) dissection
+ * Copyright 2007, Keith Mercer <keith.mercer@alcatel-lucent.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PACKET_CFM_H__
+#define __PACKET_CFM_H__
+
+#define IEE8021 0x00
+#define CCM 0x01
+#define LBR 0x02
+#define LBM 0x03
+#define LTR 0x04
+#define LTM 0X05
+
+#define AIS 0x21
+#define LCK 0x23
+#define TST 0x25
+#define APS 0x27
+#define MCC 0x29
+#define LMM 0x2B
+#define LMR 0x2A
+#define ODM 0x2D
+#define DMM 0x2F
+#define DMR 0x2E
+#define EXM 0x31
+#define EXR 0x30
+#define VSM 0x33
+#define VSR 0x32
+
+#define END_TLV 0x00
+#define SENDER_ID_TLV 0x01
+#define PORT_STAT_TLV 0x02
+#define DATA_TLV 0x03
+#define INTERF_STAT_TLV 0x04
+#define REPLY_ING_TLV 0x05
+#define REPLY_EGR_TLV 0x06
+#define LTM_EGR_ID_TLV 0x07
+#define LTR_EGR_ID_TLV 0x08
+#define ORG_SPEC_TLV 0x1F
+
+#endif