diff options
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r-- | net/tipc/link.c | 230 |
1 files changed, 174 insertions, 56 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index 784b24b6d102..c10e18a49b96 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/link.c: TIPC link code | 2 | * net/tipc/link.c: TIPC link code |
3 | * | 3 | * |
4 | * Copyright (c) 1996-2006, Ericsson AB | 4 | * Copyright (c) 1996-2006, Ericsson AB |
5 | * Copyright (c) 2004-2005, Wind River Systems | 5 | * Copyright (c) 2004-2006, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -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; |
@@ -982,17 +988,20 @@ static int link_bundle_buf(struct link *l_ptr, | |||
982 | struct tipc_msg *bundler_msg = buf_msg(bundler); | 988 | struct tipc_msg *bundler_msg = buf_msg(bundler); |
983 | struct tipc_msg *msg = buf_msg(buf); | 989 | struct tipc_msg *msg = buf_msg(buf); |
984 | u32 size = msg_size(msg); | 990 | u32 size = msg_size(msg); |
985 | u32 to_pos = align(msg_size(bundler_msg)); | 991 | u32 bundle_size = msg_size(bundler_msg); |
986 | u32 rest = link_max_pkt(l_ptr) - to_pos; | 992 | u32 to_pos = align(bundle_size); |
993 | u32 pad = to_pos - bundle_size; | ||
987 | 994 | ||
988 | if (msg_user(bundler_msg) != MSG_BUNDLER) | 995 | if (msg_user(bundler_msg) != MSG_BUNDLER) |
989 | return 0; | 996 | return 0; |
990 | if (msg_type(bundler_msg) != OPEN_MSG) | 997 | if (msg_type(bundler_msg) != OPEN_MSG) |
991 | return 0; | 998 | return 0; |
992 | if (rest < align(size)) | 999 | if (skb_tailroom(bundler) < (pad + size)) |
1000 | return 0; | ||
1001 | if (link_max_pkt(l_ptr) < (to_pos + size)) | ||
993 | return 0; | 1002 | return 0; |
994 | 1003 | ||
995 | skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size); | 1004 | skb_put(bundler, pad + size); |
996 | memcpy(bundler->data + to_pos, buf->data, size); | 1005 | memcpy(bundler->data + to_pos, buf->data, size); |
997 | msg_set_size(bundler_msg, to_pos + size); | 1006 | msg_set_size(bundler_msg, to_pos + size); |
998 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); | 1007 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); |
@@ -1050,7 +1059,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
1050 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); | 1059 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); |
1051 | buf_discard(buf); | 1060 | buf_discard(buf); |
1052 | if (imp > CONN_MANAGER) { | 1061 | if (imp > CONN_MANAGER) { |
1053 | warn("Resetting <%s>, send queue full", l_ptr->name); | 1062 | warn("Resetting link <%s>, send queue full", l_ptr->name); |
1054 | tipc_link_reset(l_ptr); | 1063 | tipc_link_reset(l_ptr); |
1055 | } | 1064 | } |
1056 | return dsz; | 1065 | return dsz; |
@@ -1135,9 +1144,13 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
1135 | if (n_ptr) { | 1144 | if (n_ptr) { |
1136 | tipc_node_lock(n_ptr); | 1145 | tipc_node_lock(n_ptr); |
1137 | l_ptr = n_ptr->active_links[selector & 1]; | 1146 | 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) { | 1147 | if (l_ptr) { |
1148 | dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); | ||
1140 | res = tipc_link_send_buf(l_ptr, buf); | 1149 | res = tipc_link_send_buf(l_ptr, buf); |
1150 | } else { | ||
1151 | dbg("Attempt to send msg to unreachable node:\n"); | ||
1152 | msg_dbg(buf_msg(buf),">>>"); | ||
1153 | buf_discard(buf); | ||
1141 | } | 1154 | } |
1142 | tipc_node_unlock(n_ptr); | 1155 | tipc_node_unlock(n_ptr); |
1143 | } else { | 1156 | } else { |
@@ -1242,8 +1255,6 @@ int tipc_link_send_sections_fast(struct port *sender, | |||
1242 | int res; | 1255 | int res; |
1243 | u32 selector = msg_origport(hdr) & 1; | 1256 | u32 selector = msg_origport(hdr) & 1; |
1244 | 1257 | ||
1245 | assert(destaddr != tipc_own_addr); | ||
1246 | |||
1247 | again: | 1258 | again: |
1248 | /* | 1259 | /* |
1249 | * Try building message using port's max_pkt hint. | 1260 | * Try building message using port's max_pkt hint. |
@@ -1604,40 +1615,121 @@ void tipc_link_push_queue(struct link *l_ptr) | |||
1604 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); | 1615 | tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); |
1605 | } | 1616 | } |
1606 | 1617 | ||
1618 | static void link_reset_all(unsigned long addr) | ||
1619 | { | ||
1620 | struct node *n_ptr; | ||
1621 | char addr_string[16]; | ||
1622 | u32 i; | ||
1623 | |||
1624 | read_lock_bh(&tipc_net_lock); | ||
1625 | n_ptr = tipc_node_find((u32)addr); | ||
1626 | if (!n_ptr) { | ||
1627 | read_unlock_bh(&tipc_net_lock); | ||
1628 | return; /* node no longer exists */ | ||
1629 | } | ||
1630 | |||
1631 | tipc_node_lock(n_ptr); | ||
1632 | |||
1633 | warn("Resetting all links to %s\n", | ||
1634 | addr_string_fill(addr_string, n_ptr->addr)); | ||
1635 | |||
1636 | for (i = 0; i < MAX_BEARERS; i++) { | ||
1637 | if (n_ptr->links[i]) { | ||
1638 | link_print(n_ptr->links[i], TIPC_OUTPUT, | ||
1639 | "Resetting link\n"); | ||
1640 | tipc_link_reset(n_ptr->links[i]); | ||
1641 | } | ||
1642 | } | ||
1643 | |||
1644 | tipc_node_unlock(n_ptr); | ||
1645 | read_unlock_bh(&tipc_net_lock); | ||
1646 | } | ||
1647 | |||
1648 | static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) | ||
1649 | { | ||
1650 | struct tipc_msg *msg = buf_msg(buf); | ||
1651 | |||
1652 | warn("Retransmission failure on link <%s>\n", l_ptr->name); | ||
1653 | tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>"); | ||
1654 | |||
1655 | if (l_ptr->addr) { | ||
1656 | |||
1657 | /* Handle failure on standard link */ | ||
1658 | |||
1659 | link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n"); | ||
1660 | tipc_link_reset(l_ptr); | ||
1661 | |||
1662 | } else { | ||
1663 | |||
1664 | /* Handle failure on broadcast link */ | ||
1665 | |||
1666 | struct node *n_ptr; | ||
1667 | char addr_string[16]; | ||
1668 | |||
1669 | tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); | ||
1670 | tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle); | ||
1671 | |||
1672 | n_ptr = l_ptr->owner->next; | ||
1673 | tipc_node_lock(n_ptr); | ||
1674 | |||
1675 | addr_string_fill(addr_string, n_ptr->addr); | ||
1676 | tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); | ||
1677 | tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); | ||
1678 | tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); | ||
1679 | tipc_printf(TIPC_OUTPUT, "Last in: %u, ", n_ptr->bclink.last_in); | ||
1680 | tipc_printf(TIPC_OUTPUT, "Gap after: %u, ", n_ptr->bclink.gap_after); | ||
1681 | tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to); | ||
1682 | tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync); | ||
1683 | |||
1684 | tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); | ||
1685 | |||
1686 | tipc_node_unlock(n_ptr); | ||
1687 | |||
1688 | l_ptr->stale_count = 0; | ||
1689 | } | ||
1690 | } | ||
1691 | |||
1607 | void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | 1692 | void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, |
1608 | u32 retransmits) | 1693 | u32 retransmits) |
1609 | { | 1694 | { |
1610 | struct tipc_msg *msg; | 1695 | struct tipc_msg *msg; |
1611 | 1696 | ||
1697 | if (!buf) | ||
1698 | return; | ||
1699 | |||
1700 | msg = buf_msg(buf); | ||
1701 | |||
1612 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | 1702 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); |
1613 | 1703 | ||
1614 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { | 1704 | if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { |
1615 | msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); | 1705 | if (!skb_cloned(buf)) { |
1616 | dbg_print_link(l_ptr, " "); | 1706 | msg_dbg(msg, ">NO_RETR->BCONG>"); |
1617 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | 1707 | dbg_print_link(l_ptr, " "); |
1618 | l_ptr->retransm_queue_size = retransmits; | 1708 | l_ptr->retransm_queue_head = msg_seqno(msg); |
1619 | return; | 1709 | l_ptr->retransm_queue_size = retransmits; |
1710 | return; | ||
1711 | } else { | ||
1712 | /* Don't retransmit if driver already has the buffer */ | ||
1713 | } | ||
1714 | } else { | ||
1715 | /* Detect repeated retransmit failures on uncongested bearer */ | ||
1716 | |||
1717 | if (l_ptr->last_retransmitted == msg_seqno(msg)) { | ||
1718 | if (++l_ptr->stale_count > 100) { | ||
1719 | link_retransmit_failure(l_ptr, buf); | ||
1720 | return; | ||
1721 | } | ||
1722 | } else { | ||
1723 | l_ptr->last_retransmitted = msg_seqno(msg); | ||
1724 | l_ptr->stale_count = 1; | ||
1725 | } | ||
1620 | } | 1726 | } |
1727 | |||
1621 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | 1728 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { |
1622 | msg = buf_msg(buf); | 1729 | msg = buf_msg(buf); |
1623 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | 1730 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); |
1624 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 1731 | 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)) { | 1732 | 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>"); | 1733 | msg_dbg(buf_msg(buf), ">RETR>"); |
1642 | buf = buf->next; | 1734 | buf = buf->next; |
1643 | retransmits--; | 1735 | retransmits--; |
@@ -1650,6 +1742,7 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, | |||
1650 | return; | 1742 | return; |
1651 | } | 1743 | } |
1652 | } | 1744 | } |
1745 | |||
1653 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; | 1746 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; |
1654 | } | 1747 | } |
1655 | 1748 | ||
@@ -1720,6 +1813,11 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | |||
1720 | link_recv_non_seq(buf); | 1813 | link_recv_non_seq(buf); |
1721 | continue; | 1814 | continue; |
1722 | } | 1815 | } |
1816 | |||
1817 | if (unlikely(!msg_short(msg) && | ||
1818 | (msg_destnode(msg) != tipc_own_addr))) | ||
1819 | goto cont; | ||
1820 | |||
1723 | n_ptr = tipc_node_find(msg_prevnode(msg)); | 1821 | n_ptr = tipc_node_find(msg_prevnode(msg)); |
1724 | if (unlikely(!n_ptr)) | 1822 | if (unlikely(!n_ptr)) |
1725 | goto cont; | 1823 | goto cont; |
@@ -2140,7 +2238,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | |||
2140 | 2238 | ||
2141 | if (msg_linkprio(msg) && | 2239 | if (msg_linkprio(msg) && |
2142 | (msg_linkprio(msg) != l_ptr->priority)) { | 2240 | (msg_linkprio(msg) != l_ptr->priority)) { |
2143 | warn("Changing prio <%s>: %u->%u\n", | 2241 | warn("Resetting link <%s>, priority change %u->%u\n", |
2144 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); | 2242 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); |
2145 | l_ptr->priority = msg_linkprio(msg); | 2243 | l_ptr->priority = msg_linkprio(msg); |
2146 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ | 2244 | tipc_link_reset(l_ptr); /* Enforce change to take effect */ |
@@ -2209,17 +2307,22 @@ void tipc_link_tunnel(struct link *l_ptr, | |||
2209 | u32 length = msg_size(msg); | 2307 | u32 length = msg_size(msg); |
2210 | 2308 | ||
2211 | tunnel = l_ptr->owner->active_links[selector & 1]; | 2309 | tunnel = l_ptr->owner->active_links[selector & 1]; |
2212 | if (!tipc_link_is_up(tunnel)) | 2310 | if (!tipc_link_is_up(tunnel)) { |
2311 | warn("Link changeover error, " | ||
2312 | "tunnel link no longer available\n"); | ||
2213 | return; | 2313 | return; |
2314 | } | ||
2214 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); | 2315 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); |
2215 | buf = buf_acquire(length + INT_H_SIZE); | 2316 | buf = buf_acquire(length + INT_H_SIZE); |
2216 | if (!buf) | 2317 | if (!buf) { |
2318 | warn("Link changeover error, " | ||
2319 | "unable to send tunnel msg\n"); | ||
2217 | return; | 2320 | return; |
2321 | } | ||
2218 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); | 2322 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); |
2219 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); | 2323 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); |
2220 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); | 2324 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); |
2221 | msg_dbg(buf_msg(buf), ">SEND>"); | 2325 | msg_dbg(buf_msg(buf), ">SEND>"); |
2222 | assert(tunnel); | ||
2223 | tipc_link_send_buf(tunnel, buf); | 2326 | tipc_link_send_buf(tunnel, buf); |
2224 | } | 2327 | } |
2225 | 2328 | ||
@@ -2235,23 +2338,27 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2235 | u32 msgcount = l_ptr->out_queue_size; | 2338 | u32 msgcount = l_ptr->out_queue_size; |
2236 | struct sk_buff *crs = l_ptr->first_out; | 2339 | struct sk_buff *crs = l_ptr->first_out; |
2237 | struct link *tunnel = l_ptr->owner->active_links[0]; | 2340 | 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; | 2341 | struct tipc_msg tunnel_hdr; |
2342 | int split_bundles; | ||
2240 | 2343 | ||
2241 | if (!tunnel) | 2344 | if (!tunnel) |
2242 | return; | 2345 | return; |
2243 | 2346 | ||
2244 | if (!l_ptr->owner->permit_changeover) | 2347 | if (!l_ptr->owner->permit_changeover) { |
2348 | warn("Link changeover error, " | ||
2349 | "peer did not permit changeover\n"); | ||
2245 | return; | 2350 | return; |
2351 | } | ||
2246 | 2352 | ||
2247 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | 2353 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, |
2248 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | 2354 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); |
2249 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | 2355 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); |
2250 | msg_set_msgcnt(&tunnel_hdr, msgcount); | 2356 | msg_set_msgcnt(&tunnel_hdr, msgcount); |
2357 | dbg("Link changeover requires %u tunnel messages\n", msgcount); | ||
2358 | |||
2251 | if (!l_ptr->first_out) { | 2359 | if (!l_ptr->first_out) { |
2252 | struct sk_buff *buf; | 2360 | struct sk_buff *buf; |
2253 | 2361 | ||
2254 | assert(!msgcount); | ||
2255 | buf = buf_acquire(INT_H_SIZE); | 2362 | buf = buf_acquire(INT_H_SIZE); |
2256 | if (buf) { | 2363 | if (buf) { |
2257 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | 2364 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); |
@@ -2261,10 +2368,15 @@ void tipc_link_changeover(struct link *l_ptr) | |||
2261 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); | 2368 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); |
2262 | tipc_link_send_buf(tunnel, buf); | 2369 | tipc_link_send_buf(tunnel, buf); |
2263 | } else { | 2370 | } else { |
2264 | warn("Memory squeeze; link changeover failed\n"); | 2371 | warn("Link changeover error, " |
2372 | "unable to send changeover msg\n"); | ||
2265 | } | 2373 | } |
2266 | return; | 2374 | return; |
2267 | } | 2375 | } |
2376 | |||
2377 | split_bundles = (l_ptr->owner->active_links[0] != | ||
2378 | l_ptr->owner->active_links[1]); | ||
2379 | |||
2268 | while (crs) { | 2380 | while (crs) { |
2269 | struct tipc_msg *msg = buf_msg(crs); | 2381 | struct tipc_msg *msg = buf_msg(crs); |
2270 | 2382 | ||
@@ -2310,7 +2422,8 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) | |||
2310 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); | 2422 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); |
2311 | outbuf = buf_acquire(length + INT_H_SIZE); | 2423 | outbuf = buf_acquire(length + INT_H_SIZE); |
2312 | if (outbuf == NULL) { | 2424 | if (outbuf == NULL) { |
2313 | warn("Memory squeeze; buffer duplication failed\n"); | 2425 | warn("Link changeover error, " |
2426 | "unable to send duplicate msg\n"); | ||
2314 | return; | 2427 | return; |
2315 | } | 2428 | } |
2316 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | 2429 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); |
@@ -2364,11 +2477,15 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2364 | u32 msg_count = msg_msgcnt(tunnel_msg); | 2477 | u32 msg_count = msg_msgcnt(tunnel_msg); |
2365 | 2478 | ||
2366 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; | 2479 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; |
2367 | assert(dest_link != *l_ptr); | ||
2368 | if (!dest_link) { | 2480 | if (!dest_link) { |
2369 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); | 2481 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); |
2370 | goto exit; | 2482 | goto exit; |
2371 | } | 2483 | } |
2484 | if (dest_link == *l_ptr) { | ||
2485 | err("Unexpected changeover message on link <%s>\n", | ||
2486 | (*l_ptr)->name); | ||
2487 | goto exit; | ||
2488 | } | ||
2372 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, | 2489 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, |
2373 | (*l_ptr)->b_ptr->net_plane); | 2490 | (*l_ptr)->b_ptr->net_plane); |
2374 | *l_ptr = dest_link; | 2491 | *l_ptr = dest_link; |
@@ -2381,7 +2498,7 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2381 | } | 2498 | } |
2382 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); | 2499 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); |
2383 | if (*buf == NULL) { | 2500 | if (*buf == NULL) { |
2384 | warn("Memory squeeze; failed to extract msg\n"); | 2501 | warn("Link changeover error, duplicate msg dropped\n"); |
2385 | goto exit; | 2502 | goto exit; |
2386 | } | 2503 | } |
2387 | msg_dbg(tunnel_msg, "TNL<REC<"); | 2504 | msg_dbg(tunnel_msg, "TNL<REC<"); |
@@ -2393,13 +2510,17 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2393 | 2510 | ||
2394 | if (tipc_link_is_up(dest_link)) { | 2511 | if (tipc_link_is_up(dest_link)) { |
2395 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); | 2512 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); |
2513 | info("Resetting link <%s>, changeover initiated by peer\n", | ||
2514 | dest_link->name); | ||
2396 | tipc_link_reset(dest_link); | 2515 | tipc_link_reset(dest_link); |
2397 | dest_link->exp_msg_count = msg_count; | 2516 | dest_link->exp_msg_count = msg_count; |
2517 | dbg("Expecting %u tunnelled messages\n", msg_count); | ||
2398 | if (!msg_count) | 2518 | if (!msg_count) |
2399 | goto exit; | 2519 | goto exit; |
2400 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { | 2520 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { |
2401 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); | 2521 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); |
2402 | dest_link->exp_msg_count = msg_count; | 2522 | dest_link->exp_msg_count = msg_count; |
2523 | dbg("Expecting %u tunnelled messages\n", msg_count); | ||
2403 | if (!msg_count) | 2524 | if (!msg_count) |
2404 | goto exit; | 2525 | goto exit; |
2405 | } | 2526 | } |
@@ -2407,6 +2528,8 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2407 | /* Receive original message */ | 2528 | /* Receive original message */ |
2408 | 2529 | ||
2409 | if (dest_link->exp_msg_count == 0) { | 2530 | if (dest_link->exp_msg_count == 0) { |
2531 | warn("Link switchover error, " | ||
2532 | "got too many tunnelled messages\n"); | ||
2410 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); | 2533 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); |
2411 | dbg_print_link(dest_link, "LINK:"); | 2534 | dbg_print_link(dest_link, "LINK:"); |
2412 | goto exit; | 2535 | goto exit; |
@@ -2422,7 +2545,7 @@ static int link_recv_changeover_msg(struct link **l_ptr, | |||
2422 | buf_discard(tunnel_buf); | 2545 | buf_discard(tunnel_buf); |
2423 | return 1; | 2546 | return 1; |
2424 | } else { | 2547 | } else { |
2425 | warn("Memory squeeze; dropped incoming msg\n"); | 2548 | warn("Link changeover error, original msg dropped\n"); |
2426 | } | 2549 | } |
2427 | } | 2550 | } |
2428 | exit: | 2551 | exit: |
@@ -2444,13 +2567,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf) | |||
2444 | while (msgcount--) { | 2567 | while (msgcount--) { |
2445 | obuf = buf_extract(buf, pos); | 2568 | obuf = buf_extract(buf, pos); |
2446 | if (obuf == NULL) { | 2569 | if (obuf == NULL) { |
2447 | char addr_string[16]; | 2570 | warn("Link unable to unbundle message(s)\n"); |
2448 | 2571 | 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 | }; | 2572 | }; |
2455 | pos += align(msg_size(buf_msg(obuf))); | 2573 | pos += align(msg_size(buf_msg(obuf))); |
2456 | msg_dbg(buf_msg(obuf), " /"); | 2574 | msg_dbg(buf_msg(obuf), " /"); |
@@ -2508,7 +2626,7 @@ int tipc_link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2508 | } | 2626 | } |
2509 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); | 2627 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); |
2510 | if (fragm == NULL) { | 2628 | if (fragm == NULL) { |
2511 | warn("Memory squeeze; failed to fragment msg\n"); | 2629 | warn("Link unable to fragment message\n"); |
2512 | dsz = -ENOMEM; | 2630 | dsz = -ENOMEM; |
2513 | goto exit; | 2631 | goto exit; |
2514 | } | 2632 | } |
@@ -2623,7 +2741,7 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | |||
2623 | set_fragm_size(pbuf,fragm_sz); | 2741 | set_fragm_size(pbuf,fragm_sz); |
2624 | set_expected_frags(pbuf,exp_fragm_cnt - 1); | 2742 | set_expected_frags(pbuf,exp_fragm_cnt - 1); |
2625 | } else { | 2743 | } else { |
2626 | warn("Memory squeeze; got no defragmenting buffer\n"); | 2744 | warn("Link unable to reassemble fragmented message\n"); |
2627 | } | 2745 | } |
2628 | buf_discard(fbuf); | 2746 | buf_discard(fbuf); |
2629 | return 0; | 2747 | return 0; |