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
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 * This module defines routines to handle Ethernet-encapsulated MPLS IP packets.
39 * It should implement all the functionality in <draft-ietf-mpls-label-encaps-07.txt>
40 * Multicast MPLS support is not tested yet
45 * The OAM patch should dissect OAM pdus as described in ITU-T Y.1711
53 #include <epan/packet.h>
54 #include <epan/ppptypes.h>
55 #include <epan/etypes.h>
56 #include <epan/prefs.h>
57 #include <epan/ipproto.h>
58 #include <epan/addr_resolv.h>
59 #include "packet-ppp.h"
60 #include "packet-mpls.h"
61 #include "packet-pw-common.h"
63 static gint proto_mpls = -1;
64 static gint proto_pw_ach = -1;
65 static gint proto_pw_mcw = -1;
67 static gint ett_mpls = -1;
68 static gint ett_mpls_pw_ach = -1;
69 static gint ett_mpls_pw_mcw = -1;
70 static gint ett_mpls_oam = -1;
72 void proto_reg_handoff_mpls(void);
74 const value_string special_labels[] = {
75 {LABEL_IP4_EXPLICIT_NULL, "IPv4 Explicit-Null"},
76 {LABEL_ROUTER_ALERT, "Router Alert"},
77 {LABEL_IP6_EXPLICIT_NULL, "IPv6 Explicit-Null"},
78 {LABEL_IMPLICIT_NULL, "Implicit-Null"},
79 {LABEL_OAM_ALERT, "OAM Alert"},
83 /* MPLS filter values */
84 enum mpls_filter_keys {
85 /* MPLS encap properties */
88 MPLSF_BOTTOM_OF_STACK,
93 static dissector_handle_t dissector_data;
94 static dissector_handle_t dissector_ipv6;
95 static dissector_handle_t dissector_ip;
96 static dissector_handle_t dissector_bfd;
97 static dissector_handle_t dissector_pw_eth_heuristic;
98 static dissector_handle_t dissector_pw_fr;
99 static dissector_handle_t dissector_pw_hdlc_nocw_fr;
100 static dissector_handle_t dissector_pw_hdlc_nocw_hdlc_ppp;
101 static dissector_handle_t dissector_pw_eth_cw;
102 static dissector_handle_t dissector_pw_eth_nocw;
103 static dissector_handle_t dissector_pw_satop;
104 static dissector_handle_t dissector_itdm;
105 static dissector_handle_t dissector_mpls_pw_atm_n1_cw;
106 static dissector_handle_t dissector_mpls_pw_atm_n1_nocw;
107 static dissector_handle_t dissector_mpls_pw_atm_11_aal5pdu;
108 static dissector_handle_t dissector_mpls_pw_atm_aal5_sdu;
109 static dissector_handle_t dissector_pw_cesopsn;
111 enum mpls_default_dissector_t {
116 ,MDD_MPLS_PW_HDLC_NOCW_FRPORT
117 ,MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP
119 ,MDD_MPLS_PW_ETH_NOCW
122 ,MDD_MPLS_PW_ATM_N1_CW
123 ,MDD_MPLS_PW_ATM_N1_NOCW
124 ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
125 ,MDD_MPLS_PW_ATM_AAL5_SDU
128 /* TODO the content of mpls_default_payload menu
129 * should be automatically built like mpls "decode as..." menu;
130 * this way, mpls_default_payload will be automatically filled up when
131 * new mpls-specific dissector added.
133 static enum_val_t mpls_default_payload_defs[] = {
136 ,pwc_longname_pw_satop
141 ,pwc_longname_pw_cesopsn
145 "mpls pw ethernet heuristic"
146 ,"Ethernet MPLS PW (CW is heuristically detected)"
151 ,"Frame relay DLCI MPLS PW"
155 "mpls pw hdlc no_cw fr_port"
156 ,"HDLC MPLS PW (no CW), FR Port mode"
157 ,MDD_MPLS_PW_HDLC_NOCW_FRPORT
160 "mpls pw hdlc no_cw hdlc payload_ppp"
161 ,"HDLC MPLS PW (no CW), HDLC mode, PPP payload"
162 ,MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP
165 "mpls pw ethernet cw"
166 ,"Ethernet MPLS PW (with CW)"
170 "mpls pw ethernet no_cw"
171 ,"Ethernet MPLS PW (no CW, early implementations)"
172 ,MDD_MPLS_PW_ETH_NOCW
176 ,"Generic MPLS PW (with Generic/Preferred MPLS CW)"
185 "mpls pw atm n_to_one cw"
186 ,pwc_longname_pw_atm_n1_cw
187 ,MDD_MPLS_PW_ATM_N1_CW
190 "mpls pw atm n_to_one no_cw"
191 ,pwc_longname_pw_atm_n1_nocw
192 ,MDD_MPLS_PW_ATM_N1_NOCW
195 "mpls pw atm one_to_one or aal5_pdu"
196 ,pwc_longname_pw_atm_11_or_aal5_pdu
197 ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
200 "mpls pw atm aal5_sdu"
201 ,pwc_longname_pw_atm_aal5_sdu
202 ,MDD_MPLS_PW_ATM_AAL5_SDU
211 static int mpls_filter[MPLSF_MAX];
213 static gint mpls_default_payload = 0;
214 static gboolean mpls_pref_pwac_all_as_bfd_xipv4 = FALSE;
215 static gboolean mpls_pref_pwac_0x0_as_bfd = FALSE;
216 static gboolean mpls_pref_pwac_try_ppp = TRUE;
218 static int hf_mpls_1st_nibble = -1;
220 static int hf_mpls_pw_ach_ver = -1;
221 static int hf_mpls_pw_ach_res = -1;
222 static int hf_mpls_pw_ach_channel_type = -1;
224 static int hf_mpls_pw_mcw_flags = -1;
225 static int hf_mpls_pw_mcw_length = -1;
226 static int hf_mpls_pw_mcw_sequence_number = -1;
228 static int hf_mpls_oam_function_type = -1;
229 static int hf_mpls_oam_ttsi = -1;
230 static int hf_mpls_oam_frequency = -1;
231 static int hf_mpls_oam_defect_type = -1;
232 static int hf_mpls_oam_defect_location = -1;
233 static int hf_mpls_oam_bip16 = -1;
235 static const value_string oam_function_type_vals[] = {
237 {0x01, "CV (Connectivity Verification)"},
238 {0x02, "FDI (Forward Defect Indicator)"},
239 {0x03, "BDI (Backward Defect Indicator)"},
240 {0x04, "Reserved for Performance packets"},
241 {0x05, "Reserved for LB-Req (Loopback Request)"},
242 {0x06, "Reserved for LB-Rsp (Loopback Response)"},
243 {0x07, "FDD (Fast Failure Detection)"},
247 static const value_string oam_frequency_vals[] = {
251 {0x03, "50 ms (default value)"},
259 static const value_string oam_defect_type_vals[] = {
260 {0x0000, "Reserved"},
264 {0x0202, "dTTSI_Mismatch"},
265 {0x0203, "dTTSI_Mismerge"},
267 {0x02FF, "dUnknown"},
268 {0xFFFF, "Reserved"},
272 #if 0 /*not used yet*/
275 * http://www.iana.org/assignments/pwe3-parameters
277 static const value_string mpls_pw_types[] = {
278 { 0x0001, "Frame Relay DLCI ( Martini Mode )" },
279 { 0x0002, "ATM AAL5 SDU VCC transport" },
280 { 0x0003, "ATM transparent cell transport" },
281 { 0x0004, "Ethernet Tagged Mode" },
282 { 0x0005, "Ethernet" },
285 { 0x0008, "SONET/SDH Circuit Emulation Service Over MPLS" },
286 { 0x0009, "ATM n-to-one VCC cell transport" },
287 { 0x000A, "ATM n-to-one VPC cell transport" },
288 { 0x000B, "IP Layer2 Transport" },
289 { 0x000C, "ATM one-to-one VCC Cell Mode" },
290 { 0x000D, "ATM one-to-one VPC Cell Mode" },
291 { 0x000E, "ATM AAL5 PDU VCC transport" },
292 { 0x000F, "Frame-Relay Port mode" },
293 { 0x0010, "SONET/SDH Circuit Emulation over Packet" },
294 { 0x0011, "Structure-agnostic E1 over Packet" },
295 { 0x0012, "Structure-agnostic T1 (DS1) over Packet" },
296 { 0x0013, "Structure-agnostic E3 over Packet" },
297 { 0x0014, "Structure-agnostic T3 (DS3) over Packet" },
298 { 0x0015, "CESoPSN basic mode" },
299 { 0x0016, "TDMoIP AAL1 Mode" },
300 { 0x0017, "CESoPSN TDM with CAS" },
301 { 0x0018, "TDMoIP AAL2 Mode" },
302 { 0x0019, "Frame Relay DLCI" },
303 { 0x001A, "ROHC Transport Header-compressed Packets" },/*[RFC4995][RFC4901]*/
304 { 0x001B, "ECRTP Transport Header-compressed Packets" },/*[RFC3545][RFC4901]*/
305 { 0x001C, "IPHC Transport Header-compressed Packets" },/*[RFC2507][RFC4901]*/
306 { 0x001D, "cRTP Transport Header-compressed Packets" },/*[RFC2508][RFC4901]*/
307 { 0x001E, "ATM VP Virtual Trunk" },/*[MFA9]*/
308 { 0x001F, "Reserved" },/*[Bryant] 2008-04-17*/
314 * MPLS PW Associated Channel Types
315 * as per http://www.iana.org/assignments/pwe3-parameters
316 * and http://tools.ietf.org/html/draft-ietf-pwe3-vccv-bfd-05 clause 3.2
318 static const value_string mpls_pwac_types[] = {
319 { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
320 { 0x0021, "IPv4 packet" },
321 { 0x0057, "IPv6 packet" },
326 static dissector_table_t ppp_subdissector_table;
327 static dissector_table_t mpls_subdissector_table;
330 * Given a 4-byte MPLS label starting at offset "offset", in tvbuff "tvb",
332 * Return the label in "label", EXP bits in "exp",
333 * bottom_of_stack in "bos", and TTL in "ttl"
335 void decode_mpls_label(tvbuff_t *tvb, int offset,
336 guint32 *label, guint8 *exp,
337 guint8 *bos, guint8 *ttl)
339 guint8 octet0 = tvb_get_guint8(tvb, offset+0);
340 guint8 octet1 = tvb_get_guint8(tvb, offset+1);
341 guint8 octet2 = tvb_get_guint8(tvb, offset+2);
343 *label = (octet0 << 12) + (octet1 << 4) + ((octet2 >> 4) & 0xff);
344 *exp = (octet2 >> 1) & 0x7;
345 *bos = (octet2 & 0x1);
346 *ttl = tvb_get_guint8(tvb, offset+3);
350 * FF: PW Associated Channel Header dissection as per RFC 4385.
353 dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
355 proto_tree *mpls_pw_ach_tree = NULL;
356 proto_item *ti = NULL;
357 tvbuff_t *next_tvb = NULL;
360 guint16 channel_type = 0;
362 if (tvb_reported_length_remaining(tvb, 0) < 4) {
364 proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
367 ver = (tvb_get_guint8(tvb, 0) & 0x0F);
368 res = tvb_get_guint8(tvb, 1);
369 channel_type = tvb_get_ntohs(tvb, 2);
371 ti = proto_tree_add_item(tree, proto_pw_ach, tvb, 0, 4, FALSE);
372 mpls_pw_ach_tree = proto_item_add_subtree(ti, ett_mpls_pw_ach);
373 if (mpls_pw_ach_tree == NULL)
375 proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_ver,
376 tvb, 0, 1, ver, "Version: %d", ver);
377 ti = proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
378 tvb, 1, 1, res, "Reserved: 0x%02x", res);
380 proto_tree_add_text(mpls_pw_ach_tree, tvb, 1, 1,
381 "Error: this byte is reserved and must be 0");
383 PROTO_ITEM_SET_HIDDEN(ti);
384 proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
385 tvb, 2, 2, channel_type,
386 "Channel Type: %s (0x%04x)",
387 val_to_str(channel_type, mpls_pwac_types, "Unknown"),
390 next_tvb = tvb_new_subset_remaining(tvb, 4);
392 if (0x21 == channel_type /*IPv4, RFC4385 clause 6.*/)
394 call_dissector(dissector_ip, next_tvb, pinfo, tree);
396 else if (0x7 == channel_type /*PWACH-encapsulated BFD, draft-ietf-pwe3-vccv-bfd-05 3.2*/
397 || mpls_pref_pwac_all_as_bfd_xipv4)
399 call_dissector(dissector_bfd, next_tvb, pinfo, tree);
401 else if (0x57 == channel_type /*IPv6, RFC4385 clause 6.*/)
403 call_dissector(dissector_ipv6, next_tvb, pinfo, tree);
405 else if (0x0 == channel_type && mpls_pref_pwac_0x0_as_bfd)
407 call_dissector(dissector_bfd, next_tvb, pinfo, tree);
409 else if (mpls_pref_pwac_try_ppp)
411 /* XXX perhaps this code should be reconsidered */
412 /* non-standard extension, therefore controlled by option*/
413 /* appeared in revision 10862 from Carlos M. Pignataro */
414 if (!dissector_try_port(ppp_subdissector_table, channel_type,
415 next_tvb, pinfo, tree)) {
416 call_dissector(dissector_data, next_tvb, pinfo, tree);
421 call_dissector(dissector_data, next_tvb, pinfo, tree);
425 gboolean dissect_try_cw_first_nibble( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
428 nibble = (tvb_get_guint8(tvb, 0 ) >> 4) & 0x0F;
432 call_dissector( dissector_ipv6, tvb, pinfo, tree);
435 call_dissector( dissector_ip, tvb, pinfo, tree);
438 dissect_pw_ach( tvb, pinfo, tree );
447 * FF: Generic/Preferred PW MPLS Control Word dissection as per RFC 4385.
450 dissect_pw_mcw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
452 proto_tree *mpls_pw_mcw_tree = NULL;
453 proto_item *ti = NULL;
454 tvbuff_t *next_tvb = NULL;
458 guint16 sequence_number = 0;
460 if (tvb_reported_length_remaining(tvb, 0) < 4) {
462 proto_tree_add_text(tree, tvb, 0, -1, "Error processing Message");
466 if ( dissect_try_cw_first_nibble( tvb, pinfo, tree ))
469 /* bits 4 to 7 and FRG bits are displayed together */
470 flags = (tvb_get_guint8(tvb, 0) & 0x0F) << 2;
471 frg = (tvb_get_guint8(tvb, 1) & 0xC0) >> 6;
473 length = tvb_get_guint8(tvb, 1) & 0x3F;
474 sequence_number = tvb_get_ntohs(tvb, 2);
476 ti = proto_tree_add_item(tree, proto_pw_mcw, tvb, 0, 4, FALSE);
477 mpls_pw_mcw_tree = proto_item_add_subtree(ti, ett_mpls_pw_mcw);
478 if (mpls_pw_mcw_tree == NULL)
480 proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_flags,
481 tvb, 0, 1, flags, "Flags: 0x%02x", flags);
482 ti = proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_length,
483 tvb, 1, 1, length, "Length: %u", length);
484 proto_tree_add_uint_format(mpls_pw_mcw_tree, hf_mpls_pw_mcw_sequence_number,
485 tvb, 2, 2, sequence_number,
486 "Sequence Number: %d", sequence_number);
488 next_tvb = tvb_new_subset_remaining(tvb, 4);
489 call_dissector( dissector_data, next_tvb, pinfo, tree );
493 dissect_mpls_oam_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *mpls_tree,
494 int offset, guint8 exp, guint8 bos, guint8 ttl)
496 proto_tree *mpls_oam_tree = NULL;
497 proto_item *ti = NULL;
499 const guint8 allone[] = { 0xff, 0xff };
500 const guint8 allzero[] = { 0x00, 0x00, 0x00, 0x00, 0x00,
501 0x00, 0x00, 0x00, 0x00, 0x00,
502 0x00, 0x00, 0x00, 0x00, 0x00,
503 0x00, 0x00, 0x00, 0x00, 0x00 };
505 /* if called with main tree == null just set col info with func type string and return */
507 if (check_col(pinfo->cinfo, COL_INFO)) {
508 if (tvb_bytes_exist(tvb, offset, 1)) {
509 functype = tvb_get_guint8(tvb, offset);
510 col_append_fstr(pinfo->cinfo, COL_INFO, " (OAM: %s)",
511 (functype == 0x01) ? "CV" :
512 (functype == 0x02) ? "FDI" :
513 (functype == 0x03) ? "BDI" :
514 (functype == 0x07) ? "FDD" : "reserved/unknown");
524 if (!tvb_bytes_exist(tvb, offset, 44)) {
525 /* ITU-T Y.1711, 5.3: OAM pdus must have a minimum payload length of 44 bytes */
526 proto_tree_add_text(mpls_tree, tvb, offset, -1, "Error: must have a minimum payload length of 44 bytes");
530 ti = proto_tree_add_text(mpls_tree, tvb, offset, 44, "MPLS Operation & Maintenance");
531 mpls_oam_tree = proto_item_add_subtree(ti, ett_mpls_oam);
536 /* checks for exp, bos and ttl encoding */
539 proto_tree_add_text(mpls_oam_tree, tvb, offset - 2, 1, "Warning: Exp bits should be 0 for OAM");
542 proto_tree_add_text(mpls_oam_tree, tvb, offset - 2, 1, "Warning: S bit should be 1 for OAM");
545 proto_tree_add_text(mpls_oam_tree, tvb, offset - 1, 1, "Warning: TTL should be 1 for OAM");
547 /* starting dissection */
549 functype = tvb_get_guint8(tvb, offset);
550 proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_function_type, tvb, offset, 1, TRUE);
556 guint32 lsrid_ipv4addr;
558 /* 3 octets reserved (all 0x00) */
559 if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
560 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
561 "Error: these bytes are reserved and must be 0x00");
565 /* ttsi (ipv4 flavor as in RFC 2373) */
566 if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
567 proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
568 "Error: these bytes are padding and must be 0x00");
572 if (tvb_memeql(tvb, offset, allone, 2) == -1) {
573 proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
574 "Error: these bytes are padding and must be 0xFF");
578 lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
579 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
582 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
585 /* 18 octets of padding (all 0x00) */
586 if (tvb_memeql(tvb, offset, allzero, 18) == -1) {
587 proto_tree_add_text(mpls_oam_tree, tvb, offset, 18,
588 "Error: these bytes are padding and must be 0x00");
597 guint32 lsrid_ipv4addr;
599 /* 1 octets reserved (all 0x00) */
600 if (tvb_memeql(tvb, offset, allzero, 1) == -1) {
601 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
602 "Error: this byte is reserved and must be 0x00");
606 proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_defect_type, tvb, offset, 2, TRUE);
609 /* ttsi (ipv4 flavor as in RFC 2373) is optional if not used must be set to all 0x00 */
610 if (tvb_memeql(tvb, offset, allzero, 20) == 0) {
611 proto_tree_add_text(mpls_oam_tree, tvb, offset, 20, "TTSI not preset (optional for FDI/BDI)");
614 if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
615 proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
616 "Error: these bytes are padding and must be 0x00");
620 if (tvb_memeql(tvb, offset, allone, 2) == -1) {
621 proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
622 "Error: these bytes are padding and must be 0xFF");
626 lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
627 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
630 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
634 /* defect location */
635 proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_defect_location, tvb, offset, 4, TRUE);
638 /* 14 octets of padding (all 0x00) */
639 if (tvb_memeql(tvb, offset, allzero, 14) == -1) {
640 proto_tree_add_text(mpls_oam_tree, tvb, offset, 14,
641 "Error: these bytes are padding and must be 0x00");
649 guint32 lsrid_ipv4addr;
651 /* 3 octets reserved (all 0x00) */
652 if (tvb_memeql(tvb, offset, allzero, 3) == -1) {
653 proto_tree_add_text(mpls_oam_tree, tvb, offset, 3,
654 "Error: these bytes are reserved and must be 0x00");
658 /* ttsi (ipv4 flavor as in RFC 2373) */
659 if (tvb_memeql(tvb, offset, allzero, 10) == -1) {
660 proto_tree_add_text(mpls_oam_tree, tvb, offset, 10,
661 "Error: these bytes are padding and must be 0x00");
665 if (tvb_memeql(tvb, offset, allone, 2) == -1) {
666 proto_tree_add_text(mpls_oam_tree, tvb, offset, 2,
667 "Error: these bytes are padding and must be 0xFF");
671 lsrid_ipv4addr = tvb_get_ipv4(tvb, offset);
672 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSR ID: %s", ip_to_str((guint8 *)&lsrid_ipv4addr));
675 proto_tree_add_text(mpls_oam_tree, tvb, offset, 4, "LSP ID: %d", tvb_get_ntohl(tvb, offset));
678 proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_frequency, tvb, offset, 1, TRUE);
681 /* 17 octets of padding (all 0x00) */
682 if (tvb_memeql(tvb, offset, allzero, 17) == -1) {
683 proto_tree_add_text(mpls_oam_tree, tvb, offset, 17,
684 "Error: these bytes are padding and must be 0x00");
691 proto_tree_add_text(mpls_oam_tree, tvb, offset - 1, -1, "Unknown MPLS OAM pdu");
696 proto_tree_add_item(mpls_oam_tree, hf_mpls_oam_bip16, tvb, offset, 2, TRUE);
701 dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
704 guint32 label = LABEL_INVALID;
708 proto_tree *mpls_tree = NULL;
712 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS");
714 col_set_str(pinfo->cinfo, COL_INFO, "MPLS Label Switched Packet");
716 /* Start Decoding Here. */
717 while (tvb_reported_length_remaining(tvb, offset) > 0) {
719 decode_mpls_label(tvb, offset, &label, &exp, &bos, &ttl);
720 pinfo->mpls_label = label;
724 ti = proto_tree_add_item(tree, proto_mpls, tvb, offset, 4, FALSE);
725 mpls_tree = proto_item_add_subtree(ti, ett_mpls);
727 proto_item_append_text(ti, ", Label: %u", label);
728 if (label <= LABEL_MAX_RESERVED){
729 proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
730 offset, 3, label, "MPLS Label: %u (%s)",
731 label, val_to_str(label, special_labels,
732 "Reserved - Unknown"));
733 proto_item_append_text(ti, " (%s)", val_to_str(label, special_labels,
734 "Reserved - Unknown"));
736 proto_tree_add_uint_format(mpls_tree, mpls_filter[MPLSF_LABEL], tvb,
737 offset, 3, label, "MPLS Label: %u", label);
740 proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_EXP], tvb,
742 proto_item_append_text(ti, ", Exp: %u", exp);
744 proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_BOTTOM_OF_STACK], tvb,
746 proto_item_append_text(ti, ", S: %u", bos);
748 proto_tree_add_uint(mpls_tree,mpls_filter[MPLSF_TTL], tvb,
750 proto_item_append_text(ti, ", TTL: %u", ttl);
753 if (label == LABEL_OAM_ALERT) {
754 /* OAM pdus are injected in normal data plane flow in order to test a LSP,
755 * they carry no user data.
757 dissect_mpls_oam_pdu(tvb, pinfo, tree, mpls_tree, offset + 4, exp, bos, ttl);
765 next_tvb = tvb_new_subset_remaining(tvb, offset);
767 if ( !dissector_try_port(mpls_subdissector_table, label, next_tvb, pinfo, tree))
769 switch ( mpls_default_payload )
772 call_dissector(dissector_pw_satop, next_tvb, pinfo, tree);
775 call_dissector(dissector_pw_cesopsn, next_tvb, pinfo, tree);
777 case MDD_PW_ETH_HEUR:
778 call_dissector(dissector_pw_eth_heuristic, next_tvb, pinfo, tree);
780 case MDD_MPLS_PW_FR_DLCI:
781 call_dissector(dissector_pw_fr, next_tvb, pinfo, tree);
783 case MDD_MPLS_PW_HDLC_NOCW_FRPORT:
784 call_dissector(dissector_pw_hdlc_nocw_fr, next_tvb, pinfo, tree);
786 case MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP:
787 call_dissector(dissector_pw_hdlc_nocw_hdlc_ppp, next_tvb, pinfo, tree);
789 case MDD_MPLS_PW_ETH_CW:
790 call_dissector(dissector_pw_eth_cw, next_tvb, pinfo, tree);
792 case MDD_MPLS_PW_ETH_NOCW:
793 call_dissector(dissector_pw_eth_nocw, next_tvb, pinfo, tree);
796 call_dissector(dissector_itdm, next_tvb, pinfo, tree);
798 case MDD_MPLS_PW_ATM_N1_CW:
799 call_dissector(dissector_mpls_pw_atm_n1_cw, next_tvb, pinfo, tree);
801 case MDD_MPLS_PW_ATM_N1_NOCW:
802 call_dissector(dissector_mpls_pw_atm_n1_nocw, next_tvb, pinfo, tree);
804 case MDD_MPLS_PW_ATM_11_OR_AAL5_PDU:
805 call_dissector(dissector_mpls_pw_atm_11_aal5pdu, next_tvb, pinfo, tree);
807 case MDD_MPLS_PW_ATM_AAL5_SDU:
808 call_dissector(dissector_mpls_pw_atm_aal5_sdu, next_tvb, pinfo, tree);
810 default: /*fallthrough*/
811 case MDD_MPLS_PW_GENERIC:
812 dissect_pw_mcw(next_tvb, pinfo, tree);
819 proto_register_mpls(void)
821 static hf_register_info mplsf_info[] = {
823 /* MPLS header fields */
824 {&mpls_filter[MPLSF_LABEL],
825 {"MPLS Label", "mpls.label", FT_UINT32, BASE_DEC, VALS(special_labels), 0x0,
828 {&mpls_filter[MPLSF_EXP],
829 {"MPLS Experimental Bits", "mpls.exp", FT_UINT8, BASE_DEC, NULL, 0x0,
832 {&mpls_filter[MPLSF_BOTTOM_OF_STACK],
833 {"MPLS Bottom Of Label Stack", "mpls.bottom", FT_UINT8, BASE_DEC, NULL, 0x0,
836 {&mpls_filter[MPLSF_TTL],
837 {"MPLS TTL", "mpls.ttl", FT_UINT8, BASE_DEC, NULL, 0x0,
841 {&hf_mpls_1st_nibble,
842 {"MPLS 1st nibble", "mpls.1st_nibble", FT_UINT8,
843 BASE_DEC, NULL, 0x0, NULL, HFILL }},
845 /* PW Associated Channel Header fields */
846 {&hf_mpls_pw_ach_ver,
847 {"PW Associated Channel Version", "pwach.ver", FT_UINT8, BASE_DEC,
848 NULL, 0x0, NULL, HFILL }},
850 {&hf_mpls_pw_ach_res,
851 {"Reserved", "pwach.res", FT_UINT8, BASE_DEC,
852 NULL, 0x0, NULL, HFILL }},
854 {&hf_mpls_pw_ach_channel_type,
855 {"PW Associated Channel Type", "pwach.channel_type", FT_UINT16, BASE_HEX,
856 NULL, 0x0, NULL, HFILL }},
858 /* Generic/Preferred PW MPLS Control Word fields */
859 {&hf_mpls_pw_mcw_flags,
860 {"Generic/Preferred PW MPLS Control Word Flags", "pwmcw.flags", FT_UINT8,
861 BASE_HEX, NULL, 0x0, NULL,
864 {&hf_mpls_pw_mcw_length,
865 {"Generic/Preferred PW MPLS Control Word Length", "pwmcw.length", FT_UINT8,
866 BASE_DEC, NULL, 0x0, NULL,
869 {&hf_mpls_pw_mcw_sequence_number,
870 {"Generic/Preferred PW MPLS Control Word Sequence Number",
871 "pwmcw.sequence_number", FT_UINT16, BASE_DEC, NULL, 0x0,
874 /* OAM header fields */
875 {&hf_mpls_oam_function_type,
876 {"Function Type", "mpls.oam.function_type", FT_UINT8,
877 BASE_HEX, VALS(oam_function_type_vals), 0x0, "Function Type codepoint", HFILL }},
880 {"Trail Termination Source Identifier", "mpls.oam.ttsi", FT_UINT32,
881 BASE_HEX, NULL, 0x0, NULL, HFILL }},
883 {&hf_mpls_oam_frequency,
884 {"Frequency", "mpls.oam.frequency", FT_UINT8,
885 BASE_HEX, VALS(oam_frequency_vals), 0x0, "Frequency of probe injection", HFILL }},
887 {&hf_mpls_oam_defect_type,
888 {"Defect Type", "mpls.oam.defect_type", FT_UINT16,
889 BASE_HEX, VALS(oam_defect_type_vals), 0x0, NULL, HFILL }},
891 {&hf_mpls_oam_defect_location,
892 {"Defect Location (AS)", "mpls.oam.defect_location", FT_UINT32,
893 BASE_DEC, NULL, 0x0, "Defect Location", HFILL }},
896 {"BIP16", "mpls.oam.bip16", FT_UINT16,
897 BASE_HEX, NULL, 0x0, NULL, HFILL }},
900 static gint *ett[] = {
906 module_t * module_mpls;
908 /* FF: mpls subdissector table is indexed by label */
909 mpls_subdissector_table = register_dissector_table("mpls.label",
911 FT_UINT32, BASE_DEC);
912 proto_mpls = proto_register_protocol("MultiProtocol Label Switching Header",
914 proto_pw_ach = proto_register_protocol("PW Associated Channel Header",
915 "PW Associated Channel", "pwach");
916 proto_pw_mcw = proto_register_protocol("PW MPLS Control Word (generic/preferred)",
917 "Generic PW (with CW)", "pwmcw");
919 proto_register_field_array(proto_mpls, mplsf_info, array_length(mplsf_info));
920 proto_register_subtree_array(ett, array_length(ett));
921 register_dissector("mpls", dissect_mpls, proto_mpls);
922 register_dissector("mplspwcw", dissect_pw_mcw, proto_pw_mcw );
924 module_mpls = prefs_register_protocol( proto_mpls, proto_reg_handoff_mpls );
926 prefs_register_enum_preference( module_mpls,
928 "Default decoder for MPLS payload",
929 "Default decoder for MPLS payload",
930 &mpls_default_payload,
931 mpls_default_payload_defs,
933 prefs_register_bool_preference(module_mpls
934 ,"mplspref.pwac_0x0_as_bfd"
935 ,"Assume PWAC Channel Type 0x0 is raw BFD"
936 ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
937 " when VCCV carries PW-ACH-encapsulated BFD (i.e., BFD without IP/UDP Headers, or \"raw\" BFD)"
939 "Legacy or buggy devices may not comply to this and use Channel Type 0x0 for BFD."
940 " Enable this preference to decode such BFD traffic."
941 " Disable for standard behavior of PWAC dissector (default)."
942 ,&mpls_pref_pwac_0x0_as_bfd);
943 prefs_register_bool_preference(module_mpls
944 ,"mplspref.pwac_all_as_bfd_xip"
945 ,"Assume that all PWAC Channel Types (except 0x21) are raw BFD"
946 ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
947 " when VCCV carries PW-ACH-encapsulated BFD (i.e., \"raw\" BFD)"
949 "Legacy or buggy devices may not comply to this and use voluntary Channel Type for BFD."
950 " Enable this preference to decode all PWAC Channel Types as raw BFD,"
951 " except Channel Type 0x21 (IPv4)."
952 " Disable for standard behavior of PWAC dissector (default)."
953 ,&mpls_pref_pwac_all_as_bfd_xipv4);
954 prefs_register_bool_preference(module_mpls
955 ,"mplspref.pwac_try_ppp"
956 ,"As a last resort, try to decode PWAC payloads as PPP traffic"
957 ,"Legacy devices may use MPLS PW Associated Channel for PPP traffic."
959 "Enable this preference to allow PWAC dissector to try PPP,"
960 " if no other suitable dissector found (default)."
961 ,&mpls_pref_pwac_try_ppp);
965 proto_reg_handoff_mpls(void)
967 static gboolean initialized=FALSE;
971 dissector_handle_t mpls_handle;
973 ppp_subdissector_table = find_dissector_table("ppp.protocol");
975 mpls_handle = find_dissector("mpls");
976 dissector_add("ethertype", ETHERTYPE_MPLS, mpls_handle);
977 dissector_add("ethertype", ETHERTYPE_MPLS_MULTI, mpls_handle);
978 dissector_add("ppp.protocol", PPP_MPLS_UNI, mpls_handle);
979 dissector_add("ppp.protocol", PPP_MPLS_MULTI, mpls_handle);
980 dissector_add("chdlctype", ETHERTYPE_MPLS, mpls_handle);
981 dissector_add("chdlctype", ETHERTYPE_MPLS_MULTI, mpls_handle);
982 dissector_add("gre.proto", ETHERTYPE_MPLS, mpls_handle);
983 dissector_add("gre.proto", ETHERTYPE_MPLS_MULTI, mpls_handle);
984 dissector_add("ip.proto", IP_PROTO_MPLS_IN_IP, mpls_handle);
986 mpls_handle = find_dissector("mplspwcw");
987 dissector_add( "mpls.label", LABEL_INVALID, mpls_handle );
989 dissector_data = find_dissector("data");
990 dissector_ipv6 = find_dissector("ipv6");
991 dissector_ip = find_dissector("ip");
992 dissector_bfd = find_dissector("bfd");
993 dissector_pw_eth_heuristic = find_dissector("pw_eth_heuristic");
994 dissector_pw_fr = find_dissector("pw_fr");
995 dissector_pw_hdlc_nocw_fr = find_dissector("pw_hdlc_nocw_fr");
996 dissector_pw_hdlc_nocw_hdlc_ppp = find_dissector("pw_hdlc_nocw_hdlc_ppp");
997 dissector_pw_eth_cw = find_dissector("pw_eth_cw");
998 dissector_pw_eth_nocw = find_dissector("pw_eth_nocw");
999 dissector_pw_satop = find_dissector("pw_satop_mpls");
1000 dissector_itdm = find_dissector("itdm");
1001 dissector_mpls_pw_atm_n1_cw = find_dissector("mpls_pw_atm_n1_cw");
1002 dissector_mpls_pw_atm_n1_nocw = find_dissector("mpls_pw_atm_n1_nocw");
1003 dissector_mpls_pw_atm_11_aal5pdu= find_dissector("mpls_pw_atm_11_or_aal5_pdu");
1004 dissector_mpls_pw_atm_aal5_sdu = find_dissector("mpls_pw_atm_aal5_sdu");
1005 dissector_pw_cesopsn = find_dissector("pw_cesopsn_mpls");