Root/
1 | /* |
2 | * net/tipc/msg.c: TIPC message header routines |
3 | * |
4 | * Copyright (c) 2000-2006, Ericsson AB |
5 | * Copyright (c) 2005, Wind River Systems |
6 | * All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions are met: |
10 | * |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the names of the copyright holders nor the names of its |
17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. |
19 | * |
20 | * Alternatively, this software may be distributed under the terms of the |
21 | * GNU General Public License ("GPL") version 2 as published by the Free |
22 | * Software Foundation. |
23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ |
36 | |
37 | #include "core.h" |
38 | #include "addr.h" |
39 | #include "dbg.h" |
40 | #include "msg.h" |
41 | #include "bearer.h" |
42 | |
43 | u32 tipc_msg_tot_importance(struct tipc_msg *m) |
44 | { |
45 | if (likely(msg_isdata(m))) { |
46 | if (likely(msg_orignode(m) == tipc_own_addr)) |
47 | return msg_importance(m); |
48 | return msg_importance(m) + 4; |
49 | } |
50 | if ((msg_user(m) == MSG_FRAGMENTER) && |
51 | (msg_type(m) == FIRST_FRAGMENT)) |
52 | return msg_importance(msg_get_wrapped(m)); |
53 | return msg_importance(m); |
54 | } |
55 | |
56 | |
57 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, |
58 | u32 hsize, u32 destnode) |
59 | { |
60 | memset(m, 0, hsize); |
61 | msg_set_version(m); |
62 | msg_set_user(m, user); |
63 | msg_set_hdr_sz(m, hsize); |
64 | msg_set_size(m, hsize); |
65 | msg_set_prevnode(m, tipc_own_addr); |
66 | msg_set_type(m, type); |
67 | if (!msg_short(m)) { |
68 | msg_set_orignode(m, tipc_own_addr); |
69 | msg_set_destnode(m, destnode); |
70 | } |
71 | } |
72 | |
73 | /** |
74 | * tipc_msg_calc_data_size - determine total data size for message |
75 | */ |
76 | |
77 | int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) |
78 | { |
79 | int dsz = 0; |
80 | int i; |
81 | |
82 | for (i = 0; i < num_sect; i++) |
83 | dsz += msg_sect[i].iov_len; |
84 | return dsz; |
85 | } |
86 | |
87 | /** |
88 | * tipc_msg_build - create message using specified header and data |
89 | * |
90 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! |
91 | * |
92 | * Returns message data size or errno |
93 | */ |
94 | |
95 | int tipc_msg_build(struct tipc_msg *hdr, |
96 | struct iovec const *msg_sect, u32 num_sect, |
97 | int max_size, int usrmem, struct sk_buff** buf) |
98 | { |
99 | int dsz, sz, hsz, pos, res, cnt; |
100 | |
101 | dsz = tipc_msg_calc_data_size(msg_sect, num_sect); |
102 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { |
103 | *buf = NULL; |
104 | return -EINVAL; |
105 | } |
106 | |
107 | pos = hsz = msg_hdr_sz(hdr); |
108 | sz = hsz + dsz; |
109 | msg_set_size(hdr, sz); |
110 | if (unlikely(sz > max_size)) { |
111 | *buf = NULL; |
112 | return dsz; |
113 | } |
114 | |
115 | *buf = buf_acquire(sz); |
116 | if (!(*buf)) |
117 | return -ENOMEM; |
118 | skb_copy_to_linear_data(*buf, hdr, hsz); |
119 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { |
120 | if (likely(usrmem)) |
121 | res = !copy_from_user((*buf)->data + pos, |
122 | msg_sect[cnt].iov_base, |
123 | msg_sect[cnt].iov_len); |
124 | else |
125 | skb_copy_to_linear_data_offset(*buf, pos, |
126 | msg_sect[cnt].iov_base, |
127 | msg_sect[cnt].iov_len); |
128 | pos += msg_sect[cnt].iov_len; |
129 | } |
130 | if (likely(res)) |
131 | return dsz; |
132 | |
133 | buf_discard(*buf); |
134 | *buf = NULL; |
135 | return -EFAULT; |
136 | } |
137 | |
138 | #ifdef CONFIG_TIPC_DEBUG |
139 | |
140 | void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str) |
141 | { |
142 | u32 usr = msg_user(msg); |
143 | tipc_printf(buf, str); |
144 | |
145 | switch (usr) { |
146 | case MSG_BUNDLER: |
147 | tipc_printf(buf, "BNDL::"); |
148 | tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg)); |
149 | break; |
150 | case BCAST_PROTOCOL: |
151 | tipc_printf(buf, "BCASTP::"); |
152 | break; |
153 | case MSG_FRAGMENTER: |
154 | tipc_printf(buf, "FRAGM::"); |
155 | switch (msg_type(msg)) { |
156 | case FIRST_FRAGMENT: |
157 | tipc_printf(buf, "FIRST:"); |
158 | break; |
159 | case FRAGMENT: |
160 | tipc_printf(buf, "BODY:"); |
161 | break; |
162 | case LAST_FRAGMENT: |
163 | tipc_printf(buf, "LAST:"); |
164 | break; |
165 | default: |
166 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); |
167 | |
168 | } |
169 | tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg), |
170 | msg_fragm_no(msg)); |
171 | break; |
172 | case TIPC_LOW_IMPORTANCE: |
173 | case TIPC_MEDIUM_IMPORTANCE: |
174 | case TIPC_HIGH_IMPORTANCE: |
175 | case TIPC_CRITICAL_IMPORTANCE: |
176 | tipc_printf(buf, "DAT%u:", msg_user(msg)); |
177 | if (msg_short(msg)) { |
178 | tipc_printf(buf, "CON:"); |
179 | break; |
180 | } |
181 | switch (msg_type(msg)) { |
182 | case TIPC_CONN_MSG: |
183 | tipc_printf(buf, "CON:"); |
184 | break; |
185 | case TIPC_MCAST_MSG: |
186 | tipc_printf(buf, "MCST:"); |
187 | break; |
188 | case TIPC_NAMED_MSG: |
189 | tipc_printf(buf, "NAM:"); |
190 | break; |
191 | case TIPC_DIRECT_MSG: |
192 | tipc_printf(buf, "DIR:"); |
193 | break; |
194 | default: |
195 | tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg)); |
196 | } |
197 | if (msg_routed(msg) && !msg_non_seq(msg)) |
198 | tipc_printf(buf, "ROUT:"); |
199 | if (msg_reroute_cnt(msg)) |
200 | tipc_printf(buf, "REROUTED(%u):", |
201 | msg_reroute_cnt(msg)); |
202 | break; |
203 | case NAME_DISTRIBUTOR: |
204 | tipc_printf(buf, "NMD::"); |
205 | switch (msg_type(msg)) { |
206 | case PUBLICATION: |
207 | tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */ |
208 | break; |
209 | case WITHDRAWAL: |
210 | tipc_printf(buf, "WDRW:"); |
211 | break; |
212 | default: |
213 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); |
214 | } |
215 | if (msg_routed(msg)) |
216 | tipc_printf(buf, "ROUT:"); |
217 | if (msg_reroute_cnt(msg)) |
218 | tipc_printf(buf, "REROUTED(%u):", |
219 | msg_reroute_cnt(msg)); |
220 | break; |
221 | case CONN_MANAGER: |
222 | tipc_printf(buf, "CONN_MNG:"); |
223 | switch (msg_type(msg)) { |
224 | case CONN_PROBE: |
225 | tipc_printf(buf, "PROBE:"); |
226 | break; |
227 | case CONN_PROBE_REPLY: |
228 | tipc_printf(buf, "PROBE_REPLY:"); |
229 | break; |
230 | case CONN_ACK: |
231 | tipc_printf(buf, "CONN_ACK:"); |
232 | tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg)); |
233 | break; |
234 | default: |
235 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); |
236 | } |
237 | if (msg_routed(msg)) |
238 | tipc_printf(buf, "ROUT:"); |
239 | if (msg_reroute_cnt(msg)) |
240 | tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg)); |
241 | break; |
242 | case LINK_PROTOCOL: |
243 | tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg)); |
244 | switch (msg_type(msg)) { |
245 | case STATE_MSG: |
246 | tipc_printf(buf, "STATE:"); |
247 | tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :""); |
248 | tipc_printf(buf, "NXS(%u):",msg_next_sent(msg)); |
249 | tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg)); |
250 | tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg)); |
251 | break; |
252 | case RESET_MSG: |
253 | tipc_printf(buf, "RESET:"); |
254 | if (msg_size(msg) != msg_hdr_sz(msg)) |
255 | tipc_printf(buf, "BEAR:%s:",msg_data(msg)); |
256 | break; |
257 | case ACTIVATE_MSG: |
258 | tipc_printf(buf, "ACTIVATE:"); |
259 | break; |
260 | default: |
261 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); |
262 | } |
263 | tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg)); |
264 | tipc_printf(buf, "SESS(%u):",msg_session(msg)); |
265 | break; |
266 | case CHANGEOVER_PROTOCOL: |
267 | tipc_printf(buf, "TUNL:"); |
268 | switch (msg_type(msg)) { |
269 | case DUPLICATE_MSG: |
270 | tipc_printf(buf, "DUPL:"); |
271 | break; |
272 | case ORIGINAL_MSG: |
273 | tipc_printf(buf, "ORIG:"); |
274 | tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg)); |
275 | break; |
276 | default: |
277 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); |
278 | } |
279 | break; |
280 | case ROUTE_DISTRIBUTOR: |
281 | tipc_printf(buf, "ROUTING_MNG:"); |
282 | switch (msg_type(msg)) { |
283 | case EXT_ROUTING_TABLE: |
284 | tipc_printf(buf, "EXT_TBL:"); |
285 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); |
286 | break; |
287 | case LOCAL_ROUTING_TABLE: |
288 | tipc_printf(buf, "LOCAL_TBL:"); |
289 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); |
290 | break; |
291 | case SLAVE_ROUTING_TABLE: |
292 | tipc_printf(buf, "DP_TBL:"); |
293 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); |
294 | break; |
295 | case ROUTE_ADDITION: |
296 | tipc_printf(buf, "ADD:"); |
297 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); |
298 | break; |
299 | case ROUTE_REMOVAL: |
300 | tipc_printf(buf, "REMOVE:"); |
301 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); |
302 | break; |
303 | default: |
304 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); |
305 | } |
306 | break; |
307 | case LINK_CONFIG: |
308 | tipc_printf(buf, "CFG:"); |
309 | switch (msg_type(msg)) { |
310 | case DSC_REQ_MSG: |
311 | tipc_printf(buf, "DSC_REQ:"); |
312 | break; |
313 | case DSC_RESP_MSG: |
314 | tipc_printf(buf, "DSC_RESP:"); |
315 | break; |
316 | default: |
317 | tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg)); |
318 | break; |
319 | } |
320 | break; |
321 | default: |
322 | tipc_printf(buf, "UNKNOWN USER:"); |
323 | } |
324 | |
325 | switch (usr) { |
326 | case CONN_MANAGER: |
327 | case TIPC_LOW_IMPORTANCE: |
328 | case TIPC_MEDIUM_IMPORTANCE: |
329 | case TIPC_HIGH_IMPORTANCE: |
330 | case TIPC_CRITICAL_IMPORTANCE: |
331 | switch (msg_errcode(msg)) { |
332 | case TIPC_OK: |
333 | break; |
334 | case TIPC_ERR_NO_NAME: |
335 | tipc_printf(buf, "NO_NAME:"); |
336 | break; |
337 | case TIPC_ERR_NO_PORT: |
338 | tipc_printf(buf, "NO_PORT:"); |
339 | break; |
340 | case TIPC_ERR_NO_NODE: |
341 | tipc_printf(buf, "NO_PROC:"); |
342 | break; |
343 | case TIPC_ERR_OVERLOAD: |
344 | tipc_printf(buf, "OVERLOAD:"); |
345 | break; |
346 | case TIPC_CONN_SHUTDOWN: |
347 | tipc_printf(buf, "SHUTDOWN:"); |
348 | break; |
349 | default: |
350 | tipc_printf(buf, "UNKNOWN ERROR(%x):", |
351 | msg_errcode(msg)); |
352 | } |
353 | default:{} |
354 | } |
355 | |
356 | tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); |
357 | tipc_printf(buf, "SZ(%u):", msg_size(msg)); |
358 | tipc_printf(buf, "SQNO(%u):", msg_seqno(msg)); |
359 | |
360 | if (msg_non_seq(msg)) |
361 | tipc_printf(buf, "NOSEQ:"); |
362 | else { |
363 | tipc_printf(buf, "ACK(%u):", msg_ack(msg)); |
364 | } |
365 | tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); |
366 | tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); |
367 | |
368 | if (msg_isdata(msg)) { |
369 | if (msg_named(msg)) { |
370 | tipc_printf(buf, "NTYP(%u):", msg_nametype(msg)); |
371 | tipc_printf(buf, "NINST(%u)", msg_nameinst(msg)); |
372 | } |
373 | } |
374 | |
375 | if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) && |
376 | (usr != MSG_BUNDLER)) { |
377 | if (!msg_short(msg)) { |
378 | tipc_printf(buf, ":ORIG(%x:%u):", |
379 | msg_orignode(msg), msg_origport(msg)); |
380 | tipc_printf(buf, ":DEST(%x:%u):", |
381 | msg_destnode(msg), msg_destport(msg)); |
382 | } else { |
383 | tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); |
384 | tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); |
385 | } |
386 | if (msg_routed(msg) && !msg_non_seq(msg)) |
387 | tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg)); |
388 | } |
389 | if (msg_user(msg) == NAME_DISTRIBUTOR) { |
390 | tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); |
391 | tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); |
392 | if (msg_routed(msg)) { |
393 | tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg)); |
394 | } |
395 | } |
396 | |
397 | if (msg_user(msg) == LINK_CONFIG) { |
398 | u32* raw = (u32*)msg; |
399 | struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5]; |
400 | tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); |
401 | tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); |
402 | tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); |
403 | tipc_media_addr_printf(buf, orig); |
404 | } |
405 | if (msg_user(msg) == BCAST_PROTOCOL) { |
406 | tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); |
407 | tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); |
408 | } |
409 | tipc_printf(buf, "\n"); |
410 | if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { |
411 | tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); |
412 | } |
413 | if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { |
414 | tipc_msg_dbg(buf, msg_get_wrapped(msg), " /"); |
415 | } |
416 | } |
417 | |
418 | #endif |
419 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9