3 * Routines for MPLS delay and loss measurement: it should conform
4 * to RFC 6374. 'PM' stands for Performance Measurement.
8 * Francesco Fondelli <francesco dot fondelli, gmail dot com>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include <epan/packet.h>
21 #include <wsutil/array.h>
22 #include "packet-ip.h"
23 #include "packet-mpls.h"
25 void proto_register_mpls_pm(void);
26 void proto_reg_handoff_mpls_pm(void);
28 /* message control flags */
29 #define MPLS_PM_FLAGS_R 0x08
30 #define MPLS_PM_FLAGS_T 0x04
31 #define MPLS_PM_FLAGS_RES 0x03
32 #define MPLS_PM_FLAGS_MASK 0x0F
34 /* data format flags */
35 #define MPLS_PM_DFLAGS_X 0x80
36 #define MPLS_PM_DFLAGS_B 0x40
37 #define MPLS_PM_DFLAGS_RES 0x30
38 #define MPLS_PM_DFLAGS_MASK 0xF0
40 static int proto_mpls_pm_dlm
;
41 static int proto_mpls_pm_ilm
;
42 static int proto_mpls_pm_dm
;
43 static int proto_mpls_pm_dlm_dm
;
44 static int proto_mpls_pm_ilm_dm
;
46 static int ett_mpls_pm
;
47 static int ett_mpls_pm_flags
;
48 static int ett_mpls_pm_dflags
;
50 static int hf_mpls_pm_version
;
51 static int hf_mpls_pm_flags
;
52 static int hf_mpls_pm_flags_r
;
53 static int hf_mpls_pm_flags_t
;
54 static int hf_mpls_pm_flags_res
;
55 static int hf_mpls_pm_query_ctrl_code
;
56 static int hf_mpls_pm_response_ctrl_code
;
57 static int hf_mpls_pm_length
;
58 static int hf_mpls_pm_dflags
;
59 static int hf_mpls_pm_dflags_x
;
60 static int hf_mpls_pm_dflags_b
;
61 static int hf_mpls_pm_dflags_res
;
62 static int hf_mpls_pm_otf
;
63 static int hf_mpls_pm_session_id
;
64 static int hf_mpls_pm_ds
;
65 static int hf_mpls_pm_origin_timestamp_null
;
66 static int hf_mpls_pm_origin_timestamp_seq
;
67 static int hf_mpls_pm_origin_timestamp_ntp
;
68 static int hf_mpls_pm_origin_timestamp_ptp
;
69 static int hf_mpls_pm_origin_timestamp_unk
;
70 static int hf_mpls_pm_counter1
;
71 static int hf_mpls_pm_counter2
;
72 static int hf_mpls_pm_counter3
;
73 static int hf_mpls_pm_counter4
;
74 static int hf_mpls_pm_qtf
;
75 static int hf_mpls_pm_qtf_combined
;
76 static int hf_mpls_pm_rtf
;
77 static int hf_mpls_pm_rtf_combined
;
78 static int hf_mpls_pm_rptf
;
79 static int hf_mpls_pm_rptf_combined
;
80 static int hf_mpls_pm_timestamp1_q_null
;
81 static int hf_mpls_pm_timestamp1_r_null
;
82 static int hf_mpls_pm_timestamp1_q_seq
;
83 static int hf_mpls_pm_timestamp1_r_seq
;
84 static int hf_mpls_pm_timestamp1_q_ntp
;
85 static int hf_mpls_pm_timestamp1_r_ntp
;
86 static int hf_mpls_pm_timestamp1_q_ptp
;
87 static int hf_mpls_pm_timestamp1_r_ptp
;
88 static int hf_mpls_pm_timestamp1_unk
;
89 static int hf_mpls_pm_timestamp2_q_null
;
90 static int hf_mpls_pm_timestamp2_r_null
;
91 static int hf_mpls_pm_timestamp2_q_seq
;
92 static int hf_mpls_pm_timestamp2_r_seq
;
93 static int hf_mpls_pm_timestamp2_q_ntp
;
94 static int hf_mpls_pm_timestamp2_r_ntp
;
95 static int hf_mpls_pm_timestamp2_q_ptp
;
96 static int hf_mpls_pm_timestamp2_r_ptp
;
97 static int hf_mpls_pm_timestamp2_unk
;
98 static int hf_mpls_pm_timestamp3_null
;
99 static int hf_mpls_pm_timestamp3_r_null
;
100 static int hf_mpls_pm_timestamp3_r_seq
;
101 static int hf_mpls_pm_timestamp3_r_ntp
;
102 static int hf_mpls_pm_timestamp3_r_ptp
;
103 static int hf_mpls_pm_timestamp3_unk
;
104 static int hf_mpls_pm_timestamp4_null
;
105 static int hf_mpls_pm_timestamp4_r_null
;
106 static int hf_mpls_pm_timestamp4_r_seq
;
107 static int hf_mpls_pm_timestamp4_r_ntp
;
108 static int hf_mpls_pm_timestamp4_r_ptp
;
109 static int hf_mpls_pm_timestamp4_unk
;
112 * FF: please keep this list in sync with
113 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
114 * Registry Name: 'Loss/Delay Measurement Control Code: Query Codes'
116 static const range_string mpls_pm_query_ctrl_code_rvals
[] = {
117 { 0x00, 0x00, "In-band Response Requested" },
118 { 0x01, 0x01, "Out-of-band Response Requested" },
119 { 0x02, 0x02, "No Response Requested" },
120 { 0x03, 0xFF, "Unassigned" },
125 * FF: please keep this list in sync with
126 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
127 * Registry Name: 'Loss/Delay Measurement Control Code: Response Codes'
129 static const range_string mpls_pm_response_ctrl_code_rvals
[] = {
130 { 0x00, 0x00, "Reserved" },
131 { 0x01, 0x01, "Success" },
132 { 0x02, 0x02, "Data Format Invalid" },
133 { 0x03, 0x03, "Initialization in Progress" },
134 { 0x04, 0x04, "Data Reset Occurred" },
135 { 0x05, 0x05, "Resource Temporarily Unavailable" },
136 { 0x06, 0x0F, "Unassigned" },
137 { 0x10, 0x10, "Unspecified Error" },
138 { 0x11, 0x11, "Unsupported Version" },
139 { 0x12, 0x12, "Unsupported Control Code" },
140 { 0x13, 0x13, "Unsupported Data Format" },
141 { 0x14, 0x14, "Authentication Failure" },
142 { 0x15, 0x15, "Invalid Destination Node Identifier" },
143 { 0x16, 0x16, "Connection Mismatch" },
144 { 0x17, 0x17, "Unsupported Mandatory TLV Object" },
145 { 0x18, 0x18, "Unsupported Query Interval" },
146 { 0x19, 0x19, "Administrative Block" },
147 { 0x1A, 0x1A, "Resource Unavailable" },
148 { 0x1B, 0x1B, "Resource Released" },
149 { 0x1C, 0x1C, "Invalid Message" },
150 { 0x1D, 0x1D, "Protocol Error" },
151 { 0x1E, 0xFF, "Unassigned" },
161 static const value_string pmt_vals
[] = {
171 * FF: please keep this list in sync with
172 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
173 * Registry Name: 'Loss/Delay Measurement Control Code: Response Codes'
175 #define MPLS_PM_TSF_NULL 0
176 #define MPLS_PM_TSF_SEQ 1
177 #define MPLS_PM_TSF_NTP 2
178 #define MPLS_PM_TSF_PTP 3
179 static const range_string mpls_pm_time_stamp_format_rvals
[] = {
180 { MPLS_PM_TSF_NULL
, MPLS_PM_TSF_NULL
,
182 { MPLS_PM_TSF_SEQ
, MPLS_PM_TSF_SEQ
,
184 { MPLS_PM_TSF_NTP
, MPLS_PM_TSF_NTP
,
185 "Network Time Protocol version 4 64-bit Timestamp" },
186 { MPLS_PM_TSF_PTP
, MPLS_PM_TSF_PTP
,
187 "Truncated IEEE 1588v2 PTP Timestamp" },
188 { 4, 15, "Unassigned" },
193 mpls_pm_dissect_counter(tvbuff_t
*tvb
, proto_tree
*pm_tree
,
194 uint32_t offset
, bool query
, bool bflag
,
199 * FF: when bflag is true, indicates that the Counter 1-4
200 * fields represent octet counts. Otherwise Counter 1-4 fields
201 * represent packet counts
203 const char *unit
= bflag
? "octets" : "packets";
208 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter1
, tvb
,
209 offset
, 8, ENC_BIG_ENDIAN
);
210 proto_item_append_text(ti
, " %s (A_Tx)", unit
);
213 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter2
, tvb
,
214 offset
, 8, ENC_BIG_ENDIAN
);
217 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter3
, tvb
,
218 offset
, 8, ENC_BIG_ENDIAN
);
221 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter4
, tvb
,
222 offset
, 8, ENC_BIG_ENDIAN
);
232 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter1
, tvb
,
233 offset
, 8, ENC_BIG_ENDIAN
);
234 proto_item_append_text(ti
, " %s (B_Tx)", unit
);
237 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter2
, tvb
,
238 offset
, 8, ENC_BIG_ENDIAN
);
241 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter3
, tvb
,
242 offset
, 8, ENC_BIG_ENDIAN
);
243 proto_item_append_text(ti
, " %s (A_Tx)", unit
);
246 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter4
, tvb
,
247 offset
, 8, ENC_BIG_ENDIAN
);
248 proto_item_append_text(ti
, " %s (B_Rx)", unit
);
258 mpls_pm_dissect_timestamp(tvbuff_t
*tvb
, proto_tree
*pm_tree
,
259 uint32_t offset
, uint8_t qtf
, uint8_t rtf
,
260 bool query
, uint8_t i
)
264 * FF: when a query is sent from A, Timestamp 1 is set to T1 and the
265 * other timestamp fields are set to 0. Moreover, it might be useful
266 * to decode Timestamp 2 (set to T2) as well because data can be captured
267 * somewhere at the responder box after the timestamp has been taken.
273 * FF: the actual formats of the timestamp fields written by A
274 * are indicated by the Querier Timestamp Format.
276 case MPLS_PM_TSF_NULL
:
277 proto_tree_add_item(pm_tree
,
278 hf_mpls_pm_timestamp1_q_null
, tvb
,
279 offset
, 8, ENC_BIG_ENDIAN
);
281 case MPLS_PM_TSF_SEQ
:
282 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_q_seq
, tvb
,
283 offset
, 8, ENC_BIG_ENDIAN
);
285 case MPLS_PM_TSF_NTP
:
286 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_q_ntp
, tvb
,
287 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
289 case MPLS_PM_TSF_PTP
:
290 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_q_ptp
, tvb
,
291 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
294 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_unk
, tvb
,
295 offset
, 8, ENC_BIG_ENDIAN
);
301 case MPLS_PM_TSF_NULL
:
302 proto_tree_add_item(pm_tree
,
303 hf_mpls_pm_timestamp2_q_null
, tvb
,
304 offset
, 8, ENC_BIG_ENDIAN
);
306 case MPLS_PM_TSF_SEQ
:
307 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_q_seq
, tvb
,
308 offset
, 8, ENC_BIG_ENDIAN
);
310 case MPLS_PM_TSF_NTP
:
311 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_q_ntp
, tvb
,
312 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
314 case MPLS_PM_TSF_PTP
:
315 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_q_ptp
, tvb
,
316 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
319 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_unk
, tvb
,
320 offset
, 8, ENC_BIG_ENDIAN
);
325 proto_tree_add_item(pm_tree
,
326 hf_mpls_pm_timestamp3_null
, tvb
,
327 offset
, 8, ENC_BIG_ENDIAN
);
330 proto_tree_add_item(pm_tree
,
331 hf_mpls_pm_timestamp4_null
, tvb
,
332 offset
, 8, ENC_BIG_ENDIAN
);
337 } /* end of switch (i) */
340 * FF: when B transmits the response, Timestamp 1 is set to T3,
341 * Timestamp 3 is set to T1 and Timestamp 4 is set to T2. Timestamp 2
342 * is set to 0. Moreover, it might be useful to decode Timestamp 2
343 * (set to T4) as well because data can be captured somewhere at the
344 * querier box after the timestamp has been taken.
350 * FF: the actual formats of the timestamp fields written by B
351 * are indicated by the Responder Timestamp Format.
353 case MPLS_PM_TSF_NULL
:
354 proto_tree_add_item(pm_tree
,
355 hf_mpls_pm_timestamp1_r_null
, tvb
,
356 offset
, 8, ENC_BIG_ENDIAN
);
358 case MPLS_PM_TSF_SEQ
:
359 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_r_seq
, tvb
,
360 offset
, 8, ENC_BIG_ENDIAN
);
362 case MPLS_PM_TSF_NTP
:
363 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_r_ntp
, tvb
,
364 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
366 case MPLS_PM_TSF_PTP
:
367 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_r_ptp
, tvb
,
368 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
371 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_unk
, tvb
,
372 offset
, 8, ENC_BIG_ENDIAN
);
378 case MPLS_PM_TSF_NULL
:
379 proto_tree_add_item(pm_tree
,
380 hf_mpls_pm_timestamp2_r_null
, tvb
,
381 offset
, 8, ENC_BIG_ENDIAN
);
383 case MPLS_PM_TSF_SEQ
:
384 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_r_seq
, tvb
,
385 offset
, 8, ENC_BIG_ENDIAN
);
387 case MPLS_PM_TSF_NTP
:
388 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_r_ntp
, tvb
,
389 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
391 case MPLS_PM_TSF_PTP
:
392 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_r_ptp
, tvb
,
393 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
396 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp2_unk
, tvb
,
397 offset
, 8, ENC_BIG_ENDIAN
);
403 case MPLS_PM_TSF_NULL
:
404 proto_tree_add_item(pm_tree
,
405 hf_mpls_pm_timestamp3_r_null
, tvb
,
406 offset
, 8, ENC_BIG_ENDIAN
);
408 case MPLS_PM_TSF_SEQ
:
409 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_r_seq
, tvb
,
410 offset
, 8, ENC_BIG_ENDIAN
);
412 case MPLS_PM_TSF_NTP
:
413 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_r_ntp
, tvb
,
414 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
416 case MPLS_PM_TSF_PTP
:
417 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_r_ptp
, tvb
,
418 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
421 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_unk
, tvb
,
422 offset
, 8, ENC_BIG_ENDIAN
);
428 case MPLS_PM_TSF_NULL
:
429 proto_tree_add_item(pm_tree
,
430 hf_mpls_pm_timestamp4_r_null
, tvb
,
431 offset
, 8, ENC_BIG_ENDIAN
);
433 case MPLS_PM_TSF_SEQ
:
434 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_r_seq
, tvb
,
435 offset
, 8, ENC_BIG_ENDIAN
);
437 case MPLS_PM_TSF_NTP
:
438 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_r_ntp
, tvb
,
439 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
441 case MPLS_PM_TSF_PTP
:
442 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_r_ptp
, tvb
,
443 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
446 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_unk
, tvb
,
447 offset
, 8, ENC_BIG_ENDIAN
);
454 } /* end of switch (i) */
459 mpls_pm_build_cinfo(tvbuff_t
*tvb
, packet_info
*pinfo
, const char *str_pmt
,
460 bool *query
, bool *response
,
461 bool *class_specific
,
462 uint32_t *sid
, uint8_t *code
)
464 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "MPLS PM (%s)", str_pmt
);
465 col_clear(pinfo
->cinfo
, COL_INFO
);
467 *response
= (tvb_get_uint8(tvb
, 0) & 0x08) ? true : false;
468 *class_specific
= (tvb_get_uint8(tvb
, 0) & 0x04) ? true : false;
469 *query
= !(*response
);
470 *code
= tvb_get_uint8(tvb
, 1);
472 if (!(*class_specific
)) {
474 * FF: when the T flag is set to 0 the DS field can be considered
475 * part of the Session Identifier.
477 *sid
= tvb_get_ntohl(tvb
, 8);
479 *sid
= tvb_get_ntohl(tvb
, 8) >> 6;
483 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
484 "Query, sid: %u", *sid
);
486 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
487 "Response, sid: %u, code: %s (%u)",
489 rval_to_str_const(*code
,
490 mpls_pm_response_ctrl_code_rvals
,
496 /* FF: the message formats for direct and inferred LM are identical */
498 dissect_mpls_pm_loss(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
501 proto_item
*ti
= NULL
;
503 proto_tree
*pm_tree_flags
;
504 proto_tree
*pm_tree_dflags
;
508 bool class_specific
= 0;
515 mpls_pm_build_cinfo(tvb
, pinfo
,
516 val_to_str_const(pmt
, pmt_vals
, ""),
517 &query
, &response
, &class_specific
, &sid
, &code
);
523 /* create display subtree for the protocol */
525 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dlm
, tvb
, 0, -1, ENC_NA
);
527 ti
= proto_tree_add_item(tree
, proto_mpls_pm_ilm
, tvb
, 0, -1, ENC_NA
);
530 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
532 /* add version to the subtree */
533 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
535 /* ctrl flags subtree */
537 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
,
538 offset
, 1, ENC_BIG_ENDIAN
);
539 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
540 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
542 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
544 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
549 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
550 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
552 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
553 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
557 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
558 offset
, 2, ENC_BIG_ENDIAN
);
561 /* data flags subtree */
562 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_dflags
, tvb
,
563 offset
, 1, ENC_BIG_ENDIAN
);
564 pm_tree_dflags
= proto_item_add_subtree(ti
, ett_mpls_pm_dflags
);
565 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_x
, tvb
,
567 bflag
= (tvb_get_uint8(tvb
, offset
) & 0x40) ? true : false;
568 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_b
, tvb
,
570 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_res
, tvb
,
573 otf
= tvb_get_uint8(tvb
, offset
) & 0x0F;
574 proto_tree_add_item(pm_tree
, hf_mpls_pm_otf
, tvb
,
575 offset
, 1, ENC_BIG_ENDIAN
);
578 /* skip 3 reserved bytes */
581 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
583 if (class_specific
) {
584 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
589 case MPLS_PM_TSF_NULL
:
590 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_null
, tvb
,
591 offset
, 8, ENC_BIG_ENDIAN
);
593 case MPLS_PM_TSF_SEQ
:
594 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_seq
, tvb
,
595 offset
, 8, ENC_BIG_ENDIAN
);
597 case MPLS_PM_TSF_NTP
:
598 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_ntp
, tvb
,
599 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
601 case MPLS_PM_TSF_PTP
:
602 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_ptp
, tvb
,
603 offset
, 8, ENC_TIME_SECS_NSECS
|ENC_BIG_ENDIAN
);
606 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_unk
, tvb
,
607 offset
, 8, ENC_BIG_ENDIAN
);
613 for (i
= 1; i
<= 4; i
++) {
614 mpls_pm_dissect_counter(tvb
, pm_tree
, offset
, query
, bflag
, i
);
620 dissect_mpls_pm_dlm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
622 /* the message formats for direct and inferred LM are identical */
623 dissect_mpls_pm_loss(tvb
, pinfo
, tree
, DLM
);
624 return tvb_captured_length(tvb
);
628 dissect_mpls_pm_ilm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
630 /* the message formats for direct and inferred LM are identical */
631 dissect_mpls_pm_loss(tvb
, pinfo
, tree
, ILM
);
632 return tvb_captured_length(tvb
);
636 dissect_mpls_pm_delay(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
640 proto_tree
*pm_tree_flags
;
644 bool class_specific
= 0;
651 mpls_pm_build_cinfo(tvb
, pinfo
,
653 &query
, &response
, &class_specific
, &sid
, &code
);
655 /* create display subtree for the protocol */
656 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dm
, tvb
, 0, -1, ENC_NA
);
657 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
659 /* add version to the subtree */
660 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
662 /* ctrl flags subtree */
663 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
664 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
665 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
667 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
669 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
674 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
675 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
677 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
678 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
682 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
683 offset
, 2, ENC_BIG_ENDIAN
);
687 qtf
= (tvb_get_uint8(tvb
, offset
) & 0xF0) >> 4;
688 proto_tree_add_item(pm_tree
, hf_mpls_pm_qtf
, tvb
,
689 offset
, 1, ENC_BIG_ENDIAN
);
691 rtf
= tvb_get_uint8(tvb
, offset
) & 0x0F;
692 proto_tree_add_item(pm_tree
, hf_mpls_pm_rtf
, tvb
,
693 offset
, 1, ENC_BIG_ENDIAN
);
697 proto_tree_add_item(pm_tree
, hf_mpls_pm_rptf
, tvb
,
698 offset
, 1, ENC_BIG_ENDIAN
);
700 /* skip 20 reserved bits */
703 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
705 if (class_specific
) {
706 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
710 /* timestamps 1..4 */
711 for (i
= 1; i
<= 4; i
++) {
712 mpls_pm_dissect_timestamp(tvb
, pm_tree
, offset
, qtf
, rtf
, query
, i
);
715 return tvb_captured_length(tvb
);
719 dissect_mpls_pm_combined(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
722 proto_item
*ti
= NULL
;
724 proto_tree
*pm_tree_flags
;
725 proto_tree
*pm_tree_dflags
;
729 bool class_specific
= 0;
737 mpls_pm_build_cinfo(tvb
, pinfo
,
738 val_to_str_const(pmt
, pmt_vals
, ""),
739 &query
, &response
, &class_specific
, &sid
, &code
);
745 /* create display subtree for the protocol */
747 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dlm_dm
,
750 ti
= proto_tree_add_item(tree
, proto_mpls_pm_ilm_dm
,
754 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
756 /* add version to the subtree */
757 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
759 /* ctrl flags subtree */
760 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
761 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
762 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
764 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
766 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
771 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
772 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
774 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
775 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
779 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
780 offset
, 2, ENC_BIG_ENDIAN
);
783 /* data flags subtree */
784 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_dflags
, tvb
,
785 offset
, 1, ENC_BIG_ENDIAN
);
786 pm_tree_dflags
= proto_item_add_subtree(ti
, ett_mpls_pm_dflags
);
787 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_x
, tvb
,
789 bflag
= (tvb_get_uint8(tvb
, offset
) & 0x40) ? true : false;
790 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_b
, tvb
,
792 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_res
, tvb
,
796 * FF: the roles of the OTF and Origin Timestamp fields for LM are
797 * here played by the QTF and Timestamp 1 fields, respectively.
799 qtf
= tvb_get_uint8(tvb
, offset
) & 0x0F;
800 proto_tree_add_item(pm_tree
, hf_mpls_pm_qtf_combined
, tvb
,
801 offset
, 1, ENC_BIG_ENDIAN
);
805 rtf
= tvb_get_uint8(tvb
, offset
) & 0xF0 >> 4;
806 proto_tree_add_item(pm_tree
, hf_mpls_pm_rtf_combined
, tvb
,
807 offset
, 1, ENC_BIG_ENDIAN
);
809 proto_tree_add_item(pm_tree
, hf_mpls_pm_rptf_combined
, tvb
,
810 offset
, 1, ENC_BIG_ENDIAN
);
813 /* skip 2 reserved bytes */
816 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
818 if (class_specific
) {
819 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_BIG_ENDIAN
);
823 /* timestamps 1..4 */
824 for (i
= 1; i
<= 4; i
++) {
825 mpls_pm_dissect_timestamp(tvb
, pm_tree
, offset
, qtf
, rtf
, query
, i
);
830 for (i
= 1; i
<= 4; i
++) {
831 mpls_pm_dissect_counter(tvb
, pm_tree
, offset
, query
, bflag
, i
);
837 dissect_mpls_pm_dlm_dm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
839 /* the formats of the DLM+DM and ILM+DM messages are also identical */
840 dissect_mpls_pm_combined(tvb
, pinfo
, tree
, DLMDM
);
841 return tvb_captured_length(tvb
);
845 dissect_mpls_pm_ilm_dm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
847 /* the formats of the DLM+DM and ILM+DM messages are also identical */
848 dissect_mpls_pm_combined(tvb
, pinfo
, tree
, ILMDM
);
849 return tvb_captured_length(tvb
);
853 proto_register_mpls_pm(void)
855 static hf_register_info hf
[] = {
859 "Version", "mpls_pm.version", FT_UINT8
, BASE_DEC
, NULL
,
866 "Flags", "mpls_pm.flags", FT_UINT8
,
867 BASE_HEX
, NULL
, MPLS_PM_FLAGS_MASK
, NULL
, HFILL
873 "Response indicator (R)", "mpls_pm.flags.r",
874 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_R
,
881 "Traffic-class-specific measurement indicator (T)",
883 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_T
,
888 &hf_mpls_pm_flags_res
,
892 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_RES
,
897 &hf_mpls_pm_query_ctrl_code
,
901 FT_UINT8
, BASE_RANGE_STRING
| BASE_HEX
,
902 RVALS(mpls_pm_query_ctrl_code_rvals
), 0x0,
903 "Code identifying the query type", HFILL
907 &hf_mpls_pm_response_ctrl_code
,
911 FT_UINT8
, BASE_RANGE_STRING
| BASE_HEX
,
912 RVALS(mpls_pm_response_ctrl_code_rvals
), 0x0,
913 "Code identifying the response type", HFILL
921 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
922 "Total length of this message in bytes", HFILL
928 "DFlags", "mpls_pm.dflags", FT_UINT8
,
929 BASE_HEX
, NULL
, MPLS_PM_DFLAGS_MASK
,
934 &hf_mpls_pm_dflags_x
,
936 "Extended counter format indicator (X)", "mpls_pm.dflags.x",
937 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MPLS_PM_DFLAGS_X
,
942 &hf_mpls_pm_dflags_b
,
944 "Octet/Byte count indicator (B)", "mpls_pm.dflags.b",
945 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), MPLS_PM_DFLAGS_B
,
950 &hf_mpls_pm_dflags_res
,
953 "mpls_pm.dflags.res",
954 FT_BOOLEAN
, 8, NULL
, MPLS_PM_DFLAGS_RES
,
961 "Origin Timestamp Format (OTF)",
963 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
964 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
969 &hf_mpls_pm_session_id
,
971 "Session Identifier",
972 "mpls_pm.session.id",
981 "Differentiated Services Codepoint",
983 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
,
984 &dscp_vals_ext
, 0x3F,
989 &hf_mpls_pm_origin_timestamp_null
,
992 "mpls_pm.origin.timestamp.null",
999 &hf_mpls_pm_origin_timestamp_seq
,
1002 "mpls_pm.origin.timestamp.seq",
1003 FT_UINT64
, BASE_DEC
,
1009 &hf_mpls_pm_origin_timestamp_ntp
,
1012 "mpls_pm.origin.timestamp.ntp",
1013 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1019 &hf_mpls_pm_origin_timestamp_ptp
,
1022 "mpls_pm.origin.timestamp.ptp",
1023 FT_RELATIVE_TIME
, BASE_NONE
,
1029 &hf_mpls_pm_origin_timestamp_unk
,
1031 "Origin Timestamp (Unknown Type)",
1032 "mpls_pm.origin.timestamp.unk",
1033 FT_UINT64
, BASE_DEC
,
1039 &hf_mpls_pm_counter1
,
1043 FT_UINT64
, BASE_DEC
,
1049 &hf_mpls_pm_counter2
,
1053 FT_UINT64
, BASE_DEC
,
1059 &hf_mpls_pm_counter3
,
1063 FT_UINT64
, BASE_DEC
,
1069 &hf_mpls_pm_counter4
,
1073 FT_UINT64
, BASE_DEC
,
1081 "Querier timestamp format (QTF)",
1083 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1084 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1089 &hf_mpls_pm_qtf_combined
,
1091 "Querier timestamp format (QTF)",
1093 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1094 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1101 "Responder timestamp format (RTF)",
1103 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1104 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1109 &hf_mpls_pm_rtf_combined
,
1111 "Responder timestamp format (RTF)",
1113 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1114 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1121 "Responder's preferred timestamp format (RPTF)",
1123 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1124 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1129 &hf_mpls_pm_rptf_combined
,
1131 "Responder's preferred timestamp format (RPTF)",
1133 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1134 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1139 &hf_mpls_pm_timestamp1_q_null
,
1142 "mpls_pm.timestamp1.null",
1143 FT_UINT64
, BASE_DEC
,
1149 &hf_mpls_pm_timestamp1_r_null
,
1152 "mpls_pm.timestamp1.null",
1153 FT_UINT64
, BASE_DEC
,
1159 &hf_mpls_pm_timestamp1_q_seq
,
1162 "mpls_pm.timestamp1.seq",
1163 FT_UINT64
, BASE_DEC
,
1169 &hf_mpls_pm_timestamp1_r_seq
,
1172 "mpls_pm.timestamp1.seq",
1173 FT_UINT64
, BASE_DEC
,
1179 &hf_mpls_pm_timestamp1_q_ntp
,
1182 "mpls_pm.timestamp1.ntp",
1183 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1189 &hf_mpls_pm_timestamp1_r_ntp
,
1192 "mpls_pm.timestamp1.ntp",
1193 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1199 &hf_mpls_pm_timestamp1_q_ptp
,
1202 "mpls_pm.timestamp1.ptp",
1203 FT_RELATIVE_TIME
, BASE_NONE
,
1209 &hf_mpls_pm_timestamp1_r_ptp
,
1212 "mpls_pm.timestamp1.ptp",
1213 FT_RELATIVE_TIME
, BASE_NONE
,
1219 &hf_mpls_pm_timestamp1_unk
,
1221 "Timestamp 1 (Unknown Type)",
1222 "mpls_pm.timestamp1.unk",
1223 FT_UINT64
, BASE_DEC
,
1229 &hf_mpls_pm_timestamp2_q_null
,
1232 "mpls_pm.timestamp2.null",
1233 FT_UINT64
, BASE_DEC
,
1239 &hf_mpls_pm_timestamp2_r_null
,
1242 "mpls_pm.timestamp2.null",
1243 FT_UINT64
, BASE_DEC
,
1249 &hf_mpls_pm_timestamp2_q_seq
,
1252 "mpls_pm.timestamp2.seq",
1253 FT_UINT64
, BASE_DEC
,
1259 &hf_mpls_pm_timestamp2_r_seq
,
1262 "mpls_pm.timestamp2.seq",
1263 FT_UINT64
, BASE_DEC
,
1269 &hf_mpls_pm_timestamp2_q_ntp
,
1272 "mpls_pm.timestamp2.ntp",
1273 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1279 &hf_mpls_pm_timestamp2_r_ntp
,
1282 "mpls_pm.timestamp2.ntp",
1283 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1289 &hf_mpls_pm_timestamp2_q_ptp
,
1292 "mpls_pm.timestamp2.ptp",
1293 FT_RELATIVE_TIME
, BASE_NONE
,
1299 &hf_mpls_pm_timestamp2_r_ptp
,
1302 "mpls_pm.timestamp2.ptp",
1303 FT_RELATIVE_TIME
, BASE_NONE
,
1309 &hf_mpls_pm_timestamp2_unk
,
1311 "Timestamp 2 (Unknown Type)",
1312 "mpls_pm.timestamp2.unk",
1313 FT_UINT64
, BASE_DEC
,
1319 &hf_mpls_pm_timestamp3_null
,
1322 "mpls_pm.timestamp3.null",
1323 FT_UINT64
, BASE_DEC
,
1329 &hf_mpls_pm_timestamp3_r_null
,
1332 "mpls_pm.timestamp3.null",
1333 FT_UINT64
, BASE_DEC
,
1339 &hf_mpls_pm_timestamp3_r_seq
,
1342 "mpls_pm.timestamp3.seq",
1343 FT_UINT64
, BASE_DEC
,
1349 &hf_mpls_pm_timestamp3_r_ntp
,
1352 "mpls_pm.timestamp3.ntp",
1353 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1359 &hf_mpls_pm_timestamp3_r_ptp
,
1362 "mpls_pm.timestamp3_ptp",
1363 FT_RELATIVE_TIME
, BASE_NONE
,
1369 &hf_mpls_pm_timestamp3_unk
,
1371 "Timestamp 3 (Unknown Type)",
1372 "mpls_pm.timestamp3.unk",
1373 FT_UINT64
, BASE_DEC
,
1379 &hf_mpls_pm_timestamp4_null
,
1382 "mpls_pm.timestamp4.null",
1383 FT_UINT64
, BASE_DEC
,
1389 &hf_mpls_pm_timestamp4_r_null
,
1392 "mpls_pm.timestamp4.null",
1393 FT_UINT64
, BASE_DEC
,
1399 &hf_mpls_pm_timestamp4_r_seq
,
1402 "mpls_pm.timestamp4.seq",
1403 FT_UINT64
, BASE_DEC
,
1409 &hf_mpls_pm_timestamp4_r_ntp
,
1412 "mpls_pm.timestamp4.ntp",
1413 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
,
1419 &hf_mpls_pm_timestamp4_r_ptp
,
1422 "mpls_pm.timestamp4.ptp",
1423 FT_RELATIVE_TIME
, BASE_NONE
,
1429 &hf_mpls_pm_timestamp4_unk
,
1431 "Timestamp 4 (Unknown Type)",
1432 "mpls_pm.timestamp4.unk",
1433 FT_UINT64
, BASE_DEC
,
1440 static int *ett
[] = {
1447 proto_register_protocol("MPLS Direct Loss Measurement (DLM)",
1448 "MPLS Direct Loss Measurement (DLM)",
1452 proto_register_protocol("MPLS Inferred Loss Measurement (ILM)",
1453 "MPLS Inferred Loss Measurement (ILM)",
1457 proto_register_protocol("MPLS Delay Measurement (DM)",
1458 "MPLS Delay Measurement (DM)",
1461 proto_mpls_pm_dlm_dm
=
1462 proto_register_protocol("MPLS Direct Loss and Delay "
1463 "Measurement (DLM+DM)",
1464 "MPLS Direct Loss and Delay "
1465 "Measurement (DLM+DM)",
1468 proto_mpls_pm_ilm_dm
=
1469 proto_register_protocol("MPLS Inferred Loss and Delay "
1470 "Measurement (ILM+DM)",
1471 "MPLS Inferred Loss and Delay "
1472 "Measurement (ILM+DM)",
1475 proto_register_field_array(proto_mpls_pm_dlm
, hf
, array_length(hf
));
1476 proto_register_subtree_array(ett
, array_length(ett
));
1480 proto_reg_handoff_mpls_pm(void)
1482 dissector_handle_t mpls_pm_dlm_handle
, mpls_pm_ilm_handle
, mpls_pm_dm_handle
,
1483 mpls_pm_dlm_dm_handle
, mpls_pm_ilm_dm_handle
;
1485 mpls_pm_dlm_handle
= create_dissector_handle( dissect_mpls_pm_dlm
, proto_mpls_pm_dlm
);
1486 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_DLM
, mpls_pm_dlm_handle
);
1487 mpls_pm_ilm_handle
= create_dissector_handle( dissect_mpls_pm_ilm
, proto_mpls_pm_ilm
);
1488 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_ILM
, mpls_pm_ilm_handle
);
1489 mpls_pm_dm_handle
= create_dissector_handle( dissect_mpls_pm_delay
, proto_mpls_pm_dm
);
1490 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_DM
, mpls_pm_dm_handle
);
1491 mpls_pm_dlm_dm_handle
= create_dissector_handle( dissect_mpls_pm_dlm_dm
, proto_mpls_pm_dlm_dm
);
1492 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_DLM_DM
, mpls_pm_dlm_dm_handle
);
1493 mpls_pm_ilm_dm_handle
= create_dissector_handle( dissect_mpls_pm_ilm_dm
, proto_mpls_pm_ilm_dm
);
1494 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_ILM_DM
, mpls_pm_ilm_dm_handle
);
1498 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1503 * indent-tabs-mode: nil
1506 * vi: set shiftwidth=4 tabstop=8 expandtab:
1507 * :indentSize=4:tabSize=8:noTabs=true: