aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-05-14 05:39:12 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-14 15:19:48 -0400
commit37e22164a8a3c39bdad45aa463b1e69a1fdf4110 (patch)
treef59a133e852df71ad5d34615f60d08483ec1ed18
parent5074ab89c555dd130ceeac129546670423d634b8 (diff)
tipc: rename and move message reassembly function
The function tipc_link_frag_rcv() is in reality a re-entrant generic message reassemby function that has nothing in particular to do with the link, where it is defined now. This becomes obvious when we see the need to call the function from other places in the code. In this commit rename it to tipc_buf_append() and move it to the file msg.c. We also simplify its signature by moving the tail pointer to the control block of the head buffer, hence making the head buffer self-contained. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bcast.c10
-rw-r--r--net/tipc/core.h1
-rw-r--r--net/tipc/link.c67
-rw-r--r--net/tipc/link.h14
-rw-r--r--net/tipc/msg.c55
-rw-r--r--net/tipc/msg.h5
-rw-r--r--net/tipc/node.c7
-rw-r--r--net/tipc/node.h6
8 files changed, 74 insertions, 91 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index a0978d0890cb..671f9817b4f4 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -506,18 +506,14 @@ receive:
506 tipc_node_unlock(node); 506 tipc_node_unlock(node);
507 tipc_link_bundle_rcv(buf); 507 tipc_link_bundle_rcv(buf);
508 } else if (msg_user(msg) == MSG_FRAGMENTER) { 508 } else if (msg_user(msg) == MSG_FRAGMENTER) {
509 int ret; 509 tipc_buf_append(&node->bclink.reasm_buf, &buf);
510 ret = tipc_link_frag_rcv(&node->bclink.reasm_head, 510 if (unlikely(!buf && !node->bclink.reasm_buf))
511 &node->bclink.reasm_tail,
512 &buf);
513 if (ret == LINK_REASM_ERROR)
514 goto unlock; 511 goto unlock;
515 tipc_bclink_lock(); 512 tipc_bclink_lock();
516 bclink_accept_pkt(node, seqno); 513 bclink_accept_pkt(node, seqno);
517 bcl->stats.recv_fragments++; 514 bcl->stats.recv_fragments++;
518 if (ret == LINK_REASM_COMPLETE) { 515 if (buf) {
519 bcl->stats.recv_fragmented++; 516 bcl->stats.recv_fragmented++;
520 /* Point msg to inner header */
521 msg = buf_msg(buf); 517 msg = buf_msg(buf);
522 tipc_bclink_unlock(); 518 tipc_bclink_unlock();
523 goto receive; 519 goto receive;
diff --git a/net/tipc/core.h b/net/tipc/core.h
index ae55d37267e6..2e00682bc455 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -187,6 +187,7 @@ static inline void k_term_timer(struct timer_list *timer)
187struct tipc_skb_cb { 187struct tipc_skb_cb {
188 void *handle; 188 void *handle;
189 bool deferred; 189 bool deferred;
190 struct sk_buff *tail;
190}; 191};
191 192
192#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) 193#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 9272d4cc0225..24d058796cd9 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -398,9 +398,8 @@ static void link_release_outqueue(struct tipc_link *l_ptr)
398 */ 398 */
399void tipc_link_reset_fragments(struct tipc_link *l_ptr) 399void tipc_link_reset_fragments(struct tipc_link *l_ptr)
400{ 400{
401 kfree_skb(l_ptr->reasm_head); 401 kfree_skb(l_ptr->reasm_buf);
402 l_ptr->reasm_head = NULL; 402 l_ptr->reasm_buf = NULL;
403 l_ptr->reasm_tail = NULL;
404} 403}
405 404
406/** 405/**
@@ -1573,17 +1572,12 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr)
1573 } 1572 }
1574 msg = buf_msg(buf); 1573 msg = buf_msg(buf);
1575 } else if (msg_user(msg) == MSG_FRAGMENTER) { 1574 } else if (msg_user(msg) == MSG_FRAGMENTER) {
1576 int rc;
1577
1578 l_ptr->stats.recv_fragments++; 1575 l_ptr->stats.recv_fragments++;
1579 rc = tipc_link_frag_rcv(&l_ptr->reasm_head, 1576 if (tipc_buf_append(&l_ptr->reasm_buf, &buf)) {
1580 &l_ptr->reasm_tail,
1581 &buf);
1582 if (rc == LINK_REASM_COMPLETE) {
1583 l_ptr->stats.recv_fragmented++; 1577 l_ptr->stats.recv_fragmented++;
1584 msg = buf_msg(buf); 1578 msg = buf_msg(buf);
1585 } else { 1579 } else {
1586 if (rc == LINK_REASM_ERROR) 1580 if (!l_ptr->reasm_buf)
1587 tipc_link_reset(l_ptr); 1581 tipc_link_reset(l_ptr);
1588 tipc_node_unlock(n_ptr); 1582 tipc_node_unlock(n_ptr);
1589 continue; 1583 continue;
@@ -2169,9 +2163,7 @@ static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr,
2169 } 2163 }
2170 if (msg_user(msg) == MSG_FRAGMENTER) { 2164 if (msg_user(msg) == MSG_FRAGMENTER) {
2171 l_ptr->stats.recv_fragments++; 2165 l_ptr->stats.recv_fragments++;
2172 tipc_link_frag_rcv(&l_ptr->reasm_head, 2166 tipc_buf_append(&l_ptr->reasm_buf, &buf);
2173 &l_ptr->reasm_tail,
2174 &buf);
2175 } 2167 }
2176 } 2168 }
2177exit: 2169exit:
@@ -2309,55 +2301,6 @@ static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf)
2309 return dsz; 2301 return dsz;
2310} 2302}
2311 2303
2312/* tipc_link_frag_rcv(): Called with node lock on. Returns
2313 * the reassembled buffer if message is complete.
2314 */
2315int tipc_link_frag_rcv(struct sk_buff **head, struct sk_buff **tail,
2316 struct sk_buff **fbuf)
2317{
2318 struct sk_buff *frag = *fbuf;
2319 struct tipc_msg *msg = buf_msg(frag);
2320 u32 fragid = msg_type(msg);
2321 bool headstolen;
2322 int delta;
2323
2324 skb_pull(frag, msg_hdr_sz(msg));
2325 if (fragid == FIRST_FRAGMENT) {
2326 if (*head || skb_unclone(frag, GFP_ATOMIC))
2327 goto out_free;
2328 *head = frag;
2329 skb_frag_list_init(*head);
2330 *fbuf = NULL;
2331 return 0;
2332 } else if (*head &&
2333 skb_try_coalesce(*head, frag, &headstolen, &delta)) {
2334 kfree_skb_partial(frag, headstolen);
2335 } else {
2336 if (!*head)
2337 goto out_free;
2338 if (!skb_has_frag_list(*head))
2339 skb_shinfo(*head)->frag_list = frag;
2340 else
2341 (*tail)->next = frag;
2342 *tail = frag;
2343 (*head)->truesize += frag->truesize;
2344 (*head)->data_len += frag->len;
2345 (*head)->len += frag->len;
2346 }
2347 if (fragid == LAST_FRAGMENT) {
2348 *fbuf = *head;
2349 *tail = *head = NULL;
2350 return LINK_REASM_COMPLETE;
2351 }
2352 *fbuf = NULL;
2353 return 0;
2354out_free:
2355 pr_warn_ratelimited("Link unable to reassemble fragmented message\n");
2356 kfree_skb(*fbuf);
2357 *fbuf = NULL;
2358 return LINK_REASM_ERROR;
2359}
2360
2361static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) 2304static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance)
2362{ 2305{
2363 if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL)) 2306 if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL))
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 7ba73fa6b81e..200d518b218e 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -40,11 +40,6 @@
40#include "msg.h" 40#include "msg.h"
41#include "node.h" 41#include "node.h"
42 42
43/* Link reassembly status codes
44 */
45#define LINK_REASM_ERROR -1
46#define LINK_REASM_COMPLETE 1
47
48/* Out-of-range value for link sequence numbers 43/* Out-of-range value for link sequence numbers
49 */ 44 */
50#define INVALID_LINK_SEQ 0x10000 45#define INVALID_LINK_SEQ 0x10000
@@ -140,8 +135,7 @@ struct tipc_stats {
140 * @next_out: ptr to first unsent outbound message in queue 135 * @next_out: ptr to first unsent outbound message in queue
141 * @waiting_ports: linked list of ports waiting for link congestion to abate 136 * @waiting_ports: linked list of ports waiting for link congestion to abate
142 * @long_msg_seq_no: next identifier to use for outbound fragmented messages 137 * @long_msg_seq_no: next identifier to use for outbound fragmented messages
143 * @reasm_head: list head of partially reassembled inbound message fragments 138 * @reasm_buf: head of partially reassembled inbound message fragments
144 * @reasm_tail: last fragment received
145 * @stats: collects statistics regarding link activity 139 * @stats: collects statistics regarding link activity
146 */ 140 */
147struct tipc_link { 141struct tipc_link {
@@ -204,8 +198,7 @@ struct tipc_link {
204 198
205 /* Fragmentation/reassembly */ 199 /* Fragmentation/reassembly */
206 u32 long_msg_seq_no; 200 u32 long_msg_seq_no;
207 struct sk_buff *reasm_head; 201 struct sk_buff *reasm_buf;
208 struct sk_buff *reasm_tail;
209 202
210 /* Statistics */ 203 /* Statistics */
211 struct tipc_stats stats; 204 struct tipc_stats stats;
@@ -242,9 +235,6 @@ int tipc_link_iovec_xmit_fast(struct tipc_port *sender,
242 struct iovec const *msg_sect, 235 struct iovec const *msg_sect,
243 unsigned int len, u32 destnode); 236 unsigned int len, u32 destnode);
244void tipc_link_bundle_rcv(struct sk_buff *buf); 237void tipc_link_bundle_rcv(struct sk_buff *buf);
245int tipc_link_frag_rcv(struct sk_buff **reasm_head,
246 struct sk_buff **reasm_tail,
247 struct sk_buff **fbuf);
248void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, 238void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob,
249 u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); 239 u32 gap, u32 tolerance, u32 priority, u32 acked_mtu);
250void tipc_link_push_queue(struct tipc_link *l_ptr); 240void tipc_link_push_queue(struct tipc_link *l_ptr);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index e525f8ce1dee..8be6e94a1ca9 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/msg.c: TIPC message header routines 2 * net/tipc/msg.c: TIPC message header routines
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, 2014, Ericsson AB
5 * Copyright (c) 2005, 2010-2011, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -99,3 +99,56 @@ int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
99 } 99 }
100 return dsz; 100 return dsz;
101} 101}
102
103/* tipc_buf_append(): Append a buffer to the fragment list of another buffer
104 * Let first buffer become head buffer
105 * Returns 1 and sets *buf to headbuf if chain is complete, otherwise 0
106 * Leaves headbuf pointer at NULL if failure
107 */
108int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
109{
110 struct sk_buff *head = *headbuf;
111 struct sk_buff *frag = *buf;
112 struct sk_buff *tail;
113 struct tipc_msg *msg = buf_msg(frag);
114 u32 fragid = msg_type(msg);
115 bool headstolen;
116 int delta;
117
118 skb_pull(frag, msg_hdr_sz(msg));
119
120 if (fragid == FIRST_FRAGMENT) {
121 if (head || skb_unclone(frag, GFP_ATOMIC))
122 goto out_free;
123 head = *headbuf = frag;
124 skb_frag_list_init(head);
125 return 0;
126 }
127 if (!head)
128 goto out_free;
129 tail = TIPC_SKB_CB(head)->tail;
130 if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
131 kfree_skb_partial(frag, headstolen);
132 } else {
133 if (!skb_has_frag_list(head))
134 skb_shinfo(head)->frag_list = frag;
135 else
136 tail->next = frag;
137 head->truesize += frag->truesize;
138 head->data_len += frag->len;
139 head->len += frag->len;
140 TIPC_SKB_CB(head)->tail = frag;
141 }
142 if (fragid == LAST_FRAGMENT) {
143 *buf = head;
144 TIPC_SKB_CB(head)->tail = NULL;
145 *headbuf = NULL;
146 return 1;
147 }
148 *buf = NULL;
149 return 0;
150out_free:
151 pr_warn_ratelimited("Unable to build fragment list\n");
152 kfree_skb(*buf);
153 return 0;
154}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 76d1269b9443..503511903d1d 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/msg.h: Include file for TIPC message header routines 2 * net/tipc/msg.h: Include file for TIPC message header routines
3 * 3 *
4 * Copyright (c) 2000-2007, Ericsson AB 4 * Copyright (c) 2000-2007, 2014, Ericsson AB
5 * Copyright (c) 2005-2008, 2010-2011, Wind River Systems 5 * Copyright (c) 2005-2008, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -711,4 +711,7 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
711 u32 destnode); 711 u32 destnode);
712int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, 712int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect,
713 unsigned int len, int max_size, struct sk_buff **buf); 713 unsigned int len, int max_size, struct sk_buff **buf);
714
715int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf);
716
714#endif 717#endif
diff --git a/net/tipc/node.c b/net/tipc/node.c
index facd5611e785..5b44c3041be4 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -286,10 +286,9 @@ static void node_lost_contact(struct tipc_node *n_ptr)
286 kfree_skb_list(n_ptr->bclink.deferred_head); 286 kfree_skb_list(n_ptr->bclink.deferred_head);
287 n_ptr->bclink.deferred_size = 0; 287 n_ptr->bclink.deferred_size = 0;
288 288
289 if (n_ptr->bclink.reasm_head) { 289 if (n_ptr->bclink.reasm_buf) {
290 kfree_skb(n_ptr->bclink.reasm_head); 290 kfree_skb(n_ptr->bclink.reasm_buf);
291 n_ptr->bclink.reasm_head = NULL; 291 n_ptr->bclink.reasm_buf = NULL;
292 n_ptr->bclink.reasm_tail = NULL;
293 } 292 }
294 293
295 tipc_bclink_remove_node(n_ptr->addr); 294 tipc_bclink_remove_node(n_ptr->addr);
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 5454edf994c3..9087063793f2 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -69,8 +69,7 @@ enum {
69 * @deferred_size: number of OOS b'cast messages in deferred queue 69 * @deferred_size: number of OOS b'cast messages in deferred queue
70 * @deferred_head: oldest OOS b'cast message received from node 70 * @deferred_head: oldest OOS b'cast message received from node
71 * @deferred_tail: newest OOS b'cast message received from node 71 * @deferred_tail: newest OOS b'cast message received from node
72 * @reasm_head: broadcast reassembly queue head from node 72 * @reasm_buf: broadcast reassembly queue head from node
73 * @reasm_tail: last broadcast fragment received from node
74 * @recv_permitted: true if node is allowed to receive b'cast messages 73 * @recv_permitted: true if node is allowed to receive b'cast messages
75 */ 74 */
76struct tipc_node_bclink { 75struct tipc_node_bclink {
@@ -81,8 +80,7 @@ struct tipc_node_bclink {
81 u32 deferred_size; 80 u32 deferred_size;
82 struct sk_buff *deferred_head; 81 struct sk_buff *deferred_head;
83 struct sk_buff *deferred_tail; 82 struct sk_buff *deferred_tail;
84 struct sk_buff *reasm_head; 83 struct sk_buff *reasm_buf;
85 struct sk_buff *reasm_tail;
86 bool recv_permitted; 84 bool recv_permitted;
87}; 85};
88 86