diff options
-rw-r--r-- | net/tipc/link.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c index b678c2e0080a..663623c5896d 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1484,7 +1484,7 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) if ((n_ptr->block_setup & WAIT_PEER_DOWN) && msg_user(msg) == LINK_PROTOCOL && (msg_type(msg) == RESET_MSG || - msg_type(msg) == ACTIVATE_MSG) && + msg_type(msg) == ACTIVATE_MSG) && !msg_redundant_link(msg)) n_ptr->block_setup &= ~WAIT_PEER_DOWN; @@ -1503,7 +1503,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) while ((crs != l_ptr->next_out) && less_eq(buf_seqno(crs), ackd)) { struct sk_buff *next = crs->next; - kfree_skb(crs); crs = next; released++; @@ -1516,14 +1515,17 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) /* Try sending any messages link endpoint has pending */ if (unlikely(l_ptr->next_out)) tipc_link_push_queue(l_ptr); + if (unlikely(!list_empty(&l_ptr->waiting_ports))) tipc_link_wakeup_ports(l_ptr, 0); + if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { l_ptr->stats.sent_acks++; - tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); + tipc_link_send_proto_msg(l_ptr, STATE_MSG, + 0, 0, 0, 0, 0); } - /* Now (finally!) process the incoming message */ + /* Process the incoming packet */ if (unlikely(!link_working_working(l_ptr))) { if (msg_user(msg) == LINK_PROTOCOL) { link_recv_proto_msg(l_ptr, buf); @@ -1555,14 +1557,40 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) l_ptr->next_in_no++; if (unlikely(l_ptr->oldest_deferred_in)) head = link_insert_deferred_queue(l_ptr, head); -deliver: - if (likely(msg_isdata(msg))) { + + /* Deliver packet/message to correct user: */ + if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL)) { + if (!tipc_link_tunnel_rcv(n_ptr, &buf)) { + tipc_node_unlock(n_ptr); + continue; + } + msg = buf_msg(buf); + } else if (msg_user(msg) == MSG_FRAGMENTER) { + int rc; + + l_ptr->stats.recv_fragments++; + rc = tipc_link_frag_rcv(&l_ptr->reasm_head, + &l_ptr->reasm_tail, + &buf); + if (rc == LINK_REASM_COMPLETE) { + l_ptr->stats.recv_fragmented++; + msg = buf_msg(buf); + } else { + if (rc == LINK_REASM_ERROR) + tipc_link_reset(l_ptr); + tipc_node_unlock(n_ptr); + continue; + } + } + + switch (msg_user(msg)) { + case TIPC_LOW_IMPORTANCE: + case TIPC_MEDIUM_IMPORTANCE: + case TIPC_HIGH_IMPORTANCE: + case TIPC_CRITICAL_IMPORTANCE: tipc_node_unlock(n_ptr); tipc_port_recv_msg(buf); continue; - } - switch (msg_user(msg)) { - int ret; case MSG_BUNDLER: l_ptr->stats.recv_bundles++; l_ptr->stats.recv_bundled += msg_msgcnt(msg); @@ -1574,44 +1602,20 @@ deliver: tipc_node_unlock(n_ptr); tipc_named_recv(buf); continue; - case BCAST_PROTOCOL: - tipc_link_recv_sync(n_ptr, buf); - tipc_node_unlock(n_ptr); - continue; case CONN_MANAGER: tipc_node_unlock(n_ptr); tipc_port_recv_proto_msg(buf); continue; - case MSG_FRAGMENTER: - l_ptr->stats.recv_fragments++; - ret = tipc_link_frag_rcv(&l_ptr->reasm_head, - &l_ptr->reasm_tail, - &buf); - if (ret == LINK_REASM_COMPLETE) { - l_ptr->stats.recv_fragmented++; - msg = buf_msg(buf); - goto deliver; - } - if (ret == LINK_REASM_ERROR) - tipc_link_reset(l_ptr); - tipc_node_unlock(n_ptr); - continue; - case CHANGEOVER_PROTOCOL: - if (!tipc_link_tunnel_rcv(n_ptr, &buf)) - break; - msg = buf_msg(buf); - seq_no = msg_seqno(msg); - goto deliver; + case BCAST_PROTOCOL: + tipc_link_recv_sync(n_ptr, buf); + break; default: kfree_skb(buf); - buf = NULL; break; } tipc_node_unlock(n_ptr); - tipc_net_route_msg(buf); continue; unlock_discard: - tipc_node_unlock(n_ptr); discard: kfree_skb(buf); |