summaryrefslogtreecommitdiffstats
path: root/net/tipc/msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r--net/tipc/msg.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index f48e5857210f..e6d49cdc61b4 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -244,6 +244,65 @@ bool tipc_msg_validate(struct sk_buff **_skb)
244} 244}
245 245
246/** 246/**
247 * tipc_msg_fragment - build a fragment skb list for TIPC message
248 *
249 * @skb: TIPC message skb
250 * @hdr: internal msg header to be put on the top of the fragments
251 * @pktmax: max size of a fragment incl. the header
252 * @frags: returned fragment skb list
253 *
254 * Returns 0 if the fragmentation is successful, otherwise: -EINVAL
255 * or -ENOMEM
256 */
257int tipc_msg_fragment(struct sk_buff *skb, const struct tipc_msg *hdr,
258 int pktmax, struct sk_buff_head *frags)
259{
260 int pktno, nof_fragms, dsz, dmax, eat;
261 struct tipc_msg *_hdr;
262 struct sk_buff *_skb;
263 u8 *data;
264
265 /* Non-linear buffer? */
266 if (skb_linearize(skb))
267 return -ENOMEM;
268
269 data = (u8 *)skb->data;
270 dsz = msg_size(buf_msg(skb));
271 dmax = pktmax - INT_H_SIZE;
272 if (dsz <= dmax || !dmax)
273 return -EINVAL;
274
275 nof_fragms = dsz / dmax + 1;
276 for (pktno = 1; pktno <= nof_fragms; pktno++) {
277 if (pktno < nof_fragms)
278 eat = dmax;
279 else
280 eat = dsz % dmax;
281 /* Allocate a new fragment */
282 _skb = tipc_buf_acquire(INT_H_SIZE + eat, GFP_ATOMIC);
283 if (!_skb)
284 goto error;
285 skb_orphan(_skb);
286 __skb_queue_tail(frags, _skb);
287 /* Copy header & data to the fragment */
288 skb_copy_to_linear_data(_skb, hdr, INT_H_SIZE);
289 skb_copy_to_linear_data_offset(_skb, INT_H_SIZE, data, eat);
290 data += eat;
291 /* Update the fragment's header */
292 _hdr = buf_msg(_skb);
293 msg_set_fragm_no(_hdr, pktno);
294 msg_set_nof_fragms(_hdr, nof_fragms);
295 msg_set_size(_hdr, INT_H_SIZE + eat);
296 }
297 return 0;
298
299error:
300 __skb_queue_purge(frags);
301 __skb_queue_head_init(frags);
302 return -ENOMEM;
303}
304
305/**
247 * tipc_msg_build - create buffer chain containing specified header and data 306 * tipc_msg_build - create buffer chain containing specified header and data
248 * @mhdr: Message header, to be prepended to data 307 * @mhdr: Message header, to be prepended to data
249 * @m: User message 308 * @m: User message