diff options
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 96 |
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 | ||
40 | u32 tipc_msg_tot_importance(struct tipc_msg *m) | 40 | static 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 | |||
54 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | 45 | void 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 | */ | ||
155 | bool 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 | */ | ||
197 | bool 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 | } | ||