]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/tipc/node.c
tipc: transfer broadcast nacks in link state messages
[karo-tx-linux.git] / net / tipc / node.c
index 7e8b75fd1a02da768f9d203f47223eaf9f477b9b..7ef14e2d2356590d72284e3ef056d63dee3d1b12 100644 (file)
@@ -1262,6 +1262,34 @@ void tipc_node_broadcast(struct net *net, struct sk_buff *skb)
        kfree_skb(skb);
 }
 
+static void tipc_node_bc_sync_rcv(struct tipc_node *n, struct tipc_msg *hdr,
+                                 int bearer_id, struct sk_buff_head *xmitq)
+{
+       struct tipc_link *ucl;
+       int rc;
+
+       rc = tipc_bcast_sync_rcv(n->net, n->bc_entry.link, hdr);
+
+       if (rc & TIPC_LINK_DOWN_EVT) {
+               tipc_bearer_reset_all(n->net);
+               return;
+       }
+
+       if (!(rc & TIPC_LINK_SND_STATE))
+               return;
+
+       /* If probe message, a STATE response will be sent anyway */
+       if (msg_probe(hdr))
+               return;
+
+       /* Produce a STATE message carrying broadcast NACK */
+       tipc_node_read_lock(n);
+       ucl = n->links[bearer_id].link;
+       if (ucl)
+               tipc_link_build_state_msg(ucl, xmitq);
+       tipc_node_read_unlock(n);
+}
+
 /**
  * tipc_node_bc_rcv - process TIPC broadcast packet arriving from off-node
  * @net: the applicable net namespace
@@ -1298,7 +1326,7 @@ static void tipc_node_bc_rcv(struct net *net, struct sk_buff *skb, int bearer_id
        rc = tipc_bcast_rcv(net, be->link, skb);
 
        /* Broadcast ACKs are sent on a unicast link */
-       if (rc & TIPC_LINK_SND_BC_ACK) {
+       if (rc & TIPC_LINK_SND_STATE) {
                tipc_node_read_lock(n);
                tipc_link_build_state_msg(le->link, &xmitq);
                tipc_node_read_unlock(n);
@@ -1505,7 +1533,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b)
 
        /* Ensure broadcast reception is in synch with peer's send state */
        if (unlikely(usr == LINK_PROTOCOL))
-               tipc_bcast_sync_rcv(net, n->bc_entry.link, hdr);
+               tipc_node_bc_sync_rcv(n, hdr, bearer_id, &xmitq);
        else if (unlikely(tipc_link_acked(n->bc_entry.link) != bc_ack))
                tipc_bcast_ack_rcv(net, n->bc_entry.link, bc_ack);