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