Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-mrp-msrp.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-mrp_msrp.c
2
 * Routines for MSRP (MRP Multiple Stream Reservation Protocol) dissection
3
 * Copyright 2010, Torrey Atcitty <tatcitty@harman.com>
4
 *                 Craig Gunther <craig.gunther@harman.com>
5
 *
6
 * Based on the code from packet-mmrp.c (MMRP) from
7
 * Markus Seehofer <mseehofe@nt.hirschmann.de> Copyright 2001
8
 *
9
 * Wireshark - Network traffic analyzer
10
 * By Gerald Combs <gerald@wireshark.org>
11
 * Copyright 1998 Gerald Combs
12
 *
13
 * SPDX-License-Identifier: GPL-2.0-or-later
14
 *
15
 * The MSRP Protocol specification can be found at the following:
16
 * http://www.ieee802.org/1/files/private/at-drafts/d6/802-1at-d6-0.pdf
17
 *
18
 */
19
20
#include "config.h"
21
22
#include <epan/packet.h>
23
#include <epan/expert.h>
24
#include <epan/etypes.h>
25
26
void proto_register_mrp_msrp(void);
27
void proto_reg_handoff_mrp_msrp(void);
28
29
static dissector_handle_t msrp_handle;
30
31
/* MSRP End Mark Sequence */
32
120
#define MSRP_END_MARK       0x0000
33
34
/**********************************************************/
35
/* Offsets of fields within an MSRP packet                */
36
/**********************************************************/
37
914
#define MSRP_PROTOCOL_VERSION_OFFSET        0
38
39
/* Next comes the MSRP Message group */
40
887
#define MSRP_MESSAGE_GROUP_OFFSET          (MSRP_PROTOCOL_VERSION_OFFSET + 1) /* Message is a group of fields */
41
849
#define MSRP_ATTRIBUTE_TYPE_OFFSET         (MSRP_MESSAGE_GROUP_OFFSET)
42
728
#define MSRP_ATTRIBUTE_LENGTH_OFFSET       (MSRP_ATTRIBUTE_TYPE_OFFSET + 1)
43
652
#define MSRP_ATTRIBUTE_LIST_LENGTH_OFFSET  (MSRP_ATTRIBUTE_LENGTH_OFFSET + 1)
44
45
/* Next comes the MSRP AttributeList group */
46
576
#define MSRP_ATTRIBUTE_LIST_GROUP_OFFSET   (MSRP_ATTRIBUTE_LIST_LENGTH_OFFSET + 2) /* AttributeList is a group of fields */
47
48
/* Next comes the MSRP VectorAttribute group */
49
538
#define MSRP_VECTOR_ATTRIBUTE_GROUP_OFFSET (MSRP_ATTRIBUTE_LIST_GROUP_OFFSET) /* VectorAttribute is a group of fields */
50
481
#define MSRP_VECTOR_HEADER_OFFSET          (MSRP_VECTOR_ATTRIBUTE_GROUP_OFFSET) /* contains the following two fields */
51
#define MSRP_LEAVE_ALL_EVENT_OFFSET        (MSRP_VECTOR_HEADER_OFFSET)
52
14
#define MSRP_LEAVE_ALL_EVENT_MASK           0xE000
53
57
#define MSRP_NUMBER_OF_VALUES_OFFSET       (MSRP_VECTOR_HEADER_OFFSET)
54
71
#define MSRP_NUMBER_OF_VALUES_MASK          0x1fff
55
56
/* Next comes the MSRP FirstValue group */
57
292
#define MSRP_FIRST_VALUE_GROUP_OFFSET      (MSRP_VECTOR_HEADER_OFFSET + 2) /* FirstValue is a group of fields */
58
235
#define MSRP_STREAM_ID_OFFSET              (MSRP_FIRST_VALUE_GROUP_OFFSET)
59
156
#define MSRP_STREAM_DA_OFFSET              (MSRP_STREAM_ID_OFFSET + 8)
60
134
#define MSRP_VLAN_ID_OFFSET                (MSRP_STREAM_DA_OFFSET + 6)
61
112
#define MSRP_TSPEC_MAX_FRAME_SIZE_OFFSET       (MSRP_VLAN_ID_OFFSET + 2)
62
90
#define MSRP_TSPEC_MAX_INTERVAL_FRAMES_OFFSET  (MSRP_TSPEC_MAX_FRAME_SIZE_OFFSET + 2)
63
68
#define MSRP_PRIORITY_AND_RANK_OFFSET          (MSRP_TSPEC_MAX_INTERVAL_FRAMES_OFFSET + 2) /* contains the following two fields */
64
#define MSRP_PRIORITY_OFFSET               (MSRP_PRIORITY_AND_RANK_OFFSET)
65
14
#define MSRP_PRIORITY_MASK                  0xe0
66
#define MSRP_RANK_OFFSET                   (MSRP_PRIORITY_AND_RANK_OFFSET)
67
14
#define MSRP_RANK_MASK                      0x10
68
#define MSRP_RESERVED_OFFSET               (MSRP_PRIORITY_AND_RANK_OFFSET)
69
14
#define MSRP_RESERVED_MASK                  0x0F
70
46
#define MSRP_ACCUMULATED_LATENCY_OFFSET    (MSRP_PRIORITY_AND_RANK_OFFSET + 1)
71
3
#define MSRP_FAILURE_BRIDGE_ID_OFFSET      (MSRP_ACCUMULATED_LATENCY_OFFSET + 4)
72
2
#define MSRP_FAILURE_CODE_OFFSET           (MSRP_FAILURE_BRIDGE_ID_OFFSET + 8)
73
74
0
#define MSRP_DOMAIN_THREE_PACKED_OFFSET           (MSRP_FIRST_VALUE_GROUP_OFFSET + 4)
75
22
#define MSRP_LISTENER_THREE_PACKED_OFFSET         (MSRP_STREAM_ID_OFFSET + 8)
76
21
#define MSRP_TALKER_ADVERTISE_THREE_PACKED_OFFSET (MSRP_ACCUMULATED_LATENCY_OFFSET + 4)
77
1
#define MSRP_TALKER_FAILED_THREE_PACKED_OFFSET    (MSRP_FAILURE_CODE_OFFSET + 1)
78
79
/**********************************************************/
80
/* Valid field contents                                   */
81
/**********************************************************/
82
83
/* Attribute Type definitions */
84
21
#define MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE    0x01
85
1
#define MSRP_ATTRIBUTE_TYPE_TALKER_FAILED       0x02
86
79
#define MSRP_ATTRIBUTE_TYPE_LISTENER            0x03
87
57
#define MSRP_ATTRIBUTE_TYPE_DOMAIN              0x04
88
static const value_string attribute_type_vals[] = {
89
    { MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE, "Talker Advertise" },
90
    { MSRP_ATTRIBUTE_TYPE_TALKER_FAILED,    "Talker Failed" },
91
    { MSRP_ATTRIBUTE_TYPE_LISTENER,         "Listener" },
92
    { MSRP_ATTRIBUTE_TYPE_DOMAIN,           "Domain" },
93
    { 0,                                    NULL }
94
};
95
96
/* Leave All Event definitions */
97
#define MSRP_NULLLEAVEALL   0
98
#define MSRP_LEAVEALL       1
99
static const value_string leave_all_vals[] = {
100
    { MSRP_NULLLEAVEALL, "Null" },
101
    { MSRP_LEAVEALL,     "Leave All" },
102
    { 0,                 NULL }
103
};
104
105
/* Priority definitions */
106
 #define MSRP_TRAFFIC_CLASS_A    3
107
 #define MSRP_TRAFFIC_CLASS_B    2
108
109
static const value_string priority_vals[] = {
110
    { MSRP_TRAFFIC_CLASS_A, "Traffic Class A" },
111
    { MSRP_TRAFFIC_CLASS_B, "Traffic Class B" },
112
    { 0,                    NULL }
113
};
114
115
/* Rank definitions */
116
static const value_string rank_vals[] = {
117
    { 0, "Emergency" },
118
    { 1, "Non-emergency" },
119
    { 0, NULL }
120
};
121
static const value_string reserved_vals[] = {
122
    {  0, "Reserved-0" },
123
    {  1, "Reserved-1" },
124
    {  2, "Reserved-2" },
125
    {  3, "Reserved-3" },
126
    {  4, "Reserved-4" },
127
    {  5, "Reserved-5" },
128
    {  6, "Reserved-6" },
129
    {  7, "Reserved-7" },
130
    {  8, "Reserved-8" },
131
    {  9, "Reserved-9" },
132
    { 10, "Reserved-10" },
133
    { 11, "Reserved-11" },
134
    { 12, "Reserved-12" },
135
    { 13, "Reserved-13" },
136
    { 14, "Reserved-14" },
137
    { 15, "Reserved-15" },
138
    { 0,  NULL }
139
};
140
141
/* Failure Code definitions */
142
static const value_string failure_vals[] = {
143
    {  1, "Insufficient Bandwidth" },
144
    {  2, "Insufficient Bridge resources" },
145
    {  3, "Insufficient Bandwidth for Traffic Class" },
146
    {  4, "Stream ID in use by another Talker" },
147
    {  5, "Stream destination_address already in use" },
148
    {  6, "Stream preempted by higher rank" },
149
    {  7, "Reported latency has changed" },
150
    {  8, "Egress port in not AVB capable" },
151
    {  9, "Use a different destination address (i.e. MAC DA hash table full)" },
152
    { 10, "Out of MSRP resources" },
153
    { 11, "Out of MMRP resources" },
154
    { 12, "Cannot store destination_address (i.e. Bridge is out of MAC resources)" },
155
    { 13, "Requested priority not an SR Class (3.3) priority" },
156
    { 14, "MaxFrameSize (35.2.2.8.4(a)) is too large for media" },
157
    { 15, "msrpMaxFanInPorts (35.2.1.4(f)) limit has been reached" },
158
    { 16, "Changes in FirstValue for a registered StreamID" },
159
    { 17, "VLAN is blocked on this egress port (Registration Forbidden)" },
160
    { 18, "VLAN tagging is disabled on this egress port (untagged set)" },
161
    { 19, "SR class priority mismatch" },
162
    { 0, NULL }
163
};
164
165
/* SR class ID definitions */
166
 #define MSRP_SR_CLASS_A    6
167
 #define MSRP_SR_CLASS_B    5
168
 #define MSRP_SR_CLASS_C    4
169
 #define MSRP_SR_CLASS_D    3
170
 #define MSRP_SR_CLASS_E    2
171
 #define MSRP_SR_CLASS_F    1
172
 #define MSRP_SR_CLASS_G    0
173
174
static const value_string sr_class_vals[] = {
175
    { MSRP_SR_CLASS_A, "SR Class A" },
176
    { MSRP_SR_CLASS_B, "SR Class B" },
177
    { MSRP_SR_CLASS_C, "SR Class C" },
178
    { MSRP_SR_CLASS_D, "SR Class D" },
179
    { MSRP_SR_CLASS_E, "SR Class E" },
180
    { MSRP_SR_CLASS_F, "SR Class F" },
181
    { MSRP_SR_CLASS_G, "SR Class G" },
182
    { 0,                       NULL }
183
};
184
185
/* Three Packed Event definitions */
186
static const value_string three_packed_vals[] = {
187
    { 0, "New" },
188
    { 1, "JoinIn" },
189
    { 2, "In" },
190
    { 3, "JoinMt" },
191
    { 4, "Mt" },
192
    { 5, "Lv" },
193
    { 0, NULL }
194
};
195
196
/* Four Packed Event definitions */
197
static const value_string four_packed_vals[] = {
198
    { 0, "Ignore" },
199
    { 1, "Asking Failed" },
200
    { 2, "Ready" },
201
    { 3, "Ready Failed" },
202
    { 0, NULL }
203
};
204
205
/**********************************************************/
206
/* Initialize the protocol and registered fields          */
207
/**********************************************************/
208
static int proto_msrp;
209
static int hf_msrp_proto_id;
210
static int hf_msrp_message; /* Message is a group of fields */
211
static int hf_msrp_attribute_type;
212
static int hf_msrp_attribute_length;
213
static int hf_msrp_attribute_list_length;
214
static int hf_msrp_attribute_list; /* AttributeList is a group of fields */
215
static int hf_msrp_vector_attribute; /* VectorAttribute is a group of fields */
216
217
/* The following VectorHeader contains the LeaveAllEvent and NumberOfValues */
218
static int hf_msrp_vector_header;
219
static int hf_msrp_leave_all_event;
220
static int hf_msrp_number_of_values;
221
static int ett_vector_header;
222
static int * const vector_header_fields[] = {
223
    &hf_msrp_leave_all_event,
224
    &hf_msrp_number_of_values,
225
    NULL
226
};
227
228
static int hf_msrp_first_value; /* FirstValue is a group of fields */
229
static int hf_msrp_stream_id;
230
static int hf_msrp_stream_da;
231
static int hf_msrp_vlan_id;
232
static int hf_msrp_tspec_max_frame_size;
233
static int hf_msrp_tspec_max_interval_frames;
234
static int hf_msrp_priority_and_rank;
235
static int hf_msrp_priority;
236
static int hf_msrp_rank;
237
static int hf_msrp_reserved;
238
static int ett_priority_and_rank;
239
static int * const priority_and_rank_fields[] = {
240
    &hf_msrp_priority,
241
    &hf_msrp_rank,
242
    &hf_msrp_reserved,
243
    NULL
244
};
245
246
static int hf_msrp_sr_class_id;
247
static int hf_msrp_sr_class_priority;
248
static int hf_msrp_sr_class_vid;
249
250
static int hf_msrp_accumulated_latency;
251
static int hf_msrp_failure_bridge_id;
252
static int hf_msrp_failure_code;
253
254
static int hf_msrp_three_packed_event;
255
static int hf_msrp_four_packed_event;
256
257
static int hf_msrp_end_mark;
258
259
/* Initialize the subtree pointers */
260
static int ett_msrp;
261
static int ett_msg;
262
static int ett_attr_list;
263
static int ett_vect_attr;
264
static int ett_first_value;
265
266
static expert_field ei_msrp_attribute_type;
267
268
/**********************************************************/
269
/* Dissector starts here                                  */
270
/**********************************************************/
271
272
/* dissect_msrp_common1 (called from dissect_msrp)
273
 *
274
 * dissect the following fields which are common to all MSRP attributes:
275
 *   Attribute Type
276
 *   Attribute Length
277
 *   Attribute List Length
278
 */
279
static void
280
dissect_msrp_common1(proto_tree *msg_tree, tvbuff_t *tvb, int msg_offset)
281
38
{
282
38
    proto_tree_add_item(msg_tree, hf_msrp_attribute_type, tvb,
283
38
                        MSRP_ATTRIBUTE_TYPE_OFFSET + msg_offset, 1, ENC_BIG_ENDIAN);
284
38
    proto_tree_add_item(msg_tree, hf_msrp_attribute_length, tvb,
285
38
                        MSRP_ATTRIBUTE_LENGTH_OFFSET + msg_offset, 1, ENC_BIG_ENDIAN);
286
38
    proto_tree_add_item(msg_tree, hf_msrp_attribute_list_length, tvb,
287
38
                        MSRP_ATTRIBUTE_LIST_LENGTH_OFFSET + msg_offset, 2, ENC_BIG_ENDIAN);
288
38
}
289
290
291
/* dissect_msrp_common2 (called from dissect_msrp)
292
 *
293
 * dissect the following fields which are common to all MSRP attributes:
294
 *   Leave All Event
295
 *   Number of Values fields
296
 */
297
static void
298
dissect_msrp_common2(proto_tree *vect_attr_tree, tvbuff_t *tvb, int msg_offset)
299
57
{
300
57
    proto_tree_add_bitmask(vect_attr_tree, tvb, MSRP_VECTOR_HEADER_OFFSET + msg_offset,
301
57
                           hf_msrp_vector_header, ett_vector_header, vector_header_fields, ENC_BIG_ENDIAN);
302
57
}
303
304
305
/* dissect_msrp_talker_common (called from dissect_msrp)
306
 *
307
 * dissect the following fields which are common to all MSRP Talker attributes:
308
 *   Stream MAC DA
309
 *   Stream VLAN ID
310
 *   TSpec Bandwidth
311
 *   TSpec Frame Rate
312
 *   Priority (Traffic Class)
313
 *   Rank
314
 *   Accumulated Latency
315
 */
316
static void
317
dissect_msrp_talker_common(proto_tree *first_value_tree, tvbuff_t *tvb, int msg_offset)
318
22
{
319
320
22
    proto_tree_add_item(first_value_tree, hf_msrp_stream_da, tvb,
321
22
                        MSRP_STREAM_DA_OFFSET + msg_offset, 6, ENC_NA);
322
22
    proto_tree_add_item(first_value_tree, hf_msrp_vlan_id, tvb,
323
22
                        MSRP_VLAN_ID_OFFSET + msg_offset, 2, ENC_BIG_ENDIAN);
324
22
    proto_tree_add_item(first_value_tree, hf_msrp_tspec_max_frame_size, tvb,
325
22
                        MSRP_TSPEC_MAX_FRAME_SIZE_OFFSET + msg_offset, 2, ENC_BIG_ENDIAN);
326
22
    proto_tree_add_item(first_value_tree, hf_msrp_tspec_max_interval_frames, tvb,
327
22
                        MSRP_TSPEC_MAX_INTERVAL_FRAMES_OFFSET + msg_offset, 2, ENC_BIG_ENDIAN);
328
22
    proto_tree_add_bitmask(first_value_tree, tvb, MSRP_PRIORITY_AND_RANK_OFFSET + msg_offset,
329
22
                           hf_msrp_priority_and_rank, ett_priority_and_rank, priority_and_rank_fields, ENC_BIG_ENDIAN);
330
22
    proto_tree_add_item(first_value_tree, hf_msrp_accumulated_latency, tvb,
331
22
                        MSRP_ACCUMULATED_LATENCY_OFFSET + msg_offset, 4, ENC_BIG_ENDIAN);
332
22
}
333
334
335
/* dissect_msrp_talker_failed (called from dissect_msrp)
336
 *
337
 * dissect the following fields which are common to all MSRP Talker Failed attributes:
338
 *   Failure Information: Bridge ID
339
 *   Failure Information: Failure Code
340
 */
341
static void
342
dissect_msrp_talker_failed(proto_tree *first_value_tree, tvbuff_t *tvb, int msg_offset)
343
1
{
344
345
1
    proto_tree_add_item(first_value_tree, hf_msrp_failure_bridge_id, tvb,
346
1
                        MSRP_FAILURE_BRIDGE_ID_OFFSET + msg_offset, 8, ENC_BIG_ENDIAN);
347
1
    proto_tree_add_item(first_value_tree, hf_msrp_failure_code, tvb,
348
1
                        MSRP_FAILURE_CODE_OFFSET + msg_offset, 1, ENC_BIG_ENDIAN);
349
1
}
350
351
352
/* dissect_msrp_three_packed_event (called from dissect_msrp)
353
 *
354
 * dissect one or more ThreePackedEvents
355
 */
356
static unsigned
357
dissect_msrp_three_packed_event(proto_tree *vect_attr_tree, tvbuff_t *tvb, unsigned offset, uint16_t number_of_values)
358
44
{
359
44
    unsigned counter;
360
361
5.25k
    for ( counter = 0; counter < number_of_values; ) {
362
5.21k
        uint8_t value;
363
5.21k
        uint8_t three_packed_event[3];
364
365
5.21k
        value = tvb_get_uint8(tvb, offset);
366
5.21k
        three_packed_event[0] = value / 36;
367
5.21k
        value -= 36 * three_packed_event[0];
368
5.21k
        three_packed_event[1] = value / 6;
369
5.21k
        value -=  6 * three_packed_event[1];
370
5.21k
        three_packed_event[2] = value;
371
372
5.21k
        proto_tree_add_uint(vect_attr_tree, hf_msrp_three_packed_event, tvb, offset, sizeof(uint8_t),
373
5.21k
                            three_packed_event[0]);
374
5.21k
        counter++;
375
5.21k
        if ( counter < number_of_values ) {
376
5.19k
            proto_tree_add_uint(vect_attr_tree, hf_msrp_three_packed_event, tvb, offset, sizeof(uint8_t),
377
5.19k
                                three_packed_event[1]);
378
5.19k
            counter++;
379
5.19k
        }
380
5.21k
        if ( counter < number_of_values ) {
381
5.19k
            proto_tree_add_uint(vect_attr_tree, hf_msrp_three_packed_event, tvb, offset, sizeof(uint8_t),
382
5.19k
                                three_packed_event[2]);
383
5.19k
            counter++;
384
5.19k
        }
385
386
5.21k
        offset++;
387
5.21k
    }
388
44
    return offset ;
389
44
}
390
391
392
/* dissect_msrp_four_packed_event (called from dissect_msrp)
393
 *
394
 * dissect one or more FourPackedEvents
395
 */
396
static unsigned
397
dissect_msrp_four_packed_event(proto_tree *vect_attr_tree, tvbuff_t *tvb, unsigned offset, uint16_t number_of_values)
398
22
{
399
22
    unsigned counter;
400
401
1.08k
    for ( counter = 0; counter < number_of_values; ) {
402
1.06k
        uint8_t value;
403
1.06k
        uint8_t four_packed_event[4];
404
405
1.06k
        value = tvb_get_uint8(tvb, offset);
406
1.06k
        four_packed_event[0] = (value & 0xc0) >> 6;
407
1.06k
        four_packed_event[1] = (value & 0x30) >> 4;
408
1.06k
        four_packed_event[2] = (value & 0x0c) >> 2;
409
1.06k
        four_packed_event[3] = (value & 0x03);
410
411
1.06k
        proto_tree_add_uint(vect_attr_tree, hf_msrp_four_packed_event, tvb, offset, sizeof(uint8_t),
412
1.06k
                            four_packed_event[0]);
413
1.06k
        counter++;
414
1.06k
        if ( counter < number_of_values ) {
415
1.05k
            proto_tree_add_uint(vect_attr_tree, hf_msrp_four_packed_event, tvb, offset, sizeof(uint8_t),
416
1.05k
                                four_packed_event[1]);
417
1.05k
            counter++;
418
1.05k
        }
419
1.06k
        if ( counter < number_of_values ) {
420
1.05k
            proto_tree_add_uint(vect_attr_tree, hf_msrp_four_packed_event, tvb, offset, sizeof(uint8_t),
421
1.05k
                                four_packed_event[2]);
422
1.05k
            counter++;
423
1.05k
        }
424
1.06k
        if ( counter < number_of_values ) {
425
1.04k
            proto_tree_add_uint(vect_attr_tree, hf_msrp_four_packed_event, tvb, offset, sizeof(uint8_t),
426
1.04k
                                four_packed_event[3]);
427
1.04k
            counter++;
428
1.04k
        }
429
430
1.06k
        offset++;
431
1.06k
    }
432
22
    return offset;
433
22
}
434
435
436
/* dissect_main
437
 *
438
 * main dissect function that calls the other functions listed above as necessary
439
 */
440
static int
441
dissect_msrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
442
27
{
443
    /* Set up structures needed to add the protocol subtrees and manage them */
444
27
    proto_item *ti, *msg_ti, *attr_list_ti, *vect_attr_ti, *first_value_ti;
445
27
    proto_tree *msrp_tree, *msg_tree, *attr_list_tree, *vect_attr_tree, *first_value_tree;
446
447
    /* Make entries in Protocol column and Info column on summary display */
448
27
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRP-MSRP");
449
450
27
    col_set_str(pinfo->cinfo, COL_INFO, "Multiple Stream Reservation Protocol");
451
452
27
    if (tree) {
453
27
        uint8_t attribute_type;
454
27
        uint8_t attribute_length;
455
27
        uint16_t number_of_values;
456
27
        uint16_t attribute_list_length;
457
27
        unsigned offset = 0;
458
27
        int vect_attr_len;
459
27
        int msg_length;  /* Length of MSRP/MRP Message */
460
27
        int msg_offset;  /* Use when handling multiple messages.  This points to current msg being decoded. */
461
27
        int vect_offset; /* Use when handling multiple vector attributes.  This points to the current vector attribute being decoded. */
462
463
27
        ti = proto_tree_add_item(tree, proto_msrp, tvb, 0, -1, ENC_NA);
464
27
        msrp_tree = proto_item_add_subtree(ti, ett_msrp);
465
466
27
        proto_tree_add_item(msrp_tree, hf_msrp_proto_id, tvb, MSRP_PROTOCOL_VERSION_OFFSET, 1, ENC_BIG_ENDIAN);
467
468
        /* MSRP supports multiple MRP Messages per frame.  Handle those Messages in
469
         * the following while() loop. You will know you are at the end of the list
470
         * of messages when the EndMark (0x0000) is encountered instead of an
471
         * Attribute Type and Attribute Length (guaranteed to not be 0x0000).
472
         */
473
27
        msg_offset = 0;
474
45
        while (tvb_get_ntohs(tvb, MSRP_ATTRIBUTE_TYPE_OFFSET + msg_offset) != MSRP_END_MARK) {
475
476
38
            attribute_type = tvb_get_uint8(tvb, MSRP_ATTRIBUTE_TYPE_OFFSET + msg_offset);
477
38
            attribute_length = tvb_get_uint8(tvb, MSRP_ATTRIBUTE_LENGTH_OFFSET + msg_offset);
478
38
            attribute_list_length = tvb_get_ntohs(tvb, MSRP_ATTRIBUTE_LIST_LENGTH_OFFSET + msg_offset);
479
480
            /* MSRP Message is a group of fields
481
             *
482
             * Contains AttributeType (1 byte)
483
             *        + AttributeLength (1 byte)
484
             *        + AttributeListLength (2 bytes)
485
             *        + AttributeList (AttributeListLength bytes)
486
            *        bytes of data
487
            */
488
38
            msg_length = 1 + 1 + 2 + attribute_list_length;
489
38
            msg_ti = proto_tree_add_item(msrp_tree, hf_msrp_message, tvb,
490
38
                                         MSRP_MESSAGE_GROUP_OFFSET + msg_offset,
491
38
                                         msg_length, ENC_NA);
492
38
            msg_tree = proto_item_add_subtree(msg_ti, ett_msg);
493
494
            /* Append AttributeType description to the end of the "Message" heading */
495
38
            proto_item_append_text(msg_tree, ": %s (%d)",
496
38
                                   val_to_str_const(attribute_type, attribute_type_vals, "<Unknown>"),
497
38
                                   attribute_type);
498
499
38
            dissect_msrp_common1(msg_tree, tvb, msg_offset);
500
501
            /* MSRP AttributeList is a group of fields
502
             *
503
             * Contains AttributeListLength bytes of data
504
             */
505
38
            attr_list_ti = proto_tree_add_item(msg_tree, hf_msrp_attribute_list, tvb,
506
38
                                               MSRP_ATTRIBUTE_LIST_GROUP_OFFSET + msg_offset,
507
38
                                               attribute_list_length, ENC_NA);
508
38
            attr_list_tree = proto_item_add_subtree(attr_list_ti, ett_attr_list);
509
510
511
            /* MSRP supports multiple MRP Vector Attributes per Attribute List.  Handle those
512
             * Vector Attributes in the following while() loop. You will know you are at the
513
             * end of the list of Vector Attributes when the EndMark (0x0000) is encountered
514
             * instead of a Vector Header (guaranteed to not be 0x0000).
515
             */
516
38
            vect_offset = 0;
517
75
            while (tvb_get_ntohs(tvb, MSRP_VECTOR_HEADER_OFFSET + msg_offset + vect_offset) != MSRP_END_MARK) {
518
                /* MSRP VectorAttribute is a group of fields
519
                 *
520
                 * Contains VectorHeader (2 bytes)
521
                 *        + FirstValue (AttributeLength bytes)
522
                 *        + VectorThreePacked (NumberOfValues @ 3/vector bytes)
523
                 *        + VectorFourPacked (NumberOfValues @ 4/vector bytes only for Listener attributes)
524
                 *        bytes of data
525
                 */
526
57
                number_of_values = tvb_get_ntohs(tvb, MSRP_NUMBER_OF_VALUES_OFFSET + msg_offset + vect_offset)
527
57
                                   & MSRP_NUMBER_OF_VALUES_MASK;
528
529
57
                vect_attr_len = 2 + attribute_length + (number_of_values + 2)/3; /* stores 3 values per byte */
530
57
                if (attribute_type == MSRP_ATTRIBUTE_TYPE_LISTENER)
531
22
                    vect_attr_len += (number_of_values + 3)/4; /* stores 4 values per byte */
532
533
57
                vect_attr_ti = proto_tree_add_item(attr_list_tree, hf_msrp_vector_attribute, tvb,
534
57
                                                   MSRP_VECTOR_ATTRIBUTE_GROUP_OFFSET + msg_offset + vect_offset,
535
57
                                                   vect_attr_len, ENC_NA);
536
537
57
                vect_attr_tree = proto_item_add_subtree(vect_attr_ti, ett_vect_attr);
538
539
57
                dissect_msrp_common2(vect_attr_tree, tvb, msg_offset + vect_offset);
540
541
57
                if(attribute_type == MSRP_ATTRIBUTE_TYPE_DOMAIN) {
542
                    /* MSRP Domain FirstValue is a group of fields
543
                     *
544
                     * Contains SRclassID (1 byte)
545
                     *        + SRclassPriority (1 byte)
546
                     *        + SRclassVID (2 bytes)
547
                     *        bytes of data
548
                     */
549
0
                    first_value_ti = proto_tree_add_item(vect_attr_tree, hf_msrp_first_value, tvb,
550
0
                                                         MSRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset,
551
0
                                                         attribute_length, ENC_NA);
552
0
                    first_value_tree = proto_item_add_subtree(first_value_ti, ett_first_value);
553
554
                    /* Add Domain components to First Value tree */
555
0
                    proto_tree_add_item(first_value_tree, hf_msrp_sr_class_id, tvb,
556
0
                                        MSRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset, 1, ENC_BIG_ENDIAN);
557
0
                    proto_tree_add_item(first_value_tree, hf_msrp_sr_class_priority, tvb,
558
0
                                        MSRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset + 1, 1, ENC_BIG_ENDIAN);
559
0
                    proto_tree_add_item(first_value_tree, hf_msrp_sr_class_vid, tvb,
560
0
                                        MSRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset + 2, 2, ENC_BIG_ENDIAN);
561
562
                    /* Decode three packed events. */
563
0
                    offset = dissect_msrp_three_packed_event(vect_attr_tree, tvb,
564
0
                                                             MSRP_DOMAIN_THREE_PACKED_OFFSET + msg_offset + vect_offset,
565
0
                                                             number_of_values);
566
567
0
                }
568
57
                else {
569
                    /* MSRP Stream Reservations FirstValue is a group of fields
570
                     *
571
                     * Contains StreamID (8 bytes)
572
                     *        + DataFrameParameters (8 bytes on Talker attributes)
573
                     *        + TSpec (8 bytes on Talker attributes)
574
                     *        + PriorityAndRank (1 byte on Talker attributes)
575
                     *        + AccumulatedLatency (4 bytes on Talker attributes)
576
                     *        + FailureInformation (9 bytes on Talker Failed attributes)
577
                     *        bytes of data
578
                     */
579
57
                    first_value_ti = proto_tree_add_item(vect_attr_tree, hf_msrp_first_value, tvb,
580
57
                                                         MSRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset,
581
57
                                                         attribute_length, ENC_NA);
582
57
                    first_value_tree = proto_item_add_subtree(first_value_ti, ett_first_value);
583
584
                    /* Decode StreamID */
585
57
                    proto_tree_add_item(first_value_tree, hf_msrp_stream_id, tvb,
586
57
                                        MSRP_STREAM_ID_OFFSET + msg_offset + vect_offset, 8, ENC_BIG_ENDIAN);
587
588
57
                    switch ( attribute_type ) {
589
22
                    case MSRP_ATTRIBUTE_TYPE_LISTENER:
590
22
                        offset = dissect_msrp_three_packed_event(vect_attr_tree, tvb,
591
22
                                                                 MSRP_LISTENER_THREE_PACKED_OFFSET + msg_offset + vect_offset,
592
22
                                                                 number_of_values);
593
22
                        offset = dissect_msrp_four_packed_event(vect_attr_tree, tvb, offset, number_of_values);
594
22
                        break;
595
21
                    case MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE:
596
21
                        dissect_msrp_talker_common(first_value_tree, tvb, msg_offset + vect_offset);
597
21
                        offset = dissect_msrp_three_packed_event(vect_attr_tree, tvb,
598
21
                                                                 MSRP_TALKER_ADVERTISE_THREE_PACKED_OFFSET + msg_offset + vect_offset,
599
21
                                                                 number_of_values);
600
21
                        break;
601
1
                    case MSRP_ATTRIBUTE_TYPE_TALKER_FAILED:
602
1
                        dissect_msrp_talker_common(first_value_tree, tvb, msg_offset + vect_offset);
603
1
                        dissect_msrp_talker_failed(first_value_tree, tvb, msg_offset + vect_offset);
604
1
                        offset = dissect_msrp_three_packed_event(vect_attr_tree, tvb,
605
1
                                                                 MSRP_TALKER_FAILED_THREE_PACKED_OFFSET + msg_offset + vect_offset,
606
1
                                                                 number_of_values);
607
1
                        break;
608
13
                    default:
609
13
                        proto_tree_add_expert(first_value_tree, pinfo, &ei_msrp_attribute_type, tvb, msg_offset + vect_offset, vect_attr_len);
610
13
                        break;
611
57
                    }
612
57
                }
613
37
                vect_offset += vect_attr_len; /* Move to next Vector Attribute, if there is one */
614
37
            } /* Multiple VectorAttribute while() */
615
616
18
            proto_tree_add_item(attr_list_tree, hf_msrp_end_mark, tvb, offset, 2, ENC_BIG_ENDIAN); /* VectorAttribute EndMark */
617
618
18
            msg_offset += msg_length; /* Move to next Message, if there is one */
619
18
        } /* Multiple Message while() */
620
7
        proto_tree_add_item(msrp_tree, hf_msrp_end_mark, tvb, offset+2, 2, ENC_BIG_ENDIAN); /* Message EndMark */
621
7
    }
622
7
    return tvb_captured_length(tvb);
623
27
}
624
625
626
/* Register the protocol with Wireshark */
627
void
628
proto_register_mrp_msrp(void)
629
14
{
630
14
    static hf_register_info hf[] = {
631
14
        { &hf_msrp_proto_id,
632
14
            { "Protocol Version",      "mrp-msrp.protocol_version",
633
14
              FT_UINT8,  BASE_DEC, NULL, 0x0, NULL, HFILL }
634
14
        },
635
14
        { &hf_msrp_message, /* Message is a group of fields */
636
14
            { "Message",               "mrp-msrp.message",
637
14
              FT_NONE,  BASE_NONE, NULL, 0x0, NULL, HFILL }
638
14
        },
639
14
        { &hf_msrp_attribute_type,
640
14
            { "Attribute Type",        "mrp-msrp.attribute_type",
641
14
              FT_UINT8,  BASE_DEC, VALS(attribute_type_vals), 0x0, NULL, HFILL }
642
14
        },
643
14
        { &hf_msrp_attribute_length,
644
14
            { "Attribute Length",      "mrp-msrp.attribute_length",
645
14
              FT_UINT8,  BASE_DEC, NULL, 0x0, NULL, HFILL }
646
14
        },
647
14
        { &hf_msrp_attribute_list_length,
648
14
            { "Attribute List Length", "mrp-msrp.attribute_list_length",
649
14
              FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
650
14
        },
651
14
        { &hf_msrp_attribute_list, /* AttributeList is a group of fields */
652
14
            { "Attribute List",        "mrp-msrp.attribute_list",
653
14
              FT_NONE,  BASE_NONE, NULL, 0x0, NULL, HFILL }
654
14
        },
655
14
        { &hf_msrp_vector_attribute, /* VectorAttribute is a group of fields */
656
14
            { "Vector Attribute",      "mrp-msrp.vector_attribute",
657
14
              FT_NONE,  BASE_NONE, NULL, 0x0, NULL, HFILL }
658
14
        },
659
14
        { &hf_msrp_vector_header,
660
14
            { "Vector Header",         "mrp-msrp.vector_header",
661
14
              FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
662
14
        },
663
14
        { &hf_msrp_leave_all_event,
664
14
            { "Leave All Event",       "mrp-msrp.leave_all_event",
665
14
              FT_UINT16, BASE_DEC, VALS(leave_all_vals), MSRP_LEAVE_ALL_EVENT_MASK, NULL, HFILL }
666
14
        },
667
14
        { &hf_msrp_number_of_values,
668
14
            { "Number of Values",      "mrp-msrp.number_of_values",
669
14
              FT_UINT16, BASE_DEC, NULL, MSRP_NUMBER_OF_VALUES_MASK, NULL, HFILL }
670
14
        },
671
14
        { &hf_msrp_first_value, /* FirstValue is a group of fields */
672
14
            { "First Value",           "mrp-msrp.first_value",
673
14
              FT_NONE,  BASE_NONE, NULL, 0x0, NULL, HFILL }
674
14
        },
675
14
        { &hf_msrp_stream_id,
676
14
            { "Stream ID",             "mrp-msrp.stream_id",
677
14
              FT_UINT64, BASE_HEX, NULL, 0x00, NULL, HFILL }
678
14
        },
679
14
        { &hf_msrp_stream_da,
680
14
            { "Stream DA",             "mrp-msrp.stream_da",
681
14
              FT_ETHER,  BASE_NONE, NULL, 0x00, NULL, HFILL }
682
14
        },
683
14
        { &hf_msrp_vlan_id,
684
14
            { "VLAN ID",               "mrp-msrp.vlan_id",
685
14
              FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }
686
14
        },
687
14
        { &hf_msrp_tspec_max_frame_size,
688
14
            { "TSpec Max Frame Size",  "mrp-msrp.tspec_max_frame_size",
689
14
              FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
690
14
        },
691
14
        { &hf_msrp_tspec_max_interval_frames,
692
14
            { "TSpec Max Frame Interval", "mrp-msrp.tspec_max_interval_frames",
693
14
              FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
694
14
        },
695
14
        { &hf_msrp_priority_and_rank,
696
14
            { "Priority and Rank",     "mrp-msrp.priority_and_rank",
697
14
              FT_UINT8,  BASE_HEX, NULL, 0x0, NULL, HFILL }
698
14
        },
699
14
        { &hf_msrp_priority,
700
14
            { "Priority",              "mrp-msrp.priority",
701
14
              FT_UINT8,  BASE_DEC, VALS(priority_vals), MSRP_PRIORITY_MASK, NULL, HFILL }
702
14
        },
703
14
        { &hf_msrp_rank,
704
14
            { "Rank",                  "mrp-msrp.rank",
705
14
              FT_UINT8,  BASE_DEC, VALS(rank_vals), MSRP_RANK_MASK, NULL, HFILL }
706
14
        },
707
14
        { &hf_msrp_reserved,
708
14
            { "Reserved",              "mrp-msrp.reserved",
709
14
              FT_UINT8,  BASE_DEC, VALS(reserved_vals), MSRP_RESERVED_MASK, NULL, HFILL }
710
14
        },
711
14
        { &hf_msrp_accumulated_latency,
712
14
            { "Accumulated Latency",   "mrp-msrp.accumulated_latency",
713
14
              FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
714
14
        },
715
14
        { &hf_msrp_failure_bridge_id,
716
14
            { "Failure Bridge ID",     "mrp-msrp.failure_bridge_id",
717
14
              FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }
718
14
        },
719
14
        { &hf_msrp_failure_code,
720
14
            { "Failure Code",          "mrp-msrp.failure_code",
721
14
              FT_UINT8, BASE_DEC,  VALS(failure_vals), 0x0, NULL, HFILL }
722
14
        },
723
14
        { &hf_msrp_sr_class_id,
724
14
            { "SR Class ID",           "mrp-msrp.sr_class_id",
725
14
              FT_UINT8, BASE_DEC,  VALS(sr_class_vals), 0x0, NULL, HFILL }
726
14
        },
727
14
        { &hf_msrp_sr_class_priority,
728
14
            { "SR Class Priority",     "mrp-msrp.sr_class_priority",
729
14
              FT_UINT8, BASE_DEC,  NULL, 0x0, NULL, HFILL }
730
14
        },
731
14
        { &hf_msrp_sr_class_vid,
732
14
            { "SR Class VID",          "mrp-msrp.sr_class_vid",
733
14
              FT_UINT16, BASE_DEC,  NULL, 0x0, NULL, HFILL }
734
14
        },
735
14
        { &hf_msrp_three_packed_event,
736
14
            { "Attribute Event",       "mrp-msrp.three_packed_event",
737
14
              FT_UINT8, BASE_DEC,  VALS(three_packed_vals), 0x0, NULL, HFILL }
738
14
        },
739
14
        { &hf_msrp_four_packed_event,
740
14
            { "Declaration Type",      "mrp-msrp.four_packed_event",
741
14
              FT_UINT8, BASE_DEC,  VALS(four_packed_vals), 0x0, NULL, HFILL }
742
14
        },
743
14
        { &hf_msrp_end_mark,
744
14
            { "End Mark",              "mrp-msrp.end_mark",
745
14
              FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
746
14
        },
747
14
    };
748
749
    /* Setup protocol subtree array */
750
14
    static int *ett[] = {
751
14
        &ett_msrp,
752
14
        &ett_msg,
753
14
        &ett_attr_list,
754
14
        &ett_vect_attr,
755
14
        &ett_vector_header,
756
14
        &ett_first_value,
757
14
        &ett_priority_and_rank
758
14
    };
759
760
14
    static ei_register_info ei[] = {
761
14
        { &ei_msrp_attribute_type, { "mrp-msrp.attribute_type.unknown", PI_PROTOCOL, PI_WARN, "Malformed TCP/IP Status", EXPFILL }},
762
14
    };
763
764
14
    expert_module_t* expert_msrp;
765
766
    /* Register the protocol name and description */
767
14
    proto_msrp = proto_register_protocol("Multiple Stream Reservation Protocol",
768
14
                                         "MRP-MSRP", "mrp-msrp");
769
770
    /* Required function calls to register the header fields and subtrees used */
771
14
    proto_register_field_array(proto_msrp, hf, array_length(hf));
772
14
    proto_register_subtree_array(ett, array_length(ett));
773
14
    expert_msrp = expert_register_protocol(proto_msrp);
774
14
    expert_register_field_array(expert_msrp, ei, array_length(ei));
775
776
    /* Register the dissector */
777
14
    msrp_handle = register_dissector("mrp-msrp", dissect_msrp, proto_msrp);
778
14
}
779
780
void
781
proto_reg_handoff_mrp_msrp(void)
782
14
{
783
14
    dissector_add_uint("ethertype", ETHERTYPE_MSRP, msrp_handle);
784
14
}
785
786
/*
787
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
788
 *
789
 * Local variables:
790
 * c-basic-offset: 4
791
 * tab-width: 8
792
 * indent-tabs-mode: nil
793
 * End:
794
 *
795
 * vi: set shiftwidth=4 tabstop=8 expandtab:
796
 * :indentSize=4:tabSize=8:noTabs=true:
797
 */