1 | /* |
2 | * net/tipc/trace.c: TIPC tracepoints code |
3 | * |
4 | * Copyright (c) 2018, Ericsson AB |
5 | * All rights reserved. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. Neither the names of the copyright holders nor the names of its |
16 | * contributors may be used to endorse or promote products derived from |
17 | * this software without specific prior written permission. |
18 | * |
19 | * Alternatively, this software may be distributed under the terms of the |
20 | * GNU General Public License ("GPL") version 2 as published by the Free |
21 | * Software Foundation. |
22 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS" |
24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE |
25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 | * POSSIBILITY OF SUCH DAMAGE. |
34 | */ |
35 | |
36 | #define CREATE_TRACE_POINTS |
37 | #include "trace.h" |
38 | |
39 | /* |
40 | * socket tuples for filtering in socket traces: |
41 | * (portid, sock type, name type, name lower, name upper) |
42 | */ |
43 | unsigned long sysctl_tipc_sk_filter[5] __read_mostly = {0, }; |
44 | |
45 | /** |
46 | * tipc_skb_dump - dump TIPC skb data |
47 | * @skb: skb to be dumped |
48 | * @more: dump more? |
49 | * - false: dump only tipc msg data |
50 | * - true: dump kernel-related skb data and tipc cb[] array as well |
51 | * @buf: returned buffer of dump data in format |
52 | */ |
53 | int tipc_skb_dump(struct sk_buff *skb, bool more, char *buf) |
54 | { |
55 | int i = 0; |
56 | size_t sz = (more) ? SKB_LMAX : SKB_LMIN; |
57 | struct tipc_msg *hdr; |
58 | struct tipc_skb_cb *skbcb; |
59 | |
60 | if (!skb) { |
61 | i += scnprintf(buf, size: sz, fmt: "msg: (null)\n" ); |
62 | return i; |
63 | } |
64 | |
65 | hdr = buf_msg(skb); |
66 | skbcb = TIPC_SKB_CB(skb); |
67 | |
68 | /* tipc msg data section */ |
69 | i += scnprintf(buf, size: sz, fmt: "msg: %u" , msg_user(m: hdr)); |
70 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_type(m: hdr)); |
71 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_hdr_sz(m: hdr)); |
72 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_data_sz(m: hdr)); |
73 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %x" , msg_orignode(m: hdr)); |
74 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %x" , msg_destnode(m: hdr)); |
75 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_seqno(m: hdr)); |
76 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_ack(m: hdr)); |
77 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_bcast_ack(m: hdr)); |
78 | switch (msg_user(m: hdr)) { |
79 | case LINK_PROTOCOL: |
80 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %c" , msg_net_plane(m: hdr)); |
81 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_probe(m: hdr)); |
82 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_peer_stopping(m: hdr)); |
83 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_session(m: hdr)); |
84 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_next_sent(m: hdr)); |
85 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_seq_gap(m: hdr)); |
86 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_bc_snd_nxt(m: hdr)); |
87 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_bc_gap(m: hdr)); |
88 | break; |
89 | case TIPC_LOW_IMPORTANCE: |
90 | case TIPC_MEDIUM_IMPORTANCE: |
91 | case TIPC_HIGH_IMPORTANCE: |
92 | case TIPC_CRITICAL_IMPORTANCE: |
93 | case CONN_MANAGER: |
94 | case SOCK_WAKEUP: |
95 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " | %u" , msg_origport(m: hdr)); |
96 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_destport(m: hdr)); |
97 | switch (msg_type(m: hdr)) { |
98 | case TIPC_NAMED_MSG: |
99 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
100 | msg_nametype(m: hdr)); |
101 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
102 | msg_nameinst(m: hdr)); |
103 | break; |
104 | case TIPC_MCAST_MSG: |
105 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
106 | msg_nametype(m: hdr)); |
107 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
108 | msg_namelower(m: hdr)); |
109 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
110 | msg_nameupper(m: hdr)); |
111 | break; |
112 | default: |
113 | break; |
114 | } |
115 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " | %u" , |
116 | msg_src_droppable(m: hdr)); |
117 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
118 | msg_dest_droppable(m: hdr)); |
119 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_errcode(m: hdr)); |
120 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , msg_reroute_cnt(m: hdr)); |
121 | break; |
122 | default: |
123 | /* need more? */ |
124 | break; |
125 | } |
126 | |
127 | i += scnprintf(buf: buf + i, size: sz - i, fmt: "\n" ); |
128 | if (!more) |
129 | return i; |
130 | |
131 | /* kernel-related skb data section */ |
132 | i += scnprintf(buf: buf + i, size: sz - i, fmt: "skb: %s" , |
133 | (skb->dev) ? skb->dev->name : "n/a" ); |
134 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb->len); |
135 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb->data_len); |
136 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb->hdr_len); |
137 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb->truesize); |
138 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb_cloned(skb)); |
139 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %p" , skb->sk); |
140 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skb_shinfo(skb)->nr_frags); |
141 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %llx" , |
142 | ktime_to_ms(kt: skb_get_ktime(skb))); |
143 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %llx\n" , |
144 | ktime_to_ms(kt: skb_hwtstamps(skb)->hwtstamp)); |
145 | |
146 | /* tipc skb cb[] data section */ |
147 | i += scnprintf(buf: buf + i, size: sz - i, fmt: "cb[]: %u" , skbcb->bytes_read); |
148 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skbcb->orig_member); |
149 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , |
150 | jiffies_to_msecs(j: skbcb->nxt_retr)); |
151 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skbcb->validated); |
152 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u" , skbcb->chain_imp); |
153 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " %u\n" , skbcb->ackers); |
154 | |
155 | return i; |
156 | } |
157 | |
158 | /** |
159 | * tipc_list_dump - dump TIPC skb list/queue |
160 | * @list: list of skbs to be dumped |
161 | * @more: dump more? |
162 | * - false: dump only the head & tail skbs |
163 | * - true: dump the first & last 5 skbs |
164 | * @buf: returned buffer of dump data in format |
165 | */ |
166 | int tipc_list_dump(struct sk_buff_head *list, bool more, char *buf) |
167 | { |
168 | int i = 0; |
169 | size_t sz = (more) ? LIST_LMAX : LIST_LMIN; |
170 | u32 count, len; |
171 | struct sk_buff *hskb, *tskb, *skb, *tmp; |
172 | |
173 | if (!list) { |
174 | i += scnprintf(buf, size: sz, fmt: "(null)\n" ); |
175 | return i; |
176 | } |
177 | |
178 | len = skb_queue_len(list_: list); |
179 | i += scnprintf(buf, size: sz, fmt: "len = %d\n" , len); |
180 | |
181 | if (!len) |
182 | return i; |
183 | |
184 | if (!more) { |
185 | hskb = skb_peek(list_: list); |
186 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " head " ); |
187 | i += tipc_skb_dump(skb: hskb, more: false, buf: buf + i); |
188 | if (len > 1) { |
189 | tskb = skb_peek_tail(list_: list); |
190 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " tail " ); |
191 | i += tipc_skb_dump(skb: tskb, more: false, buf: buf + i); |
192 | } |
193 | } else { |
194 | count = 0; |
195 | skb_queue_walk_safe(list, skb, tmp) { |
196 | count++; |
197 | if (count == 6) |
198 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " .\n .\n" ); |
199 | if (count > 5 && count <= len - 5) |
200 | continue; |
201 | i += scnprintf(buf: buf + i, size: sz - i, fmt: " #%d " , count); |
202 | i += tipc_skb_dump(skb, more: false, buf: buf + i); |
203 | } |
204 | } |
205 | return i; |
206 | } |
207 | |