+/*
+ * TLV values in LE Control frames.
+ */
+#define TLV_TYPE(oui, ident) (((oui) << 8) | (ident))
+
+#define LE_CONTROL_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x01)
+#define LE_MAX_UNK_FRAME_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x02)
+#define LE_MAX_UNK_FRAME_TIME TLV_TYPE(OUI_ATM_FORUM, 0x03)
+#define LE_VCC_TIMEOUT_PERIOD TLV_TYPE(OUI_ATM_FORUM, 0x04)
+#define LE_MAX_RETRY_COUNT TLV_TYPE(OUI_ATM_FORUM, 0x05)
+#define LE_AGING_TIME TLV_TYPE(OUI_ATM_FORUM, 0x06)
+#define LE_FORWARD_DELAY_TIME TLV_TYPE(OUI_ATM_FORUM, 0x07)
+#define LE_EXPECTED_ARP_RESPONSE_TIME TLV_TYPE(OUI_ATM_FORUM, 0x08)
+#define LE_FLUSH_TIMEOUT TLV_TYPE(OUI_ATM_FORUM, 0x09)
+#define LE_PATH_SWITCHING_DELAY TLV_TYPE(OUI_ATM_FORUM, 0x0A)
+#define LE_LOCAL_SEGMENT_ID TLV_TYPE(OUI_ATM_FORUM, 0x0B)
+#define LE_MCAST_SEND_VCC_TYPE TLV_TYPE(OUI_ATM_FORUM, 0x0C)
+#define LE_MCAST_SEND_VCC_AVGRATE TLV_TYPE(OUI_ATM_FORUM, 0x0D)
+#define LE_MCAST_SEND_VCC_PEAKRATE TLV_TYPE(OUI_ATM_FORUM, 0x0E)
+#define LE_CONN_COMPLETION_TIMER TLV_TYPE(OUI_ATM_FORUM, 0x0F)
+#define LE_CONFIG_FRAG_INFO TLV_TYPE(OUI_ATM_FORUM, 0x10)
+#define LE_LAYER_3_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x11)
+#define LE_ELAN_ID TLV_TYPE(OUI_ATM_FORUM, 0x12)
+#define LE_SERVICE_CATEGORY TLV_TYPE(OUI_ATM_FORUM, 0x13)
+#define LE_LLC_MUXED_ATM_ADDRESS TLV_TYPE(OUI_ATM_FORUM, 0x2B)
+#define LE_X5_ADJUSTMENT TLV_TYPE(OUI_ATM_FORUM, 0x2C)
+#define LE_PREFERRED_LES TLV_TYPE(OUI_ATM_FORUM, 0x2D)
+
+static const value_string le_tlv_type_vals[] = {
+ { LE_CONTROL_TIMEOUT, "Control Time-out" },
+ { LE_MAX_UNK_FRAME_COUNT, "Maximum Unknown Frame Count" },
+ { LE_MAX_UNK_FRAME_TIME, "Maximum Unknown Frame Time" },
+ { LE_VCC_TIMEOUT_PERIOD, "VCC Time-out" },
+ { LE_MAX_RETRY_COUNT, "Maximum Retry Count" },
+ { LE_AGING_TIME, "Aging Time" },
+ { LE_FORWARD_DELAY_TIME, "Forwarding Delay Time" },
+ { LE_EXPECTED_ARP_RESPONSE_TIME, "Expected LE_ARP Response Time" },
+ { LE_FLUSH_TIMEOUT, "Flush Time-out" },
+ { LE_PATH_SWITCHING_DELAY, "Path Switching Delay" },
+ { LE_LOCAL_SEGMENT_ID, "Local Segment ID" },
+ { LE_MCAST_SEND_VCC_TYPE, "Mcast Send VCC Type" },
+ { LE_MCAST_SEND_VCC_AVGRATE, "Mcast Send VCC AvgRate" },
+ { LE_MCAST_SEND_VCC_PEAKRATE, "Mcast Send VCC PeakRate" },
+ { LE_CONN_COMPLETION_TIMER, "Connection Completion Timer" },
+ { LE_CONFIG_FRAG_INFO, "Config Frag Info" },
+ { LE_LAYER_3_ADDRESS, "Layer 3 Address" },
+ { LE_ELAN_ID, "ELAN ID" },
+ { LE_SERVICE_CATEGORY, "Service Category" },
+ { LE_LLC_MUXED_ATM_ADDRESS, "LLC-muxed ATM Address" },
+ { LE_X5_ADJUSTMENT, "X5 Adjustment" },
+ { LE_PREFERRED_LES, "Preferred LES" },
+ { 0, NULL },
+};
+
+static void
+dissect_le_control_tlvs(tvbuff_t *tvb, int offset, guint num_tlvs,
+ proto_tree *tree)
+{
+ guint32 tlv_type;
+ guint8 tlv_length;
+ proto_item *ttlv;
+ proto_tree *tlv_tree;
+
+ while (num_tlvs != 0) {
+ tlv_type = tvb_get_ntohl(tvb, offset);
+ tlv_length = tvb_get_guint8(tvb, offset+4);
+ ttlv = proto_tree_add_text(tree, tvb, offset, 5+tlv_length, "TLV type: %s",
+ val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
+ tlv_tree = proto_item_add_subtree(ttlv, ett_atm_lane_lc_tlv);
+ proto_tree_add_text(tlv_tree, tvb, offset, 4, "TLV Type: %s",
+ val_to_str(tlv_type, le_tlv_type_vals, "Unknown (0x%08x)"));
+ proto_tree_add_text(tlv_tree, tvb, offset+4, 1, "TLV Length: %u", tlv_length);
+ offset += 5+tlv_length;
+ num_tlvs--;
+ }
+}
+
+static void
+dissect_le_configure_join_frame(tvbuff_t *tvb, int offset, proto_tree *tree)
+{
+ guint8 num_tlvs;
+ guint8 name_size;
+
+ dissect_lan_destination(tvb, offset, "Source", tree);
+ offset += 8;
+
+ dissect_lan_destination(tvb, offset, "Target", tree);
+ offset += 8;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Source ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "LAN type: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), le_control_lan_type_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 1, "Maximum frame size: %s",
+ val_to_str(tvb_get_guint8(tvb, offset), le_control_frame_size_vals,
+ "Unknown (0x%02X)"));
+ offset += 1;
+
+ num_tlvs = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "Number of TLVs: %u", num_tlvs);
+ offset += 1;
+
+ name_size = tvb_get_guint8(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, 1, "ELAN name size: %u", name_size);
+ offset += 1;
+
+ proto_tree_add_text(tree, tvb, offset, 20, "Target ATM Address: %s",
+ tvb_bytes_to_str(tvb, offset, 20));
+ offset += 20;
+
+ if (name_size > 32)
+ name_size = 32;
+ if (name_size != 0) {
+ proto_tree_add_text(tree, tvb, offset, name_size, "ELAN name: %s",
+ tvb_bytes_to_str(tvb, offset, name_size));
+ }
+ offset += 32;
+
+ dissect_le_control_tlvs(tvb, offset, num_tlvs, tree);
+}
+