Skip to content

Commit 4c94cc2

Browse files
Jon Maloydavem330
authored andcommitted
tipc: fall back to smaller MTU if allocation of local send skb fails
When sending node local messages the code is using an 'mtu' of 66060 bytes to avoid unnecessary fragmentation. During situations of low memory tipc_msg_build() may sometimes fail to allocate such large buffers, resulting in unnecessary send failures. This can easily be remedied by falling back to a smaller MTU, and then reassemble the buffer chain as if the message were arriving from a remote node. At the same time, we change the initial MTU setting of the broadcast link to a lower value, so that large messages always are fragmented into smaller buffers even when we run in single node mode. Apart from obtaining the same advantage as for the 'fallback' solution above, this turns out to give a significant performance improvement. This can probably be explained with the __pskb_copy() operation performed on the buffer for each recipient during reception. We found the optimal value for this, considering the most relevant skb pool, to be 3744 bytes. Acked-by: Ying Xue <[email protected]> Signed-off-by: Jon Maloy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 201c78e commit 4c94cc2

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

net/tipc/bcast.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* net/tipc/bcast.c: TIPC broadcast code
33
*
4-
* Copyright (c) 2004-2006, 2014-2016, Ericsson AB
4+
* Copyright (c) 2004-2006, 2014-2017, Ericsson AB
55
* Copyright (c) 2004, Intel Corporation.
66
* Copyright (c) 2005, 2010-2011, Wind River Systems
77
* All rights reserved.
@@ -42,8 +42,8 @@
4242
#include "link.h"
4343
#include "name_table.h"
4444

45-
#define BCLINK_WIN_DEFAULT 50 /* bcast link window size (default) */
46-
#define BCLINK_WIN_MIN 32 /* bcast minimum link window size */
45+
#define BCLINK_WIN_DEFAULT 50 /* bcast link window size (default) */
46+
#define BCLINK_WIN_MIN 32 /* bcast minimum link window size */
4747

4848
const char tipc_bclink_name[] = "broadcast-link";
4949

@@ -74,6 +74,10 @@ static struct tipc_bc_base *tipc_bc_base(struct net *net)
7474
return tipc_net(net)->bcbase;
7575
}
7676

77+
/* tipc_bcast_get_mtu(): -get the MTU currently used by broadcast link
78+
* Note: the MTU is decremented to give room for a tunnel header, in
79+
* case the message needs to be sent as replicast
80+
*/
7781
int tipc_bcast_get_mtu(struct net *net)
7882
{
7983
return tipc_link_mtu(tipc_bc_sndlink(net)) - INT_H_SIZE;
@@ -515,7 +519,7 @@ int tipc_bcast_init(struct net *net)
515519
spin_lock_init(&tipc_net(net)->bclock);
516520

517521
if (!tipc_link_bc_create(net, 0, 0,
518-
U16_MAX,
522+
FB_MTU,
519523
BCLINK_WIN_DEFAULT,
520524
0,
521525
&bb->inputq,

net/tipc/link.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ bool tipc_link_create(struct net *net, char *if_name, int bearer_id,
483483
/**
484484
* tipc_link_bc_create - create new link to be used for broadcast
485485
* @n: pointer to associated node
486-
* @mtu: mtu to be used
486+
* @mtu: mtu to be used initially if no peers
487487
* @window: send window to be used
488488
* @inputq: queue to put messages ready for delivery
489489
* @namedq: queue to put binding table update messages ready for delivery

net/tipc/msg.c

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -251,29 +251,42 @@ bool tipc_msg_validate(struct sk_buff **_skb)
251251
* @pktmax: Max packet size that can be used
252252
* @list: Buffer or chain of buffers to be returned to caller
253253
*
254+
* Note that the recursive call we are making here is safe, since it can
255+
* logically go only one further level down.
256+
*
254257
* Returns message data size or errno: -ENOMEM, -EFAULT
255258
*/
256-
int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
257-
int offset, int dsz, int pktmax, struct sk_buff_head *list)
259+
int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset,
260+
int dsz, int pktmax, struct sk_buff_head *list)
258261
{
259262
int mhsz = msg_hdr_sz(mhdr);
263+
struct tipc_msg pkthdr;
260264
int msz = mhsz + dsz;
261-
int pktno = 1;
262-
int pktsz;
263265
int pktrem = pktmax;
264-
int drem = dsz;
265-
struct tipc_msg pkthdr;
266266
struct sk_buff *skb;
267+
int drem = dsz;
268+
int pktno = 1;
267269
char *pktpos;
270+
int pktsz;
268271
int rc;
269272

270273
msg_set_size(mhdr, msz);
271274

272275
/* No fragmentation needed? */
273276
if (likely(msz <= pktmax)) {
274277
skb = tipc_buf_acquire(msz, GFP_KERNEL);
275-
if (unlikely(!skb))
278+
279+
/* Fall back to smaller MTU if node local message */
280+
if (unlikely(!skb)) {
281+
if (pktmax != MAX_MSG_SIZE)
282+
return -ENOMEM;
283+
rc = tipc_msg_build(mhdr, m, offset, dsz, FB_MTU, list);
284+
if (rc != dsz)
285+
return rc;
286+
if (tipc_msg_assemble(list))
287+
return dsz;
276288
return -ENOMEM;
289+
}
277290
skb_orphan(skb);
278291
__skb_queue_tail(list, skb);
279292
skb_copy_to_linear_data(skb, mhdr, mhsz);
@@ -589,6 +602,30 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
589602
return true;
590603
}
591604

605+
/* tipc_msg_assemble() - assemble chain of fragments into one message
606+
*/
607+
bool tipc_msg_assemble(struct sk_buff_head *list)
608+
{
609+
struct sk_buff *skb, *tmp = NULL;
610+
611+
if (skb_queue_len(list) == 1)
612+
return true;
613+
614+
while ((skb = __skb_dequeue(list))) {
615+
skb->next = NULL;
616+
if (tipc_buf_append(&tmp, &skb)) {
617+
__skb_queue_tail(list, skb);
618+
return true;
619+
}
620+
if (!tmp)
621+
break;
622+
}
623+
__skb_queue_purge(list);
624+
__skb_queue_head_init(list);
625+
pr_warn("Failed do assemble buffer\n");
626+
return false;
627+
}
628+
592629
/* tipc_msg_reassemble() - clone a buffer chain of fragments and
593630
* reassemble the clones into one message
594631
*/

net/tipc/msg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ struct plist;
9898
#define MAX_H_SIZE 60 /* Largest possible TIPC header size */
9999

100100
#define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE)
101-
101+
#define FB_MTU 3744
102102
#define TIPC_MEDIA_INFO_OFFSET 5
103103

104104
struct tipc_skb_cb {
@@ -943,6 +943,7 @@ bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos);
943943
int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
944944
int offset, int dsz, int mtu, struct sk_buff_head *list);
945945
bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err);
946+
bool tipc_msg_assemble(struct sk_buff_head *list);
946947
bool tipc_msg_reassemble(struct sk_buff_head *list, struct sk_buff_head *rcvq);
947948
bool tipc_msg_pskb_copy(u32 dst, struct sk_buff_head *msg,
948949
struct sk_buff_head *cpy);

0 commit comments

Comments
 (0)