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