2 * Routines for Bit Index Explicit Replication (BIER) dissection
4 * Copyright 2024, John Thacker <johnthacker@gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
12 * RFC 8296: https://www.rfc-editor.org/rfc/rfc8296.html
17 #include <epan/packet.h>
19 void proto_register_bier(void);
20 void proto_reg_handoff_bier(void);
22 static int proto_bier
;
24 static int hf_bier_nibble
;
25 static int hf_bier_ver
;
26 static int hf_bier_bsl
;
27 static int hf_bier_entropy
;
28 static int hf_bier_oam
;
29 static int hf_bier_rsv
;
30 static int hf_bier_dscp
;
31 static int hf_bier_proto
;
32 static int hf_bier_bfir_id
;
33 static int hf_bier_bitstring
;
37 static dissector_table_t bier_subdissector_table
;
39 static dissector_handle_t bier_handle
;
41 static const value_string bier_bsl_vals
[] = {
52 // https://www.iana.org/assignments/bier/bier.xhtml#bier-next-protocol-identifiers
53 static const value_string bier_proto_vals
[] = {
55 { 1, "MPLS packet with downstream-assigned label at top of stack" },
56 { 2, "MPLS packet with upstream-assigned label at top of stack" },
57 { 3, "Ethernet frame" },
61 { 7, "Payload is VXLAN encapsulated (no IP/UDP header)" },
62 { 8, "Payload is NVGRE encapsulated (no IP header)" },
63 { 9, "Payload is GENEVE encapsulated (no IP/UDP header)" },
69 dissect_bier(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, void* data _U_
)
72 proto_tree
*bier_tree
;
78 if (tvb_reported_length(tvb
) < 16) {
82 if (tvb_captured_length(tvb
) < 2) {
86 /* This nibble is ignored in non-MPLS */
87 if (((tvb_get_uint8(tvb
, 0) >> 4) & 0xF) != 0x5) {
91 uint8_t bsl
= (tvb_get_uint8(tvb
, 1) >> 4) & 0xF;
92 if (bsl
== 0 || bsl
> 7) {
96 int bitstring_length
= 1 << (bsl
+ 2);
98 if (tvb_reported_length_remaining(tvb
, 8) < bitstring_length
) {
102 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "BIER");
103 col_clear(pinfo
->cinfo
, COL_INFO
);
105 ti
= proto_tree_add_item(tree
, proto_bier
, tvb
, offset
, 8 + bitstring_length
, ENC_NA
);
107 bier_tree
= proto_item_add_subtree(ti
, ett_bier
);
109 proto_tree_add_item(bier_tree
, hf_bier_nibble
, tvb
, offset
, 1, ENC_NA
);
110 proto_tree_add_item(bier_tree
, hf_bier_ver
, tvb
, offset
, 1, ENC_NA
);
113 proto_tree_add_item(bier_tree
, hf_bier_bsl
, tvb
, offset
, 1, ENC_NA
);
114 proto_tree_add_item(bier_tree
, hf_bier_entropy
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
117 proto_tree_add_item(bier_tree
, hf_bier_oam
, tvb
, offset
, 1, ENC_NA
);
118 proto_tree_add_item(bier_tree
, hf_bier_rsv
, tvb
, offset
, 1, ENC_NA
);
119 /* DSCP field unused in MPLS; may be as IP DSCP in non-MPLS. */
120 proto_tree_add_item(bier_tree
, hf_bier_dscp
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
123 proto_tree_add_item_ret_uint(bier_tree
, hf_bier_proto
, tvb
, offset
, 1, ENC_NA
, &proto
);
124 col_add_str(pinfo
->cinfo
, COL_INFO
, val_to_str_wmem(pinfo
->pool
, proto
, bier_proto_vals
, "Unknown (0x%02x)"));
127 proto_tree_add_item(bier_tree
, hf_bier_bfir_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
130 proto_tree_add_item(bier_tree
, hf_bier_bitstring
, tvb
, offset
, bitstring_length
, ENC_NA
);
131 offset
+= bitstring_length
;
133 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
134 if (!dissector_try_uint(bier_subdissector_table
, proto
, next_tvb
, pinfo
, tree
)) {
135 call_data_dissector(next_tvb
, pinfo
, tree
);
138 return tvb_captured_length(tvb
);
142 proto_register_bier(void)
144 static hf_register_info hf
[] = {
148 "Nibble", "bier.nibble", FT_UINT8
,
149 BASE_HEX
, NULL
, 0xF0, NULL
, HFILL
155 "Version", "bier.ver", FT_UINT8
,
156 BASE_DEC
, NULL
, 0x0F, NULL
, HFILL
162 "BitString Length", "bier.bsl", FT_UINT8
,
163 BASE_DEC
, VALS(bier_bsl_vals
), 0xF0, NULL
, HFILL
169 "Entropy", "bier.entropy", FT_UINT24
,
170 BASE_HEX
, NULL
, 0x0FFFFF, NULL
, HFILL
176 "OAM", "bier.oam", FT_UINT8
,
177 BASE_HEX
, NULL
, 0xC0, NULL
, HFILL
183 "Rsv", "bier.rsv", FT_UINT8
,
184 BASE_HEX
, NULL
, 0x30, NULL
, HFILL
190 "DSCP", "bier.dscp", FT_UINT16
,
191 BASE_HEX
, NULL
, 0x0FC0, NULL
, HFILL
197 "Next Protocol", "bier.proto", FT_UINT8
,
198 BASE_HEX
, VALS(bier_proto_vals
), 0x3F, NULL
, HFILL
204 "BFIR-id", "bier.bfir-id", FT_UINT16
,
205 BASE_DEC
, NULL
, 0x0, NULL
, HFILL
211 "BitString", "bier.bitstring", FT_BYTES
,
212 BASE_NONE
, NULL
, 0x0, NULL
, HFILL
217 static int *ett
[] = {
222 proto_register_protocol("Bit Index Explicit Replication", "BIER", "bier");
224 proto_register_field_array(proto_bier
, hf
, array_length(hf
));
225 proto_register_subtree_array(ett
, array_length(ett
));
226 bier_handle
= register_dissector_with_description("bier.mpls", "BIER encapsulated in MPLS", dissect_bier
, proto_bier
);
228 bier_subdissector_table
= register_dissector_table("bier.proto",
229 "BIER Next Protocol", proto_bier
, FT_UINT8
, BASE_DEC
);
233 proto_reg_handoff_bier(void)
235 dissector_handle_t mpls_handle
= find_dissector_add_dependency("mpls", proto_bier
);
237 dissector_add_for_decode_as("mpls.label", bier_handle
);
239 dissector_add_uint("mpls.pfn", 5, bier_handle
);
241 dissector_add_uint("bier.proto", 1, mpls_handle
);
242 dissector_add_uint("bier.proto", 2, mpls_handle
);
243 dissector_add_uint("bier.proto", 3, find_dissector_add_dependency("eth_maybefcs", proto_bier
));
244 dissector_add_uint("bier.proto", 4, find_dissector_add_dependency("ip", proto_bier
));
245 /* 5 is BIER OAM - https://datatracker.ietf.org/doc/draft-ietf-bier-ping/ */
246 dissector_add_uint("bier.proto", 6, find_dissector_add_dependency("ipv6", proto_bier
));
247 dissector_add_uint("bier.proto", 7, find_dissector_add_dependency("vxlan", proto_bier
));
248 dissector_add_uint("bier.proto", 8, find_dissector_add_dependency("gre", proto_bier
));
249 dissector_add_uint("bier.proto", 9, find_dissector_add_dependency("geneve", proto_bier
));