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>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <epan/packet.h>
36 #include <packet-ip.h>
38 /* message control flags */
39 #define MPLS_PM_FLAGS_R 0x08
40 #define MPLS_PM_FLAGS_T 0x04
41 #define MPLS_PM_FLAGS_RES 0x03
42 #define MPLS_PM_FLAGS_MASK 0x0F
44 /* data format flags */
45 #define MPLS_PM_DFLAGS_X 0x80
46 #define MPLS_PM_DFLAGS_B 0x40
47 #define MPLS_PM_DFLAGS_RES 0x30
48 #define MPLS_PM_DFLAGS_MASK 0xF0
50 static gint proto_mpls_pm_dlm
= -1;
51 static gint proto_mpls_pm_ilm
= -1;
52 static gint proto_mpls_pm_dm
= -1;
53 static gint proto_mpls_pm_dlm_dm
= -1;
54 static gint proto_mpls_pm_ilm_dm
= -1;
56 static gint ett_mpls_pm
= -1;
57 static gint ett_mpls_pm_flags
= -1;
58 static gint ett_mpls_pm_dflags
= -1;
60 static int hf_mpls_pm_version
= -1;
61 static int hf_mpls_pm_flags
= -1;
62 static int hf_mpls_pm_flags_r
= -1;
63 static int hf_mpls_pm_flags_t
= -1;
64 static int hf_mpls_pm_flags_res
= -1;
65 static int hf_mpls_pm_query_ctrl_code
= -1;
66 static int hf_mpls_pm_response_ctrl_code
= -1;
67 static int hf_mpls_pm_length
= -1;
68 static int hf_mpls_pm_dflags
= -1;
69 static int hf_mpls_pm_dflags_x
= -1;
70 static int hf_mpls_pm_dflags_b
= -1;
71 static int hf_mpls_pm_dflags_res
= -1;
72 static int hf_mpls_pm_otf
= -1;
73 static int hf_mpls_pm_session_id
= -1;
74 static int hf_mpls_pm_ds
= -1;
75 static int hf_mpls_pm_origin_timestamp_null
= -1;
76 static int hf_mpls_pm_origin_timestamp_seq
= -1;
77 static int hf_mpls_pm_origin_timestamp_ntp
= -1;
78 static int hf_mpls_pm_origin_timestamp_ptp
= -1;
79 static int hf_mpls_pm_origin_timestamp_unk
= -1;
80 static int hf_mpls_pm_counter1
= -1;
81 static int hf_mpls_pm_counter2
= -1;
82 static int hf_mpls_pm_counter3
= -1;
83 static int hf_mpls_pm_counter4
= -1;
84 static int hf_mpls_pm_qtf
= -1;
85 static int hf_mpls_pm_qtf_combined
= -1;
86 static int hf_mpls_pm_rtf
= -1;
87 static int hf_mpls_pm_rtf_combined
= -1;
88 static int hf_mpls_pm_rptf
= -1;
89 static int hf_mpls_pm_rptf_combined
= -1;
90 static int hf_mpls_pm_timestamp1_q_null
= -1;
91 static int hf_mpls_pm_timestamp1_r_null
= -1;
92 static int hf_mpls_pm_timestamp1_q_seq
= -1;
93 static int hf_mpls_pm_timestamp1_r_seq
= -1;
94 static int hf_mpls_pm_timestamp1_q_ntp
= -1;
95 static int hf_mpls_pm_timestamp1_r_ntp
= -1;
96 static int hf_mpls_pm_timestamp1_q_ptp
= -1;
97 static int hf_mpls_pm_timestamp1_r_ptp
= -1;
98 static int hf_mpls_pm_timestamp1_unk
= -1;
99 static int hf_mpls_pm_timestamp2_null
= -1;
100 static int hf_mpls_pm_timestamp3_null
= -1;
101 static int hf_mpls_pm_timestamp3_r_null
= -1;
102 static int hf_mpls_pm_timestamp3_r_seq
= -1;
103 static int hf_mpls_pm_timestamp3_r_ntp
= -1;
104 static int hf_mpls_pm_timestamp3_r_ptp
= -1;
105 static int hf_mpls_pm_timestamp3_unk
= -1;
106 static int hf_mpls_pm_timestamp4_null
= -1;
107 static int hf_mpls_pm_timestamp4_r_null
= -1;
108 static int hf_mpls_pm_timestamp4_r_seq
= -1;
109 static int hf_mpls_pm_timestamp4_r_ntp
= -1;
110 static int hf_mpls_pm_timestamp4_r_ptp
= -1;
111 static int hf_mpls_pm_timestamp4_unk
= -1;
113 static dissector_handle_t mpls_pm_dlm_handle
;
114 static dissector_handle_t mpls_pm_ilm_handle
;
115 static dissector_handle_t mpls_pm_dm_handle
;
116 static dissector_handle_t mpls_pm_dlm_dm_handle
;
117 static dissector_handle_t mpls_pm_ilm_dm_handle
;
120 * FF: please keep this list in sync with
121 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
122 * Registry Name: 'Loss/Delay Measurement Control Code: Query Codes'
124 const range_string mpls_pm_query_ctrl_code_rvals
[] = {
125 { 0x00, 0x00, "In-band Response Requested" },
126 { 0x01, 0x01, "Out-of-band Response Requested" },
127 { 0x02, 0x02, "No Response Requested" },
128 { 0x03, 0xFF, "Unassigned" },
133 * FF: please keep this list in sync with
134 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
135 * Registry Name: 'Loss/Delay Measurement Control Code: Response Codes'
137 const range_string mpls_pm_response_ctrl_code_rvals
[] = {
138 { 0x00, 0x00, "Reserved" },
139 { 0x01, 0x01, "Success" },
140 { 0x02, 0x02, "Data Format Invalid" },
141 { 0x03, 0x03, "Initialization in Progress" },
142 { 0x04, 0x04, "Data Reset Occurred" },
143 { 0x05, 0x05, "Resource Temporarily Unavailable" },
144 { 0x06, 0x0F, "Unassigned" },
145 { 0x10, 0x10, "Unspecified Error" },
146 { 0x11, 0x11, "Unsupported Version" },
147 { 0x12, 0x12, "Unsupported Control Code" },
148 { 0x13, 0x13, "Unsupported Data Format" },
149 { 0x14, 0x14, "Authentication Failure" },
150 { 0x15, 0x15, "Invalid Destination Node Identifier" },
151 { 0x16, 0x16, "Connection Mismatch" },
152 { 0x17, 0x17, "Unsupported Mandatory TLV Object" },
153 { 0x18, 0x18, "Unsupported Query Interval" },
154 { 0x19, 0x19, "Administrative Block" },
155 { 0x1A, 0x1A, "Resource Unavailable" },
156 { 0x1B, 0x1B, "Resource Released" },
157 { 0x1C, 0x1C, "Invalid Message" },
158 { 0x1D, 0x1D, "Protocol Error" },
159 { 0x1E, 0xFF, "Unassigned" },
169 static const value_string pmt_vals
[] = {
179 * FF: please keep this list in sync with
180 * http://www.iana.org/assignments/mpls-lsp-ping-parameters
181 * Registry Name: 'Loss/Delay Measurement Control Code: Response Codes'
183 #define MPLS_PM_TSF_NULL 0
184 #define MPLS_PM_TSF_SEQ 1
185 #define MPLS_PM_TSF_NTP 2
186 #define MPLS_PM_TSF_PTP 3
187 const range_string mpls_pm_time_stamp_format_rvals
[] = {
188 { MPLS_PM_TSF_NULL
, MPLS_PM_TSF_NULL
,
190 { MPLS_PM_TSF_SEQ
, MPLS_PM_TSF_SEQ
,
192 { MPLS_PM_TSF_NTP
, MPLS_PM_TSF_NTP
,
193 "Network Time Protocol version 4 64-bit Timestamp" },
194 { MPLS_PM_TSF_PTP
, MPLS_PM_TSF_PTP
,
195 "Truncated IEEE 1588v2 PTP Timestamp" },
196 { 4, 15, "Unassigned" },
201 mpls_pm_dissect_counter(tvbuff_t
*tvb
, proto_tree
*pm_tree
,
202 guint32 offset
, gboolean query
, gboolean bflag
,
207 * FF: when bflag is true, indicates that the Counter 1-4
208 * fields represent octet counts. Otherwise Counter 1-4 fields
209 * represent packet counts
211 const gchar
*unit
= bflag
? "octets" : "packets";
216 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter1
, tvb
,
217 offset
, 8, ENC_BIG_ENDIAN
);
218 proto_item_append_text(ti
, " %s (A_Tx)", unit
);
221 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter2
, tvb
,
222 offset
, 8, ENC_BIG_ENDIAN
);
225 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter3
, tvb
,
226 offset
, 8, ENC_BIG_ENDIAN
);
229 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter4
, tvb
,
230 offset
, 8, ENC_BIG_ENDIAN
);
240 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter1
, tvb
,
241 offset
, 8, ENC_BIG_ENDIAN
);
242 proto_item_append_text(ti
, " %s (B_Tx)", unit
);
245 proto_tree_add_item(pm_tree
, hf_mpls_pm_counter2
, tvb
,
246 offset
, 8, ENC_BIG_ENDIAN
);
249 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter3
, tvb
,
250 offset
, 8, ENC_BIG_ENDIAN
);
251 proto_item_append_text(ti
, " %s (A_Tx)", unit
);
254 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_counter4
, tvb
,
255 offset
, 8, ENC_BIG_ENDIAN
);
256 proto_item_append_text(ti
, " %s (B_Rx)", unit
);
266 mpls_pm_dissect_timestamp(tvbuff_t
*tvb
, proto_tree
*pm_tree
,
267 guint32 offset
, guint8 qtf
, guint8 rtf
,
268 gboolean query
, guint8 i
)
272 * FF: when a query is sent from A, Timestamp 1 is set to T1 and the
273 * other timestamp fields are set to 0.
279 * FF: the actual formats of the timestamp fields written by A
280 * are indicated by the Querier Timestamp Format.
282 case MPLS_PM_TSF_NULL
:
283 proto_tree_add_item(pm_tree
,
284 hf_mpls_pm_timestamp1_q_null
, tvb
,
285 offset
, 8, ENC_BIG_ENDIAN
);
287 case MPLS_PM_TSF_SEQ
:
288 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_q_seq
, tvb
,
289 offset
, 8, ENC_BIG_ENDIAN
);
291 case MPLS_PM_TSF_NTP
:
292 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_q_ntp
, tvb
,
293 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
295 case MPLS_PM_TSF_PTP
:
298 ts
.secs
= tvb_get_ntohl(tvb
, offset
);
299 ts
.nsecs
= tvb_get_ntohl(tvb
, offset
+ 4);
300 proto_tree_add_time(pm_tree
, hf_mpls_pm_timestamp1_q_ptp
,
301 tvb
, offset
, 8, &ts
);
305 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_unk
, tvb
,
306 offset
, 8, ENC_BIG_ENDIAN
);
311 proto_tree_add_item(pm_tree
,
312 hf_mpls_pm_timestamp2_null
, tvb
,
313 offset
, 8, ENC_BIG_ENDIAN
);
316 proto_tree_add_item(pm_tree
,
317 hf_mpls_pm_timestamp3_null
, tvb
,
318 offset
, 8, ENC_BIG_ENDIAN
);
321 proto_tree_add_item(pm_tree
,
322 hf_mpls_pm_timestamp4_null
, tvb
,
323 offset
, 8, ENC_BIG_ENDIAN
);
328 } /* end of switch (i) */
331 * FF: when B transmits the response, Timestamp 1 is set to T3,
332 * Timestamp 3 is set to T1 and Timestamp 4 is set to T2. Timestamp 2
339 * FF: the actual formats of the timestamp fields written by B
340 * are indicated by the Responder Timestamp Format.
342 case MPLS_PM_TSF_NULL
:
343 proto_tree_add_item(pm_tree
,
344 hf_mpls_pm_timestamp1_r_null
, tvb
,
345 offset
, 8, ENC_BIG_ENDIAN
);
347 case MPLS_PM_TSF_SEQ
:
348 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_r_seq
, tvb
,
349 offset
, 8, ENC_BIG_ENDIAN
);
351 case MPLS_PM_TSF_NTP
:
352 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_r_ntp
, tvb
,
353 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
355 case MPLS_PM_TSF_PTP
:
358 ts
.secs
= tvb_get_ntohl(tvb
, offset
);
359 ts
.nsecs
= tvb_get_ntohl(tvb
, offset
+ 4);
360 proto_tree_add_time(pm_tree
, hf_mpls_pm_timestamp1_r_ptp
,
361 tvb
, offset
, 8, &ts
);
365 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp1_unk
, tvb
,
366 offset
, 8, ENC_BIG_ENDIAN
);
371 proto_tree_add_item(pm_tree
,
372 hf_mpls_pm_timestamp2_null
, tvb
,
373 offset
, 8, ENC_BIG_ENDIAN
);
377 case MPLS_PM_TSF_NULL
:
378 proto_tree_add_item(pm_tree
,
379 hf_mpls_pm_timestamp3_r_null
, tvb
,
380 offset
, 8, ENC_BIG_ENDIAN
);
382 case MPLS_PM_TSF_SEQ
:
383 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_r_seq
, tvb
,
384 offset
, 8, ENC_BIG_ENDIAN
);
386 case MPLS_PM_TSF_NTP
:
387 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_r_ntp
, tvb
,
388 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
390 case MPLS_PM_TSF_PTP
:
393 ts
.secs
= tvb_get_ntohl(tvb
, offset
);
394 ts
.nsecs
= tvb_get_ntohl(tvb
, offset
+ 4);
395 proto_tree_add_time(pm_tree
, hf_mpls_pm_timestamp3_r_ptp
,
396 tvb
, offset
, 8, &ts
);
400 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp3_unk
, tvb
,
401 offset
, 8, ENC_BIG_ENDIAN
);
407 case MPLS_PM_TSF_NULL
:
408 proto_tree_add_item(pm_tree
,
409 hf_mpls_pm_timestamp4_r_null
, tvb
,
410 offset
, 8, ENC_BIG_ENDIAN
);
412 case MPLS_PM_TSF_SEQ
:
413 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_r_seq
, tvb
,
414 offset
, 8, ENC_BIG_ENDIAN
);
416 case MPLS_PM_TSF_NTP
:
417 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_r_ntp
, tvb
,
418 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
420 case MPLS_PM_TSF_PTP
:
423 ts
.secs
= tvb_get_ntohl(tvb
, offset
);
424 ts
.nsecs
= tvb_get_ntohl(tvb
, offset
+ 4);
425 proto_tree_add_time(pm_tree
, hf_mpls_pm_timestamp4_r_ptp
,
426 tvb
, offset
, 8, &ts
);
430 proto_tree_add_item(pm_tree
, hf_mpls_pm_timestamp4_unk
, tvb
,
431 offset
, 8, ENC_BIG_ENDIAN
);
438 } /* end of switch (i) */
443 mpls_pm_build_cinfo(tvbuff_t
*tvb
, packet_info
*pinfo
, const char *str_pmt
,
444 gboolean
*query
, gboolean
*response
,
445 gboolean
*class_specific
,
446 guint32
*sid
, guint8
*code
)
448 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
, "MPLS PM (%s)", str_pmt
);
449 col_clear(pinfo
->cinfo
, COL_INFO
);
451 *response
= (tvb_get_guint8(tvb
, 0) & 0x08) ? TRUE
: FALSE
;
452 *class_specific
= (tvb_get_guint8(tvb
, 0) & 0x04) ? TRUE
: FALSE
;
453 *query
= !(*response
);
454 *code
= tvb_get_guint8(tvb
, 1);
456 if (!(*class_specific
)) {
458 * FF: when the T flag is set to 0 the DS field can be considered
459 * part of the Session Identifier.
461 *sid
= tvb_get_ntohl(tvb
, 8);
463 *sid
= tvb_get_ntohl(tvb
, 8) >> 6;
467 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
468 "Query, sid: %u", *sid
);
470 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
471 "Response, sid: %u, code: %s (%u)",
474 mpls_pm_response_ctrl_code_rvals
,
480 /* FF: the message formats for direct and inferred LM are identical */
482 dissect_mpls_pm_loss(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
485 proto_item
*ti
= NULL
;
487 proto_tree
*pm_tree_flags
;
488 proto_tree
*pm_tree_dflags
;
491 gboolean response
= 0;
492 gboolean class_specific
= 0;
499 mpls_pm_build_cinfo(tvb
, pinfo
,
500 val_to_str_const(pmt
, pmt_vals
, ""),
501 &query
, &response
, &class_specific
, &sid
, &code
);
507 /* create display subtree for the protocol */
509 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dlm
, tvb
, 0, -1, ENC_NA
);
511 ti
= proto_tree_add_item(tree
, proto_mpls_pm_ilm
, tvb
, 0, -1, ENC_NA
);
514 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
516 /* add version to the subtree */
517 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_NA
);
519 /* ctrl flags subtree */
521 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
,
523 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
524 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
526 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
528 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
533 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
534 tvb
, offset
, 1, ENC_NA
);
536 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
537 tvb
, offset
, 1, ENC_NA
);
541 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
542 offset
, 2, ENC_BIG_ENDIAN
);
545 /* data flags subtree */
546 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_dflags
, tvb
,
548 pm_tree_dflags
= proto_item_add_subtree(ti
, ett_mpls_pm_dflags
);
549 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_x
, tvb
,
551 bflag
= (tvb_get_guint8(tvb
, offset
) & 0x40) ? TRUE
: FALSE
;
552 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_b
, tvb
,
554 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_res
, tvb
,
557 otf
= tvb_get_guint8(tvb
, offset
) & 0x0F;
558 proto_tree_add_item(pm_tree
, hf_mpls_pm_otf
, tvb
,
559 offset
, 1, ENC_BIG_ENDIAN
);
562 /* skip 3 reserved bytes */
565 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
567 if (class_specific
) {
568 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_NA
);
573 case MPLS_PM_TSF_NULL
:
574 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_null
, tvb
,
575 offset
, 8, ENC_BIG_ENDIAN
);
577 case MPLS_PM_TSF_SEQ
:
578 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_seq
, tvb
,
579 offset
, 8, ENC_BIG_ENDIAN
);
581 case MPLS_PM_TSF_NTP
:
582 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_ntp
, tvb
,
583 offset
, 8, ENC_TIME_NTP
|ENC_BIG_ENDIAN
);
585 case MPLS_PM_TSF_PTP
:
588 ts
.secs
= tvb_get_ntohl(tvb
, offset
);
589 ts
.nsecs
= tvb_get_ntohl(tvb
, offset
+ 4);
590 proto_tree_add_time(pm_tree
, hf_mpls_pm_origin_timestamp_ptp
, tvb
,
595 proto_tree_add_item(pm_tree
, hf_mpls_pm_origin_timestamp_unk
, tvb
,
596 offset
, 8, ENC_BIG_ENDIAN
);
602 for (i
= 1; i
<= 4; i
++) {
603 mpls_pm_dissect_counter(tvb
, pm_tree
, offset
, query
, bflag
, i
);
609 dissect_mpls_pm_dlm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
611 /* the message formats for direct and inferred LM are identical */
612 dissect_mpls_pm_loss(tvb
, pinfo
, tree
, DLM
);
616 dissect_mpls_pm_ilm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
618 /* the message formats for direct and inferred LM are identical */
619 dissect_mpls_pm_loss(tvb
, pinfo
, tree
, ILM
);
623 dissect_mpls_pm_delay(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
627 proto_tree
*pm_tree_flags
;
630 gboolean response
= 0;
631 gboolean class_specific
= 0;
638 mpls_pm_build_cinfo(tvb
, pinfo
,
640 &query
, &response
, &class_specific
, &sid
, &code
);
646 /* create display subtree for the protocol */
647 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dm
, tvb
, 0, -1, ENC_NA
);
648 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
650 /* add version to the subtree */
651 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_NA
);
653 /* ctrl flags subtree */
654 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
, offset
, 1, ENC_NA
);
655 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
656 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
658 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
660 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
665 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
666 tvb
, offset
, 1, ENC_NA
);
668 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
669 tvb
, offset
, 1, ENC_NA
);
673 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
674 offset
, 2, ENC_BIG_ENDIAN
);
678 qtf
= (tvb_get_guint8(tvb
, offset
) & 0xF0) >> 4;
679 proto_tree_add_item(pm_tree
, hf_mpls_pm_qtf
, tvb
,
680 offset
, 1, ENC_BIG_ENDIAN
);
682 rtf
= tvb_get_guint8(tvb
, offset
) & 0x0F;
683 proto_tree_add_item(pm_tree
, hf_mpls_pm_rtf
, tvb
,
684 offset
, 1, ENC_BIG_ENDIAN
);
688 proto_tree_add_item(pm_tree
, hf_mpls_pm_rptf
, tvb
,
689 offset
, 1, ENC_BIG_ENDIAN
);
691 /* skip 20 reserved bits */
694 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
696 if (class_specific
) {
697 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_NA
);
701 /* timestamps 1..4 */
702 for (i
= 1; i
<= 4; i
++) {
703 mpls_pm_dissect_timestamp(tvb
, pm_tree
, offset
, qtf
, rtf
, query
, i
);
709 dissect_mpls_pm_combined(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
712 proto_item
*ti
= NULL
;
714 proto_tree
*pm_tree_flags
;
715 proto_tree
*pm_tree_dflags
;
718 gboolean response
= 0;
719 gboolean class_specific
= 0;
727 mpls_pm_build_cinfo(tvb
, pinfo
,
728 val_to_str_const(pmt
, pmt_vals
, ""),
729 &query
, &response
, &class_specific
, &sid
, &code
);
735 /* create display subtree for the protocol */
737 ti
= proto_tree_add_item(tree
, proto_mpls_pm_dlm_dm
,
740 ti
= proto_tree_add_item(tree
, proto_mpls_pm_ilm_dm
,
744 pm_tree
= proto_item_add_subtree(ti
, ett_mpls_pm
);
746 /* add version to the subtree */
747 proto_tree_add_item(pm_tree
, hf_mpls_pm_version
, tvb
, offset
, 1, ENC_NA
);
749 /* ctrl flags subtree */
750 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_flags
, tvb
, offset
, 1, ENC_NA
);
751 pm_tree_flags
= proto_item_add_subtree(ti
, ett_mpls_pm_flags
);
752 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_r
, tvb
,
754 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_t
, tvb
,
756 proto_tree_add_item(pm_tree_flags
, hf_mpls_pm_flags_res
, tvb
,
761 proto_tree_add_item(pm_tree
, hf_mpls_pm_query_ctrl_code
,
762 tvb
, offset
, 1, ENC_NA
);
764 proto_tree_add_item(pm_tree
, hf_mpls_pm_response_ctrl_code
,
765 tvb
, offset
, 1, ENC_NA
);
769 proto_tree_add_item(pm_tree
, hf_mpls_pm_length
, tvb
,
770 offset
, 2, ENC_BIG_ENDIAN
);
773 /* data flags subtree */
774 ti
= proto_tree_add_item(pm_tree
, hf_mpls_pm_dflags
, tvb
,
776 pm_tree_dflags
= proto_item_add_subtree(ti
, ett_mpls_pm_dflags
);
777 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_x
, tvb
,
779 bflag
= (tvb_get_guint8(tvb
, offset
) & 0x40) ? TRUE
: FALSE
;
780 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_b
, tvb
,
782 proto_tree_add_item(pm_tree_dflags
, hf_mpls_pm_dflags_res
, tvb
,
786 * FF: the roles of the OTF and Origin Timestamp fields for LM are
787 * here played by the QTF and Timestamp 1 fields, respectively.
789 qtf
= tvb_get_guint8(tvb
, offset
) & 0x0F;
790 proto_tree_add_item(pm_tree
, hf_mpls_pm_qtf_combined
, tvb
,
791 offset
, 1, ENC_BIG_ENDIAN
);
795 rtf
= tvb_get_guint8(tvb
, offset
) & 0xF0 >> 4;
796 proto_tree_add_item(pm_tree
, hf_mpls_pm_rtf_combined
, tvb
,
797 offset
, 1, ENC_BIG_ENDIAN
);
799 proto_tree_add_item(pm_tree
, hf_mpls_pm_rptf_combined
, tvb
,
800 offset
, 1, ENC_BIG_ENDIAN
);
803 /* skip 2 reserved bytes */
806 proto_tree_add_uint(pm_tree
, hf_mpls_pm_session_id
, tvb
, offset
, 4, sid
);
808 if (class_specific
) {
809 proto_tree_add_item(pm_tree
, hf_mpls_pm_ds
, tvb
, offset
+ 3, 1, ENC_NA
);
813 /* timestamps 1..4 */
814 for (i
= 1; i
<= 4; i
++) {
815 mpls_pm_dissect_timestamp(tvb
, pm_tree
, offset
, qtf
, rtf
, query
, i
);
820 for (i
= 1; i
<= 4; i
++) {
821 mpls_pm_dissect_counter(tvb
, pm_tree
, offset
, query
, bflag
, i
);
827 dissect_mpls_pm_dlm_dm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
829 /* the formats of the DLM+DM and ILM+DM messages are also identical */
830 dissect_mpls_pm_combined(tvb
, pinfo
, tree
, DLMDM
);
834 dissect_mpls_pm_ilm_dm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
836 /* the formats of the DLM+DM and ILM+DM messages are also identical */
837 dissect_mpls_pm_combined(tvb
, pinfo
, tree
, ILMDM
);
841 proto_register_mpls_pm(void)
843 static hf_register_info hf
[] = {
847 "Version", "mpls_pm.version", FT_UINT8
, BASE_DEC
, NULL
,
854 "Flags", "mpls_pm.flags", FT_UINT8
,
855 BASE_HEX
, NULL
, MPLS_PM_FLAGS_MASK
, NULL
, HFILL
861 "Response indicator (R)", "mpls_pm.flags.r",
862 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_R
,
869 "Traffic-class-specific measurement indicator (T)",
871 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_T
,
876 &hf_mpls_pm_flags_res
,
880 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), MPLS_PM_FLAGS_RES
,
885 &hf_mpls_pm_query_ctrl_code
,
889 FT_UINT8
, BASE_RANGE_STRING
| BASE_HEX
,
890 RVALS(mpls_pm_query_ctrl_code_rvals
), 0x0,
891 "Code identifying the query type", HFILL
895 &hf_mpls_pm_response_ctrl_code
,
899 FT_UINT8
, BASE_RANGE_STRING
| BASE_HEX
,
900 RVALS(mpls_pm_response_ctrl_code_rvals
), 0x0,
901 "Code identifying the response type", HFILL
909 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
910 "Total length of this message in bytes", HFILL
916 "DFlags", "mpls_pm.dflags", FT_UINT8
,
917 BASE_HEX
, NULL
, MPLS_PM_DFLAGS_MASK
,
922 &hf_mpls_pm_dflags_x
,
924 "Extended counter format indicator (X)", "mpls_pm.dflags.x",
925 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), MPLS_PM_DFLAGS_X
,
930 &hf_mpls_pm_dflags_b
,
932 "Octet/Byte count indicator (B)", "mpls_pm.dflags.b",
933 FT_BOOLEAN
, 4, TFS(&tfs_set_notset
), MPLS_PM_DFLAGS_B
,
938 &hf_mpls_pm_dflags_res
,
941 "mpls_pm.dflags.res",
942 FT_BOOLEAN
, 4, NULL
, MPLS_PM_DFLAGS_RES
,
949 "Origin Timestamp Format (OTF)",
951 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
952 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
957 &hf_mpls_pm_session_id
,
959 "Session Identifier",
960 "mpls_pm.session.id",
969 "Differentiated Services Codepoint",
971 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
,
972 &dscp_vals_ext
, 0x3F,
977 &hf_mpls_pm_origin_timestamp_null
,
980 "mpls_pm.origin.timestamp.null",
987 &hf_mpls_pm_origin_timestamp_seq
,
990 "mpls_pm.origin.timestamp.seq",
997 &hf_mpls_pm_origin_timestamp_ntp
,
1000 "mpls_pm.origin.timestamp.ntp",
1001 FT_RELATIVE_TIME
, BASE_NONE
,
1007 &hf_mpls_pm_origin_timestamp_ptp
,
1010 "mpls_pm.origin.timestamp.ptp",
1011 FT_RELATIVE_TIME
, BASE_NONE
,
1017 &hf_mpls_pm_origin_timestamp_unk
,
1019 "Origin Timestamp (Unknown Type)",
1020 "mpls_pm.origin.timestamp.unk",
1021 FT_UINT64
, BASE_DEC
,
1027 &hf_mpls_pm_counter1
,
1031 FT_UINT64
, BASE_DEC
,
1037 &hf_mpls_pm_counter2
,
1041 FT_UINT64
, BASE_DEC
,
1047 &hf_mpls_pm_counter3
,
1051 FT_UINT64
, BASE_DEC
,
1057 &hf_mpls_pm_counter4
,
1061 FT_UINT64
, BASE_DEC
,
1069 "Querier timestamp format (QTF)",
1071 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1072 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1077 &hf_mpls_pm_qtf_combined
,
1079 "Querier timestamp format (QTF)",
1081 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1082 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1089 "Responder timestamp format (RTF)",
1091 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1092 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1097 &hf_mpls_pm_rtf_combined
,
1099 "Responder timestamp format (RTF)",
1101 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1102 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1109 "Responder's preferred timestamp format (RPTF)",
1111 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1112 RVALS(mpls_pm_time_stamp_format_rvals
), 0xF0,
1117 &hf_mpls_pm_rptf_combined
,
1119 "Responder's preferred timestamp format (RPTF)",
1121 FT_UINT8
, BASE_RANGE_STRING
| BASE_DEC
,
1122 RVALS(mpls_pm_time_stamp_format_rvals
), 0x0F,
1127 &hf_mpls_pm_timestamp1_q_null
,
1130 "mpls_pm.timestamp1.null",
1131 FT_UINT64
, BASE_DEC
,
1137 &hf_mpls_pm_timestamp1_r_null
,
1140 "mpls_pm.timestamp1.null",
1141 FT_UINT64
, BASE_DEC
,
1147 &hf_mpls_pm_timestamp1_q_seq
,
1150 "mpls_pm.timestamp1.seq",
1151 FT_UINT64
, BASE_DEC
,
1157 &hf_mpls_pm_timestamp1_r_seq
,
1160 "mpls_pm.timestamp1.seq",
1161 FT_UINT64
, BASE_DEC
,
1167 &hf_mpls_pm_timestamp1_q_ntp
,
1170 "mpls_pm.timestamp1.ntp",
1171 FT_RELATIVE_TIME
, BASE_NONE
,
1177 &hf_mpls_pm_timestamp1_r_ntp
,
1180 "mpls_pm.timestamp1.ntp",
1181 FT_RELATIVE_TIME
, BASE_NONE
,
1187 &hf_mpls_pm_timestamp1_q_ptp
,
1190 "mpls_pm.timestamp1.ptp",
1191 FT_RELATIVE_TIME
, BASE_NONE
,
1197 &hf_mpls_pm_timestamp1_r_ptp
,
1200 "mpls_pm.timestamp1.ptp",
1201 FT_RELATIVE_TIME
, BASE_NONE
,
1207 &hf_mpls_pm_timestamp1_unk
,
1209 "Timestamp 1 (Unknown Type)",
1210 "mpls_pm.timestamp1.unk",
1211 FT_UINT64
, BASE_DEC
,
1217 &hf_mpls_pm_timestamp2_null
,
1220 "mpls_pm.timestamp2.null",
1221 FT_UINT64
, BASE_DEC
,
1227 &hf_mpls_pm_timestamp3_null
,
1230 "mpls_pm.timestamp3.null",
1231 FT_UINT64
, BASE_DEC
,
1237 &hf_mpls_pm_timestamp3_r_null
,
1240 "mpls_pm.timestamp3.null",
1241 FT_UINT64
, BASE_DEC
,
1247 &hf_mpls_pm_timestamp3_r_seq
,
1250 "mpls_pm.timestamp3.seq",
1251 FT_UINT64
, BASE_DEC
,
1257 &hf_mpls_pm_timestamp3_r_ntp
,
1260 "mpls_pm.timestamp3.ntp",
1261 FT_RELATIVE_TIME
, BASE_NONE
,
1267 &hf_mpls_pm_timestamp3_r_ptp
,
1270 "mpls_pm.timestamp3_ptp",
1271 FT_RELATIVE_TIME
, BASE_NONE
,
1277 &hf_mpls_pm_timestamp3_unk
,
1279 "Timestamp 3 (Unknown Type)",
1280 "mpls_pm.timestamp3.unk",
1281 FT_UINT64
, BASE_DEC
,
1287 &hf_mpls_pm_timestamp4_null
,
1290 "mpls_pm.timestamp4.null",
1291 FT_UINT64
, BASE_DEC
,
1297 &hf_mpls_pm_timestamp4_r_null
,
1300 "mpls_pm.timestamp4.null",
1301 FT_UINT64
, BASE_DEC
,
1307 &hf_mpls_pm_timestamp4_r_seq
,
1310 "mpls_pm.timestamp4.seq",
1311 FT_UINT64
, BASE_DEC
,
1317 &hf_mpls_pm_timestamp4_r_ntp
,
1320 "mpls_pm.timestamp4.ntp",
1321 FT_RELATIVE_TIME
, BASE_NONE
,
1327 &hf_mpls_pm_timestamp4_r_ptp
,
1330 "mpls_pm.timestamp4.ptp",
1331 FT_RELATIVE_TIME
, BASE_NONE
,
1337 &hf_mpls_pm_timestamp4_unk
,
1339 "Timestamp 4 (Unknown Type)",
1340 "mpls_pm.timestamp4.unk",
1341 FT_UINT64
, BASE_DEC
,
1348 static gint
*ett
[] = {
1355 proto_register_protocol("MPLS Direct Loss Measurement (DLM)",
1356 "MPLS Direct Loss Measurement (DLM)",
1360 proto_register_protocol("MPLS Inferred Loss Measurement (ILM)",
1361 "MPLS Inferred Loss Measurement (ILM)",
1365 proto_register_protocol("MPLS Delay Measurement (DM)",
1366 "MPLS Delay Measurement (DM)",
1369 proto_mpls_pm_dlm_dm
=
1370 proto_register_protocol("MPLS Direct Loss and Delay "
1371 "Measurement (DLM+DM)",
1372 "MPLS Direct Loss and Delay "
1373 "Measurement (DLM+DM)",
1376 proto_mpls_pm_ilm_dm
=
1377 proto_register_protocol("MPLS Inferred Loss and Delay "
1378 "Measurement (ILM+DM)",
1379 "MPLS Inferred Loss and Delay "
1380 "Measurement (ILM+DM)",
1383 proto_register_field_array(proto_mpls_pm_dlm
, hf
, array_length(hf
));
1384 proto_register_subtree_array(ett
, array_length(ett
));
1386 register_dissector("mpls_pm_dlm", dissect_mpls_pm_dlm
,
1389 register_dissector("mpls_pm_ilm", dissect_mpls_pm_ilm
,
1392 register_dissector("mpls_pm_dm", dissect_mpls_pm_delay
,
1395 register_dissector("mpls_pm_dlm_dm", dissect_mpls_pm_dlm_dm
,
1396 proto_mpls_pm_dlm_dm
);
1398 register_dissector("mpls_pm_ilm_dm", dissect_mpls_pm_ilm_dm
,
1399 proto_mpls_pm_ilm_dm
);
1403 proto_reg_handoff_mpls_pm(void)
1405 mpls_pm_dlm_handle
= find_dissector("mpls_pm_dlm");
1406 mpls_pm_ilm_handle
= find_dissector("mpls_pm_ilm");
1407 mpls_pm_dm_handle
= find_dissector("mpls_pm_dm");
1408 mpls_pm_dlm_dm_handle
= find_dissector("mpls_pm_dlm_dm");
1409 mpls_pm_ilm_dm_handle
= find_dissector("mpls_pm_ilm_dm");
1413 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1418 * indent-tabs-mode: nil
1421 * vi: set shiftwidth=4 tabstop=8 expandtab:
1422 * :indentSize=4:tabSize=8:noTabs=true: