aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
diff options
context:
space:
mode:
authorJon Paul Maloy <jon.maloy@ericsson.com>2014-02-13 17:29:10 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-13 17:57:06 -0500
commit1dab3d5ac22217241ca5c5bb7d0132602b465938 (patch)
tree25ce98bddb0d4055098781fd90fe38b021706aea /net/tipc/link.c
parentc61dd61dec0b79fa22ded8b5caf2e817dc506c24 (diff)
tipc: change reception of tunnelled duplicate packets
When a second link to a destination comes up, some sender sockets will steer their subsequent traffic through the new link. In order to guarantee preserved packet order and cardinality for those sockets, we tunnel a duplicate of the old link's send queue through the new link before we open it for regular traffic. The last arriving packet copy, on whichever link, will be dropped at the receiving end based on the original sequence number, to ensure that only one copy is delivered to the end receiver. In this commit, we change the algorithm for receiving DUPLICATE_MSG packets, at the same time delegating it to a new subfunction, tipc_link_dup_rcv(). Instead of returning an extracted inner packet to the packet reception loop in tipc_rcv(), we just add it to the receiving (new) link's deferred packet queue. The packet will then be processed by that link when it receives its first non-tunneled packet, i.e., at latest when the changeover procedure is finished. Because tipc_link_tunnel_rcv()/tipc_link_dup_rcv() now is consuming all packets of type DUPLICATE_MSG, the calling tipc_rcv() function can omit testing for this. This in turn means that the current conditional jump to the label 'protocol_check' becomes redundant, and we can remove that label. Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Signed-off-by: Ying Xue <ying.xue@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/link.c')
-rw-r--r--net/tipc/link.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index e7e44ab008ec..f227a389e36e 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1437,7 +1437,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr)
1437 u32 seq_no; 1437 u32 seq_no;
1438 u32 ackd; 1438 u32 ackd;
1439 u32 released = 0; 1439 u32 released = 0;
1440 int type;
1441 1440
1442 head = head->next; 1441 head = head->next;
1443 buf->next = NULL; 1442 buf->next = NULL;
@@ -1525,7 +1524,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr)
1525 } 1524 }
1526 1525
1527 /* Now (finally!) process the incoming message */ 1526 /* Now (finally!) process the incoming message */
1528protocol_check:
1529 if (unlikely(!link_working_working(l_ptr))) { 1527 if (unlikely(!link_working_working(l_ptr))) {
1530 if (msg_user(msg) == LINK_PROTOCOL) { 1528 if (msg_user(msg) == LINK_PROTOCOL) {
1531 link_recv_proto_msg(l_ptr, buf); 1529 link_recv_proto_msg(l_ptr, buf);
@@ -1599,15 +1597,11 @@ deliver:
1599 tipc_node_unlock(n_ptr); 1597 tipc_node_unlock(n_ptr);
1600 continue; 1598 continue;
1601 case CHANGEOVER_PROTOCOL: 1599 case CHANGEOVER_PROTOCOL:
1602 type = msg_type(msg); 1600 if (!tipc_link_tunnel_rcv(&l_ptr, &buf))
1603 if (tipc_link_tunnel_rcv(&l_ptr, &buf)) { 1601 break;
1604 msg = buf_msg(buf); 1602 msg = buf_msg(buf);
1605 seq_no = msg_seqno(msg); 1603 seq_no = msg_seqno(msg);
1606 if (type == ORIGINAL_MSG) 1604 goto deliver;
1607 goto deliver;
1608 goto protocol_check;
1609 }
1610 break;
1611 default: 1605 default:
1612 kfree_skb(buf); 1606 kfree_skb(buf);
1613 buf = NULL; 1607 buf = NULL;
@@ -2107,7 +2101,30 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos)
2107 return eb; 2101 return eb;
2108} 2102}
2109 2103
2110/* tipc_link_tunnel_rcv(): Receive a tunneled packet, sent 2104
2105
2106/* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet.
2107 * Owner node is locked.
2108 */
2109static void tipc_link_dup_rcv(struct tipc_link *l_ptr,
2110 struct sk_buff *t_buf)
2111{
2112 struct sk_buff *buf;
2113
2114 if (!tipc_link_is_up(l_ptr))
2115 return;
2116
2117 buf = buf_extract(t_buf, INT_H_SIZE);
2118 if (buf == NULL) {
2119 pr_warn("%sfailed to extract inner dup pkt\n", link_co_err);
2120 return;
2121 }
2122
2123 /* Add buffer to deferred queue, if applicable: */
2124 link_handle_out_of_seq_msg(l_ptr, buf);
2125}
2126
2127/* tipc_link_tunnel_rcv(): Receive a tunnelled packet, sent
2111 * via other link as result of a failover (ORIGINAL_MSG) or 2128 * via other link as result of a failover (ORIGINAL_MSG) or
2112 * a new active link (DUPLICATE_MSG). Failover packets are 2129 * a new active link (DUPLICATE_MSG). Failover packets are
2113 * returned to the active link for delivery upwards. 2130 * returned to the active link for delivery upwards.
@@ -2126,6 +2143,7 @@ static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
2126 2143
2127 if (bearer_id >= MAX_BEARERS) 2144 if (bearer_id >= MAX_BEARERS)
2128 goto exit; 2145 goto exit;
2146
2129 dest_link = (*l_ptr)->owner->links[bearer_id]; 2147 dest_link = (*l_ptr)->owner->links[bearer_id];
2130 if (!dest_link) 2148 if (!dest_link)
2131 goto exit; 2149 goto exit;
@@ -2138,15 +2156,8 @@ static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr,
2138 msg = msg_get_wrapped(tunnel_msg); 2156 msg = msg_get_wrapped(tunnel_msg);
2139 2157
2140 if (msg_typ == DUPLICATE_MSG) { 2158 if (msg_typ == DUPLICATE_MSG) {
2141 if (less(msg_seqno(msg), mod(dest_link->next_in_no))) 2159 tipc_link_dup_rcv(dest_link, tunnel_buf);
2142 goto exit; 2160 goto exit;
2143 *buf = buf_extract(tunnel_buf, INT_H_SIZE);
2144 if (*buf == NULL) {
2145 pr_warn("%sduplicate msg dropped\n", link_co_err);
2146 goto exit;
2147 }
2148 kfree_skb(tunnel_buf);
2149 return 1;
2150 } 2161 }
2151 2162
2152 /* First original message ?: */ 2163 /* First original message ?: */