Skip to content

Commit 02d11ca

Browse files
Jon Paul Maloydavem330
authored andcommitted
tipc: transfer broadcast nacks in link state messages
When we send broadcasts in clusters of more 70-80 nodes, we sometimes see the broadcast link resetting because of an excessive number of retransmissions. This is caused by a combination of two factors: 1) A 'NACK crunch", where loss of broadcast packets is discovered and NACK'ed by several nodes simultaneously, leading to multiple redundant broadcast retransmissions. 2) The fact that the NACKS as such also are sent as broadcast, leading to excessive load and packet loss on the transmitting switch/bridge. This commit deals with the latter problem, by moving sending of broadcast nacks from the dedicated BCAST_PROTOCOL/NACK message type to regular unicast LINK_PROTOCOL/STATE messages. We allocate 10 unused bits in word 8 of the said message for this purpose, and introduce a new capability bit, TIPC_BCAST_STATE_NACK in order to keep the change backwards compatible. Reviewed-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2c896fb commit 02d11ca

7 files changed

Lines changed: 108 additions & 27 deletions

File tree

net/tipc/bcast.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,18 +269,19 @@ void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked)
269269
*
270270
* RCU is locked, no other locks set
271271
*/
272-
void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
273-
struct tipc_msg *hdr)
272+
int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
273+
struct tipc_msg *hdr)
274274
{
275275
struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
276276
struct sk_buff_head xmitq;
277+
int rc = 0;
277278

278279
__skb_queue_head_init(&xmitq);
279280

280281
tipc_bcast_lock(net);
281282
if (msg_type(hdr) == STATE_MSG) {
282283
tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq);
283-
tipc_link_bc_sync_rcv(l, hdr, &xmitq);
284+
rc = tipc_link_bc_sync_rcv(l, hdr, &xmitq);
284285
} else {
285286
tipc_link_bc_init_rcv(l, hdr);
286287
}
@@ -291,6 +292,7 @@ void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
291292
/* Any socket wakeup messages ? */
292293
if (!skb_queue_empty(inputq))
293294
tipc_sk_rcv(net, inputq);
295+
return rc;
294296
}
295297

296298
/* tipc_bcast_add_peer - add a peer node to broadcast link and bearer

net/tipc/bcast.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ int tipc_bcast_get_mtu(struct net *net);
5656
int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);
5757
int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb);
5858
void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked);
59-
void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
60-
struct tipc_msg *hdr);
59+
int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
60+
struct tipc_msg *hdr);
6161
int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
6262
int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
6363
int tipc_bclink_reset_stats(struct net *net);

net/tipc/link.c

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,18 @@ int tipc_link_bc_peers(struct tipc_link *l)
367367
return l->ackers;
368368
}
369369

370+
u16 link_bc_rcv_gap(struct tipc_link *l)
371+
{
372+
struct sk_buff *skb = skb_peek(&l->deferdq);
373+
u16 gap = 0;
374+
375+
if (more(l->snd_nxt, l->rcv_nxt))
376+
gap = l->snd_nxt - l->rcv_nxt;
377+
if (skb)
378+
gap = buf_seqno(skb) - l->rcv_nxt;
379+
return gap;
380+
}
381+
370382
void tipc_link_set_mtu(struct tipc_link *l, int mtu)
371383
{
372384
l->mtu = mtu;
@@ -1135,7 +1147,10 @@ int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
11351147
if (((l->rcv_nxt ^ tipc_own_addr(l->net)) & 0xf) != 0xf)
11361148
return 0;
11371149
l->rcv_unacked = 0;
1138-
return TIPC_LINK_SND_BC_ACK;
1150+
1151+
/* Use snd_nxt to store peer's snd_nxt in broadcast rcv link */
1152+
l->snd_nxt = l->rcv_nxt;
1153+
return TIPC_LINK_SND_STATE;
11391154
}
11401155

11411156
/* Unicast ACK */
@@ -1236,7 +1251,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
12361251
rc |= tipc_link_input(l, skb, l->inputq);
12371252
if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN))
12381253
rc |= tipc_link_build_state_msg(l, xmitq);
1239-
if (unlikely(rc & ~TIPC_LINK_SND_BC_ACK))
1254+
if (unlikely(rc & ~TIPC_LINK_SND_STATE))
12401255
break;
12411256
} while ((skb = __skb_dequeue(defq)));
12421257

@@ -1250,10 +1265,11 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12501265
u16 rcvgap, int tolerance, int priority,
12511266
struct sk_buff_head *xmitq)
12521267
{
1268+
struct tipc_link *bcl = l->bc_rcvlink;
12531269
struct sk_buff *skb;
12541270
struct tipc_msg *hdr;
12551271
struct sk_buff_head *dfq = &l->deferdq;
1256-
bool node_up = link_is_up(l->bc_rcvlink);
1272+
bool node_up = link_is_up(bcl);
12571273
struct tipc_mon_state *mstate = &l->mon_state;
12581274
int dlen = 0;
12591275
void *data;
@@ -1281,7 +1297,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12811297
msg_set_net_plane(hdr, l->net_plane);
12821298
msg_set_next_sent(hdr, l->snd_nxt);
12831299
msg_set_ack(hdr, l->rcv_nxt - 1);
1284-
msg_set_bcast_ack(hdr, l->bc_rcvlink->rcv_nxt - 1);
1300+
msg_set_bcast_ack(hdr, bcl->rcv_nxt - 1);
12851301
msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);
12861302
msg_set_link_tolerance(hdr, tolerance);
12871303
msg_set_linkprio(hdr, priority);
@@ -1291,6 +1307,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
12911307

12921308
if (mtyp == STATE_MSG) {
12931309
msg_set_seq_gap(hdr, rcvgap);
1310+
msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
12941311
msg_set_probe(hdr, probe);
12951312
tipc_mon_prep(l->net, data, &dlen, mstate, l->bearer_id);
12961313
msg_set_size(hdr, INT_H_SIZE + dlen);
@@ -1575,49 +1592,68 @@ void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr)
15751592

15761593
/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state
15771594
*/
1578-
void tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
1579-
struct sk_buff_head *xmitq)
1595+
int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
1596+
struct sk_buff_head *xmitq)
15801597
{
15811598
u16 peers_snd_nxt = msg_bc_snd_nxt(hdr);
1599+
u16 from = msg_bcast_ack(hdr) + 1;
1600+
u16 to = from + msg_bc_gap(hdr) - 1;
1601+
int rc = 0;
15821602

15831603
if (!link_is_up(l))
1584-
return;
1604+
return rc;
15851605

15861606
if (!msg_peer_node_is_up(hdr))
1587-
return;
1607+
return rc;
15881608

15891609
/* Open when peer ackowledges our bcast init msg (pkt #1) */
15901610
if (msg_ack(hdr))
15911611
l->bc_peer_is_up = true;
15921612

15931613
if (!l->bc_peer_is_up)
1594-
return;
1614+
return rc;
15951615

15961616
/* Ignore if peers_snd_nxt goes beyond receive window */
15971617
if (more(peers_snd_nxt, l->rcv_nxt + l->window))
1598-
return;
1618+
return rc;
1619+
1620+
if (!less(to, from)) {
1621+
rc = tipc_link_retrans(l->bc_sndlink, from, to, xmitq);
1622+
l->stats.recv_nacks++;
1623+
}
1624+
1625+
l->snd_nxt = peers_snd_nxt;
1626+
if (link_bc_rcv_gap(l))
1627+
rc |= TIPC_LINK_SND_STATE;
1628+
1629+
/* Return now if sender supports nack via STATE messages */
1630+
if (l->peer_caps & TIPC_BCAST_STATE_NACK)
1631+
return rc;
1632+
1633+
/* Otherwise, be backwards compatible */
15991634

16001635
if (!more(peers_snd_nxt, l->rcv_nxt)) {
16011636
l->nack_state = BC_NACK_SND_CONDITIONAL;
1602-
return;
1637+
return 0;
16031638
}
16041639

16051640
/* Don't NACK if one was recently sent or peeked */
16061641
if (l->nack_state == BC_NACK_SND_SUPPRESS) {
16071642
l->nack_state = BC_NACK_SND_UNCONDITIONAL;
1608-
return;
1643+
return 0;
16091644
}
16101645

16111646
/* Conditionally delay NACK sending until next synch rcv */
16121647
if (l->nack_state == BC_NACK_SND_CONDITIONAL) {
16131648
l->nack_state = BC_NACK_SND_UNCONDITIONAL;
16141649
if ((peers_snd_nxt - l->rcv_nxt) < TIPC_MIN_LINK_WIN)
1615-
return;
1650+
return 0;
16161651
}
16171652

16181653
/* Send NACK now but suppress next one */
16191654
tipc_link_build_bc_proto_msg(l, true, peers_snd_nxt, xmitq);
16201655
l->nack_state = BC_NACK_SND_SUPPRESS;
1656+
return 0;
16211657
}
16221658

16231659
void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
@@ -1654,6 +1690,8 @@ void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
16541690
}
16551691

16561692
/* tipc_link_bc_nack_rcv(): receive broadcast nack message
1693+
* This function is here for backwards compatibility, since
1694+
* no BCAST_PROTOCOL/STATE messages occur from TIPC v2.5.
16571695
*/
16581696
int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
16591697
struct sk_buff_head *xmitq)

net/tipc/link.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ enum {
6363
enum {
6464
TIPC_LINK_UP_EVT = 1,
6565
TIPC_LINK_DOWN_EVT = (1 << 1),
66-
TIPC_LINK_SND_BC_ACK = (1 << 2)
66+
TIPC_LINK_SND_STATE = (1 << 2)
6767
};
6868

6969
/* Starting value for maximum packet size negotiation on unicast links
@@ -138,8 +138,8 @@ void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked,
138138
void tipc_link_build_bc_sync_msg(struct tipc_link *l,
139139
struct sk_buff_head *xmitq);
140140
void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr);
141-
void tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
142-
struct sk_buff_head *xmitq);
141+
int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
142+
struct sk_buff_head *xmitq);
143143
int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
144144
struct sk_buff_head *xmitq);
145145
#endif

net/tipc/msg.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,16 @@ static inline char *msg_media_addr(struct tipc_msg *m)
719719
return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET];
720720
}
721721

722+
static inline u32 msg_bc_gap(struct tipc_msg *m)
723+
{
724+
return msg_bits(m, 8, 0, 0x3ff);
725+
}
726+
727+
static inline void msg_set_bc_gap(struct tipc_msg *m, u32 n)
728+
{
729+
msg_set_bits(m, 8, 0, 0x3ff, n);
730+
}
731+
722732
/*
723733
* Word 9
724734
*/

net/tipc/node.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,34 @@ void tipc_node_broadcast(struct net *net, struct sk_buff *skb)
12621262
kfree_skb(skb);
12631263
}
12641264

1265+
static void tipc_node_bc_sync_rcv(struct tipc_node *n, struct tipc_msg *hdr,
1266+
int bearer_id, struct sk_buff_head *xmitq)
1267+
{
1268+
struct tipc_link *ucl;
1269+
int rc;
1270+
1271+
rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr);
1272+
1273+
if (rc & TIPC_LINK_DOWN_EVT) {
1274+
tipc_bearer_reset_all(n->net);
1275+
return;
1276+
}
1277+
1278+
if (!(rc & TIPC_LINK_SND_STATE))
1279+
return;
1280+
1281+
/* If probe message, a STATE response will be sent anyway */
1282+
if (msg_probe(hdr))
1283+
return;
1284+
1285+
/* Produce a STATE message carrying broadcast NACK */
1286+
tipc_node_read_lock(n);
1287+
ucl = n->links[bearer_id].link;
1288+
if (ucl)
1289+
tipc_link_build_state_msg(ucl, xmitq);
1290+
tipc_node_read_unlock(n);
1291+
}
1292+
12651293
/**
12661294
* tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node
12671295
* @net: the applicable net namespace
@@ -1298,7 +1326,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
12981326
rc = tipc_bcast_rcv(net, be->link, skb);
12991327

13001328
/* Broadcast ACKs are sent on a unicast link */
1301-
if (rc & TIPC_LINK_SND_BC_ACK) {
1329+
if (rc & TIPC_LINK_SND_STATE) {
13021330
tipc_node_read_lock(n);
13031331
tipc_link_build_state_msg(le->link, &xmitq);
13041332
tipc_node_read_unlock(n);
@@ -1505,7 +1533,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
15051533

15061534
/* Ensure broadcast reception is in synch with peer's send state */
15071535
if (unlikely(usr == LINK_PROTOCOL))
1508-
tipc_bcast_sync_rcv(net, n->bc_entry.link, hdr);
1536+
tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);
15091537
else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
15101538
tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);
15111539

net/tipc/node.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* net/tipc/node.h: Include file for TIPC node management routines
33
*
4-
* Copyright (c) 2000-2006, 2014-2015, Ericsson AB
4+
* Copyright (c) 2000-2006, 2014-2016, Ericsson AB
55
* Copyright (c) 2005, 2010-2014, Wind River Systems
66
* All rights reserved.
77
*
@@ -45,11 +45,14 @@
4545
/* Optional capabilities supported by this code version
4646
*/
4747
enum {
48-
TIPC_BCAST_SYNCH = (1 << 1),
49-
TIPC_BLOCK_FLOWCTL = (2 << 1)
48+
TIPC_BCAST_SYNCH = (1 << 1),
49+
TIPC_BCAST_STATE_NACK = (1 << 2),
50+
TIPC_BLOCK_FLOWCTL = (1 << 3)
5051
};
5152

52-
#define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | TIPC_BLOCK_FLOWCTL)
53+
#define TIPC_NODE_CAPABILITIES (TIPC_BCAST_SYNCH | \
54+
TIPC_BCAST_STATE_NACK | \
55+
TIPC_BLOCK_FLOWCTL)
5356
#define INVALID_BEARER_ID -1
5457

5558
void tipc_node_stop(struct net *net);

0 commit comments

Comments
 (0)