aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r--net/tipc/msg.c96
1 files changed, 85 insertions, 11 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 8be6e94a1ca9..e02afc96edd7 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -37,20 +37,11 @@
37#include "core.h" 37#include "core.h"
38#include "msg.h" 38#include "msg.h"
39 39
40u32 tipc_msg_tot_importance(struct tipc_msg *m) 40static unsigned int align(unsigned int i)
41{ 41{
42 if (likely(msg_isdata(m))) { 42 return (i + 3) & ~3u;
43 if (likely(msg_orignode(m) == tipc_own_addr))
44 return msg_importance(m);
45 return msg_importance(m) + 4;
46 }
47 if ((msg_user(m) == MSG_FRAGMENTER) &&
48 (msg_type(m) == FIRST_FRAGMENT))
49 return msg_importance(msg_get_wrapped(m));
50 return msg_importance(m);
51} 43}
52 44
53
54void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, 45void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
55 u32 destnode) 46 u32 destnode)
56{ 47{
@@ -152,3 +143,86 @@ out_free:
152 kfree_skb(*buf); 143 kfree_skb(*buf);
153 return 0; 144 return 0;
154} 145}
146
147/**
148 * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one
149 * @bbuf: the existing buffer ("bundle")
150 * @buf: buffer to be appended
151 * @mtu: max allowable size for the bundle buffer
152 * Consumes buffer if successful
153 * Returns true if bundling could be performed, otherwise false
154 */
155bool tipc_msg_bundle(struct sk_buff *bbuf, struct sk_buff *buf, u32 mtu)
156{
157 struct tipc_msg *bmsg = buf_msg(bbuf);
158 struct tipc_msg *msg = buf_msg(buf);
159 unsigned int bsz = msg_size(bmsg);
160 unsigned int msz = msg_size(msg);
161 u32 start = align(bsz);
162 u32 max = mtu - INT_H_SIZE;
163 u32 pad = start - bsz;
164
165 if (likely(msg_user(msg) == MSG_FRAGMENTER))
166 return false;
167 if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL))
168 return false;
169 if (unlikely(msg_user(msg) == BCAST_PROTOCOL))
170 return false;
171 if (likely(msg_user(bmsg) != MSG_BUNDLER))
172 return false;
173 if (likely(msg_type(bmsg) != BUNDLE_OPEN))
174 return false;
175 if (unlikely(skb_tailroom(bbuf) < (pad + msz)))
176 return false;
177 if (unlikely(max < (start + msz)))
178 return false;
179
180 skb_put(bbuf, pad + msz);
181 skb_copy_to_linear_data_offset(bbuf, start, buf->data, msz);
182 msg_set_size(bmsg, start + msz);
183 msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1);
184 bbuf->next = buf->next;
185 kfree_skb(buf);
186 return true;
187}
188
189/**
190 * tipc_msg_make_bundle(): Create bundle buf and append message to its tail
191 * @buf: buffer to be appended and replaced
192 * @mtu: max allowable size for the bundle buffer, inclusive header
193 * @dnode: destination node for message. (Not always present in header)
194 * Replaces buffer if successful
195 * Returns true if sucess, otherwise false
196 */
197bool tipc_msg_make_bundle(struct sk_buff **buf, u32 mtu, u32 dnode)
198{
199 struct sk_buff *bbuf;
200 struct tipc_msg *bmsg;
201 struct tipc_msg *msg = buf_msg(*buf);
202 u32 msz = msg_size(msg);
203 u32 max = mtu - INT_H_SIZE;
204
205 if (msg_user(msg) == MSG_FRAGMENTER)
206 return false;
207 if (msg_user(msg) == CHANGEOVER_PROTOCOL)
208 return false;
209 if (msg_user(msg) == BCAST_PROTOCOL)
210 return false;
211 if (msz > (max / 2))
212 return false;
213
214 bbuf = tipc_buf_acquire(max);
215 if (!bbuf)
216 return false;
217
218 skb_trim(bbuf, INT_H_SIZE);
219 bmsg = buf_msg(bbuf);
220 tipc_msg_init(bmsg, MSG_BUNDLER, BUNDLE_OPEN, INT_H_SIZE, dnode);
221 msg_set_seqno(bmsg, msg_seqno(msg));
222 msg_set_ack(bmsg, msg_ack(msg));
223 msg_set_bcast_ack(bmsg, msg_bcast_ack(msg));
224 bbuf->next = (*buf)->next;
225 tipc_msg_bundle(bbuf, *buf, mtu);
226 *buf = bbuf;
227 return true;
228}