/src/wireshark/epan/dissectors/packet-vpp.c
Line | Count | Source |
1 | | /* packet-vpp.c |
2 | | * |
3 | | * Routines for the disassembly of fd.io vpp project |
4 | | * dispatch captures |
5 | | * |
6 | | * Copyright 2019, Dave Barach <wireshark@barachs.net> |
7 | | * |
8 | | * Wireshark - Network traffic analyzer |
9 | | * By Gerald Combs <gerald@wireshark.org> |
10 | | * Copyright 1998 Gerald Combs |
11 | | * |
12 | | * SPDX-License-Identifier: GPL-2.0-or-later |
13 | | */ |
14 | | |
15 | | #include "config.h" |
16 | | |
17 | | #include <epan/packet.h> |
18 | | #include <epan/expert.h> |
19 | | #include <epan/to_str.h> |
20 | | #include <epan/etypes.h> |
21 | | #include <wiretap/wtap.h> |
22 | | #include "packet-osi.h" |
23 | | |
24 | | void proto_register_vpp(void); |
25 | | void proto_reg_handoff_vpp(void); |
26 | | |
27 | | static int proto_vpp; |
28 | | static int proto_vpp_metadata; |
29 | | static int proto_vpp_opaque; |
30 | | static int proto_vpp_opaque2; |
31 | | static int proto_vpp_trace; |
32 | | static int hf_vpp_nodename; |
33 | | static int hf_vpp_metadata; |
34 | | static int hf_vpp_buffer_index; |
35 | | static int hf_vpp_buffer_opaque; |
36 | | static int hf_vpp_buffer_opaque2; |
37 | | static int hf_vpp_buffer_trace; |
38 | | static int hf_vpp_major_version; |
39 | | static int hf_vpp_minor_version; |
40 | | static int hf_vpp_protocol_hint; |
41 | | |
42 | | static expert_module_t* expert_vpp; |
43 | | |
44 | | static expert_field ei_vpp_major_version_error; |
45 | | static expert_field ei_vpp_minor_version_error; |
46 | | static expert_field ei_vpp_protocol_hint_error; |
47 | | |
48 | | static int ett_vpp; |
49 | | static int ett_vpp_opaque; |
50 | | static int ett_vpp_opaque2; |
51 | | static int ett_vpp_metadata; |
52 | | static int ett_vpp_trace; |
53 | | |
54 | | static dissector_handle_t vpp_dissector_handle; |
55 | | static dissector_handle_t vpp_opaque_dissector_handle; |
56 | | static dissector_handle_t vpp_opaque2_dissector_handle; |
57 | | static dissector_handle_t vpp_metadata_dissector_handle; |
58 | | static dissector_handle_t vpp_trace_dissector_handle; |
59 | | |
60 | 0 | #define VPP_MAJOR_VERSION 1 |
61 | 0 | #define VPP_MINOR_VERSION 0 |
62 | 0 | #define IP4_TYPICAL_VERSION_LENGTH 0x45 |
63 | 0 | #define IP6_TYPICAL_VERSION_AND_TRAFFIC_CLASS 0x60 |
64 | | |
65 | | typedef enum |
66 | | { |
67 | | VLIB_NODE_PROTO_HINT_NONE = 0, |
68 | | VLIB_NODE_PROTO_HINT_ETHERNET, |
69 | | VLIB_NODE_PROTO_HINT_IP4, |
70 | | VLIB_NODE_PROTO_HINT_IP6, |
71 | | VLIB_NODE_PROTO_HINT_TCP, |
72 | | VLIB_NODE_PROTO_HINT_UDP, |
73 | | VLIB_NODE_N_PROTO_HINTS, |
74 | | } vlib_node_proto_hint_t; |
75 | | |
76 | | static dissector_handle_t next_dissectors[VLIB_NODE_N_PROTO_HINTS]; |
77 | | |
78 | | /* List of next dissectors hints that we know about */ |
79 | 16 | #define foreach_next_dissector \ |
80 | 16 | _(VLIB_NODE_PROTO_HINT_ETHERNET, eth_withoutfcs) \ |
81 | 16 | _(VLIB_NODE_PROTO_HINT_IP4, ip) \ |
82 | 16 | _(VLIB_NODE_PROTO_HINT_IP6, ipv6) \ |
83 | 16 | _(VLIB_NODE_PROTO_HINT_TCP, tcp) \ |
84 | 16 | _(VLIB_NODE_PROTO_HINT_UDP, udp) |
85 | | |
86 | | static void |
87 | | add_multi_line_string_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, |
88 | | int start, |
89 | | int len, int hf) |
90 | 0 | { |
91 | 0 | unsigned next, line_len, data_len; |
92 | |
|
93 | 0 | while(len > 0) { |
94 | 0 | tvb_find_line_end_length(tvb, start, len, &line_len, &next); |
95 | 0 | data_len = next - start; |
96 | 0 | proto_tree_add_string(tree, hf, tvb, start, data_len, |
97 | 0 | tvb_format_stringzpad(pinfo->pool, tvb, start, line_len)); |
98 | 0 | start += data_len; |
99 | 0 | len -= data_len; |
100 | 0 | } |
101 | 0 | } |
102 | | |
103 | | static int |
104 | | dissect_vpp_metadata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
105 | | void* data _U_) |
106 | 0 | { |
107 | 0 | unsigned offset = 0; |
108 | 0 | proto_item *ti; |
109 | 0 | proto_tree *metadata_tree; |
110 | 0 | int metadata_string_length; |
111 | |
|
112 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "VPP-Metadata"); |
113 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
114 | |
|
115 | 0 | ti = proto_tree_add_item(tree, proto_vpp_metadata, tvb, offset, -1, ENC_NA); |
116 | 0 | metadata_tree = proto_item_add_subtree(ti, ett_vpp_metadata); |
117 | | |
118 | | /* How long is the metadata string? */ |
119 | 0 | metadata_string_length = tvb_strsize(tvb, offset); |
120 | |
|
121 | 0 | add_multi_line_string_to_tree(metadata_tree, tvb, pinfo, 0, |
122 | 0 | metadata_string_length, |
123 | 0 | hf_vpp_metadata); |
124 | 0 | return tvb_captured_length(tvb); |
125 | 0 | } |
126 | | |
127 | | static int |
128 | | dissect_vpp_trace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
129 | | void* data _U_) |
130 | 0 | { |
131 | 0 | unsigned offset = 0; |
132 | 0 | proto_item *ti; |
133 | 0 | proto_tree *trace_tree; |
134 | 0 | int trace_string_length; |
135 | |
|
136 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "VPP-Trace"); |
137 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
138 | |
|
139 | 0 | ti = proto_tree_add_item(tree, proto_vpp_trace, tvb, offset, -1, ENC_NA); |
140 | 0 | trace_tree = proto_item_add_subtree(ti, ett_vpp_trace); |
141 | | |
142 | | /* How long is the trace string? */ |
143 | 0 | trace_string_length = tvb_strsize(tvb, offset); |
144 | |
|
145 | 0 | add_multi_line_string_to_tree(trace_tree, tvb, pinfo, 0, |
146 | 0 | trace_string_length, |
147 | 0 | hf_vpp_buffer_trace); |
148 | 0 | return tvb_captured_length(tvb); |
149 | 0 | } |
150 | | |
151 | | |
152 | | static int |
153 | | dissect_vpp_opaque(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
154 | | void* data _U_) |
155 | 0 | { |
156 | 0 | unsigned offset = 0; |
157 | 0 | proto_item *ti; |
158 | 0 | proto_tree *opaque_tree; |
159 | 0 | int opaque_string_length; |
160 | |
|
161 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "VPP-Opaque"); |
162 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
163 | |
|
164 | 0 | ti = proto_tree_add_item(tree, proto_vpp_opaque, tvb, offset, -1, ENC_NA); |
165 | 0 | opaque_tree = proto_item_add_subtree(ti, ett_vpp_opaque); |
166 | |
|
167 | 0 | opaque_string_length = tvb_strsize(tvb, offset); |
168 | 0 | add_multi_line_string_to_tree(opaque_tree, tvb, pinfo, 0, opaque_string_length, |
169 | 0 | hf_vpp_buffer_opaque); |
170 | |
|
171 | 0 | return tvb_captured_length(tvb); |
172 | 0 | } |
173 | | |
174 | | static int |
175 | | dissect_vpp_opaque2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
176 | | void* data _U_) |
177 | 0 | { |
178 | 0 | unsigned offset = 0; |
179 | 0 | proto_item *ti; |
180 | 0 | proto_tree *opaque2_tree; |
181 | 0 | int opaque2_string_length; |
182 | |
|
183 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "VPP-Opaque2"); |
184 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
185 | |
|
186 | 0 | ti = proto_tree_add_item(tree, proto_vpp_opaque2, tvb, offset, -1, ENC_NA); |
187 | 0 | opaque2_tree = proto_item_add_subtree(ti, ett_vpp_opaque2); |
188 | |
|
189 | 0 | opaque2_string_length = tvb_strsize(tvb, offset); |
190 | 0 | add_multi_line_string_to_tree(opaque2_tree, tvb, pinfo, 0, opaque2_string_length, |
191 | 0 | hf_vpp_buffer_opaque2); |
192 | |
|
193 | 0 | return tvb_captured_length(tvb); |
194 | 0 | } |
195 | | |
196 | | |
197 | | static int |
198 | | dissect_vpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
199 | 0 | { |
200 | 0 | proto_item *ti; |
201 | 0 | proto_tree *vpp_tree; |
202 | 0 | tvbuff_t *metadata_tvb, *opaque_tvb, *opaque2_tvb, *eth_tvb, *trace_tvb; |
203 | 0 | unsigned offset = 0; |
204 | 0 | uint8_t major_version, minor_version, string_count, protocol_hint; |
205 | 0 | char *name; |
206 | 0 | unsigned len; |
207 | 0 | uint8_t maybe_protocol_id; |
208 | 0 | dissector_handle_t use_this_dissector; |
209 | |
|
210 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "VPP"); |
211 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
212 | |
|
213 | 0 | ti = proto_tree_add_item(tree, proto_vpp, tvb, offset, -1, ENC_NA); |
214 | 0 | vpp_tree = proto_item_add_subtree(ti, ett_vpp); |
215 | |
|
216 | 0 | major_version = tvb_get_uint8(tvb, offset); |
217 | | /* If the major version doesn't match, quit on the spot */ |
218 | 0 | if(major_version != VPP_MAJOR_VERSION) { |
219 | 0 | proto_item *major_version_item; |
220 | 0 | major_version_item = |
221 | 0 | proto_tree_add_item(tree, hf_vpp_major_version, |
222 | 0 | tvb, offset, 1, ENC_NA); |
223 | 0 | expert_add_info_format(pinfo, major_version_item, |
224 | 0 | &ei_vpp_major_version_error, |
225 | 0 | "Major Version Mismatch read %d not %d", |
226 | 0 | (int)major_version, VPP_MAJOR_VERSION); |
227 | 0 | return tvb_captured_length(tvb); |
228 | 0 | } |
229 | 0 | offset++; |
230 | |
|
231 | 0 | minor_version = tvb_get_uint8(tvb, offset); |
232 | | /* If the minor version doesn't match, make a note and try to continue */ |
233 | 0 | if(minor_version != VPP_MINOR_VERSION) { |
234 | 0 | proto_item *minor_version_item; |
235 | 0 | minor_version_item = |
236 | 0 | proto_tree_add_item(tree, hf_vpp_minor_version, |
237 | 0 | tvb, offset, 1, ENC_NA); |
238 | 0 | expert_add_info_format(pinfo, minor_version_item, |
239 | 0 | &ei_vpp_minor_version_error, |
240 | 0 | "Minor Version Mismatch read %d not %d", |
241 | 0 | (int)minor_version, VPP_MINOR_VERSION); |
242 | 0 | } |
243 | 0 | offset++; |
244 | | |
245 | | /* Number of counted strings in this trace record */ |
246 | 0 | string_count = tvb_get_uint8(tvb, offset); |
247 | 0 | offset++; |
248 | | |
249 | | /* |
250 | | * Hint: protocol which should be at b->data[b->current_data] |
251 | | * It will be a while before vpp sends useful hints for every |
252 | | * possible node, see heuristic below. |
253 | | */ |
254 | 0 | protocol_hint = tvb_get_uint8(tvb, offset); |
255 | |
|
256 | 0 | if(protocol_hint >= array_length(next_dissectors)) { |
257 | 0 | proto_item *protocol_hint_item; |
258 | 0 | protocol_hint_item = |
259 | 0 | proto_tree_add_item(tree, hf_vpp_protocol_hint, |
260 | 0 | tvb, offset, 1, ENC_NA); |
261 | 0 | expert_add_info_format(pinfo, protocol_hint_item, |
262 | 0 | &ei_vpp_protocol_hint_error, |
263 | 0 | "Protocol hint %d out of range, max %d", |
264 | 0 | (int)protocol_hint, |
265 | 0 | (int)array_length(next_dissectors)); |
266 | 0 | protocol_hint = 0; |
267 | 0 | } |
268 | |
|
269 | 0 | offset++; |
270 | | |
271 | | /* Buffer Index */ |
272 | 0 | proto_tree_add_item(vpp_tree, hf_vpp_buffer_index, tvb, |
273 | 0 | offset, 4, ENC_BIG_ENDIAN); |
274 | 0 | offset += 4; |
275 | | |
276 | | /* Nodename */ |
277 | 0 | len = tvb_strsize(tvb, offset); |
278 | 0 | name = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, len, |
279 | 0 | ENC_ASCII); |
280 | 0 | proto_tree_add_string(tree, hf_vpp_nodename, tvb, offset, len, name); |
281 | 0 | offset += len; |
282 | | |
283 | | /* Metadata */ |
284 | 0 | len = tvb_strsize(tvb, offset); |
285 | 0 | metadata_tvb = tvb_new_subset_remaining(tvb, offset); |
286 | 0 | call_dissector(vpp_metadata_dissector_handle, metadata_tvb, pinfo, tree); |
287 | 0 | offset += len; |
288 | | |
289 | | /* Opaque */ |
290 | 0 | len = tvb_strsize(tvb, offset); |
291 | 0 | opaque_tvb = tvb_new_subset_remaining(tvb, offset); |
292 | 0 | call_dissector(vpp_opaque_dissector_handle, opaque_tvb, pinfo, tree); |
293 | 0 | offset += len; |
294 | | |
295 | | /* Opaque2 */ |
296 | 0 | len = tvb_strsize(tvb, offset); |
297 | 0 | opaque2_tvb = tvb_new_subset_remaining(tvb, offset); |
298 | 0 | call_dissector(vpp_opaque2_dissector_handle, opaque2_tvb, pinfo, tree); |
299 | 0 | offset += len; |
300 | | |
301 | | /* Trace, if present */ |
302 | 0 | if(string_count > 4) { |
303 | 0 | len = tvb_strsize(tvb, offset); |
304 | 0 | trace_tvb = tvb_new_subset_remaining(tvb, offset); |
305 | 0 | call_dissector(vpp_trace_dissector_handle, trace_tvb, pinfo, tree); |
306 | 0 | offset += len; |
307 | 0 | } |
308 | |
|
309 | 0 | eth_tvb = tvb_new_subset_remaining(tvb, offset); |
310 | | |
311 | | /* |
312 | | * Delegate the rest of the packet dissection to the per-node |
313 | | * next dissector in the foreach_node_to_dissector_pair list |
314 | | * |
315 | | * Failing that, pretend its an ethernet packet |
316 | | */ |
317 | | /* See setup for hint == 0 below */ |
318 | 0 | use_this_dissector = next_dissectors [protocol_hint]; |
319 | 0 | if(protocol_hint == 0) { |
320 | 0 | maybe_protocol_id = tvb_get_uint8(tvb, offset); |
321 | |
|
322 | 0 | switch(maybe_protocol_id) { |
323 | 0 | case IP4_TYPICAL_VERSION_LENGTH: |
324 | 0 | use_this_dissector = next_dissectors[VLIB_NODE_PROTO_HINT_IP4]; |
325 | 0 | break; |
326 | 0 | case IP6_TYPICAL_VERSION_AND_TRAFFIC_CLASS: |
327 | 0 | use_this_dissector = next_dissectors[VLIB_NODE_PROTO_HINT_IP6]; |
328 | 0 | break; |
329 | 0 | default: |
330 | 0 | break; |
331 | 0 | } |
332 | 0 | } |
333 | 0 | call_dissector(use_this_dissector, eth_tvb, pinfo, tree); |
334 | 0 | return tvb_captured_length(tvb); |
335 | 0 | } |
336 | | |
337 | | void |
338 | | proto_register_vpp(void) |
339 | 16 | { |
340 | 16 | static hf_register_info vpp_hf[] = { |
341 | 16 | { &hf_vpp_buffer_index, |
342 | 16 | { "BufferIndex", "vpp.BufferIndex", FT_UINT32, BASE_HEX, NULL, 0x0, |
343 | 16 | NULL, HFILL }, |
344 | 16 | }, |
345 | 16 | { &hf_vpp_nodename, |
346 | 16 | { "NodeName", "vpp.NodeName", FT_STRINGZ, BASE_NONE, NULL, 0x0, |
347 | 16 | NULL, HFILL }, |
348 | 16 | }, |
349 | 16 | { &hf_vpp_major_version, |
350 | 16 | { "MajorVersion", "vpp.MajorVersion", FT_UINT8, BASE_DEC, NULL, 0x0, |
351 | 16 | NULL, HFILL }, |
352 | 16 | }, |
353 | 16 | { &hf_vpp_minor_version, |
354 | 16 | { "MinorVersion", "vpp.MinorVersion", FT_UINT8, BASE_DEC, NULL, 0x0, |
355 | 16 | NULL, HFILL }, |
356 | 16 | }, |
357 | 16 | { &hf_vpp_protocol_hint, |
358 | 16 | { "ProtocolHint", "vpp.ProtocolHint", FT_UINT8, BASE_DEC, NULL, 0x0, |
359 | 16 | NULL, HFILL }, |
360 | 16 | }, |
361 | 16 | }; |
362 | | |
363 | 16 | static ei_register_info vpp_ei[] = { |
364 | 16 | { &ei_vpp_major_version_error, |
365 | 16 | { "vpp.bad_major_version", PI_MALFORMED, PI_ERROR, |
366 | 16 | "Bad Major Version", EXPFILL }}, |
367 | 16 | { &ei_vpp_minor_version_error, |
368 | 16 | { "vpp.bad_minor_version", PI_UNDECODED, PI_WARN, |
369 | 16 | "Bad Minor Version", EXPFILL }}, |
370 | 16 | { &ei_vpp_protocol_hint_error, |
371 | 16 | { "vpp.bad_protocol_hint", PI_PROTOCOL, PI_WARN, |
372 | 16 | "Bad Protocol Hint", EXPFILL }}, |
373 | 16 | }; |
374 | | |
375 | 16 | static hf_register_info metadata_hf[] = { |
376 | 16 | { &hf_vpp_metadata, |
377 | 16 | { "Metadata", "vpp.metadata", |
378 | 16 | FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
379 | 16 | }, |
380 | 16 | }; |
381 | | |
382 | 16 | static hf_register_info opaque_hf[] = { |
383 | 16 | { &hf_vpp_buffer_opaque, |
384 | 16 | { "Opaque", "vpp.opaque", |
385 | 16 | FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
386 | 16 | }, |
387 | 16 | }; |
388 | | |
389 | 16 | static hf_register_info opaque2_hf[] = { |
390 | 16 | { &hf_vpp_buffer_opaque2, |
391 | 16 | { "Opaque2", "vpp.opaque2", |
392 | 16 | FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }, |
393 | 16 | }, |
394 | 16 | }; |
395 | | |
396 | 16 | static hf_register_info trace_hf[] = { |
397 | 16 | { &hf_vpp_buffer_trace, |
398 | 16 | { "Trace", "vpp.trace", FT_STRINGZ, BASE_NONE, NULL, 0x0, |
399 | 16 | NULL, HFILL }, |
400 | 16 | }, |
401 | 16 | }; |
402 | | |
403 | 16 | static int *vpp_ett[] = { |
404 | 16 | &ett_vpp, |
405 | 16 | }; |
406 | 16 | static int *ett_metadata[] = { |
407 | 16 | &ett_vpp_metadata, |
408 | 16 | }; |
409 | 16 | static int *ett_opaque[] = { |
410 | 16 | &ett_vpp_opaque, |
411 | 16 | }; |
412 | 16 | static int *ett_opaque2[] = { |
413 | 16 | &ett_vpp_opaque2, |
414 | 16 | }; |
415 | 16 | static int *ett_trace[] = { |
416 | 16 | &ett_vpp_trace, |
417 | 16 | }; |
418 | | |
419 | 16 | proto_vpp = proto_register_protocol("VPP Dispatch Trace", "VPP", "vpp"); |
420 | 16 | proto_register_field_array(proto_vpp, vpp_hf, array_length(vpp_hf)); |
421 | 16 | proto_register_subtree_array(vpp_ett, array_length(vpp_ett)); |
422 | 16 | register_dissector("vpp", dissect_vpp, proto_vpp); |
423 | | |
424 | 16 | expert_vpp = expert_register_protocol(proto_vpp); |
425 | 16 | expert_register_field_array(expert_vpp, vpp_ei, array_length(vpp_ei)); |
426 | | |
427 | 16 | proto_vpp_metadata = proto_register_protocol("VPP Buffer Metadata", |
428 | 16 | "VPP-Metadata", |
429 | 16 | "vpp-metadata"); |
430 | 16 | proto_register_field_array(proto_vpp_metadata, metadata_hf, |
431 | 16 | array_length(metadata_hf)); |
432 | 16 | proto_register_subtree_array(ett_metadata, array_length(ett_metadata)); |
433 | 16 | register_dissector("vppMetadata", dissect_vpp_metadata, proto_vpp_metadata); |
434 | | |
435 | 16 | proto_vpp_opaque = proto_register_protocol("VPP Buffer Opaque", "VPP-Opaque", |
436 | 16 | "vpp-opaque"); |
437 | 16 | proto_register_field_array(proto_vpp_opaque, opaque_hf, |
438 | 16 | array_length(opaque_hf)); |
439 | 16 | proto_register_subtree_array(ett_opaque, array_length(ett_opaque)); |
440 | 16 | register_dissector("vppOpaque", dissect_vpp_opaque, proto_vpp_opaque); |
441 | | |
442 | 16 | proto_vpp_opaque2 = proto_register_protocol("VPP Buffer Opaque2", |
443 | 16 | "VPP-Opaque2", "vpp-opaque2"); |
444 | 16 | proto_register_field_array(proto_vpp_opaque2, opaque2_hf, |
445 | 16 | array_length(opaque2_hf)); |
446 | 16 | proto_register_subtree_array(ett_opaque2, array_length(ett_opaque2)); |
447 | 16 | register_dissector("vppOpaque2", dissect_vpp_opaque2, proto_vpp_opaque2); |
448 | | |
449 | | |
450 | 16 | proto_vpp_trace = proto_register_protocol("VPP Buffer Trace", "VPP-Trace", |
451 | 16 | "vpp-trace"); |
452 | 16 | proto_register_field_array(proto_vpp_trace, trace_hf, |
453 | 16 | array_length(trace_hf)); |
454 | 16 | proto_register_subtree_array(ett_trace, array_length(ett_trace)); |
455 | 16 | register_dissector("vppTrace", dissect_vpp_trace, proto_vpp_trace); |
456 | | |
457 | 80 | #define _(idx,dname) next_dissectors[idx] = find_dissector(#dname); |
458 | 16 | foreach_next_dissector; |
459 | 16 | #undef _ |
460 | | |
461 | | /* if all else fails, dissect data as if ethernet MAC */ |
462 | 16 | next_dissectors[VLIB_NODE_PROTO_HINT_NONE] = |
463 | 16 | next_dissectors [VLIB_NODE_PROTO_HINT_ETHERNET]; |
464 | 16 | } |
465 | | |
466 | | void |
467 | | proto_reg_handoff_vpp(void) |
468 | 16 | { |
469 | 16 | vpp_dissector_handle = find_dissector("vpp"); |
470 | 16 | vpp_metadata_dissector_handle = find_dissector("vppMetadata"); |
471 | 16 | vpp_opaque_dissector_handle = find_dissector("vppOpaque"); |
472 | 16 | vpp_opaque2_dissector_handle = find_dissector("vppOpaque2"); |
473 | 16 | vpp_trace_dissector_handle = find_dissector("vppTrace"); |
474 | 16 | dissector_add_uint("wtap_encap", WTAP_ENCAP_VPP, vpp_dissector_handle); |
475 | 16 | } |
476 | | |
477 | | /* |
478 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
479 | | * |
480 | | * Local variables: |
481 | | * c-basic-offset: 4 |
482 | | * tab-width: 8 |
483 | | * indent-tabs-mode: nil |
484 | | * End: |
485 | | * |
486 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
487 | | * :indentSize=4:tabSize=8:noTabs=true: |
488 | | */ |