Merge master.kernel.org:/pub/scm/linux/kernel/git/acme/net-2.6
[linux-2.6] / net / tipc / msg.h
1 /*
2  * net/tipc/msg.h: Include file for 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 #ifndef _TIPC_MSG_H
38 #define _TIPC_MSG_H
39
40 #include "core.h"
41
42 #define TIPC_VERSION              2
43 #define DATA_LOW                  TIPC_LOW_IMPORTANCE
44 #define DATA_MEDIUM               TIPC_MEDIUM_IMPORTANCE
45 #define DATA_HIGH                 TIPC_HIGH_IMPORTANCE
46 #define DATA_CRITICAL             TIPC_CRITICAL_IMPORTANCE
47 #define SHORT_H_SIZE              24    /* Connected,in cluster */
48 #define DIR_MSG_H_SIZE            32    /* Directly addressed messages */
49 #define CONN_MSG_H_SIZE           36    /* Routed connected msgs*/
50 #define LONG_H_SIZE               40    /* Named Messages */
51 #define MCAST_H_SIZE              44    /* Multicast messages */
52 #define MAX_H_SIZE                60    /* Inclusive full options */
53 #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
54 #define LINK_CONFIG               13
55
56
57 /*
58                 TIPC user data message header format, version 2
59                 
60         - Fundamental definitions available to privileged TIPC users
61           are located in tipc_msg.h.
62         - Remaining definitions available to TIPC internal users appear below. 
63 */
64
65
66 static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val)
67 {
68         m->hdr[w] = htonl(val);
69 }
70
71 static inline void msg_set_bits(struct tipc_msg *m, u32 w,
72                                 u32 pos, u32 mask, u32 val)
73 {
74         u32 word = msg_word(m,w) & ~(mask << pos);
75         msg_set_word(m, w, (word |= (val << pos)));
76 }
77
78 /* 
79  * Word 0
80  */
81
82 static inline u32 msg_version(struct tipc_msg *m)
83 {
84         return msg_bits(m, 0, 29, 7);
85 }
86
87 static inline void msg_set_version(struct tipc_msg *m) 
88 {
89         msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
90 }
91
92 static inline u32 msg_user(struct tipc_msg *m)
93 {
94         return msg_bits(m, 0, 25, 0xf);
95 }
96
97 static inline u32 msg_isdata(struct tipc_msg *m)
98 {
99         return (msg_user(m) <= DATA_CRITICAL);
100 }
101
102 static inline void msg_set_user(struct tipc_msg *m, u32 n) 
103 {
104         msg_set_bits(m, 0, 25, 0xf, n);
105 }
106
107 static inline void msg_set_importance(struct tipc_msg *m, u32 i) 
108 {
109         msg_set_user(m, i);
110 }
111
112 static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) 
113 {
114         msg_set_bits(m, 0, 21, 0xf, n>>2);
115 }
116
117 static inline int msg_non_seq(struct tipc_msg *m) 
118 {
119         return msg_bits(m, 0, 20, 1);
120 }
121
122 static inline void msg_set_non_seq(struct tipc_msg *m) 
123 {
124         msg_set_bits(m, 0, 20, 1, 1);
125 }
126
127 static inline int msg_dest_droppable(struct tipc_msg *m) 
128 {
129         return msg_bits(m, 0, 19, 1);
130 }
131
132 static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) 
133 {
134         msg_set_bits(m, 0, 19, 1, d);
135 }
136
137 static inline int msg_src_droppable(struct tipc_msg *m) 
138 {
139         return msg_bits(m, 0, 18, 1);
140 }
141
142 static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) 
143 {
144         msg_set_bits(m, 0, 18, 1, d);
145 }
146
147 static inline void msg_set_size(struct tipc_msg *m, u32 sz)
148 {
149         m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz);
150 }
151
152
153 /* 
154  * Word 1
155  */
156
157 static inline void msg_set_type(struct tipc_msg *m, u32 n) 
158 {
159         msg_set_bits(m, 1, 29, 0x7, n);
160 }
161
162 static inline void msg_set_errcode(struct tipc_msg *m, u32 err) 
163 {
164         msg_set_bits(m, 1, 25, 0xf, err);
165 }
166
167 static inline u32 msg_reroute_cnt(struct tipc_msg *m) 
168 {
169         return msg_bits(m, 1, 21, 0xf);
170 }
171
172 static inline void msg_incr_reroute_cnt(struct tipc_msg *m) 
173 {
174         msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1);
175 }
176
177 static inline void msg_reset_reroute_cnt(struct tipc_msg *m) 
178 {
179         msg_set_bits(m, 1, 21, 0xf, 0);
180 }
181
182 static inline u32 msg_lookup_scope(struct tipc_msg *m)
183 {
184         return msg_bits(m, 1, 19, 0x3);
185 }
186
187 static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) 
188 {
189         msg_set_bits(m, 1, 19, 0x3, n);
190 }
191
192 static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz) 
193 {
194         u32 hsz = msg_hdr_sz(m);
195         char *to = (char *)&m->hdr[hsz/4];
196
197         if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE))
198                 return;
199         msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4);
200         msg_set_hdr_sz(m, hsz + sz);
201         memcpy(to, opt, sz);
202 }
203
204 static inline u32 msg_bcast_ack(struct tipc_msg *m)
205 {
206         return msg_bits(m, 1, 0, 0xffff);
207 }
208
209 static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) 
210 {
211         msg_set_bits(m, 1, 0, 0xffff, n);
212 }
213
214
215 /* 
216  * Word 2
217  */
218
219 static inline u32 msg_ack(struct tipc_msg *m)
220 {
221         return msg_bits(m, 2, 16, 0xffff);
222 }
223
224 static inline void msg_set_ack(struct tipc_msg *m, u32 n) 
225 {
226         msg_set_bits(m, 2, 16, 0xffff, n);
227 }
228
229 static inline u32 msg_seqno(struct tipc_msg *m)
230 {
231         return msg_bits(m, 2, 0, 0xffff);
232 }
233
234 static inline void msg_set_seqno(struct tipc_msg *m, u32 n) 
235 {
236         msg_set_bits(m, 2, 0, 0xffff, n);
237 }
238
239
240 /* 
241  * Words 3-10
242  */
243
244
245 static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) 
246 {
247         msg_set_word(m, 3, a);
248 }
249
250 static inline void msg_set_origport(struct tipc_msg *m, u32 p) 
251 {
252         msg_set_word(m, 4, p);
253 }
254
255 static inline void msg_set_destport(struct tipc_msg *m, u32 p) 
256 {
257         msg_set_word(m, 5, p);
258 }
259
260 static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) 
261 {
262         msg_set_word(m, 5, p);
263 }
264
265 static inline void msg_set_orignode(struct tipc_msg *m, u32 a) 
266 {
267         msg_set_word(m, 6, a);
268 }
269
270 static inline void msg_set_destnode(struct tipc_msg *m, u32 a) 
271 {
272         msg_set_word(m, 7, a);
273 }
274
275 static inline int msg_is_dest(struct tipc_msg *m, u32 d) 
276 {
277         return(msg_short(m) || (msg_destnode(m) == d));
278 }
279
280 static inline u32 msg_routed(struct tipc_msg *m)
281 {
282         if (likely(msg_short(m)))
283                 return 0;
284         return(msg_destnode(m) ^ msg_orignode(m)) >> 11;
285 }
286
287 static inline void msg_set_nametype(struct tipc_msg *m, u32 n) 
288 {
289         msg_set_word(m, 8, n);
290 }
291
292 static inline u32 msg_transp_seqno(struct tipc_msg *m)
293 {
294         return msg_word(m, 8);
295 }
296
297 static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
298 {
299         msg_set_word(m, 8, n);
300 }
301
302 static inline u32 msg_timestamp(struct tipc_msg *m)
303 {
304         return msg_word(m, 8);
305 }
306
307 static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
308 {
309         msg_set_word(m, 8, n);
310 }
311
312 static inline void msg_set_namelower(struct tipc_msg *m, u32 n) 
313 {
314         msg_set_word(m, 9, n);
315 }
316
317 static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) 
318 {
319         msg_set_namelower(m, n);
320 }
321
322 static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) 
323 {
324         msg_set_word(m, 10, n);
325 }
326
327 static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
328 {
329         return (struct tipc_msg *)msg_data(m);
330 }
331
332 static inline void msg_expand(struct tipc_msg *m, u32 destnode) 
333 {
334         if (!msg_short(m))
335                 return;
336         msg_set_hdr_sz(m, LONG_H_SIZE);
337         msg_set_orignode(m, msg_prevnode(m));
338         msg_set_destnode(m, destnode);
339         memset(&m->hdr[8], 0, 12);
340 }
341
342
343
344 /*
345                 TIPC internal message header format, version 2
346
347        1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 
348       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
349    w0:|vers |msg usr|hdr sz |n|resrv|            packet size          |
350       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
351    w1:|m typ|rsv=0|   sequence gap    |       broadcast ack no        |
352       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
353    w2:| link level ack no/bc_gap_from |     seq no / bcast_gap_to     |
354       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
355    w3:|                       previous node                           |
356       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357    w4:|  next sent broadcast/fragm no | next sent pkt/ fragm msg no   |
358       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
359    w5:|          session no           |rsv=0|r|berid|link prio|netpl|p|
360       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361    w6:|                      originating node                         |
362       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363    w7:|                      destination node                         |
364       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365    w8:|                   transport sequence number                   |
366       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367    w9:|   msg count / bcast tag       |       link tolerance          |
368       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369       \                                                               \
370       /                     User Specific Data                        /
371       \                                                               \
372       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
373
374       NB: CONN_MANAGER use data message format. LINK_CONFIG has own format.
375 */   
376
377 /* 
378  * Internal users
379  */
380
381 #define  BCAST_PROTOCOL       5
382 #define  MSG_BUNDLER          6
383 #define  LINK_PROTOCOL        7
384 #define  CONN_MANAGER         8
385 #define  ROUTE_DISTRIBUTOR    9
386 #define  CHANGEOVER_PROTOCOL  10
387 #define  NAME_DISTRIBUTOR     11
388 #define  MSG_FRAGMENTER       12
389 #define  LINK_CONFIG          13
390 #define  INT_H_SIZE           40
391 #define  DSC_H_SIZE           40
392
393 /* 
394  *  Connection management protocol messages
395  */
396
397 #define CONN_PROBE        0
398 #define CONN_PROBE_REPLY  1
399 #define CONN_ACK          2
400
401 /* 
402  * Name distributor messages
403  */
404
405 #define PUBLICATION       0
406 #define WITHDRAWAL        1
407
408
409 /* 
410  * Word 1
411  */
412
413 static inline u32 msg_seq_gap(struct tipc_msg *m)
414 {
415         return msg_bits(m, 1, 16, 0xff);
416 }
417
418 static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
419 {
420         msg_set_bits(m, 1, 16, 0xff, n);
421 }
422
423 static inline u32 msg_req_links(struct tipc_msg *m)
424 {
425         return msg_bits(m, 1, 16, 0xfff);
426 }
427
428 static inline void msg_set_req_links(struct tipc_msg *m, u32 n) 
429 {
430         msg_set_bits(m, 1, 16, 0xfff, n);
431 }
432
433
434 /* 
435  * Word 2
436  */
437
438 static inline u32 msg_dest_domain(struct tipc_msg *m)
439 {
440         return msg_word(m, 2);
441 }
442
443 static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) 
444 {
445         msg_set_word(m, 2, n);
446 }
447
448 static inline u32 msg_bcgap_after(struct tipc_msg *m)
449 {
450         return msg_bits(m, 2, 16, 0xffff);
451 }
452
453 static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n)
454 {
455         msg_set_bits(m, 2, 16, 0xffff, n);
456 }
457
458 static inline u32 msg_bcgap_to(struct tipc_msg *m)
459 {
460         return msg_bits(m, 2, 0, 0xffff);
461 }
462
463 static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) 
464 {
465         msg_set_bits(m, 2, 0, 0xffff, n);
466 }
467
468
469 /* 
470  * Word 4
471  */
472
473 static inline u32 msg_last_bcast(struct tipc_msg *m)
474 {
475         return msg_bits(m, 4, 16, 0xffff);
476 }
477
478 static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n)
479 {
480         msg_set_bits(m, 4, 16, 0xffff, n);
481 }
482
483
484 static inline u32 msg_fragm_no(struct tipc_msg *m)
485 {
486         return msg_bits(m, 4, 16, 0xffff);
487 }
488
489 static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n)
490 {
491         msg_set_bits(m, 4, 16, 0xffff, n);
492 }
493
494
495 static inline u32 msg_next_sent(struct tipc_msg *m)
496 {
497         return msg_bits(m, 4, 0, 0xffff);
498 }
499
500 static inline void msg_set_next_sent(struct tipc_msg *m, u32 n)
501 {
502         msg_set_bits(m, 4, 0, 0xffff, n);
503 }
504
505
506 static inline u32 msg_long_msgno(struct tipc_msg *m)
507 {
508         return msg_bits(m, 4, 0, 0xffff);
509 }
510
511 static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n)
512 {
513         msg_set_bits(m, 4, 0, 0xffff, n);
514 }
515
516 static inline u32 msg_bc_netid(struct tipc_msg *m)
517 {
518         return msg_word(m, 4);
519 }
520
521 static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id)
522 {
523         msg_set_word(m, 4, id);
524 }
525
526 static inline u32 msg_link_selector(struct tipc_msg *m)
527 {
528         return msg_bits(m, 4, 0, 1);
529 }
530
531 static inline void msg_set_link_selector(struct tipc_msg *m, u32 n)
532 {
533         msg_set_bits(m, 4, 0, 1, (n & 1));
534 }
535
536 /* 
537  * Word 5
538  */
539
540 static inline u32 msg_session(struct tipc_msg *m)
541 {
542         return msg_bits(m, 5, 16, 0xffff);
543 }
544
545 static inline void msg_set_session(struct tipc_msg *m, u32 n)
546 {
547         msg_set_bits(m, 5, 16, 0xffff, n);
548 }
549
550 static inline u32 msg_probe(struct tipc_msg *m)
551 {
552         return msg_bits(m, 5, 0, 1);
553 }
554
555 static inline void msg_set_probe(struct tipc_msg *m, u32 val)
556 {
557         msg_set_bits(m, 5, 0, 1, (val & 1));
558 }
559
560 static inline char msg_net_plane(struct tipc_msg *m)
561 {
562         return msg_bits(m, 5, 1, 7) + 'A';
563 }
564
565 static inline void msg_set_net_plane(struct tipc_msg *m, char n)
566 {
567         msg_set_bits(m, 5, 1, 7, (n - 'A'));
568 }
569
570 static inline u32 msg_linkprio(struct tipc_msg *m)
571 {
572         return msg_bits(m, 5, 4, 0x1f);
573 }
574
575 static inline void msg_set_linkprio(struct tipc_msg *m, u32 n)
576 {
577         msg_set_bits(m, 5, 4, 0x1f, n);
578 }
579
580 static inline u32 msg_bearer_id(struct tipc_msg *m)
581 {
582         return msg_bits(m, 5, 9, 0x7);
583 }
584
585 static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n)
586 {
587         msg_set_bits(m, 5, 9, 0x7, n);
588 }
589
590 static inline u32 msg_redundant_link(struct tipc_msg *m)
591 {
592         return msg_bits(m, 5, 12, 0x1);
593 }
594
595 static inline void msg_set_redundant_link(struct tipc_msg *m)
596 {
597         msg_set_bits(m, 5, 12, 0x1, 1);
598 }
599
600 static inline void msg_clear_redundant_link(struct tipc_msg *m)
601 {
602         msg_set_bits(m, 5, 12, 0x1, 0);
603 }
604
605
606 /* 
607  * Word 9
608  */
609
610 static inline u32 msg_msgcnt(struct tipc_msg *m)
611 {
612         return msg_bits(m, 9, 16, 0xffff);
613 }
614
615 static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n)
616 {
617         msg_set_bits(m, 9, 16, 0xffff, n);
618 }
619
620 static inline u32 msg_bcast_tag(struct tipc_msg *m)
621 {
622         return msg_bits(m, 9, 16, 0xffff);
623 }
624
625 static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n)
626 {
627         msg_set_bits(m, 9, 16, 0xffff, n);
628 }
629
630 static inline u32 msg_max_pkt(struct tipc_msg *m) 
631 {
632         return (msg_bits(m, 9, 16, 0xffff) * 4);
633 }
634
635 static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) 
636 {
637         msg_set_bits(m, 9, 16, 0xffff, (n / 4));
638 }
639
640 static inline u32 msg_link_tolerance(struct tipc_msg *m)
641 {
642         return msg_bits(m, 9, 0, 0xffff);
643 }
644
645 static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
646 {
647         msg_set_bits(m, 9, 0, 0xffff, n);
648 }
649
650 /* 
651  * Routing table message data
652  */
653
654
655 static inline u32 msg_remote_node(struct tipc_msg *m)
656 {
657         return msg_word(m, msg_hdr_sz(m)/4);
658 }
659
660 static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
661 {
662         msg_set_word(m, msg_hdr_sz(m)/4, a);
663 }
664
665 static inline int msg_dataoctet(struct tipc_msg *m, u32 pos)
666 {
667         return(msg_data(m)[pos + 4] != 0);
668 }
669
670 static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos)
671 {
672         msg_data(m)[pos + 4] = 1;
673 }
674
675 /* 
676  * Segmentation message types
677  */
678
679 #define FIRST_FRAGMENT     0
680 #define FRAGMENT           1
681 #define LAST_FRAGMENT      2
682
683 /* 
684  * Link management protocol message types
685  */
686
687 #define STATE_MSG       0
688 #define RESET_MSG       1
689 #define ACTIVATE_MSG    2
690
691 /* 
692  * Changeover tunnel message types
693  */
694 #define DUPLICATE_MSG    0
695 #define ORIGINAL_MSG     1
696
697 /* 
698  * Routing table message types
699  */
700 #define EXT_ROUTING_TABLE    0
701 #define LOCAL_ROUTING_TABLE  1
702 #define SLAVE_ROUTING_TABLE  2
703 #define ROUTE_ADDITION       3
704 #define ROUTE_REMOVAL        4
705
706 /* 
707  * Config protocol message types
708  */
709
710 #define DSC_REQ_MSG          0
711 #define DSC_RESP_MSG         1
712
713 static inline u32 msg_tot_importance(struct tipc_msg *m)
714 {
715         if (likely(msg_isdata(m))) {
716                 if (likely(msg_orignode(m) == tipc_own_addr))
717                         return msg_importance(m);
718                 return msg_importance(m) + 4;
719         }
720         if ((msg_user(m) == MSG_FRAGMENTER)  &&
721             (msg_type(m) == FIRST_FRAGMENT))
722                 return msg_importance(msg_get_wrapped(m));
723         return msg_importance(m);
724 }
725
726
727 static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, 
728                             u32 err, u32 hsize, u32 destnode)
729 {
730         memset(m, 0, hsize);
731         msg_set_version(m);
732         msg_set_user(m, user);
733         msg_set_hdr_sz(m, hsize);
734         msg_set_size(m, hsize);
735         msg_set_prevnode(m, tipc_own_addr);
736         msg_set_type(m, type);
737         msg_set_errcode(m, err);
738         if (!msg_short(m)) {
739                 msg_set_orignode(m, tipc_own_addr);
740                 msg_set_destnode(m, destnode);
741         }
742 }
743
744 /** 
745  * msg_calc_data_size - determine total data size for message
746  */
747
748 static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect)
749 {
750         int dsz = 0;
751         int i;
752
753         for (i = 0; i < num_sect; i++)
754                 dsz += msg_sect[i].iov_len;
755         return dsz;
756 }
757
758 /** 
759  * msg_build - create message using specified header and data
760  * 
761  * Note: Caller must not hold any locks in case copy_from_user() is interrupted!
762  * 
763  * Returns message data size or errno
764  */
765
766 static inline int msg_build(struct tipc_msg *hdr, 
767                             struct iovec const *msg_sect, u32 num_sect,
768                             int max_size, int usrmem, struct sk_buff** buf)
769 {
770         int dsz, sz, hsz, pos, res, cnt;
771
772         dsz = msg_calc_data_size(msg_sect, num_sect);
773         if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) {
774                 *buf = NULL;
775                 return -EINVAL;
776         }
777
778         pos = hsz = msg_hdr_sz(hdr);
779         sz = hsz + dsz;
780         msg_set_size(hdr, sz);
781         if (unlikely(sz > max_size)) {
782                 *buf = NULL;
783                 return dsz;
784         }
785
786         *buf = buf_acquire(sz);
787         if (!(*buf))
788                 return -ENOMEM;
789         memcpy((*buf)->data, (unchar *)hdr, hsz);
790         for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) {
791                 if (likely(usrmem))
792                         res = !copy_from_user((*buf)->data + pos, 
793                                               msg_sect[cnt].iov_base, 
794                                               msg_sect[cnt].iov_len);
795                 else
796                         memcpy((*buf)->data + pos, msg_sect[cnt].iov_base, 
797                                msg_sect[cnt].iov_len);
798                 pos += msg_sect[cnt].iov_len;
799         }
800         if (likely(res))
801                 return dsz;
802
803         buf_discard(*buf);
804         *buf = NULL;
805         return -EFAULT;
806 }
807
808 static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
809 {
810         memcpy(&((int *)m)[5], a, sizeof(*a));
811 }
812
813 static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
814 {
815         memcpy(a, &((int*)m)[5], sizeof(*a));
816 }
817
818 #endif