aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2006-06-26 02:40:01 -0400
committerDavid S. Miller <davem@davemloft.net>2006-06-26 02:40:01 -0400
commitd356eeba8e34786621d85468e5176052813a3059 (patch)
tree0f802091559dfafdc62fa6c3059fcebff60b2bc7
parent260082471ed3f6d751e9767e5a278d4e495d83f7 (diff)
[TIPC]: Multicast link failure now resets all links to "nacking" node.
This fix prevents node from crashing. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Per Liden <per.liden@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bcast.c32
-rw-r--r--net/tipc/link.c124
2 files changed, 128 insertions, 28 deletions
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 2c4ecbe50082..00691b7c35f8 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -49,13 +49,19 @@
49#include "name_table.h" 49#include "name_table.h"
50#include "bcast.h" 50#include "bcast.h"
51 51
52
53#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ 52#define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */
54 53
55#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ 54#define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */
56 55
57#define BCLINK_LOG_BUF_SIZE 0 56#define BCLINK_LOG_BUF_SIZE 0
58 57
58/*
59 * Loss rate for incoming broadcast frames; used to test retransmission code.
60 * Set to N to cause every N'th frame to be discarded; 0 => don't discard any.
61 */
62
63#define TIPC_BCAST_LOSS_RATE 0
64
59/** 65/**
60 * struct bcbearer_pair - a pair of bearers used by broadcast link 66 * struct bcbearer_pair - a pair of bearers used by broadcast link
61 * @primary: pointer to primary bearer 67 * @primary: pointer to primary bearer
@@ -165,21 +171,18 @@ static int bclink_ack_allowed(u32 n)
165 * @after: sequence number of last packet to *not* retransmit 171 * @after: sequence number of last packet to *not* retransmit
166 * @to: sequence number of last packet to retransmit 172 * @to: sequence number of last packet to retransmit
167 * 173 *
168 * Called with 'node' locked, bc_lock unlocked 174 * Called with bc_lock locked
169 */ 175 */
170 176
171static void bclink_retransmit_pkt(u32 after, u32 to) 177static void bclink_retransmit_pkt(u32 after, u32 to)
172{ 178{
173 struct sk_buff *buf; 179 struct sk_buff *buf;
174 180
175 spin_lock_bh(&bc_lock);
176 buf = bcl->first_out; 181 buf = bcl->first_out;
177 while (buf && less_eq(buf_seqno(buf), after)) { 182 while (buf && less_eq(buf_seqno(buf), after)) {
178 buf = buf->next; 183 buf = buf->next;
179 } 184 }
180 if (buf != NULL) 185 tipc_link_retransmit(bcl, buf, mod(to - after));
181 tipc_link_retransmit(bcl, buf, mod(to - after));
182 spin_unlock_bh(&bc_lock);
183} 186}
184 187
185/** 188/**
@@ -399,7 +402,10 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
399 */ 402 */
400 403
401void tipc_bclink_recv_pkt(struct sk_buff *buf) 404void tipc_bclink_recv_pkt(struct sk_buff *buf)
402{ 405{
406#if (TIPC_BCAST_LOSS_RATE)
407 static int rx_count = 0;
408#endif
403 struct tipc_msg *msg = buf_msg(buf); 409 struct tipc_msg *msg = buf_msg(buf);
404 struct node* node = tipc_node_find(msg_prevnode(msg)); 410 struct node* node = tipc_node_find(msg_prevnode(msg));
405 u32 next_in; 411 u32 next_in;
@@ -420,9 +426,13 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
420 tipc_node_lock(node); 426 tipc_node_lock(node);
421 tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); 427 tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
422 tipc_node_unlock(node); 428 tipc_node_unlock(node);
429 spin_lock_bh(&bc_lock);
423 bcl->stats.recv_nacks++; 430 bcl->stats.recv_nacks++;
431 bcl->owner->next = node; /* remember requestor */
424 bclink_retransmit_pkt(msg_bcgap_after(msg), 432 bclink_retransmit_pkt(msg_bcgap_after(msg),
425 msg_bcgap_to(msg)); 433 msg_bcgap_to(msg));
434 bcl->owner->next = NULL;
435 spin_unlock_bh(&bc_lock);
426 } else { 436 } else {
427 tipc_bclink_peek_nack(msg_destnode(msg), 437 tipc_bclink_peek_nack(msg_destnode(msg),
428 msg_bcast_tag(msg), 438 msg_bcast_tag(msg),
@@ -433,6 +443,14 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
433 return; 443 return;
434 } 444 }
435 445
446#if (TIPC_BCAST_LOSS_RATE)
447 if (++rx_count == TIPC_BCAST_LOSS_RATE) {
448 rx_count = 0;
449 buf_discard(buf);
450 return;
451 }
452#endif
453
436 tipc_node_lock(node); 454 tipc_node_lock(node);
437receive: 455receive:
438 deferred = node->bclink.deferred_head; 456 deferred = node->bclink.deferred_head;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 955b87d9b46c..ba7d3f19be12 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1604,40 +1604,121 @@ void tipc_link_push_queue(struct link *l_ptr)
1604 tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); 1604 tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
1605} 1605}
1606 1606
1607static void link_reset_all(unsigned long addr)
1608{
1609 struct node *n_ptr;
1610 char addr_string[16];
1611 u32 i;
1612
1613 read_lock_bh(&tipc_net_lock);
1614 n_ptr = tipc_node_find((u32)addr);
1615 if (!n_ptr) {
1616 read_unlock_bh(&tipc_net_lock);
1617 return; /* node no longer exists */
1618 }
1619
1620 tipc_node_lock(n_ptr);
1621
1622 warn("Resetting all links to %s\n",
1623 addr_string_fill(addr_string, n_ptr->addr));
1624
1625 for (i = 0; i < MAX_BEARERS; i++) {
1626 if (n_ptr->links[i]) {
1627 link_print(n_ptr->links[i], TIPC_OUTPUT,
1628 "Resetting link\n");
1629 tipc_link_reset(n_ptr->links[i]);
1630 }
1631 }
1632
1633 tipc_node_unlock(n_ptr);
1634 read_unlock_bh(&tipc_net_lock);
1635}
1636
1637static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
1638{
1639 struct tipc_msg *msg = buf_msg(buf);
1640
1641 warn("Retransmission failure on link <%s>\n", l_ptr->name);
1642 tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>");
1643
1644 if (l_ptr->addr) {
1645
1646 /* Handle failure on standard link */
1647
1648 link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n");
1649 tipc_link_reset(l_ptr);
1650
1651 } else {
1652
1653 /* Handle failure on broadcast link */
1654
1655 struct node *n_ptr;
1656 char addr_string[16];
1657
1658 tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg));
1659 tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle);
1660
1661 n_ptr = l_ptr->owner->next;
1662 tipc_node_lock(n_ptr);
1663
1664 addr_string_fill(addr_string, n_ptr->addr);
1665 tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string);
1666 tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported);
1667 tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked);
1668 tipc_printf(TIPC_OUTPUT, "Last in: %u, ", n_ptr->bclink.last_in);
1669 tipc_printf(TIPC_OUTPUT, "Gap after: %u, ", n_ptr->bclink.gap_after);
1670 tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to);
1671 tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync);
1672
1673 tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr);
1674
1675 tipc_node_unlock(n_ptr);
1676
1677 l_ptr->stale_count = 0;
1678 }
1679}
1680
1607void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, 1681void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
1608 u32 retransmits) 1682 u32 retransmits)
1609{ 1683{
1610 struct tipc_msg *msg; 1684 struct tipc_msg *msg;
1611 1685
1686 if (!buf)
1687 return;
1688
1689 msg = buf_msg(buf);
1690
1612 dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); 1691 dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
1613 1692
1614 if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { 1693 if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
1615 msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); 1694 if (!skb_cloned(buf)) {
1616 dbg_print_link(l_ptr, " "); 1695 msg_dbg(msg, ">NO_RETR->BCONG>");
1617 l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); 1696 dbg_print_link(l_ptr, " ");
1618 l_ptr->retransm_queue_size = retransmits; 1697 l_ptr->retransm_queue_head = msg_seqno(msg);
1619 return; 1698 l_ptr->retransm_queue_size = retransmits;
1699 return;
1700 } else {
1701 /* Don't retransmit if driver already has the buffer */
1702 }
1703 } else {
1704 /* Detect repeated retransmit failures on uncongested bearer */
1705
1706 if (l_ptr->last_retransmitted == msg_seqno(msg)) {
1707 if (++l_ptr->stale_count > 100) {
1708 link_retransmit_failure(l_ptr, buf);
1709 return;
1710 }
1711 } else {
1712 l_ptr->last_retransmitted = msg_seqno(msg);
1713 l_ptr->stale_count = 1;
1714 }
1620 } 1715 }
1716
1621 while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { 1717 while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
1622 msg = buf_msg(buf); 1718 msg = buf_msg(buf);
1623 msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); 1719 msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
1624 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 1720 msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
1625 if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { 1721 if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
1626 /* Catch if retransmissions fail repeatedly: */
1627 if (l_ptr->last_retransmitted == msg_seqno(msg)) {
1628 if (++l_ptr->stale_count > 100) {
1629 tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>");
1630 info("...Retransmitted %u times\n",
1631 l_ptr->stale_count);
1632 link_print(l_ptr, TIPC_CONS, "Resetting Link\n");
1633 tipc_link_reset(l_ptr);
1634 break;
1635 }
1636 } else {
1637 l_ptr->stale_count = 0;
1638 }
1639 l_ptr->last_retransmitted = msg_seqno(msg);
1640
1641 msg_dbg(buf_msg(buf), ">RETR>"); 1722 msg_dbg(buf_msg(buf), ">RETR>");
1642 buf = buf->next; 1723 buf = buf->next;
1643 retransmits--; 1724 retransmits--;
@@ -1650,6 +1731,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf,
1650 return; 1731 return;
1651 } 1732 }
1652 } 1733 }
1734
1653 l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; 1735 l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
1654} 1736}
1655 1737