Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-slowprotocols.c
1 /* packet-slowprotocols.c
2  * Routines for EtherType (0x8809) Slow Protocols disassembly.
3  *
4  * $Id$
5  *
6  * Copyright 2002 Steve Housley <steve_housley@3com.com>
7  * Copyright 2005 Dominique Bastien <dbastien@accedian.com>
8  * Copyright 2009 Artem Tamazov <artem.tamazov@telllabs.com>
9  * Copyright 2010 Roberto Morro <roberto.morro[AT]tilab.com>
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <string.h>
35 #include <glib.h>
36 #include <epan/packet.h>
37 #include <epan/etypes.h>
38 #include <epan/llcsaps.h>
39 #include <epan/ppptypes.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/expert.h>
42
43 /* General declarations */
44
45 #define SLOW_PROTO_SUBTYPE              0
46
47 #define LACP_SUBTYPE                    0x1
48 #define MARKER_SUBTYPE                  0x2
49 #define OAM_SUBTYPE                     0x3
50 #define OSSP_SUBTYPE                    0xa /* IEEE 802.3 Annex 57A*/
51
52
53 /* Offsets of fields within a LACPDU */
54
55 #define LACPDU_VERSION_NUMBER           1
56
57 #define LACPDU_ACTOR_TYPE               2
58 #define LACPDU_ACTOR_INFO_LEN           3
59 #define LACPDU_ACTOR_SYS_PRIORITY       4
60 #define LACPDU_ACTOR_SYSTEM             6
61 #define LACPDU_ACTOR_KEY                12
62 #define LACPDU_ACTOR_PORT_PRIORITY      14
63 #define LACPDU_ACTOR_PORT               16
64 #define LACPDU_ACTOR_STATE              18
65 #define LACPDU_ACTOR_RESERVED           19
66
67 #define LACPDU_PARTNER_TYPE             22
68 #define LACPDU_PARTNER_INFO_LEN         23
69 #define LACPDU_PARTNER_SYS_PRIORITY     24
70 #define LACPDU_PARTNER_SYSTEM           26
71 #define LACPDU_PARTNER_KEY              32
72 #define LACPDU_PARTNER_PORT_PRIORITY    34
73 #define LACPDU_PARTNER_PORT             36
74 #define LACPDU_PARTNER_STATE            38
75 #define LACPDU_PARTNER_RESERVED         39
76
77 #define LACPDU_COLL_TYPE                42
78 #define LACPDU_COLL_INFO_LEN            43
79 #define LACPDU_COLL_MAX_DELAY           44
80 #define LACPDU_COLL_RESERVED            46
81
82 #define LACPDU_TERM_TYPE                58
83 #define LACPDU_TERM_LEN                 59
84 #define LACPDU_TERM_RESERVED            60
85
86 /* Actor and Partner Flag bits */
87 #define LACPDU_FLAGS_ACTIVITY           0x01
88 #define LACPDU_FLAGS_TIMEOUT            0x02
89 #define LACPDU_FLAGS_AGGREGATION        0x04
90 #define LACPDU_FLAGS_SYNC               0x08
91 #define LACPDU_FLAGS_COLLECTING         0x10
92 #define LACPDU_FLAGS_DISTRIB            0x20
93 #define LACPDU_FLAGS_DEFAULTED          0x40
94 #define LACPDU_FLAGS_EXPIRED            0x80
95
96
97 /* MARKER TLVs subtype */
98 #define MARKERPDU_END_MARKER            0x0
99 #define MARKERPDU_MARKER_INFO           0x1
100 #define MARKERPDU_MARKER_RESPONSE       0x2
101
102
103 /* Offsets of fields within a OAMPDU */
104 #define OAMPDU_FLAGS                    1
105 #define OAMPDU_CODE                     3
106
107 #define OAMPDU_HEADER_SIZE              4
108
109 /* OAMPDU Flag bits */
110 #define OAMPDU_FLAGS_LINK_FAULT         0x01
111 #define OAMPDU_FLAGS_DYING_GASP         0x02
112 #define OAMPDU_FLAGS_CRITICAL_EVENT     0x04
113 #define OAMPDU_FLAGS_LOCAL_EVAL         0x08
114 #define OAMPDU_FLAGS_LOCAL_STABLE       0x10
115 #define OAMPDU_FLAGS_REMOTE_EVAL        0x20
116 #define OAMPDU_FLAGS_REMOTE_STABLE      0x40
117
118 /* OAMPDU Code */
119 #define OAMPDU_INFORMATION              0x0
120 #define OAMPDU_EVENT_NOTIFICATION       0x1
121 #define OAMPDU_VAR_REQUEST              0x2
122 #define OAMPDU_VAR_RESPONSE             0x3
123 #define OAMPDU_LOOPBACK_CTRL            0x4
124 #define OAMPDU_VENDOR_SPECIFIC          0xFE
125
126 /* Information Type */
127 #define OAMPDU_INFO_TYPE_ENDMARKER      0x0
128 #define OAMPDU_INFO_TYPE_LOCAL          0x1
129 #define OAMPDU_INFO_TYPE_REMOTE         0x2
130 #define OAMPDU_INFO_TYPE_ORG            0xFE
131
132 /* Size of fields within a OAMPDU Information */
133 #define OAMPDU_INFO_TYPE_SZ             1
134 #define OAMPDU_INFO_LENGTH_SZ           1
135 #define OAMPDU_INFO_VERSION_SZ          1
136 #define OAMPDU_INFO_REVISION_SZ         2
137 #define OAMPDU_INFO_STATE_SZ            1
138 #define OAMPDU_INFO_OAM_CONFIG_SZ       1
139 #define OAMPDU_INFO_OAMPDU_CONFIG_SZ    2
140 #define OAMPDU_INFO_OUI_SZ              3
141 #define OAMPDU_INFO_VENDOR_SPECIFIC_SZ  4
142
143 /* OAM configuration bits */
144
145 #define OAMPDU_INFO_CONFIG_MODE         0x01
146 #define OAMPDU_INFO_CONFIG_UNI          0x02
147 #define OAMPDU_INFO_CONFIG_LPBK         0x04
148 #define OAMPDU_INFO_CONFIG_EVENT        0x08
149 #define OAMPDU_INFO_CONFIG_VAR          0x10
150
151 /* Event Type */
152 #define OAMPDU_EVENT_TYPE_END           0x0
153 #define OAMPDU_EVENT_TYPE_ESPE          0x1
154 #define OAMPDU_EVENT_TYPE_EFE           0x2
155 #define OAMPDU_EVENT_TYPE_EFPE          0x3
156 #define OAMPDU_EVENT_TYPE_EFSSE         0x4
157 #define OAMPDU_EVENT_TYPE_OSE           0xFE
158
159 /* Size of fields within a OAMPDU Event notification */
160 #define OAMPDU_EVENT_SEQUENCE_SZ        2
161 #define OAMPDU_EVENT_TYPE_SZ            1
162 #define OAMPDU_EVENT_LENGTH_SZ          1
163 #define OAMPDU_EVENT_TIMESTAMP_SZ       2
164
165 /* Size of fields within a OAMPDU ESPE: Errored Symbol Period Event TLV */
166 #define OAMPDU_ESPE_WINDOW_SZ           8
167 #define OAMPDU_ESPE_THRESHOLD_SZ        8
168 #define OAMPDU_ESPE_ERRORS_SZ           8
169 #define OAMPDU_ESPE_ERR_TOTAL_SZ        8
170 #define OAMPDU_ESPE_TOTAL_SZ            4
171
172 /* Size of fields within a OAMPDU EFE: Errored Frame Event TLV */
173 #define OAMPDU_EFE_WINDOW_SZ            2
174 #define OAMPDU_EFE_THRESHOLD_SZ         4
175 #define OAMPDU_EFE_ERRORS_SZ            4
176 #define OAMPDU_EFE_ERR_TOTAL_SZ         8
177 #define OAMPDU_EFE_TOTAL_SZ             4
178
179 /* Size of fields within a OAMPDU EFPE: Errored Frame Period Event TLV */
180 #define OAMPDU_EFPE_WINDOW_SZ           4
181 #define OAMPDU_EFPE_THRESHOLD_SZ        4
182 #define OAMPDU_EFPE_ERRORS_SZ           4
183 #define OAMPDU_EFPE_ERR_TOTAL_SZ        8
184 #define OAMPDU_EFPE_TOTAL_SZ            4
185
186 /* Size of fields within a OAMPDU EFSSE: Errored Frame Seconds Summary Event TLV */
187 #define OAMPDU_EFSSE_WINDOW_SZ          2
188 #define OAMPDU_EFSSE_THRESHOLD_SZ       2
189 #define OAMPDU_EFSSE_ERRORS_SZ          2
190 #define OAMPDU_EFSSE_ERR_TOTAL_SZ       4
191 #define OAMPDU_EFSSE_TOTAL_SZ           4
192
193 /* Variable Branch Type */
194 #define OAMPDU_VARS_OBJECT              0x3
195 #define OAMPDU_VARS_PACKAGE             0x4
196 #define OAMPDU_VARS_BINDING             0x6
197 #define OAMPDU_VARS_ATTRIBUTE           0x7
198
199 /* OAMPDU Loopback Control bits */
200 #define OAMPDU_LPBK_ENABLE              0x01
201 #define OAMPDU_LPBK_DISABLE             0x02
202
203
204 static const value_string subtype_vals[] = {
205     { LACP_SUBTYPE, "LACP" },
206     { MARKER_SUBTYPE, "Marker Protocol" },
207     { OAM_SUBTYPE, "OAM" },
208     { OSSP_SUBTYPE, "Organization Specific Slow Protocol" },
209     { 0, NULL }
210 };
211
212 static const value_string marker_vals[] = {
213     { 1, "Marker Information" },
214     { 2, "Marker Response Information" },
215     { 0, NULL }
216 };
217
218 /* see IEEE802.3, table 57-4 */
219 static const value_string code_vals[] = {
220     { 0, "Information" },
221     { 1, "Event Notification" },
222     { 2, "Variable Request" },
223     { 3, "Variable Response" },
224     { 4, "Loopback Control"},
225     { 0xFE, "Organization Specific" },
226     { 0, NULL }
227 };
228
229 /* see IEEE802.3, table 57-6 */
230 static const value_string info_type_vals[] = {
231     { 0, "End of TLV marker" },
232     { 1, "Local Information TLV" },
233     { 2, "Remote Information TLV" },
234     { 0xFE, "Organization Specific Information TLV" },
235     { 0, NULL }
236 };
237
238 /* see IEEE802.3, table 57-12 */
239 static const value_string event_type_vals[] = {
240     { 0, "End of TLV marker" },
241     { 1, "Errored Symbol Period Event" },
242     { 2, "Errored Frame Event" },
243     { 3, "Errored Frame Period Event" },
244     { 4, "Errored Frame Seconds Summary Event" },
245     { 0xFE, "Organization Specific Event TLV" },
246     { 0, NULL }
247 };
248
249
250 /*
251  * In the OAM protocol the {iso(1) member-body(2) us(840) ieee802dot3(10006)
252  * csmacdmgt(30)} prefix for the objects is pre-define. Only the
253  * managedObjectClass(3) is put in the branch and the leaf is one of the
254  * following value:
255  */
256 static const value_string object_vals[] = {
257     {  1, "macObjectClass" },
258     {  2, "phyObjectClass"},
259     {  3, "repeaterObjectClass"},
260     {  4, "groupObjectClass"},
261     {  5, "repeaterPortObjectClass"},
262     {  6, "mauObjectClass"},
263     {  7, "autoNegObjectClass"},
264     {  8, "macControlObjectClass"},
265     {  9, "macControlFunctionObjectClass"},
266     { 10, "oAggregator"},
267     { 11, "oAggregationPort"},
268     { 12, "oAggPortStats"},
269     { 13, "oAggPortDebugInformation" },
270     { 15, "pseObjectClass"},
271     { 17, "midSpanObjectClass"},
272     { 18, "midSpanGroupObjectClass"},
273     { 19, "ompObjectClass"},
274     { 20, "oamObjectClass" },
275     { 21, "mpcpObjectClass" },
276     { 24, "pafObjectClass" },
277     { 25, "pmeObjectClass"},
278     { 0, NULL }
279 };
280
281 /*
282  * In the OAM protocol the {iso(1) member-body(2) us(840) ieee802dot3(10006)
283  * csmacdmgt(30)} prefix for the objects is pre-define. Only the
284  * package(4) is put in the branch and the leaf is one of the
285  * following value:
286  */
287 static const value_string package_vals[] = {
288     {  1, "macMandatoryPkg" },
289     {  2, "macRecommendedPkg" },
290     {  3, "macOptionalPkg" },
291     {  4, "macarrayPkg" },
292     {  5, "macExcessiveDeferralPkg" },
293     {  6, "phyRecommendedPkg" },
294     {  7, "phyMultiplePhyPkg" },
295     {  8, "phy100MbpsMonitor" },
296     {  9, "repeaterPerfMonitorPkg"},
297     { 10, "portPerfMonitorPkg"},
298     { 11, "portAddrTrackPkg"},
299     { 12, "port100MbpsMonitor"},
300     { 13, "mauControlPkg"},
301     { 14, "mediaLossTrackingPkg"},
302     { 15, "broadbandMAUPkg"},
303     { 16, "mau100MbpsMonitor"},
304     { 17, "macControlRecommendedPkg" },
305     { 18, "portBurst"},
306     { 19, "pAggregatorMandatory"},
307     { 20, "pAggregatorRecommended"},
308     { 21, "pAggregatorOptional"},
309     { 22, "pAggregationPortMandatory"},
310     { 23, "pAggPortStats"},
311     { 24, "pAggPortDebugInformation"},
312
313     { 27, "pseRecommendedPkg"},
314
315     { 30, "fecMonitor"},
316     { 35, "pcsMonitor"},
317     { 37, "oMPError"},
318     { 38, "pafAggregation"},
319     { 0, NULL }
320 };
321
322 /*
323  * In the OAM protocol the {iso(1) member-body(2) us(840) ieee802dot3(10006)
324  * csmacdmgt(30)} prefix for the objects is pre-define. Only the
325  * nameBinding(6) is put in the branch and the leaf is one of the
326  * following value:
327  */
328 static const value_string binding_vals[] = {
329     { 26, "repeaterPortName"},
330     { 0, NULL }
331 };
332
333 /*
334  * In the OAM protocol the {iso(1) member-body(2) us(840) ieee802dot3(10006)
335  * csmacdmgt(30)} prefix for the objects is pre-define. Only the
336  * attribute(7) is put in the branch and the leaf is one of the
337  * following value:
338  */
339 static const value_string attribute_vals[] = {
340     {   1, "aMACID" },
341     {   2, "aFramesTransmittedOK" },
342     {   3, "aSingleCollisionFrames" },
343     {   4, "aMultipleCollisionFrames" },
344     {   5, "aFramesReceivedOK" },
345     {   6, "aFrameCheckSequenceErrors" },
346     {   7, "aAlignmentErrors" },
347     {   8, "aOctetsTransmittedOK" },
348     {   9, "aFramesWithDeferredXmissions" },
349     {  10, "aLateCollisions" },
350     {  11, "aFramesAbortedDueToXSColls" },
351     {  12, "aFramesLostDueToIntMACXmitError" },
352     {  13, "aCarrierSenseErrors" },
353     {  14, "aOctetsReceivedOK" },
354     {  15, "aFramesLostDueToIntMACRcvError" },
355     {  16, "aPromiscuousStatus" },
356     {  17, "aReadMulticastAddressList" },
357     {  18, "aMulticastFramesXmittedOK" },
358     {  19, "aBroadcastFramesXmittedOK" },
359     {  20, "aFramesWithExcessiveDeferral" },
360     {  21, "aMulticastFramesReceivedOK" },
361     {  22, "aBroadcastFramesReceivedOK" },
362     {  23, "aInRangeLengthErrors" },
363     {  24, "aOutOfRangeLengthField" },
364     {  25, "aFrameTooLongErrors" },
365     {  26, "aMACEnableStatus" },
366     {  27, "aTransmitEnableStatus" },
367     {  28, "aMulticastReceiveStatus" },
368     {  29, "aReadWriteMACAddress" },
369     {  30, "aCollisionFrames" },
370     {  31, "aPHYID" },
371     {  32, "aPHYType" },
372     {  33, "aPHYTypeList" },
373     {  34, "aSQETestErrors" },
374     {  35, "aSymbolErrorDuringCarrier" },
375     {  36, "aMIIDetect" },
376     {  37, "aPHYAdminState" },
377     {  38, "aRepeaterID" },
378     {  39, "aRepeaterType" },
379     {  40, "aRepeaterGroupCapacity" },
380     {  41, "aGroupMap" },
381     {  42, "aRepeaterHealthState" },
382     {  43, "aRepeaterHealthText" },
383     {  44, "aRepeaterHealthData" },
384     {  44, "aTransmitCollisions" },
385     {  46, "aGroupID" },
386     {  47, "aGroupPortCapacity" },
387     {  48, "aPortMap" },
388     {  49, "aPortID" },
389     {  50, "aPortAdminState" },
390     {  51, "aAutoPartitionState" },
391     {  52, "aReadableFrames" },
392     {  53, "aReadableOctets" },
393     {  54, "aFrameCheckSequenceErrors" },
394     {  55, "aAlignmentErrors" },
395     {  56, "aFramesTooLong" },
396     {  57, "aShortEvents" },
397     {  58, "aRunts" },
398     {  59, "aCollisions" },
399     {  60, "aLateEvents" },
400     {  61, "aVeryLongEvents" },
401     {  62, "aDataRateMismatches" },
402     {  63, "aAutoPartitions" },
403     {  64, "aIsolates" },
404     {  65, "aSymbolErrorDuringPacket" },
405     {  66, "aLastSourceAddress" },
406     {  67, "aSourceAddressChanges" },
407     {  68, "aMAUID" },
408     {  69, "aMAUType" },
409     {  70, "aMAUTypeList" },
410     {  71, "aMediaAvailable" },
411     {  72, "aLoseMediaCounter" },
412     {  73, "aJabber" },
413     {  74, "aMAUAdminState" },
414     {  75, "aBbMAUXmitRcvSplitType" },
415     {  76, "aBroadbandFrequencies" },
416     {  77, "aFalseCarriers" },
417     {  78, "aAutoNegID" },
418     {  79, "aAutoNegAdminState" },
419     {  80, "aAutoNegRemoteSignaling" },
420     {  81, "aAutoNegAutoConfig" },
421     {  82, "aAutoNegLocalTechnologyAbility" },
422     {  83, "aAutoNegAdvertisedTechnologyAbility" },
423     {  84, "aAutoNegReceivedTechnologyAbility" },
424     {  85, "aAutoNegLocalSelectorAbility" },
425     {  86, "aAutoNegAdvertisedSelectorAbility" },
426     {  87, "aAutoNegReceivedSelectorAbility" },
427
428     {  89, "aMACCapabilities" },
429     {  90, "aDuplexStatus" },
430     {  91, "aIdleErrorCount"},
431     {  92, "aMACControlID" },
432     {  93, "aMACControlFunctionsSupported" },
433     {  94, "aMACControlFramesTransmitted" },
434     {  95, "aMACControlFramesReceived" },
435     {  96, "aUnsupportedOpcodesReceived" },
436     {  97, "aPAUSELinkDelayAllowance" },
437     {  98, "aPAUSEMACCtrlFramesTransmitted" },
438     {  99, "aPAUSEMACCtrlFramesReceived" },
439     { 100, "aBursts" },
440     { 101, "aAggID" },
441     { 102, "aAggDescription" },
442     { 103, "aAggName" },
443     { 104, "aAggActorSystemID" },
444     { 105, "aAggActorSystemPriority" },
445     { 106, "aAggAggregateOrIndividual" },
446     { 107, "aAggActorAdminKey" },
447     { 108, "aAggActorOperKey" },
448     { 109, "aAggMACAddress" },
449     { 110, "aAggPartnerSystemID" },
450     { 111, "aAggPartnerSystemPriority" },
451     { 112, "aAggPartnerOperKey" },
452     { 113, "aAggAdminState" },
453     { 114, "aAggOperState" },
454     { 115, "aAggTimeOfLastOperChange" },
455     { 116, "aAggDataRate" },
456     { 117, "aAggOctetsTxOK" },
457     { 118, "aAggOctetsRxOK" },
458     { 119, "aAggFramesTxOK" },
459     { 120, "aAggFramesRxOK" },
460     { 121, "aAggMulticastFramesTxOK" },
461     { 122, "aAggMulticastFramesRxOK" },
462     { 123, "aAggBroadcastFramesTxOK" },
463     { 124, "aAggBroadcastFramesRxOK" },
464     { 125, "aAggFramesDiscardedOnTx" },
465     { 126, "aAggFramesDiscardedOnRx" },
466     { 127, "aAggFramesWithTxErrors" },
467     { 128, "aAggFramesWithRxErrors" },
468     { 129, "aAggUnknownProtocolFrames" },
469     { 130, "aAggLinkUpDownNotificationEnable" },
470     { 131, "aAggPortList" },
471     { 132, "aAggCollectorMaxDelay" },
472     { 133, "aAggPortID" },
473     { 134, "aAggPortActorSystemPriority" },
474     { 135, "aAggPortActorSystemID" },
475     { 136, "aAggPortActorAdminKey" },
476     { 137, "aAggPortActorOperKey" },
477     { 138, "aAggPortPartnerAdminSystemPriority" },
478     { 139, "aAggPortPartnerOperSystemPriority" },
479     { 140, "aAggPortPartnerAdminSystemID" },
480     { 141, "aAggPortPartnerOperSystemID" },
481     { 142, "aAggPortPartnerAdminKey" },
482     { 143, "aAggPortPartnerOperKey" },
483     { 144, "aAggPortSelectedAggID" },
484     { 145, "aAggPortAttachedAggID" },
485     { 146, "aAggPortActorPort" },
486     { 147, "aAggPortActorPortPriority" },
487     { 148, "aAggPortPartnerAdminPort" },
488     { 149, "aAggPortPartnerOperPort" },
489     { 150, "aAggPortPartnerAdminPortPriority" },
490     { 151, "aAggPortPartnerOperPortPriority" },
491     { 152, "aAggPortActorAdminState" },
492     { 153, "aAggPortActorOperState" },
493     { 154, "aAggPortPartnerAdminState" },
494     { 155, "aAggPortPartnerOperState" },
495     { 156, "aAggPortAggregateOrIndividual" },
496     { 157, "aAggPortStatsID" },
497     { 158, "aAggPortStatsLACPDUsRx" },
498     { 159, "aAggPortStatsMarkerPDUsRx" },
499     { 160, "aAggPortStatsMarkerResponsePDUsRx" },
500     { 161, "aAggPortStatsUnknownRx" },
501     { 162, "aAggPortStatsIllegalRx" },
502     { 163, "aAggPortStatsLACPDUsTx" },
503     { 164, "aAggPortStatsMarkerPDUsTx" },
504     { 165, "aAggPortStatsMarkerResponsePDUsTx" },
505     { 166, "aAggPortDebugInformationID" },
506     { 167, "aAggPortDebugRxState" },
507     { 168, "aAggPortDebugLastRxTime" },
508     { 169, "aAggPortDebugMuxState" },
509     { 170, "aAggPortDebugMuxReason" },
510     { 171, "aAggPortDebugActorChurnState" },
511     { 172, "aAggPortDebugPartnerChurnState" },
512     { 173, "aAggPortDebugActorChurnCount" },
513     { 174, "aAggPortDebugPartnerChurnCount" },
514     { 175, "aAggPortDebugActorSyncTransitionCount" },
515     { 176, "aAggPortDebugPartnerSyncTransitionCount" },
516     { 177, "aAggPortDebugActorChangeCount" },
517     { 178, "aAggPortDebugPartnerChangeCount" },
518
519
520     { 236, "aOAMID" },
521     { 237, "aOAMAdminState" },
522     { 238, "aOAMMode" },
523     { 239, "aOAMRemoteMACAddress" },
524     { 240, "aOAMRemoteConfiguration" },
525     { 241, "aOAMRemotePDUConfiguration" },
526     { 242, "aOAMLocalFlagsField" },
527     { 243, "aOAMRemoteFlagsField" },
528     { 244, "aOAMRemoteRevision" },
529     { 245, "aOAMRemoteState" },
530     { 246, "aOAMRemoteVendorOUI" },
531     { 247, "aOAMRemoteVendorSpecificInfo" },
532
533     { 250, "aOAMUnsupportedCodesRx" },
534     { 251, "aOAMInformationTx" },
535     { 252, "aOAMInformationRx" },
536
537     { 254, "aOAMUniqueEventNotificationRx" },
538     { 255, "aOAMDuplicateEventNotificationRx" },
539     { 256, "aOAMLoopbackControlTx" },
540     { 257, "aOAMLoopbackControlRx" },
541     { 258, "aOAMVariableRequestTx" },
542     { 259, "aOAMVariableRequestRx" },
543     { 260, "aOAMVariableResponseTx" },
544     { 261, "aOAMVariableResponseRx" },
545     { 262, "aOAMOrganizationSpecificTx" },
546     { 263, "aOAMOrganizationSpecificRx" },
547     { 264, "aOAMLocalErrSymPeriodConfig" },
548     { 265, "aOAMLocalErrSymPeriodEvent" },
549     { 266, "aOAMLocalErrFrameConfig" },
550     { 267, "aOAMLocalErrFrameEvent" },
551     { 268, "aOAMLocalErrFramePeriodConfig" },
552     { 269, "aOAMLocalErrFramePeriodEvent" },
553     { 270, "aOAMLocalErrFrameSecsSummaryConfig" },
554     { 271, "aOAMLocalErrFrameSecsSummaryEvent" },
555     { 272, "aOAMRemoteErrSymPeriodEvent" },
556     { 273, "aOAMRemoteErrFrameEvent" },
557     { 274, "aOAMRemoteErrFramePeriodEvent" },
558     { 275, "aOAMRemoteErrFrameSecsSummaryEvent" },
559     { 276, "aFramesLostDueToOAMError" },
560
561     { 333, "aOAMDiscoveryState"},
562     { 334, "aOAMLocalConfiguration"},
563     { 335, "aOAMLocalPDUConfiguration"},
564     { 336, "aOAMLocalRevision"},
565     { 337, "aOAMLocalState"},
566     { 338, "aOAMUnsupportedCodesTx" },
567     { 339, "aOAMUniqueEventNotificationTx" },
568     { 340, "aOAMDuplicateEventNotificationTx" },
569     { 0, NULL }
570 };
571
572 static value_string_ext attribute_vals_ext = VALUE_STRING_EXT_INIT(attribute_vals);
573
574 /*
575  * In the OAM protocol the {iso(1) member-body(2) us(840) ieee802dot3(10006)
576  * csmacdmgt(30)} prefix for the objects is pre-define. Only the
577  * package(4) is put in the branch and the leaf is one of the
578  * following value:
579  */
580 static const value_string indication_vals[] = {
581     { 0x01, "Variable Container(s) exceeded OAMPDU data field" },
582
583     { 0x20, "Attribute->Unable to return due to an undetermined error" },
584     { 0x21, "Attribute->Unable to return because it is not supported" },
585     { 0x22, "Attribute->May have been corrupted due to reset" },
586     { 0x23, "Attribute->Unable to return due to a hardware failure" },
587     { 0x24, "Attribute->Experience an overflow error" },
588
589     { 0x40, "Object->End of object indication" },
590     { 0x41, "Object->Unable to return due to an undetermined error" },
591     { 0x42, "Object->Unable to return because it is not supported" },
592     { 0x43, "Object->May have been corrupted due to reset" },
593     { 0x44, "Object->Unable to return due to a hardware failure" },
594
595     { 0x60, "Package->End of package indication" },
596     { 0x61, "Package->Unable to return due to an undetermined error" },
597     { 0x62, "Package->Unable to return because it is not supported" },
598     { 0x63, "Package->May have been corrupted due to reset" },
599     { 0x64, "Package->Unable to return due to a hardware failure" },
600     { 0, NULL }
601 };
602
603 static const value_string status_vals[] _U_ = {
604     { 0x00, "Unsatisfied, can't complete" },
605     { 0x01, "Discovery in process" },
606     { 0x02, "Satisfied, Discovery complete" },
607     { 0x10, "Satisfied, Discovery complete" },
608     { 0x20, "Discovery in process" },
609     { 0x40, "Satisfied, Discovery complete" },
610     { 0x50, "BUG Satisfied, Discovery complete" },
611     { 0x80, "Discovery in process" },
612
613     { 0, NULL }
614 };
615
616 static const value_string branch_vals[] = {
617     { 3, "Object" },
618     { 4, "Package" },
619     { 6, "nameBinding" },
620     { 7, "Attribute" },
621     { 0, NULL }
622 };
623
624 static const value_string parser_vals[] = {
625     { 0, "Forward non-OAMPDUs to higher sublayer" },
626     { 1, "Loopback non-OAMPDUs to the lower sublayer" },
627     { 2, "Discarding non-OAMPDUs" },
628     { 3, "Reserved" },
629     { 0, NULL }
630 };
631
632 static const true_false_string mux = {
633     "Discard non-OAMPDUs",
634     "Forward non-OAMPDUs to lower sublayer"
635 };
636
637 static const true_false_string oam_mode = {
638     "DTE configured in Active mode",
639     "DTE configured in Passive mode"
640 };
641
642 static const true_false_string oam_uni = {
643     "DTE is capable of sending OAMPDUs when rcv path is down",
644     "DTE is not capable of sending OAMPDUs when rcv path is down"
645 };
646
647 static const true_false_string oam_lpbk = {
648     "DTE is capable of OAM remote loopback mode",
649     "DTE is not capable of OAM remote loopback mode"
650 };
651
652 static const true_false_string oam_event = {
653     "DTE supports interpreting Link Events",
654     "DTE does not support interpreting Link Events"
655 };
656
657 static const true_false_string oam_var = {
658     "DTE supports sending Variable Response",
659     "DTE does not support sending Variable Response"
660 };
661
662 /*
663  * ESMC
664  */
665 #define ITU_OUI_0                   0x00
666 #define ITU_OUI_1                   0x19
667 #define ITU_OUI_2                   0xa7
668 #define OUI_SIZE                       3
669 #define ESMC_ITU_SUBTYPE          0x0001
670 #define ESMC_VERSION_1              0x01
671 #define ESMC_QL_TLV_TYPE            0x01
672 #define ESMC_QL_TLV_LENGTH          0x04
673 #define ESMC_TIMESTAMP_TLV_TYPE     0x02
674 #define ESMC_TIMESTAMP_TLV_LENGTH   0x08
675
676 static const value_string esmc_event_flag_vals[] = {
677     { 0, "Information ESMC PDU" },
678     { 1, "Time-critical Event ESMC PDU" },
679     { 0, NULL }
680 };
681
682 static const value_string esmc_tlv_type_vals[] = {
683     { 1, "Quality Level" },
684     { 2, "Timestamp" },
685     { 0, NULL }
686 };
687
688 static const value_string esmc_timestamp_valid_flag_vals[] = {
689     { 0, "Not set. Do not use Timestamp value even if Timestamp TLV present" },
690     { 1, "Set. Timestamp TLV Present" },
691     { 0, NULL }
692 };
693
694 /* G.781 5.5.1.1 Option I SDH (same in G.707) */
695 static const value_string esmc_quality_level_opt_1_vals[] = {
696     {  2,   "QL-PRC, Primary reference clock (G.811)" },
697     {  4,   "QL-SSU-A, Type I or V SSU clock (G.812), 'transit node clock'" },
698     {  8,   "QL-SSU-B, Type VI SSU clock (G.812), 'local node clock'" },
699     { 11,   "QL-SEC, SEC clock (G.813, Option I) or QL-EEC1 (G.8262)" },
700     { 15,   "QL-DNU, 'Do Not Use'" },
701     { 0, NULL }
702 };
703
704 static const value_string esmc_quality_level_opt_1_vals_short[] = {
705     {  2,   "QL-PRC" },
706     {  4,   "QL-SSU-A" },
707     {  8,   "QL-SSU-B" },
708     { 11,   "QL-SEC" },
709     { 15,   "QL-DNU" },
710     { 0, NULL }
711 };
712
713 #if 0 /*not used yet*/
714 /* G.781 5.5.1.2 Option II SDH synchronization networking */
715 static const value_string esmc_quality_level_opt_2_vals[] = {
716     {  0,   "QL-STU, unknown - signal does not carry the QL message of the source" },
717     {  1,   "QL-PRS, PRS clock (G.811) / ST1, Stratum 1 Traceable" },
718     {  4,   "QL-TNC, Transit Node Clock (G.812, Type V)" },
719     {  7,   "QL-ST2, Stratum 2 clock (G.812, Type II)" },
720     { 10,   "QL-ST3, Stratum 3 clock (G.812, Type IV) or QL-EEC2 (G.8262)" },
721     { 12,   "QL-SMC, SONET self timed clock (G.813, Option II) / SMC 20 ppm Clock Traceable" },
722     { 13,   "QL-ST3E, Stratum 3E clock (G.812, Type III)" },
723     { 14,   "QL-PROV, provisionable by the network operator / Reserved for Network Synchronization" },
724     { 15,   "QL-DUS, shall not be used for synchronization" },
725     { 0, NULL }
726 };
727
728 static const value_string esmc_quality_level_opt_2_short[] = {
729     {  0,   "QL-STU" },
730     {  1,   "QL-PRS" },
731     {  4,   "QL-TNC" },
732     { 7,    "QL-ST2" },
733     { 10,   "QL-ST3" },
734     { 12,   "QL-SMC" },
735     { 13,   "QL-ST3E" },
736     { 14,   "QL-PROV" },
737     { 15,   "QL-DUS" },
738     { 0, NULL }
739 };
740 #endif
741
742 static const value_string esmc_quality_level_invalid_vals[] = {
743     {  0,   "QL-INV0" },
744     {  1,   "QL-INV1" },
745     {  2,   "QL-INV2" },
746     {  3,   "QL-INV3" },
747     {  4,   "QL-INV4" },
748     {  5,   "QL-INV5" },
749     {  6,   "QL-INV6" },
750     {  7,   "QL-INV7" },
751     {  8,   "QL-INV8" },
752     {  9,   "QL-INV9" },
753     { 10,   "QL-INV10" },
754     { 11,   "QL-INV11" },
755     { 12,   "QL-INV12" },
756     { 13,   "QL-INV13" },
757     { 14,   "QL-INV14" },
758     { 15,   "QL-INV15" },
759     { 0, NULL }
760 };
761
762 /* Initialise the protocol and registered fields */
763 static int proto_slow = -1;
764
765 static int hf_slow_subtype = -1;
766
767 static int hf_lacpdu_version_number = -1;
768 static int hf_lacpdu_actor_type = -1;
769 static int hf_lacpdu_actor_info_len = -1;
770 static int hf_lacpdu_actor_sys_priority = -1;
771 static int hf_lacpdu_actor_sys = -1;
772 static int hf_lacpdu_actor_key = -1;
773 static int hf_lacpdu_actor_port_priority = -1;
774 static int hf_lacpdu_actor_port = -1;
775 static int hf_lacpdu_actor_state = -1;
776 static int hf_lacpdu_flags_a_activity = -1;
777 static int hf_lacpdu_flags_a_timeout = -1;
778 static int hf_lacpdu_flags_a_aggregation = -1;
779 static int hf_lacpdu_flags_a_sync = -1;
780 static int hf_lacpdu_flags_a_collecting = -1;
781 static int hf_lacpdu_flags_a_distrib = -1;
782 static int hf_lacpdu_flags_a_defaulted = -1;
783 static int hf_lacpdu_flags_a_expired = -1;
784 static int hf_lacpdu_actor_reserved = -1;
785
786 static int hf_lacpdu_partner_type = -1;
787 static int hf_lacpdu_partner_info_len = -1;
788 static int hf_lacpdu_partner_sys_priority = -1;
789 static int hf_lacpdu_partner_sys = -1;
790 static int hf_lacpdu_partner_key = -1;
791 static int hf_lacpdu_partner_port_priority = -1;
792 static int hf_lacpdu_partner_port = -1;
793 static int hf_lacpdu_partner_state = -1;
794 static int hf_lacpdu_flags_p_activity = -1;
795 static int hf_lacpdu_flags_p_timeout = -1;
796 static int hf_lacpdu_flags_p_aggregation = -1;
797 static int hf_lacpdu_flags_p_sync = -1;
798 static int hf_lacpdu_flags_p_collecting = -1;
799 static int hf_lacpdu_flags_p_distrib = -1;
800 static int hf_lacpdu_flags_p_defaulted = -1;
801 static int hf_lacpdu_flags_p_expired = -1;
802 static int hf_lacpdu_partner_reserved = -1;
803
804 static int hf_lacpdu_coll_type = -1;
805 static int hf_lacpdu_coll_info_len = -1;
806 static int hf_lacpdu_coll_max_delay = -1;
807 static int hf_lacpdu_coll_reserved = -1;
808
809 static int hf_lacpdu_term_type = -1;
810 static int hf_lacpdu_term_len = -1;
811 static int hf_lacpdu_term_reserved = -1;
812
813 /* ESMC */
814 static int hf_ossp_oui = -1;
815 static int hf_itu_subtype = -1;
816 static int hf_esmc_version = -1;
817 static int hf_esmc_event_flag = -1;
818 static int hf_esmc_timestamp_valid_flag = -1;
819 static int hf_esmc_reserved_32 = -1;
820 static int hf_esmc_tlv = -1;
821 static int hf_esmc_tlv_type = -1;
822 static int hf_esmc_tlv_length = -1;
823 static int hf_esmc_tlv_ql_unused = -1;
824 static int hf_esmc_tlv_ts_reserved = -1;
825 static int hf_esmc_quality_level_opt_1 = -1;
826 #if 0 /*not used yet*/
827 static int hf_esmc_quality_level_opt_2 = -1;
828 #endif
829 static int hf_esmc_quality_level_invalid = -1;
830 static int hf_esmc_timestamp = -1;
831 static int hf_esmc_padding = -1;
832
833 /*
834  * The Timestamp TLV and Timestamp Valid Flag fields
835  * are proposed in WD56 document for G.8264.
836  * WD56 is not accepted at this moment (June 2009).
837  *
838  * The following variable controls dissection of Timestamp fields.
839  * Implementation is not fully complete yet -- in this version
840  * Timestamp dissection is always enabled.
841  *
842  * I expect that when WD56 proposal for G.8264 will be accepted,
843  * ESMC Version would be used to control Timestamp dissection.
844  * In this case this variable will be eliminated (replaced).
845  *
846  * Until that, a preference which controls Timestamp
847  * dissection may be added, if such need arise.
848  * At the moment this is not practical as nobody needs this.
849  */
850 static gboolean pref_decode_esmc_timestamp = TRUE;
851
852 /* MARKER */
853 static int hf_marker_version_number = -1;
854 static int hf_marker_tlv_type = -1;
855 static int hf_marker_tlv_length = -1;
856 static int hf_marker_req_port = -1;
857 static int hf_marker_req_system = -1;
858 static int hf_marker_req_trans_id = -1;
859
860 /* OAM */
861 static int hf_oampdu_flags = -1;
862 static int hf_oampdu_flags_link_fault = -1;
863 static int hf_oampdu_flags_dying_gasp = -1;
864 static int hf_oampdu_flags_critical_event = -1;
865 static int hf_oampdu_flags_local_evaluating = -1;
866 static int hf_oampdu_flags_local_stable = -1;
867 static int hf_oampdu_flags_remote_evaluating = -1;
868 static int hf_oampdu_flags_remote_stable = -1;
869 static int hf_oampdu_code = -1;
870
871 static int hf_oampdu_info_type = -1;
872 static int hf_oampdu_info_len = -1;
873 static int hf_oampdu_info_version = -1;
874 static int hf_oampdu_info_revision = -1;
875 static int hf_oampdu_info_state = -1;
876 static int hf_oampdu_info_oamConfig = -1;
877 static int hf_oampdu_info_oampduConfig = -1;
878 static int hf_oampdu_info_oui = -1;
879 static int hf_oampdu_info_vendor = -1;
880
881 static int hf_oampdu_info_state_parser = -1;
882 static int hf_oampdu_info_state_mux = -1;
883
884 static int hf_oampdu_info_oamConfig_mode = -1;
885 static int hf_oampdu_info_oamConfig_uni = -1;
886 static int hf_oampdu_info_oamConfig_lpbk = -1;
887 static int hf_oampdu_info_oamConfig_event = -1;
888 static int hf_oampdu_info_oamConfig_var = -1;
889
890 static int hf_oampdu_event_type = -1;
891 static int hf_oampdu_event_sequence = -1;
892 static int hf_oampdu_event_length = -1;
893 static int hf_oampdu_event_timeStamp = -1;
894
895 static int hf_oampdu_event_espeWindow = -1;
896 static int hf_oampdu_event_espeThreshold = -1;
897 static int hf_oampdu_event_espeErrors = -1;
898 static int hf_oampdu_event_espeTotalErrors = -1;
899 static int hf_oampdu_event_espeTotalEvents = -1;
900
901 static int hf_oampdu_event_efeWindow = -1;
902 static int hf_oampdu_event_efeThreshold = -1;
903 static int hf_oampdu_event_efeErrors = -1;
904 static int hf_oampdu_event_efeTotalErrors = -1;
905 static int hf_oampdu_event_efeTotalEvents = -1;
906
907 static int hf_oampdu_event_efpeWindow = -1;
908 static int hf_oampdu_event_efpeThreshold = -1;
909 static int hf_oampdu_event_efpeErrors = -1;
910 static int hf_oampdu_event_efpeTotalErrors = -1;
911 static int hf_oampdu_event_efpeTotalEvents = -1;
912
913 static int hf_oampdu_event_efsseWindow = -1;
914 static int hf_oampdu_event_efsseThreshold = -1;
915 static int hf_oampdu_event_efsseErrors = -1;
916 static int hf_oampdu_event_efsseTotalErrors = -1;
917 static int hf_oampdu_event_efsseTotalEvents = -1;
918
919 static int hf_oampdu_variable_branch = -1;
920 static int hf_oampdu_variable_object = -1;
921 static int hf_oampdu_variable_package = -1;
922 static int hf_oampdu_variable_binding = -1;
923 static int hf_oampdu_variable_attribute = -1;
924 static int hf_oampdu_variable_width = -1;
925 static int hf_oampdu_variable_indication = -1;
926 static int hf_oampdu_variable_value = -1;
927
928 static int hf_oampdu_lpbk = -1;
929 static int hf_oampdu_lpbk_enable = -1;
930 static int hf_oampdu_lpbk_disable = -1;
931
932
933 /* Initialise the subtree pointers */
934
935 static gint ett_pdu = -1;
936
937 static gint ett_lacpdu = -1;
938 static gint ett_lacpdu_a_flags = -1;
939 static gint ett_lacpdu_p_flags = -1;
940
941 static gint ett_marker = -1;
942 static gint ett_esmc = -1;
943
944 static gint ett_oampdu = -1;
945 static gint ett_oampdu_flags = -1;
946
947 static gint ett_oampdu_local_info = -1;
948 static gint ett_oampdu_local_info_state = -1;
949 static gint ett_oampdu_local_info_config = -1;
950 static gint ett_oampdu_remote_info = -1;
951 static gint ett_oampdu_remote_info_state = -1;
952 static gint ett_oampdu_remote_info_config = -1;
953 static gint ett_oampdu_org_info = -1;
954
955 static gint ett_oampdu_event_espe = -1;
956 static gint ett_oampdu_event_efe = -1;
957 static gint ett_oampdu_event_efpe = -1;
958 static gint ett_oampdu_event_efsse = -1;
959 static gint ett_oampdu_event_ose = -1;
960
961 static gint ett_oampdu_lpbk_ctrl = -1;
962
963 static gint ett_ossppdu = -1;
964 static gint ett_itu_ossp = -1;
965
966 static const char initial_sep[] = " (";
967 static const char cont_sep[] = ", ";
968
969 static dissector_handle_t dh_data;
970
971 #define APPEND_BOOLEAN_FLAG(flag, item, string) \
972     if(flag){                                   \
973         if(item)                                          \
974             proto_item_append_text(item, string, sep);    \
975         sep = cont_sep;                                   \
976     }
977
978
979 #define APPEND_OUI_NAME(item, string, tvb, offset) \
980     if(item){                              \
981         string = tvb_get_manuf_name(tvb, offset);          \
982         proto_item_append_text(item, " (");                \
983         proto_item_append_text(item, "%s", string);        \
984         proto_item_append_text(item, ")");                 \
985     }
986
987 static void
988 dissect_lacp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
989
990 static void
991 dissect_marker_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
992
993 static void
994 dissect_ossp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
995
996 static void
997 dissect_oampdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
998
999 static void
1000 dissect_oampdu_information(tvbuff_t *tvb, proto_tree *tree);
1001
1002 static void
1003 dissect_oampdu_event_notification(tvbuff_t *tvb, proto_tree *tree);
1004
1005 static void
1006 dissect_oampdu_variable_request(tvbuff_t *tvb, proto_tree *tree);
1007
1008 static void
1009 dissect_oampdu_variable_response(tvbuff_t *tvb, proto_tree *tree);
1010
1011 static void
1012 dissect_oampdu_loopback_control(tvbuff_t *tvb, proto_tree *tree);
1013
1014 static void
1015 dissect_oampdu_vendor_specific(tvbuff_t *tvb, proto_tree *tree);
1016
1017 static void
1018 dissect_esmc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *treex);
1019
1020 static void
1021 dissect_itu_ossp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1022
1023 /*
1024  * Name: dissect_slow_protocols
1025  *
1026  * Description:
1027  *    This function is used to dissect the slow protocols define in IEEE802.3
1028  *    CSMA/CD. The current slow protocols subtype are define in ANNEX 43B of
1029  *    the 802.3 document. In case of an unsupported slow protocols, we only
1030  *    fill the protocol and info columns.
1031  *
1032  * Input Arguments:
1033  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1034  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1035  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1036  *
1037  * Return Values:
1038  *    None
1039  *
1040  * Notes:
1041  *    Dominique Bastien (dbastien@accedian.com)
1042  *      + add support for OAM slow protocol (defined in clause 57).
1043  *      + add support for Marker slow protocol (defined in clause 43).
1044  *    Artem Tamazov (artem.tamazov@telllabs.com)
1045  *      + add support for ESMC (Ethernet Synchronization Messaging Channel),
1046  *        G.8264/Y.1364 clause 11).
1047  */
1048 static void
1049 dissect_slow_protocols(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1050 {
1051     guint8      subtype;
1052     proto_tree *pdu_tree;
1053     proto_item *pdu_item;
1054
1055     subtype = tvb_get_guint8(tvb, 0);
1056
1057     switch (subtype)
1058     {
1059         case LACP_SUBTYPE:
1060             dissect_lacp_pdu(tvb, pinfo, tree);
1061             break;
1062         case MARKER_SUBTYPE:
1063             dissect_marker_pdu(tvb, pinfo, tree);
1064             break;
1065         case OAM_SUBTYPE:
1066             dissect_oampdu(tvb, pinfo, tree);
1067             break;
1068         case OSSP_SUBTYPE:
1069             dissect_ossp_pdu(tvb, pinfo, tree);
1070             break;
1071         default:
1072         {
1073             col_set_str(pinfo->cinfo, COL_PROTOCOL, "Slow Protocols");
1074             col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown Subtype = %u.", subtype);
1075
1076             if (tree)
1077             {
1078                 pdu_item = proto_tree_add_item(tree, proto_slow, tvb,
1079                         0, -1, FALSE);
1080                 pdu_tree = proto_item_add_subtree(pdu_item, ett_pdu);
1081
1082                 /* Subtype */
1083                 proto_tree_add_item(pdu_tree, hf_slow_subtype, tvb,
1084                         0, 1, FALSE);
1085             }
1086
1087             break;
1088         }
1089     }
1090 }
1091
1092 /*
1093  * Name: dissect_lacp_pdu
1094  *
1095  * Description:
1096  *    This function is used to dissect the Link Aggregation Control Protocol
1097  *    slow protocols define in IEEE802.3 clause 43.3.
1098  *
1099  * Input Arguments:
1100  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1101  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1102  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1103  *
1104  * Return Values: None
1105  *
1106  * Notes:
1107  */
1108 static void
1109 dissect_lacp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1110 {
1111     guint16 raw_word;
1112     guint8  raw_octet;
1113
1114     guint8  flags;
1115
1116     proto_tree *lacpdu_tree;
1117     proto_item *lacpdu_item;
1118     proto_tree *actor_flags_tree;
1119     proto_item *actor_flags_item;
1120     proto_tree *partner_flags_tree;
1121     proto_item *partner_flags_item;
1122
1123     const char *sep;
1124
1125
1126     col_set_str(pinfo->cinfo, COL_PROTOCOL, "LACP");
1127     col_set_str(pinfo->cinfo, COL_INFO, "Link Aggregation Control Protocol");
1128
1129     if (tree)
1130     {
1131         /* Add LACP Heading */
1132         lacpdu_item = proto_tree_add_protocol_format(tree, proto_slow, tvb,
1133                 0, -1, "Link Aggregation Control Protocol");
1134         lacpdu_tree = proto_item_add_subtree(lacpdu_item, ett_lacpdu);
1135
1136         /* Subtype */
1137         proto_tree_add_item(lacpdu_tree, hf_slow_subtype, tvb,
1138                 0, 1, FALSE);
1139
1140         /* Version Number */
1141         raw_octet = tvb_get_guint8(tvb, LACPDU_VERSION_NUMBER);
1142         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_version_number, tvb,
1143                 LACPDU_VERSION_NUMBER, 1, raw_octet);
1144
1145         col_append_fstr(pinfo->cinfo, COL_INFO, "Version %d.  ", raw_octet);
1146
1147         /* Actor Type */
1148         raw_octet = tvb_get_guint8(tvb, LACPDU_ACTOR_TYPE);
1149         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_type, tvb,
1150                 LACPDU_ACTOR_TYPE, 1, raw_octet);
1151
1152         /* Actor Info Length */
1153         raw_octet = tvb_get_guint8(tvb, LACPDU_ACTOR_INFO_LEN);
1154         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_info_len, tvb,
1155                 LACPDU_ACTOR_INFO_LEN, 1, raw_octet);
1156
1157         /* Actor System Priority */
1158
1159         raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_SYS_PRIORITY);
1160         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_sys_priority, tvb,
1161                 LACPDU_ACTOR_SYS_PRIORITY, 2, raw_word);
1162         /* Actor System */
1163
1164         proto_tree_add_item(lacpdu_tree, hf_lacpdu_actor_sys, tvb,
1165                 LACPDU_ACTOR_SYSTEM, 6, ENC_NA);
1166
1167         /* Actor Key */
1168
1169         raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_KEY);
1170         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_key, tvb,
1171                 LACPDU_ACTOR_KEY, 2, raw_word);
1172
1173         /* Actor Port Priority */
1174
1175         raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_PORT_PRIORITY);
1176         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_port_priority, tvb,
1177                 LACPDU_ACTOR_PORT_PRIORITY, 2, raw_word);
1178
1179         /* Actor Port */
1180
1181         raw_word = tvb_get_ntohs(tvb, LACPDU_ACTOR_PORT);
1182         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_port, tvb,
1183                 LACPDU_ACTOR_PORT, 2, raw_word);
1184
1185         col_append_fstr(pinfo->cinfo, COL_INFO, "Actor Port = %d ", raw_word);
1186
1187         /* Actor State */
1188
1189         flags = tvb_get_guint8(tvb, LACPDU_ACTOR_STATE);
1190         actor_flags_item = proto_tree_add_uint(lacpdu_tree, hf_lacpdu_actor_state, tvb,
1191                 LACPDU_ACTOR_STATE, 1, flags);
1192         actor_flags_tree = proto_item_add_subtree(actor_flags_item, ett_lacpdu_a_flags);
1193
1194         sep = initial_sep;
1195
1196         /* Activity Flag */
1197
1198         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_ACTIVITY, actor_flags_item,
1199                 "%sActivity");
1200         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_activity, tvb,
1201                 LACPDU_ACTOR_STATE, 1, flags);
1202
1203         /* Timeout Flag */
1204
1205         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_TIMEOUT, actor_flags_item,
1206                 "%sTimeout");
1207         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_timeout, tvb,
1208                 LACPDU_ACTOR_STATE, 1, flags);
1209
1210         /* Aggregation Flag */
1211
1212         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_AGGREGATION, actor_flags_item,
1213                 "%sAggregation");
1214         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_aggregation, tvb,
1215                 LACPDU_ACTOR_STATE, 1, flags);
1216
1217         /* Synchronization Flag */
1218
1219         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_SYNC, actor_flags_item,
1220                 "%sSynchronization");
1221         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_sync, tvb,
1222                 LACPDU_ACTOR_STATE, 1, flags);
1223
1224         /* Collecting Flag */
1225
1226         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_COLLECTING, actor_flags_item,
1227                 "%sCollecting");
1228         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_collecting, tvb,
1229                 LACPDU_ACTOR_STATE, 1, flags);
1230
1231
1232         /* Distributing Flag */
1233
1234         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DISTRIB, actor_flags_item,
1235                 "%sDistributing");
1236         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_distrib, tvb,
1237                 LACPDU_ACTOR_STATE, 1, flags);
1238
1239         /* Defaulted Flag */
1240
1241         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DEFAULTED, actor_flags_item,
1242                 "%sDefaulted");
1243         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_defaulted, tvb,
1244                 LACPDU_ACTOR_STATE, 1, flags);
1245
1246         /* Expired Flag */
1247
1248         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_EXPIRED, actor_flags_item,
1249                 "%sExpired");
1250         proto_tree_add_boolean(actor_flags_tree, hf_lacpdu_flags_a_expired, tvb,
1251                 LACPDU_ACTOR_STATE, 1, flags);
1252
1253         if (sep != initial_sep)
1254         {
1255             /* We put something in; put in the terminating ")" */
1256             proto_item_append_text(actor_flags_item, ")");
1257         }
1258
1259         /* Actor Reserved */
1260
1261         proto_tree_add_item(lacpdu_tree, hf_lacpdu_actor_reserved, tvb,
1262                 LACPDU_ACTOR_RESERVED, 3, ENC_NA);
1263
1264
1265         /* Partner Type */
1266         raw_octet = tvb_get_guint8(tvb, LACPDU_PARTNER_TYPE);
1267         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_type, tvb,
1268                 LACPDU_PARTNER_TYPE, 1, raw_octet);
1269
1270         /* Partner Info Length */
1271         raw_octet = tvb_get_guint8(tvb, LACPDU_PARTNER_INFO_LEN);
1272         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_info_len, tvb,
1273                 LACPDU_PARTNER_INFO_LEN, 1, raw_octet);
1274
1275         /* Partner System Priority */
1276
1277         raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_SYS_PRIORITY);
1278         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_sys_priority, tvb,
1279                 LACPDU_PARTNER_SYS_PRIORITY, 2, raw_word);
1280
1281         /* Partner System */
1282
1283         proto_tree_add_item(lacpdu_tree, hf_lacpdu_partner_sys, tvb,
1284                 LACPDU_PARTNER_SYSTEM, 6, ENC_NA);
1285
1286         /* Partner Key */
1287
1288         raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_KEY);
1289         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_key, tvb,
1290                 LACPDU_PARTNER_KEY, 2, raw_word);
1291
1292         /* Partner Port Priority */
1293
1294         raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_PORT_PRIORITY);
1295         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_port_priority, tvb,
1296                 LACPDU_PARTNER_PORT_PRIORITY, 2, raw_word);
1297
1298         /* Partner Port */
1299
1300         raw_word = tvb_get_ntohs(tvb, LACPDU_PARTNER_PORT);
1301         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_port, tvb,
1302                 LACPDU_PARTNER_PORT, 2, raw_word);
1303
1304         col_append_fstr(pinfo->cinfo, COL_INFO, "Partner Port = %d ", raw_word);
1305
1306         /* Partner State */
1307
1308         flags = tvb_get_guint8(tvb, LACPDU_PARTNER_STATE);
1309         partner_flags_item = proto_tree_add_uint(lacpdu_tree, hf_lacpdu_partner_state, tvb,
1310                 LACPDU_PARTNER_STATE, 1, flags);
1311         partner_flags_tree = proto_item_add_subtree(partner_flags_item, ett_lacpdu_p_flags);
1312
1313         sep = initial_sep;
1314
1315         /* Activity Flag */
1316
1317         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_ACTIVITY, partner_flags_item,
1318                 "%sActivity");
1319         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_activity, tvb,
1320                 LACPDU_PARTNER_STATE, 1, flags);
1321
1322         /* Timeout Flag */
1323
1324         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_TIMEOUT, partner_flags_item,
1325                 "%sTimeout");
1326         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_timeout, tvb,
1327                 LACPDU_PARTNER_STATE, 1, flags);
1328
1329         /* Aggregation Flag */
1330
1331         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_AGGREGATION, partner_flags_item,
1332                 "%sAggregation");
1333         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_aggregation, tvb,
1334                 LACPDU_PARTNER_STATE, 1, flags);
1335
1336         /* Synchronization Flag */
1337
1338         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_SYNC, partner_flags_item,
1339                 "%sSynchronization");
1340         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_sync, tvb,
1341                 LACPDU_PARTNER_STATE, 1, flags);
1342
1343         /* Collecting Flag */
1344
1345         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_COLLECTING, partner_flags_item,
1346                 "%sCollecting");
1347         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_collecting, tvb,
1348                 LACPDU_PARTNER_STATE, 1, flags);
1349
1350
1351         /* Distributing Flag */
1352
1353         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DISTRIB, partner_flags_item,
1354                 "%sDistributing");
1355         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_distrib, tvb,
1356                 LACPDU_PARTNER_STATE, 1, flags);
1357
1358         /* Defaulted Flag */
1359
1360         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_DEFAULTED, partner_flags_item,
1361                 "%sDefaulted");
1362         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_defaulted, tvb,
1363                 LACPDU_PARTNER_STATE, 1, flags);
1364
1365         /* Expired Flag */
1366
1367         APPEND_BOOLEAN_FLAG(flags & LACPDU_FLAGS_EXPIRED, partner_flags_item,
1368                 "%sExpired");
1369         proto_tree_add_boolean(partner_flags_tree, hf_lacpdu_flags_p_expired, tvb,
1370                 LACPDU_PARTNER_STATE, 1, flags);
1371
1372         if (sep != initial_sep)
1373         {
1374             /* We put something in; put in the terminating ")" */
1375             proto_item_append_text(partner_flags_item, ")");
1376         }
1377
1378         /* Partner Reserved */
1379
1380         proto_tree_add_item(lacpdu_tree, hf_lacpdu_partner_reserved, tvb,
1381                 LACPDU_PARTNER_RESERVED, 3, ENC_NA);
1382
1383
1384         /* Collector Type */
1385         raw_octet = tvb_get_guint8(tvb, LACPDU_COLL_TYPE);
1386         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_type, tvb,
1387                 LACPDU_COLL_TYPE, 1, raw_octet);
1388
1389         /* Collector Info Length */
1390         raw_octet = tvb_get_guint8(tvb, LACPDU_COLL_INFO_LEN);
1391         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_info_len, tvb,
1392                 LACPDU_COLL_INFO_LEN, 1, raw_octet);
1393
1394         /* Collector Max Delay */
1395
1396         raw_word = tvb_get_ntohs(tvb, LACPDU_COLL_MAX_DELAY);
1397         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_coll_max_delay, tvb,
1398                 LACPDU_COLL_MAX_DELAY, 2, raw_word);
1399
1400         /* Collector Reserved */
1401
1402         proto_tree_add_item(lacpdu_tree, hf_lacpdu_coll_reserved, tvb,
1403                 LACPDU_COLL_RESERVED, 12, ENC_NA);
1404
1405         /* Terminator Type */
1406         raw_octet = tvb_get_guint8(tvb, LACPDU_TERM_TYPE);
1407         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_term_type, tvb,
1408                 LACPDU_TERM_TYPE, 1, raw_octet);
1409
1410         /* Terminator Info Length */
1411         raw_octet = tvb_get_guint8(tvb, LACPDU_TERM_LEN);
1412         proto_tree_add_uint(lacpdu_tree, hf_lacpdu_term_len, tvb,
1413                 LACPDU_TERM_LEN, 1, raw_octet);
1414
1415         /* Terminator Reserved */
1416
1417         proto_tree_add_item(lacpdu_tree, hf_lacpdu_term_reserved, tvb,
1418                 LACPDU_TERM_RESERVED, 50, ENC_NA);
1419     }
1420 }
1421
1422 /*
1423  * Name: dissect_marker_pdu
1424  *
1425  * Description:
1426  *    This function is used to dissect the Link Aggregation Marker Protocol
1427  *    slow protocols define in IEEE802.3 clause 43.5 (The PDUs are define
1428  *    in section 43.5.3.2). The TLV type are, 0x01 for a marker TLV and 0x02
1429  *    for a marker response. A value of 0x00 indicate an end of message.
1430  *
1431  * Input Arguments:
1432  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1433  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1434  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1435  *
1436  * Return Values: None
1437  *
1438  * Notes:
1439  *    Dominique Bastien (dbastien@accedian.com)
1440  *      + add support for MARKER and MARKER Response PDUs.
1441  */
1442 static void
1443 dissect_marker_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1444 {
1445     guint8  raw_octet;
1446     guint16 raw_word;
1447     guint32 dword;
1448     guint32 offset;
1449
1450     proto_tree *marker_tree;
1451     proto_item *marker_item;
1452
1453
1454     col_set_str(pinfo->cinfo, COL_PROTOCOL, "MARKER");
1455     col_set_str(pinfo->cinfo, COL_INFO, "Marker Protocol");
1456
1457     if (tree)
1458     {
1459         marker_item = proto_tree_add_protocol_format(tree, proto_slow, tvb,
1460                             0, -1, "Marker Protocol");
1461         marker_tree = proto_item_add_subtree(marker_item, ett_marker);
1462
1463         /* Subtype */
1464         proto_tree_add_item(marker_tree, hf_slow_subtype, tvb,
1465                 0, 1, FALSE);
1466
1467         offset = 1;
1468
1469         /* Version Number */
1470         raw_octet = tvb_get_guint8(tvb, offset);
1471         proto_tree_add_uint(marker_tree, hf_marker_version_number, tvb,
1472                 offset, 1, raw_octet);
1473
1474         offset += 1;
1475
1476         while (1)
1477         {
1478             /* TLV Type */
1479             raw_octet = tvb_get_guint8(tvb, offset);
1480
1481             if (raw_octet==0) break;
1482
1483             proto_tree_add_uint(marker_tree, hf_marker_tlv_type, tvb,
1484                     offset, 1, raw_octet);
1485
1486             offset += 1;
1487
1488             /* TLV Length */
1489             raw_octet = tvb_get_guint8(tvb, offset);
1490             proto_tree_add_uint(marker_tree, hf_marker_tlv_length, tvb,
1491                     offset, 1, raw_octet);
1492             offset += 1;
1493
1494             /* Requester Port */
1495             raw_word = tvb_get_ntohs(tvb, offset);
1496             proto_tree_add_uint(marker_tree, hf_marker_req_port, tvb,
1497                     offset, 2, raw_word);
1498             offset += 2;
1499
1500             /* Requester System */
1501             proto_tree_add_item(marker_tree, hf_marker_req_system, tvb,
1502                     offset, 6, ENC_NA);
1503             offset += 6;
1504
1505             /* Requester Transaction ID */
1506             dword = tvb_get_ntohl(tvb, offset);
1507             proto_tree_add_uint(marker_tree, hf_marker_req_trans_id, tvb,
1508                     offset, 4, dword);
1509             offset += 2;
1510
1511             /* Pad to align */
1512             offset += 2;
1513         }
1514     }
1515 }
1516
1517 /*
1518  * Name: dissect_ossp_pdu
1519  *
1520  * Description:
1521  *    This function is used to dissect the Organization Specific Slow
1522  *    Protocol defined in IEEE 802.3 Annex 57B. Currently only the ESMC
1523  *    slow protocol as defined in ITU-T G.8264 is implemented
1524  *
1525  * Input Arguments:
1526  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1527  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1528  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1529  *
1530  * Return Values: None
1531  *
1532  * Notes:
1533  *    Roberto Morro (roberto.morro[AT]tilab.com)
1534  */
1535 static void
1536 dissect_ossp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1537 {
1538     gint          offset = 0;
1539     const gchar  *str;
1540     proto_item   *oui_item, *ossp_item;
1541     proto_tree   *ossp_tree;
1542     tvbuff_t     *ossp_tvb;
1543     const guint8  itu_oui[] = {ITU_OUI_0, ITU_OUI_1, ITU_OUI_2};
1544
1545     /* OUI of the organization defining the protocol */
1546     str = tvb_get_manuf_name(tvb, offset+1);
1547
1548     col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSSP");
1549     col_add_fstr(pinfo->cinfo, COL_INFO, "OUI: %s", str);
1550
1551     ossp_item = proto_tree_add_protocol_format(tree, proto_slow, tvb, 0, -1,
1552                                                "Organization Specific Slow Protocol");
1553     ossp_tree = proto_item_add_subtree(ossp_item, ett_ossppdu);
1554
1555     /* Slow Protocol Subtype */
1556     proto_tree_add_item(ossp_tree, hf_slow_subtype, tvb, offset, 1, FALSE);
1557     offset++;
1558
1559     oui_item = proto_tree_add_item(ossp_tree, hf_ossp_oui,
1560                                     tvb, offset, OUI_SIZE, ENC_NA);
1561     proto_item_append_text(oui_item, " (%s)", str);
1562     offset += 3;
1563
1564     ossp_tvb = tvb_new_subset(tvb, offset, -1, -1);
1565     if (tvb_memeql(tvb, 1, itu_oui, OUI_SIZE) == 0)
1566     {
1567        dissect_itu_ossp(ossp_tvb, pinfo, ossp_tree);
1568     }
1569 /*    new Organization Specific Slow Protocols go hereafter
1570  *
1571  *  else if (tvb_memeql(tvb, 1, xxx_oui, OUI_SIZE) == 0)
1572  *  {
1573  *      dissect_xxx_ossp(ossp_tvb, pinfo, ossp_tree);
1574  *  }
1575  *  else if (tvb_memeql(tvb, 1, yyy_oui, OUI_SIZE) == 0)
1576  *  {
1577  *      dissect_yyy_ossp(ossp_tvb, pinfo, ossp_tree);
1578  *  }
1579  */
1580     else
1581     {
1582         proto_item_append_text(oui_item, " (Unknown OSSP organization)");
1583     }
1584 }
1585
1586
1587 /*
1588  * Name: dissect_itu_ossp
1589  *
1590  * Description:
1591  *    This function is used to dissect the ITU-T OSSP (Organization Specific
1592  *    Slow Protocol). Currently only the Ethernet Synchronization
1593  *    Messaging Channel (ESMC) slow protocol as defined in ITU-T G.8264
1594  *    is implemented
1595  *
1596  * Input Arguments:
1597  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1598  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1599  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1600  *    subtype: the protocol subtype (according to IEEE802.3 annex 57B)
1601  *
1602  * Return Values: None
1603  *
1604  * Notes:
1605  *    Roberto Morro (roberto.morro[AT]tilab.com)
1606  */
1607
1608 static void
1609 dissect_itu_ossp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1610 {
1611     guint16     subtype;
1612     proto_tree *itu_ossp_tree, *ti;
1613
1614     /* ITU-T OSSP Subtype */
1615     subtype = tvb_get_ntohs(tvb, 0);
1616     ti = proto_tree_add_item(tree, hf_itu_subtype, tvb, 0, 2, FALSE);
1617
1618     itu_ossp_tree = proto_item_add_subtree(ti, ett_itu_ossp);
1619
1620     switch (subtype)
1621     {
1622         case ESMC_ITU_SUBTYPE:
1623             dissect_esmc_pdu(tvb, pinfo, itu_ossp_tree);
1624             break;
1625
1626 /*    Other ITU-T defined slow protocols go hereafter
1627  *
1628  *    case XXXX_ITU_SUBTYPE:
1629  *      dissect_xxxx_pdu(tvb, pinfo, itu_ossp_tree);
1630  *      break;
1631  */
1632         default:
1633             proto_item_append_text(itu_ossp_tree, " (Unknown)");
1634     }
1635 }
1636 /*
1637  * Description:
1638  *    This function is used to dissect ESMC PDU defined G.8264/Y.1364 clause 11.3.1.1.
1639  *
1640  *    Added: TimeStamp TLV as per WD56 proposal for G.8264,
1641  *    "TLVs for ESMC and Querying Capability".
1642  */
1643 static void
1644 dissect_esmc_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *treex)
1645 {
1646     gint     offset    = 2; /*starting from ESMC Version */
1647     gboolean event_flag;
1648     gboolean malformed = FALSE;
1649     gint     ql        = -1; /*negative means unknown:*/
1650     gboolean timestamp_valid_flag = FALSE; /*set if timestamp valid*/
1651     gint32   timestamp = -1; /*nanoseconds*/
1652
1653     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ESMC");
1654
1655     proto_item_append_text(treex, ": ESMC");
1656     {
1657         proto_tree *tree_a;
1658         tree_a = proto_item_add_subtree(treex, ett_esmc);
1659
1660         { /* version */
1661             proto_item *item_b;
1662             item_b = proto_tree_add_item(tree_a, hf_esmc_version, tvb, offset, 1, FALSE);
1663             if ((tvb_get_guint8(tvb, offset) >> 4) != ESMC_VERSION_1)
1664             {
1665                 malformed = TRUE;
1666                 expert_add_info_format(pinfo, item_b, PI_MALFORMED, PI_ERROR
1667                         ,"Version must be 0x%.1x claim compliance with Version 1 of this protocol"
1668                         ,ESMC_VERSION_1);
1669             }
1670             /*stay at the same octet in tvb*/
1671         }
1672         { /* event flag */
1673             event_flag = ((tvb_get_guint8(tvb, offset) & 0x08) != 0);
1674             proto_tree_add_item(tree_a, hf_esmc_event_flag, tvb, offset, 1, FALSE);
1675             /*stay at the same octet in tvb*/
1676         }
1677         if (pref_decode_esmc_timestamp)
1678         { /* timestamp valid flag */
1679             timestamp_valid_flag = ((tvb_get_guint8(tvb, offset) & 0x04) != 0);
1680             proto_tree_add_item(tree_a, hf_esmc_timestamp_valid_flag, tvb, offset, 1, FALSE);
1681             /*stay at the same octet in tvb*/
1682         }
1683         { /* reserved bits */
1684             proto_item *item_b;
1685             guint32 reserved;
1686             reserved = tvb_get_ntohl(tvb, offset)
1687                         & (pref_decode_esmc_timestamp ? 0x3ffffff : 0x7ffffff);
1688             item_b = proto_tree_add_uint_format_value(tree_a, hf_esmc_reserved_32, tvb, offset, 4
1689                                                     , reserved, "0x%.7x", reserved);
1690             if (reserved != 0x0)
1691             {
1692                 malformed = TRUE;
1693                 expert_add_info_format(pinfo, item_b, PI_MALFORMED, PI_WARN
1694                         ,"Reserved bits must be set to all zero on transmitter");
1695             }
1696             offset += 4;
1697         }
1698         proto_item_append_text(treex, ", Event:%s", event_flag ?
1699                                "Time-critical" : "Information");
1700
1701         /*
1702          * Quality Level TLV is mandatory at fixed location.
1703          */
1704         {
1705             proto_item *item_b;
1706             guint8 type;
1707             item_b = proto_tree_add_item(tree_a, hf_esmc_tlv, tvb, offset, 4, ENC_NA);
1708             {
1709                 proto_tree *tree_b;
1710                 tree_b = proto_item_add_subtree(item_b, ett_esmc);
1711                 {
1712                     proto_item *item_c;
1713                     guint16 length;
1714                     guint8 unused;
1715
1716                     /* type */
1717                     type = tvb_get_guint8(tvb, offset);
1718                     item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_type, tvb, offset, 1, FALSE);
1719                     if (type != ESMC_QL_TLV_TYPE)
1720                     {
1721                         malformed = TRUE;
1722                         expert_add_info_format(pinfo, item_c, PI_MALFORMED, PI_ERROR
1723                                 ,"TLV Type must be == 0x%.2x (QL) because QL TLV must be first in the ESMC PDU"
1724                                 ,ESMC_QL_TLV_TYPE);
1725                         expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_NOTE
1726                                 ,"Let's decode as if this is QL TLV");
1727                     }
1728                     offset += 1;
1729
1730                     /* length */
1731                     length = tvb_get_ntohs(tvb, offset);
1732                     item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_length, tvb, offset, 2, FALSE);
1733                     if (length != ESMC_QL_TLV_LENGTH)
1734                     {
1735                         malformed = TRUE;
1736                         expert_add_info_format(pinfo, item_c, PI_MALFORMED, PI_ERROR
1737                                 ,"QL TLV Length must be == 0x%.4x", ESMC_QL_TLV_LENGTH);
1738                         expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_NOTE
1739                                 ,"Let's decode this TLV as if Length has valid value");
1740                     }
1741                     offset += 2;
1742
1743                     /* value */
1744                     unused = tvb_get_guint8(tvb, offset); /*as temp var*/
1745                     ql = unused & 0x0f;
1746                     unused &= 0xf0;
1747                     item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_ql_unused, tvb, offset, 1, FALSE);
1748                     if (unused != 0x00)
1749                     {
1750                         malformed = TRUE;
1751                         expert_add_info_format(pinfo, item_c, PI_MALFORMED, PI_WARN
1752                                 ,"Unused bits of TLV must be all zeroes");
1753                     }
1754                     if (NULL != match_strval(ql, esmc_quality_level_opt_1_vals))
1755                     {
1756                         proto_tree_add_item(tree_b, hf_esmc_quality_level_opt_1, tvb, offset, 1, FALSE);
1757                     }
1758                     else
1759                     {
1760                         item_c = proto_tree_add_item(tree_b, hf_esmc_quality_level_invalid, tvb, offset, 1, FALSE);
1761                         expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_WARN
1762                                 ,"Invalid SSM message, unknown QL code");
1763                     }
1764                     offset += 1;
1765                 }
1766             }
1767             proto_item_append_text(item_b, ", %s"
1768                 , val_to_str(ql, esmc_quality_level_opt_1_vals_short, "QL-INV%d"));
1769         }
1770         proto_item_append_text(treex, ", %s"
1771             , val_to_str(ql, esmc_quality_level_opt_1_vals_short, "QL-INV%d"));
1772
1773         if (pref_decode_esmc_timestamp)
1774         {
1775             /*
1776              * Timestamp TLV is optional at fixed location.
1777              * Decode it if Timestamp Valid flag is set,
1778              * or if type of next TLV is 0x02.
1779              */
1780             guint8 type;
1781             type = tvb_get_guint8(tvb, offset);
1782
1783             if (timestamp_valid_flag || type == ESMC_TIMESTAMP_TLV_TYPE)
1784             {
1785                 proto_item *item_b;
1786                 item_b = proto_tree_add_item(tree_a, hf_esmc_tlv, tvb, offset, 8, ENC_NA);
1787                 {
1788                     proto_tree *tree_b;
1789                     tree_b = proto_item_add_subtree(item_b, ett_esmc);
1790                     {
1791                         proto_item *item_c;
1792                         guint16 length;
1793                         guint8 reserved;
1794
1795                         /* type */
1796                         item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_type, tvb, offset, 1, FALSE);
1797                         if (type != ESMC_TIMESTAMP_TLV_TYPE)
1798                         {
1799                             malformed = TRUE;
1800                             expert_add_info_format(pinfo, item_c, PI_MALFORMED, PI_ERROR
1801                                     ,"TLV Type must be == 0x%.2x (Timestamp) because Timestamp Valid Flag is set"
1802                                     ,ESMC_TIMESTAMP_TLV_TYPE);
1803                             expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_NOTE
1804                                     ,"Let's decode as if this is Timestamp TLV");
1805                         }
1806                         offset += 1;
1807
1808                         /* length */
1809                         length = tvb_get_ntohs(tvb, offset);
1810                         item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_length, tvb, offset, 2, FALSE);
1811                         if (length != ESMC_TIMESTAMP_TLV_LENGTH)
1812                         {
1813                             malformed = TRUE;
1814                             expert_add_info_format(pinfo, item_c, PI_MALFORMED, PI_ERROR
1815                                     ,"Timestamp TLV Length must be == 0x%.4x"
1816                                     ,ESMC_TIMESTAMP_TLV_LENGTH);
1817                             expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_NOTE
1818                                     ,"Let's decode this TLV as if Length has valid value");
1819                         }
1820                         offset += 2;
1821
1822                         /* value */
1823                         timestamp = (gint32)tvb_get_ntohl(tvb, offset);
1824                         item_c = proto_tree_add_item(tree_b, hf_esmc_timestamp, tvb, offset, 4, FALSE);
1825                         if (!timestamp_valid_flag) proto_item_append_text(item_c, " [invalid]");
1826                         offset += 4;
1827
1828                         /* reserved */
1829                         reserved = tvb_get_guint8(tvb, offset);
1830                         item_c = proto_tree_add_item(tree_b, hf_esmc_tlv_ts_reserved, tvb, offset, 1, FALSE);
1831                         if (reserved != 0x0)
1832                         {
1833                             expert_add_info_format(pinfo, item_c, PI_UNDECODED, PI_WARN
1834                                     ,"Reserved bits must be set to all zero");
1835                         }
1836                         offset += 1;
1837                     }
1838                 }
1839                 proto_item_append_text(item_b, ", Timestamp: %d ns", timestamp);
1840                 if (!timestamp_valid_flag) proto_item_append_text(item_b, " [invalid]");
1841             }
1842         }
1843         if (timestamp_valid_flag)
1844         {
1845             proto_item_append_text(treex, ", Timestamp:%d", timestamp);
1846         }
1847     }
1848
1849     { /* padding */
1850         gint padding_size;
1851         padding_size = tvb_length_remaining(tvb, offset);
1852         if (0 != padding_size)
1853         {
1854             proto_tree* tree_a;
1855             tree_a = proto_item_add_subtree(treex, ett_esmc);
1856             {
1857                 proto_item* item_b;
1858                 tvbuff_t* tvb_next;
1859                 tvb_next = tvb_new_subset(tvb, offset, padding_size, -1);
1860                 item_b = proto_tree_add_item(tree_a, hf_esmc_padding, tvb_next, 0, -1, ENC_NA);
1861                 proto_item_append_text(item_b, ", %d %s%s", padding_size
1862                 , "octet", plurality(padding_size,"","s"));
1863                 {
1864                     proto_tree* tree_b;
1865                     tree_b = proto_item_add_subtree(item_b, ett_esmc);
1866                     call_dissector(dh_data, tvb_next, pinfo, tree_b);
1867                 }
1868             }
1869         }
1870     }
1871
1872     col_clear(pinfo->cinfo, COL_INFO);
1873     /* append summary info */
1874     col_append_fstr(pinfo->cinfo, COL_INFO, "Event:%s", event_flag ?
1875                     "Time-critical" : "Information");
1876     if (ql >= 0)
1877     {
1878         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s"
1879         , val_to_str(ql, esmc_quality_level_opt_1_vals_short, "QL-INVALID-%d"));
1880     }
1881     if (timestamp_valid_flag)
1882     {
1883         col_append_fstr(pinfo->cinfo, COL_INFO, ", TS:%d", timestamp);
1884     }
1885     if (malformed)
1886     {
1887         col_append_str(pinfo->cinfo, COL_INFO, ", Malformed PDU");
1888     }
1889 }
1890
1891 /*
1892  * Name: dissect_oampdu
1893  *
1894  * Description:
1895  *    This function is used to dissect the Operation, Administration, and
1896  *    Maintenance slow protocol define in IEEE802.3 clause 57 (The OAMPDUs
1897  *    common part is define in section 57.4).
1898  *
1899  *    Only the 6 folowing code are currently define in the 2004 version of this
1900  *    protocol:
1901  *       OAMPDU_INFORMATION: 0x0
1902  *       OAMPDU_EVENT_NOTIFICATION: 0x1
1903  *       OAMPDU_VAR_REQUEST: 0x2
1904  *       OAMPDU_VAR_RESPONSE: 0x3
1905  *       OAMPDU_LOOPBACK_CTRL: 0x4
1906  *       OAMPDU_VENDOR_SPECIFIC: 0xFE
1907  *
1908  * Input Arguments:
1909  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
1910  *    pinfo: structure associate with the rcv packet (see packet_info.h).
1911  *    tree: the protocol tree associate with the rcv packet (see proto.h).
1912  *
1913  * Return Values: None
1914  *
1915  * Notes:
1916  *    Dominique Bastien (dbastien@accedian.com)
1917  *      + add support for 802.3ah-2004.
1918  */
1919 static void
1920 dissect_oampdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1921 {
1922     guint8    oampdu_code;
1923     guint16   flags,state;
1924     guint32   i;
1925
1926     proto_tree *oampdu_tree;
1927     proto_item *oampdu_item;
1928     proto_tree *flags_tree;
1929     proto_item *flags_item;
1930
1931     const char *sep = initial_sep;
1932
1933     col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM");
1934
1935     oampdu_code = tvb_get_guint8(tvb, OAMPDU_CODE);
1936
1937     switch (oampdu_code)
1938     {
1939         case OAMPDU_INFORMATION:
1940             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Information");
1941             break;
1942         case OAMPDU_EVENT_NOTIFICATION:
1943             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Event Notification");
1944             break;
1945         case OAMPDU_VAR_REQUEST:
1946             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Variable Request");
1947             break;
1948         case OAMPDU_VAR_RESPONSE:
1949             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Variable Response");
1950             break;
1951         case OAMPDU_LOOPBACK_CTRL:
1952             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Loopback Control");
1953             break;
1954         case OAMPDU_VENDOR_SPECIFIC:
1955             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU: Organization Specific");
1956             break;
1957         default:
1958             col_set_str(pinfo->cinfo, COL_INFO, "OAMPDU reserved");
1959             break;
1960     }
1961
1962
1963     if (tree)
1964     {
1965         /* Add OAM Heading */
1966         oampdu_item = proto_tree_add_protocol_format(tree, proto_slow, tvb,
1967                 0, -1, "OAM Protocol");
1968         oampdu_tree = proto_item_add_subtree(oampdu_item, ett_oampdu);
1969
1970         /* Subtype */
1971         proto_tree_add_item(oampdu_tree, hf_slow_subtype, tvb,
1972                 0, 1, FALSE);
1973
1974         /* Flags field */
1975         flags = tvb_get_ntohs(tvb, OAMPDU_FLAGS);
1976         flags_item = proto_tree_add_uint(oampdu_tree, hf_oampdu_flags, tvb,
1977                 OAMPDU_FLAGS, 2, flags);
1978         flags_tree = proto_item_add_subtree(flags_item, ett_oampdu_flags);
1979
1980         /*
1981          * In this section we add keywords for the bit set on the Flags's line.
1982          * We also add all the bit inside the subtree.
1983          */
1984         APPEND_BOOLEAN_FLAG(flags & OAMPDU_FLAGS_LINK_FAULT, flags_item,
1985                 "%sLink Fault");
1986         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_link_fault,
1987                 tvb, OAMPDU_FLAGS, 1, flags);
1988
1989         APPEND_BOOLEAN_FLAG(flags & OAMPDU_FLAGS_DYING_GASP, flags_item,
1990                 "%sDying Gasp");
1991         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_dying_gasp,
1992                 tvb, OAMPDU_FLAGS, 1, flags);
1993
1994         APPEND_BOOLEAN_FLAG(flags & OAMPDU_FLAGS_CRITICAL_EVENT, flags_item,
1995                 "%sCriticalEvent");
1996         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_critical_event,
1997                 tvb, OAMPDU_FLAGS, 1, flags);
1998
1999         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_local_evaluating,
2000                 tvb, OAMPDU_FLAGS, 1, flags);
2001
2002         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_local_stable,
2003                 tvb, OAMPDU_FLAGS, 1, flags);
2004
2005         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_remote_evaluating,
2006                 tvb, OAMPDU_FLAGS, 1, flags);
2007
2008         proto_tree_add_boolean(flags_tree, hf_oampdu_flags_remote_stable,
2009                 tvb, OAMPDU_FLAGS, 1, flags);
2010
2011         if (sep != cont_sep)
2012             proto_item_append_text(flags_item, " (");
2013         else
2014             proto_item_append_text(flags_item, ", ");
2015
2016         for(i=0;i<2;i++)
2017         {
2018             if (i==0)
2019             {
2020                 proto_item_append_text(flags_item, "local: ");
2021                 state = (flags&(OAMPDU_FLAGS_LOCAL_EVAL|OAMPDU_FLAGS_LOCAL_STABLE));
2022                 state = state>>3;
2023             }
2024             else
2025             {
2026                 proto_item_append_text(flags_item, "remote: ");
2027                 state = (flags&(OAMPDU_FLAGS_REMOTE_EVAL|OAMPDU_FLAGS_REMOTE_STABLE));
2028                 state = state>>5;
2029             }
2030
2031             switch (state)
2032             {
2033                 case 0:
2034                     proto_item_append_text(flags_item, "Unsatisfied");
2035                     break;
2036                 case 1:
2037                     proto_item_append_text(flags_item, "Discovery in process");
2038                     break;
2039                 case 2:
2040                     proto_item_append_text(flags_item, "Discovery complete");
2041                     break;
2042                 default:
2043                     proto_item_append_text(flags_item, "Reserved");
2044                     break;
2045             }
2046
2047             if (i==0)
2048                 proto_item_append_text(flags_item, ", ");
2049
2050         }
2051
2052         proto_item_append_text(flags_item, ")");
2053
2054         /* OAMPDU code */
2055         oampdu_code = tvb_get_guint8(tvb, OAMPDU_CODE);
2056         proto_tree_add_uint(oampdu_tree, hf_oampdu_code, tvb,
2057                 OAMPDU_CODE, 1, oampdu_code);
2058
2059         switch (oampdu_code)
2060         {
2061             case OAMPDU_INFORMATION:
2062                 dissect_oampdu_information(tvb, oampdu_tree);
2063                 break;
2064             case OAMPDU_EVENT_NOTIFICATION:
2065                 dissect_oampdu_event_notification(tvb, oampdu_tree);
2066                 break;
2067             case OAMPDU_VAR_REQUEST:
2068                 dissect_oampdu_variable_request(tvb, oampdu_tree);
2069                 break;
2070             case OAMPDU_VAR_RESPONSE:
2071                 dissect_oampdu_variable_response(tvb, oampdu_tree);
2072                 break;
2073             case OAMPDU_LOOPBACK_CTRL:
2074                 dissect_oampdu_loopback_control(tvb, oampdu_tree);
2075                 break;
2076             case OAMPDU_VENDOR_SPECIFIC:
2077                 dissect_oampdu_vendor_specific(tvb, oampdu_tree);
2078             default:
2079                 break;
2080         }
2081     }
2082 }
2083
2084 /*
2085  * Name: dissect_oampdu_information
2086  *
2087  * Description:
2088  *    This function is used to dissect the Information TLVs define in IEEE802.3
2089  *    section 57.5.2).
2090  *
2091  *
2092  * Input Arguments:
2093  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2094  *    tree: the protocol tree associate with the oampdu (see proto.h).
2095  *
2096  * Return Values: None
2097  *
2098  * Notes:
2099  *    Dominique Bastien (dbastien@accedian.com)
2100  *      + add support for 802.3ah-2004.
2101  */
2102 static void
2103 dissect_oampdu_information(tvbuff_t *tvb, proto_tree *tree)
2104 {
2105     guint16   raw_word;
2106     guint8    raw_octet;
2107     guint8    info_type;
2108     guint32   offset;
2109     guint16   bytes;
2110
2111     const guint8 *ptr;
2112
2113     proto_tree *info_tree;
2114     proto_item *info_item;
2115     proto_tree *state_tree;
2116     proto_item *state_item;
2117     proto_tree *cfg_tree;
2118     proto_item *cfg_item;
2119     proto_item *oui_item;
2120     proto_item *item;
2121
2122
2123     offset = OAMPDU_HEADER_SIZE;
2124
2125     while (1)
2126     {
2127         bytes = tvb_length_remaining(tvb, offset);
2128         if (bytes < 1) break;
2129
2130         info_type = tvb_get_guint8(tvb, offset);
2131
2132         if (info_type == OAMPDU_INFO_TYPE_ENDMARKER) break;
2133
2134         info_item = proto_tree_add_uint(tree, hf_oampdu_info_type, tvb,
2135                                         offset, 1, info_type);
2136
2137         switch (info_type)
2138         {
2139             case OAMPDU_INFO_TYPE_LOCAL:
2140                 info_tree = proto_item_add_subtree(info_item, ett_oampdu_local_info);
2141                 break;
2142             case OAMPDU_INFO_TYPE_REMOTE:
2143                 info_tree = proto_item_add_subtree(info_item, ett_oampdu_remote_info);
2144                 break;
2145             case OAMPDU_INFO_TYPE_ORG:
2146                 info_tree = proto_item_add_subtree(info_item, ett_oampdu_org_info);
2147                 break;
2148             default:
2149                 info_tree = NULL;
2150                 break;
2151         }
2152
2153         offset += OAMPDU_INFO_TYPE_SZ;
2154
2155         if ((info_type==OAMPDU_INFO_TYPE_LOCAL)||(info_type==OAMPDU_INFO_TYPE_REMOTE))
2156         {
2157             raw_octet = tvb_get_guint8(tvb, offset);
2158             proto_tree_add_uint(info_tree, hf_oampdu_info_len,
2159                                 tvb, offset, 1, raw_octet);
2160
2161             offset += OAMPDU_INFO_LENGTH_SZ;
2162
2163             raw_octet = tvb_get_guint8(tvb, offset);
2164             proto_tree_add_uint(info_tree, hf_oampdu_info_version,
2165                                 tvb, offset, 1, raw_octet);
2166
2167             offset += OAMPDU_INFO_VERSION_SZ;
2168
2169             raw_word = tvb_get_ntohs(tvb, offset);
2170             proto_tree_add_uint(info_tree, hf_oampdu_info_revision,
2171                                 tvb, offset, 2, raw_word);
2172
2173             offset += OAMPDU_INFO_REVISION_SZ;
2174
2175             /* Build OAM State field field */
2176             raw_octet = tvb_get_guint8(tvb, offset);
2177             state_item = proto_tree_add_uint(info_tree, hf_oampdu_info_state,
2178                                              tvb, offset, 1, raw_octet);
2179
2180             if (raw_octet == OAMPDU_INFO_TYPE_LOCAL)
2181                 state_tree = proto_item_add_subtree(state_item, ett_oampdu_local_info_state);
2182             else
2183                 state_tree = proto_item_add_subtree(state_item, ett_oampdu_remote_info_state);
2184
2185             proto_tree_add_uint(state_tree, hf_oampdu_info_state_parser,
2186                                 tvb, offset, 1, raw_octet);
2187
2188             proto_tree_add_boolean(state_tree, hf_oampdu_info_state_mux,
2189                                    tvb, offset, 1, raw_octet);
2190
2191             offset += OAMPDU_INFO_STATE_SZ;
2192
2193             /* Build OAM configuration field */
2194             raw_octet = tvb_get_guint8(tvb, offset);
2195             cfg_item = proto_tree_add_uint(info_tree, hf_oampdu_info_oamConfig,
2196                                            tvb, offset, 1, raw_octet);
2197
2198             if (raw_octet == OAMPDU_INFO_TYPE_LOCAL)
2199                 cfg_tree = proto_item_add_subtree(cfg_item, ett_oampdu_local_info_config);
2200             else
2201                 cfg_tree = proto_item_add_subtree(cfg_item, ett_oampdu_remote_info_config);
2202
2203             proto_tree_add_boolean(cfg_tree, hf_oampdu_info_oamConfig_mode,
2204                                    tvb, offset, 1, raw_octet);
2205
2206             proto_tree_add_boolean(cfg_tree, hf_oampdu_info_oamConfig_uni,
2207                                    tvb, offset, 1, raw_octet);
2208
2209             proto_tree_add_boolean(cfg_tree, hf_oampdu_info_oamConfig_lpbk,
2210                                    tvb, offset, 1, raw_octet);
2211
2212             proto_tree_add_boolean(cfg_tree, hf_oampdu_info_oamConfig_event,
2213                                    tvb, offset, 1, raw_octet);
2214
2215             proto_tree_add_boolean(cfg_tree, hf_oampdu_info_oamConfig_var,
2216                                    tvb, offset, 1, raw_octet);
2217
2218             offset += OAMPDU_INFO_OAM_CONFIG_SZ;
2219
2220             raw_word = tvb_get_ntohs(tvb, offset);
2221             item = proto_tree_add_uint(info_tree, hf_oampdu_info_oampduConfig,
2222                                        tvb, offset, 2, raw_word);
2223
2224             proto_item_append_text(item, " (bytes)");
2225
2226             offset += OAMPDU_INFO_OAMPDU_CONFIG_SZ;
2227
2228             oui_item = proto_tree_add_item(info_tree, hf_oampdu_info_oui,
2229                                            tvb, offset, 3, ENC_NA);
2230
2231             APPEND_OUI_NAME(oui_item, ptr, tvb, offset);
2232
2233             offset += OAMPDU_INFO_OUI_SZ;
2234
2235             proto_tree_add_item(info_tree, hf_oampdu_info_vendor,
2236                                 tvb, offset, 4, ENC_NA);
2237
2238             offset += OAMPDU_INFO_VENDOR_SPECIFIC_SZ;
2239         }
2240         else if (info_type == OAMPDU_INFO_TYPE_ORG)
2241         {
2242             /* see IEEE802.3, section 57.5.2.3 for more details */
2243             raw_octet = tvb_get_guint8(tvb, offset);
2244             proto_tree_add_uint(info_tree, hf_oampdu_info_len,
2245                                 tvb, offset, 1, raw_octet);
2246
2247             offset += OAMPDU_INFO_LENGTH_SZ;
2248
2249             oui_item = proto_tree_add_item(info_tree, hf_oampdu_info_oui,
2250                                             tvb, offset, 3, ENC_NA);
2251
2252             APPEND_OUI_NAME(oui_item, ptr, tvb, offset);
2253
2254             offset += OAMPDU_INFO_OUI_SZ;
2255
2256             proto_tree_add_item(info_tree, hf_oampdu_info_vendor,
2257                                 tvb, offset, raw_octet-5, ENC_NA);
2258
2259             offset += raw_octet-2;
2260
2261         }
2262         else if (info_type==OAMPDU_INFO_TYPE_ENDMARKER)
2263         {
2264             /* A TLV of zero indicate an End of TLV marker */
2265             break;
2266         }
2267         else
2268         {
2269             /* If it's a unknown type jump over */
2270             raw_octet = tvb_get_guint8(tvb, offset);
2271             offset += raw_octet;
2272         }
2273     }
2274 }
2275
2276 /*
2277  * Name: dissect_oampdu_event_notification
2278  *
2279  * Description:
2280  *    This function is used to dissect the Event Notification TLVs define in
2281  *    IEEE802.3 section 57.5.3).
2282  *
2283  *
2284  * Input Arguments:
2285  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2286  *    tree: the protocol tree associate with the oampdu (see proto.h).
2287  *
2288  * Return Values: None
2289  *
2290  * Notes:
2291  *    Dominique Bastien (dbastien@accedian.com)
2292  *      + add support for 802.3ah-2004.
2293  */
2294 static void
2295 dissect_oampdu_event_notification(tvbuff_t *tvb, proto_tree *tree)
2296 {
2297     guint8    raw_octet;
2298     guint16   raw_word;
2299     guint32   dword;
2300     guint64   big;
2301
2302     guint8    event_type;
2303     guint32   offset;
2304     guint16   bytes;
2305
2306     proto_tree *event_tree;
2307     proto_item *event_item;
2308
2309     offset = OAMPDU_HEADER_SIZE;
2310
2311     /* Display the sequence number before displaying the TLVs */
2312     raw_word = tvb_get_ntohs(tvb, offset);
2313     proto_tree_add_uint(tree, hf_oampdu_event_sequence,
2314             tvb, offset, 2, raw_word);
2315
2316     offset += OAMPDU_EVENT_SEQUENCE_SZ;
2317
2318     while (1)
2319     {
2320         bytes = tvb_length_remaining(tvb, offset);
2321         if (bytes < 1) break;
2322
2323         event_type = tvb_get_guint8(tvb, offset);
2324
2325         if (event_type == 0) break;
2326
2327         event_item = proto_tree_add_uint(tree, hf_oampdu_event_type,
2328                             tvb, offset, 1, event_type);
2329
2330         offset += OAMPDU_EVENT_TYPE_SZ;
2331
2332         switch (event_type)
2333         {
2334             case OAMPDU_EVENT_TYPE_END:
2335                 break;
2336             case OAMPDU_EVENT_TYPE_ESPE:
2337             {
2338                 event_tree = proto_item_add_subtree(event_item,
2339                                     ett_oampdu_event_espe);
2340
2341                 raw_octet = tvb_get_guint8(tvb, offset);
2342                 proto_tree_add_uint(event_tree, hf_oampdu_event_length,
2343                         tvb, offset, 1, raw_octet);
2344
2345                 offset += OAMPDU_EVENT_LENGTH_SZ;
2346
2347                 raw_word = tvb_get_ntohs(tvb, offset);
2348                 proto_tree_add_uint(event_tree, hf_oampdu_event_timeStamp,
2349                         tvb, offset, 2, raw_word);
2350
2351                 offset += OAMPDU_EVENT_TIMESTAMP_SZ;
2352
2353                 big = tvb_get_ntoh64(tvb, offset);
2354                 proto_tree_add_uint64(event_tree, hf_oampdu_event_espeWindow,
2355                         tvb, offset, 8, big);
2356
2357                 offset += OAMPDU_ESPE_WINDOW_SZ;
2358
2359                 big = tvb_get_ntoh64(tvb, offset);
2360                 proto_tree_add_uint64(event_tree, hf_oampdu_event_espeThreshold,
2361                         tvb, offset, 8, big);
2362
2363                 offset += OAMPDU_ESPE_THRESHOLD_SZ;
2364
2365                 big = tvb_get_ntoh64(tvb, offset);
2366                 proto_tree_add_uint64(event_tree, hf_oampdu_event_espeErrors,
2367                         tvb, offset, 8, big);
2368
2369                 offset += OAMPDU_ESPE_ERRORS_SZ;
2370
2371                 big = tvb_get_ntoh64(tvb, offset);
2372                 proto_tree_add_uint64(event_tree, hf_oampdu_event_espeTotalErrors,
2373                         tvb, offset, 8, big);
2374
2375                 offset += OAMPDU_ESPE_ERR_TOTAL_SZ;
2376
2377                 dword = tvb_get_ntohl(tvb, offset);
2378                 proto_tree_add_uint(event_tree, hf_oampdu_event_espeTotalEvents,
2379                         tvb, offset, 4, dword);
2380
2381                 offset += OAMPDU_ESPE_TOTAL_SZ;
2382                 break;
2383             }
2384             case OAMPDU_EVENT_TYPE_EFE:
2385             {
2386                 event_tree = proto_item_add_subtree(event_item,
2387                                     ett_oampdu_event_efe);
2388
2389                 raw_octet = tvb_get_guint8(tvb, offset);
2390                 proto_tree_add_uint(event_tree, hf_oampdu_event_length,
2391                         tvb, offset, 1, raw_octet);
2392
2393                 offset += OAMPDU_EVENT_LENGTH_SZ;
2394
2395                 raw_word = tvb_get_ntohs(tvb, offset);
2396                 proto_tree_add_uint(event_tree, hf_oampdu_event_timeStamp,
2397                         tvb, offset, 2, raw_word);
2398
2399                 offset += OAMPDU_EVENT_TIMESTAMP_SZ;
2400
2401                 raw_word = tvb_get_ntohs(tvb, offset);
2402                 proto_tree_add_uint(event_tree, hf_oampdu_event_efeWindow,
2403                         tvb, offset, 2, raw_word);
2404
2405                 offset += OAMPDU_EFE_WINDOW_SZ;
2406
2407                 dword = tvb_get_ntohl(tvb, offset);
2408                 proto_tree_add_uint(event_tree, hf_oampdu_event_efeThreshold,
2409                         tvb, offset, 4, dword);
2410
2411                 offset += OAMPDU_EFE_THRESHOLD_SZ;
2412
2413                 dword = tvb_get_ntohl(tvb, offset);
2414                 proto_tree_add_uint(event_tree, hf_oampdu_event_efeErrors,
2415                         tvb, offset, 4, dword);
2416
2417                 offset += OAMPDU_EFE_ERRORS_SZ;
2418
2419                 big = tvb_get_ntoh64(tvb, offset);
2420                 proto_tree_add_uint64(event_tree, hf_oampdu_event_efeTotalErrors,
2421                         tvb, offset, 8, big);
2422
2423                 offset += OAMPDU_EFE_ERR_TOTAL_SZ;
2424
2425                 dword = tvb_get_ntohl(tvb, offset);
2426                 proto_tree_add_uint(event_tree, hf_oampdu_event_efeTotalEvents,
2427                         tvb, offset, 4, dword);
2428
2429                 offset += OAMPDU_EFE_TOTAL_SZ;
2430
2431                 break;
2432             }
2433             case OAMPDU_EVENT_TYPE_EFPE:
2434             {
2435                 event_tree = proto_item_add_subtree(event_item,
2436                                     ett_oampdu_event_efpe);
2437
2438                 raw_octet = tvb_get_guint8(tvb, offset);
2439                 proto_tree_add_uint(event_tree, hf_oampdu_event_length,
2440                         tvb, offset, 1, raw_octet);
2441
2442                 offset += OAMPDU_EVENT_LENGTH_SZ;
2443
2444                 raw_word = tvb_get_ntohs(tvb, offset);
2445                 proto_tree_add_uint(event_tree, hf_oampdu_event_timeStamp,
2446                         tvb, offset, 2, raw_word);
2447
2448                 offset += OAMPDU_EVENT_TIMESTAMP_SZ;
2449
2450                 raw_word = tvb_get_ntohl(tvb, offset);
2451                 proto_tree_add_uint(event_tree, hf_oampdu_event_efpeWindow,
2452                         tvb, offset, 4, raw_word);
2453
2454                 offset += OAMPDU_EFPE_WINDOW_SZ;
2455
2456                 dword = tvb_get_ntohl(tvb, offset);
2457                 proto_tree_add_uint(event_tree, hf_oampdu_event_efpeThreshold,
2458                         tvb, offset, 4, dword);
2459
2460                 offset += OAMPDU_EFPE_THRESHOLD_SZ;
2461
2462                 dword = tvb_get_ntohl(tvb, offset);
2463                 proto_tree_add_uint(event_tree, hf_oampdu_event_efpeErrors,
2464                         tvb, offset, 4, dword);
2465
2466                 offset += OAMPDU_EFPE_ERRORS_SZ;
2467
2468                 big = tvb_get_ntoh64(tvb, offset);
2469                 proto_tree_add_uint64(event_tree, hf_oampdu_event_efpeTotalErrors,
2470                         tvb, offset, 8, big);
2471
2472                 offset += OAMPDU_EFPE_ERR_TOTAL_SZ;
2473
2474                 dword = tvb_get_ntohl(tvb, offset);
2475                 proto_tree_add_uint(event_tree, hf_oampdu_event_efpeTotalEvents,
2476                         tvb, offset, 4, dword);
2477
2478                 offset += OAMPDU_EFPE_TOTAL_SZ;
2479
2480                 break;
2481             }
2482             case OAMPDU_EVENT_TYPE_EFSSE:
2483             {
2484                 event_tree = proto_item_add_subtree(event_item,
2485                                     ett_oampdu_event_efsse);
2486
2487                 raw_octet = tvb_get_guint8(tvb, offset);
2488                 proto_tree_add_uint(event_tree, hf_oampdu_event_length,
2489                         tvb, offset, 1, raw_octet);
2490
2491                 offset += OAMPDU_EVENT_LENGTH_SZ;
2492
2493                 raw_word = tvb_get_ntohs(tvb, offset);
2494                 proto_tree_add_uint(event_tree, hf_oampdu_event_timeStamp,
2495                         tvb, offset, 2, raw_word);
2496
2497                 offset += OAMPDU_EVENT_TIMESTAMP_SZ;
2498
2499                 raw_word = tvb_get_ntohs(tvb, offset);
2500                 proto_tree_add_uint(event_tree, hf_oampdu_event_efsseWindow,
2501                         tvb, offset, 2, raw_word);
2502
2503                 offset += OAMPDU_EFSSE_WINDOW_SZ;
2504
2505                 dword = tvb_get_ntohs(tvb, offset);
2506                 proto_tree_add_uint(event_tree, hf_oampdu_event_efsseThreshold,
2507                         tvb, offset, 2, dword);
2508
2509                 offset += OAMPDU_EFSSE_THRESHOLD_SZ;
2510
2511                 dword = tvb_get_ntohs(tvb, offset);
2512                 proto_tree_add_uint(event_tree, hf_oampdu_event_efsseErrors,
2513                         tvb, offset, 2, dword);
2514
2515                 offset += OAMPDU_EFSSE_ERRORS_SZ;
2516
2517                 dword = tvb_get_ntohl(tvb, offset);
2518                 proto_tree_add_uint(event_tree, hf_oampdu_event_efsseTotalErrors,
2519                         tvb, offset, 4, dword);
2520
2521                 offset += OAMPDU_EFSSE_ERR_TOTAL_SZ;
2522
2523                 dword = tvb_get_ntohl(tvb, offset);
2524                 proto_tree_add_uint(event_tree, hf_oampdu_event_efsseTotalEvents,
2525                         tvb, offset, 4, dword);
2526
2527                 offset += OAMPDU_EFSSE_TOTAL_SZ;
2528
2529                 break;
2530             }
2531             case OAMPDU_EVENT_TYPE_OSE:
2532             {
2533                 event_tree = proto_item_add_subtree(event_item,
2534                                     ett_oampdu_event_ose);
2535
2536                 raw_octet = tvb_get_guint8(tvb, offset);
2537                 proto_tree_add_uint(event_tree, hf_oampdu_event_length,
2538                         tvb, offset, 1, raw_octet);
2539
2540                 offset += OAMPDU_EVENT_LENGTH_SZ;
2541
2542                 offset += (raw_word-2);
2543                 break;
2544             }
2545             default:
2546               break;
2547         }
2548     }
2549 }
2550
2551 /*
2552  * Name: dissect_oampdu_variable_request
2553  *
2554  * Description:
2555  *    This function is used to dissect the Variable Request TLVs define in
2556  *    IEEE802.3 section 57.6).
2557  *
2558  *
2559  * Input Arguments:
2560  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2561  *    tree: the protocol tree associate with the oampdu (see proto.h).
2562  *
2563  * Return Values: None
2564  *
2565  * Notes:
2566  *    Dominique Bastien (dbastien@accedian.com)
2567  *      + add support for 802.3ah-2004.
2568  */
2569 static void
2570 dissect_oampdu_variable_request(tvbuff_t *tvb, proto_tree *tree)
2571 {
2572     guint16   raw_word;
2573     guint8    raw_octet;
2574     guint32   offset;
2575
2576
2577     offset = OAMPDU_HEADER_SIZE;
2578
2579     while (1)
2580     {
2581         raw_octet = tvb_get_guint8(tvb, offset);
2582
2583         if (raw_octet == 0) break;
2584
2585         proto_tree_add_uint(tree, hf_oampdu_variable_branch,
2586                 tvb,offset, 1, raw_octet);
2587
2588         offset+=1;
2589
2590         switch (raw_octet)
2591         {
2592             case OAMPDU_VARS_OBJECT:
2593             {
2594                 raw_word = tvb_get_ntohs(tvb, offset);
2595                 proto_tree_add_uint(tree, hf_oampdu_variable_object,
2596                         tvb, offset, 2, raw_word);
2597                 break;
2598             }
2599             case OAMPDU_VARS_PACKAGE:
2600             {
2601                 raw_word = tvb_get_ntohs(tvb, offset);
2602                 proto_tree_add_uint(tree, hf_oampdu_variable_package,
2603                         tvb, offset, 2, raw_word);
2604                 break;
2605             }
2606             case OAMPDU_VARS_BINDING:
2607             {
2608                 raw_word = tvb_get_ntohs(tvb, offset);
2609                 proto_tree_add_uint(tree, hf_oampdu_variable_binding,
2610                         tvb, offset, 2, raw_word);
2611                 break;
2612             }
2613             case OAMPDU_VARS_ATTRIBUTE:
2614             {
2615                 raw_word = tvb_get_ntohs(tvb, offset);
2616                 proto_tree_add_uint(tree, hf_oampdu_variable_attribute,
2617                         tvb, offset, 2, raw_word);
2618                 break;
2619             }
2620             default:
2621                 break;
2622         }
2623
2624         offset+=2;
2625     }
2626 }
2627
2628 /*
2629  * Name: dissect_oampdu_variable_response
2630  *
2631  * Description:
2632  *    This function is used to dissect the Variable Response TLVs define in
2633  *    IEEE802.3 section 57.6).
2634  *
2635  *
2636  * Input Arguments:
2637  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2638  *    tree: the protocol tree associate with the oampdu (see proto.h).
2639  *
2640  * Return Values: None
2641  *
2642  * Notes:
2643  *    Dominique Bastien (dbastien@accedian.com)
2644  *      + add support for 802.3ah-2004.
2645  */
2646 static void
2647 dissect_oampdu_variable_response(tvbuff_t *tvb, proto_tree *tree)
2648 {
2649     guint16   raw_word;
2650     guint8    raw_octet;
2651     guint32   offset;
2652
2653
2654     offset = OAMPDU_HEADER_SIZE;
2655
2656     while (1)
2657     {
2658         raw_octet = tvb_get_guint8(tvb, offset);
2659
2660         if (raw_octet == 0) break;
2661
2662         proto_tree_add_uint(tree, hf_oampdu_variable_branch,
2663                             tvb,offset, 1, raw_octet);
2664
2665         offset+=1;
2666
2667         switch (raw_octet)
2668         {
2669             case OAMPDU_VARS_OBJECT:
2670             {
2671                 raw_word = tvb_get_ntohs(tvb, offset);
2672                 proto_tree_add_uint(tree, hf_oampdu_variable_object,
2673                                     tvb, offset, 2, raw_word);
2674                 break;
2675             }
2676             case OAMPDU_VARS_PACKAGE:
2677             {
2678                 raw_word = tvb_get_ntohs(tvb, offset);
2679                 proto_tree_add_uint(tree, hf_oampdu_variable_package,
2680                                     tvb, offset, 2, raw_word);
2681                 break;
2682             }
2683             case OAMPDU_VARS_BINDING:
2684             {
2685                 raw_word = tvb_get_ntohs(tvb, offset);
2686                 proto_tree_add_uint(tree, hf_oampdu_variable_binding,
2687                                     tvb, offset, 2, raw_word);
2688                 break;
2689             }
2690             case OAMPDU_VARS_ATTRIBUTE:
2691             {
2692                 raw_word = tvb_get_ntohs(tvb, offset);
2693                 proto_tree_add_uint(tree, hf_oampdu_variable_attribute,
2694                                     tvb, offset, 2, raw_word);
2695                 break;
2696             }
2697             default:
2698                 break;
2699         }
2700
2701         offset+=2;
2702
2703         raw_octet = tvb_get_guint8(tvb, offset);
2704
2705         if (raw_octet >= 0x80)
2706         {
2707             /* Variable Indication */
2708             proto_tree_add_uint(tree, hf_oampdu_variable_indication,
2709                                 tvb,offset, 1, (raw_octet&0x7F));
2710
2711             offset+=1;
2712         }
2713         else
2714         {
2715             /* Special case for 128 bytes container */
2716             if (raw_octet == 0) raw_octet = 128;
2717
2718             proto_tree_add_uint(tree, hf_oampdu_variable_width,
2719                                 tvb,offset, 1, raw_octet);
2720
2721             offset+=1;
2722
2723             proto_tree_add_item(tree, hf_oampdu_variable_value,
2724                                  tvb, offset, raw_octet, ENC_NA);
2725
2726             offset+=raw_octet;
2727         }
2728     }
2729 }
2730
2731 /*
2732  * Name: dissect_oampdu_loopback_control
2733  *
2734  * Description:
2735  *    This function is used to dissect the Variable Request TLVs define in
2736  *    IEEE802.3 section 57.6).
2737  *
2738  *
2739  * Input Arguments:
2740  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2741  *    tree: the protocol tree associate with the oampdu (see proto.h).
2742  *
2743  * Return Values: None
2744  *
2745  * Notes:
2746  *    Dominique Bastien (dbastien@accedian.com)
2747  *      + add support for 802.3ah-2004.
2748  */
2749 static void
2750 dissect_oampdu_loopback_control(tvbuff_t *tvb, proto_tree *tree)
2751 {
2752     guint8    ctrl;
2753     guint32   offset;
2754     guint16   bytes;
2755
2756     proto_tree *ctrl_tree;
2757     proto_item *ctrl_item;
2758
2759     const char *sep;
2760
2761     offset = OAMPDU_HEADER_SIZE;
2762
2763     bytes = tvb_length_remaining(tvb, offset);
2764
2765     if (bytes >= 1)
2766     {
2767         ctrl = tvb_get_guint8(tvb, offset);
2768
2769         ctrl_item = proto_tree_add_uint(tree, hf_oampdu_lpbk,
2770                             tvb, offset, 1, ctrl);
2771
2772         ctrl_tree = proto_item_add_subtree(ctrl_item, ett_oampdu_lpbk_ctrl);
2773
2774         sep = initial_sep;
2775
2776         APPEND_BOOLEAN_FLAG(ctrl & OAMPDU_LPBK_ENABLE, ctrl_item,
2777                 "%sEnable Remote Loopack");
2778         proto_tree_add_boolean(ctrl_tree, hf_oampdu_lpbk_enable,
2779                 tvb, offset, 1, ctrl);
2780
2781         APPEND_BOOLEAN_FLAG(ctrl & OAMPDU_LPBK_DISABLE, ctrl_item,
2782                 "%sDisable Remote Loopback");
2783         proto_tree_add_boolean(ctrl_tree, hf_oampdu_lpbk_disable,
2784                 tvb, offset, 1, ctrl);
2785
2786         if (sep != initial_sep)
2787             proto_item_append_text(ctrl_item, ")");
2788     }
2789 }
2790
2791 /*
2792  * Name: dissect_oampdu_vendor_specific
2793  *
2794  * Description:
2795  *    This function is used to dissect the Vendor Specific TLV define in
2796  *    IEEE802.3 section 57.4.3.6).
2797  *
2798  *
2799  * Input Arguments:
2800  *    tvb: buffer associate with the rcv packet (see tvbuff.h).
2801  *    tree: the protocol tree associate with the oampdu (see proto.h).
2802  *
2803  * Return Values: None
2804  *
2805  * Notes:
2806  *    Dominique Bastien (dbastien@accedian.com)
2807  *      + add support for 802.3ah-2004.
2808  */
2809 static void
2810 dissect_oampdu_vendor_specific(tvbuff_t *tvb, proto_tree *tree)
2811 {
2812     guint32   offset;
2813     guint16   bytes;
2814
2815     const guint8 *ptr;
2816
2817     proto_item *oui_item;
2818
2819
2820     offset = OAMPDU_HEADER_SIZE;
2821
2822     bytes = tvb_length_remaining(tvb, offset);
2823
2824     if (bytes >= 3)
2825     {
2826         oui_item = proto_tree_add_item(tree, hf_oampdu_info_oui,
2827                                         tvb, offset, 3, ENC_NA);
2828
2829         APPEND_OUI_NAME(oui_item, ptr, tvb, offset);
2830     }
2831 }
2832
2833
2834 /* Register the protocol with Wireshark */
2835 void
2836 proto_register_slow_protocols(void)
2837 {
2838 /* Setup list of header fields */
2839
2840     static hf_register_info hf[] = {
2841
2842 /*
2843  * Generic slow protocol portion
2844  */
2845         { &hf_slow_subtype,
2846           { "Slow Protocols subtype",    "slow.subtype",
2847             FT_UINT8,    BASE_HEX,    VALS(subtype_vals),    0x0,
2848             "Identifies the LACP version", HFILL }},
2849
2850 /*
2851  *  LACP portion
2852  */
2853         { &hf_lacpdu_version_number,
2854           { "LACP Version Number",    "slow.lacp.version",
2855             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2856             "Identifies the LACP version", HFILL }},
2857
2858         { &hf_lacpdu_actor_type,
2859           { "Actor Information",    "slow.lacp.actorInfo",
2860             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2861             "TLV type = Actor", HFILL }},
2862
2863         { &hf_lacpdu_actor_info_len,
2864           { "Actor Information Length",            "slow.lacp.actorInfoLen",
2865             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2866             "The length of the Actor TLV", HFILL }},
2867
2868         { &hf_lacpdu_actor_sys_priority,
2869           { "Actor System Priority",  "slow.lacp.actorSysPriority",
2870             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2871             "The priority assigned to this System by management or admin", HFILL }},
2872
2873         { &hf_lacpdu_actor_sys,
2874           { "Actor System",            "slow.lacp.actorSystem",
2875             FT_ETHER,    BASE_NONE,    NULL,    0x0,
2876             "The Actor's System ID encoded as a MAC address", HFILL }},
2877
2878         { &hf_lacpdu_actor_key,
2879           { "Actor Key",            "slow.lacp.actorKey",
2880             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2881             "The operational Key value assigned to the port by the Actor", HFILL }},
2882
2883         { &hf_lacpdu_actor_port_priority,
2884           { "Actor Port Priority",            "slow.lacp.actorPortPriority",
2885             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2886             "The priority assigned to the port by the Actor (via Management or Admin)", HFILL }},
2887
2888         { &hf_lacpdu_actor_port,
2889           { "Actor Port",            "slow.lacp.actorPort",
2890             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2891             "The port number assigned to the port by the Actor (via Management or Admin)", HFILL }},
2892
2893         { &hf_lacpdu_actor_state,
2894           { "Actor State",            "slow.lacp.actorState",
2895             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2896             "The Actor's state variables for the port, encoded as bits within a single octet", HFILL }},
2897
2898         { &hf_lacpdu_flags_a_activity,
2899           { "LACP Activity",        "slow.lacp.actorState.activity",
2900             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_ACTIVITY,
2901             "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
2902
2903         { &hf_lacpdu_flags_a_timeout,
2904           { "LACP Timeout",        "slow.lacp.actorState.timeout",
2905             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_TIMEOUT,
2906             "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
2907
2908         { &hf_lacpdu_flags_a_aggregation,
2909           { "Aggregation",        "slow.lacp.actorState.aggregation",
2910             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_AGGREGATION,
2911             "Aggregatable = 1, Individual = 0", HFILL }},
2912
2913         { &hf_lacpdu_flags_a_sync,
2914           { "Synchronization",        "slow.lacp.actorState.synchronization",
2915             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_SYNC,
2916             "In Sync = 1, Out of Sync = 0", HFILL }},
2917
2918         { &hf_lacpdu_flags_a_collecting,
2919           { "Collecting",        "slow.lacp.actorState.collecting",
2920             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_COLLECTING,
2921             "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
2922
2923         { &hf_lacpdu_flags_a_distrib,
2924           { "Distributing",        "slow.lacp.actorState.distributing",
2925             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DISTRIB,
2926             "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
2927
2928         { &hf_lacpdu_flags_a_defaulted,
2929           { "Defaulted",        "slow.lacp.actorState.defaulted",
2930             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DEFAULTED,
2931             "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
2932
2933         { &hf_lacpdu_flags_a_expired,
2934           { "Expired",        "slow.lacp.actorState.expired",
2935             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_EXPIRED,
2936             "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
2937
2938         { &hf_lacpdu_actor_reserved,
2939           { "Reserved",        "slow.lacp.reserved",
2940             FT_BYTES,    BASE_NONE,    NULL,    0x0,
2941             NULL, HFILL }},
2942
2943         { &hf_lacpdu_partner_type,
2944           { "Partner Information",    "slow.lacp.partnerInfo",
2945             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2946             "TLV type = Partner", HFILL }},
2947
2948         { &hf_lacpdu_partner_info_len,
2949           { "Partner Information Length",            "slow.lacp.partnerInfoLen",
2950             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2951             "The length of the Partner TLV", HFILL }},
2952
2953         { &hf_lacpdu_partner_sys_priority,
2954           { "Partner System Priority",  "slow.lacp.partnerSysPriority",
2955             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2956             "The priority assigned to the Partner System by management or admin", HFILL }},
2957
2958         { &hf_lacpdu_partner_sys,
2959           { "Partner System",            "slow.lacp.partnerSystem",
2960             FT_ETHER,    BASE_NONE,    NULL,    0x0,
2961             "The Partner's System ID encoded as a MAC address", HFILL }},
2962
2963         { &hf_lacpdu_partner_key,
2964           { "Partner Key",            "slow.lacp.partnerKey",
2965             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2966             "The operational Key value assigned to the port associated with this link by the Partner", HFILL }},
2967
2968         { &hf_lacpdu_partner_port_priority,
2969           { "Partner Port Priority",            "slow.lacp.partnerPortPriority",
2970             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2971             "The priority assigned to the port by the Partner (via Management or Admin)", HFILL }},
2972
2973         { &hf_lacpdu_partner_port,
2974           { "Partner Port",            "slow.lacp.partnerPort",
2975             FT_UINT16,    BASE_DEC,    NULL,    0x0,
2976             "The port number associated with this link assigned to the port by the Partner (via Management or Admin)", HFILL }},
2977
2978         { &hf_lacpdu_partner_state,
2979           { "Partner State",            "slow.lacp.partnerState",
2980             FT_UINT8,    BASE_HEX,    NULL,    0x0,
2981             "The Partner's state variables for the port, encoded as bits within a single octet", HFILL }},
2982
2983         { &hf_lacpdu_flags_p_activity,
2984           { "LACP Activity",        "slow.lacp.partnerState.activity",
2985             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_ACTIVITY,
2986             "Activity control value for this link. Active = 1, Passive = 0", HFILL }},
2987
2988         { &hf_lacpdu_flags_p_timeout,
2989           { "LACP Timeout",        "slow.lacp.partnerState.timeout",
2990             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_TIMEOUT,
2991             "Timeout control value for this link. Short Timeout = 1, Long Timeout = 0", HFILL }},
2992
2993         { &hf_lacpdu_flags_p_aggregation,
2994           { "Aggregation",        "slow.lacp.partnerState.aggregation",
2995             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_AGGREGATION,
2996             "Aggregatable = 1, Individual = 0", HFILL }},
2997
2998         { &hf_lacpdu_flags_p_sync,
2999           { "Synchronization",        "slow.lacp.partnerState.synchronization",
3000             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_SYNC,
3001             "In Sync = 1, Out of Sync = 0", HFILL }},
3002
3003         { &hf_lacpdu_flags_p_collecting,
3004           { "Collecting",        "slow.lacp.partnerState.collecting",
3005             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_COLLECTING,
3006             "Collection of incoming frames is: Enabled = 1, Disabled = 0", HFILL }},
3007
3008         { &hf_lacpdu_flags_p_distrib,
3009           { "Distributing",        "slow.lacp.partnerState.distributing",
3010             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DISTRIB,
3011             "Distribution of outgoing frames is: Enabled = 1, Disabled = 0", HFILL }},
3012
3013         { &hf_lacpdu_flags_p_defaulted,
3014           { "Defaulted",        "slow.lacp.partnerState.defaulted",
3015             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_DEFAULTED,
3016             "1 = Actor Rx machine is using DEFAULT Partner info, 0 = using info in Rx'd LACPDU", HFILL }},
3017
3018         { &hf_lacpdu_flags_p_expired,
3019           { "Expired",        "slow.lacp.partnerState.expired",
3020             FT_BOOLEAN,    8,        TFS(&tfs_yes_no),    LACPDU_FLAGS_EXPIRED,
3021             "1 = Actor Rx machine is EXPIRED, 0 = is NOT EXPIRED", HFILL }},
3022
3023         { &hf_lacpdu_partner_reserved,
3024           { "Reserved",        "slow.lacp.reserved",
3025             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3026             NULL, HFILL }},
3027
3028         { &hf_lacpdu_coll_type,
3029           { "Collector Information",    "slow.lacp.collectorInfo",
3030             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3031             "TLV type = Collector", HFILL }},
3032
3033         { &hf_lacpdu_coll_info_len,
3034           { "Collector Information Length",            "slow.lacp.collectorInfoLen",
3035             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3036             "The length of the Collector TLV", HFILL }},
3037
3038         { &hf_lacpdu_coll_max_delay,
3039           { "Collector Max Delay",  "slow.lacp.collectorMaxDelay",
3040             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3041             "The max delay of the station tx'ing the LACPDU (in tens of usecs)", HFILL }},
3042
3043         { &hf_lacpdu_coll_reserved,
3044           { "Reserved",        "slow.lacp.coll_reserved",
3045             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3046             NULL, HFILL }},
3047
3048         { &hf_lacpdu_term_type,
3049           { "Terminator Information",    "slow.lacp.termInfo",
3050             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3051             "TLV type = Terminator", HFILL }},
3052
3053         { &hf_lacpdu_term_len,
3054           { "Terminator Length",            "slow.lacp.termLen",
3055             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3056             "The length of the Terminator TLV", HFILL }},
3057
3058         { &hf_lacpdu_term_reserved,
3059           { "Reserved",        "slow.lacp.term_reserved",
3060             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3061             NULL, HFILL }},
3062
3063
3064 /*
3065  *  MARKER portion
3066  */
3067
3068         { &hf_marker_version_number,
3069           { "Version Number",    "slow.marker.version",
3070             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3071             "Identifies the Marker version", HFILL }},
3072
3073         { &hf_marker_tlv_type,
3074           { "TLV Type",    "slow.marker.tlvType",
3075             FT_UINT8,    BASE_HEX,    VALS(marker_vals),    0x0,
3076             "Marker TLV type", HFILL }},
3077
3078         { &hf_marker_tlv_length,
3079           { "TLV Length",            "slow.marker.tlvLen",
3080             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3081             "The length of the Actor TLV", HFILL }},
3082
3083         { &hf_marker_req_port,
3084           { "Requester Port",  "slow.marker.requesterPort",
3085             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3086             "The Requester Port", HFILL }},
3087
3088         { &hf_marker_req_system,
3089           { "Requester System",  "slow.marker.requesterSystem",
3090             FT_ETHER,    BASE_NONE,    NULL,    0x0,
3091             "The Requester System ID encoded as a MAC address", HFILL }},
3092
3093         { &hf_marker_req_trans_id,
3094           { "Requester Transaction ID",  "slow.marker.requesterTransId",
3095             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3096             "The Requester Transaction ID", HFILL }},
3097
3098 /*
3099  *  ESMC portion
3100  */
3101
3102         { &hf_ossp_oui,
3103           { "OUI",    "slow.ossp.oui",
3104             FT_BYTES,     BASE_NONE,    NULL,    0,
3105             "IEEE assigned Organizationally Unique Identifier", HFILL }},
3106
3107         { &hf_itu_subtype,
3108           { "ITU-T OSSP Subtype",    "slow.ossp.itu.subtype",
3109             FT_UINT16,    BASE_HEX,    NULL,    0,
3110             "Subtype assigned by the ITU-T", HFILL }},
3111
3112         { &hf_esmc_version,
3113           { "Version",    "slow.esmc.version",
3114             FT_UINT8,     BASE_HEX,    NULL,    0xf0,
3115             "This field indicates the version of ITU-T SG15 Q13 OSSP frame format", HFILL }},
3116
3117         { &hf_esmc_event_flag,
3118           { "Event Flag",    "slow.esmc.event_flag",
3119             FT_UINT8,    BASE_HEX,    VALS(esmc_event_flag_vals),    0x08,
3120             "This bit distinguishes the critical, time sensitive behaviour of the"
3121             " ESMC Event PDU from the ESMC Information PDU", HFILL }},
3122
3123         { &hf_esmc_timestamp_valid_flag,
3124           { "Timestamp Valid Flag",    "slow.esmc.timestamp_valid_flag",
3125             FT_UINT8,    BASE_HEX,    VALS(esmc_timestamp_valid_flag_vals),    0x04,
3126             "Indicates validity (i.e. presence) of the Timestamp TLV", HFILL }},
3127
3128         { &hf_esmc_reserved_32,
3129           { "Reserved",    "slow.esmc.reserved",
3130             FT_UINT32,    BASE_HEX,    NULL,    0,
3131             "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }},
3132
3133         { &hf_esmc_tlv,
3134           { "ESMC TLV",    "slow.esmc.tlv",
3135             FT_NONE,     BASE_NONE,    NULL,    0,
3136             NULL, HFILL }},
3137
3138         { &hf_esmc_tlv_type,
3139           { "TLV Type",    "slow.esmc.tlv_type",
3140             FT_UINT8,    BASE_HEX,    VALS(esmc_tlv_type_vals),    0,
3141             NULL, HFILL }},
3142
3143         { &hf_esmc_tlv_length,
3144           { "TLV Length",    "slow.esmc.tlv_length",
3145             FT_UINT16,    BASE_HEX,    NULL,    0,
3146             NULL, HFILL }},
3147
3148         { &hf_esmc_tlv_ql_unused,
3149           { "Unused",    "slow.esmc.tlv_ql_unused",
3150             FT_UINT8,     BASE_HEX,    NULL,    0xf0,
3151             "This field is not used in QL TLV", HFILL }},
3152
3153         { &hf_esmc_quality_level_opt_1,
3154           { "SSM Code",    "slow.esmc.ql",
3155             FT_UINT8,    BASE_HEX,    VALS(esmc_quality_level_opt_1_vals),    0x0f,
3156             "Quality Level information", HFILL }},
3157
3158 #if 0 /*not used yet*/
3159         { &hf_esmc_quality_level_opt_2,
3160           { "SSM Code",    "slow.esmc.ql",
3161             FT_UINT8,    BASE_HEX,    VALS(esmc_quality_level_opt_2_vals),    0x0f,
3162             "Quality Level information", HFILL }},
3163 #endif
3164
3165         { &hf_esmc_quality_level_invalid,
3166           { "SSM Code",    "slow.esmc.ql",
3167             FT_UINT8,    BASE_HEX,    VALS(esmc_quality_level_invalid_vals),    0x0f,
3168             "Quality Level information", HFILL }},
3169
3170         { &hf_esmc_timestamp,
3171           { "Timestamp (ns)",    "slow.esmc.timestamp",
3172             FT_INT32,    BASE_DEC,    NULL,    0,
3173             "Timestamp according to the \"whole nanoseconds\" part of the IEEE 1588 originTimestamp", HFILL }},
3174
3175         { &hf_esmc_tlv_ts_reserved,
3176           { "Reserved",    "slow.esmc.tlv_ts_reserved",
3177             FT_UINT8,     BASE_HEX,    NULL,    0,
3178             "Reserved. Set to all zero at the transmitter and ignored by the receiver", HFILL }},
3179
3180         { &hf_esmc_padding,
3181           { "Padding",    "slow.esmc.padding",
3182             FT_BYTES,     BASE_NONE,    NULL,    0x0,
3183             "This field contains necessary padding to achieve the minimum frame size of 64 bytes at least", HFILL }},
3184
3185 /*
3186  *  OAMPDU portion
3187  */
3188         { &hf_oampdu_flags,
3189           { "Flags",    "slow.oam.flags",
3190             FT_UINT16,    BASE_HEX,    NULL,    0x0,
3191             "The Flags Field", HFILL }},
3192
3193         { &hf_oampdu_flags_link_fault,
3194           { "Link Fault",        "slow.oam.flags.linkFault",
3195             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_LINK_FAULT,
3196             "The PHY detected a fault in the receive direction. True = 1, False = 0", HFILL }},
3197
3198         { &hf_oampdu_flags_dying_gasp,
3199           { "Dying Gasp",        "slow.oam.flags.dyingGasp",
3200             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_DYING_GASP,
3201             "An unrecoverable local failure occured. True = 1, False = 0", HFILL }},
3202
3203         { &hf_oampdu_flags_critical_event,
3204           { "Critical Event",        "slow.oam.flags.criticalEvent",
3205             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_CRITICAL_EVENT,
3206             "A critical event has occurred. True = 1, False = 0", HFILL }},
3207
3208         { &hf_oampdu_flags_local_evaluating,
3209           { "Local Evaluating",        "slow.oam.flags.localEvaluating",
3210             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_LOCAL_EVAL,
3211             "Local DTE Discovery process in progress. True = 1, False = 0", HFILL }},
3212
3213         { &hf_oampdu_flags_local_stable,
3214           { "Local Stable",        "slow.oam.flags.localStable",
3215             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_LOCAL_STABLE,
3216             "Local DTE is Stable. True = 1, False = 0", HFILL }},
3217
3218         { &hf_oampdu_flags_remote_evaluating,
3219           { "Remote Evaluating",        "slow.oam.flags.remoteEvaluating",
3220             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_REMOTE_EVAL,
3221             "Remote DTE Discovery process in progress. True = 1, False = 0", HFILL }},
3222
3223         { &hf_oampdu_flags_remote_stable,
3224           { "Remote Stable",        "slow.oam.flags.remoteStable",
3225             FT_BOOLEAN,    8,        TFS(&tfs_true_false),    OAMPDU_FLAGS_REMOTE_STABLE,
3226             "Remote DTE is Stable. True = 1, False = 0", HFILL }},
3227
3228         { &hf_oampdu_code,
3229           { "OAMPDU code",    "slow.oam.code",
3230             FT_UINT8,    BASE_HEX,    VALS(code_vals),    0x0,
3231             "Identifies the TLVs code", HFILL }},
3232
3233         { &hf_oampdu_info_type,
3234           { "Type",    "slow.oam.info.type",
3235             FT_UINT8,    BASE_HEX,    VALS(info_type_vals),    0x0,
3236             "Identifies the TLV type", HFILL }},
3237
3238         { &hf_oampdu_info_len,
3239           { "TLV Length",    "slow.oam.info.length",
3240             FT_UINT8,    BASE_DEC,    NULL,    0x0,
3241             "Identifies the TLVs type", HFILL }},
3242
3243         { &hf_oampdu_info_version,
3244           { "TLV Version",    "slow.oam.info.version",
3245             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3246             "Identifies the TLVs version", HFILL }},
3247
3248         { &hf_oampdu_info_revision,
3249           { "TLV Revision",    "slow.oam.info.revision",
3250             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3251             "Identifies the TLVs revision", HFILL }},
3252
3253         { &hf_oampdu_info_state,
3254           { "OAM DTE States",    "slow.oam.info.state",
3255             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3256             "OAM DTE State of the Mux and the Parser", HFILL }},
3257
3258         { &hf_oampdu_info_state_parser,
3259           { "Parser Action",        "slow.oam.info.state.parser",
3260             FT_UINT8,    BASE_HEX,    VALS(parser_vals),    0x03,
3261             NULL, HFILL }},
3262
3263         { &hf_oampdu_info_state_mux,
3264           { "Muxiplexer Action",        "slow.oam.info.state.muxiplexer",
3265             FT_BOOLEAN,    8,        TFS(&mux),    0x04,
3266             NULL, HFILL }},
3267
3268         { &hf_oampdu_info_oamConfig,
3269           { "OAM Configuration",    "slow.oam.info.oamConfig",
3270             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3271             NULL, HFILL }},
3272
3273         { &hf_oampdu_info_oamConfig_mode,
3274           { "OAM Mode",        "slow.oam.info.oamConfig.mode",
3275             FT_BOOLEAN,    8,        TFS(&oam_mode),    OAMPDU_INFO_CONFIG_MODE,
3276             NULL, HFILL }},
3277
3278         { &hf_oampdu_info_oamConfig_uni,
3279           { "Unidirectional support",        "slow.oam.flags.dyingGasp",
3280             FT_BOOLEAN,    8,        TFS(&oam_uni),    OAMPDU_INFO_CONFIG_UNI,
3281             NULL, HFILL }},
3282
3283         { &hf_oampdu_info_oamConfig_lpbk,
3284           { "Loopback support",        "slow.oam.flags.criticalEvent",
3285             FT_BOOLEAN,    8,        TFS(&oam_lpbk),    OAMPDU_INFO_CONFIG_LPBK,
3286             NULL, HFILL }},
3287
3288         { &hf_oampdu_info_oamConfig_event,
3289           { "Link Events support",        "slow.oam.flags.localEvaluating",
3290             FT_BOOLEAN,    8,        TFS(&oam_event),    OAMPDU_INFO_CONFIG_EVENT,
3291             NULL, HFILL }},
3292
3293         { &hf_oampdu_info_oamConfig_var,
3294           { "Variable Retrieval",        "slow.oam.flags.localStable",
3295             FT_BOOLEAN,    8,        TFS(&oam_var),    OAMPDU_INFO_CONFIG_VAR,
3296             "Variable Retrieval support", HFILL }},
3297
3298         { &hf_oampdu_info_oampduConfig,
3299           { "Max OAMPDU Size",    "slow.oam.info.oampduConfig",
3300             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3301             "OAMPDU Configuration", HFILL }},
3302
3303         { &hf_oampdu_info_oui,
3304           { "Organizationally Unique Identifier", "slow.oam.info.oui",
3305             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3306             NULL, HFILL }},
3307
3308         { &hf_oampdu_info_vendor,
3309           { "Vendor Specific Information", "slow.oam.info.vendor",
3310             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3311             NULL, HFILL }},
3312
3313         /*
3314          * Event notification definitions
3315          */
3316         { &hf_oampdu_event_sequence,
3317           { "Sequence Number",    "slow.oam.event.sequence",
3318             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3319             "Identifies the Event Notification TLVs", HFILL }},
3320
3321         { &hf_oampdu_event_type,
3322           { "Event Type",    "slow.oam.event.type",
3323             FT_UINT8,    BASE_HEX,    VALS(event_type_vals),    0x0,
3324             "Identifies the TLV type", HFILL }},
3325
3326         { &hf_oampdu_event_length,
3327           { "Event Length",    "slow.oam.event.length",
3328             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3329             "This field indicates the length in octets of the TLV-tuple", HFILL }},
3330
3331         { &hf_oampdu_event_timeStamp,
3332           { "Event Timestamp (100ms)",    "slow.oam.event.timestamp",
3333             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3334             "Event Time Stamp in term of 100 ms intervals", HFILL }},
3335
3336         /* Errored Symbol Period Event TLV */
3337         { &hf_oampdu_event_espeWindow,
3338           { "Errored Symbol Window",    "slow.oam.event.espeWindow",
3339             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3340             "Number of symbols in the period", HFILL }},
3341
3342         { &hf_oampdu_event_espeThreshold,
3343           { "Errored Symbol Threshold",    "slow.oam.event.espeThreshold",
3344             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3345             "Number of symbols required to generate the Event", HFILL }},
3346
3347         { &hf_oampdu_event_espeErrors,
3348           { "Errored Symbols",    "slow.oam.event.espeErrors",
3349             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3350             "Number of symbols in error", HFILL }},
3351
3352         { &hf_oampdu_event_espeTotalErrors,
3353           { "Error Running Total",    "slow.oam.event.espeTotalErrors",
3354             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3355             "Number of symbols in error since reset of the sublayer", HFILL }},
3356
3357         { &hf_oampdu_event_espeTotalEvents,
3358           { "Event Running Total",    "slow.oam.event.espeTotalEvents",
3359             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3360             "Total Event generated since reset of the sublayer", HFILL }},
3361
3362         /* Errored Frame Event TLV */
3363         { &hf_oampdu_event_efeWindow,
3364           { "Errored Frame Window",    "slow.oam.event.efeWindow",
3365             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3366             "Number of symbols in the period", HFILL }},
3367
3368         { &hf_oampdu_event_efeThreshold,
3369           { "Errored Frame Threshold",    "slow.oam.event.efeThreshold",
3370             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3371             "Number of frames required to generate the Event", HFILL }},
3372
3373         { &hf_oampdu_event_efeErrors,
3374           { "Errored Frames",    "slow.oam.event.efeErrors",
3375             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3376             "Number of symbols in error", HFILL }},
3377
3378         { &hf_oampdu_event_efeTotalErrors,
3379           { "Error Running Total",    "slow.oam.event.efeTotalErrors",
3380             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3381             "Number of frames in error since reset of the sublayer", HFILL }},
3382
3383         { &hf_oampdu_event_efeTotalEvents,
3384           { "Event Running Total",    "slow.oam.event.efeTotalEvents",
3385             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3386             "Total Event generated since reset of the sublayer", HFILL }},
3387
3388         /* Errored Frame Period Event TLV */
3389         { &hf_oampdu_event_efpeWindow,
3390           { "Errored Frame Window",    "slow.oam.event.efpeWindow",
3391             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3392             "Number of frame in error during the period", HFILL }},
3393
3394         { &hf_oampdu_event_efpeThreshold,
3395           { "Errored Frame Threshold",    "slow.oam.event.efpeThreshold",
3396             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3397             "Number of frames required to generate the Event", HFILL }},
3398
3399         { &hf_oampdu_event_efpeErrors,
3400           { "Errored Frames",    "slow.oam.event.efeErrors",
3401             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3402             "Number of symbols in error", HFILL }},
3403
3404         { &hf_oampdu_event_efpeTotalErrors,
3405           { "Error Running Total",    "slow.oam.event.efpeTotalErrors",
3406             FT_UINT64,    BASE_DEC,    NULL,    0x0,
3407             "Number of frames in error since reset of the sublayer", HFILL }},
3408
3409         { &hf_oampdu_event_efpeTotalEvents,
3410           { "Event Running Total",    "slow.oam.event.efpeTotalEvents",
3411             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3412             "Total Event generated since reset of the sublayer", HFILL }},
3413
3414         /* Errored Frame Second Summary Event TLV */
3415         { &hf_oampdu_event_efsseWindow,
3416           { "Errored Frame Window",    "slow.oam.event.efsseWindow",
3417             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3418             "Number of frame in error during the period", HFILL }},
3419
3420         { &hf_oampdu_event_efsseThreshold,
3421           { "Errored Frame Threshold",    "slow.oam.event.efsseThreshold",
3422             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3423             "Number of frames required to generate the Event", HFILL }},
3424
3425         { &hf_oampdu_event_efsseErrors,
3426           { "Errored Frames",    "slow.oam.event.efeErrors",
3427             FT_UINT16,    BASE_DEC,    NULL,    0x0,
3428             "Number of symbols in error", HFILL }},
3429
3430         { &hf_oampdu_event_efsseTotalErrors,
3431           { "Error Running Total",    "slow.oam.event.efsseTotalErrors",
3432             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3433             "Number of frames in error since reset of the sublayer", HFILL }},
3434
3435         { &hf_oampdu_event_efsseTotalEvents,
3436           { "Event Running Total",    "slow.oam.event.efsseTotalEvents",
3437             FT_UINT32,    BASE_DEC,    NULL,    0x0,
3438             "Total Event generated since reset of the sublayer", HFILL }},
3439
3440         /* Variable request and response definitions*/
3441         { &hf_oampdu_variable_branch,
3442           { "Branch",    "slow.oam.variable.branch",
3443             FT_UINT8,    BASE_HEX,    VALS(branch_vals),    0x0,
3444             "Variable Branch, derived from the CMIP protocol in Annex 30A", HFILL }},
3445
3446         { &hf_oampdu_variable_object,
3447           { "Leaf",    "slow.oam.variable.object",
3448             FT_UINT16,    BASE_HEX,    VALS(object_vals),    0x0,
3449             "Object, derived from the CMIP protocol in Annex 30A", HFILL }},
3450
3451         { &hf_oampdu_variable_package,
3452           { "Leaf",    "slow.oam.variable.package",
3453             FT_UINT16,    BASE_HEX,    VALS(package_vals),    0x0,
3454             "Package, derived from the CMIP protocol in Annex 30A", HFILL }},
3455
3456         { &hf_oampdu_variable_binding,
3457           { "Leaf",    "slow.oam.variable.binding",
3458             FT_UINT16,    BASE_HEX,    VALS(binding_vals),    0x0,
3459             "Binding, derived from the CMIP protocol in Annex 30A", HFILL }},
3460
3461         { &hf_oampdu_variable_attribute,
3462           { "Leaf",    "slow.oam.variable.attribute",
3463             FT_UINT16,    BASE_HEX|BASE_EXT_STRING,  &attribute_vals_ext,   0x0,
3464             "Attribute, derived from the CMIP protocol in Annex 30A", HFILL }},
3465
3466         { &hf_oampdu_variable_width,
3467           { "Variable Width",    "slow.oam.variable.width",
3468             FT_UINT8,    BASE_DEC,    NULL,    0x0,
3469             "Width", HFILL }},
3470
3471         { &hf_oampdu_variable_indication,
3472           { "Variable indication",    "slow.oam.variable.indication",
3473             FT_UINT8,    BASE_HEX,    VALS(indication_vals),    0x0,
3474             NULL, HFILL }},
3475
3476         { &hf_oampdu_variable_value,
3477           { "Variable Value",    "slow.oam.variable.value",
3478             FT_BYTES,    BASE_NONE,    NULL,    0x0,
3479             "Value", HFILL }},
3480
3481         /* Loopback Control definitions*/
3482         { &hf_oampdu_lpbk,
3483           { "Commands", "slow.oam.lpbk.commands",
3484             FT_UINT8,    BASE_HEX,    NULL,    0x0,
3485             "The List of Loopback Commands", HFILL }},
3486
3487         { &hf_oampdu_lpbk_enable,
3488           { "Enable Remote Loopback", "slow.oam.lpbk.commands.enable",
3489             FT_BOOLEAN,    8,        NULL,    OAMPDU_LPBK_ENABLE,
3490             "Enable Remote Loopback Command", HFILL }},
3491
3492         { &hf_oampdu_lpbk_disable,
3493           { "Disable Remote Loopback", "slow.oam.lpbk.commands.disable",
3494             FT_BOOLEAN,    8,        NULL,    OAMPDU_LPBK_DISABLE,
3495             "Disable Remote Loopback Command", HFILL }}
3496     };
3497
3498     /* Setup protocol subtree array */
3499
3500     static gint *ett[] = {
3501         &ett_pdu,
3502         &ett_lacpdu,
3503         &ett_lacpdu_a_flags,
3504         &ett_lacpdu_p_flags,
3505         &ett_marker,
3506         &ett_esmc,
3507         &ett_oampdu,
3508         &ett_oampdu_flags,
3509         &ett_oampdu_local_info,
3510         &ett_oampdu_local_info_state,
3511         &ett_oampdu_local_info_config,
3512         &ett_oampdu_remote_info,
3513         &ett_oampdu_remote_info_state,
3514         &ett_oampdu_remote_info_config,
3515         &ett_oampdu_org_info,
3516         &ett_oampdu_event_espe,
3517         &ett_oampdu_event_efe,
3518         &ett_oampdu_event_efpe,
3519         &ett_oampdu_event_efsse,
3520         &ett_oampdu_event_ose,
3521         &ett_oampdu_lpbk_ctrl,
3522         &ett_ossppdu,
3523         &ett_itu_ossp
3524
3525     };
3526
3527     /* Register the protocol name and description */
3528
3529     proto_slow = proto_register_protocol("Slow Protocols", "802.3 Slow protocols", "slow");
3530
3531     /* Required function calls to register the header fields and subtrees used */
3532
3533     proto_register_field_array(proto_slow, hf, array_length(hf));
3534     proto_register_subtree_array(ett, array_length(ett));
3535 }
3536
3537
3538 void
3539 proto_reg_handoff_slow_protocols(void)
3540 {
3541     dissector_handle_t slow_protocols_handle;
3542
3543     slow_protocols_handle = create_dissector_handle(dissect_slow_protocols, proto_slow);
3544     dissector_add_uint("ethertype", ETHERTYPE_SLOW_PROTOCOLS, slow_protocols_handle);
3545     dh_data = find_dissector("data");
3546 }