2 * Routines for MPLS data packet disassembly
5 * (c) Copyright Ashok Narayanan <ashokn@cisco.com>
7 * (c) Copyright 2006, _FF_ Francesco Fondelli <francesco.fondelli@gmail.com>
8 * - added MPLS OAM support, ITU-T Y.1711
9 * - PW Associated Channel Header dissection as per RFC 4385
10 * - PW MPLS Control Word dissection as per RFC 4385
11 * - mpls subdissector table indexed by label value
12 * - enhanced "what's past last mpls label?" heuristic
14 * (c) Copyright 2011, Shobhank Sharma <ssharma5@ncsu.edu>
15 * - Removed some mpls preferences which are no longer relevant/needed like
16 * decode PWAC payloads as PPP traffic and assume all channel types except
18 * - MPLS extension from PW-ACH to MPLS Generic Associated Channel as per RFC 5586
19 * - Updated Pseudowire Associated Channel Types as per http://www.iana.org/assignments/pwe3-parameters
21 * (c) Copyright 2011, Jaihari Kalijanakiraman <jaiharik@ipinfusion.com>
22 * Krishnamurthy Mayya <krishnamurthy.mayya@ipinfusion.com>
23 * Nikitha Malgi <malgi.nikitha@ipinfusion.com>
24 * - Identification of BFD CC, BFD CV and ON-Demand CV ACH types as per RFC 6428, RFC 6426
25 * respectively and the corresponding decoding of messages
26 * - Decoding support for MPLS-TP Lock Instruct as per RFC 6435
27 * - Decoding support for MPLS-TP Fault-Management as per RFC 6427
29 * (c) Copyright 2012, Aditya Ambadkar and Diana Chris <arambadk,dvchris@ncsu.edu>
30 * - Added preference to select BOS label as flowlabel as per RFC 6391
32 * Wireshark - Network traffic analyzer
33 * By Gerald Combs <gerald@wireshark.org>
34 * Copyright 1998 Gerald Combs
36 * SPDX-License-Identifier: GPL-2.0-or-later
41 #include <epan/packet.h>
42 #include <epan/expert.h>
44 #include <epan/ppptypes.h>
45 #include <epan/etypes.h>
46 #include <epan/prefs.h>
47 #include <epan/ipproto.h>
48 #include <epan/decode_as.h>
49 #include <epan/proto_data.h>
51 #include "packet-ppp.h"
52 #include "packet-mpls.h"
53 #include "packet-pw-common.h"
54 #include "packet-bfd.h"
55 #include "packet-juniper.h"
56 #include "packet-sflow.h"
57 #include "packet-l2tp.h"
58 #include "packet-vxlan.h"
59 #include "packet-nsh.h"
61 void proto_register_mpls(void);
62 void proto_reg_handoff_mpls(void);
64 static int proto_mpls
;
65 static int proto_pw_ach
;
66 static int proto_pw_ach_mcc
;
67 static int proto_pw_mcw
;
70 static int ett_mpls_pw_ach
;
71 static int ett_mpls_pw_ach_mcc
;
72 static int ett_mpls_pw_mcw
;
73 static char PW_ACH
[50] = "PW Associated Channel Header";
75 const value_string special_labels
[] = {
76 {MPLS_LABEL_IP4_EXPLICIT_NULL
, "IPv4 Explicit-Null"},
77 {MPLS_LABEL_ROUTER_ALERT
, "Router Alert"},
78 {MPLS_LABEL_IP6_EXPLICIT_NULL
, "IPv6 Explicit-Null"},
79 {MPLS_LABEL_IMPLICIT_NULL
, "Implicit-Null"},
80 {MPLS_LABEL_OAM_ALERT
, "OAM Alert"},
81 {MPLS_LABEL_GACH
, "Generic Associated Channel Label (GAL)"},
82 {MPLS_LABEL_ELI
, "Entropy Label Indicator (ELI)"},
86 static dissector_table_t pw_ach_subdissector_table
;
87 static dissector_table_t pw_ach_mcc_subdissector_table
;
89 static dissector_handle_t dissector_ipv6
;
90 static dissector_handle_t dissector_ip
;
91 static dissector_handle_t dissector_pw_ach
;
92 static dissector_handle_t dissector_pw_eth_heuristic
;
93 static dissector_handle_t mpls_handle
;
94 static dissector_handle_t mpls_pwcw_handle
;
95 static dissector_handle_t mpls_mcc_handle
;
98 * RFC 8469 deprecated Ethernet without CW, so default this to false.
99 * https://datatracker.ietf.org/doc/html/rfc8469
101 static bool mpls_try_heuristic_first
;
102 /* For RFC6391 - Flow aware transport of pseudowire over a mpls PSN*/
103 static bool mpls_bos_flowlabel
;
105 static int hf_mpls_label
;
106 static int hf_mpls_label_special
;
107 static int hf_mpls_exp
;
108 static int hf_mpls_bos
;
109 static int hf_mpls_ttl
;
111 static int hf_mpls_pw_ach_ver
;
112 static int hf_mpls_pw_ach_res
;
113 static int hf_mpls_pw_ach_channel_type
;
115 static int hf_mpls_pw_ach_mcc_proto
;
117 static int hf_mpls_pw_mcw_flags
;
118 static int hf_mpls_pw_mcw_length
;
119 static int hf_mpls_pw_mcw_sequence_number
;
121 static expert_field ei_mpls_pw_ach_error_processing_message
;
122 static expert_field ei_mpls_pw_ach_res
;
123 static expert_field ei_mpls_pw_mcw_error_processing_message
;
124 static expert_field ei_mpls_invalid_label
;
126 #if 0 /*not used yet*/
129 * http://www.iana.org/assignments/pwe3-parameters
131 static const value_string mpls_pw_types
[] = {
132 { 0x0001, "Frame Relay DLCI ( Martini Mode )" },
133 { 0x0002, "ATM AAL5 SDU VCC transport" },
134 { 0x0003, "ATM transparent cell transport" },
135 { 0x0004, "Ethernet Tagged Mode" },
136 { 0x0005, "Ethernet" },
139 { 0x0008, "SONET/SDH Circuit Emulation Service Over MPLS" },
140 { 0x0009, "ATM n-to-one VCC cell transport" },
141 { 0x000A, "ATM n-to-one VPC cell transport" },
142 { 0x000B, "IP Layer2 Transport" },
143 { 0x000C, "ATM one-to-one VCC Cell Mode" },
144 { 0x000D, "ATM one-to-one VPC Cell Mode" },
145 { 0x000E, "ATM AAL5 PDU VCC transport" },
146 { 0x000F, "Frame-Relay Port mode" },
147 { 0x0010, "SONET/SDH Circuit Emulation over Packet" },
148 { 0x0011, "Structure-agnostic E1 over Packet" },
149 { 0x0012, "Structure-agnostic T1 (DS1) over Packet" },
150 { 0x0013, "Structure-agnostic E3 over Packet" },
151 { 0x0014, "Structure-agnostic T3 (DS3) over Packet" },
152 { 0x0015, "CESoPSN basic mode" },
153 { 0x0016, "TDMoIP AAL1 Mode" },
154 { 0x0017, "CESoPSN TDM with CAS" },
155 { 0x0018, "TDMoIP AAL2 Mode" },
156 { 0x0019, "Frame Relay DLCI" },
157 { 0x001A, "ROHC Transport Header-compressed Packets" },/*[RFC4995][RFC4901]*/
158 { 0x001B, "ECRTP Transport Header-compressed Packets" },/*[RFC3545][RFC4901]*/
159 { 0x001C, "IPHC Transport Header-compressed Packets" },/*[RFC2507][RFC4901]*/
160 { 0x001D, "cRTP Transport Header-compressed Packets" },/*[RFC2508][RFC4901]*/
161 { 0x001E, "ATM VP Virtual Trunk" },/*[MFA9]*/
162 { 0x001F, "Reserved" },/*[Bryant] 2008-04-17*/
165 static value_string_ext mpls_pw_types_ext
= VALUE_STRING_EXT_INIT(mpls_pw_types
);
169 * MPLS PW Associated Channel Types
170 * as per http://www.iana.org/assignments/pwe3-parameters
171 * and https://tools.ietf.org/html/draft-ietf-pwe3-vccv-bfd-05 clause 3.2
173 static const value_string mpls_pwac_types
[] = {
174 { 0x0000, "Reserved"},
175 { 0x0001, "Management Communication Channel (MCC)"},
176 { 0x0002, "Signaling Communication Channel (SCC)"},
177 { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
178 { 0x000A, "MPLS Direct Loss Measurement (DLM)"},
179 { 0x000B, "MPLS Inferred Loss Measurement (ILM)"},
180 { 0x000C, "MPLS Delay Measurement (DM)"},
181 { 0x000D, "MPLS Direct Loss and Delay Measurement (DLM+DM)"},
182 { 0x000E, "MPLS Inferred Loss and Delay Measurement (ILM+DM)"},
183 { 0x0021, "IPv4 packet" },
184 { 0x0022, "MPLS-TP CC message"},
185 { 0x0023, "MPLS-TP CV message"},
186 { 0x0024, "Protection State Coordination Protocol (PSC)"},
187 { 0x0025, "On-Demand CV"},
189 { 0x0027, "Pseudo-Wire OAM"},
190 { 0x0028, "MAC Withdraw OAM Msg"},
191 { 0x0057, "IPv6 packet" },
192 { 0x0058, "Fault OAM"},
193 { 0x7FF8, "Reserved for Experimental Use"},
194 { 0x7FF9, "Reserved for Experimental Use"},
195 { 0x7FFA, "Reserved for Experimental Use"},
196 { 0x7FFB, "Reserved for Experimental Use"},
197 { 0x7FFC, "Reserved for Experimental Use"},
198 { 0x7FFD, "Reserved for Experimental Use"},
199 { 0x7FFE, "Reserved for Experimental Use"},
200 { 0x7FFF, "Reserved for Experimental Use"},
201 { 0x8902, "MPLS-TP OAM"},
204 static value_string_ext mpls_pwac_types_ext
= VALUE_STRING_EXT_INIT(mpls_pwac_types
);
206 static dissector_table_t mpls_subdissector_table
;
208 * Post-stack First Nibble
209 * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
211 static dissector_table_t mpls_pfn_subdissector_table
;
212 static heur_dissector_list_t mpls_heur_subdissector_list
;
214 static void mpls_prompt(packet_info
*pinfo
, char* result
)
216 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Data after label %u as",
217 GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 0)));
220 static void *mpls_value(packet_info
*pinfo
)
222 return p_get_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 0);
225 static void mpls_pfn_prompt(packet_info
*pinfo
, char* result
)
227 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Data after post-stack first nibble %u as",
228 GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 1)));
231 static void *mpls_pfn_value(packet_info
*pinfo
)
233 return p_get_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 1);
236 static void pw_ach_prompt(packet_info
*pinfo
, char* result
)
238 snprintf(result
, MAX_DECODE_AS_PROMPT_LEN
, "Channel type 0x%x as",
239 GPOINTER_TO_UINT(p_get_proto_data(pinfo
->pool
, pinfo
, proto_pw_ach
, 0)));
242 static void *pw_ach_value(packet_info
*pinfo
)
244 return p_get_proto_data(pinfo
->pool
, pinfo
, proto_pw_ach
, 0);
248 * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
250 * Return the label in "label", EXP bits in "exp",
251 * bottom_of_stack in "bos", and TTL in "ttl"
254 decode_mpls_label(tvbuff_t
*tvb
, int offset
,
255 uint32_t *label
, uint8_t *exp
,
256 uint8_t *bos
, uint8_t *ttl
)
258 uint8_t octet0
= tvb_get_uint8(tvb
, offset
+0);
259 uint8_t octet1
= tvb_get_uint8(tvb
, offset
+1);
260 uint8_t octet2
= tvb_get_uint8(tvb
, offset
+2);
262 *label
= (octet0
<< 12) + (octet1
<< 4) + ((octet2
>> 4) & 0xff);
263 *exp
= (octet2
>> 1) & 0x7;
264 *bos
= (octet2
& 0x1);
265 *ttl
= tvb_get_uint8(tvb
, offset
+3);
269 * PW Associated Channel Header Management Communication
270 * Network (MCN) dissection as per RFC 5718.
273 dissect_pw_ach_mcc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
276 proto_tree
*mpls_pw_ach_mcc_tree
;
280 ti
= proto_tree_add_item(tree
, proto_pw_ach_mcc
, tvb
, 0,2, ENC_NA
);
281 mpls_pw_ach_mcc_tree
= proto_item_add_subtree(ti
, ett_mpls_pw_ach_mcc
);
282 proto_tree_add_item_ret_uint(mpls_pw_ach_mcc_tree
, hf_mpls_pw_ach_mcc_proto
,tvb
, 0, 2, ENC_BIG_ENDIAN
, &pid
);
284 next_tvb
= tvb_new_subset_remaining(tvb
, 2);
286 if (!dissector_try_uint(pw_ach_mcc_subdissector_table
, pid
, next_tvb
, pinfo
, tree
))
288 call_data_dissector(next_tvb
, pinfo
, tree
);
291 return tvb_captured_length(tvb
);
295 * FF: PW Associated Channel Header dissection as per RFC 4385.
298 dissect_pw_ach(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
301 unsigned channel_type
;
303 if (tvb_reported_length_remaining(tvb
, 0) < 4) {
304 proto_tree_add_expert(tree
, pinfo
, &ei_mpls_pw_ach_error_processing_message
, tvb
, 0, -1);
305 return tvb_captured_length(tvb
);
308 channel_type
= tvb_get_ntohs(tvb
, 2);
309 p_add_proto_data(pinfo
->pool
, pinfo
, proto_pw_ach
, 0, GUINT_TO_POINTER(channel_type
));
312 proto_tree
*mpls_pw_ach_tree
;
316 ti
= proto_tree_add_item(tree
, proto_pw_ach
, tvb
, 0, 4, ENC_NA
);
317 mpls_pw_ach_tree
= proto_item_add_subtree(ti
, ett_mpls_pw_ach
);
319 proto_tree_add_item(mpls_pw_ach_tree
, hf_mpls_pw_ach_ver
,
320 tvb
, 0, 1, ENC_BIG_ENDIAN
);
322 res
= tvb_get_uint8(tvb
, 1);
323 ti
= proto_tree_add_uint(mpls_pw_ach_tree
, hf_mpls_pw_ach_res
,
326 expert_add_info(pinfo
, ti
, &ei_mpls_pw_ach_res
);
328 proto_tree_add_item(mpls_pw_ach_tree
, hf_mpls_pw_ach_channel_type
,
329 tvb
, 2, 2, ENC_BIG_ENDIAN
);
333 next_tvb
= tvb_new_subset_remaining(tvb
, 4);
335 if (!dissector_try_uint(pw_ach_subdissector_table
, channel_type
, next_tvb
, pinfo
, tree
))
337 call_data_dissector(next_tvb
, pinfo
, tree
);
340 if (channel_type
== PW_ACH_TYPE_BFD_CV
)
342 /* The BFD dissector has already been called, this is called in addition
343 XXX - Perhaps a new dissector function that combines both is preferred.*/
344 dissect_bfd_mep(next_tvb
, tree
, 0);
346 return tvb_captured_length(tvb
);
350 dissect_try_cw_first_nibble( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
354 nibble
= (tvb_get_uint8(tvb
, 0 ) >> 4) & 0x0F;
359 * XXX - this could be from an pseudo-wire without a control
360 * word, with the packet's first nibble being 6.
362 call_dissector(dissector_ipv6
, tvb
, pinfo
, tree
);
366 * XXX - this could be from an pseudo-wire without a control
367 * word, with the packet's first nibble being 4.
369 call_dissector(dissector_ip
, tvb
, pinfo
, tree
);
373 * XXX - this could be from an pseudo-wire without a control
374 * word, with the packet's first nibble being 1.
376 call_dissector(dissector_pw_ach
, tvb
, pinfo
, tree
);
385 * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
388 dissect_pw_mcw(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
392 if (tvb_reported_length_remaining(tvb
, 0) < 4) {
393 proto_tree_add_expert(tree
, pinfo
, &ei_mpls_pw_mcw_error_processing_message
, tvb
, 0, -1);
394 return tvb_captured_length(tvb
);
397 if ( dissect_try_cw_first_nibble( tvb
, pinfo
, tree
))
398 return tvb_captured_length(tvb
);
401 proto_tree
*mpls_pw_mcw_tree
;
404 ti
= proto_tree_add_item(tree
, proto_pw_mcw
, tvb
, 0, 4, ENC_NA
);
405 mpls_pw_mcw_tree
= proto_item_add_subtree(ti
, ett_mpls_pw_mcw
);
407 proto_tree_add_item(mpls_pw_mcw_tree
, hf_mpls_pw_mcw_flags
,
408 tvb
, 0, 2, ENC_BIG_ENDIAN
);
409 /* bits 4 to 7 and FRG bits are displayed together */
410 proto_tree_add_item(mpls_pw_mcw_tree
, hf_mpls_pw_mcw_length
,
411 tvb
, 1, 1, ENC_BIG_ENDIAN
);
412 proto_tree_add_item(mpls_pw_mcw_tree
, hf_mpls_pw_mcw_sequence_number
,
413 tvb
, 2, 2, ENC_BIG_ENDIAN
);
415 next_tvb
= tvb_new_subset_remaining(tvb
, 4);
416 call_data_dissector(next_tvb
, pinfo
, tree
);
417 return tvb_captured_length(tvb
);
421 dissect_mpls(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
424 uint32_t label
= MPLS_LABEL_INVALID
;
430 uint8_t first_nibble
;
431 struct mplsinfo mplsinfo
;
432 heur_dtbl_entry_t
*hdtbl_entry
;
433 dissector_handle_t payload_handle
;
435 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MPLS");
436 col_set_str(pinfo
->cinfo
, COL_INFO
, "MPLS Label Switched Packet");
438 /* Ensure structure is initialized */
439 memset(&mplsinfo
, 0, sizeof(struct mplsinfo
));
441 /* Start Decoding Here. */
442 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
444 decode_mpls_label(tvb
, offset
, &label
, &exp
, &bos
, &ttl
);
447 * FF: export (last shim in stack) info to subdissectors and
450 mplsinfo
.label
= label
;
451 p_add_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 0, GUINT_TO_POINTER(label
));
458 proto_tree
*mpls_tree
;
460 ti
= proto_tree_add_item(tree
, proto_mpls
, tvb
, offset
, 4, ENC_NA
);
461 mpls_tree
= proto_item_add_subtree(ti
, ett_mpls
);
463 if (mpls_bos_flowlabel
&& bos
) {
464 proto_item_append_text(ti
, ", Label: %u (Flow Label)", label
);
466 proto_item_append_text(ti
, ", Label: %u", label
);
468 if (label
<= MPLS_LABEL_MAX_RESERVED
){
469 proto_tree_add_item(mpls_tree
, hf_mpls_label_special
, tvb
,
470 offset
, 4, ENC_BIG_ENDIAN
);
471 proto_item_append_text(ti
, " (%s)",
472 val_to_str_const(label
, special_labels
, "Reserved - Unknown"));
474 proto_tree_add_item(mpls_tree
, hf_mpls_label
, tvb
, offset
, 4,
478 proto_tree_add_item(mpls_tree
, hf_mpls_exp
, tvb
, offset
, 4,
480 proto_item_append_text(ti
, ", Exp: %u", exp
);
482 proto_tree_add_item(mpls_tree
, hf_mpls_bos
, tvb
, offset
, 4,
484 proto_item_append_text(ti
, ", S: %u", bos
);
486 proto_tree_add_item(mpls_tree
, hf_mpls_ttl
, tvb
, offset
, 4,
488 proto_item_append_text(ti
, ", TTL: %u", ttl
);
493 if ((label
== MPLS_LABEL_GACH
) && !bos
) {
494 proto_tree_add_expert(tree
, pinfo
, &ei_mpls_invalid_label
, tvb
, 0, -1);
497 if ((label
== MPLS_LABEL_GACH
) && bos
) {
498 (void) g_strlcpy(PW_ACH
, "Generic Associated Channel Header",50);
499 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
500 call_dissector(dissector_pw_ach
, next_tvb
, pinfo
, tree
);
501 return tvb_captured_length(tvb
);
504 (void) g_strlcpy(PW_ACH
, "PW Associated Channel Header",50);
510 first_nibble
= (tvb_get_uint8(tvb
, offset
) >> 4) & 0x0F;
511 p_add_proto_data(pinfo
->pool
, pinfo
, proto_mpls
, 1, GUINT_TO_POINTER(first_nibble
));
513 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
516 * Is there an explicit label-to-dissector binding?
519 found
= dissector_try_uint_with_data(mpls_subdissector_table
, label
,
520 next_tvb
, pinfo
, tree
, false, &mplsinfo
);
523 return tvb_captured_length(tvb
);
527 * Do we try heuristic dissectors first? This is necessary for, e.g.,
528 * Ethernet without CW where the address begins with a 4 or 6 nibble.
530 if (mpls_try_heuristic_first
) {
531 if (dissector_try_heuristic(mpls_heur_subdissector_list
, next_tvb
, pinfo
,
532 tree
, &hdtbl_entry
, NULL
)) {
533 return tvb_captured_length(tvb
);
538 * Use the 1st nibble logic (see BCP 128 (RFC 4928), RFC 4385 and 5586).
539 * https://datatracker.ietf.org/doc/html/draft-ietf-mpls-1stnibble-06
541 if (dissector_try_uint_with_data(mpls_pfn_subdissector_table
, first_nibble
,
542 next_tvb
, pinfo
, tree
, false, &mplsinfo
)) {
544 payload_handle
= dissector_get_uint_handle(mpls_pfn_subdissector_table
, first_nibble
);
545 if (payload_handle
== dissector_ip
|| payload_handle
== dissector_ipv6
) {
546 /* IPv4 and IPv6 dissectors may reduce the length of the tvb.
547 We need to do the same, so that any Ethernet trailer is detected.
549 set_actual_length(tvb
, offset
+tvb_reported_length(next_tvb
));
551 return tvb_captured_length(tvb
);
554 if (!mpls_try_heuristic_first
) {
555 if (dissector_try_heuristic(mpls_heur_subdissector_list
, next_tvb
, pinfo
,
556 tree
, &hdtbl_entry
, NULL
)) {
557 return tvb_captured_length(tvb
);
561 call_data_dissector(next_tvb
, pinfo
, tree
);
562 return tvb_captured_length(tvb
);
566 proto_register_mpls(void)
568 static hf_register_info mplsf_info
[] = {
570 /* MPLS header fields */
572 {"MPLS Label", "mpls.label",
573 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0xFFFFF000,
577 {&hf_mpls_label_special
,
578 {"MPLS Label", "mpls.label",
579 FT_UINT32
, BASE_DEC_HEX
, VALS(special_labels
), 0xFFFFF000,
584 {"MPLS Experimental Bits", "mpls.exp",
585 FT_UINT32
, BASE_DEC
, NULL
, 0x00000E00,
590 {"MPLS Bottom Of Label Stack", "mpls.bottom",
591 FT_UINT32
, BASE_DEC
, NULL
, 0x00000100,
596 {"MPLS TTL", "mpls.ttl",
597 FT_UINT32
, BASE_DEC
, NULL
, 0x000000FF,
601 /* PW Associated Channel Header fields */
602 {&hf_mpls_pw_ach_ver
,
603 {"Channel Version", "pwach.ver",
604 FT_UINT8
, BASE_DEC
, NULL
, 0x0F,
605 "PW Associated Channel Version", HFILL
}
608 {&hf_mpls_pw_ach_res
,
609 {"Reserved", "pwach.res",
610 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
614 {&hf_mpls_pw_ach_channel_type
,
615 {"Channel Type", "pwach.channel_type",
616 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &mpls_pwac_types_ext
, 0x0,
617 "PW Associated Channel Type", HFILL
}
620 /* Generic/Preferred PW MPLS MCC Control Word fields */
621 {&hf_mpls_pw_ach_mcc_proto
,
622 {"Protocol Id", "mcc.proto",
623 FT_UINT16
, BASE_HEX
|BASE_EXT_STRING
, &mpls_pwac_types_ext
, 0x0,
624 "MCC Protocol", HFILL
}
627 /* Generic/Preferred PW MPLS Control Word fields */
628 {&hf_mpls_pw_mcw_flags
,
629 {"Flags", "pwmcw.flags",
630 FT_UINT16
, BASE_HEX
, NULL
, 0x0FC0,
631 "Generic/Preferred PW MPLS Control Word Flags", HFILL
}
634 {&hf_mpls_pw_mcw_length
,
635 {"Length", "pwmcw.length",
636 FT_UINT8
, BASE_DEC
, NULL
, 0x3F,
637 "Generic/Preferred PW MPLS Control Word Length", HFILL
}
640 {&hf_mpls_pw_mcw_sequence_number
,
641 {"Sequence Number", "pwmcw.sequence_number",
642 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
643 "Generic/Preferred PW MPLS Control Word Sequence Number", HFILL
}
647 static int *ett
[] = {
650 &ett_mpls_pw_ach_mcc
,
654 static ei_register_info ei
[] = {
655 { &ei_mpls_pw_ach_error_processing_message
, { "pwach.error_processing_message", PI_MALFORMED
, PI_ERROR
, "Error processing Message", EXPFILL
}},
656 { &ei_mpls_pw_ach_res
, { "pwach.res.not_zero", PI_PROTOCOL
, PI_WARN
, "Error: this byte is reserved and must be 0", EXPFILL
}},
657 { &ei_mpls_pw_mcw_error_processing_message
, { "pwmcw.error_processing_message", PI_MALFORMED
, PI_ERROR
, "Error processing Message", EXPFILL
}},
658 { &ei_mpls_invalid_label
, { "mpls.invalid_label", PI_PROTOCOL
, PI_WARN
, "Invalid Label", EXPFILL
}},
661 /* Decode As handling */
662 static build_valid_func mpls_da_build_value
[1] = {mpls_value
};
663 static decode_as_value_t mpls_da_values
= {mpls_prompt
, 1, mpls_da_build_value
};
664 static decode_as_t mpls_da
= {"mpls", "mpls.label", 1, 0, &mpls_da_values
, NULL
, NULL
,
665 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
667 static build_valid_func mpls_pfn_da_build_value
[1] = {mpls_pfn_value
};
668 static decode_as_value_t mpls_pfn_da_values
= {mpls_pfn_prompt
, 1, mpls_pfn_da_build_value
};
669 static decode_as_t mpls_pfn_da
= {"mpls", "mpls.pfn", 1, 0, &mpls_pfn_da_values
, NULL
, NULL
,
670 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
672 static build_valid_func pw_ach_da_build_value
[1] = {pw_ach_value
};
673 static decode_as_value_t pw_ach_da_values
= {pw_ach_prompt
, 1, pw_ach_da_build_value
};
674 static decode_as_t pw_ach_da
= {"pwach", "pwach.channel_type", 1, 0, &pw_ach_da_values
, NULL
, NULL
,
675 decode_as_default_populate_list
, decode_as_default_reset
, decode_as_default_change
, NULL
};
677 expert_module_t
* expert_mpls
;
678 module_t
* module_mpls
;
680 proto_mpls
= proto_register_protocol("MultiProtocol Label Switching Header", "MPLS", "mpls");
681 proto_pw_ach
= proto_register_protocol(PW_ACH
, "PW Associated Channel", "pwach");
682 proto_pw_mcw
= proto_register_protocol("PW MPLS Control Word (generic/preferred)", "Generic PW (with CW)", "pwmcw");
683 proto_pw_ach_mcc
= proto_register_protocol("Management Communication Channel (MCC)", "PW Associated Management Communication Channel", "mcc");
685 proto_register_field_array(proto_mpls
, mplsf_info
, array_length(mplsf_info
));
686 proto_register_subtree_array(ett
, array_length(ett
));
687 expert_mpls
= expert_register_protocol(proto_mpls
);
688 expert_register_field_array(expert_mpls
, ei
, array_length(ei
));
690 mpls_handle
= register_dissector("mpls", dissect_mpls
, proto_mpls
);
691 mpls_mcc_handle
= register_dissector("mplsmcc", dissect_pw_ach_mcc
, proto_pw_ach_mcc
);
692 mpls_pwcw_handle
= register_dissector("mplspwcw", dissect_pw_mcw
, proto_pw_mcw
);
693 dissector_pw_ach
= register_dissector("mplspwach", dissect_pw_ach
, proto_pw_ach
);
695 /* FF: mpls subdissector table is indexed by label */
696 mpls_subdissector_table
= register_dissector_table("mpls.label",
698 proto_mpls
, FT_UINT32
, BASE_DEC
);
700 mpls_pfn_subdissector_table
= register_dissector_table("mpls.pfn",
701 "MPLS post-stack first nibble",
702 proto_mpls
, FT_UINT8
, BASE_HEX
);
704 mpls_heur_subdissector_list
= register_heur_dissector_list_with_description("mpls", "MPLS payload", proto_mpls
);
706 pw_ach_subdissector_table
= register_dissector_table("pwach.channel_type", "PW Associated Channel Type", proto_pw_ach
, FT_UINT16
, BASE_HEX
);
708 pw_ach_mcc_subdissector_table
= register_dissector_table("mcc.proto", "PW Associated Management Communication Channel Protocol", proto_pw_ach_mcc
, FT_UINT16
, BASE_HEX
);
710 module_mpls
= prefs_register_protocol( proto_mpls
, NULL
);
712 prefs_register_obsolete_preference(module_mpls
, "mplspref.payload");
714 prefs_register_bool_preference(module_mpls
, "try_heuristic_first",
715 "Try heuristic sub-dissectors first",
716 "Try to decode a packet heuristically, e.g. as "
717 "Ethernet without control word, before trying "
718 "sub-dissectors based upon the first nibble.",
719 &mpls_try_heuristic_first
);
721 /* RFC6391: Flow aware transport of pseudowire*/
722 prefs_register_bool_preference(module_mpls
,
723 "flowlabel_in_mpls_header",
724 "Assume bottom of stack label as Flow label",
725 "Lowest label is used to segregate flows inside a pseudowire",
726 &mpls_bos_flowlabel
);
728 register_decode_as(&mpls_da
);
729 register_decode_as(&mpls_pfn_da
);
730 register_decode_as(&pw_ach_da
);
734 proto_reg_handoff_mpls(void)
736 dissector_add_uint("ethertype", ETHERTYPE_MPLS
, mpls_handle
);
737 dissector_add_uint("ethertype", ETHERTYPE_MPLS_MULTI
, mpls_handle
);
738 dissector_add_uint("ppp.protocol", PPP_MPLS_UNI
, mpls_handle
);
739 dissector_add_uint("ppp.protocol", PPP_MPLS_MULTI
, mpls_handle
);
740 dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS
, mpls_handle
);
741 dissector_add_uint("chdlc.protocol", ETHERTYPE_MPLS_MULTI
, mpls_handle
);
742 dissector_add_uint("gre.proto", ETHERTYPE_MPLS
, mpls_handle
);
743 dissector_add_uint("gre.proto", ETHERTYPE_MPLS_MULTI
, mpls_handle
);
744 dissector_add_uint("ip.proto", IP_PROTO_MPLS_IN_IP
, mpls_handle
);
745 dissector_add_uint("juniper.proto", JUNIPER_PROTO_MPLS
, mpls_handle
);
746 dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP_MPLS
, mpls_handle
);
747 dissector_add_uint("juniper.proto", JUNIPER_PROTO_IP6_MPLS
, mpls_handle
);
748 dissector_add_uint("juniper.proto", JUNIPER_PROTO_CLNP_MPLS
, mpls_handle
);
749 dissector_add_for_decode_as("pwach.channel_type", mpls_handle
);
750 dissector_add_uint("sflow_245.header_protocol", SFLOW_245_HEADER_MPLS
, mpls_handle
);
751 dissector_add_for_decode_as("l2tp.pw_type", mpls_handle
);
752 dissector_add_uint_with_preference("udp.port", UDP_PORT_MPLS_OVER_UDP
, mpls_handle
);
753 dissector_add_uint("vxlan.next_proto", VXLAN_MPLS
, mpls_handle
);
754 dissector_add_uint("nsh.next_proto", NSH_MPLS
, mpls_handle
);
756 dissector_add_uint( "mpls.label", MPLS_LABEL_INVALID
, mpls_pwcw_handle
);
758 dissector_add_uint("pwach.channel_type", PW_ACH_TYPE_MCC
, mpls_mcc_handle
);
760 dissector_ipv6
= find_dissector_add_dependency("ipv6", proto_pw_mcw
);
761 dissector_ip
= find_dissector_add_dependency("ip", proto_pw_mcw
);
762 dissector_pw_eth_heuristic
= find_dissector_add_dependency("pw_eth_heuristic", proto_pw_mcw
);
765 * Our previous default behavior has been to try the Eth CW heuristic
766 * on first nibble 0. Continue doing that. For other first nibbles
767 * registered to dissectors, "try heuristic first" can be enabled.
769 dissector_add_for_decode_as("mpls.pfn", mpls_pwcw_handle
);
770 dissector_add_uint("mpls.pfn", 0, dissector_pw_eth_heuristic
);
771 dissector_add_uint("mpls.pfn", 1, dissector_pw_ach
);
772 dissector_add_uint("mpls.pfn", 4, dissector_ip
);
773 dissector_add_uint("mpls.pfn", 6, dissector_ipv6
);
782 * indent-tabs-mode: nil
785 * ex: set shiftwidth=4 tabstop=8 expandtab:
786 * :indentSize=4:tabSize=8:noTabs=true: