diff options
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r-- | net/tipc/link.c | 217 |
1 files changed, 166 insertions, 51 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 784b24b6d102..d64658053746 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -419,7 +419,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, | |||
419 | 419 | ||
420 | l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); | 420 | l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); |
421 | if (!l_ptr) { | 421 | if (!l_ptr) { |
422 | warn("Memory squeeze; Failed to create link\n"); | 422 | warn("Link creation failed, no memory\n"); |
423 | return NULL; | 423 | return NULL; |
424 | } | 424 | } |
425 | memset(l_ptr, 0, sizeof(*l_ptr)); | 425 | memset(l_ptr, 0, sizeof(*l_ptr)); |
@@ -469,7 +469,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, | |||
469 | 469 | ||
470 | if (!pb) { | 470 | if (!pb) { |
471 | kfree(l_ptr); | 471 | kfree(l_ptr); |
472 | warn("Memory squeeze; Failed to create link\n"); | 472 | warn("Link creation failed, no memory for print buffer\n"); |
473 | return NULL; | 473 | return NULL; |
474 | } | 474 | } |
475 | tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); | 475 | tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); |
@@ -574,7 +574,6 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all) | |||
574 | break; | 574 | break; |
575 | list_del_init(&p_ptr->wait_list); | 575 | list_del_init(&p_ptr->wait_list); |
576 | p_ptr->congested_link = NULL; | 576 | p_ptr->congested_link = NULL; |
577 | assert(p_ptr->wakeup); | ||
578 | spin_lock_bh(p_ptr->publ.lock); | 577 | spin_lock_bh(p_ptr->publ.lock); |
579 | p_ptr->publ.congested = 0; | 578 | p_ptr->publ.congested = 0; |
580 | p_ptr->wakeup(&p_ptr->publ); | 579 | p_ptr->wakeup(&p_ptr->publ); |
@@ -691,6 +690,7 @@ void tipc_link_reset(struct link *l_ptr) | |||
691 | struct sk_buff *buf; | 690 | struct sk_buff *buf; |
692 | u32 prev_state = l_ptr->state; | 691 | u32 prev_state = l_ptr->state; |
693 | u32 checkpoint = l_ptr->next_in_no; | 692 | u32 checkpoint = l_ptr->next_in_no; |
693 | int was_active_link = tipc_link_is_active(l_ptr); | ||
694 | 694 | ||
695 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); | 695 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); |
696 | 696 | ||
@@ -712,7 +712,7 @@ void tipc_link_reset(struct link *l_ptr) | |||
712 | tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); | 712 | tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); |
713 | dbg_link_dump(); | 713 | dbg_link_dump(); |
714 | #endif | 714 | #endif |
715 | if (tipc_node_has_active_links(l_ptr->owner) && | 715 | if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && |
716 | l_ptr->owner->permit_changeover) { | 716 | l_ptr->owner->permit_changeover) { |
717 | l_ptr->reset_checkpoint = checkpoint; | 717 | l_ptr->reset_checkpoint = checkpoint; |
718 | l_ptr->exp_msg_count = START_CHANGEOVER; | 718 | l_ptr->exp_msg_count = START_CHANGEOVER; |
@@ -755,7 +755,7 @@ void tipc_link_reset(struct link *l_ptr) | |||
755 | 755 | ||
756 | static void link_activate(struct link *l_ptr) | 756 | static void link_activate(struct link *l_ptr) |
757 | { | 757 | { |
758 | l_ptr->next_in_no = 1; | 758 | l_ptr->next_in_no = l_ptr->stats.recv_info = 1; |
759 | tipc_node_link_up(l_ptr->owner, l_ptr); | 759 | tipc_node_link_up(l_ptr->owner, l_ptr); |
760 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); | 760 | tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); |
761 | link_send_event(tipc_cfg_link_event, l_ptr, 1); | 761 | link_send_event(tipc_cfg_link_event, l_ptr, 1); |
@@ -820,6 +820,8 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
820 | break; | 820 | break; |
821 | case RESET_MSG: | 821 | case RESET_MSG: |
822 | dbg_link("RES -> RR\n"); | 822 | dbg_link("RES -> RR\n"); |
823 | info("Resetting link <%s>, requested by peer\n", | ||
824 | l_ptr->name); | ||
823 | tipc_link_reset(l_ptr); | 825 | tipc_link_reset(l_ptr); |
824 | l_ptr->state = RESET_RESET; | 826 | l_ptr->state = RESET_RESET; |
825 | l_ptr->fsm_msg_cnt = 0; | 827 | l_ptr->fsm_msg_cnt = 0; |
@@ -844,6 +846,8 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
844 | break; | 846 | break; |
845 | case RESET_MSG: | 847 | case RESET_MSG: |
846 | dbg_link("RES -> RR\n"); | 848 | dbg_link("RES -> RR\n"); |
849 | info("Resetting link <%s>, requested by peer " | ||
850 | "while probing\n", l_ptr->name); | ||
847 | tipc_link_reset(l_ptr); | 851 | tipc_link_reset(l_ptr); |
848 | l_ptr->state = RESET_RESET; | 852 | l_ptr->state = RESET_RESET; |
849 | l_ptr->fsm_msg_cnt = 0; | 853 | l_ptr->fsm_msg_cnt = 0; |
@@ -875,6 +879,8 @@ static void link_state_event(struct link *l_ptr, unsigned event) | |||
875 | } else { /* Link has failed */ | 879 | } else { /* Link has failed */ |
876 | dbg_link("-> RU (%u probes unanswered)\n", | 880 | dbg_link("-> RU (%u probes unanswered)\n", |
877 | l_ptr->fsm_msg_cnt); | 881 | l_ptr->fsm_msg_cnt); |
882 | warn("Resetting link <%s>, peer not responding\n", | ||
883 | l_ptr->name); | ||
878 | tipc_link_reset(l_ptr); | 884 | tipc_link_reset(l_ptr); |
879 | l_ptr->state = RESET_UNKNOWN; | 885 | l_ptr->state = RESET_UNKNOWN; |
880 | l_ptr->fsm_msg_cnt = 0; | 886 | l_ptr->fsm_msg_cnt = 0; |
@@ -1050,7 +1056,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
1050 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); | 1056 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); |
1051 | buf_discard(buf); | 1057 | buf_discard(buf); |
1052 | if (imp > CONN_MANAGER) { | 1058 | if (imp > CONN_MANAGER) { |
1053 | warn("Resetting <%s>, send queue full", l_ptr->name); | 1059 | warn("Resetting link <%s>, send queue full", l_ptr->name); |
1054 | tipc_link_reset(l_ptr); | 1060 | tipc_link_reset(l_ptr); |
1055 | } | 1061 | } |
1056 | return dsz; | 1062 | return dsz; |
@@ -1135,9 +1141,13 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
1135 | if (n_ptr) { | 1141 | if (n_ptr) { |
1136 | tipc_node_lock(n_ptr); | 1142 | tipc_node_lock(n_ptr); |
1137 | l_ptr = n_ptr->active_links[selector & 1]; | 1143 | l_ptr = n_ptr->active_links[selector & 1]; |
1138 | dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); | ||
1139 | if (l_ptr) { | 1144 | if (l_ptr) { |
1145 | dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); | ||
1140 | res = tipc_link_send_buf(l_ptr, buf); | 1146 | res = tipc_link_send_buf(l_ptr, buf); |
1147 | } else { | ||
1148 | dbg("Attempt to send msg to unreachable node:\n"); | ||
1149 | msg_dbg(buf_msg(buf),">>>"); | ||
1150 | buf_discard(buf); | ||
1141 | } | 1151 | } |
1142 | tipc_node_unlock(n_ptr); | 1152 | tipc_node_unlock(n_ptr); |
1143 | } else { | 1153 | } else { |
@@ -1242,8 +1252,6 @@ int tipc_link_send_sections_fast(struct port *sender, | |||
1242 | int res; | 1252 | int res; |
1243 | u32 selector = msg_origport(hdr) & 1; | 1253 | u32 selector = msg_origport(hdr) & 1; |
1244 | 1254 | ||
1245 | assert(destaddr != tipc_own_addr); | ||
1246 | |||
1247 | again: | 1255 | again: |
1248 | /* | 1256 | /* |
1249 | * Try building message using port's max_pkt hint. | 1257 | * Try building message using port's max_pkt hint. |
@@ -1604,40 +1612,121 @@ void tipc_link_push_queue(struct link *l_ptr) | |||
1604 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); | 1612 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); |
1605 | } | 1613 | } |
1606 | 1614 | ||
1615 | static void link_reset_all(unsigned long addr) | ||
1616 | { | ||
1617 | struct node *n_ptr; | ||
1618 | char addr_string[16]; | ||
1619 | u32 i; | ||
1620 | |||
1621 | read_lock_bh(&tipc_net_lock); | ||
1622 | n_ptr = tipc_node_find((u32)addr); | ||
1623 | if (!n_ptr) { | ||
1624 | read_unlock_bh(&tipc_net_lock); | ||
1625 | return; /* node no longer exists */ | ||
1626 | } | ||
1627 | |||
1628 | tipc_node_lock(n_ptr); | ||
1629 | |||
1630 | warn("Resetting all links to %s\n", | ||
1631 | addr_string_fill(addr_string, n_ptr->addr)); | ||
1632 | |||
1633 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1634 | if (n_ptr->links[i]) { | ||
1635 | link_print(n_ptr->links[i], TIPC_OUTPUT, | ||
1636 | "Resetting link\n"); | ||
1637 | tipc_link_reset(n_ptr->links[i]); | ||
1638 | } | ||
1639 | } | ||
1640 | |||
1641 | tipc_node_unlock(n_ptr); | ||
1642 | read_unlock_bh(&tipc_net_lock); | ||
1643 | } | ||
1644 | |||
1645 | static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | ||
1646 | { | ||
1647 | struct tipc_msg *msg = buf_msg(buf); | ||
1648 | |||
1649 | warn("Retransmission failure on link <%s>\n", l_ptr->name); | ||
1650 | tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>"); | ||
1651 | |||
1652 | if (l_ptr->addr) { | ||
1653 | |||
1654 | /* Handle failure on standard link */ | ||
1655 | |||
1656 | link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n"); | ||
1657 | tipc_link_reset(l_ptr); | ||
1658 | |||
1659 | } else { | ||
1660 | |||
1661 | /* Handle failure on broadcast link */ | ||
1662 | |||
1663 | struct node *n_ptr; | ||
1664 | char addr_string[16]; | ||
1665 | |||
1666 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); | ||
1667 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle); | ||
1668 | |||
1669 | n_ptr = l_ptr->owner->next; | ||
1670 | tipc_node_lock(n_ptr); | ||
1671 | |||
1672 | addr_string_fill(addr_string, n_ptr->addr); | ||
1673 | tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); | ||
1674 | tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); | ||
1675 | tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); | ||
1676 | tipc_printf(TIPC_OUTPUT, "Last in: %u, ", n_ptr->bclink.last_in); | ||
1677 | tipc_printf(TIPC_OUTPUT, "Gap after: %u, ", n_ptr->bclink.gap_after); | ||
1678 | tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to); | ||
1679 | tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync); | ||
1680 | |||
1681 | tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); | ||
1682 | |||
1683 | tipc_node_unlock(n_ptr); | ||
1684 | |||
1685 | l_ptr->stale_count = 0; | ||
1686 | } | ||
1687 | } | ||
1688 | |||
1607 | void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | 1689 | void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, |
1608 | u32 retransmits) | 1690 | u32 retransmits) |
1609 | { | 1691 | { |
1610 | struct tipc_msg *msg; | 1692 | struct tipc_msg *msg; |
1611 | 1693 | ||
1694 | if (!buf) | ||
1695 | return; | ||
1696 | |||
1697 | msg = buf_msg(buf); | ||
1698 | |||
1612 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | 1699 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); |
1613 | 1700 | ||
1614 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { | 1701 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { |
1615 | msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); | 1702 | if (!skb_cloned(buf)) { |
1616 | dbg_print_link(l_ptr, " "); | 1703 | msg_dbg(msg, ">NO_RETR->BCONG>"); |
1617 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | 1704 | dbg_print_link(l_ptr, " "); |
1618 | l_ptr->retransm_queue_size = retransmits; | 1705 | l_ptr->retransm_queue_head = msg_seqno(msg); |
1619 | return; | 1706 | l_ptr->retransm_queue_size = retransmits; |
1707 | return; | ||
1708 | } else { | ||
1709 | /* Don't retransmit if driver already has the buffer */ | ||
1710 | } | ||
1711 | } else { | ||
1712 | /* Detect repeated retransmit failures on uncongested bearer */ | ||
1713 | |||
1714 | if (l_ptr->last_retransmitted == msg_seqno(msg)) { | ||
1715 | if (++l_ptr->stale_count > 100) { | ||
1716 | link_retransmit_failure(l_ptr, buf); | ||
1717 | return; | ||
1718 | } | ||
1719 | } else { | ||
1720 | l_ptr->last_retransmitted = msg_seqno(msg); | ||
1721 | l_ptr->stale_count = 1; | ||
1722 | } | ||
1620 | } | 1723 | } |
1724 | |||
1621 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | 1725 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { |
1622 | msg = buf_msg(buf); | 1726 | msg = buf_msg(buf); |
1623 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1727 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
1624 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1728 | 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)) { | 1729 | 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>"); | 1730 | msg_dbg(buf_msg(buf), ">RETR>"); |
1642 | buf = buf->next; | 1731 | buf = buf->next; |
1643 | retransmits--; | 1732 | retransmits--; |
@@ -1650,6 +1739,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1650 | return; | 1739 | return; |
1651 | } | 1740 | } |
1652 | } | 1741 | } |
1742 | |||
1653 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; | 1743 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; |
1654 | } | 1744 | } |
1655 | 1745 | ||
@@ -1720,6 +1810,11 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1720 | link_recv_non_seq(buf); | 1810 | link_recv_non_seq(buf); |
1721 | continue; | 1811 | continue; |
1722 | } | 1812 | } |
1813 | |||
1814 | if (unlikely(!msg_short(msg) && | ||
1815 | (msg_destnode(msg) != tipc_own_addr))) | ||
1816 | goto cont; | ||
1817 | |||
1723 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1818 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
1724 | if (unlikely(!n_ptr)) | 1819 | if (unlikely(!n_ptr)) |
1725 | goto cont; | 1820 | goto cont; |
@@ -2140,7 +2235,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | |||
2140 | 2235 | ||
2141 | if (msg_linkprio(msg) && | 2236 | if (msg_linkprio(msg) && |
2142 | (msg_linkprio(msg) != l_ptr->priority)) { | 2237 | (msg_linkprio(msg) != l_ptr->priority)) { |
2143 | warn("Changing prio <%s>: %u->%u\n", | 2238 | warn("Resetting link <%s>, priority change %u->%u\n", |
2144 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); | 2239 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); |
2145 | l_ptr->priority = msg_linkprio(msg); | 2240 | l_ptr->priority = msg_linkprio(msg); |
2146 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ | 2241 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ |
@@ -2209,17 +2304,22 @@ void tipc_link_tunnel(struct link *l_ptr, | |||
2209 | u32 length = msg_size(msg); | 2304 | u32 length = msg_size(msg); |
2210 | 2305 | ||
2211 | tunnel = l_ptr->owner->active_links[selector & 1]; | 2306 | tunnel = l_ptr->owner->active_links[selector & 1]; |
2212 | if (!tipc_link_is_up(tunnel)) | 2307 | if (!tipc_link_is_up(tunnel)) { |
2308 | warn("Link changeover error, " | ||
2309 | "tunnel link no longer available\n"); | ||
2213 | return; | 2310 | return; |
2311 | } | ||
2214 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); | 2312 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); |
2215 | buf = buf_acquire(length + INT_H_SIZE); | 2313 | buf = buf_acquire(length + INT_H_SIZE); |
2216 | if (!buf) | 2314 | if (!buf) { |
2315 | warn("Link changeover error, " | ||
2316 | "unable to send tunnel msg\n"); | ||
2217 | return; | 2317 | return; |
2318 | } | ||
2218 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); | 2319 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); |
2219 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); | 2320 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); |
2220 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); | 2321 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); |
2221 | msg_dbg(buf_msg(buf), ">SEND>"); | 2322 | msg_dbg(buf_msg(buf), ">SEND>"); |
2222 | assert(tunnel); | ||
2223 | tipc_link_send_buf(tunnel, buf); | 2323 | tipc_link_send_buf(tunnel, buf); |
2224 | } | 2324 | } |
2225 | 2325 | ||
@@ -2235,23 +2335,27 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2235 | u32 msgcount = l_ptr->out_queue_size; | 2335 | u32 msgcount = l_ptr->out_queue_size; |
2236 | struct sk_buff *crs = l_ptr->first_out; | 2336 | struct sk_buff *crs = l_ptr->first_out; |
2237 | struct link *tunnel = l_ptr->owner->active_links[0]; | 2337 | struct link *tunnel = l_ptr->owner->active_links[0]; |
2238 | int split_bundles = tipc_node_has_redundant_links(l_ptr->owner); | ||
2239 | struct tipc_msg tunnel_hdr; | 2338 | struct tipc_msg tunnel_hdr; |
2339 | int split_bundles; | ||
2240 | 2340 | ||
2241 | if (!tunnel) | 2341 | if (!tunnel) |
2242 | return; | 2342 | return; |
2243 | 2343 | ||
2244 | if (!l_ptr->owner->permit_changeover) | 2344 | if (!l_ptr->owner->permit_changeover) { |
2345 | warn("Link changeover error, " | ||
2346 | "peer did not permit changeover\n"); | ||
2245 | return; | 2347 | return; |
2348 | } | ||
2246 | 2349 | ||
2247 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2350 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2248 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | 2351 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); |
2249 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2352 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2250 | msg_set_msgcnt(&tunnel_hdr, msgcount); | 2353 | msg_set_msgcnt(&tunnel_hdr, msgcount); |
2354 | dbg("Link changeover requires %u tunnel messages\n", msgcount); | ||
2355 | |||
2251 | if (!l_ptr->first_out) { | 2356 | if (!l_ptr->first_out) { |
2252 | struct sk_buff *buf; | 2357 | struct sk_buff *buf; |
2253 | 2358 | ||
2254 | assert(!msgcount); | ||
2255 | buf = buf_acquire(INT_H_SIZE); | 2359 | buf = buf_acquire(INT_H_SIZE); |
2256 | if (buf) { | 2360 | if (buf) { |
2257 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | 2361 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); |
@@ -2261,10 +2365,15 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2261 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); | 2365 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); |
2262 | tipc_link_send_buf(tunnel, buf); | 2366 | tipc_link_send_buf(tunnel, buf); |
2263 | } else { | 2367 | } else { |
2264 | warn("Memory squeeze; link changeover failed\n"); | 2368 | warn("Link changeover error, " |
2369 | "unable to send changeover msg\n"); | ||
2265 | } | 2370 | } |
2266 | return; | 2371 | return; |
2267 | } | 2372 | } |
2373 | |||
2374 | split_bundles = (l_ptr->owner->active_links[0] != | ||
2375 | l_ptr->owner->active_links[1]); | ||
2376 | |||
2268 | while (crs) { | 2377 | while (crs) { |
2269 | struct tipc_msg *msg = buf_msg(crs); | 2378 | struct tipc_msg *msg = buf_msg(crs); |
2270 | 2379 | ||
@@ -2310,7 +2419,8 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) | |||
2310 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); | 2419 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); |
2311 | outbuf = buf_acquire(length + INT_H_SIZE); | 2420 | outbuf = buf_acquire(length + INT_H_SIZE); |
2312 | if (outbuf == NULL) { | 2421 | if (outbuf == NULL) { |
2313 | warn("Memory squeeze; buffer duplication failed\n"); | 2422 | warn("Link changeover error, " |
2423 | "unable to send duplicate msg\n"); | ||
2314 | return; | 2424 | return; |
2315 | } | 2425 | } |
2316 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | 2426 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); |
@@ -2364,11 +2474,15 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2364 | u32 msg_count = msg_msgcnt(tunnel_msg); | 2474 | u32 msg_count = msg_msgcnt(tunnel_msg); |
2365 | 2475 | ||
2366 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; | 2476 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; |
2367 | assert(dest_link != *l_ptr); | ||
2368 | if (!dest_link) { | 2477 | if (!dest_link) { |
2369 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); | 2478 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); |
2370 | goto exit; | 2479 | goto exit; |
2371 | } | 2480 | } |
2481 | if (dest_link == *l_ptr) { | ||
2482 | err("Unexpected changeover message on link <%s>\n", | ||
2483 | (*l_ptr)->name); | ||
2484 | goto exit; | ||
2485 | } | ||
2372 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, | 2486 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, |
2373 | (*l_ptr)->b_ptr->net_plane); | 2487 | (*l_ptr)->b_ptr->net_plane); |
2374 | *l_ptr = dest_link; | 2488 | *l_ptr = dest_link; |
@@ -2381,7 +2495,7 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2381 | } | 2495 | } |
2382 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); | 2496 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); |
2383 | if (*buf == NULL) { | 2497 | if (*buf == NULL) { |
2384 | warn("Memory squeeze; failed to extract msg\n"); | 2498 | warn("Link changeover error, duplicate msg dropped\n"); |
2385 | goto exit; | 2499 | goto exit; |
2386 | } | 2500 | } |
2387 | msg_dbg(tunnel_msg, "TNL<REC<"); | 2501 | msg_dbg(tunnel_msg, "TNL<REC<"); |
@@ -2393,13 +2507,17 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2393 | 2507 | ||
2394 | if (tipc_link_is_up(dest_link)) { | 2508 | if (tipc_link_is_up(dest_link)) { |
2395 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); | 2509 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); |
2510 | info("Resetting link <%s>, changeover initiated by peer\n", | ||
2511 | dest_link->name); | ||
2396 | tipc_link_reset(dest_link); | 2512 | tipc_link_reset(dest_link); |
2397 | dest_link->exp_msg_count = msg_count; | 2513 | dest_link->exp_msg_count = msg_count; |
2514 | dbg("Expecting %u tunnelled messages\n", msg_count); | ||
2398 | if (!msg_count) | 2515 | if (!msg_count) |
2399 | goto exit; | 2516 | goto exit; |
2400 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { | 2517 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { |
2401 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); | 2518 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); |
2402 | dest_link->exp_msg_count = msg_count; | 2519 | dest_link->exp_msg_count = msg_count; |
2520 | dbg("Expecting %u tunnelled messages\n", msg_count); | ||
2403 | if (!msg_count) | 2521 | if (!msg_count) |
2404 | goto exit; | 2522 | goto exit; |
2405 | } | 2523 | } |
@@ -2407,6 +2525,8 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2407 | /* Receive original message */ | 2525 | /* Receive original message */ |
2408 | 2526 | ||
2409 | if (dest_link->exp_msg_count == 0) { | 2527 | if (dest_link->exp_msg_count == 0) { |
2528 | warn("Link switchover error, " | ||
2529 | "got too many tunnelled messages\n"); | ||
2410 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); | 2530 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); |
2411 | dbg_print_link(dest_link, "LINK:"); | 2531 | dbg_print_link(dest_link, "LINK:"); |
2412 | goto exit; | 2532 | goto exit; |
@@ -2422,7 +2542,7 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2422 | buf_discard(tunnel_buf); | 2542 | buf_discard(tunnel_buf); |
2423 | return 1; | 2543 | return 1; |
2424 | } else { | 2544 | } else { |
2425 | warn("Memory squeeze; dropped incoming msg\n"); | 2545 | warn("Link changeover error, original msg dropped\n"); |
2426 | } | 2546 | } |
2427 | } | 2547 | } |
2428 | exit: | 2548 | exit: |
@@ -2444,13 +2564,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf) | |||
2444 | while (msgcount--) { | 2564 | while (msgcount--) { |
2445 | obuf = buf_extract(buf, pos); | 2565 | obuf = buf_extract(buf, pos); |
2446 | if (obuf == NULL) { | 2566 | if (obuf == NULL) { |
2447 | char addr_string[16]; | 2567 | warn("Link unable to unbundle message(s)\n"); |
2448 | 2568 | break; | |
2449 | warn("Buffer allocation failure;\n"); | ||
2450 | warn(" incoming message(s) from %s lost\n", | ||
2451 | addr_string_fill(addr_string, | ||
2452 | msg_orignode(buf_msg(buf)))); | ||
2453 | return; | ||
2454 | }; | 2569 | }; |
2455 | pos += align(msg_size(buf_msg(obuf))); | 2570 | pos += align(msg_size(buf_msg(obuf))); |
2456 | msg_dbg(buf_msg(obuf), " /"); | 2571 | msg_dbg(buf_msg(obuf), " /"); |
@@ -2508,7 +2623,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2508 | } | 2623 | } |
2509 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); | 2624 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); |
2510 | if (fragm == NULL) { | 2625 | if (fragm == NULL) { |
2511 | warn("Memory squeeze; failed to fragment msg\n"); | 2626 | warn("Link unable to fragment message\n"); |
2512 | dsz = -ENOMEM; | 2627 | dsz = -ENOMEM; |
2513 | goto exit; | 2628 | goto exit; |
2514 | } | 2629 | } |
@@ -2623,7 +2738,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2623 | set_fragm_size(pbuf,fragm_sz); | 2738 | set_fragm_size(pbuf,fragm_sz); |
2624 | set_expected_frags(pbuf,exp_fragm_cnt - 1); | 2739 | set_expected_frags(pbuf,exp_fragm_cnt - 1); |
2625 | } else { | 2740 | } else { |
2626 | warn("Memory squeeze; got no defragmenting buffer\n"); | 2741 | warn("Link unable to reassemble fragmented message\n"); |
2627 | } | 2742 | } |
2628 | buf_discard(fbuf); | 2743 | buf_discard(fbuf); |
2629 | return 0; | 2744 | return 0; |