aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/bcast.c8
-rw-r--r--net/tipc/bcast.h4
-rw-r--r--net/tipc/link.c64
-rw-r--r--net/tipc/link.h6
-rw-r--r--net/tipc/msg.h10
-rw-r--r--net/tipc/node.c32
-rw-r--r--net/tipc/node.h11
7 files changed, 108 insertions, 27 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index ae469b37d852..753f774cb46f 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -269,18 +269,19 @@ void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked)
269 * 269 *
270 * RCU is locked, no other locks set 270 * RCU is locked, no other locks set
271 */ 271 */
272void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, 272int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
273 struct tipc_msg *hdr) 273 struct tipc_msg *hdr)
274{ 274{
275 struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq; 275 struct sk_buff_head *inputq = &tipc_bc_base(net)->inputq;
276 struct sk_buff_head xmitq; 276 struct sk_buff_head xmitq;
277 int rc = 0;
277 278
278 __skb_queue_head_init(&xmitq); 279 __skb_queue_head_init(&xmitq);
279 280
280 tipc_bcast_lock(net); 281 tipc_bcast_lock(net);
281 if (msg_type(hdr) == STATE_MSG) { 282 if (msg_type(hdr) == STATE_MSG) {
282 tipc_link_bc_ack_rcv(l, msg_bcast_ack(hdr), &xmitq); 283 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);
284 } else { 285 } else {
285 tipc_link_bc_init_rcv(l, hdr); 286 tipc_link_bc_init_rcv(l, hdr);
286 } 287 }
@@ -291,6 +292,7 @@ void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
291 /* Any socket wakeup messages ? */ 292 /* Any socket wakeup messages ? */
292 if (!skb_queue_empty(inputq)) 293 if (!skb_queue_empty(inputq))
293 tipc_sk_rcv(net, inputq); 294 tipc_sk_rcv(net, inputq);
295 return rc;
294} 296}
295 297
296/* tipc_bcast_add_peer - add a peer node to broadcast link and bearer 298/* tipc_bcast_add_peer - add a peer node to broadcast link and bearer
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index d5e79b3767fd..5ffe34472ccd 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -56,8 +56,8 @@ int tipc_bcast_get_mtu(struct net *net);
56int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list); 56int tipc_bcast_xmit(struct net *net, struct sk_buff_head *list);
57int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb); 57int tipc_bcast_rcv(struct net *net, struct tipc_link *l, struct sk_buff *skb);
58void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked); 58void tipc_bcast_ack_rcv(struct net *net, struct tipc_link *l, u32 acked);
59void tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l, 59int tipc_bcast_sync_rcv(struct net *net, struct tipc_link *l,
60 struct tipc_msg *hdr); 60 struct tipc_msg *hdr);
61int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg); 61int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg);
62int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]); 62int tipc_nl_bc_link_set(struct net *net, struct nlattr *attrs[]);
63int tipc_bclink_reset_stats(struct net *net); 63int tipc_bclink_reset_stats(struct net *net);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 2c6e1b9e024b..136316fb37ec 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -367,6 +367,18 @@ int tipc_link_bc_peers(struct tipc_link *l)
367 return l->ackers; 367 return l->ackers;
368} 368}
369 369
370u16 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
370void tipc_link_set_mtu(struct tipc_link *l, int mtu) 382void tipc_link_set_mtu(struct tipc_link *l, int mtu)
371{ 383{
372 l->mtu = mtu; 384 l->mtu = mtu;
@@ -1135,7 +1147,10 @@ int tipc_link_build_state_msg(struct tipc_link *l, struct sk_buff_head *xmitq)
1135 if (((l->rcv_nxt ^ tipc_own_addr(l->net)) & 0xf) != 0xf) 1147 if (((l->rcv_nxt ^ tipc_own_addr(l->net)) & 0xf) != 0xf)
1136 return 0; 1148 return 0;
1137 l->rcv_unacked = 0; 1149 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;
1139 } 1154 }
1140 1155
1141 /* Unicast ACK */ 1156 /* Unicast ACK */
@@ -1236,7 +1251,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
1236 rc |= tipc_link_input(l, skb, l->inputq); 1251 rc |= tipc_link_input(l, skb, l->inputq);
1237 if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN)) 1252 if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN))
1238 rc |= tipc_link_build_state_msg(l, xmitq); 1253 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))
1240 break; 1255 break;
1241 } while ((skb = __skb_dequeue(defq))); 1256 } while ((skb = __skb_dequeue(defq)));
1242 1257
@@ -1250,10 +1265,11 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
1250 u16 rcvgap, int tolerance, int priority, 1265 u16 rcvgap, int tolerance, int priority,
1251 struct sk_buff_head *xmitq) 1266 struct sk_buff_head *xmitq)
1252{ 1267{
1268 struct tipc_link *bcl = l->bc_rcvlink;
1253 struct sk_buff *skb; 1269 struct sk_buff *skb;
1254 struct tipc_msg *hdr; 1270 struct tipc_msg *hdr;
1255 struct sk_buff_head *dfq = &l->deferdq; 1271 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);
1257 struct tipc_mon_state *mstate = &l->mon_state; 1273 struct tipc_mon_state *mstate = &l->mon_state;
1258 int dlen = 0; 1274 int dlen = 0;
1259 void *data; 1275 void *data;
@@ -1281,7 +1297,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
1281 msg_set_net_plane(hdr, l->net_plane); 1297 msg_set_net_plane(hdr, l->net_plane);
1282 msg_set_next_sent(hdr, l->snd_nxt); 1298 msg_set_next_sent(hdr, l->snd_nxt);
1283 msg_set_ack(hdr, l->rcv_nxt - 1); 1299 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);
1285 msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1); 1301 msg_set_last_bcast(hdr, l->bc_sndlink->snd_nxt - 1);
1286 msg_set_link_tolerance(hdr, tolerance); 1302 msg_set_link_tolerance(hdr, tolerance);
1287 msg_set_linkprio(hdr, priority); 1303 msg_set_linkprio(hdr, priority);
@@ -1291,6 +1307,7 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
1291 1307
1292 if (mtyp == STATE_MSG) { 1308 if (mtyp == STATE_MSG) {
1293 msg_set_seq_gap(hdr, rcvgap); 1309 msg_set_seq_gap(hdr, rcvgap);
1310 msg_set_bc_gap(hdr, link_bc_rcv_gap(bcl));
1294 msg_set_probe(hdr, probe); 1311 msg_set_probe(hdr, probe);
1295 tipc_mon_prep(l->net, data, &dlen, mstate, l->bearer_id); 1312 tipc_mon_prep(l->net, data, &dlen, mstate, l->bearer_id);
1296 msg_set_size(hdr, INT_H_SIZE + dlen); 1313 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)
1575 1592
1576/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state 1593/* tipc_link_bc_sync_rcv - update rcv link according to peer's send state
1577 */ 1594 */
1578void tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, 1595int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
1579 struct sk_buff_head *xmitq) 1596 struct sk_buff_head *xmitq)
1580{ 1597{
1581 u16 peers_snd_nxt = msg_bc_snd_nxt(hdr); 1598 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;
1582 1602
1583 if (!link_is_up(l)) 1603 if (!link_is_up(l))
1584 return; 1604 return rc;
1585 1605
1586 if (!msg_peer_node_is_up(hdr)) 1606 if (!msg_peer_node_is_up(hdr))
1587 return; 1607 return rc;
1588 1608
1589 /* Open when peer ackowledges our bcast init msg (pkt #1) */ 1609 /* Open when peer ackowledges our bcast init msg (pkt #1) */
1590 if (msg_ack(hdr)) 1610 if (msg_ack(hdr))
1591 l->bc_peer_is_up = true; 1611 l->bc_peer_is_up = true;
1592 1612
1593 if (!l->bc_peer_is_up) 1613 if (!l->bc_peer_is_up)
1594 return; 1614 return rc;
1595 1615
1596 /* Ignore if peers_snd_nxt goes beyond receive window */ 1616 /* Ignore if peers_snd_nxt goes beyond receive window */
1597 if (more(peers_snd_nxt, l->rcv_nxt + l->window)) 1617 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 */
1599 1634
1600 if (!more(peers_snd_nxt, l->rcv_nxt)) { 1635 if (!more(peers_snd_nxt, l->rcv_nxt)) {
1601 l->nack_state = BC_NACK_SND_CONDITIONAL; 1636 l->nack_state = BC_NACK_SND_CONDITIONAL;
1602 return; 1637 return 0;
1603 } 1638 }
1604 1639
1605 /* Don't NACK if one was recently sent or peeked */ 1640 /* Don't NACK if one was recently sent or peeked */
1606 if (l->nack_state == BC_NACK_SND_SUPPRESS) { 1641 if (l->nack_state == BC_NACK_SND_SUPPRESS) {
1607 l->nack_state = BC_NACK_SND_UNCONDITIONAL; 1642 l->nack_state = BC_NACK_SND_UNCONDITIONAL;
1608 return; 1643 return 0;
1609 } 1644 }
1610 1645
1611 /* Conditionally delay NACK sending until next synch rcv */ 1646 /* Conditionally delay NACK sending until next synch rcv */
1612 if (l->nack_state == BC_NACK_SND_CONDITIONAL) { 1647 if (l->nack_state == BC_NACK_SND_CONDITIONAL) {
1613 l->nack_state = BC_NACK_SND_UNCONDITIONAL; 1648 l->nack_state = BC_NACK_SND_UNCONDITIONAL;
1614 if ((peers_snd_nxt - l->rcv_nxt) < TIPC_MIN_LINK_WIN) 1649 if ((peers_snd_nxt - l->rcv_nxt) < TIPC_MIN_LINK_WIN)
1615 return; 1650 return 0;
1616 } 1651 }
1617 1652
1618 /* Send NACK now but suppress next one */ 1653 /* Send NACK now but suppress next one */
1619 tipc_link_build_bc_proto_msg(l, true, peers_snd_nxt, xmitq); 1654 tipc_link_build_bc_proto_msg(l, true, peers_snd_nxt, xmitq);
1620 l->nack_state = BC_NACK_SND_SUPPRESS; 1655 l->nack_state = BC_NACK_SND_SUPPRESS;
1656 return 0;
1621} 1657}
1622 1658
1623void tipc_link_bc_ack_rcv(struct tipc_link *l, u16 acked, 1659void 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,
1654} 1690}
1655 1691
1656/* tipc_link_bc_nack_rcv(): receive broadcast nack message 1692/* 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.
1657 */ 1695 */
1658int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, 1696int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
1659 struct sk_buff_head *xmitq) 1697 struct sk_buff_head *xmitq)
diff --git a/net/tipc/link.h b/net/tipc/link.h
index d7e9d42fcb2d..d1bd1787a768 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -63,7 +63,7 @@ enum {
63enum { 63enum {
64 TIPC_LINK_UP_EVT = 1, 64 TIPC_LINK_UP_EVT = 1,
65 TIPC_LINK_DOWN_EVT = (1 << 1), 65 TIPC_LINK_DOWN_EVT = (1 << 1),
66 TIPC_LINK_SND_BC_ACK = (1 << 2) 66 TIPC_LINK_SND_STATE = (1 << 2)
67}; 67};
68 68
69/* Starting value for maximum packet size negotiation on unicast links 69/* 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,
138void tipc_link_build_bc_sync_msg(struct tipc_link *l, 138void tipc_link_build_bc_sync_msg(struct tipc_link *l,
139 struct sk_buff_head *xmitq); 139 struct sk_buff_head *xmitq);
140void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr); 140void tipc_link_bc_init_rcv(struct tipc_link *l, struct tipc_msg *hdr);
141void tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr, 141int tipc_link_bc_sync_rcv(struct tipc_link *l, struct tipc_msg *hdr,
142 struct sk_buff_head *xmitq); 142 struct sk_buff_head *xmitq);
143int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb, 143int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
144 struct sk_buff_head *xmitq); 144 struct sk_buff_head *xmitq);
145#endif 145#endif
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 7cf52fb39bee..c3832cdf2278 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -719,6 +719,16 @@ static inline char *msg_media_addr(struct tipc_msg *m)
719 return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET]; 719 return (char *)&m->hdr[TIPC_MEDIA_INFO_OFFSET];
720} 720}
721 721
722static inline u32 msg_bc_gap(struct tipc_msg *m)
723{
724 return msg_bits(m, 8, 0, 0x3ff);
725}
726
727static inline void msg_set_bc_gap(struct tipc_msg *m, u32 n)
728{
729 msg_set_bits(m, 8, 0, 0x3ff, n);
730}
731
722/* 732/*
723 * Word 9 733 * Word 9
724 */ 734 */
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 7e8b75fd1a02..7ef14e2d2356 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -1262,6 +1262,34 @@ void tipc_node_broadcast(struct net *net, struct sk_buff *skb)
1262 kfree_skb(skb); 1262 kfree_skb(skb);
1263} 1263}
1264 1264
1265static 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
1265/** 1293/**
1266 * tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node 1294 * tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node
1267 * @net: the applicable net namespace 1295 * @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
1298 rc = tipc_bcast_rcv(net, be->link, skb); 1326 rc = tipc_bcast_rcv(net, be->link, skb);
1299 1327
1300 /* Broadcast ACKs are sent on a unicast link */ 1328 /* Broadcast ACKs are sent on a unicast link */
1301 if (rc & TIPC_LINK_SND_BC_ACK) { 1329 if (rc & TIPC_LINK_SND_STATE) {
1302 tipc_node_read_lock(n); 1330 tipc_node_read_lock(n);
1303 tipc_link_build_state_msg(le->link, &xmitq); 1331 tipc_link_build_state_msg(le->link, &xmitq);
1304 tipc_node_read_unlock(n); 1332 tipc_node_read_unlock(n);
@@ -1505,7 +1533,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
1505 1533
1506 /* Ensure broadcast reception is in synch with peer's send state */ 1534 /* Ensure broadcast reception is in synch with peer's send state */
1507 if (unlikely(usr == LINK_PROTOCOL)) 1535 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);
1509 else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack)) 1537 else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
1510 tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack); 1538 tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);
1511 1539
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 4578b34c7dca..39ef54c1f2ad 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * net/tipc/node.h: Include file for TIPC node management routines 2 * net/tipc/node.h: Include file for TIPC node management routines
3 * 3 *
4 * Copyright (c) 2000-2006, 2014-2015, Ericsson AB 4 * Copyright (c) 2000-2006, 2014-2016, Ericsson AB
5 * Copyright (c) 2005, 2010-2014, Wind River Systems 5 * Copyright (c) 2005, 2010-2014, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
@@ -45,11 +45,14 @@
45/* Optional capabilities supported by this code version 45/* Optional capabilities supported by this code version
46 */ 46 */
47enum { 47enum {
48 TIPC_BCAST_SYNCH = (1 << 1), 48 TIPC_BCAST_SYNCH = (1 << 1),
49 TIPC_BLOCK_FLOWCTL = (2 << 1) 49 TIPC_BCAST_STATE_NACK = (1 << 2),
50 TIPC_BLOCK_FLOWCTL = (1 << 3)
50}; 51};
51 52
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)
53#define INVALID_BEARER_ID -1 56#define INVALID_BEARER_ID -1
54 57
55void tipc_node_stop(struct net *net); 58void tipc_node_stop(struct net *net);