1 /* packet-netlink-psample.c
2 * Routines for netlink-psample dissection
3 * Based on netlink-net_dm and netlink-generic dissectors
4 * Copyright 2021, Mellanox Technologies Ltd.
5 * Code by Amit Cohen <amcohen@nvidia.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
14 /* psample is a netlink-based protocol via which alerts
15 * about sampled packets are sent to user space
17 * Relevant Linux kernel header file:
18 * include/uapi/linux/psample.h
23 #include <epan/packet.h>
25 #include "packet-netlink.h"
26 #include "packet-sll.h"
28 void proto_register_netlink_psample(void);
29 void proto_reg_handoff_netlink_psample(void);
31 enum ws_psample_commands
{
32 WS_PSAMPLE_CMD_SAMPLE
,
33 WS_PSAMPLE_CMD_GET_GROUP
,
34 WS_PSAMPLE_CMD_NEW_GROUP
,
35 WS_PSAMPLE_CMD_DEL_GROUP
,
38 enum ws_psample_attrs
{
39 WS_PSAMPLE_ATTR_IIFINDEX
,
40 WS_PSAMPLE_ATTR_OIFINDEX
,
41 WS_PSAMPLE_ATTR_ORIGSIZE
,
42 WS_PSAMPLE_ATTR_SAMPLE_GROUP
,
43 WS_PSAMPLE_ATTR_GROUP_SEQ
,
44 WS_PSAMPLE_ATTR_SAMPLE_RATE
,
46 WS_PSAMPLE_ATTR_GROUP_REFCOUNT
,
47 WS_PSAMPLE_ATTR_TUNNEL
,
49 WS_PSAMPLE_ATTR_OUT_TC
,
50 WS_PSAMPLE_ATTR_OUT_TC_OCC
,
51 WS_PSAMPLE_ATTR_LATENCY
,
52 WS_PSAMPLE_ATTR_TIMESTAMP
,
53 WS_PSAMPLE_ATTR_PROTO
,
56 struct netlink_psample_info
{
58 uint16_t protocol
; /* protocol for packet payload */
61 static int proto_netlink_psample
;
63 static dissector_handle_t netlink_psample_handle
;
64 static dissector_table_t sll_ltype_table
;
66 static int hf_psample_attrs
;
67 static int hf_psample_commands
;
68 static int hf_psample_group_refcount
;
69 static int hf_psample_group_seq
;
70 static int hf_psample_iifindex
;
71 static int hf_psample_latency
;
72 static int hf_psample_oifindex
;
73 static int hf_psample_origsize
;
74 static int hf_psample_out_tc
;
75 static int hf_psample_out_tc_occ
;
76 static int hf_psample_proto
;
77 static int hf_psample_sample_group
;
78 static int hf_psample_sample_rate
;
79 static int hf_psample_timestamp
;
80 static int hf_psample_tunnel
;
82 static int ett_psample
;
83 static int ett_psample_attrs
;
85 static const value_string ws_psample_commands_vals
[] = {
86 { WS_PSAMPLE_CMD_SAMPLE
, "Sample" },
87 { WS_PSAMPLE_CMD_GET_GROUP
, "Get group" },
88 { WS_PSAMPLE_CMD_NEW_GROUP
, "New group" },
89 { WS_PSAMPLE_CMD_DEL_GROUP
, "Delete group" },
93 static value_string_ext ws_psample_commands_vals_ext
= VALUE_STRING_EXT_INIT(ws_psample_commands_vals
);
95 static const value_string ws_psample_attrs_vals
[] = {
96 { WS_PSAMPLE_ATTR_IIFINDEX
, "Input interface index" },
97 { WS_PSAMPLE_ATTR_OIFINDEX
, "Output interface index" },
98 { WS_PSAMPLE_ATTR_ORIGSIZE
, "Original size" },
99 { WS_PSAMPLE_ATTR_SAMPLE_GROUP
, "Sample group" },
100 { WS_PSAMPLE_ATTR_GROUP_SEQ
, "Group sequence number" },
101 { WS_PSAMPLE_ATTR_SAMPLE_RATE
, "Sample rate" },
102 { WS_PSAMPLE_ATTR_DATA
, "Data" },
103 { WS_PSAMPLE_ATTR_GROUP_REFCOUNT
, "Group reference count" },
104 { WS_PSAMPLE_ATTR_TUNNEL
, "Tunnel" },
105 { WS_PSAMPLE_ATTR_PAD
, "Pad" },
106 { WS_PSAMPLE_ATTR_OUT_TC
, "Output traffic class" },
107 { WS_PSAMPLE_ATTR_OUT_TC_OCC
, "Output traffic class occupancy" },
108 { WS_PSAMPLE_ATTR_LATENCY
, "Latency" },
109 { WS_PSAMPLE_ATTR_TIMESTAMP
, "Timestamp" },
110 { WS_PSAMPLE_ATTR_PROTO
, "Protocol" },
114 static value_string_ext ws_psample_attrs_vals_ext
= VALUE_STRING_EXT_INIT(ws_psample_attrs_vals
);
117 dissect_psample_attrs(tvbuff_t
*tvb
, void *data
, struct packet_netlink_data
*nl_data
, proto_tree
*tree
, int nla_type
, int offset
, int len
)
119 enum ws_psample_attrs type
= (enum ws_psample_attrs
) nla_type
& NLA_TYPE_MASK
;
120 struct netlink_psample_info
*info
= (struct netlink_psample_info
*) data
;
121 uint64_t value64
, timestamp
;
127 case WS_PSAMPLE_ATTR_IIFINDEX
:
128 proto_tree_add_item_ret_uint(tree
, hf_psample_iifindex
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
129 proto_item_append_text(tree
, ": %u", value
);
131 case WS_PSAMPLE_ATTR_OIFINDEX
:
132 proto_tree_add_item_ret_uint(tree
, hf_psample_oifindex
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
133 proto_item_append_text(tree
, ": %u", value
);
135 case WS_PSAMPLE_ATTR_ORIGSIZE
:
136 proto_tree_add_item_ret_uint(tree
, hf_psample_origsize
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
137 proto_item_append_text(tree
, ": %u", value
);
139 case WS_PSAMPLE_ATTR_SAMPLE_GROUP
:
140 proto_tree_add_item_ret_uint(tree
, hf_psample_sample_group
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
141 proto_item_append_text(tree
, ": %u", value
);
143 case WS_PSAMPLE_ATTR_GROUP_SEQ
:
144 proto_tree_add_item_ret_uint(tree
, hf_psample_group_seq
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
145 proto_item_append_text(tree
, ": %u", value
);
147 case WS_PSAMPLE_ATTR_SAMPLE_RATE
:
148 proto_tree_add_item_ret_uint(tree
, hf_psample_sample_rate
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
149 proto_item_append_text(tree
, ": %u", value
);
151 case WS_PSAMPLE_ATTR_DATA
:
152 next_tvb
= tvb_new_subset_length(tvb
, offset
, len
);
153 if (!dissector_try_uint(sll_ltype_table
, info
->protocol
, next_tvb
, info
->pinfo
, tree
))
154 call_data_dissector(next_tvb
, info
->pinfo
, tree
);
156 case WS_PSAMPLE_ATTR_GROUP_REFCOUNT
:
157 proto_tree_add_item_ret_uint(tree
, hf_psample_group_refcount
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
158 proto_item_append_text(tree
, ": %u", value
);
160 case WS_PSAMPLE_ATTR_TUNNEL
:
161 /* Currently there is no support for tunnel dissection. */
163 case WS_PSAMPLE_ATTR_OUT_TC
:
164 proto_tree_add_item_ret_uint(tree
, hf_psample_out_tc
, tvb
, offset
, len
, nl_data
->encoding
, &value
);
165 proto_item_append_text(tree
, ": %u", value
);
167 case WS_PSAMPLE_ATTR_OUT_TC_OCC
:
168 proto_tree_add_item_ret_uint64(tree
, hf_psample_out_tc_occ
, tvb
, offset
, len
, nl_data
->encoding
, &value64
);
169 proto_item_append_text(tree
, ": %"PRIu64
, value64
);
171 case WS_PSAMPLE_ATTR_LATENCY
:
172 proto_tree_add_item_ret_uint64(tree
, hf_psample_latency
, tvb
, offset
, len
, nl_data
->encoding
, &value64
);
173 proto_item_append_text(tree
, ": %"PRIu64
, value64
);
175 case WS_PSAMPLE_ATTR_TIMESTAMP
:
176 timestamp
= tvb_get_uint64(tvb
, offset
, nl_data
->encoding
);
177 ts_nstime
.secs
= timestamp
/ 1000000000;
178 ts_nstime
.nsecs
= timestamp
% 1000000000;
179 proto_tree_add_time(tree
, hf_psample_timestamp
, tvb
, offset
, 8, &ts_nstime
);
181 case WS_PSAMPLE_ATTR_PROTO
:
182 info
->protocol
= tvb_get_uint16(tvb
, offset
, nl_data
->encoding
);
183 /* This attribute encodes 'skb->protocol' and if it is greater
184 * than or equal to 1536 (0x0600), then it is an Ethertype and
185 * we need to treat the packet as Ethernet.
187 if (info
->protocol
>= 1536 || info
->protocol
== LINUX_SLL_P_802_2
)
188 info
->protocol
= LINUX_SLL_P_ETHERNET
;
189 proto_tree_add_item(tree
, hf_psample_proto
, tvb
, offset
, len
, nl_data
->encoding
);
197 dissect_netlink_psample(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
199 genl_info_t
*genl_info
= (genl_info_t
*)data
;
200 struct netlink_psample_info info
;
201 proto_tree
*nlmsg_tree
;
205 DISSECTOR_ASSERT(genl_info
);
207 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "psample");
208 col_clear(pinfo
->cinfo
, COL_INFO
);
210 /* Generic netlink header */
211 offset
= dissect_genl_header(tvb
, genl_info
, genl_info
->nl_data
, hf_psample_commands
);
213 /* Not all commands have a payload */
214 if (!tvb_reported_length_remaining(tvb
, offset
))
215 /* XXX If you do not set the protocol item, you cannot filter on these messages */
218 pi
= proto_tree_add_item(tree
, proto_netlink_psample
, tvb
, offset
, -1, ENC_NA
);
219 nlmsg_tree
= proto_item_add_subtree(pi
, ett_psample
);
224 offset
= dissect_netlink_attributes_to_end(tvb
, hf_psample_attrs
, ett_psample_attrs
, &info
, genl_info
->nl_data
, nlmsg_tree
, offset
, dissect_psample_attrs
);
230 proto_register_netlink_psample(void)
232 static hf_register_info hf
[] = {
233 { &hf_psample_commands
,
234 { "Command", "psample.cmd",
235 FT_UINT8
, BASE_DEC
| BASE_EXT_STRING
, &ws_psample_commands_vals_ext
, 0x00,
239 { "Attribute type", "psample.attr_type",
240 FT_UINT16
, BASE_DEC
| BASE_EXT_STRING
, &ws_psample_attrs_vals_ext
, NLA_TYPE_MASK
,
243 { &hf_psample_iifindex
,
244 { "Input interface index", "psample.iifindex",
245 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
248 { &hf_psample_oifindex
,
249 { "Output interface index", "psample.oifindex",
250 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
253 { &hf_psample_origsize
,
254 { "Original size", "psample.origsize",
255 FT_UINT32
, BASE_HEX
, NULL
, 0x00,
258 { &hf_psample_sample_group
,
259 { "Sample group", "psample.sample_group",
260 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
263 { &hf_psample_group_seq
,
264 { "Group sequence number", "psample.group_seq_num",
265 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
268 { &hf_psample_sample_rate
,
269 { "Sample rate", "psample.sample_rate",
270 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
273 { &hf_psample_tunnel
,
274 { "Tunnel", "psample.tunnel",
275 FT_UINT32
, BASE_HEX
, NULL
, 0x00,
278 { &hf_psample_group_refcount
,
279 { "Group reference count", "psample.group_refcount",
280 FT_UINT32
, BASE_HEX
, NULL
, 0x00,
283 { &hf_psample_out_tc
,
284 { "Output traffic class", "psample.out_tc",
285 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
288 { &hf_psample_out_tc_occ
,
289 { "Output traffic class occupancy", "psample.out_tc_occ",
290 FT_UINT64
, BASE_DEC
, NULL
, 0x00,
293 { &hf_psample_latency
,
294 { "Latency", "psample.latency",
295 FT_UINT64
, BASE_DEC
, NULL
, 0x00,
298 { &hf_psample_timestamp
,
299 { "Timestamp", "psample.timestamp",
300 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
, NULL
, 0x00,
304 { "Protocol", "psample.proto",
305 FT_UINT16
, BASE_HEX
, NULL
, 0x00,
310 static int *ett
[] = {
315 proto_netlink_psample
= proto_register_protocol("Linux psample protocol", "psample", "psample");
316 proto_register_field_array(proto_netlink_psample
, hf
, array_length(hf
));
317 proto_register_subtree_array(ett
, array_length(ett
));
319 netlink_psample_handle
= register_dissector("psample", dissect_netlink_psample
, proto_netlink_psample
);
323 proto_reg_handoff_netlink_psample(void)
325 dissector_add_string("genl.family", "psample", netlink_psample_handle
);
326 sll_ltype_table
= find_dissector_table("sll.ltype");
330 * Editor modelines - https://www.wireshark.org/tools/modelines.html
335 * indent-tabs-mode: t
338 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
339 * :indentSize=8:tabSize=8:noTabs=false: